Print this page
Update to 1.12.3.

*** 1,8 **** ! /* $Id: mdoc_argv.c,v 1.82 2012/03/23 05:50:24 kristaps Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * --- 1,9 ---- ! /* $Id: mdoc_argv.c,v 1.89 2013/12/25 00:50:05 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2012 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. *
*** 40,51 **** }; enum argvflag { ARGV_NONE, /* no args to flag (e.g., -split) */ ARGV_SINGLE, /* one arg to flag (e.g., -file xxx) */ ! ARGV_MULTI, /* multiple args (e.g., -column xxx yyy) */ ! ARGV_OPT_SINGLE /* optional arg (e.g., -offset [xxx]) */ }; struct mdocarg { enum argsflag flags; const enum mdocargt *argvs; --- 41,51 ---- }; enum argvflag { ARGV_NONE, /* no args to flag (e.g., -split) */ ARGV_SINGLE, /* one arg to flag (e.g., -file xxx) */ ! ARGV_MULTI /* multiple args (e.g., -column xxx yyy) */ }; struct mdocarg { enum argsflag flags; const enum mdocargt *argvs;
*** 55,66 **** static enum margserr args(struct mdoc *, int, int *, char *, enum argsflag, char **); static int args_checkpunct(const char *, int); static int argv_multi(struct mdoc *, int, struct mdoc_argv *, int *, char *); - static int argv_opt_single(struct mdoc *, int, - struct mdoc_argv *, int *, char *); static int argv_single(struct mdoc *, int, struct mdoc_argv *, int *, char *); static const enum argvflag argvflags[MDOC_ARG_MAX] = { ARGV_NONE, /* MDOC_Split */ --- 55,64 ----
*** 67,77 **** ARGV_NONE, /* MDOC_Nosplit */ ARGV_NONE, /* MDOC_Ragged */ ARGV_NONE, /* MDOC_Unfilled */ ARGV_NONE, /* MDOC_Literal */ ARGV_SINGLE, /* MDOC_File */ ! ARGV_OPT_SINGLE, /* MDOC_Offset */ ARGV_NONE, /* MDOC_Bullet */ ARGV_NONE, /* MDOC_Dash */ ARGV_NONE, /* MDOC_Hyphen */ ARGV_NONE, /* MDOC_Item */ ARGV_NONE, /* MDOC_Enum */ --- 65,75 ---- ARGV_NONE, /* MDOC_Nosplit */ ARGV_NONE, /* MDOC_Ragged */ ARGV_NONE, /* MDOC_Unfilled */ ARGV_NONE, /* MDOC_Literal */ ARGV_SINGLE, /* MDOC_File */ ! ARGV_SINGLE, /* MDOC_Offset */ ARGV_NONE, /* MDOC_Bullet */ ARGV_NONE, /* MDOC_Dash */ ARGV_NONE, /* MDOC_Hyphen */ ARGV_NONE, /* MDOC_Item */ ARGV_NONE, /* MDOC_Enum */
*** 79,89 **** ARGV_NONE, /* MDOC_Diag */ ARGV_NONE, /* MDOC_Hang */ ARGV_NONE, /* MDOC_Ohang */ ARGV_NONE, /* MDOC_Inset */ ARGV_MULTI, /* MDOC_Column */ ! ARGV_OPT_SINGLE, /* MDOC_Width */ ARGV_NONE, /* MDOC_Compact */ ARGV_NONE, /* MDOC_Std */ ARGV_NONE, /* MDOC_Filled */ ARGV_NONE, /* MDOC_Words */ ARGV_NONE, /* MDOC_Emphasis */ --- 77,87 ---- ARGV_NONE, /* MDOC_Diag */ ARGV_NONE, /* MDOC_Hang */ ARGV_NONE, /* MDOC_Ohang */ ARGV_NONE, /* MDOC_Inset */ ARGV_MULTI, /* MDOC_Column */ ! ARGV_SINGLE, /* MDOC_Width */ ARGV_NONE, /* MDOC_Compact */ ARGV_NONE, /* MDOC_Std */ ARGV_NONE, /* MDOC_Filled */ ARGV_NONE, /* MDOC_Words */ ARGV_NONE, /* MDOC_Emphasis */
*** 144,154 **** MDOC_Nested, MDOC_ARG_MAX }; static const struct mdocarg mdocargs[MDOC_MAX] = { ! { ARGSFL_NONE, NULL }, /* Ap */ { ARGSFL_NONE, NULL }, /* Dd */ { ARGSFL_NONE, NULL }, /* Dt */ { ARGSFL_NONE, NULL }, /* Os */ { ARGSFL_NONE, NULL }, /* Sh */ { ARGSFL_NONE, NULL }, /* Ss */ --- 142,152 ---- MDOC_Nested, MDOC_ARG_MAX }; static const struct mdocarg mdocargs[MDOC_MAX] = { ! { ARGSFL_DELIM, NULL }, /* Ap */ { ARGSFL_NONE, NULL }, /* Dd */ { ARGSFL_NONE, NULL }, /* Dt */ { ARGSFL_NONE, NULL }, /* Os */ { ARGSFL_NONE, NULL }, /* Sh */ { ARGSFL_NONE, NULL }, /* Ss */
*** 161,171 **** { ARGSFL_NONE, NULL }, /* El */ { ARGSFL_NONE, NULL }, /* It */ { ARGSFL_DELIM, NULL }, /* Ad */ { ARGSFL_DELIM, args_An }, /* An */ { ARGSFL_DELIM, NULL }, /* Ar */ ! { ARGSFL_NONE, NULL }, /* Cd */ { ARGSFL_DELIM, NULL }, /* Cm */ { ARGSFL_DELIM, NULL }, /* Dv */ { ARGSFL_DELIM, NULL }, /* Er */ { ARGSFL_DELIM, NULL }, /* Ev */ { ARGSFL_NONE, args_Ex }, /* Ex */ --- 159,169 ---- { ARGSFL_NONE, NULL }, /* El */ { ARGSFL_NONE, NULL }, /* It */ { ARGSFL_DELIM, NULL }, /* Ad */ { ARGSFL_DELIM, args_An }, /* An */ { ARGSFL_DELIM, NULL }, /* Ar */ ! { ARGSFL_DELIM, NULL }, /* Cd */ { ARGSFL_DELIM, NULL }, /* Cm */ { ARGSFL_DELIM, NULL }, /* Dv */ { ARGSFL_DELIM, NULL }, /* Er */ { ARGSFL_DELIM, NULL }, /* Ev */ { ARGSFL_NONE, args_Ex }, /* Ex */
*** 173,183 **** { ARGSFL_NONE, NULL }, /* Fd */ { ARGSFL_DELIM, NULL }, /* Fl */ { ARGSFL_DELIM, NULL }, /* Fn */ { ARGSFL_DELIM, NULL }, /* Ft */ { ARGSFL_DELIM, NULL }, /* Ic */ ! { ARGSFL_NONE, NULL }, /* In */ { ARGSFL_DELIM, NULL }, /* Li */ { ARGSFL_NONE, NULL }, /* Nd */ { ARGSFL_DELIM, NULL }, /* Nm */ { ARGSFL_DELIM, NULL }, /* Op */ { ARGSFL_NONE, NULL }, /* Ot */ --- 171,181 ---- { ARGSFL_NONE, NULL }, /* Fd */ { ARGSFL_DELIM, NULL }, /* Fl */ { ARGSFL_DELIM, NULL }, /* Fn */ { ARGSFL_DELIM, NULL }, /* Ft */ { ARGSFL_DELIM, NULL }, /* Ic */ ! { ARGSFL_DELIM, NULL }, /* In */ { ARGSFL_DELIM, NULL }, /* Li */ { ARGSFL_NONE, NULL }, /* Nd */ { ARGSFL_DELIM, NULL }, /* Nm */ { ARGSFL_DELIM, NULL }, /* Op */ { ARGSFL_NONE, NULL }, /* Ot */
*** 241,270 **** { ARGSFL_DELIM, NULL }, /* Tn */ { ARGSFL_DELIM, NULL }, /* Ux */ { ARGSFL_DELIM, NULL }, /* Xc */ { ARGSFL_NONE, NULL }, /* Xo */ { ARGSFL_NONE, NULL }, /* Fo */ ! { ARGSFL_NONE, NULL }, /* Fc */ { ARGSFL_NONE, NULL }, /* Oo */ { ARGSFL_DELIM, NULL }, /* Oc */ { ARGSFL_NONE, args_Bk }, /* Bk */ { ARGSFL_NONE, NULL }, /* Ek */ { ARGSFL_NONE, NULL }, /* Bt */ { ARGSFL_NONE, NULL }, /* Hf */ { ARGSFL_NONE, NULL }, /* Fr */ { ARGSFL_NONE, NULL }, /* Ud */ ! { ARGSFL_NONE, NULL }, /* Lb */ { ARGSFL_NONE, NULL }, /* Lp */ { ARGSFL_DELIM, NULL }, /* Lk */ { ARGSFL_DELIM, NULL }, /* Mt */ { ARGSFL_DELIM, NULL }, /* Brq */ { ARGSFL_NONE, NULL }, /* Bro */ { ARGSFL_DELIM, NULL }, /* Brc */ { ARGSFL_NONE, NULL }, /* %C */ { ARGSFL_NONE, NULL }, /* Es */ { ARGSFL_NONE, NULL }, /* En */ ! { ARGSFL_NONE, NULL }, /* Dx */ { ARGSFL_NONE, NULL }, /* %Q */ { ARGSFL_NONE, NULL }, /* br */ { ARGSFL_NONE, NULL }, /* sp */ { ARGSFL_NONE, NULL }, /* %U */ { ARGSFL_NONE, NULL }, /* Ta */ --- 239,268 ---- { ARGSFL_DELIM, NULL }, /* Tn */ { ARGSFL_DELIM, NULL }, /* Ux */ { ARGSFL_DELIM, NULL }, /* Xc */ { ARGSFL_NONE, NULL }, /* Xo */ { ARGSFL_NONE, NULL }, /* Fo */ ! { ARGSFL_DELIM, NULL }, /* Fc */ { ARGSFL_NONE, NULL }, /* Oo */ { ARGSFL_DELIM, NULL }, /* Oc */ { ARGSFL_NONE, args_Bk }, /* Bk */ { ARGSFL_NONE, NULL }, /* Ek */ { ARGSFL_NONE, NULL }, /* Bt */ { ARGSFL_NONE, NULL }, /* Hf */ { ARGSFL_NONE, NULL }, /* Fr */ { ARGSFL_NONE, NULL }, /* Ud */ ! { ARGSFL_DELIM, NULL }, /* Lb */ { ARGSFL_NONE, NULL }, /* Lp */ { ARGSFL_DELIM, NULL }, /* Lk */ { ARGSFL_DELIM, NULL }, /* Mt */ { ARGSFL_DELIM, NULL }, /* Brq */ { ARGSFL_NONE, NULL }, /* Bro */ { ARGSFL_DELIM, NULL }, /* Brc */ { ARGSFL_NONE, NULL }, /* %C */ { ARGSFL_NONE, NULL }, /* Es */ { ARGSFL_NONE, NULL }, /* En */ ! { ARGSFL_DELIM, NULL }, /* Dx */ { ARGSFL_NONE, NULL }, /* %Q */ { ARGSFL_NONE, NULL }, /* br */ { ARGSFL_NONE, NULL }, /* sp */ { ARGSFL_NONE, NULL }, /* %U */ { ARGSFL_NONE, NULL }, /* Ta */
*** 275,285 **** * Parse an argument from line text. This comes in the form of -key * [value0...], which may either have a single mandatory value, at least * one mandatory value, an optional single value, or no value. */ enum margverr ! mdoc_argv(struct mdoc *m, int line, enum mdoct tok, struct mdoc_arg **v, int *pos, char *buf) { char *p, sv; struct mdoc_argv tmp; struct mdoc_arg *arg; --- 273,283 ---- * Parse an argument from line text. This comes in the form of -key * [value0...], which may either have a single mandatory value, at least * one mandatory value, an optional single value, or no value. */ enum margverr ! mdoc_argv(struct mdoc *mdoc, int line, enum mdoct tok, struct mdoc_arg **v, int *pos, char *buf) { char *p, sv; struct mdoc_argv tmp; struct mdoc_arg *arg;
*** 342,362 **** while (buf[*pos] && ' ' == buf[*pos]) (*pos)++; switch (argvflags[tmp.arg]) { case (ARGV_SINGLE): ! if ( ! argv_single(m, line, &tmp, pos, buf)) return(ARGV_ERROR); break; case (ARGV_MULTI): ! if ( ! argv_multi(m, line, &tmp, pos, buf)) return(ARGV_ERROR); break; - case (ARGV_OPT_SINGLE): - if ( ! argv_opt_single(m, line, &tmp, pos, buf)) - return(ARGV_ERROR); - break; case (ARGV_NONE): break; } if (NULL == (arg = *v)) --- 340,356 ---- while (buf[*pos] && ' ' == buf[*pos]) (*pos)++; switch (argvflags[tmp.arg]) { case (ARGV_SINGLE): ! if ( ! argv_single(mdoc, line, &tmp, pos, buf)) return(ARGV_ERROR); break; case (ARGV_MULTI): ! if ( ! argv_multi(mdoc, line, &tmp, pos, buf)) return(ARGV_ERROR); break; case (ARGV_NONE): break; } if (NULL == (arg = *v))
*** 411,474 **** for (--p->argc; iarg < (int)p->argc; iarg++) p->argv[iarg] = p->argv[iarg+1]; } enum margserr ! mdoc_zargs(struct mdoc *m, int line, int *pos, char *buf, char **v) { ! return(args(m, line, pos, buf, ARGSFL_NONE, v)); } enum margserr ! mdoc_args(struct mdoc *m, int line, int *pos, char *buf, enum mdoct tok, char **v) { enum argsflag fl; struct mdoc_node *n; fl = mdocargs[tok].flags; if (MDOC_It != tok) ! return(args(m, line, pos, buf, fl, v)); /* * We know that we're in an `It', so it's reasonable to expect * us to be sitting in a `Bl'. Someday this may not be the case * (if we allow random `It's sitting out there), so provide a * safe fall-back into the default behaviour. */ ! for (n = m->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)); } static enum margserr ! args(struct mdoc *m, int line, int *pos, char *buf, enum argsflag fl, char **v) { char *p, *pp; enum margserr rc; 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) ! mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE); ! m->flags &= ~MDOC_PHRASELIT; return(ARGS_EOLN); } *v = &buf[*pos]; --- 405,469 ---- for (--p->argc; iarg < (int)p->argc; iarg++) p->argv[iarg] = p->argv[iarg+1]; } enum margserr ! mdoc_zargs(struct mdoc *mdoc, int line, int *pos, char *buf, char **v) { ! return(args(mdoc, line, pos, buf, ARGSFL_NONE, v)); } enum margserr ! mdoc_args(struct mdoc *mdoc, int line, int *pos, char *buf, enum mdoct tok, char **v) { enum argsflag fl; struct mdoc_node *n; fl = mdocargs[tok].flags; if (MDOC_It != tok) ! return(args(mdoc, line, pos, buf, fl, v)); /* * We know that we're in an `It', so it's reasonable to expect * us to be sitting in a `Bl'. Someday this may not be the case * (if we allow random `It's sitting out there), so provide a * safe fall-back into the default behaviour. */ ! 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(mdoc, line, pos, buf, fl, v)); } static enum margserr ! 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 & 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 & mdoc->flags) ! mdoc_pmsg(mdoc, line, *pos, MANDOCERR_BADQUOTE); ! mdoc->flags &= ~MDOC_PHRASELIT; return(ARGS_EOLN); } *v = &buf[*pos];
*** 487,497 **** /* Scan ahead to tab (can't be escaped). */ p = strchr(*v, '\t'); pp = NULL; /* Scan ahead to unescaped `Ta'. */ ! if ( ! (MDOC_PHRASELIT & m->flags)) for (pp = *v; ; pp++) { if (NULL == (pp = strstr(pp, "Ta"))) break; if (pp > *v && ' ' != *(pp - 1)) continue; --- 482,492 ---- /* Scan ahead to tab (can't be escaped). */ p = strchr(*v, '\t'); pp = NULL; /* Scan ahead to unescaped `Ta'. */ ! if ( ! (MDOC_PHRASELIT & mdoc->flags)) for (pp = *v; ; pp++) { if (NULL == (pp = strstr(pp, "Ta"))) break; if (pp > *v && ' ' != *(pp - 1)) continue;
*** 521,531 **** p = strchr(*v, 0); } /* Whitespace check for eoln case... */ if ('\0' == *p && ' ' == *(p - 1)) ! mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE); *pos += (int)(p - *v); /* Strip delimiter's preceding whitespace. */ pp = p - 1; --- 516,526 ---- p = strchr(*v, 0); } /* Whitespace check for eoln case... */ if ('\0' == *p && ' ' == *(p - 1)) ! mdoc_pmsg(mdoc, line, *pos, MANDOCERR_EOLNSPACE); *pos += (int)(p - *v); /* Strip delimiter's preceding whitespace. */ pp = p - 1;
*** 544,595 **** } /* * Process a quoted literal. A quote begins with a double-quote * and ends with a double-quote NOT preceded by a double-quote. * Whitespace is NOT involved in literal termination. */ ! 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]) continue; if ('\"' != buf[*pos + 1]) break; (*pos)++; } if ('\0' == buf[*pos]) { ! if (MDOC_PPHRASE & m->flags) return(ARGS_QWORD); ! mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE); return(ARGS_QWORD); } ! m->flags &= ~MDOC_PHRASELIT; buf[(*pos)++] = '\0'; if ('\0' == buf[*pos]) return(ARGS_QWORD); while (' ' == buf[*pos]) (*pos)++; if ('\0' == buf[*pos]) ! mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE); return(ARGS_QWORD); } p = &buf[*pos]; ! *v = mandoc_getarg(m->parse, &p, line, pos); return(ARGS_WORD); } /* --- 539,601 ---- } /* * 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 & mdoc->flags || '\"' == buf[*pos]) { ! if ( ! (MDOC_PHRASELIT & mdoc->flags)) *v = &buf[++(*pos)]; ! 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 & mdoc->flags) return(ARGS_QWORD); ! mdoc_pmsg(mdoc, line, *pos, MANDOCERR_BADQUOTE); return(ARGS_QWORD); } ! mdoc->flags &= ~MDOC_PHRASELIT; buf[(*pos)++] = '\0'; if ('\0' == buf[*pos]) return(ARGS_QWORD); while (' ' == buf[*pos]) (*pos)++; if ('\0' == buf[*pos]) ! mdoc_pmsg(mdoc, line, *pos, MANDOCERR_EOLNSPACE); return(ARGS_QWORD); } p = &buf[*pos]; ! *v = mandoc_getarg(mdoc->parse, &p, line, pos); return(ARGS_WORD); } /*
*** 641,660 **** return('\0' == buf[i]); } static int ! argv_multi(struct mdoc *m, int line, struct mdoc_argv *v, int *pos, char *buf) { enum margserr ac; char *p; for (v->sz = 0; ; v->sz++) { if ('-' == buf[*pos]) break; ! ac = args(m, line, pos, buf, ARGSFL_NONE, &p); if (ARGS_ERROR == ac) return(0); else if (ARGS_EOLN == ac) break; --- 647,666 ---- return('\0' == buf[i]); } static int ! argv_multi(struct mdoc *mdoc, int line, struct mdoc_argv *v, int *pos, char *buf) { enum margserr ac; char *p; for (v->sz = 0; ; v->sz++) { if ('-' == buf[*pos]) break; ! ac = args(mdoc, line, pos, buf, ARGSFL_NONE, &p); if (ARGS_ERROR == ac) return(0); else if (ARGS_EOLN == ac) break;
*** 667,716 **** return(1); } static int ! argv_opt_single(struct mdoc *m, int line, struct mdoc_argv *v, int *pos, char *buf) { enum margserr ac; char *p; ! if ('-' == buf[*pos]) ! return(1); ! ! ac = args(m, line, pos, buf, ARGSFL_NONE, &p); if (ARGS_ERROR == ac) return(0); if (ARGS_EOLN == ac) return(1); v->sz = 1; - v->value = mandoc_malloc(sizeof(char *)); - v->value[0] = mandoc_strdup(p); - - return(1); - } - - static int - argv_single(struct mdoc *m, int line, - struct mdoc_argv *v, int *pos, char *buf) - { - int ppos; - enum margserr ac; - char *p; - - ppos = *pos; - - ac = args(m, line, pos, buf, ARGSFL_NONE, &p); - if (ARGS_EOLN == ac) { - mdoc_pmsg(m, line, ppos, MANDOCERR_SYNTARGVCOUNT); - return(0); - } else if (ARGS_ERROR == ac) - return(0); - - v->sz = 1; v->value = mandoc_malloc(sizeof(char *)); v->value[0] = mandoc_strdup(p); return(1); } --- 673,695 ---- return(1); } static int ! argv_single(struct mdoc *mdoc, int line, struct mdoc_argv *v, int *pos, char *buf) { enum margserr ac; char *p; ! ac = args(mdoc, line, pos, buf, ARGSFL_NONE, &p); if (ARGS_ERROR == ac) return(0); if (ARGS_EOLN == ac) return(1); v->sz = 1; v->value = mandoc_malloc(sizeof(char *)); v->value[0] = mandoc_strdup(p); return(1); }