The CommandProcessor is the interface to install a run-time menu into an embedded system.

Dependents:   A_CANAdapter USB2I2C

Files at this revision

API Documentation at this revision

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