summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2011-10-09 17:59:57 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2011-10-09 17:59:57 +0000
commitc45e61c7b6744c0dd8c3296ed9a6ef961a772ac6 (patch)
tree651a796877e571db7e8dd5ce49b131d5c027ca3d /usr.bin
parent239a9a9c6888a0c342f18803191d66fac05b74e1 (diff)
Sync to version 1.12.0; all code by kristaps@:
Implement .Rv in -Tman. Let -man -Tman work a bit like cat(1). Add the -Ofragment option to -T[x]html. Minor fixes in -T[x]html. Lots of apropos(1) and -Tman code cleanup.
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/mandoc/Makefile4
-rw-r--r--usr.bin/mandoc/apropos.17
-rw-r--r--usr.bin/mandoc/apropos.c297
-rw-r--r--usr.bin/mandoc/chars.in14
-rw-r--r--usr.bin/mandoc/html.c10
-rw-r--r--usr.bin/mandoc/html.h10
-rw-r--r--usr.bin/mandoc/main.c9
-rw-r--r--usr.bin/mandoc/main.h3
-rw-r--r--usr.bin/mandoc/man.c10
-rw-r--r--usr.bin/mandoc/man.h3
-rw-r--r--usr.bin/mandoc/man_html.c35
-rw-r--r--usr.bin/mandoc/mandoc.138
-rw-r--r--usr.bin/mandoc/mandoc.h35
-rw-r--r--usr.bin/mandoc/mandocdb.88
-rw-r--r--usr.bin/mandoc/mdoc_html.c33
-rw-r--r--usr.bin/mandoc/mdoc_man.c297
-rw-r--r--usr.bin/mandoc/read.c52
17 files changed, 517 insertions, 348 deletions
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile
index 0f93eed462b..ca988968211 100644
--- a/usr.bin/mandoc/Makefile
+++ b/usr.bin/mandoc/Makefile
@@ -1,8 +1,8 @@
-# $OpenBSD: Makefile,v 1.61 2011/10/06 23:04:16 schwarze Exp $
+# $OpenBSD: Makefile,v 1.62 2011/10/09 17:59:56 schwarze Exp $
.include <bsd.own.mk>
-CFLAGS+=-DVERSION=\"1.11.7\"
+CFLAGS+=-DVERSION=\"1.12.0\"
CFLAGS+=-W -Wall -Wstrict-prototypes
.if ${COMPILER_VERSION:L} == "gcc3" || ${COMPILER_VERSION:L} == "gcc4"
diff --git a/usr.bin/mandoc/apropos.1 b/usr.bin/mandoc/apropos.1
index b5fda7ab22c..281e2ececf0 100644
--- a/usr.bin/mandoc/apropos.1
+++ b/usr.bin/mandoc/apropos.1
@@ -1,4 +1,4 @@
-.\" $Id: apropos.1,v 1.1 2011/10/06 23:04:16 schwarze Exp $
+.\" $Id: apropos.1,v 1.2 2011/10/09 17:59:56 schwarze Exp $
.\"
.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: October 6 2011 $
+.Dd $Mdocdate: October 9 2011 $
.Dt APROPOS 1
.Os
.Sh NAME
@@ -162,7 +162,8 @@ in any letter case:
The
.Nm
utility was written by
-.An Kristaps Dzonsons Aq kristaps@bsd.lv .
+.An Kristaps Dzonsons ,
+.Mt kristaps@bsd.lv .
.\" .Sh CAVEATS
.\" .Sh BUGS
.\" .Sh SECURITY CONSIDERATIONS
diff --git a/usr.bin/mandoc/apropos.c b/usr.bin/mandoc/apropos.c
index 002078010e3..7e2f5722a91 100644
--- a/usr.bin/mandoc/apropos.c
+++ b/usr.bin/mandoc/apropos.c
@@ -1,4 +1,4 @@
-/* $Id: apropos.c,v 1.1 2011/10/06 23:04:16 schwarze Exp $ */
+/* $Id: apropos.c,v 1.2 2011/10/09 17:59:56 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -32,21 +32,23 @@
#include "mandoc.h"
-#define MAXRESULTS 100
-
-#define TYPE_NAME 0x01
-#define TYPE_FUNCTION 0x02
-#define TYPE_UTILITY 0x04
-#define TYPE_INCLUDES 0x08
-#define TYPE_VARIABLE 0x10
-#define TYPE_STANDARD 0x20
-#define TYPE_AUTHOR 0x40
-#define TYPE_CONFIG 0x80
-#define TYPE_DESC 0x100
-#define TYPE_XREF 0x200
-#define TYPE_PATH 0x400
-#define TYPE_ENV 0x800
-#define TYPE_ERR 0x1000
+#define MAXRESULTS 256
+
+/* Bit-fields. See mandocdb.8. */
+
+#define TYPE_NAME 0x01
+#define TYPE_FUNCTION 0x02
+#define TYPE_UTILITY 0x04
+#define TYPE_INCLUDES 0x08
+#define TYPE_VARIABLE 0x10
+#define TYPE_STANDARD 0x20
+#define TYPE_AUTHOR 0x40
+#define TYPE_CONFIG 0x80
+#define TYPE_DESC 0x100
+#define TYPE_XREF 0x200
+#define TYPE_PATH 0x400
+#define TYPE_ENV 0x800
+#define TYPE_ERR 0x1000
enum match {
MATCH_SUBSTR = 0,
@@ -71,16 +73,16 @@ struct opts {
struct type {
int mask;
- const char *name;
+ const char *name; /* command-line type name */
};
struct rec {
- char *file;
- char *cat;
- char *title;
- char *arch;
- char *desc;
- recno_t rec;
+ char *file; /* file in file-system */
+ char *cat; /* category (3p, 3, etc.) */
+ char *title; /* title (FOO, etc.) */
+ char *arch; /* arch (or empty string) */
+ char *desc; /* description (from Nd) */
+ recno_t rec; /* record in index */
};
struct res {
@@ -92,6 +94,14 @@ struct res {
char *title; /* manual section */
char *uri; /* formatted uri of file */
recno_t rec; /* unique id of underlying manual */
+ /*
+ * Maintain a binary tree for checking the uniqueness of `rec'
+ * when adding elements to the results array.
+ * Since the results array is dynamic, use offset in the array
+ * instead of a pointer to the structure.
+ */
+ int lhs;
+ int rhs;
};
struct state {
@@ -99,8 +109,6 @@ struct state {
DB *idx; /* index */
const char *dbf; /* database name */
const char *idxf; /* index name */
- void (*err)(const char *);
- void (*errx)(const char *, ...);
};
static const char * const sorts[SORT__MAX] = {
@@ -130,27 +138,22 @@ static void buf_alloc(char **, size_t *, size_t);
static void buf_dup(struct mchars *, char **, const char *);
static void buf_redup(struct mchars *, char **,
size_t *, const char *);
-static void error(const char *, ...);
static int sort_cat(const void *, const void *);
static int sort_title(const void *, const void *);
-static void state_destroy(struct state *);
-static int state_getrecord(struct state *, recno_t, struct rec *);
-static int state_init(struct state *,
- const char *, const char *,
- void (*err)(const char *),
- void (*errx)(const char *, ...));
+static int state_getrecord(struct state *,
+ recno_t, struct rec *);
static void state_output(const struct res *, int);
-static void state_search(struct state *,
+static int state_search(struct state *,
const struct opts *, char *);
-
static void usage(void);
-static const char *progname;
+static char *progname;
int
apropos(int argc, char *argv[])
{
- int ch, i;
+ BTREEINFO info;
+ int ch, i, rc;
const char *dbf, *idxf;
struct state state;
char *q, *v;
@@ -159,10 +162,12 @@ apropos(int argc, char *argv[])
extern char *optarg;
memset(&opts, 0, sizeof(struct opts));
+ memset(&state, 0, sizeof(struct state));
dbf = "mandoc.db";
idxf = "mandoc.index";
q = NULL;
+ rc = EXIT_FAILURE;
progname = strrchr(argv[0], '/');
if (progname == NULL)
@@ -200,7 +205,7 @@ apropos(int argc, char *argv[])
if (i < SORT__MAX)
break;
- error("%s: Bad sort\n", optarg);
+ fprintf(stderr, "%s: Bad sort\n", optarg);
return(EXIT_FAILURE);
case ('t'):
while (NULL != (v = strsep(&optarg, ","))) {
@@ -218,7 +223,7 @@ apropos(int argc, char *argv[])
if (NULL == v)
break;
- error("%s: Bad type\n", v);
+ fprintf(stderr, "%s: Bad type\n", v);
return(EXIT_FAILURE);
default:
usage();
@@ -230,54 +235,85 @@ apropos(int argc, char *argv[])
if (0 == argc || '\0' == **argv) {
usage();
- return(EXIT_FAILURE);
+ goto out;
} else
q = *argv;
if (0 == opts.types)
opts.types = TYPE_NAME | TYPE_DESC;
- if ( ! state_init(&state, dbf, idxf, perror, error)) {
- state_destroy(&state);
- return(EXIT_FAILURE);
+ /*
+ * Configure databases.
+ * The keyword database is a btree that allows for duplicate
+ * entries.
+ * The index database is a recno.
+ */
+
+ memset(&info, 0, sizeof(BTREEINFO));
+ info.flags = R_DUP;
+
+ state.db = dbopen(dbf, O_RDONLY, 0, DB_BTREE, &info);
+ if (NULL == state.db) {
+ perror(dbf);
+ goto out;
+ }
+
+ state.idx = dbopen(idxf, O_RDONLY, 0, DB_RECNO, NULL);
+ if (NULL == state.idx) {
+ perror(idxf);
+ goto out;
}
- state_search(&state, &opts, q);
- state_destroy(&state);
+ /* Main search function. */
- return(EXIT_SUCCESS);
+ rc = state_search(&state, &opts, q) ?
+ EXIT_SUCCESS : EXIT_FAILURE;
+out:
+ if (state.db)
+ (*state.db->close)(state.db);
+ if (state.idx)
+ (*state.idx->close)(state.idx);
+
+ return(rc);
}
-static void
+static int
state_search(struct state *p, const struct opts *opts, char *q)
{
- int i, len, ch, rflags, dflag;
+ int leaf, root, len, ch, dflag, rc;
struct mchars *mc;
char *buf;
size_t bufsz;
recno_t rec;
uint32_t fl;
DBT key, val;
- struct res res[MAXRESULTS];
+ struct res *res;
regex_t reg;
regex_t *regp;
char filebuf[10];
struct rec record;
+ rc = 0;
+ root = leaf = -1;
+ res = NULL;
len = 0;
buf = NULL;
bufsz = 0;
- ch = 0;
regp = NULL;
+ /*
+ * Configure how we scan through results to see if we match:
+ * whether by regexp or exact matches.
+ */
+
switch (opts->match) {
case (MATCH_REGEX):
- rflags = REG_EXTENDED | REG_NOSUB |
+ ch = REG_EXTENDED | REG_NOSUB |
(opts->insens ? REG_ICASE : 0);
- if (0 != regcomp(&reg, q, rflags)) {
- error("%s: Bad pattern\n", q);
- return;
+ if (0 != regcomp(&reg, q, ch)) {
+ fprintf(stderr, "%s: Bad pattern\n", q);
+ return(0);
}
regp = &reg;
@@ -293,10 +329,7 @@ state_search(struct state *p, const struct opts *opts, char *q)
break;
}
- if (NULL == (mc = mchars_alloc())) {
- perror(NULL);
- exit(EXIT_FAILURE);
- }
+ mc = mchars_alloc();
/*
* Iterate over the entire keyword database.
@@ -305,10 +338,7 @@ state_search(struct state *p, const struct opts *opts, char *q)
* Lastly, add it to the available records.
*/
- while (len < MAXRESULTS) {
- if ((ch = (*p->db->seq)(p->db, &key, &val, dflag)))
- break;
-
+ while (0 == (ch = (*p->db->seq)(p->db, &key, &val, dflag))) {
dflag = R_NEXT;
/*
@@ -319,8 +349,8 @@ state_search(struct state *p, const struct opts *opts, char *q)
*/
if (key.size < 2 || 8 != val.size) {
- error("%s: Corrupt database\n", p->dbf);
- exit(EXIT_FAILURE);
+ fprintf(stderr, "%s: Bad database\n", p->dbf);
+ goto out;
}
buf_redup(mc, &buf, &bufsz, (char *)key.data);
@@ -357,7 +387,7 @@ state_search(struct state *p, const struct opts *opts, char *q)
memcpy(&rec, val.data + 4, sizeof(recno_t));
if ( ! state_getrecord(p, rec, &record))
- exit(EXIT_FAILURE);
+ goto out;
/* If we're in a different section, skip... */
@@ -366,15 +396,25 @@ state_search(struct state *p, const struct opts *opts, char *q)
if (opts->arch && strcasecmp(opts->arch, record.arch))
continue;
- /* FIXME: this needs to be changed. Ugh. Linear. */
+ /*
+ * Do a binary search to dedupe the results tree of the
+ * same record: we don't print the same file.
+ */
- for (i = 0; i < len; i++)
- if (res[i].rec == record.rec)
+ for (leaf = root; leaf >= 0; )
+ if (rec > res[leaf].rec && res[leaf].rhs >= 0)
+ leaf = res[leaf].rhs;
+ else if (rec < res[leaf].rec && res[leaf].lhs >= 0)
+ leaf = res[leaf].lhs;
+ else
break;
- if (i < len)
+ if (leaf >= 0 && res[leaf].rec == rec)
continue;
+ res = mandoc_realloc
+ (res, (len + 1) * sizeof(struct res));
+
/*
* Now we have our filename, keywords, types, and all
* other necessary information.
@@ -387,6 +427,7 @@ state_search(struct state *p, const struct opts *opts, char *q)
res[len].rec = record.rec;
res[len].types = fl;
+ res[len].lhs = res[len].rhs = -1;
buf_dup(mc, &res[len].keyword, buf);
buf_dup(mc, &res[len].uri, filebuf);
@@ -394,26 +435,33 @@ state_search(struct state *p, const struct opts *opts, char *q)
buf_dup(mc, &res[len].arch, record.arch);
buf_dup(mc, &res[len].title, record.title);
buf_dup(mc, &res[len].desc, record.desc);
+
+ if (leaf >= 0) {
+ if (record.rec > res[leaf].rec)
+ res[leaf].rhs = len;
+ else
+ res[leaf].lhs = len;
+ } else
+ root = len;
+
len++;
}
-send:
if (ch < 0) {
perror(p->dbf);
- exit(EXIT_FAILURE);
+ goto out;
}
+send:
+ /* Sort our results. */
- switch (opts->sort) {
- case (SORT_CAT):
+ if (SORT_CAT == opts->sort)
qsort(res, len, sizeof(struct res), sort_cat);
- break;
- default:
+ else
qsort(res, len, sizeof(struct res), sort_title);
- break;
- }
state_output(res, len);
-
+ rc = 1;
+out:
for (len-- ; len >= 0; len--) {
free(res[len].keyword);
free(res[len].title);
@@ -423,11 +471,14 @@ send:
free(res[len].uri);
}
+ free(res);
free(buf);
mchars_free(mc);
if (regp)
regfree(regp);
+
+ return(rc);
}
/*
@@ -441,10 +492,7 @@ buf_alloc(char **buf, size_t *bufsz, size_t sz)
return;
*bufsz = sz + 1024;
- if (NULL == (*buf = realloc(*buf, *bufsz))) {
- perror(NULL);
- exit(EXIT_FAILURE);
- }
+ *buf = mandoc_realloc(*buf, *bufsz);
}
/*
@@ -535,16 +583,6 @@ buf_redup(struct mchars *mc, char **buf,
}
static void
-error(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-}
-
-static void
state_output(const struct res *res, int sz)
{
int i;
@@ -571,48 +609,6 @@ usage(void)
}
static int
-state_init(struct state *p,
- const char *dbf, const char *idxf,
- void (*err)(const char *),
- void (*errx)(const char *, ...))
-{
- BTREEINFO info;
-
- memset(p, 0, sizeof(struct state));
- memset(&info, 0, sizeof(BTREEINFO));
-
- info.flags = R_DUP;
-
- p->dbf = dbf;
- p->idxf = idxf;
- p->err = err;
-
- p->db = dbopen(p->dbf, O_RDONLY, 0, DB_BTREE, &info);
- if (NULL == p->db) {
- (*err)(p->dbf);
- return(0);
- }
-
- p->idx = dbopen(p->idxf, O_RDONLY, 0, DB_RECNO, NULL);
- if (NULL == p->idx) {
- (*err)(p->idxf);
- return(0);
- }
-
- return(1);
-}
-
-static void
-state_destroy(struct state *p)
-{
-
- if (p->db)
- (*p->db->close)(p->db);
- if (p->idx)
- (*p->idx->close)(p->idx);
-}
-
-static int
state_getrecord(struct state *p, recno_t rec, struct rec *rp)
{
DBT key, val;
@@ -624,40 +620,33 @@ state_getrecord(struct state *p, recno_t rec, struct rec *rp)
rc = (*p->idx->get)(p->idx, &key, &val, 0);
if (rc < 0) {
- (*p->err)(p->idxf);
- return(0);
- } else if (rc > 0) {
- (*p->errx)("%s: Corrupt index\n", p->idxf);
+ perror(p->idxf);
return(0);
- }
+ } else if (rc > 0)
+ goto err;
rp->file = (char *)val.data;
- if ((sz = strlen(rp->file) + 1) >= val.size) {
- (*p->errx)("%s: Corrupt index\n", p->idxf);
- return(0);
- }
+ if ((sz = strlen(rp->file) + 1) >= val.size)
+ goto err;
rp->cat = (char *)val.data + (int)sz;
- if ((sz += strlen(rp->cat) + 1) >= val.size) {
- (*p->errx)("%s: Corrupt index\n", p->idxf);
- return(0);
- }
+ if ((sz += strlen(rp->cat) + 1) >= val.size)
+ goto err;
rp->title = (char *)val.data + (int)sz;
- if ((sz += strlen(rp->title) + 1) >= val.size) {
- (*p->errx)("%s: Corrupt index\n", p->idxf);
- return(0);
- }
+ if ((sz += strlen(rp->title) + 1) >= val.size)
+ goto err;
rp->arch = (char *)val.data + (int)sz;
- if ((sz += strlen(rp->arch) + 1) >= val.size) {
- (*p->errx)("%s: Corrupt index\n", p->idxf);
- return(0);
- }
+ if ((sz += strlen(rp->arch) + 1) >= val.size)
+ goto err;
rp->desc = (char *)val.data + (int)sz;
rp->rec = rec;
return(1);
+err:
+ fprintf(stderr, "%s: Corrupt index\n", p->idxf);
+ return(0);
}
static int
diff --git a/usr.bin/mandoc/chars.in b/usr.bin/mandoc/chars.in
index 357f7dba95a..e3bdbbfd760 100644
--- a/usr.bin/mandoc/chars.in
+++ b/usr.bin/mandoc/chars.in
@@ -1,4 +1,4 @@
-/* $Id: chars.in,v 1.17 2011/09/18 10:25:28 schwarze Exp $ */
+/* $Id: chars.in,v 1.18 2011/10/09 17:59:56 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -33,15 +33,15 @@ static const char ascii_nbrsp[2] = { ASCII_NBRSP, '\0' };
CHAR_TBL_START
/* Spacing. */
-CHAR("c", "", 8203)
+CHAR("c", "", 0)
CHAR("0", " ", 8194)
CHAR(" ", ascii_nbrsp, 160)
CHAR("~", ascii_nbrsp, 160)
-CHAR("%", "", 8203)
-CHAR("&", "", 8203)
-CHAR("^", "", 8203)
-CHAR("|", "", 8203)
-CHAR("}", "", 8203)
+CHAR("%", "", 0)
+CHAR("&", "", 0)
+CHAR("^", "", 0)
+CHAR("|", "", 0)
+CHAR("}", "", 0)
/* Accents. */
CHAR("a\"", "\"", 779)
diff --git a/usr.bin/mandoc/html.c b/usr.bin/mandoc/html.c
index 0f719dfe823..80f6acc6956 100644
--- a/usr.bin/mandoc/html.c
+++ b/usr.bin/mandoc/html.c
@@ -1,4 +1,4 @@
-/* $Id: html.c,v 1.28 2011/07/08 17:47:54 schwarze Exp $ */
+/* $Id: html.c,v 1.29 2011/10/09 17:59:56 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -114,13 +114,14 @@ static void *
ml_alloc(char *outopts, enum htmltype type)
{
struct html *h;
- const char *toks[4];
+ const char *toks[5];
char *v;
toks[0] = "style";
toks[1] = "man";
toks[2] = "includes";
- toks[3] = NULL;
+ toks[3] = "fragment";
+ toks[4] = NULL;
h = mandoc_calloc(1, sizeof(struct html));
@@ -139,6 +140,9 @@ ml_alloc(char *outopts, enum htmltype type)
case (2):
h->base_includes = v;
break;
+ case (3):
+ h->oflags |= HTML_FRAGMENT;
+ break;
default:
break;
}
diff --git a/usr.bin/mandoc/html.h b/usr.bin/mandoc/html.h
index 8e86973f2b0..bcc6d6f7c39 100644
--- a/usr.bin/mandoc/html.h
+++ b/usr.bin/mandoc/html.h
@@ -1,4 +1,4 @@
-/* $Id: html.h,v 1.17 2011/09/18 10:25:28 schwarze Exp $ */
+/* $Id: html.h,v 1.18 2011/10/09 17:59:56 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -104,7 +104,7 @@ struct htmlpair {
#define PAIR_STYLE_INIT(p, h) PAIR_INIT(p, ATTR_STYLE, (h)->buf)
#define PAIR_SUMMARY_INIT(p, v) PAIR_INIT(p, ATTR_SUMMARY, v)
-enum htmltype {
+enum htmltype {
HTML_HTML_4_01_STRICT,
HTML_XHTML_1_0_STRICT
};
@@ -125,11 +125,13 @@ struct html {
char *base_includes; /* base for include href */
char *style; /* style-sheet URI */
char buf[BUFSIZ]; /* see bufcat and friends */
- size_t buflen;
+ size_t buflen;
struct tag *metaf; /* current open font scope */
enum htmlfont metal; /* last used font */
enum htmlfont metac; /* current font mode */
- enum htmltype type;
+ enum htmltype type; /* output media type */
+ int oflags; /* output options */
+#define HTML_FRAGMENT (1 << 0) /* don't emit HTML/HEAD/BODY */
};
void print_gen_decls(struct html *);
diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c
index 5c858a809c5..f8d4de1e58c 100644
--- a/usr.bin/mandoc/main.c
+++ b/usr.bin/mandoc/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.79 2011/10/06 23:04:16 schwarze Exp $ */
+/* $Id: main.c,v 1.80 2011/10/09 17:59:56 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -126,6 +126,12 @@ main(int argc, char *argv[])
curp.mp = mparse_alloc(type, curp.wlevel, mmsg, &curp);
+ /*
+ * Conditionally start up the lookaside buffer before parsing.
+ */
+ if (OUTT_MAN == curp.outtype)
+ mparse_keep(curp.mp);
+
argc -= optind;
argv += optind;
@@ -251,6 +257,7 @@ parse(struct curparse *curp, int fd,
break;
case (OUTT_MAN):
curp->outmdoc = man_mdoc;
+ curp->outman = man_man;
break;
case (OUTT_PDF):
/* FALLTHROUGH */
diff --git a/usr.bin/mandoc/main.h b/usr.bin/mandoc/main.h
index 88916340d52..f6be7534525 100644
--- a/usr.bin/mandoc/main.h
+++ b/usr.bin/mandoc/main.h
@@ -1,4 +1,4 @@
-/* $Id: main.h,v 1.9 2011/09/17 14:45:22 schwarze Exp $ */
+/* $Id: main.h,v 1.10 2011/10/09 17:59:56 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -42,6 +42,7 @@ void tree_mdoc(void *, const struct mdoc *);
void tree_man(void *, const struct man *);
void man_mdoc(void *, const struct mdoc *);
+void man_man(void *, const struct man *);
void *locale_alloc(char *);
void *utf8_alloc(char *);
diff --git a/usr.bin/mandoc/man.c b/usr.bin/mandoc/man.c
index 35eaf6ab72b..3ce1b5d0b79 100644
--- a/usr.bin/mandoc/man.c
+++ b/usr.bin/mandoc/man.c
@@ -1,4 +1,4 @@
-/* $Id: man.c,v 1.61 2011/09/18 15:54:48 schwarze Exp $ */
+/* $Id: man.c,v 1.62 2011/10/09 17:59:56 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -644,3 +644,11 @@ man_node_unlink(struct man *m, struct man_node *n)
if (m && m->first == n)
m->first = NULL;
}
+
+const struct mparse *
+man_mparse(const struct man *m)
+{
+
+ assert(m && m->parse);
+ return(m->parse);
+}
diff --git a/usr.bin/mandoc/man.h b/usr.bin/mandoc/man.h
index 4595ec66fec..4a077935406 100644
--- a/usr.bin/mandoc/man.h
+++ b/usr.bin/mandoc/man.h
@@ -1,4 +1,4 @@
-/* $Id: man.h,v 1.37 2011/04/24 16:22:02 schwarze Exp $ */
+/* $Id: man.h,v 1.38 2011/10/09 17:59:56 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -105,6 +105,7 @@ struct man;
const struct man_node *man_node(const struct man *);
const struct man_meta *man_meta(const struct man *);
+const struct mparse *man_mparse(const struct man *);
__END_DECLS
diff --git a/usr.bin/mandoc/man_html.c b/usr.bin/mandoc/man_html.c
index 5192ba9761e..0e44a8074bf 100644
--- a/usr.bin/mandoc/man_html.c
+++ b/usr.bin/mandoc/man_html.c
@@ -1,4 +1,4 @@
-/* $Id: man_html.c,v 1.42 2011/09/18 15:54:48 schwarze Exp $ */
+/* $Id: man_html.c,v 1.43 2011/10/09 17:59:56 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -137,33 +137,32 @@ print_bvspace(struct html *h, const struct man_node *n)
void
html_man(void *arg, const struct man *m)
{
- struct html *h;
- struct tag *t;
struct mhtml mh;
- h = (struct html *)arg;
-
- print_gen_decls(h);
-
memset(&mh, 0, sizeof(struct mhtml));
-
- t = print_otag(h, TAG_HTML, 0, NULL);
- print_man(man_meta(m), man_node(m), &mh, h);
- print_tagq(h, t);
-
- printf("\n");
+ print_man(man_meta(m), man_node(m), &mh, (struct html *)arg);
+ putchar('\n');
}
static void
print_man(MAN_ARGS)
{
- struct tag *t;
+ struct tag *t, *tt;
+ struct htmlpair tag;
- t = print_otag(h, TAG_HEAD, 0, NULL);
- print_man_head(m, n, mh, h);
- print_tagq(h, t);
+ PAIR_CLASS_INIT(&tag, "mandoc");
+
+ if ( ! (HTML_FRAGMENT & h->oflags)) {
+ print_gen_decls(h);
+ t = print_otag(h, TAG_HTML, 0, NULL);
+ tt = print_otag(h, TAG_HEAD, 0, NULL);
+ print_man_head(m, n, mh, h);
+ print_tagq(h, tt);
+ print_otag(h, TAG_BODY, 0, NULL);
+ print_otag(h, TAG_DIV, 1, &tag);
+ } else
+ t = print_otag(h, TAG_DIV, 1, &tag);
- t = print_otag(h, TAG_BODY, 0, NULL);
print_man_nodelist(m, n, mh, h);
print_tagq(h, t);
}
diff --git a/usr.bin/mandoc/mandoc.1 b/usr.bin/mandoc/mandoc.1
index 842f6f72a27..914c2a9b7e8 100644
--- a/usr.bin/mandoc/mandoc.1
+++ b/usr.bin/mandoc/mandoc.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: mandoc.1,v 1.48 2011/09/26 14:49:03 jmc Exp $
+.\" $OpenBSD: mandoc.1,v 1.49 2011/10/09 17:59:56 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: September 26 2011 $
+.Dd $Mdocdate: October 9 2011 $
.Dt MANDOC 1
.Os
.Sh NAME
@@ -176,11 +176,11 @@ Encode output using the current locale.
See
.Sx Locale Output .
.It Fl T Ns Cm man
-Produce output in
+Produce
.Xr man 7
-format; only useful when applied to
-.Fl m Ns Cm doc
-input.
+format output.
+See
+.Sx Man Output .
.It Fl T Ns Cm pdf
Produce PDF output.
See
@@ -259,6 +259,12 @@ The following
.Fl O
arguments are accepted:
.Bl -tag -width Ds
+.It Cm fragment
+Do not emit doctype, html, and body elements.
+The
+.Cm style
+argument shall be unused.
+This is useful when embedding manual content within existing documents.
.It Cm includes Ns = Ns Ar fmt
The string
.Ar fmt ,
@@ -305,6 +311,26 @@ will fall back to
See
.Sx ASCII Output
for font style specification and available command-line arguments.
+.Ss Man Output
+Translate input format into
+.Xr man 7
+output format.
+This is useful for distributing manual sources to legancy systems
+lacking
+.Xr mdoc 7
+formatters.
+.Pp
+If
+.Xr mdoc 7
+is passed as input, it is translated into
+.Xr man 7 ;
+if the input format is
+.Xr man 7 ,
+it is parsed and re-outputted.
+In either case, the
+.Xr roff 7
+.Sq so
+macros are processed prior to producing output.
.Ss PDF Output
PDF-1.1 output may be generated by
.Fl T Ns Cm pdf .
diff --git a/usr.bin/mandoc/mandoc.h b/usr.bin/mandoc/mandoc.h
index 473d80253f1..cef90417ad9 100644
--- a/usr.bin/mandoc/mandoc.h
+++ b/usr.bin/mandoc/mandoc.h
@@ -1,4 +1,4 @@
-/* $Id: mandoc.h,v 1.40 2011/09/18 10:25:28 schwarze Exp $ */
+/* $Id: mandoc.h,v 1.41 2011/10/09 17:59:56 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -400,30 +400,31 @@ struct man;
__BEGIN_DECLS
-void mparse_free(struct mparse *);
-void mparse_reset(struct mparse *);
-struct mparse *mparse_alloc(enum mparset,
- enum mandoclevel, mandocmsg, void *);
-enum mandoclevel mparse_readfd(struct mparse *, int, const char *);
-void mparse_result(struct mparse *, struct mdoc **, struct man **);
-const char *mparse_strerror(enum mandocerr);
-const char *mparse_strlevel(enum mandoclevel);
-
void *mandoc_calloc(size_t, size_t);
+enum mandoc_esc mandoc_escape(const char **, const char **, int *);
void *mandoc_malloc(size_t);
void *mandoc_realloc(void *, size_t);
char *mandoc_strdup(const char *);
char *mandoc_strndup(const char *, size_t);
-
-enum mandoc_esc mandoc_escape(const char **, const char **, int *);
-
struct mchars *mchars_alloc(void);
+void mchars_free(struct mchars *);
char mchars_num2char(const char *, size_t);
int mchars_num2uc(const char *, size_t);
-const char *mchars_spec2str(struct mchars *, const char *, size_t, size_t *);
-int mchars_spec2cp(struct mchars *, const char *, size_t);
-void mchars_free(struct mchars *);
-
+int mchars_spec2cp(struct mchars *,
+ const char *, size_t);
+const char *mchars_spec2str(struct mchars *,
+ const char *, size_t, size_t *);
+struct mparse *mparse_alloc(enum mparset,
+ enum mandoclevel, mandocmsg, void *);
+void mparse_free(struct mparse *);
+void mparse_keep(struct mparse *);
+enum mandoclevel mparse_readfd(struct mparse *, int, const char *);
+void mparse_reset(struct mparse *);
+void mparse_result(struct mparse *,
+ struct mdoc **, struct man **);
+const char *mparse_getkeep(const struct mparse *);
+const char *mparse_strerror(enum mandocerr);
+const char *mparse_strlevel(enum mandoclevel);
__END_DECLS
diff --git a/usr.bin/mandoc/mandocdb.8 b/usr.bin/mandoc/mandocdb.8
index 12602b648fa..1602aa06cfa 100644
--- a/usr.bin/mandoc/mandocdb.8
+++ b/usr.bin/mandoc/mandocdb.8
@@ -1,4 +1,4 @@
-.\" $Id: mandocdb.8,v 1.3 2011/09/18 10:25:28 schwarze Exp $
+.\" $Id: mandocdb.8,v 1.4 2011/10/09 17:59:56 schwarze Exp $
.\"
.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: September 18 2011 $
+.Dd $Mdocdate: October 9 2011 $
.Dt MANDOCDB 8
.Os
.Sh NAME
@@ -45,12 +45,12 @@ for fast retrieval.
The arguments are as follows:
.Bl -tag -width Ds
.It Fl d Ar dir
-Remove
+Merge (remove and re-add)
.Ar
from the databases in
.Ar dir .
.It Fl u Ar dir
-Update (remove and re-add)
+Remove
.Ar
from the databases in
.Ar dir .
diff --git a/usr.bin/mandoc/mdoc_html.c b/usr.bin/mandoc/mdoc_html.c
index c3ab375ce1b..680c1cc53c7 100644
--- a/usr.bin/mandoc/mdoc_html.c
+++ b/usr.bin/mandoc/mdoc_html.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_html.c,v 1.61 2011/09/18 15:54:48 schwarze Exp $ */
+/* $Id: mdoc_html.c,v 1.62 2011/10/09 17:59:56 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -258,17 +258,9 @@ static const char * const lists[LIST_MAX] = {
void
html_mdoc(void *arg, const struct mdoc *m)
{
- struct html *h;
- struct tag *t;
-
- h = (struct html *)arg;
-
- print_gen_decls(h);
- t = print_otag(h, TAG_HTML, 0, NULL);
- print_mdoc(mdoc_meta(m), mdoc_node(m), h);
- print_tagq(h, t);
- printf("\n");
+ print_mdoc(mdoc_meta(m), mdoc_node(m), (struct html *)arg);
+ putchar('\n');
}
@@ -356,13 +348,22 @@ a2offs(const char *p, struct roffsu *su)
static void
print_mdoc(MDOC_ARGS)
{
- struct tag *t;
+ struct tag *t, *tt;
+ struct htmlpair tag;
- t = print_otag(h, TAG_HEAD, 0, NULL);
- print_mdoc_head(m, n, h);
- print_tagq(h, t);
+ PAIR_CLASS_INIT(&tag, "mandoc");
+
+ if ( ! (HTML_FRAGMENT & h->oflags)) {
+ print_gen_decls(h);
+ t = print_otag(h, TAG_HTML, 0, NULL);
+ tt = print_otag(h, TAG_HEAD, 0, NULL);
+ print_mdoc_head(m, n, h);
+ print_tagq(h, tt);
+ print_otag(h, TAG_BODY, 0, NULL);
+ print_otag(h, TAG_DIV, 1, &tag);
+ } else
+ t = print_otag(h, TAG_DIV, 1, &tag);
- t = print_otag(h, TAG_BODY, 0, NULL);
print_mdoc_nodelist(m, n, h);
print_tagq(h, t);
}
diff --git a/usr.bin/mandoc/mdoc_man.c b/usr.bin/mandoc/mdoc_man.c
index 3844eb36dea..7ba8ed6e539 100644
--- a/usr.bin/mandoc/mdoc_man.c
+++ b/usr.bin/mandoc/mdoc_man.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_man.c,v 1.3 2011/09/30 00:13:21 schwarze Exp $ */
+/* $Id: mdoc_man.c,v 1.4 2011/10/09 17:59:56 schwarze Exp $ */
/*
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
*
@@ -18,50 +18,51 @@
#include <string.h>
#include "mandoc.h"
+#include "man.h"
#include "mdoc.h"
#include "main.h"
-static int need_space = 0;
-static int need_nl = 0;
-
#define DECL_ARGS const struct mdoc_meta *m, \
- const struct mdoc_node *n
+ const struct mdoc_node *n, \
+ struct mman *mm
-struct manact {
- int (*cond)(DECL_ARGS);
- int (*pre)(DECL_ARGS);
- void (*post)(DECL_ARGS);
- const char *prefix;
- const char *suffix;
+struct mman {
+ int need_space; /* next word needs prior ws */
+ int need_nl; /* next word needs prior nl */
};
-static void print_word(const char *);
-static void print_node(DECL_ARGS);
+struct manact {
+ int (*cond)(DECL_ARGS); /* DON'T run actions */
+ int (*pre)(DECL_ARGS); /* pre-node action */
+ void (*post)(DECL_ARGS); /* post-node action */
+ const char *prefix; /* pre-node string constant */
+ const char *suffix; /* post-node string constant */
+};
-static int cond_head(DECL_ARGS);
static int cond_body(DECL_ARGS);
-static int pre_enc(DECL_ARGS);
+static int cond_head(DECL_ARGS);
+static void post_bd(DECL_ARGS);
+static void post_dl(DECL_ARGS);
static void post_enc(DECL_ARGS);
+static void post_nm(DECL_ARGS);
static void post_percent(DECL_ARGS);
-static int pre_sect(DECL_ARGS);
+static void post_pf(DECL_ARGS);
static void post_sect(DECL_ARGS);
-
+static void post_sp(DECL_ARGS);
static int pre_ap(DECL_ARGS);
static int pre_bd(DECL_ARGS);
-static void post_bd(DECL_ARGS);
static int pre_br(DECL_ARGS);
static int pre_dl(DECL_ARGS);
-static void post_dl(DECL_ARGS);
+static int pre_enc(DECL_ARGS);
static int pre_it(DECL_ARGS);
static int pre_nm(DECL_ARGS);
-static void post_nm(DECL_ARGS);
static int pre_ns(DECL_ARGS);
-static void post_pf(DECL_ARGS);
static int pre_pp(DECL_ARGS);
static int pre_sp(DECL_ARGS);
-static void post_sp(DECL_ARGS);
+static int pre_sect(DECL_ARGS);
static int pre_xr(DECL_ARGS);
-
+static void print_word(struct mman *, const char *);
+static void print_node(DECL_ARGS);
static const struct manact manacts[MDOC_MAX + 1] = {
{ NULL, pre_ap, NULL, NULL, NULL }, /* Ap */
@@ -102,7 +103,11 @@ static const struct manact manacts[MDOC_MAX + 1] = {
{ cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
{ NULL, NULL, NULL, NULL, NULL }, /* _Ot */
{ NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* _Pa */
- { NULL, NULL, NULL, NULL, NULL }, /* _Rv */
+ { NULL, pre_enc, post_enc, "The \\fB",
+ "\\fP\nfunction returns the value 0 if successful;\n"
+ "otherwise the value -1 is returned and the global\n"
+ "variable \\fIerrno\\fP is set to indicate the error."
+ }, /* Rv */
{ NULL, NULL, NULL, NULL, NULL }, /* _St */
{ NULL, NULL, NULL, NULL, NULL }, /* _Va */
{ NULL, NULL, NULL, NULL, NULL }, /* _Vt */
@@ -191,18 +196,34 @@ static const struct manact manacts[MDOC_MAX + 1] = {
{ NULL, NULL, NULL, NULL, NULL }, /* ROOT */
};
-
static void
-print_word(const char *s)
+print_word(struct mman *mm, const char *s)
{
- if (need_nl) {
+
+ if (mm->need_nl) {
+ /*
+ * If we need a newline, print it now and start afresh.
+ */
putchar('\n');
- need_space = 0;
- need_nl = 0;
- } else if (need_space &&
- (NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]))
- putchar(' ');
- need_space = ('(' != s[0] && '[' != s[0]) || '\0' != s[1];
+ mm->need_space = 0;
+ mm->need_nl = 0;
+ } else if (mm->need_space && '\0' != s[0])
+ /*
+ * If we need a space, only print it before
+ * (1) a nonzero length word;
+ * (2) a word that is non-punctuation; and
+ * (3) if punctuation, non-terminating puncutation.
+ */
+ if (NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1])
+ putchar(' ');
+
+ /*
+ * Reassign needing space if we're not following opening
+ * punctuation.
+ */
+ mm->need_space =
+ ('(' != s[0] && '[' != s[0]) || '\0' != s[1];
+
for ( ; *s; s++) {
switch (*s) {
case (ASCII_NBRSP):
@@ -212,27 +233,42 @@ print_word(const char *s)
putchar('-');
break;
default:
- putchar(*s);
+ putchar((unsigned char)*s);
break;
}
}
}
void
+man_man(void *arg, const struct man *man)
+{
+
+ /*
+ * Dump the keep buffer.
+ * We're guaranteed by now that this exists (is non-NULL).
+ * Flush stdout afterward, just in case.
+ */
+ fputs(mparse_getkeep(man_mparse(man)), stdout);
+ fflush(stdout);
+}
+
+void
man_mdoc(void *arg, const struct mdoc *mdoc)
{
const struct mdoc_meta *m;
const struct mdoc_node *n;
+ struct mman mm;
m = mdoc_meta(mdoc);
n = mdoc_node(mdoc);
printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
- m->title, m->msec, m->date, m->os, m->vol);
- need_nl = 1;
- need_space = 0;
+ m->title, m->msec, m->date, m->os, m->vol);
- print_node(m, n);
+ memset(&mm, 0, sizeof(struct mman));
+
+ mm.need_nl = 1;
+ print_node(m, n, &mm);
putchar('\n');
}
@@ -240,61 +276,93 @@ static void
print_node(DECL_ARGS)
{
const struct mdoc_node *prev, *sub;
- const struct manact *act = NULL;
+ const struct manact *act;
int cond, do_sub;
-
+
+ /*
+ * Break the line if we were parsed subsequent the current node.
+ * This makes the page structure be more consistent.
+ */
prev = n->prev ? n->prev : n->parent;
if (prev && prev->line < n->line)
- need_nl = 1;
+ mm->need_nl = 1;
+ act = NULL;
cond = 0;
do_sub = 1;
+
if (MDOC_TEXT == n->type) {
- if (need_nl && ('.' == *n->string || '\'' == *n->string)) {
- print_word("\\&");
- need_space = 0;
+ /*
+ * Make sure that we don't happen to start with a
+ * control character at the start of a line.
+ */
+ if (mm->need_nl && ('.' == *n->string ||
+ '\'' == *n->string)) {
+ print_word(mm, "\\&");
+ mm->need_space = 0;
}
- print_word(n->string);
+ print_word(mm, n->string);
} else {
+ /*
+ * Conditionally run the pre-node action handler for a
+ * node.
+ */
act = manacts + n->tok;
- cond = NULL == act->cond || (*act->cond)(m, n);
+ cond = NULL == act->cond || (*act->cond)(m, n, mm);
if (cond && act->pre)
- do_sub = (*act->pre)(m, n);
+ do_sub = (*act->pre)(m, n, mm);
}
+ /*
+ * Conditionally run all child nodes.
+ * Note that this iterates over children instead of using
+ * recursion. This prevents unnecessary depth in the stack.
+ */
if (do_sub)
for (sub = n->child; sub; sub = sub->next)
- print_node(m, sub);
+ print_node(m, sub, mm);
+ /*
+ * Lastly, conditionally run the post-node handler.
+ */
if (cond && act->post)
- (*act->post)(m, n);
+ (*act->post)(m, n, mm);
}
static int
cond_head(DECL_ARGS)
{
+
return(MDOC_HEAD == n->type);
}
static int
cond_body(DECL_ARGS)
{
+
return(MDOC_BODY == n->type);
}
+/*
+ * Output a font encoding before a node, e.g., \fR.
+ * This obviously has no trailing space.
+ */
static int
pre_enc(DECL_ARGS)
{
- const char *prefix;
+ const char *prefix;
prefix = manacts[n->tok].prefix;
if (NULL == prefix)
return(1);
- print_word(prefix);
- need_space = 0;
+ print_word(mm, prefix);
+ mm->need_space = 0;
return(1);
}
+/*
+ * Output a font encoding subsequent a node, e.g., \fP.
+ */
static void
post_enc(DECL_ARGS)
{
@@ -303,54 +371,65 @@ post_enc(DECL_ARGS)
suffix = manacts[n->tok].suffix;
if (NULL == suffix)
return;
- need_space = 0;
- print_word(suffix);
+ mm->need_space = 0;
+ print_word(mm, suffix);
}
+/*
+ * Used in listings (percent = %A, e.g.).
+ * FIXME: this is incomplete.
+ * It doesn't print a nice ", and" for lists.
+ */
static void
post_percent(DECL_ARGS)
{
- post_enc(m, n);
+ post_enc(m, n, mm);
if (n->next)
- print_word(",");
+ print_word(mm, ",");
else {
- print_word(".");
- need_nl = 1;
+ print_word(mm, ".");
+ mm->need_nl = 1;
}
}
+/*
+ * Print before a section header.
+ */
static int
pre_sect(DECL_ARGS)
{
if (MDOC_HEAD != n->type)
return(1);
- need_nl = 1;
- print_word(manacts[n->tok].prefix);
- print_word("\"");
- need_space = 0;
+ mm->need_nl = 1;
+ print_word(mm, manacts[n->tok].prefix);
+ print_word(mm, "\"");
+ mm->need_space = 0;
return(1);
}
+/*
+ * Print subsequent a section header.
+ */
static void
post_sect(DECL_ARGS)
{
if (MDOC_HEAD != n->type)
return;
- need_space = 0;
- print_word("\"");
- need_nl = 1;
+ mm->need_space = 0;
+ print_word(mm, "\"");
+ mm->need_nl = 1;
}
static int
pre_ap(DECL_ARGS)
{
- need_space = 0;
- print_word("'");
- need_space = 0;
+ mm->need_space = 0;
+ print_word(mm, "'");
+ mm->need_space = 0;
return(0);
}
@@ -360,10 +439,10 @@ pre_bd(DECL_ARGS)
if (DISP_unfilled == n->norm->Bd.type ||
DISP_literal == n->norm->Bd.type) {
- need_nl = 1;
- print_word(".nf");
+ mm->need_nl = 1;
+ print_word(mm, ".nf");
}
- need_nl = 1;
+ mm->need_nl = 1;
return(1);
}
@@ -373,19 +452,19 @@ post_bd(DECL_ARGS)
if (DISP_unfilled == n->norm->Bd.type ||
DISP_literal == n->norm->Bd.type) {
- need_nl = 1;
- print_word(".fi");
+ mm->need_nl = 1;
+ print_word(mm, ".fi");
}
- need_nl = 1;
+ mm->need_nl = 1;
}
static int
pre_br(DECL_ARGS)
{
- need_nl = 1;
- print_word(".br");
- need_nl = 1;
+ mm->need_nl = 1;
+ print_word(mm, ".br");
+ mm->need_nl = 1;
return(0);
}
@@ -393,9 +472,9 @@ static int
pre_dl(DECL_ARGS)
{
- need_nl = 1;
- print_word(".RS 6n");
- need_nl = 1;
+ mm->need_nl = 1;
+ print_word(mm, ".RS 6n");
+ mm->need_nl = 1;
return(1);
}
@@ -403,9 +482,9 @@ static void
post_dl(DECL_ARGS)
{
- need_nl = 1;
- print_word(".RE");
- need_nl = 1;
+ mm->need_nl = 1;
+ print_word(mm, ".RE");
+ mm->need_nl = 1;
}
static int
@@ -414,21 +493,21 @@ pre_it(DECL_ARGS)
const struct mdoc_node *bln;
if (MDOC_HEAD == n->type) {
- need_nl = 1;
- print_word(".TP");
+ mm->need_nl = 1;
+ print_word(mm, ".TP");
bln = n->parent->parent->prev;
switch (bln->norm->Bl.type) {
case (LIST_bullet):
- print_word("4n");
- need_nl = 1;
- print_word("\\fBo\\fP");
+ print_word(mm, "4n");
+ mm->need_nl = 1;
+ print_word(mm, "\\fBo\\fP");
break;
default:
if (bln->norm->Bl.width)
- print_word(bln->norm->Bl.width);
+ print_word(mm, bln->norm->Bl.width);
break;
}
- need_nl = 1;
+ mm->need_nl = 1;
}
return(1);
}
@@ -439,10 +518,10 @@ pre_nm(DECL_ARGS)
if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
return(1);
- print_word("\\fB");
- need_space = 0;
+ print_word(mm, "\\fB");
+ mm->need_space = 0;
if (NULL == n->child)
- print_word(m->name);
+ print_word(mm, m->name);
return(1);
}
@@ -452,15 +531,15 @@ post_nm(DECL_ARGS)
if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
return;
- need_space = 0;
- print_word("\\fP");
+ mm->need_space = 0;
+ print_word(mm, "\\fP");
}
static int
pre_ns(DECL_ARGS)
{
- need_space = 0;
+ mm->need_space = 0;
return(0);
}
@@ -468,19 +547,19 @@ static void
post_pf(DECL_ARGS)
{
- need_space = 0;
+ mm->need_space = 0;
}
static int
pre_pp(DECL_ARGS)
{
- need_nl = 1;
+ mm->need_nl = 1;
if (MDOC_It == n->parent->tok)
- print_word(".sp");
+ print_word(mm, ".sp");
else
- print_word(".PP");
- need_nl = 1;
+ print_word(mm, ".PP");
+ mm->need_nl = 1;
return(1);
}
@@ -488,8 +567,8 @@ static int
pre_sp(DECL_ARGS)
{
- need_nl = 1;
- print_word(".sp");
+ mm->need_nl = 1;
+ print_word(mm, ".sp");
return(1);
}
@@ -497,7 +576,7 @@ static void
post_sp(DECL_ARGS)
{
- need_nl = 1;
+ mm->need_nl = 1;
}
static int
@@ -507,13 +586,13 @@ pre_xr(DECL_ARGS)
n = n->child;
if (NULL == n)
return(0);
- print_node(m, n);
+ print_node(m, n, mm);
n = n->next;
if (NULL == n)
return(0);
- need_space = 0;
- print_word("(");
- print_node(m, n);
- print_word(")");
+ mm->need_space = 0;
+ print_word(mm, "(");
+ print_node(m, n, mm);
+ print_word(mm, ")");
return(0);
}
diff --git a/usr.bin/mandoc/read.c b/usr.bin/mandoc/read.c
index 1f31b7b27bb..aa31338153d 100644
--- a/usr.bin/mandoc/read.c
+++ b/usr.bin/mandoc/read.c
@@ -1,4 +1,4 @@
-/* $Id: read.c,v 1.3 2011/09/18 10:25:28 schwarze Exp $ */
+/* $Id: read.c,v 1.4 2011/10/09 17:59:56 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -53,6 +53,7 @@ struct mparse {
mandocmsg mmsg; /* warning/error message handler */
void *arg; /* argument to mmsg */
const char *file;
+ struct buf *secondary;
};
static void resize_buf(struct buf *, size_t);
@@ -401,6 +402,27 @@ mparse_buf_r(struct mparse *curp, struct buf blk, int start)
of = 0;
+ /*
+ * Maintain a lookaside buffer of all parsed lines. We
+ * only do this if mparse_keep() has been invoked (the
+ * buffer may be accessed with mparse_getkeep()).
+ */
+
+ if (curp->secondary) {
+ curp->secondary->buf =
+ mandoc_realloc
+ (curp->secondary->buf,
+ curp->secondary->sz + pos + 2);
+ memcpy(curp->secondary->buf +
+ curp->secondary->sz,
+ ln.buf, pos);
+ curp->secondary->sz += pos;
+ curp->secondary->buf
+ [curp->secondary->sz] = '\n';
+ curp->secondary->sz++;
+ curp->secondary->buf
+ [curp->secondary->sz] = '\0';
+ }
rerun:
rr = roff_parseln
(curp->roff, curp->line,
@@ -427,6 +449,13 @@ rerun:
assert(MANDOCLEVEL_FATAL <= curp->file_status);
break;
case (ROFF_SO):
+ /*
+ * We remove `so' clauses from our lookaside
+ * buffer because we're going to descend into
+ * the file recursively.
+ */
+ if (curp->secondary)
+ curp->secondary->sz -= pos + 1;
mparse_readfd_r(curp, -1, ln.buf + of, 1);
if (MANDOCLEVEL_FATAL <= curp->file_status)
break;
@@ -690,6 +719,8 @@ mparse_reset(struct mparse *curp)
mdoc_reset(curp->mdoc);
if (curp->man)
man_reset(curp->man);
+ if (curp->secondary)
+ curp->secondary->sz = 0;
curp->file_status = MANDOCLEVEL_OK;
curp->mdoc = NULL;
@@ -706,7 +737,10 @@ mparse_free(struct mparse *curp)
man_free(curp->pman);
if (curp->roff)
roff_free(curp->roff);
+ if (curp->secondary)
+ free(curp->secondary->buf);
+ free(curp->secondary);
free(curp);
}
@@ -766,3 +800,19 @@ mparse_strlevel(enum mandoclevel lvl)
{
return(mandoclevels[lvl]);
}
+
+void
+mparse_keep(struct mparse *p)
+{
+
+ assert(NULL == p->secondary);
+ p->secondary = mandoc_calloc(1, sizeof(struct buf));
+}
+
+const char *
+mparse_getkeep(const struct mparse *p)
+{
+
+ assert(p->secondary);
+ return(p->secondary->sz ? p->secondary->buf : NULL);
+}