changeset 294:3de1ea4d6b56

Fix command line option parsing so "echo -xen" actually prints "-xen". Add echo.test while I'm at it.
author Rob Landley <rob@landley.net>
date Sat, 17 May 2008 17:13:26 -0500
parents 6baa13382880
children 5a0faa267866
files lib/args.c scripts/test/echo.test toys/echo.c
diffstat 3 files changed, 52 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/lib/args.c	Mon May 12 01:23:19 2008 -0500
+++ b/lib/args.c	Sat May 17 17:13:26 2008 -0500
@@ -88,14 +88,14 @@
 
 // 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 @@
 	}
 
 	gof->this = NULL;
+	return 0;
 }
 
 // Fill out toys.optflags and toys.optargs.
@@ -150,7 +151,7 @@
 		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 @@
 					}
 				}
 
+				// 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 @@
 
 		// 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 @@
 				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;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/test/echo.test	Sat May 17 17:13:26 2008 -0500
@@ -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" "" ""
--- a/toys/echo.c	Mon May 12 01:23:19 2008 -0500
+++ b/toys/echo.c	Sat May 17 17:13:26 2008 -0500
@@ -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 @@
 	  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"