1*95c635efSGarrett D'Amore /* $Id: mdoc_validate.c,v 1.182 2012/03/23 05:50:25 kristaps Exp $ */ 2*95c635efSGarrett D'Amore /* 3*95c635efSGarrett D'Amore * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> 4*95c635efSGarrett D'Amore * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org> 5*95c635efSGarrett D'Amore * 6*95c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any 7*95c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above 8*95c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies. 9*95c635efSGarrett D'Amore * 10*95c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11*95c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12*95c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13*95c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14*95c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15*95c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16*95c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17*95c635efSGarrett D'Amore */ 18*95c635efSGarrett D'Amore #ifdef HAVE_CONFIG_H 19*95c635efSGarrett D'Amore #include "config.h" 20*95c635efSGarrett D'Amore #endif 21*95c635efSGarrett D'Amore 22*95c635efSGarrett D'Amore #ifndef OSNAME 23*95c635efSGarrett D'Amore #include <sys/utsname.h> 24*95c635efSGarrett D'Amore #endif 25*95c635efSGarrett D'Amore 26*95c635efSGarrett D'Amore #include <sys/types.h> 27*95c635efSGarrett D'Amore 28*95c635efSGarrett D'Amore #include <assert.h> 29*95c635efSGarrett D'Amore #include <ctype.h> 30*95c635efSGarrett D'Amore #include <limits.h> 31*95c635efSGarrett D'Amore #include <stdio.h> 32*95c635efSGarrett D'Amore #include <stdlib.h> 33*95c635efSGarrett D'Amore #include <string.h> 34*95c635efSGarrett D'Amore #include <time.h> 35*95c635efSGarrett D'Amore 36*95c635efSGarrett D'Amore #include "mdoc.h" 37*95c635efSGarrett D'Amore #include "mandoc.h" 38*95c635efSGarrett D'Amore #include "libmdoc.h" 39*95c635efSGarrett D'Amore #include "libmandoc.h" 40*95c635efSGarrett D'Amore 41*95c635efSGarrett D'Amore /* FIXME: .Bl -diag can't have non-text children in HEAD. */ 42*95c635efSGarrett D'Amore 43*95c635efSGarrett D'Amore #define PRE_ARGS struct mdoc *mdoc, struct mdoc_node *n 44*95c635efSGarrett D'Amore #define POST_ARGS struct mdoc *mdoc 45*95c635efSGarrett D'Amore 46*95c635efSGarrett D'Amore #define NUMSIZ 32 47*95c635efSGarrett D'Amore #define DATESIZE 32 48*95c635efSGarrett D'Amore 49*95c635efSGarrett D'Amore enum check_ineq { 50*95c635efSGarrett D'Amore CHECK_LT, 51*95c635efSGarrett D'Amore CHECK_GT, 52*95c635efSGarrett D'Amore CHECK_EQ 53*95c635efSGarrett D'Amore }; 54*95c635efSGarrett D'Amore 55*95c635efSGarrett D'Amore enum check_lvl { 56*95c635efSGarrett D'Amore CHECK_WARN, 57*95c635efSGarrett D'Amore CHECK_ERROR, 58*95c635efSGarrett D'Amore }; 59*95c635efSGarrett D'Amore 60*95c635efSGarrett D'Amore typedef int (*v_pre)(PRE_ARGS); 61*95c635efSGarrett D'Amore typedef int (*v_post)(POST_ARGS); 62*95c635efSGarrett D'Amore 63*95c635efSGarrett D'Amore struct valids { 64*95c635efSGarrett D'Amore v_pre *pre; 65*95c635efSGarrett D'Amore v_post *post; 66*95c635efSGarrett D'Amore }; 67*95c635efSGarrett D'Amore 68*95c635efSGarrett D'Amore static int check_count(struct mdoc *, enum mdoc_type, 69*95c635efSGarrett D'Amore enum check_lvl, enum check_ineq, int); 70*95c635efSGarrett D'Amore static int check_parent(PRE_ARGS, enum mdoct, enum mdoc_type); 71*95c635efSGarrett D'Amore static void check_text(struct mdoc *, int, int, char *); 72*95c635efSGarrett D'Amore static void check_argv(struct mdoc *, 73*95c635efSGarrett D'Amore struct mdoc_node *, struct mdoc_argv *); 74*95c635efSGarrett D'Amore static void check_args(struct mdoc *, struct mdoc_node *); 75*95c635efSGarrett D'Amore static int concat(char *, const struct mdoc_node *, size_t); 76*95c635efSGarrett D'Amore static enum mdoc_sec a2sec(const char *); 77*95c635efSGarrett D'Amore static size_t macro2len(enum mdoct); 78*95c635efSGarrett D'Amore 79*95c635efSGarrett D'Amore static int ebool(POST_ARGS); 80*95c635efSGarrett D'Amore static int berr_ge1(POST_ARGS); 81*95c635efSGarrett D'Amore static int bwarn_ge1(POST_ARGS); 82*95c635efSGarrett D'Amore static int ewarn_eq0(POST_ARGS); 83*95c635efSGarrett D'Amore static int ewarn_eq1(POST_ARGS); 84*95c635efSGarrett D'Amore static int ewarn_ge1(POST_ARGS); 85*95c635efSGarrett D'Amore static int ewarn_le1(POST_ARGS); 86*95c635efSGarrett D'Amore static int hwarn_eq0(POST_ARGS); 87*95c635efSGarrett D'Amore static int hwarn_eq1(POST_ARGS); 88*95c635efSGarrett D'Amore static int hwarn_ge1(POST_ARGS); 89*95c635efSGarrett D'Amore static int hwarn_le1(POST_ARGS); 90*95c635efSGarrett D'Amore 91*95c635efSGarrett D'Amore static int post_an(POST_ARGS); 92*95c635efSGarrett D'Amore static int post_at(POST_ARGS); 93*95c635efSGarrett D'Amore static int post_bf(POST_ARGS); 94*95c635efSGarrett D'Amore static int post_bl(POST_ARGS); 95*95c635efSGarrett D'Amore static int post_bl_block(POST_ARGS); 96*95c635efSGarrett D'Amore static int post_bl_block_width(POST_ARGS); 97*95c635efSGarrett D'Amore static int post_bl_block_tag(POST_ARGS); 98*95c635efSGarrett D'Amore static int post_bl_head(POST_ARGS); 99*95c635efSGarrett D'Amore static int post_bx(POST_ARGS); 100*95c635efSGarrett D'Amore static int post_dd(POST_ARGS); 101*95c635efSGarrett D'Amore static int post_dt(POST_ARGS); 102*95c635efSGarrett D'Amore static int post_defaults(POST_ARGS); 103*95c635efSGarrett D'Amore static int post_literal(POST_ARGS); 104*95c635efSGarrett D'Amore static int post_eoln(POST_ARGS); 105*95c635efSGarrett D'Amore static int post_it(POST_ARGS); 106*95c635efSGarrett D'Amore static int post_lb(POST_ARGS); 107*95c635efSGarrett D'Amore static int post_nm(POST_ARGS); 108*95c635efSGarrett D'Amore static int post_ns(POST_ARGS); 109*95c635efSGarrett D'Amore static int post_os(POST_ARGS); 110*95c635efSGarrett D'Amore static int post_ignpar(POST_ARGS); 111*95c635efSGarrett D'Amore static int post_prol(POST_ARGS); 112*95c635efSGarrett D'Amore static int post_root(POST_ARGS); 113*95c635efSGarrett D'Amore static int post_rs(POST_ARGS); 114*95c635efSGarrett D'Amore static int post_sh(POST_ARGS); 115*95c635efSGarrett D'Amore static int post_sh_body(POST_ARGS); 116*95c635efSGarrett D'Amore static int post_sh_head(POST_ARGS); 117*95c635efSGarrett D'Amore static int post_st(POST_ARGS); 118*95c635efSGarrett D'Amore static int post_std(POST_ARGS); 119*95c635efSGarrett D'Amore static int post_vt(POST_ARGS); 120*95c635efSGarrett D'Amore static int pre_an(PRE_ARGS); 121*95c635efSGarrett D'Amore static int pre_bd(PRE_ARGS); 122*95c635efSGarrett D'Amore static int pre_bl(PRE_ARGS); 123*95c635efSGarrett D'Amore static int pre_dd(PRE_ARGS); 124*95c635efSGarrett D'Amore static int pre_display(PRE_ARGS); 125*95c635efSGarrett D'Amore static int pre_dt(PRE_ARGS); 126*95c635efSGarrett D'Amore static int pre_it(PRE_ARGS); 127*95c635efSGarrett D'Amore static int pre_literal(PRE_ARGS); 128*95c635efSGarrett D'Amore static int pre_os(PRE_ARGS); 129*95c635efSGarrett D'Amore static int pre_par(PRE_ARGS); 130*95c635efSGarrett D'Amore static int pre_sh(PRE_ARGS); 131*95c635efSGarrett D'Amore static int pre_ss(PRE_ARGS); 132*95c635efSGarrett D'Amore static int pre_std(PRE_ARGS); 133*95c635efSGarrett D'Amore 134*95c635efSGarrett D'Amore static v_post posts_an[] = { post_an, NULL }; 135*95c635efSGarrett D'Amore static v_post posts_at[] = { post_at, post_defaults, NULL }; 136*95c635efSGarrett D'Amore static v_post posts_bd[] = { post_literal, hwarn_eq0, bwarn_ge1, NULL }; 137*95c635efSGarrett D'Amore static v_post posts_bf[] = { hwarn_le1, post_bf, NULL }; 138*95c635efSGarrett D'Amore static v_post posts_bk[] = { hwarn_eq0, bwarn_ge1, NULL }; 139*95c635efSGarrett D'Amore static v_post posts_bl[] = { bwarn_ge1, post_bl, NULL }; 140*95c635efSGarrett D'Amore static v_post posts_bx[] = { post_bx, NULL }; 141*95c635efSGarrett D'Amore static v_post posts_bool[] = { ebool, NULL }; 142*95c635efSGarrett D'Amore static v_post posts_eoln[] = { post_eoln, NULL }; 143*95c635efSGarrett D'Amore static v_post posts_defaults[] = { post_defaults, NULL }; 144*95c635efSGarrett D'Amore static v_post posts_dd[] = { post_dd, post_prol, NULL }; 145*95c635efSGarrett D'Amore static v_post posts_dl[] = { post_literal, bwarn_ge1, NULL }; 146*95c635efSGarrett D'Amore static v_post posts_dt[] = { post_dt, post_prol, NULL }; 147*95c635efSGarrett D'Amore static v_post posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL }; 148*95c635efSGarrett D'Amore static v_post posts_it[] = { post_it, NULL }; 149*95c635efSGarrett D'Amore static v_post posts_lb[] = { post_lb, NULL }; 150*95c635efSGarrett D'Amore static v_post posts_nd[] = { berr_ge1, NULL }; 151*95c635efSGarrett D'Amore static v_post posts_nm[] = { post_nm, NULL }; 152*95c635efSGarrett D'Amore static v_post posts_notext[] = { ewarn_eq0, NULL }; 153*95c635efSGarrett D'Amore static v_post posts_ns[] = { post_ns, NULL }; 154*95c635efSGarrett D'Amore static v_post posts_os[] = { post_os, post_prol, NULL }; 155*95c635efSGarrett D'Amore static v_post posts_rs[] = { post_rs, NULL }; 156*95c635efSGarrett D'Amore static v_post posts_sh[] = { post_ignpar, hwarn_ge1, post_sh, NULL }; 157*95c635efSGarrett D'Amore static v_post posts_sp[] = { ewarn_le1, NULL }; 158*95c635efSGarrett D'Amore static v_post posts_ss[] = { post_ignpar, hwarn_ge1, NULL }; 159*95c635efSGarrett D'Amore static v_post posts_st[] = { post_st, NULL }; 160*95c635efSGarrett D'Amore static v_post posts_std[] = { post_std, NULL }; 161*95c635efSGarrett D'Amore static v_post posts_text[] = { ewarn_ge1, NULL }; 162*95c635efSGarrett D'Amore static v_post posts_text1[] = { ewarn_eq1, NULL }; 163*95c635efSGarrett D'Amore static v_post posts_vt[] = { post_vt, NULL }; 164*95c635efSGarrett D'Amore static v_post posts_wline[] = { bwarn_ge1, NULL }; 165*95c635efSGarrett D'Amore static v_pre pres_an[] = { pre_an, NULL }; 166*95c635efSGarrett D'Amore static v_pre pres_bd[] = { pre_display, pre_bd, pre_literal, pre_par, NULL }; 167*95c635efSGarrett D'Amore static v_pre pres_bl[] = { pre_bl, pre_par, NULL }; 168*95c635efSGarrett D'Amore static v_pre pres_d1[] = { pre_display, NULL }; 169*95c635efSGarrett D'Amore static v_pre pres_dl[] = { pre_literal, pre_display, NULL }; 170*95c635efSGarrett D'Amore static v_pre pres_dd[] = { pre_dd, NULL }; 171*95c635efSGarrett D'Amore static v_pre pres_dt[] = { pre_dt, NULL }; 172*95c635efSGarrett D'Amore static v_pre pres_er[] = { NULL, NULL }; 173*95c635efSGarrett D'Amore static v_pre pres_fd[] = { NULL, NULL }; 174*95c635efSGarrett D'Amore static v_pre pres_it[] = { pre_it, pre_par, NULL }; 175*95c635efSGarrett D'Amore static v_pre pres_os[] = { pre_os, NULL }; 176*95c635efSGarrett D'Amore static v_pre pres_pp[] = { pre_par, NULL }; 177*95c635efSGarrett D'Amore static v_pre pres_sh[] = { pre_sh, NULL }; 178*95c635efSGarrett D'Amore static v_pre pres_ss[] = { pre_ss, NULL }; 179*95c635efSGarrett D'Amore static v_pre pres_std[] = { pre_std, NULL }; 180*95c635efSGarrett D'Amore 181*95c635efSGarrett D'Amore static const struct valids mdoc_valids[MDOC_MAX] = { 182*95c635efSGarrett D'Amore { NULL, NULL }, /* Ap */ 183*95c635efSGarrett D'Amore { pres_dd, posts_dd }, /* Dd */ 184*95c635efSGarrett D'Amore { pres_dt, posts_dt }, /* Dt */ 185*95c635efSGarrett D'Amore { pres_os, posts_os }, /* Os */ 186*95c635efSGarrett D'Amore { pres_sh, posts_sh }, /* Sh */ 187*95c635efSGarrett D'Amore { pres_ss, posts_ss }, /* Ss */ 188*95c635efSGarrett D'Amore { pres_pp, posts_notext }, /* Pp */ 189*95c635efSGarrett D'Amore { pres_d1, posts_wline }, /* D1 */ 190*95c635efSGarrett D'Amore { pres_dl, posts_dl }, /* Dl */ 191*95c635efSGarrett D'Amore { pres_bd, posts_bd }, /* Bd */ 192*95c635efSGarrett D'Amore { NULL, NULL }, /* Ed */ 193*95c635efSGarrett D'Amore { pres_bl, posts_bl }, /* Bl */ 194*95c635efSGarrett D'Amore { NULL, NULL }, /* El */ 195*95c635efSGarrett D'Amore { pres_it, posts_it }, /* It */ 196*95c635efSGarrett D'Amore { NULL, NULL }, /* Ad */ 197*95c635efSGarrett D'Amore { pres_an, posts_an }, /* An */ 198*95c635efSGarrett D'Amore { NULL, posts_defaults }, /* Ar */ 199*95c635efSGarrett D'Amore { NULL, NULL }, /* Cd */ 200*95c635efSGarrett D'Amore { NULL, NULL }, /* Cm */ 201*95c635efSGarrett D'Amore { NULL, NULL }, /* Dv */ 202*95c635efSGarrett D'Amore { pres_er, NULL }, /* Er */ 203*95c635efSGarrett D'Amore { NULL, NULL }, /* Ev */ 204*95c635efSGarrett D'Amore { pres_std, posts_std }, /* Ex */ 205*95c635efSGarrett D'Amore { NULL, NULL }, /* Fa */ 206*95c635efSGarrett D'Amore { pres_fd, posts_text }, /* Fd */ 207*95c635efSGarrett D'Amore { NULL, NULL }, /* Fl */ 208*95c635efSGarrett D'Amore { NULL, NULL }, /* Fn */ 209*95c635efSGarrett D'Amore { NULL, NULL }, /* Ft */ 210*95c635efSGarrett D'Amore { NULL, NULL }, /* Ic */ 211*95c635efSGarrett D'Amore { NULL, posts_text1 }, /* In */ 212*95c635efSGarrett D'Amore { NULL, posts_defaults }, /* Li */ 213*95c635efSGarrett D'Amore { NULL, posts_nd }, /* Nd */ 214*95c635efSGarrett D'Amore { NULL, posts_nm }, /* Nm */ 215*95c635efSGarrett D'Amore { NULL, NULL }, /* Op */ 216*95c635efSGarrett D'Amore { NULL, NULL }, /* Ot */ 217*95c635efSGarrett D'Amore { NULL, posts_defaults }, /* Pa */ 218*95c635efSGarrett D'Amore { pres_std, posts_std }, /* Rv */ 219*95c635efSGarrett D'Amore { NULL, posts_st }, /* St */ 220*95c635efSGarrett D'Amore { NULL, NULL }, /* Va */ 221*95c635efSGarrett D'Amore { NULL, posts_vt }, /* Vt */ 222*95c635efSGarrett D'Amore { NULL, posts_text }, /* Xr */ 223*95c635efSGarrett D'Amore { NULL, posts_text }, /* %A */ 224*95c635efSGarrett D'Amore { NULL, posts_text }, /* %B */ /* FIXME: can be used outside Rs/Re. */ 225*95c635efSGarrett D'Amore { NULL, posts_text }, /* %D */ 226*95c635efSGarrett D'Amore { NULL, posts_text }, /* %I */ 227*95c635efSGarrett D'Amore { NULL, posts_text }, /* %J */ 228*95c635efSGarrett D'Amore { NULL, posts_text }, /* %N */ 229*95c635efSGarrett D'Amore { NULL, posts_text }, /* %O */ 230*95c635efSGarrett D'Amore { NULL, posts_text }, /* %P */ 231*95c635efSGarrett D'Amore { NULL, posts_text }, /* %R */ 232*95c635efSGarrett D'Amore { NULL, posts_text }, /* %T */ /* FIXME: can be used outside Rs/Re. */ 233*95c635efSGarrett D'Amore { NULL, posts_text }, /* %V */ 234*95c635efSGarrett D'Amore { NULL, NULL }, /* Ac */ 235*95c635efSGarrett D'Amore { NULL, NULL }, /* Ao */ 236*95c635efSGarrett D'Amore { NULL, NULL }, /* Aq */ 237*95c635efSGarrett D'Amore { NULL, posts_at }, /* At */ 238*95c635efSGarrett D'Amore { NULL, NULL }, /* Bc */ 239*95c635efSGarrett D'Amore { NULL, posts_bf }, /* Bf */ 240*95c635efSGarrett D'Amore { NULL, NULL }, /* Bo */ 241*95c635efSGarrett D'Amore { NULL, NULL }, /* Bq */ 242*95c635efSGarrett D'Amore { NULL, NULL }, /* Bsx */ 243*95c635efSGarrett D'Amore { NULL, posts_bx }, /* Bx */ 244*95c635efSGarrett D'Amore { NULL, posts_bool }, /* Db */ 245*95c635efSGarrett D'Amore { NULL, NULL }, /* Dc */ 246*95c635efSGarrett D'Amore { NULL, NULL }, /* Do */ 247*95c635efSGarrett D'Amore { NULL, NULL }, /* Dq */ 248*95c635efSGarrett D'Amore { NULL, NULL }, /* Ec */ 249*95c635efSGarrett D'Amore { NULL, NULL }, /* Ef */ 250*95c635efSGarrett D'Amore { NULL, NULL }, /* Em */ 251*95c635efSGarrett D'Amore { NULL, NULL }, /* Eo */ 252*95c635efSGarrett D'Amore { NULL, NULL }, /* Fx */ 253*95c635efSGarrett D'Amore { NULL, NULL }, /* Ms */ 254*95c635efSGarrett D'Amore { NULL, posts_notext }, /* No */ 255*95c635efSGarrett D'Amore { NULL, posts_ns }, /* Ns */ 256*95c635efSGarrett D'Amore { NULL, NULL }, /* Nx */ 257*95c635efSGarrett D'Amore { NULL, NULL }, /* Ox */ 258*95c635efSGarrett D'Amore { NULL, NULL }, /* Pc */ 259*95c635efSGarrett D'Amore { NULL, posts_text1 }, /* Pf */ 260*95c635efSGarrett D'Amore { NULL, NULL }, /* Po */ 261*95c635efSGarrett D'Amore { NULL, NULL }, /* Pq */ 262*95c635efSGarrett D'Amore { NULL, NULL }, /* Qc */ 263*95c635efSGarrett D'Amore { NULL, NULL }, /* Ql */ 264*95c635efSGarrett D'Amore { NULL, NULL }, /* Qo */ 265*95c635efSGarrett D'Amore { NULL, NULL }, /* Qq */ 266*95c635efSGarrett D'Amore { NULL, NULL }, /* Re */ 267*95c635efSGarrett D'Amore { NULL, posts_rs }, /* Rs */ 268*95c635efSGarrett D'Amore { NULL, NULL }, /* Sc */ 269*95c635efSGarrett D'Amore { NULL, NULL }, /* So */ 270*95c635efSGarrett D'Amore { NULL, NULL }, /* Sq */ 271*95c635efSGarrett D'Amore { NULL, posts_bool }, /* Sm */ 272*95c635efSGarrett D'Amore { NULL, NULL }, /* Sx */ 273*95c635efSGarrett D'Amore { NULL, NULL }, /* Sy */ 274*95c635efSGarrett D'Amore { NULL, NULL }, /* Tn */ 275*95c635efSGarrett D'Amore { NULL, NULL }, /* Ux */ 276*95c635efSGarrett D'Amore { NULL, NULL }, /* Xc */ 277*95c635efSGarrett D'Amore { NULL, NULL }, /* Xo */ 278*95c635efSGarrett D'Amore { NULL, posts_fo }, /* Fo */ 279*95c635efSGarrett D'Amore { NULL, NULL }, /* Fc */ 280*95c635efSGarrett D'Amore { NULL, NULL }, /* Oo */ 281*95c635efSGarrett D'Amore { NULL, NULL }, /* Oc */ 282*95c635efSGarrett D'Amore { NULL, posts_bk }, /* Bk */ 283*95c635efSGarrett D'Amore { NULL, NULL }, /* Ek */ 284*95c635efSGarrett D'Amore { NULL, posts_eoln }, /* Bt */ 285*95c635efSGarrett D'Amore { NULL, NULL }, /* Hf */ 286*95c635efSGarrett D'Amore { NULL, NULL }, /* Fr */ 287*95c635efSGarrett D'Amore { NULL, posts_eoln }, /* Ud */ 288*95c635efSGarrett D'Amore { NULL, posts_lb }, /* Lb */ 289*95c635efSGarrett D'Amore { NULL, posts_notext }, /* Lp */ 290*95c635efSGarrett D'Amore { NULL, NULL }, /* Lk */ 291*95c635efSGarrett D'Amore { NULL, posts_defaults }, /* Mt */ 292*95c635efSGarrett D'Amore { NULL, NULL }, /* Brq */ 293*95c635efSGarrett D'Amore { NULL, NULL }, /* Bro */ 294*95c635efSGarrett D'Amore { NULL, NULL }, /* Brc */ 295*95c635efSGarrett D'Amore { NULL, posts_text }, /* %C */ 296*95c635efSGarrett D'Amore { NULL, NULL }, /* Es */ 297*95c635efSGarrett D'Amore { NULL, NULL }, /* En */ 298*95c635efSGarrett D'Amore { NULL, NULL }, /* Dx */ 299*95c635efSGarrett D'Amore { NULL, posts_text }, /* %Q */ 300*95c635efSGarrett D'Amore { NULL, posts_notext }, /* br */ 301*95c635efSGarrett D'Amore { pres_pp, posts_sp }, /* sp */ 302*95c635efSGarrett D'Amore { NULL, posts_text1 }, /* %U */ 303*95c635efSGarrett D'Amore { NULL, NULL }, /* Ta */ 304*95c635efSGarrett D'Amore }; 305*95c635efSGarrett D'Amore 306*95c635efSGarrett D'Amore #define RSORD_MAX 14 /* Number of `Rs' blocks. */ 307*95c635efSGarrett D'Amore 308*95c635efSGarrett D'Amore static const enum mdoct rsord[RSORD_MAX] = { 309*95c635efSGarrett D'Amore MDOC__A, 310*95c635efSGarrett D'Amore MDOC__T, 311*95c635efSGarrett D'Amore MDOC__B, 312*95c635efSGarrett D'Amore MDOC__I, 313*95c635efSGarrett D'Amore MDOC__J, 314*95c635efSGarrett D'Amore MDOC__R, 315*95c635efSGarrett D'Amore MDOC__N, 316*95c635efSGarrett D'Amore MDOC__V, 317*95c635efSGarrett D'Amore MDOC__P, 318*95c635efSGarrett D'Amore MDOC__Q, 319*95c635efSGarrett D'Amore MDOC__D, 320*95c635efSGarrett D'Amore MDOC__O, 321*95c635efSGarrett D'Amore MDOC__C, 322*95c635efSGarrett D'Amore MDOC__U 323*95c635efSGarrett D'Amore }; 324*95c635efSGarrett D'Amore 325*95c635efSGarrett D'Amore static const char * const secnames[SEC__MAX] = { 326*95c635efSGarrett D'Amore NULL, 327*95c635efSGarrett D'Amore "NAME", 328*95c635efSGarrett D'Amore "LIBRARY", 329*95c635efSGarrett D'Amore "SYNOPSIS", 330*95c635efSGarrett D'Amore "DESCRIPTION", 331*95c635efSGarrett D'Amore "IMPLEMENTATION NOTES", 332*95c635efSGarrett D'Amore "RETURN VALUES", 333*95c635efSGarrett D'Amore "ENVIRONMENT", 334*95c635efSGarrett D'Amore "FILES", 335*95c635efSGarrett D'Amore "EXIT STATUS", 336*95c635efSGarrett D'Amore "EXAMPLES", 337*95c635efSGarrett D'Amore "DIAGNOSTICS", 338*95c635efSGarrett D'Amore "COMPATIBILITY", 339*95c635efSGarrett D'Amore "ERRORS", 340*95c635efSGarrett D'Amore "SEE ALSO", 341*95c635efSGarrett D'Amore "STANDARDS", 342*95c635efSGarrett D'Amore "HISTORY", 343*95c635efSGarrett D'Amore "AUTHORS", 344*95c635efSGarrett D'Amore "CAVEATS", 345*95c635efSGarrett D'Amore "BUGS", 346*95c635efSGarrett D'Amore "SECURITY CONSIDERATIONS", 347*95c635efSGarrett D'Amore NULL 348*95c635efSGarrett D'Amore }; 349*95c635efSGarrett D'Amore 350*95c635efSGarrett D'Amore int 351*95c635efSGarrett D'Amore mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *n) 352*95c635efSGarrett D'Amore { 353*95c635efSGarrett D'Amore v_pre *p; 354*95c635efSGarrett D'Amore int line, pos; 355*95c635efSGarrett D'Amore char *tp; 356*95c635efSGarrett D'Amore 357*95c635efSGarrett D'Amore switch (n->type) { 358*95c635efSGarrett D'Amore case (MDOC_TEXT): 359*95c635efSGarrett D'Amore tp = n->string; 360*95c635efSGarrett D'Amore line = n->line; 361*95c635efSGarrett D'Amore pos = n->pos; 362*95c635efSGarrett D'Amore check_text(mdoc, line, pos, tp); 363*95c635efSGarrett D'Amore /* FALLTHROUGH */ 364*95c635efSGarrett D'Amore case (MDOC_TBL): 365*95c635efSGarrett D'Amore /* FALLTHROUGH */ 366*95c635efSGarrett D'Amore case (MDOC_EQN): 367*95c635efSGarrett D'Amore /* FALLTHROUGH */ 368*95c635efSGarrett D'Amore case (MDOC_ROOT): 369*95c635efSGarrett D'Amore return(1); 370*95c635efSGarrett D'Amore default: 371*95c635efSGarrett D'Amore break; 372*95c635efSGarrett D'Amore } 373*95c635efSGarrett D'Amore 374*95c635efSGarrett D'Amore check_args(mdoc, n); 375*95c635efSGarrett D'Amore 376*95c635efSGarrett D'Amore if (NULL == mdoc_valids[n->tok].pre) 377*95c635efSGarrett D'Amore return(1); 378*95c635efSGarrett D'Amore for (p = mdoc_valids[n->tok].pre; *p; p++) 379*95c635efSGarrett D'Amore if ( ! (*p)(mdoc, n)) 380*95c635efSGarrett D'Amore return(0); 381*95c635efSGarrett D'Amore return(1); 382*95c635efSGarrett D'Amore } 383*95c635efSGarrett D'Amore 384*95c635efSGarrett D'Amore 385*95c635efSGarrett D'Amore int 386*95c635efSGarrett D'Amore mdoc_valid_post(struct mdoc *mdoc) 387*95c635efSGarrett D'Amore { 388*95c635efSGarrett D'Amore v_post *p; 389*95c635efSGarrett D'Amore 390*95c635efSGarrett D'Amore if (MDOC_VALID & mdoc->last->flags) 391*95c635efSGarrett D'Amore return(1); 392*95c635efSGarrett D'Amore mdoc->last->flags |= MDOC_VALID; 393*95c635efSGarrett D'Amore 394*95c635efSGarrett D'Amore switch (mdoc->last->type) { 395*95c635efSGarrett D'Amore case (MDOC_TEXT): 396*95c635efSGarrett D'Amore /* FALLTHROUGH */ 397*95c635efSGarrett D'Amore case (MDOC_EQN): 398*95c635efSGarrett D'Amore /* FALLTHROUGH */ 399*95c635efSGarrett D'Amore case (MDOC_TBL): 400*95c635efSGarrett D'Amore return(1); 401*95c635efSGarrett D'Amore case (MDOC_ROOT): 402*95c635efSGarrett D'Amore return(post_root(mdoc)); 403*95c635efSGarrett D'Amore default: 404*95c635efSGarrett D'Amore break; 405*95c635efSGarrett D'Amore } 406*95c635efSGarrett D'Amore 407*95c635efSGarrett D'Amore if (NULL == mdoc_valids[mdoc->last->tok].post) 408*95c635efSGarrett D'Amore return(1); 409*95c635efSGarrett D'Amore for (p = mdoc_valids[mdoc->last->tok].post; *p; p++) 410*95c635efSGarrett D'Amore if ( ! (*p)(mdoc)) 411*95c635efSGarrett D'Amore return(0); 412*95c635efSGarrett D'Amore 413*95c635efSGarrett D'Amore return(1); 414*95c635efSGarrett D'Amore } 415*95c635efSGarrett D'Amore 416*95c635efSGarrett D'Amore static int 417*95c635efSGarrett D'Amore check_count(struct mdoc *m, enum mdoc_type type, 418*95c635efSGarrett D'Amore enum check_lvl lvl, enum check_ineq ineq, int val) 419*95c635efSGarrett D'Amore { 420*95c635efSGarrett D'Amore const char *p; 421*95c635efSGarrett D'Amore enum mandocerr t; 422*95c635efSGarrett D'Amore 423*95c635efSGarrett D'Amore if (m->last->type != type) 424*95c635efSGarrett D'Amore return(1); 425*95c635efSGarrett D'Amore 426*95c635efSGarrett D'Amore switch (ineq) { 427*95c635efSGarrett D'Amore case (CHECK_LT): 428*95c635efSGarrett D'Amore p = "less than "; 429*95c635efSGarrett D'Amore if (m->last->nchild < val) 430*95c635efSGarrett D'Amore return(1); 431*95c635efSGarrett D'Amore break; 432*95c635efSGarrett D'Amore case (CHECK_GT): 433*95c635efSGarrett D'Amore p = "more than "; 434*95c635efSGarrett D'Amore if (m->last->nchild > val) 435*95c635efSGarrett D'Amore return(1); 436*95c635efSGarrett D'Amore break; 437*95c635efSGarrett D'Amore case (CHECK_EQ): 438*95c635efSGarrett D'Amore p = ""; 439*95c635efSGarrett D'Amore if (val == m->last->nchild) 440*95c635efSGarrett D'Amore return(1); 441*95c635efSGarrett D'Amore break; 442*95c635efSGarrett D'Amore default: 443*95c635efSGarrett D'Amore abort(); 444*95c635efSGarrett D'Amore /* NOTREACHED */ 445*95c635efSGarrett D'Amore } 446*95c635efSGarrett D'Amore 447*95c635efSGarrett D'Amore t = lvl == CHECK_WARN ? MANDOCERR_ARGCWARN : MANDOCERR_ARGCOUNT; 448*95c635efSGarrett D'Amore mandoc_vmsg(t, m->parse, m->last->line, m->last->pos, 449*95c635efSGarrett D'Amore "want %s%d children (have %d)", 450*95c635efSGarrett D'Amore p, val, m->last->nchild); 451*95c635efSGarrett D'Amore return(1); 452*95c635efSGarrett D'Amore } 453*95c635efSGarrett D'Amore 454*95c635efSGarrett D'Amore static int 455*95c635efSGarrett D'Amore berr_ge1(POST_ARGS) 456*95c635efSGarrett D'Amore { 457*95c635efSGarrett D'Amore 458*95c635efSGarrett D'Amore return(check_count(mdoc, MDOC_BODY, CHECK_ERROR, CHECK_GT, 0)); 459*95c635efSGarrett D'Amore } 460*95c635efSGarrett D'Amore 461*95c635efSGarrett D'Amore static int 462*95c635efSGarrett D'Amore bwarn_ge1(POST_ARGS) 463*95c635efSGarrett D'Amore { 464*95c635efSGarrett D'Amore return(check_count(mdoc, MDOC_BODY, CHECK_WARN, CHECK_GT, 0)); 465*95c635efSGarrett D'Amore } 466*95c635efSGarrett D'Amore 467*95c635efSGarrett D'Amore static int 468*95c635efSGarrett D'Amore ewarn_eq0(POST_ARGS) 469*95c635efSGarrett D'Amore { 470*95c635efSGarrett D'Amore return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 0)); 471*95c635efSGarrett D'Amore } 472*95c635efSGarrett D'Amore 473*95c635efSGarrett D'Amore static int 474*95c635efSGarrett D'Amore ewarn_eq1(POST_ARGS) 475*95c635efSGarrett D'Amore { 476*95c635efSGarrett D'Amore return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1)); 477*95c635efSGarrett D'Amore } 478*95c635efSGarrett D'Amore 479*95c635efSGarrett D'Amore static int 480*95c635efSGarrett D'Amore ewarn_ge1(POST_ARGS) 481*95c635efSGarrett D'Amore { 482*95c635efSGarrett D'Amore return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_GT, 0)); 483*95c635efSGarrett D'Amore } 484*95c635efSGarrett D'Amore 485*95c635efSGarrett D'Amore static int 486*95c635efSGarrett D'Amore ewarn_le1(POST_ARGS) 487*95c635efSGarrett D'Amore { 488*95c635efSGarrett D'Amore return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_LT, 2)); 489*95c635efSGarrett D'Amore } 490*95c635efSGarrett D'Amore 491*95c635efSGarrett D'Amore static int 492*95c635efSGarrett D'Amore hwarn_eq0(POST_ARGS) 493*95c635efSGarrett D'Amore { 494*95c635efSGarrett D'Amore return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 0)); 495*95c635efSGarrett D'Amore } 496*95c635efSGarrett D'Amore 497*95c635efSGarrett D'Amore static int 498*95c635efSGarrett D'Amore hwarn_eq1(POST_ARGS) 499*95c635efSGarrett D'Amore { 500*95c635efSGarrett D'Amore return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 1)); 501*95c635efSGarrett D'Amore } 502*95c635efSGarrett D'Amore 503*95c635efSGarrett D'Amore static int 504*95c635efSGarrett D'Amore hwarn_ge1(POST_ARGS) 505*95c635efSGarrett D'Amore { 506*95c635efSGarrett D'Amore return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_GT, 0)); 507*95c635efSGarrett D'Amore } 508*95c635efSGarrett D'Amore 509*95c635efSGarrett D'Amore static int 510*95c635efSGarrett D'Amore hwarn_le1(POST_ARGS) 511*95c635efSGarrett D'Amore { 512*95c635efSGarrett D'Amore return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_LT, 2)); 513*95c635efSGarrett D'Amore } 514*95c635efSGarrett D'Amore 515*95c635efSGarrett D'Amore static void 516*95c635efSGarrett D'Amore check_args(struct mdoc *m, struct mdoc_node *n) 517*95c635efSGarrett D'Amore { 518*95c635efSGarrett D'Amore int i; 519*95c635efSGarrett D'Amore 520*95c635efSGarrett D'Amore if (NULL == n->args) 521*95c635efSGarrett D'Amore return; 522*95c635efSGarrett D'Amore 523*95c635efSGarrett D'Amore assert(n->args->argc); 524*95c635efSGarrett D'Amore for (i = 0; i < (int)n->args->argc; i++) 525*95c635efSGarrett D'Amore check_argv(m, n, &n->args->argv[i]); 526*95c635efSGarrett D'Amore } 527*95c635efSGarrett D'Amore 528*95c635efSGarrett D'Amore static void 529*95c635efSGarrett D'Amore check_argv(struct mdoc *m, struct mdoc_node *n, struct mdoc_argv *v) 530*95c635efSGarrett D'Amore { 531*95c635efSGarrett D'Amore int i; 532*95c635efSGarrett D'Amore 533*95c635efSGarrett D'Amore for (i = 0; i < (int)v->sz; i++) 534*95c635efSGarrett D'Amore check_text(m, v->line, v->pos, v->value[i]); 535*95c635efSGarrett D'Amore 536*95c635efSGarrett D'Amore /* FIXME: move to post_std(). */ 537*95c635efSGarrett D'Amore 538*95c635efSGarrett D'Amore if (MDOC_Std == v->arg) 539*95c635efSGarrett D'Amore if ( ! (v->sz || m->meta.name)) 540*95c635efSGarrett D'Amore mdoc_nmsg(m, n, MANDOCERR_NONAME); 541*95c635efSGarrett D'Amore } 542*95c635efSGarrett D'Amore 543*95c635efSGarrett D'Amore static void 544*95c635efSGarrett D'Amore check_text(struct mdoc *m, int ln, int pos, char *p) 545*95c635efSGarrett D'Amore { 546*95c635efSGarrett D'Amore char *cp; 547*95c635efSGarrett D'Amore 548*95c635efSGarrett D'Amore if (MDOC_LITERAL & m->flags) 549*95c635efSGarrett D'Amore return; 550*95c635efSGarrett D'Amore 551*95c635efSGarrett D'Amore for (cp = p; NULL != (p = strchr(p, '\t')); p++) 552*95c635efSGarrett D'Amore mdoc_pmsg(m, ln, pos + (int)(p - cp), MANDOCERR_BADTAB); 553*95c635efSGarrett D'Amore } 554*95c635efSGarrett D'Amore 555*95c635efSGarrett D'Amore static int 556*95c635efSGarrett D'Amore check_parent(PRE_ARGS, enum mdoct tok, enum mdoc_type t) 557*95c635efSGarrett D'Amore { 558*95c635efSGarrett D'Amore 559*95c635efSGarrett D'Amore assert(n->parent); 560*95c635efSGarrett D'Amore if ((MDOC_ROOT == t || tok == n->parent->tok) && 561*95c635efSGarrett D'Amore (t == n->parent->type)) 562*95c635efSGarrett D'Amore return(1); 563*95c635efSGarrett D'Amore 564*95c635efSGarrett D'Amore mandoc_vmsg(MANDOCERR_SYNTCHILD, mdoc->parse, n->line, 565*95c635efSGarrett D'Amore n->pos, "want parent %s", MDOC_ROOT == t ? 566*95c635efSGarrett D'Amore "<root>" : mdoc_macronames[tok]); 567*95c635efSGarrett D'Amore return(0); 568*95c635efSGarrett D'Amore } 569*95c635efSGarrett D'Amore 570*95c635efSGarrett D'Amore 571*95c635efSGarrett D'Amore static int 572*95c635efSGarrett D'Amore pre_display(PRE_ARGS) 573*95c635efSGarrett D'Amore { 574*95c635efSGarrett D'Amore struct mdoc_node *node; 575*95c635efSGarrett D'Amore 576*95c635efSGarrett D'Amore if (MDOC_BLOCK != n->type) 577*95c635efSGarrett D'Amore return(1); 578*95c635efSGarrett D'Amore 579*95c635efSGarrett D'Amore for (node = mdoc->last->parent; node; node = node->parent) 580*95c635efSGarrett D'Amore if (MDOC_BLOCK == node->type) 581*95c635efSGarrett D'Amore if (MDOC_Bd == node->tok) 582*95c635efSGarrett D'Amore break; 583*95c635efSGarrett D'Amore 584*95c635efSGarrett D'Amore if (node) 585*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_NESTEDDISP); 586*95c635efSGarrett D'Amore 587*95c635efSGarrett D'Amore return(1); 588*95c635efSGarrett D'Amore } 589*95c635efSGarrett D'Amore 590*95c635efSGarrett D'Amore 591*95c635efSGarrett D'Amore static int 592*95c635efSGarrett D'Amore pre_bl(PRE_ARGS) 593*95c635efSGarrett D'Amore { 594*95c635efSGarrett D'Amore int i, comp, dup; 595*95c635efSGarrett D'Amore const char *offs, *width; 596*95c635efSGarrett D'Amore enum mdoc_list lt; 597*95c635efSGarrett D'Amore struct mdoc_node *np; 598*95c635efSGarrett D'Amore 599*95c635efSGarrett D'Amore if (MDOC_BLOCK != n->type) { 600*95c635efSGarrett D'Amore if (ENDBODY_NOT != n->end) { 601*95c635efSGarrett D'Amore assert(n->pending); 602*95c635efSGarrett D'Amore np = n->pending->parent; 603*95c635efSGarrett D'Amore } else 604*95c635efSGarrett D'Amore np = n->parent; 605*95c635efSGarrett D'Amore 606*95c635efSGarrett D'Amore assert(np); 607*95c635efSGarrett D'Amore assert(MDOC_BLOCK == np->type); 608*95c635efSGarrett D'Amore assert(MDOC_Bl == np->tok); 609*95c635efSGarrett D'Amore return(1); 610*95c635efSGarrett D'Amore } 611*95c635efSGarrett D'Amore 612*95c635efSGarrett D'Amore /* 613*95c635efSGarrett D'Amore * First figure out which kind of list to use: bind ourselves to 614*95c635efSGarrett D'Amore * the first mentioned list type and warn about any remaining 615*95c635efSGarrett D'Amore * ones. If we find no list type, we default to LIST_item. 616*95c635efSGarrett D'Amore */ 617*95c635efSGarrett D'Amore 618*95c635efSGarrett D'Amore /* LINTED */ 619*95c635efSGarrett D'Amore for (i = 0; n->args && i < (int)n->args->argc; i++) { 620*95c635efSGarrett D'Amore lt = LIST__NONE; 621*95c635efSGarrett D'Amore dup = comp = 0; 622*95c635efSGarrett D'Amore width = offs = NULL; 623*95c635efSGarrett D'Amore switch (n->args->argv[i].arg) { 624*95c635efSGarrett D'Amore /* Set list types. */ 625*95c635efSGarrett D'Amore case (MDOC_Bullet): 626*95c635efSGarrett D'Amore lt = LIST_bullet; 627*95c635efSGarrett D'Amore break; 628*95c635efSGarrett D'Amore case (MDOC_Dash): 629*95c635efSGarrett D'Amore lt = LIST_dash; 630*95c635efSGarrett D'Amore break; 631*95c635efSGarrett D'Amore case (MDOC_Enum): 632*95c635efSGarrett D'Amore lt = LIST_enum; 633*95c635efSGarrett D'Amore break; 634*95c635efSGarrett D'Amore case (MDOC_Hyphen): 635*95c635efSGarrett D'Amore lt = LIST_hyphen; 636*95c635efSGarrett D'Amore break; 637*95c635efSGarrett D'Amore case (MDOC_Item): 638*95c635efSGarrett D'Amore lt = LIST_item; 639*95c635efSGarrett D'Amore break; 640*95c635efSGarrett D'Amore case (MDOC_Tag): 641*95c635efSGarrett D'Amore lt = LIST_tag; 642*95c635efSGarrett D'Amore break; 643*95c635efSGarrett D'Amore case (MDOC_Diag): 644*95c635efSGarrett D'Amore lt = LIST_diag; 645*95c635efSGarrett D'Amore break; 646*95c635efSGarrett D'Amore case (MDOC_Hang): 647*95c635efSGarrett D'Amore lt = LIST_hang; 648*95c635efSGarrett D'Amore break; 649*95c635efSGarrett D'Amore case (MDOC_Ohang): 650*95c635efSGarrett D'Amore lt = LIST_ohang; 651*95c635efSGarrett D'Amore break; 652*95c635efSGarrett D'Amore case (MDOC_Inset): 653*95c635efSGarrett D'Amore lt = LIST_inset; 654*95c635efSGarrett D'Amore break; 655*95c635efSGarrett D'Amore case (MDOC_Column): 656*95c635efSGarrett D'Amore lt = LIST_column; 657*95c635efSGarrett D'Amore break; 658*95c635efSGarrett D'Amore /* Set list arguments. */ 659*95c635efSGarrett D'Amore case (MDOC_Compact): 660*95c635efSGarrett D'Amore dup = n->norm->Bl.comp; 661*95c635efSGarrett D'Amore comp = 1; 662*95c635efSGarrett D'Amore break; 663*95c635efSGarrett D'Amore case (MDOC_Width): 664*95c635efSGarrett D'Amore /* NB: this can be empty! */ 665*95c635efSGarrett D'Amore if (n->args->argv[i].sz) { 666*95c635efSGarrett D'Amore width = n->args->argv[i].value[0]; 667*95c635efSGarrett D'Amore dup = (NULL != n->norm->Bl.width); 668*95c635efSGarrett D'Amore break; 669*95c635efSGarrett D'Amore } 670*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV); 671*95c635efSGarrett D'Amore break; 672*95c635efSGarrett D'Amore case (MDOC_Offset): 673*95c635efSGarrett D'Amore /* NB: this can be empty! */ 674*95c635efSGarrett D'Amore if (n->args->argv[i].sz) { 675*95c635efSGarrett D'Amore offs = n->args->argv[i].value[0]; 676*95c635efSGarrett D'Amore dup = (NULL != n->norm->Bl.offs); 677*95c635efSGarrett D'Amore break; 678*95c635efSGarrett D'Amore } 679*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV); 680*95c635efSGarrett D'Amore break; 681*95c635efSGarrett D'Amore default: 682*95c635efSGarrett D'Amore continue; 683*95c635efSGarrett D'Amore } 684*95c635efSGarrett D'Amore 685*95c635efSGarrett D'Amore /* Check: duplicate auxiliary arguments. */ 686*95c635efSGarrett D'Amore 687*95c635efSGarrett D'Amore if (dup) 688*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_ARGVREP); 689*95c635efSGarrett D'Amore 690*95c635efSGarrett D'Amore if (comp && ! dup) 691*95c635efSGarrett D'Amore n->norm->Bl.comp = comp; 692*95c635efSGarrett D'Amore if (offs && ! dup) 693*95c635efSGarrett D'Amore n->norm->Bl.offs = offs; 694*95c635efSGarrett D'Amore if (width && ! dup) 695*95c635efSGarrett D'Amore n->norm->Bl.width = width; 696*95c635efSGarrett D'Amore 697*95c635efSGarrett D'Amore /* Check: multiple list types. */ 698*95c635efSGarrett D'Amore 699*95c635efSGarrett D'Amore if (LIST__NONE != lt && n->norm->Bl.type != LIST__NONE) 700*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_LISTREP); 701*95c635efSGarrett D'Amore 702*95c635efSGarrett D'Amore /* Assign list type. */ 703*95c635efSGarrett D'Amore 704*95c635efSGarrett D'Amore if (LIST__NONE != lt && n->norm->Bl.type == LIST__NONE) { 705*95c635efSGarrett D'Amore n->norm->Bl.type = lt; 706*95c635efSGarrett D'Amore /* Set column information, too. */ 707*95c635efSGarrett D'Amore if (LIST_column == lt) { 708*95c635efSGarrett D'Amore n->norm->Bl.ncols = 709*95c635efSGarrett D'Amore n->args->argv[i].sz; 710*95c635efSGarrett D'Amore n->norm->Bl.cols = (void *) 711*95c635efSGarrett D'Amore n->args->argv[i].value; 712*95c635efSGarrett D'Amore } 713*95c635efSGarrett D'Amore } 714*95c635efSGarrett D'Amore 715*95c635efSGarrett D'Amore /* The list type should come first. */ 716*95c635efSGarrett D'Amore 717*95c635efSGarrett D'Amore if (n->norm->Bl.type == LIST__NONE) 718*95c635efSGarrett D'Amore if (n->norm->Bl.width || 719*95c635efSGarrett D'Amore n->norm->Bl.offs || 720*95c635efSGarrett D'Amore n->norm->Bl.comp) 721*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_LISTFIRST); 722*95c635efSGarrett D'Amore 723*95c635efSGarrett D'Amore continue; 724*95c635efSGarrett D'Amore } 725*95c635efSGarrett D'Amore 726*95c635efSGarrett D'Amore /* Allow lists to default to LIST_item. */ 727*95c635efSGarrett D'Amore 728*95c635efSGarrett D'Amore if (LIST__NONE == n->norm->Bl.type) { 729*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_LISTTYPE); 730*95c635efSGarrett D'Amore n->norm->Bl.type = LIST_item; 731*95c635efSGarrett D'Amore } 732*95c635efSGarrett D'Amore 733*95c635efSGarrett D'Amore /* 734*95c635efSGarrett D'Amore * Validate the width field. Some list types don't need width 735*95c635efSGarrett D'Amore * types and should be warned about them. Others should have it 736*95c635efSGarrett D'Amore * and must also be warned. 737*95c635efSGarrett D'Amore */ 738*95c635efSGarrett D'Amore 739*95c635efSGarrett D'Amore switch (n->norm->Bl.type) { 740*95c635efSGarrett D'Amore case (LIST_tag): 741*95c635efSGarrett D'Amore if (n->norm->Bl.width) 742*95c635efSGarrett D'Amore break; 743*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG); 744*95c635efSGarrett D'Amore break; 745*95c635efSGarrett D'Amore case (LIST_column): 746*95c635efSGarrett D'Amore /* FALLTHROUGH */ 747*95c635efSGarrett D'Amore case (LIST_diag): 748*95c635efSGarrett D'Amore /* FALLTHROUGH */ 749*95c635efSGarrett D'Amore case (LIST_ohang): 750*95c635efSGarrett D'Amore /* FALLTHROUGH */ 751*95c635efSGarrett D'Amore case (LIST_inset): 752*95c635efSGarrett D'Amore /* FALLTHROUGH */ 753*95c635efSGarrett D'Amore case (LIST_item): 754*95c635efSGarrett D'Amore if (n->norm->Bl.width) 755*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV); 756*95c635efSGarrett D'Amore break; 757*95c635efSGarrett D'Amore default: 758*95c635efSGarrett D'Amore break; 759*95c635efSGarrett D'Amore } 760*95c635efSGarrett D'Amore 761*95c635efSGarrett D'Amore return(1); 762*95c635efSGarrett D'Amore } 763*95c635efSGarrett D'Amore 764*95c635efSGarrett D'Amore 765*95c635efSGarrett D'Amore static int 766*95c635efSGarrett D'Amore pre_bd(PRE_ARGS) 767*95c635efSGarrett D'Amore { 768*95c635efSGarrett D'Amore int i, dup, comp; 769*95c635efSGarrett D'Amore enum mdoc_disp dt; 770*95c635efSGarrett D'Amore const char *offs; 771*95c635efSGarrett D'Amore struct mdoc_node *np; 772*95c635efSGarrett D'Amore 773*95c635efSGarrett D'Amore if (MDOC_BLOCK != n->type) { 774*95c635efSGarrett D'Amore if (ENDBODY_NOT != n->end) { 775*95c635efSGarrett D'Amore assert(n->pending); 776*95c635efSGarrett D'Amore np = n->pending->parent; 777*95c635efSGarrett D'Amore } else 778*95c635efSGarrett D'Amore np = n->parent; 779*95c635efSGarrett D'Amore 780*95c635efSGarrett D'Amore assert(np); 781*95c635efSGarrett D'Amore assert(MDOC_BLOCK == np->type); 782*95c635efSGarrett D'Amore assert(MDOC_Bd == np->tok); 783*95c635efSGarrett D'Amore return(1); 784*95c635efSGarrett D'Amore } 785*95c635efSGarrett D'Amore 786*95c635efSGarrett D'Amore /* LINTED */ 787*95c635efSGarrett D'Amore for (i = 0; n->args && i < (int)n->args->argc; i++) { 788*95c635efSGarrett D'Amore dt = DISP__NONE; 789*95c635efSGarrett D'Amore dup = comp = 0; 790*95c635efSGarrett D'Amore offs = NULL; 791*95c635efSGarrett D'Amore 792*95c635efSGarrett D'Amore switch (n->args->argv[i].arg) { 793*95c635efSGarrett D'Amore case (MDOC_Centred): 794*95c635efSGarrett D'Amore dt = DISP_centred; 795*95c635efSGarrett D'Amore break; 796*95c635efSGarrett D'Amore case (MDOC_Ragged): 797*95c635efSGarrett D'Amore dt = DISP_ragged; 798*95c635efSGarrett D'Amore break; 799*95c635efSGarrett D'Amore case (MDOC_Unfilled): 800*95c635efSGarrett D'Amore dt = DISP_unfilled; 801*95c635efSGarrett D'Amore break; 802*95c635efSGarrett D'Amore case (MDOC_Filled): 803*95c635efSGarrett D'Amore dt = DISP_filled; 804*95c635efSGarrett D'Amore break; 805*95c635efSGarrett D'Amore case (MDOC_Literal): 806*95c635efSGarrett D'Amore dt = DISP_literal; 807*95c635efSGarrett D'Amore break; 808*95c635efSGarrett D'Amore case (MDOC_File): 809*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_BADDISP); 810*95c635efSGarrett D'Amore return(0); 811*95c635efSGarrett D'Amore case (MDOC_Offset): 812*95c635efSGarrett D'Amore /* NB: this can be empty! */ 813*95c635efSGarrett D'Amore if (n->args->argv[i].sz) { 814*95c635efSGarrett D'Amore offs = n->args->argv[i].value[0]; 815*95c635efSGarrett D'Amore dup = (NULL != n->norm->Bd.offs); 816*95c635efSGarrett D'Amore break; 817*95c635efSGarrett D'Amore } 818*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV); 819*95c635efSGarrett D'Amore break; 820*95c635efSGarrett D'Amore case (MDOC_Compact): 821*95c635efSGarrett D'Amore comp = 1; 822*95c635efSGarrett D'Amore dup = n->norm->Bd.comp; 823*95c635efSGarrett D'Amore break; 824*95c635efSGarrett D'Amore default: 825*95c635efSGarrett D'Amore abort(); 826*95c635efSGarrett D'Amore /* NOTREACHED */ 827*95c635efSGarrett D'Amore } 828*95c635efSGarrett D'Amore 829*95c635efSGarrett D'Amore /* Check whether we have duplicates. */ 830*95c635efSGarrett D'Amore 831*95c635efSGarrett D'Amore if (dup) 832*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_ARGVREP); 833*95c635efSGarrett D'Amore 834*95c635efSGarrett D'Amore /* Make our auxiliary assignments. */ 835*95c635efSGarrett D'Amore 836*95c635efSGarrett D'Amore if (offs && ! dup) 837*95c635efSGarrett D'Amore n->norm->Bd.offs = offs; 838*95c635efSGarrett D'Amore if (comp && ! dup) 839*95c635efSGarrett D'Amore n->norm->Bd.comp = comp; 840*95c635efSGarrett D'Amore 841*95c635efSGarrett D'Amore /* Check whether a type has already been assigned. */ 842*95c635efSGarrett D'Amore 843*95c635efSGarrett D'Amore if (DISP__NONE != dt && n->norm->Bd.type != DISP__NONE) 844*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_DISPREP); 845*95c635efSGarrett D'Amore 846*95c635efSGarrett D'Amore /* Make our type assignment. */ 847*95c635efSGarrett D'Amore 848*95c635efSGarrett D'Amore if (DISP__NONE != dt && n->norm->Bd.type == DISP__NONE) 849*95c635efSGarrett D'Amore n->norm->Bd.type = dt; 850*95c635efSGarrett D'Amore } 851*95c635efSGarrett D'Amore 852*95c635efSGarrett D'Amore if (DISP__NONE == n->norm->Bd.type) { 853*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_DISPTYPE); 854*95c635efSGarrett D'Amore n->norm->Bd.type = DISP_ragged; 855*95c635efSGarrett D'Amore } 856*95c635efSGarrett D'Amore 857*95c635efSGarrett D'Amore return(1); 858*95c635efSGarrett D'Amore } 859*95c635efSGarrett D'Amore 860*95c635efSGarrett D'Amore 861*95c635efSGarrett D'Amore static int 862*95c635efSGarrett D'Amore pre_ss(PRE_ARGS) 863*95c635efSGarrett D'Amore { 864*95c635efSGarrett D'Amore 865*95c635efSGarrett D'Amore if (MDOC_BLOCK != n->type) 866*95c635efSGarrett D'Amore return(1); 867*95c635efSGarrett D'Amore return(check_parent(mdoc, n, MDOC_Sh, MDOC_BODY)); 868*95c635efSGarrett D'Amore } 869*95c635efSGarrett D'Amore 870*95c635efSGarrett D'Amore 871*95c635efSGarrett D'Amore static int 872*95c635efSGarrett D'Amore pre_sh(PRE_ARGS) 873*95c635efSGarrett D'Amore { 874*95c635efSGarrett D'Amore 875*95c635efSGarrett D'Amore if (MDOC_BLOCK != n->type) 876*95c635efSGarrett D'Amore return(1); 877*95c635efSGarrett D'Amore 878*95c635efSGarrett D'Amore roff_regunset(mdoc->roff, REG_nS); 879*95c635efSGarrett D'Amore return(check_parent(mdoc, n, MDOC_MAX, MDOC_ROOT)); 880*95c635efSGarrett D'Amore } 881*95c635efSGarrett D'Amore 882*95c635efSGarrett D'Amore 883*95c635efSGarrett D'Amore static int 884*95c635efSGarrett D'Amore pre_it(PRE_ARGS) 885*95c635efSGarrett D'Amore { 886*95c635efSGarrett D'Amore 887*95c635efSGarrett D'Amore if (MDOC_BLOCK != n->type) 888*95c635efSGarrett D'Amore return(1); 889*95c635efSGarrett D'Amore 890*95c635efSGarrett D'Amore return(check_parent(mdoc, n, MDOC_Bl, MDOC_BODY)); 891*95c635efSGarrett D'Amore } 892*95c635efSGarrett D'Amore 893*95c635efSGarrett D'Amore 894*95c635efSGarrett D'Amore static int 895*95c635efSGarrett D'Amore pre_an(PRE_ARGS) 896*95c635efSGarrett D'Amore { 897*95c635efSGarrett D'Amore int i; 898*95c635efSGarrett D'Amore 899*95c635efSGarrett D'Amore if (NULL == n->args) 900*95c635efSGarrett D'Amore return(1); 901*95c635efSGarrett D'Amore 902*95c635efSGarrett D'Amore for (i = 1; i < (int)n->args->argc; i++) 903*95c635efSGarrett D'Amore mdoc_pmsg(mdoc, n->args->argv[i].line, 904*95c635efSGarrett D'Amore n->args->argv[i].pos, MANDOCERR_IGNARGV); 905*95c635efSGarrett D'Amore 906*95c635efSGarrett D'Amore if (MDOC_Split == n->args->argv[0].arg) 907*95c635efSGarrett D'Amore n->norm->An.auth = AUTH_split; 908*95c635efSGarrett D'Amore else if (MDOC_Nosplit == n->args->argv[0].arg) 909*95c635efSGarrett D'Amore n->norm->An.auth = AUTH_nosplit; 910*95c635efSGarrett D'Amore else 911*95c635efSGarrett D'Amore abort(); 912*95c635efSGarrett D'Amore 913*95c635efSGarrett D'Amore return(1); 914*95c635efSGarrett D'Amore } 915*95c635efSGarrett D'Amore 916*95c635efSGarrett D'Amore static int 917*95c635efSGarrett D'Amore pre_std(PRE_ARGS) 918*95c635efSGarrett D'Amore { 919*95c635efSGarrett D'Amore 920*95c635efSGarrett D'Amore if (n->args && 1 == n->args->argc) 921*95c635efSGarrett D'Amore if (MDOC_Std == n->args->argv[0].arg) 922*95c635efSGarrett D'Amore return(1); 923*95c635efSGarrett D'Amore 924*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_NOARGV); 925*95c635efSGarrett D'Amore return(1); 926*95c635efSGarrett D'Amore } 927*95c635efSGarrett D'Amore 928*95c635efSGarrett D'Amore static int 929*95c635efSGarrett D'Amore pre_dt(PRE_ARGS) 930*95c635efSGarrett D'Amore { 931*95c635efSGarrett D'Amore 932*95c635efSGarrett D'Amore if (NULL == mdoc->meta.date || mdoc->meta.os) 933*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGOOO); 934*95c635efSGarrett D'Amore 935*95c635efSGarrett D'Amore if (mdoc->meta.title) 936*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGREP); 937*95c635efSGarrett D'Amore 938*95c635efSGarrett D'Amore return(1); 939*95c635efSGarrett D'Amore } 940*95c635efSGarrett D'Amore 941*95c635efSGarrett D'Amore static int 942*95c635efSGarrett D'Amore pre_os(PRE_ARGS) 943*95c635efSGarrett D'Amore { 944*95c635efSGarrett D'Amore 945*95c635efSGarrett D'Amore if (NULL == mdoc->meta.title || NULL == mdoc->meta.date) 946*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGOOO); 947*95c635efSGarrett D'Amore 948*95c635efSGarrett D'Amore if (mdoc->meta.os) 949*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGREP); 950*95c635efSGarrett D'Amore 951*95c635efSGarrett D'Amore return(1); 952*95c635efSGarrett D'Amore } 953*95c635efSGarrett D'Amore 954*95c635efSGarrett D'Amore static int 955*95c635efSGarrett D'Amore pre_dd(PRE_ARGS) 956*95c635efSGarrett D'Amore { 957*95c635efSGarrett D'Amore 958*95c635efSGarrett D'Amore if (mdoc->meta.title || mdoc->meta.os) 959*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGOOO); 960*95c635efSGarrett D'Amore 961*95c635efSGarrett D'Amore if (mdoc->meta.date) 962*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_PROLOGREP); 963*95c635efSGarrett D'Amore 964*95c635efSGarrett D'Amore return(1); 965*95c635efSGarrett D'Amore } 966*95c635efSGarrett D'Amore 967*95c635efSGarrett D'Amore 968*95c635efSGarrett D'Amore static int 969*95c635efSGarrett D'Amore post_bf(POST_ARGS) 970*95c635efSGarrett D'Amore { 971*95c635efSGarrett D'Amore struct mdoc_node *np; 972*95c635efSGarrett D'Amore enum mdocargt arg; 973*95c635efSGarrett D'Amore 974*95c635efSGarrett D'Amore /* 975*95c635efSGarrett D'Amore * Unlike other data pointers, these are "housed" by the HEAD 976*95c635efSGarrett D'Amore * element, which contains the goods. 977*95c635efSGarrett D'Amore */ 978*95c635efSGarrett D'Amore 979*95c635efSGarrett D'Amore if (MDOC_HEAD != mdoc->last->type) { 980*95c635efSGarrett D'Amore if (ENDBODY_NOT != mdoc->last->end) { 981*95c635efSGarrett D'Amore assert(mdoc->last->pending); 982*95c635efSGarrett D'Amore np = mdoc->last->pending->parent->head; 983*95c635efSGarrett D'Amore } else if (MDOC_BLOCK != mdoc->last->type) { 984*95c635efSGarrett D'Amore np = mdoc->last->parent->head; 985*95c635efSGarrett D'Amore } else 986*95c635efSGarrett D'Amore np = mdoc->last->head; 987*95c635efSGarrett D'Amore 988*95c635efSGarrett D'Amore assert(np); 989*95c635efSGarrett D'Amore assert(MDOC_HEAD == np->type); 990*95c635efSGarrett D'Amore assert(MDOC_Bf == np->tok); 991*95c635efSGarrett D'Amore return(1); 992*95c635efSGarrett D'Amore } 993*95c635efSGarrett D'Amore 994*95c635efSGarrett D'Amore np = mdoc->last; 995*95c635efSGarrett D'Amore assert(MDOC_BLOCK == np->parent->type); 996*95c635efSGarrett D'Amore assert(MDOC_Bf == np->parent->tok); 997*95c635efSGarrett D'Amore 998*95c635efSGarrett D'Amore /* 999*95c635efSGarrett D'Amore * Cannot have both argument and parameter. 1000*95c635efSGarrett D'Amore * If neither is specified, let it through with a warning. 1001*95c635efSGarrett D'Amore */ 1002*95c635efSGarrett D'Amore 1003*95c635efSGarrett D'Amore if (np->parent->args && np->child) { 1004*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, np, MANDOCERR_SYNTARGVCOUNT); 1005*95c635efSGarrett D'Amore return(0); 1006*95c635efSGarrett D'Amore } else if (NULL == np->parent->args && NULL == np->child) { 1007*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, np, MANDOCERR_FONTTYPE); 1008*95c635efSGarrett D'Amore return(1); 1009*95c635efSGarrett D'Amore } 1010*95c635efSGarrett D'Amore 1011*95c635efSGarrett D'Amore /* Extract argument into data. */ 1012*95c635efSGarrett D'Amore 1013*95c635efSGarrett D'Amore if (np->parent->args) { 1014*95c635efSGarrett D'Amore arg = np->parent->args->argv[0].arg; 1015*95c635efSGarrett D'Amore if (MDOC_Emphasis == arg) 1016*95c635efSGarrett D'Amore np->norm->Bf.font = FONT_Em; 1017*95c635efSGarrett D'Amore else if (MDOC_Literal == arg) 1018*95c635efSGarrett D'Amore np->norm->Bf.font = FONT_Li; 1019*95c635efSGarrett D'Amore else if (MDOC_Symbolic == arg) 1020*95c635efSGarrett D'Amore np->norm->Bf.font = FONT_Sy; 1021*95c635efSGarrett D'Amore else 1022*95c635efSGarrett D'Amore abort(); 1023*95c635efSGarrett D'Amore return(1); 1024*95c635efSGarrett D'Amore } 1025*95c635efSGarrett D'Amore 1026*95c635efSGarrett D'Amore /* Extract parameter into data. */ 1027*95c635efSGarrett D'Amore 1028*95c635efSGarrett D'Amore if (0 == strcmp(np->child->string, "Em")) 1029*95c635efSGarrett D'Amore np->norm->Bf.font = FONT_Em; 1030*95c635efSGarrett D'Amore else if (0 == strcmp(np->child->string, "Li")) 1031*95c635efSGarrett D'Amore np->norm->Bf.font = FONT_Li; 1032*95c635efSGarrett D'Amore else if (0 == strcmp(np->child->string, "Sy")) 1033*95c635efSGarrett D'Amore np->norm->Bf.font = FONT_Sy; 1034*95c635efSGarrett D'Amore else 1035*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, np, MANDOCERR_FONTTYPE); 1036*95c635efSGarrett D'Amore 1037*95c635efSGarrett D'Amore return(1); 1038*95c635efSGarrett D'Amore } 1039*95c635efSGarrett D'Amore 1040*95c635efSGarrett D'Amore static int 1041*95c635efSGarrett D'Amore post_lb(POST_ARGS) 1042*95c635efSGarrett D'Amore { 1043*95c635efSGarrett D'Amore const char *p; 1044*95c635efSGarrett D'Amore char *buf; 1045*95c635efSGarrett D'Amore size_t sz; 1046*95c635efSGarrett D'Amore 1047*95c635efSGarrett D'Amore check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1); 1048*95c635efSGarrett D'Amore 1049*95c635efSGarrett D'Amore assert(mdoc->last->child); 1050*95c635efSGarrett D'Amore assert(MDOC_TEXT == mdoc->last->child->type); 1051*95c635efSGarrett D'Amore 1052*95c635efSGarrett D'Amore p = mdoc_a2lib(mdoc->last->child->string); 1053*95c635efSGarrett D'Amore 1054*95c635efSGarrett D'Amore /* If lookup ok, replace with table value. */ 1055*95c635efSGarrett D'Amore 1056*95c635efSGarrett D'Amore if (p) { 1057*95c635efSGarrett D'Amore free(mdoc->last->child->string); 1058*95c635efSGarrett D'Amore mdoc->last->child->string = mandoc_strdup(p); 1059*95c635efSGarrett D'Amore return(1); 1060*95c635efSGarrett D'Amore } 1061*95c635efSGarrett D'Amore 1062*95c635efSGarrett D'Amore /* If not, use "library ``xxxx''. */ 1063*95c635efSGarrett D'Amore 1064*95c635efSGarrett D'Amore sz = strlen(mdoc->last->child->string) + 1065*95c635efSGarrett D'Amore 2 + strlen("\\(lqlibrary\\(rq"); 1066*95c635efSGarrett D'Amore buf = mandoc_malloc(sz); 1067*95c635efSGarrett D'Amore snprintf(buf, sz, "library \\(lq%s\\(rq", 1068*95c635efSGarrett D'Amore mdoc->last->child->string); 1069*95c635efSGarrett D'Amore free(mdoc->last->child->string); 1070*95c635efSGarrett D'Amore mdoc->last->child->string = buf; 1071*95c635efSGarrett D'Amore return(1); 1072*95c635efSGarrett D'Amore } 1073*95c635efSGarrett D'Amore 1074*95c635efSGarrett D'Amore static int 1075*95c635efSGarrett D'Amore post_eoln(POST_ARGS) 1076*95c635efSGarrett D'Amore { 1077*95c635efSGarrett D'Amore 1078*95c635efSGarrett D'Amore if (mdoc->last->child) 1079*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_ARGSLOST); 1080*95c635efSGarrett D'Amore return(1); 1081*95c635efSGarrett D'Amore } 1082*95c635efSGarrett D'Amore 1083*95c635efSGarrett D'Amore 1084*95c635efSGarrett D'Amore static int 1085*95c635efSGarrett D'Amore post_vt(POST_ARGS) 1086*95c635efSGarrett D'Amore { 1087*95c635efSGarrett D'Amore const struct mdoc_node *n; 1088*95c635efSGarrett D'Amore 1089*95c635efSGarrett D'Amore /* 1090*95c635efSGarrett D'Amore * The Vt macro comes in both ELEM and BLOCK form, both of which 1091*95c635efSGarrett D'Amore * have different syntaxes (yet more context-sensitive 1092*95c635efSGarrett D'Amore * behaviour). ELEM types must have a child, which is already 1093*95c635efSGarrett D'Amore * guaranteed by the in_line parsing routine; BLOCK types, 1094*95c635efSGarrett D'Amore * specifically the BODY, should only have TEXT children. 1095*95c635efSGarrett D'Amore */ 1096*95c635efSGarrett D'Amore 1097*95c635efSGarrett D'Amore if (MDOC_BODY != mdoc->last->type) 1098*95c635efSGarrett D'Amore return(1); 1099*95c635efSGarrett D'Amore 1100*95c635efSGarrett D'Amore for (n = mdoc->last->child; n; n = n->next) 1101*95c635efSGarrett D'Amore if (MDOC_TEXT != n->type) 1102*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_CHILD); 1103*95c635efSGarrett D'Amore 1104*95c635efSGarrett D'Amore return(1); 1105*95c635efSGarrett D'Amore } 1106*95c635efSGarrett D'Amore 1107*95c635efSGarrett D'Amore 1108*95c635efSGarrett D'Amore static int 1109*95c635efSGarrett D'Amore post_nm(POST_ARGS) 1110*95c635efSGarrett D'Amore { 1111*95c635efSGarrett D'Amore char buf[BUFSIZ]; 1112*95c635efSGarrett D'Amore int c; 1113*95c635efSGarrett D'Amore 1114*95c635efSGarrett D'Amore /* If no child specified, make sure we have the meta name. */ 1115*95c635efSGarrett D'Amore 1116*95c635efSGarrett D'Amore if (NULL == mdoc->last->child && NULL == mdoc->meta.name) { 1117*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NONAME); 1118*95c635efSGarrett D'Amore return(1); 1119*95c635efSGarrett D'Amore } else if (mdoc->meta.name) 1120*95c635efSGarrett D'Amore return(1); 1121*95c635efSGarrett D'Amore 1122*95c635efSGarrett D'Amore /* If no meta name, set it from the child. */ 1123*95c635efSGarrett D'Amore 1124*95c635efSGarrett D'Amore buf[0] = '\0'; 1125*95c635efSGarrett D'Amore if (-1 == (c = concat(buf, mdoc->last->child, BUFSIZ))) { 1126*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last->child, MANDOCERR_MEM); 1127*95c635efSGarrett D'Amore return(0); 1128*95c635efSGarrett D'Amore } 1129*95c635efSGarrett D'Amore 1130*95c635efSGarrett D'Amore assert(c); 1131*95c635efSGarrett D'Amore mdoc->meta.name = mandoc_strdup(buf); 1132*95c635efSGarrett D'Amore return(1); 1133*95c635efSGarrett D'Amore } 1134*95c635efSGarrett D'Amore 1135*95c635efSGarrett D'Amore static int 1136*95c635efSGarrett D'Amore post_literal(POST_ARGS) 1137*95c635efSGarrett D'Amore { 1138*95c635efSGarrett D'Amore 1139*95c635efSGarrett D'Amore /* 1140*95c635efSGarrett D'Amore * The `Dl' (note "el" not "one") and `Bd' macros unset the 1141*95c635efSGarrett D'Amore * MDOC_LITERAL flag as they leave. Note that `Bd' only sets 1142*95c635efSGarrett D'Amore * this in literal mode, but it doesn't hurt to just switch it 1143*95c635efSGarrett D'Amore * off in general since displays can't be nested. 1144*95c635efSGarrett D'Amore */ 1145*95c635efSGarrett D'Amore 1146*95c635efSGarrett D'Amore if (MDOC_BODY == mdoc->last->type) 1147*95c635efSGarrett D'Amore mdoc->flags &= ~MDOC_LITERAL; 1148*95c635efSGarrett D'Amore 1149*95c635efSGarrett D'Amore return(1); 1150*95c635efSGarrett D'Amore } 1151*95c635efSGarrett D'Amore 1152*95c635efSGarrett D'Amore static int 1153*95c635efSGarrett D'Amore post_defaults(POST_ARGS) 1154*95c635efSGarrett D'Amore { 1155*95c635efSGarrett D'Amore struct mdoc_node *nn; 1156*95c635efSGarrett D'Amore 1157*95c635efSGarrett D'Amore /* 1158*95c635efSGarrett D'Amore * The `Ar' defaults to "file ..." if no value is provided as an 1159*95c635efSGarrett D'Amore * argument; the `Mt' and `Pa' macros use "~"; the `Li' just 1160*95c635efSGarrett D'Amore * gets an empty string. 1161*95c635efSGarrett D'Amore */ 1162*95c635efSGarrett D'Amore 1163*95c635efSGarrett D'Amore if (mdoc->last->child) 1164*95c635efSGarrett D'Amore return(1); 1165*95c635efSGarrett D'Amore 1166*95c635efSGarrett D'Amore nn = mdoc->last; 1167*95c635efSGarrett D'Amore mdoc->next = MDOC_NEXT_CHILD; 1168*95c635efSGarrett D'Amore 1169*95c635efSGarrett D'Amore switch (nn->tok) { 1170*95c635efSGarrett D'Amore case (MDOC_Ar): 1171*95c635efSGarrett D'Amore if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "file")) 1172*95c635efSGarrett D'Amore return(0); 1173*95c635efSGarrett D'Amore if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "...")) 1174*95c635efSGarrett D'Amore return(0); 1175*95c635efSGarrett D'Amore break; 1176*95c635efSGarrett D'Amore case (MDOC_At): 1177*95c635efSGarrett D'Amore if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "AT&T")) 1178*95c635efSGarrett D'Amore return(0); 1179*95c635efSGarrett D'Amore if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "UNIX")) 1180*95c635efSGarrett D'Amore return(0); 1181*95c635efSGarrett D'Amore break; 1182*95c635efSGarrett D'Amore case (MDOC_Li): 1183*95c635efSGarrett D'Amore if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "")) 1184*95c635efSGarrett D'Amore return(0); 1185*95c635efSGarrett D'Amore break; 1186*95c635efSGarrett D'Amore case (MDOC_Pa): 1187*95c635efSGarrett D'Amore /* FALLTHROUGH */ 1188*95c635efSGarrett D'Amore case (MDOC_Mt): 1189*95c635efSGarrett D'Amore if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "~")) 1190*95c635efSGarrett D'Amore return(0); 1191*95c635efSGarrett D'Amore break; 1192*95c635efSGarrett D'Amore default: 1193*95c635efSGarrett D'Amore abort(); 1194*95c635efSGarrett D'Amore /* NOTREACHED */ 1195*95c635efSGarrett D'Amore } 1196*95c635efSGarrett D'Amore 1197*95c635efSGarrett D'Amore mdoc->last = nn; 1198*95c635efSGarrett D'Amore return(1); 1199*95c635efSGarrett D'Amore } 1200*95c635efSGarrett D'Amore 1201*95c635efSGarrett D'Amore static int 1202*95c635efSGarrett D'Amore post_at(POST_ARGS) 1203*95c635efSGarrett D'Amore { 1204*95c635efSGarrett D'Amore const char *p, *q; 1205*95c635efSGarrett D'Amore char *buf; 1206*95c635efSGarrett D'Amore size_t sz; 1207*95c635efSGarrett D'Amore 1208*95c635efSGarrett D'Amore /* 1209*95c635efSGarrett D'Amore * If we have a child, look it up in the standard keys. If a 1210*95c635efSGarrett D'Amore * key exist, use that instead of the child; if it doesn't, 1211*95c635efSGarrett D'Amore * prefix "AT&T UNIX " to the existing data. 1212*95c635efSGarrett D'Amore */ 1213*95c635efSGarrett D'Amore 1214*95c635efSGarrett D'Amore if (NULL == mdoc->last->child) 1215*95c635efSGarrett D'Amore return(1); 1216*95c635efSGarrett D'Amore 1217*95c635efSGarrett D'Amore assert(MDOC_TEXT == mdoc->last->child->type); 1218*95c635efSGarrett D'Amore p = mdoc_a2att(mdoc->last->child->string); 1219*95c635efSGarrett D'Amore 1220*95c635efSGarrett D'Amore if (p) { 1221*95c635efSGarrett D'Amore free(mdoc->last->child->string); 1222*95c635efSGarrett D'Amore mdoc->last->child->string = mandoc_strdup(p); 1223*95c635efSGarrett D'Amore } else { 1224*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADATT); 1225*95c635efSGarrett D'Amore p = "AT&T UNIX "; 1226*95c635efSGarrett D'Amore q = mdoc->last->child->string; 1227*95c635efSGarrett D'Amore sz = strlen(p) + strlen(q) + 1; 1228*95c635efSGarrett D'Amore buf = mandoc_malloc(sz); 1229*95c635efSGarrett D'Amore strlcpy(buf, p, sz); 1230*95c635efSGarrett D'Amore strlcat(buf, q, sz); 1231*95c635efSGarrett D'Amore free(mdoc->last->child->string); 1232*95c635efSGarrett D'Amore mdoc->last->child->string = buf; 1233*95c635efSGarrett D'Amore } 1234*95c635efSGarrett D'Amore 1235*95c635efSGarrett D'Amore return(1); 1236*95c635efSGarrett D'Amore } 1237*95c635efSGarrett D'Amore 1238*95c635efSGarrett D'Amore static int 1239*95c635efSGarrett D'Amore post_an(POST_ARGS) 1240*95c635efSGarrett D'Amore { 1241*95c635efSGarrett D'Amore struct mdoc_node *np; 1242*95c635efSGarrett D'Amore 1243*95c635efSGarrett D'Amore np = mdoc->last; 1244*95c635efSGarrett D'Amore if (AUTH__NONE == np->norm->An.auth) { 1245*95c635efSGarrett D'Amore if (0 == np->child) 1246*95c635efSGarrett D'Amore check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_GT, 0); 1247*95c635efSGarrett D'Amore } else if (np->child) 1248*95c635efSGarrett D'Amore check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 0); 1249*95c635efSGarrett D'Amore 1250*95c635efSGarrett D'Amore return(1); 1251*95c635efSGarrett D'Amore } 1252*95c635efSGarrett D'Amore 1253*95c635efSGarrett D'Amore 1254*95c635efSGarrett D'Amore static int 1255*95c635efSGarrett D'Amore post_it(POST_ARGS) 1256*95c635efSGarrett D'Amore { 1257*95c635efSGarrett D'Amore int i, cols; 1258*95c635efSGarrett D'Amore enum mdoc_list lt; 1259*95c635efSGarrett D'Amore struct mdoc_node *n, *c; 1260*95c635efSGarrett D'Amore enum mandocerr er; 1261*95c635efSGarrett D'Amore 1262*95c635efSGarrett D'Amore if (MDOC_BLOCK != mdoc->last->type) 1263*95c635efSGarrett D'Amore return(1); 1264*95c635efSGarrett D'Amore 1265*95c635efSGarrett D'Amore n = mdoc->last->parent->parent; 1266*95c635efSGarrett D'Amore lt = n->norm->Bl.type; 1267*95c635efSGarrett D'Amore 1268*95c635efSGarrett D'Amore if (LIST__NONE == lt) { 1269*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_LISTTYPE); 1270*95c635efSGarrett D'Amore return(1); 1271*95c635efSGarrett D'Amore } 1272*95c635efSGarrett D'Amore 1273*95c635efSGarrett D'Amore switch (lt) { 1274*95c635efSGarrett D'Amore case (LIST_tag): 1275*95c635efSGarrett D'Amore if (mdoc->last->head->child) 1276*95c635efSGarrett D'Amore break; 1277*95c635efSGarrett D'Amore /* FIXME: give this a dummy value. */ 1278*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS); 1279*95c635efSGarrett D'Amore break; 1280*95c635efSGarrett D'Amore case (LIST_hang): 1281*95c635efSGarrett D'Amore /* FALLTHROUGH */ 1282*95c635efSGarrett D'Amore case (LIST_ohang): 1283*95c635efSGarrett D'Amore /* FALLTHROUGH */ 1284*95c635efSGarrett D'Amore case (LIST_inset): 1285*95c635efSGarrett D'Amore /* FALLTHROUGH */ 1286*95c635efSGarrett D'Amore case (LIST_diag): 1287*95c635efSGarrett D'Amore if (NULL == mdoc->last->head->child) 1288*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS); 1289*95c635efSGarrett D'Amore break; 1290*95c635efSGarrett D'Amore case (LIST_bullet): 1291*95c635efSGarrett D'Amore /* FALLTHROUGH */ 1292*95c635efSGarrett D'Amore case (LIST_dash): 1293*95c635efSGarrett D'Amore /* FALLTHROUGH */ 1294*95c635efSGarrett D'Amore case (LIST_enum): 1295*95c635efSGarrett D'Amore /* FALLTHROUGH */ 1296*95c635efSGarrett D'Amore case (LIST_hyphen): 1297*95c635efSGarrett D'Amore if (NULL == mdoc->last->body->child) 1298*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOBODY); 1299*95c635efSGarrett D'Amore /* FALLTHROUGH */ 1300*95c635efSGarrett D'Amore case (LIST_item): 1301*95c635efSGarrett D'Amore if (mdoc->last->head->child) 1302*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_ARGSLOST); 1303*95c635efSGarrett D'Amore break; 1304*95c635efSGarrett D'Amore case (LIST_column): 1305*95c635efSGarrett D'Amore cols = (int)n->norm->Bl.ncols; 1306*95c635efSGarrett D'Amore 1307*95c635efSGarrett D'Amore assert(NULL == mdoc->last->head->child); 1308*95c635efSGarrett D'Amore 1309*95c635efSGarrett D'Amore if (NULL == mdoc->last->body->child) 1310*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOBODY); 1311*95c635efSGarrett D'Amore 1312*95c635efSGarrett D'Amore for (i = 0, c = mdoc->last->child; c; c = c->next) 1313*95c635efSGarrett D'Amore if (MDOC_BODY == c->type) 1314*95c635efSGarrett D'Amore i++; 1315*95c635efSGarrett D'Amore 1316*95c635efSGarrett D'Amore if (i < cols) 1317*95c635efSGarrett D'Amore er = MANDOCERR_ARGCOUNT; 1318*95c635efSGarrett D'Amore else if (i == cols || i == cols + 1) 1319*95c635efSGarrett D'Amore break; 1320*95c635efSGarrett D'Amore else 1321*95c635efSGarrett D'Amore er = MANDOCERR_SYNTARGCOUNT; 1322*95c635efSGarrett D'Amore 1323*95c635efSGarrett D'Amore mandoc_vmsg(er, mdoc->parse, mdoc->last->line, 1324*95c635efSGarrett D'Amore mdoc->last->pos, 1325*95c635efSGarrett D'Amore "columns == %d (have %d)", cols, i); 1326*95c635efSGarrett D'Amore return(MANDOCERR_ARGCOUNT == er); 1327*95c635efSGarrett D'Amore default: 1328*95c635efSGarrett D'Amore break; 1329*95c635efSGarrett D'Amore } 1330*95c635efSGarrett D'Amore 1331*95c635efSGarrett D'Amore return(1); 1332*95c635efSGarrett D'Amore } 1333*95c635efSGarrett D'Amore 1334*95c635efSGarrett D'Amore static int 1335*95c635efSGarrett D'Amore post_bl_block(POST_ARGS) 1336*95c635efSGarrett D'Amore { 1337*95c635efSGarrett D'Amore struct mdoc_node *n; 1338*95c635efSGarrett D'Amore 1339*95c635efSGarrett D'Amore /* 1340*95c635efSGarrett D'Amore * These are fairly complicated, so we've broken them into two 1341*95c635efSGarrett D'Amore * functions. post_bl_block_tag() is called when a -tag is 1342*95c635efSGarrett D'Amore * specified, but no -width (it must be guessed). The second 1343*95c635efSGarrett D'Amore * when a -width is specified (macro indicators must be 1344*95c635efSGarrett D'Amore * rewritten into real lengths). 1345*95c635efSGarrett D'Amore */ 1346*95c635efSGarrett D'Amore 1347*95c635efSGarrett D'Amore n = mdoc->last; 1348*95c635efSGarrett D'Amore 1349*95c635efSGarrett D'Amore if (LIST_tag == n->norm->Bl.type && 1350*95c635efSGarrett D'Amore NULL == n->norm->Bl.width) { 1351*95c635efSGarrett D'Amore if ( ! post_bl_block_tag(mdoc)) 1352*95c635efSGarrett D'Amore return(0); 1353*95c635efSGarrett D'Amore } else if (NULL != n->norm->Bl.width) { 1354*95c635efSGarrett D'Amore if ( ! post_bl_block_width(mdoc)) 1355*95c635efSGarrett D'Amore return(0); 1356*95c635efSGarrett D'Amore } else 1357*95c635efSGarrett D'Amore return(1); 1358*95c635efSGarrett D'Amore 1359*95c635efSGarrett D'Amore assert(n->norm->Bl.width); 1360*95c635efSGarrett D'Amore return(1); 1361*95c635efSGarrett D'Amore } 1362*95c635efSGarrett D'Amore 1363*95c635efSGarrett D'Amore static int 1364*95c635efSGarrett D'Amore post_bl_block_width(POST_ARGS) 1365*95c635efSGarrett D'Amore { 1366*95c635efSGarrett D'Amore size_t width; 1367*95c635efSGarrett D'Amore int i; 1368*95c635efSGarrett D'Amore enum mdoct tok; 1369*95c635efSGarrett D'Amore struct mdoc_node *n; 1370*95c635efSGarrett D'Amore char buf[NUMSIZ]; 1371*95c635efSGarrett D'Amore 1372*95c635efSGarrett D'Amore n = mdoc->last; 1373*95c635efSGarrett D'Amore 1374*95c635efSGarrett D'Amore /* 1375*95c635efSGarrett D'Amore * Calculate the real width of a list from the -width string, 1376*95c635efSGarrett D'Amore * which may contain a macro (with a known default width), a 1377*95c635efSGarrett D'Amore * literal string, or a scaling width. 1378*95c635efSGarrett D'Amore * 1379*95c635efSGarrett D'Amore * If the value to -width is a macro, then we re-write it to be 1380*95c635efSGarrett D'Amore * the macro's width as set in share/tmac/mdoc/doc-common. 1381*95c635efSGarrett D'Amore */ 1382*95c635efSGarrett D'Amore 1383*95c635efSGarrett D'Amore if (0 == strcmp(n->norm->Bl.width, "Ds")) 1384*95c635efSGarrett D'Amore width = 6; 1385*95c635efSGarrett D'Amore else if (MDOC_MAX == (tok = mdoc_hash_find(n->norm->Bl.width))) 1386*95c635efSGarrett D'Amore return(1); 1387*95c635efSGarrett D'Amore else if (0 == (width = macro2len(tok))) { 1388*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_BADWIDTH); 1389*95c635efSGarrett D'Amore return(1); 1390*95c635efSGarrett D'Amore } 1391*95c635efSGarrett D'Amore 1392*95c635efSGarrett D'Amore /* The value already exists: free and reallocate it. */ 1393*95c635efSGarrett D'Amore 1394*95c635efSGarrett D'Amore assert(n->args); 1395*95c635efSGarrett D'Amore 1396*95c635efSGarrett D'Amore for (i = 0; i < (int)n->args->argc; i++) 1397*95c635efSGarrett D'Amore if (MDOC_Width == n->args->argv[i].arg) 1398*95c635efSGarrett D'Amore break; 1399*95c635efSGarrett D'Amore 1400*95c635efSGarrett D'Amore assert(i < (int)n->args->argc); 1401*95c635efSGarrett D'Amore 1402*95c635efSGarrett D'Amore snprintf(buf, NUMSIZ, "%un", (unsigned int)width); 1403*95c635efSGarrett D'Amore free(n->args->argv[i].value[0]); 1404*95c635efSGarrett D'Amore n->args->argv[i].value[0] = mandoc_strdup(buf); 1405*95c635efSGarrett D'Amore 1406*95c635efSGarrett D'Amore /* Set our width! */ 1407*95c635efSGarrett D'Amore n->norm->Bl.width = n->args->argv[i].value[0]; 1408*95c635efSGarrett D'Amore return(1); 1409*95c635efSGarrett D'Amore } 1410*95c635efSGarrett D'Amore 1411*95c635efSGarrett D'Amore static int 1412*95c635efSGarrett D'Amore post_bl_block_tag(POST_ARGS) 1413*95c635efSGarrett D'Amore { 1414*95c635efSGarrett D'Amore struct mdoc_node *n, *nn; 1415*95c635efSGarrett D'Amore size_t sz, ssz; 1416*95c635efSGarrett D'Amore int i; 1417*95c635efSGarrett D'Amore char buf[NUMSIZ]; 1418*95c635efSGarrett D'Amore 1419*95c635efSGarrett D'Amore /* 1420*95c635efSGarrett D'Amore * Calculate the -width for a `Bl -tag' list if it hasn't been 1421*95c635efSGarrett D'Amore * provided. Uses the first head macro. NOTE AGAIN: this is 1422*95c635efSGarrett D'Amore * ONLY if the -width argument has NOT been provided. See 1423*95c635efSGarrett D'Amore * post_bl_block_width() for converting the -width string. 1424*95c635efSGarrett D'Amore */ 1425*95c635efSGarrett D'Amore 1426*95c635efSGarrett D'Amore sz = 10; 1427*95c635efSGarrett D'Amore n = mdoc->last; 1428*95c635efSGarrett D'Amore 1429*95c635efSGarrett D'Amore for (nn = n->body->child; nn; nn = nn->next) { 1430*95c635efSGarrett D'Amore if (MDOC_It != nn->tok) 1431*95c635efSGarrett D'Amore continue; 1432*95c635efSGarrett D'Amore 1433*95c635efSGarrett D'Amore assert(MDOC_BLOCK == nn->type); 1434*95c635efSGarrett D'Amore nn = nn->head->child; 1435*95c635efSGarrett D'Amore 1436*95c635efSGarrett D'Amore if (nn == NULL) 1437*95c635efSGarrett D'Amore break; 1438*95c635efSGarrett D'Amore 1439*95c635efSGarrett D'Amore if (MDOC_TEXT == nn->type) { 1440*95c635efSGarrett D'Amore sz = strlen(nn->string) + 1; 1441*95c635efSGarrett D'Amore break; 1442*95c635efSGarrett D'Amore } 1443*95c635efSGarrett D'Amore 1444*95c635efSGarrett D'Amore if (0 != (ssz = macro2len(nn->tok))) 1445*95c635efSGarrett D'Amore sz = ssz; 1446*95c635efSGarrett D'Amore 1447*95c635efSGarrett D'Amore break; 1448*95c635efSGarrett D'Amore } 1449*95c635efSGarrett D'Amore 1450*95c635efSGarrett D'Amore /* Defaults to ten ens. */ 1451*95c635efSGarrett D'Amore 1452*95c635efSGarrett D'Amore snprintf(buf, NUMSIZ, "%un", (unsigned int)sz); 1453*95c635efSGarrett D'Amore 1454*95c635efSGarrett D'Amore /* 1455*95c635efSGarrett D'Amore * We have to dynamically add this to the macro's argument list. 1456*95c635efSGarrett D'Amore * We're guaranteed that a MDOC_Width doesn't already exist. 1457*95c635efSGarrett D'Amore */ 1458*95c635efSGarrett D'Amore 1459*95c635efSGarrett D'Amore assert(n->args); 1460*95c635efSGarrett D'Amore i = (int)(n->args->argc)++; 1461*95c635efSGarrett D'Amore 1462*95c635efSGarrett D'Amore n->args->argv = mandoc_realloc(n->args->argv, 1463*95c635efSGarrett D'Amore n->args->argc * sizeof(struct mdoc_argv)); 1464*95c635efSGarrett D'Amore 1465*95c635efSGarrett D'Amore n->args->argv[i].arg = MDOC_Width; 1466*95c635efSGarrett D'Amore n->args->argv[i].line = n->line; 1467*95c635efSGarrett D'Amore n->args->argv[i].pos = n->pos; 1468*95c635efSGarrett D'Amore n->args->argv[i].sz = 1; 1469*95c635efSGarrett D'Amore n->args->argv[i].value = mandoc_malloc(sizeof(char *)); 1470*95c635efSGarrett D'Amore n->args->argv[i].value[0] = mandoc_strdup(buf); 1471*95c635efSGarrett D'Amore 1472*95c635efSGarrett D'Amore /* Set our width! */ 1473*95c635efSGarrett D'Amore n->norm->Bl.width = n->args->argv[i].value[0]; 1474*95c635efSGarrett D'Amore return(1); 1475*95c635efSGarrett D'Amore } 1476*95c635efSGarrett D'Amore 1477*95c635efSGarrett D'Amore 1478*95c635efSGarrett D'Amore static int 1479*95c635efSGarrett D'Amore post_bl_head(POST_ARGS) 1480*95c635efSGarrett D'Amore { 1481*95c635efSGarrett D'Amore struct mdoc_node *np, *nn, *nnp; 1482*95c635efSGarrett D'Amore int i, j; 1483*95c635efSGarrett D'Amore 1484*95c635efSGarrett D'Amore if (LIST_column != mdoc->last->norm->Bl.type) 1485*95c635efSGarrett D'Amore /* FIXME: this should be ERROR class... */ 1486*95c635efSGarrett D'Amore return(hwarn_eq0(mdoc)); 1487*95c635efSGarrett D'Amore 1488*95c635efSGarrett D'Amore /* 1489*95c635efSGarrett D'Amore * Convert old-style lists, where the column width specifiers 1490*95c635efSGarrett D'Amore * trail as macro parameters, to the new-style ("normal-form") 1491*95c635efSGarrett D'Amore * lists where they're argument values following -column. 1492*95c635efSGarrett D'Amore */ 1493*95c635efSGarrett D'Amore 1494*95c635efSGarrett D'Amore /* First, disallow both types and allow normal-form. */ 1495*95c635efSGarrett D'Amore 1496*95c635efSGarrett D'Amore /* 1497*95c635efSGarrett D'Amore * TODO: technically, we can accept both and just merge the two 1498*95c635efSGarrett D'Amore * lists, but I'll leave that for another day. 1499*95c635efSGarrett D'Amore */ 1500*95c635efSGarrett D'Amore 1501*95c635efSGarrett D'Amore if (mdoc->last->norm->Bl.ncols && mdoc->last->nchild) { 1502*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_COLUMNS); 1503*95c635efSGarrett D'Amore return(0); 1504*95c635efSGarrett D'Amore } else if (NULL == mdoc->last->child) 1505*95c635efSGarrett D'Amore return(1); 1506*95c635efSGarrett D'Amore 1507*95c635efSGarrett D'Amore np = mdoc->last->parent; 1508*95c635efSGarrett D'Amore assert(np->args); 1509*95c635efSGarrett D'Amore 1510*95c635efSGarrett D'Amore for (j = 0; j < (int)np->args->argc; j++) 1511*95c635efSGarrett D'Amore if (MDOC_Column == np->args->argv[j].arg) 1512*95c635efSGarrett D'Amore break; 1513*95c635efSGarrett D'Amore 1514*95c635efSGarrett D'Amore assert(j < (int)np->args->argc); 1515*95c635efSGarrett D'Amore assert(0 == np->args->argv[j].sz); 1516*95c635efSGarrett D'Amore 1517*95c635efSGarrett D'Amore /* 1518*95c635efSGarrett D'Amore * Accommodate for new-style groff column syntax. Shuffle the 1519*95c635efSGarrett D'Amore * child nodes, all of which must be TEXT, as arguments for the 1520*95c635efSGarrett D'Amore * column field. Then, delete the head children. 1521*95c635efSGarrett D'Amore */ 1522*95c635efSGarrett D'Amore 1523*95c635efSGarrett D'Amore np->args->argv[j].sz = (size_t)mdoc->last->nchild; 1524*95c635efSGarrett D'Amore np->args->argv[j].value = mandoc_malloc 1525*95c635efSGarrett D'Amore ((size_t)mdoc->last->nchild * sizeof(char *)); 1526*95c635efSGarrett D'Amore 1527*95c635efSGarrett D'Amore mdoc->last->norm->Bl.ncols = np->args->argv[j].sz; 1528*95c635efSGarrett D'Amore mdoc->last->norm->Bl.cols = (void *)np->args->argv[j].value; 1529*95c635efSGarrett D'Amore 1530*95c635efSGarrett D'Amore for (i = 0, nn = mdoc->last->child; nn; i++) { 1531*95c635efSGarrett D'Amore np->args->argv[j].value[i] = nn->string; 1532*95c635efSGarrett D'Amore nn->string = NULL; 1533*95c635efSGarrett D'Amore nnp = nn; 1534*95c635efSGarrett D'Amore nn = nn->next; 1535*95c635efSGarrett D'Amore mdoc_node_delete(NULL, nnp); 1536*95c635efSGarrett D'Amore } 1537*95c635efSGarrett D'Amore 1538*95c635efSGarrett D'Amore mdoc->last->nchild = 0; 1539*95c635efSGarrett D'Amore mdoc->last->child = NULL; 1540*95c635efSGarrett D'Amore 1541*95c635efSGarrett D'Amore return(1); 1542*95c635efSGarrett D'Amore } 1543*95c635efSGarrett D'Amore 1544*95c635efSGarrett D'Amore static int 1545*95c635efSGarrett D'Amore post_bl(POST_ARGS) 1546*95c635efSGarrett D'Amore { 1547*95c635efSGarrett D'Amore struct mdoc_node *n; 1548*95c635efSGarrett D'Amore 1549*95c635efSGarrett D'Amore if (MDOC_HEAD == mdoc->last->type) 1550*95c635efSGarrett D'Amore return(post_bl_head(mdoc)); 1551*95c635efSGarrett D'Amore if (MDOC_BLOCK == mdoc->last->type) 1552*95c635efSGarrett D'Amore return(post_bl_block(mdoc)); 1553*95c635efSGarrett D'Amore if (MDOC_BODY != mdoc->last->type) 1554*95c635efSGarrett D'Amore return(1); 1555*95c635efSGarrett D'Amore 1556*95c635efSGarrett D'Amore for (n = mdoc->last->child; n; n = n->next) { 1557*95c635efSGarrett D'Amore switch (n->tok) { 1558*95c635efSGarrett D'Amore case (MDOC_Lp): 1559*95c635efSGarrett D'Amore /* FALLTHROUGH */ 1560*95c635efSGarrett D'Amore case (MDOC_Pp): 1561*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_CHILD); 1562*95c635efSGarrett D'Amore /* FALLTHROUGH */ 1563*95c635efSGarrett D'Amore case (MDOC_It): 1564*95c635efSGarrett D'Amore /* FALLTHROUGH */ 1565*95c635efSGarrett D'Amore case (MDOC_Sm): 1566*95c635efSGarrett D'Amore continue; 1567*95c635efSGarrett D'Amore default: 1568*95c635efSGarrett D'Amore break; 1569*95c635efSGarrett D'Amore } 1570*95c635efSGarrett D'Amore 1571*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_SYNTCHILD); 1572*95c635efSGarrett D'Amore return(0); 1573*95c635efSGarrett D'Amore } 1574*95c635efSGarrett D'Amore 1575*95c635efSGarrett D'Amore return(1); 1576*95c635efSGarrett D'Amore } 1577*95c635efSGarrett D'Amore 1578*95c635efSGarrett D'Amore static int 1579*95c635efSGarrett D'Amore ebool(struct mdoc *mdoc) 1580*95c635efSGarrett D'Amore { 1581*95c635efSGarrett D'Amore 1582*95c635efSGarrett D'Amore if (NULL == mdoc->last->child) { 1583*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_MACROEMPTY); 1584*95c635efSGarrett D'Amore mdoc_node_delete(mdoc, mdoc->last); 1585*95c635efSGarrett D'Amore return(1); 1586*95c635efSGarrett D'Amore } 1587*95c635efSGarrett D'Amore check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1); 1588*95c635efSGarrett D'Amore 1589*95c635efSGarrett D'Amore assert(MDOC_TEXT == mdoc->last->child->type); 1590*95c635efSGarrett D'Amore 1591*95c635efSGarrett D'Amore if (0 == strcmp(mdoc->last->child->string, "on")) 1592*95c635efSGarrett D'Amore return(1); 1593*95c635efSGarrett D'Amore if (0 == strcmp(mdoc->last->child->string, "off")) 1594*95c635efSGarrett D'Amore return(1); 1595*95c635efSGarrett D'Amore 1596*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADBOOL); 1597*95c635efSGarrett D'Amore return(1); 1598*95c635efSGarrett D'Amore } 1599*95c635efSGarrett D'Amore 1600*95c635efSGarrett D'Amore static int 1601*95c635efSGarrett D'Amore post_root(POST_ARGS) 1602*95c635efSGarrett D'Amore { 1603*95c635efSGarrett D'Amore int erc; 1604*95c635efSGarrett D'Amore struct mdoc_node *n; 1605*95c635efSGarrett D'Amore 1606*95c635efSGarrett D'Amore erc = 0; 1607*95c635efSGarrett D'Amore 1608*95c635efSGarrett D'Amore /* Check that we have a finished prologue. */ 1609*95c635efSGarrett D'Amore 1610*95c635efSGarrett D'Amore if ( ! (MDOC_PBODY & mdoc->flags)) { 1611*95c635efSGarrett D'Amore erc++; 1612*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->first, MANDOCERR_NODOCPROLOG); 1613*95c635efSGarrett D'Amore } 1614*95c635efSGarrett D'Amore 1615*95c635efSGarrett D'Amore n = mdoc->first; 1616*95c635efSGarrett D'Amore assert(n); 1617*95c635efSGarrett D'Amore 1618*95c635efSGarrett D'Amore /* Check that we begin with a proper `Sh'. */ 1619*95c635efSGarrett D'Amore 1620*95c635efSGarrett D'Amore if (NULL == n->child) { 1621*95c635efSGarrett D'Amore erc++; 1622*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_NODOCBODY); 1623*95c635efSGarrett D'Amore } else if (MDOC_BLOCK != n->child->type || 1624*95c635efSGarrett D'Amore MDOC_Sh != n->child->tok) { 1625*95c635efSGarrett D'Amore erc++; 1626*95c635efSGarrett D'Amore /* Can this be lifted? See rxdebug.1 for example. */ 1627*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_NODOCBODY); 1628*95c635efSGarrett D'Amore } 1629*95c635efSGarrett D'Amore 1630*95c635efSGarrett D'Amore return(erc ? 0 : 1); 1631*95c635efSGarrett D'Amore } 1632*95c635efSGarrett D'Amore 1633*95c635efSGarrett D'Amore static int 1634*95c635efSGarrett D'Amore post_st(POST_ARGS) 1635*95c635efSGarrett D'Amore { 1636*95c635efSGarrett D'Amore struct mdoc_node *ch; 1637*95c635efSGarrett D'Amore const char *p; 1638*95c635efSGarrett D'Amore 1639*95c635efSGarrett D'Amore if (NULL == (ch = mdoc->last->child)) { 1640*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_MACROEMPTY); 1641*95c635efSGarrett D'Amore mdoc_node_delete(mdoc, mdoc->last); 1642*95c635efSGarrett D'Amore return(1); 1643*95c635efSGarrett D'Amore } 1644*95c635efSGarrett D'Amore 1645*95c635efSGarrett D'Amore assert(MDOC_TEXT == ch->type); 1646*95c635efSGarrett D'Amore 1647*95c635efSGarrett D'Amore if (NULL == (p = mdoc_a2st(ch->string))) { 1648*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADSTANDARD); 1649*95c635efSGarrett D'Amore mdoc_node_delete(mdoc, mdoc->last); 1650*95c635efSGarrett D'Amore } else { 1651*95c635efSGarrett D'Amore free(ch->string); 1652*95c635efSGarrett D'Amore ch->string = mandoc_strdup(p); 1653*95c635efSGarrett D'Amore } 1654*95c635efSGarrett D'Amore 1655*95c635efSGarrett D'Amore return(1); 1656*95c635efSGarrett D'Amore } 1657*95c635efSGarrett D'Amore 1658*95c635efSGarrett D'Amore static int 1659*95c635efSGarrett D'Amore post_rs(POST_ARGS) 1660*95c635efSGarrett D'Amore { 1661*95c635efSGarrett D'Amore struct mdoc_node *nn, *next, *prev; 1662*95c635efSGarrett D'Amore int i, j; 1663*95c635efSGarrett D'Amore 1664*95c635efSGarrett D'Amore switch (mdoc->last->type) { 1665*95c635efSGarrett D'Amore case (MDOC_HEAD): 1666*95c635efSGarrett D'Amore check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 0); 1667*95c635efSGarrett D'Amore return(1); 1668*95c635efSGarrett D'Amore case (MDOC_BODY): 1669*95c635efSGarrett D'Amore if (mdoc->last->child) 1670*95c635efSGarrett D'Amore break; 1671*95c635efSGarrett D'Amore check_count(mdoc, MDOC_BODY, CHECK_WARN, CHECK_GT, 0); 1672*95c635efSGarrett D'Amore return(1); 1673*95c635efSGarrett D'Amore default: 1674*95c635efSGarrett D'Amore return(1); 1675*95c635efSGarrett D'Amore } 1676*95c635efSGarrett D'Amore 1677*95c635efSGarrett D'Amore /* 1678*95c635efSGarrett D'Amore * Make sure only certain types of nodes are allowed within the 1679*95c635efSGarrett D'Amore * the `Rs' body. Delete offending nodes and raise a warning. 1680*95c635efSGarrett D'Amore * Do this before re-ordering for the sake of clarity. 1681*95c635efSGarrett D'Amore */ 1682*95c635efSGarrett D'Amore 1683*95c635efSGarrett D'Amore next = NULL; 1684*95c635efSGarrett D'Amore for (nn = mdoc->last->child; nn; nn = next) { 1685*95c635efSGarrett D'Amore for (i = 0; i < RSORD_MAX; i++) 1686*95c635efSGarrett D'Amore if (nn->tok == rsord[i]) 1687*95c635efSGarrett D'Amore break; 1688*95c635efSGarrett D'Amore 1689*95c635efSGarrett D'Amore if (i < RSORD_MAX) { 1690*95c635efSGarrett D'Amore if (MDOC__J == rsord[i] || MDOC__B == rsord[i]) 1691*95c635efSGarrett D'Amore mdoc->last->norm->Rs.quote_T++; 1692*95c635efSGarrett D'Amore next = nn->next; 1693*95c635efSGarrett D'Amore continue; 1694*95c635efSGarrett D'Amore } 1695*95c635efSGarrett D'Amore 1696*95c635efSGarrett D'Amore next = nn->next; 1697*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, nn, MANDOCERR_CHILD); 1698*95c635efSGarrett D'Amore mdoc_node_delete(mdoc, nn); 1699*95c635efSGarrett D'Amore } 1700*95c635efSGarrett D'Amore 1701*95c635efSGarrett D'Amore /* 1702*95c635efSGarrett D'Amore * Nothing to sort if only invalid nodes were found 1703*95c635efSGarrett D'Amore * inside the `Rs' body. 1704*95c635efSGarrett D'Amore */ 1705*95c635efSGarrett D'Amore 1706*95c635efSGarrett D'Amore if (NULL == mdoc->last->child) 1707*95c635efSGarrett D'Amore return(1); 1708*95c635efSGarrett D'Amore 1709*95c635efSGarrett D'Amore /* 1710*95c635efSGarrett D'Amore * The full `Rs' block needs special handling to order the 1711*95c635efSGarrett D'Amore * sub-elements according to `rsord'. Pick through each element 1712*95c635efSGarrett D'Amore * and correctly order it. This is a insertion sort. 1713*95c635efSGarrett D'Amore */ 1714*95c635efSGarrett D'Amore 1715*95c635efSGarrett D'Amore next = NULL; 1716*95c635efSGarrett D'Amore for (nn = mdoc->last->child->next; nn; nn = next) { 1717*95c635efSGarrett D'Amore /* Determine order of `nn'. */ 1718*95c635efSGarrett D'Amore for (i = 0; i < RSORD_MAX; i++) 1719*95c635efSGarrett D'Amore if (rsord[i] == nn->tok) 1720*95c635efSGarrett D'Amore break; 1721*95c635efSGarrett D'Amore 1722*95c635efSGarrett D'Amore /* 1723*95c635efSGarrett D'Amore * Remove `nn' from the chain. This somewhat 1724*95c635efSGarrett D'Amore * repeats mdoc_node_unlink(), but since we're 1725*95c635efSGarrett D'Amore * just re-ordering, there's no need for the 1726*95c635efSGarrett D'Amore * full unlink process. 1727*95c635efSGarrett D'Amore */ 1728*95c635efSGarrett D'Amore 1729*95c635efSGarrett D'Amore if (NULL != (next = nn->next)) 1730*95c635efSGarrett D'Amore next->prev = nn->prev; 1731*95c635efSGarrett D'Amore 1732*95c635efSGarrett D'Amore if (NULL != (prev = nn->prev)) 1733*95c635efSGarrett D'Amore prev->next = nn->next; 1734*95c635efSGarrett D'Amore 1735*95c635efSGarrett D'Amore nn->prev = nn->next = NULL; 1736*95c635efSGarrett D'Amore 1737*95c635efSGarrett D'Amore /* 1738*95c635efSGarrett D'Amore * Scan back until we reach a node that's 1739*95c635efSGarrett D'Amore * ordered before `nn'. 1740*95c635efSGarrett D'Amore */ 1741*95c635efSGarrett D'Amore 1742*95c635efSGarrett D'Amore for ( ; prev ; prev = prev->prev) { 1743*95c635efSGarrett D'Amore /* Determine order of `prev'. */ 1744*95c635efSGarrett D'Amore for (j = 0; j < RSORD_MAX; j++) 1745*95c635efSGarrett D'Amore if (rsord[j] == prev->tok) 1746*95c635efSGarrett D'Amore break; 1747*95c635efSGarrett D'Amore 1748*95c635efSGarrett D'Amore if (j <= i) 1749*95c635efSGarrett D'Amore break; 1750*95c635efSGarrett D'Amore } 1751*95c635efSGarrett D'Amore 1752*95c635efSGarrett D'Amore /* 1753*95c635efSGarrett D'Amore * Set `nn' back into its correct place in front 1754*95c635efSGarrett D'Amore * of the `prev' node. 1755*95c635efSGarrett D'Amore */ 1756*95c635efSGarrett D'Amore 1757*95c635efSGarrett D'Amore nn->prev = prev; 1758*95c635efSGarrett D'Amore 1759*95c635efSGarrett D'Amore if (prev) { 1760*95c635efSGarrett D'Amore if (prev->next) 1761*95c635efSGarrett D'Amore prev->next->prev = nn; 1762*95c635efSGarrett D'Amore nn->next = prev->next; 1763*95c635efSGarrett D'Amore prev->next = nn; 1764*95c635efSGarrett D'Amore } else { 1765*95c635efSGarrett D'Amore mdoc->last->child->prev = nn; 1766*95c635efSGarrett D'Amore nn->next = mdoc->last->child; 1767*95c635efSGarrett D'Amore mdoc->last->child = nn; 1768*95c635efSGarrett D'Amore } 1769*95c635efSGarrett D'Amore } 1770*95c635efSGarrett D'Amore 1771*95c635efSGarrett D'Amore return(1); 1772*95c635efSGarrett D'Amore } 1773*95c635efSGarrett D'Amore 1774*95c635efSGarrett D'Amore static int 1775*95c635efSGarrett D'Amore post_ns(POST_ARGS) 1776*95c635efSGarrett D'Amore { 1777*95c635efSGarrett D'Amore 1778*95c635efSGarrett D'Amore if (MDOC_LINE & mdoc->last->flags) 1779*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_IGNNS); 1780*95c635efSGarrett D'Amore return(1); 1781*95c635efSGarrett D'Amore } 1782*95c635efSGarrett D'Amore 1783*95c635efSGarrett D'Amore static int 1784*95c635efSGarrett D'Amore post_sh(POST_ARGS) 1785*95c635efSGarrett D'Amore { 1786*95c635efSGarrett D'Amore 1787*95c635efSGarrett D'Amore if (MDOC_HEAD == mdoc->last->type) 1788*95c635efSGarrett D'Amore return(post_sh_head(mdoc)); 1789*95c635efSGarrett D'Amore if (MDOC_BODY == mdoc->last->type) 1790*95c635efSGarrett D'Amore return(post_sh_body(mdoc)); 1791*95c635efSGarrett D'Amore 1792*95c635efSGarrett D'Amore return(1); 1793*95c635efSGarrett D'Amore } 1794*95c635efSGarrett D'Amore 1795*95c635efSGarrett D'Amore static int 1796*95c635efSGarrett D'Amore post_sh_body(POST_ARGS) 1797*95c635efSGarrett D'Amore { 1798*95c635efSGarrett D'Amore struct mdoc_node *n; 1799*95c635efSGarrett D'Amore 1800*95c635efSGarrett D'Amore if (SEC_NAME != mdoc->lastsec) 1801*95c635efSGarrett D'Amore return(1); 1802*95c635efSGarrett D'Amore 1803*95c635efSGarrett D'Amore /* 1804*95c635efSGarrett D'Amore * Warn if the NAME section doesn't contain the `Nm' and `Nd' 1805*95c635efSGarrett D'Amore * macros (can have multiple `Nm' and one `Nd'). Note that the 1806*95c635efSGarrett D'Amore * children of the BODY declaration can also be "text". 1807*95c635efSGarrett D'Amore */ 1808*95c635efSGarrett D'Amore 1809*95c635efSGarrett D'Amore if (NULL == (n = mdoc->last->child)) { 1810*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADNAMESEC); 1811*95c635efSGarrett D'Amore return(1); 1812*95c635efSGarrett D'Amore } 1813*95c635efSGarrett D'Amore 1814*95c635efSGarrett D'Amore for ( ; n && n->next; n = n->next) { 1815*95c635efSGarrett D'Amore if (MDOC_ELEM == n->type && MDOC_Nm == n->tok) 1816*95c635efSGarrett D'Amore continue; 1817*95c635efSGarrett D'Amore if (MDOC_TEXT == n->type) 1818*95c635efSGarrett D'Amore continue; 1819*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADNAMESEC); 1820*95c635efSGarrett D'Amore } 1821*95c635efSGarrett D'Amore 1822*95c635efSGarrett D'Amore assert(n); 1823*95c635efSGarrett D'Amore if (MDOC_BLOCK == n->type && MDOC_Nd == n->tok) 1824*95c635efSGarrett D'Amore return(1); 1825*95c635efSGarrett D'Amore 1826*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADNAMESEC); 1827*95c635efSGarrett D'Amore return(1); 1828*95c635efSGarrett D'Amore } 1829*95c635efSGarrett D'Amore 1830*95c635efSGarrett D'Amore static int 1831*95c635efSGarrett D'Amore post_sh_head(POST_ARGS) 1832*95c635efSGarrett D'Amore { 1833*95c635efSGarrett D'Amore char buf[BUFSIZ]; 1834*95c635efSGarrett D'Amore struct mdoc_node *n; 1835*95c635efSGarrett D'Amore enum mdoc_sec sec; 1836*95c635efSGarrett D'Amore int c; 1837*95c635efSGarrett D'Amore 1838*95c635efSGarrett D'Amore /* 1839*95c635efSGarrett D'Amore * Process a new section. Sections are either "named" or 1840*95c635efSGarrett D'Amore * "custom". Custom sections are user-defined, while named ones 1841*95c635efSGarrett D'Amore * follow a conventional order and may only appear in certain 1842*95c635efSGarrett D'Amore * manual sections. 1843*95c635efSGarrett D'Amore */ 1844*95c635efSGarrett D'Amore 1845*95c635efSGarrett D'Amore sec = SEC_CUSTOM; 1846*95c635efSGarrett D'Amore buf[0] = '\0'; 1847*95c635efSGarrett D'Amore if (-1 == (c = concat(buf, mdoc->last->child, BUFSIZ))) { 1848*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last->child, MANDOCERR_MEM); 1849*95c635efSGarrett D'Amore return(0); 1850*95c635efSGarrett D'Amore } else if (1 == c) 1851*95c635efSGarrett D'Amore sec = a2sec(buf); 1852*95c635efSGarrett D'Amore 1853*95c635efSGarrett D'Amore /* The NAME should be first. */ 1854*95c635efSGarrett D'Amore 1855*95c635efSGarrett D'Amore if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed) 1856*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NAMESECFIRST); 1857*95c635efSGarrett D'Amore 1858*95c635efSGarrett D'Amore /* The SYNOPSIS gets special attention in other areas. */ 1859*95c635efSGarrett D'Amore 1860*95c635efSGarrett D'Amore if (SEC_SYNOPSIS == sec) 1861*95c635efSGarrett D'Amore mdoc->flags |= MDOC_SYNOPSIS; 1862*95c635efSGarrett D'Amore else 1863*95c635efSGarrett D'Amore mdoc->flags &= ~MDOC_SYNOPSIS; 1864*95c635efSGarrett D'Amore 1865*95c635efSGarrett D'Amore /* Mark our last section. */ 1866*95c635efSGarrett D'Amore 1867*95c635efSGarrett D'Amore mdoc->lastsec = sec; 1868*95c635efSGarrett D'Amore 1869*95c635efSGarrett D'Amore /* 1870*95c635efSGarrett D'Amore * Set the section attribute for the current HEAD, for its 1871*95c635efSGarrett D'Amore * parent BLOCK, and for the HEAD children; the latter can 1872*95c635efSGarrett D'Amore * only be TEXT nodes, so no recursion is needed. 1873*95c635efSGarrett D'Amore * For other blocks and elements, including .Sh BODY, this is 1874*95c635efSGarrett D'Amore * done when allocating the node data structures, but for .Sh 1875*95c635efSGarrett D'Amore * BLOCK and HEAD, the section is still unknown at that time. 1876*95c635efSGarrett D'Amore */ 1877*95c635efSGarrett D'Amore 1878*95c635efSGarrett D'Amore mdoc->last->parent->sec = sec; 1879*95c635efSGarrett D'Amore mdoc->last->sec = sec; 1880*95c635efSGarrett D'Amore for (n = mdoc->last->child; n; n = n->next) 1881*95c635efSGarrett D'Amore n->sec = sec; 1882*95c635efSGarrett D'Amore 1883*95c635efSGarrett D'Amore /* We don't care about custom sections after this. */ 1884*95c635efSGarrett D'Amore 1885*95c635efSGarrett D'Amore if (SEC_CUSTOM == sec) 1886*95c635efSGarrett D'Amore return(1); 1887*95c635efSGarrett D'Amore 1888*95c635efSGarrett D'Amore /* 1889*95c635efSGarrett D'Amore * Check whether our non-custom section is being repeated or is 1890*95c635efSGarrett D'Amore * out of order. 1891*95c635efSGarrett D'Amore */ 1892*95c635efSGarrett D'Amore 1893*95c635efSGarrett D'Amore if (sec == mdoc->lastnamed) 1894*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECREP); 1895*95c635efSGarrett D'Amore 1896*95c635efSGarrett D'Amore if (sec < mdoc->lastnamed) 1897*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECOOO); 1898*95c635efSGarrett D'Amore 1899*95c635efSGarrett D'Amore /* Mark the last named section. */ 1900*95c635efSGarrett D'Amore 1901*95c635efSGarrett D'Amore mdoc->lastnamed = sec; 1902*95c635efSGarrett D'Amore 1903*95c635efSGarrett D'Amore /* Check particular section/manual conventions. */ 1904*95c635efSGarrett D'Amore 1905*95c635efSGarrett D'Amore assert(mdoc->meta.msec); 1906*95c635efSGarrett D'Amore 1907*95c635efSGarrett D'Amore switch (sec) { 1908*95c635efSGarrett D'Amore case (SEC_RETURN_VALUES): 1909*95c635efSGarrett D'Amore /* FALLTHROUGH */ 1910*95c635efSGarrett D'Amore case (SEC_ERRORS): 1911*95c635efSGarrett D'Amore /* FALLTHROUGH */ 1912*95c635efSGarrett D'Amore case (SEC_LIBRARY): 1913*95c635efSGarrett D'Amore if (*mdoc->meta.msec == '2') 1914*95c635efSGarrett D'Amore break; 1915*95c635efSGarrett D'Amore if (*mdoc->meta.msec == '3') 1916*95c635efSGarrett D'Amore break; 1917*95c635efSGarrett D'Amore if (*mdoc->meta.msec == '9') 1918*95c635efSGarrett D'Amore break; 1919*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SECMSEC); 1920*95c635efSGarrett D'Amore break; 1921*95c635efSGarrett D'Amore default: 1922*95c635efSGarrett D'Amore break; 1923*95c635efSGarrett D'Amore } 1924*95c635efSGarrett D'Amore 1925*95c635efSGarrett D'Amore return(1); 1926*95c635efSGarrett D'Amore } 1927*95c635efSGarrett D'Amore 1928*95c635efSGarrett D'Amore static int 1929*95c635efSGarrett D'Amore post_ignpar(POST_ARGS) 1930*95c635efSGarrett D'Amore { 1931*95c635efSGarrett D'Amore struct mdoc_node *np; 1932*95c635efSGarrett D'Amore 1933*95c635efSGarrett D'Amore if (MDOC_BODY != mdoc->last->type) 1934*95c635efSGarrett D'Amore return(1); 1935*95c635efSGarrett D'Amore 1936*95c635efSGarrett D'Amore if (NULL != (np = mdoc->last->child)) 1937*95c635efSGarrett D'Amore if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) { 1938*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, np, MANDOCERR_IGNPAR); 1939*95c635efSGarrett D'Amore mdoc_node_delete(mdoc, np); 1940*95c635efSGarrett D'Amore } 1941*95c635efSGarrett D'Amore 1942*95c635efSGarrett D'Amore if (NULL != (np = mdoc->last->last)) 1943*95c635efSGarrett D'Amore if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) { 1944*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, np, MANDOCERR_IGNPAR); 1945*95c635efSGarrett D'Amore mdoc_node_delete(mdoc, np); 1946*95c635efSGarrett D'Amore } 1947*95c635efSGarrett D'Amore 1948*95c635efSGarrett D'Amore return(1); 1949*95c635efSGarrett D'Amore } 1950*95c635efSGarrett D'Amore 1951*95c635efSGarrett D'Amore static int 1952*95c635efSGarrett D'Amore pre_par(PRE_ARGS) 1953*95c635efSGarrett D'Amore { 1954*95c635efSGarrett D'Amore 1955*95c635efSGarrett D'Amore if (NULL == mdoc->last) 1956*95c635efSGarrett D'Amore return(1); 1957*95c635efSGarrett D'Amore if (MDOC_ELEM != n->type && MDOC_BLOCK != n->type) 1958*95c635efSGarrett D'Amore return(1); 1959*95c635efSGarrett D'Amore 1960*95c635efSGarrett D'Amore /* 1961*95c635efSGarrett D'Amore * Don't allow prior `Lp' or `Pp' prior to a paragraph-type 1962*95c635efSGarrett D'Amore * block: `Lp', `Pp', or non-compact `Bd' or `Bl'. 1963*95c635efSGarrett D'Amore */ 1964*95c635efSGarrett D'Amore 1965*95c635efSGarrett D'Amore if (MDOC_Pp != mdoc->last->tok && MDOC_Lp != mdoc->last->tok) 1966*95c635efSGarrett D'Amore return(1); 1967*95c635efSGarrett D'Amore if (MDOC_Bl == n->tok && n->norm->Bl.comp) 1968*95c635efSGarrett D'Amore return(1); 1969*95c635efSGarrett D'Amore if (MDOC_Bd == n->tok && n->norm->Bd.comp) 1970*95c635efSGarrett D'Amore return(1); 1971*95c635efSGarrett D'Amore if (MDOC_It == n->tok && n->parent->norm->Bl.comp) 1972*95c635efSGarrett D'Amore return(1); 1973*95c635efSGarrett D'Amore 1974*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_IGNPAR); 1975*95c635efSGarrett D'Amore mdoc_node_delete(mdoc, mdoc->last); 1976*95c635efSGarrett D'Amore return(1); 1977*95c635efSGarrett D'Amore } 1978*95c635efSGarrett D'Amore 1979*95c635efSGarrett D'Amore static int 1980*95c635efSGarrett D'Amore pre_literal(PRE_ARGS) 1981*95c635efSGarrett D'Amore { 1982*95c635efSGarrett D'Amore 1983*95c635efSGarrett D'Amore if (MDOC_BODY != n->type) 1984*95c635efSGarrett D'Amore return(1); 1985*95c635efSGarrett D'Amore 1986*95c635efSGarrett D'Amore /* 1987*95c635efSGarrett D'Amore * The `Dl' (note "el" not "one") and `Bd -literal' and `Bd 1988*95c635efSGarrett D'Amore * -unfilled' macros set MDOC_LITERAL on entrance to the body. 1989*95c635efSGarrett D'Amore */ 1990*95c635efSGarrett D'Amore 1991*95c635efSGarrett D'Amore switch (n->tok) { 1992*95c635efSGarrett D'Amore case (MDOC_Dl): 1993*95c635efSGarrett D'Amore mdoc->flags |= MDOC_LITERAL; 1994*95c635efSGarrett D'Amore break; 1995*95c635efSGarrett D'Amore case (MDOC_Bd): 1996*95c635efSGarrett D'Amore if (DISP_literal == n->norm->Bd.type) 1997*95c635efSGarrett D'Amore mdoc->flags |= MDOC_LITERAL; 1998*95c635efSGarrett D'Amore if (DISP_unfilled == n->norm->Bd.type) 1999*95c635efSGarrett D'Amore mdoc->flags |= MDOC_LITERAL; 2000*95c635efSGarrett D'Amore break; 2001*95c635efSGarrett D'Amore default: 2002*95c635efSGarrett D'Amore abort(); 2003*95c635efSGarrett D'Amore /* NOTREACHED */ 2004*95c635efSGarrett D'Amore } 2005*95c635efSGarrett D'Amore 2006*95c635efSGarrett D'Amore return(1); 2007*95c635efSGarrett D'Amore } 2008*95c635efSGarrett D'Amore 2009*95c635efSGarrett D'Amore static int 2010*95c635efSGarrett D'Amore post_dd(POST_ARGS) 2011*95c635efSGarrett D'Amore { 2012*95c635efSGarrett D'Amore char buf[DATESIZE]; 2013*95c635efSGarrett D'Amore struct mdoc_node *n; 2014*95c635efSGarrett D'Amore int c; 2015*95c635efSGarrett D'Amore 2016*95c635efSGarrett D'Amore if (mdoc->meta.date) 2017*95c635efSGarrett D'Amore free(mdoc->meta.date); 2018*95c635efSGarrett D'Amore 2019*95c635efSGarrett D'Amore n = mdoc->last; 2020*95c635efSGarrett D'Amore if (NULL == n->child || '\0' == n->child->string[0]) { 2021*95c635efSGarrett D'Amore mdoc->meta.date = mandoc_normdate 2022*95c635efSGarrett D'Amore (mdoc->parse, NULL, n->line, n->pos); 2023*95c635efSGarrett D'Amore return(1); 2024*95c635efSGarrett D'Amore } 2025*95c635efSGarrett D'Amore 2026*95c635efSGarrett D'Amore buf[0] = '\0'; 2027*95c635efSGarrett D'Amore if (-1 == (c = concat(buf, n->child, DATESIZE))) { 2028*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n->child, MANDOCERR_MEM); 2029*95c635efSGarrett D'Amore return(0); 2030*95c635efSGarrett D'Amore } 2031*95c635efSGarrett D'Amore 2032*95c635efSGarrett D'Amore assert(c); 2033*95c635efSGarrett D'Amore mdoc->meta.date = mandoc_normdate 2034*95c635efSGarrett D'Amore (mdoc->parse, buf, n->line, n->pos); 2035*95c635efSGarrett D'Amore 2036*95c635efSGarrett D'Amore return(1); 2037*95c635efSGarrett D'Amore } 2038*95c635efSGarrett D'Amore 2039*95c635efSGarrett D'Amore static int 2040*95c635efSGarrett D'Amore post_dt(POST_ARGS) 2041*95c635efSGarrett D'Amore { 2042*95c635efSGarrett D'Amore struct mdoc_node *nn, *n; 2043*95c635efSGarrett D'Amore const char *cp; 2044*95c635efSGarrett D'Amore char *p; 2045*95c635efSGarrett D'Amore 2046*95c635efSGarrett D'Amore n = mdoc->last; 2047*95c635efSGarrett D'Amore 2048*95c635efSGarrett D'Amore if (mdoc->meta.title) 2049*95c635efSGarrett D'Amore free(mdoc->meta.title); 2050*95c635efSGarrett D'Amore if (mdoc->meta.vol) 2051*95c635efSGarrett D'Amore free(mdoc->meta.vol); 2052*95c635efSGarrett D'Amore if (mdoc->meta.arch) 2053*95c635efSGarrett D'Amore free(mdoc->meta.arch); 2054*95c635efSGarrett D'Amore 2055*95c635efSGarrett D'Amore mdoc->meta.title = mdoc->meta.vol = mdoc->meta.arch = NULL; 2056*95c635efSGarrett D'Amore 2057*95c635efSGarrett D'Amore /* First make all characters uppercase. */ 2058*95c635efSGarrett D'Amore 2059*95c635efSGarrett D'Amore if (NULL != (nn = n->child)) 2060*95c635efSGarrett D'Amore for (p = nn->string; *p; p++) { 2061*95c635efSGarrett D'Amore if (toupper((unsigned char)*p) == *p) 2062*95c635efSGarrett D'Amore continue; 2063*95c635efSGarrett D'Amore 2064*95c635efSGarrett D'Amore /* 2065*95c635efSGarrett D'Amore * FIXME: don't be lazy: have this make all 2066*95c635efSGarrett D'Amore * characters be uppercase and just warn once. 2067*95c635efSGarrett D'Amore */ 2068*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, nn, MANDOCERR_UPPERCASE); 2069*95c635efSGarrett D'Amore break; 2070*95c635efSGarrett D'Amore } 2071*95c635efSGarrett D'Amore 2072*95c635efSGarrett D'Amore /* Handles: `.Dt' 2073*95c635efSGarrett D'Amore * --> title = unknown, volume = local, msec = 0, arch = NULL 2074*95c635efSGarrett D'Amore */ 2075*95c635efSGarrett D'Amore 2076*95c635efSGarrett D'Amore if (NULL == (nn = n->child)) { 2077*95c635efSGarrett D'Amore /* XXX: make these macro values. */ 2078*95c635efSGarrett D'Amore /* FIXME: warn about missing values. */ 2079*95c635efSGarrett D'Amore mdoc->meta.title = mandoc_strdup("UNKNOWN"); 2080*95c635efSGarrett D'Amore mdoc->meta.vol = mandoc_strdup("LOCAL"); 2081*95c635efSGarrett D'Amore mdoc->meta.msec = mandoc_strdup("1"); 2082*95c635efSGarrett D'Amore return(1); 2083*95c635efSGarrett D'Amore } 2084*95c635efSGarrett D'Amore 2085*95c635efSGarrett D'Amore /* Handles: `.Dt TITLE' 2086*95c635efSGarrett D'Amore * --> title = TITLE, volume = local, msec = 0, arch = NULL 2087*95c635efSGarrett D'Amore */ 2088*95c635efSGarrett D'Amore 2089*95c635efSGarrett D'Amore mdoc->meta.title = mandoc_strdup 2090*95c635efSGarrett D'Amore ('\0' == nn->string[0] ? "UNKNOWN" : nn->string); 2091*95c635efSGarrett D'Amore 2092*95c635efSGarrett D'Amore if (NULL == (nn = nn->next)) { 2093*95c635efSGarrett D'Amore /* FIXME: warn about missing msec. */ 2094*95c635efSGarrett D'Amore /* XXX: make this a macro value. */ 2095*95c635efSGarrett D'Amore mdoc->meta.vol = mandoc_strdup("LOCAL"); 2096*95c635efSGarrett D'Amore mdoc->meta.msec = mandoc_strdup("1"); 2097*95c635efSGarrett D'Amore return(1); 2098*95c635efSGarrett D'Amore } 2099*95c635efSGarrett D'Amore 2100*95c635efSGarrett D'Amore /* Handles: `.Dt TITLE SEC' 2101*95c635efSGarrett D'Amore * --> title = TITLE, volume = SEC is msec ? 2102*95c635efSGarrett D'Amore * format(msec) : SEC, 2103*95c635efSGarrett D'Amore * msec = SEC is msec ? atoi(msec) : 0, 2104*95c635efSGarrett D'Amore * arch = NULL 2105*95c635efSGarrett D'Amore */ 2106*95c635efSGarrett D'Amore 2107*95c635efSGarrett D'Amore cp = mandoc_a2msec(nn->string); 2108*95c635efSGarrett D'Amore if (cp) { 2109*95c635efSGarrett D'Amore mdoc->meta.vol = mandoc_strdup(cp); 2110*95c635efSGarrett D'Amore mdoc->meta.msec = mandoc_strdup(nn->string); 2111*95c635efSGarrett D'Amore } else { 2112*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_BADMSEC); 2113*95c635efSGarrett D'Amore mdoc->meta.vol = mandoc_strdup(nn->string); 2114*95c635efSGarrett D'Amore mdoc->meta.msec = mandoc_strdup(nn->string); 2115*95c635efSGarrett D'Amore } 2116*95c635efSGarrett D'Amore 2117*95c635efSGarrett D'Amore if (NULL == (nn = nn->next)) 2118*95c635efSGarrett D'Amore return(1); 2119*95c635efSGarrett D'Amore 2120*95c635efSGarrett D'Amore /* Handles: `.Dt TITLE SEC VOL' 2121*95c635efSGarrett D'Amore * --> title = TITLE, volume = VOL is vol ? 2122*95c635efSGarrett D'Amore * format(VOL) : 2123*95c635efSGarrett D'Amore * VOL is arch ? format(arch) : 2124*95c635efSGarrett D'Amore * VOL 2125*95c635efSGarrett D'Amore */ 2126*95c635efSGarrett D'Amore 2127*95c635efSGarrett D'Amore cp = mdoc_a2vol(nn->string); 2128*95c635efSGarrett D'Amore if (cp) { 2129*95c635efSGarrett D'Amore free(mdoc->meta.vol); 2130*95c635efSGarrett D'Amore mdoc->meta.vol = mandoc_strdup(cp); 2131*95c635efSGarrett D'Amore } else { 2132*95c635efSGarrett D'Amore /* FIXME: warn about bad arch. */ 2133*95c635efSGarrett D'Amore cp = mdoc_a2arch(nn->string); 2134*95c635efSGarrett D'Amore if (NULL == cp) { 2135*95c635efSGarrett D'Amore free(mdoc->meta.vol); 2136*95c635efSGarrett D'Amore mdoc->meta.vol = mandoc_strdup(nn->string); 2137*95c635efSGarrett D'Amore } else 2138*95c635efSGarrett D'Amore mdoc->meta.arch = mandoc_strdup(cp); 2139*95c635efSGarrett D'Amore } 2140*95c635efSGarrett D'Amore 2141*95c635efSGarrett D'Amore /* Ignore any subsequent parameters... */ 2142*95c635efSGarrett D'Amore /* FIXME: warn about subsequent parameters. */ 2143*95c635efSGarrett D'Amore 2144*95c635efSGarrett D'Amore return(1); 2145*95c635efSGarrett D'Amore } 2146*95c635efSGarrett D'Amore 2147*95c635efSGarrett D'Amore static int 2148*95c635efSGarrett D'Amore post_prol(POST_ARGS) 2149*95c635efSGarrett D'Amore { 2150*95c635efSGarrett D'Amore /* 2151*95c635efSGarrett D'Amore * Remove prologue macros from the document after they're 2152*95c635efSGarrett D'Amore * processed. The final document uses mdoc_meta for these 2153*95c635efSGarrett D'Amore * values and discards the originals. 2154*95c635efSGarrett D'Amore */ 2155*95c635efSGarrett D'Amore 2156*95c635efSGarrett D'Amore mdoc_node_delete(mdoc, mdoc->last); 2157*95c635efSGarrett D'Amore if (mdoc->meta.title && mdoc->meta.date && mdoc->meta.os) 2158*95c635efSGarrett D'Amore mdoc->flags |= MDOC_PBODY; 2159*95c635efSGarrett D'Amore 2160*95c635efSGarrett D'Amore return(1); 2161*95c635efSGarrett D'Amore } 2162*95c635efSGarrett D'Amore 2163*95c635efSGarrett D'Amore static int 2164*95c635efSGarrett D'Amore post_bx(POST_ARGS) 2165*95c635efSGarrett D'Amore { 2166*95c635efSGarrett D'Amore struct mdoc_node *n; 2167*95c635efSGarrett D'Amore 2168*95c635efSGarrett D'Amore /* 2169*95c635efSGarrett D'Amore * Make `Bx's second argument always start with an uppercase 2170*95c635efSGarrett D'Amore * letter. Groff checks if it's an "accepted" term, but we just 2171*95c635efSGarrett D'Amore * uppercase blindly. 2172*95c635efSGarrett D'Amore */ 2173*95c635efSGarrett D'Amore 2174*95c635efSGarrett D'Amore n = mdoc->last->child; 2175*95c635efSGarrett D'Amore if (n && NULL != (n = n->next)) 2176*95c635efSGarrett D'Amore *n->string = (char)toupper 2177*95c635efSGarrett D'Amore ((unsigned char)*n->string); 2178*95c635efSGarrett D'Amore 2179*95c635efSGarrett D'Amore return(1); 2180*95c635efSGarrett D'Amore } 2181*95c635efSGarrett D'Amore 2182*95c635efSGarrett D'Amore static int 2183*95c635efSGarrett D'Amore post_os(POST_ARGS) 2184*95c635efSGarrett D'Amore { 2185*95c635efSGarrett D'Amore struct mdoc_node *n; 2186*95c635efSGarrett D'Amore char buf[BUFSIZ]; 2187*95c635efSGarrett D'Amore int c; 2188*95c635efSGarrett D'Amore #ifndef OSNAME 2189*95c635efSGarrett D'Amore struct utsname utsname; 2190*95c635efSGarrett D'Amore #endif 2191*95c635efSGarrett D'Amore 2192*95c635efSGarrett D'Amore n = mdoc->last; 2193*95c635efSGarrett D'Amore 2194*95c635efSGarrett D'Amore /* 2195*95c635efSGarrett D'Amore * Set the operating system by way of the `Os' macro. Note that 2196*95c635efSGarrett D'Amore * if an argument isn't provided and -DOSNAME="\"foo\"" is 2197*95c635efSGarrett D'Amore * provided during compilation, this value will be used instead 2198*95c635efSGarrett D'Amore * of filling in "sysname release" from uname(). 2199*95c635efSGarrett D'Amore */ 2200*95c635efSGarrett D'Amore 2201*95c635efSGarrett D'Amore if (mdoc->meta.os) 2202*95c635efSGarrett D'Amore free(mdoc->meta.os); 2203*95c635efSGarrett D'Amore 2204*95c635efSGarrett D'Amore buf[0] = '\0'; 2205*95c635efSGarrett D'Amore if (-1 == (c = concat(buf, n->child, BUFSIZ))) { 2206*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n->child, MANDOCERR_MEM); 2207*95c635efSGarrett D'Amore return(0); 2208*95c635efSGarrett D'Amore } 2209*95c635efSGarrett D'Amore 2210*95c635efSGarrett D'Amore assert(c); 2211*95c635efSGarrett D'Amore 2212*95c635efSGarrett D'Amore /* XXX: yes, these can all be dynamically-adjusted buffers, but 2213*95c635efSGarrett D'Amore * it's really not worth the extra hackery. 2214*95c635efSGarrett D'Amore */ 2215*95c635efSGarrett D'Amore 2216*95c635efSGarrett D'Amore if ('\0' == buf[0]) { 2217*95c635efSGarrett D'Amore #ifdef OSNAME 2218*95c635efSGarrett D'Amore if (strlcat(buf, OSNAME, BUFSIZ) >= BUFSIZ) { 2219*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_MEM); 2220*95c635efSGarrett D'Amore return(0); 2221*95c635efSGarrett D'Amore } 2222*95c635efSGarrett D'Amore #else /*!OSNAME */ 2223*95c635efSGarrett D'Amore if (-1 == uname(&utsname)) { 2224*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_UNAME); 2225*95c635efSGarrett D'Amore mdoc->meta.os = mandoc_strdup("UNKNOWN"); 2226*95c635efSGarrett D'Amore return(post_prol(mdoc)); 2227*95c635efSGarrett D'Amore } 2228*95c635efSGarrett D'Amore 2229*95c635efSGarrett D'Amore if (strlcat(buf, utsname.sysname, BUFSIZ) >= BUFSIZ) { 2230*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_MEM); 2231*95c635efSGarrett D'Amore return(0); 2232*95c635efSGarrett D'Amore } 2233*95c635efSGarrett D'Amore if (strlcat(buf, " ", BUFSIZ) >= BUFSIZ) { 2234*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_MEM); 2235*95c635efSGarrett D'Amore return(0); 2236*95c635efSGarrett D'Amore } 2237*95c635efSGarrett D'Amore if (strlcat(buf, utsname.release, BUFSIZ) >= BUFSIZ) { 2238*95c635efSGarrett D'Amore mdoc_nmsg(mdoc, n, MANDOCERR_MEM); 2239*95c635efSGarrett D'Amore return(0); 2240*95c635efSGarrett D'Amore } 2241*95c635efSGarrett D'Amore #endif /*!OSNAME*/ 2242*95c635efSGarrett D'Amore } 2243*95c635efSGarrett D'Amore 2244*95c635efSGarrett D'Amore mdoc->meta.os = mandoc_strdup(buf); 2245*95c635efSGarrett D'Amore return(1); 2246*95c635efSGarrett D'Amore } 2247*95c635efSGarrett D'Amore 2248*95c635efSGarrett D'Amore static int 2249*95c635efSGarrett D'Amore post_std(POST_ARGS) 2250*95c635efSGarrett D'Amore { 2251*95c635efSGarrett D'Amore struct mdoc_node *nn, *n; 2252*95c635efSGarrett D'Amore 2253*95c635efSGarrett D'Amore n = mdoc->last; 2254*95c635efSGarrett D'Amore 2255*95c635efSGarrett D'Amore /* 2256*95c635efSGarrett D'Amore * Macros accepting `-std' as an argument have the name of the 2257*95c635efSGarrett D'Amore * current document (`Nm') filled in as the argument if it's not 2258*95c635efSGarrett D'Amore * provided. 2259*95c635efSGarrett D'Amore */ 2260*95c635efSGarrett D'Amore 2261*95c635efSGarrett D'Amore if (n->child) 2262*95c635efSGarrett D'Amore return(1); 2263*95c635efSGarrett D'Amore 2264*95c635efSGarrett D'Amore if (NULL == mdoc->meta.name) 2265*95c635efSGarrett D'Amore return(1); 2266*95c635efSGarrett D'Amore 2267*95c635efSGarrett D'Amore nn = n; 2268*95c635efSGarrett D'Amore mdoc->next = MDOC_NEXT_CHILD; 2269*95c635efSGarrett D'Amore 2270*95c635efSGarrett D'Amore if ( ! mdoc_word_alloc(mdoc, n->line, n->pos, mdoc->meta.name)) 2271*95c635efSGarrett D'Amore return(0); 2272*95c635efSGarrett D'Amore 2273*95c635efSGarrett D'Amore mdoc->last = nn; 2274*95c635efSGarrett D'Amore return(1); 2275*95c635efSGarrett D'Amore } 2276*95c635efSGarrett D'Amore 2277*95c635efSGarrett D'Amore /* 2278*95c635efSGarrett D'Amore * Concatenate a node, stopping at the first non-text. 2279*95c635efSGarrett D'Amore * Concatenation is separated by a single whitespace. 2280*95c635efSGarrett D'Amore * Returns -1 on fatal (string overrun) error, 0 if child nodes were 2281*95c635efSGarrett D'Amore * encountered, 1 otherwise. 2282*95c635efSGarrett D'Amore */ 2283*95c635efSGarrett D'Amore static int 2284*95c635efSGarrett D'Amore concat(char *p, const struct mdoc_node *n, size_t sz) 2285*95c635efSGarrett D'Amore { 2286*95c635efSGarrett D'Amore 2287*95c635efSGarrett D'Amore for ( ; NULL != n; n = n->next) { 2288*95c635efSGarrett D'Amore if (MDOC_TEXT != n->type) 2289*95c635efSGarrett D'Amore return(0); 2290*95c635efSGarrett D'Amore if ('\0' != p[0] && strlcat(p, " ", sz) >= sz) 2291*95c635efSGarrett D'Amore return(-1); 2292*95c635efSGarrett D'Amore if (strlcat(p, n->string, sz) >= sz) 2293*95c635efSGarrett D'Amore return(-1); 2294*95c635efSGarrett D'Amore concat(p, n->child, sz); 2295*95c635efSGarrett D'Amore } 2296*95c635efSGarrett D'Amore 2297*95c635efSGarrett D'Amore return(1); 2298*95c635efSGarrett D'Amore } 2299*95c635efSGarrett D'Amore 2300*95c635efSGarrett D'Amore static enum mdoc_sec 2301*95c635efSGarrett D'Amore a2sec(const char *p) 2302*95c635efSGarrett D'Amore { 2303*95c635efSGarrett D'Amore int i; 2304*95c635efSGarrett D'Amore 2305*95c635efSGarrett D'Amore for (i = 0; i < (int)SEC__MAX; i++) 2306*95c635efSGarrett D'Amore if (secnames[i] && 0 == strcmp(p, secnames[i])) 2307*95c635efSGarrett D'Amore return((enum mdoc_sec)i); 2308*95c635efSGarrett D'Amore 2309*95c635efSGarrett D'Amore return(SEC_CUSTOM); 2310*95c635efSGarrett D'Amore } 2311*95c635efSGarrett D'Amore 2312*95c635efSGarrett D'Amore static size_t 2313*95c635efSGarrett D'Amore macro2len(enum mdoct macro) 2314*95c635efSGarrett D'Amore { 2315*95c635efSGarrett D'Amore 2316*95c635efSGarrett D'Amore switch (macro) { 2317*95c635efSGarrett D'Amore case(MDOC_Ad): 2318*95c635efSGarrett D'Amore return(12); 2319*95c635efSGarrett D'Amore case(MDOC_Ao): 2320*95c635efSGarrett D'Amore return(12); 2321*95c635efSGarrett D'Amore case(MDOC_An): 2322*95c635efSGarrett D'Amore return(12); 2323*95c635efSGarrett D'Amore case(MDOC_Aq): 2324*95c635efSGarrett D'Amore return(12); 2325*95c635efSGarrett D'Amore case(MDOC_Ar): 2326*95c635efSGarrett D'Amore return(12); 2327*95c635efSGarrett D'Amore case(MDOC_Bo): 2328*95c635efSGarrett D'Amore return(12); 2329*95c635efSGarrett D'Amore case(MDOC_Bq): 2330*95c635efSGarrett D'Amore return(12); 2331*95c635efSGarrett D'Amore case(MDOC_Cd): 2332*95c635efSGarrett D'Amore return(12); 2333*95c635efSGarrett D'Amore case(MDOC_Cm): 2334*95c635efSGarrett D'Amore return(10); 2335*95c635efSGarrett D'Amore case(MDOC_Do): 2336*95c635efSGarrett D'Amore return(10); 2337*95c635efSGarrett D'Amore case(MDOC_Dq): 2338*95c635efSGarrett D'Amore return(12); 2339*95c635efSGarrett D'Amore case(MDOC_Dv): 2340*95c635efSGarrett D'Amore return(12); 2341*95c635efSGarrett D'Amore case(MDOC_Eo): 2342*95c635efSGarrett D'Amore return(12); 2343*95c635efSGarrett D'Amore case(MDOC_Em): 2344*95c635efSGarrett D'Amore return(10); 2345*95c635efSGarrett D'Amore case(MDOC_Er): 2346*95c635efSGarrett D'Amore return(17); 2347*95c635efSGarrett D'Amore case(MDOC_Ev): 2348*95c635efSGarrett D'Amore return(15); 2349*95c635efSGarrett D'Amore case(MDOC_Fa): 2350*95c635efSGarrett D'Amore return(12); 2351*95c635efSGarrett D'Amore case(MDOC_Fl): 2352*95c635efSGarrett D'Amore return(10); 2353*95c635efSGarrett D'Amore case(MDOC_Fo): 2354*95c635efSGarrett D'Amore return(16); 2355*95c635efSGarrett D'Amore case(MDOC_Fn): 2356*95c635efSGarrett D'Amore return(16); 2357*95c635efSGarrett D'Amore case(MDOC_Ic): 2358*95c635efSGarrett D'Amore return(10); 2359*95c635efSGarrett D'Amore case(MDOC_Li): 2360*95c635efSGarrett D'Amore return(16); 2361*95c635efSGarrett D'Amore case(MDOC_Ms): 2362*95c635efSGarrett D'Amore return(6); 2363*95c635efSGarrett D'Amore case(MDOC_Nm): 2364*95c635efSGarrett D'Amore return(10); 2365*95c635efSGarrett D'Amore case(MDOC_No): 2366*95c635efSGarrett D'Amore return(12); 2367*95c635efSGarrett D'Amore case(MDOC_Oo): 2368*95c635efSGarrett D'Amore return(10); 2369*95c635efSGarrett D'Amore case(MDOC_Op): 2370*95c635efSGarrett D'Amore return(14); 2371*95c635efSGarrett D'Amore case(MDOC_Pa): 2372*95c635efSGarrett D'Amore return(32); 2373*95c635efSGarrett D'Amore case(MDOC_Pf): 2374*95c635efSGarrett D'Amore return(12); 2375*95c635efSGarrett D'Amore case(MDOC_Po): 2376*95c635efSGarrett D'Amore return(12); 2377*95c635efSGarrett D'Amore case(MDOC_Pq): 2378*95c635efSGarrett D'Amore return(12); 2379*95c635efSGarrett D'Amore case(MDOC_Ql): 2380*95c635efSGarrett D'Amore return(16); 2381*95c635efSGarrett D'Amore case(MDOC_Qo): 2382*95c635efSGarrett D'Amore return(12); 2383*95c635efSGarrett D'Amore case(MDOC_So): 2384*95c635efSGarrett D'Amore return(12); 2385*95c635efSGarrett D'Amore case(MDOC_Sq): 2386*95c635efSGarrett D'Amore return(12); 2387*95c635efSGarrett D'Amore case(MDOC_Sy): 2388*95c635efSGarrett D'Amore return(6); 2389*95c635efSGarrett D'Amore case(MDOC_Sx): 2390*95c635efSGarrett D'Amore return(16); 2391*95c635efSGarrett D'Amore case(MDOC_Tn): 2392*95c635efSGarrett D'Amore return(10); 2393*95c635efSGarrett D'Amore case(MDOC_Va): 2394*95c635efSGarrett D'Amore return(12); 2395*95c635efSGarrett D'Amore case(MDOC_Vt): 2396*95c635efSGarrett D'Amore return(12); 2397*95c635efSGarrett D'Amore case(MDOC_Xr): 2398*95c635efSGarrett D'Amore return(10); 2399*95c635efSGarrett D'Amore default: 2400*95c635efSGarrett D'Amore break; 2401*95c635efSGarrett D'Amore }; 2402*95c635efSGarrett D'Amore return(0); 2403*95c635efSGarrett D'Amore } 2404