diff options
-rw-r--r-- | usr.bin/mandoc/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/mandoc/apropos.1 | 7 | ||||
-rw-r--r-- | usr.bin/mandoc/apropos.c | 297 | ||||
-rw-r--r-- | usr.bin/mandoc/chars.in | 14 | ||||
-rw-r--r-- | usr.bin/mandoc/html.c | 10 | ||||
-rw-r--r-- | usr.bin/mandoc/html.h | 10 | ||||
-rw-r--r-- | usr.bin/mandoc/main.c | 9 | ||||
-rw-r--r-- | usr.bin/mandoc/main.h | 3 | ||||
-rw-r--r-- | usr.bin/mandoc/man.c | 10 | ||||
-rw-r--r-- | usr.bin/mandoc/man.h | 3 | ||||
-rw-r--r-- | usr.bin/mandoc/man_html.c | 35 | ||||
-rw-r--r-- | usr.bin/mandoc/mandoc.1 | 38 | ||||
-rw-r--r-- | usr.bin/mandoc/mandoc.h | 35 | ||||
-rw-r--r-- | usr.bin/mandoc/mandocdb.8 | 8 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_html.c | 33 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_man.c | 297 | ||||
-rw-r--r-- | usr.bin/mandoc/read.c | 52 |
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(®, q, rflags)) { - error("%s: Bad pattern\n", q); - return; + if (0 != regcomp(®, q, ch)) { + fprintf(stderr, "%s: Bad pattern\n", q); + return(0); } regp = ® @@ -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); +} |