Mercurial > hg > toybox
changeset 1071:e7454bb7af5a draft
Fluff out option parsing documentation, add another DEBUG test.
author | Rob Landley <rob@landley.net> |
---|---|
date | Sat, 21 Sep 2013 12:24:04 -0500 |
parents | 16167a7c1b5a |
children | 7a45b9b54d3d |
files | lib/args.c |
diffstat | 1 files changed, 66 insertions(+), 48 deletions(-) [+] |
line wrap: on
line diff
--- a/lib/args.c Mon Sep 16 23:41:51 2013 -0500 +++ b/lib/args.c Sat Sep 21 12:24:04 2013 -0500 @@ -6,50 +6,9 @@ #include "toys.h" // Design goals: -// Don't use getopt() -// Don't permute original arguments. -// handle --long gracefully "(noshort)a(along)b(blong1)(blong2)" -// After each argument: -// 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 -// <LOW - die if less than LOW -// >HIGH - die if greater than HIGH -// =DEFAULT - value if not specified -// - plus a signed long argument defaulting to negative -// . plus a double precision floating point argument (with CFG_TOYBOX_FLOAT) -// Chop this out with USE_TOYBOX_FLOAT() around option string -// Same <LOW>HIGH=DEFAULT as # -// @ plus an occurrence counter (which is a long) -// (longopt) -// | this is required. If more than one marked, only one required. -// ; long option's argument is optional, can only be supplied with --opt= -// ^ Stop parsing after encountering this argument -// " " (space char) the "plus an argument" must be separate -// I.E. "-j 3" not "-j3". So "kill -stop" != "kill -s top" -// -// at the beginning: -// ^ stop at first nonoption argument -// <0 die if less than # leftover arguments (default 0) -// >9 die if > # leftover arguments (default MAX_INT) -// ? Allow unknown arguments (pass them through to command). -// & first argument has imaginary dash (ala tar/ps) -// If given twice, all arguments have imaginary dash -// -// At the end: [groups] of previously seen options -// - Only one in group (switch off) [-abc] means -ab=-b, -ba=-a, -abc=-c -// | Synonyms (switch on all) [|abc] means -ab=-abc, -c=-abc -// ! More than one in group is error [!abc] means -ab calls error_exit() -// + First in group switches rest on [+abc] means -a=-abc, -b=-b, -c=-c -// primarily useful if you can switch things back off again. -// - -// Notes from getopt man page -// - and -- cannot be arguments. -// -- force end of arguments -// - is a synonym for stdin in file arguments -// -abc means -a -b -c +// Don't use getopt() out of libc. +// Don't permute original arguments (screwing up ps/top output). +// Integrated --long options "(noshort)a(along)b(blong1)(blong2)" /* This uses a getopt-like option string, but not getopt() itself. We call * it the get_opt string. @@ -70,17 +29,70 @@ * argv = ["command", "-b", "fruit", "-d", "walrus"] results in: * * Changes to struct toys: - * toys.optflags = 5 (-b=4 | -d=1) - * toys.optargs[0]="walrus" (leftover argument) - * toys.optargs[1]=NULL (end of list) - * toys.optc=1 (there was 1 leftover argument) + * toys.optflags = 5 (I.E. 0101 so -b = 4 | -d = 1) + * toys.optargs[0] = "walrus" (leftover argument) + * toys.optargs[1] = NULL (end of list) + * toys.optc = 1 (there was 1 leftover argument) * * Changes to union this: * this[0]=NULL (because -c didn't get an argument this time) * this[1]="fruit" (argument to -b) */ +// Enabling TOYBOX_DEBUG in .config adds syntax checks to option string parsing +// which aren't needed in the final code (your option string is hardwired and +// should be correct when you ship), but are useful for development. + +// What you can put in a get_opt string: +// Any otherwise unused character (all letters, unprefixed numbers) specify +// an option that sets a flag. The bit value is the same as the binary digit +// if you string the option characters together in order. +// So in "abcdefgh" a = 128, h = 1 +// +// Suffixes specify that this option takes an argument (stored in GLOBALS): +// 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 +// <LOW - die if less than LOW +// >HIGH - die if greater than HIGH +// =DEFAULT - value if not specified +// - plus a signed long argument defaulting to negative (say + for positive) +// . plus a double precision floating point argument (with CFG_TOYBOX_FLOAT) +// Chop this option out with USE_TOYBOX_FLOAT() in option string +// Same <LOW>HIGH=DEFAULT as # +// @ plus an occurrence counter (which is a long) +// (longopt) +// | this is required. If more than one marked, only one required. +// ; long option's argument is optional (can only be supplied with --opt=) +// ^ Stop parsing after encountering this argument +// " " (space char) the "plus an argument" must be separate +// I.E. "-j 3" not "-j3". So "kill -stop" != "kill -s top" +// +// At the beginning of the get_opt string (before any options): +// ^ stop at first nonoption argument +// <0 die if less than # leftover arguments (default 0) +// >9 die if > # leftover arguments (default MAX_INT) +// ? Allow unknown arguments (pass them through to command). +// & first argument has imaginary dash (ala tar/ps) +// If given twice, all arguments have imaginary dash +// +// At the end: [groups] of previously seen options +// - Only one in group (switch off) [-abc] means -ab=-b, -ba=-a, -abc=-c +// | Synonyms (switch on all) [|abc] means -ab=-abc, -c=-abc +// ! More than one in group is error [!abc] means -ab calls error_exit() +// + First in group switches rest on [+abc] means -a=-abc, -b=-b, -c=-c +// primarily useful if you can switch things back off again. +// + +// Notes from getopt man page +// - and -- cannot be arguments. +// -- force end of arguments +// - is a synonym for stdin in file arguments +// -abcd means -a -b -c -d (but if -b takes an argument, then it's -a -b cd) + // Linked list of all known options (option string parsed into this). +// Hangs off getoptflagstate, freed at end of option parsing. struct opts { struct opts *next; long *arg; // Pointer into union "this" to store arguments at. @@ -94,6 +106,10 @@ } val[3]; // low, high, default - range of allowed values }; +// linked list of long options. (Hangs off getoptflagstate, free at end of +// option parsing, details about flag to set and global slot to fill out +// stored in related short option struct, but if opt->c = -1 the long option +// is "bare" (has no corresponding short option). struct longopts { struct longopts *next; struct opts *opt; @@ -325,6 +341,8 @@ idx = stridx("-|!+", *++options); if (CFG_TOYBOX_DEBUG && idx == -1) error_exit("[ needs +-!"); + if (CFG_TOYBOX_DEBUG && (*options == ']' || !options)) + error_exit("empty []"); // Don't advance past ] but do process it once in loop. while (*(options++) != ']') {