Import CVS snapshot of mandoc as of 20150302
This commit is contained in:
parent
2612bc21b4
commit
d3c5aaa494
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/mdocml/dist/; revision=279524
7
LICENSE
7
LICENSE
@ -1,16 +1,17 @@
|
||||
$Id: LICENSE,v 1.5 2014/12/11 07:56:24 schwarze Exp $
|
||||
$Id: LICENSE,v 1.7 2015/02/16 14:56:22 schwarze Exp $
|
||||
|
||||
With the exceptions noted below, all code and documentation
|
||||
contained in the mdocml toolkit is protected by the Copyright
|
||||
of the following developers:
|
||||
|
||||
Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
Copyright (c) 2010, 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
Copyright (c) 2009, 2010, 2011, 2012 Joerg Sonnenberger <joerg@netbsd.org>
|
||||
Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
|
||||
Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org>
|
||||
Copyright (c) 1998, 2010 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
Copyright (c) 1998, 2004, 2010 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
|
||||
Copyright (c) 2004 Ted Unangst <tedu@openbsd.org>
|
||||
Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre <jmc@openbsd.org>
|
||||
|
||||
See the individual source files for information about who contributed
|
||||
|
19
Makefile
19
Makefile
@ -1,4 +1,4 @@
|
||||
# $Id: Makefile,v 1.453 2014/12/09 09:14:33 schwarze Exp $
|
||||
# $Id: Makefile,v 1.456 2015/02/16 16:23:54 schwarze Exp $
|
||||
#
|
||||
# Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
# Copyright (c) 2011, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,6 +15,8 @@
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
VERSION = 1.13.2
|
||||
|
||||
# === LIST OF FILES ====================================================
|
||||
|
||||
TESTSRCS = test-dirent-namlen.c \
|
||||
@ -31,6 +33,7 @@ TESTSRCS = test-dirent-namlen.c \
|
||||
test-strlcpy.c \
|
||||
test-strptime.c \
|
||||
test-strsep.c \
|
||||
test-strtonum.c \
|
||||
test-wchar.c
|
||||
|
||||
SRCS = att.c \
|
||||
@ -46,6 +49,7 @@ SRCS = att.c \
|
||||
compat_strlcat.c \
|
||||
compat_strlcpy.c \
|
||||
compat_strsep.c \
|
||||
compat_strtonum.c \
|
||||
demandoc.c \
|
||||
eqn.c \
|
||||
eqn_html.c \
|
||||
@ -189,7 +193,8 @@ COMPAT_OBJS = compat_fgetln.o \
|
||||
compat_strcasestr.o \
|
||||
compat_strlcat.o \
|
||||
compat_strlcpy.o \
|
||||
compat_strsep.o
|
||||
compat_strsep.o \
|
||||
compat_strtonum.o
|
||||
|
||||
MANDOC_HTML_OBJS = eqn_html.o \
|
||||
html.o \
|
||||
@ -211,6 +216,7 @@ BASE_OBJS = $(MANDOC_HTML_OBJS) \
|
||||
$(MANDOC_MAN_OBJS) \
|
||||
$(MANDOC_TERM_OBJS) \
|
||||
main.o \
|
||||
manpath.o \
|
||||
out.o \
|
||||
tree.o
|
||||
|
||||
@ -218,8 +224,7 @@ MAIN_OBJS = $(BASE_OBJS)
|
||||
|
||||
DB_OBJS = mandocdb.o \
|
||||
mansearch.o \
|
||||
mansearch_const.o \
|
||||
manpath.o
|
||||
mansearch_const.o
|
||||
|
||||
CGI_OBJS = $(MANDOC_HTML_OBJS) \
|
||||
cgi.o \
|
||||
@ -308,10 +313,12 @@ base-install: base-build
|
||||
mkdir -p $(DESTDIR)$(MANDIR)/man3
|
||||
mkdir -p $(DESTDIR)$(MANDIR)/man7
|
||||
$(INSTALL_PROGRAM) mandoc demandoc $(DESTDIR)$(BINDIR)
|
||||
ln -f $(DESTDIR)$(BINDIR)/mandoc $(DESTDIR)$(BINDIR)/$(BINM_MAN)
|
||||
$(INSTALL_LIB) libmandoc.a $(DESTDIR)$(LIBDIR)
|
||||
$(INSTALL_LIB) man.h mandoc.h mandoc_aux.h mdoc.h \
|
||||
$(DESTDIR)$(INCLUDEDIR)
|
||||
$(INSTALL_MAN) mandoc.1 demandoc.1 $(DESTDIR)$(MANDIR)/man1
|
||||
$(INSTALL_MAN) man.1 $(DESTDIR)$(MANDIR)/man1/$(BINM_MAN).1
|
||||
$(INSTALL_MAN) mandoc.3 mandoc_escape.3 mandoc_malloc.3 \
|
||||
mchars_alloc.3 tbl.3 $(DESTDIR)$(MANDIR)/man3
|
||||
$(INSTALL_MAN) man.7 $(DESTDIR)$(MANDIR)/man7/${MANM_MAN}.7
|
||||
@ -330,12 +337,10 @@ db-install: base-build
|
||||
mkdir -p $(DESTDIR)$(MANDIR)/man5
|
||||
mkdir -p $(DESTDIR)$(MANDIR)/man8
|
||||
ln -f $(DESTDIR)$(BINDIR)/mandoc $(DESTDIR)$(BINDIR)/$(BINM_APROPOS)
|
||||
ln -f $(DESTDIR)$(BINDIR)/mandoc $(DESTDIR)$(BINDIR)/$(BINM_MAN)
|
||||
ln -f $(DESTDIR)$(BINDIR)/mandoc $(DESTDIR)$(BINDIR)/$(BINM_WHATIS)
|
||||
ln -f $(DESTDIR)$(BINDIR)/mandoc \
|
||||
$(DESTDIR)$(SBINDIR)/$(BINM_MAKEWHATIS)
|
||||
$(INSTALL_MAN) apropos.1 $(DESTDIR)$(MANDIR)/man1/$(BINM_APROPOS).1
|
||||
$(INSTALL_MAN) man.1 $(DESTDIR)$(MANDIR)/man1/$(BINM_MAN).1
|
||||
ln -f $(DESTDIR)$(MANDIR)/man1/$(BINM_APROPOS).1 \
|
||||
$(DESTDIR)$(MANDIR)/man1/$(BINM_WHATIS).1
|
||||
$(INSTALL_MAN) mansearch.3 $(DESTDIR)$(MANDIR)/man3
|
||||
@ -377,7 +382,7 @@ demandoc: $(DEMANDOC_OBJS) libmandoc.a
|
||||
|
||||
www-install: www
|
||||
mkdir -p $(HTDOCDIR)/snapshots
|
||||
$(INSTALL_DATA) $(WWW_MANS) style.css $(HTDOCDIR)/man
|
||||
$(INSTALL_DATA) $(WWW_MANS) style.css $(HTDOCDIR)
|
||||
$(INSTALL_DATA) $(WWW_OBJS) $(HTDOCDIR)/snapshots
|
||||
$(INSTALL_DATA) mdocml.tar.gz \
|
||||
$(HTDOCDIR)/snapshots/mdocml-$(VERSION).tar.gz
|
||||
|
@ -11,6 +11,7 @@ compat_strcasestr.o: compat_strcasestr.c config.h
|
||||
compat_strlcat.o: compat_strlcat.c config.h
|
||||
compat_strlcpy.o: compat_strlcpy.c config.h
|
||||
compat_strsep.o: compat_strsep.c config.h
|
||||
compat_strtonum.o: compat_strtonum.c config.h
|
||||
demandoc.o: demandoc.c config.h man.h mdoc.h mandoc.h
|
||||
eqn.o: eqn.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h
|
||||
eqn_html.o: eqn_html.c config.h mandoc.h out.h html.h
|
||||
@ -39,7 +40,7 @@ mdoc_macro.o: mdoc_macro.c config.h mdoc.h mandoc.h libmdoc.h libmandoc.h
|
||||
mdoc_man.o: mdoc_man.c config.h mandoc.h mandoc_aux.h out.h man.h mdoc.h main.h
|
||||
mdoc_term.o: mdoc_term.c config.h mandoc.h mandoc_aux.h out.h term.h mdoc.h main.h
|
||||
mdoc_validate.o: mdoc_validate.c config.h mdoc.h mandoc.h mandoc_aux.h libmdoc.h libmandoc.h
|
||||
msec.o: msec.c config.h libmandoc.h msec.in
|
||||
msec.o: msec.c config.h mandoc.h libmandoc.h msec.in
|
||||
out.o: out.c config.h mandoc_aux.h mandoc.h out.h
|
||||
preconv.o: preconv.c config.h mandoc.h libmandoc.h
|
||||
read.o: read.c config.h mandoc.h mandoc_aux.h libmandoc.h mdoc.h man.h
|
||||
@ -69,4 +70,5 @@ test-strlcat.o: test-strlcat.c
|
||||
test-strlcpy.o: test-strlcpy.c
|
||||
test-strptime.o: test-strptime.c
|
||||
test-strsep.o: test-strsep.c
|
||||
test-strtonum.o: test-strtonum.c
|
||||
test-wchar.o: test-wchar.c
|
||||
|
30
Makefile.local
Normal file
30
Makefile.local
Normal file
@ -0,0 +1,30 @@
|
||||
BUILD_TARGETS = base-build
|
||||
INSTALL_TARGETS = base-install db-install
|
||||
CFLAGS = -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings -I/usr/local/include
|
||||
DBLIB = -L/usr/local/lib -lsqlite3
|
||||
STATIC = -static
|
||||
PREFIX = /usr/local
|
||||
BINDIR = /usr/local/bin
|
||||
SBINDIR = /usr/local/sbin
|
||||
INCLUDEDIR = /usr/local/include/mandoc
|
||||
LIBDIR = /usr/local/lib/mandoc
|
||||
MANDIR = /usr/local/man
|
||||
EXAMPLEDIR = /usr/local/share/examples/mandoc
|
||||
WWWPREFIX = /var/www
|
||||
HTDOCDIR = /var/www/htdocs
|
||||
CGIBINDIR = /var/www/cgi-bin
|
||||
BINM_APROPOS = apropos
|
||||
BINM_MAN = man
|
||||
BINM_WHATIS = whatis
|
||||
BINM_MAKEWHATIS = makewhatis
|
||||
MANM_MAN = man
|
||||
MANM_MDOC = mdoc
|
||||
MANM_ROFF = roff
|
||||
MANM_EQN = eqn
|
||||
MANM_TBL = tbl
|
||||
INSTALL = install
|
||||
INSTALL_PROGRAM = install -m 0555
|
||||
INSTALL_LIB = install -m 0444
|
||||
INSTALL_MAN = install -m 0444
|
||||
INSTALL_DATA = install -m 0444
|
||||
MAIN_OBJS = $(BASE_OBJS) $(DB_OBJS)
|
42
TODO
42
TODO
@ -1,6 +1,6 @@
|
||||
************************************************************************
|
||||
* Official mandoc TODO.
|
||||
* $Id: TODO,v 1.195 2014/12/13 13:14:39 schwarze Exp $
|
||||
* $Id: TODO,v 1.201 2015/02/20 13:47:28 schwarze Exp $
|
||||
************************************************************************
|
||||
|
||||
Many issues are annotated for difficulty as follows:
|
||||
@ -60,7 +60,7 @@ are mere guesses, and some may be wrong.
|
||||
- .fc (field control)
|
||||
found by naddy@ in xloadimage(1)
|
||||
loc ** exist *** algo * size * imp *
|
||||
|
||||
|
||||
- .nr third argument (auto-increment step size, requires \n+)
|
||||
found by bentley@ in sbcl(1) Mon, 9 Dec 2013 18:36:57 -0700
|
||||
loc * exist * algo * size * imp **
|
||||
@ -69,31 +69,37 @@ are mere guesses, and some may be wrong.
|
||||
reported by brad@ Sat, 15 Jan 2011 15:45:23 -0500
|
||||
loc *** exist *** algo *** size ** imp *
|
||||
|
||||
- .ta (tab settings) occurs in ircbug(1) and probably gnats(1)
|
||||
reported by brad@ Sat, 15 Jan 2011 15:50:51 -0500
|
||||
- .ta (tab settings)
|
||||
#1 most important issue naddy@ Mon, 16 Feb 2015 20:59:17 +0100
|
||||
ircbug(1) gnats(1) reported by brad@ Sat, 15 Jan 2011 15:50:51 -0500
|
||||
also Tcl_NewStringObj(3) via wiz@ Wed, 5 Mar 2014 22:27:43 +0100
|
||||
also posix2time(3) Carsten Kunze Mon, 1 Dec 2014 13:03:10 +0100
|
||||
loc ** exist *** algo ** size ** imp ***
|
||||
|
||||
- .ti (temporary indent)
|
||||
found by naddy@ in xloadimage(1)
|
||||
found by naddy@ in xloadimage(1) [devel/libvstr] vstr(3)
|
||||
found by bentley@ in nmh(1) Mon, 23 Apr 2012 13:38:28 -0600
|
||||
loc ** exist ** algo ** size * imp ** (parser reorg helps a lot)
|
||||
|
||||
- .while and .shift
|
||||
- .while and .shift
|
||||
found by jca@ in ratpoison(1) Sun, 30 Jun 2013 12:01:09 +0200
|
||||
loc * exist ** algo ** size ** imp **
|
||||
|
||||
- \h horizontal move
|
||||
found in cclive(1) and nasm(1) asciidoc/DocBook output
|
||||
#2 most important issue naddy@ Mon, 16 Feb 2015 20:59:17 +0100
|
||||
found in cclive(1) nasm(1) bogofilter(1) asciidoc/DocBook output
|
||||
bentley@ on discuss@ Sat, 21 Sep 2013 22:29:34 -0600
|
||||
naddy@ Thu, 4 Dec 2014 16:26:41 +0100
|
||||
loc ** exist ** algo ** size * imp ** (parser reorg helps a lot)
|
||||
loc ** exist ** algo ** size * imp *** (parser reorg helps a lot)
|
||||
|
||||
- \n+ and \n- numerical register increment and decrement
|
||||
found by bentley@ in sbcl(1) Mon, 9 Dec 2013 18:36:57 -0700
|
||||
loc * exist * algo * size * imp **
|
||||
|
||||
- \n(.$ macro argument count number register; ocserv(8) by autogen
|
||||
found by sthen@ Thu, 19 Feb 2015 22:03:01 +0000
|
||||
loc * exist ** algo * size * imp **
|
||||
|
||||
- \w'' improve width measurements
|
||||
would not be very useful without an expression parser, see below
|
||||
needed for Tcl_NewStringObj(3) via wiz@ Wed, 5 Mar 2014 22:27:43 +0100
|
||||
@ -105,10 +111,6 @@ are mere guesses, and some may be wrong.
|
||||
|
||||
--- missing mdoc features ----------------------------------------------
|
||||
|
||||
- fix bad block nesting involving multiple identical explicit blocks
|
||||
see the OpenBSD mdoc_macro.c 1.47 commit message
|
||||
loc * exist *** algo *** size * imp **
|
||||
|
||||
- .Bl -column .Xo support is missing
|
||||
ultimate goal:
|
||||
restore .Xr and .Dv to
|
||||
@ -255,6 +257,10 @@ are mere guesses, and some may be wrong.
|
||||
|
||||
--- compatibility checks -----------------------------------------------
|
||||
|
||||
- write a configure check for [[:<:]] support and provide some
|
||||
fallback for whatis(1) when it doesn't work;
|
||||
Svyatoslav Mishyn Wed, 17 Dec 2014 11:07:10 +0200
|
||||
|
||||
- is .Bk implemented correctly in modern groff?
|
||||
sobrado@ Tue, 19 Apr 2011 22:12:55 +0200
|
||||
|
||||
@ -347,6 +353,10 @@ are mere guesses, and some may be wrong.
|
||||
reminded by jmc@ Thu, 23 Sep 2010 18:13:39 +0059
|
||||
loc * exist ** algo *** size * imp ***
|
||||
|
||||
- a line starting with "\fB something" counts as starting with whitespace
|
||||
and triggers a line break; found in audio/normalize-mp3(1)
|
||||
loc ** exist * algo ** size * imp **
|
||||
|
||||
- formatting /usr/local/man/man1/latex2man.1 with groff and mandoc
|
||||
reveals lots of bugs both in groff and mandoc...
|
||||
reported by bentley@ Wed, 22 May 2013 23:49:30 -0600
|
||||
@ -457,7 +467,7 @@ are mere guesses, and some may be wrong.
|
||||
loc * exist * algo * size * imp *
|
||||
|
||||
- trailing whitespace must be ignored even when followed by a font escape,
|
||||
see for example
|
||||
see for example
|
||||
makes
|
||||
\fBdig \fR
|
||||
operate in batch mode
|
||||
@ -531,7 +541,7 @@ are mere guesses, and some may be wrong.
|
||||
How does SQLITE_CONFIG_PAGECACHE actually work? Document it!
|
||||
from kristaps@ Sat, 09 Aug 2014 13:51:36 +0200
|
||||
|
||||
Several areas can be cleaned up to make mandoc even faster. These are
|
||||
Several areas can be cleaned up to make mandoc even faster. These are
|
||||
|
||||
- improve hashing mechanism for macros (quite important: performance)
|
||||
|
||||
@ -540,7 +550,7 @@ Several areas can be cleaned up to make mandoc even faster. These are
|
||||
- the PDF file is HUGE: this can be reduced by using relative offsets
|
||||
|
||||
- instead of re-initialising the roff predefined-strings set before each
|
||||
parse, create a read-only version the first time and copy it
|
||||
parse, create a read-only version the first time and copy it
|
||||
loc * exist ** algo ** size * imp **
|
||||
|
||||
************************************************************************
|
||||
@ -556,7 +566,7 @@ Several areas can be cleaned up to make mandoc even faster. These are
|
||||
|
||||
- Find better ways to prevent endless loops
|
||||
in roff(7) macro and string expansion.
|
||||
|
||||
|
||||
- Finish cleanup of date handling.
|
||||
Decide which formats should be recognized where.
|
||||
Update both mdoc(7) and man(7) documentation.
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $Id: apropos.1,v 1.36 2014/10/25 01:03:52 schwarze Exp $
|
||||
.\" $Id: apropos.1,v 1.37 2015/02/16 16:23:54 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: October 25 2014 $
|
||||
.Dd $Mdocdate: February 16 2015 $
|
||||
.Dt APROPOS 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -24,7 +24,7 @@
|
||||
.Nd search manual page databases
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl acfhklVw
|
||||
.Op Fl acfhklw
|
||||
.Op Fl C Ar file
|
||||
.Op Fl M Ar path
|
||||
.Op Fl m Ar path
|
||||
@ -162,8 +162,6 @@ By default, pages from all sections are shown.
|
||||
See
|
||||
.Xr man 1
|
||||
for a listing of sections.
|
||||
.It Fl V
|
||||
Print version and exit.
|
||||
.It Fl w
|
||||
Instead of showing title lines, show the pathnames of the matching
|
||||
manual pages, just like
|
||||
|
36
cgi.c
36
cgi.c
@ -1,4 +1,4 @@
|
||||
/* $Id: cgi.c,v 1.102 2014/11/26 17:55:27 schwarze Exp $ */
|
||||
/* $Id: cgi.c,v 1.104 2015/02/10 08:05:30 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@usta.de>
|
||||
@ -58,10 +58,10 @@ static void catman(const struct req *, const char *);
|
||||
static void format(const struct req *, const char *);
|
||||
static void html_print(const char *);
|
||||
static void html_putchar(char);
|
||||
static int http_decode(char *);
|
||||
static int http_decode(char *);
|
||||
static void http_parse(struct req *, const char *);
|
||||
static void http_print(const char *);
|
||||
static void http_putchar(char);
|
||||
static void http_putchar(char);
|
||||
static void http_printquery(const struct req *, const char *);
|
||||
static void pathgen(struct req *);
|
||||
static void pg_error_badrequest(const char *);
|
||||
@ -186,7 +186,7 @@ http_print(const char *p)
|
||||
static void
|
||||
html_print(const char *p)
|
||||
{
|
||||
|
||||
|
||||
if (NULL == p)
|
||||
return;
|
||||
while ('\0' != *p)
|
||||
@ -621,7 +621,7 @@ pg_searchres(const struct req *req, struct manpage *r, size_t sz)
|
||||
for (i = 0; i < sz; i++) {
|
||||
printf("<TR>\n"
|
||||
"<TD CLASS=\"title\">\n"
|
||||
"<A HREF=\"%s/%s/%s?",
|
||||
"<A HREF=\"%s/%s/%s?",
|
||||
scriptname, req->q.manpath, r[i].file);
|
||||
http_printquery(req, "&");
|
||||
printf("\">");
|
||||
@ -701,7 +701,7 @@ catman(const struct req *req, const char *file)
|
||||
while (NULL != (p = fgetln(f, &len))) {
|
||||
bold = italic = 0;
|
||||
for (i = 0; i < (int)len - 1; i++) {
|
||||
/*
|
||||
/*
|
||||
* This means that the catpage is out of state.
|
||||
* Ignore it and keep going (although the
|
||||
* catpage is bogus).
|
||||
@ -742,7 +742,7 @@ catman(const struct req *req, const char *file)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Handle funny behaviour troff-isms.
|
||||
* These grok'd from the original man2html.c.
|
||||
*/
|
||||
@ -780,7 +780,7 @@ catman(const struct req *req, const char *file)
|
||||
}
|
||||
|
||||
/* Bold mode. */
|
||||
|
||||
|
||||
if (italic)
|
||||
printf("</I>");
|
||||
if ( ! bold)
|
||||
@ -791,9 +791,9 @@ catman(const struct req *req, const char *file)
|
||||
html_putchar(p[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Clean up the last character.
|
||||
* We can get to a newline; don't print that.
|
||||
* We can get to a newline; don't print that.
|
||||
*/
|
||||
|
||||
if (italic)
|
||||
@ -822,7 +822,6 @@ format(const struct req *req, const char *file)
|
||||
struct man *man;
|
||||
void *vp;
|
||||
char *opts;
|
||||
enum mandoclevel rc;
|
||||
int fd;
|
||||
int usepath;
|
||||
|
||||
@ -832,18 +831,11 @@ format(const struct req *req, const char *file)
|
||||
}
|
||||
|
||||
mchars = mchars_alloc();
|
||||
mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_FATAL, NULL,
|
||||
mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_BADARG, NULL,
|
||||
mchars, req->q.manpath);
|
||||
rc = mparse_readfd(mp, fd, file);
|
||||
mparse_readfd(mp, fd, file);
|
||||
close(fd);
|
||||
|
||||
if (rc >= MANDOCLEVEL_FATAL) {
|
||||
fprintf(stderr, "fatal mandoc error: %s/%s\n",
|
||||
req->q.manpath, file);
|
||||
pg_error_internal();
|
||||
return;
|
||||
}
|
||||
|
||||
usepath = strcmp(req->q.manpath, req->p[0]);
|
||||
mandoc_asprintf(&opts,
|
||||
"fragment,man=%s?query=%%N&sec=%%S%s%s%s%s",
|
||||
@ -899,7 +891,7 @@ pg_show(struct req *req, const char *fullpath)
|
||||
pg_error_badrequest(
|
||||
"You did not specify a page to show.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
manpath = mandoc_strndup(fullpath, file - fullpath);
|
||||
file++;
|
||||
|
||||
@ -1064,7 +1056,7 @@ main(void)
|
||||
MAN_DIR, strerror(errno));
|
||||
pg_error_internal();
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
memset(&req, 0, sizeof(struct req));
|
||||
pathgen(&req);
|
||||
|
4
chars.c
4
chars.c
@ -1,4 +1,4 @@
|
||||
/* $Id: chars.c,v 1.65 2014/10/29 00:17:43 schwarze Exp $ */
|
||||
/* $Id: chars.c,v 1.66 2015/02/17 20:37:16 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -38,7 +38,7 @@ struct ln {
|
||||
int unicode;
|
||||
};
|
||||
|
||||
#define LINES_MAX 330
|
||||
#define LINES_MAX 332
|
||||
|
||||
#define CHAR(in, ch, code) \
|
||||
{ NULL, (in), (ch), (code) },
|
||||
|
26
chars.in
26
chars.in
@ -1,4 +1,4 @@
|
||||
/* $Id: chars.in,v 1.49 2014/11/06 22:28:36 schwarze Exp $ */
|
||||
/* $Id: chars.in,v 1.52 2015/02/17 20:37:16 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -70,8 +70,10 @@ CHAR("ti", "~", 126)
|
||||
/* Quotes. */
|
||||
CHAR("Bq", ",,", 8222)
|
||||
CHAR("bq", ",", 8218)
|
||||
CHAR("lq", "``", 8220)
|
||||
CHAR("rq", "\'\'", 8221)
|
||||
CHAR("lq", "\"", 8220)
|
||||
CHAR("rq", "\"", 8221)
|
||||
CHAR("Lq", "``", 8220)
|
||||
CHAR("Rq", "''", 8221)
|
||||
CHAR("oq", "`", 8216)
|
||||
CHAR("cq", "\'", 8217)
|
||||
CHAR("aq", "\'", 39)
|
||||
@ -91,30 +93,30 @@ CHAR("ra", ">", 10217)
|
||||
CHAR("bv", "|", 9130)
|
||||
CHAR("braceex", "|", 9130)
|
||||
CHAR("bracketlefttp", "|", 9121)
|
||||
CHAR("bracketleftbp", "|", 9123)
|
||||
CHAR("bracketleftbt", "|", 9123)
|
||||
CHAR("bracketleftex", "|", 9122)
|
||||
CHAR("bracketrighttp", "|", 9124)
|
||||
CHAR("bracketrightbp", "|", 9126)
|
||||
CHAR("bracketrightbt", "|", 9126)
|
||||
CHAR("bracketrightex", "|", 9125)
|
||||
CHAR("lt", ",-", 9127)
|
||||
CHAR("bracelefttp", ",-", 9127)
|
||||
CHAR("lk", "{", 9128)
|
||||
CHAR("braceleftmid", "{", 9128)
|
||||
CHAR("lb", "`-", 9129)
|
||||
CHAR("braceleftbp", "`-", 9129)
|
||||
CHAR("braceleftbt", "`-", 9129)
|
||||
CHAR("braceleftex", "|", 9130)
|
||||
CHAR("rt", "-.", 9131)
|
||||
CHAR("bracerighttp", "-.", 9131)
|
||||
CHAR("rk", "}", 9132)
|
||||
CHAR("bracerightmid", "}", 9132)
|
||||
CHAR("rb", "-\'", 9133)
|
||||
CHAR("bracerightbp", "-\'", 9133)
|
||||
CHAR("bracerightbt", "-\'", 9133)
|
||||
CHAR("bracerightex", "|", 9130)
|
||||
CHAR("parenlefttp", "/", 9115)
|
||||
CHAR("parenleftbp", "\\", 9117)
|
||||
CHAR("parenleftbt", "\\", 9117)
|
||||
CHAR("parenleftex", "|", 9116)
|
||||
CHAR("parenrighttp", "\\", 9118)
|
||||
CHAR("parenrightbp", "/", 9120)
|
||||
CHAR("parenrightbt", "/", 9120)
|
||||
CHAR("parenrightex", "|", 9119)
|
||||
|
||||
/* Greek characters. */
|
||||
@ -281,10 +283,10 @@ CHAR("!=", "!=", 8800)
|
||||
CHAR("==", "==", 8801)
|
||||
CHAR("ne", "!==", 8802)
|
||||
CHAR("=~", "=~", 8773)
|
||||
CHAR("-~", "-~", 8771)
|
||||
CHAR("|=", "-~", 8771)
|
||||
CHAR("ap", "~", 8764)
|
||||
CHAR("~~", "~~", 8776)
|
||||
CHAR("~=", "~=", 8780)
|
||||
CHAR("~=", "~=", 8776)
|
||||
CHAR("pt", "oc", 8733)
|
||||
CHAR("es", "{}", 8709)
|
||||
CHAR("mo", "E", 8712)
|
||||
@ -357,7 +359,7 @@ CHAR("Fn", ",\bf", 402)
|
||||
CHAR("ba", "|", 124)
|
||||
CHAR("br", "|", 9474)
|
||||
CHAR("ul", "_", 95)
|
||||
CHAR("rl", "-", 8254)
|
||||
CHAR("rn", "-", 8254)
|
||||
CHAR("bb", "|", 166)
|
||||
CHAR("sl", "/", 47)
|
||||
CHAR("rs", "\\", 92)
|
||||
|
13
compat_fts.c
13
compat_fts.c
@ -6,8 +6,8 @@ int dummy;
|
||||
|
||||
#else
|
||||
|
||||
/* $Id: compat_fts.c,v 1.6 2014/12/11 18:20:07 schwarze Exp $ */
|
||||
/* $OpenBSD: fts.c,v 1.49 2014/11/23 00:14:22 guenther Exp $ */
|
||||
/* $Id: compat_fts.c,v 1.8 2015/02/07 07:53:01 schwarze Exp $ */
|
||||
/* $OpenBSD: fts.c,v 1.50 2015/01/16 16:48:51 deraadt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
@ -38,7 +38,6 @@ int dummy;
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -51,6 +50,8 @@ int dummy;
|
||||
#include <unistd.h>
|
||||
#include "compat_fts.h"
|
||||
|
||||
#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
static FTSENT *fts_alloc(FTS *, const char *, size_t);
|
||||
static FTSENT *fts_build(FTS *);
|
||||
static void fts_lfree(FTSENT *);
|
||||
@ -62,10 +63,12 @@ static unsigned short fts_stat(FTS *, FTSENT *);
|
||||
static int fts_safe_changedir(FTS *, FTSENT *, int, const char *);
|
||||
|
||||
#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
#ifndef O_DIRECTORY
|
||||
#define O_DIRECTORY 0
|
||||
#endif
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
#define CLR(opt) (sp->fts_options &= ~(opt))
|
||||
#define ISSET(opt) (sp->fts_options & (opt))
|
||||
@ -97,7 +100,7 @@ fts_open(char * const *argv, int options, void *dummy)
|
||||
* Start out with 1K of path space, and enough, in any case,
|
||||
* to hold the user's paths.
|
||||
*/
|
||||
if (fts_palloc(sp, MAX(fts_maxarglen(argv), PATH_MAX)))
|
||||
if (fts_palloc(sp, MAXIMUM(fts_maxarglen(argv), PATH_MAX)))
|
||||
goto mem1;
|
||||
|
||||
/* Allocate/initialize root's parent. */
|
||||
|
76
compat_strtonum.c
Normal file
76
compat_strtonum.c
Normal file
@ -0,0 +1,76 @@
|
||||
#include "config.h"
|
||||
|
||||
#if HAVE_STRTONUM
|
||||
|
||||
int dummy;
|
||||
|
||||
#else
|
||||
|
||||
/* $Id: compat_strtonum.c,v 1.1 2015/02/16 14:56:22 schwarze Exp $ */
|
||||
/* $OpenBSD: strtonum.c,v 1.7 2013/04/17 18:40:58 tedu Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 Ted Unangst and Todd Miller
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define INVALID 1
|
||||
#define TOOSMALL 2
|
||||
#define TOOLARGE 3
|
||||
|
||||
long long
|
||||
strtonum(const char *numstr, long long minval, long long maxval,
|
||||
const char **errstrp)
|
||||
{
|
||||
long long ll = 0;
|
||||
int error = 0;
|
||||
char *ep;
|
||||
struct errval {
|
||||
const char *errstr;
|
||||
int err;
|
||||
} ev[4] = {
|
||||
{ NULL, 0 },
|
||||
{ "invalid", EINVAL },
|
||||
{ "too small", ERANGE },
|
||||
{ "too large", ERANGE },
|
||||
};
|
||||
|
||||
ev[0].err = errno;
|
||||
errno = 0;
|
||||
if (minval > maxval) {
|
||||
error = INVALID;
|
||||
} else {
|
||||
ll = strtoll(numstr, &ep, 10);
|
||||
if (numstr == ep || *ep != '\0')
|
||||
error = INVALID;
|
||||
else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
|
||||
error = TOOSMALL;
|
||||
else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
|
||||
error = TOOLARGE;
|
||||
}
|
||||
if (errstrp != NULL)
|
||||
*errstrp = ev[error].errstr;
|
||||
errno = ev[error].err;
|
||||
if (error)
|
||||
ll = 0;
|
||||
|
||||
return (ll);
|
||||
}
|
||||
|
||||
#endif /* !HAVE_STRTONUM */
|
16
configure
vendored
16
configure
vendored
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
# Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
@ -31,10 +31,6 @@ echo "config.log: writing..."
|
||||
# Initialize all variables here,
|
||||
# such that nothing can leak in from the environment.
|
||||
|
||||
VERSION="1.13.2"
|
||||
echo "VERSION=\"${VERSION}\"" 1>&2
|
||||
echo "VERSION=\"${VERSION}\"" 1>&3
|
||||
|
||||
OSNAME=
|
||||
|
||||
CC=`printf "all:\\n\\t@echo \\\$(CC)\\n" | make -f -`
|
||||
@ -56,6 +52,7 @@ HAVE_STRLCAT=
|
||||
HAVE_STRLCPY=
|
||||
HAVE_STRPTIME=
|
||||
HAVE_STRSEP=
|
||||
HAVE_STRTONUM=
|
||||
HAVE_WCHAR=
|
||||
|
||||
HAVE_SQLITE3=
|
||||
@ -70,6 +67,7 @@ INCLUDEDIR=
|
||||
LIBDIR=
|
||||
MANDIR=
|
||||
EXAMPLEDIR=
|
||||
HOMEBREWDIR=
|
||||
|
||||
WWWPREFIX="/var/www"
|
||||
HTDOCDIR=
|
||||
@ -176,6 +174,7 @@ runtest strlcat STRLCAT || true
|
||||
runtest strlcpy STRLCPY || true
|
||||
runtest strptime STRPTIME || true
|
||||
runtest strsep STRSEP || true
|
||||
runtest strtonum STRTONUM || true
|
||||
runtest wchar WCHAR || true
|
||||
|
||||
# --- sqlite3 ---
|
||||
@ -274,8 +273,8 @@ __HEREDOC__
|
||||
[ ${HAVE_FGETLN} -eq 0 ] && echo "#include <stdio.h>"
|
||||
|
||||
echo
|
||||
echo "#define VERSION \"${VERSION}\""
|
||||
[ -n "${OSNAME}" ] && echo "#define OSNAME \"${OSNAME}\""
|
||||
[ -n "${HOMEBREWDIR}" ] && echo "#define HOMEBREWDIR \"${HOMEBREWDIR}\""
|
||||
|
||||
cat << __HEREDOC__
|
||||
#define HAVE_DIRENT_NAMLEN ${HAVE_DIRENT_NAMLEN}
|
||||
@ -289,6 +288,7 @@ cat << __HEREDOC__
|
||||
#define HAVE_STRLCPY ${HAVE_STRLCPY}
|
||||
#define HAVE_STRPTIME ${HAVE_STRPTIME}
|
||||
#define HAVE_STRSEP ${HAVE_STRSEP}
|
||||
#define HAVE_STRTONUM ${HAVE_STRTONUM}
|
||||
#define HAVE_WCHAR ${HAVE_WCHAR}
|
||||
#define HAVE_SQLITE3 ${HAVE_SQLITE3}
|
||||
#define HAVE_SQLITE3_ERRSTR ${HAVE_SQLITE3_ERRSTR}
|
||||
@ -341,6 +341,9 @@ __HEREDOC__
|
||||
[ ${HAVE_STRSEP} -eq 0 ] && \
|
||||
echo "extern char *strsep(char **, const char *);"
|
||||
|
||||
[ ${HAVE_STRTONUM} -eq 0 ] && \
|
||||
echo "extern long long strtonum(const char *, long long, long long, const char **);"
|
||||
|
||||
echo
|
||||
echo "#endif /* MANDOC_CONFIG_H */"
|
||||
|
||||
@ -379,7 +382,6 @@ INSTALL_TARGETS="base-install"
|
||||
[ ${BUILD_CGI} -gt 0 ] && INSTALL_TARGETS="${INSTALL_TARGETS} cgi-install"
|
||||
|
||||
cat << __HEREDOC__
|
||||
VERSION = ${VERSION}
|
||||
BUILD_TARGETS = ${BUILD_TARGETS}
|
||||
INSTALL_TARGETS = ${INSTALL_TARGETS}
|
||||
CFLAGS = ${CFLAGS}
|
||||
|
@ -1,6 +1,6 @@
|
||||
# $Id: configure.local.example,v 1.2 2014/12/09 09:14:33 schwarze Exp $
|
||||
# $Id: configure.local.example,v 1.6 2015/02/16 14:56:22 schwarze Exp $
|
||||
#
|
||||
# Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
# Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
@ -74,6 +74,21 @@ LIBDIR="${PREFIX}/lib/mandoc"
|
||||
MANDIR="${PREFIX}/man"
|
||||
EXAMPLEDIR="${PREFIX}/share/examples/mandoc"
|
||||
|
||||
# The man(1) utility needs to know where the manuals reside.
|
||||
# We know of two ways to tell it: via manpath(1) or man.conf(5).
|
||||
# The latter is used by OpenBSD and NetBSD, the former by most
|
||||
# other systems.
|
||||
|
||||
# Force usage of manpath(1).
|
||||
# If it is not installed or not operational,
|
||||
# man(1), makewhatis(8), and apropos(1) will not work properly.
|
||||
HAVE_MANPATH=1
|
||||
|
||||
# Force usage of man.conf(5).
|
||||
# If it does not exist or contains no valid configuration,
|
||||
# man(1), makewhatis(8), and apropos(1) will not work properly.
|
||||
HAVE_MANPATH=0
|
||||
|
||||
# Some distributions may want to avoid naming conflicts among manuals.
|
||||
# If you want to change the names of installed section 7 manual pages,
|
||||
# the following alternative names are suggested.
|
||||
@ -87,6 +102,15 @@ MANM_ROFF="mandoc_roff" # default is "roff"
|
||||
MANM_EQN="mandoc_eqn" # default is "eqn"
|
||||
MANM_TBL="mandoc_tbl" # default is "tbl"
|
||||
|
||||
# Some distributions may want to avoid naming conflicts
|
||||
# with another man(1) utility.
|
||||
# If you want to change the name of the binary program,
|
||||
# the following alternative name is suggested.
|
||||
# Using a different name is possible as well.
|
||||
# This changes the name of the installed section 1 manual page as well.
|
||||
|
||||
BINM_MAN=mman # default is "man"
|
||||
|
||||
# It is possible to change the utility program used for installation
|
||||
# and the modes files are installed with. The defaults are:
|
||||
|
||||
@ -121,38 +145,29 @@ DBLIB="-L/usr/local/lib -lsqlite3"
|
||||
|
||||
CFLAGS="${CFLAGS} -I/usr/local/include"
|
||||
|
||||
# The man(1) utility needs to know where the manuals reside.
|
||||
# We know of two ways to tell it: via manpath(1) or man.conf(5).
|
||||
# The latter is used by OpenBSD and NetBSD, the former by most
|
||||
# other systems.
|
||||
|
||||
# Force usage of manpath(1).
|
||||
# If it is not installed or not operational,
|
||||
# makewhatis(8) and apropos(1) will not work properly.
|
||||
|
||||
HAVE_MANPATH=1
|
||||
|
||||
# Force usage of man.conf(5).
|
||||
# If it does not exist or contains no valid configuration,
|
||||
# makewhatis(8) and apropos(1) will not work properly.
|
||||
|
||||
HAVE_MANPATH=0
|
||||
|
||||
# Some distributions may want to avoid naming conflicts
|
||||
# with groff, man-db, or other tools.
|
||||
# If you want to change the names of binary programs,
|
||||
# with another implementation of apropos(1) and makewhatis(8).
|
||||
# If you want to change the names of the binary programs,
|
||||
# the following alternative names are suggested.
|
||||
# Using other names is possible as well.
|
||||
# This changes the names of the installed section 1 and section 8
|
||||
# manual pages as well.
|
||||
# It is possible to set only one or a few of these variables,
|
||||
# It is possible to set only one or two of these variables,
|
||||
# there is no need to copy the whole block.
|
||||
|
||||
BINM_APROPOS=mapropos # default is "apropos"
|
||||
BINM_MAN=mman # default is "man"
|
||||
BINM_WHATIS=mwhatis # default is "whatis"
|
||||
BINM_MAKEWHATIS=mandocdb # default is "makewhatis"
|
||||
|
||||
# When using the "homebrew" package manager on Mac OS X, the actual
|
||||
# manuals are located in a so-called "cellar" and only symlinked
|
||||
# into the manual trees. To allow mandoc to follow such symlinks,
|
||||
# you have to specify the physical location of the cellar as returned
|
||||
# by realpath(3), for example:
|
||||
|
||||
PREFIX="/usr/local"
|
||||
HOMEBREWDIR="${PREFIX}/Cellar"
|
||||
|
||||
# --- user settings related man.cgi ------------------------------------
|
||||
|
||||
# By default, building man.cgi(8) is disabled. To enable it, copy
|
||||
@ -211,6 +226,7 @@ HAVE_STRLCAT=0
|
||||
HAVE_STRLCPY=0
|
||||
HAVE_STRPTIME=0
|
||||
HAVE_STRSEP=0
|
||||
HAVE_STRTONUM=0
|
||||
|
||||
HAVE_SQLITE3=0
|
||||
HAVE_SQLITE3_ERRSTR=0
|
||||
|
37
demandoc.c
37
demandoc.c
@ -1,4 +1,4 @@
|
||||
/* $Id: demandoc.c,v 1.12 2014/10/28 17:36:19 schwarze Exp $ */
|
||||
/* $Id: demandoc.c,v 1.15 2015/02/10 08:05:30 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -44,11 +44,12 @@ main(int argc, char *argv[])
|
||||
{
|
||||
struct mparse *mp;
|
||||
struct mchars *mchars;
|
||||
int ch, i, list;
|
||||
int ch, fd, i, list;
|
||||
extern int optind;
|
||||
|
||||
progname = strrchr(argv[0], '/');
|
||||
if (progname == NULL)
|
||||
if (argc < 1)
|
||||
progname = "demandoc";
|
||||
else if ((progname = strrchr(argv[0], '/')) == NULL)
|
||||
progname = argv[0];
|
||||
else
|
||||
++progname;
|
||||
@ -78,15 +79,19 @@ main(int argc, char *argv[])
|
||||
argv += optind;
|
||||
|
||||
mchars = mchars_alloc();
|
||||
mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_FATAL, NULL, mchars, NULL);
|
||||
mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_BADARG, NULL, mchars, NULL);
|
||||
assert(mp);
|
||||
|
||||
if (0 == argc)
|
||||
if (argc < 1)
|
||||
pmandoc(mp, STDIN_FILENO, "<stdin>", list);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
mparse_reset(mp);
|
||||
pmandoc(mp, -1, argv[i], list);
|
||||
if (mparse_open(mp, &fd, argv[i]) != MANDOCLEVEL_OK) {
|
||||
perror(argv[i]);
|
||||
continue;
|
||||
}
|
||||
pmandoc(mp, fd, argv[i], list);
|
||||
}
|
||||
|
||||
mparse_free(mp);
|
||||
@ -108,16 +113,12 @@ pmandoc(struct mparse *mp, int fd, const char *fn, int list)
|
||||
struct man *man;
|
||||
int line, col;
|
||||
|
||||
if (mparse_readfd(mp, fd, fn) >= MANDOCLEVEL_FATAL) {
|
||||
fprintf(stderr, "%s: Parse failure\n", fn);
|
||||
return;
|
||||
}
|
||||
|
||||
mparse_readfd(mp, fd, fn);
|
||||
mparse_result(mp, &mdoc, &man, NULL);
|
||||
line = 1;
|
||||
col = 0;
|
||||
|
||||
if (mdoc)
|
||||
if (mdoc)
|
||||
pmdoc(mdoc_node(mdoc), &line, &col, list);
|
||||
else if (man)
|
||||
pman(man_node(man), &line, &col, list);
|
||||
@ -167,7 +168,7 @@ pstring(const char *p, int col, int *colp, int list)
|
||||
end = p - 1;
|
||||
|
||||
while (end > start)
|
||||
if ('.' == *end || ',' == *end ||
|
||||
if ('.' == *end || ',' == *end ||
|
||||
'\'' == *end || '"' == *end ||
|
||||
')' == *end || '!' == *end ||
|
||||
'?' == *end || ':' == *end ||
|
||||
@ -199,7 +200,7 @@ pstring(const char *p, int col, int *colp, int list)
|
||||
/*
|
||||
* Print the input word, skipping any special characters.
|
||||
*/
|
||||
while ('\0' != *p)
|
||||
while ('\0' != *p)
|
||||
if ('\\' == *p) {
|
||||
p++;
|
||||
esc = mandoc_escape(&p, NULL, NULL);
|
||||
@ -220,7 +221,7 @@ pline(int line, int *linep, int *col, int list)
|
||||
|
||||
/*
|
||||
* Print out as many lines as needed to reach parity with the
|
||||
* original input.
|
||||
* original input.
|
||||
*/
|
||||
|
||||
while (*linep < line) {
|
||||
@ -240,7 +241,7 @@ pmdoc(const struct mdoc_node *p, int *line, int *col, int list)
|
||||
pline(p->line, line, col, list);
|
||||
if (MDOC_TEXT == p->type)
|
||||
pstring(p->string, p->pos, col, list);
|
||||
if (p->child)
|
||||
if (p->child)
|
||||
pmdoc(p->child, line, col, list);
|
||||
}
|
||||
}
|
||||
@ -254,7 +255,7 @@ pman(const struct man_node *p, int *line, int *col, int list)
|
||||
pline(p->line, line, col, list);
|
||||
if (MAN_TEXT == p->type)
|
||||
pstring(p->string, p->pos, col, list);
|
||||
if (p->child)
|
||||
if (p->child)
|
||||
pman(p->child, line, col, list);
|
||||
}
|
||||
}
|
||||
|
11
eqn.7
11
eqn.7
@ -1,4 +1,4 @@
|
||||
.\" $Id: eqn.7,v 1.31 2014/10/12 11:57:38 schwarze Exp $
|
||||
.\" $Id: eqn.7,v 1.33 2015/01/29 00:33:57 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: October 12 2014 $
|
||||
.Dd $Mdocdate: January 29 2015 $
|
||||
.Dt EQN 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -122,7 +122,7 @@ lambda, mu, nu, omega, omicron, phi, pi, psi, rho, sigma, tau, theta,
|
||||
upsilon, xi, zeta, DELTA, GAMMA, LAMBDA, OMEGA, PHI, PI, PSI, SIGMA,
|
||||
THETA, UPSILON, XI, inter (intersection), union (union), prod (product),
|
||||
int (integral), sum (summation), grad (gradient), del (vector
|
||||
differential), times (multiply), cdot (centre-dot), nothing (zero-width
|
||||
differential), times (multiply), cdot (center-dot), nothing (zero-width
|
||||
space), approx (approximately equals), prime (prime), half (one-half),
|
||||
partial (partial differential), inf (infinity), >> (much greater), <<
|
||||
(much less), \-> (left arrow), <\- (right arrow), +\- (plus-minus), !=
|
||||
@ -457,11 +457,6 @@ The
|
||||
and
|
||||
.Cm down Ar n
|
||||
commands are also ignored.
|
||||
.It
|
||||
Inline equations and the
|
||||
.Cm delim
|
||||
control statement are not yet implemented in
|
||||
.Xr mandoc 1 .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr mandoc 1 ,
|
||||
|
125
eqn.c
125
eqn.c
@ -1,7 +1,7 @@
|
||||
/* $Id: eqn.c,v 1.56 2014/10/25 15:06:30 schwarze Exp $ */
|
||||
/* $Id: eqn.c,v 1.57 2015/01/28 21:11:53 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -31,8 +31,6 @@
|
||||
#include "libmandoc.h"
|
||||
#include "libroff.h"
|
||||
|
||||
#define EQN_MSG(t, x) \
|
||||
mandoc_msg((t), (x)->parse, (x)->eqn.ln, (x)->eqn.pos, NULL)
|
||||
#define EQN_NEST_MAX 128 /* maximum nesting of defines */
|
||||
#define STRNEQ(p1, sz1, p2, sz2) \
|
||||
((sz1) == (sz2) && 0 == strncmp((p1), (p2), (sz1)))
|
||||
@ -266,6 +264,21 @@ static const struct eqnsym eqnsyms[EQNSYM__MAX] = {
|
||||
{ ">=", ">=" }, /* EQNSYM_moreequal */
|
||||
};
|
||||
|
||||
static struct eqn_box *eqn_box_alloc(struct eqn_node *, struct eqn_box *);
|
||||
static void eqn_box_free(struct eqn_box *);
|
||||
static struct eqn_box *eqn_box_makebinary(struct eqn_node *,
|
||||
enum eqn_post, struct eqn_box *);
|
||||
static void eqn_def(struct eqn_node *);
|
||||
static struct eqn_def *eqn_def_find(struct eqn_node *, const char *, size_t);
|
||||
static void eqn_delim(struct eqn_node *);
|
||||
static const char *eqn_next(struct eqn_node *, char, size_t *, int);
|
||||
static const char *eqn_nextrawtok(struct eqn_node *, size_t *);
|
||||
static const char *eqn_nexttok(struct eqn_node *, size_t *);
|
||||
static enum rofferr eqn_parse(struct eqn_node *, struct eqn_box *);
|
||||
static enum eqn_tok eqn_tok_parse(struct eqn_node *, char **);
|
||||
static void eqn_undef(struct eqn_node *);
|
||||
|
||||
|
||||
enum rofferr
|
||||
eqn_read(struct eqn_node **epp, int ln,
|
||||
const char *p, int pos, int *offs)
|
||||
@ -365,7 +378,8 @@ eqn_next(struct eqn_node *ep, char quote, size_t *sz, int repl)
|
||||
/* Prevent self-definitions. */
|
||||
|
||||
if (lim >= EQN_NEST_MAX) {
|
||||
EQN_MSG(MANDOCERR_ROFFLOOP, ep);
|
||||
mandoc_msg(MANDOCERR_ROFFLOOP, ep->parse,
|
||||
ep->eqn.ln, ep->eqn.pos, NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
@ -406,7 +420,8 @@ eqn_next(struct eqn_node *ep, char quote, size_t *sz, int repl)
|
||||
ep->cur++;
|
||||
} else {
|
||||
if (q)
|
||||
EQN_MSG(MANDOCERR_ARG_QUOTE, ep);
|
||||
mandoc_msg(MANDOCERR_ARG_QUOTE, ep->parse,
|
||||
ep->eqn.ln, ep->eqn.pos, NULL);
|
||||
next = strchr(start, '\0');
|
||||
*sz = (size_t)(next - start);
|
||||
ep->cur += *sz;
|
||||
@ -600,23 +615,27 @@ eqn_delim(struct eqn_node *ep)
|
||||
/*
|
||||
* Undefine a previously-defined string.
|
||||
*/
|
||||
static int
|
||||
static void
|
||||
eqn_undef(struct eqn_node *ep)
|
||||
{
|
||||
const char *start;
|
||||
struct eqn_def *def;
|
||||
size_t sz;
|
||||
|
||||
if (NULL == (start = eqn_nextrawtok(ep, &sz))) {
|
||||
EQN_MSG(MANDOCERR_EQNEOF, ep);
|
||||
return(0);
|
||||
} else if (NULL != (def = eqn_def_find(ep, start, sz)))
|
||||
def->keysz = 0;
|
||||
|
||||
return(1);
|
||||
if ((start = eqn_nextrawtok(ep, &sz)) == NULL) {
|
||||
mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
|
||||
ep->eqn.ln, ep->eqn.pos, "undef");
|
||||
return;
|
||||
}
|
||||
if ((def = eqn_def_find(ep, start, sz)) == NULL)
|
||||
return;
|
||||
free(def->key);
|
||||
free(def->val);
|
||||
def->key = def->val = NULL;
|
||||
def->keysz = def->valsz = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
eqn_def(struct eqn_node *ep)
|
||||
{
|
||||
const char *start;
|
||||
@ -624,9 +643,10 @@ eqn_def(struct eqn_node *ep)
|
||||
struct eqn_def *def;
|
||||
int i;
|
||||
|
||||
if (NULL == (start = eqn_nextrawtok(ep, &sz))) {
|
||||
EQN_MSG(MANDOCERR_EQNEOF, ep);
|
||||
return(0);
|
||||
if ((start = eqn_nextrawtok(ep, &sz)) == NULL) {
|
||||
mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
|
||||
ep->eqn.ln, ep->eqn.pos, "define");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -646,47 +666,51 @@ eqn_def(struct eqn_node *ep)
|
||||
ep->defs[i].key = ep->defs[i].val = NULL;
|
||||
}
|
||||
|
||||
ep->defs[i].keysz = sz;
|
||||
ep->defs[i].key = mandoc_realloc(
|
||||
ep->defs[i].key, sz + 1);
|
||||
|
||||
memcpy(ep->defs[i].key, start, sz);
|
||||
ep->defs[i].key[(int)sz] = '\0';
|
||||
def = &ep->defs[i];
|
||||
def = ep->defs + i;
|
||||
free(def->key);
|
||||
def->key = mandoc_strndup(start, sz);
|
||||
def->keysz = sz;
|
||||
}
|
||||
|
||||
start = eqn_next(ep, ep->data[(int)ep->cur], &sz, 0);
|
||||
|
||||
if (NULL == start) {
|
||||
EQN_MSG(MANDOCERR_EQNEOF, ep);
|
||||
return(-1);
|
||||
if (start == NULL) {
|
||||
mandoc_vmsg(MANDOCERR_REQ_EMPTY, ep->parse,
|
||||
ep->eqn.ln, ep->eqn.pos, "define %s", def->key);
|
||||
free(def->key);
|
||||
free(def->val);
|
||||
def->key = def->val = NULL;
|
||||
def->keysz = def->valsz = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
free(def->val);
|
||||
def->val = mandoc_strndup(start, sz);
|
||||
def->valsz = sz;
|
||||
def->val = mandoc_realloc(def->val, sz + 1);
|
||||
memcpy(def->val, start, sz);
|
||||
def->val[(int)sz] = '\0';
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Recursively parse an eqn(7) expression.
|
||||
*/
|
||||
static int
|
||||
static enum rofferr
|
||||
eqn_parse(struct eqn_node *ep, struct eqn_box *parent)
|
||||
{
|
||||
char sym[64];
|
||||
struct eqn_box *cur;
|
||||
const char *start;
|
||||
char *p;
|
||||
size_t i, sz;
|
||||
enum eqn_tok tok, subtok;
|
||||
enum eqn_post pos;
|
||||
struct eqn_box *cur;
|
||||
int rc, size;
|
||||
size_t i, sz;
|
||||
char sym[64];
|
||||
const char *start;
|
||||
int size;
|
||||
|
||||
assert(parent != NULL);
|
||||
|
||||
/*
|
||||
* Empty equation.
|
||||
* Do not add it to the high-level syntax tree.
|
||||
*/
|
||||
|
||||
if (ep->data == NULL)
|
||||
return(-1);
|
||||
return(ROFF_IGN);
|
||||
|
||||
next_tok:
|
||||
tok = eqn_tok_parse(ep, &p);
|
||||
@ -694,20 +718,17 @@ eqn_parse(struct eqn_node *ep, struct eqn_box *parent)
|
||||
this_tok:
|
||||
switch (tok) {
|
||||
case (EQN_TOK_UNDEF):
|
||||
if ((rc = eqn_undef(ep)) <= 0)
|
||||
return(rc);
|
||||
eqn_undef(ep);
|
||||
break;
|
||||
case (EQN_TOK_NDEFINE):
|
||||
case (EQN_TOK_DEFINE):
|
||||
if ((rc = eqn_def(ep)) <= 0)
|
||||
return(rc);
|
||||
eqn_def(ep);
|
||||
break;
|
||||
case (EQN_TOK_TDEFINE):
|
||||
if (NULL == eqn_nextrawtok(ep, NULL))
|
||||
EQN_MSG(MANDOCERR_EQNEOF, ep);
|
||||
else if (NULL == eqn_next(ep,
|
||||
ep->data[(int)ep->cur], NULL, 0))
|
||||
EQN_MSG(MANDOCERR_EQNEOF, ep);
|
||||
if (eqn_nextrawtok(ep, NULL) == NULL ||
|
||||
eqn_next(ep, ep->data[(int)ep->cur], NULL, 0) == NULL)
|
||||
mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
|
||||
ep->eqn.ln, ep->eqn.pos, "tdefine");
|
||||
break;
|
||||
case (EQN_TOK_DELIM):
|
||||
eqn_delim(ep);
|
||||
@ -1037,7 +1058,7 @@ eqn_parse(struct eqn_node *ep, struct eqn_box *parent)
|
||||
* End of file!
|
||||
* TODO: make sure we're not in an open subexpression.
|
||||
*/
|
||||
return(0);
|
||||
return(ROFF_EQN);
|
||||
default:
|
||||
assert(tok == EQN_TOK__MAX);
|
||||
assert(NULL != p);
|
||||
@ -1081,7 +1102,7 @@ eqn_end(struct eqn_node **epp)
|
||||
|
||||
ep->eqn.root = mandoc_calloc(1, sizeof(struct eqn_box));
|
||||
ep->eqn.root->expectargs = UINT_MAX;
|
||||
return(0 == eqn_parse(ep, ep->eqn.root) ? ROFF_EQN : ROFF_IGN);
|
||||
return(eqn_parse(ep, ep->eqn.root));
|
||||
}
|
||||
|
||||
void
|
||||
|
21
eqn_term.c
21
eqn_term.c
@ -1,7 +1,7 @@
|
||||
/* $Id: eqn_term.c,v 1.7 2014/10/12 14:49:39 schwarze Exp $ */
|
||||
/* $Id: eqn_term.c,v 1.8 2015/01/01 15:36:08 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -79,14 +79,17 @@ eqn_box(struct termp *p, const struct eqn_box *bp)
|
||||
bp->pos == EQNPOS_TO) ? "^" : "_");
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
child = child->next;
|
||||
eqn_box(p, child);
|
||||
if (bp->pos == EQNPOS_FROMTO ||
|
||||
bp->pos == EQNPOS_SUBSUP) {
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, "^");
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
child = child->next;
|
||||
if (child != NULL) {
|
||||
eqn_box(p, child);
|
||||
if (bp->pos == EQNPOS_FROMTO ||
|
||||
bp->pos == EQNPOS_SUBSUP) {
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
term_word(p, "^");
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
child = child->next;
|
||||
if (child != NULL)
|
||||
eqn_box(p, child);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
child = bp->first;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: example.style.css,v 1.54 2014/12/10 22:19:45 schwarze Exp $ */
|
||||
/* $Id: example.style.css,v 1.55 2015/02/10 08:05:30 schwarze Exp $ */
|
||||
/*
|
||||
* This is an example style-sheet provided for mandoc(1) and the -Thtml
|
||||
* or -Txhtml output mode.
|
||||
@ -6,8 +6,8 @@
|
||||
* See mdoc(7) and man(7) for macro explanations.
|
||||
*/
|
||||
|
||||
div.mandoc { min-width: 102ex;
|
||||
width: 102ex;
|
||||
div.mandoc { min-width: 102ex;
|
||||
width: 102ex;
|
||||
font-family: monospace; } /* This is the outer node of all mandoc -T[x]html documents. */
|
||||
div.mandoc h1 { margin-bottom: 0ex; font-size: inherit; margin-left: -4ex; } /* Section header (Sh, SH). */
|
||||
div.mandoc h2 { margin-bottom: 0ex; font-size: inherit; margin-left: -2ex; } /* Sub-section header (Ss, SS). */
|
||||
@ -39,7 +39,7 @@ div.mandoc .lit { font-style: normal; font-weight: normal; font-family: monosp
|
||||
div.mandoc i.addr { font-weight: normal; } /* Address (Ad). */
|
||||
div.mandoc i.arg { font-weight: normal; } /* Command argument (Ar). */
|
||||
div.mandoc span.author { } /* Author name (An). */
|
||||
div.mandoc b.cmd { font-style: normal; } /* Command (Cm). */
|
||||
div.mandoc b.cmd { font-style: normal; } /* Command (Cm). */
|
||||
div.mandoc b.config { font-style: normal; } /* Config statement (Cd). */
|
||||
div.mandoc span.define { } /* Defines (Dv). */
|
||||
div.mandoc span.desc { } /* Nd. After em-dash. */
|
||||
|
22
gmdiff
22
gmdiff
@ -19,20 +19,32 @@ if [ `id -u` -eq 0 ]; then
|
||||
fi
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "usage: $0 manual_source_file ..."
|
||||
echo "usage: $0 -h manual_source_file ..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "X$1" = "X-h" ]; then
|
||||
shift
|
||||
export PATH="/usr/local/heirloom-doctools/bin:$PATH"
|
||||
EQN="neqn"
|
||||
ROFF="nroff"
|
||||
MOPT="-Omdoc $MOPT"
|
||||
else
|
||||
EQN="eqn -Tascii"
|
||||
ROFF="groff -ww -Tascii -P -c"
|
||||
fi
|
||||
MOPT="-Werror $MOPT"
|
||||
|
||||
while [ -n "$1" ]; do
|
||||
file=$1
|
||||
shift
|
||||
echo " ========== $file ========== "
|
||||
tbl $file | groff -mandoc -Tascii -P -c 2> /tmp/groff.err > /tmp/groff.out
|
||||
mandoc -Ios='OpenBSD ports' -Werror $file 2> /tmp/mandoc.err > /tmp/mandoc.out
|
||||
for i in groff mandoc; do
|
||||
tbl $file | $EQN | $ROFF -mandoc 2> /tmp/roff.err > /tmp/roff.out
|
||||
mandoc -Ios='OpenBSD ports' $MOPT $file 2> /tmp/mandoc.err > /tmp/mandoc.out
|
||||
for i in roff mandoc; do
|
||||
[[ -s /tmp/$i.err ]] && echo "$i errors:" && cat /tmp/$i.err
|
||||
done
|
||||
diff -au /tmp/groff.out /tmp/mandoc.out 2>&1
|
||||
diff -au /tmp/roff.out /tmp/mandoc.out 2>&1
|
||||
done
|
||||
|
||||
exit 0
|
||||
|
55
html.c
55
html.c
@ -1,7 +1,7 @@
|
||||
/* $Id: html.c,v 1.183 2014/12/02 10:08:06 schwarze Exp $ */
|
||||
/* $Id: html.c,v 1.185 2015/01/21 20:33:25 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -121,7 +121,7 @@ static const char *const roffscales[SCALE_MAX] = {
|
||||
};
|
||||
|
||||
static void bufncat(struct html *, const char *, size_t);
|
||||
static void print_ctag(struct html *, enum htmltag);
|
||||
static void print_ctag(struct html *, struct tag *);
|
||||
static int print_escape(char);
|
||||
static int print_encode(struct html *, const char *, int);
|
||||
static void print_metaf(struct html *, enum mandoc_esc);
|
||||
@ -307,6 +307,8 @@ html_strlen(const char *cp)
|
||||
case ESCAPE_NUMBERED:
|
||||
/* FALLTHROUGH */
|
||||
case ESCAPE_SPECIAL:
|
||||
/* FALLTHROUGH */
|
||||
case ESCAPE_OVERSTRIKE:
|
||||
if (skip)
|
||||
skip = 0;
|
||||
else
|
||||
@ -433,6 +435,11 @@ print_encode(struct html *h, const char *p, int norecurse)
|
||||
if ('\0' == *p)
|
||||
nospace = 1;
|
||||
continue;
|
||||
case ESCAPE_OVERSTRIKE:
|
||||
if (len == 0)
|
||||
continue;
|
||||
c = seq[len - 1];
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@ -511,14 +518,26 @@ print_otag(struct html *h, enum htmltag tag,
|
||||
}
|
||||
|
||||
static void
|
||||
print_ctag(struct html *h, enum htmltag tag)
|
||||
print_ctag(struct html *h, struct tag *tag)
|
||||
{
|
||||
|
||||
printf("</%s>", htmltags[tag].name);
|
||||
if (HTML_CLRLINE & htmltags[tag].flags) {
|
||||
/*
|
||||
* Remember to close out and nullify the current
|
||||
* meta-font and table, if applicable.
|
||||
*/
|
||||
if (tag == h->metaf)
|
||||
h->metaf = NULL;
|
||||
if (tag == h->tblt)
|
||||
h->tblt = NULL;
|
||||
|
||||
printf("</%s>", htmltags[tag->tag].name);
|
||||
if (HTML_CLRLINE & htmltags[tag->tag].flags) {
|
||||
h->flags |= HTML_NOSPACE;
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
h->tags.head = tag->next;
|
||||
free(tag);
|
||||
}
|
||||
|
||||
void
|
||||
@ -580,17 +599,7 @@ print_tagq(struct html *h, const struct tag *until)
|
||||
struct tag *tag;
|
||||
|
||||
while ((tag = h->tags.head) != NULL) {
|
||||
/*
|
||||
* Remember to close out and nullify the current
|
||||
* meta-font and table, if applicable.
|
||||
*/
|
||||
if (tag == h->metaf)
|
||||
h->metaf = NULL;
|
||||
if (tag == h->tblt)
|
||||
h->tblt = NULL;
|
||||
print_ctag(h, tag->tag);
|
||||
h->tags.head = tag->next;
|
||||
free(tag);
|
||||
print_ctag(h, tag);
|
||||
if (until && tag == until)
|
||||
return;
|
||||
}
|
||||
@ -604,17 +613,7 @@ print_stagq(struct html *h, const struct tag *suntil)
|
||||
while ((tag = h->tags.head) != NULL) {
|
||||
if (suntil && tag == suntil)
|
||||
return;
|
||||
/*
|
||||
* Remember to close out and nullify the current
|
||||
* meta-font and table, if applicable.
|
||||
*/
|
||||
if (tag == h->metaf)
|
||||
h->metaf = NULL;
|
||||
if (tag == h->tblt)
|
||||
h->tblt = NULL;
|
||||
print_ctag(h, tag->tag);
|
||||
h->tags.head = tag->next;
|
||||
free(tag);
|
||||
print_ctag(h, tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
3
libman.h
3
libman.h
@ -1,4 +1,4 @@
|
||||
/* $Id: libman.h,v 1.66 2014/12/01 04:05:31 schwarze Exp $ */
|
||||
/* $Id: libman.h,v 1.67 2014/12/28 14:42:27 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -23,6 +23,7 @@ enum man_next {
|
||||
|
||||
struct man {
|
||||
struct mparse *parse; /* parse pointer */
|
||||
const char *defos; /* default OS argument for .TH */
|
||||
int quick; /* abort parse early */
|
||||
int flags; /* parse flags */
|
||||
#define MAN_ELINE (1 << 1) /* Next-line element scope. */
|
||||
|
13
libmandoc.h
13
libmandoc.h
@ -1,4 +1,4 @@
|
||||
/* $Id: libmandoc.h,v 1.51 2014/12/01 08:05:52 schwarze Exp $ */
|
||||
/* $Id: libmandoc.h,v 1.55 2015/01/15 04:26:39 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -24,8 +24,7 @@ enum rofferr {
|
||||
ROFF_SO, /* include another file */
|
||||
ROFF_IGN, /* ignore current line */
|
||||
ROFF_TBL, /* a table row was successfully parsed */
|
||||
ROFF_EQN, /* an equation was successfully parsed */
|
||||
ROFF_ERR /* badness: puke and stop */
|
||||
ROFF_EQN /* an equation was successfully parsed */
|
||||
};
|
||||
|
||||
struct buf {
|
||||
@ -37,7 +36,6 @@ __BEGIN_DECLS
|
||||
|
||||
struct mparse;
|
||||
struct mchars;
|
||||
enum mandocerr;
|
||||
struct tbl_span;
|
||||
struct eqn;
|
||||
struct roff;
|
||||
@ -62,15 +60,16 @@ struct mdoc *mdoc_alloc(struct roff *, struct mparse *,
|
||||
const char *, int);
|
||||
void mdoc_reset(struct mdoc *);
|
||||
int mdoc_parseln(struct mdoc *, int, char *, int);
|
||||
int mdoc_endparse(struct mdoc *);
|
||||
void mdoc_endparse(struct mdoc *);
|
||||
void mdoc_addspan(struct mdoc *, const struct tbl_span *);
|
||||
void mdoc_addeqn(struct mdoc *, const struct eqn *);
|
||||
|
||||
void man_free(struct man *);
|
||||
struct man *man_alloc(struct roff *, struct mparse *, int);
|
||||
struct man *man_alloc(struct roff *, struct mparse *,
|
||||
const char *, int);
|
||||
void man_reset(struct man *);
|
||||
int man_parseln(struct man *, int, char *, int);
|
||||
int man_endparse(struct man *);
|
||||
void man_endparse(struct man *);
|
||||
void man_addspan(struct man *, const struct tbl_span *);
|
||||
void man_addeqn(struct man *, const struct eqn *);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: libmdoc.h,v 1.96 2014/12/01 04:05:32 schwarze Exp $ */
|
||||
/* $Id: libmdoc.h,v 1.97 2015/02/02 04:26:44 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -106,7 +106,7 @@ struct mdoc_node *mdoc_block_alloc(struct mdoc *, int, int,
|
||||
struct mdoc_node *mdoc_head_alloc(struct mdoc *, int, int, enum mdoct);
|
||||
void mdoc_tail_alloc(struct mdoc *, int, int, enum mdoct);
|
||||
struct mdoc_node *mdoc_body_alloc(struct mdoc *, int, int, enum mdoct);
|
||||
void mdoc_endbody_alloc(struct mdoc *, int, int, enum mdoct,
|
||||
struct mdoc_node *mdoc_endbody_alloc(struct mdoc *, int, int, enum mdoct,
|
||||
struct mdoc_node *, enum mdoc_endbody);
|
||||
void mdoc_node_delete(struct mdoc *, struct mdoc_node *);
|
||||
void mdoc_node_relink(struct mdoc *, struct mdoc_node *);
|
||||
|
16
libroff.h
16
libroff.h
@ -1,7 +1,7 @@
|
||||
/* $Id: libroff.h,v 1.33 2014/12/01 08:05:52 schwarze Exp $ */
|
||||
/* $Id: libroff.h,v 1.38 2015/01/30 04:11:50 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -34,8 +34,6 @@ struct tbl_node {
|
||||
struct tbl_span *first_span;
|
||||
struct tbl_span *current_span;
|
||||
struct tbl_span *last_span;
|
||||
struct tbl_head *first_head;
|
||||
struct tbl_head *last_head;
|
||||
struct tbl_node *next;
|
||||
};
|
||||
|
||||
@ -69,12 +67,12 @@ void tbl_restart(int, int, struct tbl_node *);
|
||||
void tbl_free(struct tbl_node *);
|
||||
void tbl_reset(struct tbl_node *);
|
||||
enum rofferr tbl_read(struct tbl_node *, int, const char *, int);
|
||||
int tbl_option(struct tbl_node *, int, const char *);
|
||||
int tbl_layout(struct tbl_node *, int, const char *);
|
||||
int tbl_data(struct tbl_node *, int, const char *);
|
||||
int tbl_cdata(struct tbl_node *, int, const char *);
|
||||
void tbl_option(struct tbl_node *, int, const char *, int *);
|
||||
void tbl_layout(struct tbl_node *, int, const char *, int);
|
||||
void tbl_data(struct tbl_node *, int, const char *, int);
|
||||
int tbl_cdata(struct tbl_node *, int, const char *, int);
|
||||
const struct tbl_span *tbl_span(struct tbl_node *);
|
||||
void tbl_end(struct tbl_node **);
|
||||
int tbl_end(struct tbl_node **);
|
||||
struct eqn_node *eqn_alloc(int, int, struct mparse *);
|
||||
enum rofferr eqn_end(struct eqn_node **);
|
||||
void eqn_free(struct eqn_node *);
|
||||
|
311
main.c
311
main.c
@ -1,7 +1,7 @@
|
||||
/* $Id: main.c,v 1.205 2014/12/11 19:19:35 schwarze Exp $ */
|
||||
/* $Id: main.c,v 1.222 2015/02/27 16:02:10 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2010-2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@ -19,11 +19,13 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h> /* MACHINE */
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <glob.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
@ -82,6 +84,13 @@ struct curparse {
|
||||
char outopts[BUFSIZ]; /* buf of output opts */
|
||||
};
|
||||
|
||||
static int fs_lookup(const struct manpaths *,
|
||||
size_t ipath, const char *,
|
||||
const char *, const char *,
|
||||
struct manpage **, size_t *);
|
||||
static void fs_search(const struct mansearch *,
|
||||
const struct manpaths *, int, char**,
|
||||
struct manpage **, size_t *);
|
||||
static int koptions(int *, char *);
|
||||
#if HAVE_SQLITE3
|
||||
int mandocdb(int, char**);
|
||||
@ -91,13 +100,10 @@ static void mmsg(enum mandocerr, enum mandoclevel,
|
||||
const char *, int, int, const char *);
|
||||
static void parse(struct curparse *, int,
|
||||
const char *, enum mandoclevel *);
|
||||
#if HAVE_SQLITE3
|
||||
static enum mandoclevel passthrough(const char *, int, int);
|
||||
#endif
|
||||
static void spawn_pager(void);
|
||||
static int toptions(struct curparse *, char *);
|
||||
static void usage(enum argmode) __attribute__((noreturn));
|
||||
static void version(void) __attribute__((noreturn));
|
||||
static int woptions(struct curparse *, char *);
|
||||
|
||||
static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9};
|
||||
@ -114,14 +120,13 @@ main(int argc, char *argv[])
|
||||
struct manpaths paths;
|
||||
char *auxpaths;
|
||||
char *defos;
|
||||
#if HAVE_SQLITE3
|
||||
unsigned char *uc;
|
||||
struct manpage *res, *resp;
|
||||
char *conf_file, *defpaths;
|
||||
size_t isec, i, sz;
|
||||
int prio, best_prio, synopsis_only;
|
||||
char sec;
|
||||
#endif
|
||||
enum mandoclevel rc;
|
||||
enum mandoclevel rc, rctmp;
|
||||
enum outmode outmode;
|
||||
int fd;
|
||||
int show_usage;
|
||||
@ -129,8 +134,9 @@ main(int argc, char *argv[])
|
||||
int options;
|
||||
int c;
|
||||
|
||||
progname = strrchr(argv[0], '/');
|
||||
if (progname == NULL)
|
||||
if (argc < 1)
|
||||
progname = "mandoc";
|
||||
else if ((progname = strrchr(argv[0], '/')) == NULL)
|
||||
progname = argv[0];
|
||||
else
|
||||
++progname;
|
||||
@ -143,9 +149,7 @@ main(int argc, char *argv[])
|
||||
/* Search options. */
|
||||
|
||||
memset(&paths, 0, sizeof(struct manpaths));
|
||||
#if HAVE_SQLITE3
|
||||
conf_file = defpaths = NULL;
|
||||
#endif
|
||||
auxpaths = NULL;
|
||||
|
||||
memset(&search, 0, sizeof(struct mansearch));
|
||||
@ -166,15 +170,13 @@ main(int argc, char *argv[])
|
||||
|
||||
memset(&curp, 0, sizeof(struct curparse));
|
||||
curp.outtype = OUTT_LOCALE;
|
||||
curp.wlevel = MANDOCLEVEL_FATAL;
|
||||
curp.wlevel = MANDOCLEVEL_BADARG;
|
||||
options = MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1;
|
||||
defos = NULL;
|
||||
|
||||
use_pager = 1;
|
||||
show_usage = 0;
|
||||
#if HAVE_SQLITE3
|
||||
synopsis_only = 0;
|
||||
#endif
|
||||
outmode = OUTMODE_DEF;
|
||||
|
||||
while (-1 != (c = getopt(argc, argv,
|
||||
@ -184,9 +186,7 @@ main(int argc, char *argv[])
|
||||
outmode = OUTMODE_ALL;
|
||||
break;
|
||||
case 'C':
|
||||
#if HAVE_SQLITE3
|
||||
conf_file = optarg;
|
||||
#endif
|
||||
break;
|
||||
case 'c':
|
||||
use_pager = 0;
|
||||
@ -196,22 +196,20 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
case 'h':
|
||||
(void)strlcat(curp.outopts, "synopsis,", BUFSIZ);
|
||||
#if HAVE_SQLITE3
|
||||
synopsis_only = 1;
|
||||
#endif
|
||||
use_pager = 0;
|
||||
outmode = OUTMODE_ALL;
|
||||
break;
|
||||
case 'I':
|
||||
if (strncmp(optarg, "os=", 3)) {
|
||||
fprintf(stderr,
|
||||
"%s: -I%s: Bad argument\n",
|
||||
"%s: -I %s: Bad argument\n",
|
||||
progname, optarg);
|
||||
return((int)MANDOCLEVEL_BADARG);
|
||||
}
|
||||
if (defos) {
|
||||
fprintf(stderr,
|
||||
"%s: -I%s: Duplicate argument\n",
|
||||
"%s: -I %s: Duplicate argument\n",
|
||||
progname, optarg);
|
||||
return((int)MANDOCLEVEL_BADARG);
|
||||
}
|
||||
@ -232,9 +230,7 @@ main(int argc, char *argv[])
|
||||
outmode = OUTMODE_ALL;
|
||||
break;
|
||||
case 'M':
|
||||
#if HAVE_SQLITE3
|
||||
defpaths = optarg;
|
||||
#endif
|
||||
break;
|
||||
case 'm':
|
||||
auxpaths = optarg;
|
||||
@ -261,9 +257,6 @@ main(int argc, char *argv[])
|
||||
case 'w':
|
||||
outmode = OUTMODE_FLN;
|
||||
break;
|
||||
case 'V':
|
||||
version();
|
||||
/* NOTREACHED */
|
||||
default:
|
||||
show_usage = 1;
|
||||
break;
|
||||
@ -292,11 +285,11 @@ main(int argc, char *argv[])
|
||||
|
||||
/* Parse arguments. */
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
#if HAVE_SQLITE3
|
||||
if (argc > 0) {
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
}
|
||||
resp = NULL;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Quirks for help(1)
|
||||
@ -309,13 +302,19 @@ main(int argc, char *argv[])
|
||||
argv = help_argv;
|
||||
argc = 1;
|
||||
}
|
||||
} else if (argv[0] != NULL &&
|
||||
isdigit((unsigned char)argv[0][0]) &&
|
||||
(argv[0][1] == '\0' || !strcmp(argv[0], "3p"))) {
|
||||
search.sec = argv[0];
|
||||
} else if (argc > 1 &&
|
||||
((uc = argv[0]) != NULL) &&
|
||||
((isdigit(uc[0]) && (uc[1] == '\0' ||
|
||||
(isalpha(uc[1]) && uc[2] == '\0'))) ||
|
||||
(uc[0] == 'n' && uc[1] == '\0'))) {
|
||||
search.sec = uc;
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
if (search.arch == NULL)
|
||||
search.arch = getenv("MACHINE");
|
||||
if (search.arch == NULL)
|
||||
search.arch = MACHINE;
|
||||
}
|
||||
|
||||
rc = MANDOCLEVEL_OK;
|
||||
@ -323,7 +322,6 @@ main(int argc, char *argv[])
|
||||
/* man(1), whatis(1), apropos(1) */
|
||||
|
||||
if (search.argmode != ARG_FILE) {
|
||||
#if HAVE_SQLITE3
|
||||
if (argc == 0)
|
||||
usage(search.argmode);
|
||||
|
||||
@ -334,15 +332,23 @@ main(int argc, char *argv[])
|
||||
/* Access the mandoc database. */
|
||||
|
||||
manpath_parse(&paths, conf_file, defpaths, auxpaths);
|
||||
#if HAVE_SQLITE3
|
||||
mansearch_setup(1);
|
||||
if( ! mansearch(&search, &paths, argc, argv, &res, &sz))
|
||||
usage(search.argmode);
|
||||
resp = res;
|
||||
#else
|
||||
if (search.argmode != ARG_NAME) {
|
||||
fputs("mandoc: database support not compiled in\n",
|
||||
stderr);
|
||||
return((int)MANDOCLEVEL_BADARG);
|
||||
}
|
||||
sz = 0;
|
||||
#endif
|
||||
|
||||
if (sz == 0 && search.argmode == ARG_NAME)
|
||||
fs_search(&search, &paths, argc, argv, &res, &sz);
|
||||
|
||||
if (sz == 0) {
|
||||
if (search.argmode == ARG_NAME)
|
||||
fprintf(stderr, "%s: No entry for %s "
|
||||
"in the manual.\n", progname, argv[0]);
|
||||
rc = MANDOCLEVEL_BADARG;
|
||||
goto out;
|
||||
}
|
||||
@ -361,6 +367,7 @@ main(int argc, char *argv[])
|
||||
|
||||
/* Iterate all matching manuals. */
|
||||
|
||||
resp = res;
|
||||
for (i = 0; i < sz; i++) {
|
||||
if (outmode == OUTMODE_FLN)
|
||||
puts(res[i].file);
|
||||
@ -390,21 +397,13 @@ main(int argc, char *argv[])
|
||||
|
||||
if (outmode == OUTMODE_FLN || outmode == OUTMODE_LST)
|
||||
goto out;
|
||||
#else
|
||||
fputs("mandoc: database support not compiled in\n",
|
||||
stderr);
|
||||
return((int)MANDOCLEVEL_BADARG);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* mandoc(1) */
|
||||
|
||||
if ( ! moptions(&options, auxpaths))
|
||||
if (search.argmode == ARG_FILE && ! moptions(&options, auxpaths))
|
||||
return((int)MANDOCLEVEL_BADARG);
|
||||
|
||||
if (use_pager && isatty(STDOUT_FILENO))
|
||||
spawn_pager();
|
||||
|
||||
curp.mchars = mchars_alloc();
|
||||
curp.mp = mparse_alloc(options, curp.wlevel, mmsg,
|
||||
curp.mchars, defos);
|
||||
@ -415,37 +414,53 @@ main(int argc, char *argv[])
|
||||
if (OUTT_MAN == curp.outtype)
|
||||
mparse_keep(curp.mp);
|
||||
|
||||
if (argc == 0)
|
||||
if (argc < 1) {
|
||||
if (use_pager && isatty(STDOUT_FILENO))
|
||||
spawn_pager();
|
||||
parse(&curp, STDIN_FILENO, "<stdin>", &rc);
|
||||
}
|
||||
|
||||
while (argc) {
|
||||
#if HAVE_SQLITE3
|
||||
if (resp != NULL) {
|
||||
rc = mparse_open(curp.mp, &fd, resp->file);
|
||||
if (fd == -1)
|
||||
/* nothing */;
|
||||
while (argc > 0) {
|
||||
rctmp = mparse_open(curp.mp, &fd,
|
||||
resp != NULL ? resp->file : *argv);
|
||||
if (rc < rctmp)
|
||||
rc = rctmp;
|
||||
|
||||
if (fd != -1) {
|
||||
if (use_pager && isatty(STDOUT_FILENO))
|
||||
spawn_pager();
|
||||
use_pager = 0;
|
||||
|
||||
if (resp == NULL)
|
||||
parse(&curp, fd, *argv, &rc);
|
||||
else if (resp->form & FORM_SRC) {
|
||||
/* For .so only; ignore failure. */
|
||||
chdir(paths.paths[resp->ipath]);
|
||||
parse(&curp, fd, resp->file, &rc);
|
||||
} else
|
||||
rc = passthrough(resp->file, fd,
|
||||
} else {
|
||||
rctmp = passthrough(resp->file, fd,
|
||||
synopsis_only);
|
||||
resp++;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
rc = mparse_open(curp.mp, &fd, *argv++);
|
||||
if (fd != -1)
|
||||
parse(&curp, fd, argv[-1], &rc);
|
||||
}
|
||||
if (rc < rctmp)
|
||||
rc = rctmp;
|
||||
}
|
||||
|
||||
if (mparse_wait(curp.mp) != MANDOCLEVEL_OK)
|
||||
rc = MANDOCLEVEL_SYSERR;
|
||||
rctmp = mparse_wait(curp.mp);
|
||||
if (rc < rctmp)
|
||||
rc = rctmp;
|
||||
|
||||
if (argc > 1 && curp.outtype <= OUTT_UTF8)
|
||||
ascii_sepline(curp.outdata);
|
||||
}
|
||||
|
||||
if (MANDOCLEVEL_OK != rc && curp.wstop)
|
||||
break;
|
||||
argc--;
|
||||
|
||||
if (resp != NULL)
|
||||
resp++;
|
||||
else
|
||||
argv++;
|
||||
if (--argc)
|
||||
mparse_reset(curp.mp);
|
||||
}
|
||||
|
||||
if (curp.outfree)
|
||||
@ -453,50 +468,44 @@ main(int argc, char *argv[])
|
||||
mparse_free(curp.mp);
|
||||
mchars_free(curp.mchars);
|
||||
|
||||
#if HAVE_SQLITE3
|
||||
out:
|
||||
if (search.argmode != ARG_FILE) {
|
||||
manpath_free(&paths);
|
||||
#if HAVE_SQLITE3
|
||||
mansearch_free(res, sz);
|
||||
mansearch_setup(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
free(defos);
|
||||
|
||||
return((int)rc);
|
||||
}
|
||||
|
||||
static void
|
||||
version(void)
|
||||
{
|
||||
|
||||
printf("mandoc %s\n", VERSION);
|
||||
exit((int)MANDOCLEVEL_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(enum argmode argmode)
|
||||
{
|
||||
|
||||
switch (argmode) {
|
||||
case ARG_FILE:
|
||||
fputs("usage: mandoc [-acfhklV] [-Ios=name] "
|
||||
fputs("usage: mandoc [-acfhkl] [-Ios=name] "
|
||||
"[-Kencoding] [-mformat] [-Ooption]\n"
|
||||
"\t [-Toutput] [-Wlevel] [file ...]\n", stderr);
|
||||
break;
|
||||
case ARG_NAME:
|
||||
fputs("usage: man [-acfhklVw] [-C file] "
|
||||
"[-M path] [-m path] [-S arch] [-s section]\n"
|
||||
fputs("usage: man [-acfhklw] [-C file] [-I os=name] "
|
||||
"[-K encoding] [-M path] [-m path]\n"
|
||||
"\t [-O option=value] [-S subsection] [-s section] "
|
||||
"[-T output] [-W level]\n"
|
||||
"\t [section] name ...\n", stderr);
|
||||
break;
|
||||
case ARG_WORD:
|
||||
fputs("usage: whatis [-acfhklVw] [-C file] "
|
||||
fputs("usage: whatis [-acfhklw] [-C file] "
|
||||
"[-M path] [-m path] [-O outkey] [-S arch]\n"
|
||||
"\t [-s section] name ...\n", stderr);
|
||||
break;
|
||||
case ARG_EXPR:
|
||||
fputs("usage: apropos [-acfhklVw] [-C file] "
|
||||
fputs("usage: apropos [-acfhklw] [-C file] "
|
||||
"[-M path] [-m path] [-O outkey] [-S arch]\n"
|
||||
"\t [-s section] expression ...\n", stderr);
|
||||
break;
|
||||
@ -504,6 +513,108 @@ usage(enum argmode argmode)
|
||||
exit((int)MANDOCLEVEL_BADARG);
|
||||
}
|
||||
|
||||
static int
|
||||
fs_lookup(const struct manpaths *paths, size_t ipath,
|
||||
const char *sec, const char *arch, const char *name,
|
||||
struct manpage **res, size_t *ressz)
|
||||
{
|
||||
glob_t globinfo;
|
||||
struct manpage *page;
|
||||
char *file;
|
||||
int form, globres;
|
||||
|
||||
form = FORM_SRC;
|
||||
mandoc_asprintf(&file, "%s/man%s/%s.%s",
|
||||
paths->paths[ipath], sec, name, sec);
|
||||
if (access(file, R_OK) != -1)
|
||||
goto found;
|
||||
free(file);
|
||||
|
||||
mandoc_asprintf(&file, "%s/cat%s/%s.0",
|
||||
paths->paths[ipath], sec, name);
|
||||
if (access(file, R_OK) != -1) {
|
||||
form = FORM_CAT;
|
||||
goto found;
|
||||
}
|
||||
free(file);
|
||||
|
||||
if (arch != NULL) {
|
||||
mandoc_asprintf(&file, "%s/man%s/%s/%s.%s",
|
||||
paths->paths[ipath], sec, arch, name, sec);
|
||||
if (access(file, R_OK) != -1)
|
||||
goto found;
|
||||
free(file);
|
||||
}
|
||||
|
||||
mandoc_asprintf(&file, "%s/man%s/%s.*",
|
||||
paths->paths[ipath], sec, name);
|
||||
globres = glob(file, 0, NULL, &globinfo);
|
||||
if (globres != 0 && globres != GLOB_NOMATCH)
|
||||
fprintf(stderr, "%s: %s: glob: %s\n",
|
||||
progname, file, strerror(errno));
|
||||
free(file);
|
||||
if (globres == 0)
|
||||
file = mandoc_strdup(*globinfo.gl_pathv);
|
||||
globfree(&globinfo);
|
||||
if (globres != 0)
|
||||
return(0);
|
||||
|
||||
found:
|
||||
#if HAVE_SQLITE3
|
||||
fprintf(stderr, "%s: outdated mandoc.db lacks %s(%s) entry,\n"
|
||||
" consider running # makewhatis %s\n",
|
||||
progname, name, sec, paths->paths[ipath]);
|
||||
#endif
|
||||
|
||||
*res = mandoc_reallocarray(*res, ++*ressz, sizeof(struct manpage));
|
||||
page = *res + (*ressz - 1);
|
||||
page->file = file;
|
||||
page->names = NULL;
|
||||
page->output = NULL;
|
||||
page->ipath = ipath;
|
||||
page->bits = NAME_FILE & NAME_MASK;
|
||||
page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10;
|
||||
page->form = form;
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void
|
||||
fs_search(const struct mansearch *cfg, const struct manpaths *paths,
|
||||
int argc, char **argv, struct manpage **res, size_t *ressz)
|
||||
{
|
||||
const char *const sections[] =
|
||||
{"1", "8", "6", "2", "3", "3p", "5", "7", "4", "9"};
|
||||
const size_t nsec = sizeof(sections)/sizeof(sections[0]);
|
||||
|
||||
size_t ipath, isec, lastsz;
|
||||
|
||||
assert(cfg->argmode == ARG_NAME);
|
||||
|
||||
*res = NULL;
|
||||
*ressz = lastsz = 0;
|
||||
while (argc) {
|
||||
for (ipath = 0; ipath < paths->sz; ipath++) {
|
||||
if (cfg->sec != NULL) {
|
||||
if (fs_lookup(paths, ipath, cfg->sec,
|
||||
cfg->arch, *argv, res, ressz) &&
|
||||
cfg->firstmatch)
|
||||
return;
|
||||
} else for (isec = 0; isec < nsec; isec++)
|
||||
if (fs_lookup(paths, ipath, sections[isec],
|
||||
cfg->arch, *argv, res, ressz) &&
|
||||
cfg->firstmatch)
|
||||
return;
|
||||
}
|
||||
if (*ressz == lastsz)
|
||||
fprintf(stderr,
|
||||
"%s: No entry for %s in the manual.\n",
|
||||
progname, *argv);
|
||||
lastsz = *ressz;
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse(struct curparse *curp, int fd, const char *file,
|
||||
enum mandoclevel *level)
|
||||
@ -519,11 +630,6 @@ parse(struct curparse *curp, int fd, const char *file,
|
||||
|
||||
rc = mparse_readfd(curp->mp, fd, file);
|
||||
|
||||
/* Stop immediately if the parse has failed. */
|
||||
|
||||
if (MANDOCLEVEL_FATAL <= rc)
|
||||
goto cleanup;
|
||||
|
||||
/*
|
||||
* With -Wstop and warnings or errors of at least the requested
|
||||
* level, do not produce output.
|
||||
@ -609,15 +715,11 @@ parse(struct curparse *curp, int fd, const char *file,
|
||||
if (mdoc && curp->outmdoc)
|
||||
(*curp->outmdoc)(curp->outdata, mdoc);
|
||||
|
||||
cleanup:
|
||||
|
||||
mparse_reset(curp->mp);
|
||||
|
||||
cleanup:
|
||||
if (*level < rc)
|
||||
*level = rc;
|
||||
}
|
||||
|
||||
#if HAVE_SQLITE3
|
||||
static enum mandoclevel
|
||||
passthrough(const char *file, int fd, int synopsis_only)
|
||||
{
|
||||
@ -631,6 +733,8 @@ passthrough(const char *file, int fd, int synopsis_only)
|
||||
ssize_t nw;
|
||||
int print;
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
if ((stream = fdopen(fd, "r")) == NULL) {
|
||||
close(fd);
|
||||
syscall = "fdopen";
|
||||
@ -681,7 +785,6 @@ passthrough(const char *file, int fd, int synopsis_only)
|
||||
progname, file, syscall, strerror(errno));
|
||||
return(MANDOCLEVEL_SYSERR);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
koptions(int *options, char *arg)
|
||||
@ -696,7 +799,7 @@ koptions(int *options, char *arg)
|
||||
} else if ( ! strcmp(arg, "us-ascii")) {
|
||||
*options &= ~(MPARSE_UTF8 | MPARSE_LATIN1);
|
||||
} else {
|
||||
fprintf(stderr, "%s: -K%s: Bad argument\n",
|
||||
fprintf(stderr, "%s: -K %s: Bad argument\n",
|
||||
progname, arg);
|
||||
return(0);
|
||||
}
|
||||
@ -716,7 +819,7 @@ moptions(int *options, char *arg)
|
||||
else if (0 == strcmp(arg, "an"))
|
||||
*options |= MPARSE_MAN;
|
||||
else {
|
||||
fprintf(stderr, "%s: -m%s: Bad argument\n",
|
||||
fprintf(stderr, "%s: -m %s: Bad argument\n",
|
||||
progname, arg);
|
||||
return(0);
|
||||
}
|
||||
@ -750,7 +853,7 @@ toptions(struct curparse *curp, char *arg)
|
||||
else if (0 == strcmp(arg, "pdf"))
|
||||
curp->outtype = OUTT_PDF;
|
||||
else {
|
||||
fprintf(stderr, "%s: -T%s: Bad argument\n",
|
||||
fprintf(stderr, "%s: -T %s: Bad argument\n",
|
||||
progname, arg);
|
||||
return(0);
|
||||
}
|
||||
@ -762,14 +865,15 @@ static int
|
||||
woptions(struct curparse *curp, char *arg)
|
||||
{
|
||||
char *v, *o;
|
||||
const char *toks[6];
|
||||
const char *toks[7];
|
||||
|
||||
toks[0] = "stop";
|
||||
toks[1] = "all";
|
||||
toks[2] = "warning";
|
||||
toks[3] = "error";
|
||||
toks[4] = "fatal";
|
||||
toks[5] = NULL;
|
||||
toks[4] = "unsupp";
|
||||
toks[5] = "fatal";
|
||||
toks[6] = NULL;
|
||||
|
||||
while (*arg) {
|
||||
o = arg;
|
||||
@ -786,10 +890,13 @@ woptions(struct curparse *curp, char *arg)
|
||||
curp->wlevel = MANDOCLEVEL_ERROR;
|
||||
break;
|
||||
case 4:
|
||||
curp->wlevel = MANDOCLEVEL_FATAL;
|
||||
curp->wlevel = MANDOCLEVEL_UNSUPP;
|
||||
break;
|
||||
case 5:
|
||||
curp->wlevel = MANDOCLEVEL_BADARG;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: -W%s: Bad argument\n",
|
||||
fprintf(stderr, "%s: -W %s: Bad argument\n",
|
||||
progname, o);
|
||||
return(0);
|
||||
}
|
||||
|
4
main.h
4
main.h
@ -1,6 +1,7 @@
|
||||
/* $Id: main.h,v 1.19 2014/12/01 08:05:52 schwarze Exp $ */
|
||||
/* $Id: main.h,v 1.20 2014/12/31 16:52:40 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -45,6 +46,7 @@ void *locale_alloc(const struct mchars *, char *);
|
||||
void *utf8_alloc(const struct mchars *, char *);
|
||||
void *ascii_alloc(const struct mchars *, char *);
|
||||
void ascii_free(void *);
|
||||
void ascii_sepline(void *);
|
||||
|
||||
void *pdf_alloc(const struct mchars *, char *);
|
||||
void *ps_alloc(const struct mchars *, char *);
|
||||
|
@ -1,10 +1,10 @@
|
||||
body { font-family: Helvetica, Arial, sans-serif; }
|
||||
body > div { padding-left: 2em;
|
||||
body > div { padding-left: 2em;
|
||||
padding-top: 1em; }
|
||||
body > div#mancgi { padding-left: 0em;
|
||||
body > div#mancgi { padding-left: 0em;
|
||||
padding-top: 0em; }
|
||||
body > div.results { font-size: smaller; }
|
||||
#mancgi fieldset { text-align: center;
|
||||
#mancgi fieldset { text-align: center;
|
||||
border: thin solid silver;
|
||||
border-radius: 1em;
|
||||
font-size: small; }
|
||||
|
89
man.1
89
man.1
@ -1,9 +1,9 @@
|
||||
.\" $Id: man.1,v 1.7 2014/11/11 02:43:41 schwarze Exp $
|
||||
.\" $Id: man.1,v 1.13 2015/02/16 16:23:54 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\" Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre <jmc@openbsd.org>
|
||||
.\" Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\" Copyright (c) 2010, 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
@ -31,7 +31,7 @@
|
||||
.\"
|
||||
.\" @(#)man.1 8.2 (Berkeley) 1/2/94
|
||||
.\"
|
||||
.Dd $Mdocdate: November 11 2014 $
|
||||
.Dd $Mdocdate: February 16 2015 $
|
||||
.Dt MAN 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -39,12 +39,17 @@
|
||||
.Nd display manual pages
|
||||
.Sh SYNOPSIS
|
||||
.Nm man
|
||||
.Op Fl acfhklVw
|
||||
.Op Fl acfhklw
|
||||
.Op Fl C Ar file
|
||||
.Op Fl I Cm os Ns = Ns Ar name
|
||||
.Op Fl K Ar encoding
|
||||
.Op Fl M Ar path
|
||||
.Op Fl m Ar path
|
||||
.Op Fl O Ar option Ns = Ns Ar value
|
||||
.Op Fl S Ar subsection
|
||||
.Op Fl s Ar section
|
||||
.Op Fl T Ar output
|
||||
.Op Fl W Ar level
|
||||
.Op Ar section
|
||||
.Ar name ...
|
||||
.Sh DESCRIPTION
|
||||
@ -95,12 +100,34 @@ This overrides any earlier
|
||||
and
|
||||
.Fl l
|
||||
options.
|
||||
.It Fl I Cm os Ns = Ns Ar name
|
||||
Override the default operating system
|
||||
.Ar name
|
||||
for the
|
||||
.Xr mdoc 7
|
||||
.Ic \&Os
|
||||
and for the
|
||||
.Xr man 7
|
||||
.Ic \&TH
|
||||
macro.
|
||||
.It Fl h
|
||||
Display only the SYNOPSIS lines of the requested manual pages.
|
||||
Implies
|
||||
.Fl a
|
||||
and
|
||||
.Fl c .
|
||||
.It Fl K Ar encoding
|
||||
Specify the input encoding.
|
||||
The supported
|
||||
.Ar encoding
|
||||
arguments are
|
||||
.Cm us-ascii ,
|
||||
.Cm iso-8859-1 ,
|
||||
and
|
||||
.Cm utf-8 .
|
||||
By default, the encoding is automatically detected as described in the
|
||||
.Xr mandoc 1
|
||||
manual.
|
||||
.It Fl k
|
||||
A synonym for
|
||||
.Xr apropos 1 .
|
||||
@ -173,6 +200,11 @@ are specified by the
|
||||
line in the
|
||||
.Nm
|
||||
configuration file.
|
||||
.It Fl O Ar option Ns = Ns Ar value
|
||||
Comma-separated output options.
|
||||
For each output format, the available options are described in the
|
||||
.Xr mandoc 1
|
||||
manual.
|
||||
.It Fl S Ar subsection
|
||||
Restricts the directories that
|
||||
.Nm
|
||||
@ -242,8 +274,43 @@ specifies the possible
|
||||
.Ar section
|
||||
values, and their search order.
|
||||
Additional sections may be specified.
|
||||
.It Fl V
|
||||
Print version and exit.
|
||||
.It Fl T Ar output
|
||||
Select the output format.
|
||||
The default is
|
||||
.Cm locale .
|
||||
The other output modes
|
||||
.Cm ascii ,
|
||||
.Cm html ,
|
||||
.Cm lint ,
|
||||
.Cm man ,
|
||||
.Cm pdf ,
|
||||
.Cm ps ,
|
||||
.Cm tree ,
|
||||
and
|
||||
.Cm utf8
|
||||
are described in the
|
||||
.Xr mandoc 1
|
||||
manual.
|
||||
.It Fl W Ar level
|
||||
Specify the minimum message
|
||||
.Ar level
|
||||
to be reported on the standard error output and to affect the exit status.
|
||||
The
|
||||
.Ar level
|
||||
can be
|
||||
.Cm warning ,
|
||||
.Cm error ,
|
||||
or
|
||||
.Cm unsupp ;
|
||||
.Cm all
|
||||
is an alias for
|
||||
.Cm warning .
|
||||
By default,
|
||||
.Nm
|
||||
is silent.
|
||||
See the
|
||||
.Xr mandoc 1
|
||||
manual for details.
|
||||
.It Fl w
|
||||
List the pathnames of the manual pages which
|
||||
.Nm
|
||||
@ -254,14 +321,6 @@ and
|
||||
combination.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility also supports the options
|
||||
.Fl IKOTW
|
||||
described in the
|
||||
.Xr mandoc 1
|
||||
manual.
|
||||
.Pp
|
||||
Guidelines for writing
|
||||
man pages can be found in
|
||||
.Xr mdoc 7 .
|
||||
@ -355,7 +414,7 @@ utility is compliant with the
|
||||
specification.
|
||||
.Pp
|
||||
The flags
|
||||
.Op Fl aCcfhMmSsw ,
|
||||
.Op Fl aCcfhIKlMmOSsTWw ,
|
||||
as well as the environment variables
|
||||
.Ev MACHINE ,
|
||||
.Ev MANPAGER ,
|
||||
|
127
man.7
127
man.7
@ -1,7 +1,7 @@
|
||||
.\" $Id: man.7,v 1.127 2014/06/22 16:39:45 schwarze Exp $
|
||||
.\" $Id: man.7,v 1.132 2015/01/29 00:33:57 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\" Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\" Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
@ -16,7 +16,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: June 22 2014 $
|
||||
.Dd $Mdocdate: January 29 2015 $
|
||||
.Dt MAN 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -369,11 +369,11 @@ Begin a paragraph whose initial output line is left-justified, but
|
||||
subsequent output lines are indented, with the following syntax:
|
||||
.Bd -filled -offset indent
|
||||
.Pf \. Sx \&HP
|
||||
.Op Cm width
|
||||
.Op Ar width
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Cm width
|
||||
.Ar width
|
||||
argument is a
|
||||
.Xr roff 7
|
||||
scaling width.
|
||||
@ -413,11 +413,11 @@ and
|
||||
Begin an indented paragraph with the following syntax:
|
||||
.Bd -filled -offset indent
|
||||
.Pf \. Sx \&IP
|
||||
.Op Cm head Op Cm width
|
||||
.Op Ar head Op Ar width
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Cm width
|
||||
.Ar width
|
||||
argument is a
|
||||
.Xr roff 7
|
||||
scaling width defining the left margin.
|
||||
@ -425,7 +425,7 @@ It's saved for later paragraph left-margins; if unspecified, the saved or
|
||||
default width is used.
|
||||
.Pp
|
||||
The
|
||||
.Cm head
|
||||
.Ar head
|
||||
argument is used as a leading term, flushed to the left margin.
|
||||
This is useful for bulleted paragraphs and so on.
|
||||
.Pp
|
||||
@ -470,13 +470,13 @@ This is a non-standard GNU extension, included only for compatibility.
|
||||
It has the following syntax:
|
||||
.Bd -filled -offset indent
|
||||
.Pf \. Sx \&OP
|
||||
.Cm key Op Cm value
|
||||
.Ar key Op Ar value
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Cm key
|
||||
.Ar key
|
||||
is usually a command-line flag and
|
||||
.Cm value
|
||||
.Ar value
|
||||
its argument.
|
||||
.Ss \&P
|
||||
Synonym for
|
||||
@ -495,11 +495,11 @@ Specify the vertical space to be inserted before each new paragraph.
|
||||
The syntax is as follows:
|
||||
.Bd -filled -offset indent
|
||||
.Pf \. Sx \&PD
|
||||
.Op Cm height
|
||||
.Op Ar height
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Cm height
|
||||
.Ar height
|
||||
argument is a
|
||||
.Xr roff 7
|
||||
scaling width.
|
||||
@ -555,9 +555,29 @@ and
|
||||
.Ss \&RE
|
||||
Explicitly close out the scope of a prior
|
||||
.Sx \&RS .
|
||||
The default left margin is restored to the state of the original
|
||||
The default left margin is restored to the state before that
|
||||
.Sx \&RS
|
||||
invocation.
|
||||
.Pp
|
||||
The syntax is as follows:
|
||||
.Bd -filled -offset indent
|
||||
.Pf \. Sx \&RE
|
||||
.Op Ar level
|
||||
.Ed
|
||||
.Pp
|
||||
Without an argument, the most recent
|
||||
.Sx \&RS
|
||||
block is closed out.
|
||||
If
|
||||
.Ar level
|
||||
is 1, all open
|
||||
.Sx \&RS
|
||||
blocks are closed out.
|
||||
Otherwise,
|
||||
.Ar level No \(mi 1
|
||||
nested
|
||||
.Sx \&RS
|
||||
blocks remain open.
|
||||
.Ss \&RI
|
||||
Text is rendered alternately in roman (the default font) and italics.
|
||||
Whitespace between arguments is omitted in output.
|
||||
@ -578,11 +598,11 @@ Temporarily reset the default left margin.
|
||||
This has the following syntax:
|
||||
.Bd -filled -offset indent
|
||||
.Pf \. Sx \&RS
|
||||
.Op Cm width
|
||||
.Op Ar width
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Cm width
|
||||
.Ar width
|
||||
argument is a
|
||||
.Xr roff 7
|
||||
scaling width.
|
||||
@ -607,7 +627,8 @@ The scope of a sub-section is closed by a subsequent sub-section,
|
||||
section, or end of file.
|
||||
The paragraph left-margin width is reset to the default.
|
||||
.Ss \&TH
|
||||
Sets the title of the manual page with the following syntax:
|
||||
Sets the title of the manual page for use in the page header
|
||||
and footer with the following syntax:
|
||||
.Bd -filled -offset indent
|
||||
.Pf \. Sx \&TH
|
||||
.Ar title section date
|
||||
@ -629,6 +650,11 @@ is empty or not specified, the current date is used.
|
||||
The optional
|
||||
.Ar source
|
||||
string specifies the organisation providing the utility.
|
||||
When unspecified,
|
||||
.Xr mandoc 1
|
||||
uses its
|
||||
.Fl Ios
|
||||
argument.
|
||||
The
|
||||
.Ar volume
|
||||
string replaces the default rendered volume, which is dictated by the
|
||||
@ -645,11 +671,11 @@ Subsequent output lines are indented.
|
||||
The syntax is as follows:
|
||||
.Bd -filled -offset indent
|
||||
.Pf \. Sx \&TP
|
||||
.Op Cm width
|
||||
.Op Ar width
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Cm width
|
||||
.Ar width
|
||||
argument is a
|
||||
.Xr roff 7
|
||||
scaling width.
|
||||
@ -694,15 +720,13 @@ End literal mode begun by
|
||||
.Ss \&in
|
||||
Indent relative to the current indentation:
|
||||
.Pp
|
||||
.D1 Pf \. Sx \&in Op Cm width
|
||||
.D1 Pf \. Sx \&in Op Ar width
|
||||
.Pp
|
||||
If
|
||||
.Cm width
|
||||
.Ar width
|
||||
is signed, the new offset is relative.
|
||||
Otherwise, it is absolute.
|
||||
This value is reset upon the next paragraph, section, or sub-section.
|
||||
.Ss \&na
|
||||
Don't align to the right margin.
|
||||
.Ss \&nf
|
||||
Begin literal mode: all subsequent free-form lines have their end of
|
||||
line boundaries preserved.
|
||||
@ -716,11 +740,11 @@ or
|
||||
Insert vertical spaces into output with the following syntax:
|
||||
.Bd -filled -offset indent
|
||||
.Pf \. Sx \&sp
|
||||
.Op Cm height
|
||||
.Op Ar height
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Cm height
|
||||
.Ar height
|
||||
argument is a scaling width as described in
|
||||
.Xr roff 7 .
|
||||
If 0, this is equivalent to the
|
||||
@ -754,10 +778,9 @@ is equivalent to
|
||||
If next-line macros are invoked consecutively, only the last is used.
|
||||
If a next-line macro is followed by a non-next-line macro, an error is
|
||||
raised, except for
|
||||
.Sx \&br ,
|
||||
.Sx \&sp ,
|
||||
.Sx \&br
|
||||
and
|
||||
.Sx \&na .
|
||||
.Sx \&sp .
|
||||
.Pp
|
||||
The syntax is as follows:
|
||||
.Bd -literal -offset indent
|
||||
@ -788,7 +811,6 @@ The syntax is as follows:
|
||||
.It Sx \&br Ta 0 Ta current Ta compat
|
||||
.It Sx \&fi Ta 0 Ta current Ta compat
|
||||
.It Sx \&in Ta 1 Ta current Ta compat
|
||||
.It Sx \&na Ta 0 Ta current Ta compat
|
||||
.It Sx \&nf Ta 0 Ta current Ta compat
|
||||
.It Sx \&sp Ta 1 Ta current Ta compat
|
||||
.El
|
||||
@ -872,53 +894,6 @@ until the end of the macro scope.
|
||||
Note that macros like
|
||||
.Sx \&BR
|
||||
open and close a font scope for each argument.
|
||||
.Sh COMPATIBILITY
|
||||
This section mentions some areas of questionable portability between
|
||||
implementations of the
|
||||
.Nm
|
||||
language.
|
||||
More incompatibilities exist.
|
||||
.Pp
|
||||
.Bl -dash -compact
|
||||
.It
|
||||
Do not depend on
|
||||
.Sx \&SH
|
||||
or
|
||||
.Sx \&SS
|
||||
to close out a literal context opened with
|
||||
.Sx \&nf .
|
||||
This behaviour may not be portable.
|
||||
.It
|
||||
troff suppresses a newline before
|
||||
.Sq \(aq
|
||||
macro output; in mandoc, it is an alias for the standard
|
||||
.Sq \&.
|
||||
control character.
|
||||
.It
|
||||
In page header lines, GNU troff versions up to and including 1.21
|
||||
only print
|
||||
.Ar volume
|
||||
names explicitly specified in the
|
||||
.Sx \&TH
|
||||
macro; mandoc and newer groff print the default volume name
|
||||
corresponding to the
|
||||
.Ar section
|
||||
number when no
|
||||
.Ar volume
|
||||
is given, like in
|
||||
.Xr mdoc 7 .
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Sx EE ,
|
||||
.Sx EX ,
|
||||
.Sx OP ,
|
||||
.Sx UE ,
|
||||
and
|
||||
.Sx UR
|
||||
macros are part of the GNU extended
|
||||
.Nm
|
||||
macro set, and may not be portable to non-GNU troff implementations.
|
||||
.Sh SEE ALSO
|
||||
.Xr man 1 ,
|
||||
.Xr mandoc 1 ,
|
||||
|
134
man.c
134
man.c
@ -1,7 +1,7 @@
|
||||
/* $Id: man.c,v 1.145 2014/11/28 06:27:05 schwarze Exp $ */
|
||||
/* $Id: man.c,v 1.149 2015/01/30 21:28:46 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011 Joerg Sonnenberger <joerg@netbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@ -39,7 +39,7 @@ const char *const __man_macronames[MAN_MAX] = {
|
||||
"IP", "HP", "SM", "SB",
|
||||
"BI", "IB", "BR", "RB",
|
||||
"R", "B", "I", "IR",
|
||||
"RI", "na", "sp", "nf",
|
||||
"RI", "sp", "nf",
|
||||
"fi", "RE", "RS", "DT",
|
||||
"UC", "PD", "AT", "in",
|
||||
"ft", "OP", "EX", "EE",
|
||||
@ -48,6 +48,10 @@ const char *const __man_macronames[MAN_MAX] = {
|
||||
|
||||
const char * const *man_macronames = __man_macronames;
|
||||
|
||||
static void man_alloc1(struct man *);
|
||||
static void man_breakscope(struct man *, enum mant);
|
||||
static void man_descope(struct man *, int, int);
|
||||
static void man_free1(struct man *);
|
||||
static struct man_node *man_node_alloc(struct man *, int, int,
|
||||
enum man_type, enum mant);
|
||||
static void man_node_append(struct man *, struct man_node *);
|
||||
@ -56,9 +60,6 @@ static void man_node_unlink(struct man *,
|
||||
struct man_node *);
|
||||
static int man_ptext(struct man *, int, char *, int);
|
||||
static int man_pmacro(struct man *, int, char *, int);
|
||||
static void man_free1(struct man *);
|
||||
static void man_alloc1(struct man *);
|
||||
static void man_descope(struct man *, int, int);
|
||||
|
||||
|
||||
const struct man_node *
|
||||
@ -92,7 +93,8 @@ man_free(struct man *man)
|
||||
}
|
||||
|
||||
struct man *
|
||||
man_alloc(struct roff *roff, struct mparse *parse, int quick)
|
||||
man_alloc(struct roff *roff, struct mparse *parse,
|
||||
const char *defos, int quick)
|
||||
{
|
||||
struct man *p;
|
||||
|
||||
@ -100,6 +102,7 @@ man_alloc(struct roff *roff, struct mparse *parse, int quick)
|
||||
|
||||
man_hash_init();
|
||||
p->parse = parse;
|
||||
p->defos = defos;
|
||||
p->quick = quick;
|
||||
p->roff = roff;
|
||||
|
||||
@ -107,12 +110,11 @@ man_alloc(struct roff *roff, struct mparse *parse, int quick)
|
||||
return(p);
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
man_endparse(struct man *man)
|
||||
{
|
||||
|
||||
man_macroend(man);
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
@ -336,6 +338,7 @@ man_addspan(struct man *man, const struct tbl_span *sp)
|
||||
{
|
||||
struct man_node *n;
|
||||
|
||||
man_breakscope(man, MAN_MAX);
|
||||
n = man_node_alloc(man, sp->line, 0, MAN_TBL, MAN_MAX);
|
||||
n->span = sp;
|
||||
man_node_append(man, n);
|
||||
@ -492,62 +495,11 @@ man_pmacro(struct man *man, int ln, char *buf, int offs)
|
||||
ln, offs - 1, NULL);
|
||||
|
||||
/*
|
||||
* Remove prior ELINE macro, as it's being clobbered by a new
|
||||
* macro. Note that NSCOPED macros do not close out ELINE
|
||||
* macros---they don't print text---so we let those slip by.
|
||||
* Some macros break next-line scopes; otherwise, remember
|
||||
* whether we are in next-line scope for a block head.
|
||||
*/
|
||||
|
||||
if ( ! (man_macros[tok].flags & MAN_NSCOPED) &&
|
||||
man->flags & MAN_ELINE) {
|
||||
n = man->last;
|
||||
assert(MAN_TEXT != n->type);
|
||||
|
||||
/* Remove repeated NSCOPED macros causing ELINE. */
|
||||
|
||||
if (man_macros[n->tok].flags & MAN_NSCOPED)
|
||||
n = n->parent;
|
||||
|
||||
mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse, n->line,
|
||||
n->pos, "%s breaks %s", man_macronames[tok],
|
||||
man_macronames[n->tok]);
|
||||
|
||||
man_node_delete(man, n);
|
||||
man->flags &= ~MAN_ELINE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove prior BLINE macro that is being clobbered.
|
||||
*/
|
||||
if ((man->flags & MAN_BLINE) &&
|
||||
(man_macros[tok].flags & MAN_BSCOPE)) {
|
||||
n = man->last;
|
||||
|
||||
/* Might be a text node like 8 in
|
||||
* .TP 8
|
||||
* .SH foo
|
||||
*/
|
||||
if (n->type == MAN_TEXT)
|
||||
n = n->parent;
|
||||
|
||||
/* Remove element that didn't end BLINE, if any. */
|
||||
if ( ! (man_macros[n->tok].flags & MAN_BSCOPE))
|
||||
n = n->parent;
|
||||
|
||||
assert(n->type == MAN_HEAD);
|
||||
n = n->parent;
|
||||
assert(n->type == MAN_BLOCK);
|
||||
assert(man_macros[n->tok].flags & MAN_SCOPED);
|
||||
|
||||
mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse, n->line,
|
||||
n->pos, "%s breaks %s", man_macronames[tok],
|
||||
man_macronames[n->tok]);
|
||||
|
||||
man_node_delete(man, n);
|
||||
man->flags &= ~MAN_BLINE;
|
||||
}
|
||||
|
||||
/* Remember whether we are in next-line scope for a block head. */
|
||||
|
||||
man_breakscope(man, tok);
|
||||
bline = man->flags & MAN_BLINE;
|
||||
|
||||
/* Call to handler... */
|
||||
@ -582,6 +534,62 @@ man_pmacro(struct man *man, int ln, char *buf, int offs)
|
||||
return(1);
|
||||
}
|
||||
|
||||
void
|
||||
man_breakscope(struct man *man, enum mant tok)
|
||||
{
|
||||
struct man_node *n;
|
||||
|
||||
/*
|
||||
* An element next line scope is open,
|
||||
* and the new macro is not allowed inside elements.
|
||||
* Delete the element that is being broken.
|
||||
*/
|
||||
|
||||
if (man->flags & MAN_ELINE && (tok == MAN_MAX ||
|
||||
! (man_macros[tok].flags & MAN_NSCOPED))) {
|
||||
n = man->last;
|
||||
assert(n->type != MAN_TEXT);
|
||||
if (man_macros[n->tok].flags & MAN_NSCOPED)
|
||||
n = n->parent;
|
||||
|
||||
mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse,
|
||||
n->line, n->pos, "%s breaks %s",
|
||||
tok == MAN_MAX ? "TS" : man_macronames[tok],
|
||||
man_macronames[n->tok]);
|
||||
|
||||
man_node_delete(man, n);
|
||||
man->flags &= ~MAN_ELINE;
|
||||
}
|
||||
|
||||
/*
|
||||
* A block header next line scope is open,
|
||||
* and the new macro is not allowed inside block headers.
|
||||
* Delete the block that is being broken.
|
||||
*/
|
||||
|
||||
if (man->flags & MAN_BLINE && (tok == MAN_MAX ||
|
||||
man_macros[tok].flags & MAN_BSCOPE)) {
|
||||
n = man->last;
|
||||
if (n->type == MAN_TEXT)
|
||||
n = n->parent;
|
||||
if ( ! (man_macros[n->tok].flags & MAN_BSCOPE))
|
||||
n = n->parent;
|
||||
|
||||
assert(n->type == MAN_HEAD);
|
||||
n = n->parent;
|
||||
assert(n->type == MAN_BLOCK);
|
||||
assert(man_macros[n->tok].flags & MAN_SCOPED);
|
||||
|
||||
mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse,
|
||||
n->line, n->pos, "%s breaks %s",
|
||||
tok == MAN_MAX ? "TS" : man_macronames[tok],
|
||||
man_macronames[n->tok]);
|
||||
|
||||
man_node_delete(man, n);
|
||||
man->flags &= ~MAN_BLINE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlink a node from its context. If "man" is provided, the last parse
|
||||
* point will also be adjusted accordingly.
|
||||
|
4
man.h
4
man.h
@ -1,4 +1,4 @@
|
||||
/* $Id: man.h,v 1.67 2014/12/01 04:05:32 schwarze Exp $ */
|
||||
/* $Id: man.h,v 1.69 2015/01/24 02:41:49 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -38,7 +38,6 @@ enum mant {
|
||||
MAN_I,
|
||||
MAN_IR,
|
||||
MAN_RI,
|
||||
MAN_na,
|
||||
MAN_sp,
|
||||
MAN_nf,
|
||||
MAN_fi,
|
||||
@ -99,6 +98,7 @@ struct man_node {
|
||||
struct man_node *body; /* BLOCK node BODY ptr */
|
||||
const struct tbl_span *span; /* TBL */
|
||||
const struct eqn *eqn; /* EQN */
|
||||
int aux; /* decoded node data, type-dependent */
|
||||
};
|
||||
|
||||
/* Names of macros. Index is enum mant. */
|
||||
|
16
man_html.c
16
man_html.c
@ -1,7 +1,7 @@
|
||||
/* $Id: man_html.c,v 1.107 2014/12/04 02:05:42 schwarze Exp $ */
|
||||
/* $Id: man_html.c,v 1.111 2015/02/10 08:05:30 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -100,7 +100,6 @@ static const struct htmlman mans[MAN_MAX] = {
|
||||
{ man_I_pre, NULL }, /* I */
|
||||
{ man_alt_pre, NULL }, /* IR */
|
||||
{ man_alt_pre, NULL }, /* RI */
|
||||
{ man_ign_pre, NULL }, /* na */
|
||||
{ man_br_pre, NULL }, /* sp */
|
||||
{ man_literal_pre, NULL }, /* nf */
|
||||
{ man_literal_pre, NULL }, /* fi */
|
||||
@ -193,9 +192,10 @@ static void
|
||||
print_man_nodelist(MAN_ARGS)
|
||||
{
|
||||
|
||||
print_man_node(man, n, mh, h);
|
||||
if (n->next)
|
||||
print_man_nodelist(man, n->next, mh, h);
|
||||
while (n != NULL) {
|
||||
print_man_node(man, n, mh, h);
|
||||
n = n->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -216,7 +216,7 @@ print_man_node(MAN_ARGS)
|
||||
print_paragraph(h);
|
||||
return;
|
||||
}
|
||||
if (n->flags & MAN_LINE && (*n->string == ' ' ||
|
||||
if (n->flags & MAN_LINE && (*n->string == ' ' ||
|
||||
(n->prev != NULL && mh->fl & MANH_LITERAL &&
|
||||
! (h->flags & HTML_NONEWLINE))))
|
||||
print_otag(h, TAG_BR, 0, NULL);
|
||||
@ -362,7 +362,7 @@ man_br_pre(MAN_ARGS)
|
||||
if (MAN_sp == n->tok) {
|
||||
if (NULL != (n = n->child))
|
||||
if ( ! a2roffsu(n->string, &su, SCALE_VS))
|
||||
SCALE_VS_INIT(&su, atoi(n->string));
|
||||
su.scale = 1.0;
|
||||
} else
|
||||
su.scale = 0.0;
|
||||
|
||||
|
84
man_macro.c
84
man_macro.c
@ -1,7 +1,7 @@
|
||||
/* $Id: man_macro.c,v 1.91 2014/11/28 05:51:32 schwarze Exp $ */
|
||||
/* $Id: man_macro.c,v 1.98 2015/02/06 11:54:36 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2012, 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@ -72,11 +72,10 @@ const struct man_macro __man_macros[MAN_MAX] = {
|
||||
{ in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* I */
|
||||
{ in_line_eoln, 0 }, /* IR */
|
||||
{ in_line_eoln, 0 }, /* RI */
|
||||
{ in_line_eoln, MAN_NSCOPED }, /* na */
|
||||
{ in_line_eoln, MAN_NSCOPED }, /* sp */
|
||||
{ in_line_eoln, MAN_BSCOPE }, /* nf */
|
||||
{ in_line_eoln, MAN_BSCOPE }, /* fi */
|
||||
{ blk_close, 0 }, /* RE */
|
||||
{ blk_close, MAN_BSCOPE }, /* RE */
|
||||
{ blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* RS */
|
||||
{ in_line_eoln, 0 }, /* DT */
|
||||
{ in_line_eoln, 0 }, /* UC */
|
||||
@ -88,7 +87,7 @@ const struct man_macro __man_macros[MAN_MAX] = {
|
||||
{ in_line_eoln, MAN_BSCOPE }, /* EX */
|
||||
{ in_line_eoln, MAN_BSCOPE }, /* EE */
|
||||
{ blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* UR */
|
||||
{ blk_close, 0 }, /* UE */
|
||||
{ blk_close, MAN_BSCOPE }, /* UE */
|
||||
{ in_line_eoln, 0 }, /* ll */
|
||||
};
|
||||
|
||||
@ -279,10 +278,30 @@ blk_close(MACRO_PROT_ARGS)
|
||||
{
|
||||
enum mant ntok;
|
||||
const struct man_node *nn;
|
||||
char *p;
|
||||
int nrew, target;
|
||||
|
||||
nrew = 1;
|
||||
switch (tok) {
|
||||
case MAN_RE:
|
||||
ntok = MAN_RS;
|
||||
if ( ! man_args(man, line, pos, buf, &p))
|
||||
break;
|
||||
for (nn = man->last->parent; nn; nn = nn->parent)
|
||||
if (nn->tok == ntok && nn->type == MAN_BLOCK)
|
||||
nrew++;
|
||||
target = strtol(p, &p, 10);
|
||||
if (*p != '\0')
|
||||
mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse,
|
||||
line, p - buf, "RE ... %s", p);
|
||||
if (target == 0)
|
||||
target = 1;
|
||||
nrew -= target;
|
||||
if (nrew < 1) {
|
||||
mandoc_vmsg(MANDOCERR_RE_NOTOPEN, man->parse,
|
||||
line, ppos, "RE %d", target);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MAN_UE:
|
||||
ntok = MAN_UR;
|
||||
@ -293,45 +312,50 @@ blk_close(MACRO_PROT_ARGS)
|
||||
}
|
||||
|
||||
for (nn = man->last->parent; nn; nn = nn->parent)
|
||||
if (nn->tok == ntok && nn->type == MAN_BLOCK)
|
||||
if (nn->tok == ntok && nn->type == MAN_BLOCK && ! --nrew)
|
||||
break;
|
||||
|
||||
if (nn == NULL) {
|
||||
mandoc_msg(MANDOCERR_BLK_NOTOPEN, man->parse,
|
||||
line, ppos, man_macronames[tok]);
|
||||
rew_scope(MAN_BLOCK, man, MAN_PP);
|
||||
} else
|
||||
} else {
|
||||
line = man->last->line;
|
||||
ppos = man->last->pos;
|
||||
ntok = man->last->tok;
|
||||
man_unscope(man, nn);
|
||||
|
||||
/* Move a trailing paragraph behind the block. */
|
||||
|
||||
if (ntok == MAN_LP || ntok == MAN_PP || ntok == MAN_P) {
|
||||
*pos = strlen(buf);
|
||||
blk_imp(man, ntok, line, ppos, pos, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
blk_exp(MACRO_PROT_ARGS)
|
||||
{
|
||||
struct man_node *n;
|
||||
int la;
|
||||
struct man_node *head;
|
||||
char *p;
|
||||
int la;
|
||||
|
||||
rew_scope(MAN_BLOCK, man, tok);
|
||||
man_block_alloc(man, line, ppos, tok);
|
||||
man_head_alloc(man, line, ppos, tok);
|
||||
head = man->last;
|
||||
|
||||
for (;;) {
|
||||
la = *pos;
|
||||
if ( ! man_args(man, line, pos, buf, &p))
|
||||
break;
|
||||
la = *pos;
|
||||
if (man_args(man, line, pos, buf, &p))
|
||||
man_word_alloc(man, line, la, p);
|
||||
}
|
||||
|
||||
assert(man);
|
||||
assert(tok != MAN_MAX);
|
||||
|
||||
for (n = man->last; n; n = n->parent)
|
||||
if (n->tok == tok) {
|
||||
assert(n->type == MAN_HEAD);
|
||||
man_unscope(man, n);
|
||||
break;
|
||||
}
|
||||
if (buf[*pos] != '\0')
|
||||
mandoc_vmsg(MANDOCERR_ARG_EXCESS,
|
||||
man->parse, line, *pos, "%s ... %s",
|
||||
man_macronames[tok], buf + *pos);
|
||||
|
||||
man_unscope(man, head);
|
||||
man_body_alloc(man, line, ppos, tok);
|
||||
}
|
||||
|
||||
@ -390,6 +414,20 @@ in_line_eoln(MACRO_PROT_ARGS)
|
||||
n = man->last;
|
||||
|
||||
for (;;) {
|
||||
if (buf[*pos] != '\0' && (tok == MAN_br ||
|
||||
tok == MAN_fi || tok == MAN_nf)) {
|
||||
mandoc_vmsg(MANDOCERR_ARG_SKIP,
|
||||
man->parse, line, *pos, "%s %s",
|
||||
man_macronames[tok], buf + *pos);
|
||||
break;
|
||||
}
|
||||
if (buf[*pos] != '\0' && man->last != n &&
|
||||
(tok == MAN_PD || tok == MAN_ft || tok == MAN_sp)) {
|
||||
mandoc_vmsg(MANDOCERR_ARG_EXCESS,
|
||||
man->parse, line, *pos, "%s ... %s",
|
||||
man_macronames[tok], buf + *pos);
|
||||
break;
|
||||
}
|
||||
la = *pos;
|
||||
if ( ! man_args(man, line, pos, buf, &p))
|
||||
break;
|
||||
|
217
man_term.c
217
man_term.c
@ -1,7 +1,7 @@
|
||||
/* $Id: man_term.c,v 1.159 2014/12/04 02:05:42 schwarze Exp $ */
|
||||
/* $Id: man_term.c,v 1.168 2015/01/30 22:04:44 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -21,6 +21,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -37,7 +38,7 @@
|
||||
struct mtermp {
|
||||
int fl;
|
||||
#define MANT_LITERAL (1 << 0)
|
||||
size_t lmargin[MAXMARGINS]; /* margins (incl. visible page) */
|
||||
int lmargin[MAXMARGINS]; /* margins (incl. vis. page) */
|
||||
int lmargincur; /* index of current margin */
|
||||
int lmarginsz; /* actual number of nested margins */
|
||||
size_t offset; /* default offset to visible page */
|
||||
@ -46,7 +47,7 @@ struct mtermp {
|
||||
|
||||
#define DECL_ARGS struct termp *p, \
|
||||
struct mtermp *mt, \
|
||||
const struct man_node *n, \
|
||||
struct man_node *n, \
|
||||
const struct man_meta *meta
|
||||
|
||||
struct termact {
|
||||
@ -56,9 +57,6 @@ struct termact {
|
||||
#define MAN_NOTEXT (1 << 0) /* Never has text children. */
|
||||
};
|
||||
|
||||
static int a2width(const struct termp *, const char *);
|
||||
static size_t a2height(const struct termp *, const char *);
|
||||
|
||||
static void print_man_nodelist(DECL_ARGS);
|
||||
static void print_man_node(DECL_ARGS);
|
||||
static void print_man_head(struct termp *, const void *);
|
||||
@ -116,7 +114,6 @@ static const struct termact termacts[MAN_MAX] = {
|
||||
{ pre_I, NULL, 0 }, /* I */
|
||||
{ pre_alternate, NULL, 0 }, /* IR */
|
||||
{ pre_alternate, NULL, 0 }, /* RI */
|
||||
{ pre_ign, NULL, MAN_NOTEXT }, /* na */
|
||||
{ pre_sp, NULL, MAN_NOTEXT }, /* sp */
|
||||
{ pre_literal, NULL, 0 }, /* nf */
|
||||
{ pre_literal, NULL, 0 }, /* fi */
|
||||
@ -184,29 +181,6 @@ terminal_man(void *arg, const struct man *man)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
a2height(const struct termp *p, const char *cp)
|
||||
{
|
||||
struct roffsu su;
|
||||
|
||||
if ( ! a2roffsu(cp, &su, SCALE_VS))
|
||||
SCALE_VS_INIT(&su, atoi(cp));
|
||||
|
||||
return(term_vspan(p, &su));
|
||||
}
|
||||
|
||||
static int
|
||||
a2width(const struct termp *p, const char *cp)
|
||||
{
|
||||
struct roffsu su;
|
||||
|
||||
if ( ! a2roffsu(cp, &su, SCALE_EN))
|
||||
return(-1);
|
||||
|
||||
return((int)term_hspan(p, &su));
|
||||
}
|
||||
|
||||
/*
|
||||
* Printing leading vertical space before a block.
|
||||
* This is used for the paragraph macros.
|
||||
@ -288,14 +262,16 @@ pre_literal(DECL_ARGS)
|
||||
static int
|
||||
pre_PD(DECL_ARGS)
|
||||
{
|
||||
struct roffsu su;
|
||||
|
||||
n = n->child;
|
||||
if (0 == n) {
|
||||
if (n == NULL) {
|
||||
mt->pardist = 1;
|
||||
return(0);
|
||||
}
|
||||
assert(MAN_TEXT == n->type);
|
||||
mt->pardist = atoi(n->string);
|
||||
if (a2roffsu(n->string, &su, SCALE_VS))
|
||||
mt->pardist = term_vspan(p, &su);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -303,7 +279,7 @@ static int
|
||||
pre_alternate(DECL_ARGS)
|
||||
{
|
||||
enum termfont font[2];
|
||||
const struct man_node *nn;
|
||||
struct man_node *nn;
|
||||
int savelit, i;
|
||||
|
||||
switch (n->tok) {
|
||||
@ -423,9 +399,10 @@ pre_ft(DECL_ARGS)
|
||||
static int
|
||||
pre_in(DECL_ARGS)
|
||||
{
|
||||
int len, less;
|
||||
size_t v;
|
||||
struct roffsu su;
|
||||
const char *cp;
|
||||
size_t v;
|
||||
int less;
|
||||
|
||||
term_newln(p);
|
||||
|
||||
@ -444,10 +421,10 @@ pre_in(DECL_ARGS)
|
||||
else
|
||||
cp--;
|
||||
|
||||
if ((len = a2width(p, ++cp)) < 0)
|
||||
if ( ! a2roffsu(++cp, &su, SCALE_EN))
|
||||
return(0);
|
||||
|
||||
v = (size_t)len;
|
||||
v = term_hspan(p, &su);
|
||||
|
||||
if (less < 0)
|
||||
p->offset -= p->offset > v ? v : p->offset;
|
||||
@ -455,6 +432,8 @@ pre_in(DECL_ARGS)
|
||||
p->offset += v;
|
||||
else
|
||||
p->offset = v;
|
||||
if (p->offset > SHRT_MAX)
|
||||
p->offset = term_len(p, p->defindent);
|
||||
|
||||
return(0);
|
||||
}
|
||||
@ -462,9 +441,8 @@ pre_in(DECL_ARGS)
|
||||
static int
|
||||
pre_sp(DECL_ARGS)
|
||||
{
|
||||
char *s;
|
||||
size_t i, len;
|
||||
int neg;
|
||||
struct roffsu su;
|
||||
int i, len;
|
||||
|
||||
if ((NULL == n->prev && n->parent)) {
|
||||
switch (n->parent->tok) {
|
||||
@ -484,29 +462,20 @@ pre_sp(DECL_ARGS)
|
||||
}
|
||||
}
|
||||
|
||||
neg = 0;
|
||||
switch (n->tok) {
|
||||
case MAN_br:
|
||||
if (n->tok == MAN_br)
|
||||
len = 0;
|
||||
break;
|
||||
default:
|
||||
if (NULL == n->child) {
|
||||
len = 1;
|
||||
break;
|
||||
}
|
||||
s = n->child->string;
|
||||
if ('-' == *s) {
|
||||
neg = 1;
|
||||
s++;
|
||||
}
|
||||
len = a2height(p, s);
|
||||
break;
|
||||
else if (n->child == NULL)
|
||||
len = 1;
|
||||
else {
|
||||
if ( ! a2roffsu(n->child->string, &su, SCALE_VS))
|
||||
su.scale = 1.0;
|
||||
len = term_vspan(p, &su);
|
||||
}
|
||||
|
||||
if (0 == len)
|
||||
if (len == 0)
|
||||
term_newln(p);
|
||||
else if (neg)
|
||||
p->skipvsp += len;
|
||||
else if (len < 0)
|
||||
p->skipvsp -= len;
|
||||
else
|
||||
for (i = 0; i < len; i++)
|
||||
term_vspace(p);
|
||||
@ -517,9 +486,9 @@ pre_sp(DECL_ARGS)
|
||||
static int
|
||||
pre_HP(DECL_ARGS)
|
||||
{
|
||||
size_t len, one;
|
||||
int ival;
|
||||
struct roffsu su;
|
||||
const struct man_node *nn;
|
||||
int len;
|
||||
|
||||
switch (n->type) {
|
||||
case MAN_BLOCK:
|
||||
@ -536,25 +505,21 @@ pre_HP(DECL_ARGS)
|
||||
p->trailspace = 2;
|
||||
}
|
||||
|
||||
len = mt->lmargin[mt->lmargincur];
|
||||
ival = -1;
|
||||
|
||||
/* Calculate offset. */
|
||||
|
||||
if (NULL != (nn = n->parent->head->child))
|
||||
if ((ival = a2width(p, nn->string)) >= 0)
|
||||
len = (size_t)ival;
|
||||
|
||||
one = term_len(p, 1);
|
||||
if (len < one)
|
||||
len = one;
|
||||
if ((nn = n->parent->head->child) != NULL &&
|
||||
a2roffsu(nn->string, &su, SCALE_EN)) {
|
||||
len = term_hspan(p, &su);
|
||||
if (len < 0 && (size_t)(-len) > mt->offset)
|
||||
len = -mt->offset;
|
||||
else if (len > SHRT_MAX)
|
||||
len = term_len(p, p->defindent);
|
||||
mt->lmargin[mt->lmargincur] = len;
|
||||
} else
|
||||
len = mt->lmargin[mt->lmargincur];
|
||||
|
||||
p->offset = mt->offset;
|
||||
p->rmargin = mt->offset + len;
|
||||
|
||||
if (ival >= 0)
|
||||
mt->lmargin[mt->lmargincur] = (size_t)ival;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -595,9 +560,9 @@ pre_PP(DECL_ARGS)
|
||||
static int
|
||||
pre_IP(DECL_ARGS)
|
||||
{
|
||||
struct roffsu su;
|
||||
const struct man_node *nn;
|
||||
size_t len;
|
||||
int savelit, ival;
|
||||
int len, savelit;
|
||||
|
||||
switch (n->type) {
|
||||
case MAN_BODY:
|
||||
@ -614,28 +579,23 @@ pre_IP(DECL_ARGS)
|
||||
return(1);
|
||||
}
|
||||
|
||||
len = mt->lmargin[mt->lmargincur];
|
||||
ival = -1;
|
||||
|
||||
/* Calculate the offset from the optional second argument. */
|
||||
if (NULL != (nn = n->parent->head->child))
|
||||
if (NULL != (nn = nn->next))
|
||||
if ((ival = a2width(p, nn->string)) >= 0)
|
||||
len = (size_t)ival;
|
||||
if ((nn = n->parent->head->child) != NULL &&
|
||||
(nn = nn->next) != NULL &&
|
||||
a2roffsu(nn->string, &su, SCALE_EN)) {
|
||||
len = term_hspan(p, &su);
|
||||
if (len < 0 && (size_t)(-len) > mt->offset)
|
||||
len = -mt->offset;
|
||||
else if (len > SHRT_MAX)
|
||||
len = term_len(p, p->defindent);
|
||||
mt->lmargin[mt->lmargincur] = len;
|
||||
} else
|
||||
len = mt->lmargin[mt->lmargincur];
|
||||
|
||||
switch (n->type) {
|
||||
case MAN_HEAD:
|
||||
/* Handle zero-width lengths. */
|
||||
if (0 == len)
|
||||
len = term_len(p, 1);
|
||||
|
||||
p->offset = mt->offset;
|
||||
p->rmargin = mt->offset + len;
|
||||
if (ival < 0)
|
||||
break;
|
||||
|
||||
/* Set the saved left-margin. */
|
||||
mt->lmargin[mt->lmargincur] = (size_t)ival;
|
||||
|
||||
savelit = MANT_LITERAL & mt->fl;
|
||||
mt->fl &= ~MANT_LITERAL;
|
||||
@ -681,9 +641,9 @@ post_IP(DECL_ARGS)
|
||||
static int
|
||||
pre_TP(DECL_ARGS)
|
||||
{
|
||||
const struct man_node *nn;
|
||||
size_t len;
|
||||
int savelit, ival;
|
||||
struct roffsu su;
|
||||
struct man_node *nn;
|
||||
int len, savelit;
|
||||
|
||||
switch (n->type) {
|
||||
case MAN_HEAD:
|
||||
@ -700,22 +660,22 @@ pre_TP(DECL_ARGS)
|
||||
return(1);
|
||||
}
|
||||
|
||||
len = (size_t)mt->lmargin[mt->lmargincur];
|
||||
ival = -1;
|
||||
|
||||
/* Calculate offset. */
|
||||
|
||||
if (NULL != (nn = n->parent->head->child))
|
||||
if (nn->string && 0 == (MAN_LINE & nn->flags))
|
||||
if ((ival = a2width(p, nn->string)) >= 0)
|
||||
len = (size_t)ival;
|
||||
if ((nn = n->parent->head->child) != NULL &&
|
||||
nn->string != NULL && ! (MAN_LINE & nn->flags) &&
|
||||
a2roffsu(nn->string, &su, SCALE_EN)) {
|
||||
len = term_hspan(p, &su);
|
||||
if (len < 0 && (size_t)(-len) > mt->offset)
|
||||
len = -mt->offset;
|
||||
else if (len > SHRT_MAX)
|
||||
len = term_len(p, p->defindent);
|
||||
mt->lmargin[mt->lmargincur] = len;
|
||||
} else
|
||||
len = mt->lmargin[mt->lmargincur];
|
||||
|
||||
switch (n->type) {
|
||||
case MAN_HEAD:
|
||||
/* Handle zero-length properly. */
|
||||
if (0 == len)
|
||||
len = term_len(p, 1);
|
||||
|
||||
p->offset = mt->offset;
|
||||
p->rmargin = mt->offset + len;
|
||||
|
||||
@ -734,9 +694,6 @@ pre_TP(DECL_ARGS)
|
||||
|
||||
if (savelit)
|
||||
mt->fl |= MANT_LITERAL;
|
||||
if (ival >= 0)
|
||||
mt->lmargin[mt->lmargincur] = (size_t)ival;
|
||||
|
||||
return(0);
|
||||
case MAN_BODY:
|
||||
p->offset = mt->offset + len;
|
||||
@ -881,8 +838,7 @@ post_SH(DECL_ARGS)
|
||||
static int
|
||||
pre_RS(DECL_ARGS)
|
||||
{
|
||||
int ival;
|
||||
size_t sz;
|
||||
struct roffsu su;
|
||||
|
||||
switch (n->type) {
|
||||
case MAN_BLOCK:
|
||||
@ -894,13 +850,16 @@ pre_RS(DECL_ARGS)
|
||||
break;
|
||||
}
|
||||
|
||||
sz = term_len(p, p->defindent);
|
||||
n = n->parent->head;
|
||||
n->aux = SHRT_MAX + 1;
|
||||
if (n->child != NULL && a2roffsu(n->child->string, &su, SCALE_EN))
|
||||
n->aux = term_hspan(p, &su);
|
||||
if (n->aux < 0 && (size_t)(-n->aux) > mt->offset)
|
||||
n->aux = -mt->offset;
|
||||
else if (n->aux > SHRT_MAX)
|
||||
n->aux = term_len(p, p->defindent);
|
||||
|
||||
if (NULL != (n = n->parent->head->child))
|
||||
if ((ival = a2width(p, n->string)) >= 0)
|
||||
sz = (size_t)ival;
|
||||
|
||||
mt->offset += sz;
|
||||
mt->offset += n->aux;
|
||||
p->offset = mt->offset;
|
||||
p->rmargin = p->maxrmargin;
|
||||
|
||||
@ -914,8 +873,6 @@ pre_RS(DECL_ARGS)
|
||||
static void
|
||||
post_RS(DECL_ARGS)
|
||||
{
|
||||
int ival;
|
||||
size_t sz;
|
||||
|
||||
switch (n->type) {
|
||||
case MAN_BLOCK:
|
||||
@ -927,13 +884,7 @@ post_RS(DECL_ARGS)
|
||||
break;
|
||||
}
|
||||
|
||||
sz = term_len(p, p->defindent);
|
||||
|
||||
if (NULL != (n = n->parent->head->child))
|
||||
if ((ival = a2width(p, n->string)) >= 0)
|
||||
sz = (size_t)ival;
|
||||
|
||||
mt->offset = mt->offset < sz ? 0 : mt->offset - sz;
|
||||
mt->offset -= n->parent->head->aux;
|
||||
p->offset = mt->offset;
|
||||
|
||||
if (--mt->lmarginsz < MAXMARGINS)
|
||||
@ -998,7 +949,7 @@ print_man_node(DECL_ARGS)
|
||||
* Tables are preceded by a newline. Then process a
|
||||
* table line, which will cause line termination,
|
||||
*/
|
||||
if (TBL_SPAN_FIRST & n->span->flags)
|
||||
if (n->span->prev == NULL)
|
||||
term_newln(p);
|
||||
term_tbl(p, n->span);
|
||||
return;
|
||||
@ -1056,10 +1007,10 @@ static void
|
||||
print_man_nodelist(DECL_ARGS)
|
||||
{
|
||||
|
||||
print_man_node(p, mt, n, meta);
|
||||
if ( ! n->next)
|
||||
return;
|
||||
print_man_nodelist(p, mt, n->next, meta);
|
||||
while (n != NULL) {
|
||||
print_man_node(p, mt, n, meta);
|
||||
n = n->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $OpenBSD$ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -38,10 +38,6 @@
|
||||
|
||||
typedef void (*v_check)(CHKARGS);
|
||||
|
||||
static void check_eq0(CHKARGS);
|
||||
static void check_eq2(CHKARGS);
|
||||
static void check_le1(CHKARGS);
|
||||
static void check_le5(CHKARGS);
|
||||
static void check_par(CHKARGS);
|
||||
static void check_part(CHKARGS);
|
||||
static void check_root(CHKARGS);
|
||||
@ -53,6 +49,7 @@ static void post_vs(CHKARGS);
|
||||
static void post_fi(CHKARGS);
|
||||
static void post_ft(CHKARGS);
|
||||
static void post_nf(CHKARGS);
|
||||
static void post_OP(CHKARGS);
|
||||
static void post_TH(CHKARGS);
|
||||
static void post_UC(CHKARGS);
|
||||
static void post_UR(CHKARGS);
|
||||
@ -79,7 +76,6 @@ static v_check man_valids[MAN_MAX] = {
|
||||
NULL, /* I */
|
||||
NULL, /* IR */
|
||||
NULL, /* RI */
|
||||
check_eq0, /* na */
|
||||
post_vs, /* sp */
|
||||
post_nf, /* nf */
|
||||
post_fi, /* fi */
|
||||
@ -87,11 +83,11 @@ static v_check man_valids[MAN_MAX] = {
|
||||
check_part, /* RS */
|
||||
NULL, /* DT */
|
||||
post_UC, /* UC */
|
||||
check_le1, /* PD */
|
||||
NULL, /* PD */
|
||||
post_AT, /* AT */
|
||||
NULL, /* in */
|
||||
post_ft, /* ft */
|
||||
check_eq2, /* OP */
|
||||
post_OP, /* OP */
|
||||
post_nf, /* EX */
|
||||
post_fi, /* EE */
|
||||
post_UR, /* UR */
|
||||
@ -172,29 +168,27 @@ check_text(CHKARGS)
|
||||
n->line, n->pos + (p - cp), NULL);
|
||||
}
|
||||
|
||||
#define INEQ_DEFINE(x, ineq, name) \
|
||||
static void \
|
||||
check_##name(CHKARGS) \
|
||||
{ \
|
||||
if (n->nchild ineq (x)) \
|
||||
return; \
|
||||
mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line, n->pos, \
|
||||
"line arguments %s %d (have %d)", \
|
||||
#ineq, (x), n->nchild); \
|
||||
}
|
||||
static void
|
||||
post_OP(CHKARGS)
|
||||
{
|
||||
|
||||
INEQ_DEFINE(0, ==, eq0)
|
||||
INEQ_DEFINE(2, ==, eq2)
|
||||
INEQ_DEFINE(1, <=, le1)
|
||||
INEQ_DEFINE(5, <=, le5)
|
||||
if (n->nchild == 0)
|
||||
mandoc_msg(MANDOCERR_OP_EMPTY, man->parse,
|
||||
n->line, n->pos, "OP");
|
||||
else if (n->nchild > 2) {
|
||||
n = n->child->next->next;
|
||||
mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse,
|
||||
n->line, n->pos, "OP ... %s", n->string);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
post_UR(CHKARGS)
|
||||
{
|
||||
|
||||
if (MAN_HEAD == n->type && 1 != n->nchild)
|
||||
mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line,
|
||||
n->pos, "line arguments eq 1 (have %d)", n->nchild);
|
||||
if (n->type == MAN_HEAD && n->child == NULL)
|
||||
mandoc_vmsg(MANDOCERR_UR_NOHEAD, man->parse,
|
||||
n->line, n->pos, "UR");
|
||||
check_part(man, n);
|
||||
}
|
||||
|
||||
@ -243,19 +237,15 @@ post_ft(CHKARGS)
|
||||
n->line, n->pos, "ft %s", cp);
|
||||
*cp = '\0';
|
||||
}
|
||||
|
||||
if (1 < n->nchild)
|
||||
mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line,
|
||||
n->pos, "want one child (have %d)", n->nchild);
|
||||
}
|
||||
|
||||
static void
|
||||
check_part(CHKARGS)
|
||||
{
|
||||
|
||||
if (MAN_BODY == n->type && 0 == n->nchild)
|
||||
mandoc_msg(MANDOCERR_ARGCWARN, man->parse, n->line,
|
||||
n->pos, "want children (have none)");
|
||||
if (n->type == MAN_BODY && n->child == NULL)
|
||||
mandoc_msg(MANDOCERR_BLK_EMPTY, man->parse,
|
||||
n->line, n->pos, man_macronames[n->tok]);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -312,8 +302,6 @@ post_TH(CHKARGS)
|
||||
struct man_node *nb;
|
||||
const char *p;
|
||||
|
||||
check_le5(man, n);
|
||||
|
||||
free(man->meta.title);
|
||||
free(man->meta.vol);
|
||||
free(man->meta.source);
|
||||
@ -379,6 +367,8 @@ post_TH(CHKARGS)
|
||||
|
||||
if (n && (n = n->next))
|
||||
man->meta.source = mandoc_strdup(n->string);
|
||||
else if (man->defos != NULL)
|
||||
man->meta.source = mandoc_strdup(man->defos);
|
||||
|
||||
/* TITLE MSEC DATE SOURCE ->VOL<- */
|
||||
/* If missing, use the default VOL name for MSEC. */
|
||||
@ -389,6 +379,10 @@ post_TH(CHKARGS)
|
||||
(NULL != (p = mandoc_a2msec(man->meta.msec))))
|
||||
man->meta.vol = mandoc_strdup(p);
|
||||
|
||||
if (n != NULL && (n = n->next) != NULL)
|
||||
mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse,
|
||||
n->line, n->pos, "TH ... %s", n->string);
|
||||
|
||||
/*
|
||||
* Remove the `TH' node after we've processed it for our
|
||||
* meta-data.
|
||||
@ -400,9 +394,7 @@ static void
|
||||
post_nf(CHKARGS)
|
||||
{
|
||||
|
||||
check_eq0(man, n);
|
||||
|
||||
if (MAN_LITERAL & man->flags)
|
||||
if (man->flags & MAN_LITERAL)
|
||||
mandoc_msg(MANDOCERR_NF_SKIP, man->parse,
|
||||
n->line, n->pos, "nf");
|
||||
|
||||
@ -413,8 +405,6 @@ static void
|
||||
post_fi(CHKARGS)
|
||||
{
|
||||
|
||||
check_eq0(man, n);
|
||||
|
||||
if ( ! (MAN_LITERAL & man->flags))
|
||||
mandoc_msg(MANDOCERR_FI_SKIP, man->parse,
|
||||
n->line, n->pos, "fi");
|
||||
@ -500,11 +490,6 @@ static void
|
||||
post_vs(CHKARGS)
|
||||
{
|
||||
|
||||
if (n->tok == MAN_br)
|
||||
check_eq0(man, n);
|
||||
else
|
||||
check_le1(man, n);
|
||||
|
||||
if (NULL != n->prev)
|
||||
return;
|
||||
|
||||
|
549
mandoc.1
549
mandoc.1
@ -1,7 +1,7 @@
|
||||
.\" $Id: mandoc.1,v 1.128 2014/12/02 11:31:51 schwarze Exp $
|
||||
.\" $Id: mandoc.1,v 1.155 2015/02/23 13:31:03 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\" Copyright (c) 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
@ -15,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: December 2 2014 $
|
||||
.Dd $Mdocdate: February 23 2015 $
|
||||
.Dt MANDOC 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -23,7 +23,7 @@
|
||||
.Nd format and display UNIX manuals
|
||||
.Sh SYNOPSIS
|
||||
.Nm mandoc
|
||||
.Op Fl acfhklV
|
||||
.Op Fl acfhkl
|
||||
.Sm off
|
||||
.Op Fl I Cm os Li = Ar name
|
||||
.Sm on
|
||||
@ -85,6 +85,9 @@ Override the default operating system
|
||||
for the
|
||||
.Xr mdoc 7
|
||||
.Sq \&Os
|
||||
and for the
|
||||
.Xr man 7
|
||||
.Sq \&TH
|
||||
macro.
|
||||
.It Fl h
|
||||
Display only the SYNOPSIS lines.
|
||||
@ -147,8 +150,6 @@ See
|
||||
for available formats.
|
||||
Defaults to
|
||||
.Fl T Ns Cm locale .
|
||||
.It Fl V
|
||||
Print version and exit.
|
||||
.It Fl W Ns Ar level
|
||||
Specify the minimum message
|
||||
.Ar level
|
||||
@ -159,12 +160,13 @@ can be
|
||||
.Cm warning ,
|
||||
.Cm error ,
|
||||
or
|
||||
.Cm fatal .
|
||||
The default is
|
||||
.Fl W Ns Cm fatal ;
|
||||
.Fl W Ns Cm all
|
||||
.Cm unsupp ;
|
||||
.Cm all
|
||||
is an alias for
|
||||
.Fl W Ns Cm warning .
|
||||
.Cm warning .
|
||||
By default,
|
||||
.Nm
|
||||
is silent.
|
||||
See
|
||||
.Sx EXIT STATUS
|
||||
and
|
||||
@ -317,9 +319,6 @@ Emboldened characters are rendered as
|
||||
The special characters documented in
|
||||
.Xr mandoc_char 7
|
||||
are rendered best-effort in an ASCII equivalent.
|
||||
If no equivalent is found,
|
||||
.Sq \&?
|
||||
is used instead.
|
||||
.Pp
|
||||
Output width is limited to 78 visible columns unless literal input lines
|
||||
exceed this limit.
|
||||
@ -340,7 +339,7 @@ for example overfull lines or ugly line breaks.
|
||||
.It Cm width Ns = Ns Ar width
|
||||
The output width is set to
|
||||
.Ar width ,
|
||||
which will normalise to \(>=60.
|
||||
which will normalise to \(>=58.
|
||||
.El
|
||||
.Ss HTML Output
|
||||
Output produced by
|
||||
@ -529,19 +528,25 @@ At least one warning occurred, but no error, and
|
||||
.Fl W Ns Cm warning
|
||||
was specified.
|
||||
.It 3
|
||||
At least one parsing error occurred, but no fatal error, and
|
||||
At least one parsing error occurred,
|
||||
but no unsupported feature was encountered, and
|
||||
.Fl W Ns Cm error
|
||||
or
|
||||
.Fl W Ns Cm warning
|
||||
was specified.
|
||||
.It 4
|
||||
A fatal parsing error occurred.
|
||||
At least one unsupported feature was encountered, and
|
||||
.Fl W Ns Cm unsupp ,
|
||||
.Fl W Ns Cm error
|
||||
or
|
||||
.Fl W Ns Cm warning
|
||||
was specified.
|
||||
.It 5
|
||||
Invalid command line arguments were specified.
|
||||
No input files have been read.
|
||||
.It 6
|
||||
An operating system error occurred, for example memory exhaustion or an
|
||||
error accessing input files.
|
||||
An operating system error occurred, for example exhaustion
|
||||
of memory, file descriptors, or process table entries.
|
||||
Such errors cause
|
||||
.Nm
|
||||
to exit at once, possibly in the middle of parsing or formatting a file.
|
||||
@ -600,22 +605,34 @@ fields.
|
||||
.Pp
|
||||
Message levels have the following meanings:
|
||||
.Bl -tag -width "warning"
|
||||
.It Cm syserr
|
||||
Opening or reading an input file failed, so the parser cannot
|
||||
even be started and no output is produced from that input file.
|
||||
.It Cm fatal
|
||||
The parser is unable to parse a given input file at all.
|
||||
No formatted output is produced from that input file.
|
||||
.It Cm error
|
||||
An input file contains syntax that cannot be safely interpreted,
|
||||
either because it is invalid or because
|
||||
.It Cm unsupp
|
||||
An input file uses unsupported low-level
|
||||
.Xr roff 7
|
||||
features.
|
||||
The output may be incomplete and/or misformatted,
|
||||
so using GNU troff instead of
|
||||
.Nm
|
||||
does not implement it yet.
|
||||
to process the file may be preferable.
|
||||
.It Cm error
|
||||
An input file contains invalid syntax that cannot be safely interpreted.
|
||||
By discarding part of the input or inserting missing tokens,
|
||||
the parser is able to continue, and the error does not prevent
|
||||
generation of formatted output, but typically, preparing that
|
||||
output involves information loss, broken document structure
|
||||
or unintended formatting.
|
||||
or unintended formatting, no matter whether
|
||||
.Nm
|
||||
or GNU troff is used.
|
||||
In many cases, the output of
|
||||
.Nm
|
||||
and GNU troff is identical, but in some,
|
||||
.Nm
|
||||
is more resilient than GNU troff with respect to malformed input.
|
||||
.Pp
|
||||
Non-existent or unreadable input files are also reported on the
|
||||
.Cm error
|
||||
level.
|
||||
In that case, the parser cannot even be started and no output
|
||||
is produced from those input files.
|
||||
.It Cm warning
|
||||
An input file uses obsolete, discouraged or non-portable syntax.
|
||||
All the same, the meaning of the input is unambiguous and a correct
|
||||
@ -626,10 +643,12 @@ formatting tools instead of
|
||||
.El
|
||||
.Pp
|
||||
Messages of the
|
||||
.Cm warning
|
||||
.Cm warning ,
|
||||
.Cm error ,
|
||||
and
|
||||
.Cm error
|
||||
levels are hidden unless their level, or a lower level, is requested using a
|
||||
.Cm unsupp
|
||||
levels except those about non-existent or unreadable input files
|
||||
are hidden unless their level, or a lower level, is requested using a
|
||||
.Fl W
|
||||
option or
|
||||
.Fl T Ns Cm lint
|
||||
@ -708,9 +727,9 @@ macro occurs after some non-prologue macro, but still takes effect.
|
||||
.Pq mdoc
|
||||
The
|
||||
.Ic \&Dt
|
||||
macro can only occur before the first non-prologue macro
|
||||
because traditional formatters write the page header
|
||||
before parsing the document body.
|
||||
macro appears after the first non-prologue macro.
|
||||
Traditional formatters cannot handle this because
|
||||
they write the page header before parsing the document body.
|
||||
Even though this technical restriction does not apply to
|
||||
.Nm ,
|
||||
traditional semantics is preserved.
|
||||
@ -752,17 +771,33 @@ This may confuse
|
||||
.Xr makewhatis 8
|
||||
and
|
||||
.Xr apropos 1 .
|
||||
.It Sy "bad NAME section contents"
|
||||
.It Sy "NAME section without name"
|
||||
.Pq mdoc
|
||||
The last node in the NAME section is not an
|
||||
The NAME section does not contain any
|
||||
.Ic \&Nm
|
||||
child macro.
|
||||
.It Sy "NAME section without description"
|
||||
.Pq mdoc
|
||||
The NAME section lacks the mandatory
|
||||
.Ic \&Nd
|
||||
macro, or any preceding macro is not
|
||||
.Ic \&Nm ,
|
||||
or the NAME section is completely empty.
|
||||
This may confuse
|
||||
.Xr makewhatis 8
|
||||
child macro.
|
||||
.It Sy "description not at the end of NAME"
|
||||
.Pq mdoc
|
||||
The NAME section does contain an
|
||||
.Ic \&Nd
|
||||
child macro, but other content follows it.
|
||||
.It Sy "bad NAME section content"
|
||||
.Pq mdoc
|
||||
The NAME section contains plain text or macros other than
|
||||
.Ic \&Nm
|
||||
and
|
||||
.Xr apropos 1 .
|
||||
.Ic \&Nd .
|
||||
.It Sy "missing description line, using \(dq\(dq"
|
||||
.Pq mdoc
|
||||
The
|
||||
.Ic \&Nd
|
||||
macro lacks the required argument.
|
||||
The title line of the manual will end after the dash.
|
||||
.It Sy "sections out of conventional order"
|
||||
.Pq mdoc
|
||||
A standard section occurs after another section it usually precedes.
|
||||
@ -809,7 +844,7 @@ manual for replacements.
|
||||
.Pq mdoc
|
||||
The name of a macro that is not callable appears on a macro line.
|
||||
It is printed verbatim.
|
||||
If the intention is to call it, move it to its own line;
|
||||
If the intention is to call it, move it to its own input line;
|
||||
otherwise, escape it by prepending
|
||||
.Sq \e& .
|
||||
.It Sy "skipping paragraph macro"
|
||||
@ -968,6 +1003,18 @@ clause.
|
||||
.It Sy "skipping empty macro"
|
||||
.Pq mdoc
|
||||
The indicated macro has no arguments and hence no effect.
|
||||
.It Sy "empty block"
|
||||
.Pq mdoc , man
|
||||
A
|
||||
.Ic \&Bd ,
|
||||
.Ic \&Bk ,
|
||||
.Ic \&Bl ,
|
||||
.Ic \&D1 ,
|
||||
.Ic \&Dl ,
|
||||
.Ic \&RS ,
|
||||
or
|
||||
.Ic \&UR
|
||||
block contains nothing in its body and will produce no output.
|
||||
.It Sy "empty argument, using 0n"
|
||||
.Pq mdoc
|
||||
The required width is missing after
|
||||
@ -977,12 +1024,6 @@ or
|
||||
.Fl offset
|
||||
or
|
||||
.Fl width.
|
||||
.It Sy "argument count wrong"
|
||||
.Pq mdoc , man
|
||||
The indicated macro has too few or too many arguments.
|
||||
The syntax tree will contain the wrong number of arguments as given.
|
||||
Formatting behaviour depends on the specific macro in question.
|
||||
Note that the same message may also occur as an ERROR, see below.
|
||||
.It Sy "missing display type, using -ragged"
|
||||
.Pq mdoc
|
||||
The
|
||||
@ -1014,6 +1055,12 @@ The
|
||||
macro is called without an argument before
|
||||
.Ic \&Nm
|
||||
has first been called with an argument.
|
||||
.It Sy "missing function name, using \(dq\(dq"
|
||||
.Pq mdoc
|
||||
The
|
||||
.Ic \&Fo
|
||||
macro is called without an argument.
|
||||
No function name is printed.
|
||||
.It Sy "empty head in list item"
|
||||
.Pq mdoc
|
||||
In a
|
||||
@ -1041,21 +1088,18 @@ list, an
|
||||
.Ic \&It
|
||||
block is empty.
|
||||
An empty list item is shown.
|
||||
.It Sy "missing font type"
|
||||
.It Sy "missing font type, using \efR"
|
||||
.Pq mdoc
|
||||
A
|
||||
.Ic \&Bf
|
||||
macro has no argument.
|
||||
It switches to the default font,
|
||||
.Cm \efR .
|
||||
.It Sy "unknown font type"
|
||||
It switches to the default font.
|
||||
.It Sy "unknown font type, using \efR"
|
||||
.Pq mdoc
|
||||
The
|
||||
.Ic \&Bf
|
||||
argument is invalid.
|
||||
The default font
|
||||
.Cm \efR
|
||||
is used instead.
|
||||
The default font is used instead.
|
||||
.It Sy "nothing follows prefix"
|
||||
.Pq mdoc
|
||||
A
|
||||
@ -1064,6 +1108,14 @@ macro has no argument, or only one argument and no macro follows
|
||||
on the same input line.
|
||||
This defeats its purpose; in particular, spacing is not suppressed
|
||||
before the text or macros following on the next input line.
|
||||
.It Sy "empty reference block"
|
||||
.Pq mdoc
|
||||
An
|
||||
.Ic \&Rs
|
||||
macro is immediately followed by an
|
||||
.Ic \&Re
|
||||
macro on the next input line.
|
||||
Such an empty block does not produce any output.
|
||||
.It Sy "missing -std argument, adding it"
|
||||
.Pq mdoc
|
||||
An
|
||||
@ -1078,6 +1130,18 @@ The
|
||||
utility assumes
|
||||
.Fl std
|
||||
even when it is not specified, but other implementations may not.
|
||||
.It Sy "missing option string, using \(dq\(dq"
|
||||
.Pq man
|
||||
The
|
||||
.Ic \&OP
|
||||
macro is invoked without any argument.
|
||||
An empty pair of square brackets is shown.
|
||||
.It Sy "missing resource identifier, using \(dq\(dq"
|
||||
.Pq man
|
||||
The
|
||||
.Ic \&UR
|
||||
macro is invoked without any argument.
|
||||
An empty pair of angle brackets is shown.
|
||||
.It Sy "missing eqn box, using \(dq\(dq"
|
||||
.Pq eqn
|
||||
A diacritic mark or a binary operator is found,
|
||||
@ -1142,6 +1206,15 @@ list has a
|
||||
.Fl width
|
||||
argument.
|
||||
That has no effect.
|
||||
.It Sy "wrong number of cells"
|
||||
In a line of a
|
||||
.Ic \&Bl Fl column
|
||||
list, the number of tabs or
|
||||
.Ic \&Ta
|
||||
macros is less than the number expected from the list header line
|
||||
or exceeds the expected number by more than one.
|
||||
Missing cells remain empty, and all cells exceeding the number of
|
||||
columns are joined into one single cell.
|
||||
.It Sy "unknown AT&T UNIX version"
|
||||
.Pq mdoc
|
||||
An
|
||||
@ -1193,6 +1266,12 @@ request or a
|
||||
layout modifier has an unknown
|
||||
.Ar font
|
||||
argument.
|
||||
.It Sy "odd number of characters in request"
|
||||
.Pq roff
|
||||
A
|
||||
.Ic \&tr
|
||||
request contains an odd number of characters.
|
||||
The last character is mapped to the blank character.
|
||||
.El
|
||||
.Ss "Warnings related to plain text"
|
||||
.Bl -ohang
|
||||
@ -1249,23 +1328,86 @@ its value is implicitly set to the empty string.
|
||||
However, defining strings explicitly before use
|
||||
keeps the code more readable.
|
||||
.El
|
||||
.Ss "Errors related to equations"
|
||||
.Bl -inset -compact
|
||||
.It "unexpected equation scope closure"
|
||||
.It "equation scope open on exit"
|
||||
.It "overlapping equation scopes"
|
||||
.It "unexpected end of equation"
|
||||
.Ss "Warnings related to tables"
|
||||
.Bl -ohang
|
||||
.It Sy "tbl line starts with span"
|
||||
.Pq tbl
|
||||
The first cell in a table layout line is a horizontal span
|
||||
.Pq Sq Cm s .
|
||||
Data provided for this cell is ignored, and nothing is printed in the cell.
|
||||
.It Sy "tbl column starts with span"
|
||||
.Pq tbl
|
||||
The first line of a table layout specification
|
||||
requests a vertical span
|
||||
.Pq Sq Cm ^ .
|
||||
Data provided for this cell is ignored, and nothing is printed in the cell.
|
||||
.It Sy "skipping vertical bar in tbl layout"
|
||||
.Pq tbl
|
||||
A table layout specification contains more than two consecutive vertical bars.
|
||||
A double bar is printed, all additional bars are discarded.
|
||||
.El
|
||||
.Ss "Errors related to tables"
|
||||
.Bl -inset -compact
|
||||
.It "bad table syntax"
|
||||
.It "bad table option"
|
||||
.It "bad table layout"
|
||||
.It "no table layout cells specified"
|
||||
.It "no table data cells specified"
|
||||
.It "ignore data in cell"
|
||||
.It "data block still open"
|
||||
.It "ignoring extra data cells"
|
||||
.Bl -ohang
|
||||
.It Sy "non-alphabetic character in tbl options"
|
||||
.Pq tbl
|
||||
The table options line contains a character other than a letter,
|
||||
blank, or comma where the beginning of an option name is expected.
|
||||
The character is ignored.
|
||||
.It Sy "skipping unknown tbl option"
|
||||
.Pq tbl
|
||||
The table options line contains a string of letters that does not
|
||||
match any known option name.
|
||||
The word is ignored.
|
||||
.It Sy "missing tbl option argument"
|
||||
.Pq tbl
|
||||
A table option that requires an argument is not followed by an
|
||||
opening parenthesis, or the opening parenthesis is immediately
|
||||
followed by a closing parenthesis.
|
||||
The option is ignored.
|
||||
.It Sy "wrong tbl option argument size"
|
||||
.Pq tbl
|
||||
A table option argument contains an invalid number of characters.
|
||||
Both the option and the argument are ignored.
|
||||
.It Sy "empty tbl layout"
|
||||
.Pq tbl
|
||||
A table layout specification is completely empty,
|
||||
specifying zero lines and zero columns.
|
||||
As a fallback, a single left-justified column is used.
|
||||
.It Sy "invalid character in tbl layout"
|
||||
.Pq tbl
|
||||
A table layout specification contains a character that can neither
|
||||
be interpreted as a layout key character nor as a layout modifier,
|
||||
or a modifier precedes the first key.
|
||||
The invalid character is discarded.
|
||||
.It Sy "unmatched parenthesis in tbl layout"
|
||||
.Pq tbl
|
||||
A table layout specification contains an opening parenthesis,
|
||||
but no matching closing parenthesis.
|
||||
The rest of the input line, starting from the parenthesis, has no effect.
|
||||
.It Sy "tbl without any data cells"
|
||||
.Pq tbl
|
||||
A table does not contain any data cells.
|
||||
It will probably produce no output.
|
||||
.It Sy "ignoring data in spanned tbl cell"
|
||||
.Pq tbl
|
||||
A table cell is marked as a horizontal span
|
||||
.Pq Sq Cm s
|
||||
or vertical span
|
||||
.Pq Sq Cm ^
|
||||
in the table layout, but it contains data.
|
||||
The data is ignored.
|
||||
.It Sy "ignoring extra tbl data cells"
|
||||
.Pq tbl
|
||||
A data line contains more cells than the corresponding layout line.
|
||||
The data in the extra cells is ignored.
|
||||
.It Sy "data block open at end of tbl"
|
||||
.Pq tbl
|
||||
A data block is opened with
|
||||
.Cm T{ ,
|
||||
but never closed with a matching
|
||||
.Cm T} .
|
||||
The remaining data lines of the table are all put into one cell,
|
||||
and any remaining cells stay empty.
|
||||
.El
|
||||
.Ss "Errors related to roff, mdoc, and man code"
|
||||
.Bl -ohang
|
||||
@ -1307,6 +1449,11 @@ or
|
||||
macro.
|
||||
It may be mistyped or unsupported.
|
||||
The request or macro is discarded including its arguments.
|
||||
.It Sy "skipping insecure request"
|
||||
.Pq roff
|
||||
An input file attempted to run a shell command
|
||||
or to read or write an external file.
|
||||
Such attempts are denied for security reasons.
|
||||
.It Sy "skipping item outside list"
|
||||
.Pq mdoc , eqn
|
||||
An
|
||||
@ -1343,6 +1490,16 @@ right delimiter or closing brace, or the end of an equation, table, or
|
||||
.Xr roff 7
|
||||
conditional request is encountered but no matching block is open.
|
||||
The offending request or macro is discarded.
|
||||
.It Sy "fewer RS blocks open, skipping"
|
||||
.Pq man
|
||||
The
|
||||
.Ic \&RE
|
||||
macro is invoked with an argument, but less than the specified number of
|
||||
.Ic \&RS
|
||||
blocks is open.
|
||||
The
|
||||
.Ic \&RE
|
||||
macro is discarded.
|
||||
.It Sy "inserting missing end of block"
|
||||
.Pq mdoc , tbl
|
||||
Various
|
||||
@ -1351,7 +1508,7 @@ macros as well as tables require explicit closing by dedicated macros.
|
||||
A block that doesn't support bad nesting
|
||||
ends before all of its children are properly closed.
|
||||
The open child nodes are closed implicitly.
|
||||
.It Sy "scope open on exit"
|
||||
.It Sy "appending missing end of block"
|
||||
.Pq mdoc , man , eqn , tbl , roff
|
||||
At the end of the document, an explicit
|
||||
.Xr mdoc 7
|
||||
@ -1401,12 +1558,6 @@ When parsing for a request or a user-defined macro name to be called,
|
||||
only the escape sequence is discarded.
|
||||
The characters preceding it are used as the request or macro name,
|
||||
the characters following it are used as the arguments to the request or macro.
|
||||
.It Sy "argument count wrong"
|
||||
.Pq mdoc , man , roff
|
||||
The indicated request or macro has too few or too many arguments.
|
||||
The syntax tree will contain the wrong number of arguments as given.
|
||||
Formatting behaviour depends on the specific request or macro in question.
|
||||
Note that the same message may also occur as a WARNING, see above.
|
||||
.It Sy "NOT IMPLEMENTED: Bd -file"
|
||||
.Pq mdoc
|
||||
For security reasons, the
|
||||
@ -1457,6 +1608,29 @@ or
|
||||
.Ic \&gsize
|
||||
statement has a non-numeric or negative argument or no argument at all.
|
||||
The invalid request or statement is ignored.
|
||||
.It Sy "NOT IMPLEMENTED: .so with absolute path or \(dq..\(dq"
|
||||
.Pq roff
|
||||
For security reasons,
|
||||
.Nm
|
||||
allows
|
||||
.Ic \&so
|
||||
file inclusion requests only with relative paths
|
||||
and only without ascending to any parent directory.
|
||||
By requesting the inclusion of a sensitive file, a malicious document
|
||||
might otherwise trick a privileged user into inadvertently displaying
|
||||
the file on the screen, revealing the file content to bystanders.
|
||||
.Nm
|
||||
only shows the path as it appears behind
|
||||
.Ic \&so .
|
||||
.It Sy ".so request failed"
|
||||
.Pq roff
|
||||
Servicing a
|
||||
.Ic \&so
|
||||
request requires reading an external file, but the file could not be
|
||||
opened.
|
||||
.Nm
|
||||
only shows the path as it appears behind
|
||||
.Ic \&so .
|
||||
.It Sy "skipping all arguments"
|
||||
.Pq mdoc , man , eqn , roff
|
||||
An
|
||||
@ -1466,7 +1640,10 @@ An
|
||||
.Ic \&Ef ,
|
||||
.Ic \&Ek ,
|
||||
.Ic \&El ,
|
||||
.Ic \&Lp ,
|
||||
.Ic \&Pp ,
|
||||
.Ic \&Re ,
|
||||
.Ic \&Rs ,
|
||||
or
|
||||
.Ic \&Ud
|
||||
macro, an
|
||||
@ -1484,19 +1661,57 @@ or
|
||||
.Ic \&EN
|
||||
macro, or a
|
||||
.Xr roff 7
|
||||
.Ic \&br ,
|
||||
.Ic \&fi ,
|
||||
or
|
||||
.Ic \&nf
|
||||
request or
|
||||
.Sq \&..
|
||||
block closing request is invoked with at least one argument.
|
||||
All arguments are ignored.
|
||||
.It Sy "skipping excess arguments"
|
||||
.Pq mdoc , roff
|
||||
The
|
||||
.Ic \&Bf
|
||||
macro is invoked with more than one argument, or a request of the
|
||||
.Pq mdoc , man , roff
|
||||
A macro or request is invoked with too many arguments:
|
||||
.Bl -dash -offset 2n -width 2n -compact
|
||||
.It
|
||||
.Ic \&Fo ,
|
||||
.Ic \&PD ,
|
||||
.Ic \&RS ,
|
||||
.Ic \&UR ,
|
||||
.Ic \&ft ,
|
||||
or
|
||||
.Ic \&sp
|
||||
with more than one argument
|
||||
.It
|
||||
.Ic \&An
|
||||
with another argument after
|
||||
.Fl split
|
||||
or
|
||||
.Fl nosplit
|
||||
.It
|
||||
.Ic \&RE
|
||||
with more than one argument or with a non-integer argument
|
||||
.It
|
||||
.Ic \&OP
|
||||
or a request of the
|
||||
.Ic \&de
|
||||
family is invoked with more than two arguments.
|
||||
family with more than two arguments
|
||||
.It
|
||||
.Ic \&Dt
|
||||
with more than three arguments
|
||||
.It
|
||||
.Ic \&TH
|
||||
with more than five arguments
|
||||
.It
|
||||
.Ic \&Bd ,
|
||||
.Ic \&Bk ,
|
||||
or
|
||||
.Ic \&Bl
|
||||
with invalid arguments
|
||||
.El
|
||||
The excess arguments are ignored.
|
||||
.El
|
||||
.Ss FATAL errors
|
||||
.Ss Unsupported features
|
||||
.Bl -ohang
|
||||
.It Sy "input too large"
|
||||
.Pq mdoc , man
|
||||
@ -1506,116 +1721,45 @@ cannot handle input files larger than its arbitrary size limit
|
||||
of 2^31 bytes (2 Gigabytes).
|
||||
Since useful manuals are always small, this is not a problem in practice.
|
||||
Parsing is aborted as soon as the condition is detected.
|
||||
.It Sy "NOT IMPLEMENTED: .so with absolute path or \(dq..\(dq"
|
||||
.It Sy "unsupported control character"
|
||||
.Pq roff
|
||||
For security reasons,
|
||||
An ASCII control character supported by other
|
||||
.Xr roff 7
|
||||
implementations but not by
|
||||
.Nm
|
||||
allows
|
||||
.Ic \&so
|
||||
file inclusion requests only with relative paths
|
||||
and only without ascending to any parent directory.
|
||||
By requesting the inclusion of a sensitive file, a malicious document
|
||||
might otherwise trick a privileged user into inadvertently displaying
|
||||
the file on the screen, revealing the file content to bystanders.
|
||||
The parser exits immediately.
|
||||
.It Sy ".so request failed"
|
||||
was found in an input file.
|
||||
It is replaced by a question mark.
|
||||
.It Sy "unsupported roff request"
|
||||
.Pq roff
|
||||
Servicing a
|
||||
.Ic \&so
|
||||
request requires reading an external file.
|
||||
While trying to do so, an
|
||||
.Xr open 2 ,
|
||||
.Xr stat 2 ,
|
||||
An input file contains a
|
||||
.Xr roff 7
|
||||
request supported by GNU troff or Heirloom troff but not by
|
||||
.Nm ,
|
||||
and it is likely that this will cause information loss
|
||||
or considerable misformatting.
|
||||
.It Sy "eqn delim option in tbl"
|
||||
.Pq eqn , tbl
|
||||
The options line of a table defines equation delimiters.
|
||||
Any equation source code contained in the table will be printed unformatted.
|
||||
.It Sy "unsupported table layout modifier"
|
||||
.Pq tbl
|
||||
A table layout specification contains an
|
||||
.Sq Cm m
|
||||
modifier.
|
||||
The modifier is discarded.
|
||||
.It Sy "ignoring macro in table"
|
||||
.Pq tbl , mdoc , man
|
||||
A table contains an invocation of an
|
||||
.Xr mdoc 7
|
||||
or
|
||||
.Xr read 2
|
||||
system call failed.
|
||||
The parser exits immediately.
|
||||
Before showing this message,
|
||||
.Nm
|
||||
always shows another message explaining why the system call failed.
|
||||
.El
|
||||
.Sh COMPATIBILITY
|
||||
This section summarises
|
||||
.Nm
|
||||
compatibility with GNU troff.
|
||||
Each input and output format is separately noted.
|
||||
.Ss ASCII Compatibility
|
||||
.Bl -bullet -compact
|
||||
.It
|
||||
Unrenderable unicode codepoints specified with
|
||||
.Sq \e[uNNNN]
|
||||
escapes are printed as
|
||||
.Sq \&?
|
||||
in mandoc.
|
||||
In GNU troff, these raise an error.
|
||||
.It
|
||||
The
|
||||
.Sq \&Bd \-literal
|
||||
and
|
||||
.Sq \&Bd \-unfilled
|
||||
macros of
|
||||
.Xr mdoc 7
|
||||
in
|
||||
.Fl T Ns Cm ascii
|
||||
are synonyms, as are \-filled and \-ragged.
|
||||
.It
|
||||
In historic GNU troff, the
|
||||
.Sq \&Pa
|
||||
.Xr mdoc 7
|
||||
macro does not underline when scoped under an
|
||||
.Sq \&It
|
||||
in the FILES section.
|
||||
This behaves correctly in
|
||||
.Nm .
|
||||
.It
|
||||
A list or display following the
|
||||
.Sq \&Ss
|
||||
.Xr mdoc 7
|
||||
macro in
|
||||
.Fl T Ns Cm ascii
|
||||
does not assert a prior vertical break, just as it doesn't with
|
||||
.Sq \&Sh .
|
||||
.It
|
||||
The
|
||||
.Sq \&na
|
||||
.Xr man 7
|
||||
macro in
|
||||
.Fl T Ns Cm ascii
|
||||
has no effect.
|
||||
.It
|
||||
Words aren't hyphenated.
|
||||
.El
|
||||
.Ss HTML Compatibility
|
||||
.Bl -bullet -compact
|
||||
.It
|
||||
The
|
||||
.Sq \efP
|
||||
escape will revert the font to the previous
|
||||
.Sq \ef
|
||||
escape, not to the last rendered decoration, which is now dictated by
|
||||
CSS instead of hard-coded.
|
||||
It also will not span past the current scope,
|
||||
for the same reason.
|
||||
Note that in
|
||||
.Sx ASCII Output
|
||||
mode, this will work fine.
|
||||
.It
|
||||
The
|
||||
.Xr mdoc 7
|
||||
.Sq \&Bl \-hang
|
||||
and
|
||||
.Sq \&Bl \-tag
|
||||
list types render similarly (no break following overreached left-hand
|
||||
side) due to the expressive constraints of HTML.
|
||||
.It
|
||||
The
|
||||
.Xr man 7
|
||||
.Sq IP
|
||||
and
|
||||
.Sq TP
|
||||
lists render similarly.
|
||||
macro or of an undefined macro.
|
||||
The macro is ignored, and its arguments are handled
|
||||
as if they were a text line.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr apropos 1 ,
|
||||
.Xr man 1 ,
|
||||
.Xr eqn 7 ,
|
||||
.Xr man 7 ,
|
||||
.Xr mandoc_char 7 ,
|
||||
@ -1626,32 +1770,15 @@ lists render similarly.
|
||||
The
|
||||
.Nm
|
||||
utility was written by
|
||||
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
|
||||
.Sh CAVEATS
|
||||
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv
|
||||
and is maintained by
|
||||
.An Ingo Schwarze Aq Mt schwarze@openbsd.org .
|
||||
.Sh BUGS
|
||||
In
|
||||
.Fl T Ns Cm html
|
||||
and
|
||||
.Fl T Ns Cm xhtml ,
|
||||
.Fl T Ns Cm html ,
|
||||
the maximum size of an element attribute is determined by
|
||||
.Dv BUFSIZ ,
|
||||
which is usually 1024 bytes.
|
||||
Be aware of this when setting long link
|
||||
formats such as
|
||||
.Fl O Ns Cm style Ns = Ns Ar really/long/link .
|
||||
.Pp
|
||||
Nesting elements within next-line element scopes of
|
||||
.Fl m Ns Cm an ,
|
||||
such as
|
||||
.Sq br
|
||||
within an empty
|
||||
.Sq B ,
|
||||
will confuse
|
||||
.Fl T Ns Cm html
|
||||
and
|
||||
.Fl T Ns Cm xhtml
|
||||
and cause them to forget the formatting of the prior next-line scope.
|
||||
.Pp
|
||||
The
|
||||
.Sq \(aq
|
||||
control character is an alias for the standard macro control character
|
||||
and does not emit a line-break as stipulated in GNU troff.
|
||||
|
48
mandoc.3
48
mandoc.3
@ -1,7 +1,7 @@
|
||||
.\" $Id: mandoc.3,v 1.29 2014/11/26 23:42:14 schwarze Exp $
|
||||
.\" $Id: mandoc.3,v 1.31 2015/01/15 04:26:40 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\" Copyright (c) 2010, 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
@ -15,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: November 26 2014 $
|
||||
.Dd $Mdocdate: January 15 2015 $
|
||||
.Dt MANDOC 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -39,11 +39,10 @@
|
||||
.Nm mparse_strlevel
|
||||
.Nm mparse_wait ,
|
||||
.Nd mandoc macro compiler library
|
||||
.Sh LIBRARY
|
||||
.Lb libmandoc
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In mandoc.h
|
||||
.Pp
|
||||
.Fd "#define ASCII_NBRSP"
|
||||
.Fd "#define ASCII_HYPH"
|
||||
.Fd "#define ASCII_BREAK"
|
||||
@ -176,10 +175,15 @@ initiate a parsing sequence with
|
||||
and
|
||||
.Fn mparse_alloc ;
|
||||
.It
|
||||
parse files or file descriptors with
|
||||
open a file with
|
||||
.Xr open 2
|
||||
or
|
||||
.Fn mparse_open ;
|
||||
.It
|
||||
parse it with
|
||||
.Fn mparse_readfd ;
|
||||
.It
|
||||
retrieve a parsed syntax tree, if the parse was successful, with
|
||||
retrieve the syntax tree with
|
||||
.Fn mparse_result ;
|
||||
.It
|
||||
iterate over parse nodes with
|
||||
@ -206,7 +210,7 @@ and
|
||||
.Ss Types
|
||||
.Bl -ohang
|
||||
.It Vt "enum mandocerr"
|
||||
A fatal error, error, or warning message during parsing.
|
||||
An error or warning message during parsing.
|
||||
.It Vt "enum mandoclevel"
|
||||
A classification of an
|
||||
.Vt "enum mandocerr"
|
||||
@ -227,7 +231,7 @@ This may be used across parsed input if
|
||||
.Fn mparse_reset
|
||||
is called between parses.
|
||||
.It Vt "mandocmsg"
|
||||
A prototype for a function to handle fatal error, error, and warning
|
||||
A prototype for a function to handle error and warning
|
||||
messages emitted by the parser.
|
||||
.El
|
||||
.Ss Functions
|
||||
@ -331,7 +335,7 @@ This is for example useful in
|
||||
to quickly build minimal databases.
|
||||
.It Ar wlevel
|
||||
Can be set to
|
||||
.Dv MANDOCLEVEL_FATAL ,
|
||||
.Dv MANDOCLEVEL_BADARG ,
|
||||
.Dv MANDOCLEVEL_ERROR ,
|
||||
or
|
||||
.Dv MANDOCLEVEL_WARNING .
|
||||
@ -413,17 +417,12 @@ Declared in
|
||||
implemented in
|
||||
.Pa read.c .
|
||||
.It Fn mparse_readfd
|
||||
Parse a file or file descriptor.
|
||||
If
|
||||
.Va fd
|
||||
is -1, open
|
||||
.Va fname
|
||||
with
|
||||
Parse a file descriptor opened with
|
||||
.Xr open 2
|
||||
or
|
||||
.Fn mparse_open .
|
||||
Otherwise,
|
||||
.Va fname
|
||||
is assumed to be the name associated with
|
||||
.Va fd .
|
||||
Pass the associated filename in
|
||||
.Va fname .
|
||||
Calls
|
||||
.Fn mparse_wait
|
||||
before returning.
|
||||
@ -444,14 +443,7 @@ implemented in
|
||||
.Pa read.c .
|
||||
.It Fn mparse_result
|
||||
Obtain the result of a parse.
|
||||
Only successful parses
|
||||
.Po
|
||||
i.e., those where
|
||||
.Fn mparse_readfd
|
||||
returned less than MANDOCLEVEL_FATAL
|
||||
.Pc
|
||||
should invoke this function, in which case one of the three pointers will
|
||||
be filled in.
|
||||
One of the three pointers will be filled in.
|
||||
Declared in
|
||||
.In mandoc.h ,
|
||||
implemented in
|
||||
|
28
mandoc.c
28
mandoc.c
@ -1,7 +1,7 @@
|
||||
/* $Id: mandoc.c,v 1.88 2014/10/28 13:24:44 schwarze Exp $ */
|
||||
/* $Id: mandoc.c,v 1.92 2015/02/20 23:55:10 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -156,16 +156,18 @@ mandoc_escape(const char **end, const char **start, int *sz)
|
||||
/* FALLTHROUGH */
|
||||
case 'D':
|
||||
/* FALLTHROUGH */
|
||||
case 'o':
|
||||
/* FALLTHROUGH */
|
||||
case 'R':
|
||||
/* FALLTHROUGH */
|
||||
case 'X':
|
||||
/* FALLTHROUGH */
|
||||
case 'Z':
|
||||
if ('\0' == **start)
|
||||
return(ESCAPE_ERROR);
|
||||
gly = ESCAPE_IGNORE;
|
||||
/* FALLTHROUGH */
|
||||
case 'o':
|
||||
if (**start == '\0')
|
||||
return(ESCAPE_ERROR);
|
||||
if (gly == ESCAPE_ERROR)
|
||||
gly = ESCAPE_OVERSTRIKE;
|
||||
term = **start;
|
||||
*start = ++*end;
|
||||
break;
|
||||
@ -225,7 +227,7 @@ mandoc_escape(const char **end, const char **start, int *sz)
|
||||
|
||||
/* See +/- counts as a sign. */
|
||||
if ('+' == **end || '-' == **end || ASCII_HYPH == **end)
|
||||
(*end)++;
|
||||
*start = ++*end;
|
||||
|
||||
switch (**end) {
|
||||
case '(':
|
||||
@ -240,6 +242,14 @@ mandoc_escape(const char **end, const char **start, int *sz)
|
||||
*start = ++*end;
|
||||
term = '\'';
|
||||
break;
|
||||
case '3':
|
||||
/* FALLTHROUGH */
|
||||
case '2':
|
||||
/* FALLTHROUGH */
|
||||
case '1':
|
||||
*sz = (*end)[-1] == 's' &&
|
||||
isdigit((unsigned char)(*end)[1]) ? 2 : 1;
|
||||
break;
|
||||
default:
|
||||
*sz = 1;
|
||||
break;
|
||||
@ -480,6 +490,8 @@ time2a(time_t t)
|
||||
int isz;
|
||||
|
||||
tm = localtime(&t);
|
||||
if (tm == NULL)
|
||||
return(NULL);
|
||||
|
||||
/*
|
||||
* Reserve space:
|
||||
|
12
mandoc.db.5
12
mandoc.db.5
@ -1,4 +1,4 @@
|
||||
.\" $Id: mandoc.db.5,v 1.2 2014/09/03 18:09:14 schwarze Exp $
|
||||
.\" $Id: mandoc.db.5,v 1.3 2014/12/30 21:34:57 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
@ -14,7 +14,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: September 3 2014 $
|
||||
.Dd $Mdocdate: December 30 2014 $
|
||||
.Dt MANDOC.DB 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -117,14 +117,14 @@ documented in
|
||||
The string found in those contexts.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /usr/share/mandoc.db -compact
|
||||
.It Pa /usr/share/mandoc.db
|
||||
.Bl -tag -width /usr/share/man/mandoc.db -compact
|
||||
.It Pa /usr/share/man/mandoc.db
|
||||
The manual page database for the base system.
|
||||
.It Pa /usr/X11R6/mandoc.db
|
||||
.It Pa /usr/X11R6/man/mandoc.db
|
||||
The same for the
|
||||
.Xr X 7
|
||||
Window System.
|
||||
.It Pa /usr/local/mandoc.db
|
||||
.It Pa /usr/local/man/mandoc.db
|
||||
The same for
|
||||
.Xr packages 7 .
|
||||
.El
|
||||
|
114
mandoc.h
114
mandoc.h
@ -1,7 +1,7 @@
|
||||
/* $Id: mandoc.h,v 1.176 2014/12/01 08:05:52 schwarze Exp $ */
|
||||
/* $Id: mandoc.h,v 1.201 2015/02/23 13:31:04 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -31,7 +31,7 @@ enum mandoclevel {
|
||||
MANDOCLEVEL_RESERVED,
|
||||
MANDOCLEVEL_WARNING, /* warnings: syntax, whitespace, etc. */
|
||||
MANDOCLEVEL_ERROR, /* input has been thrown away */
|
||||
MANDOCLEVEL_FATAL, /* input is borked */
|
||||
MANDOCLEVEL_UNSUPP, /* input needs unimplemented features */
|
||||
MANDOCLEVEL_BADARG, /* bad argument in invocation */
|
||||
MANDOCLEVEL_SYSERR, /* system error */
|
||||
MANDOCLEVEL_MAX
|
||||
@ -65,7 +65,11 @@ enum mandocerr {
|
||||
MANDOCERR_DOC_EMPTY, /* no document body */
|
||||
MANDOCERR_SEC_BEFORE, /* content before first section header: macro */
|
||||
MANDOCERR_NAMESEC_FIRST, /* first section is not NAME: Sh title */
|
||||
MANDOCERR_NAMESEC_BAD, /* bad NAME section contents: macro */
|
||||
MANDOCERR_NAMESEC_NONM, /* NAME section without name */
|
||||
MANDOCERR_NAMESEC_NOND, /* NAME section without description */
|
||||
MANDOCERR_NAMESEC_ND, /* description not at the end of NAME */
|
||||
MANDOCERR_NAMESEC_BAD, /* bad NAME section content: macro */
|
||||
MANDOCERR_ND_EMPTY, /* missing description line, using "" */
|
||||
MANDOCERR_SEC_ORDER, /* sections out of conventional order: Sh title */
|
||||
MANDOCERR_SEC_REP, /* duplicate section title: Sh title */
|
||||
MANDOCERR_SEC_MSEC, /* unexpected section: Sh title for ... only */
|
||||
@ -91,18 +95,22 @@ enum mandocerr {
|
||||
MANDOCERR_REQ_EMPTY, /* skipping empty request: request */
|
||||
MANDOCERR_COND_EMPTY, /* conditional request controls empty scope */
|
||||
MANDOCERR_MACRO_EMPTY, /* skipping empty macro: macro */
|
||||
MANDOCERR_BLK_EMPTY, /* empty block: macro */
|
||||
MANDOCERR_ARG_EMPTY, /* empty argument, using 0n: macro arg */
|
||||
MANDOCERR_ARGCWARN, /* argument count wrong */
|
||||
MANDOCERR_BD_NOTYPE, /* missing display type, using -ragged: Bd */
|
||||
MANDOCERR_BL_LATETYPE, /* list type is not the first argument: Bl arg */
|
||||
MANDOCERR_BL_NOWIDTH, /* missing -width in -tag list, using 8n */
|
||||
MANDOCERR_EX_NONAME, /* missing utility name, using "": Ex */
|
||||
MANDOCERR_FO_NOHEAD, /* missing function name, using "": Fo */
|
||||
MANDOCERR_IT_NOHEAD, /* empty head in list item: Bl -type It */
|
||||
MANDOCERR_IT_NOBODY, /* empty list item: Bl -type It */
|
||||
MANDOCERR_BF_NOFONT, /* missing font type, using \fR: Bf */
|
||||
MANDOCERR_BF_BADFONT, /* unknown font type, using \fR: Bf font */
|
||||
MANDOCERR_PF_SKIP, /* nothing follows prefix: Pf arg */
|
||||
MANDOCERR_RS_EMPTY, /* empty reference block: Rs */
|
||||
MANDOCERR_ARG_STD, /* missing -std argument, adding it: macro */
|
||||
MANDOCERR_OP_EMPTY, /* missing option string, using "": OP */
|
||||
MANDOCERR_UR_NOHEAD, /* missing resource identifier, using "": UR */
|
||||
MANDOCERR_EQN_NOBOX, /* missing eqn box, using "": op */
|
||||
|
||||
/* related to bad arguments */
|
||||
@ -112,12 +120,14 @@ enum mandocerr {
|
||||
MANDOCERR_BD_REP, /* skipping duplicate display type: Bd -type */
|
||||
MANDOCERR_BL_REP, /* skipping duplicate list type: Bl -type */
|
||||
MANDOCERR_BL_SKIPW, /* skipping -width argument: Bl -type */
|
||||
MANDOCERR_BL_COL, /* wrong number of cells */
|
||||
MANDOCERR_AT_BAD, /* unknown AT&T UNIX version: At version */
|
||||
MANDOCERR_FA_COMMA, /* comma in function argument: arg */
|
||||
MANDOCERR_FN_PAREN, /* parenthesis in function name: arg */
|
||||
MANDOCERR_RS_BAD, /* invalid content in Rs block: macro */
|
||||
MANDOCERR_SM_BAD, /* invalid Boolean argument: macro arg */
|
||||
MANDOCERR_FT_BAD, /* unknown font, skipping request: ft font */
|
||||
MANDOCERR_TR_ODD, /* odd number of characters in request: tr char */
|
||||
|
||||
/* related to plain text */
|
||||
MANDOCERR_FI_BLANK, /* blank line in fill mode, using .sp */
|
||||
@ -127,65 +137,61 @@ enum mandocerr {
|
||||
MANDOCERR_ESC_BAD, /* invalid escape sequence: esc */
|
||||
MANDOCERR_STR_UNDEF, /* undefined string, using "": name */
|
||||
|
||||
/* related to tables */
|
||||
MANDOCERR_TBLLAYOUT_SPAN, /* tbl line starts with span */
|
||||
MANDOCERR_TBLLAYOUT_DOWN, /* tbl column starts with span */
|
||||
MANDOCERR_TBLLAYOUT_VERT, /* skipping vertical bar in tbl layout */
|
||||
|
||||
MANDOCERR_ERROR, /* ===== start of errors ===== */
|
||||
|
||||
/* related to equations */
|
||||
MANDOCERR_EQNNSCOPE, /* unexpected equation scope closure*/
|
||||
MANDOCERR_EQNSCOPE, /* equation scope open on exit */
|
||||
MANDOCERR_EQNBADSCOPE, /* overlapping equation scopes */
|
||||
MANDOCERR_EQNEOF, /* unexpected end of equation */
|
||||
|
||||
/* related to tables */
|
||||
MANDOCERR_TBL, /* bad table syntax */
|
||||
MANDOCERR_TBLOPT, /* bad table option */
|
||||
MANDOCERR_TBLLAYOUT, /* bad table layout */
|
||||
MANDOCERR_TBLNOLAYOUT, /* no table layout cells specified */
|
||||
MANDOCERR_TBLNODATA, /* no table data cells specified */
|
||||
MANDOCERR_TBLIGNDATA, /* ignore data in cell */
|
||||
MANDOCERR_TBLBLOCK, /* data block still open */
|
||||
MANDOCERR_TBLEXTRADAT, /* ignoring extra data cells */
|
||||
MANDOCERR_TBLOPT_ALPHA, /* non-alphabetic character in tbl options */
|
||||
MANDOCERR_TBLOPT_BAD, /* skipping unknown tbl option: option */
|
||||
MANDOCERR_TBLOPT_NOARG, /* missing tbl option argument: option */
|
||||
MANDOCERR_TBLOPT_ARGSZ, /* wrong tbl option argument size: option */
|
||||
MANDOCERR_TBLLAYOUT_NONE, /* empty tbl layout */
|
||||
MANDOCERR_TBLLAYOUT_CHAR, /* invalid character in tbl layout: char */
|
||||
MANDOCERR_TBLLAYOUT_PAR, /* unmatched parenthesis in tbl layout */
|
||||
MANDOCERR_TBLDATA_NONE, /* tbl without any data cells */
|
||||
MANDOCERR_TBLDATA_SPAN, /* ignoring data in spanned tbl cell: data */
|
||||
MANDOCERR_TBLDATA_EXTRA, /* ignoring extra tbl data cells: data */
|
||||
MANDOCERR_TBLDATA_BLK, /* data block open at end of tbl: macro */
|
||||
|
||||
/* related to document structure and macros */
|
||||
MANDOCERR_FILE, /* cannot open file */
|
||||
MANDOCERR_ROFFLOOP, /* input stack limit exceeded, infinite loop? */
|
||||
MANDOCERR_BADCHAR, /* skipping bad character: number */
|
||||
MANDOCERR_CHAR_BAD, /* skipping bad character: number */
|
||||
MANDOCERR_MACRO, /* skipping unknown macro: macro */
|
||||
MANDOCERR_REQ_INSEC, /* skipping insecure request: request */
|
||||
MANDOCERR_IT_STRAY, /* skipping item outside list: It ... */
|
||||
MANDOCERR_TA_STRAY, /* skipping column outside column list: Ta */
|
||||
MANDOCERR_BLK_NOTOPEN, /* skipping end of block that is not open */
|
||||
MANDOCERR_RE_NOTOPEN, /* fewer RS blocks open, skipping: RE arg */
|
||||
MANDOCERR_BLK_BROKEN, /* inserting missing end of block: macro ... */
|
||||
MANDOCERR_BLK_NOEND, /* appending missing end of block: macro */
|
||||
|
||||
/* related to request and macro arguments */
|
||||
MANDOCERR_NAMESC, /* escaped character not allowed in a name: name */
|
||||
MANDOCERR_ARGCOUNT, /* argument count wrong */
|
||||
MANDOCERR_BD_FILE, /* NOT IMPLEMENTED: Bd -file */
|
||||
MANDOCERR_BL_NOTYPE, /* missing list type, using -item: Bl */
|
||||
MANDOCERR_NM_NONAME, /* missing manual name, using "": Nm */
|
||||
MANDOCERR_OS_UNAME, /* uname(3) system call failed, using UNKNOWN */
|
||||
MANDOCERR_ST_BAD, /* unknown standard specifier: St standard */
|
||||
MANDOCERR_IT_NONUM, /* skipping request without numeric argument */
|
||||
MANDOCERR_SO_PATH, /* NOT IMPLEMENTED: .so with absolute path or ".." */
|
||||
MANDOCERR_SO_FAIL, /* .so request failed */
|
||||
MANDOCERR_ARG_SKIP, /* skipping all arguments: macro args */
|
||||
MANDOCERR_ARG_EXCESS, /* skipping excess arguments: macro ... args */
|
||||
MANDOCERR_DIVZERO, /* divide by zero */
|
||||
|
||||
MANDOCERR_FATAL, /* ===== start of fatal errors ===== */
|
||||
MANDOCERR_UNSUPP, /* ===== start of unsupported features ===== */
|
||||
|
||||
MANDOCERR_TOOLARGE, /* input too large */
|
||||
MANDOCERR_SO_PATH, /* NOT IMPLEMENTED: .so with absolute path or ".." */
|
||||
MANDOCERR_SO_FAIL, /* .so request failed */
|
||||
|
||||
/* ===== system errors ===== */
|
||||
|
||||
MANDOCERR_SYSDUP, /* cannot dup file descriptor */
|
||||
MANDOCERR_SYSEXEC, /* cannot exec */
|
||||
MANDOCERR_SYSEXIT, /* gunzip failed with code */
|
||||
MANDOCERR_SYSFORK, /* cannot fork */
|
||||
MANDOCERR_SYSOPEN, /* cannot open file */
|
||||
MANDOCERR_SYSPIPE, /* cannot open pipe */
|
||||
MANDOCERR_SYSREAD, /* cannot read file */
|
||||
MANDOCERR_SYSSIG, /* gunzip died from signal */
|
||||
MANDOCERR_SYSSTAT, /* cannot stat file */
|
||||
MANDOCERR_SYSWAIT, /* wait failed */
|
||||
MANDOCERR_CHAR_UNSUPP, /* unsupported control character: number */
|
||||
MANDOCERR_REQ_UNSUPP, /* unsupported roff request: request */
|
||||
MANDOCERR_TBLOPT_EQN, /* eqn delim option in tbl: arg */
|
||||
MANDOCERR_TBLLAYOUT_MOD, /* unsupported tbl layout modifier: m */
|
||||
MANDOCERR_TBLMACRO, /* ignoring macro in table: macro */
|
||||
|
||||
MANDOCERR_MAX
|
||||
};
|
||||
@ -193,7 +199,6 @@ enum mandocerr {
|
||||
struct tbl_opts {
|
||||
char tab; /* cell-separator */
|
||||
char decimal; /* decimal point */
|
||||
int linesize;
|
||||
int opts;
|
||||
#define TBL_OPT_CENTRE (1 << 0)
|
||||
#define TBL_OPT_EXPAND (1 << 1)
|
||||
@ -202,19 +207,10 @@ struct tbl_opts {
|
||||
#define TBL_OPT_ALLBOX (1 << 4)
|
||||
#define TBL_OPT_NOKEEP (1 << 5)
|
||||
#define TBL_OPT_NOSPACE (1 << 6)
|
||||
#define TBL_OPT_NOWARN (1 << 7)
|
||||
int cols; /* number of columns */
|
||||
};
|
||||
|
||||
/*
|
||||
* The head of a table specifies all of its columns. When formatting a
|
||||
* tbl_span, iterate over these and plug in data from the tbl_span when
|
||||
* appropriate, using tbl_cell as a guide to placement.
|
||||
*/
|
||||
struct tbl_head {
|
||||
int ident; /* 0 <= unique id < cols */
|
||||
int vert; /* width of preceding vertical line */
|
||||
struct tbl_head *next;
|
||||
struct tbl_head *prev;
|
||||
int lvert; /* width of left vertical line */
|
||||
int rvert; /* width of right vertical line */
|
||||
};
|
||||
|
||||
enum tbl_cellt {
|
||||
@ -235,9 +231,10 @@ enum tbl_cellt {
|
||||
*/
|
||||
struct tbl_cell {
|
||||
struct tbl_cell *next;
|
||||
int vert; /* width of preceding vertical line */
|
||||
int vert; /* width of subsequent vertical line */
|
||||
enum tbl_cellt pos;
|
||||
size_t spacing;
|
||||
int col; /* column number, starting from 0 */
|
||||
int flags;
|
||||
#define TBL_CELL_TALIGN (1 << 0) /* t, T */
|
||||
#define TBL_CELL_BALIGN (1 << 1) /* d, D */
|
||||
@ -247,7 +244,6 @@ struct tbl_cell {
|
||||
#define TBL_CELL_UP (1 << 5) /* u, U */
|
||||
#define TBL_CELL_WIGN (1 << 6) /* z, Z */
|
||||
#define TBL_CELL_WMAX (1 << 7) /* x, X */
|
||||
struct tbl_head *head;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -257,7 +253,7 @@ struct tbl_row {
|
||||
struct tbl_row *next;
|
||||
struct tbl_cell *first;
|
||||
struct tbl_cell *last;
|
||||
int vert; /* trailing vertical line */
|
||||
int vert; /* width of left vertical line */
|
||||
};
|
||||
|
||||
enum tbl_datt {
|
||||
@ -292,16 +288,13 @@ enum tbl_spant {
|
||||
*/
|
||||
struct tbl_span {
|
||||
struct tbl_opts *opts;
|
||||
struct tbl_head *head;
|
||||
struct tbl_row *layout; /* layout row */
|
||||
struct tbl_dat *first;
|
||||
struct tbl_dat *last;
|
||||
int line; /* parse line */
|
||||
int flags;
|
||||
#define TBL_SPAN_FIRST (1 << 0)
|
||||
#define TBL_SPAN_LAST (1 << 1)
|
||||
enum tbl_spant pos;
|
||||
struct tbl_span *prev;
|
||||
struct tbl_span *next;
|
||||
int line; /* parse line */
|
||||
enum tbl_spant pos;
|
||||
};
|
||||
|
||||
enum eqn_boxt {
|
||||
@ -408,7 +401,8 @@ enum mandoc_esc {
|
||||
ESCAPE_NUMBERED, /* a numbered glyph */
|
||||
ESCAPE_UNICODE, /* a unicode codepoint */
|
||||
ESCAPE_NOSPACE, /* suppress space if the last on a line */
|
||||
ESCAPE_SKIPCHAR /* skip the next character */
|
||||
ESCAPE_SKIPCHAR, /* skip the next character */
|
||||
ESCAPE_OVERSTRIKE /* overstrike all chars in the argument */
|
||||
};
|
||||
|
||||
typedef void (*mandocmsg)(enum mandocerr, enum mandoclevel,
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $Id: mandoc_char.7,v 1.56 2013/12/26 17:23:42 schwarze Exp $
|
||||
.\" $Id: mandoc_char.7,v 1.59 2015/01/20 19:39:34 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2003 Jason McIntyre <jmc@openbsd.org>
|
||||
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
@ -16,7 +16,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: December 26 2013 $
|
||||
.Dd $Mdocdate: January 20 2015 $
|
||||
.Dt MANDOC_CHAR 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -210,7 +210,7 @@ Lines:
|
||||
.It \e(ba Ta \(ba Ta bar
|
||||
.It \e(br Ta \(br Ta box rule
|
||||
.It \e(ul Ta \(ul Ta underscore
|
||||
.It \e(rl Ta \(rl Ta overline
|
||||
.It \e(rn Ta \(rn Ta overline
|
||||
.It \e(bb Ta \(bb Ta broken bar
|
||||
.It \e(sl Ta \(sl Ta forward slash
|
||||
.It \e(rs Ta \(rs Ta backward slash
|
||||
@ -273,7 +273,7 @@ Quotes:
|
||||
.El
|
||||
.Pp
|
||||
Brackets:
|
||||
.Bl -column "xxbracketrightbpx" Rendered Description -offset indent -compact
|
||||
.Bl -column "xxbracketrightbtx" Rendered Description -offset indent -compact
|
||||
.It Em Input Ta Em Rendered Ta Em Description
|
||||
.It \e(lB Ta \(lB Ta left bracket
|
||||
.It \e(rB Ta \(rB Ta right bracket
|
||||
@ -284,30 +284,30 @@ Brackets:
|
||||
.It \e(bv Ta \(bv Ta brace extension
|
||||
.It \e[braceex] Ta \[braceex] Ta brace extension
|
||||
.It \e[bracketlefttp] Ta \[bracketlefttp] Ta top-left hooked bracket
|
||||
.It \e[bracketleftbp] Ta \[bracketleftbp] Ta bottom-left hooked bracket
|
||||
.It \e[bracketleftbt] Ta \[bracketleftbt] Ta bottom-left hooked bracket
|
||||
.It \e[bracketleftex] Ta \[bracketleftex] Ta left hooked bracket extension
|
||||
.It \e[bracketrighttp] Ta \[bracketrighttp] Ta top-right hooked bracket
|
||||
.It \e[bracketrightbp] Ta \[bracketrightbp] Ta bottom-right hooked bracket
|
||||
.It \e[bracketrightbt] Ta \[bracketrightbt] Ta bottom-right hooked bracket
|
||||
.It \e[bracketrightex] Ta \[bracketrightex] Ta right hooked bracket extension
|
||||
.It \e(lt Ta \(lt Ta top-left hooked brace
|
||||
.It \e[bracelefttp] Ta \[bracelefttp] Ta top-left hooked brace
|
||||
.It \e(lk Ta \(lk Ta mid-left hooked brace
|
||||
.It \e[braceleftmid] Ta \[braceleftmid] Ta mid-left hooked brace
|
||||
.It \e(lb Ta \(lb Ta bottom-left hooked brace
|
||||
.It \e[braceleftbp] Ta \[braceleftbp] Ta bottom-left hooked brace
|
||||
.It \e[braceleftbt] Ta \[braceleftbt] Ta bottom-left hooked brace
|
||||
.It \e[braceleftex] Ta \[braceleftex] Ta left hooked brace extension
|
||||
.It \e(rt Ta \(rt Ta top-left hooked brace
|
||||
.It \e[bracerighttp] Ta \[bracerighttp] Ta top-right hooked brace
|
||||
.It \e(rk Ta \(rk Ta mid-right hooked brace
|
||||
.It \e[bracerightmid] Ta \[bracerightmid] Ta mid-right hooked brace
|
||||
.It \e(rb Ta \(rb Ta bottom-right hooked brace
|
||||
.It \e[bracerightbp] Ta \[bracerightbp] Ta bottom-right hooked brace
|
||||
.It \e[bracerightbt] Ta \[bracerightbt] Ta bottom-right hooked brace
|
||||
.It \e[bracerightex] Ta \[bracerightex] Ta right hooked brace extension
|
||||
.It \e[parenlefttp] Ta \[parenlefttp] Ta top-left hooked parenthesis
|
||||
.It \e[parenleftbp] Ta \[parenleftbp] Ta bottom-left hooked parenthesis
|
||||
.It \e[parenleftbt] Ta \[parenleftbt] Ta bottom-left hooked parenthesis
|
||||
.It \e[parenleftex] Ta \[parenleftex] Ta left hooked parenthesis extension
|
||||
.It \e[parenrighttp] Ta \[parenrighttp] Ta top-right hooked parenthesis
|
||||
.It \e[parenrightbp] Ta \[parenrightbp] Ta bottom-right hooked parenthesis
|
||||
.It \e[parenrightbt] Ta \[parenrightbt] Ta bottom-right hooked parenthesis
|
||||
.It \e[parenrightex] Ta \[parenrightex] Ta right hooked parenthesis extension
|
||||
.El
|
||||
.Pp
|
||||
@ -352,7 +352,7 @@ Mathematical:
|
||||
.It \e(-+ Ta \(-+ Ta minus-plus
|
||||
.It \e(+- Ta \(+- Ta plus-minus
|
||||
.It \e[t+-] Ta \[t+-] Ta plus-minus (text)
|
||||
.It \e(pc Ta \(pc Ta centre-dot
|
||||
.It \e(pc Ta \(pc Ta center-dot
|
||||
.It \e(mu Ta \(mu Ta multiply
|
||||
.It \e[tmu] Ta \[tmu] Ta multiply (text)
|
||||
.It \e(c* Ta \(c* Ta circle-multiply
|
||||
@ -369,11 +369,11 @@ Mathematical:
|
||||
.It \e(!= Ta \(!= Ta not equal
|
||||
.It \e(== Ta \(== Ta equivalent
|
||||
.It \e(ne Ta \(ne Ta not equivalent
|
||||
.It \e(=~ Ta \(=~ Ta congruent
|
||||
.It \e(-~ Ta \(-~ Ta asymptotically congruent
|
||||
.It \e(ap Ta \(ap Ta asymptotically similar
|
||||
.It \e(~~ Ta \(~~ Ta approximately similar
|
||||
.It \e(~= Ta \(~= Ta approximately equal
|
||||
.It \e(ap Ta \(ap Ta tilde operator
|
||||
.It \e(|= Ta \(|= Ta asymptotically equal
|
||||
.It \e(=~ Ta \(=~ Ta approximately equal
|
||||
.It \e(~~ Ta \(~~ Ta almost equal
|
||||
.It \e(~= Ta \(~= Ta almost equal
|
||||
.It \e(pt Ta \(pt Ta proportionate
|
||||
.It \e(es Ta \(es Ta empty set
|
||||
.It \e(mo Ta \(mo Ta element
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $Id: mandoc_escape.3,v 1.2 2014/10/28 14:06:31 schwarze Exp $
|
||||
.\" $Id: mandoc_escape.3,v 1.3 2015/01/21 20:33:25 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
@ -14,14 +14,12 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: October 28 2014 $
|
||||
.Dd $Mdocdate: January 21 2015 $
|
||||
.Dt MANDOC_ESCAPE 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mandoc_escape
|
||||
.Nd parse roff escape sequences
|
||||
.Sh LIBRARY
|
||||
.Lb libmandoc
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In mandoc.h
|
||||
@ -119,8 +117,8 @@ in turn contain other escape sequences,
|
||||
for error detection internally by the
|
||||
.Xr roff 7
|
||||
parser part of the
|
||||
.Lb libmandoc ,
|
||||
see the file
|
||||
.Xr mandoc 3
|
||||
library, see the file
|
||||
.Pa roff.c ,
|
||||
.It
|
||||
above all externally by the
|
||||
@ -256,6 +254,10 @@ Such ASCII character escape sequences can be rendered using the function
|
||||
described in the
|
||||
.Xr mchars_alloc 3
|
||||
manual.
|
||||
.It Dv ESCAPE_OVERSTRIKE
|
||||
The escape sequence
|
||||
.Ic \eo
|
||||
followed by an argument delimited by an arbitrary character.
|
||||
.It Dv ESCAPE_IGNORE
|
||||
.Bl -bullet -width 2n
|
||||
.It
|
||||
@ -288,7 +290,6 @@ The escape sequences
|
||||
.Ic \eA ,
|
||||
.Ic \eb ,
|
||||
.Ic \eD ,
|
||||
.Ic \eo ,
|
||||
.Ic \eR ,
|
||||
.Ic \eX ,
|
||||
and
|
||||
|
@ -47,7 +47,7 @@ HTML formatters
|
||||
search tools
|
||||
.El
|
||||
.Pp
|
||||
Note that mere usage of an opaque type does
|
||||
Note that mere usage of an opaque struct type does
|
||||
.Em not
|
||||
require inclusion of the header where that type is defined.
|
||||
.Ss Parser interface
|
||||
@ -204,7 +204,11 @@ are included, the same file should not include any formatter headers.
|
||||
Requires
|
||||
.In sys/types.h
|
||||
for
|
||||
.Vt size_t .
|
||||
.Vt size_t
|
||||
and
|
||||
.Qq Pa mandoc.h
|
||||
for
|
||||
.Vt enum mandocerr .
|
||||
.Pp
|
||||
Provides
|
||||
.Vt enum rofferr ,
|
||||
@ -222,8 +226,7 @@ from
|
||||
.Pa roff.c
|
||||
for function prototypes.
|
||||
Uses the types
|
||||
.Vt enum mandocerr ,
|
||||
.Vt struct tbl_span ,
|
||||
.Vt struct tbl_span
|
||||
and
|
||||
.Vt struct eqn
|
||||
from
|
||||
|
68
mandocdb.c
68
mandocdb.c
@ -1,7 +1,7 @@
|
||||
/* $Id: mandocdb.c,v 1.179 2014/12/09 07:29:42 schwarze Exp $ */
|
||||
/* $Id: mandocdb.c,v 1.185 2015/02/27 16:22:09 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -350,7 +350,8 @@ mandocdb(int argc, char *argv[])
|
||||
|
||||
mpages_info.alloc = mlinks_info.alloc = hash_alloc;
|
||||
mpages_info.calloc = mlinks_info.calloc = hash_calloc;
|
||||
mpages_info.free = mlinks_info.free = hash_free;
|
||||
mpages_info.free = mlinks_info.free = hash_free;
|
||||
mpages_info.data = mlinks_info.data = NULL;
|
||||
|
||||
mpages_info.key_offset = offsetof(struct mpage, inodev);
|
||||
mlinks_info.key_offset = offsetof(struct mlink, file);
|
||||
@ -441,7 +442,7 @@ mandocdb(int argc, char *argv[])
|
||||
|
||||
exitcode = (int)MANDOCLEVEL_OK;
|
||||
mchars = mchars_alloc();
|
||||
mp = mparse_alloc(mparse_options, MANDOCLEVEL_FATAL, NULL,
|
||||
mp = mparse_alloc(mparse_options, MANDOCLEVEL_BADARG, NULL,
|
||||
mchars, NULL);
|
||||
ohash_init(&mpages, 6, &mpages_info);
|
||||
ohash_init(&mlinks, 6, &mlinks_info);
|
||||
@ -612,7 +613,11 @@ treescan(void)
|
||||
say(path, "&realpath");
|
||||
continue;
|
||||
}
|
||||
if (strstr(buf, basedir) != buf) {
|
||||
if (strstr(buf, basedir) != buf
|
||||
#ifdef HOMEBREWDIR
|
||||
&& strstr(buf, HOMEBREWDIR) != buf
|
||||
#endif
|
||||
) {
|
||||
if (warnings) say("",
|
||||
"%s: outside base directory", buf);
|
||||
continue;
|
||||
@ -667,7 +672,8 @@ treescan(void)
|
||||
say(path, "Skip pdf");
|
||||
continue;
|
||||
} else if ( ! use_all &&
|
||||
((FORM_SRC == dform && strcmp(fsec, dsec)) ||
|
||||
((FORM_SRC == dform &&
|
||||
strncmp(fsec, dsec, strlen(dsec))) ||
|
||||
(FORM_CAT == dform && strcmp(fsec, "0")))) {
|
||||
if (warnings)
|
||||
say(path, "Wrong filename suffix");
|
||||
@ -817,6 +823,10 @@ filescan(const char *file)
|
||||
start = buf;
|
||||
else if (strstr(buf, basedir) == buf)
|
||||
start = buf + strlen(basedir);
|
||||
#ifdef HOMEBREWDIR
|
||||
else if (strstr(buf, HOMEBREWDIR) == buf)
|
||||
start = buf;
|
||||
#endif
|
||||
else {
|
||||
exitcode = (int)MANDOCLEVEL_BADARG;
|
||||
say("", "%s: outside base directory", buf);
|
||||
@ -852,6 +862,7 @@ filescan(const char *file)
|
||||
if (strlcpy(mlink->file, start, sizeof(mlink->file)) >=
|
||||
sizeof(mlink->file)) {
|
||||
say(start, "Filename too long");
|
||||
free(mlink);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1100,11 +1111,11 @@ mpages_merge(struct mparse *mp)
|
||||
char *cp;
|
||||
int fd;
|
||||
unsigned int pslot;
|
||||
enum mandoclevel lvl;
|
||||
|
||||
str_info.alloc = hash_alloc;
|
||||
str_info.calloc = hash_calloc;
|
||||
str_info.free = hash_free;
|
||||
str_info.data = NULL;
|
||||
str_info.key_offset = offsetof(struct str, key);
|
||||
|
||||
if ( ! nodb)
|
||||
@ -1113,7 +1124,7 @@ mpages_merge(struct mparse *mp)
|
||||
mpage = ohash_first(&mpages, &pslot);
|
||||
while (mpage != NULL) {
|
||||
mlinks_undupe(mpage);
|
||||
if (mpage->mlinks == NULL) {
|
||||
if ((mlink = mpage->mlinks) == NULL) {
|
||||
mpage = ohash_next(&mpages, &pslot);
|
||||
continue;
|
||||
}
|
||||
@ -1126,22 +1137,19 @@ mpages_merge(struct mparse *mp)
|
||||
man = NULL;
|
||||
sodest = NULL;
|
||||
|
||||
mparse_open(mp, &fd, mpage->mlinks->file);
|
||||
mparse_open(mp, &fd, mlink->file);
|
||||
if (fd == -1) {
|
||||
say(mpage->mlinks->file, "&open");
|
||||
say(mlink->file, "&open");
|
||||
goto nextpage;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try interpreting the file as mdoc(7) or man(7)
|
||||
* source code, unless it is already known to be
|
||||
* formatted. Fall back to formatted mode.
|
||||
* Interpret the file as mdoc(7) or man(7) source
|
||||
* code, unless it is known to be formatted.
|
||||
*/
|
||||
if (mpage->mlinks->dform != FORM_CAT ||
|
||||
mpage->mlinks->fform != FORM_CAT) {
|
||||
lvl = mparse_readfd(mp, fd, mpage->mlinks->file);
|
||||
if (lvl < MANDOCLEVEL_FATAL)
|
||||
mparse_result(mp, &mdoc, &man, &sodest);
|
||||
if (mlink->dform != FORM_CAT || mlink->fform != FORM_CAT) {
|
||||
mparse_readfd(mp, fd, mlink->file);
|
||||
mparse_result(mp, &mdoc, &man, &sodest);
|
||||
}
|
||||
|
||||
if (sodest != NULL) {
|
||||
@ -1158,7 +1166,6 @@ mpages_merge(struct mparse *mp)
|
||||
/* The .so target exists. */
|
||||
|
||||
mpage_dest = mlink_dest->mpage;
|
||||
mlink = mpage->mlinks;
|
||||
while (1) {
|
||||
mlink->mpage = mpage_dest;
|
||||
|
||||
@ -1198,26 +1205,20 @@ mpages_merge(struct mparse *mp)
|
||||
mandoc_strdup(mdoc_meta(mdoc)->title);
|
||||
} else if (man != NULL) {
|
||||
mpage->form = FORM_SRC;
|
||||
mpage->sec =
|
||||
mandoc_strdup(man_meta(man)->msec);
|
||||
mpage->arch =
|
||||
mandoc_strdup(mpage->mlinks->arch);
|
||||
mpage->title =
|
||||
mandoc_strdup(man_meta(man)->title);
|
||||
mpage->sec = mandoc_strdup(man_meta(man)->msec);
|
||||
mpage->arch = mandoc_strdup(mlink->arch);
|
||||
mpage->title = mandoc_strdup(man_meta(man)->title);
|
||||
} else {
|
||||
mpage->form = FORM_CAT;
|
||||
mpage->sec =
|
||||
mandoc_strdup(mpage->mlinks->dsec);
|
||||
mpage->arch =
|
||||
mandoc_strdup(mpage->mlinks->arch);
|
||||
mpage->title =
|
||||
mandoc_strdup(mpage->mlinks->name);
|
||||
mpage->sec = mandoc_strdup(mlink->dsec);
|
||||
mpage->arch = mandoc_strdup(mlink->arch);
|
||||
mpage->title = mandoc_strdup(mlink->name);
|
||||
}
|
||||
putkey(mpage, mpage->sec, TYPE_sec);
|
||||
if (*mpage->arch != '\0')
|
||||
putkey(mpage, mpage->arch, TYPE_arch);
|
||||
|
||||
for (mlink = mpage->mlinks; mlink; mlink = mlink->next) {
|
||||
for ( ; mlink != NULL; mlink = mlink->next) {
|
||||
if ('\0' != *mlink->dsec)
|
||||
putkey(mpage, mlink->dsec, TYPE_sec);
|
||||
if ('\0' != *mlink->fsec)
|
||||
@ -1243,11 +1244,12 @@ mpages_merge(struct mparse *mp)
|
||||
mlink_check(mpage, mlink);
|
||||
|
||||
dbadd(mpage);
|
||||
mlink = mpage->mlinks;
|
||||
|
||||
nextpage:
|
||||
if (mparse_wait(mp) != MANDOCLEVEL_OK) {
|
||||
exitcode = (int)MANDOCLEVEL_SYSERR;
|
||||
say(mpage->mlinks->file, "&wait gunzip");
|
||||
say(mlink->file, "&wait gunzip");
|
||||
}
|
||||
ohash_delete(&strings);
|
||||
ohash_delete(&names);
|
||||
|
12
manpage.c
12
manpage.c
@ -1,4 +1,4 @@
|
||||
/* $Id: manpage.c,v 1.9 2014/08/17 03:24:47 schwarze Exp $ */
|
||||
/* $Id: manpage.c,v 1.10 2015/02/10 08:05:30 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -107,7 +107,7 @@ main(int argc, char *argv[])
|
||||
return(EXIT_FAILURE);
|
||||
|
||||
for (i = 0; i < sz; i++) {
|
||||
printf("%6zu %s: %s\n",
|
||||
printf("%6zu %s: %s\n",
|
||||
i + 1, res[i].names, res[i].output);
|
||||
free(res[i].names);
|
||||
free(res[i].output);
|
||||
@ -148,11 +148,11 @@ main(int argc, char *argv[])
|
||||
/* NOTREACHED */
|
||||
usage:
|
||||
fprintf(stderr, "usage: %s [-C conf] "
|
||||
"[-M paths] "
|
||||
"[-M paths] "
|
||||
"[-m paths] "
|
||||
"[-S arch] "
|
||||
"[-s section] "
|
||||
"expr ...\n",
|
||||
"expr ...\n",
|
||||
progname);
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
@ -174,9 +174,9 @@ show(const char *cmd, const char *file)
|
||||
} else if (pid > 0) {
|
||||
dup2(fds[0], STDIN_FILENO);
|
||||
close(fds[1]);
|
||||
cmd = NULL != getenv("MANPAGER") ?
|
||||
cmd = NULL != getenv("MANPAGER") ?
|
||||
getenv("MANPAGER") :
|
||||
(NULL != getenv("PAGER") ?
|
||||
(NULL != getenv("PAGER") ?
|
||||
getenv("PAGER") : "more");
|
||||
execlp(cmd, cmd, (char *)NULL);
|
||||
perror(cmd);
|
||||
|
103
mansearch.c
103
mansearch.c
@ -1,7 +1,7 @@
|
||||
/* $Id: mansearch.c,v 1.52 2014/12/06 01:23:24 schwarze Exp $ */
|
||||
/* $Id: mansearch.c,v 1.54 2015/02/27 16:02:10 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -24,6 +24,7 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <glob.h>
|
||||
#include <limits.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
@ -85,7 +86,8 @@ struct match {
|
||||
int form; /* bit field: formatted, zipped? */
|
||||
};
|
||||
|
||||
static void buildnames(struct manpage *, sqlite3 *,
|
||||
static void buildnames(const struct mansearch *,
|
||||
struct manpage *, sqlite3 *,
|
||||
sqlite3_stmt *, uint64_t,
|
||||
const char *, int form);
|
||||
static char *buildoutput(sqlite3 *, sqlite3_stmt *,
|
||||
@ -96,8 +98,6 @@ static void *hash_calloc(size_t, size_t, void *);
|
||||
static struct expr *exprcomp(const struct mansearch *,
|
||||
int, char *[]);
|
||||
static void exprfree(struct expr *);
|
||||
static struct expr *exprspec(struct expr *, uint64_t,
|
||||
const char *, const char *);
|
||||
static struct expr *exprterm(const struct mansearch *, char *, int);
|
||||
static int manpage_compare(const void *, const void *);
|
||||
static void sql_append(char **sql, size_t *sz,
|
||||
@ -343,14 +343,16 @@ mansearch(const struct mansearch *search,
|
||||
mpage->bits = mp->bits;
|
||||
mpage->sec = 10;
|
||||
mpage->form = mp->form;
|
||||
buildnames(mpage, db, s, mp->pageid,
|
||||
buildnames(search, mpage, db, s, mp->pageid,
|
||||
paths->paths[i], mp->form);
|
||||
mpage->output = TYPE_Nd & outbit ?
|
||||
mp->desc : outbit ?
|
||||
buildoutput(db, s2, mp->pageid, outbit) : NULL;
|
||||
|
||||
if (mpage->names != NULL) {
|
||||
mpage->output = TYPE_Nd & outbit ?
|
||||
mp->desc : outbit ?
|
||||
buildoutput(db, s2, mp->pageid, outbit) :
|
||||
NULL;
|
||||
cur++;
|
||||
}
|
||||
free(mp);
|
||||
cur++;
|
||||
}
|
||||
|
||||
sqlite3_finalize(s);
|
||||
@ -407,17 +409,19 @@ manpage_compare(const void *vp1, const void *vp2)
|
||||
}
|
||||
|
||||
static void
|
||||
buildnames(struct manpage *mpage, sqlite3 *db, sqlite3_stmt *s,
|
||||
buildnames(const struct mansearch *search, struct manpage *mpage,
|
||||
sqlite3 *db, sqlite3_stmt *s,
|
||||
uint64_t pageid, const char *path, int form)
|
||||
{
|
||||
char *newnames, *prevsec, *prevarch;
|
||||
glob_t globinfo;
|
||||
char *firstname, *newnames, *prevsec, *prevarch;
|
||||
const char *oldnames, *sep1, *name, *sec, *sep2, *arch, *fsec;
|
||||
size_t i;
|
||||
int c;
|
||||
int c, globres;
|
||||
|
||||
mpage->file = NULL;
|
||||
mpage->names = NULL;
|
||||
prevsec = prevarch = NULL;
|
||||
firstname = prevsec = prevarch = NULL;
|
||||
i = 1;
|
||||
SQL_BIND_INT64(db, s, i, pageid);
|
||||
while (SQLITE_ROW == (c = sqlite3_step(s))) {
|
||||
@ -432,10 +436,15 @@ buildnames(struct manpage *mpage, sqlite3 *db, sqlite3_stmt *s,
|
||||
sep1 = ", ";
|
||||
}
|
||||
|
||||
/* Fetch the next name. */
|
||||
/* Fetch the next name, rejecting sec/arch mismatches. */
|
||||
|
||||
sec = (const char *)sqlite3_column_text(s, 0);
|
||||
if (search->sec != NULL && strcasecmp(sec, search->sec))
|
||||
continue;
|
||||
arch = (const char *)sqlite3_column_text(s, 1);
|
||||
if (search->arch != NULL && *arch != '\0' &&
|
||||
strcasecmp(arch, search->arch))
|
||||
continue;
|
||||
name = (const char *)sqlite3_column_text(s, 2);
|
||||
|
||||
/* Remember the first section found. */
|
||||
@ -487,11 +496,34 @@ buildnames(struct manpage *mpage, sqlite3 *db, sqlite3_stmt *s,
|
||||
sep2 = *arch == '\0' ? "" : "/";
|
||||
mandoc_asprintf(&mpage->file, "%s/%s%s%s%s/%s.%s",
|
||||
path, sep1, sec, sep2, arch, name, fsec);
|
||||
if (access(mpage->file, R_OK) != -1)
|
||||
continue;
|
||||
|
||||
/* Handle unusual file name extensions. */
|
||||
|
||||
if (firstname == NULL)
|
||||
firstname = mpage->file;
|
||||
else
|
||||
free(mpage->file);
|
||||
mandoc_asprintf(&mpage->file, "%s/%s%s%s%s/%s.*",
|
||||
path, sep1, sec, sep2, arch, name);
|
||||
globres = glob(mpage->file, 0, NULL, &globinfo);
|
||||
free(mpage->file);
|
||||
mpage->file = globres ? NULL :
|
||||
mandoc_strdup(*globinfo.gl_pathv);
|
||||
globfree(&globinfo);
|
||||
}
|
||||
if (c != SQLITE_DONE)
|
||||
fprintf(stderr, "%s\n", sqlite3_errmsg(db));
|
||||
sqlite3_reset(s);
|
||||
|
||||
/* If none of the files is usable, use the first name. */
|
||||
|
||||
if (mpage->file == NULL)
|
||||
mpage->file = firstname;
|
||||
else if (mpage->file != firstname)
|
||||
free(firstname);
|
||||
|
||||
/* Append one final section to the names. */
|
||||
|
||||
if (prevsec != NULL) {
|
||||
@ -645,8 +677,7 @@ exprcomp(const struct mansearch *search, int argc, char *argv[])
|
||||
struct expr *first, *prev, *cur, *next;
|
||||
|
||||
first = cur = NULL;
|
||||
logic = igncase = toclose = 0;
|
||||
toopen = NULL != search->sec || NULL != search->arch;
|
||||
logic = igncase = toopen = toclose = 0;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (0 == strcmp("(", argv[i])) {
|
||||
@ -712,17 +743,8 @@ exprcomp(const struct mansearch *search, int argc, char *argv[])
|
||||
|
||||
toopen = logic = igncase = 0;
|
||||
}
|
||||
if (toopen || logic || igncase || toclose)
|
||||
goto fail;
|
||||
|
||||
if (NULL != search->sec || NULL != search->arch)
|
||||
cur->close++;
|
||||
if (NULL != search->arch)
|
||||
cur = exprspec(cur, TYPE_arch, search->arch, "^(%s|any)$");
|
||||
if (NULL != search->sec)
|
||||
exprspec(cur, TYPE_sec, search->sec, "^%s$");
|
||||
|
||||
return(first);
|
||||
if ( ! (toopen || logic || igncase || toclose))
|
||||
return(first);
|
||||
|
||||
fail:
|
||||
if (NULL != first)
|
||||
@ -730,29 +752,6 @@ exprcomp(const struct mansearch *search, int argc, char *argv[])
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static struct expr *
|
||||
exprspec(struct expr *cur, uint64_t key, const char *value,
|
||||
const char *format)
|
||||
{
|
||||
char errbuf[BUFSIZ];
|
||||
char *cp;
|
||||
int irc;
|
||||
|
||||
mandoc_asprintf(&cp, format, value);
|
||||
cur->next = mandoc_calloc(1, sizeof(struct expr));
|
||||
cur = cur->next;
|
||||
cur->and = 1;
|
||||
cur->bits = key;
|
||||
if (0 != (irc = regcomp(&cur->regexp, cp,
|
||||
REG_EXTENDED | REG_NOSUB | REG_ICASE))) {
|
||||
regerror(irc, &cur->regexp, errbuf, sizeof(errbuf));
|
||||
fprintf(stderr, "regcomp: %s\n", errbuf);
|
||||
cur->substr = value;
|
||||
}
|
||||
free(cp);
|
||||
return(cur);
|
||||
}
|
||||
|
||||
static struct expr *
|
||||
exprterm(const struct mansearch *search, char *buf, int cs)
|
||||
{
|
||||
|
212
mdoc.7
212
mdoc.7
@ -1,4 +1,4 @@
|
||||
.\" $Id: mdoc.7,v 1.245 2014/11/30 21:56:18 schwarze Exp $
|
||||
.\" $Id: mdoc.7,v 1.252 2015/02/23 13:31:04 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2010, 2011, 2013 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -15,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: November 30 2014 $
|
||||
.Dd $Mdocdate: February 23 2015 $
|
||||
.Dt MDOC 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -454,6 +454,7 @@ in the alphabetical
|
||||
.Op Fl compact
|
||||
.It Sx \&D1 Ta indented display (one line)
|
||||
.It Sx \&Dl Ta indented literal display (one line)
|
||||
.It Sx \&Ql Ta in-line literal display: Ql text
|
||||
.It Sx \&Bl , \&El Ta list block:
|
||||
.Fl Ar type
|
||||
.Op Fl width Ar val
|
||||
@ -528,7 +529,6 @@ in the alphabetical
|
||||
.It Sx \&Dq , \&Do , \&Dc Ta enclose in typographic double quotes: Dq text
|
||||
.It Sx \&Qq , \&Qo , \&Qc Ta enclose in typewriter double quotes: Qq text
|
||||
.It Sx \&Sq , \&So , \&Sc Ta enclose in single quotes: Sq text
|
||||
.It Sx \&Ql Ta single-quoted literal text: Ql text
|
||||
.It Sx \&Pq , \&Po , \&Pc Ta enclose in parentheses: Pq text
|
||||
.It Sx \&Bq , \&Bo , \&Bc Ta enclose in square brackets: Bq text
|
||||
.It Sx \&Brq , \&Bro , \&Brc Ta enclose in curly braces: Brq text
|
||||
@ -777,7 +777,7 @@ The
|
||||
must be one of the following:
|
||||
.Bl -tag -width 13n -offset indent
|
||||
.It Fl centered
|
||||
Produce one output line from each input line, and centre-justify each line.
|
||||
Produce one output line from each input line, and center-justify each line.
|
||||
Using this display type is not recommended; many
|
||||
.Nm
|
||||
implementations render it poorly.
|
||||
@ -822,7 +822,7 @@ which has no effect;
|
||||
.Cm right ,
|
||||
which justifies to the right margin; or
|
||||
.Cm center ,
|
||||
which aligns around an imagined centre axis.
|
||||
which aligns around an imagined center axis.
|
||||
.It
|
||||
A macro invocation, which selects a predefined width
|
||||
associated with that macro.
|
||||
@ -1256,7 +1256,9 @@ Examples:
|
||||
.Dl \&.Dl % mandoc mdoc.7 \e(ba less
|
||||
.Pp
|
||||
See also
|
||||
.Sx \&Ql ,
|
||||
.Sx \&Bd
|
||||
.Fl literal ,
|
||||
and
|
||||
.Sx \&D1 .
|
||||
.Ss \&Do
|
||||
@ -1314,38 +1316,26 @@ it should by convention be all caps.
|
||||
The manual section.
|
||||
This may be one of
|
||||
.Cm 1
|
||||
.Pq utilities ,
|
||||
.Pq General Commands ,
|
||||
.Cm 2
|
||||
.Pq system calls ,
|
||||
.Pq System Calls ,
|
||||
.Cm 3
|
||||
.Pq libraries ,
|
||||
.Pq Library Functions ,
|
||||
.Cm 3p
|
||||
.Pq Perl libraries ,
|
||||
.Pq Perl Library ,
|
||||
.Cm 4
|
||||
.Pq devices ,
|
||||
.Pq Device Drivers ,
|
||||
.Cm 5
|
||||
.Pq file formats ,
|
||||
.Pq File Formats ,
|
||||
.Cm 6
|
||||
.Pq games ,
|
||||
.Pq Games ,
|
||||
.Cm 7
|
||||
.Pq miscellaneous ,
|
||||
.Pq Miscellaneous Information ,
|
||||
.Cm 8
|
||||
.Pq system utilities ,
|
||||
.Cm 9
|
||||
.Pq kernel functions ,
|
||||
.Cm X11
|
||||
.Pq X Window System ,
|
||||
.Cm X11R6
|
||||
.Pq X Window System ,
|
||||
.Cm unass
|
||||
.Pq unassociated ,
|
||||
.Cm local
|
||||
.Pq local system ,
|
||||
.Cm draft
|
||||
.Pq draft manual ,
|
||||
.Pq System Manager's Manual ,
|
||||
or
|
||||
.Cm paper
|
||||
.Pq paper .
|
||||
.Cm 9
|
||||
.Pq Kernel Developer's Manual .
|
||||
It should correspond to the manual's filename suffix and defaults to
|
||||
the empty string if unspecified.
|
||||
.It Ar arch
|
||||
@ -1768,17 +1758,18 @@ is preferred for displaying code; the
|
||||
.Sx \&Ic
|
||||
macro is used when referring to specific instructions.
|
||||
.Ss \&In
|
||||
An
|
||||
.Dq include
|
||||
file.
|
||||
The name of an include file.
|
||||
This macro is most often used in section 2, 3, and 9 manual pages.
|
||||
.Pp
|
||||
When invoked as the first macro on an input line in the
|
||||
.Em SYNOPSIS
|
||||
section, the argument is displayed in angle brackets
|
||||
and preceded by
|
||||
.Dq #include ,
|
||||
.Qq #include ,
|
||||
and a blank line is inserted in front if there is a preceding
|
||||
function declaration.
|
||||
This is most often used in section 2, 3, and 9 manual pages.
|
||||
In other sections, it only encloses its argument in angle brackets
|
||||
and causes no line break.
|
||||
.Pp
|
||||
Examples:
|
||||
.Dl \&.In sys/types.h
|
||||
@ -1939,11 +1930,9 @@ Examples:
|
||||
.Dl \&.An Kristaps Dzonsons \&Aq \&Mt kristaps@bsd.lv
|
||||
.Ss \&Nd
|
||||
A one line description of the manual's content.
|
||||
This may only be invoked in the
|
||||
.Em SYNOPSIS
|
||||
section subsequent the
|
||||
.Sx \&Nm
|
||||
macro.
|
||||
This is the mandatory last macro of the
|
||||
.Em NAME
|
||||
section and not appropriate for other sections.
|
||||
.Pp
|
||||
Examples:
|
||||
.Dl Pf . Sx \&Nd mdoc language reference
|
||||
@ -2100,8 +2089,16 @@ Its syntax is as follows:
|
||||
The optional
|
||||
.Ar system
|
||||
parameter specifies the relevant operating system or environment.
|
||||
Left unspecified, it defaults to the local operating system version.
|
||||
This is the suggested form.
|
||||
It is suggested to leave it unspecified, in which case
|
||||
.Xr mandoc 1
|
||||
uses its
|
||||
.Fl Ios
|
||||
argument, or, if that isn't specified either,
|
||||
.Fa sysname
|
||||
and
|
||||
.Fa release
|
||||
as returned by
|
||||
.Xr uname 3 .
|
||||
.Pp
|
||||
Examples:
|
||||
.Dl \&.Os
|
||||
@ -2205,11 +2202,21 @@ See also
|
||||
Close quoted context opened by
|
||||
.Sx \&Qo .
|
||||
.Ss \&Ql
|
||||
Format a single-quoted literal.
|
||||
In-line literal display.
|
||||
This can for example be used for complete command invocations and
|
||||
for multi-word code fragments when more specific markup is not
|
||||
appropriate and an indented display is not desired.
|
||||
While
|
||||
.Xr mandoc 1
|
||||
always encloses the arguments in single quotes, other formatters
|
||||
usually omit the quotes on non-terminal output devices when the
|
||||
arguments have three or more characters.
|
||||
.Pp
|
||||
See also
|
||||
.Sx \&Qq
|
||||
.Sx \&Dl
|
||||
and
|
||||
.Sx \&Sq .
|
||||
.Sx \&Bd
|
||||
.Fl literal .
|
||||
.Ss \&Qo
|
||||
Multi-line version of
|
||||
.Sx \&Qq .
|
||||
@ -3125,50 +3132,13 @@ Manually switching the font using the
|
||||
font escape sequences is never required.
|
||||
.Sh COMPATIBILITY
|
||||
This section provides an incomplete list of compatibility issues
|
||||
between mandoc and other troff implementations, at this time limited
|
||||
to GNU troff
|
||||
between mandoc and GNU troff
|
||||
.Pq Qq groff .
|
||||
The term
|
||||
.Qq historic groff
|
||||
refers to groff versions before 1.17,
|
||||
which featured a significant update of the
|
||||
.Pa doc.tmac
|
||||
file.
|
||||
.Pp
|
||||
Heirloom troff, the other significant troff implementation accepting
|
||||
\-mdoc, is similar to historic groff.
|
||||
.Pp
|
||||
The following problematic behaviour is found in groff:
|
||||
.ds hist (Historic groff only.)
|
||||
.Pp
|
||||
.Bl -dash -compact
|
||||
.It
|
||||
Display macros
|
||||
.Po
|
||||
.Sx \&Bd ,
|
||||
.Sx \&Dl ,
|
||||
and
|
||||
.Sx \&D1
|
||||
.Pc
|
||||
may not be nested.
|
||||
\*[hist]
|
||||
.It
|
||||
.Sx \&At
|
||||
with unknown arguments produces no output at all.
|
||||
\*[hist]
|
||||
Newer groff and mandoc print
|
||||
.Qq AT&T UNIX
|
||||
and the arguments.
|
||||
.It
|
||||
.Sx \&Bl Fl column
|
||||
does not recognise trailing punctuation characters when they immediately
|
||||
precede tabulator characters, but treats them as normal text and
|
||||
outputs a space before them.
|
||||
.It
|
||||
.Sx \&Bd Fl ragged compact
|
||||
does not start a new line.
|
||||
\*[hist]
|
||||
.It
|
||||
.Sx \&Dd
|
||||
with non-standard arguments behaves very strangely.
|
||||
When there are three arguments, they are printed verbatim.
|
||||
@ -3177,53 +3147,6 @@ but without any arguments the string
|
||||
.Dq Epoch
|
||||
is printed.
|
||||
.It
|
||||
.Sx \&Fl
|
||||
does not print a dash for an empty argument.
|
||||
\*[hist]
|
||||
.It
|
||||
.Sx \&Fn
|
||||
does not start a new line unless invoked as the line macro in the
|
||||
.Em SYNOPSIS
|
||||
section.
|
||||
\*[hist]
|
||||
.It
|
||||
.Sx \&Fo
|
||||
with
|
||||
.Pf non- Sx \&Fa
|
||||
children causes inconsistent spacing between arguments.
|
||||
In mandoc, a single space is always inserted between arguments.
|
||||
.It
|
||||
.Sx \&Ft
|
||||
in the
|
||||
.Em SYNOPSIS
|
||||
causes inconsistent vertical spacing, depending on whether a prior
|
||||
.Sx \&Fn
|
||||
has been invoked.
|
||||
See
|
||||
.Sx \&Ft
|
||||
and
|
||||
.Sx \&Fn
|
||||
for the normalised behaviour in mandoc.
|
||||
.It
|
||||
.Sx \&In
|
||||
ignores additional arguments and is not treated specially in the
|
||||
.Em SYNOPSIS .
|
||||
\*[hist]
|
||||
.It
|
||||
.Sx \&It
|
||||
sometimes requires a
|
||||
.Fl nested
|
||||
flag.
|
||||
\*[hist]
|
||||
In new groff and mandoc, any list may be nested by default and
|
||||
.Fl enum
|
||||
lists will restart the sequence only for the sub-list.
|
||||
.It
|
||||
.Sx \&Li
|
||||
followed by a delimiter is incorrectly used in some manuals
|
||||
instead of properly quoting that character, which sometimes works with
|
||||
historic groff.
|
||||
.It
|
||||
.Sx \&Lk
|
||||
only accepts a single link-name argument; the remainder is misformatted.
|
||||
.It
|
||||
@ -3237,19 +3160,6 @@ can only be called by other macros, but not at the beginning of a line.
|
||||
.Sx \&%C
|
||||
is not implemented (up to and including groff-1.22.2).
|
||||
.It
|
||||
Historic groff only allows up to eight or nine arguments per macro input
|
||||
line, depending on the exact situation.
|
||||
Providing more arguments causes garbled output.
|
||||
The number of arguments on one input line is not limited with mandoc.
|
||||
.It
|
||||
Historic groff has many un-callable macros.
|
||||
Most of these (excluding some block-level macros) are callable
|
||||
in new groff and mandoc.
|
||||
.It
|
||||
.Sq \(ba
|
||||
(vertical bar) is not fully supported as a delimiter.
|
||||
\*[hist]
|
||||
.It
|
||||
.Sq \ef
|
||||
.Pq font face
|
||||
and
|
||||
@ -3267,13 +3177,27 @@ The following features are unimplemented in mandoc:
|
||||
.Bl -dash -compact
|
||||
.It
|
||||
.Sx \&Bd
|
||||
.Fl file Ar file .
|
||||
.Fl file Ar file
|
||||
is unsupported for security reasons.
|
||||
.It
|
||||
.Sx \&Bd
|
||||
.Fl filled
|
||||
does not adjust the right margin, but is an alias for
|
||||
.Sx \&Bd
|
||||
.Fl ragged .
|
||||
.It
|
||||
.Sx \&Bd
|
||||
.Fl literal
|
||||
does not use a literal font, but is an alias for
|
||||
.Sx \&Bd
|
||||
.Fl unfilled .
|
||||
.It
|
||||
.Sx \&Bd
|
||||
.Fl offset Cm center
|
||||
and
|
||||
.Fl offset Cm right .
|
||||
Groff does not implement centred and flush-right rendering either,
|
||||
.Fl offset Cm right
|
||||
don't work.
|
||||
Groff does not implement centered and flush-right rendering either,
|
||||
but produces large indentations.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
|
23
mdoc.c
23
mdoc.c
@ -1,7 +1,7 @@
|
||||
/* $Id: mdoc.c,v 1.233 2014/11/28 06:27:05 schwarze Exp $ */
|
||||
/* $Id: mdoc.c,v 1.238 2015/02/12 13:00:52 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -190,12 +190,11 @@ mdoc_alloc(struct roff *roff, struct mparse *parse,
|
||||
return(p);
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
mdoc_endparse(struct mdoc *mdoc)
|
||||
{
|
||||
|
||||
mdoc_macroend(mdoc);
|
||||
return(1);
|
||||
}
|
||||
|
||||
void
|
||||
@ -364,7 +363,6 @@ node_alloc(struct mdoc *mdoc, int line, int pos,
|
||||
p->sec = mdoc->lastsec;
|
||||
p->line = line;
|
||||
p->pos = pos;
|
||||
p->lastline = line;
|
||||
p->tok = tok;
|
||||
p->type = type;
|
||||
|
||||
@ -415,18 +413,21 @@ mdoc_body_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok)
|
||||
return(p);
|
||||
}
|
||||
|
||||
void
|
||||
struct mdoc_node *
|
||||
mdoc_endbody_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok,
|
||||
struct mdoc_node *body, enum mdoc_endbody end)
|
||||
{
|
||||
struct mdoc_node *p;
|
||||
|
||||
body->flags |= MDOC_ENDED;
|
||||
body->parent->flags |= MDOC_ENDED;
|
||||
p = node_alloc(mdoc, line, pos, tok, MDOC_BODY);
|
||||
p->pending = body;
|
||||
p->body = body;
|
||||
p->norm = body->norm;
|
||||
p->end = end;
|
||||
node_append(mdoc, p);
|
||||
mdoc->next = MDOC_NEXT_SIBLING;
|
||||
return(p);
|
||||
}
|
||||
|
||||
struct mdoc_node *
|
||||
@ -600,8 +601,8 @@ mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs)
|
||||
* process within its context in the normal way).
|
||||
*/
|
||||
|
||||
if (MDOC_Bl == n->tok && MDOC_BODY == n->type &&
|
||||
LIST_column == n->norm->Bl.type) {
|
||||
if (n->tok == MDOC_Bl && n->type == MDOC_BODY &&
|
||||
n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) {
|
||||
/* `Bl' is open without any children. */
|
||||
mdoc->flags |= MDOC_FREECOL;
|
||||
mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf);
|
||||
@ -777,8 +778,8 @@ mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs)
|
||||
* context around the parsed macro.
|
||||
*/
|
||||
|
||||
if (MDOC_Bl == n->tok && MDOC_BODY == n->type &&
|
||||
LIST_column == n->norm->Bl.type) {
|
||||
if (n->tok == MDOC_Bl && n->type == MDOC_BODY &&
|
||||
n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) {
|
||||
mdoc->flags |= MDOC_FREECOL;
|
||||
mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf);
|
||||
return(1);
|
||||
|
12
mdoc.h
12
mdoc.h
@ -1,6 +1,7 @@
|
||||
/* $Id: mdoc.h,v 1.132 2014/12/01 04:05:32 schwarze Exp $ */
|
||||
/* $Id: mdoc.h,v 1.136 2015/02/12 12:24:33 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -352,25 +353,24 @@ struct mdoc_node {
|
||||
int nchild; /* number children */
|
||||
int line; /* parse line */
|
||||
int pos; /* parse column */
|
||||
int lastline; /* the node ends on this line */
|
||||
enum mdoct tok; /* tok or MDOC__MAX if none */
|
||||
int flags;
|
||||
#define MDOC_VALID (1 << 0) /* has been validated */
|
||||
#define MDOC_ENDED (1 << 1) /* gone past body end mark */
|
||||
#define MDOC_EOS (1 << 2) /* at sentence boundary */
|
||||
#define MDOC_LINE (1 << 3) /* first macro/text on line */
|
||||
#define MDOC_SYNPRETTY (1 << 4) /* SYNOPSIS-style formatting */
|
||||
#define MDOC_ENDED (1 << 5) /* rendering has been ended */
|
||||
#define MDOC_BROKEN (1 << 5) /* must validate parent when ending */
|
||||
#define MDOC_DELIMO (1 << 6)
|
||||
#define MDOC_DELIMC (1 << 7)
|
||||
enum mdoc_type type; /* AST node type */
|
||||
enum mdoc_sec sec; /* current named section */
|
||||
union mdoc_data *norm; /* normalised args */
|
||||
const void *prev_font; /* before entering this node */
|
||||
int prev_font; /* before entering this node */
|
||||
/* FIXME: these can be union'd to shave a few bytes. */
|
||||
struct mdoc_arg *args; /* BLOCK/ELEM */
|
||||
struct mdoc_node *pending; /* BLOCK */
|
||||
struct mdoc_node *head; /* BLOCK */
|
||||
struct mdoc_node *body; /* BLOCK */
|
||||
struct mdoc_node *body; /* BLOCK/ENDBODY */
|
||||
struct mdoc_node *tail; /* BLOCK */
|
||||
char *string; /* TEXT */
|
||||
const struct tbl_span *span; /* TBL */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD$ */
|
||||
/* $Id: mdoc_argv.c,v 1.100 2015/02/04 18:59:45 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -339,7 +339,7 @@ mdoc_argv(struct mdoc *mdoc, int line, enum mdoct tok,
|
||||
/* Parse the arguments of the flag. */
|
||||
|
||||
tmpv.line = line;
|
||||
tmpv.pos = ipos;
|
||||
tmpv.pos = *pos;
|
||||
tmpv.sz = 0;
|
||||
tmpv.value = NULL;
|
||||
|
||||
|
115
mdoc_html.c
115
mdoc_html.c
@ -1,7 +1,7 @@
|
||||
/* $Id: mdoc_html.c,v 1.216 2014/12/02 10:08:06 schwarze Exp $ */
|
||||
/* $Id: mdoc_html.c,v 1.225 2015/02/12 12:24:33 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -35,7 +35,7 @@
|
||||
#define INDENT 5
|
||||
|
||||
#define MDOC_ARGS const struct mdoc_meta *meta, \
|
||||
const struct mdoc_node *n, \
|
||||
struct mdoc_node *n, \
|
||||
struct html *h
|
||||
|
||||
#ifndef MIN
|
||||
@ -81,6 +81,8 @@ static int mdoc_fl_pre(MDOC_ARGS);
|
||||
static int mdoc_fn_pre(MDOC_ARGS);
|
||||
static int mdoc_ft_pre(MDOC_ARGS);
|
||||
static int mdoc_em_pre(MDOC_ARGS);
|
||||
static void mdoc_eo_post(MDOC_ARGS);
|
||||
static int mdoc_eo_pre(MDOC_ARGS);
|
||||
static int mdoc_er_pre(MDOC_ARGS);
|
||||
static int mdoc_ev_pre(MDOC_ARGS);
|
||||
static int mdoc_ex_pre(MDOC_ARGS);
|
||||
@ -189,7 +191,7 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = {
|
||||
{NULL, NULL}, /* Ec */ /* FIXME: no space */
|
||||
{NULL, NULL}, /* Ef */
|
||||
{mdoc_em_pre, NULL}, /* Em */
|
||||
{mdoc_quote_pre, mdoc_quote_post}, /* Eo */
|
||||
{mdoc_eo_pre, mdoc_eo_post}, /* Eo */
|
||||
{mdoc_xx_pre, NULL}, /* Fx */
|
||||
{mdoc_ms_pre, NULL}, /* Ms */
|
||||
{mdoc_no_pre, NULL}, /* No */
|
||||
@ -265,7 +267,7 @@ void
|
||||
html_mdoc(void *arg, const struct mdoc *mdoc)
|
||||
{
|
||||
|
||||
print_mdoc(mdoc_meta(mdoc), mdoc_node(mdoc),
|
||||
print_mdoc(mdoc_meta(mdoc), mdoc_node(mdoc)->child,
|
||||
(struct html *)arg);
|
||||
putchar('\n');
|
||||
}
|
||||
@ -279,10 +281,11 @@ static void
|
||||
a2width(const char *p, struct roffsu *su)
|
||||
{
|
||||
|
||||
if ( ! a2roffsu(p, su, SCALE_MAX)) {
|
||||
if (a2roffsu(p, su, SCALE_MAX) < 2) {
|
||||
su->unit = SCALE_EN;
|
||||
su->scale = html_strlen(p);
|
||||
}
|
||||
} else if (su->scale < 0.0)
|
||||
su->scale = 0.0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -370,9 +373,10 @@ static void
|
||||
print_mdoc_nodelist(MDOC_ARGS)
|
||||
{
|
||||
|
||||
print_mdoc_node(meta, n, h);
|
||||
if (n->next)
|
||||
print_mdoc_nodelist(meta, n->next, h);
|
||||
while (n != NULL) {
|
||||
print_mdoc_node(meta, n, h);
|
||||
n = n->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -383,6 +387,7 @@ print_mdoc_node(MDOC_ARGS)
|
||||
|
||||
child = 1;
|
||||
t = h->tags.head;
|
||||
n->flags &= ~MDOC_ENDED;
|
||||
|
||||
switch (n->type) {
|
||||
case MDOC_ROOT:
|
||||
@ -432,12 +437,9 @@ print_mdoc_node(MDOC_ARGS)
|
||||
break;
|
||||
}
|
||||
|
||||
if (HTML_KEEP & h->flags) {
|
||||
if (n->prev ? (n->prev->lastline != n->line) :
|
||||
(n->parent && n->parent->line != n->line)) {
|
||||
h->flags &= ~HTML_KEEP;
|
||||
h->flags |= HTML_PREKEEP;
|
||||
}
|
||||
if (h->flags & HTML_KEEP && n->flags & MDOC_LINE) {
|
||||
h->flags &= ~HTML_KEEP;
|
||||
h->flags |= HTML_PREKEEP;
|
||||
}
|
||||
|
||||
if (child && n->child)
|
||||
@ -456,7 +458,7 @@ print_mdoc_node(MDOC_ARGS)
|
||||
break;
|
||||
(*mdocs[n->tok].post)(meta, n, h);
|
||||
if (n->end != ENDBODY_NOT)
|
||||
n->pending->flags |= MDOC_ENDED;
|
||||
n->body->flags |= MDOC_ENDED;
|
||||
if (n->end == ENDBODY_NOSPACE)
|
||||
h->flags |= HTML_NOSPACE;
|
||||
break;
|
||||
@ -1121,7 +1123,7 @@ mdoc_bd_pre(MDOC_ARGS)
|
||||
{
|
||||
struct htmlpair tag[2];
|
||||
int comp, sv;
|
||||
const struct mdoc_node *nn;
|
||||
struct mdoc_node *nn;
|
||||
struct roffsu su;
|
||||
|
||||
if (MDOC_HEAD == n->type)
|
||||
@ -1252,9 +1254,6 @@ mdoc_an_pre(MDOC_ARGS)
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (n->child == NULL)
|
||||
return(0);
|
||||
|
||||
if (h->flags & HTML_SPLIT)
|
||||
print_otag(h, TAG_BR, 0, NULL);
|
||||
|
||||
@ -1566,9 +1565,12 @@ mdoc_sp_pre(MDOC_ARGS)
|
||||
SCALE_VS_INIT(&su, 1);
|
||||
|
||||
if (MDOC_sp == n->tok) {
|
||||
if (NULL != (n = n->child))
|
||||
if (NULL != (n = n->child)) {
|
||||
if ( ! a2roffsu(n->string, &su, SCALE_VS))
|
||||
SCALE_VS_INIT(&su, atoi(n->string));
|
||||
su.scale = 1.0;
|
||||
else if (su.scale < 0.0)
|
||||
su.scale = 0.0;
|
||||
}
|
||||
} else
|
||||
su.scale = 0.0;
|
||||
|
||||
@ -2080,8 +2082,8 @@ mdoc_quote_pre(MDOC_ARGS)
|
||||
case MDOC_Ao:
|
||||
/* FALLTHROUGH */
|
||||
case MDOC_Aq:
|
||||
print_text(h, n->parent->prev != NULL &&
|
||||
n->parent->prev->tok == MDOC_An ? "<" : "\\(la");
|
||||
print_text(h, n->nchild == 1 &&
|
||||
n->child->tok == MDOC_Mt ? "<" : "\\(la");
|
||||
break;
|
||||
case MDOC_Bro:
|
||||
/* FALLTHROUGH */
|
||||
@ -2107,8 +2109,6 @@ mdoc_quote_pre(MDOC_ARGS)
|
||||
return(1);
|
||||
print_text(h, n->norm->Es->child->string);
|
||||
break;
|
||||
case MDOC_Eo:
|
||||
break;
|
||||
case MDOC_Do:
|
||||
/* FALLTHROUGH */
|
||||
case MDOC_Dq:
|
||||
@ -2150,16 +2150,14 @@ mdoc_quote_post(MDOC_ARGS)
|
||||
if (n->type != MDOC_BODY && n->type != MDOC_ELEM)
|
||||
return;
|
||||
|
||||
if ( ! (n->tok == MDOC_En ||
|
||||
(n->tok == MDOC_Eo && n->end == ENDBODY_SPACE)))
|
||||
h->flags |= HTML_NOSPACE;
|
||||
h->flags |= HTML_NOSPACE;
|
||||
|
||||
switch (n->tok) {
|
||||
case MDOC_Ao:
|
||||
/* FALLTHROUGH */
|
||||
case MDOC_Aq:
|
||||
print_text(h, n->parent->prev != NULL &&
|
||||
n->parent->prev->tok == MDOC_An ? ">" : "\\(ra");
|
||||
print_text(h, n->nchild == 1 &&
|
||||
n->child->tok == MDOC_Mt ? ">" : "\\(ra");
|
||||
break;
|
||||
case MDOC_Bro:
|
||||
/* FALLTHROUGH */
|
||||
@ -2176,14 +2174,12 @@ mdoc_quote_post(MDOC_ARGS)
|
||||
print_text(h, "\\(rB");
|
||||
break;
|
||||
case MDOC_En:
|
||||
if (NULL != n->norm->Es &&
|
||||
NULL != n->norm->Es->child &&
|
||||
NULL != n->norm->Es->child->next) {
|
||||
h->flags |= HTML_NOSPACE;
|
||||
if (n->norm->Es == NULL ||
|
||||
n->norm->Es->child == NULL ||
|
||||
n->norm->Es->child->next == NULL)
|
||||
h->flags &= ~HTML_NOSPACE;
|
||||
else
|
||||
print_text(h, n->norm->Es->child->next->string);
|
||||
}
|
||||
break;
|
||||
case MDOC_Eo:
|
||||
break;
|
||||
case MDOC_Qo:
|
||||
/* FALLTHROUGH */
|
||||
@ -2211,3 +2207,44 @@ mdoc_quote_post(MDOC_ARGS)
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mdoc_eo_pre(MDOC_ARGS)
|
||||
{
|
||||
|
||||
if (n->type != MDOC_BODY)
|
||||
return(1);
|
||||
|
||||
if (n->end == ENDBODY_NOT &&
|
||||
n->parent->head->child == NULL &&
|
||||
n->child != NULL &&
|
||||
n->child->end != ENDBODY_NOT)
|
||||
print_text(h, "\\&");
|
||||
else if (n->end != ENDBODY_NOT ? n->child != NULL :
|
||||
n->parent->head->child != NULL && (n->child != NULL ||
|
||||
(n->parent->tail != NULL && n->parent->tail->child != NULL)))
|
||||
h->flags |= HTML_NOSPACE;
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void
|
||||
mdoc_eo_post(MDOC_ARGS)
|
||||
{
|
||||
int body, tail;
|
||||
|
||||
if (n->type != MDOC_BODY)
|
||||
return;
|
||||
|
||||
if (n->end != ENDBODY_NOT) {
|
||||
h->flags &= ~HTML_NOSPACE;
|
||||
return;
|
||||
}
|
||||
|
||||
body = n->child != NULL || n->parent->head->child != NULL;
|
||||
tail = n->parent->tail != NULL && n->parent->tail->child != NULL;
|
||||
|
||||
if (body && tail)
|
||||
h->flags |= HTML_NOSPACE;
|
||||
else if ( ! tail)
|
||||
h->flags &= ~HTML_NOSPACE;
|
||||
}
|
||||
|
756
mdoc_macro.c
756
mdoc_macro.c
File diff suppressed because it is too large
Load Diff
131
mdoc_man.c
131
mdoc_man.c
@ -1,6 +1,6 @@
|
||||
/* $Id: mdoc_man.c,v 1.77 2014/11/30 05:29:00 schwarze Exp $ */
|
||||
/* $Id: mdoc_man.c,v 1.88 2015/02/17 20:37:17 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -29,8 +29,7 @@
|
||||
#include "mdoc.h"
|
||||
#include "main.h"
|
||||
|
||||
#define DECL_ARGS const struct mdoc_meta *meta, \
|
||||
const struct mdoc_node *n
|
||||
#define DECL_ARGS const struct mdoc_meta *meta, struct mdoc_node *n
|
||||
|
||||
struct manact {
|
||||
int (*cond)(DECL_ARGS); /* DON'T run actions */
|
||||
@ -116,8 +115,8 @@ static void print_word(const char *);
|
||||
static void print_line(const char *, int);
|
||||
static void print_block(const char *, int);
|
||||
static void print_offs(const char *, int);
|
||||
static void print_width(const char *,
|
||||
const struct mdoc_node *, size_t);
|
||||
static void print_width(const struct mdoc_bl *,
|
||||
const struct mdoc_node *);
|
||||
static void print_count(int *);
|
||||
static void print_node(DECL_ARGS);
|
||||
|
||||
@ -186,8 +185,8 @@ static const struct manact manacts[MDOC_MAX + 1] = {
|
||||
{ NULL, pre_bx, NULL, NULL, NULL }, /* Bx */
|
||||
{ NULL, pre_skip, NULL, NULL, NULL }, /* Db */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Dc */
|
||||
{ cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Do */
|
||||
{ cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Dq */
|
||||
{ cond_body, pre_enc, post_enc, "\\(Lq", "\\(Rq" }, /* Do */
|
||||
{ cond_body, pre_enc, post_enc, "\\(Lq", "\\(Rq" }, /* Dq */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Ec */
|
||||
{ NULL, NULL, NULL, NULL, NULL }, /* Ef */
|
||||
{ NULL, pre_em, post_font, NULL, NULL }, /* Em */
|
||||
@ -265,7 +264,7 @@ static int outflags;
|
||||
|
||||
#define BL_STACK_MAX 32
|
||||
|
||||
static size_t Bl_stack[BL_STACK_MAX]; /* offsets [chars] */
|
||||
static int Bl_stack[BL_STACK_MAX]; /* offsets [chars] */
|
||||
static int Bl_stack_post[BL_STACK_MAX]; /* add final .RE */
|
||||
static int Bl_stack_len; /* number of nested Bl blocks */
|
||||
static int TPremain; /* characters before tag is full */
|
||||
@ -423,7 +422,7 @@ print_offs(const char *v, int keywords)
|
||||
{
|
||||
char buf[24];
|
||||
struct roffsu su;
|
||||
size_t sz;
|
||||
int sz;
|
||||
|
||||
print_line(".RS", MMAN_Bk_susp);
|
||||
|
||||
@ -434,7 +433,7 @@ print_offs(const char *v, int keywords)
|
||||
sz = 6;
|
||||
else if (keywords && !strcmp(v, "indent-two"))
|
||||
sz = 12;
|
||||
else if (a2roffsu(v, &su, SCALE_MAX)) {
|
||||
else if (a2roffsu(v, &su, SCALE_EN) > 1) {
|
||||
if (SCALE_EN == su.unit)
|
||||
sz = su.scale;
|
||||
else {
|
||||
@ -459,7 +458,7 @@ print_offs(const char *v, int keywords)
|
||||
if (Bl_stack_len)
|
||||
sz += Bl_stack[Bl_stack_len - 1];
|
||||
|
||||
(void)snprintf(buf, sizeof(buf), "%zun", sz);
|
||||
(void)snprintf(buf, sizeof(buf), "%dn", sz);
|
||||
print_word(buf);
|
||||
outflags |= MMAN_nl;
|
||||
}
|
||||
@ -468,20 +467,19 @@ print_offs(const char *v, int keywords)
|
||||
* Set up the indentation for a list item; used from pre_it().
|
||||
*/
|
||||
static void
|
||||
print_width(const char *v, const struct mdoc_node *child, size_t defsz)
|
||||
print_width(const struct mdoc_bl *bl, const struct mdoc_node *child)
|
||||
{
|
||||
char buf[24];
|
||||
struct roffsu su;
|
||||
size_t sz, chsz;
|
||||
int numeric, remain;
|
||||
int numeric, remain, sz, chsz;
|
||||
|
||||
numeric = 1;
|
||||
remain = 0;
|
||||
|
||||
/* Convert v into a number (of characters). */
|
||||
if (NULL == v)
|
||||
sz = defsz;
|
||||
else if (a2roffsu(v, &su, SCALE_MAX)) {
|
||||
/* Convert the width into a number (of characters). */
|
||||
if (bl->width == NULL)
|
||||
sz = (bl->type == LIST_hang) ? 6 : 0;
|
||||
else if (a2roffsu(bl->width, &su, SCALE_MAX) > 1) {
|
||||
if (SCALE_EN == su.unit)
|
||||
sz = su.scale;
|
||||
else {
|
||||
@ -489,11 +487,15 @@ print_width(const char *v, const struct mdoc_node *child, size_t defsz)
|
||||
numeric = 0;
|
||||
}
|
||||
} else
|
||||
sz = strlen(v);
|
||||
sz = strlen(bl->width);
|
||||
|
||||
/* XXX Rough estimation, might have multiple parts. */
|
||||
chsz = (NULL != child && MDOC_TEXT == child->type) ?
|
||||
strlen(child->string) : 0;
|
||||
if (bl->type == LIST_enum)
|
||||
chsz = (bl->count > 8) + 1;
|
||||
else if (child != NULL && child->type == MDOC_TEXT)
|
||||
chsz = strlen(child->string);
|
||||
else
|
||||
chsz = 0;
|
||||
|
||||
/* Maybe we are inside an enclosing list? */
|
||||
mid_it();
|
||||
@ -505,17 +507,17 @@ print_width(const char *v, const struct mdoc_node *child, size_t defsz)
|
||||
Bl_stack[Bl_stack_len++] = sz + 2;
|
||||
|
||||
/* Set up the current list. */
|
||||
if (defsz && chsz > sz)
|
||||
if (chsz > sz && bl->type != LIST_tag)
|
||||
print_block(".HP", 0);
|
||||
else {
|
||||
print_block(".TP", 0);
|
||||
remain = sz + 2;
|
||||
}
|
||||
if (numeric) {
|
||||
(void)snprintf(buf, sizeof(buf), "%zun", sz + 2);
|
||||
(void)snprintf(buf, sizeof(buf), "%dn", sz + 2);
|
||||
print_word(buf);
|
||||
} else
|
||||
print_word(v);
|
||||
print_word(bl->width);
|
||||
TPremain = remain;
|
||||
}
|
||||
|
||||
@ -524,7 +526,7 @@ print_count(int *count)
|
||||
{
|
||||
char buf[24];
|
||||
|
||||
(void)snprintf(buf, sizeof(buf), "%d.", ++*count);
|
||||
(void)snprintf(buf, sizeof(buf), "%d.\\&", ++*count);
|
||||
print_word(buf);
|
||||
}
|
||||
|
||||
@ -545,10 +547,10 @@ void
|
||||
man_mdoc(void *arg, const struct mdoc *mdoc)
|
||||
{
|
||||
const struct mdoc_meta *meta;
|
||||
const struct mdoc_node *n;
|
||||
struct mdoc_node *n;
|
||||
|
||||
meta = mdoc_meta(mdoc);
|
||||
n = mdoc_node(mdoc);
|
||||
n = mdoc_node(mdoc)->child;
|
||||
|
||||
printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n",
|
||||
meta->title,
|
||||
@ -564,15 +566,18 @@ man_mdoc(void *arg, const struct mdoc *mdoc)
|
||||
fontqueue.head = fontqueue.tail = mandoc_malloc(8);
|
||||
*fontqueue.tail = 'R';
|
||||
}
|
||||
print_node(meta, n);
|
||||
while (n != NULL) {
|
||||
print_node(meta, n);
|
||||
n = n->next;
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
static void
|
||||
print_node(DECL_ARGS)
|
||||
{
|
||||
const struct mdoc_node *sub;
|
||||
const struct manact *act;
|
||||
struct mdoc_node *sub;
|
||||
int cond, do_sub;
|
||||
|
||||
/*
|
||||
@ -585,6 +590,7 @@ print_node(DECL_ARGS)
|
||||
act = NULL;
|
||||
cond = 0;
|
||||
do_sub = 1;
|
||||
n->flags &= ~MDOC_ENDED;
|
||||
|
||||
if (MDOC_TEXT == n->type) {
|
||||
/*
|
||||
@ -632,7 +638,7 @@ print_node(DECL_ARGS)
|
||||
(*act->post)(meta, n);
|
||||
|
||||
if (ENDBODY_NOT != n->end)
|
||||
n->pending->flags |= MDOC_ENDED;
|
||||
n->body->flags |= MDOC_ENDED;
|
||||
|
||||
if (ENDBODY_NOSPACE == n->end)
|
||||
outflags &= ~(MMAN_spc | MMAN_nl);
|
||||
@ -876,8 +882,8 @@ static int
|
||||
pre_aq(DECL_ARGS)
|
||||
{
|
||||
|
||||
print_word(n->parent->prev != NULL &&
|
||||
n->parent->prev->tok == MDOC_An ? "<" : "\\(la");
|
||||
print_word(n->nchild == 1 &&
|
||||
n->child->tok == MDOC_Mt ? "<" : "\\(la");
|
||||
outflags &= ~MMAN_spc;
|
||||
return(1);
|
||||
}
|
||||
@ -887,8 +893,8 @@ post_aq(DECL_ARGS)
|
||||
{
|
||||
|
||||
outflags &= ~(MMAN_spc | MMAN_nl);
|
||||
print_word(n->parent->prev != NULL &&
|
||||
n->parent->prev->tok == MDOC_An ? ">" : "\\(ra");
|
||||
print_word(n->nchild == 1 &&
|
||||
n->child->tok == MDOC_Mt ? ">" : "\\(ra");
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1003,10 +1009,12 @@ pre_bl(DECL_ARGS)
|
||||
return(1);
|
||||
}
|
||||
|
||||
print_line(".TS", MMAN_nl);
|
||||
for (icol = 0; icol < n->norm->Bl.ncols; icol++)
|
||||
print_word("l");
|
||||
print_word(".");
|
||||
if (n->nchild) {
|
||||
print_line(".TS", MMAN_nl);
|
||||
for (icol = 0; icol < n->norm->Bl.ncols; icol++)
|
||||
print_word("l");
|
||||
print_word(".");
|
||||
}
|
||||
outflags |= MMAN_nl;
|
||||
return(1);
|
||||
}
|
||||
@ -1017,7 +1025,8 @@ post_bl(DECL_ARGS)
|
||||
|
||||
switch (n->norm->Bl.type) {
|
||||
case LIST_column:
|
||||
print_line(".TE", 0);
|
||||
if (n->nchild)
|
||||
print_line(".TE", 0);
|
||||
break;
|
||||
case LIST_enum:
|
||||
n->norm->Bl.count = 0;
|
||||
@ -1128,16 +1137,37 @@ static int
|
||||
pre_eo(DECL_ARGS)
|
||||
{
|
||||
|
||||
outflags &= ~(MMAN_spc | MMAN_nl);
|
||||
if (n->end == ENDBODY_NOT &&
|
||||
n->parent->head->child == NULL &&
|
||||
n->child != NULL &&
|
||||
n->child->end != ENDBODY_NOT)
|
||||
print_word("\\&");
|
||||
else if (n->end != ENDBODY_NOT ? n->child != NULL :
|
||||
n->parent->head->child != NULL && (n->child != NULL ||
|
||||
(n->parent->tail != NULL && n->parent->tail->child != NULL)))
|
||||
outflags &= ~(MMAN_spc | MMAN_nl);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void
|
||||
post_eo(DECL_ARGS)
|
||||
{
|
||||
int body, tail;
|
||||
|
||||
if (n->end != ENDBODY_SPACE)
|
||||
if (n->end != ENDBODY_NOT) {
|
||||
outflags |= MMAN_spc;
|
||||
return;
|
||||
}
|
||||
|
||||
body = n->child != NULL || n->parent->head->child != NULL;
|
||||
tail = n->parent->tail != NULL && n->parent->tail->child != NULL;
|
||||
|
||||
if (body && tail)
|
||||
outflags &= ~MMAN_spc;
|
||||
else if ( ! (body || tail))
|
||||
print_word("\\&");
|
||||
else if ( ! tail)
|
||||
outflags |= MMAN_spc;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1256,12 +1286,14 @@ pre_fo(DECL_ARGS)
|
||||
pre_syn(n);
|
||||
break;
|
||||
case MDOC_HEAD:
|
||||
if (n->child == NULL)
|
||||
return(0);
|
||||
if (MDOC_SYNPRETTY & n->flags)
|
||||
print_block(".HP 4n", MMAN_nl);
|
||||
font_push('B');
|
||||
break;
|
||||
case MDOC_BODY:
|
||||
outflags &= ~MMAN_spc;
|
||||
outflags &= ~(MMAN_spc | MMAN_nl);
|
||||
print_word("(");
|
||||
outflags &= ~MMAN_spc;
|
||||
break;
|
||||
@ -1277,7 +1309,8 @@ post_fo(DECL_ARGS)
|
||||
|
||||
switch (n->type) {
|
||||
case MDOC_HEAD:
|
||||
font_pop();
|
||||
if (n->child != NULL)
|
||||
font_pop();
|
||||
break;
|
||||
case MDOC_BODY:
|
||||
post_fn(meta, n);
|
||||
@ -1362,7 +1395,7 @@ pre_it(DECL_ARGS)
|
||||
case LIST_dash:
|
||||
/* FALLTHROUGH */
|
||||
case LIST_hyphen:
|
||||
print_width(bln->norm->Bl.width, NULL, 0);
|
||||
print_width(&bln->norm->Bl, NULL);
|
||||
TPremain = 0;
|
||||
outflags |= MMAN_nl;
|
||||
font_push('B');
|
||||
@ -1374,19 +1407,19 @@ pre_it(DECL_ARGS)
|
||||
outflags |= MMAN_nl;
|
||||
return(0);
|
||||
case LIST_enum:
|
||||
print_width(bln->norm->Bl.width, NULL, 0);
|
||||
print_width(&bln->norm->Bl, NULL);
|
||||
TPremain = 0;
|
||||
outflags |= MMAN_nl;
|
||||
print_count(&bln->norm->Bl.count);
|
||||
outflags |= MMAN_nl;
|
||||
return(0);
|
||||
case LIST_hang:
|
||||
print_width(bln->norm->Bl.width, n->child, 6);
|
||||
print_width(&bln->norm->Bl, n->child);
|
||||
TPremain = 0;
|
||||
outflags |= MMAN_nl;
|
||||
return(1);
|
||||
case LIST_tag:
|
||||
print_width(bln->norm->Bl.width, n->child, 0);
|
||||
print_width(&bln->norm->Bl, n->child);
|
||||
putchar('\n');
|
||||
outflags &= ~MMAN_spc;
|
||||
return(1);
|
||||
@ -1418,7 +1451,7 @@ mid_it(void)
|
||||
|
||||
/* Restore the indentation of the enclosing list. */
|
||||
print_line(".RS", MMAN_Bk_susp);
|
||||
(void)snprintf(buf, sizeof(buf), "%zun",
|
||||
(void)snprintf(buf, sizeof(buf), "%dn",
|
||||
Bl_stack[Bl_stack_len - 1]);
|
||||
print_word(buf);
|
||||
|
||||
|
235
mdoc_term.c
235
mdoc_term.c
@ -1,7 +1,7 @@
|
||||
/* $Id: mdoc_term.c,v 1.299 2014/12/02 10:08:06 schwarze Exp $ */
|
||||
/* $Id: mdoc_term.c,v 1.311 2015/02/17 20:37:17 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@ -22,6 +22,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -49,8 +50,7 @@ struct termact {
|
||||
void (*post)(DECL_ARGS);
|
||||
};
|
||||
|
||||
static size_t a2width(const struct termp *, const char *);
|
||||
static size_t a2height(const struct termp *, const char *);
|
||||
static int a2width(const struct termp *, const char *);
|
||||
|
||||
static void print_bvspace(struct termp *,
|
||||
const struct mdoc_node *,
|
||||
@ -67,6 +67,7 @@ static void termp__t_post(DECL_ARGS);
|
||||
static void termp_bd_post(DECL_ARGS);
|
||||
static void termp_bk_post(DECL_ARGS);
|
||||
static void termp_bl_post(DECL_ARGS);
|
||||
static void termp_eo_post(DECL_ARGS);
|
||||
static void termp_fd_post(DECL_ARGS);
|
||||
static void termp_fo_post(DECL_ARGS);
|
||||
static void termp_in_post(DECL_ARGS);
|
||||
@ -91,6 +92,7 @@ static int termp_bt_pre(DECL_ARGS);
|
||||
static int termp_bx_pre(DECL_ARGS);
|
||||
static int termp_cd_pre(DECL_ARGS);
|
||||
static int termp_d1_pre(DECL_ARGS);
|
||||
static int termp_eo_pre(DECL_ARGS);
|
||||
static int termp_ex_pre(DECL_ARGS);
|
||||
static int termp_fa_pre(DECL_ARGS);
|
||||
static int termp_fd_pre(DECL_ARGS);
|
||||
@ -190,7 +192,7 @@ static const struct termact termacts[MDOC_MAX] = {
|
||||
{ NULL, NULL }, /* Ec */ /* FIXME: no space */
|
||||
{ NULL, NULL }, /* Ef */
|
||||
{ termp_under_pre, NULL }, /* Em */
|
||||
{ termp_quote_pre, termp_quote_post }, /* Eo */
|
||||
{ termp_eo_pre, termp_eo_post }, /* Eo */
|
||||
{ termp_xx_pre, NULL }, /* Fx */
|
||||
{ termp_bold_pre, NULL }, /* Ms */
|
||||
{ termp_li_pre, NULL }, /* No */
|
||||
@ -291,9 +293,10 @@ static void
|
||||
print_mdoc_nodelist(DECL_ARGS)
|
||||
{
|
||||
|
||||
print_mdoc_node(p, pair, meta, n);
|
||||
if (n->next)
|
||||
print_mdoc_nodelist(p, pair, meta, n->next);
|
||||
while (n != NULL) {
|
||||
print_mdoc_node(p, pair, meta, n);
|
||||
n = n->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -306,7 +309,8 @@ print_mdoc_node(DECL_ARGS)
|
||||
chld = 1;
|
||||
offset = p->offset;
|
||||
rmargin = p->rmargin;
|
||||
n->prev_font = term_fontq(p);
|
||||
n->flags &= ~MDOC_ENDED;
|
||||
n->prev_font = p->fonti;
|
||||
|
||||
memset(&npair, 0, sizeof(struct termpair));
|
||||
npair.ppair = pair;
|
||||
@ -316,12 +320,9 @@ print_mdoc_node(DECL_ARGS)
|
||||
* invoked in a prior line, revert it to PREKEEP.
|
||||
*/
|
||||
|
||||
if (TERMP_KEEP & p->flags) {
|
||||
if (n->prev ? (n->prev->lastline != n->line) :
|
||||
(n->parent && n->parent->line != n->line)) {
|
||||
p->flags &= ~TERMP_KEEP;
|
||||
p->flags |= TERMP_PREKEEP;
|
||||
}
|
||||
if (p->flags & TERMP_KEEP && n->flags & MDOC_LINE) {
|
||||
p->flags &= ~TERMP_KEEP;
|
||||
p->flags |= TERMP_PREKEEP;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -361,7 +362,7 @@ print_mdoc_node(DECL_ARGS)
|
||||
print_mdoc_nodelist(p, &npair, meta, n->child);
|
||||
|
||||
term_fontpopq(p,
|
||||
(ENDBODY_NOT == n->end ? n : n->pending)->prev_font);
|
||||
(ENDBODY_NOT == n->end ? n : n->body)->prev_font);
|
||||
|
||||
switch (n->type) {
|
||||
case MDOC_TEXT:
|
||||
@ -381,7 +382,7 @@ print_mdoc_node(DECL_ARGS)
|
||||
* that it must not call the post handler again.
|
||||
*/
|
||||
if (ENDBODY_NOT != n->end)
|
||||
n->pending->flags |= MDOC_ENDED;
|
||||
n->body->flags |= MDOC_ENDED;
|
||||
|
||||
/*
|
||||
* End of line terminating an implicit block
|
||||
@ -526,30 +527,15 @@ print_mdoc_head(struct termp *p, const void *arg)
|
||||
free(volume);
|
||||
}
|
||||
|
||||
static size_t
|
||||
a2height(const struct termp *p, const char *v)
|
||||
{
|
||||
struct roffsu su;
|
||||
|
||||
|
||||
assert(v);
|
||||
if ( ! a2roffsu(v, &su, SCALE_VS))
|
||||
SCALE_VS_INIT(&su, atoi(v));
|
||||
|
||||
return(term_vspan(p, &su));
|
||||
}
|
||||
|
||||
static size_t
|
||||
static int
|
||||
a2width(const struct termp *p, const char *v)
|
||||
{
|
||||
struct roffsu su;
|
||||
|
||||
assert(v);
|
||||
if ( ! a2roffsu(v, &su, SCALE_MAX)) {
|
||||
if (a2roffsu(v, &su, SCALE_MAX) < 2) {
|
||||
SCALE_HS_INIT(&su, term_strlen(p, v));
|
||||
su.scale /= term_strlen(p, "0");
|
||||
}
|
||||
|
||||
return(term_hspan(p, &su));
|
||||
}
|
||||
|
||||
@ -620,10 +606,10 @@ termp_ll_pre(DECL_ARGS)
|
||||
static int
|
||||
termp_it_pre(DECL_ARGS)
|
||||
{
|
||||
const struct mdoc_node *bl, *nn;
|
||||
char buf[24];
|
||||
int i;
|
||||
size_t width, offset, ncols, dcol;
|
||||
const struct mdoc_node *bl, *nn;
|
||||
size_t ncols, dcol;
|
||||
int i, offset, width;
|
||||
enum mdoc_list type;
|
||||
|
||||
if (MDOC_BLOCK == n->type) {
|
||||
@ -634,16 +620,47 @@ termp_it_pre(DECL_ARGS)
|
||||
bl = n->parent->parent->parent;
|
||||
type = bl->norm->Bl.type;
|
||||
|
||||
/*
|
||||
* Defaults for specific list types.
|
||||
*/
|
||||
|
||||
switch (type) {
|
||||
case LIST_bullet:
|
||||
/* FALLTHROUGH */
|
||||
case LIST_dash:
|
||||
/* FALLTHROUGH */
|
||||
case LIST_hyphen:
|
||||
/* FALLTHROUGH */
|
||||
case LIST_enum:
|
||||
width = term_len(p, 2);
|
||||
break;
|
||||
case LIST_hang:
|
||||
width = term_len(p, 8);
|
||||
break;
|
||||
case LIST_column:
|
||||
/* FALLTHROUGH */
|
||||
case LIST_tag:
|
||||
width = term_len(p, 10);
|
||||
break;
|
||||
default:
|
||||
width = 0;
|
||||
break;
|
||||
}
|
||||
offset = 0;
|
||||
|
||||
/*
|
||||
* First calculate width and offset. This is pretty easy unless
|
||||
* we're a -column list, in which case all prior columns must
|
||||
* be accounted for.
|
||||
*/
|
||||
|
||||
width = offset = 0;
|
||||
|
||||
if (bl->norm->Bl.offs)
|
||||
if (bl->norm->Bl.offs != NULL) {
|
||||
offset = a2width(p, bl->norm->Bl.offs);
|
||||
if (offset < 0 && (size_t)(-offset) > p->offset)
|
||||
offset = -p->offset;
|
||||
else if (offset > SHRT_MAX)
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case LIST_column:
|
||||
@ -698,39 +715,11 @@ termp_it_pre(DECL_ARGS)
|
||||
* number for buffering single arguments. See the above
|
||||
* handling for column for how this changes.
|
||||
*/
|
||||
assert(bl->norm->Bl.width);
|
||||
width = a2width(p, bl->norm->Bl.width) + term_len(p, 2);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* List-type can override the width in the case of fixed-head
|
||||
* values (bullet, dash/hyphen, enum). Tags need a non-zero
|
||||
* offset.
|
||||
*/
|
||||
|
||||
switch (type) {
|
||||
case LIST_bullet:
|
||||
/* FALLTHROUGH */
|
||||
case LIST_dash:
|
||||
/* FALLTHROUGH */
|
||||
case LIST_hyphen:
|
||||
/* FALLTHROUGH */
|
||||
case LIST_enum:
|
||||
if (width < term_len(p, 2))
|
||||
width = term_len(p, 2);
|
||||
break;
|
||||
case LIST_hang:
|
||||
if (0 == width)
|
||||
width = term_len(p, 8);
|
||||
break;
|
||||
case LIST_column:
|
||||
/* FALLTHROUGH */
|
||||
case LIST_tag:
|
||||
if (0 == width)
|
||||
width = term_len(p, 10);
|
||||
break;
|
||||
default:
|
||||
if (width < 0 && (size_t)(-width) > p->offset)
|
||||
width = -p->offset;
|
||||
else if (width > SHRT_MAX)
|
||||
width = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -776,16 +765,16 @@ termp_it_pre(DECL_ARGS)
|
||||
case LIST_enum:
|
||||
/*
|
||||
* Weird special case.
|
||||
* Very narrow enum lists actually hang.
|
||||
* Some very narrow lists actually hang.
|
||||
*/
|
||||
if (width == term_len(p, 2))
|
||||
p->flags |= TERMP_HANG;
|
||||
/* FALLTHROUGH */
|
||||
case LIST_bullet:
|
||||
/* FALLTHROUGH */
|
||||
case LIST_dash:
|
||||
/* FALLTHROUGH */
|
||||
case LIST_hyphen:
|
||||
if (width <= (int)term_len(p, 2))
|
||||
p->flags |= TERMP_HANG;
|
||||
if (MDOC_HEAD != n->type)
|
||||
break;
|
||||
p->flags |= TERMP_NOBREAK;
|
||||
@ -874,7 +863,6 @@ termp_it_pre(DECL_ARGS)
|
||||
case LIST_hyphen:
|
||||
/* FALLTHROUGH */
|
||||
case LIST_tag:
|
||||
assert(width);
|
||||
if (MDOC_HEAD == n->type)
|
||||
p->rmargin = p->offset + width;
|
||||
else
|
||||
@ -1104,9 +1092,6 @@ termp_an_pre(DECL_ARGS)
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (n->child == NULL)
|
||||
return(0);
|
||||
|
||||
if (p->flags & TERMP_SPLIT)
|
||||
term_newln(p);
|
||||
|
||||
@ -1554,6 +1539,7 @@ termp_bd_pre(DECL_ARGS)
|
||||
{
|
||||
size_t tabwidth, lm, len, rm, rmax;
|
||||
struct mdoc_node *nn;
|
||||
int offset;
|
||||
|
||||
if (MDOC_BLOCK == n->type) {
|
||||
print_bvspace(p, n, n);
|
||||
@ -1570,8 +1556,13 @@ termp_bd_pre(DECL_ARGS)
|
||||
p->offset += term_len(p, p->defindent + 1);
|
||||
else if ( ! strcmp(n->norm->Bd.offs, "indent-two"))
|
||||
p->offset += term_len(p, (p->defindent + 1) * 2);
|
||||
else
|
||||
p->offset += a2width(p, n->norm->Bd.offs);
|
||||
else {
|
||||
offset = a2width(p, n->norm->Bd.offs);
|
||||
if (offset < 0 && (size_t)(-offset) > p->offset)
|
||||
p->offset = 0;
|
||||
else if (offset < SHRT_MAX)
|
||||
p->offset += offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* If -ragged or -filled are specified, the block does nothing
|
||||
@ -1816,11 +1807,17 @@ termp_in_post(DECL_ARGS)
|
||||
static int
|
||||
termp_sp_pre(DECL_ARGS)
|
||||
{
|
||||
struct roffsu su;
|
||||
size_t i, len;
|
||||
|
||||
switch (n->tok) {
|
||||
case MDOC_sp:
|
||||
len = n->child ? a2height(p, n->child->string) : 1;
|
||||
if (n->child) {
|
||||
if ( ! a2roffsu(n->child->string, &su, SCALE_VS))
|
||||
su.scale = 1.0;
|
||||
len = term_vspan(p, &su);
|
||||
} else
|
||||
len = 1;
|
||||
break;
|
||||
case MDOC_br:
|
||||
len = 0;
|
||||
@ -1856,8 +1853,8 @@ termp_quote_pre(DECL_ARGS)
|
||||
case MDOC_Ao:
|
||||
/* FALLTHROUGH */
|
||||
case MDOC_Aq:
|
||||
term_word(p, n->parent->prev != NULL &&
|
||||
n->parent->prev->tok == MDOC_An ? "<" : "\\(la");
|
||||
term_word(p, n->nchild == 1 &&
|
||||
n->child->tok == MDOC_Mt ? "<" : "\\(la");
|
||||
break;
|
||||
case MDOC_Bro:
|
||||
/* FALLTHROUGH */
|
||||
@ -1876,7 +1873,7 @@ termp_quote_pre(DECL_ARGS)
|
||||
case MDOC_Do:
|
||||
/* FALLTHROUGH */
|
||||
case MDOC_Dq:
|
||||
term_word(p, "\\(lq");
|
||||
term_word(p, "\\(Lq");
|
||||
break;
|
||||
case MDOC_En:
|
||||
if (NULL == n->norm->Es ||
|
||||
@ -1884,8 +1881,6 @@ termp_quote_pre(DECL_ARGS)
|
||||
return(1);
|
||||
term_word(p, n->norm->Es->child->string);
|
||||
break;
|
||||
case MDOC_Eo:
|
||||
break;
|
||||
case MDOC_Po:
|
||||
/* FALLTHROUGH */
|
||||
case MDOC_Pq:
|
||||
@ -1921,16 +1916,14 @@ termp_quote_post(DECL_ARGS)
|
||||
if (n->type != MDOC_BODY && n->type != MDOC_ELEM)
|
||||
return;
|
||||
|
||||
if ( ! (n->tok == MDOC_En ||
|
||||
(n->tok == MDOC_Eo && n->end == ENDBODY_SPACE)))
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
|
||||
switch (n->tok) {
|
||||
case MDOC_Ao:
|
||||
/* FALLTHROUGH */
|
||||
case MDOC_Aq:
|
||||
term_word(p, n->parent->prev != NULL &&
|
||||
n->parent->prev->tok == MDOC_An ? ">" : "\\(ra");
|
||||
term_word(p, n->nchild == 1 &&
|
||||
n->child->tok == MDOC_Mt ? ">" : "\\(ra");
|
||||
break;
|
||||
case MDOC_Bro:
|
||||
/* FALLTHROUGH */
|
||||
@ -1949,17 +1942,15 @@ termp_quote_post(DECL_ARGS)
|
||||
case MDOC_Do:
|
||||
/* FALLTHROUGH */
|
||||
case MDOC_Dq:
|
||||
term_word(p, "\\(rq");
|
||||
term_word(p, "\\(Rq");
|
||||
break;
|
||||
case MDOC_En:
|
||||
if (NULL != n->norm->Es &&
|
||||
NULL != n->norm->Es->child &&
|
||||
NULL != n->norm->Es->child->next) {
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
if (n->norm->Es == NULL ||
|
||||
n->norm->Es->child == NULL ||
|
||||
n->norm->Es->child->next == NULL)
|
||||
p->flags &= ~TERMP_NOSPACE;
|
||||
else
|
||||
term_word(p, n->norm->Es->child->next->string);
|
||||
}
|
||||
break;
|
||||
case MDOC_Eo:
|
||||
break;
|
||||
case MDOC_Po:
|
||||
/* FALLTHROUGH */
|
||||
@ -1986,6 +1977,50 @@ termp_quote_post(DECL_ARGS)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
termp_eo_pre(DECL_ARGS)
|
||||
{
|
||||
|
||||
if (n->type != MDOC_BODY)
|
||||
return(1);
|
||||
|
||||
if (n->end == ENDBODY_NOT &&
|
||||
n->parent->head->child == NULL &&
|
||||
n->child != NULL &&
|
||||
n->child->end != ENDBODY_NOT)
|
||||
term_word(p, "\\&");
|
||||
else if (n->end != ENDBODY_NOT ? n->child != NULL :
|
||||
n->parent->head->child != NULL && (n->child != NULL ||
|
||||
(n->parent->tail != NULL && n->parent->tail->child != NULL)))
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void
|
||||
termp_eo_post(DECL_ARGS)
|
||||
{
|
||||
int body, tail;
|
||||
|
||||
if (n->type != MDOC_BODY)
|
||||
return;
|
||||
|
||||
if (n->end != ENDBODY_NOT) {
|
||||
p->flags &= ~TERMP_NOSPACE;
|
||||
return;
|
||||
}
|
||||
|
||||
body = n->child != NULL || n->parent->head->child != NULL;
|
||||
tail = n->parent->tail != NULL && n->parent->tail->child != NULL;
|
||||
|
||||
if (body && tail)
|
||||
p->flags |= TERMP_NOSPACE;
|
||||
else if ( ! (body || tail))
|
||||
term_word(p, "\\&");
|
||||
else if ( ! tail)
|
||||
p->flags &= ~TERMP_NOSPACE;
|
||||
}
|
||||
|
||||
static int
|
||||
termp_fo_pre(DECL_ARGS)
|
||||
{
|
||||
|
630
mdoc_validate.c
630
mdoc_validate.c
File diff suppressed because it is too large
Load Diff
3
msec.c
3
msec.c
@ -1,4 +1,4 @@
|
||||
/* $Id: msec.c,v 1.13 2014/12/01 08:05:52 schwarze Exp $ */
|
||||
/* $Id: msec.c,v 1.14 2014/12/21 14:14:35 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mandoc.h"
|
||||
#include "libmandoc.h"
|
||||
|
||||
#define LINE(x, y) \
|
||||
|
151
out.c
151
out.c
@ -1,7 +1,7 @@
|
||||
/* $Id: out.c,v 1.54 2014/12/04 02:05:42 schwarze Exp $ */
|
||||
/* $Id: out.c,v 1.59 2015/01/30 04:11:50 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -20,8 +20,6 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
@ -39,97 +37,64 @@ static void tblcalc_number(struct rofftbl *, struct roffcol *,
|
||||
|
||||
|
||||
/*
|
||||
* Convert a `scaling unit' to a consistent form, or fail. Scaling
|
||||
* units are documented in groff.7, mdoc.7, man.7.
|
||||
* Parse the *src string and store a scaling unit into *dst.
|
||||
* If the string doesn't specify the unit, use the default.
|
||||
* If no default is specified, fail.
|
||||
* Return 2 on complete success, 1 when a conversion was done,
|
||||
* but there was trailing garbage, and 0 on total failure.
|
||||
*/
|
||||
int
|
||||
a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
|
||||
{
|
||||
char buf[BUFSIZ], hasd;
|
||||
int i;
|
||||
enum roffscale unit;
|
||||
char *endptr;
|
||||
|
||||
if ('\0' == *src)
|
||||
dst->unit = def == SCALE_MAX ? SCALE_BU : def;
|
||||
dst->scale = strtod(src, &endptr);
|
||||
if (endptr == src)
|
||||
return(0);
|
||||
|
||||
i = hasd = 0;
|
||||
|
||||
switch (*src) {
|
||||
case '+':
|
||||
src++;
|
||||
break;
|
||||
case '-':
|
||||
buf[i++] = *src++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ('\0' == *src)
|
||||
return(0);
|
||||
|
||||
while (i < BUFSIZ) {
|
||||
if ( ! isdigit((unsigned char)*src)) {
|
||||
if ('.' != *src)
|
||||
break;
|
||||
else if (hasd)
|
||||
break;
|
||||
else
|
||||
hasd = 1;
|
||||
}
|
||||
buf[i++] = *src++;
|
||||
}
|
||||
|
||||
if (BUFSIZ == i || (*src && *(src + 1)))
|
||||
return(0);
|
||||
|
||||
buf[i] = '\0';
|
||||
|
||||
switch (*src) {
|
||||
switch (*endptr++) {
|
||||
case 'c':
|
||||
unit = SCALE_CM;
|
||||
dst->unit = SCALE_CM;
|
||||
break;
|
||||
case 'i':
|
||||
unit = SCALE_IN;
|
||||
break;
|
||||
case 'P':
|
||||
unit = SCALE_PC;
|
||||
break;
|
||||
case 'p':
|
||||
unit = SCALE_PT;
|
||||
dst->unit = SCALE_IN;
|
||||
break;
|
||||
case 'f':
|
||||
unit = SCALE_FS;
|
||||
break;
|
||||
case 'v':
|
||||
unit = SCALE_VS;
|
||||
break;
|
||||
case 'm':
|
||||
unit = SCALE_EM;
|
||||
break;
|
||||
case '\0':
|
||||
if (SCALE_MAX == def)
|
||||
return(0);
|
||||
unit = def;
|
||||
break;
|
||||
case 'u':
|
||||
unit = SCALE_BU;
|
||||
dst->unit = SCALE_FS;
|
||||
break;
|
||||
case 'M':
|
||||
unit = SCALE_MM;
|
||||
dst->unit = SCALE_MM;
|
||||
break;
|
||||
case 'm':
|
||||
dst->unit = SCALE_EM;
|
||||
break;
|
||||
case 'n':
|
||||
unit = SCALE_EN;
|
||||
dst->unit = SCALE_EN;
|
||||
break;
|
||||
case 'P':
|
||||
dst->unit = SCALE_PC;
|
||||
break;
|
||||
case 'p':
|
||||
dst->unit = SCALE_PT;
|
||||
break;
|
||||
case 'u':
|
||||
dst->unit = SCALE_BU;
|
||||
break;
|
||||
case 'v':
|
||||
dst->unit = SCALE_VS;
|
||||
break;
|
||||
case '\0':
|
||||
endptr--;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
return(0);
|
||||
if (SCALE_MAX == def)
|
||||
return(0);
|
||||
dst->unit = def;
|
||||
break;
|
||||
}
|
||||
|
||||
/* FIXME: do this in the caller. */
|
||||
if ((dst->scale = atof(buf)) < 0.0)
|
||||
dst->scale = 0.0;
|
||||
dst->unit = unit;
|
||||
return(1);
|
||||
return(*endptr == '\0' ? 2 : 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -142,11 +107,12 @@ void
|
||||
tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
|
||||
size_t totalwidth)
|
||||
{
|
||||
const struct tbl_opts *opts;
|
||||
const struct tbl_dat *dp;
|
||||
struct roffcol *col;
|
||||
size_t ewidth, xwidth;
|
||||
int spans;
|
||||
int icol, maxcol, necol, nxcol;
|
||||
int icol, maxcol, necol, nxcol, quirkcol;
|
||||
|
||||
/*
|
||||
* Allocate the master column specifiers. These will hold the
|
||||
@ -157,6 +123,7 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
|
||||
assert(NULL == tbl->cols);
|
||||
tbl->cols = mandoc_calloc((size_t)sp->opts->cols,
|
||||
sizeof(struct roffcol));
|
||||
opts = sp->opts;
|
||||
|
||||
for (maxcol = -1; sp; sp = sp->next) {
|
||||
if (TBL_SPAN_DATA != sp->pos)
|
||||
@ -173,14 +140,14 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
|
||||
spans = dp->spans;
|
||||
if (1 < spans)
|
||||
continue;
|
||||
icol = dp->layout->head->ident;
|
||||
icol = dp->layout->col;
|
||||
if (maxcol < icol)
|
||||
maxcol = icol;
|
||||
col = tbl->cols + icol;
|
||||
col->flags |= dp->layout->flags;
|
||||
if (dp->layout->flags & TBL_CELL_WIGN)
|
||||
continue;
|
||||
tblcalc_data(tbl, col, sp->opts, dp);
|
||||
tblcalc_data(tbl, col, opts, dp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,13 +197,35 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
|
||||
*/
|
||||
|
||||
if (nxcol && totalwidth) {
|
||||
xwidth = totalwidth - 3*maxcol - xwidth;
|
||||
xwidth = totalwidth - xwidth - 3*maxcol -
|
||||
(opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX) ?
|
||||
2 : !!opts->lvert + !!opts->rvert);
|
||||
|
||||
/*
|
||||
* Emulate a bug in GNU tbl width calculation that
|
||||
* manifests itself for large numbers of x-columns.
|
||||
* Emulating it for 5 x-columns gives identical
|
||||
* behaviour for up to 6 x-columns.
|
||||
*/
|
||||
|
||||
if (nxcol == 5) {
|
||||
quirkcol = xwidth % nxcol + 2;
|
||||
if (quirkcol != 3 && quirkcol != 4)
|
||||
quirkcol = -1;
|
||||
} else
|
||||
quirkcol = -1;
|
||||
|
||||
necol = 0;
|
||||
ewidth = 0;
|
||||
for (icol = 0; icol <= maxcol; icol++) {
|
||||
col = tbl->cols + icol;
|
||||
if ( ! (col->flags & TBL_CELL_WMAX))
|
||||
continue;
|
||||
col->width = xwidth / nxcol--;
|
||||
xwidth -= col->width;
|
||||
col->width = (double)xwidth * ++necol / nxcol
|
||||
- ewidth + 0.4995;
|
||||
if (necol == quirkcol)
|
||||
col->width--;
|
||||
ewidth += col->width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
133
preconv.c
133
preconv.c
@ -1,4 +1,4 @@
|
||||
/* $Id: preconv.c,v 1.12 2014/11/14 04:24:04 schwarze Exp $ */
|
||||
/* $Id: preconv.c,v 1.13 2014/12/19 04:58:35 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -19,6 +19,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mandoc.h"
|
||||
@ -28,88 +29,70 @@ int
|
||||
preconv_encode(struct buf *ib, size_t *ii, struct buf *ob, size_t *oi,
|
||||
int *filenc)
|
||||
{
|
||||
size_t i;
|
||||
int state;
|
||||
unsigned char *cu;
|
||||
int nby;
|
||||
unsigned int accum;
|
||||
unsigned char cu;
|
||||
|
||||
cu = ib->buf + *ii;
|
||||
assert(*cu & 0x80);
|
||||
|
||||
if ( ! (*filenc & MPARSE_UTF8))
|
||||
goto latin;
|
||||
|
||||
state = 0;
|
||||
accum = 0U;
|
||||
nby = 1;
|
||||
while (nby < 5 && *cu & (1 << (7 - nby)))
|
||||
nby++;
|
||||
|
||||
for (i = *ii; i < ib->sz; i++) {
|
||||
cu = ib->buf[i];
|
||||
if (state) {
|
||||
if ( ! (cu & 128) || (cu & 64)) {
|
||||
/* Bad sequence header. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Accept only legitimate bit patterns. */
|
||||
|
||||
if (cu > 191 || cu < 128) {
|
||||
/* Bad in-sequence bits. */
|
||||
break;
|
||||
}
|
||||
|
||||
accum |= (cu & 63) << --state * 6;
|
||||
|
||||
if (state)
|
||||
continue;
|
||||
|
||||
if (accum < 0x80)
|
||||
ob->buf[(*oi)++] = accum;
|
||||
else
|
||||
*oi += snprintf(ob->buf + *oi,
|
||||
11, "\\[u%.4X]", accum);
|
||||
*ii = i + 1;
|
||||
*filenc &= ~MPARSE_LATIN1;
|
||||
return(1);
|
||||
} else {
|
||||
/*
|
||||
* Entering a UTF-8 state: if we encounter a
|
||||
* UTF-8 bitmask, calculate the expected UTF-8
|
||||
* state from it.
|
||||
*/
|
||||
for (state = 0; state < 7; state++)
|
||||
if ( ! (cu & (1 << (7 - state))))
|
||||
break;
|
||||
|
||||
/* Accept only legitimate bit patterns. */
|
||||
|
||||
switch (state--) {
|
||||
case (4):
|
||||
if (cu <= 244 && cu >= 240) {
|
||||
accum = (cu & 7) << 18;
|
||||
continue;
|
||||
}
|
||||
/* Bad 4-sequence start bits. */
|
||||
break;
|
||||
case (3):
|
||||
if (cu <= 239 && cu >= 224) {
|
||||
accum = (cu & 15) << 12;
|
||||
continue;
|
||||
}
|
||||
/* Bad 3-sequence start bits. */
|
||||
break;
|
||||
case (2):
|
||||
if (cu <= 223 && cu >= 194) {
|
||||
accum = (cu & 31) << 6;
|
||||
continue;
|
||||
}
|
||||
/* Bad 2-sequence start bits. */
|
||||
break;
|
||||
default:
|
||||
/* Bad sequence bit mask. */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch (nby) {
|
||||
case 2:
|
||||
accum = *cu & 0x1f;
|
||||
if (accum < 0x02) /* Obfuscated ASCII. */
|
||||
goto latin;
|
||||
break;
|
||||
case 3:
|
||||
accum = *cu & 0x0f;
|
||||
break;
|
||||
case 4:
|
||||
accum = *cu & 0x07;
|
||||
if (accum > 0x04) /* Beyond Unicode. */
|
||||
goto latin;
|
||||
break;
|
||||
default: /* Bad sequence header. */
|
||||
goto latin;
|
||||
}
|
||||
|
||||
/* FALLTHROUGH: Invalid or incomplete UTF-8 sequence. */
|
||||
cu++;
|
||||
switch (nby) {
|
||||
case 3:
|
||||
if ((accum == 0x00 && ! (*cu & 0x20)) || /* Use 2-byte. */
|
||||
(accum == 0x0d && *cu & 0x20)) /* Surrogates. */
|
||||
goto latin;
|
||||
break;
|
||||
case 4:
|
||||
if ((accum == 0x00 && ! (*cu & 0x30)) || /* Use 3-byte. */
|
||||
(accum == 0x04 && *cu & 0x30)) /* Beyond Unicode. */
|
||||
goto latin;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
while (--nby) {
|
||||
if ((*cu & 0xc0) != 0x80) /* Invalid continuation. */
|
||||
goto latin;
|
||||
accum <<= 6;
|
||||
accum += *cu & 0x3f;
|
||||
cu++;
|
||||
}
|
||||
|
||||
assert(accum > 0x7f);
|
||||
assert(accum < 0x110000);
|
||||
assert(accum < 0xd800 || accum > 0xdfff);
|
||||
|
||||
*oi += snprintf(ob->buf + *oi, 11, "\\[u%.4X]", accum);
|
||||
*ii = (char *)cu - ib->buf;
|
||||
*filenc &= ~MPARSE_LATIN1;
|
||||
return(1);
|
||||
|
||||
latin:
|
||||
if ( ! (*filenc & MPARSE_LATIN1))
|
||||
|
264
read.c
264
read.c
@ -1,7 +1,7 @@
|
||||
/* $Id: read.c,v 1.104 2014/12/01 04:14:14 schwarze Exp $ */
|
||||
/* $Id: read.c,v 1.129 2015/03/02 14:50:17 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2010, 2012 Joerg Sonnenberger <joerg@netbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@ -80,7 +80,7 @@ static const enum mandocerr mandoclimits[MANDOCLEVEL_MAX] = {
|
||||
MANDOCERR_WARNING,
|
||||
MANDOCERR_WARNING,
|
||||
MANDOCERR_ERROR,
|
||||
MANDOCERR_FATAL,
|
||||
MANDOCERR_UNSUPP,
|
||||
MANDOCERR_MAX,
|
||||
MANDOCERR_MAX
|
||||
};
|
||||
@ -109,7 +109,11 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
||||
"no document body",
|
||||
"content before first section header",
|
||||
"first section is not \"NAME\"",
|
||||
"bad NAME section contents",
|
||||
"NAME section without name",
|
||||
"NAME section without description",
|
||||
"description not at the end of NAME",
|
||||
"bad NAME section content",
|
||||
"missing description line, using \"\"",
|
||||
"sections out of conventional order",
|
||||
"duplicate section title",
|
||||
"unexpected section",
|
||||
@ -135,18 +139,22 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
||||
"skipping empty request",
|
||||
"conditional request controls empty scope",
|
||||
"skipping empty macro",
|
||||
"empty block",
|
||||
"empty argument, using 0n",
|
||||
"argument count wrong",
|
||||
"missing display type, using -ragged",
|
||||
"list type is not the first argument",
|
||||
"missing -width in -tag list, using 8n",
|
||||
"missing utility name, using \"\"",
|
||||
"missing function name, using \"\"",
|
||||
"empty head in list item",
|
||||
"empty list item",
|
||||
"missing font type, using \\fR",
|
||||
"unknown font type, using \\fR",
|
||||
"nothing follows prefix",
|
||||
"empty reference block",
|
||||
"missing -std argument, adding it",
|
||||
"missing option string, using \"\"",
|
||||
"missing resource identifier, using \"\"",
|
||||
"missing eqn box, using \"\"",
|
||||
|
||||
/* related to bad macro arguments */
|
||||
@ -156,12 +164,14 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
||||
"skipping duplicate display type",
|
||||
"skipping duplicate list type",
|
||||
"skipping -width argument",
|
||||
"wrong number of cells",
|
||||
"unknown AT&T UNIX version",
|
||||
"comma in function argument",
|
||||
"parenthesis in function name",
|
||||
"invalid content in Rs block",
|
||||
"invalid Boolean argument",
|
||||
"unknown font, skipping request",
|
||||
"odd number of characters in request",
|
||||
|
||||
/* related to plain text */
|
||||
"blank line in fill mode, using .sp",
|
||||
@ -171,64 +181,60 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
|
||||
"invalid escape sequence",
|
||||
"undefined string, using \"\"",
|
||||
|
||||
/* related to tables */
|
||||
"tbl line starts with span",
|
||||
"tbl column starts with span",
|
||||
"skipping vertical bar in tbl layout",
|
||||
|
||||
"generic error",
|
||||
|
||||
/* related to equations */
|
||||
"unexpected equation scope closure",
|
||||
"equation scope open on exit",
|
||||
"overlapping equation scopes",
|
||||
"unexpected end of equation",
|
||||
|
||||
/* related to tables */
|
||||
"bad table syntax",
|
||||
"bad table option",
|
||||
"bad table layout",
|
||||
"no table layout cells specified",
|
||||
"no table data cells specified",
|
||||
"ignore data in cell",
|
||||
"data block still open",
|
||||
"ignoring extra data cells",
|
||||
"non-alphabetic character in tbl options",
|
||||
"skipping unknown tbl option",
|
||||
"missing tbl option argument",
|
||||
"wrong tbl option argument size",
|
||||
"empty tbl layout",
|
||||
"invalid character in tbl layout",
|
||||
"unmatched parenthesis in tbl layout",
|
||||
"tbl without any data cells",
|
||||
"ignoring data in spanned tbl cell",
|
||||
"ignoring extra tbl data cells",
|
||||
"data block open at end of tbl",
|
||||
|
||||
/* related to document structure and macros */
|
||||
NULL,
|
||||
"input stack limit exceeded, infinite loop?",
|
||||
"skipping bad character",
|
||||
"skipping unknown macro",
|
||||
"skipping insecure request",
|
||||
"skipping item outside list",
|
||||
"skipping column outside column list",
|
||||
"skipping end of block that is not open",
|
||||
"fewer RS blocks open, skipping",
|
||||
"inserting missing end of block",
|
||||
"appending missing end of block",
|
||||
|
||||
/* related to request and macro arguments */
|
||||
"escaped character not allowed in a name",
|
||||
"argument count wrong",
|
||||
"NOT IMPLEMENTED: Bd -file",
|
||||
"missing list type, using -item",
|
||||
"missing manual name, using \"\"",
|
||||
"uname(3) system call failed, using UNKNOWN",
|
||||
"unknown standard specifier",
|
||||
"skipping request without numeric argument",
|
||||
"NOT IMPLEMENTED: .so with absolute path or \"..\"",
|
||||
".so request failed",
|
||||
"skipping all arguments",
|
||||
"skipping excess arguments",
|
||||
"divide by zero",
|
||||
|
||||
"generic fatal error",
|
||||
|
||||
"unsupported feature",
|
||||
"input too large",
|
||||
"NOT IMPLEMENTED: .so with absolute path or \"..\"",
|
||||
".so request failed",
|
||||
|
||||
/* system errors */
|
||||
"cannot dup file descriptor",
|
||||
"cannot exec",
|
||||
"gunzip failed with code",
|
||||
"cannot fork",
|
||||
NULL,
|
||||
"cannot open pipe",
|
||||
"cannot read file",
|
||||
"gunzip died from signal",
|
||||
"cannot stat file",
|
||||
"wait failed",
|
||||
"unsupported control character",
|
||||
"unsupported roff request",
|
||||
"eqn delim option in tbl",
|
||||
"unsupported tbl layout modifier",
|
||||
"ignoring macro in table",
|
||||
};
|
||||
|
||||
static const char * const mandoclevels[MANDOCLEVEL_MAX] = {
|
||||
@ -236,7 +242,7 @@ static const char * const mandoclevels[MANDOCLEVEL_MAX] = {
|
||||
"RESERVED",
|
||||
"WARNING",
|
||||
"ERROR",
|
||||
"FATAL",
|
||||
"UNSUPP",
|
||||
"BADARG",
|
||||
"SYSERR"
|
||||
};
|
||||
@ -297,7 +303,8 @@ choose_parser(struct mparse *curp)
|
||||
/* Fall back to man(7) as a last resort. */
|
||||
|
||||
if (NULL == curp->pman)
|
||||
curp->pman = man_alloc(curp->roff, curp,
|
||||
curp->pman = man_alloc(
|
||||
curp->roff, curp, curp->defos,
|
||||
MPARSE_QUICK & curp->options ? 1 : 0);
|
||||
assert(curp->pman);
|
||||
curp->man = curp->pman;
|
||||
@ -315,10 +322,14 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
|
||||
{
|
||||
const struct tbl_span *span;
|
||||
struct buf ln;
|
||||
const char *save_file;
|
||||
char *cp;
|
||||
size_t pos; /* byte number in the ln buffer */
|
||||
enum rofferr rr;
|
||||
int of;
|
||||
int lnn; /* line number in the real file */
|
||||
int fd;
|
||||
pid_t save_child;
|
||||
unsigned char c;
|
||||
|
||||
memset(&ln, 0, sizeof(ln));
|
||||
@ -373,9 +384,8 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
|
||||
if (c & 0x80) {
|
||||
if ( ! (curp->filenc && preconv_encode(
|
||||
&blk, &i, &ln, &pos, &curp->filenc))) {
|
||||
mandoc_vmsg(MANDOCERR_BADCHAR,
|
||||
curp, curp->line, pos,
|
||||
"0x%x", c);
|
||||
mandoc_vmsg(MANDOCERR_CHAR_BAD, curp,
|
||||
curp->line, pos, "0x%x", c);
|
||||
ln.buf[pos++] = '?';
|
||||
i++;
|
||||
}
|
||||
@ -387,10 +397,13 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
|
||||
*/
|
||||
|
||||
if (c == 0x7f || (c < 0x20 && c != 0x09)) {
|
||||
mandoc_vmsg(MANDOCERR_BADCHAR, curp,
|
||||
curp->line, pos, "0x%x", c);
|
||||
mandoc_vmsg(c == 0x00 || c == 0x04 ||
|
||||
c > 0x0a ? MANDOCERR_CHAR_BAD :
|
||||
MANDOCERR_CHAR_UNSUPP,
|
||||
curp, curp->line, pos, "0x%x", c);
|
||||
i++;
|
||||
ln.buf[pos++] = '?';
|
||||
if (c != '\r')
|
||||
ln.buf[pos++] = '?';
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -444,7 +457,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
|
||||
|
||||
if ( ! (isascii(c) &&
|
||||
(isgraph(c) || isblank(c)))) {
|
||||
mandoc_vmsg(MANDOCERR_BADCHAR, curp,
|
||||
mandoc_vmsg(MANDOCERR_CHAR_BAD, curp,
|
||||
curp->line, pos, "0x%x", c);
|
||||
i += 2;
|
||||
ln.buf[pos++] = '?';
|
||||
@ -513,9 +526,6 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
|
||||
case ROFF_IGN:
|
||||
pos = 0;
|
||||
continue;
|
||||
case ROFF_ERR:
|
||||
assert(MANDOCLEVEL_FATAL <= curp->file_status);
|
||||
break;
|
||||
case ROFF_SO:
|
||||
if ( ! (curp->options & MPARSE_SO) &&
|
||||
(i >= blk.sz || blk.buf[i] == '\0')) {
|
||||
@ -530,27 +540,32 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
|
||||
*/
|
||||
if (curp->secondary)
|
||||
curp->secondary->sz -= pos + 1;
|
||||
mparse_readfd(curp, -1, ln.buf + of);
|
||||
if (MANDOCLEVEL_FATAL <= curp->file_status) {
|
||||
save_file = curp->file;
|
||||
save_child = curp->child;
|
||||
if (mparse_open(curp, &fd, ln.buf + of) ==
|
||||
MANDOCLEVEL_OK) {
|
||||
mparse_readfd(curp, fd, ln.buf + of);
|
||||
curp->file = save_file;
|
||||
} else {
|
||||
curp->file = save_file;
|
||||
mandoc_vmsg(MANDOCERR_SO_FAIL,
|
||||
curp, curp->line, pos,
|
||||
".so %s", ln.buf + of);
|
||||
break;
|
||||
ln.sz = mandoc_asprintf(&cp,
|
||||
".sp\nSee the file %s.\n.sp",
|
||||
ln.buf + of);
|
||||
free(ln.buf);
|
||||
ln.buf = cp;
|
||||
of = 0;
|
||||
mparse_buf_r(curp, ln, of, 0);
|
||||
}
|
||||
curp->child = save_child;
|
||||
pos = 0;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we encounter errors in the recursive parse, make
|
||||
* sure we don't continue parsing.
|
||||
*/
|
||||
|
||||
if (MANDOCLEVEL_FATAL <= curp->file_status)
|
||||
break;
|
||||
|
||||
/*
|
||||
* If input parsers have not been allocated, do so now.
|
||||
* We keep these instanced between parsers, but set them
|
||||
@ -609,11 +624,8 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
|
||||
#if HAVE_MMAP
|
||||
struct stat st;
|
||||
if (-1 == fstat(fd, &st)) {
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
if (curp->mmsg)
|
||||
(*curp->mmsg)(MANDOCERR_SYSSTAT, curp->file_status,
|
||||
file, 0, 0, strerror(errno));
|
||||
return(0);
|
||||
perror(file);
|
||||
exit((int)MANDOCLEVEL_SYSERR);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -625,10 +637,7 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
|
||||
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
if (st.st_size >= (1U << 31)) {
|
||||
curp->file_status = MANDOCLEVEL_FATAL;
|
||||
if (curp->mmsg)
|
||||
(*curp->mmsg)(MANDOCERR_TOOLARGE,
|
||||
curp->file_status, file, 0, 0, NULL);
|
||||
mandoc_msg(MANDOCERR_TOOLARGE, curp, 0, 0, NULL);
|
||||
return(0);
|
||||
}
|
||||
*with_mmap = 1;
|
||||
@ -651,11 +660,8 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
|
||||
for (;;) {
|
||||
if (off == fb->sz) {
|
||||
if (fb->sz == (1U << 31)) {
|
||||
curp->file_status = MANDOCLEVEL_FATAL;
|
||||
if (curp->mmsg)
|
||||
(*curp->mmsg)(MANDOCERR_TOOLARGE,
|
||||
curp->file_status,
|
||||
file, 0, 0, NULL);
|
||||
mandoc_msg(MANDOCERR_TOOLARGE, curp,
|
||||
0, 0, NULL);
|
||||
break;
|
||||
}
|
||||
resize_buf(fb, 65536);
|
||||
@ -666,12 +672,8 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
|
||||
return(1);
|
||||
}
|
||||
if (ssz == -1) {
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
if (curp->mmsg)
|
||||
(*curp->mmsg)(MANDOCERR_SYSREAD,
|
||||
curp->file_status, file, 0, 0,
|
||||
strerror(errno));
|
||||
break;
|
||||
perror(file);
|
||||
exit((int)MANDOCLEVEL_SYSERR);
|
||||
}
|
||||
off += (size_t)ssz;
|
||||
}
|
||||
@ -685,9 +687,6 @@ static void
|
||||
mparse_end(struct mparse *curp)
|
||||
{
|
||||
|
||||
if (MANDOCLEVEL_FATAL <= curp->file_status)
|
||||
return;
|
||||
|
||||
if (curp->mdoc == NULL &&
|
||||
curp->man == NULL &&
|
||||
curp->sodest == NULL) {
|
||||
@ -695,22 +694,16 @@ mparse_end(struct mparse *curp)
|
||||
curp->mdoc = curp->pmdoc;
|
||||
else {
|
||||
if (curp->pman == NULL)
|
||||
curp->pman = man_alloc(curp->roff, curp,
|
||||
curp->pman = man_alloc(
|
||||
curp->roff, curp, curp->defos,
|
||||
curp->options & MPARSE_QUICK ? 1 : 0);
|
||||
curp->man = curp->pman;
|
||||
}
|
||||
}
|
||||
|
||||
if (curp->mdoc && ! mdoc_endparse(curp->mdoc)) {
|
||||
assert(MANDOCLEVEL_FATAL <= curp->file_status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (curp->man && ! man_endparse(curp->man)) {
|
||||
assert(MANDOCLEVEL_FATAL <= curp->file_status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (curp->mdoc)
|
||||
mdoc_endparse(curp->mdoc);
|
||||
if (curp->man)
|
||||
man_endparse(curp->man);
|
||||
roff_endparse(curp->roff);
|
||||
}
|
||||
|
||||
@ -747,7 +740,7 @@ mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file)
|
||||
|
||||
mparse_buf_r(curp, blk, offset, 1);
|
||||
|
||||
if (0 == --recursion_depth && MANDOCLEVEL_FATAL > curp->file_status)
|
||||
if (--recursion_depth == 0)
|
||||
mparse_end(curp);
|
||||
|
||||
curp->primary = svprimary;
|
||||
@ -768,8 +761,6 @@ mparse_readmem(struct mparse *curp, void *buf, size_t len,
|
||||
}
|
||||
|
||||
/*
|
||||
* If a file descriptor is given, use it and assume it points
|
||||
* to the named file. Otherwise, open the named file.
|
||||
* Read the whole file into memory and call the parsers.
|
||||
* Called recursively when an .so request is encountered.
|
||||
*/
|
||||
@ -779,13 +770,6 @@ mparse_readfd(struct mparse *curp, int fd, const char *file)
|
||||
struct buf blk;
|
||||
int with_mmap;
|
||||
int save_filenc;
|
||||
pid_t save_child;
|
||||
|
||||
save_child = curp->child;
|
||||
if (fd != -1)
|
||||
curp->child = 0;
|
||||
else if (mparse_open(curp, &fd, file) >= MANDOCLEVEL_SYSERR)
|
||||
goto out;
|
||||
|
||||
if (read_whole_file(curp, file, fd, &blk, &with_mmap)) {
|
||||
save_filenc = curp->filenc;
|
||||
@ -805,8 +789,6 @@ mparse_readfd(struct mparse *curp, int fd, const char *file)
|
||||
perror(file);
|
||||
|
||||
mparse_wait(curp);
|
||||
out:
|
||||
curp->child = save_child;
|
||||
return(curp->file_status);
|
||||
}
|
||||
|
||||
@ -816,9 +798,7 @@ mparse_open(struct mparse *curp, int *fd, const char *file)
|
||||
int pfd[2];
|
||||
int save_errno;
|
||||
char *cp;
|
||||
enum mandocerr err;
|
||||
|
||||
pfd[1] = -1;
|
||||
curp->file = file;
|
||||
|
||||
/* Unless zipped, try to just open the file. */
|
||||
@ -842,50 +822,38 @@ mparse_open(struct mparse *curp, int *fd, const char *file)
|
||||
if (access(file, R_OK) == -1) {
|
||||
if (cp != NULL)
|
||||
errno = save_errno;
|
||||
err = MANDOCERR_SYSOPEN;
|
||||
goto out;
|
||||
free(cp);
|
||||
*fd = -1;
|
||||
curp->child = 0;
|
||||
mandoc_msg(MANDOCERR_FILE, curp, 0, 0, strerror(errno));
|
||||
return(MANDOCLEVEL_ERROR);
|
||||
}
|
||||
|
||||
/* Run gunzip(1). */
|
||||
|
||||
if (pipe(pfd) == -1) {
|
||||
err = MANDOCERR_SYSPIPE;
|
||||
goto out;
|
||||
perror("pipe");
|
||||
exit((int)MANDOCLEVEL_SYSERR);
|
||||
}
|
||||
|
||||
switch (curp->child = fork()) {
|
||||
case -1:
|
||||
err = MANDOCERR_SYSFORK;
|
||||
close(pfd[0]);
|
||||
close(pfd[1]);
|
||||
pfd[1] = -1;
|
||||
break;
|
||||
perror("fork");
|
||||
exit((int)MANDOCLEVEL_SYSERR);
|
||||
case 0:
|
||||
close(pfd[0]);
|
||||
if (dup2(pfd[1], STDOUT_FILENO) == -1) {
|
||||
err = MANDOCERR_SYSDUP;
|
||||
break;
|
||||
perror("dup");
|
||||
exit((int)MANDOCLEVEL_SYSERR);
|
||||
}
|
||||
execlp("gunzip", "gunzip", "-c", file, NULL);
|
||||
err = MANDOCERR_SYSEXEC;
|
||||
break;
|
||||
perror("exec");
|
||||
exit((int)MANDOCLEVEL_SYSERR);
|
||||
default:
|
||||
close(pfd[1]);
|
||||
*fd = pfd[0];
|
||||
return(MANDOCLEVEL_OK);
|
||||
}
|
||||
|
||||
out:
|
||||
free(cp);
|
||||
*fd = -1;
|
||||
curp->child = 0;
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
if (curp->mmsg)
|
||||
(*curp->mmsg)(err, curp->file_status, curp->file,
|
||||
0, 0, strerror(errno));
|
||||
if (pfd[1] != -1)
|
||||
exit(1);
|
||||
return(curp->file_status);
|
||||
}
|
||||
|
||||
enum mandoclevel
|
||||
@ -897,22 +865,19 @@ mparse_wait(struct mparse *curp)
|
||||
return(MANDOCLEVEL_OK);
|
||||
|
||||
if (waitpid(curp->child, &status, 0) == -1) {
|
||||
mandoc_msg(MANDOCERR_SYSWAIT, curp, 0, 0,
|
||||
strerror(errno));
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
return(curp->file_status);
|
||||
perror("wait");
|
||||
exit((int)MANDOCLEVEL_SYSERR);
|
||||
}
|
||||
curp->child = 0;
|
||||
if (WIFSIGNALED(status)) {
|
||||
mandoc_vmsg(MANDOCERR_SYSSIG, curp, 0, 0,
|
||||
"%d", WTERMSIG(status));
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
return(curp->file_status);
|
||||
mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,
|
||||
"gunzip died from signal %d", WTERMSIG(status));
|
||||
return(MANDOCLEVEL_ERROR);
|
||||
}
|
||||
if (WEXITSTATUS(status)) {
|
||||
mandoc_vmsg(MANDOCERR_SYSEXIT, curp, 0, 0,
|
||||
"%d", WEXITSTATUS(status));
|
||||
curp->file_status = MANDOCLEVEL_SYSERR;
|
||||
return(curp->file_status);
|
||||
mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0,
|
||||
"gunzip failed with code %d", WEXITSTATUS(status));
|
||||
return(MANDOCLEVEL_ERROR);
|
||||
}
|
||||
return(MANDOCLEVEL_OK);
|
||||
}
|
||||
@ -923,8 +888,6 @@ mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg,
|
||||
{
|
||||
struct mparse *curp;
|
||||
|
||||
assert(wlevel <= MANDOCLEVEL_FATAL);
|
||||
|
||||
curp = mandoc_calloc(1, sizeof(struct mparse));
|
||||
|
||||
curp->options = options;
|
||||
@ -939,7 +902,8 @@ mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg,
|
||||
curp->roff, curp, curp->defos,
|
||||
curp->options & MPARSE_QUICK ? 1 : 0);
|
||||
if (curp->options & MPARSE_MAN)
|
||||
curp->pman = man_alloc(curp->roff, curp,
|
||||
curp->pman = man_alloc(
|
||||
curp->roff, curp, curp->defos,
|
||||
curp->options & MPARSE_QUICK ? 1 : 0);
|
||||
|
||||
return(curp);
|
||||
@ -1020,11 +984,11 @@ mandoc_msg(enum mandocerr er, struct mparse *m,
|
||||
{
|
||||
enum mandoclevel level;
|
||||
|
||||
level = MANDOCLEVEL_FATAL;
|
||||
level = MANDOCLEVEL_UNSUPP;
|
||||
while (er < mandoclimits[level])
|
||||
level--;
|
||||
|
||||
if (level < m->wlevel)
|
||||
if (level < m->wlevel && er != MANDOCERR_FILE)
|
||||
return;
|
||||
|
||||
if (m->mmsg)
|
||||
|
90
st.in
90
st.in
@ -1,4 +1,4 @@
|
||||
/* $Id: st.in,v 1.27 2014/11/30 21:56:18 schwarze Exp $ */
|
||||
/* $Id: st.in,v 1.28 2015/02/17 20:37:17 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -28,50 +28,50 @@
|
||||
* REMEMBER TO ADD NEW STANDARDS TO MDOC.7!
|
||||
*/
|
||||
|
||||
LINE("-p1003.1-88", "IEEE Std 1003.1-1988 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1-90", "IEEE Std 1003.1-1990 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1-96", "ISO/IEC 9945-1:1996 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1-2001", "IEEE Std 1003.1-2001 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1-2004", "IEEE Std 1003.1-2004 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1-2008", "IEEE Std 1003.1-2008 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1-2013", "IEEE Std 1003.1-2008/Cor 1-2013 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1", "IEEE Std 1003.1 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-p1003.1b", "IEEE Std 1003.1b (\\(lqPOSIX.1b\\(rq)")
|
||||
LINE("-p1003.1b-93", "IEEE Std 1003.1b-1993 (\\(lqPOSIX.1b\\(rq)")
|
||||
LINE("-p1003.1c-95", "IEEE Std 1003.1c-1995 (\\(lqPOSIX.1c\\(rq)")
|
||||
LINE("-p1003.1g-2000", "IEEE Std 1003.1g-2000 (\\(lqPOSIX.1g\\(rq)")
|
||||
LINE("-p1003.1i-95", "IEEE Std 1003.1i-1995 (\\(lqPOSIX.1i\\(rq)")
|
||||
LINE("-p1003.2", "IEEE Std 1003.2 (\\(lqPOSIX.2\\(rq)")
|
||||
LINE("-p1003.2-92", "IEEE Std 1003.2-1992 (\\(lqPOSIX.2\\(rq)")
|
||||
LINE("-p1003.2a-92", "IEEE Std 1003.2a-1992 (\\(lqPOSIX.2\\(rq)")
|
||||
LINE("-isoC", "ISO/IEC 9899:1990 (\\(lqISO\\~C90\\(rq)")
|
||||
LINE("-isoC-90", "ISO/IEC 9899:1990 (\\(lqISO\\~C90\\(rq)")
|
||||
LINE("-isoC-amd1", "ISO/IEC 9899/AMD1:1995 (\\(lqISO\\~C90, Amendment 1\\(rq)")
|
||||
LINE("-isoC-tcor1", "ISO/IEC 9899/TCOR1:1994 (\\(lqISO\\~C90, Technical Corrigendum 1\\(rq)")
|
||||
LINE("-isoC-tcor2", "ISO/IEC 9899/TCOR2:1995 (\\(lqISO\\~C90, Technical Corrigendum 2\\(rq)")
|
||||
LINE("-isoC-99", "ISO/IEC 9899:1999 (\\(lqISO\\~C99\\(rq)")
|
||||
LINE("-isoC-2011", "ISO/IEC 9899:2011 (\\(lqISO\\~C11\\(rq)")
|
||||
LINE("-iso9945-1-90", "ISO/IEC 9945-1:1990 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-iso9945-1-96", "ISO/IEC 9945-1:1996 (\\(lqPOSIX.1\\(rq)")
|
||||
LINE("-iso9945-2-93", "ISO/IEC 9945-2:1993 (\\(lqPOSIX.2\\(rq)")
|
||||
LINE("-ansiC", "ANSI X3.159-1989 (\\(lqANSI\\~C89\\(rq)")
|
||||
LINE("-ansiC-89", "ANSI X3.159-1989 (\\(lqANSI\\~C89\\(rq)")
|
||||
LINE("-p1003.1-88", "IEEE Std 1003.1-1988 (\\(LqPOSIX.1\\(Rq)")
|
||||
LINE("-p1003.1-90", "IEEE Std 1003.1-1990 (\\(LqPOSIX.1\\(Rq)")
|
||||
LINE("-p1003.1-96", "ISO/IEC 9945-1:1996 (\\(LqPOSIX.1\\(Rq)")
|
||||
LINE("-p1003.1-2001", "IEEE Std 1003.1-2001 (\\(LqPOSIX.1\\(Rq)")
|
||||
LINE("-p1003.1-2004", "IEEE Std 1003.1-2004 (\\(LqPOSIX.1\\(Rq)")
|
||||
LINE("-p1003.1-2008", "IEEE Std 1003.1-2008 (\\(LqPOSIX.1\\(Rq)")
|
||||
LINE("-p1003.1-2013", "IEEE Std 1003.1-2008/Cor 1-2013 (\\(LqPOSIX.1\\(Rq)")
|
||||
LINE("-p1003.1", "IEEE Std 1003.1 (\\(LqPOSIX.1\\(Rq)")
|
||||
LINE("-p1003.1b", "IEEE Std 1003.1b (\\(LqPOSIX.1b\\(Rq)")
|
||||
LINE("-p1003.1b-93", "IEEE Std 1003.1b-1993 (\\(LqPOSIX.1b\\(Rq)")
|
||||
LINE("-p1003.1c-95", "IEEE Std 1003.1c-1995 (\\(LqPOSIX.1c\\(Rq)")
|
||||
LINE("-p1003.1g-2000", "IEEE Std 1003.1g-2000 (\\(LqPOSIX.1g\\(Rq)")
|
||||
LINE("-p1003.1i-95", "IEEE Std 1003.1i-1995 (\\(LqPOSIX.1i\\(Rq)")
|
||||
LINE("-p1003.2", "IEEE Std 1003.2 (\\(LqPOSIX.2\\(Rq)")
|
||||
LINE("-p1003.2-92", "IEEE Std 1003.2-1992 (\\(LqPOSIX.2\\(Rq)")
|
||||
LINE("-p1003.2a-92", "IEEE Std 1003.2a-1992 (\\(LqPOSIX.2\\(Rq)")
|
||||
LINE("-isoC", "ISO/IEC 9899:1990 (\\(LqISO\\~C90\\(Rq)")
|
||||
LINE("-isoC-90", "ISO/IEC 9899:1990 (\\(LqISO\\~C90\\(Rq)")
|
||||
LINE("-isoC-amd1", "ISO/IEC 9899/AMD1:1995 (\\(LqISO\\~C90, Amendment 1\\(Rq)")
|
||||
LINE("-isoC-tcor1", "ISO/IEC 9899/TCOR1:1994 (\\(LqISO\\~C90, Technical Corrigendum 1\\(Rq)")
|
||||
LINE("-isoC-tcor2", "ISO/IEC 9899/TCOR2:1995 (\\(LqISO\\~C90, Technical Corrigendum 2\\(Rq)")
|
||||
LINE("-isoC-99", "ISO/IEC 9899:1999 (\\(LqISO\\~C99\\(Rq)")
|
||||
LINE("-isoC-2011", "ISO/IEC 9899:2011 (\\(LqISO\\~C11\\(Rq)")
|
||||
LINE("-iso9945-1-90", "ISO/IEC 9945-1:1990 (\\(LqPOSIX.1\\(Rq)")
|
||||
LINE("-iso9945-1-96", "ISO/IEC 9945-1:1996 (\\(LqPOSIX.1\\(Rq)")
|
||||
LINE("-iso9945-2-93", "ISO/IEC 9945-2:1993 (\\(LqPOSIX.2\\(Rq)")
|
||||
LINE("-ansiC", "ANSI X3.159-1989 (\\(LqANSI\\~C89\\(Rq)")
|
||||
LINE("-ansiC-89", "ANSI X3.159-1989 (\\(LqANSI\\~C89\\(Rq)")
|
||||
LINE("-ieee754", "IEEE Std 754-1985")
|
||||
LINE("-iso8802-3", "ISO 8802-3: 1989")
|
||||
LINE("-iso8601", "ISO 8601")
|
||||
LINE("-ieee1275-94", "IEEE Std 1275-1994 (\\(lqOpen Firmware\\(rq)")
|
||||
LINE("-xpg3", "X/Open Portability Guide Issue\\~3 (\\(lqXPG3\\(rq)")
|
||||
LINE("-xpg4", "X/Open Portability Guide Issue\\~4 (\\(lqXPG4\\(rq)")
|
||||
LINE("-xpg4.2", "X/Open Portability Guide Issue\\~4, Version\\~2 (\\(lqXPG4.2\\(rq)")
|
||||
LINE("-xbd5", "X/Open Base Definitions Issue\\~5 (\\(lqXBD5\\(rq)")
|
||||
LINE("-xcu5", "X/Open Commands and Utilities Issue\\~5 (\\(lqXCU5\\(rq)")
|
||||
LINE("-xsh4.2", "X/Open System Interfaces and Headers Issue\\~4, Version\\~2 (\\(lqXSH4.2\\(rq)")
|
||||
LINE("-xsh5", "X/Open System Interfaces and Headers Issue\\~5 (\\(lqXSH5\\(rq)")
|
||||
LINE("-xns5", "X/Open Networking Services Issue\\~5 (\\(lqXNS5\\(rq)")
|
||||
LINE("-xns5.2", "X/Open Networking Services Issue\\~5.2 (\\(lqXNS5.2\\(rq)")
|
||||
LINE("-xcurses4.2", "X/Open Curses Issue\\~4, Version\\~2 (\\(lqXCURSES4.2\\(rq)")
|
||||
LINE("-susv1", "Version\\~1 of the Single UNIX Specification (\\(lqSUSv1\\(rq)")
|
||||
LINE("-susv2", "Version\\~2 of the Single UNIX Specification (\\(lqSUSv2\\(rq)")
|
||||
LINE("-susv3", "Version\\~3 of the Single UNIX Specification (\\(lqSUSv3\\(rq)")
|
||||
LINE("-susv4", "Version\\~4 of the Single UNIX Specification (\\(lqSUSv4\\(rq)")
|
||||
LINE("-svid4", "System\\~V Interface Definition, Fourth Edition (\\(lqSVID4\\(rq)")
|
||||
LINE("-ieee1275-94", "IEEE Std 1275-1994 (\\(LqOpen Firmware\\(Rq)")
|
||||
LINE("-xpg3", "X/Open Portability Guide Issue\\~3 (\\(LqXPG3\\(Rq)")
|
||||
LINE("-xpg4", "X/Open Portability Guide Issue\\~4 (\\(LqXPG4\\(Rq)")
|
||||
LINE("-xpg4.2", "X/Open Portability Guide Issue\\~4, Version\\~2 (\\(LqXPG4.2\\(Rq)")
|
||||
LINE("-xbd5", "X/Open Base Definitions Issue\\~5 (\\(LqXBD5\\(Rq)")
|
||||
LINE("-xcu5", "X/Open Commands and Utilities Issue\\~5 (\\(LqXCU5\\(Rq)")
|
||||
LINE("-xsh4.2", "X/Open System Interfaces and Headers Issue\\~4, Version\\~2 (\\(LqXSH4.2\\(Rq)")
|
||||
LINE("-xsh5", "X/Open System Interfaces and Headers Issue\\~5 (\\(LqXSH5\\(Rq)")
|
||||
LINE("-xns5", "X/Open Networking Services Issue\\~5 (\\(LqXNS5\\(Rq)")
|
||||
LINE("-xns5.2", "X/Open Networking Services Issue\\~5.2 (\\(LqXNS5.2\\(Rq)")
|
||||
LINE("-xcurses4.2", "X/Open Curses Issue\\~4, Version\\~2 (\\(LqXCURSES4.2\\(Rq)")
|
||||
LINE("-susv1", "Version\\~1 of the Single UNIX Specification (\\(LqSUSv1\\(Rq)")
|
||||
LINE("-susv2", "Version\\~2 of the Single UNIX Specification (\\(LqSUSv2\\(Rq)")
|
||||
LINE("-susv3", "Version\\~3 of the Single UNIX Specification (\\(LqSUSv3\\(Rq)")
|
||||
LINE("-susv4", "Version\\~4 of the Single UNIX Specification (\\(LqSUSv4\\(Rq)")
|
||||
LINE("-svid4", "System\\~V Interface Definition, Fourth Edition (\\(LqSVID4\\(Rq)")
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: style.css,v 1.30 2014/09/27 11:16:24 kristaps Exp $ */
|
||||
/* $Id: style.css,v 1.31 2015/02/10 08:05:30 schwarze Exp $ */
|
||||
|
||||
/*
|
||||
* This is an example style-sheet provided for mandoc(1) and the -Thtml
|
||||
@ -51,7 +51,7 @@ small { } /* Small: SB, SM. */
|
||||
i.addr { font-weight: normal; } /* Address (Ad). */
|
||||
i.arg { font-weight: normal; } /* Command argument (Ar). */
|
||||
span.author { } /* Author name (An). */
|
||||
b.cmd { font-style: normal; } /* Command (Cm). */
|
||||
b.cmd { font-style: normal; } /* Command (Cm). */
|
||||
b.config { font-style: normal; } /* Config statement (Cd). */
|
||||
span.define { } /* Defines (Dv). */
|
||||
span.desc { } /* Nd. After em-dash. */
|
||||
|
129
tbl.3
129
tbl.3
@ -1,4 +1,4 @@
|
||||
.\" $Id: tbl.3,v 1.1 2013/06/01 05:44:39 schwarze Exp $
|
||||
.\" $Id: tbl.3,v 1.2 2015/01/30 04:11:50 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
@ -14,7 +14,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: June 1 2013 $
|
||||
.Dd $Mdocdate: January 30 2015 $
|
||||
.Dt TBL 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -79,12 +79,37 @@ It is defined in
|
||||
created in
|
||||
.Fn tbl_alloc ,
|
||||
and stored in the members
|
||||
.Va first_tbl ,
|
||||
.Va last_tbl ,
|
||||
.Fa first_tbl ,
|
||||
.Fa last_tbl ,
|
||||
and
|
||||
.Va tbl
|
||||
.Fa tbl
|
||||
of
|
||||
.Vt struct roff Bq Pa roff.c .
|
||||
.Pp
|
||||
The
|
||||
.Fa first_span ,
|
||||
.Fa current_span ,
|
||||
.Fa last_span ,
|
||||
and
|
||||
.Fa next
|
||||
members may be
|
||||
.Dv NULL .
|
||||
The
|
||||
.Fa first_row
|
||||
and
|
||||
.Fa last_row
|
||||
members may be
|
||||
.Dv NULL ,
|
||||
but if there is a span, the function
|
||||
.Fn tbl_layout
|
||||
guarantees that these pointers are not
|
||||
.Dv NULL .
|
||||
The function
|
||||
.Fn tbl_alloc
|
||||
guarantees that the
|
||||
.Fa parse
|
||||
member is not
|
||||
.Dv NULL .
|
||||
.It Vt struct tbl_opts
|
||||
This structure describes the options of one table.
|
||||
It is used as a substructure of
|
||||
@ -92,26 +117,27 @@ It is used as a substructure of
|
||||
and thus created and deleted together with it.
|
||||
It is filled in
|
||||
.Fn tbl_options .
|
||||
.It Vt struct tbl_head
|
||||
This structure describes one layout column in a table,
|
||||
in particular the vertical line to its left.
|
||||
It is allocated and filled in
|
||||
.Fn cell_alloc Bq Pa tbl_layout.c
|
||||
and referenced from the
|
||||
.Va first_head
|
||||
and
|
||||
.Va last_head
|
||||
members of
|
||||
.Vt struct tbl_node .
|
||||
.It Vt struct tbl_row
|
||||
This structure describes one layout line in a table
|
||||
by maintaining a list of all the cells in that line.
|
||||
It is allocated and filled in
|
||||
.Fn row Bq Pa tbl_layout.c
|
||||
and referenced from the
|
||||
.Va layout
|
||||
.Fa layout
|
||||
member of
|
||||
.Vt struct tbl_node .
|
||||
.Pp
|
||||
The
|
||||
.Fa next
|
||||
member may be
|
||||
.Dv NULL .
|
||||
The function
|
||||
.Fn tbl_layout
|
||||
guarantees that the
|
||||
.Fa first
|
||||
and
|
||||
.Fa last
|
||||
members are not NULL.
|
||||
.It Vt struct tbl_cell
|
||||
This structure describes one layout cell in a table,
|
||||
in particular its alignment, membership in spans, and
|
||||
@ -119,11 +145,16 @@ usage for lines.
|
||||
It is allocated and filled in
|
||||
.Fn cell_alloc Bq Pa tbl_layout.c
|
||||
and referenced from the
|
||||
.Va first
|
||||
.Fa first
|
||||
and
|
||||
.Va last
|
||||
.Fa last
|
||||
members of
|
||||
.Vt struct tbl_row .
|
||||
.Pp
|
||||
The
|
||||
.Fa next
|
||||
member may be
|
||||
.Dv NULL .
|
||||
.It Vt struct tbl_span
|
||||
This structure describes one data line in a table
|
||||
by maintaining a list of all data cells in that line
|
||||
@ -133,14 +164,14 @@ It is allocated and filled in
|
||||
which is called from
|
||||
.Fn tbl_data
|
||||
and referenced from the
|
||||
.Va first_span ,
|
||||
.Va current_span ,
|
||||
.Fa first_span ,
|
||||
.Fa current_span ,
|
||||
and
|
||||
.Va last_span
|
||||
.Fa last_span
|
||||
members of
|
||||
.Vt struct tbl_node ,
|
||||
and from the
|
||||
.Va span
|
||||
.Fa span
|
||||
members of
|
||||
.Vt struct man_node
|
||||
and
|
||||
@ -149,18 +180,48 @@ from
|
||||
.In man.h
|
||||
and
|
||||
.In mdoc.h .
|
||||
.Pp
|
||||
The
|
||||
.Fa first ,
|
||||
.Fa last ,
|
||||
.Fa prev ,
|
||||
and
|
||||
.Fa next
|
||||
members may be
|
||||
.Dv NULL .
|
||||
The function
|
||||
.Fn newspan Bq Pa tbl_data.c
|
||||
guarantees that the
|
||||
.Fa opts
|
||||
and
|
||||
.Fa layout
|
||||
members are not
|
||||
.Dv NULL .
|
||||
.It Vt struct tbl_dat
|
||||
This structure describes one data cell in a table by specifying
|
||||
whether it contains a line or data, whether it spans additional
|
||||
layout cells, and by storing the data.
|
||||
It is allocated and filled in
|
||||
.Fn data
|
||||
.Fn tbl_data
|
||||
and referenced from the
|
||||
.Va first
|
||||
.Fa first
|
||||
and
|
||||
.Va last
|
||||
.Fa last
|
||||
members of
|
||||
.Vt struct tbl_span .
|
||||
.Pp
|
||||
The
|
||||
.Fa string
|
||||
and
|
||||
.Fa next
|
||||
members may be
|
||||
.Dv NULL .
|
||||
The function
|
||||
.Fn getdata
|
||||
guarantees that the
|
||||
.Fa layout
|
||||
member is not
|
||||
.Dv NULL .
|
||||
.El
|
||||
.Ss Interface functions
|
||||
The following functions are implemented in
|
||||
@ -185,7 +246,7 @@ Called from
|
||||
.Fn roff_parseln .
|
||||
.It Fn tbl_restart
|
||||
Resets the
|
||||
.Va part
|
||||
.Fa part
|
||||
member of
|
||||
.Vt struct tbl_node
|
||||
to
|
||||
@ -210,7 +271,7 @@ and
|
||||
.It Fn tbl_free
|
||||
Frees the specified
|
||||
.Vt struct tbl_node
|
||||
and all the tbl_row, tbl_cell, tbl_span, tbl_dat and tbl_head structures
|
||||
and all the tbl_row, tbl_cell, tbl_span, and tbl_dat structures
|
||||
referenced from it.
|
||||
Called from
|
||||
.Fn roff_free
|
||||
@ -228,10 +289,8 @@ called from
|
||||
.Fn tbl_read .
|
||||
.It Ft int Fn tbl_layout "struct tbl_node *tbl" "int ln" "const char *p"
|
||||
Allocates and fills one
|
||||
.Vt struct tbl_head
|
||||
for each layout column, one
|
||||
.Vt struct tbl_row
|
||||
for each layout line, and one
|
||||
for each layout line and one
|
||||
.Vt struct tbl_cell
|
||||
for each layout cell.
|
||||
Implemented in
|
||||
@ -242,8 +301,8 @@ called from
|
||||
Allocates one
|
||||
.Vt struct tbl_span
|
||||
for each data line and calls
|
||||
.Fn data
|
||||
on that line.
|
||||
.Fn getdata
|
||||
for each data cell.
|
||||
Implemented in
|
||||
.Pa tbl_data.c ,
|
||||
called from
|
||||
@ -255,7 +314,7 @@ When finding
|
||||
switches back to
|
||||
.Dv TBL_PART_DATA
|
||||
mode and calls
|
||||
.Fn data
|
||||
.Fn getdata
|
||||
if there are more data cells on the line.
|
||||
Otherwise, appends the data to the current data cell.
|
||||
Implemented in
|
||||
@ -264,7 +323,7 @@ called from
|
||||
.Fn tbl_read .
|
||||
.It Xo
|
||||
.Ft int
|
||||
.Fo data
|
||||
.Fo getdata
|
||||
.Fa "struct tbl_node *tbl"
|
||||
.Fa "struct tbl_span *dp"
|
||||
.Fa "int ln"
|
||||
|
143
tbl.7
143
tbl.7
@ -1,7 +1,7 @@
|
||||
.\" $Id: tbl.7,v 1.21 2014/11/26 17:51:55 schwarze Exp $
|
||||
.\" $Id: tbl.7,v 1.26 2015/01/29 00:33:57 schwarze Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\" Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
@ -15,7 +15,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: November 26 2014 $
|
||||
.Dd $Mdocdate: January 29 2015 $
|
||||
.Dt TBL 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -50,7 +50,7 @@ macro tags, whose precise syntax is documented in
|
||||
Tables consist of a series of options on a single line, followed by the
|
||||
table layout, followed by data.
|
||||
.Pp
|
||||
For example, the following creates a boxed table with digits centred in
|
||||
For example, the following creates a boxed table with digits centered in
|
||||
the cells.
|
||||
.Bd -literal -offset indent
|
||||
\&.TS
|
||||
@ -133,58 +133,59 @@ c c c.
|
||||
in the case of
|
||||
.Xr man 7 .
|
||||
.Ss Options
|
||||
The first line of a table consists of space-separated option keys and
|
||||
modifiers terminated by a semicolon.
|
||||
For GNU compatibility, option keys can also be separated by commas.
|
||||
The first line of a table may contain options separated by spaces, tabs,
|
||||
or commas and terminated by a semicolon.
|
||||
If the first line does not have a terminating semicolon, it is assumed
|
||||
that no options are specified and instead a
|
||||
.Sx Layout
|
||||
is processed.
|
||||
Some options accept arguments enclosed by parenthesis.
|
||||
Some options require arguments enclosed by parentheses.
|
||||
The following case-insensitive options are available:
|
||||
.Bl -tag -width Ds
|
||||
.It Cm center
|
||||
This option is not supported by
|
||||
.Xr mandoc 1 .
|
||||
This may also be invoked with
|
||||
.Cm centre .
|
||||
.It Cm delim
|
||||
Accepts a two-character argument.
|
||||
This option is not supported by
|
||||
.Xr mandoc 1 .
|
||||
.It Cm expand
|
||||
This option is not supported by
|
||||
.Xr mandoc 1 .
|
||||
.It Cm allbox
|
||||
Draw a single-line box around each table cell.
|
||||
Currently treated as a synonym for
|
||||
.Cm box .
|
||||
.It Cm box
|
||||
Draw a single-line box around the table.
|
||||
This may also be invoked with
|
||||
For GNU compatibility, this may also be invoked with
|
||||
.Cm frame .
|
||||
.It Cm doublebox
|
||||
Draw a double-line box around the table.
|
||||
This may also be invoked with
|
||||
.Cm doubleframe .
|
||||
.It Cm allbox
|
||||
This option is not supported by
|
||||
.Xr mandoc 1 .
|
||||
.It Cm tab
|
||||
Accepts a single-character argument.
|
||||
This character is used as a delimiter between data cells, which otherwise
|
||||
defaults to the tab character.
|
||||
.It Cm linesize
|
||||
Accepts a natural number (all digits).
|
||||
This option is not supported by
|
||||
.Xr mandoc 1 .
|
||||
.It Cm nokeep
|
||||
This option is not supported by
|
||||
.Xr mandoc 1 .
|
||||
.It Cm center
|
||||
Center the table instead of left-adjusting it.
|
||||
For GNU compatibility, this may also be invoked with
|
||||
.Cm centre .
|
||||
.It Cm decimalpoint
|
||||
Accepts a single-character argument.
|
||||
This character will be used as the decimal point with the
|
||||
Use the single-character argument as the decimal point with the
|
||||
.Cm n
|
||||
layout key.
|
||||
This is a GNU extension.
|
||||
.It Cm delim
|
||||
Use the two characters of the argument as
|
||||
.Xr eqn 7
|
||||
delimiters.
|
||||
Currently unsupported.
|
||||
.It Cm doublebox
|
||||
Draw a double-line box around the table.
|
||||
For GNU compatibility, this may also be invoked with
|
||||
.Cm doubleframe .
|
||||
.It Cm expand
|
||||
Increase the width of the table to the current line length.
|
||||
Currently ignored.
|
||||
.It Cm linesize
|
||||
Draw lines with the point size given by the unsigned integer argument.
|
||||
Currently ignored.
|
||||
.It Cm nokeep
|
||||
Allow page breaks within the table.
|
||||
This is a GNU extension and currently ignored.
|
||||
.It Cm nospaces
|
||||
This option is not supported by
|
||||
.Xr mandoc 1 .
|
||||
Ignore leading and trailing spaces in data cells.
|
||||
This is a GNU extension and currently ignored.
|
||||
.It Cm nowarn
|
||||
Suppress warnings about tables exceeding the current line length.
|
||||
This is a GNU extension and currently ignored.
|
||||
.It Cm tab
|
||||
Use the single-character argument as a delimiter between data cells.
|
||||
By default, the tab character is used.
|
||||
.El
|
||||
.Ss Layout
|
||||
The table layout follows
|
||||
@ -199,7 +200,7 @@ Layout lines may also be separated by a comma.
|
||||
Each layout cell consists of one of the following case-insensitive keys:
|
||||
.Bl -tag -width 2n
|
||||
.It Cm c
|
||||
Centre a literal string within its column.
|
||||
Center a literal string within its column.
|
||||
.It Cm r
|
||||
Right-justify a literal string within its column.
|
||||
.It Cm l
|
||||
@ -249,6 +250,9 @@ The following case-insensitive modifier keys are available:
|
||||
.Bl -tag -width 2n
|
||||
.It Cm b
|
||||
Use a bold font for the contents of this column.
|
||||
.It Cm d
|
||||
Move cell content down to the last cell of a vertical span.
|
||||
Currently ignored.
|
||||
.It Cm e
|
||||
Make this column wider to match the maximum width
|
||||
of any other column also having the
|
||||
@ -261,6 +265,27 @@ See the
|
||||
manual for supported one-character font names.
|
||||
.It Cm i
|
||||
Use an italic font for the contents of this column.
|
||||
.It Cm m
|
||||
Specify a cell start macro.
|
||||
This is a GNU extension and currently unsupported.
|
||||
.It Cm p
|
||||
Set the point size to the following unsigned argument,
|
||||
or change it by the following signed argument.
|
||||
Currently ignored.
|
||||
.It Cm v
|
||||
Set the vertical line spacing to the following unsigned argument,
|
||||
or change it by the following signed argument.
|
||||
Currently ignored.
|
||||
.It Cm t
|
||||
Do not vertically center cell content in the vertical span,
|
||||
leave it at the top.
|
||||
Currently ignored.
|
||||
.It Cm u
|
||||
Move cell content up by half a table line.
|
||||
Currently ignored.
|
||||
.It Cm w
|
||||
Specify minimum column width.
|
||||
Currently ignored.
|
||||
.It Cm x
|
||||
After determining the width of all other columns, distribute the
|
||||
rest of the line length among all columns having the
|
||||
@ -270,16 +295,7 @@ modifier.
|
||||
Do not use this cell for determining the width of this column.
|
||||
.El
|
||||
.Pp
|
||||
The modifiers
|
||||
.Cm d ,
|
||||
.Cm t ,
|
||||
.Cm u ,
|
||||
and
|
||||
.Cm w
|
||||
are ignored by
|
||||
.Xr mandoc 1 .
|
||||
.Pp
|
||||
For example, the following layout specifies a centre-justified column of
|
||||
For example, the following layout specifies a center-justified column of
|
||||
minimum width 10, followed by vertical bar, followed by a left-justified
|
||||
column of minimum width 10, another vertical bar, then a column using
|
||||
bold font justified about the decimal point in numbers:
|
||||
@ -312,18 +328,17 @@ It may then be followed by a tab
|
||||
.Pq or as designated by Cm tab
|
||||
or an end-of-line to terminate the row.
|
||||
.Sh COMPATIBILITY
|
||||
This section documents compatibility between mandoc and other
|
||||
.Nm
|
||||
implementations, at this time limited to GNU tbl.
|
||||
.Pp
|
||||
.Bl -dash -compact
|
||||
.It
|
||||
In GNU tbl, comments and macros are disallowed prior to the data block
|
||||
of a table.
|
||||
The
|
||||
.Xr mandoc 1
|
||||
implementation allows them.
|
||||
.El
|
||||
implementation of
|
||||
.Nm
|
||||
doesn't support
|
||||
.Xr mdoc 7
|
||||
and
|
||||
.Xr man 7
|
||||
macros and
|
||||
.Xr eqn 7
|
||||
equations inside tables.
|
||||
.Sh SEE ALSO
|
||||
.Xr mandoc 1 ,
|
||||
.Xr man 7 ,
|
||||
|
115
tbl.c
115
tbl.c
@ -1,7 +1,7 @@
|
||||
/* $Id: tbl.c,v 1.30 2014/08/10 23:54:41 schwarze Exp $ */
|
||||
/* $Id: tbl.c,v 1.39 2015/01/30 17:32:16 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -32,43 +32,58 @@
|
||||
|
||||
|
||||
enum rofferr
|
||||
tbl_read(struct tbl_node *tbl, int ln, const char *p, int offs)
|
||||
tbl_read(struct tbl_node *tbl, int ln, const char *p, int pos)
|
||||
{
|
||||
int len;
|
||||
const char *cp;
|
||||
|
||||
cp = &p[offs];
|
||||
len = (int)strlen(cp);
|
||||
int active;
|
||||
|
||||
/*
|
||||
* If we're in the options section and we don't have a
|
||||
* terminating semicolon, assume we've moved directly into the
|
||||
* layout section. No need to report a warning: this is,
|
||||
* apparently, standard behaviour.
|
||||
* In the options section, proceed to the layout section
|
||||
* after a semicolon, or right away if there is no semicolon.
|
||||
* Ignore semicolons in arguments.
|
||||
*/
|
||||
|
||||
if (TBL_PART_OPTS == tbl->part && len)
|
||||
if (';' != cp[len - 1])
|
||||
tbl->part = TBL_PART_LAYOUT;
|
||||
if (tbl->part == TBL_PART_OPTS) {
|
||||
tbl->part = TBL_PART_LAYOUT;
|
||||
active = 1;
|
||||
for (cp = p + pos; *cp != '\0'; cp++) {
|
||||
switch (*cp) {
|
||||
case '(':
|
||||
active = 0;
|
||||
continue;
|
||||
case ')':
|
||||
active = 1;
|
||||
continue;
|
||||
case ';':
|
||||
if (active)
|
||||
break;
|
||||
continue;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (*cp == ';') {
|
||||
tbl_option(tbl, ln, p, &pos);
|
||||
if (p[pos] == '\0')
|
||||
return(ROFF_IGN);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now process each logical section of the table. */
|
||||
/* Process the other section types. */
|
||||
|
||||
switch (tbl->part) {
|
||||
case TBL_PART_OPTS:
|
||||
return(tbl_option(tbl, ln, p) ? ROFF_IGN : ROFF_ERR);
|
||||
case TBL_PART_LAYOUT:
|
||||
return(tbl_layout(tbl, ln, p) ? ROFF_IGN : ROFF_ERR);
|
||||
tbl_layout(tbl, ln, p, pos);
|
||||
return(ROFF_IGN);
|
||||
case TBL_PART_CDATA:
|
||||
return(tbl_cdata(tbl, ln, p) ? ROFF_TBL : ROFF_IGN);
|
||||
return(tbl_cdata(tbl, ln, p, pos) ? ROFF_TBL : ROFF_IGN);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* This only returns zero if the line is empty, so we ignore it
|
||||
* and continue on.
|
||||
*/
|
||||
return(tbl_data(tbl, ln, p) ? ROFF_TBL : ROFF_IGN);
|
||||
tbl_data(tbl, ln, p, pos);
|
||||
return(ROFF_TBL);
|
||||
}
|
||||
|
||||
struct tbl_node *
|
||||
@ -76,13 +91,12 @@ tbl_alloc(int pos, int line, struct mparse *parse)
|
||||
{
|
||||
struct tbl_node *tbl;
|
||||
|
||||
tbl = mandoc_calloc(1, sizeof(struct tbl_node));
|
||||
tbl = mandoc_calloc(1, sizeof(*tbl));
|
||||
tbl->line = line;
|
||||
tbl->pos = pos;
|
||||
tbl->parse = parse;
|
||||
tbl->part = TBL_PART_OPTS;
|
||||
tbl->opts.tab = '\t';
|
||||
tbl->opts.linesize = 12;
|
||||
tbl->opts.decimal = '.';
|
||||
return(tbl);
|
||||
}
|
||||
@ -94,11 +108,10 @@ tbl_free(struct tbl_node *tbl)
|
||||
struct tbl_cell *cp;
|
||||
struct tbl_span *sp;
|
||||
struct tbl_dat *dp;
|
||||
struct tbl_head *hp;
|
||||
|
||||
while (NULL != (rp = tbl->first_row)) {
|
||||
while ((rp = tbl->first_row) != NULL) {
|
||||
tbl->first_row = rp->next;
|
||||
while (rp->first) {
|
||||
while (rp->first != NULL) {
|
||||
cp = rp->first;
|
||||
rp->first = cp->next;
|
||||
free(cp);
|
||||
@ -106,40 +119,30 @@ tbl_free(struct tbl_node *tbl)
|
||||
free(rp);
|
||||
}
|
||||
|
||||
while (NULL != (sp = tbl->first_span)) {
|
||||
while ((sp = tbl->first_span) != NULL) {
|
||||
tbl->first_span = sp->next;
|
||||
while (sp->first) {
|
||||
while (sp->first != NULL) {
|
||||
dp = sp->first;
|
||||
sp->first = dp->next;
|
||||
if (dp->string)
|
||||
free(dp->string);
|
||||
free(dp->string);
|
||||
free(dp);
|
||||
}
|
||||
free(sp);
|
||||
}
|
||||
|
||||
while (NULL != (hp = tbl->first_head)) {
|
||||
tbl->first_head = hp->next;
|
||||
free(hp);
|
||||
}
|
||||
|
||||
free(tbl);
|
||||
}
|
||||
|
||||
void
|
||||
tbl_restart(int line, int pos, struct tbl_node *tbl)
|
||||
{
|
||||
if (TBL_PART_CDATA == tbl->part)
|
||||
mandoc_msg(MANDOCERR_TBLBLOCK, tbl->parse,
|
||||
tbl->line, tbl->pos, NULL);
|
||||
if (tbl->part == TBL_PART_CDATA)
|
||||
mandoc_msg(MANDOCERR_TBLDATA_BLK, tbl->parse,
|
||||
line, pos, "T&");
|
||||
|
||||
tbl->part = TBL_PART_LAYOUT;
|
||||
tbl->line = line;
|
||||
tbl->pos = pos;
|
||||
|
||||
if (NULL == tbl->first_span || NULL == tbl->first_span->first)
|
||||
mandoc_msg(MANDOCERR_TBLNODATA, tbl->parse,
|
||||
tbl->line, tbl->pos, NULL);
|
||||
}
|
||||
|
||||
const struct tbl_span *
|
||||
@ -155,22 +158,26 @@ tbl_span(struct tbl_node *tbl)
|
||||
return(span);
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
tbl_end(struct tbl_node **tblp)
|
||||
{
|
||||
struct tbl_node *tbl;
|
||||
struct tbl_span *sp;
|
||||
|
||||
tbl = *tblp;
|
||||
*tblp = NULL;
|
||||
|
||||
if (NULL == tbl->first_span || NULL == tbl->first_span->first)
|
||||
mandoc_msg(MANDOCERR_TBLNODATA, tbl->parse,
|
||||
tbl->line, tbl->pos, NULL);
|
||||
if (tbl->part == TBL_PART_CDATA)
|
||||
mandoc_msg(MANDOCERR_TBLDATA_BLK, tbl->parse,
|
||||
tbl->line, tbl->pos, "TE");
|
||||
|
||||
if (tbl->last_span)
|
||||
tbl->last_span->flags |= TBL_SPAN_LAST;
|
||||
|
||||
if (TBL_PART_CDATA == tbl->part)
|
||||
mandoc_msg(MANDOCERR_TBLBLOCK, tbl->parse,
|
||||
sp = tbl->first_span;
|
||||
while (sp != NULL && sp->first == NULL)
|
||||
sp = sp->next;
|
||||
if (sp == NULL) {
|
||||
mandoc_msg(MANDOCERR_TBLDATA_NONE, tbl->parse,
|
||||
tbl->line, tbl->pos, NULL);
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
151
tbl_data.c
151
tbl_data.c
@ -1,7 +1,7 @@
|
||||
/* $Id: tbl_data.c,v 1.32 2014/08/10 23:54:41 schwarze Exp $ */
|
||||
/* $Id: tbl_data.c,v 1.39 2015/01/30 17:32:16 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -30,32 +30,24 @@
|
||||
#include "libmandoc.h"
|
||||
#include "libroff.h"
|
||||
|
||||
static int getdata(struct tbl_node *, struct tbl_span *,
|
||||
static void getdata(struct tbl_node *, struct tbl_span *,
|
||||
int, const char *, int *);
|
||||
static struct tbl_span *newspan(struct tbl_node *, int,
|
||||
struct tbl_row *);
|
||||
|
||||
|
||||
static int
|
||||
static void
|
||||
getdata(struct tbl_node *tbl, struct tbl_span *dp,
|
||||
int ln, const char *p, int *pos)
|
||||
{
|
||||
struct tbl_dat *dat;
|
||||
struct tbl_cell *cp;
|
||||
int sv, spans;
|
||||
int sv;
|
||||
|
||||
cp = NULL;
|
||||
if (dp->last && dp->last->layout)
|
||||
cp = dp->last->layout->next;
|
||||
else if (NULL == dp->last)
|
||||
cp = dp->layout->first;
|
||||
/* Advance to the next layout cell, skipping spanners. */
|
||||
|
||||
/*
|
||||
* Skip over spanners, since
|
||||
* we want to match data with data layout cells in the header.
|
||||
*/
|
||||
|
||||
while (cp && TBL_CELL_SPAN == cp->pos)
|
||||
cp = dp->last == NULL ? dp->layout->first : dp->last->layout->next;
|
||||
while (cp != NULL && cp->pos == TBL_CELL_SPAN)
|
||||
cp = cp->next;
|
||||
|
||||
/*
|
||||
@ -63,34 +55,30 @@ getdata(struct tbl_node *tbl, struct tbl_span *dp,
|
||||
* cells. This means that we have extra input.
|
||||
*/
|
||||
|
||||
if (NULL == cp) {
|
||||
mandoc_msg(MANDOCERR_TBLEXTRADAT, tbl->parse,
|
||||
ln, *pos, NULL);
|
||||
if (cp == NULL) {
|
||||
mandoc_msg(MANDOCERR_TBLDATA_EXTRA, tbl->parse,
|
||||
ln, *pos, p + *pos);
|
||||
/* Skip to the end... */
|
||||
while (p[*pos])
|
||||
(*pos)++;
|
||||
return(1);
|
||||
return;
|
||||
}
|
||||
|
||||
dat = mandoc_calloc(1, sizeof(struct tbl_dat));
|
||||
dat = mandoc_calloc(1, sizeof(*dat));
|
||||
dat->layout = cp;
|
||||
dat->pos = TBL_DATA_NONE;
|
||||
|
||||
assert(TBL_CELL_SPAN != cp->pos);
|
||||
|
||||
for (spans = 0, cp = cp->next; cp; cp = cp->next)
|
||||
if (TBL_CELL_SPAN == cp->pos)
|
||||
spans++;
|
||||
dat->spans = 0;
|
||||
for (cp = cp->next; cp != NULL; cp = cp->next)
|
||||
if (cp->pos == TBL_CELL_SPAN)
|
||||
dat->spans++;
|
||||
else
|
||||
break;
|
||||
|
||||
dat->spans = spans;
|
||||
|
||||
if (dp->last) {
|
||||
if (dp->last == NULL)
|
||||
dp->first = dat;
|
||||
else
|
||||
dp->last->next = dat;
|
||||
dp->last = dat;
|
||||
} else
|
||||
dp->last = dp->first = dat;
|
||||
dp->last = dat;
|
||||
|
||||
sv = *pos;
|
||||
while (p[*pos] && p[*pos] != tbl->opts.tab)
|
||||
@ -102,16 +90,12 @@ getdata(struct tbl_node *tbl, struct tbl_span *dp,
|
||||
* until a standalone `T}', are included in our cell.
|
||||
*/
|
||||
|
||||
if (*pos - sv == 2 && 'T' == p[sv] && '{' == p[sv + 1]) {
|
||||
if (*pos - sv == 2 && p[sv] == 'T' && p[sv + 1] == '{') {
|
||||
tbl->part = TBL_PART_CDATA;
|
||||
return(1);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(*pos - sv >= 0);
|
||||
|
||||
dat->string = mandoc_malloc((size_t)(*pos - sv + 1));
|
||||
memcpy(dat->string, &p[sv], (size_t)(*pos - sv));
|
||||
dat->string[*pos - sv] = '\0';
|
||||
dat->string = mandoc_strndup(p + sv, *pos - sv);
|
||||
|
||||
if (p[*pos])
|
||||
(*pos)++;
|
||||
@ -127,24 +111,19 @@ getdata(struct tbl_node *tbl, struct tbl_span *dp,
|
||||
else
|
||||
dat->pos = TBL_DATA_DATA;
|
||||
|
||||
if (TBL_CELL_HORIZ == dat->layout->pos ||
|
||||
TBL_CELL_DHORIZ == dat->layout->pos ||
|
||||
TBL_CELL_DOWN == dat->layout->pos)
|
||||
if (TBL_DATA_DATA == dat->pos && '\0' != *dat->string)
|
||||
mandoc_msg(MANDOCERR_TBLIGNDATA,
|
||||
tbl->parse, ln, sv, NULL);
|
||||
|
||||
return(1);
|
||||
if ((dat->layout->pos == TBL_CELL_HORIZ ||
|
||||
dat->layout->pos == TBL_CELL_DHORIZ ||
|
||||
dat->layout->pos == TBL_CELL_DOWN) &&
|
||||
dat->pos == TBL_DATA_DATA && *dat->string != '\0')
|
||||
mandoc_msg(MANDOCERR_TBLDATA_SPAN,
|
||||
tbl->parse, ln, sv, dat->string);
|
||||
}
|
||||
|
||||
int
|
||||
tbl_cdata(struct tbl_node *tbl, int ln, const char *p)
|
||||
tbl_cdata(struct tbl_node *tbl, int ln, const char *p, int pos)
|
||||
{
|
||||
struct tbl_dat *dat;
|
||||
size_t sz;
|
||||
int pos;
|
||||
|
||||
pos = 0;
|
||||
|
||||
dat = tbl->last_span->last;
|
||||
|
||||
@ -153,8 +132,9 @@ tbl_cdata(struct tbl_node *tbl, int ln, const char *p)
|
||||
if (p[pos] == tbl->opts.tab) {
|
||||
tbl->part = TBL_PART_DATA;
|
||||
pos++;
|
||||
return(getdata(tbl, tbl->last_span, ln, p, &pos));
|
||||
} else if ('\0' == p[pos]) {
|
||||
getdata(tbl, tbl->last_span, ln, p, &pos);
|
||||
return(1);
|
||||
} else if (p[pos] == '\0') {
|
||||
tbl->part = TBL_PART_DATA;
|
||||
return(1);
|
||||
}
|
||||
@ -164,17 +144,17 @@ tbl_cdata(struct tbl_node *tbl, int ln, const char *p)
|
||||
|
||||
dat->pos = TBL_DATA_DATA;
|
||||
|
||||
if (dat->string) {
|
||||
sz = strlen(p) + strlen(dat->string) + 2;
|
||||
if (dat->string != NULL) {
|
||||
sz = strlen(p + pos) + strlen(dat->string) + 2;
|
||||
dat->string = mandoc_realloc(dat->string, sz);
|
||||
(void)strlcat(dat->string, " ", sz);
|
||||
(void)strlcat(dat->string, p, sz);
|
||||
(void)strlcat(dat->string, p + pos, sz);
|
||||
} else
|
||||
dat->string = mandoc_strdup(p);
|
||||
dat->string = mandoc_strdup(p + pos);
|
||||
|
||||
if (TBL_CELL_DOWN == dat->layout->pos)
|
||||
mandoc_msg(MANDOCERR_TBLIGNDATA, tbl->parse,
|
||||
ln, pos, NULL);
|
||||
if (dat->layout->pos == TBL_CELL_DOWN)
|
||||
mandoc_msg(MANDOCERR_TBLDATA_SPAN, tbl->parse,
|
||||
ln, pos, dat->string);
|
||||
|
||||
return(0);
|
||||
}
|
||||
@ -184,37 +164,27 @@ newspan(struct tbl_node *tbl, int line, struct tbl_row *rp)
|
||||
{
|
||||
struct tbl_span *dp;
|
||||
|
||||
dp = mandoc_calloc(1, sizeof(struct tbl_span));
|
||||
dp = mandoc_calloc(1, sizeof(*dp));
|
||||
dp->line = line;
|
||||
dp->opts = &tbl->opts;
|
||||
dp->layout = rp;
|
||||
dp->head = tbl->first_head;
|
||||
dp->prev = tbl->last_span;
|
||||
|
||||
if (tbl->last_span) {
|
||||
tbl->last_span->next = dp;
|
||||
tbl->last_span = dp;
|
||||
} else {
|
||||
tbl->last_span = tbl->first_span = dp;
|
||||
if (dp->prev == NULL) {
|
||||
tbl->first_span = dp;
|
||||
tbl->current_span = NULL;
|
||||
dp->flags |= TBL_SPAN_FIRST;
|
||||
}
|
||||
} else
|
||||
dp->prev->next = dp;
|
||||
tbl->last_span = dp;
|
||||
|
||||
return(dp);
|
||||
}
|
||||
|
||||
int
|
||||
tbl_data(struct tbl_node *tbl, int ln, const char *p)
|
||||
void
|
||||
tbl_data(struct tbl_node *tbl, int ln, const char *p, int pos)
|
||||
{
|
||||
struct tbl_span *dp;
|
||||
struct tbl_row *rp;
|
||||
int pos;
|
||||
|
||||
pos = 0;
|
||||
|
||||
if ('\0' == p[pos]) {
|
||||
mandoc_msg(MANDOCERR_TBL, tbl->parse, ln, pos, NULL);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Choose a layout row: take the one following the last parsed
|
||||
@ -224,11 +194,11 @@ tbl_data(struct tbl_node *tbl, int ln, const char *p)
|
||||
* (it doesn't "consume" the layout).
|
||||
*/
|
||||
|
||||
if (tbl->last_span) {
|
||||
assert(tbl->last_span->layout);
|
||||
if (tbl->last_span != NULL) {
|
||||
if (tbl->last_span->pos == TBL_SPAN_DATA) {
|
||||
for (rp = tbl->last_span->layout->next;
|
||||
rp && rp->first; rp = rp->next) {
|
||||
rp != NULL && rp->first != NULL;
|
||||
rp = rp->next) {
|
||||
switch (rp->first->pos) {
|
||||
case TBL_CELL_HORIZ:
|
||||
dp = newspan(tbl, ln, rp);
|
||||
@ -246,7 +216,7 @@ tbl_data(struct tbl_node *tbl, int ln, const char *p)
|
||||
} else
|
||||
rp = tbl->last_span->layout;
|
||||
|
||||
if (NULL == rp)
|
||||
if (rp == NULL)
|
||||
rp = tbl->last_span->layout;
|
||||
} else
|
||||
rp = tbl->first_row;
|
||||
@ -257,19 +227,14 @@ tbl_data(struct tbl_node *tbl, int ln, const char *p)
|
||||
|
||||
if ( ! strcmp(p, "_")) {
|
||||
dp->pos = TBL_SPAN_HORIZ;
|
||||
return(1);
|
||||
return;
|
||||
} else if ( ! strcmp(p, "=")) {
|
||||
dp->pos = TBL_SPAN_DHORIZ;
|
||||
return(1);
|
||||
return;
|
||||
}
|
||||
|
||||
dp->pos = TBL_SPAN_DATA;
|
||||
|
||||
/* This returns 0 when TBL_PART_CDATA is entered. */
|
||||
|
||||
while ('\0' != p[pos])
|
||||
if ( ! getdata(tbl, dp, ln, p, &pos))
|
||||
return(0);
|
||||
|
||||
return(1);
|
||||
while (p[pos] != '\0')
|
||||
getdata(tbl, dp, ln, p, &pos);
|
||||
}
|
||||
|
26
tbl_html.c
26
tbl_html.c
@ -1,4 +1,4 @@
|
||||
/* $Id: tbl_html.c,v 1.13 2014/10/14 02:16:06 schwarze Exp $ */
|
||||
/* $Id: tbl_html.c,v 1.16 2015/01/30 17:32:16 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
*
|
||||
@ -49,12 +49,12 @@ html_tbl_strlen(const char *p, void *arg)
|
||||
static void
|
||||
html_tblopen(struct html *h, const struct tbl_span *sp)
|
||||
{
|
||||
const struct tbl_head *hp;
|
||||
struct htmlpair tag;
|
||||
struct roffsu su;
|
||||
struct roffcol *col;
|
||||
int ic;
|
||||
|
||||
if (TBL_SPAN_FIRST & sp->flags) {
|
||||
if (h->tbl.cols == NULL) {
|
||||
h->tbl.len = html_tbl_len;
|
||||
h->tbl.slen = html_tbl_strlen;
|
||||
tblcalc(&h->tbl, sp, 0);
|
||||
@ -64,9 +64,9 @@ html_tblopen(struct html *h, const struct tbl_span *sp)
|
||||
PAIR_CLASS_INIT(&tag, "tbl");
|
||||
h->tblt = print_otag(h, TAG_TABLE, 1, &tag);
|
||||
|
||||
for (hp = sp->head; hp; hp = hp->next) {
|
||||
for (ic = 0; ic < sp->opts->cols; ic++) {
|
||||
bufinit(h);
|
||||
col = &h->tbl.cols[hp->ident];
|
||||
col = h->tbl.cols + ic;
|
||||
SCALE_HS_INIT(&su, col->width);
|
||||
bufcat_su(h, "width", &su);
|
||||
PAIR_STYLE_INIT(&tag, h);
|
||||
@ -88,14 +88,14 @@ print_tblclose(struct html *h)
|
||||
void
|
||||
print_tbl(struct html *h, const struct tbl_span *sp)
|
||||
{
|
||||
const struct tbl_head *hp;
|
||||
const struct tbl_dat *dp;
|
||||
struct htmlpair tag;
|
||||
struct tag *tt;
|
||||
int ic;
|
||||
|
||||
/* Inhibit printing of spaces: we do padding ourselves. */
|
||||
|
||||
if (NULL == h->tblt)
|
||||
if (h->tblt == NULL)
|
||||
html_tblopen(h, sp);
|
||||
|
||||
assert(h->tblt);
|
||||
@ -114,14 +114,14 @@ print_tbl(struct html *h, const struct tbl_span *sp)
|
||||
break;
|
||||
default:
|
||||
dp = sp->first;
|
||||
for (hp = sp->head; hp; hp = hp->next) {
|
||||
for (ic = 0; ic < sp->opts->cols; ic++) {
|
||||
print_stagq(h, tt);
|
||||
print_otag(h, TAG_TD, 0, NULL);
|
||||
|
||||
if (NULL == dp)
|
||||
break;
|
||||
if (TBL_CELL_DOWN != dp->layout->pos)
|
||||
if (dp->string)
|
||||
if (dp == NULL || dp->layout->col > ic)
|
||||
continue;
|
||||
if (dp->layout->pos != TBL_CELL_DOWN)
|
||||
if (dp->string != NULL)
|
||||
print_text(h, dp->string);
|
||||
dp = dp->next;
|
||||
}
|
||||
@ -132,7 +132,7 @@ print_tbl(struct html *h, const struct tbl_span *sp)
|
||||
|
||||
h->flags &= ~HTML_NONOSPACE;
|
||||
|
||||
if (TBL_SPAN_LAST & sp->flags) {
|
||||
if (sp->next == NULL) {
|
||||
assert(h->tbl.cols);
|
||||
free(h->tbl.cols);
|
||||
h->tbl.cols = NULL;
|
||||
|
399
tbl_layout.c
399
tbl_layout.c
@ -1,7 +1,7 @@
|
||||
/* $Id: tbl_layout.c,v 1.30 2014/11/25 21:41:47 schwarze Exp $ */
|
||||
/* $Id: tbl_layout.c,v 1.38 2015/02/10 11:03:13 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -34,15 +34,7 @@ struct tbl_phrase {
|
||||
enum tbl_cellt key;
|
||||
};
|
||||
|
||||
/*
|
||||
* FIXME: we can make this parse a lot nicer by, when an error is
|
||||
* encountered in a layout key, bailing to the next key (i.e. to the
|
||||
* next whitespace then continuing).
|
||||
*/
|
||||
|
||||
#define KEYS_MAX 11
|
||||
|
||||
static const struct tbl_phrase keys[KEYS_MAX] = {
|
||||
static const struct tbl_phrase keys[] = {
|
||||
{ 'c', TBL_CELL_CENTRE },
|
||||
{ 'r', TBL_CELL_RIGHT },
|
||||
{ 'l', TBL_CELL_LEFT },
|
||||
@ -55,57 +47,30 @@ static const struct tbl_phrase keys[KEYS_MAX] = {
|
||||
{ '=', TBL_CELL_DHORIZ }
|
||||
};
|
||||
|
||||
static int mods(struct tbl_node *, struct tbl_cell *,
|
||||
#define KEYS_MAX ((int)(sizeof(keys)/sizeof(keys[0])))
|
||||
|
||||
static void mods(struct tbl_node *, struct tbl_cell *,
|
||||
int, const char *, int *);
|
||||
static int cell(struct tbl_node *, struct tbl_row *,
|
||||
static void cell(struct tbl_node *, struct tbl_row *,
|
||||
int, const char *, int *);
|
||||
static struct tbl_cell *cell_alloc(struct tbl_node *, struct tbl_row *,
|
||||
enum tbl_cellt, int vert);
|
||||
enum tbl_cellt);
|
||||
|
||||
|
||||
static int
|
||||
static void
|
||||
mods(struct tbl_node *tbl, struct tbl_cell *cp,
|
||||
int ln, const char *p, int *pos)
|
||||
{
|
||||
char buf[5];
|
||||
int i;
|
||||
|
||||
/* Not all types accept modifiers. */
|
||||
|
||||
switch (cp->pos) {
|
||||
case TBL_CELL_DOWN:
|
||||
/* FALLTHROUGH */
|
||||
case TBL_CELL_HORIZ:
|
||||
/* FALLTHROUGH */
|
||||
case TBL_CELL_DHORIZ:
|
||||
return(1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
char *endptr;
|
||||
|
||||
mod:
|
||||
/*
|
||||
* XXX: since, at least for now, modifiers are non-conflicting
|
||||
* (are separable by value, regardless of position), we let
|
||||
* modifiers come in any order. The existing tbl doesn't let
|
||||
* this happen.
|
||||
*/
|
||||
switch (p[*pos]) {
|
||||
case '\0':
|
||||
/* FALLTHROUGH */
|
||||
case ' ':
|
||||
/* FALLTHROUGH */
|
||||
case '\t':
|
||||
/* FALLTHROUGH */
|
||||
case ',':
|
||||
/* FALLTHROUGH */
|
||||
case '.':
|
||||
/* FALLTHROUGH */
|
||||
case '|':
|
||||
return(1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
while (p[*pos] == ' ' || p[*pos] == '\t')
|
||||
(*pos)++;
|
||||
|
||||
/* Row delimiters and cell specifiers end modifier lists. */
|
||||
|
||||
if (strchr(".,-=^_ACLNRSaclnrs", p[*pos]) != NULL)
|
||||
return;
|
||||
|
||||
/* Throw away parenthesised expression. */
|
||||
|
||||
@ -117,123 +82,138 @@ mods(struct tbl_node *tbl, struct tbl_cell *cp,
|
||||
(*pos)++;
|
||||
goto mod;
|
||||
}
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT_PAR, tbl->parse,
|
||||
ln, *pos, NULL);
|
||||
return(0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parse numerical spacing from modifier string. */
|
||||
|
||||
if (isdigit((unsigned char)p[*pos])) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if ( ! isdigit((unsigned char)p[*pos + i]))
|
||||
break;
|
||||
buf[i] = p[*pos + i];
|
||||
}
|
||||
buf[i] = '\0';
|
||||
|
||||
/* No greater than 4 digits. */
|
||||
|
||||
if (4 == i) {
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT,
|
||||
tbl->parse, ln, *pos, NULL);
|
||||
return(0);
|
||||
}
|
||||
|
||||
*pos += i;
|
||||
cp->spacing = (size_t)atoi(buf);
|
||||
|
||||
cp->spacing = strtoull(p + *pos, &endptr, 10);
|
||||
*pos = endptr - p;
|
||||
goto mod;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* TODO: GNU has many more extensions. */
|
||||
|
||||
switch (tolower((unsigned char)p[(*pos)++])) {
|
||||
case 'z':
|
||||
cp->flags |= TBL_CELL_WIGN;
|
||||
case 'b':
|
||||
cp->flags |= TBL_CELL_BOLD;
|
||||
goto mod;
|
||||
case 'u':
|
||||
cp->flags |= TBL_CELL_UP;
|
||||
case 'd':
|
||||
cp->flags |= TBL_CELL_BALIGN;
|
||||
goto mod;
|
||||
case 'e':
|
||||
cp->flags |= TBL_CELL_EQUAL;
|
||||
goto mod;
|
||||
case 'f':
|
||||
break;
|
||||
case 'i':
|
||||
cp->flags |= TBL_CELL_ITALIC;
|
||||
goto mod;
|
||||
case 'm':
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT_MOD, tbl->parse,
|
||||
ln, *pos, "m");
|
||||
goto mod;
|
||||
case 'p':
|
||||
/* FALLTHROUGH */
|
||||
case 'v':
|
||||
if (p[*pos] == '-' || p[*pos] == '+')
|
||||
(*pos)++;
|
||||
while (isdigit((unsigned char)p[*pos]))
|
||||
(*pos)++;
|
||||
goto mod;
|
||||
case 't':
|
||||
cp->flags |= TBL_CELL_TALIGN;
|
||||
goto mod;
|
||||
case 'd':
|
||||
cp->flags |= TBL_CELL_BALIGN;
|
||||
case 'u':
|
||||
cp->flags |= TBL_CELL_UP;
|
||||
goto mod;
|
||||
case 'w': /* XXX for now, ignore minimal column width */
|
||||
goto mod;
|
||||
case 'x':
|
||||
cp->flags |= TBL_CELL_WMAX;
|
||||
goto mod;
|
||||
case 'f':
|
||||
break;
|
||||
case 'r':
|
||||
/* FALLTHROUGH */
|
||||
case 'b':
|
||||
/* FALLTHROUGH */
|
||||
case 'i':
|
||||
(*pos)--;
|
||||
break;
|
||||
case 'z':
|
||||
cp->flags |= TBL_CELL_WIGN;
|
||||
goto mod;
|
||||
case '|':
|
||||
if (cp->vert < 2)
|
||||
cp->vert++;
|
||||
else
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT_VERT,
|
||||
tbl->parse, ln, *pos - 1, NULL);
|
||||
goto mod;
|
||||
default:
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
|
||||
ln, *pos - 1, NULL);
|
||||
return(0);
|
||||
mandoc_vmsg(MANDOCERR_TBLLAYOUT_CHAR, tbl->parse,
|
||||
ln, *pos - 1, "%c", p[*pos - 1]);
|
||||
goto mod;
|
||||
}
|
||||
|
||||
switch (tolower((unsigned char)p[(*pos)++])) {
|
||||
/* Ignore parenthised font names for now. */
|
||||
|
||||
if (p[*pos] == '(')
|
||||
goto mod;
|
||||
|
||||
/* Support only one-character font-names for now. */
|
||||
|
||||
if (p[*pos] == '\0' || (p[*pos + 1] != ' ' && p[*pos + 1] != '.')) {
|
||||
mandoc_vmsg(MANDOCERR_FT_BAD, tbl->parse,
|
||||
ln, *pos, "TS %s", p + *pos - 1);
|
||||
if (p[*pos] != '\0')
|
||||
(*pos)++;
|
||||
if (p[*pos] != '\0')
|
||||
(*pos)++;
|
||||
goto mod;
|
||||
}
|
||||
|
||||
switch (p[(*pos)++]) {
|
||||
case '3':
|
||||
/* FALLTHROUGH */
|
||||
case 'b':
|
||||
case 'B':
|
||||
cp->flags |= TBL_CELL_BOLD;
|
||||
goto mod;
|
||||
case '2':
|
||||
/* FALLTHROUGH */
|
||||
case 'i':
|
||||
case 'I':
|
||||
cp->flags |= TBL_CELL_ITALIC;
|
||||
goto mod;
|
||||
case '1':
|
||||
/* FALLTHROUGH */
|
||||
case 'r':
|
||||
case 'R':
|
||||
goto mod;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (isalnum((unsigned char)p[*pos - 1])) {
|
||||
mandoc_vmsg(MANDOCERR_FT_BAD, tbl->parse,
|
||||
ln, *pos - 1, "TS f%c", p[*pos - 1]);
|
||||
goto mod;
|
||||
}
|
||||
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
|
||||
ln, *pos - 1, NULL);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
cell(struct tbl_node *tbl, struct tbl_row *rp,
|
||||
int ln, const char *p, int *pos)
|
||||
{
|
||||
int vert, i;
|
||||
int i;
|
||||
enum tbl_cellt c;
|
||||
|
||||
/* Handle vertical lines. */
|
||||
/* Handle leading vertical lines */
|
||||
|
||||
for (vert = 0; '|' == p[*pos]; ++*pos)
|
||||
vert++;
|
||||
while (' ' == p[*pos])
|
||||
while (p[*pos] == ' ' || p[*pos] == '\t' || p[*pos] == '|') {
|
||||
if (p[*pos] == '|') {
|
||||
if (rp->vert < 2)
|
||||
rp->vert++;
|
||||
else
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT_VERT,
|
||||
tbl->parse, ln, *pos, NULL);
|
||||
}
|
||||
(*pos)++;
|
||||
}
|
||||
|
||||
again:
|
||||
while (p[*pos] == ' ' || p[*pos] == '\t')
|
||||
(*pos)++;
|
||||
|
||||
/* Handle trailing vertical lines */
|
||||
|
||||
if ('.' == p[*pos] || '\0' == p[*pos]) {
|
||||
rp->vert = vert;
|
||||
return(1);
|
||||
}
|
||||
if (p[*pos] == '.' || p[*pos] == '\0')
|
||||
return;
|
||||
|
||||
/* Parse the column position (`c', `l', `r', ...). */
|
||||
|
||||
@ -241,77 +221,44 @@ cell(struct tbl_node *tbl, struct tbl_row *rp,
|
||||
if (tolower((unsigned char)p[*pos]) == keys[i].name)
|
||||
break;
|
||||
|
||||
if (KEYS_MAX == i) {
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
|
||||
ln, *pos, NULL);
|
||||
return(0);
|
||||
if (i == KEYS_MAX) {
|
||||
mandoc_vmsg(MANDOCERR_TBLLAYOUT_CHAR, tbl->parse,
|
||||
ln, *pos, "%c", p[*pos]);
|
||||
(*pos)++;
|
||||
goto again;
|
||||
}
|
||||
|
||||
c = keys[i].key;
|
||||
|
||||
/*
|
||||
* If a span cell is found first, raise a warning and abort the
|
||||
* parse. If a span cell is found and the last layout element
|
||||
* isn't a "normal" layout, bail.
|
||||
*
|
||||
* FIXME: recover from this somehow?
|
||||
*/
|
||||
/* Special cases of spanners. */
|
||||
|
||||
if (TBL_CELL_SPAN == c) {
|
||||
if (NULL == rp->first) {
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
|
||||
ln, *pos, NULL);
|
||||
return(0);
|
||||
} else if (rp->last)
|
||||
switch (rp->last->pos) {
|
||||
case TBL_CELL_HORIZ:
|
||||
/* FALLTHROUGH */
|
||||
case TBL_CELL_DHORIZ:
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT,
|
||||
tbl->parse, ln, *pos, NULL);
|
||||
return(0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If a vertical spanner is found, we may not be in the first
|
||||
* row.
|
||||
*/
|
||||
|
||||
if (TBL_CELL_DOWN == c && rp == tbl->first_row) {
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse, ln, *pos, NULL);
|
||||
return(0);
|
||||
}
|
||||
if (c == TBL_CELL_SPAN) {
|
||||
if (rp->last == NULL)
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT_SPAN,
|
||||
tbl->parse, ln, *pos, NULL);
|
||||
else if (rp->last->pos == TBL_CELL_HORIZ ||
|
||||
rp->last->pos == TBL_CELL_DHORIZ)
|
||||
c = rp->last->pos;
|
||||
} else if (c == TBL_CELL_DOWN && rp == tbl->first_row)
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT_DOWN,
|
||||
tbl->parse, ln, *pos, NULL);
|
||||
|
||||
(*pos)++;
|
||||
|
||||
/* Disallow adjacent spacers. */
|
||||
|
||||
if (vert > 2) {
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse, ln, *pos - 1, NULL);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Allocate cell then parse its modifiers. */
|
||||
|
||||
return(mods(tbl, cell_alloc(tbl, rp, c, vert), ln, p, pos));
|
||||
mods(tbl, cell_alloc(tbl, rp, c), ln, p, pos);
|
||||
}
|
||||
|
||||
int
|
||||
tbl_layout(struct tbl_node *tbl, int ln, const char *p)
|
||||
void
|
||||
tbl_layout(struct tbl_node *tbl, int ln, const char *p, int pos)
|
||||
{
|
||||
struct tbl_row *rp;
|
||||
int pos;
|
||||
|
||||
pos = 0;
|
||||
rp = NULL;
|
||||
|
||||
for (;;) {
|
||||
/* Skip whitespace before and after each cell. */
|
||||
|
||||
while (isspace((unsigned char)p[pos]))
|
||||
while (p[pos] == ' ' || p[pos] == '\t')
|
||||
pos++;
|
||||
|
||||
switch (p[pos]) {
|
||||
@ -320,74 +267,92 @@ tbl_layout(struct tbl_node *tbl, int ln, const char *p)
|
||||
rp = NULL;
|
||||
continue;
|
||||
case '\0': /* Next row on next input line. */
|
||||
return(1);
|
||||
return;
|
||||
case '.': /* End of layout. */
|
||||
pos++;
|
||||
tbl->part = TBL_PART_DATA;
|
||||
if (tbl->first_row != NULL)
|
||||
return(1);
|
||||
mandoc_msg(MANDOCERR_TBLNOLAYOUT,
|
||||
tbl->parse, ln, pos, NULL);
|
||||
rp = mandoc_calloc(1, sizeof(*rp));
|
||||
cell_alloc(tbl, rp, TBL_CELL_LEFT, 0);
|
||||
tbl->first_row = tbl->last_row = rp;
|
||||
return(1);
|
||||
|
||||
/*
|
||||
* When the layout is completely empty,
|
||||
* default to one left-justified column.
|
||||
*/
|
||||
|
||||
if (tbl->first_row == NULL) {
|
||||
tbl->first_row = tbl->last_row =
|
||||
mandoc_calloc(1, sizeof(*rp));
|
||||
}
|
||||
if (tbl->first_row->first == NULL) {
|
||||
mandoc_msg(MANDOCERR_TBLLAYOUT_NONE,
|
||||
tbl->parse, ln, pos, NULL);
|
||||
cell_alloc(tbl, tbl->first_row,
|
||||
TBL_CELL_LEFT);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for the widest line
|
||||
* along the left and right margins.
|
||||
*/
|
||||
|
||||
for (rp = tbl->first_row; rp; rp = rp->next) {
|
||||
if (tbl->opts.lvert < rp->vert)
|
||||
tbl->opts.lvert = rp->vert;
|
||||
if (rp->last != NULL &&
|
||||
rp->last->col + 1 == tbl->opts.cols &&
|
||||
tbl->opts.rvert < rp->last->vert)
|
||||
tbl->opts.rvert = rp->last->vert;
|
||||
|
||||
/* If the last line is empty, drop it. */
|
||||
|
||||
if (rp->next != NULL &&
|
||||
rp->next->first == NULL) {
|
||||
free(rp->next);
|
||||
rp->next = NULL;
|
||||
}
|
||||
}
|
||||
return;
|
||||
default: /* Cell. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (rp == NULL) { /* First cell on this line. */
|
||||
rp = mandoc_calloc(1, sizeof(*rp));
|
||||
if (tbl->last_row)
|
||||
tbl->last_row->next = rp;
|
||||
else
|
||||
tbl->first_row = rp;
|
||||
tbl->last_row = rp;
|
||||
/*
|
||||
* If the last line had at least one cell,
|
||||
* start a new one; otherwise, continue it.
|
||||
*/
|
||||
|
||||
if (rp == NULL) {
|
||||
if (tbl->last_row == NULL ||
|
||||
tbl->last_row->first != NULL) {
|
||||
rp = mandoc_calloc(1, sizeof(*rp));
|
||||
if (tbl->last_row)
|
||||
tbl->last_row->next = rp;
|
||||
else
|
||||
tbl->first_row = rp;
|
||||
tbl->last_row = rp;
|
||||
} else
|
||||
rp = tbl->last_row;
|
||||
}
|
||||
if ( ! cell(tbl, rp, ln, p, &pos))
|
||||
return(1);
|
||||
cell(tbl, rp, ln, p, &pos);
|
||||
}
|
||||
}
|
||||
|
||||
static struct tbl_cell *
|
||||
cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos,
|
||||
int vert)
|
||||
cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos)
|
||||
{
|
||||
struct tbl_cell *p, *pp;
|
||||
struct tbl_head *h, *hp;
|
||||
|
||||
p = mandoc_calloc(1, sizeof(struct tbl_cell));
|
||||
p = mandoc_calloc(1, sizeof(*p));
|
||||
p->pos = pos;
|
||||
|
||||
if (NULL != (pp = rp->last)) {
|
||||
if ((pp = rp->last) != NULL) {
|
||||
pp->next = p;
|
||||
h = pp->head->next;
|
||||
} else {
|
||||
p->col = pp->col + 1;
|
||||
} else
|
||||
rp->first = p;
|
||||
h = tbl->first_head;
|
||||
}
|
||||
rp->last = p;
|
||||
|
||||
p->pos = pos;
|
||||
p->vert = vert;
|
||||
if (tbl->opts.cols <= p->col)
|
||||
tbl->opts.cols = p->col + 1;
|
||||
|
||||
/* Re-use header. */
|
||||
|
||||
if (h) {
|
||||
p->head = h;
|
||||
return(p);
|
||||
}
|
||||
|
||||
hp = mandoc_calloc(1, sizeof(struct tbl_head));
|
||||
hp->ident = tbl->opts.cols++;
|
||||
hp->vert = vert;
|
||||
|
||||
if (tbl->last_head) {
|
||||
hp->prev = tbl->last_head;
|
||||
tbl->last_head->next = hp;
|
||||
} else
|
||||
tbl->first_head = hp;
|
||||
tbl->last_head = hp;
|
||||
|
||||
p->head = hp;
|
||||
return(p);
|
||||
}
|
||||
|
301
tbl_opts.c
301
tbl_opts.c
@ -1,6 +1,7 @@
|
||||
/* $Id: tbl_opts.c,v 1.15 2014/11/26 17:51:55 schwarze Exp $ */
|
||||
/* $Id: tbl_opts.c,v 1.20 2015/01/28 17:32:07 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -27,245 +28,147 @@
|
||||
#include "libmandoc.h"
|
||||
#include "libroff.h"
|
||||
|
||||
enum tbl_ident {
|
||||
KEY_CENTRE = 0,
|
||||
KEY_DELIM,
|
||||
KEY_EXPAND,
|
||||
KEY_BOX,
|
||||
KEY_DBOX,
|
||||
KEY_ALLBOX,
|
||||
KEY_TAB,
|
||||
KEY_LINESIZE,
|
||||
KEY_NOKEEP,
|
||||
KEY_DPOINT,
|
||||
KEY_NOSPACE,
|
||||
KEY_FRAME,
|
||||
KEY_DFRAME,
|
||||
KEY_MAX
|
||||
};
|
||||
#define KEY_DPOINT 0
|
||||
#define KEY_DELIM 1
|
||||
#define KEY_LINESIZE 2
|
||||
#define KEY_TAB 3
|
||||
|
||||
struct tbl_phrase {
|
||||
const char *name;
|
||||
int key;
|
||||
enum tbl_ident ident;
|
||||
};
|
||||
|
||||
/* Handle Commonwealth/American spellings. */
|
||||
#define KEY_MAXKEYS 14
|
||||
|
||||
/* Maximum length of key name string. */
|
||||
#define KEY_MAXNAME 13
|
||||
|
||||
/* Maximum length of key number size. */
|
||||
#define KEY_MAXNUMSZ 10
|
||||
|
||||
static const struct tbl_phrase keys[KEY_MAXKEYS] = {
|
||||
{ "center", TBL_OPT_CENTRE, KEY_CENTRE},
|
||||
{ "centre", TBL_OPT_CENTRE, KEY_CENTRE},
|
||||
{ "delim", 0, KEY_DELIM},
|
||||
{ "expand", TBL_OPT_EXPAND, KEY_EXPAND},
|
||||
{ "box", TBL_OPT_BOX, KEY_BOX},
|
||||
{ "doublebox", TBL_OPT_DBOX, KEY_DBOX},
|
||||
{ "allbox", TBL_OPT_ALLBOX, KEY_ALLBOX},
|
||||
{ "frame", TBL_OPT_BOX, KEY_FRAME},
|
||||
{ "doubleframe", TBL_OPT_DBOX, KEY_DFRAME},
|
||||
{ "tab", 0, KEY_TAB},
|
||||
{ "linesize", 0, KEY_LINESIZE},
|
||||
{ "nokeep", TBL_OPT_NOKEEP, KEY_NOKEEP},
|
||||
{ "decimalpoint", 0, KEY_DPOINT},
|
||||
{ "nospaces", TBL_OPT_NOSPACE, KEY_NOSPACE},
|
||||
static const struct tbl_phrase keys[] = {
|
||||
{"decimalpoint", 0},
|
||||
{"delim", 0},
|
||||
{"linesize", 0},
|
||||
{"tab", 0},
|
||||
{"allbox", TBL_OPT_ALLBOX | TBL_OPT_BOX},
|
||||
{"box", TBL_OPT_BOX},
|
||||
{"frame", TBL_OPT_BOX},
|
||||
{"center", TBL_OPT_CENTRE},
|
||||
{"centre", TBL_OPT_CENTRE},
|
||||
{"doublebox", TBL_OPT_DBOX},
|
||||
{"doubleframe", TBL_OPT_DBOX},
|
||||
{"expand", TBL_OPT_EXPAND},
|
||||
{"nokeep", TBL_OPT_NOKEEP},
|
||||
{"nospaces", TBL_OPT_NOSPACE},
|
||||
{"nowarn", TBL_OPT_NOWARN},
|
||||
};
|
||||
|
||||
static int arg(struct tbl_node *, int,
|
||||
const char *, int *, enum tbl_ident);
|
||||
static void opt(struct tbl_node *, int,
|
||||
const char *, int *);
|
||||
#define KEY_MAXKEYS ((int)(sizeof(keys)/sizeof(keys[0])))
|
||||
|
||||
static void arg(struct tbl_node *, int, const char *, int *, int);
|
||||
|
||||
|
||||
static int
|
||||
arg(struct tbl_node *tbl, int ln, const char *p, int *pos, enum tbl_ident key)
|
||||
static void
|
||||
arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key)
|
||||
{
|
||||
int i;
|
||||
char buf[KEY_MAXNUMSZ];
|
||||
int len, want;
|
||||
|
||||
while (isspace((unsigned char)p[*pos]))
|
||||
while (p[*pos] == ' ' || p[*pos] == '\t')
|
||||
(*pos)++;
|
||||
|
||||
/* Arguments always begin with a parenthesis. */
|
||||
/* Arguments are enclosed in parentheses. */
|
||||
|
||||
if ('(' != p[*pos]) {
|
||||
mandoc_msg(MANDOCERR_TBL, tbl->parse,
|
||||
ln, *pos, NULL);
|
||||
return(0);
|
||||
len = 0;
|
||||
if (p[*pos] == '(') {
|
||||
(*pos)++;
|
||||
while (p[*pos + len] != ')')
|
||||
len++;
|
||||
}
|
||||
|
||||
(*pos)++;
|
||||
|
||||
/*
|
||||
* The arguments can be ANY value, so we can't just stop at the
|
||||
* next close parenthesis (the argument can be a closed
|
||||
* parenthesis itself).
|
||||
*/
|
||||
|
||||
switch (key) {
|
||||
case KEY_DELIM:
|
||||
if ('\0' == p[(*pos)++]) {
|
||||
mandoc_msg(MANDOCERR_TBL, tbl->parse,
|
||||
ln, *pos - 1, NULL);
|
||||
return(0);
|
||||
}
|
||||
|
||||
if ('\0' == p[(*pos)++]) {
|
||||
mandoc_msg(MANDOCERR_TBL, tbl->parse,
|
||||
ln, *pos - 1, NULL);
|
||||
return(0);
|
||||
}
|
||||
mandoc_vmsg(MANDOCERR_TBLOPT_EQN, tbl->parse,
|
||||
ln, *pos, "%.*s", len, p + *pos);
|
||||
want = 2;
|
||||
break;
|
||||
case KEY_TAB:
|
||||
if ('\0' != (tbl->opts.tab = p[(*pos)++]))
|
||||
break;
|
||||
|
||||
mandoc_msg(MANDOCERR_TBL, tbl->parse,
|
||||
ln, *pos - 1, NULL);
|
||||
return(0);
|
||||
want = 1;
|
||||
if (len == want)
|
||||
tbl->opts.tab = p[*pos];
|
||||
break;
|
||||
case KEY_LINESIZE:
|
||||
for (i = 0; i < KEY_MAXNUMSZ && p[*pos]; i++, (*pos)++) {
|
||||
buf[i] = p[*pos];
|
||||
if ( ! isdigit((unsigned char)buf[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < KEY_MAXNUMSZ) {
|
||||
buf[i] = '\0';
|
||||
tbl->opts.linesize = atoi(buf);
|
||||
break;
|
||||
}
|
||||
|
||||
mandoc_msg(MANDOCERR_TBL, tbl->parse, ln, *pos, NULL);
|
||||
return(0);
|
||||
want = 0;
|
||||
break;
|
||||
case KEY_DPOINT:
|
||||
if ('\0' != (tbl->opts.decimal = p[(*pos)++]))
|
||||
break;
|
||||
|
||||
mandoc_msg(MANDOCERR_TBL, tbl->parse,
|
||||
ln, *pos - 1, NULL);
|
||||
return(0);
|
||||
want = 1;
|
||||
if (len == want)
|
||||
tbl->opts.decimal = p[*pos];
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* End with a close parenthesis. */
|
||||
if (len == 0)
|
||||
mandoc_msg(MANDOCERR_TBLOPT_NOARG,
|
||||
tbl->parse, ln, *pos, keys[key].name);
|
||||
else if (want && len != want)
|
||||
mandoc_vmsg(MANDOCERR_TBLOPT_ARGSZ,
|
||||
tbl->parse, ln, *pos, "%s want %d have %d",
|
||||
keys[key].name, want, len);
|
||||
|
||||
if (')' == p[(*pos)++])
|
||||
return(1);
|
||||
|
||||
mandoc_msg(MANDOCERR_TBL, tbl->parse, ln, *pos - 1, NULL);
|
||||
return(0);
|
||||
*pos += len;
|
||||
if (p[*pos] == ')')
|
||||
(*pos)++;
|
||||
}
|
||||
|
||||
static void
|
||||
opt(struct tbl_node *tbl, int ln, const char *p, int *pos)
|
||||
/*
|
||||
* Parse one line of options up to the semicolon.
|
||||
* Each option can be preceded by blanks and/or commas,
|
||||
* and some options are followed by arguments.
|
||||
*/
|
||||
void
|
||||
tbl_option(struct tbl_node *tbl, int ln, const char *p, int *offs)
|
||||
{
|
||||
int i, sv;
|
||||
char buf[KEY_MAXNAME];
|
||||
int i, pos, len;
|
||||
|
||||
/*
|
||||
* Parse individual options from the stream as surrounded by
|
||||
* this goto. Each pass through the routine parses out a single
|
||||
* option and registers it. Option arguments are processed in
|
||||
* the arg() function.
|
||||
*/
|
||||
pos = *offs;
|
||||
for (;;) {
|
||||
while (p[pos] == ' ' || p[pos] == '\t' || p[pos] == ',')
|
||||
pos++;
|
||||
|
||||
again: /*
|
||||
* EBNF describing this section:
|
||||
*
|
||||
* options ::= option_list [:space:]* [;][\n]
|
||||
* option_list ::= option option_tail
|
||||
* option_tail ::= [,:space:]+ option_list |
|
||||
* ::= epsilon
|
||||
* option ::= [:alpha:]+ args
|
||||
* args ::= [:space:]* [(] [:alpha:]+ [)]
|
||||
*/
|
||||
if (p[pos] == ';') {
|
||||
*offs = pos + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
while (isspace((unsigned char)p[*pos]))
|
||||
(*pos)++;
|
||||
/* Parse one option name. */
|
||||
|
||||
/* Safe exit point. */
|
||||
len = 0;
|
||||
while (isalpha((unsigned char)p[pos + len]))
|
||||
len++;
|
||||
|
||||
if (';' == p[*pos])
|
||||
return;
|
||||
|
||||
/* Copy up to first non-alpha character. */
|
||||
|
||||
for (sv = *pos, i = 0; i < KEY_MAXNAME; i++, (*pos)++) {
|
||||
buf[i] = (char)tolower((unsigned char)p[*pos]);
|
||||
if ( ! isalpha((unsigned char)buf[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Exit if buffer is empty (or overrun). */
|
||||
|
||||
if (KEY_MAXNAME == i || 0 == i) {
|
||||
mandoc_msg(MANDOCERR_TBL, tbl->parse, ln, *pos, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
buf[i] = '\0';
|
||||
|
||||
while (isspace((unsigned char)p[*pos]) || p[*pos] == ',')
|
||||
(*pos)++;
|
||||
|
||||
/*
|
||||
* Look through all of the available keys to find one that
|
||||
* matches the input. FIXME: hashtable this.
|
||||
*/
|
||||
|
||||
for (i = 0; i < KEY_MAXKEYS; i++) {
|
||||
if (strcmp(buf, keys[i].name))
|
||||
if (len == 0) {
|
||||
mandoc_vmsg(MANDOCERR_TBLOPT_ALPHA,
|
||||
tbl->parse, ln, pos, "%c", p[pos]);
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: this is more difficult to recover from, as we
|
||||
* can be anywhere in the option sequence and it's
|
||||
* harder to jump to the next. Meanwhile, just bail out
|
||||
* of the sequence altogether.
|
||||
*/
|
||||
/* Look up the option name. */
|
||||
|
||||
i = 0;
|
||||
while (i < KEY_MAXKEYS &&
|
||||
(strncasecmp(p + pos, keys[i].name, len) ||
|
||||
keys[i].name[len] != '\0'))
|
||||
i++;
|
||||
|
||||
if (i == KEY_MAXKEYS) {
|
||||
mandoc_vmsg(MANDOCERR_TBLOPT_BAD, tbl->parse,
|
||||
ln, pos, "%.*s", len, p + pos);
|
||||
pos += len;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Handle the option. */
|
||||
|
||||
pos += len;
|
||||
if (keys[i].key)
|
||||
tbl->opts.opts |= keys[i].key;
|
||||
else if ( ! arg(tbl, ln, p, pos, keys[i].ident))
|
||||
return;
|
||||
|
||||
break;
|
||||
else
|
||||
arg(tbl, ln, p, &pos, i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow us to recover from bad options by continuing to another
|
||||
* parse sequence.
|
||||
*/
|
||||
|
||||
if (KEY_MAXKEYS == i)
|
||||
mandoc_msg(MANDOCERR_TBLOPT, tbl->parse, ln, sv, NULL);
|
||||
|
||||
goto again;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
int
|
||||
tbl_option(struct tbl_node *tbl, int ln, const char *p)
|
||||
{
|
||||
int pos;
|
||||
|
||||
/*
|
||||
* Table options are always on just one line, so automatically
|
||||
* switch into the next input mode here.
|
||||
*/
|
||||
tbl->part = TBL_PART_LAYOUT;
|
||||
|
||||
pos = 0;
|
||||
opt(tbl, ln, p, &pos);
|
||||
|
||||
/* Always succeed. */
|
||||
return(1);
|
||||
}
|
||||
|
282
tbl_term.c
282
tbl_term.c
@ -1,7 +1,7 @@
|
||||
/* $Id: tbl_term.c,v 1.31 2014/10/14 18:18:05 schwarze Exp $ */
|
||||
/* $Id: tbl_term.c,v 1.38 2015/01/31 00:12:41 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2011, 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -34,15 +34,12 @@ static void tbl_char(struct termp *, char, size_t);
|
||||
static void tbl_data(struct termp *, const struct tbl_opts *,
|
||||
const struct tbl_dat *,
|
||||
const struct roffcol *);
|
||||
static size_t tbl_rulewidth(struct termp *, const struct tbl_head *);
|
||||
static void tbl_hframe(struct termp *, const struct tbl_span *, int);
|
||||
static void tbl_literal(struct termp *, const struct tbl_dat *,
|
||||
const struct roffcol *);
|
||||
static void tbl_number(struct termp *, const struct tbl_opts *,
|
||||
const struct tbl_dat *,
|
||||
const struct roffcol *);
|
||||
static void tbl_hrule(struct termp *, const struct tbl_span *);
|
||||
static void tbl_vrule(struct termp *, const struct tbl_head *);
|
||||
static void tbl_hrule(struct termp *, const struct tbl_span *, int);
|
||||
static void tbl_word(struct termp *, const struct tbl_dat *);
|
||||
|
||||
|
||||
@ -63,11 +60,11 @@ term_tbl_len(size_t sz, void *arg)
|
||||
void
|
||||
term_tbl(struct termp *tp, const struct tbl_span *sp)
|
||||
{
|
||||
const struct tbl_head *hp;
|
||||
const struct tbl_cell *cp;
|
||||
const struct tbl_dat *dp;
|
||||
struct roffcol *col;
|
||||
int spans;
|
||||
size_t rmargin, maxrmargin;
|
||||
static size_t offset;
|
||||
size_t rmargin, maxrmargin, tsz;
|
||||
int ic, horiz, spans, vert;
|
||||
|
||||
rmargin = tp->rmargin;
|
||||
maxrmargin = tp->maxrmargin;
|
||||
@ -84,7 +81,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
|
||||
* calculate the table widths and decimal positions.
|
||||
*/
|
||||
|
||||
if (TBL_SPAN_FIRST & sp->flags) {
|
||||
if (tp->tbl.cols == NULL) {
|
||||
term_flushln(tp);
|
||||
|
||||
tp->tbl.len = term_tbl_len;
|
||||
@ -92,79 +89,99 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
|
||||
tp->tbl.arg = tp;
|
||||
|
||||
tblcalc(&tp->tbl, sp, rmargin - tp->offset);
|
||||
}
|
||||
|
||||
/* Horizontal frame at the start of boxed tables. */
|
||||
/* Center the table as a whole. */
|
||||
|
||||
if (TBL_SPAN_FIRST & sp->flags) {
|
||||
if (TBL_OPT_DBOX & sp->opts->opts)
|
||||
tbl_hframe(tp, sp, 1);
|
||||
if (TBL_OPT_DBOX & sp->opts->opts ||
|
||||
TBL_OPT_BOX & sp->opts->opts)
|
||||
tbl_hframe(tp, sp, 0);
|
||||
offset = tp->offset;
|
||||
if (sp->opts->opts & TBL_OPT_CENTRE) {
|
||||
tsz = sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX)
|
||||
? 2 : !!sp->opts->lvert + !!sp->opts->rvert;
|
||||
for (ic = 0; ic < sp->opts->cols; ic++)
|
||||
tsz += tp->tbl.cols[ic].width + 3;
|
||||
tsz -= 3;
|
||||
if (offset + tsz > rmargin)
|
||||
tsz -= 1;
|
||||
tp->offset = (offset + rmargin > tsz) ?
|
||||
(offset + rmargin - tsz) / 2 : 0;
|
||||
}
|
||||
|
||||
/* Horizontal frame at the start of boxed tables. */
|
||||
|
||||
if (sp->opts->opts & TBL_OPT_DBOX)
|
||||
tbl_hrule(tp, sp, 2);
|
||||
if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX))
|
||||
tbl_hrule(tp, sp, 1);
|
||||
}
|
||||
|
||||
/* Vertical frame at the start of each row. */
|
||||
|
||||
if ((TBL_OPT_BOX | TBL_OPT_DBOX) & sp->opts->opts ||
|
||||
(sp->head != NULL && sp->head->vert))
|
||||
term_word(tp, TBL_SPAN_HORIZ == sp->pos ||
|
||||
TBL_SPAN_DHORIZ == sp->pos ? "+" : "|");
|
||||
horiz = sp->pos == TBL_SPAN_HORIZ || sp->pos == TBL_SPAN_DHORIZ;
|
||||
|
||||
if (sp->layout->vert ||
|
||||
(sp->prev != NULL && sp->prev->layout->vert) ||
|
||||
sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX))
|
||||
term_word(tp, horiz ? "+" : "|");
|
||||
else if (sp->opts->lvert)
|
||||
tbl_char(tp, horiz ? '-' : ASCII_NBRSP, 1);
|
||||
|
||||
/*
|
||||
* Now print the actual data itself depending on the span type.
|
||||
* Spanner spans get a horizontal rule; data spanners have their
|
||||
* data printed by matching data to header.
|
||||
* Match data cells to column numbers.
|
||||
*/
|
||||
|
||||
switch (sp->pos) {
|
||||
case TBL_SPAN_HORIZ:
|
||||
/* FALLTHROUGH */
|
||||
case TBL_SPAN_DHORIZ:
|
||||
tbl_hrule(tp, sp);
|
||||
break;
|
||||
case TBL_SPAN_DATA:
|
||||
/* Iterate over template headers. */
|
||||
if (sp->pos == TBL_SPAN_DATA) {
|
||||
cp = sp->layout->first;
|
||||
dp = sp->first;
|
||||
spans = 0;
|
||||
for (hp = sp->head; hp; hp = hp->next) {
|
||||
for (ic = 0; ic < sp->opts->cols; ic++) {
|
||||
|
||||
/*
|
||||
* If the current data header is invoked during
|
||||
* a spanner ("spans" > 0), don't emit anything
|
||||
* at all.
|
||||
* Remeber whether we need a vertical bar
|
||||
* after this cell.
|
||||
*/
|
||||
|
||||
if (--spans >= 0)
|
||||
vert = cp == NULL ? 0 : cp->vert;
|
||||
|
||||
/*
|
||||
* Print the data and advance to the next cell.
|
||||
*/
|
||||
|
||||
if (spans == 0) {
|
||||
tbl_data(tp, sp->opts, dp, tp->tbl.cols + ic);
|
||||
if (dp != NULL) {
|
||||
spans = dp->spans;
|
||||
dp = dp->next;
|
||||
}
|
||||
} else
|
||||
spans--;
|
||||
if (cp != NULL)
|
||||
cp = cp->next;
|
||||
|
||||
/*
|
||||
* Separate columns, except in the middle
|
||||
* of spans and after the last cell.
|
||||
*/
|
||||
|
||||
if (ic + 1 == sp->opts->cols || spans)
|
||||
continue;
|
||||
|
||||
/* Separate columns. */
|
||||
|
||||
if (NULL != hp->prev)
|
||||
tbl_vrule(tp, hp);
|
||||
|
||||
col = &tp->tbl.cols[hp->ident];
|
||||
tbl_data(tp, sp->opts, dp, col);
|
||||
|
||||
/*
|
||||
* Go to the next data cell and assign the
|
||||
* number of subsequent spans, if applicable.
|
||||
*/
|
||||
|
||||
if (dp) {
|
||||
spans = dp->spans;
|
||||
dp = dp->next;
|
||||
}
|
||||
tbl_char(tp, ASCII_NBRSP, 1);
|
||||
if (vert > 0)
|
||||
tbl_char(tp, '|', vert);
|
||||
if (vert < 2)
|
||||
tbl_char(tp, ASCII_NBRSP, 2 - vert);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (horiz)
|
||||
tbl_hrule(tp, sp, 0);
|
||||
|
||||
/* Vertical frame at the end of each row. */
|
||||
|
||||
if ((TBL_OPT_BOX | TBL_OPT_DBOX) & sp->opts->opts ||
|
||||
sp->layout->vert)
|
||||
term_word(tp, TBL_SPAN_HORIZ == sp->pos ||
|
||||
TBL_SPAN_DHORIZ == sp->pos ? "+" : " |");
|
||||
if (sp->layout->last->vert ||
|
||||
(sp->prev != NULL && sp->prev->layout->last->vert) ||
|
||||
(sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX)))
|
||||
term_word(tp, horiz ? "+" : " |");
|
||||
else if (sp->opts->rvert)
|
||||
tbl_char(tp, horiz ? '-' : ASCII_NBRSP, 1);
|
||||
term_flushln(tp);
|
||||
|
||||
/*
|
||||
@ -172,88 +189,67 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
|
||||
* existing table configuration and set it to NULL.
|
||||
*/
|
||||
|
||||
if (TBL_SPAN_LAST & sp->flags) {
|
||||
if (TBL_OPT_DBOX & sp->opts->opts ||
|
||||
TBL_OPT_BOX & sp->opts->opts) {
|
||||
tbl_hframe(tp, sp, 0);
|
||||
if (sp->next == NULL) {
|
||||
if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) {
|
||||
tbl_hrule(tp, sp, 1);
|
||||
tp->skipvsp = 1;
|
||||
}
|
||||
if (TBL_OPT_DBOX & sp->opts->opts) {
|
||||
tbl_hframe(tp, sp, 1);
|
||||
if (sp->opts->opts & TBL_OPT_DBOX) {
|
||||
tbl_hrule(tp, sp, 2);
|
||||
tp->skipvsp = 2;
|
||||
}
|
||||
assert(tp->tbl.cols);
|
||||
free(tp->tbl.cols);
|
||||
tp->tbl.cols = NULL;
|
||||
tp->offset = offset;
|
||||
}
|
||||
|
||||
tp->flags &= ~TERMP_NONOSPACE;
|
||||
tp->rmargin = rmargin;
|
||||
tp->maxrmargin = maxrmargin;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Horizontal rules extend across the entire table.
|
||||
* Calculate the width by iterating over columns.
|
||||
*/
|
||||
static size_t
|
||||
tbl_rulewidth(struct termp *tp, const struct tbl_head *hp)
|
||||
{
|
||||
size_t width;
|
||||
|
||||
width = tp->tbl.cols[hp->ident].width;
|
||||
|
||||
/* Account for leading blanks. */
|
||||
if (hp->prev)
|
||||
width += 2 - hp->vert;
|
||||
|
||||
/* Account for trailing blank. */
|
||||
width++;
|
||||
|
||||
return(width);
|
||||
}
|
||||
|
||||
/*
|
||||
* Rules inside the table can be single or double
|
||||
* and have crossings with vertical rules marked with pluses.
|
||||
* Kinds of horizontal rulers:
|
||||
* 0: inside the table (single or double line with crossings)
|
||||
* 1: inner frame (single line with crossings and ends)
|
||||
* 2: outer frame (single line without crossings with ends)
|
||||
*/
|
||||
static void
|
||||
tbl_hrule(struct termp *tp, const struct tbl_span *sp)
|
||||
tbl_hrule(struct termp *tp, const struct tbl_span *sp, int kind)
|
||||
{
|
||||
const struct tbl_head *hp;
|
||||
char c;
|
||||
const struct tbl_cell *c1, *c2;
|
||||
int vert;
|
||||
char line, cross;
|
||||
|
||||
c = '-';
|
||||
if (TBL_SPAN_DHORIZ == sp->pos)
|
||||
c = '=';
|
||||
line = (kind == 0 && TBL_SPAN_DHORIZ == sp->pos) ? '=' : '-';
|
||||
cross = (kind < 2) ? '+' : '-';
|
||||
|
||||
for (hp = sp->head; hp; hp = hp->next) {
|
||||
if (hp->prev && hp->vert)
|
||||
tbl_char(tp, '+', hp->vert);
|
||||
tbl_char(tp, c, tbl_rulewidth(tp, hp));
|
||||
if (kind)
|
||||
term_word(tp, "+");
|
||||
c1 = sp->layout->first;
|
||||
c2 = sp->prev == NULL ? NULL : sp->prev->layout->first;
|
||||
if (c2 == c1)
|
||||
c2 = NULL;
|
||||
for (;;) {
|
||||
tbl_char(tp, line, tp->tbl.cols[c1->col].width + 1);
|
||||
vert = c1->vert;
|
||||
if ((c1 = c1->next) == NULL)
|
||||
break;
|
||||
if (c2 != NULL) {
|
||||
if (vert < c2->vert)
|
||||
vert = c2->vert;
|
||||
c2 = c2->next;
|
||||
}
|
||||
if (vert)
|
||||
tbl_char(tp, cross, vert);
|
||||
if (vert < 2)
|
||||
tbl_char(tp, line, 2 - vert);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Rules above and below the table are always single
|
||||
* and have an additional plus at the beginning and end.
|
||||
* For double frames, this function is called twice,
|
||||
* and the outer one does not have crossings.
|
||||
*/
|
||||
static void
|
||||
tbl_hframe(struct termp *tp, const struct tbl_span *sp, int outer)
|
||||
{
|
||||
const struct tbl_head *hp;
|
||||
|
||||
term_word(tp, "+");
|
||||
for (hp = sp->head; hp; hp = hp->next) {
|
||||
if (hp->prev && hp->vert)
|
||||
tbl_char(tp, (outer ? '-' : '+'), hp->vert);
|
||||
tbl_char(tp, '-', tbl_rulewidth(tp, hp));
|
||||
if (kind) {
|
||||
term_word(tp, "+");
|
||||
term_flushln(tp);
|
||||
}
|
||||
term_word(tp, "+");
|
||||
term_flushln(tp);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -262,11 +258,10 @@ tbl_data(struct termp *tp, const struct tbl_opts *opts,
|
||||
const struct roffcol *col)
|
||||
{
|
||||
|
||||
if (NULL == dp) {
|
||||
if (dp == NULL) {
|
||||
tbl_char(tp, ASCII_NBRSP, col->width);
|
||||
return;
|
||||
}
|
||||
assert(dp->layout);
|
||||
|
||||
switch (dp->pos) {
|
||||
case TBL_DATA_NONE:
|
||||
@ -314,17 +309,6 @@ tbl_data(struct termp *tp, const struct tbl_opts *opts,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tbl_vrule(struct termp *tp, const struct tbl_head *hp)
|
||||
{
|
||||
|
||||
tbl_char(tp, ASCII_NBRSP, 1);
|
||||
if (0 < hp->vert)
|
||||
tbl_char(tp, '|', hp->vert);
|
||||
if (2 > hp->vert)
|
||||
tbl_char(tp, ASCII_NBRSP, 2 - hp->vert);
|
||||
}
|
||||
|
||||
static void
|
||||
tbl_char(struct termp *tp, char c, size_t len)
|
||||
{
|
||||
@ -344,17 +328,16 @@ static void
|
||||
tbl_literal(struct termp *tp, const struct tbl_dat *dp,
|
||||
const struct roffcol *col)
|
||||
{
|
||||
struct tbl_head *hp;
|
||||
size_t width, len, padl, padr;
|
||||
int spans;
|
||||
size_t len, padl, padr, width;
|
||||
int ic, spans;
|
||||
|
||||
assert(dp->string);
|
||||
len = term_strlen(tp, dp->string);
|
||||
|
||||
hp = dp->layout->head->next;
|
||||
width = col->width;
|
||||
for (spans = dp->spans; spans--; hp = hp->next)
|
||||
width += tp->tbl.cols[hp->ident].width + 3;
|
||||
ic = dp->layout->col;
|
||||
spans = dp->spans;
|
||||
while (spans--)
|
||||
width += tp->tbl.cols[++ic].width + 3;
|
||||
|
||||
padr = width > len ? width - len : 0;
|
||||
padl = 0;
|
||||
@ -407,8 +390,7 @@ tbl_number(struct termp *tp, const struct tbl_opts *opts,
|
||||
|
||||
psz = term_strlen(tp, buf);
|
||||
|
||||
if (NULL != (cp = strrchr(dp->string, opts->decimal))) {
|
||||
buf[1] = '\0';
|
||||
if ((cp = strrchr(dp->string, opts->decimal)) != NULL) {
|
||||
for (ssz = 0, i = 0; cp != &dp->string[i]; i++) {
|
||||
buf[0] = dp->string[i];
|
||||
ssz += term_strlen(tp, buf);
|
||||
@ -417,9 +399,13 @@ tbl_number(struct termp *tp, const struct tbl_opts *opts,
|
||||
} else
|
||||
d = sz + psz;
|
||||
|
||||
padl = col->decimal - d;
|
||||
|
||||
tbl_char(tp, ASCII_NBRSP, padl);
|
||||
if (col->decimal > d && col->width > sz) {
|
||||
padl = col->decimal - d;
|
||||
if (padl + sz > col->width)
|
||||
padl = col->width - sz;
|
||||
tbl_char(tp, ASCII_NBRSP, padl);
|
||||
} else
|
||||
padl = 0;
|
||||
tbl_word(tp, dp);
|
||||
if (col->width > sz + padl)
|
||||
tbl_char(tp, ASCII_NBRSP, col->width - sz - padl);
|
||||
@ -428,9 +414,9 @@ tbl_number(struct termp *tp, const struct tbl_opts *opts,
|
||||
static void
|
||||
tbl_word(struct termp *tp, const struct tbl_dat *dp)
|
||||
{
|
||||
const void *prev_font;
|
||||
int prev_font;
|
||||
|
||||
prev_font = term_fontq(tp);
|
||||
prev_font = tp->fonti;
|
||||
if (dp->layout->flags & TBL_CELL_BOLD)
|
||||
term_fontpush(tp, TERMFONT_BOLD);
|
||||
else if (dp->layout->flags & TBL_CELL_ITALIC)
|
||||
|
118
term.c
118
term.c
@ -1,7 +1,7 @@
|
||||
/* $Id: term.c,v 1.237 2014/12/02 10:08:06 schwarze Exp $ */
|
||||
/* $Id: term.c,v 1.244 2015/01/31 00:12:41 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -43,6 +43,7 @@ term_free(struct termp *p)
|
||||
{
|
||||
|
||||
free(p->buf);
|
||||
free(p->fontq);
|
||||
free(p);
|
||||
}
|
||||
|
||||
@ -100,7 +101,6 @@ term_flushln(struct termp *p)
|
||||
size_t j; /* temporary loop index for p->buf */
|
||||
size_t jhy; /* last hyph before overflow w/r/t j */
|
||||
size_t maxvis; /* output position of visible boundary */
|
||||
size_t rmargin; /* the rightmost of the two margins */
|
||||
|
||||
/*
|
||||
* First, establish the maximum columns of "visible" content.
|
||||
@ -113,8 +113,7 @@ term_flushln(struct termp *p)
|
||||
* is negative, it gets sign extended. Subtracting that
|
||||
* very large size_t effectively adds a small number to dv.
|
||||
*/
|
||||
rmargin = p->rmargin > p->offset ? p->rmargin : p->offset;
|
||||
dv = p->rmargin - p->offset;
|
||||
dv = p->rmargin > p->offset ? p->rmargin - p->offset : 0;
|
||||
maxvis = (int)dv > p->overstep ? dv - (size_t)p->overstep : 0;
|
||||
|
||||
if (p->flags & TERMP_NOBREAK) {
|
||||
@ -192,8 +191,9 @@ term_flushln(struct termp *p)
|
||||
(*p->endline)(p);
|
||||
p->viscol = 0;
|
||||
if (TERMP_BRIND & p->flags) {
|
||||
vbl = rmargin;
|
||||
vend += rmargin - p->offset;
|
||||
vbl = p->rmargin;
|
||||
vend += p->rmargin;
|
||||
vend -= p->offset;
|
||||
} else
|
||||
vbl = p->offset;
|
||||
|
||||
@ -273,7 +273,7 @@ term_flushln(struct termp *p)
|
||||
}
|
||||
|
||||
if (TERMP_HANG & p->flags) {
|
||||
p->overstep = (int)(vis - maxvis +
|
||||
p->overstep += (int)(p->offset + vis - p->rmargin +
|
||||
p->trailspace * (*p->width)(p, ' '));
|
||||
|
||||
/*
|
||||
@ -329,6 +329,7 @@ term_vspace(struct termp *p)
|
||||
(*p->endline)(p);
|
||||
}
|
||||
|
||||
/* Swap current and previous font; for \fP and .ft P */
|
||||
void
|
||||
term_fontlast(struct termp *p)
|
||||
{
|
||||
@ -339,6 +340,7 @@ term_fontlast(struct termp *p)
|
||||
p->fontq[p->fonti] = f;
|
||||
}
|
||||
|
||||
/* Set font, save current, discard previous; for \f, .ft, .B etc. */
|
||||
void
|
||||
term_fontrepl(struct termp *p, enum termfont f)
|
||||
{
|
||||
@ -347,38 +349,31 @@ term_fontrepl(struct termp *p, enum termfont f)
|
||||
p->fontq[p->fonti] = f;
|
||||
}
|
||||
|
||||
/* Set font, save previous. */
|
||||
void
|
||||
term_fontpush(struct termp *p, enum termfont f)
|
||||
{
|
||||
|
||||
assert(p->fonti + 1 < 10);
|
||||
p->fontl = p->fontq[p->fonti];
|
||||
p->fontq[++p->fonti] = f;
|
||||
}
|
||||
|
||||
const void *
|
||||
term_fontq(struct termp *p)
|
||||
{
|
||||
|
||||
return(&p->fontq[p->fonti]);
|
||||
}
|
||||
|
||||
enum termfont
|
||||
term_fonttop(struct termp *p)
|
||||
{
|
||||
|
||||
return(p->fontq[p->fonti]);
|
||||
if (++p->fonti == p->fontsz) {
|
||||
p->fontsz += 8;
|
||||
p->fontq = mandoc_reallocarray(p->fontq,
|
||||
p->fontsz, sizeof(enum termfont *));
|
||||
}
|
||||
p->fontq[p->fonti] = f;
|
||||
}
|
||||
|
||||
/* Flush to make the saved pointer current again. */
|
||||
void
|
||||
term_fontpopq(struct termp *p, const void *key)
|
||||
term_fontpopq(struct termp *p, int i)
|
||||
{
|
||||
|
||||
while (p->fonti >= 0 && key < (void *)(p->fontq + p->fonti))
|
||||
p->fonti--;
|
||||
assert(p->fonti >= 0);
|
||||
assert(i >= 0);
|
||||
if (p->fonti > i)
|
||||
p->fonti = i;
|
||||
}
|
||||
|
||||
/* Pop one font off the stack. */
|
||||
void
|
||||
term_fontpop(struct termp *p)
|
||||
{
|
||||
@ -492,6 +487,17 @@ term_word(struct termp *p, const char *word)
|
||||
case ESCAPE_SKIPCHAR:
|
||||
p->flags |= TERMP_SKIPCHAR;
|
||||
continue;
|
||||
case ESCAPE_OVERSTRIKE:
|
||||
cp = seq + sz;
|
||||
while (seq < cp) {
|
||||
if (*seq == '\\') {
|
||||
mandoc_escape(&seq, NULL, NULL);
|
||||
continue;
|
||||
}
|
||||
encode1(p, *seq++);
|
||||
if (seq < cp)
|
||||
encode(p, "\b", 1);
|
||||
}
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@ -554,7 +560,7 @@ encode1(struct termp *p, int c)
|
||||
if (p->col + 6 >= p->maxcols)
|
||||
adjbuf(p, p->col + 6);
|
||||
|
||||
f = term_fonttop(p);
|
||||
f = p->fontq[p->fonti];
|
||||
|
||||
if (TERMFONT_UNDER == f || TERMFONT_BI == f) {
|
||||
p->buf[p->col++] = '_';
|
||||
@ -586,7 +592,7 @@ encode(struct termp *p, const char *word, size_t sz)
|
||||
* character by character.
|
||||
*/
|
||||
|
||||
if (TERMFONT_NONE == term_fonttop(p)) {
|
||||
if (p->fontq[p->fonti] == TERMFONT_NONE) {
|
||||
if (p->col + sz >= p->maxcols)
|
||||
adjbuf(p, p->col + sz);
|
||||
for (i = 0; i < sz; i++)
|
||||
@ -713,6 +719,20 @@ term_strlen(const struct termp *p, const char *cp)
|
||||
case ESCAPE_SKIPCHAR:
|
||||
skip = 1;
|
||||
continue;
|
||||
case ESCAPE_OVERSTRIKE:
|
||||
rsz = 0;
|
||||
rhs = seq + ssz;
|
||||
while (seq < rhs) {
|
||||
if (*seq == '\\') {
|
||||
mandoc_escape(&seq, NULL, NULL);
|
||||
continue;
|
||||
}
|
||||
i = (*p->width)(p, *seq++);
|
||||
if (rsz < i)
|
||||
rsz = i;
|
||||
}
|
||||
sz += rsz;
|
||||
continue;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@ -766,47 +786,55 @@ term_strlen(const struct termp *p, const char *cp)
|
||||
return(sz);
|
||||
}
|
||||
|
||||
size_t
|
||||
int
|
||||
term_vspan(const struct termp *p, const struct roffsu *su)
|
||||
{
|
||||
double r;
|
||||
int ri;
|
||||
|
||||
switch (su->unit) {
|
||||
case SCALE_BU:
|
||||
r = su->scale / 40.0;
|
||||
break;
|
||||
case SCALE_CM:
|
||||
r = su->scale * 2.0;
|
||||
r = su->scale * 6.0 / 2.54;
|
||||
break;
|
||||
case SCALE_FS:
|
||||
r = su->scale * 65536.0 / 40.0;
|
||||
break;
|
||||
case SCALE_IN:
|
||||
r = su->scale * 6.0;
|
||||
break;
|
||||
case SCALE_MM:
|
||||
r = su->scale * 0.006;
|
||||
break;
|
||||
case SCALE_PC:
|
||||
r = su->scale;
|
||||
break;
|
||||
case SCALE_PT:
|
||||
r = su->scale / 8.0;
|
||||
r = su->scale / 12.0;
|
||||
break;
|
||||
case SCALE_MM:
|
||||
r = su->scale / 1000.0;
|
||||
case SCALE_EN:
|
||||
/* FALLTHROUGH */
|
||||
case SCALE_EM:
|
||||
r = su->scale * 0.6;
|
||||
break;
|
||||
case SCALE_VS:
|
||||
r = su->scale;
|
||||
break;
|
||||
default:
|
||||
r = su->scale - 1.0;
|
||||
break;
|
||||
abort();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
if (r < 0.0)
|
||||
r = 0.0;
|
||||
return((size_t)(r + 0.0005));
|
||||
ri = r > 0.0 ? r + 0.4995 : r - 0.4995;
|
||||
return(ri < 66 ? ri : 1);
|
||||
}
|
||||
|
||||
size_t
|
||||
int
|
||||
term_hspan(const struct termp *p, const struct roffsu *su)
|
||||
{
|
||||
double v;
|
||||
|
||||
v = (*p->hspan)(p, su);
|
||||
if (v < 0.0)
|
||||
v = 0.0;
|
||||
return((size_t)(v + 0.0005));
|
||||
return(v > 0.0 ? v + 0.0005 : v - 0.0005);
|
||||
}
|
||||
|
15
term.h
15
term.h
@ -1,4 +1,4 @@
|
||||
/* $Id: term.h,v 1.108 2014/12/02 10:08:06 schwarze Exp $ */
|
||||
/* $Id: term.h,v 1.111 2015/01/31 00:12:41 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -84,7 +84,8 @@ struct termp {
|
||||
enum termenc enc; /* Type of encoding. */
|
||||
const struct mchars *symtab; /* Character table. */
|
||||
enum termfont fontl; /* Last font set. */
|
||||
enum termfont fontq[10]; /* Symmetric fonts. */
|
||||
enum termfont *fontq; /* Symmetric fonts. */
|
||||
int fontsz; /* Allocated size of font stack */
|
||||
int fonti; /* Index of font stack. */
|
||||
term_margin headf; /* invoked to print head */
|
||||
term_margin footf; /* invoked to print foot */
|
||||
@ -120,18 +121,14 @@ void term_begin(struct termp *, term_margin,
|
||||
void term_end(struct termp *);
|
||||
|
||||
void term_setwidth(struct termp *, const char *);
|
||||
size_t term_hspan(const struct termp *,
|
||||
const struct roffsu *);
|
||||
size_t term_vspan(const struct termp *,
|
||||
const struct roffsu *);
|
||||
int term_hspan(const struct termp *, const struct roffsu *);
|
||||
int term_vspan(const struct termp *, const struct roffsu *);
|
||||
size_t term_strlen(const struct termp *, const char *);
|
||||
size_t term_len(const struct termp *, size_t);
|
||||
|
||||
enum termfont term_fonttop(struct termp *);
|
||||
const void *term_fontq(struct termp *);
|
||||
void term_fontpush(struct termp *, enum termfont);
|
||||
void term_fontpop(struct termp *);
|
||||
void term_fontpopq(struct termp *, const void *);
|
||||
void term_fontpopq(struct termp *, int);
|
||||
void term_fontrepl(struct termp *, enum termfont);
|
||||
void term_fontlast(struct termp *);
|
||||
|
||||
|
29
term_ascii.c
29
term_ascii.c
@ -1,4 +1,4 @@
|
||||
/* $Id: term_ascii.c,v 1.40 2014/11/20 13:56:20 schwarze Exp $ */
|
||||
/* $Id: term_ascii.c,v 1.43 2015/02/16 14:11:41 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
@ -63,12 +63,17 @@ ascii_init(enum termenc enc, const struct mchars *mchars, char *outopts)
|
||||
const char *toks[5];
|
||||
char *v;
|
||||
struct termp *p;
|
||||
const char *errstr;
|
||||
int num;
|
||||
|
||||
p = mandoc_calloc(1, sizeof(struct termp));
|
||||
|
||||
p->symtab = mchars;
|
||||
p->tabwidth = 5;
|
||||
p->defrmargin = p->lastrmargin = 78;
|
||||
p->fontq = mandoc_reallocarray(NULL,
|
||||
(p->fontsz = 8), sizeof(enum termfont));
|
||||
p->fontq[0] = p->fontl = TERMFONT_NONE;
|
||||
|
||||
p->begin = ascii_begin;
|
||||
p->end = ascii_end;
|
||||
@ -106,10 +111,14 @@ ascii_init(enum termenc enc, const struct mchars *mchars, char *outopts)
|
||||
while (outopts && *outopts)
|
||||
switch (getsubopt(&outopts, UNCONST(toks), &v)) {
|
||||
case 0:
|
||||
p->defindent = (size_t)atoi(v);
|
||||
num = strtonum(v, 0, 1000, &errstr);
|
||||
if (!errstr)
|
||||
p->defindent = num;
|
||||
break;
|
||||
case 1:
|
||||
p->defrmargin = (size_t)atoi(v);
|
||||
num = strtonum(v, 0, 1000, &errstr);
|
||||
if (!errstr)
|
||||
p->defrmargin = num;
|
||||
break;
|
||||
case 2:
|
||||
/*
|
||||
@ -171,6 +180,20 @@ ascii_setwidth(struct termp *p, int iop, size_t width)
|
||||
p->rmargin = p->maxrmargin = p->defrmargin;
|
||||
}
|
||||
|
||||
void
|
||||
ascii_sepline(void *arg)
|
||||
{
|
||||
struct termp *p;
|
||||
size_t i;
|
||||
|
||||
p = (struct termp *)arg;
|
||||
putchar('\n');
|
||||
for (i = 0; i < p->defrmargin; i++)
|
||||
putchar('-');
|
||||
putchar('\n');
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
static size_t
|
||||
ascii_width(const struct termp *p, int c)
|
||||
{
|
||||
|
41
term_ps.c
41
term_ps.c
@ -1,7 +1,7 @@
|
||||
/* $Id: term_ps.c,v 1.70 2014/12/01 08:05:52 schwarze Exp $ */
|
||||
/* $Id: term_ps.c,v 1.72 2015/01/21 19:40:54 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -60,6 +60,7 @@ struct termp_ps {
|
||||
#define PS_NEWPAGE (1 << 2) /* new page, no words yet */
|
||||
#define PS_BACKSP (1 << 3) /* last character was backspace */
|
||||
size_t pscol; /* visible column (AFM units) */
|
||||
size_t pscolnext; /* used for overstrike */
|
||||
size_t psrow; /* visible row (AFM units) */
|
||||
char *psmarg; /* margin buf */
|
||||
size_t psmargsz; /* margin buf size */
|
||||
@ -540,6 +541,9 @@ pspdf_alloc(const struct mchars *mchars, char *outopts)
|
||||
p = mandoc_calloc(1, sizeof(struct termp));
|
||||
p->symtab = mchars;
|
||||
p->enc = TERMENC_ASCII;
|
||||
p->fontq = mandoc_reallocarray(NULL,
|
||||
(p->fontsz = 8), sizeof(enum termfont));
|
||||
p->fontq[0] = p->fontl = TERMFONT_NONE;
|
||||
p->ps = mandoc_calloc(1, sizeof(struct termp_ps));
|
||||
|
||||
p->advance = ps_advance;
|
||||
@ -1069,7 +1073,7 @@ ps_fclose(struct termp *p)
|
||||
static void
|
||||
ps_letter(struct termp *p, int arg)
|
||||
{
|
||||
size_t savecol;
|
||||
size_t savecol, wx;
|
||||
char c;
|
||||
|
||||
c = arg >= 128 || arg <= 0 ? '?' : arg;
|
||||
@ -1141,7 +1145,30 @@ ps_letter(struct termp *p, int arg)
|
||||
ps_setfont(p, p->ps->nextf);
|
||||
}
|
||||
p->ps->nextf = TERMFONT_NONE;
|
||||
|
||||
/*
|
||||
* For an overstrike, if a previous character
|
||||
* was wider, advance to center the new one.
|
||||
*/
|
||||
|
||||
if (p->ps->pscolnext) {
|
||||
wx = fonts[p->ps->lastf].gly[(int)p->ps->last-32].wx;
|
||||
if (p->ps->pscol + wx < p->ps->pscolnext)
|
||||
p->ps->pscol = (p->ps->pscol +
|
||||
p->ps->pscolnext - wx) / 2;
|
||||
}
|
||||
|
||||
ps_pletter(p, p->ps->last);
|
||||
|
||||
/*
|
||||
* For an overstrike, if a previous character
|
||||
* was wider, advance to the end of the old one.
|
||||
*/
|
||||
|
||||
if (p->ps->pscol < p->ps->pscolnext) {
|
||||
ps_pclose(p);
|
||||
p->ps->pscol = p->ps->pscolnext;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1155,13 +1182,19 @@ ps_letter(struct termp *p, int arg)
|
||||
|
||||
/*
|
||||
* For an overstrike, back up to the previous position.
|
||||
* If the previous character is wider than any it overstrikes,
|
||||
* remember the current position, because it might also be
|
||||
* wider than all that will overstrike it.
|
||||
*/
|
||||
|
||||
if (savecol != SIZE_MAX) {
|
||||
if (p->ps->pscolnext < p->ps->pscol)
|
||||
p->ps->pscolnext = p->ps->pscol;
|
||||
ps_pclose(p);
|
||||
p->ps->pscol = savecol;
|
||||
p->ps->flags &= ~PS_BACKSP;
|
||||
}
|
||||
} else
|
||||
p->ps->pscolnext = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
42
test-strtonum.c
Normal file
42
test-strtonum.c
Normal file
@ -0,0 +1,42 @@
|
||||
/* $Id: test-strtonum.c,v 1.1 2015/02/16 14:56:22 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const char *errstr;
|
||||
|
||||
if (strtonum("1", 0, 2, &errstr) != 1)
|
||||
return(1);
|
||||
if (errstr != NULL)
|
||||
return(2);
|
||||
if (strtonum("1x", 0, 2, &errstr) != 0)
|
||||
return(3);
|
||||
if (errstr == NULL)
|
||||
return(4);
|
||||
if (strtonum("2", 0, 1, &errstr) != 0)
|
||||
return(5);
|
||||
if (errstr == NULL)
|
||||
return(6);
|
||||
if (strtonum("0", 1, 2, &errstr) != 0)
|
||||
return(7);
|
||||
if (errstr == NULL)
|
||||
return(8);
|
||||
return(0);
|
||||
}
|
39
tree.c
39
tree.c
@ -1,7 +1,7 @@
|
||||
/* $Id: tree.c,v 1.60 2014/11/28 05:51:32 schwarze Exp $ */
|
||||
/* $Id: tree.c,v 1.62 2015/02/05 00:14:13 schwarze Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
|
||||
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -40,14 +40,14 @@ void
|
||||
tree_mdoc(void *arg, const struct mdoc *mdoc)
|
||||
{
|
||||
|
||||
print_mdoc(mdoc_node(mdoc), 0);
|
||||
print_mdoc(mdoc_node(mdoc)->child, 0);
|
||||
}
|
||||
|
||||
void
|
||||
tree_man(void *arg, const struct man *man)
|
||||
{
|
||||
|
||||
print_man(man_node(man), 0);
|
||||
print_man(man_node(man)->child, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -58,6 +58,9 @@ print_mdoc(const struct mdoc_node *n, int indent)
|
||||
size_t argc;
|
||||
struct mdoc_argv *argv;
|
||||
|
||||
if (n == NULL)
|
||||
return;
|
||||
|
||||
argv = NULL;
|
||||
argc = 0;
|
||||
t = p = NULL;
|
||||
@ -142,7 +145,7 @@ print_mdoc(const struct mdoc_node *n, int indent)
|
||||
print_span(n->span, indent);
|
||||
} else {
|
||||
for (i = 0; i < indent; i++)
|
||||
putchar('\t');
|
||||
putchar(' ');
|
||||
|
||||
printf("%s (%s)", p, t);
|
||||
|
||||
@ -159,16 +162,14 @@ print_mdoc(const struct mdoc_node *n, int indent)
|
||||
putchar(' ');
|
||||
if (MDOC_LINE & n->flags)
|
||||
putchar('*');
|
||||
printf("%d:%d", n->line, n->pos + 1);
|
||||
if (n->lastline != n->line)
|
||||
printf("-%d", n->lastline);
|
||||
putchar('\n');
|
||||
printf("%d:%d\n", n->line, n->pos + 1);
|
||||
}
|
||||
|
||||
if (n->eqn)
|
||||
print_box(n->eqn->root->first, indent + 1);
|
||||
print_box(n->eqn->root->first, indent + 4);
|
||||
if (n->child)
|
||||
print_mdoc(n->child, indent + 1);
|
||||
print_mdoc(n->child, indent +
|
||||
(n->type == MDOC_BLOCK ? 2 : 4));
|
||||
if (n->next)
|
||||
print_mdoc(n->next, indent);
|
||||
}
|
||||
@ -179,6 +180,9 @@ print_man(const struct man_node *n, int indent)
|
||||
const char *p, *t;
|
||||
int i;
|
||||
|
||||
if (n == NULL)
|
||||
return;
|
||||
|
||||
t = p = NULL;
|
||||
|
||||
switch (n->type) {
|
||||
@ -241,7 +245,7 @@ print_man(const struct man_node *n, int indent)
|
||||
print_span(n->span, indent);
|
||||
} else {
|
||||
for (i = 0; i < indent; i++)
|
||||
putchar('\t');
|
||||
putchar(' ');
|
||||
printf("%s (%s) ", p, t);
|
||||
if (MAN_LINE & n->flags)
|
||||
putchar('*');
|
||||
@ -249,9 +253,10 @@ print_man(const struct man_node *n, int indent)
|
||||
}
|
||||
|
||||
if (n->eqn)
|
||||
print_box(n->eqn->root->first, indent + 1);
|
||||
print_box(n->eqn->root->first, indent + 4);
|
||||
if (n->child)
|
||||
print_man(n->child, indent + 1);
|
||||
print_man(n->child, indent +
|
||||
(n->type == MAN_BLOCK ? 2 : 4));
|
||||
if (n->next)
|
||||
print_man(n->next, indent);
|
||||
}
|
||||
@ -270,7 +275,7 @@ print_box(const struct eqn_box *ep, int indent)
|
||||
if (NULL == ep)
|
||||
return;
|
||||
for (i = 0; i < indent; i++)
|
||||
putchar('\t');
|
||||
putchar(' ');
|
||||
|
||||
t = NULL;
|
||||
switch (ep->type) {
|
||||
@ -318,7 +323,7 @@ print_box(const struct eqn_box *ep, int indent)
|
||||
printf(" args=%zu", ep->args);
|
||||
putchar('\n');
|
||||
|
||||
print_box(ep->first, indent + 1);
|
||||
print_box(ep->first, indent + 4);
|
||||
print_box(ep->next, indent);
|
||||
}
|
||||
|
||||
@ -329,7 +334,7 @@ print_span(const struct tbl_span *sp, int indent)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < indent; i++)
|
||||
putchar('\t');
|
||||
putchar(' ');
|
||||
|
||||
switch (sp->pos) {
|
||||
case TBL_SPAN_HORIZ:
|
||||
|
Loading…
Reference in New Issue
Block a user