From d0da523a3f8ef2686af201acbcfb9bb85968eca2 Mon Sep 17 00:00:00 2001 From: mdw Date: Sun, 8 Oct 2000 09:57:31 +0000 Subject: [PATCH] Use a copy of @str_qword@ for word splitting, to handle quotes properly. If building in mLib, use the real thing directly rather than the copy. --- mdwopt.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 101 insertions(+), 19 deletions(-) diff --git a/mdwopt.c b/mdwopt.c index fcea1b6..167772b 100644 --- a/mdwopt.c +++ b/mdwopt.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: mdwopt.c,v 1.8 1999/08/19 18:35:27 mdw Exp $ + * $Id: mdwopt.c,v 1.9 2000/10/08 09:57:31 mdw Exp $ * * Options parsing, similar to GNU @getopt_long@ * @@ -30,6 +30,11 @@ /*----- Revision history --------------------------------------------------* * * $Log: mdwopt.c,v $ + * Revision 1.9 2000/10/08 09:57:31 mdw + * Use a copy of @str_qword@ for word splitting, to handle quotes + * properly. If building in mLib, use the real thing directly rather than + * the copy. + * * Revision 1.8 1999/08/19 18:35:27 mdw * Lots of reformatting. Spurious wing comments expunged. * @@ -115,9 +120,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 +221,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 +640,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 +789,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 +869,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", -- 2.11.0