=================================================================== RCS file: /cvs/mandoc/mdoc_argv.c,v retrieving revision 1.106 retrieving revision 1.111 diff -u -p -r1.106 -r1.111 --- mandoc/mdoc_argv.c 2015/10/15 22:45:43 1.106 +++ mandoc/mdoc_argv.c 2017/04/24 23:06:18 1.111 @@ -1,7 +1,7 @@ -/* $Id: mdoc_argv.c,v 1.106 2015/10/15 22:45:43 schwarze Exp $ */ +/* $Id: mdoc_argv.c,v 1.111 2017/04/24 23:06:18 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons - * Copyright (c) 2012, 2014, 2015 Ingo Schwarze + * Copyright (c) 2012, 2014-2017 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -29,6 +29,7 @@ #include "roff.h" #include "mdoc.h" #include "libmandoc.h" +#include "roff_int.h" #include "libmdoc.h" #define MULTI_STEP 5 /* pre-allocate argument values */ @@ -143,8 +144,7 @@ static const enum mdocargt args_Bl[] = { MDOC_ARG_MAX }; -static const struct mdocarg mdocargs[MDOC_MAX] = { - { ARGSFL_DELIM, NULL }, /* Ap */ +static const struct mdocarg __mdocargs[MDOC_MAX - MDOC_Dd] = { { ARGSFL_NONE, NULL }, /* Dd */ { ARGSFL_NONE, NULL }, /* Dt */ { ARGSFL_NONE, NULL }, /* Os */ @@ -160,6 +160,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = { { ARGSFL_NONE, NULL }, /* It */ { ARGSFL_DELIM, NULL }, /* Ad */ { ARGSFL_DELIM, args_An }, /* An */ + { ARGSFL_DELIM, NULL }, /* Ap */ { ARGSFL_DELIM, NULL }, /* Ar */ { ARGSFL_DELIM, NULL }, /* Cd */ { ARGSFL_DELIM, NULL }, /* Cm */ @@ -268,6 +269,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = { { ARGSFL_NONE, NULL }, /* Ta */ { ARGSFL_NONE, NULL }, /* ll */ }; +static const struct mdocarg *const mdocargs = __mdocargs - MDOC_Dd; /* @@ -276,7 +278,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = { * Some flags take no argument, some one, some multiple. */ void -mdoc_argv(struct roff_man *mdoc, int line, int tok, +mdoc_argv(struct roff_man *mdoc, int line, enum roff_tok tok, struct mdoc_arg **reta, int *pos, char *buf) { struct mdoc_argv tmpv; @@ -290,6 +292,7 @@ mdoc_argv(struct roff_man *mdoc, int line, int tok, /* Which flags does this macro support? */ + assert(tok >= MDOC_Dd && tok < MDOC_MAX); argtable = mdocargs[tok].argvs; if (argtable == NULL) return; @@ -414,7 +417,7 @@ argn_free(struct mdoc_arg *p, int iarg) enum margserr mdoc_args(struct roff_man *mdoc, int line, int *pos, - char *buf, int tok, char **v) + char *buf, enum roff_tok tok, char **v) { struct roff_node *n; char *v_local; @@ -423,8 +426,6 @@ mdoc_args(struct roff_man *mdoc, int line, int *pos, if (v == NULL) v = &v_local; fl = tok == TOKEN_NONE ? ARGSFL_NONE : mdocargs[tok].flags; - if (tok != MDOC_It) - return args(mdoc, line, pos, buf, fl, v); /* * We know that we're in an `It', so it's reasonable to expect @@ -433,12 +434,15 @@ mdoc_args(struct roff_man *mdoc, int line, int *pos, * 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) { + if (tok == MDOC_It) { + for (n = mdoc->last; n != NULL; n = n->parent) { + if (n->tok != MDOC_Bl) + continue; + if (n->norm->Bl.type == LIST_column) fl = ARGSFL_TABSEP; - break; - } + break; + } + } return args(mdoc, line, pos, buf, fl, v); } @@ -449,11 +453,10 @@ args(struct roff_man *mdoc, int line, int *pos, { char *p; int pairs; - enum margserr rc; if (buf[*pos] == '\0') { if (mdoc->flags & MDOC_PHRASELIT && - ! (mdoc->flags & MDOC_PPHRASE)) { + ! (mdoc->flags & MDOC_PHRASE)) { mandoc_msg(MANDOCERR_ARG_QUOTE, mdoc->parse, line, *pos, NULL); mdoc->flags &= ~MDOC_PHRASELIT; @@ -473,18 +476,41 @@ args(struct roff_man *mdoc, int line, int *pos, if (fl == ARGSFL_TABSEP) { if ((p = strchr(*v, '\t')) != NULL) { - /* Skip any blank characters after the tab. */ + + /* + * Words right before and right after + * tab characters are not parsed, + * unless there is a blank in between. + */ + + if (p > buf && p[-1] != ' ') + mdoc->flags |= MDOC_PHRASEQL; + if (p[1] != ' ') + mdoc->flags |= MDOC_PHRASEQN; + + /* + * One or more blanks after a tab cause + * one leading blank in the next column. + * So skip all but one of them. + */ + *pos += (int)(p - *v) + 1; - while (buf[*pos] == ' ') + while (buf[*pos] == ' ' && buf[*pos + 1] == ' ') (*pos)++; - rc = ARGS_PPHRASE; + + /* + * A tab at the end of an input line + * switches to the next column. + */ + + if (buf[*pos] == '\0' || buf[*pos + 1] == '\0') + mdoc->flags |= MDOC_PHRASEQN; } else { p = strchr(*v, '\0'); if (p[-1] == ' ') mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse, line, *pos, NULL); *pos += (int)(p - *v); - rc = ARGS_PEND; } /* Skip any trailing blank characters. */ @@ -493,7 +519,7 @@ args(struct roff_man *mdoc, int line, int *pos, p--; *p = '\0'; - return rc; + return ARGS_PHRASE; } /* @@ -504,11 +530,11 @@ args(struct roff_man *mdoc, int line, int *pos, * Whitespace is NOT involved in literal termination. */ - if (MDOC_PHRASELIT & mdoc->flags || '\"' == buf[*pos]) { - if ( ! (MDOC_PHRASELIT & mdoc->flags)) + if (mdoc->flags & MDOC_PHRASELIT || buf[*pos] == '\"') { + if ( ! (mdoc->flags & MDOC_PHRASELIT)) *v = &buf[++(*pos)]; - if (MDOC_PPHRASE & mdoc->flags) + if (mdoc->flags & MDOC_PHRASE) mdoc->flags |= MDOC_PHRASELIT; pairs = 0; @@ -528,11 +554,10 @@ args(struct roff_man *mdoc, int line, int *pos, if (pairs) buf[*pos - pairs] = '\0'; - if ('\0' == buf[*pos]) { - if (MDOC_PPHRASE & mdoc->flags) - return ARGS_QWORD; - mandoc_msg(MANDOCERR_ARG_QUOTE, - mdoc->parse, line, *pos, NULL); + if (buf[*pos] == '\0') { + if ( ! (mdoc->flags & MDOC_PHRASE)) + mandoc_msg(MANDOCERR_ARG_QUOTE, + mdoc->parse, line, *pos, NULL); return ARGS_QWORD; } @@ -555,6 +580,15 @@ args(struct roff_man *mdoc, int line, int *pos, p = &buf[*pos]; *v = mandoc_getarg(mdoc->parse, &p, line, pos); + /* + * After parsing the last word in this phrase, + * tell lookup() whether or not to interpret it. + */ + + if (*p == '\0' && mdoc->flags & MDOC_PHRASEQL) { + mdoc->flags &= ~MDOC_PHRASEQL; + mdoc->flags |= MDOC_PHRASEQF; + } return ARGS_WORD; }