diff options
Diffstat (limited to 'argv.c')
-rw-r--r-- | argv.c | 188 |
1 files changed, 153 insertions, 35 deletions
@@ -26,17 +26,49 @@ #include "private.h" -static int parse_next(struct mdoc *, int, - int *, char *, char **); +static int lookup(int, const char *); +static int parse(struct mdoc *, int, + struct mdoc_arg *, int *, char *); +static int postparse(struct mdoc *, int, + const struct mdoc_arg *, int); -static int -parse_next(struct mdoc *mdoc, int tok, - int *pos, char *buf, char **v) +int +mdoc_args(struct mdoc *mdoc, int tok, int *pos, char *buf, int fl, char **v) { + int i; if (0 == buf[*pos]) - return(0); + return(ARGS_EOLN); + + if ('\"' == buf[*pos] && ! (fl & ARGS_QUOTED)) + if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_QUOTED)) + return(ARGS_ERROR); + + if ('-' == buf[*pos]) + if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_ARGLIKE)) + return(ARGS_ERROR); + + if ((fl & ARGS_DELIM) && mdoc_iscdelim(buf[*pos])) { + for (i = *pos; buf[i]; ) { + if ( ! mdoc_iscdelim(buf[i])) + break; + i++; + if (0 == buf[i] || ! isspace(buf[i])) + break; + i++; + while (buf[i] && isspace(buf[i])) + i++; + } + if (0 == buf[i]) { + *v = &buf[*pos]; + return(ARGS_PUNCT); + } + } + + /* + * Parse routine for non-quoted string. + */ if ('\"' != buf[*pos]) { *v = &buf[*pos]; @@ -45,26 +77,31 @@ parse_next(struct mdoc *mdoc, int tok, (*pos)++; if (0 == buf[*pos]) - return(1); + return(ARGS_WORD); buf[(*pos)++] = 0; if (0 == buf[*pos]) - return(1); + return(ARGS_WORD); while (buf[*pos] && isspace(buf[*pos])) (*pos)++; if (buf[*pos]) - return(1); + return(ARGS_WORD); if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_WS_EOLN)) - return(-1); - return(1); - } + return(ARGS_ERROR); - if ('-' == buf[*pos]) - if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_ARGLIKE)) - return(-1); + return(ARGS_WORD); + } + + /* + * If we're a quoted string (and quoted strings are allowed), + * then parse ahead to the next quote. If none's found, it's an + * error. After, parse to the next word. We're not allowed to + * also be DELIM requests (for now). + */ + assert( ! (fl & ARGS_DELIM)); *v = &buf[++(*pos)]; @@ -73,31 +110,32 @@ parse_next(struct mdoc *mdoc, int tok, if (0 == buf[*pos]) { (void)mdoc_err(mdoc, tok, *pos, ERR_SYNTAX_UNQUOTE); - return(-1); + return(ARGS_ERROR); } buf[(*pos)++] = 0; if (0 == buf[*pos]) - return(1); + return(ARGS_WORD); while (buf[*pos] && isspace(buf[*pos])) (*pos)++; if (buf[*pos]) - return(1); + return(ARGS_WORD); if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_WS_EOLN)) - return(-1); - return(1); + return(ARGS_ERROR); + + return(ARGS_WORD); } -int -mdoc_argv_lookup(int tok, const char *argv) +static int +lookup(int tok, const char *argv) { switch (tok) { - case (MDOC_Bl): + case (MDOC_Bd): if (xstrcmp(argv, "ragged")) return(MDOC_Ragged); else if (xstrcmp(argv, "unfilled")) @@ -108,7 +146,10 @@ mdoc_argv_lookup(int tok, const char *argv) return(MDOC_File); else if (xstrcmp(argv, "offset")) return(MDOC_Offset); - else if (xstrcmp(argv, "bullet")) + break; + + case (MDOC_Bl): + if (xstrcmp(argv, "bullet")) return(MDOC_Bullet); else if (xstrcmp(argv, "dash")) return(MDOC_Dash); @@ -132,10 +173,12 @@ mdoc_argv_lookup(int tok, const char *argv) return(MDOC_Column); else if (xstrcmp(argv, "width")) return(MDOC_Width); + else if (xstrcmp(argv, "offset")) + return(MDOC_Offset); else if (xstrcmp(argv, "compact")) return(MDOC_Compact); - break; + default: abort(); /* NOTREACHED */ @@ -145,17 +188,43 @@ mdoc_argv_lookup(int tok, const char *argv) } -int -mdoc_argv_parse(struct mdoc *mdoc, int tok, int arg, +static int +postparse(struct mdoc *mdoc, int tok, const struct mdoc_arg *v, int pos) +{ + + switch (v->arg) { + case (MDOC_Offset): + assert(v->value); + assert(v->value[0]); + if (xstrcmp(v->value[0], "left")) + break; + if (xstrcmp(v->value[0], "right")) + break; + if (xstrcmp(v->value[0], "center")) + break; + if (xstrcmp(v->value[0], "indent")) + break; + if (xstrcmp(v->value[0], "indent-two")) + break; + return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_ARGBAD)); + default: + break; + } + + return(1); +} + + +static int +parse(struct mdoc *mdoc, int tok, struct mdoc_arg *v, int *pos, char *buf) { char *p; int c, ppos, i; - v->arg = arg; ppos = *pos; - switch (arg) { + switch (v->arg) { case(MDOC_Compact): /* FALLTHROUGH */ case(MDOC_Ragged): @@ -195,10 +264,10 @@ mdoc_argv_parse(struct mdoc *mdoc, int tok, int arg, /* * This has a single value for an argument. */ - c = parse_next(mdoc, tok, pos, buf, &p); - if (-1 == c) + c = mdoc_args(mdoc, tok, pos, buf, ARGS_QUOTED, &p); + if (ARGS_ERROR == c) return(0); - else if (0 == c) + else if (ARGS_EOLN == c) return(mdoc_err(mdoc, tok, ppos, ERR_SYNTAX_ARGVAL)); v->sz = 1; @@ -215,11 +284,11 @@ mdoc_argv_parse(struct mdoc *mdoc, int tok, int arg, v->sz = 0; v->value = xcalloc(MDOC_LINEARG_MAX, sizeof(char *)); for (i = 0; i < MDOC_LINEARG_MAX; i++) { - c = parse_next(mdoc, tok, pos, buf, &p); - if (-1 == c) { + c = mdoc_args(mdoc, tok, pos, buf, ARGS_QUOTED, &p); + if (ARGS_ERROR == c) { free(v->value); return(0); - } else if (0 == c) + } else if (ARGS_EOLN == c) break; v->value[i] = p; } @@ -240,6 +309,54 @@ mdoc_argv_parse(struct mdoc *mdoc, int tok, int arg, } +int +mdoc_argv(struct mdoc *mdoc, int tok, + struct mdoc_arg *v, int *pos, char *buf) +{ + int i, ppos; + char *argv; + + (void)memset(v, 0, sizeof(struct mdoc_arg)); + + if (0 == buf[*pos]) + return(0); + + assert( ! isspace(buf[*pos])); + + if ('-' != buf[*pos]) { + (void)mdoc_err(mdoc, tok, *pos, ERR_SYNTAX_ARGFORM); + return(-1); + } + + i = *pos; + argv = &buf[++(*pos)]; + + while (buf[*pos] && ! isspace(buf[*pos])) + (*pos)++; + + if (buf[*pos]) + buf[(*pos)++] = 0; + + if (MDOC_ARG_MAX == (v->arg = lookup(tok, argv))) { + (void)mdoc_err(mdoc, tok, i, ERR_SYNTAX_ARG); + return(-1); + } + + while (buf[*pos] && isspace(buf[*pos])) + (*pos)++; + + /* FIXME: whitespace if no value. */ + + ppos = *pos; + if ( ! parse(mdoc, tok, v, pos, buf)) + return(-1); + if ( ! postparse(mdoc, tok, v, ppos)) + return(-1); + + return(1); +} + + void mdoc_argv_free(int sz, struct mdoc_arg *arg) { @@ -254,3 +371,4 @@ mdoc_argv_free(int sz, struct mdoc_arg *arg) free(arg[i].value); } } + |