1*260e9a87SYuri Pankov /* $OpenBSD$ */ 295c635efSGarrett D'Amore /* 395c635efSGarrett D'Amore * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> 4*260e9a87SYuri Pankov * Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org> 595c635efSGarrett D'Amore * 695c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any 795c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above 895c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies. 995c635efSGarrett D'Amore * 1095c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1195c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1295c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1395c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1495c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1595c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1695c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1795c635efSGarrett D'Amore */ 1895c635efSGarrett D'Amore #include "config.h" 1995c635efSGarrett D'Amore 2095c635efSGarrett D'Amore #include <sys/types.h> 2195c635efSGarrett D'Amore 2295c635efSGarrett D'Amore #include <assert.h> 2395c635efSGarrett D'Amore #include <ctype.h> 2495c635efSGarrett D'Amore #include <errno.h> 2595c635efSGarrett D'Amore #include <limits.h> 2695c635efSGarrett D'Amore #include <stdarg.h> 2795c635efSGarrett D'Amore #include <stdlib.h> 2895c635efSGarrett D'Amore #include <string.h> 2995c635efSGarrett D'Amore #include <time.h> 3095c635efSGarrett D'Amore 3195c635efSGarrett D'Amore #include "man.h" 3295c635efSGarrett D'Amore #include "mandoc.h" 33*260e9a87SYuri Pankov #include "mandoc_aux.h" 3495c635efSGarrett D'Amore #include "libman.h" 3595c635efSGarrett D'Amore #include "libmandoc.h" 3695c635efSGarrett D'Amore 37698f87a4SGarrett D'Amore #define CHKARGS struct man *man, struct man_node *n 3895c635efSGarrett D'Amore 39*260e9a87SYuri Pankov typedef void (*v_check)(CHKARGS); 4095c635efSGarrett D'Amore 41*260e9a87SYuri Pankov static void check_par(CHKARGS); 42*260e9a87SYuri Pankov static void check_part(CHKARGS); 43*260e9a87SYuri Pankov static void check_root(CHKARGS); 4495c635efSGarrett D'Amore static void check_text(CHKARGS); 4595c635efSGarrett D'Amore 46*260e9a87SYuri Pankov static void post_AT(CHKARGS); 47*260e9a87SYuri Pankov static void post_IP(CHKARGS); 48*260e9a87SYuri Pankov static void post_vs(CHKARGS); 49*260e9a87SYuri Pankov static void post_fi(CHKARGS); 50*260e9a87SYuri Pankov static void post_ft(CHKARGS); 51*260e9a87SYuri Pankov static void post_nf(CHKARGS); 52*260e9a87SYuri Pankov static void post_OP(CHKARGS); 53*260e9a87SYuri Pankov static void post_TH(CHKARGS); 54*260e9a87SYuri Pankov static void post_UC(CHKARGS); 55*260e9a87SYuri Pankov static void post_UR(CHKARGS); 5695c635efSGarrett D'Amore 57*260e9a87SYuri Pankov static v_check man_valids[MAN_MAX] = { 58*260e9a87SYuri Pankov post_vs, /* br */ 59*260e9a87SYuri Pankov post_TH, /* TH */ 60*260e9a87SYuri Pankov NULL, /* SH */ 61*260e9a87SYuri Pankov NULL, /* SS */ 62*260e9a87SYuri Pankov NULL, /* TP */ 63*260e9a87SYuri Pankov check_par, /* LP */ 64*260e9a87SYuri Pankov check_par, /* PP */ 65*260e9a87SYuri Pankov check_par, /* P */ 66*260e9a87SYuri Pankov post_IP, /* IP */ 67*260e9a87SYuri Pankov NULL, /* HP */ 68*260e9a87SYuri Pankov NULL, /* SM */ 69*260e9a87SYuri Pankov NULL, /* SB */ 70*260e9a87SYuri Pankov NULL, /* BI */ 71*260e9a87SYuri Pankov NULL, /* IB */ 72*260e9a87SYuri Pankov NULL, /* BR */ 73*260e9a87SYuri Pankov NULL, /* RB */ 74*260e9a87SYuri Pankov NULL, /* R */ 75*260e9a87SYuri Pankov NULL, /* B */ 76*260e9a87SYuri Pankov NULL, /* I */ 77*260e9a87SYuri Pankov NULL, /* IR */ 78*260e9a87SYuri Pankov NULL, /* RI */ 79*260e9a87SYuri Pankov post_vs, /* sp */ 80*260e9a87SYuri Pankov post_nf, /* nf */ 81*260e9a87SYuri Pankov post_fi, /* fi */ 82*260e9a87SYuri Pankov NULL, /* RE */ 83*260e9a87SYuri Pankov check_part, /* RS */ 84*260e9a87SYuri Pankov NULL, /* DT */ 85*260e9a87SYuri Pankov post_UC, /* UC */ 86*260e9a87SYuri Pankov NULL, /* PD */ 87*260e9a87SYuri Pankov post_AT, /* AT */ 88*260e9a87SYuri Pankov NULL, /* in */ 89*260e9a87SYuri Pankov post_ft, /* ft */ 90*260e9a87SYuri Pankov post_OP, /* OP */ 91*260e9a87SYuri Pankov post_nf, /* EX */ 92*260e9a87SYuri Pankov post_fi, /* EE */ 93*260e9a87SYuri Pankov post_UR, /* UR */ 94*260e9a87SYuri Pankov NULL, /* UE */ 95*260e9a87SYuri Pankov NULL, /* ll */ 9695c635efSGarrett D'Amore }; 9795c635efSGarrett D'Amore 9895c635efSGarrett D'Amore 99*260e9a87SYuri Pankov void 100698f87a4SGarrett D'Amore man_valid_post(struct man *man) 10195c635efSGarrett D'Amore { 102*260e9a87SYuri Pankov struct man_node *n; 10395c635efSGarrett D'Amore v_check *cp; 10495c635efSGarrett D'Amore 105*260e9a87SYuri Pankov n = man->last; 106*260e9a87SYuri Pankov if (n->flags & MAN_VALID) 107*260e9a87SYuri Pankov return; 108*260e9a87SYuri Pankov n->flags |= MAN_VALID; 10995c635efSGarrett D'Amore 110*260e9a87SYuri Pankov switch (n->type) { 111*260e9a87SYuri Pankov case MAN_TEXT: 112*260e9a87SYuri Pankov check_text(man, n); 113*260e9a87SYuri Pankov break; 114*260e9a87SYuri Pankov case MAN_ROOT: 115*260e9a87SYuri Pankov check_root(man, n); 116*260e9a87SYuri Pankov break; 117*260e9a87SYuri Pankov case MAN_EQN: 11895c635efSGarrett D'Amore /* FALLTHROUGH */ 119*260e9a87SYuri Pankov case MAN_TBL: 120*260e9a87SYuri Pankov break; 12195c635efSGarrett D'Amore default: 122*260e9a87SYuri Pankov cp = man_valids + n->tok; 123*260e9a87SYuri Pankov if (*cp) 124*260e9a87SYuri Pankov (*cp)(man, n); 12595c635efSGarrett D'Amore break; 12695c635efSGarrett D'Amore } 12795c635efSGarrett D'Amore } 12895c635efSGarrett D'Amore 129*260e9a87SYuri Pankov static void 13095c635efSGarrett D'Amore check_root(CHKARGS) 13195c635efSGarrett D'Amore { 13295c635efSGarrett D'Amore 133*260e9a87SYuri Pankov assert((man->flags & (MAN_BLINE | MAN_ELINE)) == 0); 13495c635efSGarrett D'Amore 135*260e9a87SYuri Pankov if (NULL == man->first->child) 136*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_DOC_EMPTY, man->parse, 137*260e9a87SYuri Pankov n->line, n->pos, NULL); 138*260e9a87SYuri Pankov else 139*260e9a87SYuri Pankov man->meta.hasbody = 1; 14095c635efSGarrett D'Amore 141*260e9a87SYuri Pankov if (NULL == man->meta.title) { 142*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_TH_NOTITLE, man->parse, 143*260e9a87SYuri Pankov n->line, n->pos, NULL); 14495c635efSGarrett D'Amore 14595c635efSGarrett D'Amore /* 14695c635efSGarrett D'Amore * If a title hasn't been set, do so now (by 14795c635efSGarrett D'Amore * implication, date and section also aren't set). 14895c635efSGarrett D'Amore */ 14995c635efSGarrett D'Amore 150*260e9a87SYuri Pankov man->meta.title = mandoc_strdup(""); 151*260e9a87SYuri Pankov man->meta.msec = mandoc_strdup(""); 152*260e9a87SYuri Pankov man->meta.date = man->quick ? mandoc_strdup("") : 153*260e9a87SYuri Pankov mandoc_normdate(man->parse, NULL, n->line, n->pos); 15495c635efSGarrett D'Amore } 15595c635efSGarrett D'Amore } 15695c635efSGarrett D'Amore 15795c635efSGarrett D'Amore static void 15895c635efSGarrett D'Amore check_text(CHKARGS) 15995c635efSGarrett D'Amore { 16095c635efSGarrett D'Amore char *cp, *p; 16195c635efSGarrett D'Amore 162698f87a4SGarrett D'Amore if (MAN_LITERAL & man->flags) 16395c635efSGarrett D'Amore return; 16495c635efSGarrett D'Amore 16595c635efSGarrett D'Amore cp = n->string; 16695c635efSGarrett D'Amore for (p = cp; NULL != (p = strchr(p, '\t')); p++) 167*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_FI_TAB, man->parse, 168*260e9a87SYuri Pankov n->line, n->pos + (p - cp), NULL); 16995c635efSGarrett D'Amore } 17095c635efSGarrett D'Amore 171*260e9a87SYuri Pankov static void 172*260e9a87SYuri Pankov post_OP(CHKARGS) 173698f87a4SGarrett D'Amore { 174698f87a4SGarrett D'Amore 175*260e9a87SYuri Pankov if (n->nchild == 0) 176*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_OP_EMPTY, man->parse, 177*260e9a87SYuri Pankov n->line, n->pos, "OP"); 178*260e9a87SYuri Pankov else if (n->nchild > 2) { 179*260e9a87SYuri Pankov n = n->child->next->next; 180*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse, 181*260e9a87SYuri Pankov n->line, n->pos, "OP ... %s", n->string); 182*260e9a87SYuri Pankov } 183698f87a4SGarrett D'Amore } 184698f87a4SGarrett D'Amore 185*260e9a87SYuri Pankov static void 186*260e9a87SYuri Pankov post_UR(CHKARGS) 187*260e9a87SYuri Pankov { 188*260e9a87SYuri Pankov 189*260e9a87SYuri Pankov if (n->type == MAN_HEAD && n->child == NULL) 190*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_UR_NOHEAD, man->parse, 191*260e9a87SYuri Pankov n->line, n->pos, "UR"); 192*260e9a87SYuri Pankov check_part(man, n); 193*260e9a87SYuri Pankov } 194*260e9a87SYuri Pankov 195*260e9a87SYuri Pankov static void 19695c635efSGarrett D'Amore post_ft(CHKARGS) 19795c635efSGarrett D'Amore { 19895c635efSGarrett D'Amore char *cp; 19995c635efSGarrett D'Amore int ok; 20095c635efSGarrett D'Amore 20195c635efSGarrett D'Amore if (0 == n->nchild) 202*260e9a87SYuri Pankov return; 20395c635efSGarrett D'Amore 20495c635efSGarrett D'Amore ok = 0; 20595c635efSGarrett D'Amore cp = n->child->string; 20695c635efSGarrett D'Amore switch (*cp) { 207*260e9a87SYuri Pankov case '1': 20895c635efSGarrett D'Amore /* FALLTHROUGH */ 209*260e9a87SYuri Pankov case '2': 21095c635efSGarrett D'Amore /* FALLTHROUGH */ 211*260e9a87SYuri Pankov case '3': 21295c635efSGarrett D'Amore /* FALLTHROUGH */ 213*260e9a87SYuri Pankov case '4': 21495c635efSGarrett D'Amore /* FALLTHROUGH */ 215*260e9a87SYuri Pankov case 'I': 21695c635efSGarrett D'Amore /* FALLTHROUGH */ 217*260e9a87SYuri Pankov case 'P': 21895c635efSGarrett D'Amore /* FALLTHROUGH */ 219*260e9a87SYuri Pankov case 'R': 22095c635efSGarrett D'Amore if ('\0' == cp[1]) 22195c635efSGarrett D'Amore ok = 1; 22295c635efSGarrett D'Amore break; 223*260e9a87SYuri Pankov case 'B': 22495c635efSGarrett D'Amore if ('\0' == cp[1] || ('I' == cp[1] && '\0' == cp[2])) 22595c635efSGarrett D'Amore ok = 1; 22695c635efSGarrett D'Amore break; 227*260e9a87SYuri Pankov case 'C': 22895c635efSGarrett D'Amore if ('W' == cp[1] && '\0' == cp[2]) 22995c635efSGarrett D'Amore ok = 1; 23095c635efSGarrett D'Amore break; 23195c635efSGarrett D'Amore default: 23295c635efSGarrett D'Amore break; 23395c635efSGarrett D'Amore } 23495c635efSGarrett D'Amore 23595c635efSGarrett D'Amore if (0 == ok) { 236*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_FT_BAD, man->parse, 237*260e9a87SYuri Pankov n->line, n->pos, "ft %s", cp); 23895c635efSGarrett D'Amore *cp = '\0'; 23995c635efSGarrett D'Amore } 24095c635efSGarrett D'Amore } 24195c635efSGarrett D'Amore 242*260e9a87SYuri Pankov static void 24395c635efSGarrett D'Amore check_part(CHKARGS) 24495c635efSGarrett D'Amore { 24595c635efSGarrett D'Amore 246*260e9a87SYuri Pankov if (n->type == MAN_BODY && n->child == NULL) 247*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_BLK_EMPTY, man->parse, 248*260e9a87SYuri Pankov n->line, n->pos, man_macronames[n->tok]); 24995c635efSGarrett D'Amore } 25095c635efSGarrett D'Amore 251*260e9a87SYuri Pankov static void 25295c635efSGarrett D'Amore check_par(CHKARGS) 25395c635efSGarrett D'Amore { 25495c635efSGarrett D'Amore 25595c635efSGarrett D'Amore switch (n->type) { 256*260e9a87SYuri Pankov case MAN_BLOCK: 25795c635efSGarrett D'Amore if (0 == n->body->nchild) 258698f87a4SGarrett D'Amore man_node_delete(man, n); 25995c635efSGarrett D'Amore break; 260*260e9a87SYuri Pankov case MAN_BODY: 26195c635efSGarrett D'Amore if (0 == n->nchild) 262*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_PAR_SKIP, 263*260e9a87SYuri Pankov man->parse, n->line, n->pos, 264*260e9a87SYuri Pankov "%s empty", man_macronames[n->tok]); 26595c635efSGarrett D'Amore break; 266*260e9a87SYuri Pankov case MAN_HEAD: 26795c635efSGarrett D'Amore if (n->nchild) 268*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_SKIP, 269*260e9a87SYuri Pankov man->parse, n->line, n->pos, 270*260e9a87SYuri Pankov "%s %s%s", man_macronames[n->tok], 271*260e9a87SYuri Pankov n->child->string, 272*260e9a87SYuri Pankov n->nchild > 1 ? " ..." : ""); 27395c635efSGarrett D'Amore break; 27495c635efSGarrett D'Amore default: 27595c635efSGarrett D'Amore break; 27695c635efSGarrett D'Amore } 27795c635efSGarrett D'Amore } 27895c635efSGarrett D'Amore 279*260e9a87SYuri Pankov static void 280698f87a4SGarrett D'Amore post_IP(CHKARGS) 281698f87a4SGarrett D'Amore { 282698f87a4SGarrett D'Amore 283698f87a4SGarrett D'Amore switch (n->type) { 284*260e9a87SYuri Pankov case MAN_BLOCK: 285698f87a4SGarrett D'Amore if (0 == n->head->nchild && 0 == n->body->nchild) 286698f87a4SGarrett D'Amore man_node_delete(man, n); 287698f87a4SGarrett D'Amore break; 288*260e9a87SYuri Pankov case MAN_BODY: 289698f87a4SGarrett D'Amore if (0 == n->parent->head->nchild && 0 == n->nchild) 290*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_PAR_SKIP, 291*260e9a87SYuri Pankov man->parse, n->line, n->pos, 292*260e9a87SYuri Pankov "%s empty", man_macronames[n->tok]); 293698f87a4SGarrett D'Amore break; 294698f87a4SGarrett D'Amore default: 295698f87a4SGarrett D'Amore break; 296698f87a4SGarrett D'Amore } 297698f87a4SGarrett D'Amore } 29895c635efSGarrett D'Amore 299*260e9a87SYuri Pankov static void 30095c635efSGarrett D'Amore post_TH(CHKARGS) 30195c635efSGarrett D'Amore { 302*260e9a87SYuri Pankov struct man_node *nb; 30395c635efSGarrett D'Amore const char *p; 30495c635efSGarrett D'Amore 305698f87a4SGarrett D'Amore free(man->meta.title); 306698f87a4SGarrett D'Amore free(man->meta.vol); 307698f87a4SGarrett D'Amore free(man->meta.source); 308698f87a4SGarrett D'Amore free(man->meta.msec); 309698f87a4SGarrett D'Amore free(man->meta.date); 31095c635efSGarrett D'Amore 311698f87a4SGarrett D'Amore man->meta.title = man->meta.vol = man->meta.date = 312698f87a4SGarrett D'Amore man->meta.msec = man->meta.source = NULL; 31395c635efSGarrett D'Amore 314*260e9a87SYuri Pankov nb = n; 315*260e9a87SYuri Pankov 31695c635efSGarrett D'Amore /* ->TITLE<- MSEC DATE SOURCE VOL */ 31795c635efSGarrett D'Amore 31895c635efSGarrett D'Amore n = n->child; 31995c635efSGarrett D'Amore if (n && n->string) { 32095c635efSGarrett D'Amore for (p = n->string; '\0' != *p; p++) { 32195c635efSGarrett D'Amore /* Only warn about this once... */ 32295c635efSGarrett D'Amore if (isalpha((unsigned char)*p) && 32395c635efSGarrett D'Amore ! isupper((unsigned char)*p)) { 324*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_TITLE_CASE, 325*260e9a87SYuri Pankov man->parse, n->line, 326*260e9a87SYuri Pankov n->pos + (p - n->string), 327*260e9a87SYuri Pankov "TH %s", n->string); 32895c635efSGarrett D'Amore break; 32995c635efSGarrett D'Amore } 33095c635efSGarrett D'Amore } 331698f87a4SGarrett D'Amore man->meta.title = mandoc_strdup(n->string); 332*260e9a87SYuri Pankov } else { 333698f87a4SGarrett D'Amore man->meta.title = mandoc_strdup(""); 334*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_TH_NOTITLE, man->parse, 335*260e9a87SYuri Pankov nb->line, nb->pos, "TH"); 336*260e9a87SYuri Pankov } 33795c635efSGarrett D'Amore 33895c635efSGarrett D'Amore /* TITLE ->MSEC<- DATE SOURCE VOL */ 33995c635efSGarrett D'Amore 34095c635efSGarrett D'Amore if (n) 34195c635efSGarrett D'Amore n = n->next; 34295c635efSGarrett D'Amore if (n && n->string) 343698f87a4SGarrett D'Amore man->meta.msec = mandoc_strdup(n->string); 344*260e9a87SYuri Pankov else { 345698f87a4SGarrett D'Amore man->meta.msec = mandoc_strdup(""); 346*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_MSEC_MISSING, man->parse, 347*260e9a87SYuri Pankov nb->line, nb->pos, "TH %s", man->meta.title); 348*260e9a87SYuri Pankov } 34995c635efSGarrett D'Amore 35095c635efSGarrett D'Amore /* TITLE MSEC ->DATE<- SOURCE VOL */ 35195c635efSGarrett D'Amore 35295c635efSGarrett D'Amore if (n) 35395c635efSGarrett D'Amore n = n->next; 35495c635efSGarrett D'Amore if (n && n->string && '\0' != n->string[0]) { 355*260e9a87SYuri Pankov man->meta.date = man->quick ? 356*260e9a87SYuri Pankov mandoc_strdup(n->string) : 357*260e9a87SYuri Pankov mandoc_normdate(man->parse, n->string, 358*260e9a87SYuri Pankov n->line, n->pos); 359*260e9a87SYuri Pankov } else { 360698f87a4SGarrett D'Amore man->meta.date = mandoc_strdup(""); 361*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_DATE_MISSING, man->parse, 362*260e9a87SYuri Pankov n ? n->line : nb->line, 363*260e9a87SYuri Pankov n ? n->pos : nb->pos, "TH"); 364*260e9a87SYuri Pankov } 36595c635efSGarrett D'Amore 36695c635efSGarrett D'Amore /* TITLE MSEC DATE ->SOURCE<- VOL */ 36795c635efSGarrett D'Amore 36895c635efSGarrett D'Amore if (n && (n = n->next)) 369698f87a4SGarrett D'Amore man->meta.source = mandoc_strdup(n->string); 370*260e9a87SYuri Pankov else if (man->defos != NULL) 371*260e9a87SYuri Pankov man->meta.source = mandoc_strdup(man->defos); 37295c635efSGarrett D'Amore 37395c635efSGarrett D'Amore /* TITLE MSEC DATE SOURCE ->VOL<- */ 37495c635efSGarrett D'Amore /* If missing, use the default VOL name for MSEC. */ 37595c635efSGarrett D'Amore 37695c635efSGarrett D'Amore if (n && (n = n->next)) 377698f87a4SGarrett D'Amore man->meta.vol = mandoc_strdup(n->string); 378698f87a4SGarrett D'Amore else if ('\0' != man->meta.msec[0] && 379698f87a4SGarrett D'Amore (NULL != (p = mandoc_a2msec(man->meta.msec)))) 380698f87a4SGarrett D'Amore man->meta.vol = mandoc_strdup(p); 38195c635efSGarrett D'Amore 382*260e9a87SYuri Pankov if (n != NULL && (n = n->next) != NULL) 383*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse, 384*260e9a87SYuri Pankov n->line, n->pos, "TH ... %s", n->string); 385*260e9a87SYuri Pankov 38695c635efSGarrett D'Amore /* 38795c635efSGarrett D'Amore * Remove the `TH' node after we've processed it for our 38895c635efSGarrett D'Amore * meta-data. 38995c635efSGarrett D'Amore */ 390698f87a4SGarrett D'Amore man_node_delete(man, man->last); 39195c635efSGarrett D'Amore } 39295c635efSGarrett D'Amore 393*260e9a87SYuri Pankov static void 39495c635efSGarrett D'Amore post_nf(CHKARGS) 39595c635efSGarrett D'Amore { 39695c635efSGarrett D'Amore 397*260e9a87SYuri Pankov if (man->flags & MAN_LITERAL) 398*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_NF_SKIP, man->parse, 399*260e9a87SYuri Pankov n->line, n->pos, "nf"); 40095c635efSGarrett D'Amore 401698f87a4SGarrett D'Amore man->flags |= MAN_LITERAL; 40295c635efSGarrett D'Amore } 40395c635efSGarrett D'Amore 404*260e9a87SYuri Pankov static void 40595c635efSGarrett D'Amore post_fi(CHKARGS) 40695c635efSGarrett D'Amore { 40795c635efSGarrett D'Amore 408698f87a4SGarrett D'Amore if ( ! (MAN_LITERAL & man->flags)) 409*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_FI_SKIP, man->parse, 410*260e9a87SYuri Pankov n->line, n->pos, "fi"); 41195c635efSGarrett D'Amore 412698f87a4SGarrett D'Amore man->flags &= ~MAN_LITERAL; 41395c635efSGarrett D'Amore } 41495c635efSGarrett D'Amore 415*260e9a87SYuri Pankov static void 41695c635efSGarrett D'Amore post_UC(CHKARGS) 41795c635efSGarrett D'Amore { 41895c635efSGarrett D'Amore static const char * const bsd_versions[] = { 41995c635efSGarrett D'Amore "3rd Berkeley Distribution", 42095c635efSGarrett D'Amore "4th Berkeley Distribution", 42195c635efSGarrett D'Amore "4.2 Berkeley Distribution", 42295c635efSGarrett D'Amore "4.3 Berkeley Distribution", 42395c635efSGarrett D'Amore "4.4 Berkeley Distribution", 42495c635efSGarrett D'Amore }; 42595c635efSGarrett D'Amore 42695c635efSGarrett D'Amore const char *p, *s; 42795c635efSGarrett D'Amore 42895c635efSGarrett D'Amore n = n->child; 42995c635efSGarrett D'Amore 43095c635efSGarrett D'Amore if (NULL == n || MAN_TEXT != n->type) 43195c635efSGarrett D'Amore p = bsd_versions[0]; 43295c635efSGarrett D'Amore else { 43395c635efSGarrett D'Amore s = n->string; 43495c635efSGarrett D'Amore if (0 == strcmp(s, "3")) 43595c635efSGarrett D'Amore p = bsd_versions[0]; 43695c635efSGarrett D'Amore else if (0 == strcmp(s, "4")) 43795c635efSGarrett D'Amore p = bsd_versions[1]; 43895c635efSGarrett D'Amore else if (0 == strcmp(s, "5")) 43995c635efSGarrett D'Amore p = bsd_versions[2]; 44095c635efSGarrett D'Amore else if (0 == strcmp(s, "6")) 44195c635efSGarrett D'Amore p = bsd_versions[3]; 44295c635efSGarrett D'Amore else if (0 == strcmp(s, "7")) 44395c635efSGarrett D'Amore p = bsd_versions[4]; 44495c635efSGarrett D'Amore else 44595c635efSGarrett D'Amore p = bsd_versions[0]; 44695c635efSGarrett D'Amore } 44795c635efSGarrett D'Amore 448698f87a4SGarrett D'Amore free(man->meta.source); 449698f87a4SGarrett D'Amore man->meta.source = mandoc_strdup(p); 45095c635efSGarrett D'Amore } 45195c635efSGarrett D'Amore 452*260e9a87SYuri Pankov static void 45395c635efSGarrett D'Amore post_AT(CHKARGS) 45495c635efSGarrett D'Amore { 45595c635efSGarrett D'Amore static const char * const unix_versions[] = { 45695c635efSGarrett D'Amore "7th Edition", 45795c635efSGarrett D'Amore "System III", 45895c635efSGarrett D'Amore "System V", 45995c635efSGarrett D'Amore "System V Release 2", 46095c635efSGarrett D'Amore }; 46195c635efSGarrett D'Amore 46295c635efSGarrett D'Amore const char *p, *s; 46395c635efSGarrett D'Amore struct man_node *nn; 46495c635efSGarrett D'Amore 46595c635efSGarrett D'Amore n = n->child; 46695c635efSGarrett D'Amore 46795c635efSGarrett D'Amore if (NULL == n || MAN_TEXT != n->type) 46895c635efSGarrett D'Amore p = unix_versions[0]; 46995c635efSGarrett D'Amore else { 47095c635efSGarrett D'Amore s = n->string; 47195c635efSGarrett D'Amore if (0 == strcmp(s, "3")) 47295c635efSGarrett D'Amore p = unix_versions[0]; 47395c635efSGarrett D'Amore else if (0 == strcmp(s, "4")) 47495c635efSGarrett D'Amore p = unix_versions[1]; 47595c635efSGarrett D'Amore else if (0 == strcmp(s, "5")) { 47695c635efSGarrett D'Amore nn = n->next; 47795c635efSGarrett D'Amore if (nn && MAN_TEXT == nn->type && nn->string[0]) 47895c635efSGarrett D'Amore p = unix_versions[3]; 47995c635efSGarrett D'Amore else 48095c635efSGarrett D'Amore p = unix_versions[2]; 48195c635efSGarrett D'Amore } else 48295c635efSGarrett D'Amore p = unix_versions[0]; 48395c635efSGarrett D'Amore } 48495c635efSGarrett D'Amore 485698f87a4SGarrett D'Amore free(man->meta.source); 486698f87a4SGarrett D'Amore man->meta.source = mandoc_strdup(p); 48795c635efSGarrett D'Amore } 48895c635efSGarrett D'Amore 489*260e9a87SYuri Pankov static void 49095c635efSGarrett D'Amore post_vs(CHKARGS) 49195c635efSGarrett D'Amore { 49295c635efSGarrett D'Amore 493698f87a4SGarrett D'Amore if (NULL != n->prev) 494*260e9a87SYuri Pankov return; 495698f87a4SGarrett D'Amore 496698f87a4SGarrett D'Amore switch (n->parent->tok) { 497*260e9a87SYuri Pankov case MAN_SH: 498698f87a4SGarrett D'Amore /* FALLTHROUGH */ 499*260e9a87SYuri Pankov case MAN_SS: 500*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_PAR_SKIP, man->parse, n->line, n->pos, 501*260e9a87SYuri Pankov "%s after %s", man_macronames[n->tok], 502*260e9a87SYuri Pankov man_macronames[n->parent->tok]); 503698f87a4SGarrett D'Amore /* FALLTHROUGH */ 504*260e9a87SYuri Pankov case MAN_MAX: 50595c635efSGarrett D'Amore /* 506698f87a4SGarrett D'Amore * Don't warn about this because it occurs in pod2man 507698f87a4SGarrett D'Amore * and would cause considerable (unfixable) warnage. 50895c635efSGarrett D'Amore */ 509698f87a4SGarrett D'Amore man_node_delete(man, n); 510698f87a4SGarrett D'Amore break; 511698f87a4SGarrett D'Amore default: 512698f87a4SGarrett D'Amore break; 513698f87a4SGarrett D'Amore } 51495c635efSGarrett D'Amore } 515