diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2011-01-11 00:11:45 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2011-01-11 00:11:45 +0000 |
commit | e86d735736590229d3795c7000334674b1b54359 (patch) | |
tree | a09d91906261b72cce7cb3b703831fe3895d7f1b | |
parent | ed5e3c51cf000a55a9774ad85994aa7c35abc0df (diff) | |
download | mandoc-e86d735736590229d3795c7000334674b1b54359.tar.gz |
Refactoring in preparation for .rm support:
Unify parsing of names given as roff request arguments into a new
function roff_getname(), which is rather different from the parsing
function for normal arguments, mandoc_getarg(), because names cannot
be quoted and cannot contain whitespace or escaped characters.
The new function now throws an ERROR when finding escaped characters
in a name.
"I'm fine with this." kristaps@
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | mandoc.h | 1 | ||||
-rw-r--r-- | roff.c | 83 |
3 files changed, 47 insertions, 38 deletions
@@ -192,6 +192,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = { "input stack limit exceeded, infinite loop?", "skipping bad character", + "escaped character not allowed in a name", "skipping text before the first section header", "skipping unknown macro", "NOT IMPLEMENTED: skipping request", @@ -114,6 +114,7 @@ enum mandocerr { MANDOCERR_ROFFLOOP, /* input stack limit exceeded, infinite loop? */ MANDOCERR_BADCHAR, /* skipping bad character */ + MANDOCERR_NAMESC, /* escaped character not allowed in a name */ MANDOCERR_NOTEXT, /* skipping text before the first section header */ MANDOCERR_MACRO, /* skipping unknown macro */ MANDOCERR_REQUEST, /* NOT IMPLEMENTED: skipping request */ @@ -134,6 +134,7 @@ static enum rofferr roff_cond_sub(ROFF_ARGS); static enum rofferr roff_ds(ROFF_ARGS); static enum roffrule roff_evalcond(const char *, int *); static void roff_freestr(struct roff *); +static char *roff_getname(struct roff *, char **, int, int); static const char *roff_getstrn(const struct roff *, const char *, size_t); static enum rofferr roff_line_ignore(ROFF_ARGS); @@ -520,7 +521,7 @@ roff_endparse(struct roff *r) { if (r->last) - (*r->msg)(MANDOCERR_SCOPEEXIT, r->data, + (*r->msg)(MANDOCERR_SCOPEEXIT, r->data, r->last->line, r->last->col, NULL); if (r->tbl) { @@ -1056,25 +1057,13 @@ roff_ds(ROFF_ARGS) * will have `bar " ' as its value. */ - name = *bufp + pos; + string = *bufp + pos; + name = roff_getname(r, &string, ln, pos); if ('\0' == *name) return(ROFF_IGN); - string = name; - /* Read until end of name. */ - while (*string && ' ' != *string) - string++; - - /* Nil-terminate name. */ - if (*string) - *(string++) = '\0'; - - /* Read past spaces. */ - while (*string && ' ' == *string) - string++; - - /* Read passed initial double-quote. */ - if (*string && '"' == *string) + /* Read past initial double-quote. */ + if ('"' == *string) string++; /* The rest is the value. */ @@ -1087,31 +1076,14 @@ roff_ds(ROFF_ARGS) static enum rofferr roff_nr(ROFF_ARGS) { - const char *key, *val; + const char *key; + char *val; struct reg *rg; - key = &(*bufp)[pos]; + val = *bufp + pos; + key = roff_getname(r, &val, ln, pos); rg = r->regs->regs; - /* Parse register request. */ - while ((*bufp)[pos] && ' ' != (*bufp)[pos]) - pos++; - - /* - * Set our nil terminator. Because this line is going to be - * ignored anyway, we can munge it as we please. - */ - if ((*bufp)[pos]) - (*bufp)[pos++] = '\0'; - - /* Skip whitespace to register token. */ - while ((*bufp)[pos] && ' ' == (*bufp)[pos]) - pos++; - - val = &(*bufp)[pos]; - - /* Process register token. */ - if (0 == strcmp(key, "nS")) { rg[(int)REG_nS].set = 1; if ( ! roff_parse_nat(val, &rg[(int)REG_nS].v.u)) @@ -1250,6 +1222,41 @@ roff_userdef(ROFF_ARGS) ROFF_REPARSE : ROFF_APPEND); } + +static char * +roff_getname(struct roff *r, char **cpp, int ln, int pos) +{ + char *name, *cp; + + name = *cpp; + if ('\0' == *name) + return(name); + + /* Read until end of name. */ + for (cp = name; '\0' != *cp && ' ' != *cp; cp++) { + if ('\\' != *cp) + continue; + cp++; + if ('\\' == *cp) + continue; + (*r->msg)(MANDOCERR_NAMESC, r->data, ln, pos, NULL); + *cp = '\0'; + name = cp; + } + + /* Nil-terminate name. */ + if ('\0' != *cp) + *(cp++) = '\0'; + + /* Read past spaces. */ + while (' ' == *cp) + cp++; + + *cpp = cp; + return(name); +} + + /* * Store *string into the user-defined string called *name. * In multiline mode, append to an existing entry and append '\n'; |