diff options
-rw-r--r-- | include/wordsplit.h | 1 | ||||
-rw-r--r-- | src/wordsplit.c | 30 | ||||
-rw-r--r-- | tests/wordsplit.at | 34 |
3 files changed, 62 insertions, 3 deletions
diff --git a/include/wordsplit.h b/include/wordsplit.h index d4975b3..2fac3c6 100644 --- a/include/wordsplit.h +++ b/include/wordsplit.h | |||
@@ -117,12 +117,13 @@ struct wordsplit | |||
117 | int ws_errno; /* [Output] Error code, if an error occurred. */ | 117 | int ws_errno; /* [Output] Error code, if an error occurred. */ |
118 | char *ws_usererr; /* Points to textual description of | 118 | char *ws_usererr; /* Points to textual description of |
119 | the error, if ws_errno is WRDSE_USERERR. Must | 119 | the error, if ws_errno is WRDSE_USERERR. Must |
120 | be allocated with malloc(3). */ | 120 | be allocated with malloc(3). */ |
121 | struct wordsplit_node *ws_head, *ws_tail; | 121 | struct wordsplit_node *ws_head, *ws_tail; |
122 | /* Doubly-linked list of parsed out nodes. */ | 122 | /* Doubly-linked list of parsed out nodes. */ |
123 | char ws_sep[2]; /* Temporary storage used during splitting */ | ||
123 | int ws_lvl; /* Invocation nesting level. */ | 124 | int ws_lvl; /* Invocation nesting level. */ |
124 | }; | 125 | }; |
125 | 126 | ||
126 | /* Initial size for ws_env, if allocated automatically */ | 127 | /* Initial size for ws_env, if allocated automatically */ |
127 | #define WORDSPLIT_ENV_INIT 16 | 128 | #define WORDSPLIT_ENV_INIT 16 |
128 | 129 | ||
diff --git a/src/wordsplit.c b/src/wordsplit.c index f563725..4e633fa 100644 --- a/src/wordsplit.c +++ b/src/wordsplit.c | |||
@@ -253,12 +253,15 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, | |||
253 | if (!(wsp->ws_flags & WRDSF_DOOFFS)) | 253 | if (!(wsp->ws_flags & WRDSF_DOOFFS)) |
254 | wsp->ws_offs = 0; | 254 | wsp->ws_offs = 0; |
255 | 255 | ||
256 | if (!(wsp->ws_flags & WRDSF_DELIM)) | 256 | if (!(wsp->ws_flags & WRDSF_DELIM)) |
257 | wsp->ws_delim = " \t\n"; | 257 | wsp->ws_delim = " \t\n"; |
258 | 258 | ||
259 | wsp->ws_sep[0] = wsp->ws_delim[0]; | ||
260 | wsp->ws_sep[1] = 0; | ||
261 | |||
259 | if (!(wsp->ws_flags & WRDSF_COMMENT)) | 262 | if (!(wsp->ws_flags & WRDSF_COMMENT)) |
260 | wsp->ws_comment = NULL; | 263 | wsp->ws_comment = NULL; |
261 | 264 | ||
262 | if (!(wsp->ws_flags & WRDSF_CLOSURE)) | 265 | if (!(wsp->ws_flags & WRDSF_CLOSURE)) |
263 | wsp->ws_closure = NULL; | 266 | wsp->ws_closure = NULL; |
264 | 267 | ||
@@ -346,13 +349,13 @@ alloc_space (struct wordsplit *wsp, size_t count) | |||
346 | #define _WSNF_WORD 0x02 /* node contains word in v.word */ | 349 | #define _WSNF_WORD 0x02 /* node contains word in v.word */ |
347 | #define _WSNF_QUOTE 0x04 /* text is quoted */ | 350 | #define _WSNF_QUOTE 0x04 /* text is quoted */ |
348 | #define _WSNF_NOEXPAND 0x08 /* text is not subject to expansion */ | 351 | #define _WSNF_NOEXPAND 0x08 /* text is not subject to expansion */ |
349 | #define _WSNF_JOIN 0x10 /* node must be joined with the next node */ | 352 | #define _WSNF_JOIN 0x10 /* node must be joined with the next node */ |
350 | #define _WSNF_SEXP 0x20 /* is a sed expression */ | 353 | #define _WSNF_SEXP 0x20 /* is a sed expression */ |
351 | #define _WSNF_DELIM 0x40 /* node is a delimiter */ | 354 | #define _WSNF_DELIM 0x40 /* node is a delimiter */ |
352 | 355 | #define _WSNF_CONST 0x80 /* with _WSNF_WORD: v.word is constant */ | |
353 | #define _WSNF_EMPTYOK 0x0100 /* special flag indicating that | 356 | #define _WSNF_EMPTYOK 0x0100 /* special flag indicating that |
354 | wordsplit_add_segm must add the | 357 | wordsplit_add_segm must add the |
355 | segment even if it is empty */ | 358 | segment even if it is empty */ |
356 | 359 | ||
357 | struct wordsplit_node | 360 | struct wordsplit_node |
358 | { | 361 | { |
@@ -438,13 +441,13 @@ wsnode_new (struct wordsplit *wsp, struct wordsplit_node **pnode) | |||
438 | return 0; | 441 | return 0; |
439 | } | 442 | } |
440 | 443 | ||
441 | static void | 444 | static void |
442 | wsnode_free (struct wordsplit_node *p) | 445 | wsnode_free (struct wordsplit_node *p) |
443 | { | 446 | { |
444 | if (p->flags & _WSNF_WORD) | 447 | if ((p->flags & (_WSNF_WORD|_WSNF_CONST)) == _WSNF_WORD) |
445 | free (p->v.word); | 448 | free (p->v.word); |
446 | free (p); | 449 | free (p); |
447 | } | 450 | } |
448 | 451 | ||
449 | static void | 452 | static void |
450 | wsnode_append (struct wordsplit *wsp, struct wordsplit_node *node) | 453 | wsnode_append (struct wordsplit *wsp, struct wordsplit_node *node) |
@@ -1247,12 +1250,13 @@ expand_paramv (struct wordsplit *wsp, struct wordsplit_node **ptail, int flg, | |||
1247 | { | 1250 | { |
1248 | struct wordsplit ws; | 1251 | struct wordsplit ws; |
1249 | int wsflags = WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_QUOTE | 1252 | int wsflags = WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_QUOTE |
1250 | | (WSP_RETURN_DELIMS (wsp) ? WRDSF_RETURN_DELIMS : 0) | 1253 | | (WSP_RETURN_DELIMS (wsp) ? WRDSF_RETURN_DELIMS : 0) |
1251 | | (q ? WRDSF_NOSPLIT : 0); | 1254 | | (q ? WRDSF_NOSPLIT : 0); |
1252 | size_t i; | 1255 | size_t i; |
1256 | struct wordsplit_node *tail = *ptail; | ||
1253 | 1257 | ||
1254 | for (i = 0; i < wsp->ws_paramc; i++) | 1258 | for (i = 0; i < wsp->ws_paramc; i++) |
1255 | { | 1259 | { |
1256 | struct wordsplit_node *np; | 1260 | struct wordsplit_node *np; |
1257 | int rc = _wsplt_subsplit (wsp, &ws, | 1261 | int rc = _wsplt_subsplit (wsp, &ws, |
1258 | wsp->ws_paramv[i], strlen (wsp->ws_paramv[i]), | 1262 | wsp->ws_paramv[i], strlen (wsp->ws_paramv[i]), |
@@ -1285,12 +1289,34 @@ expand_paramv (struct wordsplit *wsp, struct wordsplit_node **ptail, int flg, | |||
1285 | } | 1289 | } |
1286 | 1290 | ||
1287 | wsflags |= WRDSF_REUSE; | 1291 | wsflags |= WRDSF_REUSE; |
1288 | } | 1292 | } |
1289 | if (wsflags & WRDSF_REUSE) | 1293 | if (wsflags & WRDSF_REUSE) |
1290 | wordsplit_free (&ws); | 1294 | wordsplit_free (&ws); |
1295 | |||
1296 | if (flg & _WSNF_QUOTE) | ||
1297 | { | ||
1298 | tail = tail->next; | ||
1299 | /* Insert delimiters, mark nodes as joinable */ | ||
1300 | while (tail != *ptail) | ||
1301 | { | ||
1302 | struct wordsplit_node *next = tail->next; | ||
1303 | struct wordsplit_node *newnode; | ||
1304 | |||
1305 | tail->flags |= _WSNF_JOIN; | ||
1306 | |||
1307 | if (wsnode_new (wsp, &newnode)) | ||
1308 | return 1; | ||
1309 | newnode->flags = _WSNF_WORD | _WSNF_CONST | _WSNF_NOEXPAND | _WSNF_JOIN; | ||
1310 | newnode->v.word = wsp->ws_sep; | ||
1311 | |||
1312 | wsnode_insert (wsp, newnode, tail, 0); | ||
1313 | tail = next; | ||
1314 | } | ||
1315 | } | ||
1316 | |||
1291 | return 0; | 1317 | return 0; |
1292 | } | 1318 | } |
1293 | 1319 | ||
1294 | static int | 1320 | static int |
1295 | expvar (struct wordsplit *wsp, const char *str, size_t len, | 1321 | expvar (struct wordsplit *wsp, const char *str, size_t len, |
1296 | struct wordsplit_node **ptail, const char **pend, int flg) | 1322 | struct wordsplit_node **ptail, const char **pend, int flg) |
diff --git a/tests/wordsplit.at b/tests/wordsplit.at index 0a9c4d6..0a7d7db 100644 --- a/tests/wordsplit.at +++ b/tests/wordsplit.at | |||
@@ -971,25 +971,57 @@ NF: 1 | |||
971 | 0: 12 | 971 | 0: 12 |
972 | TOTAL: 1 | 972 | TOTAL: 1 |
973 | ]) | 973 | ]) |
974 | 974 | ||
975 | TESTWSP([$* and $@],[],['one two' three 'four five'], | 975 | TESTWSP([$* and $@],[],['one two' three 'four five'], |
976 | [$* | 976 | [$* |
977 | $@], | 977 | $@ |
978 | "$*" | ||
979 | "$@"], | ||
978 | [NF: 5 | 980 | [NF: 5 |
979 | 0: one | 981 | 0: one |
980 | 1: two | 982 | 1: two |
981 | 2: three | 983 | 2: three |
982 | 3: four | 984 | 3: four |
983 | 4: five | 985 | 4: five |
984 | TOTAL: 5 | 986 | TOTAL: 5 |
985 | NF: 3 | 987 | NF: 3 |
986 | 0: "one two" | 988 | 0: "one two" |
987 | 1: three | 989 | 1: three |
988 | 2: "four five" | 990 | 2: "four five" |
989 | TOTAL: 3 | 991 | TOTAL: 3 |
992 | NF: 1 | ||
993 | 0: "one two three four five" | ||
994 | TOTAL: 1 | ||
995 | NF: 1 | ||
996 | 0: "one two three four five" | ||
997 | TOTAL: 1 | ||
998 | ]) | ||
999 | |||
1000 | TESTWSP([$* and $@ in nosplit mode],[], | ||
1001 | [-trimnl -nosplit 'one two' three 'four five'], | ||
1002 | [$* | ||
1003 | $@], | ||
1004 | [NF: 1 | ||
1005 | 0: "one two three four five" | ||
1006 | TOTAL: 1 | ||
1007 | NF: 1 | ||
1008 | 0: "one two three four five" | ||
1009 | TOTAL: 1 | ||
1010 | ]) | ||
1011 | |||
1012 | TESTWSP([$* and $@ in nosplit mode with delimiter],[], | ||
1013 | [-trimnl -nosplit -delim : 'one two' three 'four five'], | ||
1014 | [$* | ||
1015 | $@], | ||
1016 | [NF: 1 | ||
1017 | 0: "one two:three:four five" | ||
1018 | TOTAL: 1 | ||
1019 | NF: 1 | ||
1020 | 0: "one two:three:four five" | ||
1021 | TOTAL: 1 | ||
990 | ]) | 1022 | ]) |
991 | 1023 | ||
992 | m4_popdef([TESTWSP]) | 1024 | m4_popdef([TESTWSP]) |
993 | m4_popdef([wspnum]) | 1025 | m4_popdef([wspnum]) |
994 | m4_popdef([wspid]) | 1026 | m4_popdef([wspid]) |
995 | m4_popdef([genkw]) | 1027 | m4_popdef([genkw]) |