From 401898110f0c584769f5a0b342993f447553da50 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Tue, 17 May 2022 09:22:20 -0500 Subject: [PATCH] Add ~ to collate bare longopts. --- lib/args.c | 10 +++++----- lib/portability.h | 8 ++++++-- scripts/mkflags.c | 21 ++++++++++++++------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/lib/args.c b/lib/args.c index 2b8da7c7..ce748948 100644 --- a/lib/args.c +++ b/lib/args.c @@ -71,13 +71,13 @@ // 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 arg has imaginary dash (ala tar/ps/ar) which sets FLAGS_NODASH // 0 Include argv[0] in optargs -// note: ^ and ? implied when no options +// ^ stop at first nonoption argument (implied when no flags) +// ? Pass unknown arguments through to command (implied when no flags). +// & first arg has imaginary dash (ala tar/ps/ar) which sets FLAGS_NODASH +// ~ Collate following bare longopts (as if under short opt, repeatable) // // At the end: [groups] of previously seen options // - Only one in group (switch off) [-abc] means -ab=-b, -ba=-a, -abc=-c @@ -332,7 +332,7 @@ static int parse_optflaglist(struct getoptflagstate *gof) for (new = gof->opts; new; new = new->next) { unsigned long long u = 1LL<c == 1) new->c = 0; + if (new->c == 1 || new->c=='~') new->c = 0; new->dex[1] = u; if (new->flags & 1) gof->requires |= u; if (new->type) { diff --git a/lib/portability.h b/lib/portability.h index 77b6a2a6..cefc3a37 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -292,8 +292,12 @@ typedef float FLOAT; pid_t xfork(void); #endif -//#define strncpy(...) @@strncpyisbadmmkay@@ -//#define strncat(...) @@strncatisbadmmkay@@ +// gratuitously memsets ALL the extra space with zeroes (not just a terminator) +// but to make up for it truncating doesn't null terminate the output at all. +// There are occasions to use it, but it is NOT A GENERAL PURPOSE FUNCTION. +// #define strncpy(...) @@strncpyisbadmmkay@@ +// strncat writes a null terminator one byte PAST the buffer size it's given. +#define strncat(...) strncatisbadmmkay // Support building the Android tools on glibc, so hermetic AOSP builds can // use toybox before they're ready to switch to host bionic. diff --git a/scripts/mkflags.c b/scripts/mkflags.c index 6560db50..222b00b9 100644 --- a/scripts/mkflags.c +++ b/scripts/mkflags.c @@ -1,5 +1,5 @@ // Take three word input lines on stdin and produce flag #defines to stdout. -// The three words on each input lnie are command name, option string with +// The three words on each input line are command name, option string with // current config, option string from allyesconfig. The three are space // separated and the last two are in double quotes. @@ -14,9 +14,8 @@ #include struct flag { - struct flag *next; + struct flag *next, *lopt; char *command; - struct flag *lopt; }; int chrtype(char c) @@ -38,7 +37,7 @@ int chrtype(char c) char *mark_gaps(char *flags, char *all) { char *n, *new, c; - int bare = 2; + int bare = 1; // Shell feeds in " " for blank args, leading space not meaningful. while (isspace(*flags)) flags++; @@ -50,7 +49,6 @@ char *mark_gaps(char *flags, char *all) if (*all == '(') { int len = 0; - if (bare) bare = 1; while (all[len]) if (all[len++] == ')') break; if (strncmp(flags, all, len)) { // bare longopts need their own skip placeholders @@ -95,6 +93,10 @@ struct flag *digest(char *string) if (*string == '(') { struct flag *new = calloc(sizeof(struct flag), 1); + if (string[1]==')') { + fprintf(stderr, "empty () longopt in '%s'", err); + exit(1); + } new->command = ++string; // Attach longopt to previous short opt, if any. @@ -131,6 +133,10 @@ struct flag *digest(char *string) } else { struct flag *new = calloc(sizeof(struct flag), 1); + if (string[0]=='~' && string[1]!='(') { + fprintf(stderr, "~ without (longopt) in '%s'", err); + exit(1); + } new->command = string++; new->next = list; list = new; @@ -208,7 +214,8 @@ int main(int argc, char *argv[]) while (offlist) { char *s = (char []){0, 0, 0, 0}; - if (!offlist->command) s = offlist->lopt->command; + if (!offlist->command || *offlist->command=='~') + s = offlist->lopt->command; else { *s = *offlist->command; if (127 < (unsigned char)*s) sprintf(s, "X%02X", 127&*s); @@ -227,7 +234,7 @@ int main(int argc, char *argv[]) int enabled = 0; // Output flag macro for bare longopts - if (!aflist->command) { + if (!aflist->command || *aflist->command=='~') { s = aflist->lopt->command; if (flist && flist->lopt && !strcmp(flist->lopt->command, aflist->lopt->command)) enabled++; -- 2.39.2