diff options
-rw-r--r-- | argv.c | 145 | ||||
-rw-r--r-- | macro.c | 8 | ||||
-rw-r--r-- | mdoc.c | 2 | ||||
-rw-r--r-- | mdocml.c | 8 | ||||
-rw-r--r-- | private.h | 2 | ||||
-rw-r--r-- | validate.c | 170 |
6 files changed, 217 insertions, 118 deletions
@@ -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; } @@ -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); @@ -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 */ @@ -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); @@ -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); @@ -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 |