changeset 1032:f5fa0e095f5e

Add RedBoot command history
author msalter
date Tue, 20 May 2003 18:43:51 +0000
parents 6b4a1f23fbbb
children 8f7a10771d67
files packages/redboot/current/ChangeLog packages/redboot/current/cdl/redboot.cdl packages/redboot/current/doc/redboot.sgml packages/redboot/current/src/io.c
diffstat 4 files changed, 162 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/packages/redboot/current/ChangeLog
+++ b/packages/redboot/current/ChangeLog
@@ -1,3 +1,9 @@
+2003-05-20  Mark Salter  <msalter@redhat.com>
+
+	* cdl/redboot.cdl (CYGBLD_REDBOOT_CMD_LINE_HISTORY): New option.
+	* src/io.c: Support history command and history expansion.
+	* doc/redboot.sgml: Document command history support.
+
 2003-05-14  Mark Salter  <msalter@redhat.com>
 
 	* src/flash.c (flash_get_config): Add CONFIG_NETPORT case.
--- a/packages/redboot/current/cdl/redboot.cdl
+++ b/packages/redboot/current/cdl/redboot.cdl
@@ -128,6 +128,17 @@ cdl_package CYGPKG_REDBOOT {
                enable rudimentary editting of the lines themselves."
         }
 
+        cdl_option CYGBLD_REDBOOT_CMD_LINE_HISTORY {
+            display        "Enable history command and expansion"
+            requires       { CYGNUM_REDBOOT_CMD_LINE_EDITING > 0 }
+            flavor         bool
+            default_value  1
+            description  "
+              Enabling this option will allow RedBoot to provide a history command
+              to list previous commands. Also enables history expansion via '!'
+              character similar to bash shell."
+        }
+    
         cdl_option CYGBLD_BUILD_REDBOOT_WITH_ZLIB {
             display       "Include support gzip/zlib decompression"
             active_if     CYGPKG_COMPRESS_ZLIB
--- a/packages/redboot/current/doc/redboot.sgml
+++ b/packages/redboot/current/doc/redboot.sgml
@@ -223,6 +223,39 @@ value for the start-up script; it must a
 </itemizedlist></para>
 </sect1>
 
+<sect1 id="RedBoot-Command-History">
+<title>RedBoot Command History</title>
+<para>
+<indexterm><primary>RedBoot</primary><secondary>command history</secondary></indexterm>
+<indexterm><primary>command history</primary></indexterm>
+<indexterm><primary>commands</primary><secondary>history</secondary></indexterm>
+RedBoot provides support for listing and repeating previously entered commands. A
+list of previously entered commands may be obtained by typing <command>history</command>
+at the command line:
+<screen>
+RedBoot> <userinput>history</userinput>
+  0 fis list
+  1 fconfig -l
+  2 load -m ymodem
+  3 history
+</screen>
+</para><para>
+The following history expansions may be used to execute commands in the history list:
+<itemizedlist>
+<listitem><para>
+!! repeats last command.
+</para></listitem>
+<listitem><para>
+!<userinput>n</userinput> repeats command <userinput>n</userinput>.
+</para></listitem>
+<listitem><para>
+!<userinput>string</userinput> repeats most recent command starting with
+<userinput>string</userinput>.
+</para></listitem>
+</itemizedlist>
+</para>
+</sect1>
+
 <sect1 id="startup-mode">
 <title>RedBoot Startup Mode</title>
 <para>
--- a/packages/redboot/current/src/io.c
+++ b/packages/redboot/current/src/io.c
@@ -8,7 +8,7 @@
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
 // Copyright (C) 2002 Gary Thomas
 //
 // eCos is free software; you can redistribute it and/or modify it under
@@ -296,6 +296,17 @@ getc_script(char *cp)
 }
 #endif
 
+#if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
+#define _CL_NUM_LINES CYGNUM_REDBOOT_CMD_LINE_EDITING       // Number of lines to keep
+static char _cl_lines[_CL_NUM_LINES][CYGPKG_REDBOOT_MAX_CMD_LINE];
+static int  _cl_index = -1;      // Last known command line
+static int  _cl_max_index = -1;  // Last command in buffers
+
+#ifdef CYGBLD_REDBOOT_CMD_LINE_HISTORY
+static void expand_history(char *);
+#endif
+#endif
+
 //
 // Read a line of input from the user
 // Return:
@@ -304,6 +315,15 @@ getc_script(char *cp)
 //   _GETS_TIMEOUT: No input before timeout
 //     _GETS_CTRLC: ^C typed
 //
