]> git.cameronkatri.com Git - mandoc.git/blobdiff - mdoc_validate.c
do not break the line between Bsx/Bx/Fx/Nx/Ox/Dx and its arguments
[mandoc.git] / mdoc_validate.c
index 043145ae1ccc9f5fe082f108dca4ae9863cf2568..9bf1efb3d784ac19467e9790bd6d0fd399ecd591 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_validate.c,v 1.317 2017/01/11 17:39:53 schwarze Exp $ */
+/*     $Id: mdoc_validate.c,v 1.332 2017/06/08 00:23:30 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -53,12 +53,13 @@ typedef     void    (*v_post)(POST_ARGS);
 
 static int      build_list(struct roff_man *, int);
 static void     check_text(struct roff_man *, int, int, char *);
+static void     check_bsd(struct roff_man *, int, int, char *);
 static void     check_argv(struct roff_man *,
                        struct roff_node *, struct mdoc_argv *);
 static void     check_args(struct roff_man *, struct roff_node *);
 static int      child_an(const struct roff_node *);
-static size_t          macro2len(int);
-static void     rewrite_macro2len(char **);
+static size_t          macro2len(enum roff_tok);
+static void     rewrite_macro2len(struct roff_man *, char **);
 
 static void     post_an(POST_ARGS);
 static void     post_an_norm(POST_ARGS);
@@ -105,11 +106,11 @@ static    void     post_sh_authors(POST_ARGS);
 static void     post_sm(POST_ARGS);
 static void     post_st(POST_ARGS);
 static void     post_std(POST_ARGS);
+static void     post_useless(POST_ARGS);
 static void     post_xr(POST_ARGS);
 static void     post_xx(POST_ARGS);
 
-static v_post mdoc_valids[MDOC_MAX] = {
-       NULL,           /* Ap */
+static const v_post __mdoc_valids[MDOC_MAX - MDOC_Dd] = {
        post_dd,        /* Dd */
        post_dt,        /* Dt */
        post_os,        /* Os */
@@ -125,6 +126,7 @@ static      v_post mdoc_valids[MDOC_MAX] = {
        post_it,        /* It */
        NULL,           /* Ad */
        post_an,        /* An */
+       NULL,           /* Ap */
        post_defaults,  /* Ar */
        NULL,           /* Cd */
        NULL,           /* Cm */
@@ -201,7 +203,7 @@ static      v_post mdoc_valids[MDOC_MAX] = {
        post_sm,        /* Sm */
        post_hyph,      /* Sx */
        NULL,           /* Sy */
-       NULL,           /* Tn */
+       post_useless,   /* Tn */
        post_xx,        /* Ux */
        NULL,           /* Xc */
        NULL,           /* Xo */
@@ -227,16 +229,14 @@ static    v_post mdoc_valids[MDOC_MAX] = {
        post_en,        /* En */
        post_xx,        /* Dx */
        NULL,           /* %Q */
-       post_par,       /* br */
-       post_par,       /* sp */
        NULL,           /* %U */
        NULL,           /* Ta */
-       NULL,           /* ll */
 };
+static const v_post *const mdoc_valids = __mdoc_valids - MDOC_Dd;
 
 #define        RSORD_MAX 14 /* Number of `Rs' blocks. */
 
-static const int rsord[RSORD_MAX] = {
+static const enum roff_tok rsord[RSORD_MAX] = {
        MDOC__A,
        MDOC__T,
        MDOC__B,
@@ -284,7 +284,7 @@ void
 mdoc_node_validate(struct roff_man *mdoc)
 {
        struct roff_node *n;
-       v_post *p;
+       const v_post *p;
 
        n = mdoc->last;
        mdoc->last = mdoc->last->child;
@@ -303,6 +303,10 @@ mdoc_node_validate(struct roff_man *mdoc)
                if (n->sec != SEC_SYNOPSIS ||
                    (n->parent->tok != MDOC_Cd && n->parent->tok != MDOC_Fd))
                        check_text(mdoc, n->line, n->pos, n->string);
+               if (n->parent->tok == MDOC_Sh ||
+                   n->parent->tok == MDOC_Ss ||
+                   n->parent->tok == MDOC_It)
+                       check_bsd(mdoc, n->line, n->pos, n->string);
                break;
        case ROFFT_EQN:
        case ROFFT_TBL:
@@ -326,6 +330,20 @@ mdoc_node_validate(struct roff_man *mdoc)
 
                /* Call the macro's postprocessor. */
 
+               if (n->tok < ROFF_MAX) {
+                       switch(n->tok) {
+                       case ROFF_br:
+                       case ROFF_sp:
+                               post_par(mdoc);
+                               break;
+                       default:
+                               roff_validate(mdoc);
+                               break;
+                       }
+                       break;
+               }
+
+               assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
                p = mdoc_valids + n->tok;
                if (*p)
                        (*p)(mdoc);
@@ -370,6 +388,25 @@ check_text(struct roff_man *mdoc, int ln, int pos, char *p)
                    ln, pos + (int)(p - cp), NULL);
 }
 
+static void
+check_bsd(struct roff_man *mdoc, int ln, int pos, char *p)
+{
+       const char      *cp;
+
+       if ((cp = strstr(p, "OpenBSD")) != NULL)
+               mandoc_msg(MANDOCERR_BX, mdoc->parse,
+                   ln, pos + (cp - p), "Ox");
+       if ((cp = strstr(p, "NetBSD")) != NULL)
+               mandoc_msg(MANDOCERR_BX, mdoc->parse,
+                   ln, pos + (cp - p), "Nx");
+       if ((cp = strstr(p, "FreeBSD")) != NULL)
+               mandoc_msg(MANDOCERR_BX, mdoc->parse,
+                   ln, pos + (cp - p), "Fx");
+       if ((cp = strstr(p, "DragonFly")) != NULL)
+               mandoc_msg(MANDOCERR_BX, mdoc->parse,
+                   ln, pos + (cp - p), "Dx");
+}
+
 static void
 post_bl_norm(POST_ARGS)
 {
@@ -450,7 +487,7 @@ post_bl_norm(POST_ARGS)
                                    mdoc->parse, argv->line,
                                    argv->pos, "Bl -width %s",
                                    argv->value[0]);
-                       rewrite_macro2len(argv->value);
+                       rewrite_macro2len(mdoc, argv->value);
                        n->norm->Bl.width = argv->value[0];
                        break;
                case MDOC_Offset:
@@ -465,7 +502,7 @@ post_bl_norm(POST_ARGS)
                                    mdoc->parse, argv->line,
                                    argv->pos, "Bl -offset %s",
                                    argv->value[0]);
-                       rewrite_macro2len(argv->value);
+                       rewrite_macro2len(mdoc, argv->value);
                        n->norm->Bl.offs = argv->value[0];
                        break;
                default:
@@ -592,7 +629,7 @@ post_bd(POST_ARGS)
                                    mdoc->parse, argv->line,
                                    argv->pos, "Bd -offset %s",
                                    argv->value[0]);
-                       rewrite_macro2len(argv->value);
+                       rewrite_macro2len(mdoc, argv->value);
                        n->norm->Bd.offs = argv->value[0];
                        break;
                case MDOC_Compact:
@@ -659,11 +696,11 @@ post_eoln(POST_ARGS)
 {
        struct roff_node        *n;
 
+       post_useless(mdoc);
        n = mdoc->last;
        if (n->child != NULL)
-               mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse,
-                   n->line, n->pos, "%s %s",
-                   mdoc_macronames[n->tok], n->child->string);
+               mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse, n->line,
+                   n->pos, "%s %s", roff_name[n->tok], n->child->string);
 
        while (n->child != NULL)
                roff_node_delete(mdoc, n->child);
@@ -757,6 +794,9 @@ post_lb(POST_ARGS)
                return;
        }
 
