/* argloop.c 2.9.0 92/07/06 - interpret command-line arguments * ----------------------------------------------------------------------- This software module copyright (c) 1990, 1991 Damian Cugley. It is provided for free on an "as-is" basis. See the file COPYING for more information. See argloop(3) for more information on this software module. ----------------------------------------------------------------------- * 2.0 * created - Damian Cugley Fri 12 Jan 1990 * 2.1 * files as well * 2.2 * Standard initalisiation files * 2.3 - pdc Sun 25 Feb 1990 * Added the global variable |verbose| to argloop rather than importing * it from the main program. * 2.4 - pdc Mon 2 Apr 1990 * Added argloop_verbatim * 2.5 - pdc Mon 14 May 1990 * -vf+qz is same as -v -f +q +z * 2.7 - pdc Sat. 2 Mar. 1991 * uses simpler file format (less shell-like) * Made properly reentrant (!) * 2.7.1 - pdc Tue. 12 Mar. 1991 * Put xmalloc in strword.c & added strmisc header file * 2.7.2 - pdc Fri. 21 June 1991 * Added support for MS-DOS filenames */ #include "config.h" #include "xstdio.h" /* plus prototypes */ #include "strmisc.h" /* inludes */ #include "argloop.h" #ifndef NDEBUG int argloop_debug = 0; # define log1(X,A) if (argloop_debug) fprintf(stderr, X,A) #else # define log1(X,A) #endif int argloop_verbatim = 0; typedef char *(*Argloop_next_fn)ARGS((void)); void argloop(cxt, opts) Argloop_context *cxt; Argloop_options *opts; { register const char *p; int flag; /* Boolean */ const char *arg; if (!cxt) return; arg = (cxt->first ? cxt->first : cxt->word(cxt->data)); while (arg) { log1("%%%%%s\n", arg); if (argloop_verbatim || !(*arg == '-' || *arg == '+')) opts->arg(0, arg); /* unflagged argument */ else { flag = (*arg == '-'); while (*++arg) { for (p = opts->optstring; *p && *p != *arg; p++) ; /* search for flag letter */ if (!*p) { if (*arg == '-' || *arg == '+') flag = (*arg == '-'); else { opts->error(*arg); return; } } else if (flag && *(p + 1) == ':') { /* this flag wants an argument too */ if (*++arg) { /* use the remainder of this cmd-line arg */ opts->arg(*p, arg); } else { /* get new cmd-line arg */ const char *t = cxt->word(cxt->data); log1("%%%%%%\"%s\"\n", (t ? t : "[NIL]") ); opts->arg(*p, t); if (!t) { if (cxt->free) cxt->free(cxt->data); return; } } break; /* from inner while loop */ } else opts->flag(*p, flag); } } arg = cxt->word(cxt->data); } if (cxt->free) cxt->free(cxt->data); xfree((addr)cxt); } /* * How to use the above to parse command-line arguments */ struct argv { int argc; const char **argv; }; static const char * argv_word(st) struct argv *st; { return ((--st->argc > 0) ? *++st->argv : (char *)0); } static void argv_free(st) struct argv *st; { xfree(st); } Argloop_context * al_argv(argc, argv) int argc; const char *argv[]; { struct argv *av = (struct argv *)xmalloc(sizeof (struct argv)); Argloop_context *cxt = (Argloop_context *)xmalloc(sizeof (Argloop_context)); av->argc = argc; av->argv = argv; cxt->data = (char *)av; cxt->first = (char *)0; cxt->word = argv_word; cxt->free = argv_free; return cxt; } static const char * string_word(st) char **st; { return strword((char *)0, st); } static void string_free(st) char **st; { xfree(st); } Argloop_context * al_string(string) char *string; /* will be destroyed */ { Argloop_context *cxt; if (!string) return (Argloop_context *)0; cxt = (Argloop_context *)xmalloc(sizeof (Argloop_context)); cxt->word = string_word; cxt->free = string_free; cxt->data = xmalloc(sizeof (char *)); cxt->first = strword(string, (char **)cxt->data); return cxt; }