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

Dependents:   A_CANAdapter USB2I2C

Revision:
10:9e52bd1a4a71
Parent:
9:41046d2fd8e7
Child:
11:4a3cd3f2183b
--- 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;