From 0fe0edf89487fb5d13d2cd07f35eecdb45e87af7 Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Tue, 11 Jan 2011 00:11:45 +0000 Subject: 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@ --- main.c | 3 ++- mandoc.h | 3 ++- roff.c | 85 +++++++++++++++++++++++++++++++++++----------------------------- 3 files changed, 50 insertions(+), 41 deletions(-) diff --git a/main.c b/main.c index 941fa5e2..b6954da2 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.136 2011/01/10 14:40:30 kristaps Exp $ */ +/* $Id: main.c,v 1.137 2011/01/11 00:11:45 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010 Ingo Schwarze @@ -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", diff --git a/mandoc.h b/mandoc.h index e7c0e96a..9cfb350a 100644 --- a/mandoc.h +++ b/mandoc.h @@ -1,4 +1,4 @@ -/* $Id: mandoc.h,v 1.51 2011/01/10 15:31:00 kristaps Exp $ */ +/* $Id: mandoc.h,v 1.52 2011/01/11 00:11:45 schwarze Exp $ */ /* * Copyright (c) 2010, 2011 Kristaps Dzonsons * @@ -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 */ diff --git a/roff.c b/roff.c index 5053bef5..56106228 100644 --- a/roff.c +++ b/roff.c @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.120 2011/01/03 23:24:16 schwarze Exp $ */ +/* $Id: roff.c,v 1.121 2011/01/11 00:11:45 schwarze Exp $ */ /* * Copyright (c) 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010, 2011 Ingo Schwarze @@ -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'; -- cgit v1.2.3-56-ge451