diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-10-24 22:41:25 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-12-17 15:25:24 +0200 |
commit | 8383ec3a522a944969b3fc44069a3ff056da554a (patch) | |
tree | 6fde51206df3e0a9a07c6edaf5f80aa580676f36 | |
parent | 790e1d4e29514da57265875496f9dcb7c2d6f1c2 (diff) | |
download | grecs-8383ec3a522a944969b3fc44069a3ff056da554a.tar.gz grecs-8383ec3a522a944969b3fc44069a3ff056da554a.tar.bz2 |
Improve wordsplit documentation and debug output.
-rw-r--r-- | src/wordsplit.c | 101 | ||||
-rw-r--r-- | src/wordsplit.h | 93 |
2 files changed, 146 insertions, 48 deletions
diff --git a/src/wordsplit.c b/src/wordsplit.c index 403ffed..4a69725 100644 --- a/src/wordsplit.c +++ b/src/wordsplit.c @@ -100,6 +100,43 @@ _wsplt_nomem (struct wordsplit *wsp) return wsp->ws_errno; } +static int wordsplit_run (const char *command, size_t length, + struct wordsplit *wsp, + int flags, int lvl); + +static int +_wsplt_subsplit (struct wordsplit *wsp, struct wordsplit *wss, + char const *str, int len, + int flags) +{ + 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; + + flags |= WRDSF_DELIM + | WRDSF_ALLOC_DIE + | WRDSF_ERROR + | WRDSF_DEBUG + | (wsp->ws_flags & (WRDSF_SHOWDBG | WRDSF_SHOWERR)); + + return wordsplit_run (str, len, wss, flags, wsp->ws_lvl + 1); +} + +static void +_wsplt_seterr_sub (struct wordsplit *wsp, struct wordsplit *wss) +{ + if (wsp->ws_errno == WRDSE_USERERR) + free (wsp->ws_usererr); + wsp->ws_errno = wss->ws_errno; + if (wss->ws_errno == WRDSE_USERERR) + { + wsp->ws_usererr = wss->ws_usererr; + wss->ws_errno = WRDSE_EOF; + wss->ws_usererr = NULL; + } +} + static void wordsplit_init0 (struct wordsplit *wsp) { @@ -429,10 +466,12 @@ wordsplit_dump_nodes (struct wordsplit *wsp) for (p = wsp->ws_head, n = 0; p; p = p->next, n++) { if (p->flags & _WSNF_WORD) - wsp->ws_debug ("%4d: %p: %#04x (%s):%s;", + wsp->ws_debug ("(%02d) %4d: %p: %#04x (%s):%s;", + wsp->ws_lvl, n, p, p->flags, wsnode_flagstr (p->flags), p->v.word); else - wsp->ws_debug ("%4d: %p: %#04x (%s):%.*s;", + wsp->ws_debug ("(%02d) %4d: %p: %#04x (%s):%.*s;", + wsp->ws_lvl, n, p, p->flags, wsnode_flagstr (p->flags), (int) (p->v.segm.end - p->v.segm.beg), wsp->ws_input + p->v.segm.beg); @@ -897,14 +936,14 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, { struct wordsplit ws; int i, rc; - - ws.ws_delim = wsp->ws_delim; - rc = wordsplit (value, &ws, - WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_DELIM | - WRDSF_WS | WRDSF_QUOTE); + + rc = _wsplt_subsplit (wsp, &ws, value, strlen (value), + WRDSF_NOVAR | WRDSF_NOCMD | + WRDSF_WS | WRDSF_QUOTE); free (value); if (rc) { + _wsplt_seterr_sub (wsp, &ws); wordsplit_free (&ws); return 1; } @@ -1076,11 +1115,17 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len, { struct wordsplit ws; - ws.ws_delim = wsp->ws_delim; - rc = wordsplit_len (str, j, &ws, - WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_DELIM | - (wsp->ws_flags & (WRDSF_WS | WRDSF_QUOTE))); + rc = _wsplt_subsplit (wsp, &ws, str, j, + WRDSF_NOVAR | WRDSF_NOCMD | + WRDSF_WS | WRDSF_QUOTE); + 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); } else rc = wsp->ws_command (&value, str, j, NULL, wsp->ws_closure); @@ -1125,13 +1170,13 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len, struct wordsplit ws; int i, rc; - ws.ws_delim = wsp->ws_delim; - rc = wordsplit (value, &ws, - WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_DELIM | - WRDSF_WS | WRDSF_QUOTE); + rc = _wsplt_subsplit (wsp, &ws, value, strlen (value), + WRDSF_NOVAR | WRDSF_NOCMD | + WRDSF_WS | WRDSF_QUOTE); free (value); if (rc) { + _wsplt_seterr_sub (wsp, &ws); wordsplit_free (&ws); return 1; } @@ -1858,7 +1903,7 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start) if (wsp->ws_flags & WRDSF_SHOWDBG) { - wsp->ws_debug (_("Initial list:")); + wsp->ws_debug ("(%02d) %s", wsp->ws_lvl, _("Initial list:")); wordsplit_dump_nodes (wsp); } @@ -1873,7 +1918,8 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start) break; if (wsp->ws_flags & WRDSF_SHOWDBG) { - wsp->ws_debug (_("Coalesced list:")); + wsp->ws_debug ("(%02d) %s", wsp->ws_lvl, + _("Coalesced list:")); wordsplit_dump_nodes (wsp); } } @@ -1883,7 +1929,7 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start) break; if (wsp->ws_flags & WRDSF_SHOWDBG) { - wsp->ws_debug ("%s:", _(p->descr)); + wsp->ws_debug ("(%02d) %s", wsp->ws_lvl, _(p->descr)); wordsplit_dump_nodes (wsp); } } @@ -1892,9 +1938,9 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start) return wsp->ws_errno; } -int -wordsplit_len (const char *command, size_t length, struct wordsplit *wsp, - int flags) +static int +wordsplit_run (const char *command, size_t length, struct wordsplit *wsp, + int flags, int lvl) { int rc; size_t start; @@ -1923,10 +1969,11 @@ wordsplit_len (const char *command, size_t length, struct wordsplit *wsp, rc = wordsplit_init (wsp, cmdptr, cmdlen, flags); if (rc) return rc; + wsp->ws_lvl = lvl; } if (wsp->ws_flags & WRDSF_SHOWDBG) - wsp->ws_debug (_("Input:%.*s;"), (int) cmdlen, cmdptr); + wsp->ws_debug (_("(%02d) Input:%.*s;"), wsp->ws_lvl, (int) cmdlen, cmdptr); rc = wordsplit_process_list (wsp, start); if (rc == 0 && (flags & WRDSF_INCREMENTAL)) @@ -1938,7 +1985,8 @@ wordsplit_len (const char *command, size_t length, struct wordsplit *wsp, { cmdptr = wsp->ws_input + wsp->ws_endp; cmdlen = wsp->ws_len - wsp->ws_endp; - wsp->ws_debug (_("Restart:%.*s;"), (int) cmdlen, cmdptr); + wsp->ws_debug (_("(%02d) Restart:%.*s;"), + wsp->ws_lvl, (int) cmdlen, cmdptr); } rc = wordsplit_process_list (wsp, start); if (rc) @@ -1956,6 +2004,13 @@ wordsplit_len (const char *command, size_t length, struct wordsplit *wsp, } int +wordsplit_len (const char *command, size_t length, struct wordsplit *wsp, + int flags) +{ + return wordsplit_run (command, length, wsp, flags, 0); +} + +int wordsplit (const char *command, struct wordsplit *ws, int flags) { return wordsplit_len (command, command ? strlen (command) : 0, ws, flags); diff --git a/src/wordsplit.h b/src/wordsplit.h index a531ac0..6a78c48 100644 --- a/src/wordsplit.h +++ b/src/wordsplit.h @@ -19,39 +19,82 @@ #include <stddef.h> -struct wordsplit +/* 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 the ws_flags 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 { - size_t ws_wordc; - char **ws_wordv; - size_t ws_offs; - size_t ws_wordn; - int ws_flags; - int ws_options; - const char *ws_delim; - const char *ws_comment; - const char *ws_escape; - void (*ws_alloc_die) (struct wordsplit * wsp); + 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. */ + int ws_flags; /* [Input] Flags passed to wordsplit. */ + int ws_options; /* [Input] (WRDSF_PATHEXPAND) + Additional options. */ + const char *ws_delim; /* [Input] (WRDSF_DELIM) Word delimiters. */ + const char *ws_comment; /* [Input] (WRDSF_COMMENT) Comment characters. */ + const char *ws_escape; /* [Input] (WRDSF_ESCAPE) Characters to be escaped + with backslash. */ + void (*ws_alloc_die) (struct wordsplit *wsp); + /* [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 + reporting */ void (*ws_debug) (const char *, ...) __attribute__ ((__format__ (__printf__, 1, 2))); - - const char **ws_env; - int (*ws_getvar) (char **, const char *, size_t, void *); - void *ws_closure; - - int (*ws_command) (char **, const char *, size_t, char **, void *); + /* [Input] (WRDSF_DEBUG) Function used for debug + output. */ + const char **ws_env; /* [Input] (WRDSF_ENV, !WRDSF_NOVAR) Array of + environment variables. */ + int (*ws_getvar) (char **ret, const char *var, size_t len, void *clos); + /* [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 + 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 + location pointed to by RET the expansion of + the command CMD (LEN bytes nong). If WRDSF_ARGV + flag is set, ARGV contains CMD split out to + words. Otherwise ARGV is NULL. + + See ws_getvar for a discussion of possible + return values. */ - const char *ws_input; - size_t ws_len; - size_t ws_endp; - int ws_errno; - char *ws_usererr; + 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; /* [Input/Output] 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. */ + int ws_lvl; /* Invocation nesting level. */ }; -/* Wordsplit flags. Only 1 bit of a 32-bit word remains unused. - It is getting crowded... */ +/* Wordsplit flags. */ /* Append the words found to the array resulting from a previous call. */ #define WRDSF_APPEND 0x00000001 @@ -134,7 +177,7 @@ struct wordsplit #define WRDSO_NULLGLOB 0x01 /* Print error message if path expansion produces empty string */ #define WRDSO_FAILGLOB 0x02 -/* Allow a leading period to be matched by metacharacters. */ +/* Allow a leading period to be matched by metacharacters. */ #define WRDSO_DOTGLOB 0x04 #define WRDSE_OK 0 |