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