X-Git-Url: https://git.distorted.org.uk/~mdw/cfd/blobdiff_plain/4ab923c488adf11a9fd2be93afc8a8d9828268b8..6247b831dd0e3f9200025241ac93c14e5c1b2539:/mdwopt.c diff --git a/mdwopt.c b/mdwopt.c index fcea1b6..fc76635 100644 --- a/mdwopt.c +++ b/mdwopt.c @@ -1,7 +1,5 @@ /* -*-c-*- * - * $Id: mdwopt.c,v 1.8 1999/08/19 18:35:27 mdw Exp $ - * * Options parsing, similar to GNU @getopt_long@ * * (c) 1996 Straylight/Edgeware @@ -27,64 +25,6 @@ * MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: mdwopt.c,v $ - * Revision 1.8 1999/08/19 18:35:27 mdw - * Lots of reformatting. Spurious wing comments expunged. - * - * Revision 1.7 1999/06/18 21:59:46 mdw - * Fix stupid bug which only read one word from environment variables. - * - * Revision 1.6 1999/05/20 23:00:42 mdw - * Little formatting things. - * - * Revision 1.5 1999/05/19 20:23:59 mdw - * Change naming to match newer mLib conventions. - * - * Revision 1.4 1999/05/15 10:25:38 mdw - * Fix copyright information. - * - * Revision 1.3 1999/05/14 18:51:42 mdw - * Reformat the LGPL notice slightly. - * - * Revision 1.2 1999/05/13 22:57:23 mdw - * Change `-ise' to `-ize' throughout. - * - * Revision 1.1.1.1 1999/05/05 19:23:47 mdw - * New import. The old CVS repository was lost in a disk disaster. - * - * --- Previous lives --- - * - * %Log: mdwopt.c,v % - * Revision 1.7 1997/09/11 09:19:11 mdw - * (mo__nextWord): Arrrgh. Don't free the environment variable buffer! - * People are still using it! - * - * Revision 1.6 1997/09/11 09:05:54 mdw - * (mo__nextWord): Fix bug which returns too many words from environment - * variables. - * - * Revision 1.5 1997/08/09 20:27:59 mdw - * Fix spelling of `Licensing'. - * - * Revision 1.4 1997/07/29 21:11:35 mdw - * Reformatted. Fixed buffer overflow when dealing with environment - * variables. Included NT in list of daft operating systems with `\' as a - * path separator. Fixed address of the FSF. - * - * Revision 1.3 1997/02/26 00:41:10 mdw - * Added GPL notice to the top. Slight formatting changes. - * - * Revision 1.2 1996/10/28 13:12:13 mdw - * Fixed calls to ctype.h routines. Arguments are cast to unsigned char - * to avoid invoking undefined behaviour caused by signedness of chars. - * - * Revision 1.1 1996/09/24 18:01:28 mdw - * Initial revision - * - */ - /*----- External dependencies ---------------------------------------------*/ #include @@ -115,9 +55,96 @@ enum { ORD_NEGATE = 4 /* Magic negate-next-thing flag */ }; +/*----- Word splitting ----------------------------------------------------*/ + +#ifdef BUILDING_MLIB +# include "str.h" +# define qword str_qword +#else + +/* --- @qword@ --- * + * + * Arguments: @char **pp@ = address of pointer into string + * @unsigned f@ = various flags + * + * Returns: Pointer to the next space-separated possibly-quoted word from + * the string, or null. + * + * Use: Fetches the next word from a string. If the flag + * @STRF_QUOTE@ is set, the `\' character acts as an escape, and + * single and double quotes protect whitespace. + */ + +#define STRF_QUOTE 1u + +static char *qword(char **pp, unsigned f) +{ + char *p = *pp, *q, *qq; + int st = 0, pst = 0; + + /* --- Preliminaries --- */ + + if (!p) + return (0); + while (isspace((unsigned char)*p)) + p++; + if (!*p) { + *pp = 0; + return (0); + } + + /* --- Main work --- */ + + for (q = qq = p; *q; q++) { + switch (st) { + case '\\': + *qq++ = *q; + st = pst; + break; + case '\'': + case '\"': + if (*q == st) + st = pst = 0; + else if (*q == '\\') + st = '\\'; + else + *qq++ = *q; + break; + default: + if (isspace((unsigned char)*q)) { + do q++; while (*q && isspace((unsigned char)*q)); + goto done; + } else if (!(f & STRF_QUOTE)) + goto stdchar; + switch (*q) { + case '\\': + st = '\\'; + break; + case '\'': + case '\"': + st = pst = *q; + break; + default: + stdchar: + *qq++ = *q; + break; + } + } + } + + /* --- Finished --- */ + +done: + *pp = *q ? q : 0; + *qq++ = 0; + return (p); +} + +#endif + /*----- Main code ---------------------------------------------------------*/ -/* --- @nextWord@ --- * +/* --- @nextword@ --- * * * Arguments: @int argc@ = number of command line options * @char *argv[]@ = pointer to command line options @@ -129,22 +156,12 @@ enum { * variable. */ -static char *nextWord(int argc, char *const *argv, mdwopt_data *data) +static char *nextword(int argc, char *const *argv, mdwopt_data *data) { if (data->ind == -1) { - char *p = data->env; - char *q; - while (isspace((unsigned char)*p)) - p++; - q = p; - while (*p && !isspace((unsigned char)*p)) - p++; - if (*p) - *p++ = 0; - data->env = p; - if (p != q) - return (q); - data->env = 0; + char *p; + if ((p = qword(&data->env, STRF_QUOTE)) != 0) + return (p); data->ind = 1; } @@ -558,7 +575,7 @@ int mdwopt(int argc, char *const *argv, */ for (;;) { - p = nextWord(argc, argv, data); + p = nextword(argc, argv, data); if (!p) return (EOF); @@ -707,7 +724,7 @@ int mdwopt(int argc, char *const *argv, case OPTF_ARGREQ: if (!p) { - p = nextWord(argc, argv, data); + p = nextword(argc, argv, data); if (!p) { if (data->err) { @@ -787,7 +804,7 @@ int mdwopt(int argc, char *const *argv, /* --- Same code as before --- */ - q = nextWord(argc, argv, data); + q = nextword(argc, argv, data); if (!q) { if (data->err) { fprintf(stderr, "%s: option `%c%c' requires an argument\n",