diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2010-05-15 13:12:56 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2010-05-15 13:12:56 +0000 |
commit | 1943a41de13092e8e3da688f4172b121a46bd157 (patch) | |
tree | 2ea9e8ce296dd662fd8c886cfedde9ec2f902845 | |
parent | a355e7868a2177fe355b4911c68ec4103093780b (diff) |
proper handling of quoted tab-separated column lists
by kristaps@
-rw-r--r-- | usr.bin/mandoc/libmdoc.h | 10 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_argv.c | 58 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_macro.c | 51 |
3 files changed, 64 insertions, 55 deletions
diff --git a/usr.bin/mandoc/libmdoc.h b/usr.bin/mandoc/libmdoc.h index 3b59e440d82..6ac17daf5d7 100644 --- a/usr.bin/mandoc/libmdoc.h +++ b/usr.bin/mandoc/libmdoc.h @@ -1,4 +1,4 @@ -/* $Id: libmdoc.h,v 1.31 2010/05/15 12:30:59 schwarze Exp $ */ +/* $Id: libmdoc.h,v 1.32 2010/05/15 13:12:55 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> * @@ -32,6 +32,8 @@ struct mdoc { #define MDOC_LITERAL (1 << 1) /* in a literal scope */ #define MDOC_PBODY (1 << 2) /* in the document body */ #define MDOC_NEWLINE (1 << 3) /* first macro/text in a line */ +#define MDOC_PHRASELIT (1 << 4) /* literal within a partila phrase */ +#define MDOC_PPHRASE (1 << 5) /* within a partial phrase */ int pflags; enum mdoc_next next; struct mdoc_node *last; @@ -193,9 +195,9 @@ enum margserr mdoc_args(struct mdoc *, int, int *, char *, enum mdoct, char **); enum margserr mdoc_zargs(struct mdoc *, int, int *, char *, int, char **); -#define ARGS_DELIM (1 << 1) /* See args(). */ -#define ARGS_TABSEP (1 << 2) /* See args(). */ -#define ARGS_NOWARN (1 << 3) /* See args(). */ +#define ARGS_DELIM (1 << 1) +#define ARGS_TABSEP (1 << 2) +#define ARGS_NOWARN (1 << 3) int mdoc_macroend(struct mdoc *); diff --git a/usr.bin/mandoc/mdoc_argv.c b/usr.bin/mandoc/mdoc_argv.c index 6e284601a2f..d4b1cc4bb6c 100644 --- a/usr.bin/mandoc/mdoc_argv.c +++ b/usr.bin/mandoc/mdoc_argv.c @@ -1,4 +1,4 @@ -/* $Id: mdoc_argv.c,v 1.27 2010/05/15 12:30:59 schwarze Exp $ */ +/* $Id: mdoc_argv.c,v 1.28 2010/05/15 13:12:55 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> * @@ -394,8 +394,21 @@ args(struct mdoc *m, int line, int *pos, assert(*pos); assert(' ' != buf[*pos]); - if ('\0' == buf[*pos]) + if ('\0' == buf[*pos]) { + if (MDOC_PPHRASE & m->flags) + return(ARGS_EOLN); + /* + * If we're not in a partial phrase and the flag for + * being a phrase literal is still set, the punctuation + * is unterminated. + */ + if (MDOC_PHRASELIT & m->flags) + if ( ! mdoc_pwarn(m, line, *pos, EQUOTTERM)) + return(ARGS_ERROR); + + m->flags &= ~MDOC_PHRASELIT; return(ARGS_EOLN); + } /* * If the first character is a closing delimiter and we're to @@ -441,16 +454,18 @@ args(struct mdoc *m, int line, int *pos, if (ARGS_TABSEP & fl) { /* Scan ahead to tab (can't be escaped). */ p = strchr(*v, '\t'); + pp = NULL; /* Scan ahead to unescaped `Ta'. */ - for (pp = *v; ; pp++) { - if (NULL == (pp = strstr(pp, "Ta"))) - break; - if (pp > *v && ' ' != *(pp - 1)) - continue; - if (' ' == *(pp + 2) || 0 == *(pp + 2)) - break; - } + if ( ! (MDOC_PHRASELIT & m->flags)) + for (pp = *v; ; pp++) { + if (NULL == (pp = strstr(pp, "Ta"))) + break; + if (pp > *v && ' ' != *(pp - 1)) + continue; + if (' ' == *(pp + 2) || 0 == *(pp + 2)) + break; + } /* By default, assume a phrase. */ rc = ARGS_PHRASE; @@ -503,8 +518,12 @@ args(struct mdoc *m, int line, int *pos, * Whitespace is NOT involved in literal termination. */ - if ('\"' == buf[*pos]) { - *v = &buf[++(*pos)]; + if (MDOC_PHRASELIT & m->flags || '\"' == buf[*pos]) { + if ( ! (MDOC_PHRASELIT & m->flags)) + *v = &buf[++(*pos)]; + + if (MDOC_PPHRASE & m->flags) + m->flags |= MDOC_PHRASELIT; for ( ; buf[*pos]; (*pos)++) { if ('\"' != buf[*pos]) @@ -514,17 +533,18 @@ args(struct mdoc *m, int line, int *pos, (*pos)++; } - if (0 == buf[*pos]) { - if (ARGS_NOWARN & fl) + if ('\0' == buf[*pos]) { + if (ARGS_NOWARN & fl || MDOC_PPHRASE & m->flags) return(ARGS_QWORD); if ( ! mdoc_pwarn(m, line, *pos, EQUOTTERM)) return(ARGS_ERROR); return(ARGS_QWORD); } - buf[(*pos)++] = 0; + m->flags &= ~MDOC_PHRASELIT; + buf[(*pos)++] = '\0'; - if (0 == buf[*pos]) + if ('\0' == buf[*pos]) return(ARGS_QWORD); while (' ' == buf[*pos]) @@ -546,15 +566,15 @@ args(struct mdoc *m, int line, int *pos, if (' ' == buf[*pos] && '\\' != buf[*pos - 1]) break; - if (0 == buf[*pos]) + if ('\0' == buf[*pos]) return(ARGS_WORD); - buf[(*pos)++] = 0; + buf[(*pos)++] = '\0'; while (' ' == buf[*pos]) (*pos)++; - if (0 == buf[*pos] && ! (ARGS_NOWARN & fl)) + if ('\0' == buf[*pos] && ! (ARGS_NOWARN & fl)) if ( ! mdoc_pwarn(m, line, *pos, ETAILWS)) return(ARGS_ERROR); diff --git a/usr.bin/mandoc/mdoc_macro.c b/usr.bin/mandoc/mdoc_macro.c index a87b7827372..4f24b9adb77 100644 --- a/usr.bin/mandoc/mdoc_macro.c +++ b/usr.bin/mandoc/mdoc_macro.c @@ -1,4 +1,4 @@ -/* $Id: mdoc_macro.c,v 1.40 2010/05/15 12:30:59 schwarze Exp $ */ +/* $Id: mdoc_macro.c,v 1.41 2010/05/15 13:12:55 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> * @@ -45,7 +45,7 @@ static int append_delims(struct mdoc *, static enum mdoct lookup(enum mdoct, const char *); static enum mdoct lookup_raw(const char *); static int phrase(struct mdoc *, int, int, - char *, enum margserr, int); + char *, enum margserr); static enum mdoct rew_alt(enum mdoct); static int rew_dobreak(enum mdoct, const struct mdoc_node *); @@ -883,7 +883,7 @@ in_line(MACRO_PROT_ARGS) static int blk_full(MACRO_PROT_ARGS) { - int la, pcnt; + int la; struct mdoc_arg *arg; struct mdoc_node *head; /* save of head macro */ struct mdoc_node *body; /* save of body macro */ @@ -952,7 +952,7 @@ blk_full(MACRO_PROT_ARGS) ac = ARGS_ERROR; - for (pcnt = 0; ; ) { + for ( ; ; ) { la = *pos; lac = ac; ac = mdoc_args(m, line, pos, buf, tok, &p); @@ -962,12 +962,18 @@ blk_full(MACRO_PROT_ARGS) if (ARGS_EOLN == ac) break; + if (ARGS_PEND == ac) { + if (ARGS_PPHRASE == lac) + ac = ARGS_PPHRASE; + else + ac = ARGS_PHRASE; + } + /* Don't emit leading punct. for phrases. */ if (NULL == head && ARGS_PHRASE != ac && ARGS_PPHRASE != ac && - ARGS_PEND != ac && ARGS_QWORD != ac && DELIM_OPEN == mdoc_isdelim(p)) { if ( ! mdoc_word_alloc(m, line, la, p)) @@ -979,29 +985,18 @@ blk_full(MACRO_PROT_ARGS) if (NULL == head || ARGS_PHRASE == ac || - ARGS_PEND == ac || ARGS_PPHRASE == ac) { if ( ! mdoc_head_alloc(m, line, ppos, tok)) return(0); head = m->last; } - if (ARGS_PHRASE == ac || - ARGS_PEND == ac || - ARGS_PPHRASE == ac) { - /* - * Special treatment for the last phrase. A - * prior ARGS_PHRASE gets is handled as a - * regular ARGS_PHRASE, but a prior ARGS_PPHRASE - * has special handling. - */ - if (ARGS_PEND == ac && ARGS_ERROR == lac) - ac = ARGS_PHRASE; - else if (ARGS_PEND == ac && ARGS_PHRASE == lac) - ac = ARGS_PHRASE; - - if ( ! phrase(m, line, la, buf, ac, pcnt++)) + if (ARGS_PHRASE == ac || ARGS_PPHRASE == ac) { + if (ARGS_PPHRASE == ac) + m->flags |= MDOC_PPHRASE; + if ( ! phrase(m, line, la, buf, ac)) return(0); + m->flags &= ~MDOC_PPHRASE; if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos)) return(0); continue; @@ -1543,25 +1538,18 @@ obsolete(MACRO_PROT_ARGS) * macro is encountered. */ static int -phrase(struct mdoc *m, int line, int ppos, char *buf, - enum margserr ac, int count) +phrase(struct mdoc *m, int line, int ppos, char *buf, enum margserr ac) { int la, pos; enum margserr aac; enum mdoct ntok; char *p; - assert(ARGS_PHRASE == ac || - ARGS_PEND == ac || - ARGS_PPHRASE == ac); - - if (count && ARGS_PPHRASE == ac) - return(mdoc_word_alloc(m, line, ppos, &buf[ppos])); + assert(ARGS_PHRASE == ac || ARGS_PPHRASE == ac); for (pos = ppos; ; ) { la = pos; - /* Note: no calling context! */ aac = mdoc_zargs(m, line, &pos, buf, 0, &p); if (ARGS_ERROR == aac) @@ -1569,8 +1557,7 @@ phrase(struct mdoc *m, int line, int ppos, char *buf, if (ARGS_EOLN == aac) break; - ntok = ARGS_QWORD == aac || ARGS_PEND == ac ? - MDOC_MAX : lookup_raw(p); + ntok = ARGS_QWORD == aac ? MDOC_MAX : lookup_raw(p); if (MDOC_MAX == ntok) { if ( ! mdoc_word_alloc(m, line, la, p)) |