mirror of
git://git.gnu.org.ua/wordsplit.git
synced 2025-04-26 00:29:54 +03:00
Improve wordsplit documentation and debug output.
This commit is contained in:
parent
731d730447
commit
73180a045d
2 changed files with 145 additions and 47 deletions
101
src/wordsplit.c
101
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)
|
||||
|
@ -1955,6 +2003,13 @@ wordsplit_len (const char *command, size_t length, struct wordsplit *wsp,
|
|||
return wsp->ws_errno;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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)));
|
||||
/* [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.
|
||||
|
||||
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 *);
|
||||
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue