summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2009-06-17 10:53:32 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2009-06-17 10:53:32 +0000
commit08234e1261b84672fa81eab4dd6640e9b55e2f63 (patch)
tree3321dec2f6157aa567b7f0845a6e86753b314ff5
parentaa8ebdeebdc3218708b91a72e0b499258a3e5cef (diff)
downloadmandoc-08234e1261b84672fa81eab4dd6640e9b55e2f63.tar.gz
Section orders are more elegantly handled (MDOC_PBODY is a flag).
Cleaned up string->enum conversion for section lookup.
-rw-r--r--libmdoc.h5
-rw-r--r--mdoc.c34
-rw-r--r--mdoc.h64
-rw-r--r--mdoc_action.c2
-rw-r--r--mdoc_strings.c60
-rw-r--r--mdoc_validate.c49
6 files changed, 103 insertions, 111 deletions
diff --git a/libmdoc.h b/libmdoc.h
index 7c3b9f35..f402ac13 100644
--- a/libmdoc.h
+++ b/libmdoc.h
@@ -29,8 +29,9 @@ struct mdoc {
struct mdoc_cb cb;
void *htab;
int flags;
-#define MDOC_HALT (1 << 0)
-#define MDOC_LITERAL (1 << 1)
+#define MDOC_HALT (1 << 0) /* Error in parse. Halt. */
+#define MDOC_LITERAL (1 << 1) /* In a literal scope. */
+#define MDOC_PBODY (1 << 2) /* In the document body. */
int pflags;
enum mdoc_next next;
struct mdoc_node *last;
diff --git a/mdoc.c b/mdoc.c
index 60b22717..f2ac080d 100644
--- a/mdoc.c
+++ b/mdoc.c
@@ -113,6 +113,9 @@ mdoc_meta(const struct mdoc *m)
}
+/*
+ * Frees volatile resources (parse tree, meta-data, fields).
+ */
static void
mdoc_free1(struct mdoc *mdoc)
{
@@ -132,13 +135,16 @@ mdoc_free1(struct mdoc *mdoc)
}
+/*
+ * Allocate all volatile resources (parse tree, meta-data, fields).
+ */
static int
mdoc_alloc1(struct mdoc *mdoc)
{
bzero(&mdoc->meta, sizeof(struct mdoc_meta));
mdoc->flags = 0;
- mdoc->lastnamed = mdoc->lastsec = 0;
+ mdoc->lastnamed = mdoc->lastsec = SEC_NONE;
mdoc->last = calloc(1, sizeof(struct mdoc_node));
if (NULL == mdoc->last)
return(0);
@@ -151,9 +157,10 @@ mdoc_alloc1(struct mdoc *mdoc)
/*
- * Free up all resources contributed by a parse: the node tree,
- * meta-data and so on. Then reallocate the root node for another
- * parse.
+ * Free up volatile resources (see mdoc_free1()) then re-initialises the
+ * data with mdoc_alloc1(). After invocation, parse data has been reset
+ * and the parser is ready for re-invocation on a new tree; however,
+ * cross-parse non-volatile data is kept intact.
*/
int
mdoc_reset(struct mdoc *mdoc)
@@ -165,7 +172,8 @@ mdoc_reset(struct mdoc *mdoc)
/*
- * Completely free up all resources.
+ * Completely free up all volatile and non-volatile parse resources.
+ * After invocation, the pointer is no longer usable.
*/
void
mdoc_free(struct mdoc *mdoc)
@@ -178,6 +186,9 @@ mdoc_free(struct mdoc *mdoc)
}
+/*
+ * Allocate volatile and non-volatile parse resources.
+ */
struct mdoc *
mdoc_alloc(void *data, int pflags, const struct mdoc_cb *cb)
{
@@ -204,7 +215,7 @@ mdoc_alloc(void *data, int pflags, const struct mdoc_cb *cb)
/*
* Climb back up the parse tree, validating open scopes. Mostly calls
- * through to macro_end in macro.c.
+ * through to macro_end() in macro.c.
*/
int
mdoc_endparse(struct mdoc *m)
@@ -221,7 +232,7 @@ mdoc_endparse(struct mdoc *m)
/*
* Main parse routine. Parses a single line -- really just hands off to
- * the macro or text parser.
+ * the macro (parsemacro()) or text parser (parsetext()).
*/
int
mdoc_parseln(struct mdoc *m, int ln, char *buf)
@@ -360,14 +371,11 @@ mdoc_macro(struct mdoc *m, int tok,
int ln, int pp, int *pos, char *buf)
{
- /* FIXME - these should happen during validation. */
-
if (MDOC_PROLOGUE & mdoc_macros[tok].flags &&
- SEC_PROLOGUE != m->lastnamed)
+ MDOC_PBODY & m->flags)
return(perr(m, ln, pp, EPROLBODY));
-
if ( ! (MDOC_PROLOGUE & mdoc_macros[tok].flags) &&
- SEC_PROLOGUE == m->lastnamed)
+ ! (MDOC_PBODY & m->flags))
return(perr(m, ln, pp, EBODYPROL));
if (1 != pp && ! (MDOC_CALLABLE & mdoc_macros[tok].flags))
@@ -618,7 +626,7 @@ static int
parsetext(struct mdoc *m, int line, char *buf)
{
- if (SEC_PROLOGUE == m->lastnamed)
+ if (SEC_NONE == m->lastnamed)
return(perr(m, line, 0, ETEXTPROL));
if (0 == buf[0] && ! (MDOC_LITERAL & m->flags))
diff --git a/mdoc.h b/mdoc.h
index 0f8a0cb1..b053e533 100644
--- a/mdoc.h
+++ b/mdoc.h
@@ -198,27 +198,26 @@ enum mdoc_type {
/* Section (named/unnamed) of `Sh'. */
enum mdoc_sec {
- SEC_PROLOGUE = 0,
- SEC_BODY = 1,
- SEC_NAME = 2,
- SEC_LIBRARY = 3,
- SEC_SYNOPSIS = 4,
- SEC_DESCRIPTION = 5,
- SEC_IMPLEMENTATION = 6,
- SEC_RETURN_VALUES = 7,
- SEC_ENVIRONMENT = 8,
- SEC_FILES = 9,
- SEC_EXAMPLES = 10,
- SEC_DIAGNOSTICS = 11,
- SEC_COMPATIBILITY = 12,
- SEC_ERRORS = 13,
- SEC_SEE_ALSO = 14,
- SEC_STANDARDS = 15,
- SEC_HISTORY = 16,
- SEC_AUTHORS = 17,
- SEC_CAVEATS = 18,
- SEC_BUGS = 19,
- SEC_CUSTOM
+ SEC_NONE, /* No section, yet. */
+ SEC_NAME,
+ SEC_LIBRARY,
+ SEC_SYNOPSIS,
+ SEC_DESCRIPTION,
+ SEC_IMPLEMENTATION,
+ SEC_RETURN_VALUES,
+ SEC_ENVIRONMENT,
+ SEC_FILES,
+ SEC_EXAMPLES,
+ SEC_DIAGNOSTICS,
+ SEC_COMPATIBILITY,
+ SEC_ERRORS,
+ SEC_SEE_ALSO,
+ SEC_STANDARDS,
+ SEC_HISTORY,
+ SEC_AUTHORS,
+ SEC_CAVEATS,
+ SEC_BUGS,
+ SEC_CUSTOM /* User-defined. */
};
/* Information from prologue. */
@@ -276,45 +275,32 @@ struct mdoc_node {
#define MDOC_IGN_CHARS (1 << 3) /* Ignore disallowed chars. */
/* Call-backs for parse messages. */
+/* FIXME: unify somehow with man_cb. */
struct mdoc_cb {
int (*mdoc_err)(void *, int, int, const char *);
int (*mdoc_warn)(void *, int, int,
enum mdoc_warn, const char *);
};
-/* Global table of macro names (`Bd', `Ed', etc.). */
-extern const char *const *mdoc_macronames;
+/* See mdoc.3 for documentation. */
-/* Global table of argument names (`column', `tag', etc.). */
+extern const char *const *mdoc_macronames;
extern const char *const *mdoc_argnames;
__BEGIN_DECLS
struct mdoc;
-/* Free memory allocated with mdoc_alloc. */
-void mdoc_free(struct mdoc *);
+/* See mdoc.3 for documentation. */
-/* Allocate a new parser instance. */
+void mdoc_free(struct mdoc *);
struct mdoc *mdoc_alloc(void *, int, const struct mdoc_cb *);
-
-/* Gets system ready for another parse. */
int mdoc_reset(struct mdoc *);
-
-/* Parse a single line in a stream (boolean retval). */
int mdoc_parseln(struct mdoc *, int, char *buf);
-
-/* Get result first node (after mdoc_endparse!). */
const struct mdoc_node *mdoc_node(const struct mdoc *);
-
-/* Get result meta-information (after mdoc_endparse!). */
const struct mdoc_meta *mdoc_meta(const struct mdoc *);
-
-/* Signal end of parse sequence (boolean retval). */
int mdoc_endparse(struct mdoc *);
-/* The following are utility functions. */
-
const char *mdoc_a2att(const char *);
const char *mdoc_a2lib(const char *);
const char *mdoc_a2st(const char *);
diff --git a/mdoc_action.c b/mdoc_action.c
index 4a314905..0b7face0 100644
--- a/mdoc_action.c
+++ b/mdoc_action.c
@@ -515,8 +515,8 @@ post_os(POST_ARGS)
if (NULL == (m->meta.os = strdup(buf)))
return(verr(m, EMALLOC));
- m->lastnamed = m->lastsec = SEC_BODY;
+ m->flags |= MDOC_PBODY;
return(post_prol(m));
}
diff --git a/mdoc_strings.c b/mdoc_strings.c
index d1781a98..25711de7 100644
--- a/mdoc_strings.c
+++ b/mdoc_strings.c
@@ -24,36 +24,34 @@
#include "libmdoc.h"
+/* FIXME: this file is poorly named. */
+
struct mdoc_secname {
const char *name; /* Name of section. */
- int flag;
-#define MSECNAME_META (1 << 0)/* Logical section (not real). */
+ enum mdoc_sec sec; /* Corresponding section. */
};
-/* Section names corresponding to mdoc_sec. */
+#define SECNAME_MAX (18)
-static const struct mdoc_secname secnames[] = {
- { "PROLOGUE", MSECNAME_META },
- { "BODY", MSECNAME_META },
- { "NAME", 0 },
- { "LIBRARY", 0 },
- { "SYNOPSIS", 0 },
- { "DESCRIPTION", 0 },
- { "IMPLEMENTATION NOTES", 0 },
- { "RETURN VALUES", 0 },
- { "ENVIRONMENT", 0 },
- { "FILES", 0 },
- { "EXAMPLES", 0 },
- { "DIAGNOSTICS", 0 },
- { "COMPATIBILITY", 0 },
- { "ERRORS", 0 },
- { "SEE ALSO", 0 },
- { "STANDARDS", 0 },
- { "HISTORY", 0 },
- { "AUTHORS", 0 },
- { "CAVEATS", 0 },
- { "BUGS", 0 },
- { NULL, 0 }
+static const struct mdoc_secname secnames[SECNAME_MAX] = {
+ { "NAME", SEC_NAME },
+ { "LIBRARY", SEC_LIBRARY },
+ { "SYNOPSIS", SEC_SYNOPSIS },
+ { "DESCRIPTION", SEC_DESCRIPTION },
+ { "IMPLEMENTATION NOTES", SEC_IMPLEMENTATION },
+ { "RETURN VALUES", SEC_RETURN_VALUES },
+ { "ENVIRONMENT", SEC_ENVIRONMENT },
+ { "FILES", SEC_FILES },
+ { "EXAMPLES", SEC_EXAMPLES },
+ { "DIAGNOSTICS", SEC_DIAGNOSTICS },
+ { "COMPATIBILITY", SEC_COMPATIBILITY },
+ { "ERRORS", SEC_ERRORS },
+ { "SEE ALSO", SEC_SEE_ALSO },
+ { "STANDARDS", SEC_STANDARDS },
+ { "HISTORY", SEC_HISTORY },
+ { "AUTHORS", SEC_AUTHORS },
+ { "CAVEATS", SEC_CAVEATS },
+ { "BUGS", SEC_BUGS },
};
#ifdef __linux__
@@ -191,13 +189,11 @@ mdoc_isdelim(const char *p)
enum mdoc_sec
mdoc_atosec(const char *p)
{
- const struct mdoc_secname *n;
- int i;
+ int i;
- for (i = 0, n = secnames; n->name; n++, i++)
- if ( ! (n->flag & MSECNAME_META))
- if (0 == strcmp(p, n->name))
- return((enum mdoc_sec)i);
+ for (i = 0; i < SECNAME_MAX; i++)
+ if (0 == strcmp(p, secnames[i].name))
+ return(secnames[i].sec);
return(SEC_CUSTOM);
}
@@ -209,7 +205,7 @@ mdoc_atotime(const char *p)
struct tm tm;
char *pp;
- (void)memset(&tm, 0, sizeof(struct tm));
+ bzero(&tm, sizeof(struct tm));
if (0 == strcmp(p, "$" "Mdocdate$"))
return(time(NULL));
diff --git a/mdoc_validate.c b/mdoc_validate.c
index ac42fe45..edc03a41 100644
--- a/mdoc_validate.c
+++ b/mdoc_validate.c
@@ -42,6 +42,7 @@ enum merr {
ELISTTYPE,
EDISPTYPE,
EMULTIDISP,
+ ESECNAME,
EMULTILIST,
EARGREP,
EBOOL,
@@ -116,7 +117,6 @@ static int pre_fd(PRE_ARGS);
static int pre_it(PRE_ARGS);
static int pre_lb(PRE_ARGS);
static int pre_os(PRE_ARGS);
-static int pre_prologue(PRE_ARGS);
static int pre_rv(PRE_ARGS);
static int pre_sh(PRE_ARGS);
static int pre_ss(PRE_ARGS);
@@ -155,15 +155,15 @@ static v_pre pres_an[] = { pre_an, NULL };
static v_pre pres_bd[] = { pre_display, pre_bd, NULL };
static v_pre pres_bl[] = { pre_bl, NULL };
static v_pre pres_cd[] = { pre_cd, NULL };
-static v_pre pres_dd[] = { pre_prologue, pre_dd, NULL };
+static v_pre pres_dd[] = { pre_dd, NULL };
static v_pre pres_d1[] = { pre_display, NULL };
-static v_pre pres_dt[] = { pre_prologue, pre_dt, NULL };
+static v_pre pres_dt[] = { pre_dt, NULL };
static v_pre pres_er[] = { pre_er, NULL };
static v_pre pres_ex[] = { pre_ex, NULL };
static v_pre pres_fd[] = { pre_fd, NULL };
static v_pre pres_it[] = { pre_it, NULL };
static v_pre pres_lb[] = { pre_lb, NULL };
-static v_pre pres_os[] = { pre_prologue, pre_os, NULL };
+static v_pre pres_os[] = { pre_os, NULL };
static v_pre pres_rv[] = { pre_rv, NULL };
static v_pre pres_sh[] = { pre_sh, NULL };
static v_pre pres_ss[] = { pre_ss, NULL };
@@ -413,6 +413,9 @@ perr(struct mdoc *m, int line, int pos, enum merr type)
case (EDISPTYPE):
p = "missing display type";
break;
+ case (ESECNAME):
+ p = "the NAME section must come first";
+ break;
case (ELINE):
p = "expected line arguments";
break;
@@ -1019,14 +1022,6 @@ pre_cd(PRE_ARGS)
static int
-pre_prologue(PRE_ARGS)
-{
-
- return(check_sec(mdoc, n, SEC_PROLOGUE, SEC_CUSTOM));
-}
-
-
-static int
pre_dt(PRE_ARGS)
{
@@ -1077,8 +1072,12 @@ post_bf(POST_ARGS)
if (MDOC_BLOCK != mdoc->last->type)
return(1);
+ /* FIXME: clean-up .*/
+
head = mdoc->last->head;
+ if (mdoc->last->args && head->child)
+
if (NULL == mdoc->last->args) {
if (NULL == head->child ||
MDOC_TEXT != head->child->type)
@@ -1313,7 +1312,7 @@ post_root(POST_ARGS)
if (NULL == mdoc->first->child)
return(verr(mdoc, ENODATA));
- if (SEC_PROLOGUE == mdoc->lastnamed)
+ if ( ! (MDOC_PBODY & mdoc->flags))
return(verr(mdoc, ENOPROLOGUE));
if (MDOC_BLOCK != mdoc->first->child->type)
@@ -1394,13 +1393,12 @@ post_sh_head(POST_ARGS)
* certain manual sections.
*/
- assert(MDOC_Sh == mdoc->last->tok);
-
- /* This is just concat() inlined, which is irritating. */
-
buf[0] = 0;
+
for (n = mdoc->last->child; n; n = n->next) {
+ /* XXX - copied from compact(). */
assert(MDOC_TEXT == n->type);
+
if (strlcat(buf, n->string, 64) >= 64)
return(nerr(mdoc, n, ETOOLONG));
if (NULL == n->next)
@@ -1411,21 +1409,24 @@ post_sh_head(POST_ARGS)
sec = mdoc_atosec(buf);
- /* The NAME section should always be first. */
+ /*
+ * Check: NAME should always be first, CUSTOM has no roles,
+ * non-CUSTOM has a conventional order to be followed.
+ */
- if (SEC_BODY == mdoc->lastnamed && SEC_NAME != sec)
- return(vwarn(mdoc, WSECOOO));
+ if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed)
+ return(verr(mdoc, ESECNAME));
if (SEC_CUSTOM == sec)
return(1);
-
- /* Check for repeated or out-of-order sections. */
-
if (sec == mdoc->lastnamed)
return(vwarn(mdoc, WSECREP));
if (sec < mdoc->lastnamed)
return(vwarn(mdoc, WSECOOO));
- /* Check particular section/manual section conventions. */
+ /*
+ * Check particular section/manual conventions. LIBRARY can
+ * only occur in msec 2, 3 (TODO: are there more of these?).
+ */
switch (sec) {
case (SEC_LIBRARY):