diff options
Diffstat (limited to 'wordsplit.c')
-rw-r--r-- | wordsplit.c | 119 |
1 files changed, 60 insertions, 59 deletions
diff --git a/wordsplit.c b/wordsplit.c index d3ec9e1..99a8b4f 100644 --- a/wordsplit.c +++ b/wordsplit.c @@ -52,7 +52,14 @@ #define ISPRINT(c) (' ' <= ((unsigned) (c)) && ((unsigned) (c)) <= 127) #define ISVARBEG(c) (ISALPHA(c) || c == '_') -#define ISVARCHR(c) (ISALNUM(c) || c == '_') +static inline int +is_name_char (struct wordsplit *wsp, int c) +{ + return ISALNUM (c) + || c == '_' + || ((wsp->ws_options & WRDSO_NAMECHAR) + && strchr (wsp->ws_namechar, c)); +} #define WSP_RETURN_DELIMS(wsp) \ ((wsp)->ws_flags & WRDSF_RETURN_DELIMS || ((wsp)->ws_options & WRDSO_MAXWORDS)) @@ -92,6 +99,8 @@ _wsplt_seterr (struct wordsplit *wsp, int ec) wsp->ws_errno = ec; if (wsp->ws_flags & WRDSF_SHOWERR) wordsplit_perror (wsp); + if (ec == WRDSE_USAGE) + errno = EINVAL; return ec; } @@ -172,8 +181,9 @@ _wsplt_subsplit (struct wordsplit *wsp, struct wordsplit *wss, flags |= wsp->ws_flags & WRDSF_CLOSURE; } - wss->ws_options = wsp->ws_options; - + wss->ws_options = wsp->ws_options & ~WRDSO_MAXWORDS; + wss->ws_namechar = wsp->ws_namechar; + flags |= WRDSF_DELIM | WRDSF_ALLOC_DIE | WRDSF_ERROR @@ -260,11 +270,7 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, if (!(wsp->ws_flags & WRDSF_NOCMD)) { if (!wsp->ws_command) - { - _wsplt_seterr (wsp, WRDSE_USAGE); - errno = EINVAL; - return wsp->ws_errno; - } + return _wsplt_seterr (wsp, WRDSE_USAGE); } if (wsp->ws_flags & WRDSF_SHOWDBG) @@ -333,6 +339,14 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, wsp->ws_paramidx = wsp->ws_paramsiz = 0; wsp->ws_parambuf = NULL; + if (wsp->ws_options & WRDSO_NAMECHAR) + { + if (wsp->ws_namechar[strcspn(wsp->ws_namechar, "${}*@-+?=")]) + return _wsplt_seterr (wsp, WRDSE_USAGE); + } + else + wsp->ws_namechar = NULL; + wsp->ws_endp = 0; wsp->ws_wordi = 0; @@ -1387,7 +1401,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, if (ISVARBEG (str[0])) { for (i = 1; i < len; i++) - if (!ISVARCHR (str[i])) + if (!is_name_char (wsp, str[i])) break; *pend = str + i - 1; } @@ -1429,21 +1443,12 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, && (str[1] == '-' && ISDIGIT (str[2]))))) != 0)) { + int i0 = str[0] == '-' ? 1 : 0; str++; len--; - for (i = str[0] == '-' ? 1 : 0; i < len; i++) + for (i = i0; i < len; i++) { - if (str[i] == ':') - { - size_t j; - - defstr = str + i + 1; - if (find_closing_paren (str, i + 1, len, &j, "{}")) - return _wsplt_seterr (wsp, WRDSE_CBRACE); - *pend = str + j; - break; - } - else if (str[i] == '}') + if (str[i] == '}') { defstr = NULL; *pend = str + i; @@ -1456,6 +1461,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, defstr = str + i; if (find_closing_paren (str, i, len, &j, "{}")) return _wsplt_seterr (wsp, WRDSE_CBRACE); + if (i > i0 + 1 && str[i-1] == ':') + i--; *pend = str + j; break; } @@ -1473,8 +1480,10 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, return expvar_recover (wsp, str - 1, ptail, pend, flg); } } - else if (!ISVARCHR (str[i])) + else if (!is_name_char (wsp, str[i])) { + if (str[i] == ':' && i + 1 < len && strchr ("-+?=", str[i+1])) + continue; return expvar_recover (wsp, str - 1, ptail, pend, flg); } } @@ -1495,54 +1504,46 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, i - its length defstr - default replacement str */ - if (defstr && strchr("-+?=", defstr[0]) == 0) + if (is_param) { - rc = WRDSE_UNDEF; - defstr = NULL; + if (param_idx >= 0 && param_idx < wsp->ws_paramc) + { + value = strdup (wsp->ws_paramv[param_idx]); + if (!value) + rc = WRDSE_NOSPACE; + else + rc = WRDSE_OK; + } + else + rc = WRDSE_UNDEF; } else { - if (is_param) + if (wsp->ws_flags & WRDSF_GETVAR) { - if (param_idx >= 0 && param_idx < wsp->ws_paramc) + if (wsp->ws_options & WRDSO_GETVARPREF) { - value = strdup (wsp->ws_paramv[param_idx]); - if (!value) - rc = WRDSE_NOSPACE; - else - rc = WRDSE_OK; + rc = wsplt_env_getvar (wsp, str, i, &value); + if (rc == WRDSE_UNDEF) + rc = wsplt_env_lookup (wsp, str, i, &value); } else - rc = WRDSE_UNDEF; - } - else - { - if (wsp->ws_flags & WRDSF_GETVAR) { - if (wsp->ws_options & WRDSO_GETVARPREF) - { - rc = wsplt_env_getvar (wsp, str, i, &value); - if (rc == WRDSE_UNDEF) - rc = wsplt_env_lookup (wsp, str, i, &value); - } - else - { - rc = wsplt_env_lookup (wsp, str, i, &value); - if (rc == WRDSE_UNDEF) - rc = wsplt_env_getvar (wsp, str, i, &value); - } + rc = wsplt_env_lookup (wsp, str, i, &value); + if (rc == WRDSE_UNDEF) + rc = wsplt_env_getvar (wsp, str, i, &value); } - else - rc = wsplt_env_lookup (wsp, str, i, &value); } + else + rc = wsplt_env_lookup (wsp, str, i, &value); + } - if (rc == WRDSE_OK - && (!value || value[0] == 0) - && defstr && defstr[-1] == ':') - { - free (value); - rc = WRDSE_UNDEF; - } + if (rc == WRDSE_OK + && (!value || value[0] == 0) + && defstr && defstr[-1] == ':') + { + free (value); + rc = WRDSE_UNDEF; } switch (rc) @@ -1628,7 +1629,7 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, } else if (wsp->ws_flags & WRDSF_UNDEF) { - _wsplt_setctxerr (wsp, WRDSE_UNDEF, str, *pend - str + 1); + _wsplt_setctxerr (wsp, WRDSE_UNDEF, str, i); return 1; } else |