aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2014-10-24 22:41:25 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2015-12-17 15:25:24 +0200
commit8383ec3a522a944969b3fc44069a3ff056da554a (patch)
tree6fde51206df3e0a9a07c6edaf5f80aa580676f36 /src
parent790e1d4e29514da57265875496f9dcb7c2d6f1c2 (diff)
downloadgrecs-8383ec3a522a944969b3fc44069a3ff056da554a.tar.gz
grecs-8383ec3a522a944969b3fc44069a3ff056da554a.tar.bz2
Improve wordsplit documentation and debug output.
Diffstat (limited to 'src')
-rw-r--r--src/wordsplit.c101
-rw-r--r--src/wordsplit.h93
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
@@ -102,2 +102,39 @@ _wsplt_nomem (struct wordsplit *wsp)
+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
@@ -431,6 +468,8 @@ wordsplit_dump_nodes (struct wordsplit *wsp)
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),
@@ -899,7 +938,6 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
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);
@@ -907,2 +945,3 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
{
+ _wsplt_seterr_sub (wsp, &ws);
wordsplit_free (&ws);
@@ -1078,7 +1117,13 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
- 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);
}
@@ -1127,6 +1172,5 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
- 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);
@@ -1134,2 +1178,3 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
{
+ _wsplt_seterr_sub (wsp, &ws);
wordsplit_free (&ws);
@@ -1860,3 +1905,3 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start)
{
- wsp->ws_debug (_("Initial list:"));
+ wsp->ws_debug ("(%02d) %s", wsp->ws_lvl, _("Initial list:"));
wordsplit_dump_nodes (wsp);
@@ -1875,3 +1920,4 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start)
{
- wsp->ws_debug (_("Coalesced list:"));
+ wsp->ws_debug ("(%02d) %s", wsp->ws_lvl,
+ _("Coalesced list:"));
wordsplit_dump_nodes (wsp);
@@ -1885,3 +1931,3 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start)
{
- wsp->ws_debug ("%s:", _(p->descr));
+ wsp->ws_debug ("(%02d) %s", wsp->ws_lvl, _(p->descr));
wordsplit_dump_nodes (wsp);
@@ -1894,5 +1940,5 @@ wordsplit_process_list (struct wordsplit *wsp, size_t start)
-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)
{
@@ -1925,2 +1971,3 @@ wordsplit_len (const char *command, size_t length, struct wordsplit *wsp,
return rc;
+ wsp->ws_lvl = lvl;
}
@@ -1928,3 +1975,3 @@ wordsplit_len (const char *command, size_t length, struct wordsplit *wsp,
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);
@@ -1940,3 +1987,4 @@ wordsplit_len (const char *command, size_t length, struct wordsplit *wsp,
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);
}
@@ -1958,2 +2006,9 @@ 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)
diff --git a/src/wordsplit.h b/src/wordsplit.h
index a531ac0..6a78c48 100644
--- a/src/wordsplit.h
+++ b/src/wordsplit.h
@@ -21,35 +21,78 @@
-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
@@ -136,3 +179,3 @@ struct wordsplit
#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

Return to:

Send suggestions and report system problems to the System administrator.