+       mandoc_vmsg(MANDOCERR_LB_BAD, mdoc->parse, n->child->line,
+           n->child->pos, "Lb %s", n->child->string);
+
        roff_word_alloc(mdoc, n->line, n->pos, "library");
        mdoc->last->flags = NODE_NOSRC;
        roff_word_alloc(mdoc, n->line, n->pos, "\\(Lq");
@@ -817,7 +857,7 @@ post_std(POST_ARGS)
                        return;
 
        mandoc_msg(MANDOCERR_ARG_STD, mdoc->parse,
-           n->line, n->pos, mdoc_macronames[n->tok]);
+           n->line, n->pos, roff_name[n->tok]);
 }
 
 static void
@@ -852,7 +892,17 @@ post_obsolete(POST_ARGS)
        n = mdoc->last;
        if (n->type == ROFFT_ELEM || n->type == ROFFT_BLOCK)
                mandoc_msg(MANDOCERR_MACRO_OBS, mdoc->parse,
-                   n->line, n->pos, mdoc_macronames[n->tok]);
+                   n->line, n->pos, roff_name[n->tok]);
+}
+
+static void
+post_useless(POST_ARGS)
+{
+       struct roff_node *n;
+
+       n = mdoc->last;
+       mandoc_msg(MANDOCERR_MACRO_USELESS, mdoc->parse,
+           n->line, n->pos, roff_name[n->tok]);
 }
 
 /*
@@ -1013,21 +1063,41 @@ post_nm(POST_ARGS)
            (mdoc->lastsec == SEC_NAME && n->child == NULL))
                mandoc_msg(MANDOCERR_NM_NONAME, mdoc->parse,
                    n->line, n->pos, "Nm");
+
+       if ((n->type != ROFFT_ELEM && n->type != ROFFT_HEAD) ||
+           (n->child != NULL && n->child->type == ROFFT_TEXT) ||
+           mdoc->meta.name == NULL)
+               return;
+
+       mdoc->next = ROFF_NEXT_CHILD;
+       roff_word_alloc(mdoc, n->line, n->pos, mdoc->meta.name);
+       mdoc->last->flags |= NODE_NOSRC;
+       mdoc->last = n;
 }
 
 static void
 post_nd(POST_ARGS)
 {
        struct roff_node        *n;
+       size_t                   sz;
 
        n = mdoc->last;
 
        if (n->type != ROFFT_BODY)
                return;
 
+       if (n->sec != SEC_NAME)
+               mandoc_msg(MANDOCERR_ND_LATE, mdoc->parse,
+                   n->line, n->pos, "Nd");
+
        if (n->child == NULL)
                mandoc_msg(MANDOCERR_ND_EMPTY, mdoc->parse,
                    n->line, n->pos, "Nd");
+       else if (n->last->type == ROFFT_TEXT &&
+           (sz = strlen(n->last->string)) != 0 &&
+           n->last->string[sz - 1] == '.')
+               mandoc_msg(MANDOCERR_ND_DOT, mdoc->parse,
+                   n->last->line, n->last->pos + sz - 1, NULL);
 
        post_hyph(mdoc);
 }
@@ -1046,7 +1116,7 @@ post_display(POST_ARGS)
                                roff_node_delete(mdoc, n);
                } else if (n->child == NULL)
                        mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse,
-                           n->line, n->pos, mdoc_macronames[n->tok]);
+                           n->line, n->pos, roff_name[n->tok]);
                else if (n->tok == MDOC_D1)
                        post_hyph(mdoc);
                break;
@@ -1069,7 +1139,7 @@ post_display(POST_ARGS)
                        if (np->type == ROFFT_BLOCK && np->tok == MDOC_Bd) {
                                mandoc_vmsg(MANDOCERR_BD_NEST,
                                    mdoc->parse, n->line, n->pos,
-                                   "%s in Bd", mdoc_macronames[n->tok]);
+                                   "%s in Bd", roff_name[n->tok]);
                                break;
                        }
                }
@@ -1255,10 +1325,10 @@ post_it(POST_ARGS)
                /* FALLTHROUGH */
        case LIST_item:
                if ((nch = nit->head->child) != NULL)
