]> git.cameronkatri.com Git - mandoc.git/commitdiff
Prologue Dd and Dt macros.
authorKristaps Dzonsons <kristaps@bsd.lv>
Wed, 17 Dec 2008 17:18:38 +0000 (17:18 +0000)
committerKristaps Dzonsons <kristaps@bsd.lv>
Wed, 17 Dec 2008 17:18:38 +0000 (17:18 +0000)
macro.c
mdoc.c
mdoc.h
mdocml.c
private.h
strings.c

diff --git a/macro.c b/macro.c
index 6b8e53654d1ecda0a84b0d9eda95c0f0d153c6e6..16d74306c9dae9b6ef927077b4e2ca11c8979f17 100644 (file)
--- a/macro.c
+++ b/macro.c
@@ -1,4 +1,4 @@
-/* $Id: macro.c,v 1.4 2008/12/15 03:13:01 kristaps Exp $ */
+/* $Id: macro.c,v 1.5 2008/12/17 17:18:38 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
 #include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "private.h"
 
 #define        _CC(p)  ((const char **)p)
 
+static int       xstrlcat(char *, const char *, size_t);
+static int       xstrlcpy(char *, const char *, size_t);
+static int       xstrcmp(const char *, const char *);
 static int       append_text(struct mdoc *, int, 
                        int, int, char *[]);
 static int       append_scoped(struct mdoc *, int, 
@@ -81,10 +85,25 @@ static int
 append_scoped(struct mdoc *mdoc, int tok, 
                int pos, int sz, char *args[])
 {
+       enum mdoc_sec    sec;
+
+       if (0 == sz) 
+               return(mdoc_err(mdoc, tok, pos, ERR_ARGS_GE1));
 
        switch (tok) {
         /* ======= ADD MORE MACRO CHECKS BELOW. ======= */
        case (MDOC_Sh):
+               sec = mdoc_atosec((size_t)sz, _CC(args));
+               if (SEC_CUSTOM != sec && sec < mdoc->sec_lastn)
+                       if ( ! mdoc_warn(mdoc, tok, pos, WARN_SEC_OO))
+                               return(0);
+
+               if (SEC_BODY == mdoc->sec_last && SEC_NAME != sec)
+                       return(mdoc_err(mdoc, tok, pos, ERR_SEC_NAME));
+
+               if (SEC_CUSTOM != sec)
+                       mdoc->sec_lastn = sec;
+               mdoc->sec_last = sec;
                break;
        case (MDOC_Ss):
                break;
