1*6d38604fSBaptiste Daroussin /* $Id: mdoc_state.c,v 1.17 2020/06/22 19:20:40 schwarze Exp $ */ 261d06d6bSBaptiste Daroussin /* 361d06d6bSBaptiste Daroussin * Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org> 461d06d6bSBaptiste Daroussin * 561d06d6bSBaptiste Daroussin * Permission to use, copy, modify, and distribute this software for any 661d06d6bSBaptiste Daroussin * purpose with or without fee is hereby granted, provided that the above 761d06d6bSBaptiste Daroussin * copyright notice and this permission notice appear in all copies. 861d06d6bSBaptiste Daroussin * 961d06d6bSBaptiste Daroussin * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1061d06d6bSBaptiste Daroussin * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1161d06d6bSBaptiste Daroussin * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1261d06d6bSBaptiste Daroussin * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1361d06d6bSBaptiste Daroussin * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1461d06d6bSBaptiste Daroussin * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1561d06d6bSBaptiste Daroussin * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1661d06d6bSBaptiste Daroussin */ 17*6d38604fSBaptiste Daroussin #include "config.h" 18*6d38604fSBaptiste Daroussin 1961d06d6bSBaptiste Daroussin #include <sys/types.h> 2061d06d6bSBaptiste Daroussin 2161d06d6bSBaptiste Daroussin #include <assert.h> 227295610fSBaptiste Daroussin #include <stdio.h> 2361d06d6bSBaptiste Daroussin #include <stdlib.h> 2461d06d6bSBaptiste Daroussin #include <string.h> 2561d06d6bSBaptiste Daroussin 2661d06d6bSBaptiste Daroussin #include "mandoc.h" 2761d06d6bSBaptiste Daroussin #include "roff.h" 2861d06d6bSBaptiste Daroussin #include "mdoc.h" 2961d06d6bSBaptiste Daroussin #include "libmandoc.h" 307295610fSBaptiste Daroussin #include "roff_int.h" 3161d06d6bSBaptiste Daroussin #include "libmdoc.h" 3261d06d6bSBaptiste Daroussin 3361d06d6bSBaptiste Daroussin #define STATE_ARGS struct roff_man *mdoc, struct roff_node *n 3461d06d6bSBaptiste Daroussin 3561d06d6bSBaptiste Daroussin typedef void (*state_handler)(STATE_ARGS); 3661d06d6bSBaptiste Daroussin 3761d06d6bSBaptiste Daroussin static void state_bl(STATE_ARGS); 3861d06d6bSBaptiste Daroussin static void state_sh(STATE_ARGS); 3961d06d6bSBaptiste Daroussin static void state_sm(STATE_ARGS); 4061d06d6bSBaptiste Daroussin 417295610fSBaptiste Daroussin static const state_handler state_handlers[MDOC_MAX - MDOC_Dd] = { 4261d06d6bSBaptiste Daroussin NULL, /* Dd */ 4361d06d6bSBaptiste Daroussin NULL, /* Dt */ 4461d06d6bSBaptiste Daroussin NULL, /* Os */ 4561d06d6bSBaptiste Daroussin state_sh, /* Sh */ 4661d06d6bSBaptiste Daroussin NULL, /* Ss */ 4761d06d6bSBaptiste Daroussin NULL, /* Pp */ 4861d06d6bSBaptiste Daroussin NULL, /* D1 */ 497295610fSBaptiste Daroussin NULL, /* Dl */ 507295610fSBaptiste Daroussin NULL, /* Bd */ 5161d06d6bSBaptiste Daroussin NULL, /* Ed */ 5261d06d6bSBaptiste Daroussin state_bl, /* Bl */ 5361d06d6bSBaptiste Daroussin NULL, /* El */ 5461d06d6bSBaptiste Daroussin NULL, /* It */ 5561d06d6bSBaptiste Daroussin NULL, /* Ad */ 5661d06d6bSBaptiste Daroussin NULL, /* An */ 5761d06d6bSBaptiste Daroussin NULL, /* Ap */ 5861d06d6bSBaptiste Daroussin NULL, /* Ar */ 5961d06d6bSBaptiste Daroussin NULL, /* Cd */ 6061d06d6bSBaptiste Daroussin NULL, /* Cm */ 6161d06d6bSBaptiste Daroussin NULL, /* Dv */ 6261d06d6bSBaptiste Daroussin NULL, /* Er */ 6361d06d6bSBaptiste Daroussin NULL, /* Ev */ 6461d06d6bSBaptiste Daroussin NULL, /* Ex */ 6561d06d6bSBaptiste Daroussin NULL, /* Fa */ 6661d06d6bSBaptiste Daroussin NULL, /* Fd */ 6761d06d6bSBaptiste Daroussin NULL, /* Fl */ 6861d06d6bSBaptiste Daroussin NULL, /* Fn */ 6961d06d6bSBaptiste Daroussin NULL, /* Ft */ 7061d06d6bSBaptiste Daroussin NULL, /* Ic */ 7161d06d6bSBaptiste Daroussin NULL, /* In */ 7261d06d6bSBaptiste Daroussin NULL, /* Li */ 7361d06d6bSBaptiste Daroussin NULL, /* Nd */ 7461d06d6bSBaptiste Daroussin NULL, /* Nm */ 7561d06d6bSBaptiste Daroussin NULL, /* Op */ 7661d06d6bSBaptiste Daroussin NULL, /* Ot */ 7761d06d6bSBaptiste Daroussin NULL, /* Pa */ 7861d06d6bSBaptiste Daroussin NULL, /* Rv */ 7961d06d6bSBaptiste Daroussin NULL, /* St */ 8061d06d6bSBaptiste Daroussin NULL, /* Va */ 8161d06d6bSBaptiste Daroussin NULL, /* Vt */ 8261d06d6bSBaptiste Daroussin NULL, /* Xr */ 8361d06d6bSBaptiste Daroussin NULL, /* %A */ 8461d06d6bSBaptiste Daroussin NULL, /* %B */ 8561d06d6bSBaptiste Daroussin NULL, /* %D */ 8661d06d6bSBaptiste Daroussin NULL, /* %I */ 8761d06d6bSBaptiste Daroussin NULL, /* %J */ 8861d06d6bSBaptiste Daroussin NULL, /* %N */ 8961d06d6bSBaptiste Daroussin NULL, /* %O */ 9061d06d6bSBaptiste Daroussin NULL, /* %P */ 9161d06d6bSBaptiste Daroussin NULL, /* %R */ 9261d06d6bSBaptiste Daroussin NULL, /* %T */ 9361d06d6bSBaptiste Daroussin NULL, /* %V */ 9461d06d6bSBaptiste Daroussin NULL, /* Ac */ 9561d06d6bSBaptiste Daroussin NULL, /* Ao */ 9661d06d6bSBaptiste Daroussin NULL, /* Aq */ 9761d06d6bSBaptiste Daroussin NULL, /* At */ 9861d06d6bSBaptiste Daroussin NULL, /* Bc */ 9961d06d6bSBaptiste Daroussin NULL, /* Bf */ 10061d06d6bSBaptiste Daroussin NULL, /* Bo */ 10161d06d6bSBaptiste Daroussin NULL, /* Bq */ 10261d06d6bSBaptiste Daroussin NULL, /* Bsx */ 10361d06d6bSBaptiste Daroussin NULL, /* Bx */ 10461d06d6bSBaptiste Daroussin NULL, /* Db */ 10561d06d6bSBaptiste Daroussin NULL, /* Dc */ 10661d06d6bSBaptiste Daroussin NULL, /* Do */ 10761d06d6bSBaptiste Daroussin NULL, /* Dq */ 10861d06d6bSBaptiste Daroussin NULL, /* Ec */ 10961d06d6bSBaptiste Daroussin NULL, /* Ef */ 11061d06d6bSBaptiste Daroussin NULL, /* Em */ 11161d06d6bSBaptiste Daroussin NULL, /* Eo */ 11261d06d6bSBaptiste Daroussin NULL, /* Fx */ 11361d06d6bSBaptiste Daroussin NULL, /* Ms */ 11461d06d6bSBaptiste Daroussin NULL, /* No */ 11561d06d6bSBaptiste Daroussin NULL, /* Ns */ 11661d06d6bSBaptiste Daroussin NULL, /* Nx */ 11761d06d6bSBaptiste Daroussin NULL, /* Ox */ 11861d06d6bSBaptiste Daroussin NULL, /* Pc */ 11961d06d6bSBaptiste Daroussin NULL, /* Pf */ 12061d06d6bSBaptiste Daroussin NULL, /* Po */ 12161d06d6bSBaptiste Daroussin NULL, /* Pq */ 12261d06d6bSBaptiste Daroussin NULL, /* Qc */ 12361d06d6bSBaptiste Daroussin NULL, /* Ql */ 12461d06d6bSBaptiste Daroussin NULL, /* Qo */ 12561d06d6bSBaptiste Daroussin NULL, /* Qq */ 12661d06d6bSBaptiste Daroussin NULL, /* Re */ 12761d06d6bSBaptiste Daroussin NULL, /* Rs */ 12861d06d6bSBaptiste Daroussin NULL, /* Sc */ 12961d06d6bSBaptiste Daroussin NULL, /* So */ 13061d06d6bSBaptiste Daroussin NULL, /* Sq */ 13161d06d6bSBaptiste Daroussin state_sm, /* Sm */ 13261d06d6bSBaptiste Daroussin NULL, /* Sx */ 13361d06d6bSBaptiste Daroussin NULL, /* Sy */ 13461d06d6bSBaptiste Daroussin NULL, /* Tn */ 13561d06d6bSBaptiste Daroussin NULL, /* Ux */ 13661d06d6bSBaptiste Daroussin NULL, /* Xc */ 13761d06d6bSBaptiste Daroussin NULL, /* Xo */ 13861d06d6bSBaptiste Daroussin NULL, /* Fo */ 13961d06d6bSBaptiste Daroussin NULL, /* Fc */ 14061d06d6bSBaptiste Daroussin NULL, /* Oo */ 14161d06d6bSBaptiste Daroussin NULL, /* Oc */ 14261d06d6bSBaptiste Daroussin NULL, /* Bk */ 14361d06d6bSBaptiste Daroussin NULL, /* Ek */ 14461d06d6bSBaptiste Daroussin NULL, /* Bt */ 14561d06d6bSBaptiste Daroussin NULL, /* Hf */ 14661d06d6bSBaptiste Daroussin NULL, /* Fr */ 14761d06d6bSBaptiste Daroussin NULL, /* Ud */ 14861d06d6bSBaptiste Daroussin NULL, /* Lb */ 14961d06d6bSBaptiste Daroussin NULL, /* Lp */ 15061d06d6bSBaptiste Daroussin NULL, /* Lk */ 15161d06d6bSBaptiste Daroussin NULL, /* Mt */ 15261d06d6bSBaptiste Daroussin NULL, /* Brq */ 15361d06d6bSBaptiste Daroussin NULL, /* Bro */ 15461d06d6bSBaptiste Daroussin NULL, /* Brc */ 15561d06d6bSBaptiste Daroussin NULL, /* %C */ 15661d06d6bSBaptiste Daroussin NULL, /* Es */ 15761d06d6bSBaptiste Daroussin NULL, /* En */ 15861d06d6bSBaptiste Daroussin NULL, /* Dx */ 15961d06d6bSBaptiste Daroussin NULL, /* %Q */ 16061d06d6bSBaptiste Daroussin NULL, /* %U */ 16161d06d6bSBaptiste Daroussin NULL, /* Ta */ 162*6d38604fSBaptiste Daroussin NULL, /* Tg */ 16361d06d6bSBaptiste Daroussin }; 16461d06d6bSBaptiste Daroussin 16561d06d6bSBaptiste Daroussin 16661d06d6bSBaptiste Daroussin void 16761d06d6bSBaptiste Daroussin mdoc_state(struct roff_man *mdoc, struct roff_node *n) 16861d06d6bSBaptiste Daroussin { 16961d06d6bSBaptiste Daroussin state_handler handler; 17061d06d6bSBaptiste Daroussin 17161d06d6bSBaptiste Daroussin if (n->tok == TOKEN_NONE || n->tok < ROFF_MAX) 17261d06d6bSBaptiste Daroussin return; 17361d06d6bSBaptiste Daroussin 17461d06d6bSBaptiste Daroussin assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX); 1757295610fSBaptiste Daroussin if ((mdoc_macro(n->tok)->flags & MDOC_PROLOGUE) == 0) 17661d06d6bSBaptiste Daroussin mdoc->flags |= MDOC_PBODY; 17761d06d6bSBaptiste Daroussin 1787295610fSBaptiste Daroussin handler = state_handlers[n->tok - MDOC_Dd]; 17961d06d6bSBaptiste Daroussin if (*handler) 18061d06d6bSBaptiste Daroussin (*handler)(mdoc, n); 18161d06d6bSBaptiste Daroussin } 18261d06d6bSBaptiste Daroussin 18361d06d6bSBaptiste Daroussin static void 18461d06d6bSBaptiste Daroussin state_bl(STATE_ARGS) 18561d06d6bSBaptiste Daroussin { 18661d06d6bSBaptiste Daroussin struct mdoc_arg *args; 18761d06d6bSBaptiste Daroussin size_t i; 18861d06d6bSBaptiste Daroussin 18961d06d6bSBaptiste Daroussin if (n->type != ROFFT_HEAD || n->parent->args == NULL) 19061d06d6bSBaptiste Daroussin return; 19161d06d6bSBaptiste Daroussin 19261d06d6bSBaptiste Daroussin args = n->parent->args; 19361d06d6bSBaptiste Daroussin for (i = 0; i < args->argc; i++) { 19461d06d6bSBaptiste Daroussin switch(args->argv[i].arg) { 19561d06d6bSBaptiste Daroussin case MDOC_Diag: 19661d06d6bSBaptiste Daroussin n->norm->Bl.type = LIST_diag; 19761d06d6bSBaptiste Daroussin return; 19861d06d6bSBaptiste Daroussin case MDOC_Column: 19961d06d6bSBaptiste Daroussin n->norm->Bl.type = LIST_column; 20061d06d6bSBaptiste Daroussin return; 20161d06d6bSBaptiste Daroussin default: 20261d06d6bSBaptiste Daroussin break; 20361d06d6bSBaptiste Daroussin } 20461d06d6bSBaptiste Daroussin } 20561d06d6bSBaptiste Daroussin } 20661d06d6bSBaptiste Daroussin 20761d06d6bSBaptiste Daroussin static void 20861d06d6bSBaptiste Daroussin state_sh(STATE_ARGS) 20961d06d6bSBaptiste Daroussin { 21061d06d6bSBaptiste Daroussin struct roff_node *nch; 21161d06d6bSBaptiste Daroussin char *secname; 21261d06d6bSBaptiste Daroussin 21361d06d6bSBaptiste Daroussin if (n->type != ROFFT_HEAD) 21461d06d6bSBaptiste Daroussin return; 21561d06d6bSBaptiste Daroussin 21661d06d6bSBaptiste Daroussin if ( ! (n->flags & NODE_VALID)) { 21761d06d6bSBaptiste Daroussin secname = NULL; 21861d06d6bSBaptiste Daroussin deroff(&secname, n); 21961d06d6bSBaptiste Daroussin 22061d06d6bSBaptiste Daroussin /* 22161d06d6bSBaptiste Daroussin * Set the section attribute for the BLOCK, HEAD, 22261d06d6bSBaptiste Daroussin * and HEAD children; the latter can only be TEXT 22361d06d6bSBaptiste Daroussin * nodes, so no recursion is needed. For other 22461d06d6bSBaptiste Daroussin * nodes, including the .Sh BODY, this is done 22561d06d6bSBaptiste Daroussin * when allocating the node data structures, but 22661d06d6bSBaptiste Daroussin * for .Sh BLOCK and HEAD, the section is still 22761d06d6bSBaptiste Daroussin * unknown at that time. 22861d06d6bSBaptiste Daroussin */ 22961d06d6bSBaptiste Daroussin 23061d06d6bSBaptiste Daroussin n->sec = n->parent->sec = secname == NULL ? 23161d06d6bSBaptiste Daroussin SEC_CUSTOM : mdoc_a2sec(secname); 23261d06d6bSBaptiste Daroussin for (nch = n->child; nch != NULL; nch = nch->next) 23361d06d6bSBaptiste Daroussin nch->sec = n->sec; 23461d06d6bSBaptiste Daroussin free(secname); 23561d06d6bSBaptiste Daroussin } 23661d06d6bSBaptiste Daroussin 23761d06d6bSBaptiste Daroussin if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) { 23861d06d6bSBaptiste Daroussin roff_setreg(mdoc->roff, "nS", 1, '='); 23961d06d6bSBaptiste Daroussin mdoc->flags |= MDOC_SYNOPSIS; 24061d06d6bSBaptiste Daroussin } else { 24161d06d6bSBaptiste Daroussin roff_setreg(mdoc->roff, "nS", 0, '='); 24261d06d6bSBaptiste Daroussin mdoc->flags &= ~MDOC_SYNOPSIS; 24361d06d6bSBaptiste Daroussin } 24461d06d6bSBaptiste Daroussin } 24561d06d6bSBaptiste Daroussin 24661d06d6bSBaptiste Daroussin static void 24761d06d6bSBaptiste Daroussin state_sm(STATE_ARGS) 24861d06d6bSBaptiste Daroussin { 24961d06d6bSBaptiste Daroussin 25061d06d6bSBaptiste Daroussin if (n->child == NULL) 25161d06d6bSBaptiste Daroussin mdoc->flags ^= MDOC_SMOFF; 25261d06d6bSBaptiste Daroussin else if ( ! strcmp(n->child->string, "on")) 25361d06d6bSBaptiste Daroussin mdoc->flags &= ~MDOC_SMOFF; 25461d06d6bSBaptiste Daroussin else if ( ! strcmp(n->child->string, "off")) 25561d06d6bSBaptiste Daroussin mdoc->flags |= MDOC_SMOFF; 25661d06d6bSBaptiste Daroussin } 257