1*260e9a87SYuri Pankov /* $Id: mdoc_validate.c,v 1.283 2015/02/23 13:55:55 schwarze Exp $ */ 295c635efSGarrett D'Amore /* 3698f87a4SGarrett D'Amore * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> 4*260e9a87SYuri Pankov * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> 5*260e9a87SYuri Pankov * Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org> 695c635efSGarrett D'Amore * 795c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any 895c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above 995c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies. 1095c635efSGarrett D'Amore * 1195c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1295c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1395c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1495c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1595c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1695c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1795c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1895c635efSGarrett D'Amore */ 1995c635efSGarrett D'Amore #include "config.h" 2095c635efSGarrett D'Amore 21*260e9a87SYuri Pankov #include <sys/types.h> 2295c635efSGarrett D'Amore #ifndef OSNAME 2395c635efSGarrett D'Amore #include <sys/utsname.h> 2495c635efSGarrett D'Amore #endif 2595c635efSGarrett D'Amore 2695c635efSGarrett D'Amore #include <assert.h> 2795c635efSGarrett D'Amore #include <ctype.h> 2895c635efSGarrett D'Amore #include <limits.h> 2995c635efSGarrett D'Amore #include <stdio.h> 3095c635efSGarrett D'Amore #include <stdlib.h> 3195c635efSGarrett D'Amore #include <string.h> 3295c635efSGarrett D'Amore #include <time.h> 3395c635efSGarrett D'Amore 3495c635efSGarrett D'Amore #include "mdoc.h" 3595c635efSGarrett D'Amore #include "mandoc.h" 36*260e9a87SYuri Pankov #include "mandoc_aux.h" 3795c635efSGarrett D'Amore #include "libmdoc.h" 3895c635efSGarrett D'Amore #include "libmandoc.h" 3995c635efSGarrett D'Amore 4095c635efSGarrett D'Amore /* FIXME: .Bl -diag can't have non-text children in HEAD. */ 4195c635efSGarrett D'Amore 4295c635efSGarrett D'Amore #define PRE_ARGS struct mdoc *mdoc, struct mdoc_node *n 4395c635efSGarrett D'Amore #define POST_ARGS struct mdoc *mdoc 4495c635efSGarrett D'Amore 4595c635efSGarrett D'Amore enum check_ineq { 4695c635efSGarrett D'Amore CHECK_LT, 4795c635efSGarrett D'Amore CHECK_GT, 4895c635efSGarrett D'Amore CHECK_EQ 4995c635efSGarrett D'Amore }; 5095c635efSGarrett D'Amore 51*260e9a87SYuri Pankov typedef void (*v_pre)(PRE_ARGS); 52*260e9a87SYuri Pankov typedef void (*v_post)(POST_ARGS); 5395c635efSGarrett D'Amore 5495c635efSGarrett D'Amore struct valids { 55*260e9a87SYuri Pankov v_pre pre; 56*260e9a87SYuri Pankov v_post post; 5795c635efSGarrett D'Amore }; 5895c635efSGarrett D'Amore 5995c635efSGarrett D'Amore static void check_text(struct mdoc *, int, int, char *); 6095c635efSGarrett D'Amore static void check_argv(struct mdoc *, 6195c635efSGarrett D'Amore struct mdoc_node *, struct mdoc_argv *); 6295c635efSGarrett D'Amore static void check_args(struct mdoc *, struct mdoc_node *); 63*260e9a87SYuri Pankov static int child_an(const struct mdoc_node *); 6495c635efSGarrett D'Amore static enum mdoc_sec a2sec(const char *); 6595c635efSGarrett D'Amore static size_t macro2len(enum mdoct); 66*260e9a87SYuri Pankov static void rewrite_macro2len(char **); 6795c635efSGarrett D'Amore 68*260e9a87SYuri Pankov static void post_an(POST_ARGS); 69*260e9a87SYuri Pankov static void post_at(POST_ARGS); 70*260e9a87SYuri Pankov static void post_bf(POST_ARGS); 71*260e9a87SYuri Pankov static void post_bk(POST_ARGS); 72*260e9a87SYuri Pankov static void post_bl(POST_ARGS); 73*260e9a87SYuri Pankov static void post_bl_block(POST_ARGS); 74*260e9a87SYuri Pankov static void post_bl_block_tag(POST_ARGS); 75*260e9a87SYuri Pankov static void post_bl_head(POST_ARGS); 76*260e9a87SYuri Pankov static void post_bx(POST_ARGS); 77*260e9a87SYuri Pankov static void post_d1(POST_ARGS); 78*260e9a87SYuri Pankov static void post_defaults(POST_ARGS); 79*260e9a87SYuri Pankov static void post_dd(POST_ARGS); 80*260e9a87SYuri Pankov static void post_dt(POST_ARGS); 81*260e9a87SYuri Pankov static void post_en(POST_ARGS); 82*260e9a87SYuri Pankov static void post_es(POST_ARGS); 83*260e9a87SYuri Pankov static void post_eoln(POST_ARGS); 84*260e9a87SYuri Pankov static void post_ex(POST_ARGS); 85*260e9a87SYuri Pankov static void post_fa(POST_ARGS); 86*260e9a87SYuri Pankov static void post_fn(POST_ARGS); 87*260e9a87SYuri Pankov static void post_fname(POST_ARGS); 88*260e9a87SYuri Pankov static void post_fo(POST_ARGS); 89*260e9a87SYuri Pankov static void post_hyph(POST_ARGS); 90*260e9a87SYuri Pankov static void post_ignpar(POST_ARGS); 91*260e9a87SYuri Pankov static void post_it(POST_ARGS); 92*260e9a87SYuri Pankov static void post_lb(POST_ARGS); 93*260e9a87SYuri Pankov static void post_literal(POST_ARGS); 94*260e9a87SYuri Pankov static void post_nd(POST_ARGS); 95*260e9a87SYuri Pankov static void post_nm(POST_ARGS); 96*260e9a87SYuri Pankov static void post_ns(POST_ARGS); 97*260e9a87SYuri Pankov static void post_os(POST_ARGS); 98*260e9a87SYuri Pankov static void post_par(POST_ARGS); 99*260e9a87SYuri Pankov static void post_root(POST_ARGS); 100*260e9a87SYuri Pankov static void post_rs(POST_ARGS); 101*260e9a87SYuri Pankov static void post_sh(POST_ARGS); 102*260e9a87SYuri Pankov static void post_sh_head(POST_ARGS); 103*260e9a87SYuri Pankov static void post_sh_name(POST_ARGS); 104*260e9a87SYuri Pankov static void post_sh_see_also(POST_ARGS); 105*260e9a87SYuri Pankov static void post_sh_authors(POST_ARGS); 106*260e9a87SYuri Pankov static void post_sm(POST_ARGS); 107*260e9a87SYuri Pankov static void post_st(POST_ARGS); 108*260e9a87SYuri Pankov static void post_vt(POST_ARGS); 10995c635efSGarrett D'Amore 110*260e9a87SYuri Pankov static void pre_an(PRE_ARGS); 111*260e9a87SYuri Pankov static void pre_bd(PRE_ARGS); 112*260e9a87SYuri Pankov static void pre_bl(PRE_ARGS); 113*260e9a87SYuri Pankov static void pre_dd(PRE_ARGS); 114*260e9a87SYuri Pankov static void pre_display(PRE_ARGS); 115*260e9a87SYuri Pankov static void pre_dt(PRE_ARGS); 116*260e9a87SYuri Pankov static void pre_literal(PRE_ARGS); 117*260e9a87SYuri Pankov static void pre_obsolete(PRE_ARGS); 118*260e9a87SYuri Pankov static void pre_os(PRE_ARGS); 119*260e9a87SYuri Pankov static void pre_par(PRE_ARGS); 120*260e9a87SYuri Pankov static void pre_std(PRE_ARGS); 12195c635efSGarrett D'Amore 12295c635efSGarrett D'Amore static const struct valids mdoc_valids[MDOC_MAX] = { 12395c635efSGarrett D'Amore { NULL, NULL }, /* Ap */ 124*260e9a87SYuri Pankov { pre_dd, post_dd }, /* Dd */ 125*260e9a87SYuri Pankov { pre_dt, post_dt }, /* Dt */ 126*260e9a87SYuri Pankov { pre_os, post_os }, /* Os */ 127*260e9a87SYuri Pankov { NULL, post_sh }, /* Sh */ 128*260e9a87SYuri Pankov { NULL, post_ignpar }, /* Ss */ 129*260e9a87SYuri Pankov { pre_par, post_par }, /* Pp */ 130*260e9a87SYuri Pankov { pre_display, post_d1 }, /* D1 */ 131*260e9a87SYuri Pankov { pre_literal, post_literal }, /* Dl */ 132*260e9a87SYuri Pankov { pre_bd, post_literal }, /* Bd */ 13395c635efSGarrett D'Amore { NULL, NULL }, /* Ed */ 134*260e9a87SYuri Pankov { pre_bl, post_bl }, /* Bl */ 13595c635efSGarrett D'Amore { NULL, NULL }, /* El */ 136*260e9a87SYuri Pankov { pre_par, post_it }, /* It */ 13795c635efSGarrett D'Amore { NULL, NULL }, /* Ad */ 138*260e9a87SYuri Pankov { pre_an, post_an }, /* An */ 139*260e9a87SYuri Pankov { NULL, post_defaults }, /* Ar */ 14095c635efSGarrett D'Amore { NULL, NULL }, /* Cd */ 14195c635efSGarrett D'Amore { NULL, NULL }, /* Cm */ 14295c635efSGarrett D'Amore { NULL, NULL }, /* Dv */ 143698f87a4SGarrett D'Amore { NULL, NULL }, /* Er */ 14495c635efSGarrett D'Amore { NULL, NULL }, /* Ev */ 145*260e9a87SYuri Pankov { pre_std, post_ex }, /* Ex */ 146*260e9a87SYuri Pankov { NULL, post_fa }, /* Fa */ 147*260e9a87SYuri Pankov { NULL, NULL }, /* Fd */ 14895c635efSGarrett D'Amore { NULL, NULL }, /* Fl */ 149*260e9a87SYuri Pankov { NULL, post_fn }, /* Fn */ 15095c635efSGarrett D'Amore { NULL, NULL }, /* Ft */ 15195c635efSGarrett D'Amore { NULL, NULL }, /* Ic */ 152*260e9a87SYuri Pankov { NULL, NULL }, /* In */ 153*260e9a87SYuri Pankov { NULL, post_defaults }, /* Li */ 154*260e9a87SYuri Pankov { NULL, post_nd }, /* Nd */ 155*260e9a87SYuri Pankov { NULL, post_nm }, /* Nm */ 15695c635efSGarrett D'Amore { NULL, NULL }, /* Op */ 157*260e9a87SYuri Pankov { pre_obsolete, NULL }, /* Ot */ 158*260e9a87SYuri Pankov { NULL, post_defaults }, /* Pa */ 159*260e9a87SYuri Pankov { pre_std, NULL }, /* Rv */ 160*260e9a87SYuri Pankov { NULL, post_st }, /* St */ 16195c635efSGarrett D'Amore { NULL, NULL }, /* Va */ 162*260e9a87SYuri Pankov { NULL, post_vt }, /* Vt */ 163*260e9a87SYuri Pankov { NULL, NULL }, /* Xr */ 164*260e9a87SYuri Pankov { NULL, NULL }, /* %A */ 165*260e9a87SYuri Pankov { NULL, post_hyph }, /* %B */ /* FIXME: can be used outside Rs/Re. */ 166*260e9a87SYuri Pankov { NULL, NULL }, /* %D */ 167*260e9a87SYuri Pankov { NULL, NULL }, /* %I */ 168*260e9a87SYuri Pankov { NULL, NULL }, /* %J */ 169*260e9a87SYuri Pankov { NULL, post_hyph }, /* %N */ 170*260e9a87SYuri Pankov { NULL, post_hyph }, /* %O */ 171*260e9a87SYuri Pankov { NULL, NULL }, /* %P */ 172*260e9a87SYuri Pankov { NULL, post_hyph }, /* %R */ 173*260e9a87SYuri Pankov { NULL, post_hyph }, /* %T */ /* FIXME: can be used outside Rs/Re. */ 174*260e9a87SYuri Pankov { NULL, NULL }, /* %V */ 17595c635efSGarrett D'Amore { NULL, NULL }, /* Ac */ 17695c635efSGarrett D'Amore { NULL, NULL }, /* Ao */ 17795c635efSGarrett D'Amore { NULL, NULL }, /* Aq */ 178*260e9a87SYuri Pankov { NULL, post_at }, /* At */ 17995c635efSGarrett D'Amore { NULL, NULL }, /* Bc */ 180*260e9a87SYuri Pankov { NULL, post_bf }, /* Bf */ 18195c635efSGarrett D'Amore { NULL, NULL }, /* Bo */ 18295c635efSGarrett D'Amore { NULL, NULL }, /* Bq */ 18395c635efSGarrett D'Amore { NULL, NULL }, /* Bsx */ 184*260e9a87SYuri Pankov { NULL, post_bx }, /* Bx */ 185*260e9a87SYuri Pankov { pre_obsolete, NULL }, /* Db */ 18695c635efSGarrett D'Amore { NULL, NULL }, /* Dc */ 18795c635efSGarrett D'Amore { NULL, NULL }, /* Do */ 18895c635efSGarrett D'Amore { NULL, NULL }, /* Dq */ 18995c635efSGarrett D'Amore { NULL, NULL }, /* Ec */ 19095c635efSGarrett D'Amore { NULL, NULL }, /* Ef */ 19195c635efSGarrett D'Amore { NULL, NULL }, /* Em */ 19295c635efSGarrett D'Amore { NULL, NULL }, /* Eo */ 19395c635efSGarrett D'Amore { NULL, NULL }, /* Fx */ 19495c635efSGarrett D'Amore { NULL, NULL }, /* Ms */ 195*260e9a87SYuri Pankov { NULL, NULL }, /* No */ 196*260e9a87SYuri Pankov { NULL, post_ns }, /* Ns */ 19795c635efSGarrett D'Amore { NULL, NULL }, /* Nx */ 19895c635efSGarrett D'Amore { NULL, NULL }, /* Ox */ 19995c635efSGarrett D'Amore { NULL, NULL }, /* Pc */ 200*260e9a87SYuri Pankov { NULL, NULL }, /* Pf */ 20195c635efSGarrett D'Amore { NULL, NULL }, /* Po */ 20295c635efSGarrett D'Amore { NULL, NULL }, /* Pq */ 20395c635efSGarrett D'Amore { NULL, NULL }, /* Qc */ 20495c635efSGarrett D'Amore { NULL, NULL }, /* Ql */ 20595c635efSGarrett D'Amore { NULL, NULL }, /* Qo */ 20695c635efSGarrett D'Amore { NULL, NULL }, /* Qq */ 20795c635efSGarrett D'Amore { NULL, NULL }, /* Re */ 208*260e9a87SYuri Pankov { NULL, post_rs }, /* Rs */ 20995c635efSGarrett D'Amore { NULL, NULL }, /* Sc */ 21095c635efSGarrett D'Amore { NULL, NULL }, /* So */ 21195c635efSGarrett D'Amore { NULL, NULL }, /* Sq */ 212*260e9a87SYuri Pankov { NULL, post_sm }, /* Sm */ 213*260e9a87SYuri Pankov { NULL, post_hyph }, /* Sx */ 21495c635efSGarrett D'Amore { NULL, NULL }, /* Sy */ 21595c635efSGarrett D'Amore { NULL, NULL }, /* Tn */ 21695c635efSGarrett D'Amore { NULL, NULL }, /* Ux */ 21795c635efSGarrett D'Amore { NULL, NULL }, /* Xc */ 21895c635efSGarrett D'Amore { NULL, NULL }, /* Xo */ 219*260e9a87SYuri Pankov { NULL, post_fo }, /* Fo */ 22095c635efSGarrett D'Amore { NULL, NULL }, /* Fc */ 22195c635efSGarrett D'Amore { NULL, NULL }, /* Oo */ 22295c635efSGarrett D'Amore { NULL, NULL }, /* Oc */ 223*260e9a87SYuri Pankov { NULL, post_bk }, /* Bk */ 22495c635efSGarrett D'Amore { NULL, NULL }, /* Ek */ 225*260e9a87SYuri Pankov { NULL, post_eoln }, /* Bt */ 22695c635efSGarrett D'Amore { NULL, NULL }, /* Hf */ 227*260e9a87SYuri Pankov { pre_obsolete, NULL }, /* Fr */ 228*260e9a87SYuri Pankov { NULL, post_eoln }, /* Ud */ 229*260e9a87SYuri Pankov { NULL, post_lb }, /* Lb */ 230*260e9a87SYuri Pankov { pre_par, post_par }, /* Lp */ 23195c635efSGarrett D'Amore { NULL, NULL }, /* Lk */ 232*260e9a87SYuri Pankov { NULL, post_defaults }, /* Mt */ 23395c635efSGarrett D'Amore { NULL, NULL }, /* Brq */ 23495c635efSGarrett D'Amore { NULL, NULL }, /* Bro */ 23595c635efSGarrett D'Amore { NULL, NULL }, /* Brc */ 236*260e9a87SYuri Pankov { NULL, NULL }, /* %C */ 237*260e9a87SYuri Pankov { pre_obsolete, post_es }, /* Es */ 238*260e9a87SYuri Pankov { pre_obsolete, post_en }, /* En */ 23995c635efSGarrett D'Amore { NULL, NULL }, /* Dx */ 240*260e9a87SYuri Pankov { NULL, NULL }, /* %Q */ 241*260e9a87SYuri Pankov { NULL, post_par }, /* br */ 242*260e9a87SYuri Pankov { NULL, post_par }, /* sp */ 243*260e9a87SYuri Pankov { NULL, NULL }, /* %U */ 24495c635efSGarrett D'Amore { NULL, NULL }, /* Ta */ 245*260e9a87SYuri Pankov { NULL, NULL }, /* ll */ 24695c635efSGarrett D'Amore }; 24795c635efSGarrett D'Amore 24895c635efSGarrett D'Amore #define RSORD_MAX 14 /* Number of `Rs' blocks. */ 24995c635efSGarrett D'Amore 25095c635efSGarrett D'Amore static const enum mdoct rsord[RSORD_MAX] = { 25195c635efSGarrett D'Amore MDOC__A, 25295c635efSGarrett D'Amore MDOC__T, 25395c635efSGarrett D'Amore MDOC__B, 25495c635efSGarrett D'Amore MDOC__I, 25595c635efSGarrett D'Amore MDOC__J, 25695c635efSGarrett D'Amore MDOC__R, 25795c635efSGarrett D'Amore MDOC__N, 25895c635efSGarrett D'Amore MDOC__V, 259698f87a4SGarrett D'Amore MDOC__U, 26095c635efSGarrett D'Amore MDOC__P, 26195c635efSGarrett D'Amore MDOC__Q, 26295c635efSGarrett D'Amore MDOC__C, 263698f87a4SGarrett D'Amore MDOC__D, 264698f87a4SGarrett D'Amore MDOC__O 26595c635efSGarrett D'Amore }; 26695c635efSGarrett D'Amore 26795c635efSGarrett D'Amore static const char * const secnames[SEC__MAX] = { 26895c635efSGarrett D'Amore NULL, 26995c635efSGarrett D'Amore "NAME", 27095c635efSGarrett D'Amore "LIBRARY", 27195c635efSGarrett D'Amore "SYNOPSIS", 27295c635efSGarrett D'Amore "DESCRIPTION", 273*260e9a87SYuri Pankov "CONTEXT", 27495c635efSGarrett D'Amore "IMPLEMENTATION NOTES", 27595c635efSGarrett D'Amore "RETURN VALUES", 27695c635efSGarrett D'Amore "ENVIRONMENT", 27795c635efSGarrett D'Amore "FILES", 27895c635efSGarrett D'Amore "EXIT STATUS", 27995c635efSGarrett D'Amore "EXAMPLES", 28095c635efSGarrett D'Amore "DIAGNOSTICS", 28195c635efSGarrett D'Amore "COMPATIBILITY", 28295c635efSGarrett D'Amore "ERRORS", 28395c635efSGarrett D'Amore "SEE ALSO", 28495c635efSGarrett D'Amore "STANDARDS", 28595c635efSGarrett D'Amore "HISTORY", 28695c635efSGarrett D'Amore "AUTHORS", 28795c635efSGarrett D'Amore "CAVEATS", 28895c635efSGarrett D'Amore "BUGS", 28995c635efSGarrett D'Amore "SECURITY CONSIDERATIONS", 29095c635efSGarrett D'Amore NULL 29195c635efSGarrett D'Amore }; 29295c635efSGarrett D'Amore 293*260e9a87SYuri Pankov 294*260e9a87SYuri Pankov void 29595c635efSGarrett D'Amore mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *n) 29695c635efSGarrett D'Amore { 297*260e9a87SYuri Pankov v_pre p; 29895c635efSGarrett D'Amore 29995c635efSGarrett D'Amore switch (n->type) { 300*260e9a87SYuri Pankov case MDOC_TEXT: 301*260e9a87SYuri Pankov if (n->sec != SEC_SYNOPSIS || n->parent->tok != MDOC_Fd) 302*260e9a87SYuri Pankov check_text(mdoc, n->line, n->pos, n->string); 30395c635efSGarrett D'Amore /* FALLTHROUGH */ 304*260e9a87SYuri Pankov case MDOC_TBL: 30595c635efSGarrett D'Amore /* FALLTHROUGH */ 306*260e9a87SYuri Pankov case MDOC_EQN: 30795c635efSGarrett D'Amore /* FALLTHROUGH */ 308*260e9a87SYuri Pankov case MDOC_ROOT: 309*260e9a87SYuri Pankov return; 31095c635efSGarrett D'Amore default: 31195c635efSGarrett D'Amore break; 31295c635efSGarrett D'Amore } 31395c635efSGarrett D'Amore 31495c635efSGarrett D'Amore check_args(mdoc, n); 315*260e9a87SYuri Pankov p = mdoc_valids[n->tok].pre; 316*260e9a87SYuri Pankov if (*p) 317*260e9a87SYuri Pankov (*p)(mdoc, n); 31895c635efSGarrett D'Amore } 31995c635efSGarrett D'Amore 320*260e9a87SYuri Pankov void 32195c635efSGarrett D'Amore mdoc_valid_post(struct mdoc *mdoc) 32295c635efSGarrett D'Amore { 323*260e9a87SYuri Pankov struct mdoc_node *n; 324*260e9a87SYuri Pankov v_post p; 32595c635efSGarrett D'Amore 326*260e9a87SYuri Pankov n = mdoc->last; 327*260e9a87SYuri Pankov if (n->flags & MDOC_VALID) 328*260e9a87SYuri Pankov return; 329*260e9a87SYuri Pankov n->flags |= MDOC_VALID | MDOC_ENDED; 33095c635efSGarrett D'Amore 331*260e9a87SYuri Pankov switch (n->type) { 332*260e9a87SYuri Pankov case MDOC_TEXT: 33395c635efSGarrett D'Amore /* FALLTHROUGH */ 334*260e9a87SYuri Pankov case MDOC_EQN: 33595c635efSGarrett D'Amore /* FALLTHROUGH */ 336*260e9a87SYuri Pankov case MDOC_TBL: 33795c635efSGarrett D'Amore break; 338*260e9a87SYuri Pankov case MDOC_ROOT: 339*260e9a87SYuri Pankov post_root(mdoc); 34095c635efSGarrett D'Amore break; 34195c635efSGarrett D'Amore default: 342*260e9a87SYuri Pankov 343*260e9a87SYuri Pankov /* 344*260e9a87SYuri Pankov * Closing delimiters are not special at the 345*260e9a87SYuri Pankov * beginning of a block, opening delimiters 346*260e9a87SYuri Pankov * are not special at the end. 347*260e9a87SYuri Pankov */ 348*260e9a87SYuri Pankov 349*260e9a87SYuri Pankov if (n->child != NULL) 350*260e9a87SYuri Pankov n->child->flags &= ~MDOC_DELIMC; 351*260e9a87SYuri Pankov if (n->last != NULL) 352*260e9a87SYuri Pankov n->last->flags &= ~MDOC_DELIMO; 353*260e9a87SYuri Pankov 354*260e9a87SYuri Pankov /* Call the macro's postprocessor. */ 355*260e9a87SYuri Pankov 356*260e9a87SYuri Pankov p = mdoc_valids[n->tok].post; 357*260e9a87SYuri Pankov if (*p) 358*260e9a87SYuri Pankov (*p)(mdoc); 359*260e9a87SYuri Pankov break; 36095c635efSGarrett D'Amore } 36195c635efSGarrett D'Amore } 36295c635efSGarrett D'Amore 36395c635efSGarrett D'Amore static void 364698f87a4SGarrett D'Amore check_args(struct mdoc *mdoc, struct mdoc_node *n) 36595c635efSGarrett D'Amore { 36695c635efSGarrett D'Amore int i; 36795c635efSGarrett D'Amore 36895c635efSGarrett D'Amore if (NULL == n->args) 36995c635efSGarrett D'Amore return; 37095c635efSGarrett D'Amore 37195c635efSGarrett D'Amore assert(n->args->argc); 37295c635efSGarrett D'Amore for (i = 0; i < (int)n->args->argc; i++) 373698f87a4SGarrett D'Amore check_argv(mdoc, n, &n->args->argv[i]); 37495c635efSGarrett D'Amore } 37595c635efSGarrett D'Amore 37695c635efSGarrett D'Amore static void 377698f87a4SGarrett D'Amore check_argv(struct mdoc *mdoc, struct mdoc_node *n, struct mdoc_argv *v) 37895c635efSGarrett D'Amore { 37995c635efSGarrett D'Amore int i; 38095c635efSGarrett D'Amore 38195c635efSGarrett D'Amore for (i = 0; i < (int)v->sz; i++) 382698f87a4SGarrett D'Amore check_text(mdoc, v->line, v->pos, v->value[i]); 38395c635efSGarrett D'Amore } 38495c635efSGarrett D'Amore 38595c635efSGarrett D'Amore static void 386698f87a4SGarrett D'Amore check_text(struct mdoc *mdoc, int ln, int pos, char *p) 38795c635efSGarrett D'Amore { 38895c635efSGarrett D'Amore char *cp; 38995c635efSGarrett D'Amore 390698f87a4SGarrett D'Amore if (MDOC_LITERAL & mdoc->flags) 39195c635efSGarrett D'Amore return; 39295c635efSGarrett D'Amore 39395c635efSGarrett D'Amore for (cp = p; NULL != (p = strchr(p, '\t')); p++) 394*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_FI_TAB, mdoc->parse, 395*260e9a87SYuri Pankov ln, pos + (int)(p - cp), NULL); 39695c635efSGarrett D'Amore } 39795c635efSGarrett D'Amore 398*260e9a87SYuri Pankov static void 39995c635efSGarrett D'Amore pre_display(PRE_ARGS) 40095c635efSGarrett D'Amore { 40195c635efSGarrett D'Amore struct mdoc_node *node; 40295c635efSGarrett D'Amore 40395c635efSGarrett D'Amore if (MDOC_BLOCK != n->type) 404*260e9a87SYuri Pankov return; 40595c635efSGarrett D'Amore 40695c635efSGarrett D'Amore for (node = mdoc->last->parent; node; node = node->parent) 40795c635efSGarrett D'Amore if (MDOC_BLOCK == node->type) 40895c635efSGarrett D'Amore if (MDOC_Bd == node->tok) 40995c635efSGarrett D'Amore break; 41095c635efSGarrett D'Amore 41195c635efSGarrett D'Amore if (node) 412*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_BD_NEST, 413*260e9a87SYuri Pankov mdoc->parse, n->line, n->pos, 414*260e9a87SYuri Pankov "%s in Bd", mdoc_macronames[n->tok]); 41595c635efSGarrett D'Amore } 41695c635efSGarrett D'Amore 417*260e9a87SYuri Pankov static void 41895c635efSGarrett D'Amore pre_bl(PRE_ARGS) 41995c635efSGarrett D'Amore { 420*260e9a87SYuri Pankov struct mdoc_argv *argv, *wa; 421*260e9a87SYuri Pankov int i; 422*260e9a87SYuri Pankov enum mdocargt mdoclt; 42395c635efSGarrett D'Amore enum mdoc_list lt; 42495c635efSGarrett D'Amore 425*260e9a87SYuri Pankov if (n->type != MDOC_BLOCK) 426*260e9a87SYuri Pankov return; 42795c635efSGarrett D'Amore 42895c635efSGarrett D'Amore /* 42995c635efSGarrett D'Amore * First figure out which kind of list to use: bind ourselves to 43095c635efSGarrett D'Amore * the first mentioned list type and warn about any remaining 43195c635efSGarrett D'Amore * ones. If we find no list type, we default to LIST_item. 43295c635efSGarrett D'Amore */ 43395c635efSGarrett D'Amore 434*260e9a87SYuri Pankov wa = (n->args == NULL) ? NULL : n->args->argv; 435*260e9a87SYuri Pankov mdoclt = MDOC_ARG_MAX; 43695c635efSGarrett D'Amore for (i = 0; n->args && i < (int)n->args->argc; i++) { 437*260e9a87SYuri Pankov argv = n->args->argv + i; 43895c635efSGarrett D'Amore lt = LIST__NONE; 439*260e9a87SYuri Pankov switch (argv->arg) { 44095c635efSGarrett D'Amore /* Set list types. */ 441*260e9a87SYuri Pankov case MDOC_Bullet: 44295c635efSGarrett D'Amore lt = LIST_bullet; 44395c635efSGarrett D'Amore break; 444*260e9a87SYuri Pankov case MDOC_Dash: 44595c635efSGarrett D'Amore lt = LIST_dash; 44695c635efSGarrett D'Amore break; 447*260e9a87SYuri Pankov case MDOC_Enum: 44895c635efSGarrett D'Amore lt = LIST_enum; 44995c635efSGarrett D'Amore break; 450*260e9a87SYuri Pankov case MDOC_Hyphen: 45195c635efSGarrett D'Amore lt = LIST_hyphen; 45295c635efSGarrett D'Amore break; 453*260e9a87SYuri Pankov case MDOC_Item: 45495c635efSGarrett D'Amore lt = LIST_item; 45595c635efSGarrett D'Amore break; 456*260e9a87SYuri Pankov case MDOC_Tag: 45795c635efSGarrett D'Amore lt = LIST_tag; 45895c635efSGarrett D'Amore break; 459*260e9a87SYuri Pankov case MDOC_Diag: 46095c635efSGarrett D'Amore lt = LIST_diag; 46195c635efSGarrett D'Amore break; 462*260e9a87SYuri Pankov case MDOC_Hang: 46395c635efSGarrett D'Amore lt = LIST_hang; 46495c635efSGarrett D'Amore break; 465*260e9a87SYuri Pankov case MDOC_Ohang: 46695c635efSGarrett D'Amore lt = LIST_ohang; 46795c635efSGarrett D'Amore break; 468*260e9a87SYuri Pankov case MDOC_Inset: 46995c635efSGarrett D'Amore lt = LIST_inset; 47095c635efSGarrett D'Amore break; 471*260e9a87SYuri Pankov case MDOC_Column: 47295c635efSGarrett D'Amore lt = LIST_column; 47395c635efSGarrett D'Amore break; 47495c635efSGarrett D'Amore /* Set list arguments. */ 475*260e9a87SYuri Pankov case MDOC_Compact: 476*260e9a87SYuri Pankov if (n->norm->Bl.comp) 477*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_ARG_REP, 478*260e9a87SYuri Pankov mdoc->parse, argv->line, 479*260e9a87SYuri Pankov argv->pos, "Bl -compact"); 480*260e9a87SYuri Pankov n->norm->Bl.comp = 1; 48195c635efSGarrett D'Amore break; 482*260e9a87SYuri Pankov case MDOC_Width: 483*260e9a87SYuri Pankov wa = argv; 484*260e9a87SYuri Pankov if (0 == argv->sz) { 485*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_ARG_EMPTY, 486*260e9a87SYuri Pankov mdoc->parse, argv->line, 487*260e9a87SYuri Pankov argv->pos, "Bl -width"); 488*260e9a87SYuri Pankov n->norm->Bl.width = "0n"; 48995c635efSGarrett D'Amore break; 49095c635efSGarrett D'Amore } 491*260e9a87SYuri Pankov if (NULL != n->norm->Bl.width) 492*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_REP, 493*260e9a87SYuri Pankov mdoc->parse, argv->line, 494*260e9a87SYuri Pankov argv->pos, "Bl -width %s", 495*260e9a87SYuri Pankov argv->value[0]); 496*260e9a87SYuri Pankov rewrite_macro2len(argv->value); 497*260e9a87SYuri Pankov n->norm->Bl.width = argv->value[0]; 49895c635efSGarrett D'Amore break; 499*260e9a87SYuri Pankov case MDOC_Offset: 500*260e9a87SYuri Pankov if (0 == argv->sz) { 501*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_ARG_EMPTY, 502*260e9a87SYuri Pankov mdoc->parse, argv->line, 503*260e9a87SYuri Pankov argv->pos, "Bl -offset"); 50495c635efSGarrett D'Amore break; 50595c635efSGarrett D'Amore } 506*260e9a87SYuri Pankov if (NULL != n->norm->Bl.offs) 507*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_REP, 508*260e9a87SYuri Pankov mdoc->parse, argv->line, 509*260e9a87SYuri Pankov argv->pos, "Bl -offset %s", 510*260e9a87SYuri Pankov argv->value[0]); 511*260e9a87SYuri Pankov rewrite_macro2len(argv->value); 512*260e9a87SYuri Pankov n->norm->Bl.offs = argv->value[0]; 51395c635efSGarrett D'Amore break; 51495c635efSGarrett D'Amore default: 51595c635efSGarrett D'Amore continue; 51695c635efSGarrett D'Amore } 517*260e9a87SYuri Pankov if (LIST__NONE == lt) 518*260e9a87SYuri Pankov continue; 519*260e9a87SYuri Pankov mdoclt = argv->arg; 52095c635efSGarrett D'Amore 52195c635efSGarrett D'Amore /* Check: multiple list types. */ 52295c635efSGarrett D'Amore 523*260e9a87SYuri Pankov if (LIST__NONE != n->norm->Bl.type) { 524*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_BL_REP, 525*260e9a87SYuri Pankov mdoc->parse, n->line, n->pos, 526*260e9a87SYuri Pankov "Bl -%s", mdoc_argnames[argv->arg]); 527*260e9a87SYuri Pankov continue; 52895c635efSGarrett D'Amore } 52995c635efSGarrett D'Amore 53095c635efSGarrett D'Amore /* The list type should come first. */ 53195c635efSGarrett D'Amore 53295c635efSGarrett D'Amore if (n->norm->Bl.width || 53395c635efSGarrett D'Amore n->norm->Bl.offs || 53495c635efSGarrett D'Amore n->norm->Bl.comp) 535*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_BL_LATETYPE, 536*260e9a87SYuri Pankov mdoc->parse, n->line, n->pos, "Bl -%s", 537*260e9a87SYuri Pankov mdoc_argnames[n->args->argv[0].arg]); 53895c635efSGarrett D'Amore 539*260e9a87SYuri Pankov n->norm->Bl.type = lt; 540*260e9a87SYuri Pankov if (LIST_column == lt) { 541*260e9a87SYuri Pankov n->norm->Bl.ncols = argv->sz; 542*260e9a87SYuri Pankov n->norm->Bl.cols = (void *)argv->value; 543*260e9a87SYuri Pankov } 54495c635efSGarrett D'Amore } 54595c635efSGarrett D'Amore 54695c635efSGarrett D'Amore /* Allow lists to default to LIST_item. */ 54795c635efSGarrett D'Amore 54895c635efSGarrett D'Amore if (LIST__NONE == n->norm->Bl.type) { 549*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_BL_NOTYPE, mdoc->parse, 550*260e9a87SYuri Pankov n->line, n->pos, "Bl"); 55195c635efSGarrett D'Amore n->norm->Bl.type = LIST_item; 55295c635efSGarrett D'Amore } 55395c635efSGarrett D'Amore 55495c635efSGarrett D'Amore /* 55595c635efSGarrett D'Amore * Validate the width field. Some list types don't need width 55695c635efSGarrett D'Amore * types and should be warned about them. Others should have it 557698f87a4SGarrett D'Amore * and must also be warned. Yet others have a default and need 558698f87a4SGarrett D'Amore * no warning. 55995c635efSGarrett D'Amore */ 56095c635efSGarrett D'Amore 56195c635efSGarrett D'Amore switch (n->norm->Bl.type) { 562*260e9a87SYuri Pankov case LIST_tag: 563698f87a4SGarrett D'Amore if (NULL == n->norm->Bl.width) 564*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_BL_NOWIDTH, mdoc->parse, 565*260e9a87SYuri Pankov n->line, n->pos, "Bl -tag"); 56695c635efSGarrett D'Amore break; 567*260e9a87SYuri Pankov case LIST_column: 56895c635efSGarrett D'Amore /* FALLTHROUGH */ 569*260e9a87SYuri Pankov case LIST_diag: 57095c635efSGarrett D'Amore /* FALLTHROUGH */ 571*260e9a87SYuri Pankov case LIST_ohang: 57295c635efSGarrett D'Amore /* FALLTHROUGH */ 573*260e9a87SYuri Pankov case LIST_inset: 57495c635efSGarrett D'Amore /* FALLTHROUGH */ 575*260e9a87SYuri Pankov case LIST_item: 57695c635efSGarrett D'Amore if (n->norm->Bl.width) 577*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_BL_SKIPW, mdoc->parse, 578*260e9a87SYuri Pankov wa->line, wa->pos, "Bl -%s", 579*260e9a87SYuri Pankov mdoc_argnames[mdoclt]); 58095c635efSGarrett D'Amore break; 581*260e9a87SYuri Pankov case LIST_bullet: 582698f87a4SGarrett D'Amore /* FALLTHROUGH */ 583*260e9a87SYuri Pankov case LIST_dash: 584698f87a4SGarrett D'Amore /* FALLTHROUGH */ 585*260e9a87SYuri Pankov case LIST_hyphen: 586698f87a4SGarrett D'Amore if (NULL == n->norm->Bl.width) 587698f87a4SGarrett D'Amore n->norm->Bl.width = "2n"; 588698f87a4SGarrett D'Amore break; 589*260e9a87SYuri Pankov case LIST_enum: 590698f87a4SGarrett D'Amore if (NULL == n->norm->Bl.width) 591698f87a4SGarrett D'Amore n->norm->Bl.width = "3n"; 592698f87a4SGarrett D'Amore break; 59395c635efSGarrett D'Amore default: 59495c635efSGarrett D'Amore break; 59595c635efSGarrett D'Amore } 596*260e9a87SYuri Pankov pre_par(mdoc, n); 59795c635efSGarrett D'Amore } 59895c635efSGarrett D'Amore 599*260e9a87SYuri Pankov static void 60095c635efSGarrett D'Amore pre_bd(PRE_ARGS) 60195c635efSGarrett D'Amore { 602*260e9a87SYuri Pankov struct mdoc_argv *argv; 603*260e9a87SYuri Pankov int i; 60495c635efSGarrett D'Amore enum mdoc_disp dt; 60595c635efSGarrett D'Amore 606*260e9a87SYuri Pankov pre_literal(mdoc, n); 60795c635efSGarrett D'Amore 608*260e9a87SYuri Pankov if (n->type != MDOC_BLOCK) 609*260e9a87SYuri Pankov return; 61095c635efSGarrett D'Amore 61195c635efSGarrett D'Amore for (i = 0; n->args && i < (int)n->args->argc; i++) { 612*260e9a87SYuri Pankov argv = n->args->argv + i; 61395c635efSGarrett D'Amore dt = DISP__NONE; 61495c635efSGarrett D'Amore 615*260e9a87SYuri Pankov switch (argv->arg) { 616*260e9a87SYuri Pankov case MDOC_Centred: 617*260e9a87SYuri Pankov dt = DISP_centered; 61895c635efSGarrett D'Amore break; 619*260e9a87SYuri Pankov case MDOC_Ragged: 62095c635efSGarrett D'Amore dt = DISP_ragged; 62195c635efSGarrett D'Amore break; 622*260e9a87SYuri Pankov case MDOC_Unfilled: 62395c635efSGarrett D'Amore dt = DISP_unfilled; 62495c635efSGarrett D'Amore break; 625*260e9a87SYuri Pankov case MDOC_Filled: 62695c635efSGarrett D'Amore dt = DISP_filled; 62795c635efSGarrett D'Amore break; 628*260e9a87SYuri Pankov case MDOC_Literal: 62995c635efSGarrett D'Amore dt = DISP_literal; 63095c635efSGarrett D'Amore break; 631*260e9a87SYuri Pankov case MDOC_File: 632*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_BD_FILE, mdoc->parse, 633*260e9a87SYuri Pankov n->line, n->pos, NULL); 634*260e9a87SYuri Pankov break; 635*260e9a87SYuri Pankov case MDOC_Offset: 636*260e9a87SYuri Pankov if (0 == argv->sz) { 637*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_ARG_EMPTY, 638*260e9a87SYuri Pankov mdoc->parse, argv->line, 639*260e9a87SYuri Pankov argv->pos, "Bd -offset"); 64095c635efSGarrett D'Amore break; 64195c635efSGarrett D'Amore } 642*260e9a87SYuri Pankov if (NULL != n->norm->Bd.offs) 643*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_REP, 644*260e9a87SYuri Pankov mdoc->parse, argv->line, 645*260e9a87SYuri Pankov argv->pos, "Bd -offset %s", 646*260e9a87SYuri Pankov argv->value[0]); 647*260e9a87SYuri Pankov rewrite_macro2len(argv->value); 648*260e9a87SYuri Pankov n->norm->Bd.offs = argv->value[0]; 64995c635efSGarrett D'Amore break; 650*260e9a87SYuri Pankov case MDOC_Compact: 651*260e9a87SYuri Pankov if (n->norm->Bd.comp) 652*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_ARG_REP, 653*260e9a87SYuri Pankov mdoc->parse, argv->line, 654*260e9a87SYuri Pankov argv->pos, "Bd -compact"); 655*260e9a87SYuri Pankov n->norm->Bd.comp = 1; 65695c635efSGarrett D'Amore break; 65795c635efSGarrett D'Amore default: 65895c635efSGarrett D'Amore abort(); 65995c635efSGarrett D'Amore /* NOTREACHED */ 66095c635efSGarrett D'Amore } 661*260e9a87SYuri Pankov if (DISP__NONE == dt) 662*260e9a87SYuri Pankov continue; 66395c635efSGarrett D'Amore 664*260e9a87SYuri Pankov if (DISP__NONE == n->norm->Bd.type) 66595c635efSGarrett D'Amore n->norm->Bd.type = dt; 666*260e9a87SYuri Pankov else 667*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_BD_REP, 668*260e9a87SYuri Pankov mdoc->parse, n->line, n->pos, 669*260e9a87SYuri Pankov "Bd -%s", mdoc_argnames[argv->arg]); 67095c635efSGarrett D'Amore } 67195c635efSGarrett D'Amore 67295c635efSGarrett D'Amore if (DISP__NONE == n->norm->Bd.type) { 673*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_BD_NOTYPE, mdoc->parse, 674*260e9a87SYuri Pankov n->line, n->pos, "Bd"); 67595c635efSGarrett D'Amore n->norm->Bd.type = DISP_ragged; 67695c635efSGarrett D'Amore } 677*260e9a87SYuri Pankov pre_par(mdoc, n); 67895c635efSGarrett D'Amore } 67995c635efSGarrett D'Amore 680*260e9a87SYuri Pankov static void 68195c635efSGarrett D'Amore pre_an(PRE_ARGS) 68295c635efSGarrett D'Amore { 683*260e9a87SYuri Pankov struct mdoc_argv *argv; 684*260e9a87SYuri Pankov size_t i; 68595c635efSGarrett D'Amore 686*260e9a87SYuri Pankov if (n->args == NULL) 687*260e9a87SYuri Pankov return; 68895c635efSGarrett D'Amore 689*260e9a87SYuri Pankov for (i = 1; i < n->args->argc; i++) { 690*260e9a87SYuri Pankov argv = n->args->argv + i; 691*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_AN_REP, 692*260e9a87SYuri Pankov mdoc->parse, argv->line, argv->pos, 693*260e9a87SYuri Pankov "An -%s", mdoc_argnames[argv->arg]); 694*260e9a87SYuri Pankov } 69595c635efSGarrett D'Amore 696*260e9a87SYuri Pankov argv = n->args->argv; 697*260e9a87SYuri Pankov if (argv->arg == MDOC_Split) 69895c635efSGarrett D'Amore n->norm->An.auth = AUTH_split; 699*260e9a87SYuri Pankov else if (argv->arg == MDOC_Nosplit) 70095c635efSGarrett D'Amore n->norm->An.auth = AUTH_nosplit; 70195c635efSGarrett D'Amore else 70295c635efSGarrett D'Amore abort(); 70395c635efSGarrett D'Amore } 70495c635efSGarrett D'Amore 705*260e9a87SYuri Pankov static void 70695c635efSGarrett D'Amore pre_std(PRE_ARGS) 70795c635efSGarrett D'Amore { 70895c635efSGarrett D'Amore 70995c635efSGarrett D'Amore if (n->args && 1 == n->args->argc) 71095c635efSGarrett D'Amore if (MDOC_Std == n->args->argv[0].arg) 711*260e9a87SYuri Pankov return; 71295c635efSGarrett D'Amore 713*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_ARG_STD, mdoc->parse, 714*260e9a87SYuri Pankov n->line, n->pos, mdoc_macronames[n->tok]); 71595c635efSGarrett D'Amore } 71695c635efSGarrett D'Amore 717*260e9a87SYuri Pankov static void 718*260e9a87SYuri Pankov pre_obsolete(PRE_ARGS) 719*260e9a87SYuri Pankov { 720*260e9a87SYuri Pankov 721*260e9a87SYuri Pankov if (MDOC_ELEM == n->type || MDOC_BLOCK == n->type) 722*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_MACRO_OBS, mdoc->parse, 723*260e9a87SYuri Pankov n->line, n->pos, mdoc_macronames[n->tok]); 724*260e9a87SYuri Pankov } 725*260e9a87SYuri Pankov 726*260e9a87SYuri Pankov static void 72795c635efSGarrett D'Amore pre_dt(PRE_ARGS) 72895c635efSGarrett D'Amore { 72995c635efSGarrett D'Amore 730*260e9a87SYuri Pankov if (mdoc->meta.title != NULL) 731*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse, 732*260e9a87SYuri Pankov n->line, n->pos, "Dt"); 733*260e9a87SYuri Pankov else if (mdoc->meta.os != NULL) 734*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, 735*260e9a87SYuri Pankov n->line, n->pos, "Dt after Os"); 73695c635efSGarrett D'Amore } 73795c635efSGarrett D'Amore 738*260e9a87SYuri Pankov static void 73995c635efSGarrett D'Amore pre_os(PRE_ARGS) 74095c635efSGarrett D'Amore { 74195c635efSGarrett D'Amore 742*260e9a87SYuri Pankov if (mdoc->meta.os != NULL) 743*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse, 744*260e9a87SYuri Pankov n->line, n->pos, "Os"); 745*260e9a87SYuri Pankov else if (mdoc->flags & MDOC_PBODY) 746*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse, 747*260e9a87SYuri Pankov n->line, n->pos, "Os"); 74895c635efSGarrett D'Amore } 74995c635efSGarrett D'Amore 750*260e9a87SYuri Pankov static void 75195c635efSGarrett D'Amore pre_dd(PRE_ARGS) 75295c635efSGarrett D'Amore { 75395c635efSGarrett D'Amore 754*260e9a87SYuri Pankov if (mdoc->meta.date != NULL) 755*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse, 756*260e9a87SYuri Pankov n->line, n->pos, "Dd"); 757*260e9a87SYuri Pankov else if (mdoc->flags & MDOC_PBODY) 758*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse, 759*260e9a87SYuri Pankov n->line, n->pos, "Dd"); 760*260e9a87SYuri Pankov else if (mdoc->meta.title != NULL) 761*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, 762*260e9a87SYuri Pankov n->line, n->pos, "Dd after Dt"); 763*260e9a87SYuri Pankov else if (mdoc->meta.os != NULL) 764*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, 765*260e9a87SYuri Pankov n->line, n->pos, "Dd after Os"); 76695c635efSGarrett D'Amore } 76795c635efSGarrett D'Amore 768*260e9a87SYuri Pankov static void 76995c635efSGarrett D'Amore post_bf(POST_ARGS) 77095c635efSGarrett D'Amore { 771*260e9a87SYuri Pankov struct mdoc_node *np, *nch; 77295c635efSGarrett D'Amore enum mdocargt arg; 77395c635efSGarrett D'Amore 77495c635efSGarrett D'Amore /* 77595c635efSGarrett D'Amore * Unlike other data pointers, these are "housed" by the HEAD 77695c635efSGarrett D'Amore * element, which contains the goods. 77795c635efSGarrett D'Amore */ 77895c635efSGarrett D'Amore 77995c635efSGarrett D'Amore np = mdoc->last; 780*260e9a87SYuri Pankov if (MDOC_HEAD != np->type) 781*260e9a87SYuri Pankov return; 782*260e9a87SYuri Pankov 78395c635efSGarrett D'Amore assert(MDOC_BLOCK == np->parent->type); 78495c635efSGarrett D'Amore assert(MDOC_Bf == np->parent->tok); 78595c635efSGarrett D'Amore 786*260e9a87SYuri Pankov /* Check the number of arguments. */ 78795c635efSGarrett D'Amore 788*260e9a87SYuri Pankov nch = np->child; 789*260e9a87SYuri Pankov if (NULL == np->parent->args) { 790*260e9a87SYuri Pankov if (NULL == nch) { 791*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_BF_NOFONT, mdoc->parse, 792*260e9a87SYuri Pankov np->line, np->pos, "Bf"); 793*260e9a87SYuri Pankov return; 79495c635efSGarrett D'Amore } 795*260e9a87SYuri Pankov nch = nch->next; 796*260e9a87SYuri Pankov } 797*260e9a87SYuri Pankov if (NULL != nch) 798*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, 799*260e9a87SYuri Pankov nch->line, nch->pos, "Bf ... %s", nch->string); 80095c635efSGarrett D'Amore 80195c635efSGarrett D'Amore /* Extract argument into data. */ 80295c635efSGarrett D'Amore 80395c635efSGarrett D'Amore if (np->parent->args) { 80495c635efSGarrett D'Amore arg = np->parent->args->argv[0].arg; 80595c635efSGarrett D'Amore if (MDOC_Emphasis == arg) 80695c635efSGarrett D'Amore np->norm->Bf.font = FONT_Em; 80795c635efSGarrett D'Amore else if (MDOC_Literal == arg) 80895c635efSGarrett D'Amore np->norm->Bf.font = FONT_Li; 80995c635efSGarrett D'Amore else if (MDOC_Symbolic == arg) 81095c635efSGarrett D'Amore np->norm->Bf.font = FONT_Sy; 81195c635efSGarrett D'Amore else 81295c635efSGarrett D'Amore abort(); 813*260e9a87SYuri Pankov return; 81495c635efSGarrett D'Amore } 81595c635efSGarrett D'Amore 81695c635efSGarrett D'Amore /* Extract parameter into data. */ 81795c635efSGarrett D'Amore 81895c635efSGarrett D'Amore if (0 == strcmp(np->child->string, "Em")) 81995c635efSGarrett D'Amore np->norm->Bf.font = FONT_Em; 82095c635efSGarrett D'Amore else if (0 == strcmp(np->child->string, "Li")) 82195c635efSGarrett D'Amore np->norm->Bf.font = FONT_Li; 82295c635efSGarrett D'Amore else if (0 == strcmp(np->child->string, "Sy")) 82395c635efSGarrett D'Amore np->norm->Bf.font = FONT_Sy; 82495c635efSGarrett D'Amore else 825*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_BF_BADFONT, mdoc->parse, 826*260e9a87SYuri Pankov np->child->line, np->child->pos, 827*260e9a87SYuri Pankov "Bf %s", np->child->string); 82895c635efSGarrett D'Amore } 82995c635efSGarrett D'Amore 830*260e9a87SYuri Pankov static void 83195c635efSGarrett D'Amore post_lb(POST_ARGS) 83295c635efSGarrett D'Amore { 833*260e9a87SYuri Pankov struct mdoc_node *n; 834*260e9a87SYuri Pankov const char *stdlibname; 835*260e9a87SYuri Pankov char *libname; 83695c635efSGarrett D'Amore 837*260e9a87SYuri Pankov n = mdoc->last->child; 838*260e9a87SYuri Pankov assert(MDOC_TEXT == n->type); 83995c635efSGarrett D'Amore 840*260e9a87SYuri Pankov if (NULL == (stdlibname = mdoc_a2lib(n->string))) 841*260e9a87SYuri Pankov mandoc_asprintf(&libname, 842*260e9a87SYuri Pankov "library \\(Lq%s\\(Rq", n->string); 843*260e9a87SYuri Pankov else 844*260e9a87SYuri Pankov libname = mandoc_strdup(stdlibname); 84595c635efSGarrett D'Amore 846*260e9a87SYuri Pankov free(n->string); 847*260e9a87SYuri Pankov n->string = libname; 84895c635efSGarrett D'Amore } 84995c635efSGarrett D'Amore 850*260e9a87SYuri Pankov static void 85195c635efSGarrett D'Amore post_eoln(POST_ARGS) 85295c635efSGarrett D'Amore { 853*260e9a87SYuri Pankov const struct mdoc_node *n; 85495c635efSGarrett D'Amore 855*260e9a87SYuri Pankov n = mdoc->last; 856*260e9a87SYuri Pankov if (n->child) 857*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_SKIP, 858*260e9a87SYuri Pankov mdoc->parse, n->line, n->pos, 859*260e9a87SYuri Pankov "%s %s", mdoc_macronames[n->tok], 860*260e9a87SYuri Pankov n->child->string); 86195c635efSGarrett D'Amore } 86295c635efSGarrett D'Amore 863*260e9a87SYuri Pankov static void 864*260e9a87SYuri Pankov post_fname(POST_ARGS) 865*260e9a87SYuri Pankov { 866*260e9a87SYuri Pankov const struct mdoc_node *n; 867*260e9a87SYuri Pankov const char *cp; 868*260e9a87SYuri Pankov size_t pos; 86995c635efSGarrett D'Amore 870*260e9a87SYuri Pankov n = mdoc->last->child; 871*260e9a87SYuri Pankov pos = strcspn(n->string, "()"); 872*260e9a87SYuri Pankov cp = n->string + pos; 873*260e9a87SYuri Pankov if ( ! (cp[0] == '\0' || (cp[0] == '(' && cp[1] == '*'))) 874*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_FN_PAREN, mdoc->parse, 875*260e9a87SYuri Pankov n->line, n->pos + pos, n->string); 876*260e9a87SYuri Pankov } 877*260e9a87SYuri Pankov 878*260e9a87SYuri Pankov static void 879*260e9a87SYuri Pankov post_fn(POST_ARGS) 880*260e9a87SYuri Pankov { 881*260e9a87SYuri Pankov 882*260e9a87SYuri Pankov post_fname(mdoc); 883*260e9a87SYuri Pankov post_fa(mdoc); 884*260e9a87SYuri Pankov } 885*260e9a87SYuri Pankov 886*260e9a87SYuri Pankov static void 887*260e9a87SYuri Pankov post_fo(POST_ARGS) 888*260e9a87SYuri Pankov { 889*260e9a87SYuri Pankov const struct mdoc_node *n; 890*260e9a87SYuri Pankov 891*260e9a87SYuri Pankov n = mdoc->last; 892*260e9a87SYuri Pankov 893*260e9a87SYuri Pankov if (n->type != MDOC_HEAD) 894*260e9a87SYuri Pankov return; 895*260e9a87SYuri Pankov 896*260e9a87SYuri Pankov if (n->child == NULL) { 897*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_FO_NOHEAD, mdoc->parse, 898*260e9a87SYuri Pankov n->line, n->pos, "Fo"); 899*260e9a87SYuri Pankov return; 900*260e9a87SYuri Pankov } 901*260e9a87SYuri Pankov if (n->child != n->last) { 902*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, 903*260e9a87SYuri Pankov n->child->next->line, n->child->next->pos, 904*260e9a87SYuri Pankov "Fo ... %s", n->child->next->string); 905*260e9a87SYuri Pankov while (n->child != n->last) 906*260e9a87SYuri Pankov mdoc_node_delete(mdoc, n->last); 907*260e9a87SYuri Pankov } 908*260e9a87SYuri Pankov 909*260e9a87SYuri Pankov post_fname(mdoc); 910*260e9a87SYuri Pankov } 911*260e9a87SYuri Pankov 912*260e9a87SYuri Pankov static void 913*260e9a87SYuri Pankov post_fa(POST_ARGS) 914*260e9a87SYuri Pankov { 915*260e9a87SYuri Pankov const struct mdoc_node *n; 916*260e9a87SYuri Pankov const char *cp; 917*260e9a87SYuri Pankov 918*260e9a87SYuri Pankov for (n = mdoc->last->child; n != NULL; n = n->next) { 919*260e9a87SYuri Pankov for (cp = n->string; *cp != '\0'; cp++) { 920*260e9a87SYuri Pankov /* Ignore callbacks and alterations. */ 921*260e9a87SYuri Pankov if (*cp == '(' || *cp == '{') 922*260e9a87SYuri Pankov break; 923*260e9a87SYuri Pankov if (*cp != ',') 924*260e9a87SYuri Pankov continue; 925*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_FA_COMMA, mdoc->parse, 926*260e9a87SYuri Pankov n->line, n->pos + (cp - n->string), 927*260e9a87SYuri Pankov n->string); 928*260e9a87SYuri Pankov break; 929*260e9a87SYuri Pankov } 930*260e9a87SYuri Pankov } 931*260e9a87SYuri Pankov } 932*260e9a87SYuri Pankov 933*260e9a87SYuri Pankov static void 93495c635efSGarrett D'Amore post_vt(POST_ARGS) 93595c635efSGarrett D'Amore { 93695c635efSGarrett D'Amore const struct mdoc_node *n; 93795c635efSGarrett D'Amore 93895c635efSGarrett D'Amore /* 93995c635efSGarrett D'Amore * The Vt macro comes in both ELEM and BLOCK form, both of which 94095c635efSGarrett D'Amore * have different syntaxes (yet more context-sensitive 94195c635efSGarrett D'Amore * behaviour). ELEM types must have a child, which is already 94295c635efSGarrett D'Amore * guaranteed by the in_line parsing routine; BLOCK types, 94395c635efSGarrett D'Amore * specifically the BODY, should only have TEXT children. 94495c635efSGarrett D'Amore */ 94595c635efSGarrett D'Amore 94695c635efSGarrett D'Amore if (MDOC_BODY != mdoc->last->type) 947*260e9a87SYuri Pankov return; 94895c635efSGarrett D'Amore 94995c635efSGarrett D'Amore for (n = mdoc->last->child; n; n = n->next) 95095c635efSGarrett D'Amore if (MDOC_TEXT != n->type) 951*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_VT_CHILD, mdoc->parse, 952*260e9a87SYuri Pankov n->line, n->pos, mdoc_macronames[n->tok]); 95395c635efSGarrett D'Amore } 95495c635efSGarrett D'Amore 955*260e9a87SYuri Pankov static void 95695c635efSGarrett D'Amore post_nm(POST_ARGS) 95795c635efSGarrett D'Amore { 958*260e9a87SYuri Pankov struct mdoc_node *n; 959*260e9a87SYuri Pankov 960*260e9a87SYuri Pankov n = mdoc->last; 961*260e9a87SYuri Pankov 962*260e9a87SYuri Pankov if (n->last != NULL && 963*260e9a87SYuri Pankov (n->last->tok == MDOC_Pp || 964*260e9a87SYuri Pankov n->last->tok == MDOC_Lp)) 965*260e9a87SYuri Pankov mdoc_node_relink(mdoc, n->last); 96695c635efSGarrett D'Amore 967698f87a4SGarrett D'Amore if (NULL != mdoc->meta.name) 968*260e9a87SYuri Pankov return; 96995c635efSGarrett D'Amore 970*260e9a87SYuri Pankov mdoc_deroff(&mdoc->meta.name, n); 97195c635efSGarrett D'Amore 972*260e9a87SYuri Pankov if (NULL == mdoc->meta.name) 973*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_NM_NONAME, mdoc->parse, 974*260e9a87SYuri Pankov n->line, n->pos, "Nm"); 97595c635efSGarrett D'Amore } 97695c635efSGarrett D'Amore 977*260e9a87SYuri Pankov static void 978*260e9a87SYuri Pankov post_nd(POST_ARGS) 979*260e9a87SYuri Pankov { 980*260e9a87SYuri Pankov struct mdoc_node *n; 981*260e9a87SYuri Pankov 982*260e9a87SYuri Pankov n = mdoc->last; 983*260e9a87SYuri Pankov 984*260e9a87SYuri Pankov if (n->type != MDOC_BODY) 985*260e9a87SYuri Pankov return; 986*260e9a87SYuri Pankov 987*260e9a87SYuri Pankov if (n->child == NULL) 988*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_ND_EMPTY, mdoc->parse, 989*260e9a87SYuri Pankov n->line, n->pos, "Nd"); 990*260e9a87SYuri Pankov 991*260e9a87SYuri Pankov post_hyph(mdoc); 992*260e9a87SYuri Pankov } 993*260e9a87SYuri Pankov 994*260e9a87SYuri Pankov static void 995*260e9a87SYuri Pankov post_d1(POST_ARGS) 996*260e9a87SYuri Pankov { 997*260e9a87SYuri Pankov struct mdoc_node *n; 998*260e9a87SYuri Pankov 999*260e9a87SYuri Pankov n = mdoc->last; 1000*260e9a87SYuri Pankov 1001*260e9a87SYuri Pankov if (n->type != MDOC_BODY) 1002*260e9a87SYuri Pankov return; 1003*260e9a87SYuri Pankov 1004*260e9a87SYuri Pankov if (n->child == NULL) 1005*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse, 1006*260e9a87SYuri Pankov n->line, n->pos, "D1"); 1007*260e9a87SYuri Pankov 1008*260e9a87SYuri Pankov post_hyph(mdoc); 1009*260e9a87SYuri Pankov } 1010*260e9a87SYuri Pankov 1011*260e9a87SYuri Pankov static void 101295c635efSGarrett D'Amore post_literal(POST_ARGS) 101395c635efSGarrett D'Amore { 1014*260e9a87SYuri Pankov struct mdoc_node *n; 101595c635efSGarrett D'Amore 1016*260e9a87SYuri Pankov n = mdoc->last; 101795c635efSGarrett D'Amore 1018*260e9a87SYuri Pankov if (n->type != MDOC_BODY) 1019*260e9a87SYuri Pankov return; 1020*260e9a87SYuri Pankov 1021*260e9a87SYuri Pankov if (n->child == NULL) 1022*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse, 1023*260e9a87SYuri Pankov n->line, n->pos, mdoc_macronames[n->tok]); 1024*260e9a87SYuri Pankov 1025*260e9a87SYuri Pankov if (n->tok == MDOC_Bd && 1026*260e9a87SYuri Pankov n->norm->Bd.type != DISP_literal && 1027*260e9a87SYuri Pankov n->norm->Bd.type != DISP_unfilled) 1028*260e9a87SYuri Pankov return; 1029*260e9a87SYuri Pankov 103095c635efSGarrett D'Amore mdoc->flags &= ~MDOC_LITERAL; 103195c635efSGarrett D'Amore } 103295c635efSGarrett D'Amore 1033*260e9a87SYuri Pankov static void 103495c635efSGarrett D'Amore post_defaults(POST_ARGS) 103595c635efSGarrett D'Amore { 103695c635efSGarrett D'Amore struct mdoc_node *nn; 103795c635efSGarrett D'Amore 103895c635efSGarrett D'Amore /* 103995c635efSGarrett D'Amore * The `Ar' defaults to "file ..." if no value is provided as an 104095c635efSGarrett D'Amore * argument; the `Mt' and `Pa' macros use "~"; the `Li' just 104195c635efSGarrett D'Amore * gets an empty string. 104295c635efSGarrett D'Amore */ 104395c635efSGarrett D'Amore 104495c635efSGarrett D'Amore if (mdoc->last->child) 1045*260e9a87SYuri Pankov return; 104695c635efSGarrett D'Amore 104795c635efSGarrett D'Amore nn = mdoc->last; 104895c635efSGarrett D'Amore mdoc->next = MDOC_NEXT_CHILD; 104995c635efSGarrett D'Amore 105095c635efSGarrett D'Amore switch (nn->tok) { 1051*260e9a87SYuri Pankov case MDOC_Ar: 1052*260e9a87SYuri Pankov mdoc_word_alloc(mdoc, nn->line, nn->pos, "file"); 1053*260e9a87SYuri Pankov mdoc_word_alloc(mdoc, nn->line, nn->pos, "..."); 105495c635efSGarrett D'Amore break; 1055*260e9a87SYuri Pankov case MDOC_Pa: 105695c635efSGarrett D'Amore /* FALLTHROUGH */ 1057*260e9a87SYuri Pankov case MDOC_Mt: 1058*260e9a87SYuri Pankov mdoc_word_alloc(mdoc, nn->line, nn->pos, "~"); 105995c635efSGarrett D'Amore break; 106095c635efSGarrett D'Amore default: 106195c635efSGarrett D'Amore abort(); 106295c635efSGarrett D'Amore /* NOTREACHED */ 106395c635efSGarrett D'Amore } 106495c635efSGarrett D'Amore mdoc->last = nn; 106595c635efSGarrett D'Amore } 106695c635efSGarrett D'Amore 1067*260e9a87SYuri Pankov static void 106895c635efSGarrett D'Amore post_at(POST_ARGS) 106995c635efSGarrett D'Amore { 1070*260e9a87SYuri Pankov struct mdoc_node *n; 1071*260e9a87SYuri Pankov const char *std_att; 1072*260e9a87SYuri Pankov char *att; 1073*260e9a87SYuri Pankov 1074*260e9a87SYuri Pankov n = mdoc->last; 1075*260e9a87SYuri Pankov if (n->child == NULL) { 1076*260e9a87SYuri Pankov mdoc->next = MDOC_NEXT_CHILD; 1077*260e9a87SYuri Pankov mdoc_word_alloc(mdoc, n->line, n->pos, "AT&T UNIX"); 1078*260e9a87SYuri Pankov mdoc->last = n; 1079*260e9a87SYuri Pankov return; 1080*260e9a87SYuri Pankov } 108195c635efSGarrett D'Amore 108295c635efSGarrett D'Amore /* 108395c635efSGarrett D'Amore * If we have a child, look it up in the standard keys. If a 108495c635efSGarrett D'Amore * key exist, use that instead of the child; if it doesn't, 108595c635efSGarrett D'Amore * prefix "AT&T UNIX " to the existing data. 108695c635efSGarrett D'Amore */ 108795c635efSGarrett D'Amore 1088*260e9a87SYuri Pankov n = n->child; 1089*260e9a87SYuri Pankov assert(MDOC_TEXT == n->type); 1090*260e9a87SYuri Pankov if (NULL == (std_att = mdoc_a2att(n->string))) { 1091*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_AT_BAD, mdoc->parse, 1092*260e9a87SYuri Pankov n->line, n->pos, "At %s", n->string); 1093*260e9a87SYuri Pankov mandoc_asprintf(&att, "AT&T UNIX %s", n->string); 1094*260e9a87SYuri Pankov } else 1095*260e9a87SYuri Pankov att = mandoc_strdup(std_att); 109695c635efSGarrett D'Amore 1097*260e9a87SYuri Pankov free(n->string); 1098*260e9a87SYuri Pankov n->string = att; 109995c635efSGarrett D'Amore } 110095c635efSGarrett D'Amore 1101*260e9a87SYuri Pankov static void 110295c635efSGarrett D'Amore post_an(POST_ARGS) 110395c635efSGarrett D'Amore { 1104*260e9a87SYuri Pankov struct mdoc_node *np, *nch; 110595c635efSGarrett D'Amore 110695c635efSGarrett D'Amore np = mdoc->last; 1107*260e9a87SYuri Pankov nch = np->child; 1108*260e9a87SYuri Pankov if (np->norm->An.auth == AUTH__NONE) { 1109*260e9a87SYuri Pankov if (nch == NULL) 1110*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, 1111*260e9a87SYuri Pankov np->line, np->pos, "An"); 1112*260e9a87SYuri Pankov } else if (nch != NULL) 1113*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, 1114*260e9a87SYuri Pankov nch->line, nch->pos, "An ... %s", nch->string); 111595c635efSGarrett D'Amore } 111695c635efSGarrett D'Amore 1117*260e9a87SYuri Pankov static void 1118*260e9a87SYuri Pankov post_en(POST_ARGS) 1119*260e9a87SYuri Pankov { 112095c635efSGarrett D'Amore 1121*260e9a87SYuri Pankov if (MDOC_BLOCK == mdoc->last->type) 1122*260e9a87SYuri Pankov mdoc->last->norm->Es = mdoc->last_es; 1123*260e9a87SYuri Pankov } 1124*260e9a87SYuri Pankov 1125*260e9a87SYuri Pankov static void 1126*260e9a87SYuri Pankov post_es(POST_ARGS) 1127*260e9a87SYuri Pankov { 1128*260e9a87SYuri Pankov 1129*260e9a87SYuri Pankov mdoc->last_es = mdoc->last; 1130*260e9a87SYuri Pankov } 1131*260e9a87SYuri Pankov 1132*260e9a87SYuri Pankov static void 113395c635efSGarrett D'Amore post_it(POST_ARGS) 113495c635efSGarrett D'Amore { 113595c635efSGarrett D'Amore int i, cols; 113695c635efSGarrett D'Amore enum mdoc_list lt; 1137*260e9a87SYuri Pankov struct mdoc_node *nbl, *nit, *nch; 113895c635efSGarrett D'Amore 1139*260e9a87SYuri Pankov nit = mdoc->last; 1140*260e9a87SYuri Pankov if (nit->type != MDOC_BLOCK) 1141*260e9a87SYuri Pankov return; 114295c635efSGarrett D'Amore 1143*260e9a87SYuri Pankov nbl = nit->parent->parent; 1144*260e9a87SYuri Pankov lt = nbl->norm->Bl.type; 114595c635efSGarrett D'Amore 114695c635efSGarrett D'Amore switch (lt) { 1147*260e9a87SYuri Pankov case LIST_tag: 1148*260e9a87SYuri Pankov /* FALLTHROUGH */ 1149*260e9a87SYuri Pankov case LIST_hang: 1150*260e9a87SYuri Pankov /* FALLTHROUGH */ 1151*260e9a87SYuri Pankov case LIST_ohang: 1152*260e9a87SYuri Pankov /* FALLTHROUGH */ 1153*260e9a87SYuri Pankov case LIST_inset: 1154*260e9a87SYuri Pankov /* FALLTHROUGH */ 1155*260e9a87SYuri Pankov case LIST_diag: 1156*260e9a87SYuri Pankov if (nit->head->child == NULL) 1157*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_IT_NOHEAD, 1158*260e9a87SYuri Pankov mdoc->parse, nit->line, nit->pos, 1159*260e9a87SYuri Pankov "Bl -%s It", 1160*260e9a87SYuri Pankov mdoc_argnames[nbl->args->argv[0].arg]); 116195c635efSGarrett D'Amore break; 1162*260e9a87SYuri Pankov case LIST_bullet: 1163*260e9a87SYuri Pankov /* FALLTHROUGH */ 1164*260e9a87SYuri Pankov case LIST_dash: 1165*260e9a87SYuri Pankov /* FALLTHROUGH */ 1166*260e9a87SYuri Pankov case LIST_enum: 1167*260e9a87SYuri Pankov /* FALLTHROUGH */ 1168*260e9a87SYuri Pankov case LIST_hyphen: 1169*260e9a87SYuri Pankov if (nit->body == NULL || nit->body->child == NULL) 1170*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_IT_NOBODY, 1171*260e9a87SYuri Pankov mdoc->parse, nit->line, nit->pos, 1172*260e9a87SYuri Pankov "Bl -%s It", 1173*260e9a87SYuri Pankov mdoc_argnames[nbl->args->argv[0].arg]); 1174*260e9a87SYuri Pankov /* FALLTHROUGH */ 1175*260e9a87SYuri Pankov case LIST_item: 1176*260e9a87SYuri Pankov if (nit->head->child != NULL) 1177*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_SKIP, 1178*260e9a87SYuri Pankov mdoc->parse, nit->line, nit->pos, 1179*260e9a87SYuri Pankov "It %s", nit->head->child->string); 118095c635efSGarrett D'Amore break; 1181*260e9a87SYuri Pankov case LIST_column: 1182*260e9a87SYuri Pankov cols = (int)nbl->norm->Bl.ncols; 118395c635efSGarrett D'Amore 1184*260e9a87SYuri Pankov assert(nit->head->child == NULL); 118595c635efSGarrett D'Amore 1186*260e9a87SYuri Pankov for (i = 0, nch = nit->child; nch; nch = nch->next) 1187*260e9a87SYuri Pankov if (nch->type == MDOC_BODY) 118895c635efSGarrett D'Amore i++; 118995c635efSGarrett D'Amore 1190*260e9a87SYuri Pankov if (i < cols || i > cols + 1) 1191*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_BL_COL, 1192*260e9a87SYuri Pankov mdoc->parse, nit->line, nit->pos, 1193*260e9a87SYuri Pankov "%d columns, %d cells", cols, i); 119495c635efSGarrett D'Amore break; 119595c635efSGarrett D'Amore default: 1196*260e9a87SYuri Pankov abort(); 1197*260e9a87SYuri Pankov } 119895c635efSGarrett D'Amore } 119995c635efSGarrett D'Amore 1200*260e9a87SYuri Pankov static void 120195c635efSGarrett D'Amore post_bl_block(POST_ARGS) 120295c635efSGarrett D'Amore { 1203698f87a4SGarrett D'Amore struct mdoc_node *n, *ni, *nc; 120495c635efSGarrett D'Amore 120595c635efSGarrett D'Amore /* 120695c635efSGarrett D'Amore * These are fairly complicated, so we've broken them into two 120795c635efSGarrett D'Amore * functions. post_bl_block_tag() is called when a -tag is 120895c635efSGarrett D'Amore * specified, but no -width (it must be guessed). The second 120995c635efSGarrett D'Amore * when a -width is specified (macro indicators must be 121095c635efSGarrett D'Amore * rewritten into real lengths). 121195c635efSGarrett D'Amore */ 121295c635efSGarrett D'Amore 121395c635efSGarrett D'Amore n = mdoc->last; 121495c635efSGarrett D'Amore 121595c635efSGarrett D'Amore if (LIST_tag == n->norm->Bl.type && 121695c635efSGarrett D'Amore NULL == n->norm->Bl.width) { 1217*260e9a87SYuri Pankov post_bl_block_tag(mdoc); 121895c635efSGarrett D'Amore assert(n->norm->Bl.width); 1219698f87a4SGarrett D'Amore } 1220698f87a4SGarrett D'Amore 1221698f87a4SGarrett D'Amore for (ni = n->body->child; ni; ni = ni->next) { 1222698f87a4SGarrett D'Amore if (NULL == ni->body) 1223698f87a4SGarrett D'Amore continue; 1224698f87a4SGarrett D'Amore nc = ni->body->last; 1225698f87a4SGarrett D'Amore while (NULL != nc) { 1226698f87a4SGarrett D'Amore switch (nc->tok) { 1227*260e9a87SYuri Pankov case MDOC_Pp: 1228698f87a4SGarrett D'Amore /* FALLTHROUGH */ 1229*260e9a87SYuri Pankov case MDOC_Lp: 1230698f87a4SGarrett D'Amore /* FALLTHROUGH */ 1231*260e9a87SYuri Pankov case MDOC_br: 1232698f87a4SGarrett D'Amore break; 1233698f87a4SGarrett D'Amore default: 1234698f87a4SGarrett D'Amore nc = NULL; 1235698f87a4SGarrett D'Amore continue; 1236698f87a4SGarrett D'Amore } 1237698f87a4SGarrett D'Amore if (NULL == ni->next) { 1238*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_PAR_MOVE, 1239*260e9a87SYuri Pankov mdoc->parse, nc->line, nc->pos, 1240*260e9a87SYuri Pankov mdoc_macronames[nc->tok]); 1241*260e9a87SYuri Pankov mdoc_node_relink(mdoc, nc); 1242698f87a4SGarrett D'Amore } else if (0 == n->norm->Bl.comp && 1243698f87a4SGarrett D'Amore LIST_column != n->norm->Bl.type) { 1244*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_PAR_SKIP, 1245*260e9a87SYuri Pankov mdoc->parse, nc->line, nc->pos, 1246*260e9a87SYuri Pankov "%s before It", 1247*260e9a87SYuri Pankov mdoc_macronames[nc->tok]); 1248698f87a4SGarrett D'Amore mdoc_node_delete(mdoc, nc); 1249698f87a4SGarrett D'Amore } else 1250698f87a4SGarrett D'Amore break; 1251698f87a4SGarrett D'Amore nc = ni->body->last; 1252698f87a4SGarrett D'Amore } 1253698f87a4SGarrett D'Amore } 125495c635efSGarrett D'Amore } 125595c635efSGarrett D'Amore 125695c635efSGarrett D'Amore /* 1257*260e9a87SYuri Pankov * If the argument of -offset or -width is a macro, 1258*260e9a87SYuri Pankov * replace it with the associated default width. 125995c635efSGarrett D'Amore */ 1260*260e9a87SYuri Pankov void 1261*260e9a87SYuri Pankov rewrite_macro2len(char **arg) 1262*260e9a87SYuri Pankov { 1263*260e9a87SYuri Pankov size_t width; 1264*260e9a87SYuri Pankov enum mdoct tok; 126595c635efSGarrett D'Amore 1266*260e9a87SYuri Pankov if (*arg == NULL) 1267*260e9a87SYuri Pankov return; 1268*260e9a87SYuri Pankov else if ( ! strcmp(*arg, "Ds")) 126995c635efSGarrett D'Amore width = 6; 1270*260e9a87SYuri Pankov else if ((tok = mdoc_hash_find(*arg)) == MDOC_MAX) 1271*260e9a87SYuri Pankov return; 1272*260e9a87SYuri Pankov else 1273*260e9a87SYuri Pankov width = macro2len(tok); 1274*260e9a87SYuri Pankov 1275*260e9a87SYuri Pankov free(*arg); 1276*260e9a87SYuri Pankov mandoc_asprintf(arg, "%zun", width); 127795c635efSGarrett D'Amore } 127895c635efSGarrett D'Amore 1279*260e9a87SYuri Pankov static void 128095c635efSGarrett D'Amore post_bl_block_tag(POST_ARGS) 128195c635efSGarrett D'Amore { 128295c635efSGarrett D'Amore struct mdoc_node *n, *nn; 128395c635efSGarrett D'Amore size_t sz, ssz; 128495c635efSGarrett D'Amore int i; 1285*260e9a87SYuri Pankov char buf[24]; 128695c635efSGarrett D'Amore 128795c635efSGarrett D'Amore /* 128895c635efSGarrett D'Amore * Calculate the -width for a `Bl -tag' list if it hasn't been 128995c635efSGarrett D'Amore * provided. Uses the first head macro. NOTE AGAIN: this is 129095c635efSGarrett D'Amore * ONLY if the -width argument has NOT been provided. See 1291*260e9a87SYuri Pankov * rewrite_macro2len() for converting the -width string. 129295c635efSGarrett D'Amore */ 129395c635efSGarrett D'Amore 129495c635efSGarrett D'Amore sz = 10; 129595c635efSGarrett D'Amore n = mdoc->last; 129695c635efSGarrett D'Amore 129795c635efSGarrett D'Amore for (nn = n->body->child; nn; nn = nn->next) { 129895c635efSGarrett D'Amore if (MDOC_It != nn->tok) 129995c635efSGarrett D'Amore continue; 130095c635efSGarrett D'Amore 130195c635efSGarrett D'Amore assert(MDOC_BLOCK == nn->type); 130295c635efSGarrett D'Amore nn = nn->head->child; 130395c635efSGarrett D'Amore 130495c635efSGarrett D'Amore if (nn == NULL) 130595c635efSGarrett D'Amore break; 130695c635efSGarrett D'Amore 130795c635efSGarrett D'Amore if (MDOC_TEXT == nn->type) { 130895c635efSGarrett D'Amore sz = strlen(nn->string) + 1; 130995c635efSGarrett D'Amore break; 131095c635efSGarrett D'Amore } 131195c635efSGarrett D'Amore 131295c635efSGarrett D'Amore if (0 != (ssz = macro2len(nn->tok))) 131395c635efSGarrett D'Amore sz = ssz; 131495c635efSGarrett D'Amore 131595c635efSGarrett D'Amore break; 131695c635efSGarrett D'Amore } 131795c635efSGarrett D'Amore 131895c635efSGarrett D'Amore /* Defaults to ten ens. */ 131995c635efSGarrett D'Amore 1320*260e9a87SYuri Pankov (void)snprintf(buf, sizeof(buf), "%un", (unsigned int)sz); 132195c635efSGarrett D'Amore 132295c635efSGarrett D'Amore /* 132395c635efSGarrett D'Amore * We have to dynamically add this to the macro's argument list. 132495c635efSGarrett D'Amore * We're guaranteed that a MDOC_Width doesn't already exist. 132595c635efSGarrett D'Amore */ 132695c635efSGarrett D'Amore 132795c635efSGarrett D'Amore assert(n->args); 132895c635efSGarrett D'Amore i = (int)(n->args->argc)++; 132995c635efSGarrett D'Amore 1330*260e9a87SYuri Pankov n->args->argv = mandoc_reallocarray(n->args->argv, 1331*260e9a87SYuri Pankov n->args->argc, sizeof(struct mdoc_argv)); 133295c635efSGarrett D'Amore 133395c635efSGarrett D'Amore n->args->argv[i].arg = MDOC_Width; 133495c635efSGarrett D'Amore n->args->argv[i].line = n->line; 133595c635efSGarrett D'Amore n->args->argv[i].pos = n->pos; 133695c635efSGarrett D'Amore n->args->argv[i].sz = 1; 133795c635efSGarrett D'Amore n->args->argv[i].value = mandoc_malloc(sizeof(char *)); 133895c635efSGarrett D'Amore n->args->argv[i].value[0] = mandoc_strdup(buf); 133995c635efSGarrett D'Amore 134095c635efSGarrett D'Amore /* Set our width! */ 134195c635efSGarrett D'Amore n->norm->Bl.width = n->args->argv[i].value[0]; 134295c635efSGarrett D'Amore } 134395c635efSGarrett D'Amore 1344*260e9a87SYuri Pankov static void 134595c635efSGarrett D'Amore post_bl_head(POST_ARGS) 134695c635efSGarrett D'Amore { 1347*260e9a87SYuri Pankov struct mdoc_node *nbl, *nh, *nch, *nnext; 1348*260e9a87SYuri Pankov struct mdoc_argv *argv; 134995c635efSGarrett D'Amore int i, j; 135095c635efSGarrett D'Amore 1351*260e9a87SYuri Pankov nh = mdoc->last; 1352*260e9a87SYuri Pankov 1353*260e9a87SYuri Pankov if (nh->norm->Bl.type != LIST_column) { 1354*260e9a87SYuri Pankov if ((nch = nh->child) == NULL) 1355*260e9a87SYuri Pankov return; 1356*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, 1357*260e9a87SYuri Pankov nch->line, nch->pos, "Bl ... %s", nch->string); 1358*260e9a87SYuri Pankov while (nch != NULL) { 1359*260e9a87SYuri Pankov mdoc_node_delete(mdoc, nch); 1360*260e9a87SYuri Pankov nch = nh->child; 1361*260e9a87SYuri Pankov } 1362*260e9a87SYuri Pankov return; 1363*260e9a87SYuri Pankov } 136495c635efSGarrett D'Amore 136595c635efSGarrett D'Amore /* 1366*260e9a87SYuri Pankov * Append old-style lists, where the column width specifiers 136795c635efSGarrett D'Amore * trail as macro parameters, to the new-style ("normal-form") 136895c635efSGarrett D'Amore * lists where they're argument values following -column. 136995c635efSGarrett D'Amore */ 137095c635efSGarrett D'Amore 1371*260e9a87SYuri Pankov if (nh->child == NULL) 1372*260e9a87SYuri Pankov return; 137395c635efSGarrett D'Amore 1374*260e9a87SYuri Pankov nbl = nh->parent; 1375*260e9a87SYuri Pankov for (j = 0; j < (int)nbl->args->argc; j++) 1376*260e9a87SYuri Pankov if (nbl->args->argv[j].arg == MDOC_Column) 137795c635efSGarrett D'Amore break; 137895c635efSGarrett D'Amore 1379*260e9a87SYuri Pankov assert(j < (int)nbl->args->argc); 138095c635efSGarrett D'Amore 138195c635efSGarrett D'Amore /* 138295c635efSGarrett D'Amore * Accommodate for new-style groff column syntax. Shuffle the 138395c635efSGarrett D'Amore * child nodes, all of which must be TEXT, as arguments for the 138495c635efSGarrett D'Amore * column field. Then, delete the head children. 138595c635efSGarrett D'Amore */ 138695c635efSGarrett D'Amore 1387*260e9a87SYuri Pankov argv = nbl->args->argv + j; 1388*260e9a87SYuri Pankov i = argv->sz; 1389*260e9a87SYuri Pankov argv->sz += nh->nchild; 1390*260e9a87SYuri Pankov argv->value = mandoc_reallocarray(argv->value, 1391*260e9a87SYuri Pankov argv->sz, sizeof(char *)); 139295c635efSGarrett D'Amore 1393*260e9a87SYuri Pankov nh->norm->Bl.ncols = argv->sz; 1394*260e9a87SYuri Pankov nh->norm->Bl.cols = (void *)argv->value; 139595c635efSGarrett D'Amore 1396*260e9a87SYuri Pankov for (nch = nh->child; nch != NULL; nch = nnext) { 1397*260e9a87SYuri Pankov argv->value[i++] = nch->string; 1398*260e9a87SYuri Pankov nch->string = NULL; 1399*260e9a87SYuri Pankov nnext = nch->next; 1400*260e9a87SYuri Pankov mdoc_node_delete(NULL, nch); 1401*260e9a87SYuri Pankov } 1402*260e9a87SYuri Pankov nh->nchild = 0; 1403*260e9a87SYuri Pankov nh->child = NULL; 140495c635efSGarrett D'Amore } 140595c635efSGarrett D'Amore 1406*260e9a87SYuri Pankov static void 140795c635efSGarrett D'Amore post_bl(POST_ARGS) 140895c635efSGarrett D'Amore { 1409698f87a4SGarrett D'Amore struct mdoc_node *nparent, *nprev; /* of the Bl block */ 1410698f87a4SGarrett D'Amore struct mdoc_node *nblock, *nbody; /* of the Bl */ 1411698f87a4SGarrett D'Amore struct mdoc_node *nchild, *nnext; /* of the Bl body */ 141295c635efSGarrett D'Amore 1413698f87a4SGarrett D'Amore nbody = mdoc->last; 1414698f87a4SGarrett D'Amore switch (nbody->type) { 1415*260e9a87SYuri Pankov case MDOC_BLOCK: 1416*260e9a87SYuri Pankov post_bl_block(mdoc); 1417*260e9a87SYuri Pankov return; 1418*260e9a87SYuri Pankov case MDOC_HEAD: 1419*260e9a87SYuri Pankov post_bl_head(mdoc); 1420*260e9a87SYuri Pankov return; 1421*260e9a87SYuri Pankov case MDOC_BODY: 142295c635efSGarrett D'Amore break; 1423698f87a4SGarrett D'Amore default: 1424*260e9a87SYuri Pankov return; 142595c635efSGarrett D'Amore } 142695c635efSGarrett D'Amore 1427698f87a4SGarrett D'Amore nchild = nbody->child; 1428*260e9a87SYuri Pankov if (nchild == NULL) { 1429*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse, 1430*260e9a87SYuri Pankov nbody->line, nbody->pos, "Bl"); 1431*260e9a87SYuri Pankov return; 1432*260e9a87SYuri Pankov } 1433*260e9a87SYuri Pankov while (nchild != NULL) { 1434*260e9a87SYuri Pankov if (nchild->tok == MDOC_It || 1435*260e9a87SYuri Pankov (nchild->tok == MDOC_Sm && 1436*260e9a87SYuri Pankov nchild->next != NULL && 1437*260e9a87SYuri Pankov nchild->next->tok == MDOC_It)) { 1438698f87a4SGarrett D'Amore nchild = nchild->next; 1439698f87a4SGarrett D'Amore continue; 1440698f87a4SGarrett D'Amore } 1441698f87a4SGarrett D'Amore 1442*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_BL_MOVE, mdoc->parse, 1443*260e9a87SYuri Pankov nchild->line, nchild->pos, 1444*260e9a87SYuri Pankov mdoc_macronames[nchild->tok]); 1445698f87a4SGarrett D'Amore 1446698f87a4SGarrett D'Amore /* 1447698f87a4SGarrett D'Amore * Move the node out of the Bl block. 1448698f87a4SGarrett D'Amore * First, collect all required node pointers. 1449698f87a4SGarrett D'Amore */ 1450698f87a4SGarrett D'Amore 1451698f87a4SGarrett D'Amore nblock = nbody->parent; 1452698f87a4SGarrett D'Amore nprev = nblock->prev; 1453698f87a4SGarrett D'Amore nparent = nblock->parent; 1454698f87a4SGarrett D'Amore nnext = nchild->next; 1455698f87a4SGarrett D'Amore 1456698f87a4SGarrett D'Amore /* 1457698f87a4SGarrett D'Amore * Unlink this child. 1458698f87a4SGarrett D'Amore */ 1459698f87a4SGarrett D'Amore 1460698f87a4SGarrett D'Amore assert(NULL == nchild->prev); 1461698f87a4SGarrett D'Amore if (0 == --nbody->nchild) { 1462698f87a4SGarrett D'Amore nbody->child = NULL; 1463698f87a4SGarrett D'Amore nbody->last = NULL; 1464698f87a4SGarrett D'Amore assert(NULL == nnext); 1465698f87a4SGarrett D'Amore } else { 1466698f87a4SGarrett D'Amore nbody->child = nnext; 1467698f87a4SGarrett D'Amore nnext->prev = NULL; 1468698f87a4SGarrett D'Amore } 1469698f87a4SGarrett D'Amore 1470698f87a4SGarrett D'Amore /* 1471698f87a4SGarrett D'Amore * Relink this child. 1472698f87a4SGarrett D'Amore */ 1473698f87a4SGarrett D'Amore 1474698f87a4SGarrett D'Amore nchild->parent = nparent; 1475698f87a4SGarrett D'Amore nchild->prev = nprev; 1476698f87a4SGarrett D'Amore nchild->next = nblock; 1477698f87a4SGarrett D'Amore 1478698f87a4SGarrett D'Amore nblock->prev = nchild; 1479698f87a4SGarrett D'Amore nparent->nchild++; 1480698f87a4SGarrett D'Amore if (NULL == nprev) 1481698f87a4SGarrett D'Amore nparent->child = nchild; 1482698f87a4SGarrett D'Amore else 1483698f87a4SGarrett D'Amore nprev->next = nchild; 1484698f87a4SGarrett D'Amore 1485698f87a4SGarrett D'Amore nchild = nnext; 148695c635efSGarrett D'Amore } 148795c635efSGarrett D'Amore } 148895c635efSGarrett D'Amore 1489*260e9a87SYuri Pankov static void 1490*260e9a87SYuri Pankov post_bk(POST_ARGS) 149195c635efSGarrett D'Amore { 149295c635efSGarrett D'Amore struct mdoc_node *n; 149395c635efSGarrett D'Amore 1494*260e9a87SYuri Pankov n = mdoc->last; 149595c635efSGarrett D'Amore 1496*260e9a87SYuri Pankov if (n->type == MDOC_BLOCK && n->body->child == NULL) { 1497*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_BLK_EMPTY, 1498*260e9a87SYuri Pankov mdoc->parse, n->line, n->pos, "Bk"); 1499*260e9a87SYuri Pankov mdoc_node_delete(mdoc, n); 1500*260e9a87SYuri Pankov } 150195c635efSGarrett D'Amore } 150295c635efSGarrett D'Amore 1503*260e9a87SYuri Pankov static void 1504*260e9a87SYuri Pankov post_sm(struct mdoc *mdoc) 1505*260e9a87SYuri Pankov { 1506*260e9a87SYuri Pankov struct mdoc_node *nch; 1507*260e9a87SYuri Pankov 1508*260e9a87SYuri Pankov nch = mdoc->last->child; 1509*260e9a87SYuri Pankov 1510*260e9a87SYuri Pankov if (nch == NULL) { 1511*260e9a87SYuri Pankov mdoc->flags ^= MDOC_SMOFF; 1512*260e9a87SYuri Pankov return; 1513*260e9a87SYuri Pankov } 1514*260e9a87SYuri Pankov 1515*260e9a87SYuri Pankov assert(nch->type == MDOC_TEXT); 1516*260e9a87SYuri Pankov 1517*260e9a87SYuri Pankov if ( ! strcmp(nch->string, "on")) { 1518*260e9a87SYuri Pankov mdoc->flags &= ~MDOC_SMOFF; 1519*260e9a87SYuri Pankov return; 1520*260e9a87SYuri Pankov } 1521*260e9a87SYuri Pankov if ( ! strcmp(nch->string, "off")) { 1522*260e9a87SYuri Pankov mdoc->flags |= MDOC_SMOFF; 1523*260e9a87SYuri Pankov return; 1524*260e9a87SYuri Pankov } 1525*260e9a87SYuri Pankov 1526*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_SM_BAD, 1527*260e9a87SYuri Pankov mdoc->parse, nch->line, nch->pos, 1528*260e9a87SYuri Pankov "%s %s", mdoc_macronames[mdoc->last->tok], nch->string); 1529*260e9a87SYuri Pankov mdoc_node_relink(mdoc, nch); 1530*260e9a87SYuri Pankov return; 1531*260e9a87SYuri Pankov } 1532*260e9a87SYuri Pankov 1533*260e9a87SYuri Pankov static void 1534*260e9a87SYuri Pankov post_root(POST_ARGS) 1535*260e9a87SYuri Pankov { 1536*260e9a87SYuri Pankov struct mdoc_node *n; 1537*260e9a87SYuri Pankov 1538*260e9a87SYuri Pankov /* Add missing prologue data. */ 1539*260e9a87SYuri Pankov 1540*260e9a87SYuri Pankov if (mdoc->meta.date == NULL) 1541*260e9a87SYuri Pankov mdoc->meta.date = mdoc->quick ? 1542*260e9a87SYuri Pankov mandoc_strdup("") : 1543*260e9a87SYuri Pankov mandoc_normdate(mdoc->parse, NULL, 0, 0); 1544*260e9a87SYuri Pankov 1545*260e9a87SYuri Pankov if (mdoc->meta.title == NULL) { 1546*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_DT_NOTITLE, 1547*260e9a87SYuri Pankov mdoc->parse, 0, 0, "EOF"); 1548*260e9a87SYuri Pankov mdoc->meta.title = mandoc_strdup("UNTITLED"); 1549*260e9a87SYuri Pankov } 1550*260e9a87SYuri Pankov 1551*260e9a87SYuri Pankov if (mdoc->meta.vol == NULL) 1552*260e9a87SYuri Pankov mdoc->meta.vol = mandoc_strdup("LOCAL"); 1553*260e9a87SYuri Pankov 1554*260e9a87SYuri Pankov if (mdoc->meta.os == NULL) { 1555*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_OS_MISSING, 1556*260e9a87SYuri Pankov mdoc->parse, 0, 0, NULL); 1557*260e9a87SYuri Pankov mdoc->meta.os = mandoc_strdup(""); 1558*260e9a87SYuri Pankov } 155995c635efSGarrett D'Amore 156095c635efSGarrett D'Amore /* Check that we begin with a proper `Sh'. */ 156195c635efSGarrett D'Amore 1562*260e9a87SYuri Pankov n = mdoc->first->child; 1563*260e9a87SYuri Pankov while (n != NULL && mdoc_macros[n->tok].flags & MDOC_PROLOGUE) 1564*260e9a87SYuri Pankov n = n->next; 1565*260e9a87SYuri Pankov 1566*260e9a87SYuri Pankov if (n == NULL) 1567*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_DOC_EMPTY, mdoc->parse, 0, 0, NULL); 1568*260e9a87SYuri Pankov else if (n->tok != MDOC_Sh) 1569*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_SEC_BEFORE, mdoc->parse, 1570*260e9a87SYuri Pankov n->line, n->pos, mdoc_macronames[n->tok]); 157195c635efSGarrett D'Amore } 157295c635efSGarrett D'Amore 1573*260e9a87SYuri Pankov static void 157495c635efSGarrett D'Amore post_st(POST_ARGS) 157595c635efSGarrett D'Amore { 1576*260e9a87SYuri Pankov struct mdoc_node *n, *nch; 157795c635efSGarrett D'Amore const char *p; 157895c635efSGarrett D'Amore 1579*260e9a87SYuri Pankov n = mdoc->last; 1580*260e9a87SYuri Pankov nch = n->child; 158195c635efSGarrett D'Amore 1582*260e9a87SYuri Pankov assert(MDOC_TEXT == nch->type); 158395c635efSGarrett D'Amore 1584*260e9a87SYuri Pankov if (NULL == (p = mdoc_a2st(nch->string))) { 1585*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ST_BAD, mdoc->parse, 1586*260e9a87SYuri Pankov nch->line, nch->pos, "St %s", nch->string); 1587*260e9a87SYuri Pankov mdoc_node_delete(mdoc, n); 158895c635efSGarrett D'Amore } else { 1589*260e9a87SYuri Pankov free(nch->string); 1590*260e9a87SYuri Pankov nch->string = mandoc_strdup(p); 1591*260e9a87SYuri Pankov } 159295c635efSGarrett D'Amore } 159395c635efSGarrett D'Amore 1594*260e9a87SYuri Pankov static void 159595c635efSGarrett D'Amore post_rs(POST_ARGS) 159695c635efSGarrett D'Amore { 1597*260e9a87SYuri Pankov struct mdoc_node *np, *nch, *next, *prev; 159895c635efSGarrett D'Amore int i, j; 159995c635efSGarrett D'Amore 1600*260e9a87SYuri Pankov np = mdoc->last; 1601*260e9a87SYuri Pankov 1602*260e9a87SYuri Pankov if (np->type != MDOC_BODY) 1603*260e9a87SYuri Pankov return; 1604*260e9a87SYuri Pankov 1605*260e9a87SYuri Pankov if (np->child == NULL) { 1606*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_RS_EMPTY, mdoc->parse, 1607*260e9a87SYuri Pankov np->line, np->pos, "Rs"); 1608*260e9a87SYuri Pankov return; 160995c635efSGarrett D'Amore } 161095c635efSGarrett D'Amore 161195c635efSGarrett D'Amore /* 161295c635efSGarrett D'Amore * The full `Rs' block needs special handling to order the 161395c635efSGarrett D'Amore * sub-elements according to `rsord'. Pick through each element 1614*260e9a87SYuri Pankov * and correctly order it. This is an insertion sort. 161595c635efSGarrett D'Amore */ 161695c635efSGarrett D'Amore 161795c635efSGarrett D'Amore next = NULL; 1618*260e9a87SYuri Pankov for (nch = np->child->next; nch != NULL; nch = next) { 1619*260e9a87SYuri Pankov /* Determine order number of this child. */ 162095c635efSGarrett D'Amore for (i = 0; i < RSORD_MAX; i++) 1621*260e9a87SYuri Pankov if (rsord[i] == nch->tok) 162295c635efSGarrett D'Amore break; 162395c635efSGarrett D'Amore 1624*260e9a87SYuri Pankov if (i == RSORD_MAX) { 1625*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_RS_BAD, 1626*260e9a87SYuri Pankov mdoc->parse, nch->line, nch->pos, 1627*260e9a87SYuri Pankov mdoc_macronames[nch->tok]); 1628*260e9a87SYuri Pankov i = -1; 1629*260e9a87SYuri Pankov } else if (nch->tok == MDOC__J || nch->tok == MDOC__B) 1630*260e9a87SYuri Pankov np->norm->Rs.quote_T++; 1631*260e9a87SYuri Pankov 163295c635efSGarrett D'Amore /* 1633*260e9a87SYuri Pankov * Remove this child from the chain. This somewhat 163495c635efSGarrett D'Amore * repeats mdoc_node_unlink(), but since we're 163595c635efSGarrett D'Amore * just re-ordering, there's no need for the 163695c635efSGarrett D'Amore * full unlink process. 163795c635efSGarrett D'Amore */ 163895c635efSGarrett D'Amore 1639*260e9a87SYuri Pankov if ((next = nch->next) != NULL) 1640*260e9a87SYuri Pankov next->prev = nch->prev; 164195c635efSGarrett D'Amore 1642*260e9a87SYuri Pankov if ((prev = nch->prev) != NULL) 1643*260e9a87SYuri Pankov prev->next = nch->next; 164495c635efSGarrett D'Amore 1645*260e9a87SYuri Pankov nch->prev = nch->next = NULL; 164695c635efSGarrett D'Amore 164795c635efSGarrett D'Amore /* 164895c635efSGarrett D'Amore * Scan back until we reach a node that's 1649*260e9a87SYuri Pankov * to be ordered before this child. 165095c635efSGarrett D'Amore */ 165195c635efSGarrett D'Amore 165295c635efSGarrett D'Amore for ( ; prev ; prev = prev->prev) { 165395c635efSGarrett D'Amore /* Determine order of `prev'. */ 165495c635efSGarrett D'Amore for (j = 0; j < RSORD_MAX; j++) 165595c635efSGarrett D'Amore if (rsord[j] == prev->tok) 165695c635efSGarrett D'Amore break; 1657*260e9a87SYuri Pankov if (j == RSORD_MAX) 1658*260e9a87SYuri Pankov j = -1; 165995c635efSGarrett D'Amore 166095c635efSGarrett D'Amore if (j <= i) 166195c635efSGarrett D'Amore break; 166295c635efSGarrett D'Amore } 166395c635efSGarrett D'Amore 166495c635efSGarrett D'Amore /* 1665*260e9a87SYuri Pankov * Set this child back into its correct place 1666*260e9a87SYuri Pankov * in front of the `prev' node. 166795c635efSGarrett D'Amore */ 166895c635efSGarrett D'Amore 1669*260e9a87SYuri Pankov nch->prev = prev; 167095c635efSGarrett D'Amore 1671*260e9a87SYuri Pankov if (prev == NULL) { 1672*260e9a87SYuri Pankov np->child->prev = nch; 1673*260e9a87SYuri Pankov nch->next = np->child; 1674*260e9a87SYuri Pankov np->child = nch; 167595c635efSGarrett D'Amore } else { 1676*260e9a87SYuri Pankov if (prev->next) 1677*260e9a87SYuri Pankov prev->next->prev = nch; 1678*260e9a87SYuri Pankov nch->next = prev->next; 1679*260e9a87SYuri Pankov prev->next = nch; 168095c635efSGarrett D'Amore } 168195c635efSGarrett D'Amore } 168295c635efSGarrett D'Amore } 168395c635efSGarrett D'Amore 1684698f87a4SGarrett D'Amore /* 1685698f87a4SGarrett D'Amore * For some arguments of some macros, 1686698f87a4SGarrett D'Amore * convert all breakable hyphens into ASCII_HYPH. 1687698f87a4SGarrett D'Amore */ 1688*260e9a87SYuri Pankov static void 1689698f87a4SGarrett D'Amore post_hyph(POST_ARGS) 1690698f87a4SGarrett D'Amore { 1691*260e9a87SYuri Pankov struct mdoc_node *nch; 1692698f87a4SGarrett D'Amore char *cp; 1693698f87a4SGarrett D'Amore 1694*260e9a87SYuri Pankov for (nch = mdoc->last->child; nch != NULL; nch = nch->next) { 1695*260e9a87SYuri Pankov if (nch->type != MDOC_TEXT) 1696698f87a4SGarrett D'Amore continue; 1697698f87a4SGarrett D'Amore cp = nch->string; 1698*260e9a87SYuri Pankov if (*cp == '\0') 1699698f87a4SGarrett D'Amore continue; 1700*260e9a87SYuri Pankov while (*(++cp) != '\0') 1701*260e9a87SYuri Pankov if (*cp == '-' && 1702698f87a4SGarrett D'Amore isalpha((unsigned char)cp[-1]) && 1703698f87a4SGarrett D'Amore isalpha((unsigned char)cp[1])) 1704698f87a4SGarrett D'Amore *cp = ASCII_HYPH; 1705698f87a4SGarrett D'Amore } 1706698f87a4SGarrett D'Amore } 1707698f87a4SGarrett D'Amore 1708*260e9a87SYuri Pankov static void 170995c635efSGarrett D'Amore post_ns(POST_ARGS) 171095c635efSGarrett D'Amore { 171195c635efSGarrett D'Amore 171295c635efSGarrett D'Amore if (MDOC_LINE & mdoc->last->flags) 1713*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_NS_SKIP, mdoc->parse, 1714*260e9a87SYuri Pankov mdoc->last->line, mdoc->last->pos, NULL); 171595c635efSGarrett D'Amore } 171695c635efSGarrett D'Amore 1717*260e9a87SYuri Pankov static void 171895c635efSGarrett D'Amore post_sh(POST_ARGS) 171995c635efSGarrett D'Amore { 172095c635efSGarrett D'Amore 1721*260e9a87SYuri Pankov post_ignpar(mdoc); 172295c635efSGarrett D'Amore 1723*260e9a87SYuri Pankov switch (mdoc->last->type) { 1724*260e9a87SYuri Pankov case MDOC_HEAD: 1725*260e9a87SYuri Pankov post_sh_head(mdoc); 1726*260e9a87SYuri Pankov break; 1727*260e9a87SYuri Pankov case MDOC_BODY: 1728*260e9a87SYuri Pankov switch (mdoc->lastsec) { 1729*260e9a87SYuri Pankov case SEC_NAME: 1730*260e9a87SYuri Pankov post_sh_name(mdoc); 1731*260e9a87SYuri Pankov break; 1732*260e9a87SYuri Pankov case SEC_SEE_ALSO: 1733*260e9a87SYuri Pankov post_sh_see_also(mdoc); 1734*260e9a87SYuri Pankov break; 1735*260e9a87SYuri Pankov case SEC_AUTHORS: 1736*260e9a87SYuri Pankov post_sh_authors(mdoc); 1737*260e9a87SYuri Pankov break; 1738*260e9a87SYuri Pankov default: 1739*260e9a87SYuri Pankov break; 1740*260e9a87SYuri Pankov } 1741*260e9a87SYuri Pankov break; 1742*260e9a87SYuri Pankov default: 1743*260e9a87SYuri Pankov break; 1744*260e9a87SYuri Pankov } 174595c635efSGarrett D'Amore } 174695c635efSGarrett D'Amore 1747*260e9a87SYuri Pankov static void 1748*260e9a87SYuri Pankov post_sh_name(POST_ARGS) 174995c635efSGarrett D'Amore { 175095c635efSGarrett D'Amore struct mdoc_node *n; 1751*260e9a87SYuri Pankov int hasnm, hasnd; 175295c635efSGarrett D'Amore 1753*260e9a87SYuri Pankov hasnm = hasnd = 0; 175495c635efSGarrett D'Amore 1755*260e9a87SYuri Pankov for (n = mdoc->last->child; n != NULL; n = n->next) { 1756*260e9a87SYuri Pankov switch (n->tok) { 1757*260e9a87SYuri Pankov case MDOC_Nm: 1758*260e9a87SYuri Pankov hasnm = 1; 1759*260e9a87SYuri Pankov break; 1760*260e9a87SYuri Pankov case MDOC_Nd: 1761*260e9a87SYuri Pankov hasnd = 1; 1762*260e9a87SYuri Pankov if (n->next != NULL) 1763*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_NAMESEC_ND, 1764*260e9a87SYuri Pankov mdoc->parse, n->line, n->pos, NULL); 1765*260e9a87SYuri Pankov break; 1766*260e9a87SYuri Pankov case MDOC_MAX: 1767*260e9a87SYuri Pankov if (hasnm) 1768*260e9a87SYuri Pankov break; 1769*260e9a87SYuri Pankov /* FALLTHROUGH */ 1770*260e9a87SYuri Pankov default: 1771*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_NAMESEC_BAD, mdoc->parse, 1772*260e9a87SYuri Pankov n->line, n->pos, mdoc_macronames[n->tok]); 1773*260e9a87SYuri Pankov break; 1774*260e9a87SYuri Pankov } 177595c635efSGarrett D'Amore } 177695c635efSGarrett D'Amore 1777*260e9a87SYuri Pankov if ( ! hasnm) 1778*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_NAMESEC_NONM, mdoc->parse, 1779*260e9a87SYuri Pankov mdoc->last->line, mdoc->last->pos, NULL); 1780*260e9a87SYuri Pankov if ( ! hasnd) 1781*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_NAMESEC_NOND, mdoc->parse, 1782*260e9a87SYuri Pankov mdoc->last->line, mdoc->last->pos, NULL); 178395c635efSGarrett D'Amore } 178495c635efSGarrett D'Amore 1785*260e9a87SYuri Pankov static void 1786*260e9a87SYuri Pankov post_sh_see_also(POST_ARGS) 1787*260e9a87SYuri Pankov { 1788*260e9a87SYuri Pankov const struct mdoc_node *n; 1789*260e9a87SYuri Pankov const char *name, *sec; 1790*260e9a87SYuri Pankov const char *lastname, *lastsec, *lastpunct; 1791*260e9a87SYuri Pankov int cmp; 179295c635efSGarrett D'Amore 1793*260e9a87SYuri Pankov n = mdoc->last->child; 1794*260e9a87SYuri Pankov lastname = lastsec = lastpunct = NULL; 1795*260e9a87SYuri Pankov while (n != NULL) { 1796*260e9a87SYuri Pankov if (n->tok != MDOC_Xr || n->nchild < 2) 1797*260e9a87SYuri Pankov break; 1798*260e9a87SYuri Pankov 1799*260e9a87SYuri Pankov /* Process one .Xr node. */ 1800*260e9a87SYuri Pankov 1801*260e9a87SYuri Pankov name = n->child->string; 1802*260e9a87SYuri Pankov sec = n->child->next->string; 1803*260e9a87SYuri Pankov if (lastsec != NULL) { 1804*260e9a87SYuri Pankov if (lastpunct[0] != ',' || lastpunct[1] != '\0') 1805*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_XR_PUNCT, 1806*260e9a87SYuri Pankov mdoc->parse, n->line, n->pos, 1807*260e9a87SYuri Pankov "%s before %s(%s)", lastpunct, 1808*260e9a87SYuri Pankov name, sec); 1809*260e9a87SYuri Pankov cmp = strcmp(lastsec, sec); 1810*260e9a87SYuri Pankov if (cmp > 0) 1811*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_XR_ORDER, 1812*260e9a87SYuri Pankov mdoc->parse, n->line, n->pos, 1813*260e9a87SYuri Pankov "%s(%s) after %s(%s)", name, 1814*260e9a87SYuri Pankov sec, lastname, lastsec); 1815*260e9a87SYuri Pankov else if (cmp == 0 && 1816*260e9a87SYuri Pankov strcasecmp(lastname, name) > 0) 1817*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_XR_ORDER, 1818*260e9a87SYuri Pankov mdoc->parse, n->line, n->pos, 1819*260e9a87SYuri Pankov "%s after %s", name, lastname); 1820*260e9a87SYuri Pankov } 1821*260e9a87SYuri Pankov lastname = name; 1822*260e9a87SYuri Pankov lastsec = sec; 1823*260e9a87SYuri Pankov 1824*260e9a87SYuri Pankov /* Process the following node. */ 1825*260e9a87SYuri Pankov 1826*260e9a87SYuri Pankov n = n->next; 1827*260e9a87SYuri Pankov if (n == NULL) 1828*260e9a87SYuri Pankov break; 1829*260e9a87SYuri Pankov if (n->tok == MDOC_Xr) { 1830*260e9a87SYuri Pankov lastpunct = "none"; 1831*260e9a87SYuri Pankov continue; 1832*260e9a87SYuri Pankov } 1833*260e9a87SYuri Pankov if (n->type != MDOC_TEXT) 1834*260e9a87SYuri Pankov break; 1835*260e9a87SYuri Pankov for (name = n->string; *name != '\0'; name++) 1836*260e9a87SYuri Pankov if (isalpha((const unsigned char)*name)) 1837*260e9a87SYuri Pankov return; 1838*260e9a87SYuri Pankov lastpunct = n->string; 1839*260e9a87SYuri Pankov if (n->next == NULL) 1840*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_XR_PUNCT, mdoc->parse, 1841*260e9a87SYuri Pankov n->line, n->pos, "%s after %s(%s)", 1842*260e9a87SYuri Pankov lastpunct, lastname, lastsec); 1843*260e9a87SYuri Pankov n = n->next; 1844*260e9a87SYuri Pankov } 184595c635efSGarrett D'Amore } 184695c635efSGarrett D'Amore 184795c635efSGarrett D'Amore static int 1848*260e9a87SYuri Pankov child_an(const struct mdoc_node *n) 1849*260e9a87SYuri Pankov { 1850*260e9a87SYuri Pankov 1851*260e9a87SYuri Pankov for (n = n->child; n != NULL; n = n->next) 1852*260e9a87SYuri Pankov if ((n->tok == MDOC_An && n->nchild) || child_an(n)) 1853*260e9a87SYuri Pankov return(1); 1854*260e9a87SYuri Pankov return(0); 1855*260e9a87SYuri Pankov } 1856*260e9a87SYuri Pankov 1857*260e9a87SYuri Pankov static void 1858*260e9a87SYuri Pankov post_sh_authors(POST_ARGS) 1859*260e9a87SYuri Pankov { 1860*260e9a87SYuri Pankov 1861*260e9a87SYuri Pankov if ( ! child_an(mdoc->last)) 1862*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_AN_MISSING, mdoc->parse, 1863*260e9a87SYuri Pankov mdoc->last->line, mdoc->last->pos, NULL); 1864*260e9a87SYuri Pankov } 1865*260e9a87SYuri Pankov 1866*260e9a87SYuri Pankov static void 186795c635efSGarrett D'Amore post_sh_head(POST_ARGS) 186895c635efSGarrett D'Amore { 186995c635efSGarrett D'Amore struct mdoc_node *n; 1870*260e9a87SYuri Pankov const char *goodsec; 1871*260e9a87SYuri Pankov char *secname; 187295c635efSGarrett D'Amore enum mdoc_sec sec; 187395c635efSGarrett D'Amore 187495c635efSGarrett D'Amore /* 187595c635efSGarrett D'Amore * Process a new section. Sections are either "named" or 187695c635efSGarrett D'Amore * "custom". Custom sections are user-defined, while named ones 187795c635efSGarrett D'Amore * follow a conventional order and may only appear in certain 187895c635efSGarrett D'Amore * manual sections. 187995c635efSGarrett D'Amore */ 188095c635efSGarrett D'Amore 1881*260e9a87SYuri Pankov secname = NULL; 188295c635efSGarrett D'Amore sec = SEC_CUSTOM; 1883*260e9a87SYuri Pankov mdoc_deroff(&secname, mdoc->last); 1884*260e9a87SYuri Pankov sec = NULL == secname ? SEC_CUSTOM : a2sec(secname); 188595c635efSGarrett D'Amore 188695c635efSGarrett D'Amore /* The NAME should be first. */ 188795c635efSGarrett D'Amore 188895c635efSGarrett D'Amore if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed) 1889*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_NAMESEC_FIRST, mdoc->parse, 1890*260e9a87SYuri Pankov mdoc->last->line, mdoc->last->pos, 1891*260e9a87SYuri Pankov "Sh %s", secname); 189295c635efSGarrett D'Amore 189395c635efSGarrett D'Amore /* The SYNOPSIS gets special attention in other areas. */ 189495c635efSGarrett D'Amore 1895698f87a4SGarrett D'Amore if (SEC_SYNOPSIS == sec) { 1896698f87a4SGarrett D'Amore roff_setreg(mdoc->roff, "nS", 1, '='); 189795c635efSGarrett D'Amore mdoc->flags |= MDOC_SYNOPSIS; 1898698f87a4SGarrett D'Amore } else { 1899698f87a4SGarrett D'Amore roff_setreg(mdoc->roff, "nS", 0, '='); 190095c635efSGarrett D'Amore mdoc->flags &= ~MDOC_SYNOPSIS; 1901698f87a4SGarrett D'Amore } 190295c635efSGarrett D'Amore 190395c635efSGarrett D'Amore /* Mark our last section. */ 190495c635efSGarrett D'Amore 190595c635efSGarrett D'Amore mdoc->lastsec = sec; 190695c635efSGarrett D'Amore 190795c635efSGarrett D'Amore /* 190895c635efSGarrett D'Amore * Set the section attribute for the current HEAD, for its 190995c635efSGarrett D'Amore * parent BLOCK, and for the HEAD children; the latter can 191095c635efSGarrett D'Amore * only be TEXT nodes, so no recursion is needed. 191195c635efSGarrett D'Amore * For other blocks and elements, including .Sh BODY, this is 191295c635efSGarrett D'Amore * done when allocating the node data structures, but for .Sh 191395c635efSGarrett D'Amore * BLOCK and HEAD, the section is still unknown at that time. 191495c635efSGarrett D'Amore */ 191595c635efSGarrett D'Amore 191695c635efSGarrett D'Amore mdoc->last->parent->sec = sec; 191795c635efSGarrett D'Amore mdoc->last->sec = sec; 191895c635efSGarrett D'Amore for (n = mdoc->last->child; n; n = n->next) 191995c635efSGarrett D'Amore n->sec = sec; 192095c635efSGarrett D'Amore 192195c635efSGarrett D'Amore /* We don't care about custom sections after this. */ 192295c635efSGarrett D'Amore 1923*260e9a87SYuri Pankov if (SEC_CUSTOM == sec) { 1924*260e9a87SYuri Pankov free(secname); 1925*260e9a87SYuri Pankov return; 1926*260e9a87SYuri Pankov } 192795c635efSGarrett D'Amore 192895c635efSGarrett D'Amore /* 192995c635efSGarrett D'Amore * Check whether our non-custom section is being repeated or is 193095c635efSGarrett D'Amore * out of order. 193195c635efSGarrett D'Amore */ 193295c635efSGarrett D'Amore 193395c635efSGarrett D'Amore if (sec == mdoc->lastnamed) 1934*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_SEC_REP, mdoc->parse, 1935*260e9a87SYuri Pankov mdoc->last->line, mdoc->last->pos, 1936*260e9a87SYuri Pankov "Sh %s", secname); 193795c635efSGarrett D'Amore 193895c635efSGarrett D'Amore if (sec < mdoc->lastnamed) 1939*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_SEC_ORDER, mdoc->parse, 1940*260e9a87SYuri Pankov mdoc->last->line, mdoc->last->pos, 1941*260e9a87SYuri Pankov "Sh %s", secname); 194295c635efSGarrett D'Amore 194395c635efSGarrett D'Amore /* Mark the last named section. */ 194495c635efSGarrett D'Amore 194595c635efSGarrett D'Amore mdoc->lastnamed = sec; 194695c635efSGarrett D'Amore 194795c635efSGarrett D'Amore /* Check particular section/manual conventions. */ 194895c635efSGarrett D'Amore 1949*260e9a87SYuri Pankov if (mdoc->meta.msec == NULL) { 1950*260e9a87SYuri Pankov free(secname); 1951*260e9a87SYuri Pankov return; 1952*260e9a87SYuri Pankov } 195395c635efSGarrett D'Amore 1954*260e9a87SYuri Pankov goodsec = NULL; 195595c635efSGarrett D'Amore switch (sec) { 1956*260e9a87SYuri Pankov case SEC_ERRORS: 1957*260e9a87SYuri Pankov if (*mdoc->meta.msec == '4') 1958*260e9a87SYuri Pankov break; 1959*260e9a87SYuri Pankov goodsec = "2, 3, 4, 9"; 196095c635efSGarrett D'Amore /* FALLTHROUGH */ 1961*260e9a87SYuri Pankov case SEC_RETURN_VALUES: 196295c635efSGarrett D'Amore /* FALLTHROUGH */ 1963*260e9a87SYuri Pankov case SEC_LIBRARY: 196495c635efSGarrett D'Amore if (*mdoc->meta.msec == '2') 196595c635efSGarrett D'Amore break; 196695c635efSGarrett D'Amore if (*mdoc->meta.msec == '3') 196795c635efSGarrett D'Amore break; 1968*260e9a87SYuri Pankov if (NULL == goodsec) 1969*260e9a87SYuri Pankov goodsec = "2, 3, 9"; 1970*260e9a87SYuri Pankov /* FALLTHROUGH */ 1971*260e9a87SYuri Pankov case SEC_CONTEXT: 197295c635efSGarrett D'Amore if (*mdoc->meta.msec == '9') 197395c635efSGarrett D'Amore break; 1974*260e9a87SYuri Pankov if (NULL == goodsec) 1975*260e9a87SYuri Pankov goodsec = "9"; 1976*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_SEC_MSEC, mdoc->parse, 1977*260e9a87SYuri Pankov mdoc->last->line, mdoc->last->pos, 1978*260e9a87SYuri Pankov "Sh %s for %s only", secname, goodsec); 197995c635efSGarrett D'Amore break; 198095c635efSGarrett D'Amore default: 198195c635efSGarrett D'Amore break; 198295c635efSGarrett D'Amore } 1983*260e9a87SYuri Pankov free(secname); 198495c635efSGarrett D'Amore } 198595c635efSGarrett D'Amore 1986*260e9a87SYuri Pankov static void 198795c635efSGarrett D'Amore post_ignpar(POST_ARGS) 198895c635efSGarrett D'Amore { 198995c635efSGarrett D'Amore struct mdoc_node *np; 199095c635efSGarrett D'Amore 1991*260e9a87SYuri Pankov switch (mdoc->last->type) { 1992*260e9a87SYuri Pankov case MDOC_HEAD: 1993*260e9a87SYuri Pankov post_hyph(mdoc); 1994*260e9a87SYuri Pankov return; 1995*260e9a87SYuri Pankov case MDOC_BODY: 1996*260e9a87SYuri Pankov break; 1997*260e9a87SYuri Pankov default: 1998*260e9a87SYuri Pankov return; 1999*260e9a87SYuri Pankov } 200095c635efSGarrett D'Amore 200195c635efSGarrett D'Amore if (NULL != (np = mdoc->last->child)) 200295c635efSGarrett D'Amore if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) { 2003*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_PAR_SKIP, 2004*260e9a87SYuri Pankov mdoc->parse, np->line, np->pos, 2005*260e9a87SYuri Pankov "%s after %s", mdoc_macronames[np->tok], 2006*260e9a87SYuri Pankov mdoc_macronames[mdoc->last->tok]); 200795c635efSGarrett D'Amore mdoc_node_delete(mdoc, np); 200895c635efSGarrett D'Amore } 200995c635efSGarrett D'Amore 201095c635efSGarrett D'Amore if (NULL != (np = mdoc->last->last)) 201195c635efSGarrett D'Amore if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) { 2012*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse, 2013*260e9a87SYuri Pankov np->line, np->pos, "%s at the end of %s", 2014*260e9a87SYuri Pankov mdoc_macronames[np->tok], 2015*260e9a87SYuri Pankov mdoc_macronames[mdoc->last->tok]); 201695c635efSGarrett D'Amore mdoc_node_delete(mdoc, np); 201795c635efSGarrett D'Amore } 201895c635efSGarrett D'Amore } 201995c635efSGarrett D'Amore 2020*260e9a87SYuri Pankov static void 202195c635efSGarrett D'Amore pre_par(PRE_ARGS) 202295c635efSGarrett D'Amore { 202395c635efSGarrett D'Amore 202495c635efSGarrett D'Amore if (NULL == mdoc->last) 2025*260e9a87SYuri Pankov return; 202695c635efSGarrett D'Amore if (MDOC_ELEM != n->type && MDOC_BLOCK != n->type) 2027*260e9a87SYuri Pankov return; 202895c635efSGarrett D'Amore 202995c635efSGarrett D'Amore /* 203095c635efSGarrett D'Amore * Don't allow prior `Lp' or `Pp' prior to a paragraph-type 203195c635efSGarrett D'Amore * block: `Lp', `Pp', or non-compact `Bd' or `Bl'. 203295c635efSGarrett D'Amore */ 203395c635efSGarrett D'Amore 2034698f87a4SGarrett D'Amore if (MDOC_Pp != mdoc->last->tok && 2035698f87a4SGarrett D'Amore MDOC_Lp != mdoc->last->tok && 2036698f87a4SGarrett D'Amore MDOC_br != mdoc->last->tok) 2037*260e9a87SYuri Pankov return; 203895c635efSGarrett D'Amore if (MDOC_Bl == n->tok && n->norm->Bl.comp) 2039*260e9a87SYuri Pankov return; 204095c635efSGarrett D'Amore if (MDOC_Bd == n->tok && n->norm->Bd.comp) 2041*260e9a87SYuri Pankov return; 204295c635efSGarrett D'Amore if (MDOC_It == n->tok && n->parent->norm->Bl.comp) 2043*260e9a87SYuri Pankov return; 204495c635efSGarrett D'Amore 2045*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse, 2046*260e9a87SYuri Pankov mdoc->last->line, mdoc->last->pos, 2047*260e9a87SYuri Pankov "%s before %s", mdoc_macronames[mdoc->last->tok], 2048*260e9a87SYuri Pankov mdoc_macronames[n->tok]); 204995c635efSGarrett D'Amore mdoc_node_delete(mdoc, mdoc->last); 205095c635efSGarrett D'Amore } 205195c635efSGarrett D'Amore 2052*260e9a87SYuri Pankov static void 2053698f87a4SGarrett D'Amore post_par(POST_ARGS) 2054698f87a4SGarrett D'Amore { 2055*260e9a87SYuri Pankov struct mdoc_node *np; 2056698f87a4SGarrett D'Amore 2057*260e9a87SYuri Pankov np = mdoc->last; 2058698f87a4SGarrett D'Amore 2059*260e9a87SYuri Pankov if (np->tok == MDOC_sp) { 2060*260e9a87SYuri Pankov if (np->nchild > 1) 2061*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, 2062*260e9a87SYuri Pankov np->child->next->line, np->child->next->pos, 2063*260e9a87SYuri Pankov "sp ... %s", np->child->next->string); 2064*260e9a87SYuri Pankov } else if (np->child != NULL) 2065*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_SKIP, 2066*260e9a87SYuri Pankov mdoc->parse, np->line, np->pos, "%s %s", 2067*260e9a87SYuri Pankov mdoc_macronames[np->tok], np->child->string); 2068*260e9a87SYuri Pankov 2069*260e9a87SYuri Pankov if (NULL == (np = mdoc->last->prev)) { 2070*260e9a87SYuri Pankov np = mdoc->last->parent; 2071*260e9a87SYuri Pankov if (MDOC_Sh != np->tok && MDOC_Ss != np->tok) 2072*260e9a87SYuri Pankov return; 2073*260e9a87SYuri Pankov } else if (MDOC_Pp != np->tok && MDOC_Lp != np->tok && 2074698f87a4SGarrett D'Amore (MDOC_br != mdoc->last->tok || 2075*260e9a87SYuri Pankov (MDOC_sp != np->tok && MDOC_br != np->tok))) 2076*260e9a87SYuri Pankov return; 2077698f87a4SGarrett D'Amore 2078*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse, 2079*260e9a87SYuri Pankov mdoc->last->line, mdoc->last->pos, 2080*260e9a87SYuri Pankov "%s after %s", mdoc_macronames[mdoc->last->tok], 2081*260e9a87SYuri Pankov mdoc_macronames[np->tok]); 2082698f87a4SGarrett D'Amore mdoc_node_delete(mdoc, mdoc->last); 2083698f87a4SGarrett D'Amore } 2084698f87a4SGarrett D'Amore 2085*260e9a87SYuri Pankov static void 208695c635efSGarrett D'Amore pre_literal(PRE_ARGS) 208795c635efSGarrett D'Amore { 208895c635efSGarrett D'Amore 2089*260e9a87SYuri Pankov pre_display(mdoc, n); 2090*260e9a87SYuri Pankov 209195c635efSGarrett D'Amore if (MDOC_BODY != n->type) 2092*260e9a87SYuri Pankov return; 209395c635efSGarrett D'Amore 209495c635efSGarrett D'Amore /* 209595c635efSGarrett D'Amore * The `Dl' (note "el" not "one") and `Bd -literal' and `Bd 209695c635efSGarrett D'Amore * -unfilled' macros set MDOC_LITERAL on entrance to the body. 209795c635efSGarrett D'Amore */ 209895c635efSGarrett D'Amore 209995c635efSGarrett D'Amore switch (n->tok) { 2100*260e9a87SYuri Pankov case MDOC_Dl: 210195c635efSGarrett D'Amore mdoc->flags |= MDOC_LITERAL; 210295c635efSGarrett D'Amore break; 2103*260e9a87SYuri Pankov case MDOC_Bd: 210495c635efSGarrett D'Amore if (DISP_literal == n->norm->Bd.type) 210595c635efSGarrett D'Amore mdoc->flags |= MDOC_LITERAL; 210695c635efSGarrett D'Amore if (DISP_unfilled == n->norm->Bd.type) 210795c635efSGarrett D'Amore mdoc->flags |= MDOC_LITERAL; 210895c635efSGarrett D'Amore break; 210995c635efSGarrett D'Amore default: 211095c635efSGarrett D'Amore abort(); 211195c635efSGarrett D'Amore /* NOTREACHED */ 211295c635efSGarrett D'Amore } 211395c635efSGarrett D'Amore } 211495c635efSGarrett D'Amore 2115*260e9a87SYuri Pankov static void 211695c635efSGarrett D'Amore post_dd(POST_ARGS) 211795c635efSGarrett D'Amore { 211895c635efSGarrett D'Amore struct mdoc_node *n; 2119*260e9a87SYuri Pankov char *datestr; 212095c635efSGarrett D'Amore 212195c635efSGarrett D'Amore if (mdoc->meta.date) 212295c635efSGarrett D'Amore free(mdoc->meta.date); 212395c635efSGarrett D'Amore 212495c635efSGarrett D'Amore n = mdoc->last; 212595c635efSGarrett D'Amore if (NULL == n->child || '\0' == n->child->string[0]) { 2126*260e9a87SYuri Pankov mdoc->meta.date = mdoc->quick ? mandoc_strdup("") : 2127*260e9a87SYuri Pankov mandoc_normdate(mdoc->parse, NULL, n->line, n->pos); 2128*260e9a87SYuri Pankov goto out; 212995c635efSGarrett D'Amore } 213095c635efSGarrett D'Amore 2131*260e9a87SYuri Pankov datestr = NULL; 2132*260e9a87SYuri Pankov mdoc_deroff(&datestr, n); 2133*260e9a87SYuri Pankov if (mdoc->quick) 2134*260e9a87SYuri Pankov mdoc->meta.date = datestr; 2135*260e9a87SYuri Pankov else { 2136*260e9a87SYuri Pankov mdoc->meta.date = mandoc_normdate(mdoc->parse, 2137*260e9a87SYuri Pankov datestr, n->line, n->pos); 2138*260e9a87SYuri Pankov free(datestr); 2139*260e9a87SYuri Pankov } 2140*260e9a87SYuri Pankov out: 2141*260e9a87SYuri Pankov mdoc_node_delete(mdoc, n); 214295c635efSGarrett D'Amore } 214395c635efSGarrett D'Amore 2144*260e9a87SYuri Pankov static void 214595c635efSGarrett D'Amore post_dt(POST_ARGS) 214695c635efSGarrett D'Amore { 214795c635efSGarrett D'Amore struct mdoc_node *nn, *n; 214895c635efSGarrett D'Amore const char *cp; 214995c635efSGarrett D'Amore char *p; 215095c635efSGarrett D'Amore 215195c635efSGarrett D'Amore n = mdoc->last; 215295c635efSGarrett D'Amore 215395c635efSGarrett D'Amore free(mdoc->meta.title); 2154*260e9a87SYuri Pankov free(mdoc->meta.msec); 215595c635efSGarrett D'Amore free(mdoc->meta.vol); 215695c635efSGarrett D'Amore free(mdoc->meta.arch); 215795c635efSGarrett D'Amore 2158*260e9a87SYuri Pankov mdoc->meta.title = NULL; 2159*260e9a87SYuri Pankov mdoc->meta.msec = NULL; 2160*260e9a87SYuri Pankov mdoc->meta.vol = NULL; 2161*260e9a87SYuri Pankov mdoc->meta.arch = NULL; 216295c635efSGarrett D'Amore 2163*260e9a87SYuri Pankov /* Mandatory first argument: title. */ 216495c635efSGarrett D'Amore 2165*260e9a87SYuri Pankov nn = n->child; 2166*260e9a87SYuri Pankov if (nn == NULL || *nn->string == '\0') { 2167*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_DT_NOTITLE, 2168*260e9a87SYuri Pankov mdoc->parse, n->line, n->pos, "Dt"); 2169*260e9a87SYuri Pankov mdoc->meta.title = mandoc_strdup("UNTITLED"); 2170*260e9a87SYuri Pankov } else { 2171*260e9a87SYuri Pankov mdoc->meta.title = mandoc_strdup(nn->string); 217295c635efSGarrett D'Amore 2173*260e9a87SYuri Pankov /* Check that all characters are uppercase. */ 2174*260e9a87SYuri Pankov 2175*260e9a87SYuri Pankov for (p = nn->string; *p != '\0'; p++) 2176*260e9a87SYuri Pankov if (islower((unsigned char)*p)) { 2177*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_TITLE_CASE, 2178*260e9a87SYuri Pankov mdoc->parse, nn->line, 2179*260e9a87SYuri Pankov nn->pos + (p - nn->string), 2180*260e9a87SYuri Pankov "Dt %s", nn->string); 218195c635efSGarrett D'Amore break; 218295c635efSGarrett D'Amore } 218395c635efSGarrett D'Amore } 218495c635efSGarrett D'Amore 2185*260e9a87SYuri Pankov /* Mandatory second argument: section.�*/ 218695c635efSGarrett D'Amore 2187*260e9a87SYuri Pankov if (nn != NULL) 2188*260e9a87SYuri Pankov nn = nn->next; 218995c635efSGarrett D'Amore 2190*260e9a87SYuri Pankov if (nn == NULL) { 2191*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_MSEC_MISSING, 2192*260e9a87SYuri Pankov mdoc->parse, n->line, n->pos, 2193*260e9a87SYuri Pankov "Dt %s", mdoc->meta.title); 219495c635efSGarrett D'Amore mdoc->meta.vol = mandoc_strdup("LOCAL"); 2195*260e9a87SYuri Pankov goto out; /* msec and arch remain NULL. */ 219695c635efSGarrett D'Amore } 219795c635efSGarrett D'Amore 2198*260e9a87SYuri Pankov mdoc->meta.msec = mandoc_strdup(nn->string); 2199*260e9a87SYuri Pankov 2200*260e9a87SYuri Pankov /* Infer volume title from section number. */ 220195c635efSGarrett D'Amore 220295c635efSGarrett D'Amore cp = mandoc_a2msec(nn->string); 2203*260e9a87SYuri Pankov if (cp == NULL) { 2204*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_MSEC_BAD, mdoc->parse, 2205*260e9a87SYuri Pankov nn->line, nn->pos, "Dt ... %s", nn->string); 220695c635efSGarrett D'Amore mdoc->meta.vol = mandoc_strdup(nn->string); 220795c635efSGarrett D'Amore } else 2208*260e9a87SYuri Pankov mdoc->meta.vol = mandoc_strdup(cp); 2209*260e9a87SYuri Pankov 2210*260e9a87SYuri Pankov /* Optional third argument: architecture. */ 2211*260e9a87SYuri Pankov 2212*260e9a87SYuri Pankov if ((nn = nn->next) == NULL) 2213*260e9a87SYuri Pankov goto out; 2214*260e9a87SYuri Pankov 2215*260e9a87SYuri Pankov for (p = nn->string; *p != '\0'; p++) 2216*260e9a87SYuri Pankov *p = tolower((unsigned char)*p); 2217*260e9a87SYuri Pankov mdoc->meta.arch = mandoc_strdup(nn->string); 2218*260e9a87SYuri Pankov 2219*260e9a87SYuri Pankov /* Ignore fourth and later arguments. */ 2220*260e9a87SYuri Pankov 2221*260e9a87SYuri Pankov if ((nn = nn->next) != NULL) 2222*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, 2223*260e9a87SYuri Pankov nn->line, nn->pos, "Dt ... %s", nn->string); 2224*260e9a87SYuri Pankov 2225*260e9a87SYuri Pankov out: 2226*260e9a87SYuri Pankov mdoc_node_delete(mdoc, n); 222795c635efSGarrett D'Amore } 222895c635efSGarrett D'Amore 2229*260e9a87SYuri Pankov static void 223095c635efSGarrett D'Amore post_bx(POST_ARGS) 223195c635efSGarrett D'Amore { 223295c635efSGarrett D'Amore struct mdoc_node *n; 223395c635efSGarrett D'Amore 223495c635efSGarrett D'Amore /* 223595c635efSGarrett D'Amore * Make `Bx's second argument always start with an uppercase 223695c635efSGarrett D'Amore * letter. Groff checks if it's an "accepted" term, but we just 223795c635efSGarrett D'Amore * uppercase blindly. 223895c635efSGarrett D'Amore */ 223995c635efSGarrett D'Amore 224095c635efSGarrett D'Amore n = mdoc->last->child; 224195c635efSGarrett D'Amore if (n && NULL != (n = n->next)) 2242*260e9a87SYuri Pankov *n->string = (char)toupper((unsigned char)*n->string); 224395c635efSGarrett D'Amore } 224495c635efSGarrett D'Amore 2245*260e9a87SYuri Pankov static void 224695c635efSGarrett D'Amore post_os(POST_ARGS) 224795c635efSGarrett D'Amore { 224895c635efSGarrett D'Amore #ifndef OSNAME 224995c635efSGarrett D'Amore struct utsname utsname; 2250*260e9a87SYuri Pankov static char *defbuf; 225195c635efSGarrett D'Amore #endif 2252*260e9a87SYuri Pankov struct mdoc_node *n; 225395c635efSGarrett D'Amore 225495c635efSGarrett D'Amore n = mdoc->last; 225595c635efSGarrett D'Amore 225695c635efSGarrett D'Amore /* 2257698f87a4SGarrett D'Amore * Set the operating system by way of the `Os' macro. 2258698f87a4SGarrett D'Amore * The order of precedence is: 2259698f87a4SGarrett D'Amore * 1. the argument of the `Os' macro, unless empty 2260698f87a4SGarrett D'Amore * 2. the -Ios=foo command line argument, if provided 2261698f87a4SGarrett D'Amore * 3. -DOSNAME="\"foo\"", if provided during compilation 2262698f87a4SGarrett D'Amore * 4. "sysname release" from uname(3) 226395c635efSGarrett D'Amore */ 226495c635efSGarrett D'Amore 226595c635efSGarrett D'Amore free(mdoc->meta.os); 2266*260e9a87SYuri Pankov mdoc->meta.os = NULL; 2267*260e9a87SYuri Pankov mdoc_deroff(&mdoc->meta.os, n); 2268*260e9a87SYuri Pankov if (mdoc->meta.os) 2269*260e9a87SYuri Pankov goto out; 227095c635efSGarrett D'Amore 2271698f87a4SGarrett D'Amore if (mdoc->defos) { 2272698f87a4SGarrett D'Amore mdoc->meta.os = mandoc_strdup(mdoc->defos); 2273*260e9a87SYuri Pankov goto out; 2274698f87a4SGarrett D'Amore } 2275*260e9a87SYuri Pankov 227695c635efSGarrett D'Amore #ifdef OSNAME 2277*260e9a87SYuri Pankov mdoc->meta.os = mandoc_strdup(OSNAME); 227895c635efSGarrett D'Amore #else /*!OSNAME */ 2279*260e9a87SYuri Pankov if (NULL == defbuf) { 228095c635efSGarrett D'Amore if (-1 == uname(&utsname)) { 2281*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_OS_UNAME, mdoc->parse, 2282*260e9a87SYuri Pankov n->line, n->pos, "Os"); 2283*260e9a87SYuri Pankov defbuf = mandoc_strdup("UNKNOWN"); 2284*260e9a87SYuri Pankov } else 2285*260e9a87SYuri Pankov mandoc_asprintf(&defbuf, "%s %s", 2286*260e9a87SYuri Pankov utsname.sysname, utsname.release); 228795c635efSGarrett D'Amore } 2288*260e9a87SYuri Pankov mdoc->meta.os = mandoc_strdup(defbuf); 228995c635efSGarrett D'Amore #endif /*!OSNAME*/ 2290*260e9a87SYuri Pankov 2291*260e9a87SYuri Pankov out: 2292*260e9a87SYuri Pankov mdoc_node_delete(mdoc, n); 229395c635efSGarrett D'Amore } 229495c635efSGarrett D'Amore 2295*260e9a87SYuri Pankov /* 2296*260e9a87SYuri Pankov * If no argument is provided, 2297*260e9a87SYuri Pankov * fill in the name of the current manual page. 2298*260e9a87SYuri Pankov */ 2299*260e9a87SYuri Pankov static void 2300*260e9a87SYuri Pankov post_ex(POST_ARGS) 230195c635efSGarrett D'Amore { 2302*260e9a87SYuri Pankov struct mdoc_node *n; 230395c635efSGarrett D'Amore 230495c635efSGarrett D'Amore n = mdoc->last; 230595c635efSGarrett D'Amore 230695c635efSGarrett D'Amore if (n->child) 2307*260e9a87SYuri Pankov return; 230895c635efSGarrett D'Amore 2309*260e9a87SYuri Pankov if (mdoc->meta.name == NULL) { 2310*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_EX_NONAME, mdoc->parse, 2311*260e9a87SYuri Pankov n->line, n->pos, "Ex"); 2312*260e9a87SYuri Pankov return; 2313*260e9a87SYuri Pankov } 231495c635efSGarrett D'Amore 231595c635efSGarrett D'Amore mdoc->next = MDOC_NEXT_CHILD; 2316*260e9a87SYuri Pankov mdoc_word_alloc(mdoc, n->line, n->pos, mdoc->meta.name); 2317*260e9a87SYuri Pankov mdoc->last = n; 231895c635efSGarrett D'Amore } 231995c635efSGarrett D'Amore 232095c635efSGarrett D'Amore static enum mdoc_sec 232195c635efSGarrett D'Amore a2sec(const char *p) 232295c635efSGarrett D'Amore { 232395c635efSGarrett D'Amore int i; 232495c635efSGarrett D'Amore 232595c635efSGarrett D'Amore for (i = 0; i < (int)SEC__MAX; i++) 232695c635efSGarrett D'Amore if (secnames[i] && 0 == strcmp(p, secnames[i])) 232795c635efSGarrett D'Amore return((enum mdoc_sec)i); 232895c635efSGarrett D'Amore 232995c635efSGarrett D'Amore return(SEC_CUSTOM); 233095c635efSGarrett D'Amore } 233195c635efSGarrett D'Amore 233295c635efSGarrett D'Amore static size_t 233395c635efSGarrett D'Amore macro2len(enum mdoct macro) 233495c635efSGarrett D'Amore { 233595c635efSGarrett D'Amore 233695c635efSGarrett D'Amore switch (macro) { 2337*260e9a87SYuri Pankov case MDOC_Ad: 233895c635efSGarrett D'Amore return(12); 2339*260e9a87SYuri Pankov case MDOC_Ao: 234095c635efSGarrett D'Amore return(12); 2341*260e9a87SYuri Pankov case MDOC_An: 234295c635efSGarrett D'Amore return(12); 2343*260e9a87SYuri Pankov case MDOC_Aq: 234495c635efSGarrett D'Amore return(12); 2345*260e9a87SYuri Pankov case MDOC_Ar: 234695c635efSGarrett D'Amore return(12); 2347*260e9a87SYuri Pankov case MDOC_Bo: 234895c635efSGarrett D'Amore return(12); 2349*260e9a87SYuri Pankov case MDOC_Bq: 235095c635efSGarrett D'Amore return(12); 2351*260e9a87SYuri Pankov case MDOC_Cd: 235295c635efSGarrett D'Amore return(12); 2353*260e9a87SYuri Pankov case MDOC_Cm: 235495c635efSGarrett D'Amore return(10); 2355*260e9a87SYuri Pankov case MDOC_Do: 235695c635efSGarrett D'Amore return(10); 2357*260e9a87SYuri Pankov case MDOC_Dq: 235895c635efSGarrett D'Amore return(12); 2359*260e9a87SYuri Pankov case MDOC_Dv: 236095c635efSGarrett D'Amore return(12); 2361*260e9a87SYuri Pankov case MDOC_Eo: 236295c635efSGarrett D'Amore return(12); 2363*260e9a87SYuri Pankov case MDOC_Em: 236495c635efSGarrett D'Amore return(10); 2365*260e9a87SYuri Pankov case MDOC_Er: 236695c635efSGarrett D'Amore return(17); 2367*260e9a87SYuri Pankov case MDOC_Ev: 236895c635efSGarrett D'Amore return(15); 2369*260e9a87SYuri Pankov case MDOC_Fa: 237095c635efSGarrett D'Amore return(12); 2371*260e9a87SYuri Pankov case MDOC_Fl: 237295c635efSGarrett D'Amore return(10); 2373*260e9a87SYuri Pankov case MDOC_Fo: 237495c635efSGarrett D'Amore return(16); 2375*260e9a87SYuri Pankov case MDOC_Fn: 237695c635efSGarrett D'Amore return(16); 2377*260e9a87SYuri Pankov case MDOC_Ic: 237895c635efSGarrett D'Amore return(10); 2379*260e9a87SYuri Pankov case MDOC_Li: 238095c635efSGarrett D'Amore return(16); 2381*260e9a87SYuri Pankov case MDOC_Ms: 238295c635efSGarrett D'Amore return(6); 2383*260e9a87SYuri Pankov case MDOC_Nm: 238495c635efSGarrett D'Amore return(10); 2385*260e9a87SYuri Pankov case MDOC_No: 238695c635efSGarrett D'Amore return(12); 2387*260e9a87SYuri Pankov case MDOC_Oo: 238895c635efSGarrett D'Amore return(10); 2389*260e9a87SYuri Pankov case MDOC_Op: 239095c635efSGarrett D'Amore return(14); 2391*260e9a87SYuri Pankov case MDOC_Pa: 239295c635efSGarrett D'Amore return(32); 2393*260e9a87SYuri Pankov case MDOC_Pf: 239495c635efSGarrett D'Amore return(12); 2395*260e9a87SYuri Pankov case MDOC_Po: 239695c635efSGarrett D'Amore return(12); 2397*260e9a87SYuri Pankov case MDOC_Pq: 239895c635efSGarrett D'Amore return(12); 2399*260e9a87SYuri Pankov case MDOC_Ql: 240095c635efSGarrett D'Amore return(16); 2401*260e9a87SYuri Pankov case MDOC_Qo: 240295c635efSGarrett D'Amore return(12); 2403*260e9a87SYuri Pankov case MDOC_So: 240495c635efSGarrett D'Amore return(12); 2405*260e9a87SYuri Pankov case MDOC_Sq: 240695c635efSGarrett D'Amore return(12); 2407*260e9a87SYuri Pankov case MDOC_Sy: 240895c635efSGarrett D'Amore return(6); 2409*260e9a87SYuri Pankov case MDOC_Sx: 241095c635efSGarrett D'Amore return(16); 2411*260e9a87SYuri Pankov case MDOC_Tn: 241295c635efSGarrett D'Amore return(10); 2413*260e9a87SYuri Pankov case MDOC_Va: 241495c635efSGarrett D'Amore return(12); 2415*260e9a87SYuri Pankov case MDOC_Vt: 241695c635efSGarrett D'Amore return(12); 2417*260e9a87SYuri Pankov case MDOC_Xr: 241895c635efSGarrett D'Amore return(10); 241995c635efSGarrett D'Amore default: 242095c635efSGarrett D'Amore break; 242195c635efSGarrett D'Amore }; 242295c635efSGarrett D'Amore return(0); 242395c635efSGarrett D'Amore } 2424