1*95c635efSGarrett D'Amore /* $Id: man.c,v 1.115 2012/01/03 15:16:24 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 * 5*95c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any 6*95c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above 7*95c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies. 8*95c635efSGarrett D'Amore * 9*95c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10*95c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*95c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12*95c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*95c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*95c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15*95c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16*95c635efSGarrett D'Amore */ 17*95c635efSGarrett D'Amore #ifdef HAVE_CONFIG_H 18*95c635efSGarrett D'Amore #include "config.h" 19*95c635efSGarrett D'Amore #endif 20*95c635efSGarrett D'Amore 21*95c635efSGarrett D'Amore #include <sys/types.h> 22*95c635efSGarrett D'Amore 23*95c635efSGarrett D'Amore #include <assert.h> 24*95c635efSGarrett D'Amore #include <stdarg.h> 25*95c635efSGarrett D'Amore #include <stdlib.h> 26*95c635efSGarrett D'Amore #include <stdio.h> 27*95c635efSGarrett D'Amore #include <string.h> 28*95c635efSGarrett D'Amore 29*95c635efSGarrett D'Amore #include "man.h" 30*95c635efSGarrett D'Amore #include "mandoc.h" 31*95c635efSGarrett D'Amore #include "libman.h" 32*95c635efSGarrett D'Amore #include "libmandoc.h" 33*95c635efSGarrett D'Amore 34*95c635efSGarrett D'Amore const char *const __man_macronames[MAN_MAX] = { 35*95c635efSGarrett D'Amore "br", "TH", "SH", "SS", 36*95c635efSGarrett D'Amore "TP", "LP", "PP", "P", 37*95c635efSGarrett D'Amore "IP", "HP", "SM", "SB", 38*95c635efSGarrett D'Amore "BI", "IB", "BR", "RB", 39*95c635efSGarrett D'Amore "R", "B", "I", "IR", 40*95c635efSGarrett D'Amore "RI", "na", "sp", "nf", 41*95c635efSGarrett D'Amore "fi", "RE", "RS", "DT", 42*95c635efSGarrett D'Amore "UC", "PD", "AT", "in", 43*95c635efSGarrett D'Amore "ft", "OP" 44*95c635efSGarrett D'Amore }; 45*95c635efSGarrett D'Amore 46*95c635efSGarrett D'Amore const char * const *man_macronames = __man_macronames; 47*95c635efSGarrett D'Amore 48*95c635efSGarrett D'Amore static struct man_node *man_node_alloc(struct man *, int, int, 49*95c635efSGarrett D'Amore enum man_type, enum mant); 50*95c635efSGarrett D'Amore static int man_node_append(struct man *, 51*95c635efSGarrett D'Amore struct man_node *); 52*95c635efSGarrett D'Amore static void man_node_free(struct man_node *); 53*95c635efSGarrett D'Amore static void man_node_unlink(struct man *, 54*95c635efSGarrett D'Amore struct man_node *); 55*95c635efSGarrett D'Amore static int man_ptext(struct man *, int, char *, int); 56*95c635efSGarrett D'Amore static int man_pmacro(struct man *, int, char *, int); 57*95c635efSGarrett D'Amore static void man_free1(struct man *); 58*95c635efSGarrett D'Amore static void man_alloc1(struct man *); 59*95c635efSGarrett D'Amore static int man_descope(struct man *, int, int); 60*95c635efSGarrett D'Amore 61*95c635efSGarrett D'Amore 62*95c635efSGarrett D'Amore const struct man_node * 63*95c635efSGarrett D'Amore man_node(const struct man *m) 64*95c635efSGarrett D'Amore { 65*95c635efSGarrett D'Amore 66*95c635efSGarrett D'Amore assert( ! (MAN_HALT & m->flags)); 67*95c635efSGarrett D'Amore return(m->first); 68*95c635efSGarrett D'Amore } 69*95c635efSGarrett D'Amore 70*95c635efSGarrett D'Amore 71*95c635efSGarrett D'Amore const struct man_meta * 72*95c635efSGarrett D'Amore man_meta(const struct man *m) 73*95c635efSGarrett D'Amore { 74*95c635efSGarrett D'Amore 75*95c635efSGarrett D'Amore assert( ! (MAN_HALT & m->flags)); 76*95c635efSGarrett D'Amore return(&m->meta); 77*95c635efSGarrett D'Amore } 78*95c635efSGarrett D'Amore 79*95c635efSGarrett D'Amore 80*95c635efSGarrett D'Amore void 81*95c635efSGarrett D'Amore man_reset(struct man *man) 82*95c635efSGarrett D'Amore { 83*95c635efSGarrett D'Amore 84*95c635efSGarrett D'Amore man_free1(man); 85*95c635efSGarrett D'Amore man_alloc1(man); 86*95c635efSGarrett D'Amore } 87*95c635efSGarrett D'Amore 88*95c635efSGarrett D'Amore 89*95c635efSGarrett D'Amore void 90*95c635efSGarrett D'Amore man_free(struct man *man) 91*95c635efSGarrett D'Amore { 92*95c635efSGarrett D'Amore 93*95c635efSGarrett D'Amore man_free1(man); 94*95c635efSGarrett D'Amore free(man); 95*95c635efSGarrett D'Amore } 96*95c635efSGarrett D'Amore 97*95c635efSGarrett D'Amore 98*95c635efSGarrett D'Amore struct man * 99*95c635efSGarrett D'Amore man_alloc(struct roff *roff, struct mparse *parse) 100*95c635efSGarrett D'Amore { 101*95c635efSGarrett D'Amore struct man *p; 102*95c635efSGarrett D'Amore 103*95c635efSGarrett D'Amore p = mandoc_calloc(1, sizeof(struct man)); 104*95c635efSGarrett D'Amore 105*95c635efSGarrett D'Amore man_hash_init(); 106*95c635efSGarrett D'Amore p->parse = parse; 107*95c635efSGarrett D'Amore p->roff = roff; 108*95c635efSGarrett D'Amore 109*95c635efSGarrett D'Amore man_alloc1(p); 110*95c635efSGarrett D'Amore return(p); 111*95c635efSGarrett D'Amore } 112*95c635efSGarrett D'Amore 113*95c635efSGarrett D'Amore 114*95c635efSGarrett D'Amore int 115*95c635efSGarrett D'Amore man_endparse(struct man *m) 116*95c635efSGarrett D'Amore { 117*95c635efSGarrett D'Amore 118*95c635efSGarrett D'Amore assert( ! (MAN_HALT & m->flags)); 119*95c635efSGarrett D'Amore if (man_macroend(m)) 120*95c635efSGarrett D'Amore return(1); 121*95c635efSGarrett D'Amore m->flags |= MAN_HALT; 122*95c635efSGarrett D'Amore return(0); 123*95c635efSGarrett D'Amore } 124*95c635efSGarrett D'Amore 125*95c635efSGarrett D'Amore 126*95c635efSGarrett D'Amore int 127*95c635efSGarrett D'Amore man_parseln(struct man *m, int ln, char *buf, int offs) 128*95c635efSGarrett D'Amore { 129*95c635efSGarrett D'Amore 130*95c635efSGarrett D'Amore m->flags |= MAN_NEWLINE; 131*95c635efSGarrett D'Amore 132*95c635efSGarrett D'Amore assert( ! (MAN_HALT & m->flags)); 133*95c635efSGarrett D'Amore 134*95c635efSGarrett D'Amore return (mandoc_getcontrol(buf, &offs) ? 135*95c635efSGarrett D'Amore man_pmacro(m, ln, buf, offs) : 136*95c635efSGarrett D'Amore man_ptext(m, ln, buf, offs)); 137*95c635efSGarrett D'Amore } 138*95c635efSGarrett D'Amore 139*95c635efSGarrett D'Amore 140*95c635efSGarrett D'Amore static void 141*95c635efSGarrett D'Amore man_free1(struct man *man) 142*95c635efSGarrett D'Amore { 143*95c635efSGarrett D'Amore 144*95c635efSGarrett D'Amore if (man->first) 145*95c635efSGarrett D'Amore man_node_delete(man, man->first); 146*95c635efSGarrett D'Amore if (man->meta.title) 147*95c635efSGarrett D'Amore free(man->meta.title); 148*95c635efSGarrett D'Amore if (man->meta.source) 149*95c635efSGarrett D'Amore free(man->meta.source); 150*95c635efSGarrett D'Amore if (man->meta.date) 151*95c635efSGarrett D'Amore free(man->meta.date); 152*95c635efSGarrett D'Amore if (man->meta.vol) 153*95c635efSGarrett D'Amore free(man->meta.vol); 154*95c635efSGarrett D'Amore if (man->meta.msec) 155*95c635efSGarrett D'Amore free(man->meta.msec); 156*95c635efSGarrett D'Amore } 157*95c635efSGarrett D'Amore 158*95c635efSGarrett D'Amore 159*95c635efSGarrett D'Amore static void 160*95c635efSGarrett D'Amore man_alloc1(struct man *m) 161*95c635efSGarrett D'Amore { 162*95c635efSGarrett D'Amore 163*95c635efSGarrett D'Amore memset(&m->meta, 0, sizeof(struct man_meta)); 164*95c635efSGarrett D'Amore m->flags = 0; 165*95c635efSGarrett D'Amore m->last = mandoc_calloc(1, sizeof(struct man_node)); 166*95c635efSGarrett D'Amore m->first = m->last; 167*95c635efSGarrett D'Amore m->last->type = MAN_ROOT; 168*95c635efSGarrett D'Amore m->last->tok = MAN_MAX; 169*95c635efSGarrett D'Amore m->next = MAN_NEXT_CHILD; 170*95c635efSGarrett D'Amore } 171*95c635efSGarrett D'Amore 172*95c635efSGarrett D'Amore 173*95c635efSGarrett D'Amore static int 174*95c635efSGarrett D'Amore man_node_append(struct man *man, struct man_node *p) 175*95c635efSGarrett D'Amore { 176*95c635efSGarrett D'Amore 177*95c635efSGarrett D'Amore assert(man->last); 178*95c635efSGarrett D'Amore assert(man->first); 179*95c635efSGarrett D'Amore assert(MAN_ROOT != p->type); 180*95c635efSGarrett D'Amore 181*95c635efSGarrett D'Amore switch (man->next) { 182*95c635efSGarrett D'Amore case (MAN_NEXT_SIBLING): 183*95c635efSGarrett D'Amore man->last->next = p; 184*95c635efSGarrett D'Amore p->prev = man->last; 185*95c635efSGarrett D'Amore p->parent = man->last->parent; 186*95c635efSGarrett D'Amore break; 187*95c635efSGarrett D'Amore case (MAN_NEXT_CHILD): 188*95c635efSGarrett D'Amore man->last->child = p; 189*95c635efSGarrett D'Amore p->parent = man->last; 190*95c635efSGarrett D'Amore break; 191*95c635efSGarrett D'Amore default: 192*95c635efSGarrett D'Amore abort(); 193*95c635efSGarrett D'Amore /* NOTREACHED */ 194*95c635efSGarrett D'Amore } 195*95c635efSGarrett D'Amore 196*95c635efSGarrett D'Amore assert(p->parent); 197*95c635efSGarrett D'Amore p->parent->nchild++; 198*95c635efSGarrett D'Amore 199*95c635efSGarrett D'Amore if ( ! man_valid_pre(man, p)) 200*95c635efSGarrett D'Amore return(0); 201*95c635efSGarrett D'Amore 202*95c635efSGarrett D'Amore switch (p->type) { 203*95c635efSGarrett D'Amore case (MAN_HEAD): 204*95c635efSGarrett D'Amore assert(MAN_BLOCK == p->parent->type); 205*95c635efSGarrett D'Amore p->parent->head = p; 206*95c635efSGarrett D'Amore break; 207*95c635efSGarrett D'Amore case (MAN_TAIL): 208*95c635efSGarrett D'Amore assert(MAN_BLOCK == p->parent->type); 209*95c635efSGarrett D'Amore p->parent->tail = p; 210*95c635efSGarrett D'Amore break; 211*95c635efSGarrett D'Amore case (MAN_BODY): 212*95c635efSGarrett D'Amore assert(MAN_BLOCK == p->parent->type); 213*95c635efSGarrett D'Amore p->parent->body = p; 214*95c635efSGarrett D'Amore break; 215*95c635efSGarrett D'Amore default: 216*95c635efSGarrett D'Amore break; 217*95c635efSGarrett D'Amore } 218*95c635efSGarrett D'Amore 219*95c635efSGarrett D'Amore man->last = p; 220*95c635efSGarrett D'Amore 221*95c635efSGarrett D'Amore switch (p->type) { 222*95c635efSGarrett D'Amore case (MAN_TBL): 223*95c635efSGarrett D'Amore /* FALLTHROUGH */ 224*95c635efSGarrett D'Amore case (MAN_TEXT): 225*95c635efSGarrett D'Amore if ( ! man_valid_post(man)) 226*95c635efSGarrett D'Amore return(0); 227*95c635efSGarrett D'Amore break; 228*95c635efSGarrett D'Amore default: 229*95c635efSGarrett D'Amore break; 230*95c635efSGarrett D'Amore } 231*95c635efSGarrett D'Amore 232*95c635efSGarrett D'Amore return(1); 233*95c635efSGarrett D'Amore } 234*95c635efSGarrett D'Amore 235*95c635efSGarrett D'Amore 236*95c635efSGarrett D'Amore static struct man_node * 237*95c635efSGarrett D'Amore man_node_alloc(struct man *m, int line, int pos, 238*95c635efSGarrett D'Amore enum man_type type, enum mant tok) 239*95c635efSGarrett D'Amore { 240*95c635efSGarrett D'Amore struct man_node *p; 241*95c635efSGarrett D'Amore 242*95c635efSGarrett D'Amore p = mandoc_calloc(1, sizeof(struct man_node)); 243*95c635efSGarrett D'Amore p->line = line; 244*95c635efSGarrett D'Amore p->pos = pos; 245*95c635efSGarrett D'Amore p->type = type; 246*95c635efSGarrett D'Amore p->tok = tok; 247*95c635efSGarrett D'Amore 248*95c635efSGarrett D'Amore if (MAN_NEWLINE & m->flags) 249*95c635efSGarrett D'Amore p->flags |= MAN_LINE; 250*95c635efSGarrett D'Amore m->flags &= ~MAN_NEWLINE; 251*95c635efSGarrett D'Amore return(p); 252*95c635efSGarrett D'Amore } 253*95c635efSGarrett D'Amore 254*95c635efSGarrett D'Amore 255*95c635efSGarrett D'Amore int 256*95c635efSGarrett D'Amore man_elem_alloc(struct man *m, int line, int pos, enum mant tok) 257*95c635efSGarrett D'Amore { 258*95c635efSGarrett D'Amore struct man_node *p; 259*95c635efSGarrett D'Amore 260*95c635efSGarrett D'Amore p = man_node_alloc(m, line, pos, MAN_ELEM, tok); 261*95c635efSGarrett D'Amore if ( ! man_node_append(m, p)) 262*95c635efSGarrett D'Amore return(0); 263*95c635efSGarrett D'Amore m->next = MAN_NEXT_CHILD; 264*95c635efSGarrett D'Amore return(1); 265*95c635efSGarrett D'Amore } 266*95c635efSGarrett D'Amore 267*95c635efSGarrett D'Amore 268*95c635efSGarrett D'Amore int 269*95c635efSGarrett D'Amore man_tail_alloc(struct man *m, int line, int pos, enum mant tok) 270*95c635efSGarrett D'Amore { 271*95c635efSGarrett D'Amore struct man_node *p; 272*95c635efSGarrett D'Amore 273*95c635efSGarrett D'Amore p = man_node_alloc(m, line, pos, MAN_TAIL, tok); 274*95c635efSGarrett D'Amore if ( ! man_node_append(m, p)) 275*95c635efSGarrett D'Amore return(0); 276*95c635efSGarrett D'Amore m->next = MAN_NEXT_CHILD; 277*95c635efSGarrett D'Amore return(1); 278*95c635efSGarrett D'Amore } 279*95c635efSGarrett D'Amore 280*95c635efSGarrett D'Amore 281*95c635efSGarrett D'Amore int 282*95c635efSGarrett D'Amore man_head_alloc(struct man *m, int line, int pos, enum mant tok) 283*95c635efSGarrett D'Amore { 284*95c635efSGarrett D'Amore struct man_node *p; 285*95c635efSGarrett D'Amore 286*95c635efSGarrett D'Amore p = man_node_alloc(m, line, pos, MAN_HEAD, tok); 287*95c635efSGarrett D'Amore if ( ! man_node_append(m, p)) 288*95c635efSGarrett D'Amore return(0); 289*95c635efSGarrett D'Amore m->next = MAN_NEXT_CHILD; 290*95c635efSGarrett D'Amore return(1); 291*95c635efSGarrett D'Amore } 292*95c635efSGarrett D'Amore 293*95c635efSGarrett D'Amore 294*95c635efSGarrett D'Amore int 295*95c635efSGarrett D'Amore man_body_alloc(struct man *m, int line, int pos, enum mant tok) 296*95c635efSGarrett D'Amore { 297*95c635efSGarrett D'Amore struct man_node *p; 298*95c635efSGarrett D'Amore 299*95c635efSGarrett D'Amore p = man_node_alloc(m, line, pos, MAN_BODY, tok); 300*95c635efSGarrett D'Amore if ( ! man_node_append(m, p)) 301*95c635efSGarrett D'Amore return(0); 302*95c635efSGarrett D'Amore m->next = MAN_NEXT_CHILD; 303*95c635efSGarrett D'Amore return(1); 304*95c635efSGarrett D'Amore } 305*95c635efSGarrett D'Amore 306*95c635efSGarrett D'Amore 307*95c635efSGarrett D'Amore int 308*95c635efSGarrett D'Amore man_block_alloc(struct man *m, int line, int pos, enum mant tok) 309*95c635efSGarrett D'Amore { 310*95c635efSGarrett D'Amore struct man_node *p; 311*95c635efSGarrett D'Amore 312*95c635efSGarrett D'Amore p = man_node_alloc(m, line, pos, MAN_BLOCK, tok); 313*95c635efSGarrett D'Amore if ( ! man_node_append(m, p)) 314*95c635efSGarrett D'Amore return(0); 315*95c635efSGarrett D'Amore m->next = MAN_NEXT_CHILD; 316*95c635efSGarrett D'Amore return(1); 317*95c635efSGarrett D'Amore } 318*95c635efSGarrett D'Amore 319*95c635efSGarrett D'Amore int 320*95c635efSGarrett D'Amore man_word_alloc(struct man *m, int line, int pos, const char *word) 321*95c635efSGarrett D'Amore { 322*95c635efSGarrett D'Amore struct man_node *n; 323*95c635efSGarrett D'Amore 324*95c635efSGarrett D'Amore n = man_node_alloc(m, line, pos, MAN_TEXT, MAN_MAX); 325*95c635efSGarrett D'Amore n->string = roff_strdup(m->roff, word); 326*95c635efSGarrett D'Amore 327*95c635efSGarrett D'Amore if ( ! man_node_append(m, n)) 328*95c635efSGarrett D'Amore return(0); 329*95c635efSGarrett D'Amore 330*95c635efSGarrett D'Amore m->next = MAN_NEXT_SIBLING; 331*95c635efSGarrett D'Amore return(1); 332*95c635efSGarrett D'Amore } 333*95c635efSGarrett D'Amore 334*95c635efSGarrett D'Amore 335*95c635efSGarrett D'Amore /* 336*95c635efSGarrett D'Amore * Free all of the resources held by a node. This does NOT unlink a 337*95c635efSGarrett D'Amore * node from its context; for that, see man_node_unlink(). 338*95c635efSGarrett D'Amore */ 339*95c635efSGarrett D'Amore static void 340*95c635efSGarrett D'Amore man_node_free(struct man_node *p) 341*95c635efSGarrett D'Amore { 342*95c635efSGarrett D'Amore 343*95c635efSGarrett D'Amore if (p->string) 344*95c635efSGarrett D'Amore free(p->string); 345*95c635efSGarrett D'Amore free(p); 346*95c635efSGarrett D'Amore } 347*95c635efSGarrett D'Amore 348*95c635efSGarrett D'Amore 349*95c635efSGarrett D'Amore void 350*95c635efSGarrett D'Amore man_node_delete(struct man *m, struct man_node *p) 351*95c635efSGarrett D'Amore { 352*95c635efSGarrett D'Amore 353*95c635efSGarrett D'Amore while (p->child) 354*95c635efSGarrett D'Amore man_node_delete(m, p->child); 355*95c635efSGarrett D'Amore 356*95c635efSGarrett D'Amore man_node_unlink(m, p); 357*95c635efSGarrett D'Amore man_node_free(p); 358*95c635efSGarrett D'Amore } 359*95c635efSGarrett D'Amore 360*95c635efSGarrett D'Amore int 361*95c635efSGarrett D'Amore man_addeqn(struct man *m, const struct eqn *ep) 362*95c635efSGarrett D'Amore { 363*95c635efSGarrett D'Amore struct man_node *n; 364*95c635efSGarrett D'Amore 365*95c635efSGarrett D'Amore assert( ! (MAN_HALT & m->flags)); 366*95c635efSGarrett D'Amore 367*95c635efSGarrett D'Amore n = man_node_alloc(m, ep->ln, ep->pos, MAN_EQN, MAN_MAX); 368*95c635efSGarrett D'Amore n->eqn = ep; 369*95c635efSGarrett D'Amore 370*95c635efSGarrett D'Amore if ( ! man_node_append(m, n)) 371*95c635efSGarrett D'Amore return(0); 372*95c635efSGarrett D'Amore 373*95c635efSGarrett D'Amore m->next = MAN_NEXT_SIBLING; 374*95c635efSGarrett D'Amore return(man_descope(m, ep->ln, ep->pos)); 375*95c635efSGarrett D'Amore } 376*95c635efSGarrett D'Amore 377*95c635efSGarrett D'Amore int 378*95c635efSGarrett D'Amore man_addspan(struct man *m, const struct tbl_span *sp) 379*95c635efSGarrett D'Amore { 380*95c635efSGarrett D'Amore struct man_node *n; 381*95c635efSGarrett D'Amore 382*95c635efSGarrett D'Amore assert( ! (MAN_HALT & m->flags)); 383*95c635efSGarrett D'Amore 384*95c635efSGarrett D'Amore n = man_node_alloc(m, sp->line, 0, MAN_TBL, MAN_MAX); 385*95c635efSGarrett D'Amore n->span = sp; 386*95c635efSGarrett D'Amore 387*95c635efSGarrett D'Amore if ( ! man_node_append(m, n)) 388*95c635efSGarrett D'Amore return(0); 389*95c635efSGarrett D'Amore 390*95c635efSGarrett D'Amore m->next = MAN_NEXT_SIBLING; 391*95c635efSGarrett D'Amore return(man_descope(m, sp->line, 0)); 392*95c635efSGarrett D'Amore } 393*95c635efSGarrett D'Amore 394*95c635efSGarrett D'Amore static int 395*95c635efSGarrett D'Amore man_descope(struct man *m, int line, int offs) 396*95c635efSGarrett D'Amore { 397*95c635efSGarrett D'Amore /* 398*95c635efSGarrett D'Amore * Co-ordinate what happens with having a next-line scope open: 399*95c635efSGarrett D'Amore * first close out the element scope (if applicable), then close 400*95c635efSGarrett D'Amore * out the block scope (also if applicable). 401*95c635efSGarrett D'Amore */ 402*95c635efSGarrett D'Amore 403*95c635efSGarrett D'Amore if (MAN_ELINE & m->flags) { 404*95c635efSGarrett D'Amore m->flags &= ~MAN_ELINE; 405*95c635efSGarrett D'Amore if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX)) 406*95c635efSGarrett D'Amore return(0); 407*95c635efSGarrett D'Amore } 408*95c635efSGarrett D'Amore 409*95c635efSGarrett D'Amore if ( ! (MAN_BLINE & m->flags)) 410*95c635efSGarrett D'Amore return(1); 411*95c635efSGarrett D'Amore m->flags &= ~MAN_BLINE; 412*95c635efSGarrett D'Amore 413*95c635efSGarrett D'Amore if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX)) 414*95c635efSGarrett D'Amore return(0); 415*95c635efSGarrett D'Amore return(man_body_alloc(m, line, offs, m->last->tok)); 416*95c635efSGarrett D'Amore } 417*95c635efSGarrett D'Amore 418*95c635efSGarrett D'Amore static int 419*95c635efSGarrett D'Amore man_ptext(struct man *m, int line, char *buf, int offs) 420*95c635efSGarrett D'Amore { 421*95c635efSGarrett D'Amore int i; 422*95c635efSGarrett D'Amore 423*95c635efSGarrett D'Amore /* Literal free-form text whitespace is preserved. */ 424*95c635efSGarrett D'Amore 425*95c635efSGarrett D'Amore if (MAN_LITERAL & m->flags) { 426*95c635efSGarrett D'Amore if ( ! man_word_alloc(m, line, offs, buf + offs)) 427*95c635efSGarrett D'Amore return(0); 428*95c635efSGarrett D'Amore return(man_descope(m, line, offs)); 429*95c635efSGarrett D'Amore } 430*95c635efSGarrett D'Amore 431*95c635efSGarrett D'Amore /* Pump blank lines directly into the backend. */ 432*95c635efSGarrett D'Amore 433*95c635efSGarrett D'Amore for (i = offs; ' ' == buf[i]; i++) 434*95c635efSGarrett D'Amore /* Skip leading whitespace. */ ; 435*95c635efSGarrett D'Amore 436*95c635efSGarrett D'Amore if ('\0' == buf[i]) { 437*95c635efSGarrett D'Amore /* Allocate a blank entry. */ 438*95c635efSGarrett D'Amore if ( ! man_word_alloc(m, line, offs, "")) 439*95c635efSGarrett D'Amore return(0); 440*95c635efSGarrett D'Amore return(man_descope(m, line, offs)); 441*95c635efSGarrett D'Amore } 442*95c635efSGarrett D'Amore 443*95c635efSGarrett D'Amore /* 444*95c635efSGarrett D'Amore * Warn if the last un-escaped character is whitespace. Then 445*95c635efSGarrett D'Amore * strip away the remaining spaces (tabs stay!). 446*95c635efSGarrett D'Amore */ 447*95c635efSGarrett D'Amore 448*95c635efSGarrett D'Amore i = (int)strlen(buf); 449*95c635efSGarrett D'Amore assert(i); 450*95c635efSGarrett D'Amore 451*95c635efSGarrett D'Amore if (' ' == buf[i - 1] || '\t' == buf[i - 1]) { 452*95c635efSGarrett D'Amore if (i > 1 && '\\' != buf[i - 2]) 453*95c635efSGarrett D'Amore man_pmsg(m, line, i - 1, MANDOCERR_EOLNSPACE); 454*95c635efSGarrett D'Amore 455*95c635efSGarrett D'Amore for (--i; i && ' ' == buf[i]; i--) 456*95c635efSGarrett D'Amore /* Spin back to non-space. */ ; 457*95c635efSGarrett D'Amore 458*95c635efSGarrett D'Amore /* Jump ahead of escaped whitespace. */ 459*95c635efSGarrett D'Amore i += '\\' == buf[i] ? 2 : 1; 460*95c635efSGarrett D'Amore 461*95c635efSGarrett D'Amore buf[i] = '\0'; 462*95c635efSGarrett D'Amore } 463*95c635efSGarrett D'Amore 464*95c635efSGarrett D'Amore if ( ! man_word_alloc(m, line, offs, buf + offs)) 465*95c635efSGarrett D'Amore return(0); 466*95c635efSGarrett D'Amore 467*95c635efSGarrett D'Amore /* 468*95c635efSGarrett D'Amore * End-of-sentence check. If the last character is an unescaped 469*95c635efSGarrett D'Amore * EOS character, then flag the node as being the end of a 470*95c635efSGarrett D'Amore * sentence. The front-end will know how to interpret this. 471*95c635efSGarrett D'Amore */ 472*95c635efSGarrett D'Amore 473*95c635efSGarrett D'Amore assert(i); 474*95c635efSGarrett D'Amore if (mandoc_eos(buf, (size_t)i, 0)) 475*95c635efSGarrett D'Amore m->last->flags |= MAN_EOS; 476*95c635efSGarrett D'Amore 477*95c635efSGarrett D'Amore return(man_descope(m, line, offs)); 478*95c635efSGarrett D'Amore } 479*95c635efSGarrett D'Amore 480*95c635efSGarrett D'Amore static int 481*95c635efSGarrett D'Amore man_pmacro(struct man *m, int ln, char *buf, int offs) 482*95c635efSGarrett D'Amore { 483*95c635efSGarrett D'Amore int i, ppos; 484*95c635efSGarrett D'Amore enum mant tok; 485*95c635efSGarrett D'Amore char mac[5]; 486*95c635efSGarrett D'Amore struct man_node *n; 487*95c635efSGarrett D'Amore 488*95c635efSGarrett D'Amore if ('"' == buf[offs]) { 489*95c635efSGarrett D'Amore man_pmsg(m, ln, offs, MANDOCERR_BADCOMMENT); 490*95c635efSGarrett D'Amore return(1); 491*95c635efSGarrett D'Amore } else if ('\0' == buf[offs]) 492*95c635efSGarrett D'Amore return(1); 493*95c635efSGarrett D'Amore 494*95c635efSGarrett D'Amore ppos = offs; 495*95c635efSGarrett D'Amore 496*95c635efSGarrett D'Amore /* 497*95c635efSGarrett D'Amore * Copy the first word into a nil-terminated buffer. 498*95c635efSGarrett D'Amore * Stop copying when a tab, space, or eoln is encountered. 499*95c635efSGarrett D'Amore */ 500*95c635efSGarrett D'Amore 501*95c635efSGarrett D'Amore i = 0; 502*95c635efSGarrett D'Amore while (i < 4 && '\0' != buf[offs] && 503*95c635efSGarrett D'Amore ' ' != buf[offs] && '\t' != buf[offs]) 504*95c635efSGarrett D'Amore mac[i++] = buf[offs++]; 505*95c635efSGarrett D'Amore 506*95c635efSGarrett D'Amore mac[i] = '\0'; 507*95c635efSGarrett D'Amore 508*95c635efSGarrett D'Amore tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX; 509*95c635efSGarrett D'Amore 510*95c635efSGarrett D'Amore if (MAN_MAX == tok) { 511*95c635efSGarrett D'Amore mandoc_vmsg(MANDOCERR_MACRO, m->parse, ln, 512*95c635efSGarrett D'Amore ppos, "%s", buf + ppos - 1); 513*95c635efSGarrett D'Amore return(1); 514*95c635efSGarrett D'Amore } 515*95c635efSGarrett D'Amore 516*95c635efSGarrett D'Amore /* The macro is sane. Jump to the next word. */ 517*95c635efSGarrett D'Amore 518*95c635efSGarrett D'Amore while (buf[offs] && ' ' == buf[offs]) 519*95c635efSGarrett D'Amore offs++; 520*95c635efSGarrett D'Amore 521*95c635efSGarrett D'Amore /* 522*95c635efSGarrett D'Amore * Trailing whitespace. Note that tabs are allowed to be passed 523*95c635efSGarrett D'Amore * into the parser as "text", so we only warn about spaces here. 524*95c635efSGarrett D'Amore */ 525*95c635efSGarrett D'Amore 526*95c635efSGarrett D'Amore if ('\0' == buf[offs] && ' ' == buf[offs - 1]) 527*95c635efSGarrett D'Amore man_pmsg(m, ln, offs - 1, MANDOCERR_EOLNSPACE); 528*95c635efSGarrett D'Amore 529*95c635efSGarrett D'Amore /* 530*95c635efSGarrett D'Amore * Remove prior ELINE macro, as it's being clobbered by a new 531*95c635efSGarrett D'Amore * macro. Note that NSCOPED macros do not close out ELINE 532*95c635efSGarrett D'Amore * macros---they don't print text---so we let those slip by. 533*95c635efSGarrett D'Amore */ 534*95c635efSGarrett D'Amore 535*95c635efSGarrett D'Amore if ( ! (MAN_NSCOPED & man_macros[tok].flags) && 536*95c635efSGarrett D'Amore m->flags & MAN_ELINE) { 537*95c635efSGarrett D'Amore n = m->last; 538*95c635efSGarrett D'Amore assert(MAN_TEXT != n->type); 539*95c635efSGarrett D'Amore 540*95c635efSGarrett D'Amore /* Remove repeated NSCOPED macros causing ELINE. */ 541*95c635efSGarrett D'Amore 542*95c635efSGarrett D'Amore if (MAN_NSCOPED & man_macros[n->tok].flags) 543*95c635efSGarrett D'Amore n = n->parent; 544*95c635efSGarrett D'Amore 545*95c635efSGarrett D'Amore mandoc_vmsg(MANDOCERR_LINESCOPE, m->parse, n->line, 546*95c635efSGarrett D'Amore n->pos, "%s breaks %s", man_macronames[tok], 547*95c635efSGarrett D'Amore man_macronames[n->tok]); 548*95c635efSGarrett D'Amore 549*95c635efSGarrett D'Amore man_node_delete(m, n); 550*95c635efSGarrett D'Amore m->flags &= ~MAN_ELINE; 551*95c635efSGarrett D'Amore } 552*95c635efSGarrett D'Amore 553*95c635efSGarrett D'Amore /* 554*95c635efSGarrett D'Amore * Remove prior BLINE macro that is being clobbered. 555*95c635efSGarrett D'Amore */ 556*95c635efSGarrett D'Amore if ((m->flags & MAN_BLINE) && 557*95c635efSGarrett D'Amore (MAN_BSCOPE & man_macros[tok].flags)) { 558*95c635efSGarrett D'Amore n = m->last; 559*95c635efSGarrett D'Amore 560*95c635efSGarrett D'Amore /* Might be a text node like 8 in 561*95c635efSGarrett D'Amore * .TP 8 562*95c635efSGarrett D'Amore * .SH foo 563*95c635efSGarrett D'Amore */ 564*95c635efSGarrett D'Amore if (MAN_TEXT == n->type) 565*95c635efSGarrett D'Amore n = n->parent; 566*95c635efSGarrett D'Amore 567*95c635efSGarrett D'Amore /* Remove element that didn't end BLINE, if any. */ 568*95c635efSGarrett D'Amore if ( ! (MAN_BSCOPE & man_macros[n->tok].flags)) 569*95c635efSGarrett D'Amore n = n->parent; 570*95c635efSGarrett D'Amore 571*95c635efSGarrett D'Amore assert(MAN_HEAD == n->type); 572*95c635efSGarrett D'Amore n = n->parent; 573*95c635efSGarrett D'Amore assert(MAN_BLOCK == n->type); 574*95c635efSGarrett D'Amore assert(MAN_SCOPED & man_macros[n->tok].flags); 575*95c635efSGarrett D'Amore 576*95c635efSGarrett D'Amore mandoc_vmsg(MANDOCERR_LINESCOPE, m->parse, n->line, 577*95c635efSGarrett D'Amore n->pos, "%s breaks %s", man_macronames[tok], 578*95c635efSGarrett D'Amore man_macronames[n->tok]); 579*95c635efSGarrett D'Amore 580*95c635efSGarrett D'Amore man_node_delete(m, n); 581*95c635efSGarrett D'Amore m->flags &= ~MAN_BLINE; 582*95c635efSGarrett D'Amore } 583*95c635efSGarrett D'Amore 584*95c635efSGarrett D'Amore /* 585*95c635efSGarrett D'Amore * Save the fact that we're in the next-line for a block. In 586*95c635efSGarrett D'Amore * this way, embedded roff instructions can "remember" state 587*95c635efSGarrett D'Amore * when they exit. 588*95c635efSGarrett D'Amore */ 589*95c635efSGarrett D'Amore 590*95c635efSGarrett D'Amore if (MAN_BLINE & m->flags) 591*95c635efSGarrett D'Amore m->flags |= MAN_BPLINE; 592*95c635efSGarrett D'Amore 593*95c635efSGarrett D'Amore /* Call to handler... */ 594*95c635efSGarrett D'Amore 595*95c635efSGarrett D'Amore assert(man_macros[tok].fp); 596*95c635efSGarrett D'Amore if ( ! (*man_macros[tok].fp)(m, tok, ln, ppos, &offs, buf)) 597*95c635efSGarrett D'Amore goto err; 598*95c635efSGarrett D'Amore 599*95c635efSGarrett D'Amore /* 600*95c635efSGarrett D'Amore * We weren't in a block-line scope when entering the 601*95c635efSGarrett D'Amore * above-parsed macro, so return. 602*95c635efSGarrett D'Amore */ 603*95c635efSGarrett D'Amore 604*95c635efSGarrett D'Amore if ( ! (MAN_BPLINE & m->flags)) { 605*95c635efSGarrett D'Amore m->flags &= ~MAN_ILINE; 606*95c635efSGarrett D'Amore return(1); 607*95c635efSGarrett D'Amore } 608*95c635efSGarrett D'Amore m->flags &= ~MAN_BPLINE; 609*95c635efSGarrett D'Amore 610*95c635efSGarrett D'Amore /* 611*95c635efSGarrett D'Amore * If we're in a block scope, then allow this macro to slip by 612*95c635efSGarrett D'Amore * without closing scope around it. 613*95c635efSGarrett D'Amore */ 614*95c635efSGarrett D'Amore 615*95c635efSGarrett D'Amore if (MAN_ILINE & m->flags) { 616*95c635efSGarrett D'Amore m->flags &= ~MAN_ILINE; 617*95c635efSGarrett D'Amore return(1); 618*95c635efSGarrett D'Amore } 619*95c635efSGarrett D'Amore 620*95c635efSGarrett D'Amore /* 621*95c635efSGarrett D'Amore * If we've opened a new next-line element scope, then return 622*95c635efSGarrett D'Amore * now, as the next line will close out the block scope. 623*95c635efSGarrett D'Amore */ 624*95c635efSGarrett D'Amore 625*95c635efSGarrett D'Amore if (MAN_ELINE & m->flags) 626*95c635efSGarrett D'Amore return(1); 627*95c635efSGarrett D'Amore 628*95c635efSGarrett D'Amore /* Close out the block scope opened in the prior line. */ 629*95c635efSGarrett D'Amore 630*95c635efSGarrett D'Amore assert(MAN_BLINE & m->flags); 631*95c635efSGarrett D'Amore m->flags &= ~MAN_BLINE; 632*95c635efSGarrett D'Amore 633*95c635efSGarrett D'Amore if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX)) 634*95c635efSGarrett D'Amore return(0); 635*95c635efSGarrett D'Amore return(man_body_alloc(m, ln, ppos, m->last->tok)); 636*95c635efSGarrett D'Amore 637*95c635efSGarrett D'Amore err: /* Error out. */ 638*95c635efSGarrett D'Amore 639*95c635efSGarrett D'Amore m->flags |= MAN_HALT; 640*95c635efSGarrett D'Amore return(0); 641*95c635efSGarrett D'Amore } 642*95c635efSGarrett D'Amore 643*95c635efSGarrett D'Amore /* 644*95c635efSGarrett D'Amore * Unlink a node from its context. If "m" is provided, the last parse 645*95c635efSGarrett D'Amore * point will also be adjusted accordingly. 646*95c635efSGarrett D'Amore */ 647*95c635efSGarrett D'Amore static void 648*95c635efSGarrett D'Amore man_node_unlink(struct man *m, struct man_node *n) 649*95c635efSGarrett D'Amore { 650*95c635efSGarrett D'Amore 651*95c635efSGarrett D'Amore /* Adjust siblings. */ 652*95c635efSGarrett D'Amore 653*95c635efSGarrett D'Amore if (n->prev) 654*95c635efSGarrett D'Amore n->prev->next = n->next; 655*95c635efSGarrett D'Amore if (n->next) 656*95c635efSGarrett D'Amore n->next->prev = n->prev; 657*95c635efSGarrett D'Amore 658*95c635efSGarrett D'Amore /* Adjust parent. */ 659*95c635efSGarrett D'Amore 660*95c635efSGarrett D'Amore if (n->parent) { 661*95c635efSGarrett D'Amore n->parent->nchild--; 662*95c635efSGarrett D'Amore if (n->parent->child == n) 663*95c635efSGarrett D'Amore n->parent->child = n->prev ? n->prev : n->next; 664*95c635efSGarrett D'Amore } 665*95c635efSGarrett D'Amore 666*95c635efSGarrett D'Amore /* Adjust parse point, if applicable. */ 667*95c635efSGarrett D'Amore 668*95c635efSGarrett D'Amore if (m && m->last == n) { 669*95c635efSGarrett D'Amore /*XXX: this can occur when bailing from validation. */ 670*95c635efSGarrett D'Amore /*assert(NULL == n->next);*/ 671*95c635efSGarrett D'Amore if (n->prev) { 672*95c635efSGarrett D'Amore m->last = n->prev; 673*95c635efSGarrett D'Amore m->next = MAN_NEXT_SIBLING; 674*95c635efSGarrett D'Amore } else { 675*95c635efSGarrett D'Amore m->last = n->parent; 676*95c635efSGarrett D'Amore m->next = MAN_NEXT_CHILD; 677*95c635efSGarrett D'Amore } 678*95c635efSGarrett D'Amore } 679*95c635efSGarrett D'Amore 680*95c635efSGarrett D'Amore if (m && m->first == n) 681*95c635efSGarrett D'Amore m->first = NULL; 682*95c635efSGarrett D'Amore } 683*95c635efSGarrett D'Amore 684*95c635efSGarrett D'Amore const struct mparse * 685*95c635efSGarrett D'Amore man_mparse(const struct man *m) 686*95c635efSGarrett D'Amore { 687*95c635efSGarrett D'Amore 688*95c635efSGarrett D'Amore assert(m && m->parse); 689*95c635efSGarrett D'Amore return(m->parse); 690*95c635efSGarrett D'Amore } 691