summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--argv.c145
-rw-r--r--macro.c8
-rw-r--r--mdoc.c2
-rw-r--r--mdocml.c8
-rw-r--r--private.h2
-rw-r--r--validate.c170
6 files changed, 217 insertions, 118 deletions
diff --git a/argv.c b/argv.c
index e70969b3..68d076c8 100644
--- a/argv.c
+++ b/argv.c
@@ -29,6 +29,10 @@
static int lookup(int, const char *);
static int parse(struct mdoc *, int, int,
struct mdoc_arg *, int *, char *);
+static int parse_single(struct mdoc *, int,
+ struct mdoc_arg *, int *, char *);
+static int parse_multi(struct mdoc *, int,
+ struct mdoc_arg *, int *, char *);
static int postparse(struct mdoc *, int,
const struct mdoc_arg *, int);
@@ -50,6 +54,10 @@ mdoc_args(struct mdoc *mdoc, int line, int *pos, char *buf, int fl, char **v)
return(ARGS_ERROR);
if ((fl & ARGS_DELIM) && mdoc_iscdelim(buf[*pos])) {
+ /*
+ * If ARGS_DELIM, return ARGS_PUNCT if only space-separated
+ * punctuation remains.
+ */
for (i = *pos; buf[i]; ) {
if ( ! mdoc_iscdelim(buf[i]))
break;
@@ -66,25 +74,43 @@ mdoc_args(struct mdoc *mdoc, int line, int *pos, char *buf, int fl, char **v)
}
}
- /*
- * Parse routine for non-quoted string.
- */
+ /* Parse routine for non-quoted string. */
if ('\"' != buf[*pos]) {
*v = &buf[*pos];
- while (buf[*pos] && ! isspace(buf[*pos]))
- (*pos)++;
+ /* FIXME: UGLY tab-sep processing. */
+
+ if (ARGS_TABSEP & fl)
+ while (buf[*pos]) {
+ if ('\t' == buf[*pos])
+ break;
+ if ('T' == buf[*pos]) {
+ (*pos)++;
+ if (0 == buf[*pos])
+ break;
+ if ('a' == buf[*pos]) {
+ buf[*pos - 1] = 0;
+ break;
+ }
+ }
+ (*pos)++;
+ }
+ else
+ while (buf[*pos] && ! isspace(buf[*pos]))
+ (*pos)++;
if (0 == buf[*pos])
return(ARGS_WORD);
buf[(*pos)++] = 0;
+
if (0 == buf[*pos])
return(ARGS_WORD);
- while (buf[*pos] && isspace(buf[*pos]))
- (*pos)++;
+ if ( ! (ARGS_TABSEP & fl))
+ while (buf[*pos] && isspace(buf[*pos]))
+ (*pos)++;
if (buf[*pos])
return(ARGS_WORD);
@@ -101,6 +127,8 @@ mdoc_args(struct mdoc *mdoc, int line, int *pos, char *buf, int fl, char **v)
* error. After, parse to the next word.
*/
+ assert( ! (ARGS_TABSEP & fl));
+
*v = &buf[++(*pos)];
while (buf[*pos] && '\"' != buf[*pos])
@@ -318,65 +346,78 @@ postparse(struct mdoc *mdoc, int line, const struct mdoc_arg *v, int pos)
static int
-parse(struct mdoc *mdoc, int line, int tok,
+parse_multi(struct mdoc *mdoc, int line,
struct mdoc_arg *v, int *pos, char *buf)
{
+ int c, ppos;
char *p;
- int c, ppos, i;
+
+ v->sz = 0;
+ v->value = xcalloc(MDOC_LINEARG_MAX, sizeof(char *));
ppos = *pos;
- switch (v->arg) {
- case(MDOC_Std):
- /* FALLTHROUGH */
- case(MDOC_Width):
- /* FALLTHROUGH */
- case(MDOC_Offset):
- /*
- * This has a single value for an argument.
- */
+ for (v->sz = 0; v->sz < MDOC_LINEARG_MAX; v->sz++) {
+ if ('-' == buf[*pos])
+ break;
c = mdoc_args(mdoc, line, pos, buf, ARGS_QUOTED, &p);
- if (ARGS_ERROR == c)
+ if (ARGS_ERROR == c) {
+ free(v->value);
return(0);
- else if (ARGS_EOLN != c) {
- v->sz = 1;
- v->value = xcalloc(1, sizeof(char *));
- v->value[0] = p;
+ } else if (ARGS_EOLN == c)
break;
- }
+ v->value[v->sz] = p;
+ }
+
+ if (0 < v->sz && v->sz < MDOC_LINEARG_MAX)
+ return(1);
+
+ c = 0 == v->sz ? ERR_SYNTAX_ARGVAL : ERR_SYNTAX_ARGMANY;
+ free(v->value);
+ return(mdoc_perr(mdoc, line, ppos, c));
+}
+
+
+static int
+parse_single(struct mdoc *mdoc, int line,
+ struct mdoc_arg *v, int *pos, char *buf)
+{
+ int c, ppos;
+ char *p;
+
+ ppos = *pos;
+
+ c = mdoc_args(mdoc, line, pos, buf, ARGS_QUOTED, &p);
+ if (ARGS_ERROR == c)
+ return(0);
+ if (ARGS_EOLN == c)
return(mdoc_perr(mdoc, line, ppos, ERR_SYNTAX_ARGVAL));
- case(MDOC_Column):
- /*
- * This has several value for a single argument. We
- * pre-allocate a pointer array and don't let it exceed
- * this size.
- */
- v->sz = 0;
- v->value = xcalloc(MDOC_LINEARG_MAX, sizeof(char *));
- for (i = 0; i < MDOC_LINEARG_MAX; i++) {
- c = mdoc_args(mdoc, line, pos, buf, ARGS_QUOTED, &p);
- if (ARGS_ERROR == c) {
- free(v->value);
- return(0);
- } else if (ARGS_EOLN == c)
- break;
- v->value[i] = p;
- }
- if (0 == i) {
- free(v->value);
- return(mdoc_perr(mdoc, line, ppos,
- ERR_SYNTAX_ARGVAL));
- } else if (MDOC_LINEARG_MAX == i)
- return(mdoc_perr(mdoc, line, ppos,
- ERR_SYNTAX_ARGMANY));
+ v->sz = 1;
+ v->value = xcalloc(1, sizeof(char *));
+ v->value[0] = p;
+ return(1);
+}
- v->sz = i;
- break;
+static int
+parse(struct mdoc *mdoc, int line, int tok,
+ struct mdoc_arg *v, int *pos, char *buf)
+{
+
+ v->sz = 0;
+ v->value = NULL;
+
+ switch (v->arg) {
+ case(MDOC_Std):
+ /* FALLTHROUGH */
+ case(MDOC_Width):
+ /* FALLTHROUGH */
+ case(MDOC_Offset):
+ return(parse_single(mdoc, line, v, pos, buf));
+ case(MDOC_Column):
+ return(parse_multi(mdoc, line, v, pos, buf));
default:
- v->sz = 0;
- v->value = NULL;
break;
}
diff --git a/macro.c b/macro.c
index e319cafc..37769a85 100644
--- a/macro.c
+++ b/macro.c
@@ -479,7 +479,7 @@ macro_text(MACRO_PROT_ARGS)
int
macro_scoped(MACRO_PROT_ARGS)
{
- int c, lastarg, argc, j;
+ int c, lastarg, argc, j, fl;
struct mdoc_arg argv[MDOC_LINEARG_MAX];
char *p;
@@ -529,9 +529,13 @@ macro_scoped(MACRO_PROT_ARGS)
return(0);
mdoc->next = MDOC_NEXT_CHILD;
+ fl = ARGS_DELIM;
+ if (MDOC_TABSEP & mdoc_macros[tok].flags)
+ fl |= ARGS_TABSEP;
+
for (j = 0; j < MDOC_LINEARG_MAX; j++) {
lastarg = *pos;
- c = mdoc_args(mdoc, line, pos, buf, ARGS_DELIM, &p);
+ c = mdoc_args(mdoc, line, pos, buf, fl, &p);
if (ARGS_ERROR == c)
return(0);
diff --git a/mdoc.c b/mdoc.c
index 939585e8..9c1f93b1 100644
--- a/mdoc.c
+++ b/mdoc.c
@@ -97,7 +97,7 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
{ macro_close_explicit, 0 }, /* Ed */
{ macro_scoped, MDOC_EXPLICIT }, /* Bl */
{ macro_close_explicit, 0 }, /* El */
- { macro_scoped, MDOC_NESTED | MDOC_PARSED }, /* It */
+ { macro_scoped, MDOC_NESTED | MDOC_PARSED | MDOC_TABSEP}, /* It */
{ macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
{ macro_constant, MDOC_PARSED }, /* An */
{ macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
diff --git a/mdocml.c b/mdocml.c
index 90d26349..d8195387 100644
--- a/mdocml.c
+++ b/mdocml.c
@@ -238,12 +238,16 @@ print_node(const struct mdoc_node *n, int indent)
for (i = 0; i < (int)argc; i++) {
(void)printf(" -%s", mdoc_argnames[argv[i].arg]);
+ if (j > 0)
+ (void)printf(" [");
for (j = 0; j < (int)argv[i].sz; j++)
- (void)printf(" \"%s\"", argv[i].value[j]);
+ (void)printf(" [%s]", argv[i].value[j]);
+ if (j > 0)
+ (void)printf(" ]");
}
for (i = 0; i < (int)sz; i++)
- (void)printf(" \"%s\"", params[i]);
+ (void)printf(" [%s]", params[i]);
(void)printf(" %d:%d\n", n->line, n->pos);
diff --git a/private.h b/private.h
index 5da7854e..55be0762 100644
--- a/private.h
+++ b/private.h
@@ -53,6 +53,7 @@ struct mdoc_macro {
#define MDOC_QUOTABLE (1 << 3)
#define MDOC_PROLOGUE (1 << 4)
#define MDOC_NESTED (1 << 5)
+#define MDOC_TABSEP (1 << 6)
};
extern const struct mdoc_macro *const mdoc_macros;
@@ -118,6 +119,7 @@ int mdoc_args(struct mdoc *, int,
#define ARGS_QUOTED (1 << 0)
#define ARGS_DELIM (1 << 1)
+#define ARGS_TABSEP (1 << 2)
int xstrlcat(char *, const char *, size_t);
int xstrlcpy(char *, const char *, size_t);
diff --git a/validate.c b/validate.c
index f61a850d..19702916 100644
--- a/validate.c
+++ b/validate.c
@@ -42,9 +42,11 @@ static int pre_prologue(struct mdoc *, struct mdoc_node *);
static int headchild_err_ge1(struct mdoc *);
static int headchild_err_eq0(struct mdoc *);
+static int elemchild_err_eq0(struct mdoc *);
static int elemchild_err_ge1(struct mdoc *);
static int elemchild_warn_eq0(struct mdoc *);
static int bodychild_warn_ge1(struct mdoc *);
+static int elemchild_warn_ge1(struct mdoc *);
static int post_sh(struct mdoc *);
static int post_bl(struct mdoc *);
static int post_it(struct mdoc *);
@@ -57,6 +59,9 @@ static v_pre pres_it[] = { pre_it, NULL };
static v_post posts_bd[] = { headchild_err_eq0,
bodychild_warn_ge1, NULL };
+static v_post posts_text[] = { elemchild_err_ge1, NULL };
+static v_post posts_wtext[] = { elemchild_warn_ge1, NULL };
+static v_post posts_notext[] = { elemchild_err_eq0, NULL };
static v_post posts_sh[] = { headchild_err_ge1,
bodychild_warn_ge1, post_sh, NULL };
static v_post posts_bl[] = { headchild_err_eq0,
@@ -64,104 +69,111 @@ static v_post posts_bl[] = { headchild_err_eq0,
static v_post posts_it[] = { post_it, NULL };
static v_post posts_ss[] = { headchild_err_ge1, NULL };
static v_post posts_pp[] = { elemchild_warn_eq0, NULL };
-static v_post posts_dd[] = { elemchild_err_ge1, NULL };
static v_post posts_d1[] = { headchild_err_ge1, NULL };
const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* \" */
- { pres_prologue, posts_dd }, /* Dd */
+ { pres_prologue, posts_text }, /* Dd */
{ pres_prologue, NULL }, /* Dt */
{ pres_prologue, NULL }, /* Os */
- { NULL, posts_sh }, /* Sh */ /* FIXME: preceding Pp. */
- { NULL, posts_ss }, /* Ss */ /* FIXME: preceding Pp. */
- { NULL, posts_pp }, /* Pp */ /* FIXME: proceeding... */
+ /* FIXME: preceding Pp. */
+ /* FIXME: NAME section internal ordering. */
+ { NULL, posts_sh }, /* Sh */
+ /* FIXME: preceding Pp. */
+ { NULL, posts_ss }, /* Ss */
+ /* FIXME: proceeding... */
+ { NULL, posts_pp }, /* Pp */
{ pres_d1, posts_d1 }, /* D1 */
{ pres_d1, posts_d1 }, /* Dl */
- { pres_bd, posts_bd }, /* Bd */ /* FIXME: preceding Pp. */
+ /* FIXME: preceding Pp. */
+ { pres_bd, posts_bd }, /* Bd */
{ NULL, NULL }, /* Ed */
- { pres_bl, posts_bl }, /* Bl */ /* FIXME: preceding Pp. */
+ /* FIXME: preceding Pp. */
+ { pres_bl, posts_bl }, /* Bl */
{ NULL, NULL }, /* El */
{ pres_it, posts_it }, /* It */
- { NULL, NULL }, /* Ad */
- { NULL, NULL }, /* An */
+ { NULL, posts_text }, /* Ad */
+ /* FIXME */
+ { NULL, NULL }, /* An */
{ NULL, NULL }, /* Ar */
- { NULL, NULL }, /* Cd */
+
+ { NULL, posts_text }, /* Cd */ /* FIXME: section 4 only. */
{ NULL, NULL }, /* Cm */
- { NULL, NULL }, /* Dv */
- { NULL, NULL }, /* Er */
- { NULL, NULL }, /* Ev */
- { NULL, NULL }, /* Ex */
- { NULL, NULL }, /* Fa */
- { NULL, NULL }, /* Fd */
+ { NULL, posts_text }, /* Dv */
+ { NULL, posts_text }, /* Er */ /* FIXME: section 2 only. */
+ { NULL, posts_text }, /* Ev */
+ { NULL, posts_notext }, /* Ex */ /* FIXME: sections 1,6,8 only. */ /* -std required */
+ { NULL, posts_text }, /* Fa */
+ { NULL, NULL }, /* Fd */ /* FIXME: SYNOPSIS section. */
{ NULL, NULL }, /* Fl */
- { NULL, NULL }, /* Fn */
+ { NULL, posts_text }, /* Fn */
{ NULL, NULL }, /* Ft */
- { NULL, NULL }, /* Ic */
- { NULL, NULL }, /* In */
- { NULL, NULL }, /* Li */
- { NULL, NULL }, /* Nd */
- { NULL, NULL }, /* Nm */
- { NULL, NULL }, /* Op */
+ { NULL, posts_text }, /* Ic */
+ { NULL, posts_wtext }, /* In */
+ { NULL, posts_text }, /* Li */
+ { NULL, posts_wtext }, /* Nd */
+ { NULL, NULL }, /* Nm */ /* FIXME: If name not set? */
+ { NULL, posts_wtext }, /* Op */
{ NULL, NULL }, /* Ot */
{ NULL, NULL }, /* Pa */
- { NULL, NULL }, /* Rv */
- { NULL, NULL }, /* St */
- { NULL, NULL }, /* Va */
- { NULL, NULL }, /* Vt */
- { NULL, NULL }, /* Xr */
- { NULL, NULL }, /* %A */
- { NULL, NULL }, /* %B */
- { NULL, NULL }, /* %D */
- { NULL, NULL }, /* %I */
- { NULL, NULL }, /* %J */
- { NULL, NULL }, /* %N */
- { NULL, NULL }, /* %O */
- { NULL, NULL }, /* %P */
- { NULL, NULL }, /* %R */
- { NULL, NULL }, /* %T */
- { NULL, NULL }, /* %V */
+ { NULL, posts_notext }, /* Rv */ /* -std required */
+ { NULL, posts_notext }, /* St */ /* arg required */
+ { NULL, posts_text }, /* Va */
+ { NULL, posts_text }, /* Vt */
+ { NULL, NULL }, /* Xr */ /* FIXME */
+ { NULL, posts_text }, /* %A */
+ { NULL, posts_text }, /* %B */
+ { NULL, posts_text }, /* %D */
+ { NULL, posts_text }, /* %I */
+ { NULL, posts_text }, /* %J */
+ { NULL, posts_text }, /* %N */
+ { NULL, posts_text }, /* %O */
+ { NULL, posts_text }, /* %P */
+ { NULL, posts_text }, /* %R */
+ { NULL, posts_text }, /* %T */
+ { NULL, posts_text }, /* %V */
{ NULL, NULL }, /* Ac */
{ NULL, NULL }, /* Ao */
- { NULL, NULL }, /* Aq */
+ { NULL, posts_wtext }, /* Aq */
{ NULL, NULL }, /* At */ /* FIXME */
{ NULL, NULL }, /* Bc */
{ NULL, NULL }, /* Bf */
{ NULL, NULL }, /* Bo */
- { NULL, NULL }, /* Bq */
+ { NULL, posts_wtext }, /* Bq */
{ NULL, NULL }, /* Bsx */
{ NULL, NULL }, /* Bx */
- { NULL, NULL }, /* Db */
+ { NULL, NULL }, /* Db */ /* FIXME: boolean */
{ NULL, NULL }, /* Dc */
{ NULL, NULL }, /* Do */
- { NULL, NULL }, /* Dq */
+ { NULL, posts_wtext }, /* Dq */
{ NULL, NULL }, /* Ec */
{ NULL, NULL }, /* Ef */ /* -symbolic, etc. */
- { NULL, NULL }, /* Em */
+ { NULL, posts_text }, /* Em */
{ NULL, NULL }, /* Eo */
{ NULL, NULL }, /* Fx */
- { NULL, NULL }, /* Ms */
- { NULL, NULL }, /* No */
- { NULL, NULL }, /* Ns */
+ { NULL, posts_text }, /* Ms */ /* FIXME: which symbols? */
+ { NULL, posts_notext }, /* No */
+ { NULL, posts_notext }, /* Ns */
{ NULL, NULL }, /* Nx */
{ NULL, NULL }, /* Ox */
{ NULL, NULL }, /* Pc */
- { NULL, NULL }, /* Pf */ /* 2 or more arguments */
+ { NULL, NULL }, /* Pf */ /* FIXME: 2 or more arguments */
{ NULL, NULL }, /* Po */
- { NULL, NULL }, /* Pq */ /* FIXME: ignore following Sh/Ss */
+ { NULL, posts_wtext }, /* Pq */ /* FIXME: ignore following Sh/Ss */
{ NULL, NULL }, /* Qc */
- { NULL, NULL }, /* Ql */
+ { NULL, posts_wtext }, /* Ql */
{ NULL, NULL }, /* Qo */
- { NULL, NULL }, /* Qq */
+ { NULL, posts_wtext }, /* Qq */
{ NULL, NULL }, /* Re */
{ NULL, NULL }, /* Rs */
{ NULL, NULL }, /* Sc */
{ NULL, NULL }, /* So */
- { NULL, NULL }, /* Sq */
- { NULL, NULL }, /* Sm */
- { NULL, NULL }, /* Sx */
- { NULL, NULL }, /* Sy */
- { NULL, NULL }, /* Tn */
+ { NULL, posts_wtext }, /* Sq */
+ { NULL, NULL }, /* Sm */ /* FIXME: boolean */
+ { NULL, posts_text }, /* Sx */
+ { NULL, posts_text }, /* Sy */
+ { NULL, posts_text }, /* Tn */
{ NULL, NULL }, /* Ux */
{ NULL, NULL }, /* Xc */
{ NULL, NULL }, /* Xo */
@@ -171,10 +183,10 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* Oc */
{ NULL, NULL }, /* Bk */
{ NULL, NULL }, /* Ek */
- { NULL, NULL }, /* Bt */
+ { NULL, posts_notext }, /* Bt */
{ NULL, NULL }, /* Hf */
{ NULL, NULL }, /* Fr */
- { NULL, NULL }, /* Ud */
+ { NULL, posts_notext }, /* Ud */
};
@@ -203,6 +215,28 @@ elemchild_warn_eq0(struct mdoc *mdoc)
static int
+elemchild_warn_ge1(struct mdoc *mdoc)
+{
+
+ assert(MDOC_ELEM == mdoc->last->type);
+ if (mdoc->last->child)
+ return(1);
+ return(mdoc_warn(mdoc, WARN_ARGS_GE1));
+}
+
+
+static int
+elemchild_err_eq0(struct mdoc *mdoc)
+{
+
+ assert(MDOC_ELEM == mdoc->last->type);
+ if (NULL == mdoc->last->child)
+ return(1);
+ return(mdoc_err(mdoc, ERR_ARGS_EQ0));
+}
+
+
+static int
elemchild_err_ge1(struct mdoc *mdoc)
{
@@ -293,6 +327,8 @@ pre_bl(struct mdoc *mdoc, struct mdoc_node *node)
case (MDOC_Ohang):
/* FALLTHROUGH */
case (MDOC_Inset):
+ /* FALLTHROUGH */
+ case (MDOC_Column):
if (type)
err++;
type++;
@@ -449,6 +485,8 @@ post_it(struct mdoc *mdoc)
argc = n->data.block.argc;
type = TYPE_NONE;
+
+ /* Some types require block-head, some not. */
for (i = 0; TYPE_NONE == type && i < argc; i++)
switch (n->data.block.argv[(int)i].arg) {
@@ -513,10 +551,20 @@ post_it(struct mdoc *mdoc)
if ( ! mdoc_warn(mdoc, WARN_SYNTAX_NOBODY))
return(0);
- /* TODO: make sure columns are aligned. */
- assert(MDOC_Column != sv);
+ if (MDOC_Column != sv)
+ return(1);
+
+ /* Make sure the number of columns is sane. */
- return(1);
+ sv = mdoc->last->parent->parent->data.block.argv->sz;
+ n = mdoc->last->data.block.head->child;
+
+ for (i = 0; n; n = n->next)
+ i++;
+
+ if (i == (size_t)sv)
+ return(1);
+ return(mdoc_err(mdoc, ERR_SYNTAX_ARGFORM));
#undef TYPE_NONE
#undef TYPE_BODY