summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--action.c321
-rw-r--r--macro.c6
-rw-r--r--mdoc.310
-rw-r--r--mdoc.c17
-rw-r--r--mdoc.h7
-rw-r--r--private.h3
-rw-r--r--strings.c46
-rw-r--r--validate.c244
-rw-r--r--xstd.c25
9 files changed, 401 insertions, 278 deletions
diff --git a/action.c b/action.c
index dca2bd08..c5c84c27 100644
--- a/action.c
+++ b/action.c
@@ -22,13 +22,9 @@
#include "private.h"
-typedef int (*a_pre)(struct mdoc *, struct mdoc_node *);
-typedef int (*a_post)(struct mdoc *);
-
struct actions {
- a_pre pre;
- a_post post;
+ int (*post)(struct mdoc *);
};
@@ -36,143 +32,150 @@ static int post_sh(struct mdoc *);
static int post_os(struct mdoc *);
static int post_dt(struct mdoc *);
static int post_dd(struct mdoc *);
-
+static int post_nm(struct mdoc *);
const struct actions mdoc_actions[MDOC_MAX] = {
- { NULL, NULL }, /* \" */
- { NULL, post_dd }, /* Dd */
- { NULL, post_dt }, /* Dt */
- { NULL, post_os }, /* Os */
- { NULL, post_sh }, /* Sh */
- { NULL, NULL }, /* Ss */
- { NULL, NULL }, /* Pp */
- { NULL, NULL }, /* D1 */
- { NULL, NULL }, /* Dl */
- { NULL, NULL }, /* Bd */
- { NULL, NULL }, /* Ed */
- { NULL, NULL }, /* Bl */
- { NULL, NULL }, /* El */
- { NULL, NULL }, /* It */
- { NULL, NULL }, /* Ad */
- { NULL, NULL }, /* An */
- { NULL, NULL }, /* Ar */
- { NULL, NULL }, /* Cd */
- { NULL, NULL }, /* Cm */
- { NULL, NULL }, /* Dv */
- { NULL, NULL }, /* Er */
- { NULL, NULL }, /* Ev */
- { NULL, NULL }, /* Ex */
- { NULL, NULL }, /* Fa */
- { NULL, NULL }, /* Fd */
- { NULL, NULL }, /* Fl */
- { NULL, NULL }, /* Fn */
- { NULL, NULL }, /* Ft */
- { NULL, NULL }, /* Ic */
- { NULL, NULL }, /* In */
- { NULL, NULL }, /* Li */
- { NULL, NULL }, /* Nd */
- { NULL, NULL }, /* Nm */
- { NULL, NULL }, /* 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, NULL }, /* Ac */
- { NULL, NULL }, /* Ao */
- { NULL, NULL }, /* Aq */
- { NULL, NULL }, /* At */
- { NULL, NULL }, /* Bc */
- { NULL, NULL }, /* Bf */
- { NULL, NULL }, /* Bo */
- { NULL, NULL }, /* Bq */
- { NULL, NULL }, /* Bsx */
- { NULL, NULL }, /* Bx */
- { NULL, NULL }, /* Db */
- { NULL, NULL }, /* Dc */
- { NULL, NULL }, /* Do */
- { NULL, NULL }, /* Dq */
- { NULL, NULL }, /* Ec */
- { NULL, NULL }, /* Ef */
- { NULL, NULL }, /* Em */
- { NULL, NULL }, /* Eo */
- { NULL, NULL }, /* Fx */
- { NULL, NULL }, /* Ms */
- { NULL, NULL }, /* No */
- { NULL, NULL }, /* Ns */
- { NULL, NULL }, /* Nx */
- { NULL, NULL }, /* Ox */
- { NULL, NULL }, /* Pc */
- { NULL, NULL }, /* Pf */
- { NULL, NULL }, /* Po */
- { NULL, NULL }, /* Pq */
- { NULL, NULL }, /* Qc */
- { NULL, NULL }, /* Ql */
- { NULL, NULL }, /* Qo */
- { NULL, NULL }, /* 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, NULL }, /* Ux */
- { NULL, NULL }, /* Xc */
- { NULL, NULL }, /* Xo */
- { NULL, NULL }, /* Fo */
- { NULL, NULL }, /* Fc */
- { NULL, NULL }, /* Oo */
- { NULL, NULL }, /* Oc */
- { NULL, NULL }, /* Bk */
- { NULL, NULL }, /* Ek */
- { NULL, NULL }, /* Bt */
- { NULL, NULL }, /* Hf */
- { NULL, NULL }, /* Fr */
- { NULL, NULL }, /* Ud */
+ { NULL }, /* \" */
+ { post_dd }, /* Dd */
+ { post_dt }, /* Dt */
+ { post_os }, /* Os */
+ { post_sh }, /* Sh */
+ { NULL }, /* Ss */
+ { NULL }, /* Pp */
+ { NULL }, /* D1 */
+ { NULL }, /* Dl */
+ { NULL }, /* Bd */
+ { NULL }, /* Ed */
+ { NULL }, /* Bl */
+ { NULL }, /* El */
+ { NULL }, /* It */
+ { NULL }, /* Ad */
+ { NULL }, /* An */
+ { NULL }, /* Ar */
+ { NULL }, /* Cd */
+ { NULL }, /* Cm */
+ { NULL }, /* Dv */
+ { NULL }, /* Er */
+ { NULL }, /* Ev */
+ { NULL }, /* Ex */
+ { NULL }, /* Fa */
+ { NULL }, /* Fd */
+ { NULL }, /* Fl */
+ { NULL }, /* Fn */
+ { NULL }, /* Ft */
+ { NULL }, /* Ic */
+ { NULL }, /* In */
+ { NULL }, /* Li */
+ { NULL }, /* Nd */
+ { post_nm }, /* Nm */
+ { NULL }, /* Op */
+ { NULL }, /* Ot */
+ { NULL }, /* Pa */
+ { NULL }, /* Rv */
+ { NULL }, /* St */
+ { NULL }, /* Va */
+ { NULL }, /* Vt */
+ { NULL }, /* Xr */
+ { NULL }, /* %A */
+ { NULL }, /* %B */
+ { NULL }, /* %D */
+ { NULL }, /* %I */
+ { NULL }, /* %J */
+ { NULL }, /* %N */
+ { NULL }, /* %O */
+ { NULL }, /* %P */
+ { NULL }, /* %R */
+ { NULL }, /* %T */
+ { NULL }, /* %V */
+ { NULL }, /* Ac */
+ { NULL }, /* Ao */
+ { NULL }, /* Aq */
+ { NULL }, /* At */
+ { NULL }, /* Bc */
+ { NULL }, /* Bf */
+ { NULL }, /* Bo */
+ { NULL }, /* Bq */
+ { NULL }, /* Bsx */
+ { NULL }, /* Bx */
+ { NULL }, /* Db */
+ { NULL }, /* Dc */
+ { NULL }, /* Do */
+ { NULL }, /* Dq */
+ { NULL }, /* Ec */
+ { NULL }, /* Ef */
+ { NULL }, /* Em */
+ { NULL }, /* Eo */
+ { NULL }, /* Fx */
+ { NULL }, /* Ms */
+ { NULL }, /* No */
+ { NULL }, /* Ns */
+ { NULL }, /* Nx */
+ { NULL }, /* Ox */
+ { NULL }, /* Pc */
+ { NULL }, /* Pf */
+ { NULL }, /* Po */
+ { NULL }, /* Pq */
+ { NULL }, /* Qc */
+ { NULL }, /* Ql */
+ { NULL }, /* Qo */
+ { NULL }, /* Qq */
+ { NULL }, /* Re */
+ { NULL }, /* Rs */
+ { NULL }, /* Sc */
+ { NULL }, /* So */
+ { NULL }, /* Sq */
+ { NULL }, /* Sm */
+ { NULL }, /* Sx */
+ { NULL }, /* Sy */
+ { NULL }, /* Tn */
+ { NULL }, /* Ux */
+ { NULL }, /* Xc */
+ { NULL }, /* Xo */
+ { NULL }, /* Fo */
+ { NULL }, /* Fc */
+ { NULL }, /* Oo */
+ { NULL }, /* Oc */
+ { NULL }, /* Bk */
+ { NULL }, /* Ek */
+ { NULL }, /* Bt */
+ { NULL }, /* Hf */
+ { NULL }, /* Fr */
+ { NULL }, /* Ud */
};
static int
-post_sh(struct mdoc *mdoc)
+post_nm(struct mdoc *mdoc)
{
- enum mdoc_sec sec;
- int i;
- struct mdoc_node *n;
- char *args[MDOC_LINEARG_MAX];
+ char buf[64];
- if (MDOC_HEAD != mdoc->last->type)
+ assert(MDOC_ELEM == mdoc->last->type);
+ assert(MDOC_Nm == mdoc->last->tok);
+
+ if (mdoc->meta.name)
return(1);
-
- assert(MDOC_Sh == mdoc->last->tok);
- n = mdoc->last->child;
- assert(n);
+ if ( ! xstrlcats(buf, mdoc->last->child, 64))
+ return(mdoc_err(mdoc, "macro parameters too long"));
- for (i = 0; n && i < MDOC_LINEARG_MAX; n = n->next, i++) {
- assert(MDOC_TEXT == n->type);
- assert(NULL == n->child);
- assert(n->data.text.string);
- args[i] = n->data.text.string;
- }
+ mdoc->meta.name = xstrdup(buf);
+ mdoc_msg(mdoc, "parsed name: %s", mdoc->meta.name);
+ return(1);
+}
+
+
+static int
+post_sh(struct mdoc *mdoc)
+{
+ enum mdoc_sec sec;
+ char buf[64];
+
+ if (MDOC_HEAD != mdoc->last->type)
+ return(1);
+ if ( ! xstrlcats(buf, mdoc->last->child, 64))
+ return(mdoc_err(mdoc, "macro parameters too long"));
- sec = mdoc_atosec((size_t)i, (const char **)args);
- if (SEC_CUSTOM != sec)
+ if (SEC_CUSTOM != (sec = mdoc_atosec(buf)))
mdoc->sec_lastn = sec;
mdoc->sec_last = sec;
@@ -185,15 +188,12 @@ post_dt(struct mdoc *mdoc)
{
int i;
char *p;
- size_t sz;
struct mdoc_node *n;
assert(MDOC_ELEM == mdoc->last->type);
assert(MDOC_Dt == mdoc->last->tok);
- assert(0 == mdoc->meta.title[0]);
- sz = META_TITLE_SZ;
- (void)xstrlcpy(mdoc->meta.title, "UNTITLED", sz);
+ assert(NULL == mdoc->meta.title);
for (i = 0, n = mdoc->last->child; n; n = n->next, i++) {
assert(MDOC_TEXT == n->type);
@@ -201,14 +201,13 @@ post_dt(struct mdoc *mdoc)
switch (i) {
case (0):
- if (xstrlcpy(mdoc->meta.title, p, sz))
- break;
- return(mdoc_nerr(mdoc, n, "badly-formed manual title parameter"));
+ mdoc->meta.title = xstrdup(p);
+ break;
case (1):
mdoc->meta.msec = mdoc_atomsec(p);
if (MSEC_DEFAULT != mdoc->meta.msec)
break;
- return(mdoc_nerr(mdoc, n, "badly-formed manual section parameter"));
+ return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
case (2):
mdoc->meta.vol = mdoc_atovol(p);
if (VOL_DEFAULT != mdoc->meta.vol)
@@ -216,12 +215,15 @@ post_dt(struct mdoc *mdoc)
mdoc->meta.arch = mdoc_atoarch(p);
if (ARCH_DEFAULT != mdoc->meta.arch)
break;
- return(mdoc_nerr(mdoc, n, "badly-formed manual volume parameter"));
+ return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
default:
return(mdoc_nerr(mdoc, n, "too many parameters"));
}
}
+ if (NULL == mdoc->meta.title)
+ mdoc->meta.title = xstrdup("untitled");
+
mdoc_msg(mdoc, "parsed title: %s", mdoc->meta.title);
/* TODO: print vol2a functions. */
return(1);
@@ -231,29 +233,16 @@ post_dt(struct mdoc *mdoc)
static int
post_os(struct mdoc *mdoc)
{
- char *p;
- size_t sz;
- struct mdoc_node *n;
+ char buf[64];
assert(MDOC_ELEM == mdoc->last->type);
assert(MDOC_Os == mdoc->last->tok);
- assert(0 == mdoc->meta.os[0]);
-
- sz = META_OS_SZ;
-
- for (n = mdoc->last->child; n; n = n->next) {
- assert(MDOC_TEXT == n->type);
- p = n->data.text.string;
+ assert(NULL == mdoc->meta.os);
- if ( ! xstrlcat(mdoc->meta.os, p, sz))
- return(mdoc_nerr(mdoc, n, "badly-formed manual system parameter"));
- if ( ! xstrlcat(mdoc->meta.os, " ", sz))
- return(mdoc_nerr(mdoc, n, "badly-formed manual system parameter"));
- }
-
- if (0 == mdoc->meta.os[0])
- (void)xstrlcpy(mdoc->meta.os, "LOCAL", sz);
+ if ( ! xstrlcats(buf, mdoc->last->child, 64))
+ return(mdoc_err(mdoc, "macro parameters too long"));
+ mdoc->meta.os = xstrdup(buf[0] ? buf : "local");
mdoc_msg(mdoc, "parsed operating system: %s", mdoc->meta.os);
mdoc->sec_lastn = mdoc->sec_last = SEC_BODY;
return(1);
@@ -291,9 +280,9 @@ post_dd(struct mdoc *mdoc)
continue;
if ( ! xstrlcat(date, n->data.text.string, sz))
- return(mdoc_nerr(mdoc, n, "badly-formed manual date parameter"));
+ return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
if (n->next && ! xstrlcat(date, " ", sz))
- return(mdoc_nerr(mdoc, n, "badly-formed manual date parameter"));
+ return(mdoc_nerr(mdoc, n, "invalid parameter syntax"));
}
if (mdoc->meta.date && NULL == n) {
@@ -301,7 +290,7 @@ post_dd(struct mdoc *mdoc)
mdoc->meta.date);
return(1);
} else if (n)
- return(mdoc_err(mdoc, "badly-formed manual date"));
+ return(mdoc_err(mdoc, "invalid parameter syntax"));
if ((mdoc->meta.date = mdoc_atotime(date))) {
mdoc_msg(mdoc, "parsed time: %u since epoch",
@@ -309,15 +298,7 @@ post_dd(struct mdoc *mdoc)
return(1);
}
- return(mdoc_err(mdoc, "badly-formed manual date"));
-}
-
-
-int
-mdoc_action_pre(struct mdoc *mdoc, struct mdoc_node *node)
-{
-
- return(1);
+ return(mdoc_err(mdoc, "invalid parameter syntax"));
}
@@ -329,9 +310,7 @@ mdoc_action_post(struct mdoc *mdoc)
return(1);
if (MDOC_ROOT == mdoc->last->type)
return(1);
-
if (NULL == mdoc_actions[mdoc->last->tok].post)
return(1);
- /* TODO: MDOC_Nm... ? */
return((*mdoc_actions[mdoc->last->tok].post)(mdoc));
}
diff --git a/macro.c b/macro.c
index 0b202d64..354fc258 100644
--- a/macro.c
+++ b/macro.c
@@ -577,7 +577,7 @@ macro_text(MACRO_PROT_ARGS)
return(mdoc_perr(mdoc, line, ppos, "too many arguments"));
}
- c = mdoc_elem_alloc(mdoc, line, la, tok, argc, argv);
+ c = mdoc_elem_alloc(mdoc, line, ppos, tok, argc, argv);
if (0 == c) {
mdoc_argv_free(argc, argv);
@@ -629,7 +629,7 @@ macro_text(MACRO_PROT_ARGS)
lastpunct = 1;
} else if (lastpunct) {
c = mdoc_elem_alloc(mdoc, line,
- la, tok, argc, argv);
+ ppos, tok, argc, argv);
if (0 == c) {
mdoc_argv_free(argc, argv);
return(0);
@@ -976,7 +976,7 @@ macro_constant_delimited(MACRO_PROT_ARGS)
return(0);
}
- c = mdoc_elem_alloc(mdoc, line, lastarg, tok, argc, argv);
+ c = mdoc_elem_alloc(mdoc, line, ppos, tok, argc, argv);
mdoc_argv_free(argc, argv);
if (0 == c)
diff --git a/mdoc.3 b/mdoc.3
index a1b468cd..75ac1eea 100644
--- a/mdoc.3
+++ b/mdoc.3
@@ -127,6 +127,12 @@ utility was written by
.\"
.\"
.Sh BUGS
+Both bugs and incompabilities are documented in this section. An
+incompatible macro or behaviour is relative to the default
+.Xr groff 1
+system bundled with
+.Ox .
+.Pp
The
.Sq \&Xc
and
@@ -141,3 +147,7 @@ When
is invoked, whitespace is not stripped around
.Sq \&Ta
or tab-character separators.
+.Pp
+The
+.Sq \&At
+macro only accepts a single parameter.
diff --git a/mdoc.c b/mdoc.c
index 783ea1a2..b4e6114f 100644
--- a/mdoc.c
+++ b/mdoc.c
@@ -140,7 +140,7 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
{ macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */
{ macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */
{ macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */
- { macro_constant, 0 }, /* At */
+ { macro_constant_delimited, 0 }, /* At */
{ macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */
{ macro_scoped, MDOC_EXPLICIT }, /* Bf */
{ macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */
@@ -221,6 +221,19 @@ mdoc_result(struct mdoc *mdoc)
void
+mdoc_meta_free(struct mdoc *mdoc)
+{
+
+ if (mdoc->meta.title)
+ free(mdoc->meta.title);
+ if (mdoc->meta.os)
+ free(mdoc->meta.os);
+ if (mdoc->meta.name)
+ free(mdoc->meta.name);
+}
+
+
+void
mdoc_free(struct mdoc *mdoc)
{
@@ -440,8 +453,6 @@ mdoc_node_append(struct mdoc *mdoc, struct mdoc_node *p)
if ( ! mdoc_valid_pre(mdoc, p))
return(0);
- if ( ! mdoc_action_pre(mdoc, p))
- return(0);
switch (p->type) {
case (MDOC_HEAD):
diff --git a/mdoc.h b/mdoc.h
index 506f3a57..36fc31fd 100644
--- a/mdoc.h
+++ b/mdoc.h
@@ -346,10 +346,9 @@ struct mdoc_meta {
enum mdoc_vol vol;
enum mdoc_arch arch;
time_t date;
-#define META_TITLE_SZ (64)
- char title[META_TITLE_SZ];
-#define META_OS_SZ (64)
- char os[META_OS_SZ];
+ char *title;
+ char *os;
+ char *name;
};
struct mdoc_text {
diff --git a/private.h b/private.h
index 25f96f6d..7a659db1 100644
--- a/private.h
+++ b/private.h
@@ -122,7 +122,7 @@ int mdoc_tokhash_find(const void *, const char *);
void mdoc_tokhash_free(void *);
int mdoc_isdelim(const char *);
int mdoc_iscdelim(char);
-enum mdoc_sec mdoc_atosec(size_t, const char **);
+enum mdoc_sec mdoc_atosec(const char *);
enum mdoc_msec mdoc_atomsec(const char *);
enum mdoc_vol mdoc_atovol(const char *);
enum mdoc_arch mdoc_atoarch(const char *);
@@ -154,6 +154,7 @@ int mdoc_args(struct mdoc *, int,
#define ARGS_DELIM (1 << 1)
#define ARGS_TABSEP (1 << 2)
+int xstrlcats(char *, const struct mdoc_node *, size_t);
int xstrlcat(char *, const char *, size_t);
int xstrlcpy(char *, const char *, size_t);
int xstrcmp(const char *, const char *);
diff --git a/strings.c b/strings.c
index 05015267..1d56ab68 100644
--- a/strings.c
+++ b/strings.c
@@ -81,47 +81,39 @@ mdoc_isdelim(const char *p)
enum mdoc_sec
-mdoc_atosec(size_t sz, const char **p)
+mdoc_atosec(const char *p)
{
- assert(sz > 0);
- if (sz > 2)
- return(SEC_CUSTOM);
- if (sz == 2) {
- if (0 == strcmp(*p, "RETURN") &&
- 0 == strcmp(*(p + 1), "VALUES"))
- return(SEC_RETURN_VALUES);
- if (0 == strcmp(*p, "SEE") &&
- 0 == strcmp(*(p + 1), "ALSO"))
- return(SEC_SEE_ALSO);
- return(SEC_CUSTOM);
- }
-
- if (0 == strcmp(*p, "NAME"))
+ assert(p);
+ if (0 == strcmp(p, "NAME"))
return(SEC_NAME);
- else if (0 == strcmp(*p, "SYNOPSIS"))
+ else if (0 == strcmp(p, "RETURN VALUES"))
+ return(SEC_RETURN_VALUES);
+ else if (0 == strcmp(p, "SEE ALSO"))
+ return(SEC_SEE_ALSO);
+ else if (0 == strcmp(p, "SYNOPSIS"))
return(SEC_SYNOPSIS);
- else if (0 == strcmp(*p, "DESCRIPTION"))
+ else if (0 == strcmp(p, "DESCRIPTION"))
return(SEC_DESCRIPTION);
- else if (0 == strcmp(*p, "ENVIRONMENT"))
+ else if (0 == strcmp(p, "ENVIRONMENT"))
return(SEC_ENVIRONMENT);
- else if (0 == strcmp(*p, "FILES"))
+ else if (0 == strcmp(p, "FILES"))
return(SEC_FILES);
- else if (0 == strcmp(*p, "EXAMPLES"))
+ else if (0 == strcmp(p, "EXAMPLES"))
return(SEC_EXAMPLES);
- else if (0 == strcmp(*p, "DIAGNOSTICS"))
+ else if (0 == strcmp(p, "DIAGNOSTICS"))
return(SEC_DIAGNOSTICS);
- else if (0 == strcmp(*p, "ERRORS"))
+ else if (0 == strcmp(p, "ERRORS"))
return(SEC_ERRORS);
- else if (0 == strcmp(*p, "STANDARDS"))
+ else if (0 == strcmp(p, "STANDARDS"))
return(SEC_STANDARDS);
- else if (0 == strcmp(*p, "HISTORY"))
+ else if (0 == strcmp(p, "HISTORY"))
return(SEC_HISTORY);
- else if (0 == strcmp(*p, "AUTHORS"))
+ else if (0 == strcmp(p, "AUTHORS"))
return(SEC_AUTHORS);
- else if (0 == strcmp(*p, "CAVEATS"))
+ else if (0 == strcmp(p, "CAVEATS"))
return(SEC_CAVEATS);
- else if (0 == strcmp(*p, "BUGS"))
+ else if (0 == strcmp(p, "BUGS"))
return(SEC_BUGS);
return(SEC_CUSTOM);
diff --git a/validate.c b/validate.c
index 98093752..25544b1b 100644
--- a/validate.c
+++ b/validate.c
@@ -26,6 +26,10 @@ typedef int (*v_pre)(struct mdoc *, struct mdoc_node *);
typedef int (*v_post)(struct mdoc *);
+/* FIXME: some sections should only occur in specific msecs. */
+/* FIXME: ignoring Pp. */
+/* FIXME: math symbols. */
+
struct valids {
v_pre *pre;
v_post *post;
@@ -35,6 +39,11 @@ static int pre_check_parent(struct mdoc *, struct mdoc_node *,
int, enum mdoc_type);
static int pre_check_msecs(struct mdoc *, struct mdoc_node *,
int, enum mdoc_msec *);
+static int pre_check_stdarg(struct mdoc *, struct mdoc_node *);
+static int post_check_children_count(struct mdoc *);
+static int post_check_children_lt(struct mdoc *, int);
+static int post_check_children_gt(struct mdoc *, int);
+static int post_check_children_eq(struct mdoc *, int);
static int pre_display(struct mdoc *, struct mdoc_node *);
static int pre_sh(struct mdoc *, struct mdoc_node *);
@@ -45,7 +54,9 @@ static int pre_it(struct mdoc *, struct mdoc_node *);
static int pre_cd(struct mdoc *, struct mdoc_node *);
static int pre_er(struct mdoc *, struct mdoc_node *);
static int pre_ex(struct mdoc *, struct mdoc_node *);
+static int pre_rv(struct mdoc *, struct mdoc_node *);
static int pre_an(struct mdoc *, struct mdoc_node *);
+static int pre_st(struct mdoc *, struct mdoc_node *);
static int pre_prologue(struct mdoc *, struct mdoc_node *);
static int pre_prologue(struct mdoc *, struct mdoc_node *);
static int pre_prologue(struct mdoc *, struct mdoc_node *);
@@ -55,6 +66,7 @@ static int head_warn_ge1(struct mdoc *);
static int head_err_eq0(struct mdoc *);
static int elem_err_eq0(struct mdoc *);
static int elem_err_le1(struct mdoc *);
+static int elem_err_le2(struct mdoc *);
static int elem_err_eq1(struct mdoc *);
static int elem_err_ge1(struct mdoc *);
static int elem_warn_eq0(struct mdoc *);
@@ -67,6 +79,8 @@ static int post_bl(struct mdoc *);
static int post_it(struct mdoc *);
static int post_ex(struct mdoc *);
static int post_an(struct mdoc *);
+static int post_at(struct mdoc *);
+static int post_xr(struct mdoc *);
static v_pre pres_prologue[] = { pre_prologue, NULL };
static v_pre pres_d1[] = { pre_display, NULL };
@@ -78,7 +92,9 @@ static v_pre pres_sh[] = { pre_sh, NULL };
static v_pre pres_cd[] = { pre_cd, NULL };
static v_pre pres_er[] = { pre_er, NULL };
static v_pre pres_ex[] = { pre_ex, NULL };
+static v_pre pres_rv[] = { pre_rv, NULL };
static v_pre pres_an[] = { pre_an, NULL };
+static v_pre pres_st[] = { pre_st, NULL };
static v_post posts_bool[] = { elem_err_eq1, elem_bool, NULL };
static v_post posts_bd[] = { head_err_eq0, body_warn_ge1, NULL };
@@ -96,6 +112,9 @@ static v_post posts_pp[] = { elem_warn_eq0, NULL };
static v_post posts_d1[] = { head_err_ge1, NULL };
static v_post posts_ex[] = { elem_err_le1, post_ex, NULL };
static v_post posts_an[] = { post_an, NULL };
+static v_post posts_at[] = { elem_err_eq1, post_at, NULL };
+static v_post posts_xr[] = { elem_err_ge1, elem_err_le2,
+ post_xr, NULL };
const struct valids mdoc_valids[MDOC_MAX] = {
@@ -103,19 +122,14 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ pres_prologue, posts_text }, /* Dd */
{ pres_prologue, NULL }, /* Dt */
{ pres_prologue, NULL }, /* Os */
- /* FIXME: preceding Pp. */
/* FIXME: NAME section internal ordering. */
{ pres_sh, posts_sh }, /* Sh */
- /* FIXME: preceding Pp. */
{ pres_ss, posts_ss }, /* Ss */
- /* FIXME: proceeding Pp */
{ NULL, posts_pp }, /* Pp */
{ pres_d1, posts_d1 }, /* D1 */
{ pres_d1, posts_d1 }, /* Dl */
- /* FIXME: preceding Pp. */
{ pres_bd, posts_bd }, /* Bd */
{ NULL, NULL }, /* Ed */
- /* FIXME: preceding Pp. */
{ pres_bl, posts_bl }, /* Bl */
{ NULL, NULL }, /* El */
{ pres_it, posts_it }, /* It */
@@ -143,11 +157,11 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, posts_wline }, /* Op */
{ NULL, NULL }, /* Ot */
{ NULL, NULL }, /* Pa */
- { NULL, posts_notext }, /* Rv */ /* FIXME: -std required */
- { NULL, posts_notext }, /* St */ /* FIXME: arg required */
+ { pres_rv, posts_notext }, /* Rv */
+ { pres_st, posts_notext }, /* St */
{ NULL, posts_text }, /* Va */
{ NULL, posts_text }, /* Vt */
- { NULL, NULL }, /* Xr */ /* FIXME: valid arguments */
+ { NULL, posts_xr }, /* Xr */
{ NULL, posts_text }, /* %A */
{ NULL, posts_text }, /* %B */
{ NULL, posts_text }, /* %D */
@@ -162,7 +176,7 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* Ac */
{ NULL, NULL }, /* Ao */
{ NULL, posts_wline }, /* Aq */
- { NULL, NULL }, /* At */ /* FIXME: valid arguments */
+ { NULL, posts_at }, /* At */
{ NULL, NULL }, /* Bc */
{ NULL, NULL }, /* Bf */
{ NULL, NULL }, /* Bo */
@@ -178,7 +192,7 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, posts_text }, /* Em */
{ NULL, NULL }, /* Eo */
{ NULL, NULL }, /* Fx */
- { NULL, posts_text }, /* Ms */ /* FIXME: which symbols? */
+ { NULL, posts_text }, /* Ms */
{ NULL, posts_notext }, /* No */
{ NULL, posts_notext }, /* Ns */
{ NULL, NULL }, /* Nx */
@@ -186,7 +200,7 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* Pc */
{ NULL, NULL }, /* Pf */
{ NULL, NULL }, /* Po */
- { NULL, posts_wline }, /* Pq */ /* FIXME: ignore following Sh/Ss */
+ { NULL, posts_wline }, /* Pq */
{ NULL, NULL }, /* Qc */
{ NULL, posts_wline }, /* Ql */
{ NULL, NULL }, /* Qo */
@@ -217,6 +231,67 @@ const struct valids mdoc_valids[MDOC_MAX] = {
static int
+post_check_children_count(struct mdoc *mdoc)
+{
+ struct mdoc_node *n;
+ int i;
+
+ for (i = 0, n = mdoc->last->child; n; n = n->next, i++)
+ /* Do nothing */ ;
+ return(i);
+}
+
+
+static int
+post_check_children_gt(struct mdoc *mdoc, int sz)
+{
+ int i;
+
+ if ((i = post_check_children_count(mdoc)) > sz)
+ return(1);
+ return(mdoc_err(mdoc, "macro requires more than %d "
+ "parameters (have %d)", sz, i));
+}
+
+
+static int
+post_check_children_eq(struct mdoc *mdoc, int sz)
+{
+ int i;
+
+ if ((i = post_check_children_count(mdoc)) == sz)
+ return(1);
+ return(mdoc_err(mdoc, "macro requires %d parameters "
+ "(have %d)", sz, i));
+}
+
+
+static int
+post_check_children_lt(struct mdoc *mdoc, int sz)
+{
+ int i;
+
+ if ((i = post_check_children_count(mdoc)) < sz)
+ return(1);
+ return(mdoc_err(mdoc, "macro requires less than %d "
+ "parameters (have %d)", sz, i));
+}
+
+
+static int
+pre_check_stdarg(struct mdoc *mdoc, struct mdoc_node *node)
+{
+
+ if (1 == node->data.elem.argc &&
+ MDOC_Std == node->data.elem.argv[0].arg)
+ return(1);
+ return(mdoc_nwarn(mdoc, node, WARN_COMPAT,
+ "macro suggests single `%s' argument",
+ mdoc_argnames[MDOC_Std]));
+}
+
+
+static int
pre_check_msecs(struct mdoc *mdoc, struct mdoc_node *node,
int sz, enum mdoc_msec *msecs)
{
@@ -299,11 +374,16 @@ elem_err_eq1(struct mdoc *mdoc)
{
assert(MDOC_ELEM == mdoc->last->type);
- if (NULL == mdoc->last->child)
- return(mdoc_err(mdoc, "macro expects one parameter"));
- if (mdoc->last->child->next)
- return(mdoc_err(mdoc, "macro expects one parameter"));
- return(1);
+ return(post_check_children_eq(mdoc, 1));
+}
+
+
+static int
+elem_err_le2(struct mdoc *mdoc)
+{
+
+ assert(MDOC_ELEM == mdoc->last->type);
+ return(post_check_children_lt(mdoc, 3));
}
@@ -312,11 +392,7 @@ elem_err_le1(struct mdoc *mdoc)
{
assert(MDOC_ELEM == mdoc->last->type);
- if (NULL == mdoc->last->child)
- return(1);
- if (NULL == mdoc->last->child->next)
- return(1);
- return(mdoc_err(mdoc, "macro expects one or fewer parameters"));
+ return(post_check_children_lt(mdoc, 2));
}
@@ -325,9 +401,7 @@ elem_err_eq0(struct mdoc *mdoc)
{
assert(MDOC_ELEM == mdoc->last->type);
- if (NULL == mdoc->last->child)
- return(1);
- return(mdoc_err(mdoc, "macro expects no parameters"));
+ return(post_check_children_eq(mdoc, 0));
}
@@ -336,9 +410,7 @@ elem_err_ge1(struct mdoc *mdoc)
{
assert(MDOC_ELEM == mdoc->last->type);
- if (mdoc->last->child)
- return(1);
- return(mdoc_err(mdoc, "macro expects one or more parameters"));
+ return(post_check_children_gt(mdoc, 0));
}
@@ -348,10 +420,7 @@ head_err_eq0(struct mdoc *mdoc)
if (MDOC_HEAD != mdoc->last->type)
return(1);
- if (NULL == mdoc->last->child)
- return(1);
- return(mdoc_perr(mdoc, mdoc->last->child->line,
- mdoc->last->child->pos, "macro expects no parameters"));
+ return(post_check_children_eq(mdoc, 0));
}
@@ -373,9 +442,7 @@ head_err_ge1(struct mdoc *mdoc)
if (MDOC_HEAD != mdoc->last->type)
return(1);
- if (mdoc->last->child)
- return(1);
- return(mdoc_err(mdoc, "macro expects one or more parameters"));
+ return(post_check_children_gt(mdoc, 0));
}
@@ -521,8 +588,21 @@ pre_sh(struct mdoc *mdoc, struct mdoc_node *node)
static int
+pre_st(struct mdoc *mdoc, struct mdoc_node *node)
+{
+
+ assert(MDOC_ELEM == node->type);
+ assert(MDOC_St == node->tok);
+ if (1 == node->data.elem.argc)
+ return(1);
+ return(mdoc_nerr(mdoc, node, "macro must have one argument"));
+}
+
+
+static int
pre_an(struct mdoc *mdoc, struct mdoc_node *node)
{
+
assert(MDOC_ELEM == node->type);
assert(MDOC_An == node->tok);
if (1 >= node->data.elem.argc)
@@ -532,31 +612,35 @@ pre_an(struct mdoc *mdoc, struct mdoc_node *node)
static int
+pre_rv(struct mdoc *mdoc, struct mdoc_node *node)
+{
+ enum mdoc_msec msecs[2];
+
+ assert(MDOC_ELEM == node->type);
+ assert(MDOC_Rv == node->tok);
+
+ msecs[0] = MSEC_2;
+ msecs[1] = MSEC_3;
+ if ( ! pre_check_msecs(mdoc, node, 2, msecs))
+ return(0);
+ return(pre_check_stdarg(mdoc, node));
+}
+
+
+static int
pre_ex(struct mdoc *mdoc, struct mdoc_node *node)
{
enum mdoc_msec msecs[3];
assert(MDOC_ELEM == node->type);
+ assert(MDOC_Ex == node->tok);
msecs[0] = MSEC_1;
msecs[1] = MSEC_6;
msecs[2] = MSEC_8;
if ( ! pre_check_msecs(mdoc, node, 3, msecs))
return(0);
-
- if (1 != node->data.elem.argc) {
- if ( ! mdoc_nwarn(mdoc, node, WARN_COMPAT,
- "macro suggests `%s' argument",
- mdoc_argnames[MDOC_Std]))
- return(0);
- return(1);
- }
- if (MDOC_Std != node->data.elem.argv[0].arg)
- if ( ! mdoc_nwarn(mdoc, node, WARN_COMPAT,
- "macro suggests `%s' argument",
- mdoc_argnames[MDOC_Std]))
- return(0);
- return(1);
+ return(pre_check_stdarg(mdoc, node));
}
@@ -602,15 +686,15 @@ pre_prologue(struct mdoc *mdoc, struct mdoc_node *node)
switch (node->tok) {
case (MDOC_Os):
- if (mdoc->meta.title[0] && mdoc->meta.date)
+ if (mdoc->meta.title && mdoc->meta.date)
break;
return(mdoc_nerr(mdoc, node, "prologue macro out-of-order"));
case (MDOC_Dt):
- if (0 == mdoc->meta.title[0] && mdoc->meta.date)
+ if (NULL == mdoc->meta.title && mdoc->meta.date)
break;
return(mdoc_nerr(mdoc, node, "prologue macro out-of-order"));
case (MDOC_Dd):
- if (0 == mdoc->meta.title[0] && 0 == mdoc->meta.date)
+ if (NULL == mdoc->meta.title && 0 == mdoc->meta.date)
break;
return(mdoc_nerr(mdoc, node, "prologue macro out-of-order"));
default:
@@ -622,7 +706,7 @@ pre_prologue(struct mdoc *mdoc, struct mdoc_node *node)
switch (node->tok) {
case (MDOC_Os):
- if (0 == mdoc->meta.os[0])
+ if (NULL == mdoc->meta.os)
return(1);
break;
case (MDOC_Dd):
@@ -630,7 +714,7 @@ pre_prologue(struct mdoc *mdoc, struct mdoc_node *node)
return(1);
break;
case (MDOC_Dt):
- if (0 == mdoc->meta.title[0])
+ if (NULL == mdoc->meta.title)
return(1);
break;
default:
@@ -643,6 +727,40 @@ pre_prologue(struct mdoc *mdoc, struct mdoc_node *node)
static int
+post_xr(struct mdoc *mdoc)
+{
+ struct mdoc_node *n;
+
+ assert(MDOC_ELEM == mdoc->last->type);
+ assert(MDOC_Xr == mdoc->last->tok);
+ assert(mdoc->last->child);
+ assert(MDOC_TEXT == mdoc->last->child->type);
+
+ if (NULL == (n = mdoc->last->child->next))
+ return(1);
+ assert(MDOC_TEXT == n->type);
+ if (MSEC_DEFAULT != mdoc_atomsec(n->data.text.string))
+ return(1);
+ return(mdoc_nerr(mdoc, n, "invalid manual section"));
+}
+
+
+static int
+post_at(struct mdoc *mdoc)
+{
+
+ assert(MDOC_ELEM == mdoc->last->type);
+ assert(MDOC_At == mdoc->last->tok);
+ assert(mdoc->last->child);
+ assert(MDOC_TEXT == mdoc->last->child->type);
+
+ if (ATT_DEFAULT != mdoc_atoatt(mdoc->last->child->data.text.string))
+ return(1);
+ return(mdoc_err(mdoc, "macro expects a valid AT&T version symbol"));
+}
+
+
+static int
post_an(struct mdoc *mdoc)
{
@@ -848,32 +966,20 @@ elem_bool(struct mdoc *mdoc)
static int
post_sh(struct mdoc *mdoc)
{
+ char buf[64];
enum mdoc_sec sec;
- int i;
- struct mdoc_node *n;
- char *args[MDOC_LINEARG_MAX];
if (MDOC_HEAD != mdoc->last->type)
return(1);
-
assert(MDOC_Sh == mdoc->last->tok);
- n = mdoc->last->child;
- assert(n);
+ if ( ! xstrlcats(buf, mdoc->last->child, 64))
+ return(mdoc_err(mdoc, "macro parameters too long"));
- for (i = 0; n && i < MDOC_LINEARG_MAX; n = n->next, i++) {
- assert(MDOC_TEXT == n->type);
- assert(NULL == n->child);
- assert(n->data.text.string);
- args[i] = n->data.text.string;
- }
-
- sec = mdoc_atosec((size_t)i, (const char **)args);
- if (SEC_CUSTOM == sec)
+ if (SEC_CUSTOM == (sec = mdoc_atosec(buf)))
return(1);
if (sec > mdoc->sec_lastn)
return(1);
-
if (sec == mdoc->sec_lastn)
return(mdoc_warn(mdoc, WARN_SYNTAX, "section repeated"));
return(mdoc_warn(mdoc, WARN_SYNTAX, "section out of conventional order"));
diff --git a/xstd.c b/xstd.c
index f485b737..dee1ff35 100644
--- a/xstd.c
+++ b/xstd.c
@@ -16,6 +16,7 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
+#include <assert.h>
#include <err.h>
#include <stdlib.h>
#include <string.h>
@@ -75,6 +76,30 @@ xstrdup(const char *p)
}
+int
+xstrlcats(char *buf, const struct mdoc_node *n, size_t sz)
+{
+ char *p;
+
+ assert(sz > 0);
+ assert(buf);
+ *buf = 0;
+
+ for ( ; n; n = n->next) {
+ assert(MDOC_TEXT == n->type);
+ p = n->data.text.string;
+ if ( ! xstrlcat(buf, p, sz))
+ return(0);
+ if (n->next && ! xstrlcat(buf, " ", sz))
+ return(0);
+ }
+
+ return(1);
+}
+
+
+
+
#ifdef __linux__
/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */