summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2011-01-11 00:11:45 +0000
committerIngo Schwarze <schwarze@openbsd.org>2011-01-11 00:11:45 +0000
commite86d735736590229d3795c7000334674b1b54359 (patch)
treea09d91906261b72cce7cb3b703831fe3895d7f1b
parented5e3c51cf000a55a9774ad85994aa7c35abc0df (diff)
downloadmandoc-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.c1
-rw-r--r--mandoc.h1
-rw-r--r--roff.c83
3 files changed, 47 insertions, 38 deletions
diff --git a/main.c b/main.c
index 055ad2d1..87ba122b 100644
--- a/main.c
+++ b/main.c
@@ -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 72782eb1..04aa7cdf 100644
--- a/mandoc.h
+++ b/mandoc.h
@@ -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 af7617a9..bc24a88f 100644
--- a/roff.c
+++ b/roff.c
@@ -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';