1*698f87a4SGarrett D'Amore /* $Id: man.c,v 1.121 2013/11/10 22:54:40 schwarze Exp $ */ 295c635efSGarrett D'Amore /* 395c635efSGarrett D'Amore * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> 495c635efSGarrett D'Amore * 595c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any 695c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above 795c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies. 895c635efSGarrett D'Amore * 995c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1095c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1195c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1295c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1395c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1495c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1595c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1695c635efSGarrett D'Amore */ 1795c635efSGarrett D'Amore #ifdef HAVE_CONFIG_H 1895c635efSGarrett D'Amore #include "config.h" 1995c635efSGarrett D'Amore #endif 2095c635efSGarrett D'Amore 2195c635efSGarrett D'Amore #include <sys/types.h> 2295c635efSGarrett D'Amore 2395c635efSGarrett D'Amore #include <assert.h> 2495c635efSGarrett D'Amore #include <stdarg.h> 2595c635efSGarrett D'Amore #include <stdlib.h> 2695c635efSGarrett D'Amore #include <stdio.h> 2795c635efSGarrett D'Amore #include <string.h> 2895c635efSGarrett D'Amore 2995c635efSGarrett D'Amore #include "man.h" 3095c635efSGarrett D'Amore #include "mandoc.h" 3195c635efSGarrett D'Amore #include "libman.h" 3295c635efSGarrett D'Amore #include "libmandoc.h" 3395c635efSGarrett D'Amore 3495c635efSGarrett D'Amore const char *const __man_macronames[MAN_MAX] = { 3595c635efSGarrett D'Amore "br", "TH", "SH", "SS", 3695c635efSGarrett D'Amore "TP", "LP", "PP", "P", 3795c635efSGarrett D'Amore "IP", "HP", "SM", "SB", 3895c635efSGarrett D'Amore "BI", "IB", "BR", "RB", 3995c635efSGarrett D'Amore "R", "B", "I", "IR", 4095c635efSGarrett D'Amore "RI", "na", "sp", "nf", 4195c635efSGarrett D'Amore "fi", "RE", "RS", "DT", 4295c635efSGarrett D'Amore "UC", "PD", "AT", "in", 43*698f87a4SGarrett D'Amore "ft", "OP", "EX", "EE", 44*698f87a4SGarrett D'Amore "UR", "UE" 4595c635efSGarrett D'Amore }; 4695c635efSGarrett D'Amore 4795c635efSGarrett D'Amore const char * const *man_macronames = __man_macronames; 4895c635efSGarrett D'Amore 4995c635efSGarrett D'Amore static struct man_node *man_node_alloc(struct man *, int, int, 5095c635efSGarrett D'Amore enum man_type, enum mant); 5195c635efSGarrett D'Amore static int man_node_append(struct man *, 5295c635efSGarrett D'Amore struct man_node *); 5395c635efSGarrett D'Amore static void man_node_free(struct man_node *); 5495c635efSGarrett D'Amore static void man_node_unlink(struct man *, 5595c635efSGarrett D'Amore struct man_node *); 5695c635efSGarrett D'Amore static int man_ptext(struct man *, int, char *, int); 5795c635efSGarrett D'Amore static int man_pmacro(struct man *, int, char *, int); 5895c635efSGarrett D'Amore static void man_free1(struct man *); 5995c635efSGarrett D'Amore static void man_alloc1(struct man *); 6095c635efSGarrett D'Amore static int man_descope(struct man *, int, int); 6195c635efSGarrett D'Amore 6295c635efSGarrett D'Amore 6395c635efSGarrett D'Amore const struct man_node * 64*698f87a4SGarrett D'Amore man_node(const struct man *man) 6595c635efSGarrett D'Amore { 6695c635efSGarrett D'Amore 67*698f87a4SGarrett D'Amore assert( ! (MAN_HALT & man->flags)); 68*698f87a4SGarrett D'Amore return(man->first); 6995c635efSGarrett D'Amore } 7095c635efSGarrett D'Amore 7195c635efSGarrett D'Amore 7295c635efSGarrett D'Amore const struct man_meta * 73*698f87a4SGarrett D'Amore man_meta(const struct man *man) 7495c635efSGarrett D'Amore { 7595c635efSGarrett D'Amore 76*698f87a4SGarrett D'Amore assert( ! (MAN_HALT & man->flags)); 77*698f87a4SGarrett D'Amore return(&man->meta); 7895c635efSGarrett D'Amore } 7995c635efSGarrett D'Amore 8095c635efSGarrett D'Amore 8195c635efSGarrett D'Amore void 8295c635efSGarrett D'Amore man_reset(struct man *man) 8395c635efSGarrett D'Amore { 8495c635efSGarrett D'Amore 8595c635efSGarrett D'Amore man_free1(man); 8695c635efSGarrett D'Amore man_alloc1(man); 8795c635efSGarrett D'Amore } 8895c635efSGarrett D'Amore 8995c635efSGarrett D'Amore 9095c635efSGarrett D'Amore void 9195c635efSGarrett D'Amore man_free(struct man *man) 9295c635efSGarrett D'Amore { 9395c635efSGarrett D'Amore 9495c635efSGarrett D'Amore man_free1(man); 9595c635efSGarrett D'Amore free(man); 9695c635efSGarrett D'Amore } 9795c635efSGarrett D'Amore 9895c635efSGarrett D'Amore 9995c635efSGarrett D'Amore struct man * 10095c635efSGarrett D'Amore man_alloc(struct roff *roff, struct mparse *parse) 10195c635efSGarrett D'Amore { 10295c635efSGarrett D'Amore struct man *p; 10395c635efSGarrett D'Amore 10495c635efSGarrett D'Amore p = mandoc_calloc(1, sizeof(struct man)); 10595c635efSGarrett D'Amore 10695c635efSGarrett D'Amore man_hash_init(); 10795c635efSGarrett D'Amore p->parse = parse; 10895c635efSGarrett D'Amore p->roff = roff; 10995c635efSGarrett D'Amore 11095c635efSGarrett D'Amore man_alloc1(p); 11195c635efSGarrett D'Amore return(p); 11295c635efSGarrett D'Amore } 11395c635efSGarrett D'Amore 11495c635efSGarrett D'Amore 11595c635efSGarrett D'Amore int 116*698f87a4SGarrett D'Amore man_endparse(struct man *man) 11795c635efSGarrett D'Amore { 11895c635efSGarrett D'Amore 119*698f87a4SGarrett D'Amore assert( ! (MAN_HALT & man->flags)); 120*698f87a4SGarrett D'Amore if (man_macroend(man)) 12195c635efSGarrett D'Amore return(1); 122*698f87a4SGarrett D'Amore man->flags |= MAN_HALT; 12395c635efSGarrett D'Amore return(0); 12495c635efSGarrett D'Amore } 12595c635efSGarrett D'Amore 12695c635efSGarrett D'Amore 12795c635efSGarrett D'Amore int 128*698f87a4SGarrett D'Amore man_parseln(struct man *man, int ln, char *buf, int offs) 12995c635efSGarrett D'Amore { 13095c635efSGarrett D'Amore 131*698f87a4SGarrett D'Amore man->flags |= MAN_NEWLINE; 13295c635efSGarrett D'Amore 133*698f87a4SGarrett D'Amore assert( ! (MAN_HALT & man->flags)); 13495c635efSGarrett D'Amore 135*698f87a4SGarrett D'Amore return (roff_getcontrol(man->roff, buf, &offs) ? 136*698f87a4SGarrett D'Amore man_pmacro(man, ln, buf, offs) : 137*698f87a4SGarrett D'Amore man_ptext(man, ln, buf, offs)); 13895c635efSGarrett D'Amore } 13995c635efSGarrett D'Amore 14095c635efSGarrett D'Amore 14195c635efSGarrett D'Amore static void 14295c635efSGarrett D'Amore man_free1(struct man *man) 14395c635efSGarrett D'Amore { 14495c635efSGarrett D'Amore 14595c635efSGarrett D'Amore if (man->first) 14695c635efSGarrett D'Amore man_node_delete(man, man->first); 14795c635efSGarrett D'Amore if (man->meta.title) 14895c635efSGarrett D'Amore free(man->meta.title); 14995c635efSGarrett D'Amore if (man->meta.source) 15095c635efSGarrett D'Amore free(man->meta.source); 15195c635efSGarrett D'Amore if (man->meta.date) 15295c635efSGarrett D'Amore free(man->meta.date); 15395c635efSGarrett D'Amore if (man->meta.vol) 15495c635efSGarrett D'Amore free(man->meta.vol); 15595c635efSGarrett D'Amore if (man->meta.msec) 15695c635efSGarrett D'Amore free(man->meta.msec); 15795c635efSGarrett D'Amore } 15895c635efSGarrett D'Amore 15995c635efSGarrett D'Amore 16095c635efSGarrett D'Amore static void 161*698f87a4SGarrett D'Amore man_alloc1(struct man *man) 16295c635efSGarrett D'Amore { 16395c635efSGarrett D'Amore 164*698f87a4SGarrett D'Amore memset(&man->meta, 0, sizeof(struct man_meta)); 165*698f87a4SGarrett D'Amore man->flags = 0; 166*698f87a4SGarrett D'Amore man->last = mandoc_calloc(1, sizeof(struct man_node)); 167*698f87a4SGarrett D'Amore man->first = man->last; 168*698f87a4SGarrett D'Amore man->last->type = MAN_ROOT; 169*698f87a4SGarrett D'Amore man->last->tok = MAN_MAX; 170*698f87a4SGarrett D'Amore man->next = MAN_NEXT_CHILD; 17195c635efSGarrett D'Amore } 17295c635efSGarrett D'Amore 17395c635efSGarrett D'Amore 17495c635efSGarrett D'Amore static int 17595c635efSGarrett D'Amore man_node_append(struct man *man, struct man_node *p) 17695c635efSGarrett D'Amore { 17795c635efSGarrett D'Amore 17895c635efSGarrett D'Amore assert(man->last); 17995c635efSGarrett D'Amore assert(man->first); 18095c635efSGarrett D'Amore assert(MAN_ROOT != p->type); 18195c635efSGarrett D'Amore 18295c635efSGarrett D'Amore switch (man->next) { 18395c635efSGarrett D'Amore case (MAN_NEXT_SIBLING): 18495c635efSGarrett D'Amore man->last->next = p; 18595c635efSGarrett D'Amore p->prev = man->last; 18695c635efSGarrett D'Amore p->parent = man->last->parent; 18795c635efSGarrett D'Amore break; 18895c635efSGarrett D'Amore case (MAN_NEXT_CHILD): 18995c635efSGarrett D'Amore man->last->child = p; 19095c635efSGarrett D'Amore p->parent = man->last; 19195c635efSGarrett D'Amore break; 19295c635efSGarrett D'Amore default: 19395c635efSGarrett D'Amore abort(); 19495c635efSGarrett D'Amore /* NOTREACHED */ 19595c635efSGarrett D'Amore } 19695c635efSGarrett D'Amore 19795c635efSGarrett D'Amore assert(p->parent); 19895c635efSGarrett D'Amore p->parent->nchild++; 19995c635efSGarrett D'Amore 20095c635efSGarrett D'Amore if ( ! man_valid_pre(man, p)) 20195c635efSGarrett D'Amore return(0); 20295c635efSGarrett D'Amore 20395c635efSGarrett D'Amore switch (p->type) { 20495c635efSGarrett D'Amore case (MAN_HEAD): 20595c635efSGarrett D'Amore assert(MAN_BLOCK == p->parent->type); 20695c635efSGarrett D'Amore p->parent->head = p; 20795c635efSGarrett D'Amore break; 20895c635efSGarrett D'Amore case (MAN_TAIL): 20995c635efSGarrett D'Amore assert(MAN_BLOCK == p->parent->type); 21095c635efSGarrett D'Amore p->parent->tail = p; 21195c635efSGarrett D'Amore break; 21295c635efSGarrett D'Amore case (MAN_BODY): 21395c635efSGarrett D'Amore assert(MAN_BLOCK == p->parent->type); 21495c635efSGarrett D'Amore p->parent->body = p; 21595c635efSGarrett D'Amore break; 21695c635efSGarrett D'Amore default: 21795c635efSGarrett D'Amore break; 21895c635efSGarrett D'Amore } 21995c635efSGarrett D'Amore 22095c635efSGarrett D'Amore man->last = p; 22195c635efSGarrett D'Amore 22295c635efSGarrett D'Amore switch (p->type) { 22395c635efSGarrett D'Amore case (MAN_TBL): 22495c635efSGarrett D'Amore /* FALLTHROUGH */ 22595c635efSGarrett D'Amore case (MAN_TEXT): 22695c635efSGarrett D'Amore if ( ! man_valid_post(man)) 22795c635efSGarrett D'Amore return(0); 22895c635efSGarrett D'Amore break; 22995c635efSGarrett D'Amore default: 23095c635efSGarrett D'Amore break; 23195c635efSGarrett D'Amore } 23295c635efSGarrett D'Amore 23395c635efSGarrett D'Amore return(1); 23495c635efSGarrett D'Amore } 23595c635efSGarrett D'Amore 23695c635efSGarrett D'Amore 23795c635efSGarrett D'Amore static struct man_node * 238*698f87a4SGarrett D'Amore man_node_alloc(struct man *man, int line, int pos, 23995c635efSGarrett D'Amore enum man_type type, enum mant tok) 24095c635efSGarrett D'Amore { 24195c635efSGarrett D'Amore struct man_node *p; 24295c635efSGarrett D'Amore 24395c635efSGarrett D'Amore p = mandoc_calloc(1, sizeof(struct man_node)); 24495c635efSGarrett D'Amore p->line = line; 24595c635efSGarrett D'Amore p->pos = pos; 24695c635efSGarrett D'Amore p->type = type; 24795c635efSGarrett D'Amore p->tok = tok; 24895c635efSGarrett D'Amore 249*698f87a4SGarrett D'Amore if (MAN_NEWLINE & man->flags) 25095c635efSGarrett D'Amore p->flags |= MAN_LINE; 251*698f87a4SGarrett D'Amore man->flags &= ~MAN_NEWLINE; 25295c635efSGarrett D'Amore return(p); 25395c635efSGarrett D'Amore } 25495c635efSGarrett D'Amore 25595c635efSGarrett D'Amore 25695c635efSGarrett D'Amore int 257*698f87a4SGarrett D'Amore man_elem_alloc(struct man *man, int line, int pos, enum mant tok) 25895c635efSGarrett D'Amore { 25995c635efSGarrett D'Amore struct man_node *p; 26095c635efSGarrett D'Amore 261*698f87a4SGarrett D'Amore p = man_node_alloc(man, line, pos, MAN_ELEM, tok); 262*698f87a4SGarrett D'Amore if ( ! man_node_append(man, p)) 26395c635efSGarrett D'Amore return(0); 264*698f87a4SGarrett D'Amore man->next = MAN_NEXT_CHILD; 26595c635efSGarrett D'Amore return(1); 26695c635efSGarrett D'Amore } 26795c635efSGarrett D'Amore 26895c635efSGarrett D'Amore 26995c635efSGarrett D'Amore int 270*698f87a4SGarrett D'Amore man_tail_alloc(struct man *man, int line, int pos, enum mant tok) 27195c635efSGarrett D'Amore { 27295c635efSGarrett D'Amore struct man_node *p; 27395c635efSGarrett D'Amore 274*698f87a4SGarrett D'Amore p = man_node_alloc(man, line, pos, MAN_TAIL, tok); 275*698f87a4SGarrett D'Amore if ( ! man_node_append(man, p)) 27695c635efSGarrett D'Amore return(0); 277*698f87a4SGarrett D'Amore man->next = MAN_NEXT_CHILD; 27895c635efSGarrett D'Amore return(1); 27995c635efSGarrett D'Amore } 28095c635efSGarrett D'Amore 28195c635efSGarrett D'Amore 28295c635efSGarrett D'Amore int 283*698f87a4SGarrett D'Amore man_head_alloc(struct man *man, int line, int pos, enum mant tok) 28495c635efSGarrett D'Amore { 28595c635efSGarrett D'Amore struct man_node *p; 28695c635efSGarrett D'Amore 287*698f87a4SGarrett D'Amore p = man_node_alloc(man, line, pos, MAN_HEAD, tok); 288*698f87a4SGarrett D'Amore if ( ! man_node_append(man, p)) 28995c635efSGarrett D'Amore return(0); 290*698f87a4SGarrett D'Amore man->next = MAN_NEXT_CHILD; 29195c635efSGarrett D'Amore return(1); 29295c635efSGarrett D'Amore } 29395c635efSGarrett D'Amore 29495c635efSGarrett D'Amore 29595c635efSGarrett D'Amore int 296*698f87a4SGarrett D'Amore man_body_alloc(struct man *man, int line, int pos, enum mant tok) 29795c635efSGarrett D'Amore { 29895c635efSGarrett D'Amore struct man_node *p; 29995c635efSGarrett D'Amore 300*698f87a4SGarrett D'Amore p = man_node_alloc(man, line, pos, MAN_BODY, tok); 301*698f87a4SGarrett D'Amore if ( ! man_node_append(man, p)) 30295c635efSGarrett D'Amore return(0); 303*698f87a4SGarrett D'Amore man->next = MAN_NEXT_CHILD; 30495c635efSGarrett D'Amore return(1); 30595c635efSGarrett D'Amore } 30695c635efSGarrett D'Amore 30795c635efSGarrett D'Amore 30895c635efSGarrett D'Amore int 309*698f87a4SGarrett D'Amore man_block_alloc(struct man *man, int line, int pos, enum mant tok) 31095c635efSGarrett D'Amore { 31195c635efSGarrett D'Amore struct man_node *p; 31295c635efSGarrett D'Amore 313*698f87a4SGarrett D'Amore p = man_node_alloc(man, line, pos, MAN_BLOCK, tok); 314*698f87a4SGarrett D'Amore if ( ! man_node_append(man, p)) 31595c635efSGarrett D'Amore return(0); 316*698f87a4SGarrett D'Amore man->next = MAN_NEXT_CHILD; 31795c635efSGarrett D'Amore return(1); 31895c635efSGarrett D'Amore } 31995c635efSGarrett D'Amore 32095c635efSGarrett D'Amore int 321*698f87a4SGarrett D'Amore man_word_alloc(struct man *man, int line, int pos, const char *word) 32295c635efSGarrett D'Amore { 32395c635efSGarrett D'Amore struct man_node *n; 32495c635efSGarrett D'Amore 325*698f87a4SGarrett D'Amore n = man_node_alloc(man, line, pos, MAN_TEXT, MAN_MAX); 326*698f87a4SGarrett D'Amore n->string = roff_strdup(man->roff, word); 32795c635efSGarrett D'Amore 328*698f87a4SGarrett D'Amore if ( ! man_node_append(man, n)) 32995c635efSGarrett D'Amore return(0); 33095c635efSGarrett D'Amore 331*698f87a4SGarrett D'Amore man->next = MAN_NEXT_SIBLING; 33295c635efSGarrett D'Amore return(1); 33395c635efSGarrett D'Amore } 33495c635efSGarrett D'Amore 33595c635efSGarrett D'Amore 33695c635efSGarrett D'Amore /* 33795c635efSGarrett D'Amore * Free all of the resources held by a node. This does NOT unlink a 33895c635efSGarrett D'Amore * node from its context; for that, see man_node_unlink(). 33995c635efSGarrett D'Amore */ 34095c635efSGarrett D'Amore static void 34195c635efSGarrett D'Amore man_node_free(struct man_node *p) 34295c635efSGarrett D'Amore { 34395c635efSGarrett D'Amore 34495c635efSGarrett D'Amore if (p->string) 34595c635efSGarrett D'Amore free(p->string); 34695c635efSGarrett D'Amore free(p); 34795c635efSGarrett D'Amore } 34895c635efSGarrett D'Amore 34995c635efSGarrett D'Amore 35095c635efSGarrett D'Amore void 351*698f87a4SGarrett D'Amore man_node_delete(struct man *man, struct man_node *p) 35295c635efSGarrett D'Amore { 35395c635efSGarrett D'Amore 35495c635efSGarrett D'Amore while (p->child) 355*698f87a4SGarrett D'Amore man_node_delete(man, p->child); 35695c635efSGarrett D'Amore 357*698f87a4SGarrett D'Amore man_node_unlink(man, p); 35895c635efSGarrett D'Amore man_node_free(p); 35995c635efSGarrett D'Amore } 36095c635efSGarrett D'Amore 36195c635efSGarrett D'Amore int 362*698f87a4SGarrett D'Amore man_addeqn(struct man *man, const struct eqn *ep) 36395c635efSGarrett D'Amore { 36495c635efSGarrett D'Amore struct man_node *n; 36595c635efSGarrett D'Amore 366*698f87a4SGarrett D'Amore assert( ! (MAN_HALT & man->flags)); 36795c635efSGarrett D'Amore 368*698f87a4SGarrett D'Amore n = man_node_alloc(man, ep->ln, ep->pos, MAN_EQN, MAN_MAX); 36995c635efSGarrett D'Amore n->eqn = ep; 37095c635efSGarrett D'Amore 371*698f87a4SGarrett D'Amore if ( ! man_node_append(man, n)) 37295c635efSGarrett D'Amore return(0); 37395c635efSGarrett D'Amore 374*698f87a4SGarrett D'Amore man->next = MAN_NEXT_SIBLING; 375*698f87a4SGarrett D'Amore return(man_descope(man, ep->ln, ep->pos)); 37695c635efSGarrett D'Amore } 37795c635efSGarrett D'Amore 37895c635efSGarrett D'Amore int 379*698f87a4SGarrett D'Amore man_addspan(struct man *man, const struct tbl_span *sp) 38095c635efSGarrett D'Amore { 38195c635efSGarrett D'Amore struct man_node *n; 38295c635efSGarrett D'Amore 383*698f87a4SGarrett D'Amore assert( ! (MAN_HALT & man->flags)); 38495c635efSGarrett D'Amore 385*698f87a4SGarrett D'Amore n = man_node_alloc(man, sp->line, 0, MAN_TBL, MAN_MAX); 38695c635efSGarrett D'Amore n->span = sp; 38795c635efSGarrett D'Amore 388*698f87a4SGarrett D'Amore if ( ! man_node_append(man, n)) 38995c635efSGarrett D'Amore return(0); 39095c635efSGarrett D'Amore 391*698f87a4SGarrett D'Amore man->next = MAN_NEXT_SIBLING; 392*698f87a4SGarrett D'Amore return(man_descope(man, sp->line, 0)); 39395c635efSGarrett D'Amore } 39495c635efSGarrett D'Amore 39595c635efSGarrett D'Amore static int 396*698f87a4SGarrett D'Amore man_descope(struct man *man, int line, int offs) 39795c635efSGarrett D'Amore { 39895c635efSGarrett D'Amore /* 39995c635efSGarrett D'Amore * Co-ordinate what happens with having a next-line scope open: 40095c635efSGarrett D'Amore * first close out the element scope (if applicable), then close 40195c635efSGarrett D'Amore * out the block scope (also if applicable). 40295c635efSGarrett D'Amore */ 40395c635efSGarrett D'Amore 404*698f87a4SGarrett D'Amore if (MAN_ELINE & man->flags) { 405*698f87a4SGarrett D'Amore man->flags &= ~MAN_ELINE; 406*698f87a4SGarrett D'Amore if ( ! man_unscope(man, man->last->parent, MANDOCERR_MAX)) 40795c635efSGarrett D'Amore return(0); 40895c635efSGarrett D'Amore } 40995c635efSGarrett D'Amore 410*698f87a4SGarrett D'Amore if ( ! (MAN_BLINE & man->flags)) 41195c635efSGarrett D'Amore return(1); 412*698f87a4SGarrett D'Amore man->flags &= ~MAN_BLINE; 41395c635efSGarrett D'Amore 414*698f87a4SGarrett D'Amore if ( ! man_unscope(man, man->last->parent, MANDOCERR_MAX)) 41595c635efSGarrett D'Amore return(0); 416*698f87a4SGarrett D'Amore return(man_body_alloc(man, line, offs, man->last->tok)); 41795c635efSGarrett D'Amore } 41895c635efSGarrett D'Amore 41995c635efSGarrett D'Amore static int 420*698f87a4SGarrett D'Amore man_ptext(struct man *man, int line, char *buf, int offs) 42195c635efSGarrett D'Amore { 42295c635efSGarrett D'Amore int i; 42395c635efSGarrett D'Amore 42495c635efSGarrett D'Amore /* Literal free-form text whitespace is preserved. */ 42595c635efSGarrett D'Amore 426*698f87a4SGarrett D'Amore if (MAN_LITERAL & man->flags) { 427*698f87a4SGarrett D'Amore if ( ! man_word_alloc(man, line, offs, buf + offs)) 42895c635efSGarrett D'Amore return(0); 429*698f87a4SGarrett D'Amore return(man_descope(man, line, offs)); 43095c635efSGarrett D'Amore } 43195c635efSGarrett D'Amore 43295c635efSGarrett D'Amore for (i = offs; ' ' == buf[i]; i++) 43395c635efSGarrett D'Amore /* Skip leading whitespace. */ ; 43495c635efSGarrett D'Amore 435*698f87a4SGarrett D'Amore /* 436*698f87a4SGarrett D'Amore * Blank lines are ignored right after headings 437*698f87a4SGarrett D'Amore * but add a single vertical space elsewhere. 438*698f87a4SGarrett D'Amore */ 439*698f87a4SGarrett D'Amore 44095c635efSGarrett D'Amore if ('\0' == buf[i]) { 44195c635efSGarrett D'Amore /* Allocate a blank entry. */ 442*698f87a4SGarrett D'Amore if (MAN_SH != man->last->tok && 443*698f87a4SGarrett D'Amore MAN_SS != man->last->tok) { 444*698f87a4SGarrett D'Amore if ( ! man_elem_alloc(man, line, offs, MAN_sp)) 44595c635efSGarrett D'Amore return(0); 446*698f87a4SGarrett D'Amore man->next = MAN_NEXT_SIBLING; 447*698f87a4SGarrett D'Amore } 448*698f87a4SGarrett D'Amore return(1); 44995c635efSGarrett D'Amore } 45095c635efSGarrett D'Amore 45195c635efSGarrett D'Amore /* 45295c635efSGarrett D'Amore * Warn if the last un-escaped character is whitespace. Then 45395c635efSGarrett D'Amore * strip away the remaining spaces (tabs stay!). 45495c635efSGarrett D'Amore */ 45595c635efSGarrett D'Amore 45695c635efSGarrett D'Amore i = (int)strlen(buf); 45795c635efSGarrett D'Amore assert(i); 45895c635efSGarrett D'Amore 45995c635efSGarrett D'Amore if (' ' == buf[i - 1] || '\t' == buf[i - 1]) { 46095c635efSGarrett D'Amore if (i > 1 && '\\' != buf[i - 2]) 461*698f87a4SGarrett D'Amore man_pmsg(man, line, i - 1, MANDOCERR_EOLNSPACE); 46295c635efSGarrett D'Amore 46395c635efSGarrett D'Amore for (--i; i && ' ' == buf[i]; i--) 46495c635efSGarrett D'Amore /* Spin back to non-space. */ ; 46595c635efSGarrett D'Amore 46695c635efSGarrett D'Amore /* Jump ahead of escaped whitespace. */ 46795c635efSGarrett D'Amore i += '\\' == buf[i] ? 2 : 1; 46895c635efSGarrett D'Amore 46995c635efSGarrett D'Amore buf[i] = '\0'; 47095c635efSGarrett D'Amore } 47195c635efSGarrett D'Amore 472*698f87a4SGarrett D'Amore if ( ! man_word_alloc(man, line, offs, buf + offs)) 47395c635efSGarrett D'Amore return(0); 47495c635efSGarrett D'Amore 47595c635efSGarrett D'Amore /* 47695c635efSGarrett D'Amore * End-of-sentence check. If the last character is an unescaped 47795c635efSGarrett D'Amore * EOS character, then flag the node as being the end of a 47895c635efSGarrett D'Amore * sentence. The front-end will know how to interpret this. 47995c635efSGarrett D'Amore */ 48095c635efSGarrett D'Amore 48195c635efSGarrett D'Amore assert(i); 48295c635efSGarrett D'Amore if (mandoc_eos(buf, (size_t)i, 0)) 483*698f87a4SGarrett D'Amore man->last->flags |= MAN_EOS; 48495c635efSGarrett D'Amore 485*698f87a4SGarrett D'Amore return(man_descope(man, line, offs)); 48695c635efSGarrett D'Amore } 48795c635efSGarrett D'Amore 48895c635efSGarrett D'Amore static int 489*698f87a4SGarrett D'Amore man_pmacro(struct man *man, int ln, char *buf, int offs) 49095c635efSGarrett D'Amore { 49195c635efSGarrett D'Amore int i, ppos; 49295c635efSGarrett D'Amore enum mant tok; 49395c635efSGarrett D'Amore char mac[5]; 49495c635efSGarrett D'Amore struct man_node *n; 49595c635efSGarrett D'Amore 49695c635efSGarrett D'Amore if ('"' == buf[offs]) { 497*698f87a4SGarrett D'Amore man_pmsg(man, ln, offs, MANDOCERR_BADCOMMENT); 49895c635efSGarrett D'Amore return(1); 49995c635efSGarrett D'Amore } else if ('\0' == buf[offs]) 50095c635efSGarrett D'Amore return(1); 50195c635efSGarrett D'Amore 50295c635efSGarrett D'Amore ppos = offs; 50395c635efSGarrett D'Amore 50495c635efSGarrett D'Amore /* 50595c635efSGarrett D'Amore * Copy the first word into a nil-terminated buffer. 50695c635efSGarrett D'Amore * Stop copying when a tab, space, or eoln is encountered. 50795c635efSGarrett D'Amore */ 50895c635efSGarrett D'Amore 50995c635efSGarrett D'Amore i = 0; 51095c635efSGarrett D'Amore while (i < 4 && '\0' != buf[offs] && 51195c635efSGarrett D'Amore ' ' != buf[offs] && '\t' != buf[offs]) 51295c635efSGarrett D'Amore mac[i++] = buf[offs++]; 51395c635efSGarrett D'Amore 51495c635efSGarrett D'Amore mac[i] = '\0'; 51595c635efSGarrett D'Amore 51695c635efSGarrett D'Amore tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX; 51795c635efSGarrett D'Amore 51895c635efSGarrett D'Amore if (MAN_MAX == tok) { 519*698f87a4SGarrett D'Amore mandoc_vmsg(MANDOCERR_MACRO, man->parse, ln, 52095c635efSGarrett D'Amore ppos, "%s", buf + ppos - 1); 52195c635efSGarrett D'Amore return(1); 52295c635efSGarrett D'Amore } 52395c635efSGarrett D'Amore 52495c635efSGarrett D'Amore /* The macro is sane. Jump to the next word. */ 52595c635efSGarrett D'Amore 52695c635efSGarrett D'Amore while (buf[offs] && ' ' == buf[offs]) 52795c635efSGarrett D'Amore offs++; 52895c635efSGarrett D'Amore 52995c635efSGarrett D'Amore /* 53095c635efSGarrett D'Amore * Trailing whitespace. Note that tabs are allowed to be passed 53195c635efSGarrett D'Amore * into the parser as "text", so we only warn about spaces here. 53295c635efSGarrett D'Amore */ 53395c635efSGarrett D'Amore 53495c635efSGarrett D'Amore if ('\0' == buf[offs] && ' ' == buf[offs - 1]) 535*698f87a4SGarrett D'Amore man_pmsg(man, ln, offs - 1, MANDOCERR_EOLNSPACE); 53695c635efSGarrett D'Amore 53795c635efSGarrett D'Amore /* 53895c635efSGarrett D'Amore * Remove prior ELINE macro, as it's being clobbered by a new 53995c635efSGarrett D'Amore * macro. Note that NSCOPED macros do not close out ELINE 54095c635efSGarrett D'Amore * macros---they don't print text---so we let those slip by. 54195c635efSGarrett D'Amore */ 54295c635efSGarrett D'Amore 54395c635efSGarrett D'Amore if ( ! (MAN_NSCOPED & man_macros[tok].flags) && 544*698f87a4SGarrett D'Amore man->flags & MAN_ELINE) { 545*698f87a4SGarrett D'Amore n = man->last; 54695c635efSGarrett D'Amore assert(MAN_TEXT != n->type); 54795c635efSGarrett D'Amore 54895c635efSGarrett D'Amore /* Remove repeated NSCOPED macros causing ELINE. */ 54995c635efSGarrett D'Amore 55095c635efSGarrett D'Amore if (MAN_NSCOPED & man_macros[n->tok].flags) 55195c635efSGarrett D'Amore n = n->parent; 55295c635efSGarrett D'Amore 553*698f87a4SGarrett D'Amore mandoc_vmsg(MANDOCERR_LINESCOPE, man->parse, n->line, 55495c635efSGarrett D'Amore n->pos, "%s breaks %s", man_macronames[tok], 55595c635efSGarrett D'Amore man_macronames[n->tok]); 55695c635efSGarrett D'Amore 557*698f87a4SGarrett D'Amore man_node_delete(man, n); 558*698f87a4SGarrett D'Amore man->flags &= ~MAN_ELINE; 55995c635efSGarrett D'Amore } 56095c635efSGarrett D'Amore 56195c635efSGarrett D'Amore /* 56295c635efSGarrett D'Amore * Remove prior BLINE macro that is being clobbered. 56395c635efSGarrett D'Amore */ 564*698f87a4SGarrett D'Amore if ((man->flags & MAN_BLINE) && 56595c635efSGarrett D'Amore (MAN_BSCOPE & man_macros[tok].flags)) { 566*698f87a4SGarrett D'Amore n = man->last; 56795c635efSGarrett D'Amore 56895c635efSGarrett D'Amore /* Might be a text node like 8 in 56995c635efSGarrett D'Amore * .TP 8 57095c635efSGarrett D'Amore * .SH foo 57195c635efSGarrett D'Amore */ 57295c635efSGarrett D'Amore if (MAN_TEXT == n->type) 57395c635efSGarrett D'Amore n = n->parent; 57495c635efSGarrett D'Amore 57595c635efSGarrett D'Amore /* Remove element that didn't end BLINE, if any. */ 57695c635efSGarrett D'Amore if ( ! (MAN_BSCOPE & man_macros[n->tok].flags)) 57795c635efSGarrett D'Amore n = n->parent; 57895c635efSGarrett D'Amore 57995c635efSGarrett D'Amore assert(MAN_HEAD == n->type); 58095c635efSGarrett D'Amore n = n->parent; 58195c635efSGarrett D'Amore assert(MAN_BLOCK == n->type); 58295c635efSGarrett D'Amore assert(MAN_SCOPED & man_macros[n->tok].flags); 58395c635efSGarrett D'Amore 584*698f87a4SGarrett D'Amore mandoc_vmsg(MANDOCERR_LINESCOPE, man->parse, n->line, 58595c635efSGarrett D'Amore n->pos, "%s breaks %s", man_macronames[tok], 58695c635efSGarrett D'Amore man_macronames[n->tok]); 58795c635efSGarrett D'Amore 588*698f87a4SGarrett D'Amore man_node_delete(man, n); 589*698f87a4SGarrett D'Amore man->flags &= ~MAN_BLINE; 59095c635efSGarrett D'Amore } 59195c635efSGarrett D'Amore 59295c635efSGarrett D'Amore /* 59395c635efSGarrett D'Amore * Save the fact that we're in the next-line for a block. In 59495c635efSGarrett D'Amore * this way, embedded roff instructions can "remember" state 59595c635efSGarrett D'Amore * when they exit. 59695c635efSGarrett D'Amore */ 59795c635efSGarrett D'Amore 598*698f87a4SGarrett D'Amore if (MAN_BLINE & man->flags) 599*698f87a4SGarrett D'Amore man->flags |= MAN_BPLINE; 60095c635efSGarrett D'Amore 60195c635efSGarrett D'Amore /* Call to handler... */ 60295c635efSGarrett D'Amore 60395c635efSGarrett D'Amore assert(man_macros[tok].fp); 604*698f87a4SGarrett D'Amore if ( ! (*man_macros[tok].fp)(man, tok, ln, ppos, &offs, buf)) 60595c635efSGarrett D'Amore goto err; 60695c635efSGarrett D'Amore 60795c635efSGarrett D'Amore /* 60895c635efSGarrett D'Amore * We weren't in a block-line scope when entering the 60995c635efSGarrett D'Amore * above-parsed macro, so return. 61095c635efSGarrett D'Amore */ 61195c635efSGarrett D'Amore 612*698f87a4SGarrett D'Amore if ( ! (MAN_BPLINE & man->flags)) { 613*698f87a4SGarrett D'Amore man->flags &= ~MAN_ILINE; 61495c635efSGarrett D'Amore return(1); 61595c635efSGarrett D'Amore } 616*698f87a4SGarrett D'Amore man->flags &= ~MAN_BPLINE; 61795c635efSGarrett D'Amore 61895c635efSGarrett D'Amore /* 61995c635efSGarrett D'Amore * If we're in a block scope, then allow this macro to slip by 62095c635efSGarrett D'Amore * without closing scope around it. 62195c635efSGarrett D'Amore */ 62295c635efSGarrett D'Amore 623*698f87a4SGarrett D'Amore if (MAN_ILINE & man->flags) { 624*698f87a4SGarrett D'Amore man->flags &= ~MAN_ILINE; 62595c635efSGarrett D'Amore return(1); 62695c635efSGarrett D'Amore } 62795c635efSGarrett D'Amore 62895c635efSGarrett D'Amore /* 62995c635efSGarrett D'Amore * If we've opened a new next-line element scope, then return 63095c635efSGarrett D'Amore * now, as the next line will close out the block scope. 63195c635efSGarrett D'Amore */ 63295c635efSGarrett D'Amore 633*698f87a4SGarrett D'Amore if (MAN_ELINE & man->flags) 63495c635efSGarrett D'Amore return(1); 63595c635efSGarrett D'Amore 63695c635efSGarrett D'Amore /* Close out the block scope opened in the prior line. */ 63795c635efSGarrett D'Amore 638*698f87a4SGarrett D'Amore assert(MAN_BLINE & man->flags); 639*698f87a4SGarrett D'Amore man->flags &= ~MAN_BLINE; 64095c635efSGarrett D'Amore 641*698f87a4SGarrett D'Amore if ( ! man_unscope(man, man->last->parent, MANDOCERR_MAX)) 64295c635efSGarrett D'Amore return(0); 643*698f87a4SGarrett D'Amore return(man_body_alloc(man, ln, ppos, man->last->tok)); 64495c635efSGarrett D'Amore 64595c635efSGarrett D'Amore err: /* Error out. */ 64695c635efSGarrett D'Amore 647*698f87a4SGarrett D'Amore man->flags |= MAN_HALT; 64895c635efSGarrett D'Amore return(0); 64995c635efSGarrett D'Amore } 65095c635efSGarrett D'Amore 65195c635efSGarrett D'Amore /* 652*698f87a4SGarrett D'Amore * Unlink a node from its context. If "man" is provided, the last parse 65395c635efSGarrett D'Amore * point will also be adjusted accordingly. 65495c635efSGarrett D'Amore */ 65595c635efSGarrett D'Amore static void 656*698f87a4SGarrett D'Amore man_node_unlink(struct man *man, struct man_node *n) 65795c635efSGarrett D'Amore { 65895c635efSGarrett D'Amore 65995c635efSGarrett D'Amore /* Adjust siblings. */ 66095c635efSGarrett D'Amore 66195c635efSGarrett D'Amore if (n->prev) 66295c635efSGarrett D'Amore n->prev->next = n->next; 66395c635efSGarrett D'Amore if (n->next) 66495c635efSGarrett D'Amore n->next->prev = n->prev; 66595c635efSGarrett D'Amore 66695c635efSGarrett D'Amore /* Adjust parent. */ 66795c635efSGarrett D'Amore 66895c635efSGarrett D'Amore if (n->parent) { 66995c635efSGarrett D'Amore n->parent->nchild--; 67095c635efSGarrett D'Amore if (n->parent->child == n) 67195c635efSGarrett D'Amore n->parent->child = n->prev ? n->prev : n->next; 67295c635efSGarrett D'Amore } 67395c635efSGarrett D'Amore 67495c635efSGarrett D'Amore /* Adjust parse point, if applicable. */ 67595c635efSGarrett D'Amore 676*698f87a4SGarrett D'Amore if (man && man->last == n) { 67795c635efSGarrett D'Amore /*XXX: this can occur when bailing from validation. */ 67895c635efSGarrett D'Amore /*assert(NULL == n->next);*/ 67995c635efSGarrett D'Amore if (n->prev) { 680*698f87a4SGarrett D'Amore man->last = n->prev; 681*698f87a4SGarrett D'Amore man->next = MAN_NEXT_SIBLING; 68295c635efSGarrett D'Amore } else { 683*698f87a4SGarrett D'Amore man->last = n->parent; 684*698f87a4SGarrett D'Amore man->next = MAN_NEXT_CHILD; 68595c635efSGarrett D'Amore } 68695c635efSGarrett D'Amore } 68795c635efSGarrett D'Amore 688*698f87a4SGarrett D'Amore if (man && man->first == n) 689*698f87a4SGarrett D'Amore man->first = NULL; 69095c635efSGarrett D'Amore } 69195c635efSGarrett D'Amore 69295c635efSGarrett D'Amore const struct mparse * 693*698f87a4SGarrett D'Amore man_mparse(const struct man *man) 69495c635efSGarrett D'Amore { 69595c635efSGarrett D'Amore 696*698f87a4SGarrett D'Amore assert(man && man->parse); 697*698f87a4SGarrett D'Amore return(man->parse); 69895c635efSGarrett D'Amore } 699