changeset 78:cd1f36a96185

Update args.c to implement numeric arguments.
author Rob Landley <rob@landley.net>
date Thu, 25 Jan 2007 16:11:23 -0500
parents 8018c40605d9
children 1aff4181427b
files lib/args.c toys/toylist.h
diffstat 2 files changed, 30 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/lib/args.c	Thu Jan 25 16:10:37 2007 -0500
+++ b/lib/args.c	Thu Jan 25 16:11:23 2007 -0500
@@ -14,7 +14,7 @@
 //       Note that pointer and long are always the same size, even on 64 bit.
 //     : plus a string argument, keep most recent if more than one
 //     * plus a string argument, appended to a list
-//     ? plus a signed long argument (TODO: Bounds checking?)
+//     # plus a signed long argument (TODO: Bounds checking?)
 //     @ plus an occurrence counter (which is a long)
 //     | this is required.  If more than one marked, only one required.
 //     (longopt)
@@ -27,7 +27,7 @@
 //     + stop at first nonoption argument
 //     <0 at least # leftover arguments needed (default 0)
 //     >9 at most # leftover arguments needed (default MAX_INT)
-//     # don't show_usage() on unknown argument.
+//     ? don't show_usage() on unknown argument.
 //     & first argument has imaginary dash (ala tar/ps)
 //       If given twice, all arguments have imaginary dash
 
@@ -39,18 +39,25 @@
 
 /* This uses a getopt-like option string, but not getopt() itself.
  * 
- *   Each option in options corresponds to a bit position in the return
- * value (last argument is (1<<0), the next to last is (1<<1) and so on.
- * If the option isn't seen in argv its bit is 0.  Options which have an
- * argument use the next vararg.  (So varargs used by options go from left to
- * right, but bits set by arguments go from right to left.)
+ * Each option in options corresponds to a bit position in the return
+ * value (last argument is (1<<0), the next to last is (1<<1) and so on).
+ * If the option isn't seen in argv[] its bit is 0.
+ *
+ * Options which have an argument fill in the corresponding slot in the global
+ * toys.command struct, which it treats as an array of longs (note that
+ * sizeof(long)==sizeof(pointer) is guaranteed by LP64).
+ *
+ * You don't have to free the option strings, which point into the environment
+ * space.  List list objects should be freed by main() when command_main()
+ * returns.
  *
  * Example:
- *   get_optflags("ab:c:d", NULL, &bstring, &cstring);
+ *   get_optflags() when toys.which->options="ab:c:d"
  *   argv = ["command", "-b", "fruit", "-d"]
- *   flags = 5, bstring="fruit", cstring=NULL;
+ *   flags = 5, toy[0]=NULL, toy[1]="fruit";
  */
 
+// 
 struct opts {
 	struct opts *next;
 	char c;
@@ -101,8 +108,8 @@
 			temp->arg = gof.arg;
 			temp->next = *list;
 			*list = temp;
-		} else if (type == '?') {
-		} else if (type == '@') {
+		} else if (type == '#') *(gof.this->arg) = atol((char *)gof.arg);
+		else if (type == '@') {
 		}
 
 		gof.arg = "";
@@ -139,7 +146,7 @@
 			if (*options == '+') stopearly++;
 			else if (*options == '<') minargs=*(++options)-'0';
 			else if (*options == '>') maxargs=*(++options)-'0';
-			else if (*options == '#') gof.noerror++;
+			else if (*options == '?') gof.noerror++;
 			else if (*options == '&') nodash++;
 			else break;
 			options++;
@@ -179,11 +186,8 @@
 
 			// If this is the start of a new option that wasn't a longopt,
 
-			} else if (index(":*?@", *options)) {
+			} else if (index(":*#@", *options)) {
 				gof.this->type |= *options;
-				// Pointer and long guaranteed to be the same size by LP64.
-				gof.this->arg = (void *)nextarg;
-				*(nextarg++) = 0;
 			} else if (*options == '|') {
 			} else if (*options == '+') {
 			} else if (*options == '~') {
@@ -205,12 +209,17 @@
 		}
 	}
 
-	// Initialize shift bits (have to calculate this ahead of time because
-	// longopts jump into the middle of the list), and allocate space to
-	// store optargs.
+	// Initialize shift bits and pointers to store arguments.  (We have to
+	// calculate this ahead of time because longopts jump into the middle of
+	// the list.)
 	gof.argc = 0;
-	for (gof.this = gof.opts; gof.this; gof.this = gof.this->next)
+	for (gof.this = gof.opts; gof.this; gof.this = gof.this->next) {
 		gof.this->shift = gof.argc++;
+		if (gof.this->type & 255) {
+			gof.this->arg = (void *)nextarg;
+			*(nextarg++) = 0;
+		}
+	}
 
 	// Iterate through command line arguments, skipping argv[0]
 	for (gof.argc=1; toys.argv[gof.argc]; gof.argc++) {
--- a/toys/toylist.h	Thu Jan 25 16:10:37 2007 -0500
+++ b/toys/toylist.h	Thu Jan 25 16:11:23 2007 -0500
@@ -37,7 +37,7 @@
 };
 
 // "E:jJ:L:m:O:"
-#define MKE2FS_OPTSTRING "<1>2Fnqm:N:i:b:"
+#define MKE2FS_OPTSTRING "<1>2Fnqm#N#i#b#"
 
 union toy_union {
 	struct df_data df;