@@ -166,7 +185,7 @@ append_text(struct mdoc *mdoc, int tok,
 
 
 int
-macro_text(struct mdoc *mdoc, int tok, int ppos, int *pos, char *buf)
+macro_text(MACRO_PROT_ARGS)
 {
        int               lastarg, c, lasttok, lastpunct, j;
        char             *args[MDOC_LINEARG_MAX], *p;
@@ -175,6 +194,9 @@ macro_text(struct mdoc *mdoc, int tok, int ppos, int *pos, char *buf)
        lastpunct = 0;
        j = 0;
 
+       if (SEC_PROLOGUE == mdoc->sec_lastn)
+               return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
+
 again:
 
        lastarg = *pos;
@@ -224,19 +246,131 @@ again:
 
 
 int
-macro_scoped_implicit(struct mdoc *mdoc, 
-               int tok, int ppos, int *pos, char *buf)
+macro_prologue_dtitle(MACRO_PROT_ARGS)
+{
+       int               c, lastarg, j;
+       char             *args[MDOC_LINEARG_MAX];
+
+       if (SEC_PROLOGUE != mdoc->sec_lastn)
+               return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE));
+       if (0 == mdoc->meta.date)
+               return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO));
+       if (mdoc->meta.title[0])
+               return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP));
+
+       j = -1;
+
+again:
+       lastarg = *pos;
+       c = args_next(mdoc, tok, pos, buf, &args[++j]);
+
+       if (0 == c) {
+               mdoc->sec_lastn = mdoc->sec_last = SEC_BODY; /* FIXME */
+               if (mdoc->meta.title)
+                       return(1);
+               if ( ! mdoc_warn(mdoc, tok, ppos, WARN_ARGS_GE1))
+                       return(0);
+               (void)xstrlcpy(mdoc->meta.title, 
+                               "UNTITLED", META_TITLE_SZ);
+               return(1);
+       } else if (-1 == c)
+               return(0);
+       
+       if (MDOC_MAX != mdoc_find(mdoc, args[j]) && ! mdoc_warn
+                       (mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
+               return(0);
+
+       if (0 == j) {
+               if (xstrlcpy(mdoc->meta.title, args[0], META_TITLE_SZ))
+                       goto again;
+               return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGS));
+
+       } else if (1 == j) {
+               mdoc->meta.msec = mdoc_atomsec(args[1]);
+               if (MSEC_DEFAULT != mdoc->meta.msec)
+                       goto again;
+               return(mdoc_err(mdoc, tok, -1, ERR_SYNTAX_ARGS));
+
+       } else if (2 == j) {
+               mdoc->meta.vol = mdoc_atovol(args[2]);
+               if (VOL_DEFAULT != mdoc->meta.vol)
+                       goto again;
+               mdoc->meta.arch = mdoc_atoarch(args[2]);
+               if (ARCH_DEFAULT != mdoc->meta.arch)
+                       goto again;
+               return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGS));
+       }
+
+       return(mdoc_err(mdoc, tok, lastarg, ERR_ARGS_MANY));
+}
+
+
+int
+macro_prologue_ddate(MACRO_PROT_ARGS)
+{
+       int               c, lastarg, j;
+       char             *args[MDOC_LINEARG_MAX], date[64];
+
+       if (SEC_PROLOGUE != mdoc->sec_lastn)
+               return(mdoc_err(mdoc, tok, ppos, ERR_SEC_NPROLOGUE));
+       if (mdoc->meta.title[0])
+               return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_OO));
+       if (mdoc->meta.date)
+               return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE_REP));
+
+       j = -1;
+       date[0] = 0;
+
+again:
+
+       lastarg = *pos;
+       c = args_next(mdoc, tok, pos, buf, &args[++j]);
+       if (0 == c) {
+               if (mdoc->meta.date)
+                       return(1);
+               mdoc->meta.date = mdoc_atotime(date);
+               if (mdoc->meta.date)
+                       return(1);
+               return(mdoc_err(mdoc, tok, ppos, ERR_SYNTAX_ARGS));
+       } else if (-1 == c) 
+               return(0);
+       
+       if (MDOC_MAX != mdoc_find(mdoc, args[j]) && ! mdoc_warn
+                       (mdoc, tok, lastarg, WARN_SYNTAX_MACLIKE))
+               return(0);
+       
+       if (0 == j) {
+               if (xstrcmp("$Mdocdate: December 17 2008 $", args[j])) {
+                       mdoc->meta.date = time(NULL);
+                       goto again;
+               } else if (xstrcmp("$Mdocdate:", args[j])) 
+                       goto again;
+       } else if (4 == j)
+               if ( ! xstrcmp("$", args[j]))
+                       goto again;
+
+       if ( ! xstrlcat(date, args[j], sizeof(date)))
+               return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGS));
+       if ( ! xstrlcat(date, " ", sizeof(date)))
+               return(mdoc_err(mdoc, tok, lastarg, ERR_SYNTAX_ARGS));
+
+       goto again;
+       /* NOTREACHED */
+}
+
+
+int
+macro_scoped_implicit(MACRO_PROT_ARGS)
 {
        int               t, c, lastarg, j;
        char             *args[MDOC_LINEARG_MAX];
        struct mdoc_node *n;
 
-       /*
-        * Look for an implicit parent.
-        */
-
        assert( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags));
 
