diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-05-14 19:59:07 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-05-14 19:59:07 +0300 |
commit | 39beda10e855d265b5af74ea53a5d7a89a91296a (patch) | |
tree | 86f671ebea706d691d1667304522c260f56924bd | |
parent | f6586d810d8430d6d9f833119af39726a60e4a6c (diff) | |
download | grecs-39beda10e855d265b5af74ea53a5d7a89a91296a.tar.gz grecs-39beda10e855d265b5af74ea53a5d7a89a91296a.tar.bz2 |
wordsplit: whitespace cleanup
-rw-r--r-- | include/wordsplit.h | 38 | ||||
-rw-r--r-- | src/wordsplit.c | 147 |
2 files changed, 92 insertions, 93 deletions
diff --git a/include/wordsplit.h b/include/wordsplit.h index d7eb26f..d4975b3 100644 --- a/include/wordsplit.h +++ b/include/wordsplit.h @@ -21,114 +21,114 @@ typedef struct wordsplit wordsplit_t; /* Structure used to direct the splitting. Members marked with [Input] can be defined before calling wordsplit(), those marked with [Output] provide return values when the function returns. If neither mark is used, the member is internal and must not be used by the caller. In the comments below, the identifiers in parentheses indicate bits that must be set (or unset, if starting with !) in ws_flags (if starting with WRDSF_) or ws_options (if starting with WRDSO_) to initialize or use the given member. - + If not redefined explicitly, most of them are set to some reasonable default value upon entry to wordsplit(). */ -struct wordsplit +struct wordsplit { size_t ws_wordc; /* [Output] Number of words in ws_wordv. */ char **ws_wordv; /* [Output] Array of parsed out words. */ size_t ws_offs; /* [Input] (WRDSF_DOOFFS) Number of initial elements in ws_wordv to fill with NULLs. */ - size_t ws_wordn; /* Number of elements ws_wordv can accomodate. */ + size_t ws_wordn; /* Number of elements ws_wordv can accomodate. */ int ws_flags; /* [Input] Flags passed to wordsplit. */ int ws_options; /* [Input] (WRDSF_OPTIONS) Additional options. */ size_t ws_maxwords; /* [Input] (WRDSO_MAXWORDS) Return at most that many words */ size_t ws_wordi; /* [Output] (WRDSF_INCREMENTAL) Total number of words returned so far */ const char *ws_delim; /* [Input] (WRDSF_DELIM) Word delimiters. */ const char *ws_comment; /* [Input] (WRDSF_COMMENT) Comment characters. */ const char *ws_escape[2]; /* [Input] (WRDSF_ESCAPE) Characters to be escaped with backslash. */ void (*ws_alloc_die) (wordsplit_t *wsp); - /* [Input] (WRDSF_ALLOC_DIE) Function called when + /* [Input] (WRDSF_ALLOC_DIE) Function called when out of memory. Must not return. */ void (*ws_error) (const char *, ...) - __attribute__ ((__format__ (__printf__, 1, 2))); - /* [Input] (WRDSF_ERROR) Function used for error + __attribute__ ((__format__ (__printf__, 1, 2))); + /* [Input] (WRDSF_ERROR) Function used for error reporting */ void (*ws_debug) (const char *, ...) - __attribute__ ((__format__ (__printf__, 1, 2))); - /* [Input] (WRDSF_DEBUG) Function used for debug + __attribute__ ((__format__ (__printf__, 1, 2))); + /* [Input] (WRDSF_DEBUG) Function used for debug output. */ const char **ws_env; /* [Input] (WRDSF_ENV, !WRDSF_NOVAR) Array of environment variables. */ /* Temporary storage for environment variables. It is initialized upon first assignment which occurs during the parsing process (e.g. ${x:=2}). When this happens, all variables from ws_env are moved to ws_envbuf first, and the ws_envbuf address is assigned to ws_env. From this moment on, all variable expansions are served from ws_envbuf. */ char **ws_envbuf; /* Storage for variables */ size_t ws_envidx; /* Index of first free slot */ size_t ws_envsiz; /* Size of the ws_envbuf array */ char const **ws_paramv; /* [WRDSO_PARAMV] User-supplied positional parameters */ size_t ws_paramc; /* Number of positional parameters */ - /* Temporary storage for parameters. Works similarly to ws_enbuf. + /* Temporary storage for parameters. Works similarly to ws_enbuf. */ char **ws_parambuf; size_t ws_paramidx; size_t ws_paramsiz; - + int (*ws_getvar) (char **ret, const char *var, size_t len, void *clos); - /* [Input] (WRDSF_GETVAR, !WRDSF_NOVAR) Looks up + /* [Input] (WRDSF_GETVAR, !WRDSF_NOVAR) Looks up the name VAR (LEN bytes long) in the table of variables and if found returns in memory location pointed to by RET the value of that variable. Returns WRDSE_OK (0) on success, and an error code (see WRDSE_* defines below) on error. User-specific errors can be returned by storing the error diagnostic string in RET and returning WRDSE_USERERR. - Whatever is stored in RET, it must be allocated + Whatever is stored in RET, it must be allocated using malloc(3). */ void *ws_closure; /* [Input] (WRDSF_CLOSURE) Passed as the CLOS argument to ws_getvar and ws_command. */ int (*ws_command) (char **ret, const char *cmd, size_t len, char **argv, - void *clos); - /* [Input] (!WRDSF_NOCMD) Returns in the memory + void *clos); + /* [Input] (!WRDSF_NOCMD) Returns in the memory location pointed to by RET the expansion of the command CMD (LEN bytes long). On input, ARGV contains CMD split out to words. See ws_getvar for a discussion of possible return values. */ - const char *ws_input; /* Input string (the S argument to wordsplit. */ + const char *ws_input; /* Input string (the S argument to wordsplit. */ size_t ws_len; /* Length of ws_input. */ size_t ws_endp; /* Points past the last processed byte in ws_input. */ int ws_errno; /* [Output] Error code, if an error occurred. */ char *ws_usererr; /* Points to textual description of the error, if ws_errno is WRDSE_USERERR. Must be allocated with malloc(3). */ struct wordsplit_node *ws_head, *ws_tail; - /* Doubly-linked list of parsed out nodes. */ + /* Doubly-linked list of parsed out nodes. */ int ws_lvl; /* Invocation nesting level. */ }; /* Initial size for ws_env, if allocated automatically */ #define WORDSPLIT_ENV_INIT 16 /* Wordsplit flags. */ /* Append the words found to the array resulting from a previous call. */ #define WRDSF_APPEND 0x00000001 /* Insert ws_offs initial NULLs in the array ws_wordv. (These are not counted in the returned ws_wordc.) */ @@ -233,27 +233,27 @@ struct wordsplit (e.g. ${VAR:-foo bar}) */ #define WRDSO_NOVARSPLIT 0x00001000 /* Don't split commands, even containing whitespace, e.g. $(echo foo bar) */ #define WRDSO_NOCMDSPLIT 0x00002000 /* Enable positional parameters */ #define WRDSO_PARAMV 0x00004000 /* Enable negative positional indices (${-1} is the last positional parameter) */ #define WRDSO_PARAM_NEGIDX 0x00008000 -#define WRDSO_BSKEEP WRDSO_BSKEEP_WORD -#define WRDSO_OESC WRDSO_OESC_WORD -#define WRDSO_XESC WRDSO_XESC_WORD +#define WRDSO_BSKEEP WRDSO_BSKEEP_WORD +#define WRDSO_OESC WRDSO_OESC_WORD +#define WRDSO_XESC WRDSO_XESC_WORD /* Indices into ws_escape */ #define WRDSX_WORD 0 #define WRDSX_QUOTE 1 /* Set escape option F in WS for words (Q==0) or quoted strings (Q==1) */ #define WRDSO_ESC_SET(ws,q,f) ((ws)->ws_options |= ((f) << 4*(q))) /* Test WS for escape option F for words (Q==0) or quoted strings (Q==1) */ #define WRDSO_ESC_TEST(ws,q,f) ((ws)->ws_options & ((f) << 4*(q))) #define WRDSE_OK 0 #define WRDSE_EOF WRDSE_OK diff --git a/src/wordsplit.c b/src/wordsplit.c index 05c3643..f563725 100644 --- a/src/wordsplit.c +++ b/src/wordsplit.c @@ -61,46 +61,46 @@ (ISDIGIT(c) ? c - '0' : (ISXDIGIT(c) ? toupper(c) - 'A' + 10 : 255 )) #define ALLOC_INIT 128 #define ALLOC_INCR 128 static void _wsplt_alloc_die (struct wordsplit *wsp) { wsp->ws_error ("%s", _("memory exhausted")); abort (); } -static void +static void _wsplt_error (const char *fmt, ...) { va_list ap; va_start (ap, fmt); vfprintf (stderr, fmt, ap); va_end (ap); fputc ('\n', stderr); } static void wordsplit_free_nodes (struct wordsplit *); static int _wsplt_seterr (struct wordsplit *wsp, int ec) { wsp->ws_errno = ec; if (wsp->ws_flags & WRDSF_SHOWERR) wordsplit_perror (wsp); return ec; } - + static int _wsplt_nomem (struct wordsplit *wsp) { errno = ENOMEM; wsp->ws_errno = WRDSE_NOSPACE; if (wsp->ws_flags & WRDSF_ENOMEMABRT) wsp->ws_alloc_die (wsp); if (wsp->ws_flags & WRDSF_SHOWERR) wordsplit_perror (wsp); if (!(wsp->ws_flags & WRDSF_REUSE)) wordsplit_free (wsp); wordsplit_free_nodes (wsp); @@ -113,54 +113,54 @@ static int wordsplit_run (const char *command, size_t length, static int wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, int flags); static int wordsplit_process_list (struct wordsplit *wsp, size_t start); static int wordsplit_finish (struct wordsplit *wsp); static int _wsplt_subsplit (struct wordsplit *wsp, struct wordsplit *wss, char const *str, int len, int flags, int finalize) { int rc; - + wss->ws_delim = wsp->ws_delim; wss->ws_debug = wsp->ws_debug; wss->ws_error = wsp->ws_error; wss->ws_alloc_die = wsp->ws_alloc_die; if (!(flags & WRDSF_NOVAR)) { wss->ws_env = wsp->ws_env; wss->ws_getvar = wsp->ws_getvar; flags |= wsp->ws_flags & (WRDSF_ENV | WRDSF_ENV_KV | WRDSF_GETVAR); } if (!(flags & WRDSF_NOCMD)) { wss->ws_command = wsp->ws_command; } if ((flags & (WRDSF_NOVAR|WRDSF_NOCMD)) != (WRDSF_NOVAR|WRDSF_NOCMD)) { wss->ws_closure = wsp->ws_closure; flags |= wsp->ws_flags & WRDSF_CLOSURE; } wss->ws_options = wsp->ws_options; - + flags |= WRDSF_DELIM - | WRDSF_ALLOC_DIE - | WRDSF_ERROR - | WRDSF_DEBUG - | (wsp->ws_flags & (WRDSF_SHOWDBG | WRDSF_SHOWERR | WRDSF_OPTIONS)); + | WRDSF_ALLOC_DIE + | WRDSF_ERROR + | WRDSF_DEBUG + | (wsp->ws_flags & (WRDSF_SHOWDBG | WRDSF_SHOWERR | WRDSF_OPTIONS)); rc = wordsplit_init (wss, str, len, flags); if (rc) return rc; wss->ws_lvl = wsp->ws_lvl + 1; rc = wordsplit_process_list (wss, 0); if (rc) { wordsplit_free_nodes (wss); return rc; } if (finalize) @@ -196,25 +196,25 @@ wordsplit_init0 (struct wordsplit *wsp) } else { wsp->ws_wordv = NULL; wsp->ws_wordc = 0; wsp->ws_wordn = 0; } wsp->ws_errno = 0; } 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) { wsp->ws_flags = flags; if (!(wsp->ws_flags & WRDSF_ALLOC_DIE)) wsp->ws_alloc_die = _wsplt_alloc_die; if (!(wsp->ws_flags & WRDSF_ERROR)) wsp->ws_error = _wsplt_error; if (!(wsp->ws_flags & WRDSF_NOVAR)) @@ -269,52 +269,52 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, { if (!wsp->ws_escape[WRDSX_WORD]) wsp->ws_escape[WRDSX_WORD] = ""; if (!wsp->ws_escape[WRDSX_QUOTE]) wsp->ws_escape[WRDSX_QUOTE] = ""; } else { if (wsp->ws_flags & WRDSF_CESCAPES) { wsp->ws_escape[WRDSX_WORD] = wordsplit_c_escape_tab; wsp->ws_escape[WRDSX_QUOTE] = wordsplit_c_escape_tab; - wsp->ws_options |= WRDSO_OESC_QUOTE | WRDSO_OESC_WORD - | WRDSO_XESC_QUOTE | WRDSO_XESC_WORD; + wsp->ws_options |= WRDSO_OESC_QUOTE | WRDSO_OESC_WORD + | WRDSO_XESC_QUOTE | WRDSO_XESC_WORD; } else { wsp->ws_escape[WRDSX_WORD] = ""; wsp->ws_escape[WRDSX_QUOTE] = "\\\\\"\""; wsp->ws_options |= WRDSO_BSKEEP_QUOTE; } } if (!(wsp->ws_options & WRDSO_PARAMV)) { wsp->ws_paramv = NULL; wsp->ws_paramc = 0; } wsp->ws_paramidx = wsp->ws_paramsiz = 0; wsp->ws_parambuf = NULL; - + wsp->ws_endp = 0; wsp->ws_wordi = 0; if (wsp->ws_flags & WRDSF_REUSE) wordsplit_free_nodes (wsp); wsp->ws_head = wsp->ws_tail = NULL; - + wordsplit_init0 (wsp); - + return 0; } static int alloc_space (struct wordsplit *wsp, size_t count) { size_t offs = (wsp->ws_flags & WRDSF_DOOFFS) ? wsp->ws_offs : 0; char **ptr; size_t newalloc; if (wsp->ws_wordv == NULL) { @@ -582,25 +582,25 @@ wordsplit_dump_nodes (struct wordsplit *wsp) } static int coalesce_segment (struct wordsplit *wsp, struct wordsplit_node *node) { struct wordsplit_node *p, *end; size_t len = 0; char *buf, *cur; int stop; if (!(node->flags & _WSNF_JOIN)) return 0; - + for (p = node; p && (p->flags & _WSNF_JOIN); p = p->next) { len += wsnode_len (p); } if (p) len += wsnode_len (p); end = p; buf = malloc (len + 1); if (!buf) return _wsplt_nomem (wsp); cur = buf; @@ -712,42 +712,42 @@ static size_t skip_delim (struct wordsplit *wsp); static int wordsplit_finish (struct wordsplit *wsp) { struct wordsplit_node *p; size_t n; int delim; /* Postprocess delimiters. It would be rather simple, if it weren't for the incremental operation. Nodes of type _WSNF_DELIM get inserted to the node list if either WRDSF_RETURN_DELIMS flag or WRDSO_MAXWORDS option is set. - + The following cases should be distinguished: 1. If both WRDSF_SQUEEZE_DELIMS and WRDSF_RETURN_DELIMS are set, compress - any runs of similar delimiter nodes to a single node. The nodes are + any runs of similar delimiter nodes to a single node. The nodes are 'similar' if they point to the same delimiter character. If WRDSO_MAXWORDS option is set, stop compressing when ws_wordi + 1 == ws_maxwords, and coalesce the rest of nodes into a single last node. 2. If WRDSO_MAXWORDS option is set, but WRDSF_RETURN_DELIMS is not, - remove any delimiter nodes. Stop operation when + remove any delimiter nodes. Stop operation when ws_wordi + 1 == ws_maxwords, and coalesce the rest of nodes into a single last node. 3. If incremental operation is in progress, restart the loop any time - a delimiter node is about to be returned, unless WRDSF_RETURN_DELIMS + a delimiter node is about to be returned, unless WRDSF_RETURN_DELIMS is set. */ again: delim = 0; /* Delimiter being processed (if any) */ n = 0; /* Number of words processed so far */ p = wsp->ws_head; /* Current node */ while (p) { struct wordsplit_node *next = p->next; if (p->flags & _WSNF_DELIM) { @@ -776,25 +776,25 @@ wordsplit_finish (struct wordsplit *wsp) p = next; continue; } } } else if (wsp->ws_options & WRDSO_MAXWORDS) { wsnode_remove (wsp, p); p = next; continue; } } - else + else { if (delim) { /* Last node was a delimiter or a compressed run of delimiters; Count it, and clear the delimiter marker */ n++; delim = 0; } if (wsp->ws_options & WRDSO_MAXWORDS) { if (wsp->ws_wordi + n + 1 == wsp->ws_maxwords) break; @@ -849,26 +849,26 @@ wordsplit_finish (struct wordsplit *wsp) } if (alloc_space (wsp, n + 1)) return wsp->ws_errno; while (wsp->ws_head) { const char *str = wsnode_ptr (wsp, wsp->ws_head); size_t slen = wsnode_len (wsp->ws_head); char *newstr = malloc (slen + 1); /* Assign newstr first, even if it is NULL. This way - wordsplit_free will work even if we return - nomem later. */ + wordsplit_free will work even if we return + nomem later. */ wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc] = newstr; if (!newstr) return _wsplt_nomem (wsp); memcpy (newstr, str, slen); newstr[slen] = 0; wsnode_remove (wsp, wsp->ws_head); wsp->ws_wordc++; wsp->ws_wordi++; if (wsp->ws_flags & WRDSF_INCREMENTAL) @@ -963,25 +963,25 @@ find_closing_paren (const char *str, size_t i, size_t len, size_t *poff, break; } else if (str[i] == paren[1]) { if (--level == 0) { *poff = i; return 0; } break; } break; - + case '"': state = st_dquote; break; case '\'': state = st_squote; break; } break; case st_squote: if (str[i] == '\'') @@ -1043,94 +1043,94 @@ wordsplit_find_env (struct wordsplit *wsp, const char *name, size_t len, } } } return WRDSE_UNDEF; } static int wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen, char const *value) { int n = (wsp->ws_flags & WRDSF_ENV_KV) ? 2 : 1; char *v; - + if (wsp->ws_envidx + n >= wsp->ws_envsiz) { size_t sz; char **newenv; if (!wsp->ws_envbuf) { if (wsp->ws_flags & WRDSF_ENV) { size_t i = 0, j; if (wsp->ws_env) { for (; wsp->ws_env[i]; i++) ; } - + sz = i + n + 1; newenv = calloc (sz, sizeof(newenv[0])); if (!newenv) return _wsplt_nomem (wsp); for (j = 0; j < i; j++) { newenv[j] = strdup (wsp->ws_env[j]); if (!newenv[j]) { for (; j > 1; j--) free (newenv[j-1]); free (newenv); return _wsplt_nomem (wsp); } } newenv[j] = NULL; - + wsp->ws_envbuf = newenv; wsp->ws_envidx = i; wsp->ws_envsiz = sz; wsp->ws_env = (const char**) wsp->ws_envbuf; } else { newenv = calloc (WORDSPLIT_ENV_INIT, sizeof(newenv[0])); if (!newenv) return _wsplt_nomem (wsp); wsp->ws_envbuf = newenv; wsp->ws_envidx = 0; wsp->ws_envsiz = WORDSPLIT_ENV_INIT; wsp->ws_env = (const char**) wsp->ws_envbuf; wsp->ws_flags |= WRDSF_ENV; } } else { size_t n = wsp->ws_envsiz; - + if ((size_t) -1 / 3 * 2 / sizeof (wsp->ws_envbuf[0]) <= n) return _wsplt_nomem (wsp); n += (n + 1) / 2; newenv = realloc (wsp->ws_envbuf, n * sizeof (wsp->ws_envbuf[0])); if (!newenv) return _wsplt_nomem (wsp); wsp->ws_envbuf = newenv; wsp->ws_envsiz = n; wsp->ws_env = (const char**) wsp->ws_envbuf; } } - + if (wsp->ws_flags & WRDSF_ENV_KV) { /* A key-value pair environment */ char *p = malloc (namelen + 1); if (!p) return _wsplt_nomem (wsp); memcpy (p, name, namelen); p[namelen] = 0; v = strdup (value); if (!v) { @@ -1149,79 +1149,79 @@ wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen, v[namelen++] = '='; strcpy(v + namelen, value); wsp->ws_env[wsp->ws_envidx++] = v; } wsp->ws_env[wsp->ws_envidx++] = NULL; return WRDSE_OK; } int wsplt_assign_param (struct wordsplit *wsp, int param_idx, char *value) { char *v; - + if (param_idx < 0) return WRDSE_BADPARAM; if (param_idx == wsp->ws_paramc) { char **parambuf; if (!wsp->ws_parambuf) { size_t i; - + parambuf = calloc ((size_t)param_idx + 1, sizeof (parambuf[0])); if (!parambuf) return _wsplt_nomem (wsp); for (i = 0; i < wsp->ws_paramc; i++) { parambuf[i] = strdup (wsp->ws_paramv[i]); if (!parambuf[i]) { for (; i > 1; i--) free (parambuf[i-1]); free (parambuf); return _wsplt_nomem (wsp); } } - + wsp->ws_parambuf = parambuf; wsp->ws_paramidx = param_idx; wsp->ws_paramsiz = param_idx + 1; } else { size_t n = wsp->ws_paramsiz; - + if ((size_t) -1 / 3 * 2 / sizeof (wsp->ws_parambuf[0]) <= n) return _wsplt_nomem (wsp); n += (n + 1) / 2; parambuf = realloc (wsp->ws_parambuf, n * sizeof (wsp->ws_parambuf[0])); if (!parambuf) return _wsplt_nomem (wsp); wsp->ws_parambuf = parambuf; wsp->ws_paramsiz = n; wsp->ws_parambuf[param_idx] = NULL; } wsp->ws_paramv = (const char**) wsp->ws_parambuf; wsp->ws_paramc = param_idx + 1; } else if (param_idx > wsp->ws_paramc) return WRDSE_BADPARAM; - + v = strdup (value); if (!v) return _wsplt_nomem (wsp); - + free (wsp->ws_parambuf[param_idx]); wsp->ws_parambuf[param_idx] = v; return WRDSE_OK; } /* Recover from what looked like a variable reference, but turned out not to be one. STR points to first character after '$'. */ static int expvar_recover (struct wordsplit *wsp, const char *str, struct wordsplit_node **ptail, const char **pend, int flg) { struct wordsplit_node *newnode; @@ -1238,83 +1238,83 @@ expvar_recover (struct wordsplit *wsp, const char *str, newnode->v.word[1] = str[0]; newnode->v.word[2] = 0; *pend = str; return 0; } static int expand_paramv (struct wordsplit *wsp, struct wordsplit_node **ptail, int flg, int q) { struct wordsplit ws; int wsflags = WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_QUOTE - | (WSP_RETURN_DELIMS (wsp) ? WRDSF_RETURN_DELIMS : 0) - | (q ? WRDSF_NOSPLIT : 0); + | (WSP_RETURN_DELIMS (wsp) ? WRDSF_RETURN_DELIMS : 0) + | (q ? WRDSF_NOSPLIT : 0); size_t i; - + for (i = 0; i < wsp->ws_paramc; i++) { struct wordsplit_node *np; int rc = _wsplt_subsplit (wsp, &ws, wsp->ws_paramv[i], strlen (wsp->ws_paramv[i]), wsflags, q); if (rc) { _wsplt_seterr_sub (wsp, &ws); wordsplit_free (&ws); return 1; } if (q) { if (wsnode_new (wsp, &np)) return 1; wsnode_insert (wsp, np, *ptail, 0); *ptail = np; np->flags = _WSNF_WORD | _WSNF_NOEXPAND | flg; np->v.word = ws.ws_wordv[0]; - + ws.ws_wordv[0] = NULL; } else { for (np = ws.ws_head; np; np = np->next) np->flags = _WSNF_WORD | _WSNF_NOEXPAND | flg; wsnode_insert (wsp, ws.ws_head, *ptail, 0); *ptail = ws.ws_tail; ws.ws_head = ws.ws_tail = NULL; } - + wsflags |= WRDSF_REUSE; } if (wsflags & WRDSF_REUSE) wordsplit_free (&ws); return 0; } static int expvar (struct wordsplit *wsp, const char *str, size_t len, struct wordsplit_node **ptail, const char **pend, int flg) { size_t i = 0; const char *defstr = NULL; char *value; const char *vptr; struct wordsplit_node *newnode; const char *start = str - 1; int rc; struct wordsplit ws; int is_param = 0; long param_idx = 0; - + if (ISVARBEG (str[0])) { for (i = 1; i < len; i++) if (!ISVARCHR (str[i])) break; *pend = str + i - 1; } else if ((wsp->ws_options & WRDSO_PARAMV) && ISDIGIT (str[0])) { i = 1; *pend = str; is_param = 1; @@ -1349,41 +1349,41 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, && ISDIGIT (str[1])) || ((wsp->ws_options & WRDSO_PARAM_NEGIDX) && (str[1] == '-' && ISDIGIT (str[2]))))) != 0)) { str++; len--; for (i = str[0] == '-' ? 1 : 0; 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] == '}') { defstr = NULL; *pend = str + i; break; } else if (strchr ("-+?=", str[i])) { size_t j; - + defstr = str + i; if (find_closing_paren (str, i, len, &j, "{}")) return _wsplt_seterr (wsp, WRDSE_CBRACE); *pend = str + j; break; } else if (is_param) { if (ISDIGIT (str[i])) { param_idx = param_idx * 10 + to_num (str[i]); if ((str[0] == '-' && -param_idx < INT_MIN) @@ -1391,28 +1391,28 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, return expvar_recover (wsp, str - 1, ptail, pend, flg); } else { return expvar_recover (wsp, str - 1, ptail, pend, flg); } } else if (!ISVARCHR (str[i])) { return expvar_recover (wsp, str - 1, ptail, pend, flg); } } - + if (is_param && str[0] == '-') param_idx = wsp->ws_paramc - param_idx; - + if (i == len) return _wsplt_seterr (wsp, WRDSE_CBRACE); } else { return expvar_recover (wsp, str, ptail, pend, flg); } /* Actually expand the variable */ /* str - start of the variable name i - its length defstr - default replacement str */ @@ -1447,88 +1447,88 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, value = strdup (vptr); if (!value) rc = WRDSE_NOSPACE; } else rc = WRDSE_UNDEF; } 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 || value[0] == 0) && defstr && defstr[-1] == ':') { free (value); rc = WRDSE_UNDEF; } } - + switch (rc) { case WRDSE_OK: if (defstr && *defstr == '+') { size_t size = *pend - ++defstr; rc = _wsplt_subsplit (wsp, &ws, defstr, size, WRDSF_NOSPLIT | WRDSF_WS | WRDSF_QUOTE | (wsp->ws_flags & (WRDSF_NOVAR | WRDSF_NOCMD)), 1); if (rc) return rc; free (value); value = ws.ws_wordv[0]; ws.ws_wordv[0] = NULL; wordsplit_free (&ws); } break; - + case WRDSE_UNDEF: if (defstr) { size_t size; if (*defstr == '-' || *defstr == '=') { size = *pend - ++defstr; rc = _wsplt_subsplit (wsp, &ws, defstr, size, WRDSF_NOSPLIT | WRDSF_WS | WRDSF_QUOTE | (wsp->ws_flags & (WRDSF_NOVAR | WRDSF_NOCMD)), 1); if (rc) return rc; value = ws.ws_wordv[0]; ws.ws_wordv[0] = NULL; wordsplit_free (&ws); - + if (defstr[-1] == '=') { if (is_param) rc = wsplt_assign_param (wsp, param_idx, value); else rc = wsplt_assign_var (wsp, str, i, value); } if (rc) { free (value); return rc; } } - else + else { if (*defstr == '?') { size = *pend - ++defstr; if (size == 0) wsp->ws_error (_("%.*s: variable null or not set"), (int) i, str); else { rc = _wsplt_subsplit (wsp, &ws, defstr, size, WRDSF_NOSPLIT | WRDSF_WS | WRDSF_QUOTE | @@ -1558,25 +1558,25 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, wsp->ws_error (_("warning: undefined variable `%.*s'"), (int) i, str); if (wsp->ws_flags & WRDSF_KEEPUNDEF) value = NULL; else { value = strdup (""); if (!value) return _wsplt_nomem (wsp); } } break; - + case WRDSE_NOSPACE: return _wsplt_nomem (wsp); case WRDSE_USERERR: if (wsp->ws_errno == WRDSE_USERERR) free (wsp->ws_usererr); wsp->ws_usererr = value; /* fall through */ default: _wsplt_seterr (wsp, rc); return 1; } @@ -1597,25 +1597,25 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, free (value); /* Empty string is a special case */ if (wsnode_new (wsp, &newnode)) return 1; wsnode_insert (wsp, newnode, *ptail, 0); *ptail = newnode; newnode->flags = _WSNF_NULL; } else { struct wordsplit ws; int rc; - + rc = _wsplt_subsplit (wsp, &ws, value, strlen (value), WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_QUOTE | (WSP_RETURN_DELIMS (wsp) ? WRDSF_RETURN_DELIMS : 0) , 0); free (value); if (rc) { _wsplt_seterr_sub (wsp, &ws); wordsplit_free (&ws); return 1; } @@ -1702,25 +1702,25 @@ node_expand (struct wordsplit *wsp, struct wordsplit_node *node, tail->flags |= _WSNF_JOIN; if (node_split_prefix (wsp, &tail, node, off, p - str, node->flags & (_WSNF_JOIN|_WSNF_QUOTE))) return 1; } if (tail != node) { wsnode_remove (wsp, node); wsnode_free (node); } return 0; } - + /* Remove NULL nodes from the list */ static void wsnode_nullelim (struct wordsplit *wsp) { struct wordsplit_node *p; for (p = wsp->ws_head; p;) { struct wordsplit_node *next = p->next; if (p->flags & _WSNF_DELIM && p->prev) p->prev->flags &= ~_WSNF_JOIN; if (p->flags & _WSNF_NULL) @@ -1756,45 +1756,45 @@ begin_cmd_p (int c) return c == '('; } static int expcmd (struct wordsplit *wsp, const char *str, size_t len, struct wordsplit_node **ptail, const char **pend, int flg) { int rc; size_t j; char *value; struct wordsplit_node *newnode; struct wordsplit ws; - + str++; len--; if (find_closing_paren (str, 0, len, &j, "()")) { _wsplt_seterr (wsp, WRDSE_PAREN); return 1; } *pend = str + j; rc = _wsplt_subsplit (wsp, &ws, str, j, WRDSF_WS | WRDSF_QUOTE, 1); if (rc) { _wsplt_seterr_sub (wsp, &ws); wordsplit_free (&ws); return 1; } rc = wsp->ws_command (&value, str, j, ws.ws_wordv, wsp->ws_closure); wordsplit_free (&ws); - + if (rc == WRDSE_NOSPACE) return _wsplt_nomem (wsp); else if (rc) { if (rc == WRDSE_USERERR) { if (wsp->ws_errno == WRDSE_USERERR) free (wsp->ws_usererr); wsp->ws_usererr = value; } _wsplt_seterr (wsp, rc); return 1; @@ -1884,65 +1884,65 @@ wordsplit_trimws (struct wordsplit *wsp) for (p = wsp->ws_head; p; p = p->next) { size_t n; if (!(p->flags & _WSNF_QUOTE)) { /* Skip leading whitespace: */ for (n = p->v.segm.beg; n < p->v.segm.end && ISWS (wsp->ws_input[n]); n++) ; p->v.segm.beg = n; } - + while (p->next && (p->flags & _WSNF_JOIN)) p = p->next; - + if (p->flags & _WSNF_QUOTE) continue; - + /* Trim trailing whitespace */ for (n = p->v.segm.end; n > p->v.segm.beg && ISWS (wsp->ws_input[n - 1]); n--); p->v.segm.end = n; if (p->v.segm.beg == p->v.segm.end) p->flags |= _WSNF_NULL; } wsnode_nullelim (wsp); return 0; } static int wordsplit_tildexpand (struct wordsplit *wsp) { struct wordsplit_node *p; char *uname = NULL; size_t usize = 0; - + for (p = wsp->ws_head; p; p = p->next) { const char *str; if (p->flags & _WSNF_QUOTE) continue; str = wsnode_ptr (wsp, p); if (str[0] == '~') { size_t i, size, dlen; size_t slen = wsnode_len (p); struct passwd *pw; char *newstr; - + for (i = 1; i < slen && str[i] != '/'; i++) ; if (i == slen) continue; if (i > 1) { if (i > usize) { char *p = realloc (uname, i); if (!p) { free (uname); @@ -2000,96 +2000,96 @@ static int wordsplit_pathexpand (struct wordsplit *wsp) { struct wordsplit_node *p, *next; char *pattern = NULL; size_t patsize = 0; size_t slen; int flags = 0; #ifdef GLOB_PERIOD if (wsp->ws_options & WRDSO_DOTGLOB) < |