aboutsummaryrefslogtreecommitdiff
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
parent790e1d4e29514da57265875496f9dcb7c2d6f1c2 (diff)
downloadgrecs-8383ec3a522a944969b3fc44069a3ff056da554a.tar.gz
grecs-8383ec3a522a944969b3fc44069a3ff056da554a.tar.bz2
Improve wordsplit documentation and debug output.
-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
@@ -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

Return to:

Send suggestions and report system problems to the System administrator.