+       if (SEC_PROLOGUE == mdoc->sec_lastn)
+               return(mdoc_err(mdoc, tok, ppos, ERR_SEC_PROLOGUE));
+
        /* LINTED */
        for (n = mdoc->last; n; n = n->parent) {
                if (MDOC_BLOCK != n->type) 
@@ -281,3 +415,27 @@ again:
 
        /* NOTREACHED */
 }
+
+
+static int
+xstrcmp(const char *p1, const char *p2)
+{
+
+       return(0 == strcmp(p1, p2));
+}
+
+
+static int
+xstrlcat(char *dst, const char *src, size_t sz)
+{
+
+       return(strlcat(dst, src, sz) < sz);
+}
+
+
+static int
+xstrlcpy(char *dst, const char *src, size_t sz)
+{
+
+       return(strlcpy(dst, src, sz) < sz);
+}
diff --git a/mdoc.c b/mdoc.c
index 4bdc32f0c2d603a87869b544ac653f412ca99d16..1fcdc833bb6a961aeb3517fc9f24ca3a14cbdb18 100644 (file)
--- a/mdoc.c
+++ b/mdoc.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc.c,v 1.2 2008/12/15 02:23:12 kristaps Exp $ */
+/* $Id: mdoc.c,v 1.3 2008/12/17 17:18:38 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
 
 #include "private.h"
 
-extern int     macro_text(struct mdoc *, int, int, int *, char *);
-extern int     macro_scoped_implicit(struct mdoc *, 
-                       int, int, int *, char *);
-
 const  char *const __mdoc_macronames[MDOC_MAX] = {              
        "\\\"",         "Dd",           "Dt",           "Os",
        "Sh",           "Ss",           "Pp",           "D1",
@@ -88,8 +84,8 @@ const char *const __mdoc_argnames[MDOC_ARG_MAX] = {
 
 const  struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
        { NULL, 0 }, /* \" */
-       { NULL, 0 }, /* Dd */
-       { NULL, 0 }, /* Dt */
+       { macro_prologue_ddate, 0 }, /* Dd */
+       { macro_prologue_dtitle, 0 }, /* Dt */
        { NULL, 0 }, /* Os */
        { macro_scoped_implicit, 0 }, /* Sh */
        { macro_scoped_implicit, 0 }, /* Ss */ 
@@ -310,12 +306,7 @@ mdoc_parseln(struct mdoc *mdoc, char *buf)
        while (buf[i] && isspace(buf[i]))
                i++;
 
-       if (NULL == (mdoc_macros[c].fp)) {
-               (void)mdoc_err(mdoc, c, 1, ERR_MACRO_NOTSUP);
-               return(0);
-       } 
-
-       return((*mdoc_macros[c].fp)(mdoc, c, 1, &i, buf));
+       return(mdoc_macro(mdoc, c, 1, &i, buf));
 }
 
 
@@ -363,7 +354,9 @@ mdoc_macro(struct mdoc *mdoc, int tok, int ppos, int *pos, char *buf)
        if (NULL == (mdoc_macros[tok].fp)) {
                (void)mdoc_err(mdoc, tok, ppos, ERR_MACRO_NOTSUP);
                return(0);
-       } else if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
+       }
+
+       if (1 != ppos && ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
                (void)mdoc_err(mdoc, tok, ppos, ERR_MACRO_NOTCALL);
                return(0);
        }
