diff options
Diffstat (limited to 'src/wordsplit.c')
-rw-r--r-- | src/wordsplit.c | 138 |
1 files changed, 76 insertions, 62 deletions
diff --git a/src/wordsplit.c b/src/wordsplit.c index c726239..671fcb9 100644 --- a/src/wordsplit.c +++ b/src/wordsplit.c @@ -176,6 +176,8 @@ wordsplit_init0 (struct wordsplit *wsp) wsp->ws_head = wsp->ws_tail = NULL; } +char wordsplit_c_escape_tab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v"; + static int wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, int flags) @@ -234,6 +236,30 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, if (!(wsp->ws_flags & WRDSF_OPTIONS)) wsp->ws_options = 0; + + if (wsp->ws_flags & WRDSF_ESCAPE) + { + if (!wsp->ws_escape[0]) + wsp->ws_escape[0] = ""; + if (!wsp->ws_escape[1]) + wsp->ws_escape[1] = ""; + } + else + { + if (wsp->ws_flags & WRDSF_CESCAPES) + { + wsp->ws_escape[0] = wordsplit_c_escape_tab; + wsp->ws_escape[1] = wordsplit_c_escape_tab; + wsp->ws_options |= WRDSO_OESC_QUOTE | WRDSO_OESC_WORD + | WRDSO_XESC_QUOTE | WRDSO_XESC_WORD; + } + else + { + wsp->ws_escape[0] = ""; + wsp->ws_escape[1] = "\\\\\"\""; + wsp->ws_options |= WRDSO_BSKEEP_QUOTE; + } + } wsp->ws_endp = 0; @@ -551,13 +577,14 @@ coalesce_segment (struct wordsplit *wsp, struct wordsplit_node *node) return 0; } +static void wordsplit_string_unquote_copy (struct wordsplit *ws, int inquote, + char *dst, const char *src, + size_t n); + static int wsnode_quoteremoval (struct wordsplit *wsp) { struct wordsplit_node *p; - void (*uqfn) (char *, const char *, size_t) = - (wsp->ws_flags & WRDSF_CESCAPES) ? - wordsplit_c_unquote_copy : wordsplit_sh_unquote_copy; for (p = wsp->ws_head; p; p = p->next) { @@ -585,11 +612,8 @@ wsnode_quoteremoval (struct wordsplit *wsp) p->flags |= _WSNF_WORD; } - if (wsp->ws_flags & WRDSF_ESCAPE) - wordsplit_general_unquote_copy (p->v.word, str, slen, - wsp->ws_escape); - else - uqfn (p->v.word, str, slen); + wordsplit_string_unquote_copy (wsp, p->flags & _WSNF_QUOTE, + p->v.word, str, slen); } } return 0; @@ -1825,35 +1849,6 @@ scan_word (struct wordsplit *wsp, size_t start) return _WRDS_OK; } -static char quote_transtab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v"; - -int -wordsplit_c_unquote_char (int c) -{ - char *p; - - for (p = quote_transtab; *p; p += 2) - { - if (*p == c) - return p[1]; - } - return c; -} - -int -wordsplit_c_quote_char (int c) -{ - char *p; - - for (p = quote_transtab + sizeof (quote_transtab) - 2; - p > quote_transtab; p -= 2) - { - if (*p == c) - return p[-1]; - } - return -1; -} - #define to_num(c) \ (ISDIGIT(c) ? c - '0' : (ISXDIGIT(c) ? toupper(c) - 'A' + 10 : 255 )) @@ -1894,7 +1889,7 @@ wordsplit_c_quoted_length (const char *str, int quote_hex, int *quote) len += 3; else { - if (wordsplit_c_quote_char (*str) != -1) + if (wordsplit_c_quote_char (*str)) len += 2; else len += 4; @@ -1903,47 +1898,56 @@ wordsplit_c_quoted_length (const char *str, int quote_hex, int *quote) return len; } -void -wordsplit_general_unquote_copy (char *dst, const char *src, size_t n, - const char *escapable) +int +wsplt_unquote_char (const char *transtab, int c) { - int i; - - for (i = 0; i < n;) + while (*transtab && transtab[1]) { - if (src[i] == '\\' && i < n && strchr (escapable, src[i + 1])) - i++; - *dst++ = src[i++]; + if (*transtab++ == c) + return *transtab; + ++transtab; } - *dst = 0; + return 0; } -void -wordsplit_sh_unquote_copy (char *dst, const char *src, size_t n) +int +wsplt_quote_char (const char *transtab, int c) { - int i; - - for (i = 0; i < n;) + for (; *transtab && transtab[1]; transtab += 2) { - if (src[i] == '\\') - i++; - *dst++ = src[i++]; + if (transtab[1] == c) + return *transtab; } - *dst = 0; + return 0; +} + +int +wordsplit_c_unquote_char (int c) +{ + return wsplt_unquote_char (wordsplit_c_escape_tab, c); +} + +int +wordsplit_c_quote_char (int c) +{ + return wsplt_quote_char (wordsplit_c_escape_tab, c); } void -wordsplit_c_unquote_copy (char *dst, const char *src, size_t n) +wordsplit_string_unquote_copy (struct wordsplit *ws, int inquote, + char *dst, const char *src, size_t n) { int i = 0; int c; + inquote = !!inquote; while (i < n) { if (src[i] == '\\') { ++i; - if (src[i] == 'x' || src[i] == 'X') + if (WRDSO_ESC_TEST (ws, inquote, WRDSO_XESC) + && (src[i] == 'x' || src[i] == 'X')) { if (n - i < 2) { @@ -1966,7 +1970,8 @@ wordsplit_c_unquote_copy (char *dst, const char *src, size_t n) } } } - else if ((unsigned char) src[i] < 128 && ISDIGIT (src[i])) + else if (WRDSO_ESC_TEST (ws, inquote, WRDSO_OESC) + && (unsigned char) src[i] < 128 && ISDIGIT (src[i])) { if (n - i < 1) { @@ -1988,8 +1993,17 @@ wordsplit_c_unquote_copy (char *dst, const char *src, size_t n) } } } + else if ((c = wsplt_unquote_char (ws->ws_escape[inquote], src[i]))) + { + *dst++ = c; + ++i; + } else - *dst++ = wordsplit_c_unquote_char (src[i++]); + { + if (WRDSO_ESC_TEST (ws, inquote, WRDSO_BSKEEP)) + *dst++ = '\\'; + *dst++ = src[i++]; + } } else *dst++ = src[i++]; @@ -2023,7 +2037,7 @@ wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex) { int c = wordsplit_c_quote_char (*src); *dst++ = '\\'; - if (c != -1) + if (c) *dst++ = c; else { |