diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2010-06-06 18:08:42 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2010-06-06 18:08:42 +0000 |
commit | e63e697bedbb9649d9bb7b924b7b17fe2f675c6c (patch) | |
tree | e8acbe3cfe405322142abee52cb4e5b105fe1014 /usr.bin | |
parent | 543a8dc3357c78204d94ced0db8695ea9bf8dfd7 (diff) |
Merge bsd.lv release 1.10.0,
which is mostly the post-hackathon release,
bringing in the OpenBSD changes to bsd.lv,
but which also has a few additional minor fixes:
* .Lb is an in-line macro, not in_line_eoln
* .Bt, .Ud now warn when discarding arguments
* allow bad -man dates to flow verbatim into the front-ends
- so far all reported by Ulrich Spoerlein
* .Ar, .Fl and .Li starting with closing punctuation emit an empty element
* empty .Li macros print nothing, but may cause spacing
* proper EOS handling for .Bt, .Ex, .Rv, and .Ud.
* cleanup: collapse posts_xr into posts_wtext (which is the same)
* efficiency: very simple table lookup for roff.c
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/mandoc/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/mandoc/man.7 | 9 | ||||
-rw-r--r-- | usr.bin/mandoc/man.c | 4 | ||||
-rw-r--r-- | usr.bin/mandoc/man.h | 3 | ||||
-rw-r--r-- | usr.bin/mandoc/man_action.c | 17 | ||||
-rw-r--r-- | usr.bin/mandoc/man_html.c | 7 | ||||
-rw-r--r-- | usr.bin/mandoc/man_term.c | 7 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc.7 | 32 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_action.c | 26 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_macro.c | 47 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_term.c | 6 | ||||
-rw-r--r-- | usr.bin/mandoc/mdoc_validate.c | 26 | ||||
-rw-r--r-- | usr.bin/mandoc/roff.c | 94 |
13 files changed, 217 insertions, 65 deletions
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile index f4bfff4f0dc..6bf027e8d37 100644 --- a/usr.bin/mandoc/Makefile +++ b/usr.bin/mandoc/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.37 2010/05/16 00:54:03 schwarze Exp $ +# $OpenBSD: Makefile,v 1.38 2010/06/06 18:08:41 schwarze Exp $ .include <bsd.own.mk> -VERSION=1.9.25 +VERSION=1.10.0 CFLAGS+=-DVERSION=\"${VERSION}\" CFLAGS+=-W -Wall -Wstrict-prototypes diff --git a/usr.bin/mandoc/man.7 b/usr.bin/mandoc/man.7 index e76b6637c88..f032b171d85 100644 --- a/usr.bin/mandoc/man.7 +++ b/usr.bin/mandoc/man.7 @@ -1,4 +1,4 @@ -.\" $Id: man.7,v 1.26 2010/05/26 02:55:16 schwarze Exp $ +.\" $Id: man.7,v 1.27 2010/06/06 18:08:41 schwarze Exp $ .\" .\" Copyright (c) 2009 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: May 26 2010 $ +.Dd $Mdocdate: June 6 2010 $ .Dt MAN 7 .Os .Sh NAME @@ -809,8 +809,9 @@ arguments must be provided. The .Cm date argument should be formatted as described in -.Sx Dates : -if it does not conform, the current date is used instead. +.Sx Dates , +but will be printed verbatim if it is not. +If the date is not specified, the current date is used. The .Cm source string specifies the organisation providing the utility. diff --git a/usr.bin/mandoc/man.c b/usr.bin/mandoc/man.c index cca4344147b..312fa3f5831 100644 --- a/usr.bin/mandoc/man.c +++ b/usr.bin/mandoc/man.c @@ -1,4 +1,4 @@ -/* $Id: man.c,v 1.33 2010/05/23 22:45:00 schwarze Exp $ */ +/* $Id: man.c,v 1.34 2010/06/06 18:08:41 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> * @@ -142,6 +142,8 @@ man_free1(struct man *man) free(man->meta.title); if (man->meta.source) free(man->meta.source); + if (man->meta.rawdate) + free(man->meta.rawdate); if (man->meta.vol) free(man->meta.vol); if (man->meta.msec) diff --git a/usr.bin/mandoc/man.h b/usr.bin/mandoc/man.h index 47ca389fdfe..1c191e39ceb 100644 --- a/usr.bin/mandoc/man.h +++ b/usr.bin/mandoc/man.h @@ -1,4 +1,4 @@ -/* $Id: man.h,v 1.22 2010/05/23 22:45:00 schwarze Exp $ */ +/* $Id: man.h,v 1.23 2010/06/06 18:08:41 schwarze Exp $ */ /* * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se> * @@ -71,6 +71,7 @@ enum man_type { struct man_meta { char *msec; time_t date; + char *rawdate; char *vol; char *title; char *source; diff --git a/usr.bin/mandoc/man_action.c b/usr.bin/mandoc/man_action.c index 7b72907e6c5..8550fafa97e 100644 --- a/usr.bin/mandoc/man_action.c +++ b/usr.bin/mandoc/man_action.c @@ -1,4 +1,4 @@ -/* $Id: man_action.c,v 1.22 2010/05/24 13:42:58 schwarze Exp $ */ +/* $Id: man_action.c,v 1.23 2010/06/06 18:08:41 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -133,8 +133,10 @@ post_TH(struct man *m) free(m->meta.source); if (m->meta.msec) free(m->meta.msec); + if (m->meta.rawdate) + free(m->meta.rawdate); - m->meta.title = m->meta.vol = + m->meta.title = m->meta.vol = m->meta.rawdate = m->meta.msec = m->meta.source = NULL; m->meta.date = 0; @@ -152,14 +154,21 @@ post_TH(struct man *m) /* TITLE MSEC ->DATE<- SOURCE VOL */ + /* + * Try to parse the date. If this works, stash the epoch (this + * is optimal because we can reformat it in the canonical form). + * If it doesn't parse, isn't specified at all, or is an empty + * string, then use the current date. + */ + n = n->next; - if (n) { + if (n && n->string && *n->string) { m->meta.date = mandoc_a2time (MTIME_ISO_8601, n->string); if (0 == m->meta.date) { if ( ! man_nmsg(m, n, MANDOCERR_BADDATE)) return(0); - m->meta.date = time(NULL); + m->meta.rawdate = mandoc_strdup(n->string); } } else m->meta.date = time(NULL); diff --git a/usr.bin/mandoc/man_html.c b/usr.bin/mandoc/man_html.c index 97dbbe95036..93553434905 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.14 2010/05/23 22:45:00 schwarze Exp $ */ +/* $Id: man_html.c,v 1.15 2010/06/06 18:08:41 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> * @@ -304,7 +304,10 @@ man_root_post(MAN_ARGS) struct tag *t, *tt; char b[DATESIZ]; - time2a(m->date, b, DATESIZ); + if (m->rawdate) + strlcpy(b, m->rawdate, DATESIZ); + else + time2a(m->date, b, DATESIZ); PAIR_CLASS_INIT(&tag[0], "footer"); bufcat_style(h, "width", "100%"); diff --git a/usr.bin/mandoc/man_term.c b/usr.bin/mandoc/man_term.c index 8fb34d5849e..89faae3db5c 100644 --- a/usr.bin/mandoc/man_term.c +++ b/usr.bin/mandoc/man_term.c @@ -1,4 +1,4 @@ -/* $Id: man_term.c,v 1.39 2010/06/05 19:09:55 schwarze Exp $ */ +/* $Id: man_term.c,v 1.40 2010/06/06 18:08:41 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> * @@ -861,7 +861,10 @@ print_man_foot(struct termp *p, const struct man_meta *meta) term_fontrepl(p, TERMFONT_NONE); - time2a(meta->date, buf, DATESIZ); + if (meta->rawdate) + strlcpy(buf, meta->rawdate, DATESIZ); + else + time2a(meta->date, buf, DATESIZ); term_vspace(p); term_vspace(p); diff --git a/usr.bin/mandoc/mdoc.7 b/usr.bin/mandoc/mdoc.7 index 9e4c5fc5ee6..32b7ab70401 100644 --- a/usr.bin/mandoc/mdoc.7 +++ b/usr.bin/mandoc/mdoc.7 @@ -1,4 +1,4 @@ -.\" $Id: mdoc.7,v 1.32 2010/05/16 02:06:50 schwarze Exp $ +.\" $Id: mdoc.7,v 1.33 2010/06/06 18:08:41 schwarze Exp $ .\" .\" Copyright (c) 2009 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: May 16 2010 $ +.Dd $Mdocdate: June 6 2010 $ .Dt MDOC 7 .Os .Sh NAME @@ -731,7 +731,9 @@ Note that the macro is a .Sx Block partial-implicit only when invoked as the first macro -in a SYNOPSIS section line, else it is +in a +.Em SYNOPSIS +section line, else it is .Sx In-line . .Ss In-line Closed by @@ -1644,6 +1646,28 @@ and .Ss \&In .Ss \&It .Ss \&Lb +Specify a library. +The calling syntax is as follows: +.Pp +.D1 \. Ns Sx \&Lb Cm library +.Pp +The +.Cm library +parameter may be a system library, such as +.Cm libz +or +.Cm libpam , +in which case a small library description is printed next to the linker +invocation; or a custom library, in which case the library name is +printed in quotes. +This is most commonly used in the +.Em SYNOPSIS +section as described in +.Sx MANUAL STRUCTURE . +.Pp +Examples: +.D1 \&.Lb libz +.D1 \&.Lb mdoc .Ss \&Li .Ss \&Lk Format a hyperlink. @@ -1796,6 +1820,8 @@ line. .Ss \&Sy .Ss \&Tn .Ss \&Ud +Prints out +.Dq currently under development. .Ss \&Ux Format the UNIX name. Accepts no argument. diff --git a/usr.bin/mandoc/mdoc_action.c b/usr.bin/mandoc/mdoc_action.c index 764232d9f60..833ca34c497 100644 --- a/usr.bin/mandoc/mdoc_action.c +++ b/usr.bin/mandoc/mdoc_action.c @@ -1,4 +1,4 @@ -/* $Id: mdoc_action.c,v 1.38 2010/05/24 02:24:05 schwarze Exp $ */ +/* $Id: mdoc_action.c,v 1.39 2010/06/06 18:08:41 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> * @@ -53,6 +53,7 @@ static int post_dd(POST_ARGS); static int post_display(POST_ARGS); static int post_dt(POST_ARGS); static int post_lb(POST_ARGS); +static int post_li(POST_ARGS); static int post_nm(POST_ARGS); static int post_os(POST_ARGS); static int post_pa(POST_ARGS); @@ -98,7 +99,7 @@ static const struct actions mdoc_actions[MDOC_MAX] = { { NULL, NULL }, /* Ft */ { NULL, NULL }, /* Ic */ { NULL, NULL }, /* In */ - { NULL, NULL }, /* Li */ + { NULL, post_li }, /* Li */ { NULL, NULL }, /* Nd */ { NULL, post_nm }, /* Nm */ { NULL, NULL }, /* Op */ @@ -833,6 +834,27 @@ post_pa(POST_ARGS) /* + * Empty `Li' macros get an empty string to make front-ends add an extra + * space. + */ +static int +post_li(POST_ARGS) +{ + struct mdoc_node *np; + + if (n->child) + return(1); + + np = n; + m->next = MDOC_NEXT_CHILD; + if ( ! mdoc_word_alloc(m, n->line, n->pos, "")) + return(0); + m->last = np; + return(1); +} + + +/* * The `Ar' macro defaults to two strings "file ..." if no value is * provided as an argument. */ diff --git a/usr.bin/mandoc/mdoc_macro.c b/usr.bin/mandoc/mdoc_macro.c index 099888c6564..230dbd2c8ef 100644 --- a/usr.bin/mandoc/mdoc_macro.c +++ b/usr.bin/mandoc/mdoc_macro.c @@ -1,4 +1,4 @@ -/* $Id: mdoc_macro.c,v 1.44 2010/05/23 22:45:00 schwarze Exp $ */ +/* $Id: mdoc_macro.c,v 1.45 2010/06/06 18:08:41 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> * @@ -167,7 +167,7 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { { in_line_eoln, 0 }, /* Hf */ { obsolete, 0 }, /* Fr */ { in_line_eoln, 0 }, /* Ud */ - { in_line_eoln, 0 }, /* Lb */ + { in_line, 0 }, /* Lb */ { in_line_eoln, 0 }, /* Lp */ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */ @@ -747,7 +747,7 @@ blk_exp_close(MACRO_PROT_ARGS) static int in_line(MACRO_PROT_ARGS) { - int la, lastpunct, cnt, nc, nl; + int la, scope, cnt, nc, nl; enum margverr av; enum mdoct ntok; enum margserr ac; @@ -798,7 +798,7 @@ in_line(MACRO_PROT_ARGS) return(0); } - for (cnt = 0, lastpunct = 1;; ) { + for (cnt = scope = 0;; ) { la = *pos; ac = mdoc_args(m, line, pos, buf, tok, &p); @@ -819,7 +819,7 @@ in_line(MACRO_PROT_ARGS) */ if (MDOC_MAX != ntok) { - if (0 == lastpunct && ! rew_elem(m, tok)) + if (scope && ! rew_elem(m, tok)) return(0); if (nc && 0 == cnt) { if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) @@ -846,14 +846,35 @@ in_line(MACRO_PROT_ARGS) d = ARGS_QWORD == ac ? DELIM_NONE : mdoc_isdelim(p); - if (ARGS_QWORD != ac && DELIM_NONE != d) { - if (0 == lastpunct && ! rew_elem(m, tok)) + if (DELIM_NONE != d) { + /* + * If we encounter closing punctuation, no word + * has been omitted, no scope is open, and we're + * allowed to have an empty element, then start + * a new scope. `Ar', `Fl', and `Li', only do + * this once per invocation. There may be more + * of these (all of them?). + */ + if (0 == cnt && (nc || MDOC_Li == tok) && + DELIM_CLOSE == d && ! scope) { + if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) + return(0); + if (MDOC_Ar == tok || MDOC_Li == tok || + MDOC_Fl == tok) + cnt++; + scope = 1; + } + /* + * Close out our scope, if one is open, before + * any punctuation. + */ + if (scope && ! rew_elem(m, tok)) return(0); - lastpunct = 1; - } else if (lastpunct) { + scope = 0; + } else if ( ! scope) { if ( ! mdoc_elem_alloc(m, line, ppos, tok, arg)) return(0); - lastpunct = 0; + scope = 1; } if (DELIM_NONE == d) @@ -866,14 +887,14 @@ in_line(MACRO_PROT_ARGS) * word so that the `-' can be added to each one without * having to parse out spaces. */ - if (0 == lastpunct && MDOC_Fl == tok) { + if (scope && MDOC_Fl == tok) { if ( ! rew_elem(m, tok)) return(0); - lastpunct = 1; + scope = 0; } } - if (0 == lastpunct && ! rew_elem(m, tok)) + if (scope && ! rew_elem(m, tok)) return(0); /* diff --git a/usr.bin/mandoc/mdoc_term.c b/usr.bin/mandoc/mdoc_term.c index c07ff140199..43d2a3d3593 100644 --- a/usr.bin/mandoc/mdoc_term.c +++ b/usr.bin/mandoc/mdoc_term.c @@ -1,4 +1,4 @@ -/* $Id: mdoc_term.c,v 1.83 2010/05/24 00:37:01 schwarze Exp $ */ +/* $Id: mdoc_term.c,v 1.84 2010/06/06 18:08:41 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se> * @@ -1188,6 +1188,7 @@ termp_rv_pre(DECL_ARGS) term_fontpop(p); term_word(p, "is set to indicate the error."); + p->flags |= TERMP_SENTENCE; return(0); } @@ -1220,6 +1221,7 @@ termp_ex_pre(DECL_ARGS) term_word(p, "utility exits"); term_word(p, "0 on success, and >0 if an error occurs."); + p->flags |= TERMP_SENTENCE; return(0); } @@ -1421,6 +1423,7 @@ termp_bt_pre(DECL_ARGS) { term_word(p, "is currently in beta test."); + p->flags |= TERMP_SENTENCE; return(0); } @@ -1441,6 +1444,7 @@ termp_ud_pre(DECL_ARGS) { term_word(p, "currently under development."); + p->flags |= TERMP_SENTENCE; return(0); } diff --git a/usr.bin/mandoc/mdoc_validate.c b/usr.bin/mandoc/mdoc_validate.c index 7ac6c642a67..459da6d17cf 100644 --- a/usr.bin/mandoc/mdoc_validate.c +++ b/usr.bin/mandoc/mdoc_validate.c @@ -1,4 +1,4 @@ -/* $Id: mdoc_validate.c,v 1.58 2010/05/26 02:39:58 schwarze Exp $ */ +/* $Id: mdoc_validate.c,v 1.59 2010/06/06 18:08:41 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -88,6 +88,7 @@ static int post_sh(POST_ARGS); static int post_sh_body(POST_ARGS); static int post_sh_head(POST_ARGS); static int post_st(POST_ARGS); +static int post_eoln(POST_ARGS); static int post_vt(POST_ARGS); static int pre_an(PRE_ARGS); static int pre_bd(PRE_ARGS); @@ -107,6 +108,7 @@ static v_post posts_bd[] = { hwarn_eq0, bwarn_ge1, NULL }; static v_post posts_bf[] = { hwarn_le1, post_bf, NULL }; static v_post posts_bl[] = { bwarn_ge1, post_bl, NULL }; static v_post posts_bool[] = { eerr_eq1, ebool, NULL }; +static v_post posts_eoln[] = { post_eoln, NULL }; static v_post posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL }; static v_post posts_it[] = { post_it, NULL }; static v_post posts_lb[] = { eerr_eq1, post_lb, NULL }; @@ -123,7 +125,6 @@ static v_post posts_text1[] = { eerr_eq1, NULL }; static v_post posts_vt[] = { post_vt, NULL }; static v_post posts_wline[] = { bwarn_ge1, herr_eq0, NULL }; static v_post posts_wtext[] = { ewarn_ge1, NULL }; -static v_post posts_xr[] = { ewarn_ge1, NULL }; static v_pre pres_an[] = { pre_an, NULL }; static v_pre pres_bd[] = { pre_display, pre_bd, NULL }; static v_pre pres_bl[] = { pre_bl, NULL }; @@ -134,7 +135,6 @@ static v_pre pres_er[] = { NULL, NULL }; static v_pre pres_ex[] = { NULL, NULL }; static v_pre pres_fd[] = { NULL, NULL }; static v_pre pres_it[] = { pre_it, NULL }; -static v_pre pres_lb[] = { NULL, NULL }; static v_pre pres_os[] = { pre_os, NULL }; static v_pre pres_rv[] = { pre_rv, NULL }; static v_pre pres_sh[] = { pre_sh, NULL }; @@ -181,7 +181,7 @@ const struct valids mdoc_valids[MDOC_MAX] = { { NULL, posts_st }, /* St */ { NULL, NULL }, /* Va */ { NULL, posts_vt }, /* Vt */ - { NULL, posts_xr }, /* Xr */ + { NULL, posts_wtext }, /* Xr */ { NULL, posts_text }, /* %A */ { NULL, posts_text }, /* %B */ /* FIXME: can be used outside Rs/Re. */ { NULL, posts_text }, /* %D */ /* FIXME: check date with mandoc_a2time(). */ @@ -243,11 +243,11 @@ const struct valids mdoc_valids[MDOC_MAX] = { { NULL, NULL }, /* Oc */ { NULL, posts_wline }, /* Bk */ { NULL, NULL }, /* Ek */ - { NULL, posts_notext }, /* Bt */ + { NULL, posts_eoln }, /* Bt */ { NULL, NULL }, /* Hf */ { NULL, NULL }, /* Fr */ - { NULL, posts_notext }, /* Ud */ - { pres_lb, posts_lb }, /* Lb */ + { NULL, posts_eoln }, /* Ud */ + { NULL, posts_lb }, /* Lb */ { NULL, posts_notext }, /* Lp */ { NULL, posts_text }, /* Lk */ { NULL, posts_text }, /* Mt */ @@ -388,7 +388,7 @@ CHECK_CHILD_DEFN(err, lt, <) /* err_child_lt() */ CHECK_CHILD_DEFN(warn, lt, <) /* warn_child_lt() */ CHECK_BODY_DEFN(ge1, warn, warn_child_gt, 0) /* bwarn_ge1() */ CHECK_BODY_DEFN(ge1, err, err_child_gt, 0) /* berr_ge1() */ -CHECK_ELEM_DEFN(ge1, warn, warn_child_gt, 0) /* ewarn_gt1() */ +CHECK_ELEM_DEFN(ge1, warn, warn_child_gt, 0) /* ewarn_ge1() */ CHECK_ELEM_DEFN(eq1, err, err_child_eq, 1) /* eerr_eq1() */ CHECK_ELEM_DEFN(le1, err, err_child_lt, 2) /* eerr_le1() */ CHECK_ELEM_DEFN(eq0, err, err_child_eq, 0) /* eerr_eq0() */ @@ -826,6 +826,16 @@ post_lb(POST_ARGS) static int +post_eoln(POST_ARGS) +{ + + if (NULL == mdoc->last->child) + return(1); + return(mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_ARGSLOST)); +} + + +static int post_vt(POST_ARGS) { const struct mdoc_node *n; diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c index e81112eef7d..62f17651a63 100644 --- a/usr.bin/mandoc/roff.c +++ b/usr.bin/mandoc/roff.c @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.2 2010/05/20 00:58:02 schwarze Exp $ */ +/* $Id: roff.c,v 1.3 2010/06/06 18:08:41 schwarze Exp $ */ /* * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -19,6 +19,7 @@ #endif #include <assert.h> +#include <ctype.h> #include <stdlib.h> #include <string.h> #include <stdio.h> @@ -91,6 +92,7 @@ struct roffmac { roffproc sub; /* process as child of macro */ int flags; #define ROFFMAC_STRUCT (1 << 0) /* always interpret */ + struct roffmac *next; }; static enum rofferr roff_block(ROFF_ARGS); @@ -103,32 +105,65 @@ static enum rofferr roff_cond_text(ROFF_ARGS); static enum rofferr roff_cond_sub(ROFF_ARGS); static enum rofferr roff_line(ROFF_ARGS); -const struct roffmac roffs[ROFF_MAX] = { - { "am", roff_block, roff_block_text, roff_block_sub, 0 }, - { "ami", roff_block, roff_block_text, roff_block_sub, 0 }, - { "am1", roff_block, roff_block_text, roff_block_sub, 0 }, - { "de", roff_block, roff_block_text, roff_block_sub, 0 }, - { "dei", roff_block, roff_block_text, roff_block_sub, 0 }, - { "de1", roff_block, roff_block_text, roff_block_sub, 0 }, - { "ds", roff_line, NULL, NULL, 0 }, - { "el", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT }, - { "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT }, - { "if", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT }, - { "ig", roff_block, roff_block_text, roff_block_sub, 0 }, - { "rm", roff_line, NULL, NULL, 0 }, - { "tr", roff_line, NULL, NULL, 0 }, - { ".", roff_cblock, NULL, NULL, 0 }, - { "\\}", roff_ccond, NULL, NULL, 0 }, +/* See roff_hash_find() */ + +#define ASCII_HI 126 +#define ASCII_LO 33 +#define HASHWIDTH (ASCII_HI - ASCII_LO + 1) + +static struct roffmac *hash[HASHWIDTH]; + +static struct roffmac roffs[ROFF_MAX] = { + { "am", roff_block, roff_block_text, roff_block_sub, 0, NULL }, + { "ami", roff_block, roff_block_text, roff_block_sub, 0, NULL }, + { "am1", roff_block, roff_block_text, roff_block_sub, 0, NULL }, + { "de", roff_block, roff_block_text, roff_block_sub, 0, NULL }, + { "dei", roff_block, roff_block_text, roff_block_sub, 0, NULL }, + { "de1", roff_block, roff_block_text, roff_block_sub, 0, NULL }, + { "ds", roff_line, NULL, NULL, 0, NULL }, + { "el", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL }, + { "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL }, + { "if", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL }, + { "ig", roff_block, roff_block_text, roff_block_sub, 0, NULL }, + { "rm", roff_line, NULL, NULL, 0, NULL }, + { "tr", roff_line, NULL, NULL, 0, NULL }, + { ".", roff_cblock, NULL, NULL, 0, NULL }, + { "\\}", roff_ccond, NULL, NULL, 0, NULL }, }; static void roff_free1(struct roff *); static enum rofft roff_hash_find(const char *); +static void roff_hash_init(void); static void roffnode_cleanscope(struct roff *); static int roffnode_push(struct roff *, enum rofft, int, int); static void roffnode_pop(struct roff *); static enum rofft roff_parse(const char *, int *); +/* See roff_hash_find() */ +#define ROFF_HASH(p) (p[0] - ASCII_LO) + +static void +roff_hash_init(void) +{ + struct roffmac *n; + int buc, i; + + for (i = 0; i < (int)ROFF_MAX; i++) { + assert(roffs[i].name[0] >= ASCII_LO); + assert(roffs[i].name[0] <= ASCII_HI); + + buc = ROFF_HASH(roffs[i].name); + + if (NULL != (n = hash[buc])) { + for ( ; n->next; n = n->next) + /* Do nothing. */ ; + n->next = &roffs[i]; + } else + hash[buc] = &roffs[i]; + } +} + /* * Look up a roff token by its name. Returns ROFF_MAX if no macro by @@ -137,13 +172,26 @@ static enum rofft roff_parse(const char *, int *); static enum rofft roff_hash_find(const char *p) { - int i; + int buc; + struct roffmac *n; - /* FIXME: make this be fast and efficient. */ + /* + * libroff has an extremely simple hashtable, for the time + * being, which simply keys on the first character, which must + * be printable, then walks a chain. It works well enough until + * optimised. + */ - for (i = 0; i < (int)ROFF_MAX; i++) - if (0 == strcmp(roffs[i].name, p)) - return((enum rofft)i); + if (p[0] < ASCII_LO || p[0] > ASCII_HI) + return(ROFF_MAX); + + buc = ROFF_HASH(p); + + if (NULL == (n = hash[buc])) + return(ROFF_MAX); + for ( ; n; n = n->next) + if (0 == strcmp(n->name, p)) + return((enum rofft)(n - roffs)); return(ROFF_MAX); } @@ -236,6 +284,8 @@ roff_alloc(const mandocmsg msg, void *data) r->msg = msg; r->data = data; r->rstackpos = -1; + + roff_hash_init(); return(r); } |