diff --git a/mdoc.h b/mdoc.h
index 14478cf49814a31323ffdb6fa9ee9b10eaec0299..532fa9c6556d4bfb2c45c4434fcb4339cc3730c3 100644 (file)
--- a/mdoc.h
+++ b/mdoc.h
@@ -1,4 +1,4 @@
-/* $Id: mdoc.h,v 1.2 2008/12/15 03:13:01 kristaps Exp $ */
+/* $Id: mdoc.h,v 1.3 2008/12/17 17:18:38 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
 enum   mdoc_err {
        ERR_SYNTAX_QUOTE,
        ERR_SYNTAX_WS,
+       ERR_SYNTAX_ARGS,
        ERR_MACRO_NOTSUP,
        ERR_MACRO_NOTCALL,
        ERR_SCOPE_BREAK,
-       ERR_ARGS_GE1
+       ERR_SEC_PROLOGUE,
+       ERR_SEC_NPROLOGUE,
+       ERR_SEC_PROLOGUE_OO,
+       ERR_SEC_PROLOGUE_REP,
+       ERR_SEC_NAME,
+       ERR_ARGS_GE1,
+       ERR_ARGS_MANY
 };
 
 enum   mdoc_warn {
        WARN_SYNTAX_WS_EOLN,
        WARN_SYNTAX_MACLIKE,
+       WARN_SEC_OO,
        WARN_ARGS_GE1
 };
 
@@ -221,6 +229,7 @@ enum        mdoc_type {
 };
 
 enum   mdoc_msec {
+       MSEC_DEFAULT = 0,
        MSEC_1,
        MSEC_2,
        MSEC_3,
@@ -238,12 +247,12 @@ enum      mdoc_msec {
        MSEC_n,
        MSEC_unass,
        MSEC_draft,
-       MSEC_paper,
-       MSEC_NONE
+       MSEC_paper
 };
 
 enum   mdoc_sec {
-       SEC_PROLOGUE,
+       SEC_PROLOGUE = 0,
+       SEC_BODY,
        SEC_NAME,
        SEC_SYNOPSIS,
        SEC_DESCRIPTION,
@@ -263,6 +272,7 @@ enum        mdoc_sec {
 };
 
 enum   mdoc_vol {
+       VOL_DEFAULT = 0,
        VOL_AMD,
        VOL_IND,
        VOL_KM,
@@ -271,11 +281,11 @@ enum      mdoc_vol {
        VOL_PS1,
        VOL_SMM,
        VOL_URM,
-       VOL_USD,
-       VOL_DEFAULT
+       VOL_USD
 };
 
 enum   mdoc_arch {
+       ARCH_DEFAULT = 0,
        ARCH_alpha, 
        ARCH_amd64, 
        ARCH_amiga, 
@@ -300,15 +310,16 @@ enum      mdoc_arch {
        ARCH_sparc64, 
        ARCH_sun3, 
        ARCH_vax, 
-       ARCH_zaurus,
-       ARCH_DEFAULT
+       ARCH_zaurus
 };
 
 struct mdoc_meta {
        enum mdoc_msec    msec;
        enum mdoc_vol     vol;
        enum mdoc_arch    arch;
-       struct tm         tm;
+       time_t            date;
+#define        META_TITLE_SZ    (64)
+       char              title[META_TITLE_SZ];
 };
 
 struct mdoc_text {
index 60bf8943773beb4d4c8372af3341e2bc00dbfc9d..3829dc54042cb64c9c4ac2645422cd01bbc86672 100644 (file)
--- a/mdocml.c
+++ b/mdocml.c
@@ -1,4 +1,4 @@
-/* $Id: mdocml.c,v 1.22 2008/12/15 02:23:12 kristaps Exp $ */
+/* $Id: mdocml.c,v 1.23 2008/12/17 17:18:38 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -265,9 +265,9 @@ parse_begin(struct md_parse *p)
                for (i = 0; i < sz; i++) {
                        if ('\n' != p->buf[i]) {
                                if (pos < sizeof(line)) {
-                                       /* LINTED */
-                                       sv[pos] = p->buf[i];
-                                       line[pos++] = p->buf[i];
+                                       sv[(int)pos] = p->buf[(int)i];
+                                       line[(int)pos++] = 
+                                               p->buf[(int)i];
                                        continue;
                                }
                                warnx("%s: line %d too long", 
@@ -306,6 +306,9 @@ msg_err(void *arg, int tok, int col, enum mdoc_err type)
        case (ERR_SYNTAX_WS):
                lit = "syntax: whitespace in argument";
                break;
+       case (ERR_SYNTAX_ARGS):
+               fmt = "syntax: macro `%s' arguments malformed";
+               break;
        case (ERR_SCOPE_BREAK):
                /* Which scope is broken? */
                fmt = "macro `%s' breaks prior explicit scope";
@@ -316,9 +319,27 @@ msg_err(void *arg, int tok, int col, enum mdoc_err type)
        case (ERR_MACRO_NOTCALL):
                fmt = "macro `%s' not callable";
                break;
+       case (ERR_SEC_PROLOGUE):
+               fmt = "macro `%s' cannot be called in the prologue";
+               break;
+       case (ERR_SEC_NPROLOGUE):
+               fmt = "macro `%s' called outside of prologue";
+               break;
        case (ERR_ARGS_GE1):
                fmt = "macro `%s' expects one or more arguments";
                break;
+       case (ERR_ARGS_MANY):
+               fmt = "macro `%s' has too many arguments";
+               break;
+       case (ERR_SEC_PROLOGUE_OO):
+               fmt = "prologue macro `%s' is out-of-order";
+               break;
+       case (ERR_SEC_PROLOGUE_REP):
+               fmt = "prologue macro `%s' repeated";
+               break;
+       case (ERR_SEC_NAME):
+               lit = "`NAME' section must be first";
+               break;
        default:
                abort();
                /* NOTREACHED */
@@ -333,7 +354,11 @@ msg_err(void *arg, int tok, int col, enum mdoc_err type)
                                p->name, p->lnn, lit);
 
        if (p->dbg < 1) {
-               (void)fprintf(stderr, " (column %d)\n", col);
+               if (-1 != col)
+                       (void)fprintf(stderr, " (column %d)\n", col);
+               return(0);
+       } else if (-1 == col) {
+               (void)fprintf(stderr, "\nFrom: %s", p->line);
                return(0);
        }
 