-                       mandoc_vmsg(MANDOCERR_ARG_SKIP,
-                           mdoc->parse, nit->line, nit->pos,
-                           "It %s", nch->string == NULL ?
-                           mdoc_macronames[nch->tok] : nch->string);
+                       mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse,
+                           nit->line, nit->pos, "It %s",
+                           nch->string == NULL ? roff_name[nch->tok] :
+                           nch->string);
                break;
        case LIST_column:
                cols = (int)nbl->norm->Bl.ncols;
@@ -1296,7 +1366,7 @@ post_bl_block(POST_ARGS)
                        switch (nc->tok) {
                        case MDOC_Pp:
                        case MDOC_Lp:
-                       case MDOC_br:
+                       case ROFF_br:
                                break;
                        default:
                                nc = NULL;
@@ -1305,14 +1375,13 @@ post_bl_block(POST_ARGS)
                        if (ni->next == NULL) {
                                mandoc_msg(MANDOCERR_PAR_MOVE,
                                    mdoc->parse, nc->line, nc->pos,
-                                   mdoc_macronames[nc->tok]);
+                                   roff_name[nc->tok]);
                                mdoc_node_relink(mdoc, nc);
                        } else if (n->norm->Bl.comp == 0 &&
                            n->norm->Bl.type != LIST_column) {
                                mandoc_vmsg(MANDOCERR_PAR_SKIP,
                                    mdoc->parse, nc->line, nc->pos,
-                                   "%s before It",
-                                   mdoc_macronames[nc->tok]);
+                                   "%s before It", roff_name[nc->tok]);
                                roff_node_delete(mdoc, nc);
                        } else
                                break;
