Import mandoc snapshot 2019-07-23

This commit is contained in:
Baptiste Daroussin 2019-07-26 09:51:35 +00:00
parent 8f0c701250
commit a5efdeedef
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/mandoc/dist/; revision=350349
svn path=/vendor/mandoc/20190723/; revision=350350; tag=vendor/mandoc/20190723
43 changed files with 892 additions and 635 deletions

View File

@ -29,7 +29,7 @@ dbm.o: dbm.c config.h mansearch.h dbm_map.h dbm.h
dbm_map.o: dbm_map.c config.h mansearch.h dbm_map.h dbm.h
demandoc.o: demandoc.c config.h mandoc.h roff.h man.h mdoc.h mandoc_parse.h
eqn.o: eqn.c config.h mandoc_aux.h mandoc.h roff.h eqn.h libmandoc.h eqn_parse.h
eqn_html.o: eqn_html.c config.h mandoc.h eqn.h out.h html.h
eqn_html.o: eqn_html.c config.h mandoc.h roff.h eqn.h out.h html.h
eqn_term.o: eqn_term.c config.h eqn.h out.h term.h
html.o: html.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc.h roff.h out.h html.h manconf.h main.h
lib.o: lib.c config.h roff.h libmdoc.h lib.in
@ -37,16 +37,16 @@ main.o: main.c config.h mandoc_aux.h mandoc.h mandoc_xr.h roff.h mdoc.h man.h ma
man.o: man.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h
man_html.o: man_html.c config.h mandoc_aux.h mandoc.h roff.h man.h out.h html.h main.h
man_macro.o: man_macro.c config.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h
man_term.o: man_term.c config.h mandoc_aux.h roff.h man.h out.h term.h main.h
man_term.o: man_term.c config.h mandoc_aux.h mandoc.h roff.h man.h out.h term.h tag.h main.h
man_validate.o: man_validate.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h
mandoc.o: mandoc.c config.h mandoc_aux.h mandoc.h roff.h libmandoc.h roff_int.h
mandoc_aux.o: mandoc_aux.c config.h mandoc.h mandoc_aux.h
mandoc_msg.o: mandoc_msg.c mandoc.h
mandoc_msg.o: mandoc_msg.c config.h mandoc.h
mandoc_ohash.o: mandoc_ohash.c mandoc_aux.h mandoc_ohash.h compat_ohash.h
mandoc_xr.o: mandoc_xr.c mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc_xr.h
mandocd.o: mandocd.c config.h mandoc.h roff.h mdoc.h man.h mandoc_parse.h main.h manconf.h
mandocdb.o: mandocdb.c config.h compat_fts.h mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc.h roff.h mdoc.h man.h mandoc_parse.h manconf.h mansearch.h dba_array.h dba.h
manpath.o: manpath.c config.h mandoc_aux.h manconf.h
manpath.o: manpath.c config.h mandoc_aux.h mandoc.h manconf.h
mansearch.o: mansearch.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h manconf.h mansearch.h dbm.h
mdoc.o: mdoc.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
mdoc_argv.o: mdoc_argv.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h
@ -67,10 +67,10 @@ roff_term.o: roff_term.c mandoc.h roff.h out.h term.h
roff_validate.o: roff_validate.c mandoc.h roff.h libmandoc.h roff_int.h
soelim.o: soelim.c config.h compat_stringlist.h
st.o: st.c config.h mandoc.h roff.h libmdoc.h
tag.o: tag.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h tag.h
tag.o: tag.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h mandoc.h tag.h
tbl.o: tbl.c config.h mandoc_aux.h mandoc.h tbl.h libmandoc.h tbl_parse.h tbl_int.h
tbl_data.o: tbl_data.c config.h mandoc_aux.h mandoc.h tbl.h libmandoc.h tbl_int.h
tbl_html.o: tbl_html.c config.h mandoc.h tbl.h out.h html.h
tbl_html.o: tbl_html.c config.h mandoc.h roff.h tbl.h out.h html.h
tbl_layout.o: tbl_layout.c config.h mandoc_aux.h mandoc.h tbl.h libmandoc.h tbl_int.h
tbl_opts.o: tbl_opts.c config.h mandoc.h tbl.h libmandoc.h tbl_int.h
tbl_term.o: tbl_term.c config.h mandoc.h tbl.h out.h term.h

26
TODO
View File

@ -1,6 +1,6 @@
************************************************************************
* Official mandoc TODO.
* $Id: TODO,v 1.289 2019/03/04 13:01:57 schwarze Exp $
* $Id: TODO,v 1.295 2019/06/11 16:04:36 schwarze Exp $
************************************************************************
Many issues are annotated for difficulty as follows:
@ -62,6 +62,27 @@ are mere guesses, and some may be wrong.
needed for Tcl_NewStringObj(3) via wiz@ Wed, 5 Mar 2014 22:27:43 +0100
loc ** exist *** algo *** size * imp ***
- .als only works for macros in mandoc, not for user-defined strings.
Also, the "val" field in struct roffkv would have to be replaced
with a pointer to a reference-counted wrapper, and an alias
would have to point to the same wrapper as the original.
.als to undefined does nothing; the alias is not created.
.rm'ing the original leaves the alias to point to the old value.
.de .als .de changes both, but
.de .als .rm .de only changes the new value, not the alias.
Found in groffer(1) version 1.19
Jan Stary 20 Apr 2019 20:16:54 +0200
loc * exist ** algo ** size ** imp *
- roff string condition comparisons fail when vars contain quotes:
.ds s '
.if '\*s'' \&...
hard to fix because of the basic architecture (string replacement
happens before roff(7) syntax parsing)
Found in groffer(1) version 1.19
Jan Stary 20 Apr 2019 20:16:54 +0200
loc * exist *** algo *** size ** imp *
--- missing mdoc features ----------------------------------------------
- .Bl -column .Xo support is missing
@ -264,6 +285,9 @@ are mere guesses, and some may be wrong.
https://github.com/schmonz/ikiwiki/compare/mandoc
Amitai Schlair Mon, 19 May 2014 14:05:53 -0400
- check compatibility with
https://git.sr.ht/~sircmpwn/scdoc
- check features of the Slackware man.conf(5) format
Carsten Kunze Wed, 11 Mar 2015 17:57:24 +0100

4
arch.c
View File

@ -1,4 +1,4 @@
/* $Id: arch.c,v 1.14 2019/03/04 13:01:57 schwarze Exp $ */
/* $Id: arch.c,v 1.15 2019/05/21 07:52:00 schwarze Exp $ */
/*
* Copyright (c) 2017, 2019 Ingo Schwarze <schwarze@openbsd.org>
*
@ -26,7 +26,7 @@ arch_valid(const char *arch, enum mandoc_os os)
const char *openbsd_arch[] = {
"alpha", "amd64", "arm64", "armv7", "hppa", "i386",
"landisk", "loongson", "luna88k", "macppc", "mips64",
"octeon", "sgi", "socppc", "sparc64", NULL
"octeon", "sgi", "sparc64", NULL
};
const char *netbsd_arch[] = {
"acorn26", "acorn32", "algor", "alpha", "amiga",

3
cgi.c
View File

@ -1,4 +1,4 @@
/* $Id: cgi.c,v 1.166 2019/03/06 12:32:41 schwarze Exp $ */
/* $Id: cgi.c,v 1.167 2019/07/10 12:49:20 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015, 2016, 2017, 2018 Ingo Schwarze <schwarze@usta.de>
@ -869,7 +869,6 @@ resp_format(const struct req *req, const char *file)
memset(&conf, 0, sizeof(conf));
conf.fragment = 1;
conf.style = mandoc_strdup(CSS_DIR "/mandoc.css");
conf.toc = 1;
usepath = strcmp(req->q.manpath, req->p[0]);
mandoc_asprintf(&conf.man, "/%s%s%s%s%%N.%%S",
scriptname, *scriptname == '\0' ? "" : "/",

4
configure vendored
View File

@ -1,6 +1,6 @@
#!/bin/sh
#
# $Id: configure,v 1.70 2019/03/06 16:04:31 schwarze Exp $
# $Id: configure,v 1.71 2019/07/01 22:56:24 schwarze Exp $
#
# Copyright (c) 2014-2019 Ingo Schwarze <schwarze@openbsd.org>
#
@ -529,7 +529,7 @@ fi
echo "extern char *mkdtemp(char *);"
if [ ${HAVE_PROGNAME} -eq 0 ]; then
echo "extern const char *getprogname(void);"
echo "extern const char *getprogname(void);"
echo "extern void setprogname(const char *);"
fi

6
dbm.c
View File

@ -1,4 +1,4 @@
/* $Id: dbm.c,v 1.6 2018/11/19 19:22:07 schwarze Exp $ */
/* $Id: dbm.c,v 1.7 2019/07/01 22:56:24 schwarze Exp $ */
/*
* Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
*
@ -233,7 +233,7 @@ static struct dbm_res
page_bytitle(enum iter arg_iter, const struct dbm_match *arg_match)
{
static const struct dbm_match *match;
static const char *cp;
static const char *cp;
static int32_t ip;
struct dbm_res res = {-1, 0};
@ -315,7 +315,7 @@ page_byarch(const struct dbm_match *arg_match)
static const struct dbm_match *match;
struct dbm_res res = {-1, 0};
static int32_t ip;
const char *cp;
const char *cp;
/* Initialize for a new iteration. */

View File

@ -1,4 +1,4 @@
/* $Id: dbm_map.h,v 1.1 2016/07/19 21:31:55 schwarze Exp $ */
/* $Id: dbm_map.h,v 1.2 2019/07/01 22:56:24 schwarze Exp $ */
/*
* Copyright (c) 2016 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.
*
* Private interface for low-level routines for the map-based version
* Private interface for low-level routines for the map-based version
* of the mandoc database, for read-only access.
* To be used by dbm*.c only.
*/

6
eqn.7
View File

