-/* $Id: mdoc_argv.c,v 1.57 2010/07/21 09:08:26 kristaps Exp $ */
+/* $Id: mdoc_argv.c,v 1.65 2011/03/17 01:23:28 kristaps Exp $ */
/*
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
static enum mdocargt argv_a2arg(enum mdoct, const char *);
static enum margserr args(struct mdoc *, int, int *,
char *, int, char **);
+static int args_checkpunct(const char *);
static int argv(struct mdoc *, int,
struct mdoc_argv *, int *, char *);
static int argv_single(struct mdoc *, int,
0, /* Os */
0, /* Sh */
0, /* Ss */
- ARGS_DELIM, /* Pp */
+ 0, /* Pp */
ARGS_DELIM, /* D1 */
ARGS_DELIM, /* Dl */
0, /* Bd */
0, /* Fr */
0, /* Ud */
0, /* Lb */
- ARGS_DELIM, /* Lp */
+ 0, /* Lp */
ARGS_DELIM, /* Lk */
ARGS_DELIM, /* Mt */
ARGS_DELIM, /* Brq */
void
mdoc_argn_free(struct mdoc_arg *p, int iarg)
{
- struct mdoc_argv *arg = &p->argv[iarg]; /* FIXME: decl/assign */
+ struct mdoc_argv *arg;
int j;
+ arg = &p->argv[iarg];
+
if (arg->sz && arg->value) {
for (j = (int)arg->sz - 1; j >= 0; j--)
free(arg->value[j]);
if (MDOC_Bl == n->tok)
break;
- assert(n->data.Bl);
- if (n && LIST_column == n->data.Bl->type) {
+ if (n && LIST_column == n->norm->Bl.type) {
fl |= ARGS_TABSEP;
fl &= ~ARGS_DELIM;
}
int i;
char *p, *pp;
enum margserr rc;
- enum mdelim d;
/*
* Parse out the terms (like `val' in `.Xx -arg val' or simply
return(ARGS_EOLN);
}
- /*
- * If the first character is a closing delimiter and we're to
- * look for delimited strings, then pass down the buffer seeing
- * if it follows the pattern of [[::delim::][ ]+]+. Note that
- * we ONLY care about closing delimiters.
- */
-
- if ((fl & ARGS_DELIM) && DELIM_CLOSE == mdoc_iscdelim(buf[*pos])) {
- for (i = *pos; buf[i]; ) {
- d = mdoc_iscdelim(buf[i]);
- if (DELIM_NONE == d || DELIM_OPEN == d)
- break;
- i++;
- if ('\0' == buf[i] || ' ' != buf[i])
- break;
- i++;
- while (buf[i] && ' ' == buf[i])
- i++;
- }
+ *v = &buf[*pos];
- if ('\0' == buf[i]) {
- *v = &buf[*pos];
- if (i && ' ' != buf[i - 1])
- return(ARGS_PUNCT);
- if (ARGS_NOWARN & fl)
- return(ARGS_PUNCT);
- if ( ! mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE))
- return(ARGS_ERROR);
+ if (ARGS_DELIM & fl && args_checkpunct(&buf[*pos])) {
+ i = strlen(&buf[*pos]) + *pos;
+ if (i && ' ' != buf[i - 1])
return(ARGS_PUNCT);
- }
+ if (ARGS_NOWARN & fl)
+ return(ARGS_PUNCT);
+ /* FIXME: remove conditional messages... */
+ if ( ! mdoc_pmsg(m, line, *pos, MANDOCERR_EOLNSPACE))
+ return(ARGS_ERROR);
+ return(ARGS_PUNCT);
}
- *v = &buf[*pos];
-
/*
* First handle TABSEP items, restricted to `Bl -column'. This
* ignores conventional token parsing and instead uses tabs or
return(ARGS_WORD);
}
+/*
+ * 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
+ * whitespace may separate these tokens.
+ */
+static int
+args_checkpunct(const char *p)
+{
+ int i, j;
+ char buf[DELIMSZ];
+ enum mdelim d;
+
+ i = 0;
+ /* First token must be a close-delimiter. */
+
+ for (j = 0; p[i] && ' ' != p[i] && j < DELIMSZ; j++, i++)
+ buf[j] = p[i];
+
+ if (DELIMSZ == j)
+ return(0);
+
+ buf[j] = '\0';
+ if (DELIM_CLOSE != mdoc_isdelim(buf))
+ return(0);
+
+ while (' ' == p[i])
+ i++;
+
+ /* Remaining must NOT be open/none. */
+
+ while (p[i]) {
+ j = 0;
+ while (p[i] && ' ' != p[i] && j < DELIMSZ)
+ buf[j++] = p[i++];
+
+ if (DELIMSZ == j)
+ return(0);
+
+ buf[j] = '\0';
+ d = mdoc_isdelim(buf);
+ if (DELIM_NONE == d || DELIM_OPEN == d)
+ return(0);
+
+ while (' ' == p[i])
+ i++;
+ }
+
+ return('\0' == p[i]);
+}
+
+/*
+ * Match up an argument string (e.g., `-foo bar' having "foo") with the
+ * correrct identifier. It must apply to the given macro. If none was
+ * found (including bad matches), return MDOC_ARG_MAX.
+ */
static enum mdocargt
argv_a2arg(enum mdoct tok, const char *p)
{
+ enum mdocargt args[MDOC_ARG_MAX];
+ int i, len;
- /*
- * Parse an argument identifier from its text. XXX - this
- * should really be table-driven to clarify the code.
- *
- * If you add an argument to the list, make sure that you
- * register it here with its one or more macros!
- */
+ len = 0;
switch (tok) {
case (MDOC_An):
- if (0 == strcmp(p, "split"))
- return(MDOC_Split);
- else if (0 == strcmp(p, "nosplit"))
- return(MDOC_Nosplit);
+ args[len++] = MDOC_Split;
+ args[len++] = MDOC_Nosplit;
break;
-
case (MDOC_Bd):
- if (0 == strcmp(p, "ragged"))
- return(MDOC_Ragged);
- else if (0 == strcmp(p, "unfilled"))
- return(MDOC_Unfilled);
- else if (0 == strcmp(p, "filled"))
- return(MDOC_Filled);
- else if (0 == strcmp(p, "literal"))
- return(MDOC_Literal);
- else if (0 == strcmp(p, "file"))
- return(MDOC_File);
- else if (0 == strcmp(p, "offset"))
- return(MDOC_Offset);
- else if (0 == strcmp(p, "compact"))
- return(MDOC_Compact);
- else if (0 == strcmp(p, "centered"))
- return(MDOC_Centred);
+ args[len++] = MDOC_Ragged;
+ args[len++] = MDOC_Unfilled;
+ args[len++] = MDOC_Filled;
+ args[len++] = MDOC_Literal;
+ args[len++] = MDOC_File;
+ args[len++] = MDOC_Offset;
+ args[len++] = MDOC_Compact;
+ args[len++] = MDOC_Centred;
break;
-
case (MDOC_Bf):
- if (0 == strcmp(p, "emphasis"))
- return(MDOC_Emphasis);
- else if (0 == strcmp(p, "literal"))
- return(MDOC_Literal);
- else if (0 == strcmp(p, "symbolic"))
- return(MDOC_Symbolic);
+ args[len++] = MDOC_Emphasis;
+ args[len++] = MDOC_Literal;
+ args[len++] = MDOC_Symbolic;
break;
-
case (MDOC_Bk):
- if (0 == strcmp(p, "words"))
- return(MDOC_Words);
+ args[len++] = MDOC_Words;
break;
-
case (MDOC_Bl):
- if (0 == strcmp(p, "bullet"))
- return(MDOC_Bullet);
- else if (0 == strcmp(p, "dash"))
- return(MDOC_Dash);
- else if (0 == strcmp(p, "hyphen"))
- return(MDOC_Hyphen);
- else if (0 == strcmp(p, "item"))
- return(MDOC_Item);
- else if (0 == strcmp(p, "enum"))
- return(MDOC_Enum);
- else if (0 == strcmp(p, "tag"))
- return(MDOC_Tag);
- else if (0 == strcmp(p, "diag"))
- return(MDOC_Diag);
- else if (0 == strcmp(p, "hang"))
- return(MDOC_Hang);
- else if (0 == strcmp(p, "ohang"))
- return(MDOC_Ohang);
- else if (0 == strcmp(p, "inset"))
- return(MDOC_Inset);
- else if (0 == strcmp(p, "column"))
- return(MDOC_Column);
- else if (0 == strcmp(p, "width"))
- return(MDOC_Width);
- else if (0 == strcmp(p, "offset"))
- return(MDOC_Offset);
- else if (0 == strcmp(p, "compact"))
- return(MDOC_Compact);
- else if (0 == strcmp(p, "nested"))
- return(MDOC_Nested);
+ args[len++] = MDOC_Bullet;
+ args[len++] = MDOC_Dash;
+ args[len++] = MDOC_Hyphen;
+ args[len++] = MDOC_Item;
+ args[len++] = MDOC_Enum;
+ args[len++] = MDOC_Tag;
+ args[len++] = MDOC_Diag;
+ args[len++] = MDOC_Hang;
+ args[len++] = MDOC_Ohang;
+ args[len++] = MDOC_Inset;
+ args[len++] = MDOC_Column;
+ args[len++] = MDOC_Width;
+ args[len++] = MDOC_Offset;
+ args[len++] = MDOC_Compact;
+ args[len++] = MDOC_Nested;
break;
-
case (MDOC_Rv):
/* FALLTHROUGH */
case (MDOC_Ex):
- if (0 == strcmp(p, "std"))
- return(MDOC_Std);
+ args[len++] = MDOC_Std;
break;
default:
break;
}
+ for (i = 0; i < len; i++)
+ if (0 == strcmp(p, mdoc_argnames[args[i]]))
+ return(args[i]);
+
return(MDOC_ARG_MAX);
}