@@ -1325,17 +1394,17 @@ post_bl_block(POST_ARGS)
  * If the argument of -offset or -width is a macro,
  * replace it with the associated default width.
  */
-void
-rewrite_macro2len(char **arg)
+static void
+rewrite_macro2len(struct roff_man *mdoc, char **arg)
 {
        size_t            width;
-       int               tok;
+       enum roff_tok     tok;
 
        if (*arg == NULL)
                return;
        else if ( ! strcmp(*arg, "Ds"))
                width = 6;
-       else if ((tok = mdoc_hash_find(*arg)) == TOKEN_NONE)
+       else if ((tok = roffhash_find(mdoc->mdocmac, *arg, 0)) == TOKEN_NONE)
                return;
        else
                width = macro2len(tok);
@@ -1413,6 +1482,8 @@ post_bl(POST_ARGS)
        struct roff_node        *nparent, *nprev; /* of the Bl block */
        struct roff_node        *nblock, *nbody;  /* of the Bl */
        struct roff_node        *nchild, *nnext;  /* of the Bl body */
+       const char              *prev_Er;
+       int                      order;
 
        nbody = mdoc->last;
        switch (nbody->type) {
@@ -1476,8 +1547,7 @@ post_bl(POST_ARGS)
                }
 
                mandoc_msg(MANDOCERR_BL_MOVE, mdoc->parse,
-                   nchild->line, nchild->pos,
-                   mdoc_macronames[nchild->tok]);
+                   nchild->line, nchild->pos, roff_name[nchild->tok]);
 
                /*
                 * Move the node out of the Bl block.
@@ -1514,6 +1584,34 @@ post_bl(POST_ARGS)
 
                nchild = nnext;
        }
+
+       if (mdoc->meta.os_e != MDOC_OS_NETBSD)
+               return;
+
+       prev_Er = NULL;
+       for (nchild = nbody->child; nchild != NULL; nchild = nchild->next) {
+               if (nchild->tok != MDOC_It)
+                       continue;
+               if ((nnext = nchild->head->child) == NULL)
+                       continue;
+               if (nnext->type == ROFFT_BLOCK)
+                       nnext = nnext->body->child;
+               if (nnext == NULL || nnext->tok != MDOC_Er)
+                       continue;
+               nnext = nnext->child;
+               if (prev_Er != NULL) {
+                       order = strcmp(prev_Er, nnext->string);
+                       if (order > 0)
+                               mandoc_vmsg(MANDOCERR_ER_ORDER,
+                                   mdoc->parse, nnext->line, nnext->pos,
+                                   "Er %s %s", prev_Er, nnext->string);
+                       else if (order == 0)
+                               mandoc_vmsg(MANDOCERR_ER_REP,
+                                   mdoc->parse, nnext->line, nnext->pos,
+                                   "Er %s", prev_Er);
+               }
+               prev_Er = nnext->string;
+       }
 }
 
 static void
@@ -1555,7 +1653,7 @@ post_sm(POST_ARGS)
 
        mandoc_vmsg(MANDOCERR_SM_BAD,
            mdoc->parse, nch->line, nch->pos,
-           "%s %s", mdoc_macronames[mdoc->last->tok], nch->string);
+           "%s %s", roff_name[mdoc->last->tok], nch->string);
        mdoc_node_relink(mdoc, nch);
        return;
 }
@@ -1598,7 +1696,7 @@ post_root(POST_ARGS)
                mandoc_msg(MANDOCERR_DOC_EMPTY, mdoc->parse, 0, 0, NULL);
        else if (n->tok != MDOC_Sh)
                mandoc_msg(MANDOCERR_SEC_BEFORE, mdoc->parse,
-                   n->line, n->pos, mdoc_macronames[n->tok]);
+                   n->line, n->pos, roff_name[n->tok]);
 }
 
 static void
@@ -1632,9 +1730,8 @@ post_rs(POST_ARGS)
                                break;
 
                if (i == RSORD_MAX) {
-                       mandoc_msg(MANDOCERR_RS_BAD,
-                           mdoc->parse, nch->line, nch->pos,
-                           mdoc_macronames[nch->tok]);
+                       mandoc_msg(MANDOCERR_RS_BAD, mdoc->parse,
+                           nch->line, nch->pos, roff_name[nch->tok]);
                        i = -1;
                } else if (nch->tok == MDOC__J || nch->tok == MDOC__B)
                        np->norm->Rs.quote_T++;
@@ -1787,7 +1884,7 @@ post_sh_name(POST_ARGS)
                        /* FALLTHROUGH */
                default:
                        mandoc_msg(MANDOCERR_NAMESEC_BAD, mdoc->parse,
-                           n->line, n->pos, mdoc_macronames[n->tok]);
+                           n->line, n->pos, roff_name[n->tok]);
                        continue;
                }
                break;
