aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2014-10-23 12:12:02 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2015-12-17 15:25:24 +0200
commite66e2edfa50c8535e05b334c6a5d867fafeb9469 (patch)
tree5af187dea3750df11c404658c624300bae324d97 /src
parentbeda81512afdcf16432ebd5b76930392f427a7fc (diff)
downloadgrecs-e66e2edfa50c8535e05b334c6a5d867fafeb9469.tar.gz
grecs-e66e2edfa50c8535e05b334c6a5d867fafeb9469.tar.bz2
Change prototypes of ws_getvar and ws_command.
New invocation sequence ensures proper error handling. This is an incompatible change. Authors using ws_getvar member will have to rewrite their ws_getvar function accordingly. * src/wordsplit.c (wordsplit_init0): Call wordsplit_clearerr on reuse. (wordsplit_init): Fix ws_errno (expvar): Change invocation of ws_getvar. (expcmd): Change invocation of ws_command. (wordsplit_clearerr): New function. (wordsplit_strerror): Handle WRDSE_USERERR. * src/wordsplit.h (ws_getvar): Change return value and signature of ws_getvar and ws_command. New member 'ws_usererr'. (WRDSF_ARGV): New flag. (WRDSE_OK): New define. Same as WRDSE_EOF. (WRDSE_USERERR): New error code. (wordsplit_clearerr): New proto. * tests/wsp.c (wsp_getvar, wsp_runcmd): Rewrite.
Diffstat (limited to 'src')
-rw-r--r--src/wordsplit.c67
-rw-r--r--src/wordsplit.h14
2 files changed, 74 insertions, 7 deletions
diff --git a/src/wordsplit.c b/src/wordsplit.c
index f17ed98..2b99b42 100644
--- a/src/wordsplit.c
+++ b/src/wordsplit.c
@@ -93,12 +93,13 @@ static void
wordsplit_init0 (struct wordsplit *wsp)
{
if (wsp->ws_flags & WRDSF_REUSE)
{
if (!(wsp->ws_flags & WRDSF_APPEND))
wordsplit_free_words (wsp);
+ wordsplit_clearerr (wsp);
}
else
{
wsp->ws_wordv = NULL;
wsp->ws_wordc = 0;
wsp->ws_wordn = 0;
@@ -131,13 +132,13 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
if (!(wsp->ws_flags & WRDSF_NOCMD))
{
if (!wsp->ws_command)
{
errno = EINVAL;
- wsp->ws_errno = WRDSE_NOSUPP;
+ wsp->ws_errno = WRDSE_USAGE;
if (wsp->ws_flags & WRDSF_SHOWERR)
wordsplit_perror (wsp);
return wsp->ws_errno;
}
}
@@ -783,13 +784,36 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
{
value = strdup (vptr);
if (!value)
return _wsplt_nomem (wsp);
}
else if (wsp->ws_flags & WRDSF_GETVAR)
- value = wsp->ws_getvar (str, i, wsp->ws_closure);
+ {
+ int rc = wsp->ws_getvar (&value, str, i, wsp->ws_closure);
+ switch (rc)
+ {
+ case WRDSE_OK:
+ break;
+
+ case WRDSE_NOSPACE:
+ return _wsplt_nomem (wsp);
+
+ case WRDSE_UNDEF:
+ value = NULL;
+ break;
+
+ case WRDSE_USERERR:
+ wsp->ws_usererr = value;
+ /* fall through */
+ default:
+ wsp->ws_errno = rc;
+ if (wsp->ws_flags & WRDSF_SHOWERR)
+ wordsplit_perror (wsp);
+ return 1;
+ }
+ }
else
value = NULL;
if (!value)
{
if (defstr)
@@ -815,13 +839,13 @@ expvar (struct wordsplit *wsp, const char *str, size_t len,
(int) i, str, (int) size, defstr);
}
}
else if (wsp->ws_flags & WRDSF_UNDEF)
{
wsp->ws_errno = WRDSE_UNDEF;
- if (wsp->ws_flags & WRDSF_SHOWERR)
+ if (wsp->ws_flags & WRDSF_SHOWERR)
wordsplit_perror (wsp);
return 1;
}
else
{
if (wsp->ws_flags & WRDSF_WARNUNDEF)
@@ -1030,12 +1054,13 @@ begin_cmd_p (int 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;
str++;
len--;
@@ -1044,13 +1069,36 @@ expcmd (struct wordsplit *wsp, const char *str, size_t len,
{
wsp->ws_errno = WRDSE_CBRACE;
return 1;
}
*pend = str + j;
- value = wsp->ws_command (str, j, wsp);
+ if (wsp->ws_flags & WRDSF_ARGV)
+ {
+ 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 = wsp->ws_command (&value, str, j, ws.ws_wordv, wsp->ws_closure);
+ }
+ else
+ rc = wsp->ws_command (&value, str, j, NULL, wsp->ws_closure);
+
+ if (rc == WRDSE_NOSPACE)
+ return _wsplt_nomem (wsp);
+ else if (rc)
+ {
+ if (rc == WRDSE_USERERR)
+ wsp->ws_usererr = value;
+ wsp->ws_errno = rc;
+ if (wsp->ws_flags & WRDSF_SHOWERR)
+ wordsplit_perror (wsp);
+ return 1;
+ }
if (value)
{
if (flg & _WSNF_QUOTE)
{
if (wsnode_new (wsp, &newnode))
@@ -1749,12 +1797,21 @@ wordsplit_free_words (struct wordsplit *ws)
}
}
ws->ws_wordc = 0;
}
void
+wordsplit_clearerr (struct wordsplit *ws)
+{
+ if (ws->ws_errno == WRDSE_USERERR)
+ free (ws->ws_usererr);
+ ws->ws_usererr = NULL;
+ ws->ws_errno = WRDSE_OK;
+}
+
+void
wordsplit_free (struct wordsplit *ws)
{
wordsplit_free_words (ws);
free (ws->ws_wordv);
ws->ws_wordv = NULL;
}
@@ -1816,10 +1873,12 @@ const char *_wordsplit_errstr[] = {
int _wordsplit_nerrs =
sizeof (_wordsplit_errstr) / sizeof (_wordsplit_errstr[0]);
const char *
wordsplit_strerror (struct wordsplit *ws)
{
+ if (ws->ws_errno == WRDSE_USERERR)
+ return ws->ws_usererr;
if (ws->ws_errno < _wordsplit_nerrs)
return _wordsplit_errstr[ws->ws_errno];
return N_("unknown error");
}
diff --git a/src/wordsplit.h b/src/wordsplit.h
index 96088f9..4a0cd88 100644
--- a/src/wordsplit.h
+++ b/src/wordsplit.h
@@ -33,25 +33,26 @@ struct wordsplit
void (*ws_error) (const char *, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
void (*ws_debug) (const char *, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
const char **ws_env;
- char *(*ws_getvar) (const char *, size_t, void *);
+ int (*ws_getvar) (char **, const char *, size_t, void *);
void *ws_closure;
- char *(*ws_command) (const char *, size_t, struct wordsplit const *);
+ int (*ws_command) (char **, const char *, size_t, char **, void *);
const char *ws_input;
size_t ws_len;
size_t ws_endp;
int ws_errno;
+ char *ws_usererr;
struct wordsplit_node *ws_head, *ws_tail;
};
-/* Wordsplit flags. Only 2 bits of a 32-bit word remain unused.
+/* Wordsplit flags. Only 1 bit of a 32-bit word remains unused.
It is getting crowded... */
/* Append the words found to the array resulting from a previous
call. */
#define WRDSF_APPEND 0x00000001
/* Insert we_offs initial NULLs in the array ws_wordv.
(These are not counted in the returned ws_wordc.) */
@@ -122,24 +123,29 @@ struct wordsplit
/* ws_escape is set */
#define WRDSF_ESCAPE 0x10000000
/* Incremental mode */
#define WRDSF_INCREMENTAL 0x20000000
+/* ws_command needs argv parameter */
+#define WRDSF_ARGV 0x40000000
+
#define WRDSF_DEFFLAGS \
(WRDSF_NOVAR | WRDSF_NOCMD | \
WRDSF_QUOTE | WRDSF_SQUEEZE_DELIMS | WRDSF_CESCAPES)
+#define WRDSE_OK 0
#define WRDSE_EOF 0
#define WRDSE_QUOTE 1
#define WRDSE_NOSPACE 2
#define WRDSE_NOSUPP 3
#define WRDSE_USAGE 4
#define WRDSE_CBRACE 5
#define WRDSE_UNDEF 6
#define WRDSE_NOINPUT 7
+#define WRDSE_USERERR 8
int wordsplit (const char *s, struct wordsplit *p, int flags);
int wordsplit_len (const char *s, size_t len,
struct wordsplit *p, int flags);
void wordsplit_free (struct wordsplit *p);
void wordsplit_free_words (struct wordsplit *ws);
@@ -154,8 +160,10 @@ void wordsplit_sh_unquote_copy (char *dst, const char *src, size_t n);
void wordsplit_c_unquote_copy (char *dst, const char *src, size_t n);
void wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex);
void wordsplit_perror (struct wordsplit *ws);
const char *wordsplit_strerror (struct wordsplit *ws);
+void wordsplit_clearerr (struct wordsplit *ws);
+
#endif

Return to:

Send suggestions and report system problems to the System administrator.