diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/wordsplit.c | 75 |
1 files changed, 61 insertions, 14 deletions
diff --git a/src/wordsplit.c b/src/wordsplit.c index 9381ae7..4884a22 100644 --- a/src/wordsplit.c +++ b/src/wordsplit.c @@ -671,13 +671,41 @@ wordsplit_finish (struct wordsplit *wsp) } wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc] = NULL; return 0; } +int +wordsplit_append (wordsplit_t *wsp, int argc, char **argv) +{ + int rc; + size_t i; + rc = alloc_space (wsp, wsp->ws_wordc + argc + 1); + if (rc) + return rc; + for (i = 0; i < argc; i++) + { + char *newstr = strdup (argv[i]); + if (!newstr) + { + while (i > 0) + { + free (wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc + i - 1]); + wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc + i - 1] = NULL; + i--; + } + return _wsplt_nomem (wsp); + } + wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc + i] = newstr; + } + wsp->ws_wordc += i; + wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc] = NULL; + return 0; +} + /* Variable expansion */ static int node_split_prefix (struct wordsplit *wsp, struct wordsplit_node **ptail, struct wordsplit_node *node, size_t beg, size_t len, int flg) @@ -1012,13 +1040,15 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, } else if (wsp->ws_flags & WRDSF_GETVAR) rc = wsp->ws_getvar (&value, str, i, wsp->ws_closure); else rc = WRDSE_UNDEF; - if (rc == WRDSE_OK && value[0] == 0 && defstr && defstr[-1] == ':') + if (rc == WRDSE_OK + && (!value || value[0] == 0) + && defstr && defstr[-1] == ':') { free (value); rc = WRDSE_UNDEF; } } @@ -1329,13 +1359,12 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len, *pend = str + j; if (wsp->ws_options & WRDSO_ARGV) { struct wordsplit ws; rc = _wsplt_subsplit (wsp, &ws, str, j, - WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_WS | WRDSF_QUOTE); if (rc) { _wsplt_seterr_sub (wsp, &ws); wordsplit_free (&ws); return 1; @@ -2062,35 +2091,47 @@ wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex) } } } } } + +/* This structure describes a single expansion phase */ struct exptab { - char *descr; - int flag; - int opt; - int (*expansion) (struct wordsplit *wsp); + char *descr; /* Textual description (for debugging) */ + int flag; /* WRDSF_ bit that controls this phase */ + int opt; /* Entry-specific options (see EXPOPT_ flags below */ + int (*expansion) (struct wordsplit *wsp); /* expansion function */ }; +/* The following options control expansions: */ +/* Normally the exptab entry is run if its flag bit is set in struct + wordsplit. The EXPOPT_NEG option negates this test so that expansion + is performed if its associated flag bit is not set in struct wordsplit. */ #define EXPOPT_NEG 0x01 +/* Coalesce the input list before running the expansion. */ #define EXPOPT_COALESCE 0x02 static struct exptab exptab[] = { - { N_("WS trimming"), WRDSF_WS, 0, wordsplit_trimws }, - { N_("tilde expansion"), WRDSF_PATHEXPAND, 0, wordsplit_tildexpand }, + { N_("WS trimming"), WRDSF_WS, 0, + wordsplit_trimws }, + { N_("command substitution"), WRDSF_NOCMD, EXPOPT_NEG|EXPOPT_COALESCE, + wordsplit_cmdexp }, + { N_("coalesce list"), 0, EXPOPT_NEG|EXPOPT_COALESCE, + NULL }, + { N_("tilde expansion"), WRDSF_PATHEXPAND, 0, + wordsplit_tildexpand }, { N_("variable expansion"), WRDSF_NOVAR, EXPOPT_NEG, wordsplit_varexp }, { N_("quote removal"), 0, EXPOPT_NEG, wsnode_quoteremoval }, - { N_("command substitution"), WRDSF_NOCMD, EXPOPT_NEG|EXPOPT_COALESCE, - wordsplit_cmdexp }, { N_("coalesce list"), 0, EXPOPT_NEG|EXPOPT_COALESCE, NULL }, - { N_("path expansion"), WRDSF_PATHEXPAND, 0, wordsplit_pathexpand }, + { N_("path expansion"), WRDSF_PATHEXPAND, 0, + wordsplit_pathexpand }, { NULL } }; static int wordsplit_process_list (struct wordsplit *wsp, size_t start) { @@ -2098,12 +2139,13 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start) if (wsp->ws_flags & WRDSF_NOSPLIT) { /* Treat entire input as a quoted argument */ if (wordsplit_add_segm (wsp, start, wsp->ws_len, _WSNF_QUOTE)) return wsp->ws_errno; + wsp->ws_endp = wsp->ws_len; } else { int rc; while ((rc = scan_word (wsp, start)) == _WRDS_OK) @@ -2279,22 +2321,27 @@ wordsplit_free (struct wordsplit *ws) wordsplit_free_words (ws); free (ws->ws_wordv); ws->ws_wordv = NULL; wordsplit_free_envbuf (ws); } -void -wordsplit_getwords (struct wordsplit *ws, size_t *wordc, char ***wordv) +int +wordsplit_get_words (struct wordsplit *ws, size_t *wordc, char ***wordv) { char **p = realloc (ws->ws_wordv, (ws->ws_wordc + 1) * sizeof (ws->ws_wordv[0])); - *wordv = p ? p : ws->ws_wordv; + if (!p) + return -1; + *wordv = p; *wordc = ws->ws_wordc; + ws->ws_wordv = NULL; ws->ws_wordc = 0; ws->ws_wordn = 0; + + return 0; } const char *_wordsplit_errstr[] = { N_("no error"), N_("missing closing quote"), N_("memory exhausted"), |