@ -1,4 +1,4 @@
.\" $Id: eqn.7,v 1.37 2017/09/04 10:35:27 schwarze Exp $
.\" $Id: eqn.7,v 1.38 2019/04/23 17:57:49 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: September 4 2017 $
.Dd $Mdocdate: April 23 2019 $
.Dt EQN 7
.Os
.Sh NAME
@ -470,7 +470,7 @@ commands are also ignored.
.%T System for Typesetting Mathematics
.%J Communications of the ACM
.%V 18
.%P 151\(en157
.%P pp. 151\(en157
.%D March, 1975
.Re
.Rs

View File

@ -1,4 +1,4 @@
/* $Id: eqn_html.c,v 1.18 2018/12/13 05:23:38 schwarze Exp $ */
/* $Id: eqn_html.c,v 1.19 2019/03/17 18:21:45 schwarze Exp $ */
/*
* Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
@ -26,6 +26,7 @@
#include <string.h>
#include "mandoc.h"
#include "roff.h"
#include "eqn.h"
#include "out.h"
#include "html.h"

74
html.c
View File

@ -1,4 +1,4 @@
/* $Id: html.c,v 1.254 2019/03/03 13:02:11 schwarze Exp $ */
/* $Id: html.c,v 1.255 2019/04/30 15:53:00 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
@ -120,6 +120,7 @@ static void print_ctag(struct html *, struct tag *);
static int print_escape(struct html *, char);
static int print_encode(struct html *, const char *, const char *, int);
static void print_href(struct html *, const char *, const char *, int);
static void print_metaf(struct html *);
void *
@ -222,55 +223,49 @@ print_gen_head(struct html *h)
print_tagq(h, t);
}
void
print_metaf(struct html *h, enum mandoc_esc deco)
int
html_setfont(struct html *h, enum mandoc_esc font)
{
enum htmlfont font;
switch (deco) {
switch (font) {
case ESCAPE_FONTPREV:
font = h->metal;
break;
case ESCAPE_FONTITALIC:
font = HTMLFONT_ITALIC;
break;
case ESCAPE_FONTBOLD:
font = HTMLFONT_BOLD;
break;
case ESCAPE_FONTBI:
font = HTMLFONT_BI;
break;
case ESCAPE_FONTCW:
font = HTMLFONT_CW;
case ESCAPE_FONTROMAN:
break;
case ESCAPE_FONT:
case ESCAPE_FONTROMAN:
font = HTMLFONT_NONE;
font = ESCAPE_FONTROMAN;
break;
default:
return;
return 0;
}
h->metal = h->metac;
h->metac = font;
return 1;
}
static void
print_metaf(struct html *h)
{
if (h->metaf) {
print_tagq(h, h->metaf);
h->metaf = NULL;
}
h->metal = h->metac;
h->metac = font;
switch (font) {
case HTMLFONT_ITALIC:
switch (h->metac) {
case ESCAPE_FONTITALIC:
h->metaf = print_otag(h, TAG_I, "");
break;
case HTMLFONT_BOLD:
case ESCAPE_FONTBOLD:
h->metaf = print_otag(h, TAG_B, "");
break;
case HTMLFONT_BI:
case ESCAPE_FONTBI:
h->metaf = print_otag(h, TAG_B, "");
print_otag(h, TAG_I, "");
break;
case HTMLFONT_CW:
case ESCAPE_FONTCW:
h->metaf = print_otag(h, TAG_SPAN, "c", "Li");
break;
default:
@ -479,7 +474,8 @@ print_encode(struct html *h, const char *p, const char *pend, int norecurse)
case ESCAPE_FONTROMAN:
if (0 == norecurse) {
h->flags |= HTML_NOSPACE;
print_metaf(h, esc);
if (html_setfont(h, esc))
print_metaf(h);
h->flags &= ~HTML_NOSPACE;
}
continue;
@ -806,27 +802,9 @@ print_text(struct html *h, const char *word)
print_word(h, "&#x00A0;");
}
assert(NULL == h->metaf);
switch (h->metac) {
case HTMLFONT_ITALIC:
h->metaf = print_otag(h, TAG_I, "");
break;
case HTMLFONT_BOLD:
h->metaf = print_otag(h, TAG_B, "");
break;
case HTMLFONT_BI:
h->metaf = print_otag(h, TAG_B, "");
print_otag(h, TAG_I, "");
break;
case HTMLFONT_CW:
h->metaf = print_otag(h, TAG_SPAN, "c", "Li");
break;
default:
print_indent(h);
break;
}
assert(word);
assert(h->metaf == NULL);
print_metaf(h);
print_indent(h);
if ( ! print_encode(h, word, NULL, 0)) {
if ( ! (h->flags & HTML_NONOSPACE))
h->flags &= ~HTML_NOSPACE;
@ -834,7 +812,7 @@ print_text(struct html *h, const char *word)
} else
h->flags |= HTML_NOSPACE | HTML_NONEWLINE;
if (h->metaf) {
if (h->metaf != NULL) {
print_tagq(h, h->metaf);
h->metaf = NULL;
}

17
html.h
View File

@ -1,4 +1,4 @@
/* $Id: html.h,v 1.102 2019/03/01 10:57:18 schwarze Exp $ */
/* $Id: html.h,v 1.103 2019/04/30 15:53:00 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2017, 2018, 2019 Ingo Schwarze <schwarze@openbsd.org>
@ -69,15 +69,6 @@ enum htmltag {
TAG_MAX
};
enum htmlfont {
HTMLFONT_NONE = 0,
HTMLFONT_BOLD,
HTMLFONT_ITALIC,
HTMLFONT_BI,
HTMLFONT_CW,
HTMLFONT_MAX
};
struct tag {
struct tag *next;
int refcnt;
@ -111,8 +102,8 @@ struct html {
char *base_includes; /* base for include href */
char *style; /* style-sheet URI */
struct tag *metaf; /* current open font scope */
enum htmlfont metal; /* last used font */
enum htmlfont metac; /* current font mode */
enum mandoc_esc metal; /* last used font */
enum mandoc_esc metac; /* current font mode */
int oflags; /* output options */
#define HTML_FRAGMENT (1 << 0) /* don't emit HTML/HEAD/BODY */
#define HTML_TOC (1 << 1) /* emit a table of contents */
@ -128,7 +119,6 @@ void roff_html_pre(struct html *, const struct roff_node *);
void print_gen_comment(struct html *, struct roff_node *);
void print_gen_decls(struct html *);
void print_gen_head(struct html *);
void print_metaf(struct html *, enum mandoc_esc);
struct tag *print_otag(struct html *, enum htmltag, const char *, ...);
void print_tagq(struct html *, const struct tag *);
void print_stagq(struct html *, const struct tag *);
@ -141,3 +131,4 @@ void print_endline(struct html *);
void html_close_paragraph(struct html *);
enum roff_tok html_fillmode(struct html *, enum roff_tok);
char *html_make_id(const struct roff_node *, int);
int html_setfont(struct html *, enum mandoc_esc);

4
lib.in
View File

@ -1,4 +1,4 @@
/* $Id: lib.in,v 1.21 2019/03/04 17:35:21 schwarze Exp $ */
/* $Id: lib.in,v 1.22 2019/07/01 22:56:24 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2009, 2012 Joerg Sonnenberger <joerg@netbsd.org>
@ -43,7 +43,7 @@ LINE("libcipher", "FreeSec Crypt Library (libcipher, \\-lcipher)")
LINE("libcompat", "Compatibility Library (libcompat, \\-lcompat)")
LINE("libcrypt", "Crypt Library (libcrypt, \\-lcrypt)")
LINE("libcurses", "Curses Library (libcurses, \\-lcurses)")
LINE("libcuse", "Userland Character Device Library (libcuse, \\-lcuse)")
LINE("libcuse", "Userland Character Device Library (libcuse, \\-lcuse)")
LINE("libdevattr", "Device attribute and event library (libdevattr, \\-ldevattr)")
LINE("libdevctl", "Device Control Library (libdevctl, \\-ldevctl)")
LINE("libdevinfo", "Device and Resource Information Utility Library (libdevinfo, \\-ldevinfo)")

View File

@ -1,80 +0,0 @@
/* $Id: libroff.h,v 1.42 2017/07/08 17:52:49 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015, 2017 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.
*/
enum tbl_part {
TBL_PART_OPTS, /* in options (first line) */
TBL_PART_LAYOUT, /* describing layout */
TBL_PART_DATA, /* creating data rows */
TBL_PART_CDATA /* continue previous row */
};
struct tbl_node {
struct mparse *parse; /* parse point */
int pos; /* invocation column */
int line; /* invocation line */
enum tbl_part part;
struct tbl_opts opts;
struct tbl_row *first_row;
struct tbl_row *last_row;
struct tbl_span *first_span;
struct tbl_span *current_span;
struct tbl_span *last_span;
struct tbl_node *next;
};
struct eqn_node {
struct mparse *parse; /* main parser, for error reporting */
struct roff_node *node; /* syntax tree of this equation */
struct eqn_def *defs; /* array of definitions */
char *data; /* source code of this equation */
char *start; /* first byte of the current token */
char *end; /* first byte of the next token */
size_t defsz; /* number of definitions */
size_t sz; /* length of the source code */
size_t toksz; /* length of the current token */
int gsize; /* default point size */
int delim; /* in-line delimiters enabled */
char odelim; /* in-line opening delimiter */
char cdelim; /* in-line closing delimiter */
};
struct eqn_def {
char *key;
size_t keysz;
char *val;
size_t valsz;
};
struct tbl_node *tbl_alloc(int, int, struct mparse *);
void tbl_restart(int, int, struct tbl_node *);
void tbl_free(struct tbl_node *);
void tbl_reset(struct tbl_node *);
void tbl_read(struct tbl_node *, int, const char *, int);
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);
void tbl_cdata(struct tbl_node *, int, const char *, int);
const struct tbl_span *tbl_span(struct tbl_node *);
int tbl_end(struct tbl_node *);
struct eqn_node *eqn_alloc(struct mparse *);
void eqn_box_free(struct eqn_box *);
void eqn_free(struct eqn_node *);
void eqn_parse(struct eqn_node *);
void eqn_read(struct eqn_node *, const char *);
void eqn_reset(struct eqn_node *);

359
main.c
View File

@ -1,4 +1,4 @@
/* $Id: main.c,v 1.322 2019/03/06 10:18:58 schwarze Exp $ */
/* $Id: main.c,v 1.332 2019/07/19 20:27:25 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2012, 2014-2019 Ingo Schwarze <schwarze@openbsd.org>
@ -21,6 +21,7 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/param.h> /* MACHINE */
#include <sys/stat.h>
#include <sys/wait.h>
#include <assert.h>
@ -97,13 +98,10 @@ static int fs_lookup(const struct manpaths *,
static int fs_search(const struct mansearch *,
const struct manpaths *, int, char**,
struct manpage **, size_t *);
static int koptions(int *, char *);
static void moptions(int *, char *);
static void outdata_alloc(struct curparse *);
static void parse(struct curparse *, int, const char *);
static void passthrough(const char *, int, int);
static void passthrough(int, int);
static pid_t spawn_pager(struct tag_files *);
static int toptions(struct curparse *, char *);
static void usage(enum argmode) __attribute__((__noreturn__));
static int woptions(struct curparse *, char *);
@ -125,7 +123,7 @@ main(int argc, char *argv[])
char *conf_file, *defpaths, *auxpaths;
char *oarg, *tagarg;
unsigned char *uc;
size_t i, sz;
size_t i, sz, ssz;
int prio, best_prio;
enum outmode outmode;
int fd, startdir;
@ -154,10 +152,11 @@ main(int argc, char *argv[])
return mandocdb(argc, argv);
#if HAVE_PLEDGE
if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1)
err((int)MANDOCLEVEL_SYSERR, "pledge");
if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1) {
mandoc_msg(MANDOCERR_PLEDGE, 0, 0, "%s", strerror(errno));
return mandoc_msg_getrc();
}
#endif
#if HAVE_SANDBOX_INIT
if (sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, NULL) == -1)
errx((int)MANDOCLEVEL_SYSERR, "sandbox_init");
@ -221,19 +220,29 @@ main(int argc, char *argv[])
outmode = OUTMODE_ALL;
break;
case 'I':
if (strncmp(optarg, "os=", 3)) {
warnx("-I %s: Bad argument", optarg);
return (int)MANDOCLEVEL_BADARG;
if (strncmp(optarg, "os=", 3) != 0) {
mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0,
"-I %s", optarg);
return mandoc_msg_getrc();
}
if (curp.os_s != NULL) {
warnx("-I %s: Duplicate argument", optarg);
return (int)MANDOCLEVEL_BADARG;
mandoc_msg(MANDOCERR_BADARG_DUPE, 0, 0,
"-I %s", optarg);
return mandoc_msg_getrc();
}
curp.os_s = mandoc_strdup(optarg + 3);
break;
case 'K':
if ( ! koptions(&options, optarg))
return (int)MANDOCLEVEL_BADARG;
options &= ~(MPARSE_UTF8 | MPARSE_LATIN1);
if (strcmp(optarg, "utf-8") == 0)
options |= MPARSE_UTF8;
else if (strcmp(optarg, "iso-8859-1") == 0)
options |= MPARSE_LATIN1;
else if (strcmp(optarg, "us-ascii") != 0) {
mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0,
"-K %s", optarg);
return mandoc_msg_getrc();
}
break;
case 'k':
search.argmode = ARG_EXPR;
@ -258,12 +267,37 @@ main(int argc, char *argv[])
search.sec = optarg;
break;
case 'T':
if ( ! toptions(&curp, optarg))
return (int)MANDOCLEVEL_BADARG;
if (strcmp(optarg, "ascii") == 0)
curp.outtype = OUTT_ASCII;
else if (strcmp(optarg, "lint") == 0) {
curp.outtype = OUTT_LINT;
mandoc_msg_setoutfile(stdout);
mandoc_msg_setmin(MANDOCERR_BASE);
} else if (strcmp(optarg, "tree") == 0)
curp.outtype = OUTT_TREE;
else if (strcmp(optarg, "man") == 0)
curp.outtype = OUTT_MAN;
else if (strcmp(optarg, "html") == 0)
curp.outtype = OUTT_HTML;
else if (strcmp(optarg, "markdown") == 0)
curp.outtype = OUTT_MARKDOWN;
else if (strcmp(optarg, "utf8") == 0)
curp.outtype = OUTT_UTF8;
else if (strcmp(optarg, "locale") == 0)
curp.outtype = OUTT_LOCALE;
else if (strcmp(optarg, "ps") == 0)
curp.outtype = OUTT_PS;
else if (strcmp(optarg, "pdf") == 0)
curp.outtype = OUTT_PDF;
else {
mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0,
"-T %s", optarg);
return mandoc_msg_getrc();
}
break;
case 'W':
if ( ! woptions(&curp, optarg))
return (int)MANDOCLEVEL_BADARG;
if (woptions(&curp, optarg) == -1)
return mandoc_msg_getrc();
break;
case 'w':
outmode = OUTMODE_FLN;
@ -299,12 +333,9 @@ main(int argc, char *argv[])
search.outkey = oarg;
else {
while (oarg != NULL) {
thisarg = oarg;
if (manconf_output(&conf.output,
strsep(&oarg, ","), 0) == 0)
continue;
warnx("-O %s: Bad argument", thisarg);
return (int)MANDOCLEVEL_BADARG;
strsep(&oarg, ","), 0) == -1)
return mandoc_msg_getrc();
}
}
}
@ -328,9 +359,13 @@ main(int argc, char *argv[])
}
#if HAVE_PLEDGE
if (!use_pager)
if (pledge("stdio rpath", NULL) == -1)
err((int)MANDOCLEVEL_SYSERR, "pledge");
if (use_pager == 0) {
if (pledge("stdio rpath", NULL) == -1) {
mandoc_msg(MANDOCERR_PLEDGE, 0, 0,
"%s", strerror(errno));
return mandoc_msg_getrc();
}
}
#endif
/* Parse arguments. */
@ -355,7 +390,7 @@ main(int argc, char *argv[])
} else if (argc > 1 &&
((uc = (unsigned char *)argv[0]) != NULL) &&
((isdigit(uc[0]) && (uc[1] == '\0' ||
(isalpha(uc[1]) && uc[2] == '\0'))) ||
isalpha(uc[1]))) ||
(uc[0] == 'n' && uc[1] == '\0'))) {
search.sec = (char *)uc;
argv++;
@ -395,7 +430,7 @@ main(int argc, char *argv[])
usage(search.argmode);
if (sz == 0 && search.argmode == ARG_NAME)
fs_search(&search, &conf.manpath,
(void)fs_search(&search, &conf.manpath,
argc, argv, &res, &sz);
if (search.argmode == ARG_NAME) {
@ -403,7 +438,10 @@ main(int argc, char *argv[])
if (strchr(argv[c], '/') == NULL)
continue;
if (access(argv[c], R_OK) == -1) {
warn("%s", argv[c]);
mandoc_msg_setinfilename(argv[c]);
mandoc_msg(MANDOCERR_BADARG_BAD,
0, 0, "%s", strerror(errno));
mandoc_msg_setinfilename(NULL);
continue;
}
res = mandoc_reallocarray(res,
@ -411,6 +449,7 @@ main(int argc, char *argv[])
res[sz].file = mandoc_strdup(argv[c]);
res[sz].names = NULL;
res[sz].output = NULL;
res[sz].bits = 0;
res[sz].ipath = SIZE_MAX;
res[sz].sec = 10;
res[sz].form = FORM_SRC;
@ -433,7 +472,7 @@ main(int argc, char *argv[])
if (outmode == OUTMODE_ONE) {
argc = 1;
best_prio = 20;
best_prio = 40;
} else if (outmode == OUTMODE_ALL)
argc = (int)sz;
@ -452,10 +491,21 @@ main(int argc, char *argv[])
sec = res[i].file;
sec += strcspn(sec, "123456789");
if (sec[0] == '\0')
continue;
continue; /* No section at all. */
prio = sec_prios[sec[0] - '1'];
if (sec[1] != '/')
prio += 10;
if (search.sec != NULL) {
ssz = strlen(search.sec);
if (strncmp(sec, search.sec, ssz) == 0)
sec += ssz;
} else
sec++; /* Prefer without suffix. */
if (*sec != '/')
prio += 10; /* Wrong dir name. */
if (search.sec != NULL &&
(strlen(sec) <= ssz + 3 ||
strcmp(sec + strlen(sec) - ssz,
search.sec) != 0))
prio += 20; /* Wrong file ext. */
if (prio >= best_prio)
continue;
best_prio = prio;
@ -477,16 +527,26 @@ main(int argc, char *argv[])
#if HAVE_PLEDGE
if (use_pager) {
if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1)
err((int)MANDOCLEVEL_SYSERR, "pledge");
if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1) {
mandoc_msg(MANDOCERR_PLEDGE, 0, 0,
"%s", strerror(errno));
return mandoc_msg_getrc();
}
} else {
if (pledge("stdio rpath", NULL) == -1)
err((int)MANDOCLEVEL_SYSERR, "pledge");
if (pledge("stdio rpath", NULL) == -1) {
mandoc_msg(MANDOCERR_PLEDGE, 0, 0,
"%s", strerror(errno));
return mandoc_msg_getrc();
}
}
#endif
if (search.argmode == ARG_FILE)
moptions(&options, auxpaths);
if (search.argmode == ARG_FILE && auxpaths != NULL) {
if (strcmp(auxpaths, "doc") == 0)
options |= MPARSE_MDOC;
else if (strcmp(auxpaths, "an") == 0)
options |= MPARSE_MAN;
}
mchars_alloc();
curp.mp = mparse_alloc(options, curp.os_e, curp.os_s);
@ -494,7 +554,8 @@ main(int argc, char *argv[])
if (argc < 1) {
if (use_pager) {
tag_files = tag_init();
tag_files->tagname = conf.output.tag;
if (tag_files != NULL)
tag_files->tagname = conf.output.tag;
}
thisarg = "<stdin>";
mandoc_msg_setinfilename(thisarg);
@ -527,30 +588,31 @@ main(int argc, char *argv[])
} else
thisarg = *argv;
mandoc_msg_setinfilename(thisarg);
fd = mparse_open(curp.mp, thisarg);
if (fd != -1) {
if (use_pager) {
use_pager = 0;
tag_files = tag_init();
tag_files->tagname = conf.output.tag;
if (tag_files != NULL)
tag_files->tagname = conf.output.tag;
}
mandoc_msg_setinfilename(thisarg);
if (resp == NULL || resp->form == FORM_SRC)
parse(&curp, fd, thisarg);
else
passthrough(resp->file, fd,
conf.output.synopsisonly);
mandoc_msg_setinfilename(NULL);
passthrough(fd, conf.output.synopsisonly);
if (ferror(stdout)) {
if (tag_files != NULL) {
warn("%s", tag_files->ofn);
mandoc_msg(MANDOCERR_WRITE, 0, 0,
"%s: %s", tag_files->ofn,
strerror(errno));
tag_unlink();
tag_files = NULL;
} else
warn("stdout");
mandoc_msg_setrc(MANDOCLEVEL_SYSERR);
mandoc_msg(MANDOCERR_WRITE, 0, 0,
"%s", strerror(errno));
break;
}
@ -560,8 +622,10 @@ main(int argc, char *argv[])
terminal_sepline(curp.outdata);
}
} else
mandoc_msg(MANDOCERR_FILE, 0, 0,
"%s: %s", thisarg, strerror(errno));
mandoc_msg(resp == NULL ? MANDOCERR_BADARG_BAD :
MANDOCERR_OPEN, 0, 0, "%s", strerror(errno));
mandoc_msg_setinfilename(NULL);
if (curp.wstop && mandoc_msg_getrc() != MANDOCLEVEL_OK)
break;
@ -653,8 +717,8 @@ out:
continue;
if (pid == -1) {
warn("wait");
mandoc_msg_setrc(MANDOCLEVEL_SYSERR);
mandoc_msg(MANDOCERR_WAIT, 0, 0,
"%s", strerror(errno));
break;
}
if (!WIFSTOPPED(status))
@ -663,14 +727,16 @@ out:
signum = WSTOPSIG(status);
}
tag_unlink();
}
} else if (curp.outtype != OUTT_LINT &&
(search.argmode == ARG_FILE || sz > 0))
mandoc_msg_summary();
return (int)mandoc_msg_getrc();
}
static void
usage(enum argmode argmode)
{
switch (argmode) {
case ARG_FILE:
fputs("usage: mandoc [-ac] [-I os=name] "
@ -701,6 +767,7 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
const char *sec, const char *arch, const char *name,
struct manpage **res, size_t *ressz)
{
struct stat sb;
glob_t globinfo;
struct manpage *page;
char *file;
@ -710,13 +777,13 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
form = FORM_SRC;
mandoc_asprintf(&file, "%s/man%s/%s.%s",
paths->paths[ipath], sec, name, sec);
if (access(file, R_OK) != -1)
if (stat(file, &sb) != -1)
goto found;
free(file);
mandoc_asprintf(&file, "%s/cat%s/%s.0",
paths->paths[ipath], sec, name);
if (access(file, R_OK) != -1) {
if (stat(file, &sb) != -1) {
form = FORM_CAT;
goto found;
}
@ -725,7 +792,7 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
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)
if (stat(file, &sb) != -1)
goto found;
free(file);
}
@ -734,37 +801,42 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
paths->paths[ipath], sec, name);
globres = glob(file, 0, NULL, &globinfo);
if (globres != 0 && globres != GLOB_NOMATCH)
warn("%s: glob", file);
mandoc_msg(MANDOCERR_GLOB, 0, 0,
"%s: %s", file, strerror(errno));
free(file);
if (globres == 0)
file = mandoc_strdup(*globinfo.gl_pathv);
globfree(&globinfo);
if (globres == 0)
goto found;
if (globres == 0) {
if (stat(file, &sb) != -1)
goto found;
free(file);
}
if (res != NULL || ipath + 1 != paths->sz)
return 0;
return -1;
mandoc_asprintf(&file, "%s.%s", name, sec);
globres = access(file, R_OK);
globres = stat(file, &sb);
free(file);
return globres != -1;
return globres;
found:
warnx("outdated mandoc.db lacks %s(%s) entry, run %s %s",
name, sec, BINM_MAKEWHATIS, paths->paths[ipath]);
if (res == NULL) {
free(file);
return 1;
return 0;
}
*res = mandoc_reallocarray(*res, ++*ressz, sizeof(struct manpage));
*res = mandoc_reallocarray(*res, ++*ressz, sizeof(**res));
page = *res + (*ressz - 1);
page->file = file;
page->names = NULL;
page->output = NULL;
page->bits = NAME_FILE & NAME_MASK;
page->ipath = ipath;
page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10;
page->form = form;
return 1;
return 0;
}
static int
@ -786,14 +858,14 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths,
for (ipath = 0; ipath < paths->sz; ipath++) {
if (cfg->sec != NULL) {
if (fs_lookup(paths, ipath, cfg->sec,
cfg->arch, *argv, res, ressz) &&
cfg->arch, *argv, res, ressz) != -1 &&
cfg->firstmatch)
return 1;
return 0;
} else for (isec = 0; isec < nsec; isec++)
if (fs_lookup(paths, ipath, sections[isec],
cfg->arch, *argv, res, ressz) &&
cfg->arch, *argv, res, ressz) != -1 &&
cfg->firstmatch)
return 1;
return 0;
}
if (res != NULL && *ressz == lastsz &&
strchr(*argv, '/') == NULL) {
@ -812,7 +884,7 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths,
argv++;
argc--;
}
return 0;
return -1;
}
static void
@ -919,7 +991,7 @@ check_xr(void)
search.firstmatch = 1;
if (mansearch(&search, &paths, 1, &xr->name, NULL, &sz))
continue;
if (fs_search(&search, &paths, 1, &xr->name, NULL, &sz))
if (fs_search(&search, &paths, 1, &xr->name, NULL, &sz) != -1)
continue;
if (xr->count == 1)
mandoc_msg(MANDOCERR_XR_BAD, xr->line,
@ -959,34 +1031,34 @@ outdata_alloc(struct curparse *curp)
}
static void
passthrough(const char *file, int fd, int synopsis_only)
passthrough(int fd, int synopsis_only)
{
const char synb[] = "S\bSY\bYN\bNO\bOP\bPS\bSI\bIS\bS";
const char synr[] = "SYNOPSIS";
FILE *stream;
const char *syscall;
char *line, *cp;
size_t linesz;
ssize_t len, written;
int print;
int lno, print;
stream = NULL;
line = NULL;
linesz = 0;
if (fflush(stdout) == EOF) {
syscall = "fflush";
goto fail;
mandoc_msg(MANDOCERR_FFLUSH, 0, 0, "%s", strerror(errno));
goto done;
}
if ((stream = fdopen(fd, "r")) == NULL) {
close(fd);
syscall = "fdopen";
goto fail;
mandoc_msg(MANDOCERR_FDOPEN, 0, 0, "%s", strerror(errno));
goto done;
}
print = 0;
lno = print = 0;
while ((len = getline(&line, &linesz, stream)) != -1) {
lno++;
cp = line;
if (synopsis_only) {
if (print) {
@ -1004,94 +1076,20 @@ passthrough(const char *file, int fd, int synopsis_only)
}
}
for (; len > 0; len -= written) {
if ((written = write(STDOUT_FILENO, cp, len)) != -1)
continue;
fclose(stream);
syscall = "write";
goto fail;
if ((written = write(STDOUT_FILENO, cp, len)) == -1) {
mandoc_msg(MANDOCERR_WRITE, 0, 0,
"%s", strerror(errno));
goto done;
}
}
}
if (ferror(stream)) {
fclose(stream);
syscall = "getline";
goto fail;
}
if (ferror(stream))
mandoc_msg(MANDOCERR_GETLINE, lno, 0, "%s", strerror(errno));
done:
free(line);
fclose(stream);
return;
fail:
free(line);
warn("%s: SYSERR: %s", file, syscall);
mandoc_msg_setrc(MANDOCLEVEL_SYSERR);
}
static int
koptions(int *options, char *arg)
{
if ( ! strcmp(arg, "utf-8")) {
*options |= MPARSE_UTF8;
*options &= ~MPARSE_LATIN1;
} else if ( ! strcmp(arg, "iso-8859-1")) {
*options |= MPARSE_LATIN1;
*options &= ~MPARSE_UTF8;
} else if ( ! strcmp(arg, "us-ascii")) {
*options &= ~(MPARSE_UTF8 | MPARSE_LATIN1);
} else {
warnx("-K %s: Bad argument", arg);
return 0;
}
return 1;
}
static void
moptions(int *options, char *arg)
{
if (arg == NULL)
return;
if (strcmp(arg, "doc") == 0)
*options |= MPARSE_MDOC;
else if (strcmp(arg, "an") == 0)
*options |= MPARSE_MAN;
}
static int
toptions(struct curparse *curp, char *arg)
{
if (0 == strcmp(arg, "ascii"))
curp->outtype = OUTT_ASCII;
else if (0 == strcmp(arg, "lint")) {
curp->outtype = OUTT_LINT;
mandoc_msg_setoutfile(stdout);
mandoc_msg_setmin(MANDOCERR_BASE);
} else if (0 == strcmp(arg, "tree"))
curp->outtype = OUTT_TREE;
else if (0 == strcmp(arg, "man"))
curp->outtype = OUTT_MAN;
else if (0 == strcmp(arg, "html"))
curp->outtype = OUTT_HTML;
else if (0 == strcmp(arg, "markdown"))
curp->outtype = OUTT_MARKDOWN;
else if (0 == strcmp(arg, "utf8"))
curp->outtype = OUTT_UTF8;
else if (0 == strcmp(arg, "locale"))
curp->outtype = OUTT_LOCALE;
else if (0 == strcmp(arg, "ps"))
curp->outtype = OUTT_PS;
else if (0 == strcmp(arg, "pdf"))
curp->outtype = OUTT_PDF;
else {
warnx("-T %s: Bad argument", arg);
return 0;
}
return 1;
if (stream != NULL)
fclose(stream);
}
static int
@ -1135,7 +1133,7 @@ woptions(struct curparse *curp, char *arg)
mandoc_msg_setmin(MANDOCERR_UNSUPP);
break;
case 7:
mandoc_msg_setmin(MANDOCERR_MAX);
mandoc_msg_setmin(MANDOCERR_BADARG);
break;
case 8:
mandoc_msg_setmin(MANDOCERR_BASE);
@ -1146,11 +1144,11 @@ woptions(struct curparse *curp, char *arg)
curp->os_e = MANDOC_OS_NETBSD;
break;
default:
warnx("-W %s: Bad argument", o);
return 0;
mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0, "-W %s", o);
return -1;
}
}
return 1;
return 0;
}
static pid_t
@ -1196,7 +1194,7 @@ spawn_pager(struct tag_files *tag_files)
use_ofn = 1;
#if HAVE_LESS_T
if ((cmdlen = strlen(argv[0])) >= 4) {
if (*tag_files->tfn != '\0' && (cmdlen = strlen(argv[0])) >= 4) {
cp = argv[0] + cmdlen - 4;
if (strcmp(cp, "less") == 0) {
argv[argc++] = mandoc_strdup("-T");
@ -1215,15 +1213,19 @@ spawn_pager(struct tag_files *tag_files)
switch (pager_pid = fork()) {
case -1:
err((int)MANDOCLEVEL_SYSERR, "fork");
mandoc_msg(MANDOCERR_FORK, 0, 0, "%s", strerror(errno));
exit(mandoc_msg_getrc());
case 0:
break;
default:
(void)setpgid(pager_pid, 0);
(void)tcsetpgrp(tag_files->ofd, pager_pid);
#if HAVE_PLEDGE
if (pledge("stdio rpath tmppath tty proc", NULL) == -1)
err((int)MANDOCLEVEL_SYSERR, "pledge");
if (pledge("stdio rpath tmppath tty proc", NULL) == -1) {
mandoc_msg(MANDOCERR_PLEDGE, 0, 0,
"%s", strerror(errno));
exit(mandoc_msg_getrc());
}
#endif
tag_files->pager_pid = pager_pid;
return pager_pid;
@ -1231,8 +1233,10 @@ spawn_pager(struct tag_files *tag_files)
/* The child process becomes the pager. */
if (dup2(tag_files->ofd, STDOUT_FILENO) == -1)
err((int)MANDOCLEVEL_SYSERR, "pager stdout");
if (dup2(tag_files->ofd, STDOUT_FILENO) == -1) {
mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno));
_exit(mandoc_msg_getrc());
}
close(tag_files->ofd);
assert(tag_files->tfd == -1);
@ -1242,5 +1246,6 @@ spawn_pager(struct tag_files *tag_files)
nanosleep(&timeout, NULL);
execvp(argv[0], argv);
err((int)MANDOCLEVEL_SYSERR, "exec %s", argv[0]);
mandoc_msg(MANDOCERR_EXEC, 0, 0, "%s: %s", argv[0], strerror(errno));
_exit(mandoc_msg_getrc());
}

16
man.7
View File

@ -1,4 +1,4 @@
.\" $Id: man.7,v 1.143 2019/03/02 22:04:40 schwarze Exp $
.\" $Id: man.7,v 1.144 2019/07/09 03:46:59 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2011-2015,2017,2018,2019 Ingo Schwarze <schwarze@openbsd.org>
@ -17,7 +17,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: March 2 2019 $
.Dd $Mdocdate: July 9 2019 $
.Dt MAN 7
.Os
.Sh NAME
@ -160,7 +160,9 @@ This has no effect unless the tabulator positions were changed with the
.Ic ta
request.
.It Ic EE
This is a non-standard GNU extension.
This is a non-standard Version 9
.At
extension later adopted by GNU.
In
.Xr mandoc 1 ,
it does the same as the
@ -168,7 +170,9 @@ it does the same as the
.Ic fi
request (switch to fill mode).
.It Ic EX
This is a non-standard GNU extension.
This is a non-standard Version 9
.At
extension later adopted by GNU.
In
.Xr mandoc 1 ,
it does the same as the
@ -496,8 +500,8 @@ The syntax is as follows:
.It Ic BI Ta n Ta current Ta \&
.It Ic BR Ta n Ta current Ta \&
.It Ic DT Ta 0 Ta current Ta \&
.It Ic EE Ta 0 Ta current Ta GNU
.It Ic EX Ta 0 Ta current Ta GNU
.It Ic EE Ta 0 Ta current Ta Version 9 At
.It Ic EX Ta 0 Ta current Ta Version 9 At
.It Ic I Ta n Ta next-line Ta \&
.It Ic IB Ta n Ta current Ta \&
.It Ic IR Ta n Ta current Ta \&

View File

@ -1,4 +1,4 @@
/* $Id: man_html.c,v 1.173 2019/03/02 16:30:53 schwarze Exp $ */
/* $Id: man_html.c,v 1.174 2019/04/30 15:53:00 schwarze Exp $ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
@ -203,9 +203,9 @@ print_man_node(MAN_ARGS)
* Close out scope of font prior to opening a macro
* scope.
*/
if (HTMLFONT_NONE != h->metac) {
if (h->metac != ESCAPE_FONTROMAN) {
h->metal = h->metac;
h->metac = HTMLFONT_NONE;
h->metac = ESCAPE_FONTROMAN;
}
/*

View File

@ -1,4 +1,4 @@
/* $Id: man_term.c,v 1.228 2019/01/05 21:18:26 schwarze Exp $ */
/* $Id: man_term.c,v 1.232 2019/07/23 17:53:35 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
@ -27,10 +27,12 @@
#include <string.h>
#include "mandoc_aux.h"
#include "mandoc.h"
#include "roff.h"
#include "man.h"
#include "out.h"
#include "term.h"
#include "tag.h"
#include "main.h"
#define MAXMARGINS 64 /* maximum number of indented scopes */
@ -92,6 +94,8 @@ static void post_SY(DECL_ARGS);
static void post_TP(DECL_ARGS);
static void post_UR(DECL_ARGS);
static void tag_man(struct termp *, struct roff_node *);
static const struct man_term_act man_term_acts[MAN_MAX - MAN_TH] = {
{ NULL, NULL, 0 }, /* TH */
{ pre_SH, post_SH, 0 }, /* SH */
@ -146,7 +150,7 @@ terminal_man(void *arg, const struct roff_meta *man)
{
struct mtermp mt;
struct termp *p;
struct roff_node *n;
struct roff_node *n, *nc, *nn;
size_t save_defindent;
p = (struct termp *)arg;
@ -165,18 +169,23 @@ terminal_man(void *arg, const struct roff_meta *man)
n = man->first->child;
if (p->synopsisonly) {
while (n != NULL) {
if (n->tok == MAN_SH &&
n->child->child->type == ROFFT_TEXT &&
!strcmp(n->child->child->string, "SYNOPSIS")) {
if (n->child->next->child != NULL)
print_man_nodelist(p, &mt,
n->child->next->child, man);
term_newln(p);
for (nn = NULL; n != NULL; n = n->next) {
if (n->tok != MAN_SH)
continue;
nc = n->child->child;
if (nc->type != ROFFT_TEXT)
continue;
if (strcmp(nc->string, "SYNOPSIS") == 0)
break;
}
n = n->next;
if (nn == NULL && strcmp(nc->string, "NAME") == 0)
nn = n;
}
if (n == NULL)
n = nn;
p->flags |= TERMP_NOSPACE;
if (n != NULL && (n = n->child->next->child) != NULL)
print_man_nodelist(p, &mt, n, man);
term_newln(p);
} else {
term_begin(p, print_man_head, print_man_foot, man);
p->flags |= TERMP_NOSPACE;
@ -310,7 +319,7 @@ pre_alternate(DECL_ARGS)
assert(nn->type == ROFFT_TEXT);
term_word(p, nn->string);
if (nn->flags & NODE_EOS)
p->flags |= TERMP_SENTENCE;
p->flags |= TERMP_SENTENCE;
if (nn->next != NULL)
p->flags |= TERMP_NOSPACE;
}
@ -529,8 +538,10 @@ pre_IP(DECL_ARGS)
case ROFFT_HEAD:
p->tcol->offset = mt->offset;
p->tcol->rmargin = mt->offset + len;
if (n->child != NULL)
if (n->child != NULL) {
print_man_node(p, mt, n->child, meta);
tag_man(p, n->child);
}
return 0;
case ROFFT_BODY:
p->tcol->offset = mt->offset + len;
@ -610,6 +621,18 @@ pre_TP(DECL_ARGS)
while (nn != NULL && (nn->flags & NODE_LINE) == 0)
nn = nn->next;
if (nn == NULL)
return 0;
if (nn->type == ROFFT_TEXT)
tag_man(p, nn);
else if (nn->child != NULL &&
nn->child->type == ROFFT_TEXT &&
(nn->tok == MAN_B || nn->tok == MAN_BI ||
nn->tok == MAN_BR || nn->tok == MAN_I ||
nn->tok == MAN_IB || nn->tok == MAN_IR))
tag_man(p, nn->child);
while (nn != NULL) {
print_man_node(p, mt, nn, meta);
nn = nn->next;
@ -1143,3 +1166,60 @@ print_man_head(struct termp *p, const struct roff_meta *meta)
}
free(title);
}
/*
* Skip leading whitespace, dashes, backslashes, and font escapes,
* then create a tag if the first following byte is a letter.
* Priority is high unless whitespace is present.
*/
static void
tag_man(struct termp *p, struct roff_node *n)
{
const char *cp, *arg;
int prio, sz;
assert(n->type == ROFFT_TEXT);
cp = n->string;
prio = 1;
for (;;) {
switch (*cp) {
case ' ':
case '\t':
prio = INT_MAX;
/* FALLTHROUGH */
case '-':
cp++;
break;
case '\\':
cp++;
switch (mandoc_escape(&cp, &arg, &sz)) {
case ESCAPE_FONT:
case ESCAPE_FONTROMAN:
case ESCAPE_FONTITALIC:
case ESCAPE_FONTBOLD:
case ESCAPE_FONTPREV:
case ESCAPE_FONTBI:
break;
case ESCAPE_SPECIAL:
if (sz != 1)
return;
switch (*arg) {
case '&':
case '-':
case 'e':
break;
default:
return;
}
break;
default:
return;
}
break;
default:
if (isalpha((unsigned char)*cp))
tag_put(cp, prio, p->line);
return;
}
}
}

View File

@ -1,4 +1,4 @@
/* $Id: man_validate.c,v 1.146 2018/12/31 10:04:39 schwarze Exp $ */
/* $Id: man_validate.c,v 1.149 2019/06/27 15:07:30 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2018 Ingo Schwarze <schwarze@openbsd.org>
@ -41,7 +41,7 @@
typedef void (*v_check)(CHKARGS);
static void check_abort(CHKARGS);
static void check_abort(CHKARGS) __attribute__((__noreturn__));
static void check_par(CHKARGS);
static void check_part(CHKARGS);
static void check_root(CHKARGS);
@ -185,8 +185,7 @@ check_root(CHKARGS)
man->meta.title = mandoc_strdup("");
man->meta.msec = mandoc_strdup("");
man->meta.date = man->quick ? mandoc_strdup("") :
mandoc_normdate(man, NULL, n->line, n->pos);
man->meta.date = mandoc_normdate(man, NULL, n->line, n->pos);
}
if (man->meta.os_e &&
@ -369,8 +368,8 @@ post_TH(CHKARGS)
/* ->TITLE<- MSEC DATE OS VOL */
n = n->child;
if (n && n->string) {
for (p = n->string; '\0' != *p; p++) {
if (n != NULL && n->string != NULL) {
for (p = n->string; *p != '\0'; p++) {
/* Only warn about this once... */
if (isalpha((unsigned char)*p) &&
! isupper((unsigned char)*p)) {
@ -388,9 +387,9 @@ post_TH(CHKARGS)
/* TITLE ->MSEC<- DATE OS VOL */
if (n)
if (n != NULL)
n = n->next;
if (n && n->string)
if (n != NULL && n->string != NULL)
man->meta.msec = mandoc_strdup(n->string);
else {
man->meta.msec = mandoc_strdup("");
@ -400,17 +399,16 @@ post_TH(CHKARGS)
/* TITLE MSEC ->DATE<- OS VOL */
if (n)
if (n != NULL)
n = n->next;
if (n && n->string && '\0' != n->string[0]) {
man->meta.date = man->quick ?
mandoc_strdup(n->string) :
mandoc_normdate(man, n->string, n->line, n->pos);
} else {
if (n != NULL && n->string != NULL && n->string[0] != '\0')
man->meta.date = mandoc_normdate(man,
n->string, n->line, n->pos);
else {
man->meta.date = mandoc_strdup("");
mandoc_msg(MANDOCERR_DATE_MISSING,
n ? n->line : nb->line,
n ? n->pos : nb->pos, "TH");
n == NULL ? nb->line : n->line,
n == NULL ? nb->pos : n->pos, "TH");
}
/* TITLE MSEC DATE ->OS<- VOL */

View File

@ -1,7 +1,7 @@
.\" $Id: mandoc.1,v 1.237 2019/02/23 18:53:54 schwarze Exp $
.\" $Id: mandoc.1,v 1.240 2019/07/10 19:39:01 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2012, 2014-2018 Ingo Schwarze <schwarze@openbsd.org>
.\" Copyright (c) 2012, 2014-2019 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: February 23 2019 $
.Dd $Mdocdate: July 10 2019 $
.Dt MANDOC 1
.Os
.Sh NAME
@ -222,7 +222,8 @@ reads from standard input.
.Pp
The options
.Fl fhklw
are also supported and are documented in man(1).
are also supported and are documented in
.Xr man 1 .
In
.Fl f
and
@ -697,7 +698,7 @@ No input files have been read.
.It 6
An operating system error occurred, for example exhaustion
of memory, file descriptors, or process table entries.
Such errors cause
Such errors may cause
.Nm
to exit at once, possibly in the middle of parsing or formatting a file.
.El
@ -777,6 +778,13 @@ fields.
.Pp
Message levels have the following meanings:
.Bl -tag -width "warning"
.It Cm syserr
An operating system error occurred.
There isn't necessarily anything wrong with the input files.
Output may all the same be missing or incomplete.
.It Cm badarg
Invalid command line arguments were specified.
No input files have been read and no output is produced.
.It Cm unsupp
An input file uses unsupported low-level
.Xr roff 7
@ -825,8 +833,7 @@ Messages of the
.Cm error ,
and
.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
levels are hidden unless their level, or a lower level, is requested using a
.Fl W
option or
.Fl T Cm lint
@ -1699,9 +1706,12 @@ The meaning of blank input lines is only well-defined in non-fill mode:
In fill mode, line breaks of text input lines are not supposed to be
significant.
However, for compatibility with groff, blank lines in fill mode
are replaced with
are formatted like
.Ic \&sp
requests.
To request a paragraph break, use
.Ic \&Pp
instead of a blank line.
.It Sy "tab in filled text"
.Pq mdoc , man
The meaning of tab characters is only well-defined in non-fill mode:
@ -2238,6 +2248,43 @@ macro or of an undefined macro.
The macro is ignored, and its arguments are handled
as if they were a text line.
.El
.Ss Bad command line arguments
.Bl -ohang
.It Sy "bad command line argument"
The argument following one of the
.Fl IKMmOTW
command line options is invalid, or a
.Ar file
given as a command line argument cannot be opened.
.It Sy "duplicate command line argument"
The
.Fl I
command line option was specified twice.
.It Sy "option has a superfluous value"
An argument to the
.Fl O
option has a value but does not accept one.
.It Sy "missing option value"
An argument to the
.Fl O
option has no argument but requires one.
.It Sy "bad option value"
An argument to the
.Fl O
.Cm indent
or
.Cm width
option has an invalid value.
.It Sy "duplicate option value"
The same
.Fl O
option is specified more than once.
.It Sy "no such tag"
The
.Fl O Cm tag
option was specified but the tag was not found in any of the displayed
manual pages.
.El
.Sh SEE ALSO
.Xr apropos 1 ,
.Xr man 1 ,

View File

@ -1,4 +1,4 @@
/* $Id: mandoc.c,v 1.114 2018/12/30 00:49:55 schwarze Exp $ */
/* $Id: mandoc.c,v 1.116 2019/06/27 15:07:30 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
@ -494,9 +494,10 @@ time2a(time_t t)
size_t ssz;
int isz;
buf = NULL;
tm = localtime(&t);
if (tm == NULL)
return NULL;
goto fail;
/*
* Reserve space:
@ -520,7 +521,8 @@ time2a(time_t t)
* of looking at LC_TIME.
*/
if ((isz = snprintf(p, 4 + 1, "%d, ", tm->tm_mday)) == -1)
isz = snprintf(p, 4 + 1, "%d, ", tm->tm_mday);
if (isz < 0 || isz > 4)
goto fail;
p += isz;
@ -530,7 +532,7 @@ time2a(time_t t)
fail:
free(buf);
return NULL;
return mandoc_strdup("");
}
char *
@ -539,12 +541,15 @@ mandoc_normdate(struct roff_man *man, char *in, int ln, int pos)
char *cp;
time_t t;
if (man->quick)
return mandoc_strdup(in == NULL ? "" : in);
/* No date specified: use today's date. */
if (in == NULL || *in == '\0' || strcmp(in, "$" "Mdocdate$") == 0) {
if (in == NULL || *in == '\0')
mandoc_msg(MANDOCERR_DATE_MISSING, ln, pos, NULL);
if (in == NULL || *in == '\0' || strcmp(in, "$" "Mdocdate$") == 0)
return time2a(time(NULL));
}
/* Valid mdoc(7) date format. */

View File

@ -1,4 +1,4 @@
/* $Id: mandoc.css,v 1.45 2019/03/01 10:57:18 schwarze Exp $ */
/* $Id: mandoc.css,v 1.46 2019/06/02 16:57:13 schwarze Exp $ */
/*
* Standard style sheet for mandoc(1) -Thtml and man.cgi(8).
*
@ -10,8 +10,13 @@
/* Global defaults. */
html { max-width: 65em; }
body { font-family: Helvetica,Arial,sans-serif; }
html { max-width: 65em;
--bg: #FFFFFF;
--fg: #000000; }
body { background: var(--bg);
color: var(--fg);
font-family: Helvetica,Arial,sans-serif; }
h1 { font-size: 110%; }
table { margin-top: 0em;
margin-bottom: 0em;
border-collapse: collapse; }
@ -69,8 +74,7 @@ td.foot-os { text-align: right; }
section.Sh { }
h1.Sh { margin-top: 1.2em;
margin-bottom: 0.6em;
margin-left: -3.2em;
font-size: 110%; }
margin-left: -3.2em; }
section.Ss { }
h2.Ss { margin-top: 1.2em;
margin-bottom: 0.6em;
@ -310,14 +314,14 @@ h1.Sh::before, h2.Ss::before, .St::before, .Sx::before, .Sy::before,
pointer-events: none;
position: absolute;
bottom: 100%;
box-shadow: 0 0 .35em #000;
box-shadow: 0 0 .35em var(--fg);
padding: .15em .25em;
white-space: nowrap;
font-family: Helvetica,Arial,sans-serif;
font-style: normal;
font-weight: bold;
color: black;
background: #fff; }
background: var(--bg);
color: var(--fg); }
.An:hover::before, .Ar:hover::before, .Cd:hover::before, .Cm:hover::before,
.Dv:hover::before, .Em:hover::before, .Er:hover::before, .Ev:hover::before,
.Fa:hover::before, .Fd:hover::before, .Fl:hover::before, .Fn:hover::before,
@ -345,3 +349,12 @@ h1.Sh, h2.Ss { margin-left: 0em; }
.HP { margin-left: 2em;
text-indent: -2em; }
}
/* Overrides for a dark color scheme for accessibility. */
@media (prefers-color-scheme: dark) {
html { --bg: #1E1F21;
--fg: #EEEFF1; }
:link { color: #BAD7FF; }
:visited { color: #F6BAFF; }
}

View File

@ -1,7 +1,7 @@
/* $Id: mandoc.h,v 1.262 2018/12/16 00:17:02 schwarze Exp $ */
/* $Id: mandoc.h,v 1.264 2019/07/14 18:16:13 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2012-2018 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2012-2019 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
@ -193,7 +193,6 @@ enum mandocerr {
MANDOCERR_TBLDATA_BLK, /* data block open at end of tbl: macro */
/* related to document structure and macros */
MANDOCERR_FILE, /* cannot open file */
MANDOCERR_PROLOG_REP, /* duplicate prologue macro: macro */
MANDOCERR_DT_LATE, /* skipping late title macro: Dt args */
MANDOCERR_ROFFLOOP, /* input stack limit exceeded, infinite loop? */
@ -242,6 +241,35 @@ enum mandocerr {
MANDOCERR_TBLLAYOUT_MOD, /* unsupported tbl layout modifier: m */
MANDOCERR_TBLMACRO, /* ignoring macro in table: macro */
MANDOCERR_BADARG, /* ===== start of bad invocations ===== */
MANDOCERR_BADARG_BAD, /* bad argument */
MANDOCERR_BADARG_DUPE, /* duplicate argument */
MANDOCERR_BADVAL, /* does not take a value */
MANDOCERR_BADVAL_MISS, /* missing argument value */
MANDOCERR_BADVAL_BAD, /* bad argument value */
MANDOCERR_BADVAL_DUPE, /* duplicate argument value */
MANDOCERR_TAG, /* no such tag */
MANDOCERR_SYSERR, /* ===== start of system errors ===== */
MANDOCERR_DUP,
MANDOCERR_EXEC,
MANDOCERR_FDOPEN,
MANDOCERR_FFLUSH,
MANDOCERR_FORK,
MANDOCERR_FSTAT,
MANDOCERR_GETLINE,
MANDOCERR_GLOB,
MANDOCERR_GZCLOSE,
MANDOCERR_GZDOPEN,
MANDOCERR_MKSTEMP,
MANDOCERR_OPEN,
MANDOCERR_PLEDGE,
MANDOCERR_READ,
MANDOCERR_WAIT,
MANDOCERR_WRITE,
MANDOCERR_MAX
};
@ -281,6 +309,7 @@ enum mandoclevel mandoc_msg_getrc(void);
void mandoc_msg_setrc(enum mandoclevel);
void mandoc_msg(enum mandocerr, int, int, const char *, ...)
__attribute__((__format__ (__printf__, 4, 5)));
void mandoc_msg_summary(void);
void mchars_alloc(void);
void mchars_free(void);
int mchars_num2char(const char *, size_t);

View File

@ -1,4 +1,4 @@
.\" $Id: mandoc_char.7,v 1.75 2018/12/15 19:30:26 schwarze Exp $
.\" $Id: mandoc_char.7,v 1.76 2019/03/31 19:17:26 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 15 2018 $
.Dd $Mdocdate: March 31 2019 $
.Dt MANDOC_CHAR 7
.Os
.Sh NAME
@ -107,8 +107,8 @@ supporting it, for example in
.Fl T Cm utf8
and
.Fl T Cm html .
But currently, no practically relevant manual page formatter actually
requires that subtlety, so in manual pages just write plain
But currently, no practically relevant manual page formatter requires
that subtlety, so in manual pages, it is sufficient to write plain
.Sq -
to represent hyphen, minus, and hyphen-minus.
.Pp

View File

@ -1,4 +1,20 @@
.Dd $Mdocdate: December 30 2018 $
.\" $Id: mandoc_headers.3,v 1.31 2019/03/17 18:21:45 schwarze Exp $
.\"
.\" Copyright (c) 2014-2019 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.
.\"
.Dd $Mdocdate: March 17 2019 $
.Dt MANDOC_HEADERS 3
.Os
.Sh NAME
@ -129,19 +145,19 @@ and the function
Uses pointers to the types
.Vt struct ohash
from
.Pa mandoc_ohash.h ,
.Qq Pa mandoc_ohash.h ,
.Vt struct mdoc_arg
and
.Vt union mdoc_data
from
.Pa mdoc.h ,
.Qq Pa mdoc.h ,
.Vt struct tbl_span
from
.Pa tbl.h ,
.Qq Pa tbl.h ,
and
.Vt struct eqn_box
from
.Pa eqn.h
.Qq Pa eqn.h
as opaque struct members.
.It Qq Pa tbl.h
Data structures for the
@ -184,13 +200,13 @@ Top level parser interface, for use in the main program
and in the main parser, but not in formatters.
.Pp
Requires
.Pa mandoc.h
.Qq Pa mandoc.h
for
.Vt enum mandocerr
and
.Vt enum mandoclevel
and
.Pa roff.h
.Qq Pa roff.h
for
.Vt enum mandoc_os .
.Pp
@ -202,7 +218,7 @@ for function prototypes.
Uses
.Vt struct roff_meta
from
.Pa roff.h
.Qq Pa roff.h
as an opaque type for function prototypes.
.It Qq Pa mandoc_xr.h
Cross reference validation; intended for use in the main program
@ -251,11 +267,11 @@ described in
Uses the types
.Vt struct roff_node
from
.Pa roff.h
.Qq Pa roff.h
and
.Vt struct roff_man
from
.Pa roff_int.h
.Qq Pa roff_int.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
@ -269,7 +285,7 @@ described in
Uses the type
.Vt struct roff_man
from
.Pa roff.h
.Qq Pa roff.h
as an opaque type for function prototypes.
.Pp
When this header is included, the same file should not include
@ -305,7 +321,7 @@ for function prototypes.
Uses the type
.Vt struct roff_man
from
.Pa roff.h
.Qq Pa roff.h
as an opaque type for function prototypes.
.It Qq Pa roff_int.h
Parser internals shared by multiple parsers.
@ -334,24 +350,24 @@ and the two special functions
and
.Fn mdoc_argv_free
because the latter two are needed by
.Qq Pa roff.c .
.Pa roff.c .
.Pp
Uses the types
.Vt struct ohash
from
.Pa mandoc_ohash.h ,
.Qq Pa mandoc_ohash.h ,
.Vt struct roff_node
and
.Vt struct roff_meta
from
.Pa roff.h ,
.Qq Pa roff.h ,
.Vt struct roff
from
.Pa roff.c ,
and
.Vt struct mdoc_arg
from
.Pa mdoc.h
.Qq Pa mdoc.h
as opaque types for function prototypes.
.It Qq Pa libmdoc.h
Requires
@ -372,14 +388,14 @@ parser.
Uses the types
.Vt struct roff_node
from
.Pa roff.h ,
.Qq Pa roff.h ,
.Vt struct roff_man
from
.Pa roff_int.h ,
.Qq Pa roff_int.h ,
and
.Vt struct mdoc_arg
from
.Pa mdoc.h
.Qq Pa mdoc.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
@ -399,11 +415,11 @@ parser.
Uses the types
.Vt struct roff_node
from
.Pa roff.h
.Qq Pa roff.h
and
.Vt struct roff_man
from
.Pa roff_int.h
.Qq Pa roff_int.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
@ -437,12 +453,12 @@ and
Uses the type
.Vt struct eqn_box
from
.Pa mandoc.h
.Qq Pa mandoc.h
as an opaque type for function prototypes.
Uses the types
.Vt struct roff_node
from
.Pa roff.h
.Qq Pa roff.h
and
.Vt struct eqn_def
from
@ -466,11 +482,11 @@ Provides the functions documented in
Uses the types
.Vt struct tbl_span
from
.Pa tbl.h
.Qq Pa tbl.h
and
.Vt struct tbl_node
from
.Pa tbl_int.h
.Qq Pa tbl_int.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
@ -523,11 +539,11 @@ and
Uses
.Vt struct tbl_span
from
.Pa mandoc.h
.Qq Pa mandoc.h
as an opaque type for function prototypes.
.Pp
When this header is included, the same file should not include
.Pa mansearch.h .
.Qq Pa mansearch.h .
.It Qq Pa term.h
Requires
.In sys/types.h
@ -558,27 +574,30 @@ Uses
and
.Vt struct eqn_box
from
.Pa mandoc.h
.Qq Pa mandoc.h
and
.Vt struct roff_meta
and
.Vt struct roff_node
from
.Pa roff.h
.Qq Pa roff.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
.Pa html.h
.Qq Pa html.h
or
.Pa mansearch.h .
.Qq Pa mansearch.h .
.It Qq Pa html.h
Requires
.In sys/types.h
for
.Vt size_t ,
.Pa mandoc.h
.Qq Pa mandoc.h
for
.Vt enum mandoc_esc ,
.Qq Pa roff.h
for
.Vt enum roff_tok ,
and
.Qq Pa out.h
for
@ -602,17 +621,17 @@ Uses
and
.Vt struct eqn_box
from
.Pa mandoc.h
.Qq Pa mandoc.h
and
.Vt struct roff_node
from
.Pa roff.h
.Qq Pa roff.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
.Pa term.h
.Qq Pa term.h
or
.Pa mansearch.h .
.Qq Pa mansearch.h .
.It Qq Pa tag.h
Requires
.In sys/types.h
@ -631,7 +650,7 @@ Provides the top level steering functions for all formatters.
Uses the type
.Vt struct roff_meta
from
.Pa roff.h
.Qq Pa roff.h
as an opaque type for function prototypes.
.It Qq Pa manconf.h
Requires
@ -671,12 +690,12 @@ and
Uses
.Vt struct manpaths
from
.Pa manconf.h
.Qq Pa manconf.h
as an opaque type for function prototypes.
.Pp
When this header is included, the same file should not include
.Pa out.h ,
.Pa term.h ,
.Qq Pa out.h ,
.Qq Pa term.h ,
or
.Pa html.h .
.Qq Pa html.h .
.El

View File

@ -1,7 +1,7 @@
/* $Id: mandoc_msg.c,v 1.6 2019/03/06 15:55:38 schwarze Exp $ */
/* $Id: mandoc_msg.c,v 1.8 2019/07/14 18:16:13 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014,2015,2016,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2014-2019 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,8 @@ static const enum mandocerr lowest_type[MANDOCLEVEL_MAX] = {
MANDOCERR_WARNING,
MANDOCERR_ERROR,
MANDOCERR_UNSUPP,
MANDOCERR_MAX,
MANDOCERR_MAX
MANDOCERR_BADARG,
MANDOCERR_SYSERR
};
static const char *const level_name[MANDOCLEVEL_MAX] = {
@ -193,7 +193,6 @@ static const char *const type_message[MANDOCERR_MAX] = {
"data block open at end of tbl",
/* related to document structure and macros */
NULL,
"duplicate prologue macro",
"skipping late title macro",
"input stack limit exceeded, infinite loop?",
@ -240,11 +239,40 @@ static const char *const type_message[MANDOCERR_MAX] = {
"eqn delim option in tbl",
"unsupported tbl layout modifier",
"ignoring macro in table",
/* bad command line arguments */
NULL,
"bad command line argument",
"duplicate command line argument",
"option has a superfluous value",
"missing option value",
"bad option value",
"duplicate option value",
"no such tag",
/* system errors */
NULL,
"dup",
"exec",
"fdopen",
"fflush",
"fork",
"fstat",
"getline",
"glob",
"gzclose",
"gzdopen",
"mkstemp",
"open",
"pledge",
"read",
"wait",
"write",
};
static FILE *fileptr = NULL;
static const char *filename = NULL;
static enum mandocerr min_type = MANDOCERR_MAX;
static enum mandocerr min_type = MANDOCERR_BADARG;
static enum mandoclevel rc = MANDOCLEVEL_OK;
@ -297,10 +325,10 @@ mandoc_msg(enum mandocerr t, int line, int col, const char *fmt, ...)
va_list ap;
enum mandoclevel level;
if (t < min_type && t != MANDOCERR_FILE)
if (t < min_type)
return;
level = MANDOCLEVEL_UNSUPP;
level = MANDOCLEVEL_SYSERR;
while (t < lowest_type[level])
level--;
mandoc_msg_setrc(level);
@ -327,3 +355,12 @@ mandoc_msg(enum mandocerr t, int line, int col, const char *fmt, ...)
}
fputc('\n', fileptr);
}
void
mandoc_msg_summary(void)
{
if (fileptr != NULL && rc != MANDOCLEVEL_OK)
fprintf(fileptr,
"%s: see above the output for %s messages\n",
getprogname(), level_name[rc]);
}

View File

@ -1,7 +1,7 @@
/* $Id: mandocdb.c,v 1.262 2018/12/30 00:49:55 schwarze Exp $ */
/* $Id: mandocdb.c,v 1.263 2019/05/03 18:17:12 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2018 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011-2019 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2016 Ed Maste <emaste@freebsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@ -1186,9 +1186,11 @@ mpages_merge(struct dba *dba, struct mparse *mp)
mlink->next = mlink_dest->next;
mlink_dest->next = mpage->mlinks;
mpage->mlinks = NULL;
goto nextpage;
}
goto nextpage;
} else if (meta != NULL && meta->macroset == MACROSET_MDOC) {
meta->macroset = MACROSET_NONE;
}
if (meta != NULL && meta->macroset == MACROSET_MDOC) {
mpage->form = FORM_SRC;
mpage->sec = meta->msec;
mpage->sec = mandoc_strdup(
@ -1208,12 +1210,15 @@ mpages_merge(struct dba *dba, struct mparse *mp)
}
assert(mpage->desc == NULL);
if (meta == NULL) {
mpage->form = FORM_CAT;
if (meta == NULL || meta->sodest != NULL) {
mpage->sec = mandoc_strdup(mlink->dsec);
mpage->arch = mandoc_strdup(mlink->arch);
mpage->title = mandoc_strdup(mlink->name);
parse_cat(mpage, fd);
if (meta == NULL) {
mpage->form = FORM_CAT;
parse_cat(mpage, fd);
} else
mpage->form = FORM_SRC;
} else if (meta->macroset == MACROSET_MDOC)
parse_mdoc(mpage, meta, meta->first);
else

View File

@ -1,6 +1,6 @@
/* $Id: manpath.c,v 1.37 2018/11/22 11:30:23 schwarze Exp $ */
/* $Id: manpath.c,v 1.40 2019/07/10 19:39:01 schwarze Exp $ */
/*
* Copyright (c) 2011,2014,2015,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011,2014,2015,2017-2019 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
@ -21,20 +21,19 @@
#include <sys/stat.h>
#include <ctype.h>
#if HAVE_ERR
#include <err.h>
#endif
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mandoc_aux.h"
#include "mandoc.h"
#include "manconf.h"
static void manconf_file(struct manconf *, const char *);
static void manpath_add(struct manpaths *, const char *, int);
static void manpath_parseline(struct manpaths *, char *, int);
static void manpath_add(struct manpaths *, const char *, char);
static void manpath_parseline(struct manpaths *, char *, char);
void
@ -44,11 +43,11 @@ manconf_parse(struct manconf *conf, const char *file,
char *insert;
/* Always prepend -m. */
manpath_parseline(&conf->manpath, auxp, 1);
manpath_parseline(&conf->manpath, auxp, 'm');
/* If -M is given, it overrides everything else. */
if (NULL != defp) {
manpath_parseline(&conf->manpath, defp, 1);
manpath_parseline(&conf->manpath, defp, 'M');
return;
}
@ -66,13 +65,13 @@ manconf_parse(struct manconf *conf, const char *file,
/* Prepend man.conf(5) to MANPATH. */
if (':' == defp[0]) {
manconf_file(conf, file);
manpath_parseline(&conf->manpath, defp, 0);
manpath_parseline(&conf->manpath, defp, '\0');
return;
}
/* Append man.conf(5) to MANPATH. */
if (':' == defp[strlen(defp) - 1]) {
manpath_parseline(&conf->manpath, defp, 0);
manpath_parseline(&conf->manpath, defp, '\0');
manconf_file(conf, file);
return;
}
@ -81,28 +80,28 @@ manconf_parse(struct manconf *conf, const char *file,
insert = strstr(defp, "::");
if (NULL != insert) {
*insert++ = '\0';
manpath_parseline(&conf->manpath, defp, 0);
manpath_parseline(&conf->manpath, defp, '\0');
manconf_file(conf, file);
manpath_parseline(&conf->manpath, insert + 1, 0);
manpath_parseline(&conf->manpath, insert + 1, '\0');
return;
}
/* MANPATH overrides man.conf(5) completely. */
manpath_parseline(&conf->manpath, defp, 0);
manpath_parseline(&conf->manpath, defp, '\0');
}
void
manpath_base(struct manpaths *dirs)
{
char path_base[] = MANPATH_BASE;
manpath_parseline(dirs, path_base, 0);
manpath_parseline(dirs, path_base, '\0');
}
/*
* Parse a FULL pathname from a colon-separated list of arrays.
*/
static void
manpath_parseline(struct manpaths *dirs, char *path, int complain)
manpath_parseline(struct manpaths *dirs, char *path, char option)
{
char *dir;
@ -110,7 +109,7 @@ manpath_parseline(struct manpaths *dirs, char *path, int complain)
return;
for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":"))
manpath_add(dirs, dir, complain);
manpath_add(dirs, dir, option);
}
/*
@ -118,33 +117,32 @@ manpath_parseline(struct manpaths *dirs, char *path, int complain)
* Grow the array one-by-one for simplicity's sake.
*/
static void
manpath_add(struct manpaths *dirs, const char *dir, int complain)
manpath_add(struct manpaths *dirs, const char *dir, char option)
{
char buf[PATH_MAX];
struct stat sb;
char *cp;
size_t i;
if (NULL == (cp = realpath(dir, buf))) {
if (complain)
warn("manpath: %s", dir);
return;
}
if ((cp = realpath(dir, buf)) == NULL)
goto fail;
for (i = 0; i < dirs->sz; i++)
if (0 == strcmp(dirs->paths[i], dir))
if (strcmp(dirs->paths[i], dir) == 0)
return;
if (stat(cp, &sb) == -1) {
if (complain)
warn("manpath: %s", dir);
return;
}
if (stat(cp, &sb) == -1)
goto fail;
dirs->paths = mandoc_reallocarray(dirs->paths,
dirs->sz + 1, sizeof(char *));
dirs->sz + 1, sizeof(*dirs->paths));
dirs->paths[dirs->sz++] = mandoc_strdup(cp);
return;
fail:
if (option != '\0')
mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0,
"-%c %s: %s", option, dir, strerror(errno));
}
void
@ -210,7 +208,7 @@ manconf_file(struct manconf *conf, const char *file)
*ep = '\0';
/* FALLTHROUGH */
case 0: /* manpath */
manpath_add(&conf->manpath, cp, 0);
manpath_add(&conf->manpath, cp, '\0');
*manpath_default = '\0';
break;
case 1: /* output */
@ -225,7 +223,7 @@ manconf_file(struct manconf *conf, const char *file)
out:
if (*manpath_default != '\0')
manpath_parseline(&conf->manpath, manpath_default, 0);
manpath_parseline(&conf->manpath, manpath_default, '\0');
}
int
@ -235,14 +233,15 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile)
"includes", "man", "paper", "style", "indent", "width",
"tag", "fragment", "mdoc", "noval", "toc"
};
const size_t ntoks = sizeof(toks) / sizeof(toks[0]);
const char *errstr;
char *oldval;
size_t len, tok;
for (tok = 0; tok < sizeof(toks)/sizeof(toks[0]); tok++) {
for (tok = 0; tok < ntoks; tok++) {
len = strlen(toks[tok]);
if ( ! strncmp(cp, toks[tok], len) &&
if (strncmp(cp, toks[tok], len) == 0 &&
strchr(" = ", cp[len]) != NULL) {
cp += len;
if (*cp == '=')
@ -254,11 +253,11 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile)
}
if (tok < 6 && *cp == '\0') {
warnx("-O %s=?: Missing argument value", toks[tok]);
mandoc_msg(MANDOCERR_BADVAL_MISS, 0, 0, "-O %s=?", toks[tok]);
return -1;
}
if (tok > 6 && *cp != '\0') {
warnx("-O %s: Does not take a value: %s", toks[tok], cp);
if (tok > 6 && tok < ntoks && *cp != '\0') {
mandoc_msg(MANDOCERR_BADVAL, 0, 0, "-O %s=%s", toks[tok], cp);
return -1;
}
@ -299,7 +298,8 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile)
conf->indent = strtonum(cp, 0, 1000, &errstr);
if (errstr == NULL)
return 0;
warnx("-O indent=%s is %s", cp, errstr);
mandoc_msg(MANDOCERR_BADVAL_BAD, 0, 0,
"-O indent=%s is %s", cp, errstr);
return -1;
case 5:
if (conf->width) {
@ -309,7 +309,8 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile)
conf->width = strtonum(cp, 1, 1000, &errstr);
if (errstr == NULL)
return 0;
warnx("-O width=%s is %s", cp, errstr);
mandoc_msg(MANDOCERR_BADVAL_BAD, 0, 0,
"-O width=%s is %s", cp, errstr);
return -1;
case 6:
if (conf->tag != NULL) {
@ -331,13 +332,16 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile)
conf->toc = 1;
return 0;
default:
if (fromfile)
warnx("-O %s: Bad argument", cp);
mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0, "-O %s", cp);
return -1;
}
if (fromfile) {
free(oldval);
return 0;
} else {
mandoc_msg(MANDOCERR_BADVAL_DUPE, 0, 0,
"-O %s=%s: already set to %s", toks[tok], cp, oldval);
free(oldval);
return -1;
}
if (fromfile == 0)
warnx("-O %s=%s: Option already set to %s",
toks[tok], cp, oldval);
free(oldval);
return -1;
}

View File

@ -1,4 +1,4 @@
/* $Id: mansearch.c,v 1.80 2018/12/13 11:55:46 schwarze Exp $ */
/* $Id: mansearch.c,v 1.82 2019/07/01 22:56:24 schwarze Exp $ */
/*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013-2018 Ingo Schwarze <schwarze@openbsd.org>
@ -191,7 +191,7 @@ mansearch(const struct mansearch *search,
mpage->file, R_OK) == -1) {
warn("%s", mpage->file);
warnx("outdated mandoc.db contains "
"bogus %s entry, run makewhatis %s",
"bogus %s entry, run makewhatis %s",
page->file + 1, paths->paths[i]);
free(mpage->file);
free(rp);
@ -199,6 +199,7 @@ mansearch(const struct mansearch *search,
}
mpage->names = buildnames(page);
mpage->output = buildoutput(outkey, page);
mpage->bits = search->firstmatch ? rp->bits : 0;
mpage->ipath = i;
mpage->sec = *page->sect - '0';
if (mpage->sec < 0 || mpage->sec > 9)
@ -294,8 +295,10 @@ manmerge_term(struct expr *e, struct ohash *htab)
break;
slot = ohash_lookup_memory(htab,
(char *)&res, sizeof(res.page), res.page);
if ((rp = ohash_find(htab, slot)) != NULL)
if ((rp = ohash_find(htab, slot)) != NULL) {
rp->bits |= res.bits;
continue;
}
rp = mandoc_malloc(sizeof(*rp));
*rp = res;
ohash_insert(htab, slot, rp);
@ -408,7 +411,8 @@ manpage_compare(const void *vp1, const void *vp2)
mp1 = vp1;
mp2 = vp2;
if ((diff = mp1->sec - mp2->sec))
if ((diff = mp2->bits - mp1->bits) ||
(diff = mp1->sec - mp2->sec))
return diff;
/* Fall back to alphabetic ordering of names. */

View File

@ -1,4 +1,4 @@
/* $Id: mansearch.h,v 1.29 2018/11/22 12:01:46 schwarze Exp $ */
/* $Id: mansearch.h,v 1.30 2019/04/30 18:51:57 schwarze Exp $ */
/*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2016, 2017 Ingo Schwarze <schwarze@openbsd.org>
@ -92,6 +92,7 @@ struct manpage {
char *file; /* to be prefixed by manpath */
char *names; /* a list of names with sections */
char *output; /* user-defined additional output */
uint64_t bits; /* name type mask */
size_t ipath; /* number of the manpath */
int sec; /* section number, 10 means invalid */
enum form form;

38
mdoc.7
View File

@ -1,4 +1,4 @@
.\" $Id: mdoc.7,v 1.276 2019/02/07 15:45:53 schwarze Exp $
.\" $Id: mdoc.7,v 1.279 2019/07/15 19:20:30 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010, 2011, 2013-2018 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: February 7 2019 $
.Dd $Mdocdate: July 15 2019 $
.Dt MDOC 7
.Os
.Sh NAME
@ -596,6 +596,13 @@ block.
Book or journal page number of an
.Ic \&Rs
block.
Conventionally, the argument starts with
.Ql p.\&
for a single page or
.Ql pp.\&
for a range of pages, for example:
.Pp
.Dl .%P pp. 42\e(en47
.It Ic \&%Q Ar name
Institutional author (school, government, etc.) of an
.Ic \&Rs
@ -1156,17 +1163,19 @@ declarations.
This practise is discouraged.
.It Ic \&Cm Ar keyword ...
Command modifiers.
Typically used for fixed strings passed as arguments, unless
Typically used for fixed strings passed as arguments to interactive
commands, to commands in interpreted scripts, or to configuration
file directives, unless
.Ic \&Fl
is more appropriate.
Also useful when specifying configuration options or keys.
.Pp
Examples:
.Dl ".Nm mt Fl f Ar device Cm rewind"
.Dl ".Nm ps Fl o Cm pid , Ns Cm command"
.Dl ".Nm dd Cm if= Ns Ar file1 Cm of= Ns Ar file2"
.Dl ".Cm IdentityFile Pa ~/.ssh/id_rsa"
.Dl ".Cm LogLevel Dv DEBUG"
.Dl ".Ic set Fl o Cm vi"
.Dl ".Ic lookup Cm file bind"
.Dl ".Ic permit Ar identity Op Cm as Ar target"
.It Ic \&D1 Ar line
One-line indented display.
This is formatted by the default rules and is useful for simple indented
@ -1677,10 +1686,10 @@ This macro is not implemented in
.Xr mandoc 1 .
It was used to include the contents of a (header) file literally.
.It Ic \&Ic Ar keyword ...
Designate an internal or interactive command.
This is similar to
.Ic \&Cm
but used for instructions rather than values.
Internal or interactive command, or configuration instruction
in a configuration file.
See also
.Ic \&Cm .
.Pp
Examples:
.Dl \&.Ic :wq
@ -2969,7 +2978,7 @@ exclamation mark
Note that even a period preceded by a backslash
.Pq Sq \e.\&
gets this special handling; use
.Sq \e&.
.Sq \e&.\&
to prevent that.
.Pp
Many in-line macros interrupt their scope when they encounter
@ -2996,6 +3005,13 @@ in the same way as a plain
.Sq \&|
character.
Using this predefined string is not recommended in new manuals.
.Pp
Appending a zero-width space
.Pq Sq \e&
to the end of an input line is also useful to prevent the interpretation
of a trailing period, exclamation or question mark as the end of a
sentence, for example when an abbreviation happens to occur
at the end of a text or macro input line.
.Ss Font handling
In
.Nm

View File

@ -1,7 +1,7 @@
/* $Id: mdoc_argv.c,v 1.119 2018/12/21 17:15:19 schwarze Exp $ */
/* $Id: mdoc_argv.c,v 1.120 2019/07/11 17:06:17 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2012, 2014-2018 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2012, 2014-2019 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
@ -454,6 +454,7 @@ args(struct roff_man *mdoc, int line, int *pos,
mandoc_msg(MANDOCERR_ARG_QUOTE, line, *pos, NULL);
mdoc->flags &= ~MDOC_PHRASELIT;
}
mdoc->flags &= ~MDOC_PHRASEQL;
return ARGS_EOLN;
}

View File

@ -1,4 +1,4 @@
/* $Id: mdoc_markdown.c,v 1.30 2018/12/30 00:49:55 schwarze Exp $ */
/* $Id: mdoc_markdown.c,v 1.31 2019/07/01 22:56:24 schwarze Exp $ */
/*
* Copyright (c) 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
*
@ -1290,7 +1290,7 @@ md_post_It(struct roff_node *n)
while ((n = n->prev) != NULL && n->type != ROFFT_HEAD)
i++;
/*
/*
* If a width was specified for this column,
* subtract what printed, and
* add the same spacing as in mdoc_term.c.

View File

@ -1,4 +1,4 @@
/* $Id: mdoc_term.c,v 1.372 2019/01/04 03:39:01 schwarze Exp $ */
/* $Id: mdoc_term.c,v 1.374 2019/06/27 12:20:18 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2019 Ingo Schwarze <schwarze@openbsd.org>
@ -253,7 +253,7 @@ static int fn_prio;
void
terminal_mdoc(void *arg, const struct roff_meta *mdoc)
{
struct roff_node *n;
struct roff_node *n, *nn;
struct termp *p;
size_t save_defindent;
@ -265,16 +265,20 @@ terminal_mdoc(void *arg, const struct roff_meta *mdoc)
n = mdoc->first->child;
if (p->synopsisonly) {
while (n != NULL) {
if (n->tok == MDOC_Sh && n->sec == SEC_SYNOPSIS) {
if (n->child->next->child != NULL)
print_mdoc_nodelist(p, NULL,
mdoc, n->child->next->child);
term_newln(p);
for (nn = NULL; n != NULL; n = n->next) {
if (n->tok != MDOC_Sh)
continue;
if (n->sec == SEC_SYNOPSIS)
break;
}
n = n->next;
if (nn == NULL && n->sec == SEC_NAME)
nn = n;
}
if (n == NULL)
n = nn;
p->flags |= TERMP_NOSPACE;
if (n != NULL && (n = n->child->next->child) != NULL)
print_mdoc_nodelist(p, NULL, mdoc, n);
term_newln(p);
} else {
save_defindent = p->defindent;
if (p->defindent == 0)
@ -352,6 +356,7 @@ print_mdoc_node(DECL_ARGS)
* produce output. Note that some pre-handlers do so.
*/
act = NULL;
switch (n->type) {
case ROFFT_TEXT:
if (n->flags & NODE_LINE) {

View File

@ -1,4 +1,4 @@
/* $Id: mdoc_validate.c,v 1.371 2019/03/04 13:01:57 schwarze Exp $ */
/* $Id: mdoc_validate.c,v 1.374 2019/06/27 15:07:30 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2019 Ingo Schwarze <schwarze@openbsd.org>
@ -64,7 +64,7 @@ static size_t macro2len(enum roff_tok);
static void rewrite_macro2len(struct roff_man *, char **);
static int similar(const char *, const char *);
static void post_abort(POST_ARGS);
static void post_abort(POST_ARGS) __attribute__((__noreturn__));
static void post_an(POST_ARGS);
static void post_an_norm(POST_ARGS);
static void post_at(POST_ARGS);
@ -1903,8 +1903,7 @@ post_root(POST_ARGS)
/* Add missing prologue data. */
if (mdoc->meta.date == NULL)
mdoc->meta.date = mdoc->quick ? mandoc_strdup("") :
mandoc_normdate(mdoc, NULL, 0, 0);
mdoc->meta.date = mandoc_normdate(mdoc, NULL, 0, 0);
if (mdoc->meta.title == NULL) {
mandoc_msg(MANDOCERR_DT_NOTITLE, 0, 0, "EOF");
@ -2519,21 +2518,10 @@ post_dd(POST_ARGS)
mandoc_msg(MANDOCERR_PROLOG_ORDER,
n->line, n->pos, "Dd after Os");
if (n->child == NULL || n->child->string[0] == '\0') {
mdoc->meta.date = mdoc->quick ? mandoc_strdup("") :
mandoc_normdate(mdoc, NULL, n->line, n->pos);
return;
}
datestr = NULL;
deroff(&datestr, n);
if (mdoc->quick)
mdoc->meta.date = datestr;
else {
mdoc->meta.date = mandoc_normdate(mdoc,
datestr, n->line, n->pos);
free(datestr);
}
mdoc->meta.date = mandoc_normdate(mdoc, datestr, n->line, n->pos);
free(datestr);
}
static void

4
out.c
View File

@ -1,4 +1,4 @@
/* $Id: out.c,v 1.77 2018/12/13 11:55:47 schwarze Exp $ */
/* $Id: out.c,v 1.78 2019/03/29 21:27:06 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011,2014,2015,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
@ -149,7 +149,7 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp_first,
gp = &first_group;
for (dp = sp->first; dp != NULL; dp = dp->next) {
icol = dp->layout->col;
while (icol > maxcol)
while (maxcol < icol + dp->hspans)
tbl->cols[++maxcol].spacing = SIZE_MAX;
col = tbl->cols + icol;
col->flags |= dp->layout->flags;

39
read.c
View File

@ -1,4 +1,4 @@
/* $Id: read.c,v 1.211 2019/01/11 17:04:44 schwarze Exp $ */
/* $Id: read.c,v 1.214 2019/07/10 19:39:01 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2019 Ingo Schwarze <schwarze@openbsd.org>
@ -157,7 +157,7 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
ln.sz = 256;
ln.buf = mandoc_malloc(ln.sz);
ln.next = NULL;
firstln = loop = NULL;
firstln = lastln = loop = NULL;
lnn = curp->line;
pos = 0;
inloop = 0;
@ -255,6 +255,8 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
/* XXX Ugly hack to mark the end of the input. */
if (i == blk.sz || blk.buf[i] == '\0') {
if (pos + 2 > ln.sz)
resize_buf(&ln, 256);
ln.buf[pos++] = '\n';
ln.buf[pos] = '\0';
}
@ -429,9 +431,8 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap)
int gzerrnum, retval;
if (fstat(fd, &st) == -1) {
mandoc_msg(MANDOCERR_FILE, 0, 0,
"fstat: %s", strerror(errno));
return 0;
mandoc_msg(MANDOCERR_FSTAT, 0, 0, "%s", strerror(errno));
return -1;
}
/*
@ -444,13 +445,13 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap)
if (curp->gzip == 0 && S_ISREG(st.st_mode)) {
if (st.st_size > 0x7fffffff) {
mandoc_msg(MANDOCERR_TOOLARGE, 0, 0, NULL);
return 0;
return -1;
}
*with_mmap = 1;
fb->sz = (size_t)st.st_size;
fb->buf = mmap(NULL, fb->sz, PROT_READ, MAP_SHARED, fd, 0);
if (fb->buf != MAP_FAILED)
return 1;
return 0;
}
if (curp->gzip) {
@ -462,15 +463,15 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap)
* which this function must not do.
*/
if ((fd = dup(fd)) == -1) {
mandoc_msg(MANDOCERR_FILE, 0, 0,
"dup: %s", strerror(errno));
return 0;
mandoc_msg(MANDOCERR_DUP, 0, 0,
"%s", strerror(errno));
return -1;
}
if ((gz = gzdopen(fd, "rb")) == NULL) {
mandoc_msg(MANDOCERR_FILE, 0, 0,
"gzdopen: %s", strerror(errno));
mandoc_msg(MANDOCERR_GZDOPEN, 0, 0,
"%s", strerror(errno));
close(fd);
return 0;
return -1;
}
} else
gz = NULL;
@ -482,7 +483,7 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap)
*with_mmap = 0;
off = 0;
retval = 0;
retval = -1;
fb->sz = 0;
fb->buf = NULL;
for (;;) {
@ -498,13 +499,13 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap)
read(fd, fb->buf + (int)off, fb->sz - off);
if (ssz == 0) {
fb->sz = off;
retval = 1;
retval = 0;
break;
}
if (ssz == -1) {
if (curp->gzip)
(void)gzerror(gz, &gzerrnum);
mandoc_msg(MANDOCERR_FILE, 0, 0, "read: %s",
mandoc_msg(MANDOCERR_READ, 0, 0, "%s",
curp->gzip && gzerrnum != Z_ERRNO ?
zError(gzerrnum) : strerror(errno));
break;
@ -513,10 +514,10 @@ read_whole_file(struct mparse *curp, int fd, struct buf *fb, int *with_mmap)
}
if (curp->gzip && (gzerrnum = gzclose(gz)) != Z_OK)
mandoc_msg(MANDOCERR_FILE, 0, 0, "gzclose: %s",
mandoc_msg(MANDOCERR_GZCLOSE, 0, 0, "%s",
gzerrnum == Z_ERRNO ? strerror(errno) :
zError(gzerrnum));
if (retval == 0) {
if (retval == -1) {
free(fb->buf);
fb->buf = NULL;
}
@ -555,7 +556,7 @@ mparse_readfd(struct mparse *curp, int fd, const char *filename)
mandoc_msg(MANDOCERR_ROFFLOOP, curp->line, 0, NULL);
return;
}
if (read_whole_file(curp, fd, &blk, &with_mmap) == 0)
if (read_whole_file(curp, fd, &blk, &with_mmap) == -1)
return;
/*

15
roff.7
View File

@ -1,4 +1,4 @@
.\" $Id: roff.7,v 1.111 2019/01/01 03:45:29 schwarze Exp $
.\" $Id: roff.7,v 1.114 2019/07/15 19:20:30 schwarze Exp $
.\"
.\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010-2019 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: January 1 2019 $
.Dd $Mdocdate: July 15 2019 $
.Dt ROFF 7
.Os
.Sh NAME
@ -315,12 +315,18 @@ delimiters
The proper spacing is also intelligently preserved if a sentence ends at
the boundary of a macro line.
.Pp
If an input line happens to end with a period, exclamation or question
mark that isn't the end of a sentence, append a zero-width space
.Pq Sq \e& .
.Pp
Examples:
.Bd -literal -offset indent -compact
Do not end sentences mid-line like this. Instead,
end a sentence like this.
A macro would end like this:
\&.Xr mandoc 1 \&.
An abbreviation at the end of an input line needs escaping, e.g.\e&
like this.
.Ed
.Sh REQUEST SYNTAX
A request or macro line consists of:
@ -503,10 +509,9 @@ This is a Heirloom extension and currently unsupported.
.It Ic \&br
Break the output line.
.It Ic \&break
Break out of a
Break out of the innermost
.Ic \&while
loop.
Currently unsupported.
.It Ic \&breakchar Ar char ...
Optional line break characters.
This is a Heirloom extension and currently ignored.
@ -2279,7 +2284,7 @@ code.
.Pp
The special semantics of the
.Cm nS
number register is an idiosyncracy of
number register is an idiosyncrasy of
.Ox
manuals and not supported by other
.Xr mdoc 7

66
roff.c
View File

@ -1,4 +1,4 @@
/* $Id: roff.c,v 1.363 2019/02/06 21:11:43 schwarze Exp $ */
/* $Id: roff.c,v 1.366 2019/07/01 22:56:24 schwarze Exp $ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
@ -133,15 +133,18 @@ struct roff {
char escape; /* escape character */
};
/*
* A macro definition, condition, or ignored block.
*/
struct roffnode {
enum roff_tok tok; /* type of node */
struct roffnode *parent; /* up one in stack */
int line; /* parse line */
int col; /* parse col */
char *name; /* node name, e.g. macro name */
char *end; /* end-rules: custom token */
int endspan; /* end-rules: next-line or infty */
int rule; /* current evaluation rule */
char *end; /* custom end macro of the block */
int endspan; /* scope to: 1=eol 2=next line -1=\} */
int rule; /* content is: 1=evaluated 0=skipped */
};
#define ROFF_ARGS struct roff *r, /* parse ctx */ \
@ -181,6 +184,7 @@ static int roff_als(ROFF_ARGS);
static int roff_block(ROFF_ARGS);
static int roff_block_text(ROFF_ARGS);
static int roff_block_sub(ROFF_ARGS);
static int roff_break(ROFF_ARGS);
static int roff_cblock(ROFF_ARGS);
static int roff_cc(ROFF_ARGS);
static int roff_ccond(struct roff *, int, int);
@ -400,7 +404,7 @@ static struct roffmac roffs[TOKEN_NONE] = {
{ roff_unsupp, NULL, NULL, 0 }, /* boxa */
{ roff_line_ignore, NULL, NULL, 0 }, /* bp */
{ roff_unsupp, NULL, NULL, 0 }, /* BP */
{ roff_unsupp, NULL, NULL, 0 }, /* break */
{ roff_break, NULL, NULL, 0 }, /* break */
{ roff_line_ignore, NULL, NULL, 0 }, /* breakchar */
{ roff_line_ignore, NULL, NULL, 0 }, /* brnl */
{ roff_noarg, NULL, NULL, 0 }, /* brp */
@ -685,7 +689,7 @@ roffhash_find(struct ohash *htab, const char *name, size_t sz)
/*
* Pop the current node off of the stack of roff instructions currently
* pending.
* pending. Return 1 if it is a loop or 0 otherwise.
*/
static int
roffnode_pop(struct roff *r)
@ -779,7 +783,7 @@ roff_reset(struct roff *r)
void
roff_free(struct roff *r)
{
int i;
int i;
roff_free1(r);
for (i = 0; i < r->mstacksz; i++)
@ -1586,7 +1590,7 @@ char *
roff_getarg(struct roff *r, char **cpp, int ln, int *pos)
{
struct buf buf;
char *cp, *start;
char *cp, *start;
int newesc, pairs, quoted, white;
/* Quoting can only start with a new word. */
@ -2002,6 +2006,10 @@ roff_cblock(ROFF_ARGS)
}
/*
* Pop all nodes ending at the end of the current input line.
* Return the number of loops ended.
*/
static int
roffnode_cleanscope(struct roff *r)
{
@ -2016,6 +2024,11 @@ roffnode_cleanscope(struct roff *r)
return inloop;
}
/*
* Handle the closing \} of a conditional block.
* Apart from generating warnings, this only pops nodes.
* Return the number of loops ended.
*/
static int
roff_ccond(struct roff *r, int ln, int ppos)
{
@ -2235,6 +2248,7 @@ roff_block_text(ROFF_ARGS)
static int
roff_cond_sub(ROFF_ARGS)
{
struct roffnode *bl;
char *ep;
int endloop, irc, rr;
enum roff_tok t;
@ -2282,9 +2296,21 @@ roff_cond_sub(ROFF_ARGS)
*/
t = roff_parse(r, buf->buf, &pos, ln, ppos);
irc |= t != TOKEN_NONE && (rr || roffs[t].flags & ROFFMAC_STRUCT) ?
(*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs) :
rr ? ROFF_CONT : ROFF_IGN;
if (t == ROFF_break) {
if (irc & ROFF_LOOPMASK)
irc = ROFF_IGN | ROFF_LOOPEXIT;
else if (rr) {
for (bl = r->last; bl != NULL; bl = bl->parent) {
bl->rule = 0;
if (bl->tok == ROFF_while)
break;
}
}
} else if (t != TOKEN_NONE &&
(rr || roffs[t].flags & ROFFMAC_STRUCT))
irc |= (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs);
else
irc |= rr ? ROFF_CONT : ROFF_IGN;
return irc;
}
@ -3482,6 +3508,17 @@ roff_als(ROFF_ARGS)
return ROFF_IGN;
}
/*
* The .break request only makes sense inside conditionals,
* and that case is already handled in roff_cond_sub().
*/
static int
roff_break(ROFF_ARGS)
{
mandoc_msg(MANDOCERR_BLK_NOTOPEN, ln, pos, "break");
return ROFF_IGN;
}
static int
roff_cc(ROFF_ARGS)
{
@ -3804,6 +3841,11 @@ roff_userdef(ROFF_ARGS)
char *arg, *ap, *dst, *src;
size_t sz;
/* If the macro is empty, ignore it altogether. */
if (*r->current_string == '\0')
return ROFF_IGN;
/* Initialize a new macro stack context. */
if (++r->mstackpos == r->mstacksz) {
@ -3851,7 +3893,7 @@ roff_userdef(ROFF_ARGS)
buf->sz = strlen(buf->buf) + 1;
*offs = 0;
return buf->sz > 1 && buf->buf[buf->sz - 2] == '\n' ?
return buf->buf[buf->sz - 2] == '\n' ?
ROFF_REPARSE | ROFF_USERCALL : ROFF_IGN | ROFF_APPEND;
}

View File

@ -1,4 +1,4 @@
/* $Id: roff_html.c,v 1.19 2019/01/07 07:26:29 schwarze Exp $ */
/* $Id: roff_html.c,v 1.20 2019/04/30 15:53:01 schwarze Exp $ */
/*
* Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2017, 2018, 2019 Ingo Schwarze <schwarze@openbsd.org>
@ -94,7 +94,7 @@ roff_html_pre_ft(ROFF_HTML_ARGS)
const char *cp;
cp = n->child->string;
print_metaf(h, mandoc_font(cp, (int)strlen(cp)));
html_setfont(h, mandoc_font(cp, (int)strlen(cp)));
}
static void

49
tag.c
View File

@ -1,6 +1,6 @@
/* $Id: tag.c,v 1.21 2018/11/22 11:30:23 schwarze Exp $ */
/* $Id: tag.c,v 1.24 2019/07/22 03:21:50 schwarze Exp $ */
/*
* Copyright (c) 2015, 2016, 2018 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2015, 2016, 2018, 2019 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
@ -18,9 +18,7 @@
#include <sys/types.h>
#if HAVE_ERR
#include <err.h>
#endif
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stddef.h>
@ -32,6 +30,7 @@
#include "mandoc_aux.h"
#include "mandoc_ohash.h"
#include "mandoc.h"
#include "tag.h"
struct tag_entry {
@ -83,8 +82,10 @@ tag_init(void)
/* Save the original standard output for use by the pager. */
if ((tag_files.ofd = dup(STDOUT_FILENO)) == -1)
if ((tag_files.ofd = dup(STDOUT_FILENO)) == -1) {
mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno));
goto fail;
}
/* Create both temporary output files. */
@ -92,12 +93,20 @@ tag_init(void)
sizeof(tag_files.ofn));
(void)strlcpy(tag_files.tfn, "/tmp/man.XXXXXXXXXX",
sizeof(tag_files.tfn));
if ((ofd = mkstemp(tag_files.ofn)) == -1)
if ((ofd = mkstemp(tag_files.ofn)) == -1) {
mandoc_msg(MANDOCERR_MKSTEMP, 0, 0,
"%s: %s", tag_files.ofn, strerror(errno));
goto fail;
if ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1)
}
if ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1) {
mandoc_msg(MANDOCERR_MKSTEMP, 0, 0,
"%s: %s", tag_files.tfn, strerror(errno));
goto fail;
if (dup2(ofd, STDOUT_FILENO) == -1)
}
if (dup2(ofd, STDOUT_FILENO) == -1) {
mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno));
goto fail;
}
close(ofd);
/*
@ -142,11 +151,11 @@ tag_put(const char *s, int prio, size_t line)
s += 2;
/*
* Skip whitespace and whatever follows it,
* Skip whitespace and escapes and whatever follows,
* and if there is any, downgrade the priority.
*/
len = strcspn(s, " \t");
len = strcspn(s, " \t\\");
if (len == 0)
return;
@ -216,21 +225,27 @@ tag_write(void)
struct tag_entry *entry;
size_t i;
unsigned int slot;
int empty;
if (tag_files.tfd <= 0)
return;
if (tag_files.tagname != NULL && ohash_find(&tag_data,
ohash_qlookup(&tag_data, tag_files.tagname)) == NULL) {
warnx("%s: no such tag", tag_files.tagname);
mandoc_msg(MANDOCERR_TAG, 0, 0, "%s", tag_files.tagname);
tag_files.tagname = NULL;
}
stream = fdopen(tag_files.tfd, "w");
if ((stream = fdopen(tag_files.tfd, "w")) == NULL)
mandoc_msg(MANDOCERR_FDOPEN, 0, 0, "%s", strerror(errno));
empty = 1;
entry = ohash_first(&tag_data, &slot);
while (entry != NULL) {
if (stream != NULL && entry->prio >= 0)
for (i = 0; i < entry->nlines; i++)
if (stream != NULL && entry->prio >= 0) {
for (i = 0; i < entry->nlines; i++) {
fprintf(stream, "%s %s %zu\n",
entry->s, tag_files.ofn, entry->lines[i]);
empty = 0;
}
}
free(entry->lines);
free(entry);
entry = ohash_next(&tag_data, &slot);
@ -241,6 +256,10 @@ tag_write(void)
else
close(tag_files.tfd);
tag_files.tfd = -1;
if (empty) {
unlink(tag_files.tfn);
*tag_files.tfn = '\0';
}
}
void

