aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-06-20 09:45:03 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-06-20 09:58:05 +0300
commit9fd53c66bea84680ac782879c5095608c14d9f4a (patch)
treeded282a00341d32ddab43b6ab694197ef96eceae
parent681919ac19e607566def43cf319e65213fc4cf6d (diff)
downloadsmap-9fd53c66bea84680ac782879c5095608c14d9f4a.tar.gz
smap-9fd53c66bea84680ac782879c5095608c14d9f4a.tar.bz2
Improve wordsplit.
* include/smap/wordsplit.h (wordsplit)<ws_errno>: New member. (WRDSE_NOSUPP): New define. (wordsplit_perror,wordsplit_strerror): New prototypes. * lib/wordsplit.c (all functions): use wordsplit_perror for diagnostics if WRDSF_SHOWERR is set; set ws_errno to the actual error code before returning error. (scan_word): Revise and fix return values. (wordsplit_len): Correctly handle errors, in particular WRDSE_QUOTE. (wordsplit_perror, wordsplit_strerror): New functions. * src/cfg.c (parse_config_loop): Use wordsplit_strerror for diagnostics. * src/module.c (smap_modules_init): Likewise. * src/smapc.c (read_eval_loop): Use wordsplit_perror for diagnostics.
-rw-r--r--include/smap/wordsplit.h6
-rw-r--r--lib/wordsplit.c104
-rw-r--r--src/cfg.c23
-rw-r--r--src/module.c2
-rw-r--r--src/smapc.c4
5 files changed, 110 insertions, 29 deletions
diff --git a/include/smap/wordsplit.h b/include/smap/wordsplit.h
index 59c3ca3..92eb264 100644
--- a/include/smap/wordsplit.h
+++ b/include/smap/wordsplit.h
@@ -34,6 +34,7 @@ struct wordsplit
const char *ws_input;
size_t ws_len;
size_t ws_endp;
+ int ws_errno;
};
/* Append the words found to the array resulting from a previous
@@ -85,6 +86,7 @@ struct wordsplit
#define WRDSE_EOF 0
#define WRDSE_QUOTE 1
#define WRDSE_NOSPACE 2
+#define WRDSE_NOSUPP 3
int wordsplit(const char *s, struct wordsplit *p, int flags);
void wordsplit_free(struct wordsplit *p);
@@ -95,4 +97,8 @@ size_t wordsplit_quoted_length(const char *str, int quote_hex, int *quote);
void wordsplit_unquote_copy(char *dst, const char *src, size_t n);
void wordsplit_quote_copy(char *dst, const char *src, int quote_hex);
+void wordsplit_perror(struct wordsplit *ws);
+const char *wordsplit_strerror(struct wordsplit *ws);
+
+
#endif
diff --git a/lib/wordsplit.c b/lib/wordsplit.c
index b266f93..39b3137 100644
--- a/lib/wordsplit.c
+++ b/lib/wordsplit.c
@@ -34,6 +34,7 @@
# define gettext(s) s
#endif
#define _(msgid) gettext(msgid)
+#define N_(msgid) msgid
#define ISWS(c) ((c)==' '||(c)=='\t'||(c)=='\n')
#define ISDELIM(c,delim) (strchr(delim,(c))!=NULL)
@@ -83,12 +84,11 @@ wordsplit_init(struct wordsplit *wsp, const char *input, size_t len,
if ((wsp->ws_flags & (WRDSF_NOVAR|WRDSF_NOCMD))
!= (WRDSF_NOVAR|WRDSF_NOCMD)) {
- if (wsp->ws_flags & WRDSF_SHOWERR)
- wsp->ws_error(_("variable expansion and "
- "command substitution "
- "are not yet supported"));
errno = EINVAL;
- return 1;
+ wsp->ws_errno = WRDSE_NOSUPP;
+ if (wsp->ws_flags & WRDSF_SHOWERR)
+ wordsplit_perror(wsp);
+ return wsp->ws_errno;
}
wsp->ws_input = input;
@@ -140,12 +140,13 @@ alloc_space(struct wordsplit *wsp)
wsp->ws_wordn = newalloc;
wsp->ws_wordv = ptr;
} else {
+ errno = ENOMEM;
+ wsp->ws_errno = WRDSE_NOSPACE;
if (wsp->ws_flags & WRDSF_ENOMEMABRT)
wsp->ws_alloc_die(wsp);
else if (wsp->ws_flags & WRDSF_SHOWERR)
- wsp->ws_error(_("memory exhausted"));
- errno = ENOMEM;
- return 1;
+ wordsplit_perror(wsp);
+ return wsp->ws_errno;
}
return 0;
}
@@ -199,8 +200,10 @@ skip_delim(struct wordsplit *wsp)
return start;
}
+#define _WRDS_EOF 0
#define _WRDS_WORD 1
#define _WRDS_CONT 2
+#define _WRDS_ERR 3
static int
scan_word(struct wordsplit *wsp, size_t *pstart, size_t *pend)
@@ -213,14 +216,18 @@ scan_word(struct wordsplit *wsp, size_t *pstart, size_t *pend)
size_t i = start;
- if (i >= len)
- return WRDSE_EOF;
-
+ if (i >= len) {
+ wsp->ws_errno = WRDSE_EOF;
+ return _WRDS_EOF;
+ }
+
if (wsp->ws_flags & WRDSF_WS) {
/* Skip initial whitespace */
while (ISWS(command[i]))
- if (++i == len)
- return WRDSE_EOF;
+ if (++i == len) {
+ wsp->ws_errno = WRDSE_EOF;
+ return _WRDS_EOF;
+ }
}
start = i;
@@ -262,12 +269,13 @@ scan_word(struct wordsplit *wsp, size_t *pstart, size_t *pend)
&& command[j] == command[i])
i = j + 1;
else {
+ *pstart = start;
+ *pend = i;
wsp->ws_endp = i;
+ wsp->ws_errno = WRDSE_QUOTE;
if (wsp->ws_flags & WRDSF_SHOWERR)
- wsp->ws_error(
- _("missing closing %c (start near #%lu)"),
- command[i], (unsigned long) i);
- return WRDSE_QUOTE;
+ wordsplit_perror(wsp);
+ return _WRDS_ERR;
}
}
}
@@ -475,7 +483,7 @@ wordsplit_len(const char *command, size_t len, struct wordsplit *wsp,
if (rc)
return rc;
- for (; (rc = scan_word(wsp, &start, &end)) > 0;
+ for (; (rc = scan_word(wsp, &start, &end)) != _WRDS_EOF;
start = skip_delim(wsp)) {
int unquote = 1;
size_t n;
@@ -483,9 +491,11 @@ wordsplit_len(const char *command, size_t len, struct wordsplit *wsp,
if (rc == _WRDS_CONT)
continue;
+ if (rc == _WRDS_ERR)
+ break;
if (alloc_space(wsp))
- return WRDSE_NOSPACE;
+ return wsp->ws_errno;
n = end - start;
@@ -502,16 +512,17 @@ wordsplit_len(const char *command, size_t len, struct wordsplit *wsp,
} else
unquote = 0;
- p = malloc (n + 1);
+ p = malloc(n + 1);
if (!p) {
+ errno = ENOMEM;
+ wsp->ws_errno = WRDSE_NOSPACE;
if (wsp->ws_flags & WRDSF_ENOMEMABRT)
wsp->ws_alloc_die(wsp);
if (wsp->ws_flags & WRDSF_SHOWERR)
- wsp->ws_error(_("memory exhausted"));
+ wordsplit_perror(wsp);
if (!(wsp->ws_flags & WRDSF_REUSE))
wordsplit_free(wsp);
- errno = ENOMEM;
- return WRDSE_NOSPACE;
+ return wsp->ws_errno;
}
if (unquote)
@@ -524,7 +535,7 @@ wordsplit_len(const char *command, size_t len, struct wordsplit *wsp,
wsp->ws_wordc++;
}
if (alloc_space (wsp))
- return WRDSE_NOSPACE;
+ return wsp->ws_errno;
wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc] = NULL;
/* FIXME: if (rc) free(ws) */
return rc;
@@ -542,3 +553,48 @@ wordsplit_free(struct wordsplit *ws)
free(ws->ws_wordv);
ws->ws_wordv = NULL;
}
+
+void
+wordsplit_perror(struct wordsplit *wsp)
+{
+ switch (wsp->ws_errno) {
+ case WRDSE_EOF:
+ wsp->ws_error(_("no error"));
+ break;
+
+ case WRDSE_QUOTE:
+ wsp->ws_error(_("missing closing %c (start near #%lu)"),
+ wsp->ws_input[wsp->ws_endp], wsp->ws_endp);
+ break;
+
+ case WRDSE_NOSPACE:
+ wsp->ws_error(_("memory exhausted"));
+ break;
+
+ case WRDSE_NOSUPP:
+ wsp->ws_error(_("variable expansion and "
+ "command substitution "
+ "are not yet supported"));
+
+ default:
+ wsp->ws_error(_("unknown error"));
+ }
+}
+
+const char *_worsplit_errstr[] = {
+ N_("no error"),
+ N_("missing closing quote"),
+ N_("memory exhausted"),
+ N_("variable expansion and command substitution "
+ "are not yet supported")
+};
+int _worsplit_nerrs = sizeof(_worsplit_errstr)/sizeof(_worsplit_errstr[0]);
+
+const char *
+wordsplit_strerror(struct wordsplit *ws)
+{
+ if (ws->ws_errno < _worsplit_nerrs)
+ return _worsplit_errstr[ws->ws_errno];
+ return N_("unknown error");
+}
+
diff --git a/src/cfg.c b/src/cfg.c
index 8a7d939..0809504 100644
--- a/src/cfg.c
+++ b/src/cfg.c
@@ -174,6 +174,22 @@ save_words(struct wordsplit *ws, struct cfg_kw *kwp)
*kwp->aval = aval;
}
+int
+wrdse_to_ex(int code)
+{
+ switch (code) {
+ case WRDSE_EOF:
+ return 0;
+ case WRDSE_QUOTE:
+ return EX_CONFIG;
+ case WRDSE_NOSPACE:
+ return EX_UNAVAILABLE;
+ case WRDSE_NOSUPP:
+ return EX_SOFTWARE;
+ }
+ return EX_UNAVAILABLE;
+}
+
void
parse_config_loop(struct cfg_kw *kwtab, void *data)
{
@@ -190,9 +206,10 @@ parse_config_loop(struct cfg_kw *kwtab, void *data)
struct cfg_kw *kwp;
if (wordsplit(buf, &ws, wsflags)) {
- smap_error("%s:%u: cannot parse line",
- cfg_file_name, cfg_line);
- exit(EX_SOFTWARE);
+ smap_error("%s:%u: %s",
+ cfg_file_name, cfg_line,
+ wordsplit_strerror(&ws));
+ exit(wrdse_to_ex(ws.ws_errno));
}
wsflags |= WRDSF_REUSE;
diff --git a/src/module.c b/src/module.c
index a40182f..6160893 100644
--- a/src/module.c
+++ b/src/module.c
@@ -53,7 +53,7 @@ smap_modules_init()
WRDSF_ENOMEMABRT | WRDSF_SQUEEZE_DELIMS |
WRDSF_DELIM | WRDSF_ERROR)) {
smap_error("cannot parse load path: %s",
- strerror(errno));
+ wordsplit_strerror(&ws));
return;
}
diff --git a/src/smapc.c b/src/smapc.c
index 13a2f0b..7cec3ca 100644
--- a/src/smapc.c
+++ b/src/smapc.c
@@ -660,8 +660,10 @@ read_eval_loop(FILE *fp, int interactive)
continue;
}
if (cmdprefix == 0 || p[0] == cmdprefix) {
- if (wordsplit(p + !!cmdprefix, &ws, flags))
+ if (wordsplit(p + !!cmdprefix, &ws, flags)) {
+ wordsplit_perror(&ws);
break;
+ }
flags |= WRDSF_REUSE;
if (ws.ws_wordc && handle_command(&ws))
break;

Return to:

Send suggestions and report system problems to the System administrator.