OSDN Git Service

Fix command line option parsing so "echo -xen" actually prints "-xen". Add
authorRob Landley <rob@landley.net>
Sat, 17 May 2008 22:13:26 +0000 (17:13 -0500)
committerRob Landley <rob@landley.net>
Sat, 17 May 2008 22:13:26 +0000 (17:13 -0500)
echo.test while I'm at it.

lib/args.c
scripts/test/echo.test [new file with mode: 0755]
toys/echo.c

index 808125f..6103bb0 100644 (file)
@@ -88,14 +88,14 @@ struct getoptflagstate
 
 // Parse one command line option.
 
-static void gotflag(struct getoptflagstate *gof)
+static int gotflag(struct getoptflagstate *gof)
 {
        int type;
        struct opts *opt = gof->this;
 
        // Did we recognize this option?
        if (!opt) {
-               if (gof->noerror) return;
+               if (gof->noerror) return 1;
                error_exit("Unknown option %s", gof->arg);
        }
        toys.optflags |= opt->edx[0];
@@ -135,6 +135,7 @@ static void gotflag(struct getoptflagstate *gof)
        }
 
        gof->this = NULL;
+       return 0;
 }
 
 // Fill out toys.optflags and toys.optargs.
@@ -150,7 +151,7 @@ void get_optflags(void)
                int len;
        } *longopts = NULL;
        struct getoptflagstate gof;
-       long *nextarg = (long *)&this;
+       long *nextarg = (long *)&this, saveflags;
        char *options = toys.which->options;
        char *letters[]={"s",""};
 
@@ -302,6 +303,12 @@ void get_optflags(void)
                                        }
                                }
 
+                               // Should we handle this --longopt as a non-option argument?
+                               if (!lo && gof.noerror) {
+                                       gof.arg-=2;
+                                       goto notflag;
+                               }
+
                                // Long option parsed, handle option.
                                gotflag(&gof);
                                continue;
@@ -315,6 +322,7 @@ void get_optflags(void)
 
                // At this point, we have the args part of -args.  Loop through
                // each entry (could be -abc meaning -a -b -c)
+               saveflags = toys.optflags;
                while (*gof.arg) {
 
                        // Identify next option char.
@@ -322,7 +330,11 @@ void get_optflags(void)
                                if (*gof.arg == gof.this->c) break;
 
                        // Handle option char (advancing past what was used)
-                       gotflag(&gof);
+                       if (gotflag(&gof) ) {
+                               toys.optflags = saveflags;
+                               gof.arg = toys.argv[gof.argc];
+                               goto notflag;
+                       }
                }
                continue;
 
diff --git a/scripts/test/echo.test b/scripts/test/echo.test
new file mode 100755 (executable)
index 0000000..3eac172
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+[ -f testing.sh ] && . testing.sh
+
+# This one's tricky both because echo is a shell builtin (so $PATH is
+# irrelevant) and because the "result" field is parsed with echo -e.
+# To make it work, "$CMD" is an explicit path to the command being tested,
+# so "result" keeps using the shell builtin but we test the one in toybox.
+
+CMD="$(which echo)"
+
+#testing "name" "command" "result" "infile" "stdin"
+
+testing "echo" "$CMD && echo yes" "\nyes\n" "" ""
+testing "echo 1 2 3" "$CMD one  two    three" "one two three\n" "" ""
+testing "echo with spaces" "$CMD 'one  two     three'" \
+       "one  two       three\n" "" ""
+testing "echo -n" "$CMD -n" "" "" ""
+testing "echo -n one" "$CMD -n one" "one" "" ""
+testing "echo one -n" "$CMD one -n" "one -n\n" "" ""
+testing "echo -en" "$CMD -en 'one\ntwo'" "one\ntwo" "" ""
+testing "echo --hello" "$CMD --hello" "--hello\n" "" ""
+testing "echo -e all" "$CMD -e '\a\b\c\f\n\r\t\v\\\0123'" \
+       "\a\b\c\f\n\r\t\v\\\0123\n" "" ""
+testing "echo -nex hello" "$CMD -nex hello" "-nex hello\n" "" ""
index 8b4d7c5..fda008a 100644 (file)
@@ -6,7 +6,7 @@
  *
  * See http://www.opengroup.org/onlinepubs/009695399/utilities/echo.html
 
-USE_ECHO(NEWTOY(echo, "+en", TOYFLAG_BIN))
+USE_ECHO(NEWTOY(echo, "+?en", TOYFLAG_BIN))
 
 config ECHO
        bool "echo"
@@ -18,16 +18,16 @@ config ECHO
          by a newline.
 
          -n    No trailing newline.
-          -e   Process the following escape sequences:
-               \\      backslash
-               \a      alert (beep/flash)
-               \b      backspace
-               \c      Stop output here (avoids trailing newline)
-               \f      form feed
-               \n      newline
-               \r      carriage return
-               \t      horizontal tab
-               \v      vertical tab
+         -e    Process the following escape sequences:
+               \\      backslash
+               \a      alert (beep/flash)
+               \b      backspace
+               \c      Stop output here (avoids trailing newline)
+               \f      form feed
+               \n      newline
+               \r      carriage return
+               \t      horizontal tab
+               \v      vertical tab
 */
 
 #include "toys.h"