@@ -360,7 +385,11 @@ msg_msg(void *arg, int col, const char *msg)
        (void)printf("%s:%d: %s", p->name, p->lnn, msg);
 
        if (p->dbg < 3) {
-               (void)printf(" (column %d)\n", col);
+               if (-1 != col)
+                       (void)printf(" (column %d)\n", col);
+               return;
+       } else if (-1 == col) {
+               (void)printf("\nFrom %s\n", p->line);
                return;
        }
 
@@ -393,6 +422,9 @@ msg_warn(void *arg, int tok, int col, enum mdoc_warn type)
        case (WARN_SYNTAX_MACLIKE):
                lit = "syntax: macro-like argument";
                break;
+       case (WARN_SEC_OO):
+               lit = "section is out of conventional order";
+               break;
        case (WARN_ARGS_GE1):
                fmt = "macro `%s' suggests one or more arguments";
                break;
index fd763152deaa3c5dc62967f0782590bc0aba8f88..cc6585fff4cc40c1d446b7c9cf21eed5bfcad851 100644 (file)
--- a/private.h
+++ b/private.h
@@ -1,4 +1,4 @@
-/* $Id: private.h,v 1.42 2008/12/15 03:13:01 kristaps Exp $ */
+/* $Id: private.h,v 1.43 2008/12/17 17:18:38 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -27,7 +27,7 @@ struct        mdoc {
        void             *htab;
        struct mdoc_node *last;
        struct mdoc_node *first;
-
+       struct mdoc_meta  meta;
        enum mdoc_sec     sec_lastn;
        enum mdoc_sec     sec_last;
 };
@@ -41,6 +41,9 @@ struct        mdoc_macro {
 
 extern const struct mdoc_macro *const mdoc_macros;
 
+#define        MACRO_PROT_ARGS struct mdoc *mdoc, int tok, \
+                       int ppos, int *pos, char *buf
+
 __BEGIN_DECLS
 
 int              mdoc_err(struct mdoc *, int, int, enum mdoc_err);
@@ -64,6 +67,16 @@ void          *mdoc_hash_alloc(void);
 int              mdoc_hash_find(const void *, const char *);
 void             mdoc_hash_free(void *);
 int              mdoc_isdelim(const char *);
+enum   mdoc_sec  mdoc_atosec(size_t, const char **);
+enum   mdoc_msec mdoc_atomsec(const char *);
+enum   mdoc_vol  mdoc_atovol(const char *);
+enum   mdoc_arch mdoc_atoarch(const char *);
+time_t           mdoc_atotime(const char *);
+
+int              macro_text(MACRO_PROT_ARGS);
+int              macro_scoped_implicit(MACRO_PROT_ARGS);
+int              macro_prologue_ddate(MACRO_PROT_ARGS);
+int              macro_prologue_dtitle(MACRO_PROT_ARGS);
 
 __END_DECLS
 
index 1380bf7dccacf4e55bdf78109f887f67cc45734b..0125671da30f1afa86891f678461e12712c118d4 100644 (file)
--- a/strings.c
+++ b/strings.c
@@ -1,4 +1,4 @@
-/* $Id: strings.c,v 1.1 2008/12/15 03:13:01 kristaps Exp $ */
+/* $Id: strings.c,v 1.2 2008/12/17 17:18:38 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -20,6 +20,7 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "private.h"
 
@@ -64,3 +65,195 @@ mdoc_isdelim(const char *p)
        return(0);
 }
 
+
+enum mdoc_sec 
+mdoc_atosec(size_t sz, 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"))
+               return(SEC_NAME);
+       else if (0 == strcmp(*p, "SYNOPSIS"))
+               return(SEC_SYNOPSIS);
+       else if (0 == strcmp(*p, "DESCRIPTION"))
+               return(SEC_DESCRIPTION);
+       else if (0 == strcmp(*p, "ENVIRONMENT"))
+               return(SEC_ENVIRONMENT);
+       else if (0 == strcmp(*p, "FILES"))
+               return(SEC_FILES);
+       else if (0 == strcmp(*p, "EXAMPLES"))
+               return(SEC_EXAMPLES);
+       else if (0 == strcmp(*p, "DIAGNOSTICS"))
+               return(SEC_DIAGNOSTICS);
+       else if (0 == strcmp(*p, "ERRORS"))
+               return(SEC_ERRORS);
+       else if (0 == strcmp(*p, "STANDARDS"))
+               return(SEC_STANDARDS);
+       else if (0 == strcmp(*p, "HISTORY"))
+               return(SEC_HISTORY);
+       else if (0 == strcmp(*p, "AUTHORS"))
+               return(SEC_AUTHORS);
+       else if (0 == strcmp(*p, "CAVEATS"))
+               return(SEC_CAVEATS);
+       else if (0 == strcmp(*p, "BUGS"))
+               return(SEC_BUGS);
+
+       return(SEC_CUSTOM);
+}
+
+
+time_t
+mdoc_atotime(const char *p)
+{
+       struct tm        tm;
+
+       if (strptime(p, "%b %d %Y", &tm))
+               return(mktime(&tm));
+       if (strptime(p, "%b %d, %Y", &tm))
+               return(mktime(&tm));
+
+       return(0);
+}
+
+
+enum mdoc_msec
+mdoc_atomsec(const char *p)
+{
+
+       if (0 == strcmp(p, "1"))
+               return(MSEC_1);
+       else if (0 == strcmp(p, "2"))
+               return(MSEC_2);
+       else if (0 == strcmp(p, "3"))
+               return(MSEC_3);
+       else if (0 == strcmp(p, "3f"))
+               return(MSEC_3f);
+       else if (0 == strcmp(p, "3p"))
+               return(MSEC_3p);
+       else if (0 == strcmp(p, "4"))
+               return(MSEC_4);
+       else if (0 == strcmp(p, "5"))
+               return(MSEC_5);
+       else if (0 == strcmp(p, "6"))
+               return(MSEC_6);
+       else if (0 == strcmp(p, "7"))
+               return(MSEC_7);
+       else if (0 == strcmp(p, "8"))
+               return(MSEC_8);
+       else if (0 == strcmp(p, "9"))
+               return(MSEC_9);
+       else if (0 == strcmp(p, "X11"))
+               return(MSEC_X11);
+       else if (0 == strcmp(p, "X11R6"))
+               return(MSEC_X11R6);
+       else if (0 == strcmp(p, "local"))
+               return(MSEC_local);
+       else if (0 == strcmp(p, "n"))
+               return(MSEC_n);
+       else if (0 == strcmp(p, "unass"))
+               return(MSEC_unass);
+       else if (0 == strcmp(p, "draft"))
+               return(MSEC_draft);
+       else if (0 == strcmp(p, "paper"))
+               return(MSEC_paper);
+
+       return(MSEC_DEFAULT);
+}
+
+
+enum mdoc_vol
+mdoc_atovol(const char *p)
+{
+
+       if (0 == strcmp(p, "AMD"))
+               return(VOL_AMD);
+       else if (0 == strcmp(p, "IND"))
+               return(VOL_IND);
+       else if (0 == strcmp(p, "KM"))
+               return(VOL_KM);
+       else if (0 == strcmp(p, "LOCAL"))
+               return(VOL_LOCAL);
+       else if (0 == strcmp(p, "PRM"))
+               return(VOL_PRM);
+       else if (0 == strcmp(p, "PS1"))
+               return(VOL_PS1);
+       else if (0 == strcmp(p, "SMM"))
+               return(VOL_SMM);
+       else if (0 == strcmp(p, "URM"))
+               return(VOL_URM);
+       else if (0 == strcmp(p, "USD"))
+               return(VOL_USD);
+
+       return(VOL_DEFAULT);
+}
+
+
+enum mdoc_arch
+mdoc_atoarch(const char *p)
+{
+
+       if (0 == strcmp(p, "alpha"))
+               return(ARCH_alpha);
+       else if (0 == strcmp(p, "amd64"))
+               return(ARCH_amd64);
+       else if (0 == strcmp(p, "amiga"))
+               return(ARCH_amiga);
+       else if (0 == strcmp(p, "arc"))
+               return(ARCH_arc);
+       else if (0 == strcmp(p, "armish"))
+               return(ARCH_armish);
+       else if (0 == strcmp(p, "aviion"))
+               return(ARCH_aviion);
+       else if (0 == strcmp(p, "hp300"))
+               return(ARCH_hp300);
+       else if (0 == strcmp(p, "hppa"))
+               return(ARCH_hppa);
+       else if (0 == strcmp(p, "hppa64"))
+               return(ARCH_hppa64);
+       else if (0 == strcmp(p, "i386"))
+               return(ARCH_i386);
+       else if (0 == strcmp(p, "landisk"))
+               return(ARCH_landisk);
+       else if (0 == strcmp(p, "luna88k"))
+               return(ARCH_luna88k);
+       else if (0 == strcmp(p, "mac68k"))
+               return(ARCH_mac68k);
+       else if (0 == strcmp(p, "macppc"))
+               return(ARCH_macppc);
+       else if (0 == strcmp(p, "mvme68k"))
+               return(ARCH_mvme68k);
+       else if (0 == strcmp(p, "mvme88k"))
+               return(ARCH_mvme88k);
+       else if (0 == strcmp(p, "mvmeppc"))
+               return(ARCH_mvmeppc);
+       else if (0 == strcmp(p, "pmax"))
+               return(ARCH_pmax);
+       else if (0 == strcmp(p, "sgi"))
+               return(ARCH_sgi);
+       else if (0 == strcmp(p, "socppc"))
+               return(ARCH_socppc);
+       else if (0 == strcmp(p, "sparc"))
+               return(ARCH_sparc);
+       else if (0 == strcmp(p, "sparc64"))
+               return(ARCH_sparc64);
+       else if (0 == strcmp(p, "sun3"))
+               return(ARCH_sun3);
+       else if (0 == strcmp(p, "vax"))
+               return(ARCH_vax);
+       else if (0 == strcmp(p, "zaurus"))
+               return(ARCH_zaurus);
+
+       return(ARCH_DEFAULT);
+}