summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2010-06-06 18:08:42 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2010-06-06 18:08:42 +0000
commite63e697bedbb9649d9bb7b924b7b17fe2f675c6c (patch)
treee8acbe3cfe405322142abee52cb4e5b105fe1014 /usr.bin
parent543a8dc3357c78204d94ced0db8695ea9bf8dfd7 (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/Makefile4
-rw-r--r--usr.bin/mandoc/man.79
-rw-r--r--usr.bin/mandoc/man.c4
-rw-r--r--usr.bin/mandoc/man.h3
-rw-r--r--usr.bin/mandoc/man_action.c17
-rw-r--r--usr.bin/mandoc/man_html.c7
-rw-r--r--usr.bin/mandoc/man_term.c7
-rw-r--r--usr.bin/mandoc/mdoc.732
-rw-r--r--usr.bin/mandoc/mdoc_action.c26
-rw-r--r--usr.bin/mandoc/mdoc_macro.c47
-rw-r--r--usr.bin/mandoc/mdoc_term.c6
-rw-r--r--usr.bin/mandoc/mdoc_validate.c26
-rw-r--r--usr.bin/mandoc/roff.c94
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);
}