371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov/* $Id: mdoc.c,v 1.256 2015/10/30 19:04:16 schwarze Exp $ */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore/*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore *
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * copyright notice and this permission notice appear in all copies.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore *
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include "config.h"
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <sys/types.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <assert.h>
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov#include <ctype.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <stdarg.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <stdio.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <stdlib.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <string.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <time.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov#include "mandoc_aux.h"
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov#include "mandoc.h"
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov#include "roff.h"
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov#include "mdoc.h"
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include "libmandoc.h"
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov#include "roff_int.h"
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov#include "libmdoc.h"
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovconst char *const __mdoc_macronames[MDOC_MAX + 1] = {
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov "text",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Ap", "Dd", "Dt", "Os",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Sh", "Ss", "Pp", "D1",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Dl", "Bd", "Ed", "Bl",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "El", "It", "Ad", "An",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Ar", "Cd", "Cm", "Dv",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Er", "Ev", "Ex", "Fa",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Fd", "Fl", "Fn", "Ft",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Ic", "In", "Li", "Nd",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Nm", "Op", "Ot", "Pa",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Rv", "St", "Va", "Vt",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Xr", "%A", "%B", "%D",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "%I", "%J", "%N", "%O",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "%P", "%R", "%T", "%V",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Ac", "Ao", "Aq", "At",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Bc", "Bf", "Bo", "Bq",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Bsx", "Bx", "Db", "Dc",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Do", "Dq", "Ec", "Ef",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Em", "Eo", "Fx", "Ms",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "No", "Ns", "Nx", "Ox",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Pc", "Pf", "Po", "Pq",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Qc", "Ql", "Qo", "Qq",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Re", "Rs", "Sc", "So",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Sq", "Sm", "Sx", "Sy",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Tn", "Ux", "Xc", "Xo",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Fo", "Fc", "Oo", "Oc",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Bk", "Ek", "Bt", "Hf",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Fr", "Ud", "Lb", "Lp",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Lk", "Mt", "Brq", "Bro",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Brc", "%C", "Es", "En",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "Dx", "%Q", "br", "sp",
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov "%U", "Ta", "ll",
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov};
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovconst char *const __mdoc_argnames[MDOC_ARG_MAX] = {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "split", "nosplit", "ragged",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "unfilled", "literal", "file",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "offset", "bullet", "dash",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "hyphen", "item", "enum",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "tag", "diag", "hang",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "ohang", "inset", "column",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "width", "compact", "std",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "filled", "words", "emphasis",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "symbolic", "nested", "centered"
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore };
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovconst char * const *mdoc_macronames = __mdoc_macronames + 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreconst char * const *mdoc_argnames = __mdoc_argnames;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovstatic int mdoc_ptext(struct roff_man *, int, char *, int);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovstatic int mdoc_pmacro(struct roff_man *, int, char *, int);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore/*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Main parse routine. Parses a single line -- really just hands off to
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * the macro (mdoc_pmacro()) or text parser (mdoc_ptext()).
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreint
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovmdoc_parseln(struct roff_man *mdoc, int ln, char *buf, int offs)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (mdoc->last->type != ROFFT_EQN || ln > mdoc->last->line)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mdoc->flags |= MDOC_NEWLINE;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Let the roff nS register switch SYNOPSIS mode early,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * such that the parser knows at all times
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * whether this mode is on or off.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Note that this mode is also switched by the Sh macro.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore if (roff_getreg(mdoc->roff, "nS"))
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore mdoc->flags |= MDOC_SYNOPSIS;
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore else
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore mdoc->flags &= ~MDOC_SYNOPSIS;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return roff_getcontrol(mdoc->roff, buf, &offs) ?
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mdoc_pmacro(mdoc, ln, buf, offs) :
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mdoc_ptext(mdoc, ln, buf, offs);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovvoid
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoremdoc_macro(MACRO_PROT_ARGS)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov assert(tok > TOKEN_NONE && tok < MDOC_MAX);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov (*mdoc_macros[tok].fp)(mdoc, tok, line, ppos, pos, buf);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovvoid
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovmdoc_tail_alloc(struct roff_man *mdoc, int line, int pos, int tok)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov struct roff_node *p;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov p = roff_node_alloc(mdoc, line, pos, ROFFT_TAIL, tok);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov roff_node_append(mdoc, p);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mdoc->next = ROFF_NEXT_CHILD;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovstruct roff_node *
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovmdoc_endbody_alloc(struct roff_man *mdoc, int line, int pos, int tok,
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov struct roff_node *body, enum mdoc_endbody end)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov struct roff_node *p;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov body->flags |= MDOC_ENDED;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov body->parent->flags |= MDOC_ENDED;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov p = roff_node_alloc(mdoc, line, pos, ROFFT_BODY, tok);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov p->body = body;
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore p->norm = body->norm;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore p->end = end;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov roff_node_append(mdoc, p);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mdoc->next = ROFF_NEXT_SIBLING;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return p;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovstruct roff_node *
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovmdoc_block_alloc(struct roff_man *mdoc, int line, int pos,
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov int tok, struct mdoc_arg *args)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov struct roff_node *p;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov p = roff_node_alloc(mdoc, line, pos, ROFFT_BLOCK, tok);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore p->args = args;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (p->args)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore (args->refcnt)++;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore switch (tok) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case MDOC_Bd:
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case MDOC_Bf:
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case MDOC_Bl:
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case MDOC_En:
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case MDOC_Rs:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore p->norm = mandoc_calloc(1, sizeof(union mdoc_data));
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore default:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov roff_node_append(mdoc, p);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mdoc->next = ROFF_NEXT_CHILD;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return p;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovvoid
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovmdoc_elem_alloc(struct roff_man *mdoc, int line, int pos,
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov int tok, struct mdoc_arg *args)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov struct roff_node *p;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov p = roff_node_alloc(mdoc, line, pos, ROFFT_ELEM, tok);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore p->args = args;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (p->args)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore (args->refcnt)++;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore switch (tok) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case MDOC_An:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore p->norm = mandoc_calloc(1, sizeof(union mdoc_data));
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore default:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov roff_node_append(mdoc, p);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mdoc->next = ROFF_NEXT_CHILD;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amorevoid
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovmdoc_node_relink(struct roff_man *mdoc, struct roff_node *p)
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore{
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov roff_node_unlink(mdoc, p);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov p->prev = p->next = NULL;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov roff_node_append(mdoc, p);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore/*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Parse free-form text, that is, a line that does not begin with the
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * control character.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic int
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovmdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov struct roff_node *n;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore char *c, *ws, *end;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore assert(mdoc->last);
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore n = mdoc->last;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Divert directly to list processing if we're encountering a
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov * columnar ROFFT_BLOCK with or without a prior ROFFT_BLOCK entry
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov * (a ROFFT_BODY means it's already open, in which case we should
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * process within its context in the normal way).
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (n->tok == MDOC_Bl && n->type == ROFFT_BODY &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* `Bl' is open without any children. */
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore mdoc->flags |= MDOC_FREECOL;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (n->tok == MDOC_It && n->type == ROFFT_BLOCK &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov NULL != n->parent &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov MDOC_Bl == n->parent->tok &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov LIST_column == n->parent->norm->Bl.type) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* `Bl' has block-level `It' children. */
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore mdoc->flags |= MDOC_FREECOL;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Search for the beginning of unescaped trailing whitespace (ws)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * and for the first character not to be output (end).
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* FIXME: replace with strcspn(). */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ws = NULL;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore for (c = end = buf + offs; *c; c++) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore switch (*c) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore case ' ':
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (NULL == ws)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ws = c;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore continue;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore case '\t':
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Always warn about trailing tabs,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * even outside literal context,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * where they should be put on the next line.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (NULL == ws)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ws = c;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Strip trailing tabs in literal context only;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * outside, they affect the next line.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore if (MDOC_LITERAL & mdoc->flags)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore continue;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore case '\\':
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* Skip the escaped character, too, if any. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (c[1])
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore c++;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* FALLTHROUGH */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore default:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ws = NULL;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore end = c + 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore *end = '\0';
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (ws)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov line, (int)(ws-buf), NULL);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (buf[offs] == '\0' && ! (mdoc->flags & MDOC_LITERAL)) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_msg(MANDOCERR_FI_BLANK, mdoc->parse,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov line, (int)(c - buf), NULL);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Insert a `sp' in the case of a blank line. Technically,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * blank lines aren't allowed, but enough manuals assume this
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * behaviour that we want to work around it.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov roff_elem_alloc(mdoc, line, offs, MDOC_sp);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mdoc->last->flags |= MDOC_VALID | MDOC_ENDED;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mdoc->next = ROFF_NEXT_SIBLING;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov roff_word_alloc(mdoc, line, offs, buf+offs);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (mdoc->flags & MDOC_LITERAL)
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * End-of-sentence check. If the last character is an unescaped
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * EOS character, then flag the node as being the end of a
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * sentence. The front-end will know how to interpret this.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore assert(buf < end);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (mandoc_eos(buf+offs, (size_t)(end-buf-offs)))
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore mdoc->last->flags |= MDOC_EOS;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore/*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Parse a macro line, that is, a line beginning with the control
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * character.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic int
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovmdoc_pmacro(struct roff_man *mdoc, int ln, char *buf, int offs)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov struct roff_node *n;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov const char *cp;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov int tok;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore int i, sv;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore char mac[5];
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore sv = offs;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Copy the first word into a nil-terminated buffer.
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * Stop when a space, tab, escape, or eoln is encountered.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore i = 0;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov while (i < 4 && strchr(" \t\\", buf[offs]) == NULL)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore mac[i++] = buf[offs++];
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore mac[i] = '\0';
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov tok = (i > 1 && i < 4) ? mdoc_hash_find(mac) : TOKEN_NONE;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (tok == TOKEN_NONE) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_msg(MANDOCERR_MACRO, mdoc->parse,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov ln, sv, buf + sv - 1);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /* Skip a leading escape sequence or tab. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov switch (buf[offs]) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case '\\':
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov cp = buf + offs + 1;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_escape(&cp, NULL, NULL);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov offs = cp - buf;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov break;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case '\t':
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore offs++;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov break;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov default:
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov break;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* Jump to the next non-whitespace word. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore while (buf[offs] && ' ' == buf[offs])
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore offs++;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Trailing whitespace. Note that tabs are allowed to be passed
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * into the parser as "text", so we only warn about spaces here.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if ('\0' == buf[offs] && ' ' == buf[offs - 1])
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov ln, offs - 1, NULL);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * If an initial macro or a list invocation, divert directly
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * into macro processing.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore if (NULL == mdoc->last || MDOC_It == tok || MDOC_El == tok) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mdoc_macro(mdoc, tok, ln, sv, &offs, buf);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore n = mdoc->last;
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore assert(mdoc->last);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * If the first macro of a `Bl -column', open an `It' block
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * context around the parsed macro.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (n->tok == MDOC_Bl && n->type == ROFFT_BODY &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) {
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore mdoc->flags |= MDOC_FREECOL;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * If we're following a block-level `It' within a `Bl -column'
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * context (perhaps opened in the above block or in ptext()),
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * then open an `It' block context around the parsed macro.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (n->tok == MDOC_It && n->type == ROFFT_BLOCK &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov NULL != n->parent &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov MDOC_Bl == n->parent->tok &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov LIST_column == n->parent->norm->Bl.type) {
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore mdoc->flags |= MDOC_FREECOL;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* Normal processing of a macro. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mdoc_macro(mdoc, tok, ln, sv, &offs, buf);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /* In quick mode (for mandocdb), abort after the NAME section. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (mdoc->quick && MDOC_Sh == tok &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov SEC_NAME != mdoc->last->sec)
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 2;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreenum mdelim
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoremdoc_isdelim(const char *p)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if ('\0' == p[0])
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return DELIM_NONE;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if ('\0' == p[1])
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore switch (p[0]) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case '(':
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case '[':
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return DELIM_OPEN;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case '|':
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return DELIM_MIDDLE;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case '.':
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case ',':
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case ';':
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case ':':
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case '?':
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case '!':
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case ')':
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case ']':
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return DELIM_CLOSE;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore default:
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return DELIM_NONE;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if ('\\' != p[0])
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return DELIM_NONE;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (0 == strcmp(p + 1, "."))
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return DELIM_CLOSE;
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore if (0 == strcmp(p + 1, "fR|\\fP"))
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return DELIM_MIDDLE;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return DELIM_NONE;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovvoid
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovmdoc_validate(struct roff_man *mdoc)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov{
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mdoc->last = mdoc->first;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mdoc_node_validate(mdoc);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mdoc_state_reset(mdoc);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov}