/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
/*
* 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.
*
*
* 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.
*
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-static enum margserr args(struct mdoc *, int, int *,
+static enum margserr args(struct roff_man *, int, int *,
char *, enum argsflag, char **);
static int args_checkpunct(const char *, int);
char *, enum argsflag, char **);
static int args_checkpunct(const char *, int);
struct mdoc_argv *, int *, char *);
static const enum argvflag argvflags[MDOC_ARG_MAX] = {
struct mdoc_argv *, int *, char *);
static const enum argvflag argvflags[MDOC_ARG_MAX] = {
{ ARGSFL_NONE, NULL }, /* Dd */
{ ARGSFL_NONE, NULL }, /* Dt */
{ ARGSFL_NONE, NULL }, /* Os */
{ ARGSFL_NONE, NULL }, /* Sh */
{ ARGSFL_NONE, NULL }, /* Dd */
{ ARGSFL_NONE, NULL }, /* Dt */
{ ARGSFL_NONE, NULL }, /* Os */
{ ARGSFL_NONE, NULL }, /* Sh */
- { ARGSFL_NONE, NULL }, /* Ss */
- { ARGSFL_NONE, NULL }, /* Pp */
+ { ARGSFL_NONE, NULL }, /* Ss */
+ { ARGSFL_NONE, NULL }, /* Pp */
{ ARGSFL_DELIM, NULL }, /* D1 */
{ ARGSFL_DELIM, NULL }, /* Dl */
{ ARGSFL_NONE, args_Bd }, /* Bd */
{ ARGSFL_DELIM, NULL }, /* D1 */
{ ARGSFL_DELIM, NULL }, /* Dl */
{ ARGSFL_NONE, args_Bd }, /* Bd */
{ ARGSFL_NONE, args_Bl }, /* Bl */
{ ARGSFL_NONE, NULL }, /* El */
{ ARGSFL_NONE, NULL }, /* It */
{ ARGSFL_NONE, args_Bl }, /* Bl */
{ ARGSFL_NONE, NULL }, /* El */
{ ARGSFL_NONE, NULL }, /* It */
{ ARGSFL_DELIM, args_An }, /* An */
{ ARGSFL_DELIM, NULL }, /* Ar */
{ ARGSFL_DELIM, args_An }, /* An */
{ ARGSFL_DELIM, NULL }, /* Ar */
- { ARGSFL_DELIM, NULL }, /* Dv */
- { ARGSFL_DELIM, NULL }, /* Er */
- { ARGSFL_DELIM, NULL }, /* Ev */
+ { ARGSFL_DELIM, NULL }, /* Dv */
+ { ARGSFL_DELIM, NULL }, /* Er */
+ { ARGSFL_DELIM, NULL }, /* Ev */
- { ARGSFL_DELIM, NULL }, /* Fa */
- { ARGSFL_NONE, NULL }, /* Fd */
+ { ARGSFL_DELIM, NULL }, /* Fa */
+ { ARGSFL_NONE, NULL }, /* Fd */
- { ARGSFL_DELIM, NULL }, /* Fn */
- { ARGSFL_DELIM, NULL }, /* Ft */
- { ARGSFL_DELIM, NULL }, /* Ic */
- { ARGSFL_NONE, NULL }, /* In */
+ { ARGSFL_DELIM, NULL }, /* Fn */
+ { ARGSFL_DELIM, NULL }, /* Ft */
+ { ARGSFL_DELIM, NULL }, /* Ic */
+ { ARGSFL_DELIM, NULL }, /* In */
- { ARGSFL_NONE, NULL }, /* Nd */
- { ARGSFL_DELIM, NULL }, /* Nm */
+ { ARGSFL_NONE, NULL }, /* Nd */
+ { ARGSFL_DELIM, NULL }, /* Nm */
{ ARGSFL_DELIM, NULL }, /* Pa */
{ ARGSFL_NONE, args_Ex }, /* Rv */
{ ARGSFL_DELIM, NULL }, /* Pa */
{ ARGSFL_NONE, args_Ex }, /* Rv */
{ ARGSFL_DELIM, NULL }, /* Xr */
{ ARGSFL_NONE, NULL }, /* %A */
{ ARGSFL_NONE, NULL }, /* %B */
{ ARGSFL_DELIM, NULL }, /* Xr */
{ ARGSFL_NONE, NULL }, /* %A */
{ ARGSFL_NONE, NULL }, /* %B */
{ ARGSFL_DELIM, NULL }, /* Aq */
{ ARGSFL_DELIM, NULL }, /* At */
{ ARGSFL_DELIM, NULL }, /* Bc */
{ ARGSFL_DELIM, NULL }, /* Aq */
{ ARGSFL_DELIM, NULL }, /* At */
{ ARGSFL_DELIM, NULL }, /* Bc */
{ ARGSFL_NONE, NULL }, /* Bo */
{ ARGSFL_DELIM, NULL }, /* Bq */
{ ARGSFL_DELIM, NULL }, /* Bsx */
{ ARGSFL_NONE, NULL }, /* Bo */
{ ARGSFL_DELIM, NULL }, /* Bq */
{ ARGSFL_DELIM, NULL }, /* Bsx */
{ ARGSFL_DELIM, NULL }, /* Dq */
{ ARGSFL_DELIM, NULL }, /* Ec */
{ ARGSFL_NONE, NULL }, /* Ef */
{ ARGSFL_DELIM, NULL }, /* Dq */
{ ARGSFL_DELIM, NULL }, /* Ec */
{ ARGSFL_NONE, NULL }, /* Ef */
{ ARGSFL_NONE, NULL }, /* Eo */
{ ARGSFL_DELIM, NULL }, /* Fx */
{ ARGSFL_DELIM, NULL }, /* Ms */
{ ARGSFL_NONE, NULL }, /* Eo */
{ ARGSFL_DELIM, NULL }, /* Fx */
{ ARGSFL_DELIM, NULL }, /* Ms */
{ ARGSFL_DELIM, NULL }, /* Ux */
{ ARGSFL_DELIM, NULL }, /* Xc */
{ ARGSFL_NONE, NULL }, /* Xo */
{ ARGSFL_DELIM, NULL }, /* Ux */
{ ARGSFL_DELIM, NULL }, /* Xc */
{ ARGSFL_NONE, NULL }, /* Xo */
- { ARGSFL_NONE, NULL }, /* Fo */
- { ARGSFL_NONE, NULL }, /* Fc */
+ { 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 }, /* 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 }, /* Lp */
{ ARGSFL_DELIM, NULL }, /* Lk */
{ ARGSFL_DELIM, NULL }, /* Mt */
{ ARGSFL_NONE, NULL }, /* Lp */
{ ARGSFL_DELIM, NULL }, /* Lk */
{ ARGSFL_DELIM, NULL }, /* Mt */
{ ARGSFL_DELIM, NULL }, /* Brc */
{ ARGSFL_NONE, NULL }, /* %C */
{ ARGSFL_NONE, NULL }, /* Es */
{ ARGSFL_DELIM, NULL }, /* Brc */
{ ARGSFL_NONE, NULL }, /* %C */
{ ARGSFL_NONE, NULL }, /* Es */
- { ARGSFL_NONE, NULL }, /* En */
- { ARGSFL_NONE, NULL }, /* Dx */
+ { ARGSFL_DELIM, 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 */
{ ARGSFL_NONE, NULL }, /* %Q */
{ ARGSFL_NONE, NULL }, /* br */
{ ARGSFL_NONE, NULL }, /* sp */
{ ARGSFL_NONE, NULL }, /* %U */
{ ARGSFL_NONE, NULL }, /* Ta */
- * 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.
+ * Parse flags and their arguments from the input line.
+ * These come in the form -flag [argument ...].
+ * Some flags take no argument, some one, some multiple.
-enum margverr
-mdoc_argv(struct mdoc *m, int line, enum mdoct tok,
- struct mdoc_arg **v, int *pos, char *buf)
+void
+mdoc_argv(struct roff_man *mdoc, int line, int tok,
+ struct mdoc_arg **reta, int *pos, char *buf)
- /*
- * We want to nil-terminate the word to look it up (it's easier
- * that way). But we may not have a flag, in which case we need
- * to restore the line as-is. So keep around the stray byte,
- * which we'll reset upon exiting (if necessary).
- */
+ /* Seek to the first unescaped space. */
- /*
- * Now look up the word as a flag. Use temporary storage that
- * we'll copy into the node's flags, if necessary.
- */
+ /*
+ * We want to nil-terminate the word to look it up.
+ * But we may not have a flag, in which case we need
+ * to restore the line as-is. So keep around the
+ * stray byte, which we'll reset upon exiting.
+ */
- while (MDOC_ARG_MAX != (tmp.arg = *ap++))
- if (0 == strcmp(p, mdoc_argnames[tmp.arg]))
+ while ((tmpv.arg = *argtable++) != MDOC_ARG_MAX)
+ if ( ! strcmp(argname, mdoc_argnames[tmpv.arg]))
+ break;
+
+ /* If it isn't a flag, restore the saved byte. */
+
+ if (tmpv.arg == MDOC_ARG_MAX) {
+ if (savechar != '\0')
+ buf[ipos - 1] = savechar;
- /* Read to the next word (the argument). */
-
- 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_NONE):
- break;
- }
+ while (buf[ipos] == ' ')
+ ipos++;
+
+ /* Parse the arguments of the flag. */
+
+ tmpv.line = line;
+ tmpv.pos = *pos;
+ tmpv.sz = 0;
+ tmpv.value = NULL;
+
+ switch (argvflags[tmpv.arg]) {
+ case ARGV_SINGLE:
+ argv_single(mdoc, line, &tmpv, &ipos, buf);
+ break;
+ case ARGV_MULTI:
+ argv_multi(mdoc, line, &tmpv, &ipos, buf);
+ break;
+ case ARGV_NONE:
+ break;
+ }
- memcpy(&arg->argv[(int)arg->argc - 1],
- &tmp, sizeof(struct mdoc_argv));
+ retc = ++(*reta)->argc;
+ retv = &(*reta)->argv;
+ *retv = mandoc_reallocarray(*retv, retc, sizeof(**retv));
+ memcpy(*retv + retc - 1, &tmpv, sizeof(**retv));
-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)
+mdoc_args(struct roff_man *mdoc, int line, int *pos,
+ char *buf, int tok, char **v)
- if (MDOC_It != tok)
- return(args(m, line, pos, buf, fl, v));
+ 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));
- return(args(m, line, pos, buf, fl, v));
+ return(args(mdoc, line, pos, buf, fl, v));
-args(struct mdoc *m, int line, int *pos,
+args(struct roff_man *mdoc, int line, int *pos,
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.
*/
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)
+ mandoc_msg(MANDOCERR_ARG_QUOTE,
+ mdoc->parse, line, *pos, NULL);
* Adjust new-buffer position to be beyond delimiter
* mark (e.g., Ta -> end + 2).
*/
* Adjust new-buffer position to be beyond delimiter
* mark (e.g., Ta -> end + 2).
*/
* Process a quoted literal. A quote begins with a double-quote
* and ends with a double-quote NOT preceded by a double-quote.
* Process a quoted literal. A quote begins with a double-quote
* and ends with a double-quote NOT preceded by a double-quote.
- mdoc_pmsg(m, line, *pos, MANDOCERR_BADQUOTE);
+ mandoc_msg(MANDOCERR_ARG_QUOTE,
+ mdoc->parse, line, *pos, NULL);
- *v = mandoc_getarg(m->parse, &p, line, pos);
+ *v = mandoc_getarg(mdoc->parse, &p, line, pos);
* Check if the string consists only of space-separated closing
* delimiters. This is a bit of a dance: the first must be a close
* delimiter, but it may be followed by middle delimiters. Arbitrary
* Check if the string consists only of space-separated closing
* delimiters. This is a bit of a dance: the first must be a close
* delimiter, but it may be followed by middle delimiters. Arbitrary
struct mdoc_argv *v, int *pos, char *buf)
{
enum margserr ac;
char *p;
for (v->sz = 0; ; v->sz++) {
struct mdoc_argv *v, int *pos, char *buf)
{
enum margserr ac;
char *p;
for (v->sz = 0; ; v->sz++) {
- ac = args(m, line, pos, buf, ARGSFL_NONE, &p);
- if (ARGS_ERROR == ac)
- return(0);
- else if (ARGS_EOLN == ac)
+ ac = args(mdoc, line, pos, buf, ARGSFL_NONE, &p);
+ if (ac == ARGS_EOLN)
- if (0 == v->sz % MULTI_STEP)
- v->value = mandoc_realloc(v->value,
- (v->sz + MULTI_STEP) * sizeof(char *));
+ if (v->sz % MULTI_STEP == 0)
+ v->value = mandoc_reallocarray(v->value,
+ v->sz + MULTI_STEP, sizeof(char *));
- ac = args(m, line, pos, buf, ARGSFL_NONE, &p);
- if (ARGS_ERROR == ac)
- return(0);
- if (ARGS_EOLN == ac)
- return(1);
+ ac = args(mdoc, line, pos, buf, ARGSFL_NONE, &p);
+ if (ac == ARGS_EOLN)
+ return;