The CommandProcessor is the interface to install a run-time menu into an embedded system.
Dependents: A_CANAdapter USB2I2C
Revision 10:9e52bd1a4a71, committed 2011-04-23
- Comitter:
- WiredHome
- Date:
- Sat Apr 23 14:04:19 2011 +0000
- Parent:
- 9:41046d2fd8e7
- Child:
- 11:4a3cd3f2183b
- Commit message:
- Refactored the _init interface to permit \Application\ ownership and easier maintenance.
Fixed a bug when adding a new command that sorts to the front of the list.
Changed in this revision
CommandProcessor.c | Show annotated file Show diff for this revision Revisions of this file |
CommandProcessor.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/CommandProcessor.c Sun Apr 10 21:04:49 2011 +0000 +++ b/CommandProcessor.c Sat Apr 23 14:04:19 2011 +0000 @@ -8,7 +8,7 @@ /// /// Even though it is a c interface, it is somewhat object oriented. /// -/// @version 1.0 +/// @version 1.01 /// /// @note Copyright © 2011 by Smartware Computing, all rights reserved. /// This program may be used by others as long as this copyright notice @@ -46,6 +46,8 @@ static char *buffer; // buffer space must be allocated based on the longest command static struct { + CMD_T *SignOnBanner; + int showSignOnBanner; // Shows the sign-on banner at startup int caseinsensitive; // FALSE=casesensitive, TRUE=insensitive int echo; // TRUE=echo on, FALSE=echo off int bufferSize; // size of the buffer @@ -56,9 +58,8 @@ } cfg; static INITRESULT_T CommandProcessor_Init( - int defaultMenu, - int caseinsensitive, - int echo, + CMD_T *SignOnBanner, + CONFIG_T config, int maxCmdLen, int (*kbhit)(void), int (*getch)(void), @@ -87,12 +88,12 @@ static RUNRESULT_T Help(char *p); static RUNRESULT_T Echo(char *p); static RUNRESULT_T Exit(char *p); -static RUNRESULT_T About(char *p); +//static RUNRESULT_T About(char *p); static CMD_T HelpMenu = {"Help", "Help or '?' shows this help, 'Help ?' shows more details.", Help, visible}; static CMD_T QuestionMenu = {"?", "Shows this help, '? ?' shows more details.", Help, invisible}; static CMD_T EchoMenu = {"Echo", "Echo [1|on|0|off] turns echo on or off.", Echo, visible}; -static CMD_T AboutMenu = {"About", "About this CommandProcessor", About, visible}; +//static CMD_T AboutMenu = {"About", "About this CommandProcessor", About, visible}; static CMD_T ExitMenu = {"Exit", "Exits the program", Exit, visible}; /// Gets a handle to the CommandProcessor @@ -113,6 +114,7 @@ /// none for this function. /// @returns runok /// +#if 0 static RUNRESULT_T About(char *p) { cfg.puts("\r\n About this CommandProcessor:\r\n" " This CommandProcessor provides an easy facility for creating a\r\n" @@ -122,6 +124,7 @@ ); return runok; } +#endif /// Turns command prompt echo on and off /// @@ -158,8 +161,8 @@ CMDLINK_T *link = head; char buffer[100]; cfg.puts("\r\n"); - sprintf(buffer, " %-10s: %s", "Command", "Description"); - cfg.puts(buffer); + //sprintf(buffer, " %-10s: %s", "Command", "Description"); + //cfg.puts(buffer); while (link && link->menu) { if (link->menu->visible) { if (strlen(link->menu->command) + strlen(link->menu->helptext) + 5 < sizeof(buffer)) { @@ -171,10 +174,10 @@ } cfg.puts(""); if (*p == '?') { - cfg.puts("\r\n Extended Help\r\n" + cfg.puts("\r\n Extended Help:\r\n" " The general form for entering commands is:\r\n" " >command option1 option2 ...\r\n" - " [note that note all commands support optional parameters]\r\n" + " [note that not all commands support optional parameters]\r\n" " * Abbreviations of commands may be entered so long as there\r\n" " is exactly one match in the list of commands. For example,\r\n" " 'he' is the same as 'help', if there is no other command \r\n" @@ -183,6 +186,11 @@ " * <esc> can be used to cancel a command.\r\n" " * <tab> can be used to complete the entry of a partial command.\r\n" ""); + cfg.puts("\r\n About this CommandProcessor:\r\n" + " This CommandProcessor provides an easy facility for creating an\r\n" + " interactive runtime interpreter in an embedded system.\r\n" + " Copyright (c) 2011 by Smartware Computing, all rights reserved.\r\n" + " Author: David Smart, Smartware Computing\r\n"); } return runok; } @@ -265,43 +273,58 @@ return foundCount; } -/// Initialize the CommandProcessor +/// Init is the first function to call to configure the CommandProcessor. /// -/// This initializes the CommandProcessor by adding the built-in menus +/// This function has a number of parameters, which make the CommandProcessor +/// quite flexible. /// -/// @param addDefaultMenu configures it to add the Help, About, and Exit menus -/// @param bufSize configures the size of the longest command, which must be -/// greater than 6 (the size of "About\0"). -/// @returns initok if it successfully initialized the CommandProcessor -/// @returns initfailed if it could not allocate memory +/// @param SignOnBanner function, which is used as a signon banner +/// @param config enables various default menu items, based on the bit values, combine the following: +/// \li CFG_ENABLE_TERMINATE - enables the Exit command +/// \li CFG_ENABLE_SYSTEM - enables system commands Echo, Help, etc. +/// \li CFG_ECHO_ON - initialize with echo on +/// \li CFG_CASE_INSENSITIVE - Command Parser is case insensitive +/// @param maxCmdLen sizes the buffer, and is the maximum number of characters in a single +/// command, including all command arguments +/// @param kbhit is a user provided function to detect if a character is available for the CommandProcessor, +/// and when using standard io, you can typically use kbhit, or _kbhit as your system provides. +/// @param getch is a user provided function that provides a single character to the CommandProcessor +/// @param putch is a user provided function that permits the CommandProcessor to output a character +/// @param puts is a user provided function that permits the CommandProcessor to output a string +/// to which is automatically appended a \\n +/// @returns INITRESULT_T to indicate if the init was successful or failed /// INITRESULT_T CommandProcessor_Init( - int addDefaultMenu, - int caseinsensitive, - int echo, + CMD_T (*SignOnBanner), + CONFIG_T config, int maxCmdLen, int (*kbhit)(void), int (*getch)(void), int (*putch)(int ch), int (*puts)(const char * s) ) { + if (SignOnBanner) { + CommandProcessor.Add(SignOnBanner); + cfg.SignOnBanner = SignOnBanner; + cfg.showSignOnBanner = 1; + } if (maxCmdLen < 6) maxCmdLen = 6; buffer = (char *)malloc(maxCmdLen+1); cfg.bufferSize = maxCmdLen; if (buffer) { - if (addDefaultMenu & 0x0008) + if (config & CFG_ENABLE_SYSTEM) + { CommandProcessor.Add(&QuestionMenu); - if (addDefaultMenu & 0x0008) CommandProcessor.Add(&HelpMenu); - if (addDefaultMenu & 0x0004) CommandProcessor.Add(&EchoMenu); - if (addDefaultMenu & 0x0002) - CommandProcessor.Add(&AboutMenu); - if (addDefaultMenu & 0x0001) + } + if (config & CFG_ENABLE_TERMINATE) CommandProcessor.Add(&ExitMenu); - cfg.caseinsensitive = caseinsensitive; - cfg.echo = echo; + //if (addDefaultMenu & 0x0002) + // CommandProcessor.Add(&AboutMenu); + cfg.caseinsensitive = (config & CFG_CASE_INSENSITIVE) ? 1 : 0; + cfg.echo = (config & CFG_ECHO_ON) ? 1 : 0; cfg.kbhit = kbhit; cfg.getch = getch; cfg.putch = putch; @@ -344,9 +367,14 @@ prev = ptr; ptr = ptr->next; } - prev->next = temp; - prev = temp; - prev->next = ptr; + if (prev == head) { + head = temp; + head->next = prev; + } else { + prev->next = temp; + prev = temp; + prev->next = ptr; + } return addok; } @@ -371,6 +399,10 @@ CMD_T *cbk = NULL; char * params = NULL; + if (cfg.showSignOnBanner) { + cfg.SignOnBanner->callback(""); + cfg.showSignOnBanner = 0; + } if (showPrompt && cfg.echo) { cfg.putch('>'); showPrompt = FALSE; @@ -452,7 +484,6 @@ return val; } - static RUNRESULT_T CommandProcessor_Echo(int echo) { cfg.echo = echo; return runok;
--- a/CommandProcessor.h Sun Apr 10 21:04:49 2011 +0000 +++ b/CommandProcessor.h Sat Apr 23 14:04:19 2011 +0000 @@ -1,10 +1,11 @@ /// @file CommandProcessor.h defined the interface to the CommandProcessor /// -/// @mainpage +/// @mainpage The CommandProcessor +/// /// The CommandProcessor is the interface to install a run-time menu into an embedded system. /// This contains the complete interface to the CommandProcessor. /// -/// @version 1.0 +/// @version 1.01 /// /// @note The CommandProcessor is text-based, because it is intended to interact with a /// user. @@ -43,13 +44,23 @@ /// #include "CommandProcessor.h" /// } /// +/// RUNRESULT_T SignOnBanner(char *p); +/// const CMD_T SignOnBannerCmd = { +/// "About", "About this program ('About ?' for more details)", +/// SignOnBanner, invisible}; +/// /// RUNRESULT_T Who(char *p); /// const CMD_T WhoCmd = { -/// "who", -/// "Shows who is logged on, or 'who id' for specifics", -/// Who, -/// visible}; -/// +/// "who", "Shows who is logged on, or 'who id' for specifics", +/// Who, visible}; +/// +/// RUNRESULT_T SignOnBanner(char *p) +/// { +/// puts("\r\nThis great program was built " __DATE__ " " __TIME__ "."); +/// if (*p == '?') +/// puts("\r\nMore details shown here.\r\n"); +/// return runok; +/// } /// RUNRESULT_T Who(char *p) /// { /// printf("\r\nwho...\r\n"); @@ -61,7 +72,9 @@ /// int main(int argc, char* argv[]) /// { /// CMDP_T * cp = GetCommandProcessor(); -/// cp->Init(7, TRUE, 50, _kbhit, _getch, _putch, printf); +/// cp->Init(&SignOnBanner, +/// CFG_ENABLE_TERMINATE | CFG_ENABLE_SYSTEM, +/// 50, _kbhit, _getch, _putch, printf); /// cp->Add(&WhoCmd); /// /// while (cp->Run()) @@ -78,6 +91,17 @@ /// remains intact. /// @author David Smart /// +/// @note +/// History +/// v1.01 22 April 2011 +/// \li Moving 'About' content into the extended help, +/// to free 'About' for application code that uses this library. +/// \li Altered the _init api to permit a signon banner of the users choice +/// and a config parameter for other features. +/// +/// v1.0 March 2011 +/// \li Initial version +/// #ifndef COMMANDPROCESSOR_H #define COMMANDPROCESSOR_H @@ -116,6 +140,15 @@ initok ///< this indicates that the menu system was successfully initialized } INITRESULT_T; +/// Configuration options +typedef unsigned long CONFIG_T; + +#define CFG_ENABLE_TERMINATE 0x0001 +#define CFG_ENABLE_SYSTEM 0x0002 +#define CFG_ECHO_ON 0x2000 +#define CFG_CASE_INSENSITIVE 0x4000 + + /// This is the type for the basic callback, when a menu pick is activated. /// /// The callback function is executed when a command is entered on the menu and \<enter\> @@ -126,10 +159,10 @@ /// "Test1 ab c 123 567" /// If "Test1" is a valid command, the corresponding function would be called /// passing to that function the string "ab c 123 567". Note that the delimiter space -/// was removed. +/// was removed. /// -/// @param p is a pointer to a character string -/// @returns RUNRESULT_T to indicate if the CommandProcessor should continue +/// @param p is a pointer to a character string +/// @returns RUNRESULT_T to indicate if the CommandProcessor should continue /// typedef RUNRESULT_T (*MENU_CALLBACK)(char *p); @@ -139,7 +172,7 @@ /// CommandProcessor to add this item to the menu system. /// /// example: -/// @code +/// @code /// const CMD_T WhoCmd = {"who", "Shows who is logged on, or 'who id' for specifics", Who, visible}; /// @endcode /// @@ -153,7 +186,7 @@ /// This is the CommandProcessor interface from the user application. /// -/// The user aquires a handle to this set of functions with the GetCommandProcessor command. +/// The user aquires a handle to this set of functions with the GetCommandProcessor command. /// After this, the user may then initialize the CommandProcessor, add items to the menu, /// cause the CommandProcessor to run periodically, and if need be the application can end /// the CommandProcessor. @@ -163,28 +196,26 @@ /// Init is the first function to call to configure the CommandProcessor. /// /// This function has a number of parameters, which make the CommandProcessor quite flexible. - /// The user can enable a default menu, which can consist of the following functions. - /// Note that when the [bit] is set, that menu item is enabled. - /// * [3] Help - which in turn will show all the menu items and their brief descriptions - /// * [2] Echo - which adds the echo command help - /// * [1] About - just a tiny statement about the CommandProcessor itself - /// * [0] Exit - a method to permit a consistent means to exit the CommandProcessor /// - /// @param defaultMenu enables various default menu items, based on the bit values. - /// @param kbhit is a user provided function to detect if a character is available for the CommandProcessor, - /// and when using standard io, you can typically use kbhit, or _kbhit as your system provides. - /// @param getch is a user provided function that provides a single character to the CommandProcessor - /// @param putch is a user provided function that permits the CommandProcessor to output a character - /// @param puts is a user provided function that permits the CommandProcessor to output a string + /// @param SignOnBanner function, which is used as a signon banner + /// @param config enables various default menu items, based on the bit values, combine the following: + /// \li CFG_ENABLE_TERMINATE - enables the Exit command + /// \li CFG_ENABLE_SYSTEM - enables system commands Echo, Help, etc. + /// \li CFG_ECHO_ON - initialize with echo on + /// \li CFG_CASE_INSENSITIVE - Command Parser is case insensitive + /// @param maxCmdLen sizes the buffer, and is the maximum number of characters in a single + /// command, including all command arguments + /// @param kbhit is a user provided function to detect if a character is available for the CommandProcessor, + /// and when using standard io, you can typically use kbhit, or _kbhit as your system provides. + /// @param getch is a user provided function that provides a single character to the CommandProcessor + /// @param putch is a user provided function that permits the CommandProcessor to output a character + /// @param puts is a user provided function that permits the CommandProcessor to output a string /// to which is automatically appended a \\n - /// @param caseinsensitive when TRUE, as the name implies, permits "help" and "HeLp" to function the same - /// @param maxCmdLen sets the memory allocation for the command buffer. This should be sized - /// to the maximum command, including any passed in text as parameters. /// @returns INITRESULT_T to indicate if the init was successful or failed + /// INITRESULT_T (*Init)( - int defaultMenu, - int caseinsensitive, - int echo, + CMD_T *SignOnBanner, + CONFIG_T config, int maxCmdLen, int (*kbhit)(void), int (*getch)(void), @@ -278,9 +309,17 @@ /// #include "CommandProcessor.h" /// } /// +/// RUNRESULT_T About(char *p); +/// const CMD_T AboutCmd = {"About", "About this program", About, invisible}; /// RUNRESULT_T Who(char *p); /// const CMD_T WhoCmd = {"who", "Shows who is logged on, or 'who id' for specifics", Who, visible}; /// +/// RUNRESULT_T About(char *p) +/// { +/// (void)p; +/// puts("\r\nThis program does really good things for the user.\r\n"); +/// } +/// /// RUNRESULT_T Who(char *p) /// { /// printf("\r\nwho...\r\n"); @@ -292,7 +331,9 @@ /// int main(int argc, char* argv[]) /// { /// CMDP_T * cp = GetCommandProcessor(); -/// cp->Init(7, TRUE, 50, _kbhit, _getch, _putch, printf); +/// cp->Init(AboutCmd, CFG_ENABLE_TERMINATE | CFG_ENABLE_SYSTEM | CFG_SIGNON_BANNER, +/// 50, +/// _kbhit, _getch, _putch, printf); /// cp->Add(&WhoCmd); /// /// while (cp->Run()) @@ -317,7 +358,9 @@ /// example: /// @code /// CMDP_T * cp = GetCommandProcessor(); -/// cp->Init(7, TRUE, 50, _kbhit, _getch, _putch, printf); +/// cp->Init(AboutCmd, CFG_ENABLE_TERMINATE | CFG_ENABLE_SYSTEM | CFG_SIGNON_BANNER, +/// 50, +/// _kbhit, _getch, _putch, printf); /// @endcode /// /// @returns CMDP_T a handle to the CommandProcessor