=================================================================== RCS file: /cvs/mandoc/mdoc_argv.c,v retrieving revision 1.84 retrieving revision 1.90 diff -u -p -r1.84 -r1.90 --- mandoc/mdoc_argv.c 2012/11/16 18:41:18 1.84 +++ mandoc/mdoc_argv.c 2014/03/23 11:25:26 1.90 @@ -1,4 +1,4 @@ -/* $Id: mdoc_argv.c,v 1.84 2012/11/16 18:41:18 schwarze Exp $ */ +/* $Id: mdoc_argv.c,v 1.90 2014/03/23 11:25:26 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2012 Ingo Schwarze @@ -28,6 +28,7 @@ #include "mdoc.h" #include "mandoc.h" +#include "mandoc_aux.h" #include "libmdoc.h" #include "libmandoc.h" @@ -161,7 +162,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = { { ARGSFL_DELIM, NULL }, /* Ad */ { ARGSFL_DELIM, args_An }, /* An */ { ARGSFL_DELIM, NULL }, /* Ar */ - { ARGSFL_NONE, NULL }, /* Cd */ + { ARGSFL_DELIM, NULL }, /* Cd */ { ARGSFL_DELIM, NULL }, /* Cm */ { ARGSFL_DELIM, NULL }, /* Dv */ { ARGSFL_DELIM, NULL }, /* Er */ @@ -241,7 +242,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = { { ARGSFL_DELIM, NULL }, /* Xc */ { ARGSFL_NONE, NULL }, /* Xo */ { ARGSFL_NONE, NULL }, /* Fo */ - { ARGSFL_NONE, NULL }, /* Fc */ + { ARGSFL_DELIM, NULL }, /* Fc */ { ARGSFL_NONE, NULL }, /* Oo */ { ARGSFL_DELIM, NULL }, /* Oc */ { ARGSFL_NONE, args_Bk }, /* Bk */ @@ -250,7 +251,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = { { ARGSFL_NONE, NULL }, /* Hf */ { ARGSFL_NONE, NULL }, /* Fr */ { ARGSFL_NONE, NULL }, /* Ud */ - { ARGSFL_NONE, NULL }, /* Lb */ + { ARGSFL_DELIM, NULL }, /* Lb */ { ARGSFL_NONE, NULL }, /* Lp */ { ARGSFL_DELIM, NULL }, /* Lk */ { ARGSFL_DELIM, NULL }, /* Mt */ @@ -260,7 +261,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = { { ARGSFL_NONE, NULL }, /* %C */ { ARGSFL_NONE, NULL }, /* Es */ { ARGSFL_NONE, NULL }, /* En */ - { ARGSFL_NONE, NULL }, /* Dx */ + { ARGSFL_DELIM, NULL }, /* Dx */ { ARGSFL_NONE, NULL }, /* %Q */ { ARGSFL_NONE, NULL }, /* br */ { ARGSFL_NONE, NULL }, /* sp */ @@ -275,7 +276,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = { * one mandatory value, an optional single value, or no value. */ enum margverr -mdoc_argv(struct mdoc *m, int line, enum mdoct tok, +mdoc_argv(struct mdoc *mdoc, int line, enum mdoct tok, struct mdoc_arg **v, int *pos, char *buf) { char *p, sv; @@ -342,11 +343,11 @@ mdoc_argv(struct mdoc *m, int line, enum mdoct tok, switch (argvflags[tmp.arg]) { case (ARGV_SINGLE): - if ( ! argv_single(m, line, &tmp, pos, buf)) + if ( ! argv_single(mdoc, line, &tmp, pos, buf)) return(ARGV_ERROR); break; case (ARGV_MULTI): - if ( ! argv_multi(m, line, &tmp, pos, buf)) + if ( ! argv_multi(mdoc, line, &tmp, pos, buf)) return(ARGV_ERROR); break; case (ARGV_NONE): @@ -407,14 +408,14 @@ argn_free(struct mdoc_arg *p, int iarg) } enum margserr -mdoc_zargs(struct mdoc *m, int line, int *pos, char *buf, char **v) +mdoc_zargs(struct mdoc *mdoc, int line, int *pos, char *buf, char **v) { - return(args(m, line, pos, buf, ARGSFL_NONE, v)); + return(args(mdoc, line, pos, buf, ARGSFL_NONE, v)); } enum margserr -mdoc_args(struct mdoc *m, int line, int *pos, +mdoc_args(struct mdoc *mdoc, int line, int *pos, char *buf, enum mdoct tok, char **v) { enum argsflag fl; @@ -423,7 +424,7 @@ mdoc_args(struct mdoc *m, int line, int *pos, fl = mdocargs[tok].flags; if (MDOC_It != tok) - return(args(m, line, pos, buf, fl, v)); + return(args(mdoc, line, pos, buf, fl, v)); /* * We know that we're in an `It', so it's reasonable to expect @@ -432,35 +433,36 @@ mdoc_args(struct mdoc *m, int line, int *pos, * safe fall-back into the default behaviour. */ - for (n = m->last; n; n = n->parent) + for (n = mdoc->last; n; n = n->parent) if (MDOC_Bl == n->tok) if (LIST_column == n->norm->Bl.type) { fl = ARGSFL_TABSEP; break; } - return(args(m, line, pos, buf, fl, v)); + return(args(mdoc, line, pos, buf, fl, v)); } static enum margserr -args(struct mdoc *m, int line, int *pos, +args(struct mdoc *mdoc, int line, int *pos, char *buf, enum argsflag fl, char **v) { char *p, *pp; + int pairs; enum margserr rc; if ('\0' == buf[*pos]) { - if (MDOC_PPHRASE & m->flags) + if (MDOC_PPHRASE & mdoc->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) - mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE); + if (MDOC_PHRASELIT & mdoc->flags) + mdoc_pmsg(mdoc, line, *pos, MANDOCERR_BADQUOTE); - m->flags &= ~MDOC_PHRASELIT; + mdoc->flags &= ~MDOC_PHRASELIT; return(ARGS_EOLN); } @@ -483,7 +485,7 @@ args(struct mdoc *m, int line, int *pos, pp = NULL; /* Scan ahead to unescaped `Ta'. */ - if ( ! (MDOC_PHRASELIT & m->flags)) + if ( ! (MDOC_PHRASELIT & mdoc->flags)) for (pp = *v; ; pp++) { if (NULL == (pp = strstr(pp, "Ta"))) break; @@ -517,7 +519,7 @@ args(struct mdoc *m, int line, int *pos, /* Whitespace check for eoln case... */ if ('\0' == *p && ' ' == *(p - 1)) - mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE); + mdoc_pmsg(mdoc, line, *pos, MANDOCERR_EOLNSPACE); *pos += (int)(p - *v); @@ -535,37 +537,48 @@ args(struct mdoc *m, int line, int *pos, /* Skip ahead. */ ; return(rc); - } + } - /* + /* * Process a quoted literal. A quote begins with a double-quote * and ends with a double-quote NOT preceded by a double-quote. + * NUL-terminate the literal in place. + * Collapse pairs of quotes inside quoted literals. * Whitespace is NOT involved in literal termination. */ - if (MDOC_PHRASELIT & m->flags || '\"' == buf[*pos]) { - if ( ! (MDOC_PHRASELIT & m->flags)) + if (MDOC_PHRASELIT & mdoc->flags || '\"' == buf[*pos]) { + if ( ! (MDOC_PHRASELIT & mdoc->flags)) *v = &buf[++(*pos)]; - if (MDOC_PPHRASE & m->flags) - m->flags |= MDOC_PHRASELIT; + if (MDOC_PPHRASE & mdoc->flags) + mdoc->flags |= MDOC_PHRASELIT; + pairs = 0; for ( ; buf[*pos]; (*pos)++) { + /* Move following text left after quoted quotes. */ + if (pairs) + buf[*pos - pairs] = buf[*pos]; if ('\"' != buf[*pos]) continue; + /* Unquoted quotes end quoted args. */ if ('\"' != buf[*pos + 1]) break; + /* Quoted quotes collapse. */ + pairs++; (*pos)++; } + if (pairs) + buf[*pos - pairs] = '\0'; if ('\0' == buf[*pos]) { - if (MDOC_PPHRASE & m->flags) + if (MDOC_PPHRASE & mdoc->flags) return(ARGS_QWORD); - mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE); + mdoc_pmsg(mdoc, line, *pos, MANDOCERR_BADQUOTE); return(ARGS_QWORD); } - m->flags &= ~MDOC_PHRASELIT; + mdoc->flags &= ~MDOC_PHRASELIT; buf[(*pos)++] = '\0'; if ('\0' == buf[*pos]) @@ -575,13 +588,13 @@ args(struct mdoc *m, int line, int *pos, (*pos)++; if ('\0' == buf[*pos]) - mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE); + mdoc_pmsg(mdoc, line, *pos, MANDOCERR_EOLNSPACE); return(ARGS_QWORD); } p = &buf[*pos]; - *v = mandoc_getarg(m->parse, &p, line, pos); + *v = mandoc_getarg(mdoc->parse, &p, line, pos); return(ARGS_WORD); } @@ -637,7 +650,7 @@ args_checkpunct(const char *buf, int i) } static int -argv_multi(struct mdoc *m, int line, +argv_multi(struct mdoc *mdoc, int line, struct mdoc_argv *v, int *pos, char *buf) { enum margserr ac; @@ -646,7 +659,7 @@ argv_multi(struct mdoc *m, int line, for (v->sz = 0; ; v->sz++) { if ('-' == buf[*pos]) break; - ac = args(m, line, pos, buf, ARGSFL_NONE, &p); + ac = args(mdoc, line, pos, buf, ARGSFL_NONE, &p); if (ARGS_ERROR == ac) return(0); else if (ARGS_EOLN == ac) @@ -663,13 +676,13 @@ argv_multi(struct mdoc *m, int line, } static int -argv_single(struct mdoc *m, int line, +argv_single(struct mdoc *mdoc, int line, struct mdoc_argv *v, int *pos, char *buf) { enum margserr ac; char *p; - ac = args(m, line, pos, buf, ARGSFL_NONE, &p); + ac = args(mdoc, line, pos, buf, ARGSFL_NONE, &p); if (ARGS_ERROR == ac) return(0); if (ARGS_EOLN == ac)