From 1a221d9b4f058d05aa250691c381f0cfeaaeab9e Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 17 May 2008 17:13:26 -0500 Subject: Fix command line option parsing so "echo -xen" actually prints "-xen". Add echo.test while I'm at it. --- lib/args.c | 20 ++++++++++++++++---- scripts/test/echo.test | 25 +++++++++++++++++++++++++ toys/echo.c | 22 +++++++++++----------- 3 files changed, 52 insertions(+), 15 deletions(-) create mode 100755 scripts/test/echo.test diff --git a/lib/args.c b/lib/args.c index 808125fd..6103bb0c 100644 --- a/lib/args.c +++ b/lib/args.c @@ -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 index 00000000..3eac172f --- /dev/null +++ b/scripts/test/echo.test @@ -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" "" "" diff --git a/toys/echo.c b/toys/echo.c index 8b4d7c58..fda008af 100644 --- a/toys/echo.c +++ b/toys/echo.c @@ -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" -- cgit v1.2.3