371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov/* $Id: read.c,v 1.149 2016/07/10 13:34:30 schwarze Exp $ */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore/*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov * Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org>
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * Copyright (c) 2010, 2012 Joerg Sonnenberger <joerg@netbsd.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
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov#include <sys/types.h>
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov#if HAVE_MMAP
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov#include <sys/mman.h>
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov#include <sys/stat.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#endif
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <assert.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <ctype.h>
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov#if HAVE_ERR
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov#include <err.h>
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov#endif
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov#include <errno.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <fcntl.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <stdarg.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <stdint.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <stdio.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <stdlib.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <string.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include <unistd.h>
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov#include <zlib.h>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov#include "mandoc_aux.h"
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov#include "mandoc.h"
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov#include "roff.h"
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include "mdoc.h"
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#include "man.h"
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov#include "libmandoc.h"
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov#include "roff_int.h"
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#define REPARSE_LIMIT 1000
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestruct mparse {
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov struct roff_man *man; /* man parser */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore struct roff *roff; /* roff parser (!NULL) */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov char *sodest; /* filename pointed to by .so */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov const char *file; /* filename of current input file */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov struct buf *primary; /* buffer currently being parsed */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov struct buf *secondary; /* preprocessed copy of input */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov const char *defos; /* default operating system */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore mandocmsg mmsg; /* warning/error message handler */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov enum mandoclevel file_status; /* status of current parse */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov enum mandoclevel wlevel; /* ignore messages below this */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov int options; /* parser options */
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov int gzip; /* current input file is gzipped */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov int filenc; /* encoding of the current file */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov int reparse_count; /* finite interp. stack */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov int line; /* line number in the file */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore};
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovstatic void choose_parser(struct mparse *);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic void resize_buf(struct buf *, size_t);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovstatic void mparse_buf_r(struct mparse *, struct buf, size_t, int);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovstatic int read_whole_file(struct mparse *, const char *, int,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov struct buf *, int *);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic void mparse_end(struct mparse *);
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amorestatic void mparse_parse_buffer(struct mparse *, struct buf,
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore const char *);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic const enum mandocerr mandoclimits[MANDOCLEVEL_MAX] = {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore MANDOCERR_OK,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore MANDOCERR_WARNING,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore MANDOCERR_WARNING,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore MANDOCERR_ERROR,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov MANDOCERR_UNSUPP,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore MANDOCERR_MAX,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore MANDOCERR_MAX
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore};
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic const char * const mandocerrs[MANDOCERR_MAX] = {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "ok",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "generic warning",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* related to the prologue */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing manual title, using UNTITLED",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing manual title, using \"\"",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "lower case character in document title",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing manual section, using \"\"",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "unknown manual section",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing date, using today's date",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "cannot parse date, using it verbatim",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing Os macro, using \"\"",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "duplicate prologue macro",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "late prologue macro",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "skipping late title macro",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "prologue macros out of order",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* related to document structure */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ".so is fragile, better use ln(1)",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "no document body",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "content before first section header",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "first section is not \"NAME\"",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "NAME section without name",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "NAME section without description",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "description not at the end of NAME",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "bad NAME section content",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing description line, using \"\"",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "sections out of conventional order",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "duplicate section title",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "unexpected section",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "unusual Xr order",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "unusual Xr punctuation",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "AUTHORS section without An macro",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* related to macros and nesting */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "obsolete macro",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "macro neither callable nor escaped",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "skipping paragraph macro",
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore "moving paragraph macro out of list",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "skipping no-space macro",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "blocks badly nested",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "nested displays are not portable",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "moving content out of list",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "fill mode already enabled, skipping",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "fill mode already disabled, skipping",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "line scope broken",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* related to missing macro arguments */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "skipping empty request",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "conditional request controls empty scope",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "skipping empty macro",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "empty block",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "empty argument, using 0n",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing display type, using -ragged",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "list type is not the first argument",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing -width in -tag list, using 8n",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing utility name, using \"\"",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing function name, using \"\"",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "empty head in list item",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "empty list item",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing font type, using \\fR",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "unknown font type, using \\fR",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "nothing follows prefix",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "empty reference block",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing -std argument, adding it",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing option string, using \"\"",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing resource identifier, using \"\"",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing eqn box, using \"\"",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* related to bad macro arguments */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "unterminated quoted argument",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "duplicate argument",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "skipping duplicate argument",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "skipping duplicate display type",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "skipping duplicate list type",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "skipping -width argument",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "wrong number of cells",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "unknown AT&T UNIX version",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "comma in function argument",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "parenthesis in function name",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "invalid content in Rs block",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "invalid Boolean argument",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "unknown font, skipping request",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "odd number of characters in request",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* related to plain text */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "blank line in fill mode, using .sp",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "tab in filled text",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "whitespace at end of input line",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "bad comment style",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "invalid escape sequence",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "undefined string, using \"\"",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /* related to tables */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "tbl line starts with span",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "tbl column starts with span",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "skipping vertical bar in tbl layout",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "generic error",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* related to tables */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "non-alphabetic character in tbl options",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "skipping unknown tbl option",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing tbl option argument",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "wrong tbl option argument size",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "empty tbl layout",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "invalid character in tbl layout",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "unmatched parenthesis in tbl layout",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "tbl without any data cells",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "ignoring data in spanned tbl cell",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "ignoring extra tbl data cells",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "data block open at end of tbl",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /* related to document structure and macros */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov NULL,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "input stack limit exceeded, infinite loop?",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "skipping bad character",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "skipping unknown macro",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "skipping insecure request",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "skipping item outside list",
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore "skipping column outside column list",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "skipping end of block that is not open",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "fewer RS blocks open, skipping",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "inserting missing end of block",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "appending missing end of block",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /* related to request and macro arguments */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "escaped character not allowed in a name",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "NOT IMPLEMENTED: Bd -file",
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov "skipping display without arguments",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing list type, using -item",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "missing manual name, using \"\"",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "uname(3) system call failed, using UNKNOWN",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "unknown standard specifier",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "skipping request without numeric argument",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "NOT IMPLEMENTED: .so with absolute path or \"..\"",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov ".so request failed",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "skipping all arguments",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "skipping excess arguments",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "divide by zero",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "unsupported feature",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "input too large",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "unsupported control character",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "unsupported roff request",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "eqn delim option in tbl",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "unsupported tbl layout modifier",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "ignoring macro in table",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore};
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic const char * const mandoclevels[MANDOCLEVEL_MAX] = {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "SUCCESS",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "RESERVED",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "WARNING",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "ERROR",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov "UNSUPP",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "BADARG",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "SYSERR"
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore};
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic void
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreresize_buf(struct buf *buf, size_t initial)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore buf->sz = buf->sz > initial/2 ? 2 * buf->sz : initial;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore buf->buf = mandoc_realloc(buf->buf, buf->sz);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic void
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovchoose_parser(struct mparse *curp)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov char *cp, *ep;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov int format;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * If neither command line arguments -mdoc or -man select
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * a parser nor the roff parser found a .Dd or .TH macro
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * yet, look ahead in the main input buffer.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if ((format = roff_getformat(curp->roff)) == 0) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov cp = curp->primary->buf;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov ep = cp + curp->primary->sz;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov while (cp < ep) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (*cp == '.' || *cp == '\'') {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov cp++;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (cp[0] == 'D' && cp[1] == 'd') {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov format = MPARSE_MDOC;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov break;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov }
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (cp[0] == 'T' && cp[1] == 'H') {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov format = MPARSE_MAN;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov break;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov }
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov }
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov cp = memchr(cp, '\n', ep - cp);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (cp == NULL)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov cp++;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (curp->man == NULL) {
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->man = roff_man_alloc(curp->roff, curp, curp->defos,
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->options & MPARSE_QUICK ? 1 : 0);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->man->macroset = MACROSET_MAN;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->man->first->tok = TOKEN_NONE;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (format == MPARSE_MDOC) {
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mdoc_hash_init();
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->man->macroset = MACROSET_MDOC;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->man->first->tok = TOKEN_NONE;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov } else {
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov man_hash_init();
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->man->macroset = MACROSET_MAN;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->man->first->tok = TOKEN_NONE;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore/*
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * Main parse routine for a buffer.
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * It assumes encoding and line numbering are already set up.
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * It can recurse directly (for invocations of user-defined
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * macros, inline equations, and input line traps)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * and indirectly (for .so file inclusion).
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic void
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovmparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore const struct tbl_span *span;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore struct buf ln;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov const char *save_file;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov char *cp;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov size_t pos; /* byte number in the ln buffer */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore enum rofferr rr;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov int of;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore int lnn; /* line number in the real file */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov int fd;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore unsigned char c;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov memset(&ln, 0, sizeof(ln));
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov lnn = curp->line;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov pos = 0;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov while (i < blk.sz) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (0 == pos && '\0' == blk.buf[i])
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (start) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp->line = lnn;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp->reparse_count = 0;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (lnn < 3 &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->filenc & MPARSE_UTF8 &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->filenc & MPARSE_LATIN1)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->filenc = preconv_cue(&blk, i);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov while (i < blk.sz && (start || blk.buf[i] != '\0')) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * When finding an unescaped newline character,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * leave the character loop to process the line.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Skip a preceding carriage return, if any.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if ('\r' == blk.buf[i] && i + 1 < blk.sz &&
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore '\n' == blk.buf[i + 1])
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ++i;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if ('\n' == blk.buf[i]) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ++i;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ++lnn;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore /*
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * Make sure we have space for the worst
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * case of 11 bytes: "\\[u10ffff]\0"
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore */
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (pos + 11 > ln.sz)
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore resize_buf(&ln, 256);
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /*
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * Encode 8-bit input.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov c = blk.buf[i];
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (c & 0x80) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if ( ! (curp->filenc && preconv_encode(
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov &blk, &i, &ln, &pos, &curp->filenc))) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_vmsg(MANDOCERR_CHAR_BAD, curp,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->line, pos, "0x%x", c);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov ln.buf[pos++] = '?';
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov i++;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov }
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov continue;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /*
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * Exclude control characters.
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (c == 0x7f || (c < 0x20 && c != 0x09)) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_vmsg(c == 0x00 || c == 0x04 ||
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov c > 0x0a ? MANDOCERR_CHAR_BAD :
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov MANDOCERR_CHAR_UNSUPP,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp, curp->line, pos, "0x%x", c);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore i++;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (c != '\r')
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov ln.buf[pos++] = '?';
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore continue;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* Trailing backslash = a plain char. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (blk.buf[i] != '\\' || i + 1 == blk.sz) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ln.buf[pos++] = blk.buf[i++];
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore continue;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Found escape and at least one other character.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * When it's a newline character, skip it.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * When there is a carriage return in between,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * skip that one as well.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if ('\r' == blk.buf[i + 1] && i + 2 < blk.sz &&
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore '\n' == blk.buf[i + 2])
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ++i;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if ('\n' == blk.buf[i + 1]) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore i += 2;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ++lnn;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore continue;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if ('"' == blk.buf[i + 1] || '#' == blk.buf[i + 1]) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore i += 2;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* Comment, skip to end of line */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov for (; i < blk.sz; ++i) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if ('\n' == blk.buf[i]) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ++i;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ++lnn;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* Backout trailing whitespaces */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore for (; pos > 0; --pos) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (ln.buf[pos - 1] != ' ')
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (pos > 2 && ln.buf[pos - 2] == '\\')
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore /* Catch escaped bogus characters. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore c = (unsigned char) blk.buf[i+1];
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if ( ! (isascii(c) &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov (isgraph(c) || isblank(c)))) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_vmsg(MANDOCERR_CHAR_BAD, curp,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->line, pos, "0x%x", c);
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore i += 2;
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore ln.buf[pos++] = '?';
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore continue;
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore }
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore /* Some other escape sequence, copy & cont. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ln.buf[pos++] = blk.buf[i++];
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ln.buf[pos++] = blk.buf[i++];
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (pos >= ln.sz)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore resize_buf(&ln, 256);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ln.buf[pos] = '\0';
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * A significant amount of complexity is contained by
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * the roff preprocessor. It's line-oriented but can be
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * expressed on one line, so we need at times to
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * readjust our starting point and re-run it. The roff
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * preprocessor can also readjust the buffers with new
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * data, so we pass them in wholesale.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore of = 0;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Maintain a lookaside buffer of all parsed lines. We
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * only do this if mparse_keep() has been invoked (the
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * buffer may be accessed with mparse_getkeep()).
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (curp->secondary) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->secondary->buf = mandoc_realloc(
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->secondary->buf,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->secondary->sz + pos + 2);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov memcpy(curp->secondary->buf +
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->secondary->sz,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov ln.buf, pos);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp->secondary->sz += pos;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp->secondary->buf
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore [curp->secondary->sz] = '\n';
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp->secondary->sz++;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp->secondary->buf
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore [curp->secondary->sz] = '\0';
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorererun:
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov rr = roff_parseln(curp->roff, curp->line, &ln, &of);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore switch (rr) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case ROFF_REPARSE:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (REPARSE_LIMIT >= ++curp->reparse_count)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mparse_buf_r(curp, ln, of, 0);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore else
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore mandoc_msg(MANDOCERR_ROFFLOOP, curp,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->line, pos, NULL);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore pos = 0;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore continue;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case ROFF_APPEND:
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov pos = strlen(ln.buf);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore continue;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case ROFF_RERUN:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore goto rerun;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case ROFF_IGN:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore pos = 0;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore continue;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case ROFF_SO:
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if ( ! (curp->options & MPARSE_SO) &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov (i >= blk.sz || blk.buf[i] == '\0')) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->sodest = mandoc_strdup(ln.buf + of);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov free(ln.buf);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov return;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * We remove `so' clauses from our lookaside
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * buffer because we're going to descend into
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * the file recursively.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (curp->secondary)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp->secondary->sz -= pos + 1;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov save_file = curp->file;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if ((fd = mparse_open(curp, ln.buf + of)) != -1) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mparse_readfd(curp, fd, ln.buf + of);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov close(fd);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->file = save_file;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov } else {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->file = save_file;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_vmsg(MANDOCERR_SO_FAIL,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp, curp->line, pos,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov ".so %s", ln.buf + of);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov ln.sz = mandoc_asprintf(&cp,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov ".sp\nSee the file %s.\n.sp",
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov ln.buf + of);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov free(ln.buf);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov ln.buf = cp;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov of = 0;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mparse_buf_r(curp, ln, of, 0);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore pos = 0;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore continue;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore default:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * If input parsers have not been allocated, do so now.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * We keep these instanced between parsers, but set them
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * locally per parse routine since we can use different
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * parsers with each one.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (curp->man == NULL ||
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->man->macroset == MACROSET_NONE)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov choose_parser(curp);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /*
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * Lastly, push down into the parsers themselves.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * If libroff returns ROFF_TBL, then add it to the
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * currently open parse. Since we only get here if
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * there does exist data (see tbl_data.c), we're
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * guaranteed that something's been allocated.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Do the same for ROFF_EQN.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (rr == ROFF_TBL)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov while ((span = roff_span(curp->roff)) != NULL)
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov roff_addtbl(curp->man, span);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov else if (rr == ROFF_EQN)
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov roff_addeqn(curp->man, roff_eqn(curp->roff));
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov else if ((curp->man->macroset == MACROSET_MDOC ?
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mdoc_parseln(curp->man, curp->line, ln.buf, of) :
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov man_parseln(curp->man, curp->line, ln.buf, of)) == 2)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* Temporary buffers typically are not full. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (0 == start && '\0' == blk.buf[i])
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* Start the next input line. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore pos = 0;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore free(ln.buf);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic int
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovread_whole_file(struct mparse *curp, const char *file, int fd,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov struct buf *fb, int *with_mmap)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov gzFile gz;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore size_t off;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ssize_t ssz;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov#if HAVE_MMAP
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore struct stat st;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (fstat(fd, &st) == -1)
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov err((int)MANDOCLEVEL_SYSERR, "%s", file);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * If we're a regular file, try just reading in the whole entry
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * via mmap(). This is faster than reading it into blocks, and
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * since each file is only a few bytes to begin with, I'm not
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * concerned that this is going to tank any machines.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (curp->gzip == 0 && S_ISREG(st.st_mode)) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (st.st_size > 0x7fffffff) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_msg(MANDOCERR_TOOLARGE, curp, 0, 0, NULL);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 0;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore *with_mmap = 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore fb->sz = (size_t)st.st_size;
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore fb->buf = mmap(NULL, fb->sz, PROT_READ, MAP_SHARED, fd, 0);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (fb->buf != MAP_FAILED)
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#endif
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (curp->gzip) {
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if ((gz = gzdopen(fd, "rb")) == NULL)
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov err((int)MANDOCLEVEL_SYSERR, "%s", file);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov } else
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov gz = NULL;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /*
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * If this isn't a regular file (like, say, stdin), then we must
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * go the old way and just read things in bit by bit.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore *with_mmap = 0;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore off = 0;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore fb->sz = 0;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore fb->buf = NULL;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore for (;;) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (off == fb->sz) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (fb->sz == (1U << 31)) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_msg(MANDOCERR_TOOLARGE, curp,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov 0, 0, NULL);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore break;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore resize_buf(fb, 65536);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov ssz = curp->gzip ?
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov gzread(gz, fb->buf + (int)off, fb->sz - off) :
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov read(fd, fb->buf + (int)off, fb->sz - off);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (ssz == 0) {
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore fb->sz = off;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (ssz == -1)
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov err((int)MANDOCLEVEL_SYSERR, "%s", file);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore off += (size_t)ssz;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore free(fb->buf);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore fb->buf = NULL;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return 0;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic void
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoremparse_end(struct mparse *curp)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (curp->man == NULL && curp->sodest == NULL)
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->man = roff_man_alloc(curp->roff, curp, curp->defos,
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->options & MPARSE_QUICK ? 1 : 0);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (curp->man->macroset == MACROSET_NONE)
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->man->macroset = MACROSET_MAN;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (curp->man->macroset == MACROSET_MDOC)
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mdoc_endparse(curp->man);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov else
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov man_endparse(curp->man);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore roff_endparse(curp->roff);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic void
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amoremparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov struct buf *svprimary;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore const char *svfile;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov size_t offset;
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore static int recursion_depth;
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore if (64 < recursion_depth) {
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore mandoc_msg(MANDOCERR_ROFFLOOP, curp, curp->line, 0, NULL);
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore return;
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* Line number is per-file. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore svfile = curp->file;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp->file = file;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov svprimary = curp->primary;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->primary = &blk;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp->line = 1;
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore recursion_depth++;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /* Skip an UTF-8 byte order mark. */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (curp->filenc & MPARSE_UTF8 && blk.sz > 2 &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov (unsigned char)blk.buf[0] == 0xef &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov (unsigned char)blk.buf[1] == 0xbb &&
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov (unsigned char)blk.buf[2] == 0xbf) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov offset = 3;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->filenc &= ~MPARSE_LATIN1;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov } else
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov offset = 0;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mparse_buf_r(curp, blk, offset, 1);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (--recursion_depth == 0)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore mparse_end(curp);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->primary = svprimary;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp->file = svfile;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreenum mandoclevel
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovmparse_readmem(struct mparse *curp, void *buf, size_t len,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore const char *file)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore struct buf blk;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov blk.buf = buf;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore blk.sz = len;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore mparse_parse_buffer(curp, blk, file);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return curp->file_status;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov/*
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * Read the whole file into memory and call the parsers.
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * Called recursively when an .so request is encountered.
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov */
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amoreenum mandoclevel
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amoremparse_readfd(struct mparse *curp, int fd, const char *file)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore struct buf blk;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore int with_mmap;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov int save_filenc;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (read_whole_file(curp, file, fd, &blk, &with_mmap)) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov save_filenc = curp->filenc;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->filenc = curp->options &
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov (MPARSE_UTF8 | MPARSE_LATIN1);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mparse_parse_buffer(curp, blk, file);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->filenc = save_filenc;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov#if HAVE_MMAP
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (with_mmap)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov munmap(blk.buf, blk.sz);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov else
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov#endif
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov free(blk.buf);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov }
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return curp->file_status;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov}
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovint
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovmparse_open(struct mparse *curp, const char *file)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov{
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov char *cp;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov int fd;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->file = file;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov cp = strrchr(file, '.');
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->gzip = (cp != NULL && ! strcmp(cp + 1, "gz"));
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov /* First try to use the filename as it is. */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if ((fd = open(file, O_RDONLY)) != -1)
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return fd;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov /*
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov * If that doesn't work and the filename doesn't
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov * already end in .gz, try appending .gz.
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if ( ! curp->gzip) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_asprintf(&cp, "%s.gz", file);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov fd = open(cp, O_RDONLY);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov free(cp);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (fd != -1) {
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->gzip = 1;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return fd;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov }
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov }
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov /* Neither worked, give up. */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mandoc_msg(MANDOCERR_FILE, curp, 0, 0, strerror(errno));
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return -1;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestruct mparse *
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovmparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg,
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov const char *defos)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore struct mparse *curp;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp = mandoc_calloc(1, sizeof(struct mparse));
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->options = options;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp->wlevel = wlevel;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp->mmsg = mmsg;
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore curp->defos = defos;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->roff = roff_alloc(curp, options);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->man = roff_man_alloc( curp->roff, curp, curp->defos,
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->options & MPARSE_QUICK ? 1 : 0);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (curp->options & MPARSE_MDOC) {
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov mdoc_hash_init();
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->man->macroset = MACROSET_MDOC;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov } else if (curp->options & MPARSE_MAN) {
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov man_hash_init();
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->man->macroset = MACROSET_MAN;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov }
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov curp->man->first->tok = TOKEN_NONE;
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return curp;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorevoid
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoremparse_reset(struct mparse *curp)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore roff_reset(curp->roff);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov if (curp->man != NULL)
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov roff_man_reset(curp->man);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (curp->secondary)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp->secondary->sz = 0;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore curp->file_status = MANDOCLEVEL_OK;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov free(curp->sodest);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov curp->sodest = NULL;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorevoid
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoremparse_free(struct mparse *curp)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov roff_man_free(curp->man);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (curp->roff)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore roff_free(curp->roff);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (curp->secondary)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore free(curp->secondary->buf);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore free(curp->secondary);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov free(curp->sodest);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore free(curp);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorevoid
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankovmparse_result(struct mparse *curp, struct roff_man **man,
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov char **sodest)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (sodest && NULL != (*sodest = curp->sodest)) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov *man = NULL;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov return;
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov }
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (man)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore *man = curp->man;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorevoid
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoremandoc_vmsg(enum mandocerr t, struct mparse *m,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore int ln, int pos, const char *fmt, ...)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore char buf[256];
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore va_list ap;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore va_start(ap, fmt);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov (void)vsnprintf(buf, sizeof(buf), fmt, ap);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore va_end(ap);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore mandoc_msg(t, m, ln, pos, buf);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorevoid
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovmandoc_msg(enum mandocerr er, struct mparse *m,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore int ln, int col, const char *msg)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore enum mandoclevel level;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov level = MANDOCLEVEL_UNSUPP;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore while (er < mandoclimits[level])
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore level--;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (level < m->wlevel && er != MANDOCERR_FILE)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore return;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (m->mmsg)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore (*m->mmsg)(er, level, m->file, ln, col, msg);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (m->file_status < level)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore m->file_status = level;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreconst char *
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoremparse_strerror(enum mandocerr er)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return mandocerrs[er];
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreconst char *
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoremparse_strlevel(enum mandoclevel lvl)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return mandoclevels[lvl];
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorevoid
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoremparse_keep(struct mparse *p)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore assert(NULL == p->secondary);
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore p->secondary = mandoc_calloc(1, sizeof(struct buf));
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreconst char *
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoremparse_getkeep(const struct mparse *p)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore{
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore assert(p->secondary);
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov return p->secondary->sz ? p->secondary->buf : NULL;
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore}