aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wordsplit.h13
-rw-r--r--src/wordsplit.c75
-rw-r--r--tests/wordsplit.at69
-rw-r--r--tests/wsp.c21
4 files changed, 155 insertions, 23 deletions
diff --git a/include/wordsplit.h b/include/wordsplit.h
index a7f6dd5..eed88bc 100644
--- a/include/wordsplit.h
+++ b/include/wordsplit.h
@@ -235,7 +235,18 @@ int wordsplit_len (const char *s, size_t len, wordsplit_t *ws, int flags);
235void wordsplit_free (wordsplit_t *ws); 235void wordsplit_free (wordsplit_t *ws);
236void wordsplit_free_words (wordsplit_t *ws); 236void wordsplit_free_words (wordsplit_t *ws);
237void wordsplit_free_envbuf (wordsplit_t *ws); 237void wordsplit_free_envbuf (wordsplit_t *ws);
238void wordsplit_getwords (wordsplit_t *ws, size_t *wordc, char ***wordv); 238int wordsplit_get_words (wordsplit_t *ws, size_t *wordc, char ***wordv);
239
240static inline void wordsplit_getwords (wordsplit_t *ws, size_t *wordc, char ***wordv)
241 __attribute__ ((deprecated));
242
243static inline void
244wordsplit_getwords (wordsplit_t *ws, size_t *wordc, char ***wordv)
245{
246 wordsplit_get_words (ws, wordc, wordv);
247}
248
249int wordsplit_append (wordsplit_t *wsp, int argc, char **argv);
239 250
240int wordsplit_c_unquote_char (int c); 251int wordsplit_c_unquote_char (int c);
241int wordsplit_c_quote_char (int c); 252int wordsplit_c_quote_char (int c);
diff --git a/src/wordsplit.c b/src/wordsplit.c
index 9381ae7..4884a22 100644
--- a/src/wordsplit.c
+++ b/src/wordsplit.c
@@ -674,7 +674,35 @@ wordsplit_finish (struct wordsplit *wsp)
674 return 0; 674 return 0;
675} 675}
676 676
677int
678wordsplit_append (wordsplit_t *wsp, int argc, char **argv)
679{
680 int rc;
681 size_t i;
677 682
683 rc = alloc_space (wsp, wsp->ws_wordc + argc + 1);
684 if (rc)
685 return rc;
686 for (i = 0; i < argc; i++)
687 {
688 char *newstr = strdup (argv[i]);
689 if (!newstr)
690 {
691 while (i > 0)
692 {
693 free (wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc + i - 1]);
694 wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc + i - 1] = NULL;
695 i--;
696 }
697 return _wsplt_nomem (wsp);
698 }
699 wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc + i] = newstr;
700 }
701 wsp->ws_wordc += i;
702 wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc] = NULL;
703 return 0;
704}
705
678/* Variable expansion */ 706/* Variable expansion */
679static int 707static int
680node_split_prefix (struct wordsplit *wsp, 708node_split_prefix (struct wordsplit *wsp,
@@ -1015,7 +1043,9 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
1015 else 1043 else
1016 rc = WRDSE_UNDEF; 1044 rc = WRDSE_UNDEF;
1017 1045
1018 if (rc == WRDSE_OK && value[0] == 0 && defstr && defstr[-1] == ':') 1046 if (rc == WRDSE_OK
1047 && (!value || value[0] == 0)
1048 && defstr && defstr[-1] == ':')
1019 { 1049 {
1020 free (value); 1050 free (value);
1021 rc = WRDSE_UNDEF; 1051 rc = WRDSE_UNDEF;
@@ -1332,7 +1362,6 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
1332 struct wordsplit ws; 1362 struct wordsplit ws;
1333 1363
1334 rc = _wsplt_subsplit (wsp, &ws, str, j, 1364 rc = _wsplt_subsplit (wsp, &ws, str, j,
1335 WRDSF_NOVAR | WRDSF_NOCMD |
1336 WRDSF_WS | WRDSF_QUOTE); 1365 WRDSF_WS | WRDSF_QUOTE);
1337 if (rc) 1366 if (rc)
1338 { 1367 {
@@ -2065,29 +2094,41 @@ wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex)
2065 } 2094 }
2066} 2095}
2067 2096
2097
2098/* This structure describes a single expansion phase */
2068struct exptab 2099struct exptab
2069{ 2100{
2070 char *descr; 2101 char *descr; /* Textual description (for debugging) */
2071 int flag; 2102 int flag; /* WRDSF_ bit that controls this phase */
2072 int opt; 2103 int opt; /* Entry-specific options (see EXPOPT_ flags below */
2073 int (*expansion) (struct wordsplit *wsp); 2104 int (*expansion) (struct wordsplit *wsp); /* expansion function */
2074}; 2105};
2075 2106
2107/* The following options control expansions: */
2108/* Normally the exptab entry is run if its flag bit is set in struct
2109 wordsplit. The EXPOPT_NEG option negates this test so that expansion
2110 is performed if its associated flag bit is not set in struct wordsplit. */
2076#define EXPOPT_NEG 0x01 2111#define EXPOPT_NEG 0x01
2112/* Coalesce the input list before running the expansion. */
2077#define EXPOPT_COALESCE 0x02 2113#define EXPOPT_COALESCE 0x02
2078 2114
2079static struct exptab exptab[] = { 2115static struct exptab exptab[] = {
2080 { N_("WS trimming"), WRDSF_WS, 0, wordsplit_trimws }, 2116 { N_("WS trimming"), WRDSF_WS, 0,
2081 { N_("tilde expansion"), WRDSF_PATHEXPAND, 0, wordsplit_tildexpand }, 2117 wordsplit_trimws },
2118 { N_("command substitution"), WRDSF_NOCMD, EXPOPT_NEG|EXPOPT_COALESCE,
2119 wordsplit_cmdexp },
2120 { N_("coalesce list"), 0, EXPOPT_NEG|EXPOPT_COALESCE,
2121 NULL },
2122 { N_("tilde expansion"), WRDSF_PATHEXPAND, 0,
2123 wordsplit_tildexpand },
2082 { N_("variable expansion"), WRDSF_NOVAR, EXPOPT_NEG, 2124 { N_("variable expansion"), WRDSF_NOVAR, EXPOPT_NEG,
2083 wordsplit_varexp }, 2125 wordsplit_varexp },
2084 { N_("quote removal"), 0, EXPOPT_NEG, 2126 { N_("quote removal"), 0, EXPOPT_NEG,
2085 wsnode_quoteremoval }, 2127 wsnode_quoteremoval },
2086 { N_("command substitution"), WRDSF_NOCMD, EXPOPT_NEG|EXPOPT_COALESCE,
2087 wordsplit_cmdexp },
2088 { N_("coalesce list"), 0, EXPOPT_NEG|EXPOPT_COALESCE, 2128 { N_("coalesce list"), 0, EXPOPT_NEG|EXPOPT_COALESCE,
2089 NULL }, 2129 NULL },
2090 { N_("path expansion"), WRDSF_PATHEXPAND, 0, wordsplit_pathexpand }, 2130 { N_("path expansion"), WRDSF_PATHEXPAND, 0,
2131 wordsplit_pathexpand },
2091 { NULL } 2132 { NULL }
2092}; 2133};
2093 2134
@@ -2101,6 +2142,7 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start)
2101 /* Treat entire input as a quoted argument */ 2142 /* Treat entire input as a quoted argument */
2102 if (wordsplit_add_segm (wsp, start, wsp->ws_len, _WSNF_QUOTE)) 2143 if (wordsplit_add_segm (wsp, start, wsp->ws_len, _WSNF_QUOTE))
2103 return wsp->ws_errno; 2144 return wsp->ws_errno;
2145 wsp->ws_endp = wsp->ws_len;
2104 } 2146 }
2105 else 2147 else
2106 { 2148 {
@@ -2282,16 +2324,21 @@ wordsplit_free (struct wordsplit *ws)
2282 wordsplit_free_envbuf (ws); 2324 wordsplit_free_envbuf (ws);
2283} 2325}
2284 2326
2285void 2327int
2286wordsplit_getwords (struct wordsplit *ws, size_t *wordc, char ***wordv) 2328wordsplit_get_words (struct wordsplit *ws, size_t *wordc, char ***wordv)
2287{ 2329{
2288 char **p = realloc (ws->ws_wordv, 2330 char **p = realloc (ws->ws_wordv,
2289 (ws->ws_wordc + 1) * sizeof (ws->ws_wordv[0])); 2331 (ws->ws_wordc + 1) * sizeof (ws->ws_wordv[0]));
2290 *wordv = p ? p : ws->ws_wordv; 2332 if (!p)
2333 return -1;
2334 *wordv = p;
2291 *wordc = ws->ws_wordc; 2335 *wordc = ws->ws_wordc;
2336
2292 ws->ws_wordv = NULL; 2337 ws->ws_wordv = NULL;
2293 ws->ws_wordc = 0; 2338 ws->ws_wordc = 0;
2294 ws->ws_wordn = 0; 2339 ws->ws_wordn = 0;
2340
2341 return 0;
2295} 2342}
2296 2343
2297const char *_wordsplit_errstr[] = { 2344const char *_wordsplit_errstr[] = {
diff --git a/tests/wordsplit.at b/tests/wordsplit.at
index 895a392..49d47e9 100644
--- a/tests/wordsplit.at
+++ b/tests/wordsplit.at
@@ -637,6 +637,14 @@ NF: 1
637[input exhausted 637[input exhausted
638]) 638])
639 639
640TESTWSP([incremental nosplit],[],[incremental nosplit],
641[incremental "input test" line
642],
643[NF: 1
6440: "incremental \"input test\" line"
645],
646[input exhausted
647])
640 648
641dnl Something that doesn't fit into TESTWSP 649dnl Something that doesn't fit into TESTWSP
642 650
@@ -717,15 +725,16 @@ mkdir dir
717> dir/file 725> dir/file
718 726
719DIR=dir wsp -nocmd -novar<<'EOT' 727DIR=dir wsp -nocmd -novar<<'EOT'
720begin $(find $DIR) end 728begin $DIR $(find $DIR) end
721EOT 729EOT
722], 730],
723[0], 731[0],
724[NF: 4 732[NF: 5
7250: begin 7330: begin
7261: dir 7341: dir
7272: dir/file 7352: dir
7283: end 7363: dir/file
7374: end
729]) 738])
730AT_CLEANUP 739AT_CLEANUP
731 740
@@ -735,8 +744,8 @@ AT_CHECK([
735mkdir dir 744mkdir dir
736> dir/file 745> dir/file
737 746
738DIR=dir wsp -nocmd -novar<<'EOT' 747DIR=dir BEGIN=begin wsp -nocmd -novar<<'EOT'
739"begin($(find $DIR))end" 748"${BEGIN}($(find $DIR))end"
740EOT 749EOT
741], 750],
742[0], 751[0],
@@ -744,7 +753,27 @@ EOT
7440: "begin(dir dir/file)end"