1*61d06d6bSBaptiste Daroussin /* $Id: mdoc_state.c,v 1.9 2017/11/29 20:05:33 schwarze Exp $ */ 2*61d06d6bSBaptiste Daroussin /* 3*61d06d6bSBaptiste Daroussin * Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org> 4*61d06d6bSBaptiste Daroussin * 5*61d06d6bSBaptiste Daroussin * Permission to use, copy, modify, and distribute this software for any 6*61d06d6bSBaptiste Daroussin * purpose with or without fee is hereby granted, provided that the above 7*61d06d6bSBaptiste Daroussin * copyright notice and this permission notice appear in all copies. 8*61d06d6bSBaptiste Daroussin * 9*61d06d6bSBaptiste Daroussin * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10*61d06d6bSBaptiste Daroussin * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*61d06d6bSBaptiste Daroussin * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12*61d06d6bSBaptiste Daroussin * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*61d06d6bSBaptiste Daroussin * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*61d06d6bSBaptiste Daroussin * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15*61d06d6bSBaptiste Daroussin * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16*61d06d6bSBaptiste Daroussin */ 17*61d06d6bSBaptiste Daroussin #include <sys/types.h> 18*61d06d6bSBaptiste Daroussin 19*61d06d6bSBaptiste Daroussin #include <assert.h> 20*61d06d6bSBaptiste Daroussin #include <stdlib.h> 21*61d06d6bSBaptiste Daroussin #include <string.h> 22*61d06d6bSBaptiste Daroussin 23*61d06d6bSBaptiste Daroussin #include "mandoc.h" 24*61d06d6bSBaptiste Daroussin #include "roff.h" 25*61d06d6bSBaptiste Daroussin #include "mdoc.h" 26*61d06d6bSBaptiste Daroussin #include "libmandoc.h" 27*61d06d6bSBaptiste Daroussin #include "libmdoc.h" 28*61d06d6bSBaptiste Daroussin 29*61d06d6bSBaptiste Daroussin #define STATE_ARGS struct roff_man *mdoc, struct roff_node *n 30*61d06d6bSBaptiste Daroussin 31*61d06d6bSBaptiste Daroussin typedef void (*state_handler)(STATE_ARGS); 32*61d06d6bSBaptiste Daroussin 33*61d06d6bSBaptiste Daroussin static void state_bd(STATE_ARGS); 34*61d06d6bSBaptiste Daroussin static void state_bl(STATE_ARGS); 35*61d06d6bSBaptiste Daroussin static void state_dl(STATE_ARGS); 36*61d06d6bSBaptiste Daroussin static void state_sh(STATE_ARGS); 37*61d06d6bSBaptiste Daroussin static void state_sm(STATE_ARGS); 38*61d06d6bSBaptiste Daroussin 39*61d06d6bSBaptiste Daroussin static const state_handler __state_handlers[MDOC_MAX - MDOC_Dd] = { 40*61d06d6bSBaptiste Daroussin NULL, /* Dd */ 41*61d06d6bSBaptiste Daroussin NULL, /* Dt */ 42*61d06d6bSBaptiste Daroussin NULL, /* Os */ 43*61d06d6bSBaptiste Daroussin state_sh, /* Sh */ 44*61d06d6bSBaptiste Daroussin NULL, /* Ss */ 45*61d06d6bSBaptiste Daroussin NULL, /* Pp */ 46*61d06d6bSBaptiste Daroussin NULL, /* D1 */ 47*61d06d6bSBaptiste Daroussin state_dl, /* Dl */ 48*61d06d6bSBaptiste Daroussin state_bd, /* Bd */ 49*61d06d6bSBaptiste Daroussin NULL, /* Ed */ 50*61d06d6bSBaptiste Daroussin state_bl, /* Bl */ 51*61d06d6bSBaptiste Daroussin NULL, /* El */ 52*61d06d6bSBaptiste Daroussin NULL, /* It */ 53*61d06d6bSBaptiste Daroussin NULL, /* Ad */ 54*61d06d6bSBaptiste Daroussin NULL, /* An */ 55*61d06d6bSBaptiste Daroussin NULL, /* Ap */ 56*61d06d6bSBaptiste Daroussin NULL, /* Ar */ 57*61d06d6bSBaptiste Daroussin NULL, /* Cd */ 58*61d06d6bSBaptiste Daroussin NULL, /* Cm */ 59*61d06d6bSBaptiste Daroussin NULL, /* Dv */ 60*61d06d6bSBaptiste Daroussin NULL, /* Er */ 61*61d06d6bSBaptiste Daroussin NULL, /* Ev */ 62*61d06d6bSBaptiste Daroussin NULL, /* Ex */ 63*61d06d6bSBaptiste Daroussin NULL, /* Fa */ 64*61d06d6bSBaptiste Daroussin NULL, /* Fd */ 65*61d06d6bSBaptiste Daroussin NULL, /* Fl */ 66*61d06d6bSBaptiste Daroussin NULL, /* Fn */ 67*61d06d6bSBaptiste Daroussin NULL, /* Ft */ 68*61d06d6bSBaptiste Daroussin NULL, /* Ic */ 69*61d06d6bSBaptiste Daroussin NULL, /* In */ 70*61d06d6bSBaptiste Daroussin NULL, /* Li */ 71*61d06d6bSBaptiste Daroussin NULL, /* Nd */ 72*61d06d6bSBaptiste Daroussin NULL, /* Nm */ 73*61d06d6bSBaptiste Daroussin NULL, /* Op */ 74*61d06d6bSBaptiste Daroussin NULL, /* Ot */ 75*61d06d6bSBaptiste Daroussin NULL, /* Pa */ 76*61d06d6bSBaptiste Daroussin NULL, /* Rv */ 77*61d06d6bSBaptiste Daroussin NULL, /* St */ 78*61d06d6bSBaptiste Daroussin NULL, /* Va */ 79*61d06d6bSBaptiste Daroussin NULL, /* Vt */ 80*61d06d6bSBaptiste Daroussin NULL, /* Xr */ 81*61d06d6bSBaptiste Daroussin NULL, /* %A */ 82*61d06d6bSBaptiste Daroussin NULL, /* %B */ 83*61d06d6bSBaptiste Daroussin NULL, /* %D */ 84*61d06d6bSBaptiste Daroussin NULL, /* %I */ 85*61d06d6bSBaptiste Daroussin NULL, /* %J */ 86*61d06d6bSBaptiste Daroussin NULL, /* %N */ 87*61d06d6bSBaptiste Daroussin NULL, /* %O */ 88*61d06d6bSBaptiste Daroussin NULL, /* %P */ 89*61d06d6bSBaptiste Daroussin NULL, /* %R */ 90*61d06d6bSBaptiste Daroussin NULL, /* %T */ 91*61d06d6bSBaptiste Daroussin NULL, /* %V */ 92*61d06d6bSBaptiste Daroussin NULL, /* Ac */ 93*61d06d6bSBaptiste Daroussin NULL, /* Ao */ 94*61d06d6bSBaptiste Daroussin NULL, /* Aq */ 95*61d06d6bSBaptiste Daroussin NULL, /* At */ 96*61d06d6bSBaptiste Daroussin NULL, /* Bc */ 97*61d06d6bSBaptiste Daroussin NULL, /* Bf */ 98*61d06d6bSBaptiste Daroussin NULL, /* Bo */ 99*61d06d6bSBaptiste Daroussin NULL, /* Bq */ 100*61d06d6bSBaptiste Daroussin NULL, /* Bsx */ 101*61d06d6bSBaptiste Daroussin NULL, /* Bx */ 102*61d06d6bSBaptiste Daroussin NULL, /* Db */ 103*61d06d6bSBaptiste Daroussin NULL, /* Dc */ 104*61d06d6bSBaptiste Daroussin NULL, /* Do */ 105*61d06d6bSBaptiste Daroussin NULL, /* Dq */ 106*61d06d6bSBaptiste Daroussin NULL, /* Ec */ 107*61d06d6bSBaptiste Daroussin NULL, /* Ef */ 108*61d06d6bSBaptiste Daroussin NULL, /* Em */ 109*61d06d6bSBaptiste Daroussin NULL, /* Eo */ 110*61d06d6bSBaptiste Daroussin NULL, /* Fx */ 111*61d06d6bSBaptiste Daroussin NULL, /* Ms */ 112*61d06d6bSBaptiste Daroussin NULL, /* No */ 113*61d06d6bSBaptiste Daroussin NULL, /* Ns */ 114*61d06d6bSBaptiste Daroussin NULL, /* Nx */ 115*61d06d6bSBaptiste Daroussin NULL, /* Ox */ 116*61d06d6bSBaptiste Daroussin NULL, /* Pc */ 117*61d06d6bSBaptiste Daroussin NULL, /* Pf */ 118*61d06d6bSBaptiste Daroussin NULL, /* Po */ 119*61d06d6bSBaptiste Daroussin NULL, /* Pq */ 120*61d06d6bSBaptiste Daroussin NULL, /* Qc */ 121*61d06d6bSBaptiste Daroussin NULL, /* Ql */ 122*61d06d6bSBaptiste Daroussin NULL, /* Qo */ 123*61d06d6bSBaptiste Daroussin NULL, /* Qq */ 124*61d06d6bSBaptiste Daroussin NULL, /* Re */ 125*61d06d6bSBaptiste Daroussin NULL, /* Rs */ 126*61d06d6bSBaptiste Daroussin NULL, /* Sc */ 127*61d06d6bSBaptiste Daroussin NULL, /* So */ 128*61d06d6bSBaptiste Daroussin NULL, /* Sq */ 129*61d06d6bSBaptiste Daroussin state_sm, /* Sm */ 130*61d06d6bSBaptiste Daroussin NULL, /* Sx */ 131*61d06d6bSBaptiste Daroussin NULL, /* Sy */ 132*61d06d6bSBaptiste Daroussin NULL, /* Tn */ 133*61d06d6bSBaptiste Daroussin NULL, /* Ux */ 134*61d06d6bSBaptiste Daroussin NULL, /* Xc */ 135*61d06d6bSBaptiste Daroussin NULL, /* Xo */ 136*61d06d6bSBaptiste Daroussin NULL, /* Fo */ 137*61d06d6bSBaptiste Daroussin NULL, /* Fc */ 138*61d06d6bSBaptiste Daroussin NULL, /* Oo */ 139*61d06d6bSBaptiste Daroussin NULL, /* Oc */ 140*61d06d6bSBaptiste Daroussin NULL, /* Bk */ 141*61d06d6bSBaptiste Daroussin NULL, /* Ek */ 142*61d06d6bSBaptiste Daroussin NULL, /* Bt */ 143*61d06d6bSBaptiste Daroussin NULL, /* Hf */ 144*61d06d6bSBaptiste Daroussin NULL, /* Fr */ 145*61d06d6bSBaptiste Daroussin NULL, /* Ud */ 146*61d06d6bSBaptiste Daroussin NULL, /* Lb */ 147*61d06d6bSBaptiste Daroussin NULL, /* Lp */ 148*61d06d6bSBaptiste Daroussin NULL, /* Lk */ 149*61d06d6bSBaptiste Daroussin NULL, /* Mt */ 150*61d06d6bSBaptiste Daroussin NULL, /* Brq */ 151*61d06d6bSBaptiste Daroussin NULL, /* Bro */ 152*61d06d6bSBaptiste Daroussin NULL, /* Brc */ 153*61d06d6bSBaptiste Daroussin NULL, /* %C */ 154*61d06d6bSBaptiste Daroussin NULL, /* Es */ 155*61d06d6bSBaptiste Daroussin NULL, /* En */ 156*61d06d6bSBaptiste Daroussin NULL, /* Dx */ 157*61d06d6bSBaptiste Daroussin NULL, /* %Q */ 158*61d06d6bSBaptiste Daroussin NULL, /* %U */ 159*61d06d6bSBaptiste Daroussin NULL, /* Ta */ 160*61d06d6bSBaptiste Daroussin }; 161*61d06d6bSBaptiste Daroussin static const state_handler *const state_handlers = __state_handlers - MDOC_Dd; 162*61d06d6bSBaptiste Daroussin 163*61d06d6bSBaptiste Daroussin 164*61d06d6bSBaptiste Daroussin void 165*61d06d6bSBaptiste Daroussin mdoc_state(struct roff_man *mdoc, struct roff_node *n) 166*61d06d6bSBaptiste Daroussin { 167*61d06d6bSBaptiste Daroussin state_handler handler; 168*61d06d6bSBaptiste Daroussin 169*61d06d6bSBaptiste Daroussin if (n->tok == TOKEN_NONE || n->tok < ROFF_MAX) 170*61d06d6bSBaptiste Daroussin return; 171*61d06d6bSBaptiste Daroussin 172*61d06d6bSBaptiste Daroussin assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX); 173*61d06d6bSBaptiste Daroussin if ( ! (mdoc_macros[n->tok].flags & MDOC_PROLOGUE)) 174*61d06d6bSBaptiste Daroussin mdoc->flags |= MDOC_PBODY; 175*61d06d6bSBaptiste Daroussin 176*61d06d6bSBaptiste Daroussin handler = state_handlers[n->tok]; 177*61d06d6bSBaptiste Daroussin if (*handler) 178*61d06d6bSBaptiste Daroussin (*handler)(mdoc, n); 179*61d06d6bSBaptiste Daroussin } 180*61d06d6bSBaptiste Daroussin 181*61d06d6bSBaptiste Daroussin void 182*61d06d6bSBaptiste Daroussin mdoc_state_reset(struct roff_man *mdoc) 183*61d06d6bSBaptiste Daroussin { 184*61d06d6bSBaptiste Daroussin 185*61d06d6bSBaptiste Daroussin roff_setreg(mdoc->roff, "nS", 0, '='); 186*61d06d6bSBaptiste Daroussin mdoc->flags = 0; 187*61d06d6bSBaptiste Daroussin } 188*61d06d6bSBaptiste Daroussin 189*61d06d6bSBaptiste Daroussin static void 190*61d06d6bSBaptiste Daroussin state_bd(STATE_ARGS) 191*61d06d6bSBaptiste Daroussin { 192*61d06d6bSBaptiste Daroussin enum mdocargt arg; 193*61d06d6bSBaptiste Daroussin 194*61d06d6bSBaptiste Daroussin if (n->type != ROFFT_HEAD && 195*61d06d6bSBaptiste Daroussin (n->type != ROFFT_BODY || n->end != ENDBODY_NOT)) 196*61d06d6bSBaptiste Daroussin return; 197*61d06d6bSBaptiste Daroussin 198*61d06d6bSBaptiste Daroussin if (n->parent->args == NULL) 199*61d06d6bSBaptiste Daroussin return; 200*61d06d6bSBaptiste Daroussin 201*61d06d6bSBaptiste Daroussin arg = n->parent->args->argv[0].arg; 202*61d06d6bSBaptiste Daroussin if (arg != MDOC_Literal && arg != MDOC_Unfilled) 203*61d06d6bSBaptiste Daroussin return; 204*61d06d6bSBaptiste Daroussin 205*61d06d6bSBaptiste Daroussin state_dl(mdoc, n); 206*61d06d6bSBaptiste Daroussin } 207*61d06d6bSBaptiste Daroussin 208*61d06d6bSBaptiste Daroussin static void 209*61d06d6bSBaptiste Daroussin state_bl(STATE_ARGS) 210*61d06d6bSBaptiste Daroussin { 211*61d06d6bSBaptiste Daroussin struct mdoc_arg *args; 212*61d06d6bSBaptiste Daroussin size_t i; 213*61d06d6bSBaptiste Daroussin 214*61d06d6bSBaptiste Daroussin if (n->type != ROFFT_HEAD || n->parent->args == NULL) 215*61d06d6bSBaptiste Daroussin return; 216*61d06d6bSBaptiste Daroussin 217*61d06d6bSBaptiste Daroussin args = n->parent->args; 218*61d06d6bSBaptiste Daroussin for (i = 0; i < args->argc; i++) { 219*61d06d6bSBaptiste Daroussin switch(args->argv[i].arg) { 220*61d06d6bSBaptiste Daroussin case MDOC_Diag: 221*61d06d6bSBaptiste Daroussin n->norm->Bl.type = LIST_diag; 222*61d06d6bSBaptiste Daroussin return; 223*61d06d6bSBaptiste Daroussin case MDOC_Column: 224*61d06d6bSBaptiste Daroussin n->norm->Bl.type = LIST_column; 225*61d06d6bSBaptiste Daroussin return; 226*61d06d6bSBaptiste Daroussin default: 227*61d06d6bSBaptiste Daroussin break; 228*61d06d6bSBaptiste Daroussin } 229*61d06d6bSBaptiste Daroussin } 230*61d06d6bSBaptiste Daroussin } 231*61d06d6bSBaptiste Daroussin 232*61d06d6bSBaptiste Daroussin static void 233*61d06d6bSBaptiste Daroussin state_dl(STATE_ARGS) 234*61d06d6bSBaptiste Daroussin { 235*61d06d6bSBaptiste Daroussin 236*61d06d6bSBaptiste Daroussin switch (n->type) { 237*61d06d6bSBaptiste Daroussin case ROFFT_HEAD: 238*61d06d6bSBaptiste Daroussin mdoc->flags |= MDOC_LITERAL; 239*61d06d6bSBaptiste Daroussin break; 240*61d06d6bSBaptiste Daroussin case ROFFT_BODY: 241*61d06d6bSBaptiste Daroussin mdoc->flags &= ~MDOC_LITERAL; 242*61d06d6bSBaptiste Daroussin break; 243*61d06d6bSBaptiste Daroussin default: 244*61d06d6bSBaptiste Daroussin break; 245*61d06d6bSBaptiste Daroussin } 246*61d06d6bSBaptiste Daroussin } 247*61d06d6bSBaptiste Daroussin 248*61d06d6bSBaptiste Daroussin static void 249*61d06d6bSBaptiste Daroussin state_sh(STATE_ARGS) 250*61d06d6bSBaptiste Daroussin { 251*61d06d6bSBaptiste Daroussin struct roff_node *nch; 252*61d06d6bSBaptiste Daroussin char *secname; 253*61d06d6bSBaptiste Daroussin 254*61d06d6bSBaptiste Daroussin if (n->type != ROFFT_HEAD) 255*61d06d6bSBaptiste Daroussin return; 256*61d06d6bSBaptiste Daroussin 257*61d06d6bSBaptiste Daroussin if ( ! (n->flags & NODE_VALID)) { 258*61d06d6bSBaptiste Daroussin secname = NULL; 259*61d06d6bSBaptiste Daroussin deroff(&secname, n); 260*61d06d6bSBaptiste Daroussin 261*61d06d6bSBaptiste Daroussin /* 262*61d06d6bSBaptiste Daroussin * Set the section attribute for the BLOCK, HEAD, 263*61d06d6bSBaptiste Daroussin * and HEAD children; the latter can only be TEXT 264*61d06d6bSBaptiste Daroussin * nodes, so no recursion is needed. For other 265*61d06d6bSBaptiste Daroussin * nodes, including the .Sh BODY, this is done 266*61d06d6bSBaptiste Daroussin * when allocating the node data structures, but 267*61d06d6bSBaptiste Daroussin * for .Sh BLOCK and HEAD, the section is still 268*61d06d6bSBaptiste Daroussin * unknown at that time. 269*61d06d6bSBaptiste Daroussin */ 270*61d06d6bSBaptiste Daroussin 271*61d06d6bSBaptiste Daroussin n->sec = n->parent->sec = secname == NULL ? 272*61d06d6bSBaptiste Daroussin SEC_CUSTOM : mdoc_a2sec(secname); 273*61d06d6bSBaptiste Daroussin for (nch = n->child; nch != NULL; nch = nch->next) 274*61d06d6bSBaptiste Daroussin nch->sec = n->sec; 275*61d06d6bSBaptiste Daroussin free(secname); 276*61d06d6bSBaptiste Daroussin } 277*61d06d6bSBaptiste Daroussin 278*61d06d6bSBaptiste Daroussin if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) { 279*61d06d6bSBaptiste Daroussin roff_setreg(mdoc->roff, "nS", 1, '='); 280*61d06d6bSBaptiste Daroussin mdoc->flags |= MDOC_SYNOPSIS; 281*61d06d6bSBaptiste Daroussin } else { 282*61d06d6bSBaptiste Daroussin roff_setreg(mdoc->roff, "nS", 0, '='); 283*61d06d6bSBaptiste Daroussin mdoc->flags &= ~MDOC_SYNOPSIS; 284*61d06d6bSBaptiste Daroussin } 285*61d06d6bSBaptiste Daroussin } 286*61d06d6bSBaptiste Daroussin 287*61d06d6bSBaptiste Daroussin static void 288*61d06d6bSBaptiste Daroussin state_sm(STATE_ARGS) 289*61d06d6bSBaptiste Daroussin { 290*61d06d6bSBaptiste Daroussin 291*61d06d6bSBaptiste Daroussin if (n->child == NULL) 292*61d06d6bSBaptiste Daroussin mdoc->flags ^= MDOC_SMOFF; 293*61d06d6bSBaptiste Daroussin else if ( ! strcmp(n->child->string, "on")) 294*61d06d6bSBaptiste Daroussin mdoc->flags &= ~MDOC_SMOFF; 295*61d06d6bSBaptiste Daroussin else if ( ! strcmp(n->child->string, "off")) 296*61d06d6bSBaptiste Daroussin mdoc->flags |= MDOC_SMOFF; 297*61d06d6bSBaptiste Daroussin } 298