@@ -1857,7 +1954,7 @@ post_sh_see_also(POST_ARGS)
                        if (isalpha((const unsigned char)*name))
                                return;
                lastpunct = n->string;
-               if (n->next == NULL)
+               if (n->next == NULL || n->next->tok == MDOC_Rs)
                        mandoc_vmsg(MANDOCERR_XR_PUNCT, mdoc->parse,
                            n->line, n->pos, "%s after %s(%s)",
                            lastpunct, lastname, lastsec);
@@ -1908,7 +2005,7 @@ post_sh_head(POST_ARGS)
                    sec != SEC_CUSTOM ? secnames[sec] :
                    (nch = mdoc->last->child) == NULL ? "" :
                    nch->type == ROFFT_TEXT ? nch->string :
-                   mdoc_macronames[nch->tok]);
+                   roff_name[nch->tok]);
 
        /* The SYNOPSIS gets special attention in other areas. */
 
@@ -2004,6 +2101,9 @@ post_ignpar(POST_ARGS)
        struct roff_node *np;
 
        switch (mdoc->last->type) {
+       case ROFFT_BLOCK:
+               post_prevpar(mdoc);
+               return;
        case ROFFT_HEAD:
                post_hyph(mdoc);
                return;
@@ -2017,8 +2117,8 @@ post_ignpar(POST_ARGS)
                if (np->tok == MDOC_Pp || np->tok == MDOC_Lp) {
                        mandoc_vmsg(MANDOCERR_PAR_SKIP,
                            mdoc->parse, np->line, np->pos,
-                           "%s after %s", mdoc_macronames[np->tok],
-                           mdoc_macronames[mdoc->last->tok]);
+                           "%s after %s", roff_name[np->tok],
+                           roff_name[mdoc->last->tok]);
                        roff_node_delete(mdoc, np);
                }
 
@@ -2026,8 +2126,8 @@ post_ignpar(POST_ARGS)
                if (np->tok == MDOC_Pp || np->tok == MDOC_Lp) {
                        mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
                            np->line, np->pos, "%s at the end of %s",
-                           mdoc_macronames[np->tok],
-                           mdoc_macronames[mdoc->last->tok]);
+                           roff_name[np->tok],
+                           roff_name[mdoc->last->tok]);
                        roff_node_delete(mdoc, np);
                }
 }
@@ -2050,7 +2150,7 @@ post_prevpar(POST_ARGS)
 
        if (n->prev->tok != MDOC_Pp &&
            n->prev->tok != MDOC_Lp &&
-           n->prev->tok != MDOC_br)
+           n->prev->tok != ROFF_br)
                return;
        if (n->tok == MDOC_Bl && n->norm->Bl.comp)
                return;