View File

@ -1,4 +1,4 @@
/* $Id: tbl_html.c,v 1.32 2019/01/06 04:55:09 schwarze Exp $ */
/* $Id: tbl_html.c,v 1.33 2019/03/17 18:21:45 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
@ -25,6 +25,7 @@
#include <string.h>
#include "mandoc.h"
#include "roff.h"
#include "tbl.h"
#include "out.h"
#include "html.h"

View File

@ -1,4 +1,4 @@
/* $Id: tbl_term.c,v 1.68 2019/02/09 21:02:47 schwarze Exp $ */
/* $Id: tbl_term.c,v 1.72 2019/07/01 22:56:24 schwarze Exp $ */
/*
* Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2019 Ingo Schwarze <schwarze@openbsd.org>
@ -46,7 +46,8 @@ static void tbl_fill_border(struct termp *, int, size_t);
static void tbl_fill_char(struct termp *, char, size_t);
static void tbl_fill_string(struct termp *, const char *, size_t);
static void tbl_hrule(struct termp *, const struct tbl_span *,
const struct tbl_span *, int);
const struct tbl_span *, 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 *,
@ -163,7 +164,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
const struct tbl_cell *cp, *cpn, *cpp, *cps;
const struct tbl_dat *dp;
static size_t offset;
size_t save_offset;
size_t save_offset;
size_t coloff, tsz;
int hspans, ic, more;
int dvert, fc, horiz, lhori, rhori, uvert;
@ -222,9 +223,9 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
if (tp->enc == TERMENC_ASCII &&
sp->opts->opts & TBL_OPT_DBOX)
tbl_hrule(tp, NULL, sp, TBL_OPT_DBOX);
tbl_hrule(tp, NULL, sp, sp, TBL_OPT_DBOX);
if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX))
tbl_hrule(tp, NULL, sp, TBL_OPT_BOX);
tbl_hrule(tp, NULL, sp, sp, TBL_OPT_BOX);
}
/* Set up the columns. */
@ -342,7 +343,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
more = 0;
if (horiz)
tbl_hrule(tp, sp->prev, sp, 0);
tbl_hrule(tp, sp->prev, sp, sp->next, 0);
else {
cp = sp->layout->first;
cpn = sp->next == NULL ? NULL :
@ -557,12 +558,12 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
tp->tcol->rmargin = tp->maxrmargin;
if (sp->next == NULL) {
if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) {
tbl_hrule(tp, sp, NULL, TBL_OPT_BOX);
tbl_hrule(tp, sp, sp, NULL, TBL_OPT_BOX);
tp->skipvsp = 1;
}
if (tp->enc == TERMENC_ASCII &&
sp->opts->opts & TBL_OPT_DBOX) {
tbl_hrule(tp, sp, NULL, TBL_OPT_DBOX);
tbl_hrule(tp, sp, sp, NULL, TBL_OPT_DBOX);
tp->skipvsp = 2;
}
assert(tp->tbl.cols);
@ -571,7 +572,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
} else if (horiz == 0 && sp->opts->opts & TBL_OPT_ALLBOX &&
(sp->next == NULL || sp->next->pos == TBL_SPAN_DATA ||
sp->next->next != NULL))
tbl_hrule(tp, sp, sp->next, TBL_OPT_ALLBOX);
tbl_hrule(tp, sp, sp, sp->next, TBL_OPT_ALLBOX);
tp->tcol->offset = save_offset;
tp->flags &= ~TERMP_NONOSPACE;
@ -579,9 +580,10 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
static void
tbl_hrule(struct termp *tp, const struct tbl_span *spp,
const struct tbl_span *spn, int flags)
const struct tbl_span *sp, const struct tbl_span *spn, int flags)
{
const struct tbl_cell *cpp; /* Layout cell above this line. */
const struct tbl_cell *cp; /* Layout cell in this line. */
const struct tbl_cell *cpn; /* Layout cell below this line. */
const struct tbl_dat *dpn; /* Data cell below this line. */
const struct roffcol *col; /* Contains width and spacing. */
@ -592,6 +594,7 @@ tbl_hrule(struct termp *tp, const struct tbl_span *spp,
int uw, dw; /* Vertical line widths. */
cpp = spp == NULL ? NULL : spp->layout->first;
cp = sp == NULL ? NULL : sp->layout->first;
cpn = spn == NULL ? NULL : spn->layout->first;
dpn = NULL;
if (spn != NULL) {
@ -600,11 +603,11 @@ tbl_hrule(struct termp *tp, const struct tbl_span *spp,
else if (spn->next != NULL)
dpn = spn->next->first;
}
opts = spn == NULL ? spp->opts->opts : spn->opts->opts;
opts = sp->opts->opts;
bw = opts & TBL_OPT_DBOX ? (tp->enc == TERMENC_UTF8 ? 2 : 1) :
opts & (TBL_OPT_BOX | TBL_OPT_ALLBOX) ? 1 : 0;
hw = flags == TBL_OPT_DBOX || flags == TBL_OPT_BOX ? bw :
spn->pos == TBL_SPAN_DHORIZ ? 2 : 1;
sp->pos == TBL_SPAN_DHORIZ ? 2 : 1;
/* Print the left end of the line. */
@ -619,14 +622,19 @@ tbl_hrule(struct termp *tp, const struct tbl_span *spp,
(spp == NULL || cpn == NULL ||
cpn->pos != TBL_CELL_DOWN ? BRIGHT * hw : 0), 1);
col = tp->tbl.cols;
for (;;) {
col = tp->tbl.cols + (cpn == NULL ? cpp->col : cpn->col);
if (cp == NULL)
col++;
else
col = tp->tbl.cols + cp->col;
/* Print the horizontal line inside this column. */
lw = cpp == NULL || cpn == NULL ||
(cpn->pos != TBL_CELL_DOWN &&
(dpn == NULL || strcmp(dpn->string, "\\^") != 0))
(dpn == NULL || dpn->string == NULL ||
strcmp(dpn->string, "\\^") != 0))
? hw : 0;
tbl_direct_border(tp, BHORIZ * lw,
col->width + col->spacing / 2);
@ -645,7 +653,10 @@ tbl_hrule(struct termp *tp, const struct tbl_span *spp,
uw = 1;
}
cpp = cpp->next;
}
} else if (spp != NULL && opts & TBL_OPT_ALLBOX)
uw = 1;
if (cp != NULL)
cp = cp->next;
if (cpn != NULL) {
if (flags != TBL_OPT_DBOX) {
dw = cpn->vert;
@ -655,8 +666,9 @@ tbl_hrule(struct termp *tp, const struct tbl_span *spp,
cpn = cpn->next;
while (dpn != NULL && dpn->layout != cpn)
dpn = dpn->next;
}
if (cpp == NULL && cpn == NULL)
} else if (spn != NULL && opts & TBL_OPT_ALLBOX)
dw = 1;
if (col + 1 == tp->tbl.cols + sp->opts->cols)
break;
/* Vertical lines do not cross spanned cells. */
@ -670,7 +682,8 @@ tbl_hrule(struct termp *tp, const struct tbl_span *spp,
rw = cpp == NULL || cpn == NULL ||
(cpn->pos != TBL_CELL_DOWN &&
(dpn == NULL || strcmp(dpn->string, "\\^") != 0))
(dpn == NULL || dpn->string == NULL ||
strcmp(dpn->string, "\\^") != 0))
? hw : 0;
/* The line crossing at the end of this column. */

4
term.c
View File

@ -1,4 +1,4 @@
/* $Id: term.c,v 1.280 2019/01/15 12:16:18 schwarze Exp $ */
/* $Id: term.c,v 1.281 2019/06/03 20:23:41 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2019 Ingo Schwarze <schwarze@openbsd.org>
@ -281,6 +281,8 @@ term_fill(struct termp *p, size_t *nbr, size_t *vbr, size_t vtarget)
case ASCII_BREAK:
vn = vis;
break;
default:
abort();
}
/* Can break at the end of a word. */
if (breakline || vn > vtarget)