+// if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
+//   Command line history support
+//    ^P - Select previous line from history
+//    ^N - Select next line from history
+//    ^A - Move insertion [cursor] to start of line
+//    ^E - Move cursor to end of line
+//    ^B - Move cursor back [previous character]
+//    ^F - Move cursor forward [next character]
+//
 int
 _rb_gets_preloaded(char *buf, int buflen, int timeout)
 {
@@ -314,19 +334,6 @@ int
     static char last_ch = '\0';
     int _timeout;
 #if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
-//
-// Command line history support
-//    ^P - Select previous line from history
-//    ^N - Select next line from history
-//    ^A - Move insertion [cursor] to start of line
-//    ^E - Move cursor to end of line
-//    ^B - Move cursor back [previous character]
-//    ^F - Move cursor forward [next character]
-//
-#define _CL_NUM_LINES CYGNUM_REDBOOT_CMD_LINE_EDITING       // Number of lines to keep
-    static char _cl_lines[_CL_NUM_LINES][CYGPKG_REDBOOT_MAX_CMD_LINE];
-    static int  _cl_index = -1;      // Last known command line
-    static int  _cl_max_index = -1;  // Last command in buffers
     int _index = _cl_index;  // Last saved line
     char *xp;
 #endif
@@ -490,11 +497,16 @@ int
 	    }
             last_ch = c;
 #if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
-            if (cmd_history && (buf != eol)) {
-                // Save current line - only when enabled
-                if (++_cl_index == _CL_NUM_LINES) _cl_index = 0;
-                if (_cl_index > _cl_max_index) _cl_max_index = _cl_index;
-                strcpy(_cl_lines[_cl_index], buf);
+            if (cmd_history) {
+                // History handling - only when enabled
+#ifdef CYGBLD_REDBOOT_CMD_LINE_HISTORY
+		expand_history(buf);
+#endif
+		if (*buf != '\0') {
+		    if (++_cl_index == _CL_NUM_LINES) _cl_index = 0;
+		    if (_cl_index > _cl_max_index) _cl_max_index = _cl_index;
+		    strcpy(_cl_lines[_cl_index], buf);
+		}
             }
 #endif
             return _GETS_OK;
@@ -649,3 +661,84 @@ verify_action_with_timeout(int timeout, 
     va_start(ap, fmt);
     return _verify_action(timeout, fmt, ap);
 }
+
+
+#ifdef CYGBLD_REDBOOT_CMD_LINE_HISTORY
+// parse for history index number. Return number or -1 if not
+// an index number.
+static int
+parse_history_index(char *s)
+{
+    int val = 0;
+
+    while ('0' <= *s && *s <= '9')
+	val = (val * 10) + (*s++ - '0');
+
+    if (*s)
+	return -1;
+
+    return val;
+}
+
+// Check input line to see if it needs history expansion. If so,
+// try to find matching command and replace buffer as appropriate.
+static void
+expand_history(char *buf)
+{
+    int ncmds = _cl_max_index + 1;
+    int i, index, len;
+
+    if (buf[0] != '!' || buf[1] == '\0')
+	return;
+
+    if (ncmds > 0) {
+	if (!strcmp(buf, "!!")) {
+	    strcpy(buf, _cl_lines[_cl_index]);
+	    return;
+	}
+	if ((index = parse_history_index(buf + 1)) >= 0) {
+	    if (index <= _cl_max_index) {
+		strcpy(buf, _cl_lines[index]);
+		return;
+	    }
+	}
+	len = strlen(buf + 1);
+	for (i = 0, index = _cl_index; i < ncmds; i++) {
+	    if (!strncmp(_cl_lines[index], buf+1, len)) {
+		strcpy(buf, _cl_lines[index]);
+		return;
+	    }
+	    if (--index < 0)
+		index = _cl_max_index;
+	}
+    }
+
+    diag_printf("%s: event not found\n", buf);
+    *buf = '\0';
+}
+
+static void
+do_history(int argc, char *argv[])
+{
+    int ncmds = _cl_max_index + 1;
+    int i, index;
+
+    if (_cl_index == _cl_max_index) {
+	// history has not wrapped around
+	for (i = 0; i < ncmds; i++)
+	    diag_printf("%3d %s\n", i, _cl_lines[i]);
+    } else {
+	for (i = 0, index = _cl_index + 1; i < ncmds; i++) {
+	    diag_printf("%3d %s\n", i, _cl_lines[index++]);
+	    if (index > _cl_max_index)
+		index = 0;
+	}
+    }
+}
+
+RedBoot_cmd("history", 
+            "Display command history", 
+            "",
+            do_history
+    );
+#endif  // CYGBLD_REDBOOT_CMD_LINE_HISTORY