@@ -2060,9 +2160,8 @@ post_prevpar(POST_ARGS)
                return;
 
        mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
-           n->prev->line, n->prev->pos,
-           "%s before %s", mdoc_macronames[n->prev->tok],
-           mdoc_macronames[n->tok]);
+           n->prev->line, n->prev->pos, "%s before %s",
+           roff_name[n->prev->tok], roff_name[n->tok]);
        roff_node_delete(mdoc, n->prev);
 }
 
@@ -2072,10 +2171,10 @@ post_par(POST_ARGS)
        struct roff_node *np;
 
        np = mdoc->last;
-       if (np->tok != MDOC_br && np->tok != MDOC_sp)
+       if (np->tok != ROFF_br && np->tok != ROFF_sp)
                post_prevpar(mdoc);
 
-       if (np->tok == MDOC_sp) {
+       if (np->tok == ROFF_sp) {
                if (np->child != NULL && np->child->next != NULL)
                        mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
                            np->child->next->line, np->child->next->pos,
@@ -2083,21 +2182,20 @@ post_par(POST_ARGS)
        } else if (np->child != NULL)
                mandoc_vmsg(MANDOCERR_ARG_SKIP,
                    mdoc->parse, np->line, np->pos, "%s %s",
-                   mdoc_macronames[np->tok], np->child->string);
+                   roff_name[np->tok], np->child->string);
 
        if ((np = mdoc->last->prev) == NULL) {
                np = mdoc->last->parent;
                if (np->tok != MDOC_Sh && np->tok != MDOC_Ss)
                        return;
        } else if (np->tok != MDOC_Pp && np->tok != MDOC_Lp &&
-           (mdoc->last->tok != MDOC_br ||
-            (np->tok != MDOC_sp && np->tok != MDOC_br)))
+           (mdoc->last->tok != ROFF_br ||
+            (np->tok != ROFF_sp && np->tok != ROFF_br)))
                return;
 
        mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
-           mdoc->last->line, mdoc->last->pos,
-           "%s after %s", mdoc_macronames[mdoc->last->tok],
-           mdoc_macronames[np->tok]);
+           mdoc->last->line, mdoc->last->pos, "%s after %s",
+           roff_name[mdoc->last->tok], roff_name[np->tok]);
        roff_node_delete(mdoc, mdoc->last);
 }
 
@@ -2241,11 +2339,19 @@ static void
 post_bx(POST_ARGS)
 {
        struct roff_node        *n, *nch;
+       const char              *macro;
 
        n = mdoc->last;
        nch = n->child;
 
        if (nch != NULL) {
+               macro = !strcmp(nch->string, "Open") ? "Ox" :
+                   !strcmp(nch->string, "Net") ? "Nx" :
+                   !strcmp(nch->string, "Free") ? "Fx" :
+                   !strcmp(nch->string, "DragonFly") ? "Dx" : NULL;
+               if (macro != NULL)
+                       mandoc_msg(MANDOCERR_BX, mdoc->parse,
+                           n->line, n->pos, macro);
                mdoc->last = nch;
                nch = nch->next;
                mdoc->next = ROFF_NEXT_SIBLING;
@@ -2312,11 +2418,11 @@ post_os(POST_ARGS)
        mdoc->meta.os = NULL;
        deroff(&mdoc->meta.os, n);
        if (mdoc->meta.os)
-               return;
+               goto out;
 
        if (mdoc->defos) {
                mdoc->meta.os = mandoc_strdup(mdoc->defos);
-               return;
+               goto out;
        }
 
 #ifdef OSNAME
@@ -2333,6 +2439,10 @@ post_os(POST_ARGS)
        }
        mdoc->meta.os = mandoc_strdup(defbuf);
 #endif /*!OSNAME*/
+
+out:   mdoc->meta.os_e = strstr(mdoc->meta.os, "OpenBSD") != NULL ?
+           MDOC_OS_OPENBSD : strstr(mdoc->meta.os, "NetBSD") != NULL ?
+           MDOC_OS_NETBSD : MDOC_OS_OTHER;
 }
 
 enum roff_sec
@@ -2348,7 +2458,7 @@ mdoc_a2sec(const char *p)
 }
 
 static size_t
-macro2len(int macro)
+macro2len(enum roff_tok macro)
 {
 
        switch (macro) {