summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2010-05-15 13:12:56 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2010-05-15 13:12:56 +0000
commit1943a41de13092e8e3da688f4172b121a46bd157 (patch)
tree2ea9e8ce296dd662fd8c886cfedde9ec2f902845
parenta355e7868a2177fe355b4911c68ec4103093780b (diff)
proper handling of quoted tab-separated column lists
by kristaps@
-rw-r--r--usr.bin/mandoc/libmdoc.h10
-rw-r--r--usr.bin/mandoc/mdoc_argv.c58
-rw-r--r--usr.bin/mandoc/mdoc_macro.c51
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))