summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2011-09-18 15:54:49 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2011-09-18 15:54:49 +0000
commit0337c5ac54faf91532e88026ce56435641d4f390 (patch)
treea7b9b2d7dc8c18b343e6a8fa8a5bf30f50056946
parent7ef814e80d0c9c0a54668956096f0618bbf932e9 (diff)
sync to version 1.11.7 from kristaps@
main new feature: support the roff(7) .tr request plus various bugfixes and some refactoring regressions are so minor that it's better to get this in and fix them in the tree
-rw-r--r--share/man/man7/mdoc.718
-rw-r--r--share/man/man7/roff.721
-rw-r--r--usr.bin/mandoc/Makefile4
-rw-r--r--usr.bin/mandoc/eqn.c3
-rw-r--r--usr.bin/mandoc/libmandoc.h4
-rw-r--r--usr.bin/mandoc/man.c11
-rw-r--r--usr.bin/mandoc/man_hash.c14
-rw-r--r--usr.bin/mandoc/man_html.c3
-rw-r--r--usr.bin/mandoc/man_validate.c75
-rw-r--r--usr.bin/mandoc/mandoc.c39
-rw-r--r--usr.bin/mandoc/mdoc.c16
-rw-r--r--usr.bin/mandoc/mdoc_hash.c26
-rw-r--r--usr.bin/mandoc/mdoc_html.c49
-rw-r--r--usr.bin/mandoc/mdoc_macro.c6
-rw-r--r--usr.bin/mandoc/mdoc_validate.c123
-rw-r--r--usr.bin/mandoc/out.c46
-rw-r--r--usr.bin/mandoc/out.h3
-rw-r--r--usr.bin/mandoc/roff.c432
-rw-r--r--usr.bin/mandoc/tbl_html.c4
-rw-r--r--usr.bin/mandoc/tbl_layout.c12
-rw-r--r--usr.bin/mandoc/tbl_term.c4
-rw-r--r--usr.bin/mandoc/term_ps.c11
22 files changed, 547 insertions, 377 deletions
diff --git a/share/man/man7/mdoc.7 b/share/man/man7/mdoc.7
index 959a654db13..538f1831d42 100644
--- a/share/man/man7/mdoc.7
+++ b/share/man/man7/mdoc.7
@@ -1,4 +1,4 @@
-.\" $OpenBSD: mdoc.7,v 1.85 2011/09/18 10:38:57 schwarze Exp $
+.\" $OpenBSD: mdoc.7,v 1.86 2011/09/18 15:54:48 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -723,11 +723,11 @@ has multiple heads.
.Ed
.Bl -column "MacroX" "CallableX" "ParsedX" "closed by XXXXXXXXXXX" -offset indent
.It Em Macro Ta Em Callable Ta Em Parsed Ta Em Scope
-.It Sx \&It Ta \&No Ta Yes Ta closed by Sx \&It , Sx \&El
-.It Sx \&Nd Ta \&No Ta \&No Ta closed by Sx \&Sh
-.It Sx \&Nm Ta \&No Ta Yes Ta closed by Sx \&Nm , Sx \&Sh , Sx \&Ss
-.It Sx \&Sh Ta \&No Ta \&No Ta closed by Sx \&Sh
-.It Sx \&Ss Ta \&No Ta \&No Ta closed by Sx \&Sh , Sx \&Ss
+.It Sx \&It Ta \&No Ta Yes Ta closed by Sx \&It , Sx \&El
+.It Sx \&Nd Ta \&No Ta \&No Ta closed by Sx \&Sh
+.It Sx \&Nm Ta \&No Ta Yes Ta closed by Sx \&Nm , Sx \&Sh , Sx \&Ss
+.It Sx \&Sh Ta \&No Ta Yes Ta closed by Sx \&Sh
+.It Sx \&Ss Ta \&No Ta Yes Ta closed by Sx \&Sh , Sx \&Ss
.El
.Pp
Note that the
@@ -2875,6 +2875,9 @@ custom sections be used.
.Pp
Section names should be unique so that they may be keyed by
.Sx \&Sx .
+Although this macro is parsed, it should not consist of child node or it
+may not be linked with
+.Sx \&Sx .
.Pp
See also
.Sx \&Pp ,
@@ -2920,6 +2923,9 @@ rarely have subsections.
.Pp
Sub-section names should be unique so that they may be keyed by
.Sx \&Sx .
+Although this macro is parsed, it should not consist of child node or it
+may not be linked with
+.Sx \&Sx .
.Pp
See also
.Sx \&Pp ,
diff --git a/share/man/man7/roff.7 b/share/man/man7/roff.7
index c793db5e745..effd610976a 100644
--- a/share/man/man7/roff.7
+++ b/share/man/man7/roff.7
@@ -1,4 +1,4 @@
-.\" $OpenBSD: roff.7,v 1.13 2011/09/18 10:38:57 schwarze Exp $
+.\" $OpenBSD: roff.7,v 1.14 2011/09/18 15:54:48 schwarze Exp $
.\"
.\" Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -612,10 +612,21 @@ This line-scoped request can take an arbitrary number of arguments.
Currently, it is ignored including its arguments.
.Ss \&tr
Output character translation.
-This request is intended to have one argument,
-consisting of an even number of characters.
-Currently, it is ignored including its arguments,
-and the number of arguments is not checked.
+Its syntax is as follows:
+.Pp
+.D1 Pf \. Cm \&tr Ar [ab]+
+.Pp
+Pairs of
+.Ar ab
+characters are replaced
+.Ar ( a
+for
+.Ar b ) .
+Replacement (or origin) characters may also be character escapes; thus,
+.Pp
+.Dl tr \e(xx\e(yy
+.Pp
+replaces all invocations of \e(xx with \e(yy.
.Ss \&T&
Re-start a table layout, retaining the options of the prior table
invocation.
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile
index e66a47e56f1..f3edbe21538 100644
--- a/usr.bin/mandoc/Makefile
+++ b/usr.bin/mandoc/Makefile
@@ -1,8 +1,8 @@
-# $OpenBSD: Makefile,v 1.59 2011/09/18 10:25:28 schwarze Exp $
+# $OpenBSD: Makefile,v 1.60 2011/09/18 15:54:48 schwarze Exp $
.include <bsd.own.mk>
-CFLAGS+=-DVERSION=\"1.11.5\"
+CFLAGS+=-DVERSION=\"1.11.7\"
CFLAGS+=-W -Wall -Wstrict-prototypes
.if ${COMPILER_VERSION:L} == "gcc3" || ${COMPILER_VERSION:L} == "gcc4"
diff --git a/usr.bin/mandoc/eqn.c b/usr.bin/mandoc/eqn.c
index 37ed4db0889..8f7773d2b45 100644
--- a/usr.bin/mandoc/eqn.c
+++ b/usr.bin/mandoc/eqn.c
@@ -1,4 +1,4 @@
-/* $Id: eqn.c,v 1.4 2011/09/18 10:25:28 schwarze Exp $ */
+/* $Id: eqn.c,v 1.5 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include "mandoc.h"
#include "libmandoc.h"
diff --git a/usr.bin/mandoc/libmandoc.h b/usr.bin/mandoc/libmandoc.h
index 4378c6391ed..aca7c573b93 100644
--- a/usr.bin/mandoc/libmandoc.h
+++ b/usr.bin/mandoc/libmandoc.h
@@ -1,4 +1,4 @@
-/* $Id: libmandoc.h,v 1.14 2011/09/18 10:25:28 schwarze Exp $ */
+/* $Id: libmandoc.h,v 1.15 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -47,7 +47,6 @@ void mandoc_vmsg(enum mandocerr, struct mparse *,
char *mandoc_getarg(struct mparse *, char **, int, int *);
char *mandoc_normdate(struct mparse *, char *, int, int);
int mandoc_eos(const char *, size_t, int);
-int mandoc_hyph(const char *, const char *);
int mandoc_getcontrol(const char *, int *);
int mandoc_strntoi(const char *, size_t, int);
@@ -76,6 +75,7 @@ void roff_endparse(struct roff *);
int roff_regisset(const struct roff *, enum regs);
unsigned int roff_regget(const struct roff *, enum regs);
void roff_regunset(struct roff *, enum regs);
+char *roff_strdup(const struct roff *, const char *);
#if 0
char roff_eqndelim(const struct roff *);
void roff_openeqn(struct roff *, const char *,
diff --git a/usr.bin/mandoc/man.c b/usr.bin/mandoc/man.c
index 85d213099dd..35eaf6ab72b 100644
--- a/usr.bin/mandoc/man.c
+++ b/usr.bin/mandoc/man.c
@@ -1,4 +1,4 @@
-/* $Id: man.c,v 1.60 2011/09/18 10:25:28 schwarze Exp $ */
+/* $Id: man.c,v 1.61 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -316,16 +316,9 @@ int
man_word_alloc(struct man *m, int line, int pos, const char *word)
{
struct man_node *n;
- size_t sv, len;
-
- len = strlen(word);
n = man_node_alloc(m, line, pos, MAN_TEXT, MAN_MAX);
- n->string = mandoc_malloc(len + 1);
- sv = strlcpy(n->string, word, len + 1);
-
- /* Prohibit truncation. */
- assert(sv < len + 1);
+ n->string = roff_strdup(m->roff, word);
if ( ! man_node_append(m, n))
return(0);
diff --git a/usr.bin/mandoc/man_hash.c b/usr.bin/mandoc/man_hash.c
index 181da30ecf6..bf45210ad0e 100644
--- a/usr.bin/mandoc/man_hash.c
+++ b/usr.bin/mandoc/man_hash.c
@@ -1,4 +1,4 @@
-/* $Id: man_hash.c,v 1.14 2011/04/24 16:22:02 schwarze Exp $ */
+/* $Id: man_hash.c,v 1.15 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -26,10 +26,10 @@
#include "mandoc.h"
#include "libman.h"
-#define HASH_DEPTH 8
+#define HASH_DEPTH 6
#define HASH_ROW(x) do { \
- if (isupper((u_char)(x))) \
+ if (isupper((unsigned char)(x))) \
(x) -= 65; \
else \
(x) -= 97; \
@@ -43,7 +43,7 @@
* macro (the integer value of the enum stored as a char to save a bit
* of space).
*/
-static u_char table[26 * HASH_DEPTH];
+static unsigned char table[26 * HASH_DEPTH];
/*
* XXX - this hash has global scope, so if intended for use as a library
@@ -62,13 +62,13 @@ man_hash_init(void)
for (i = 0; i < (int)MAN_MAX; i++) {
x = man_macronames[i][0];
- assert(isalpha((u_char)x));
+ assert(isalpha((unsigned char)x));
HASH_ROW(x);
for (j = 0; j < HASH_DEPTH; j++)
if (UCHAR_MAX == table[x + j]) {
- table[x + j] = (u_char)i;
+ table[x + j] = (unsigned char)i;
break;
}
@@ -85,7 +85,7 @@ man_hash_find(const char *tmp)
if ('\0' == (x = tmp[0]))
return(MAN_MAX);
- if ( ! (isalpha((u_char)x)))
+ if ( ! (isalpha((unsigned char)x)))
return(MAN_MAX);
HASH_ROW(x);
diff --git a/usr.bin/mandoc/man_html.c b/usr.bin/mandoc/man_html.c
index 1dcfe5aea61..5192ba9761e 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.41 2011/09/18 10:25:28 schwarze Exp $ */
+/* $Id: man_html.c,v 1.42 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -32,7 +32,6 @@
/* FIXME: have PD set the default vspace width. */
#define INDENT 5
-#define HALFINDENT 3
#define MAN_ARGS const struct man_meta *m, \
const struct man_node *n, \
diff --git a/usr.bin/mandoc/man_validate.c b/usr.bin/mandoc/man_validate.c
index 82ad699bbd6..e24fdeb6287 100644
--- a/usr.bin/mandoc/man_validate.c
+++ b/usr.bin/mandoc/man_validate.c
@@ -1,4 +1,4 @@
-/* $Id: man_validate.c,v 1.46 2011/07/07 20:07:38 schwarze Exp $ */
+/* $Id: man_validate.c,v 1.47 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -42,42 +42,44 @@ struct man_valid {
static int check_bline(CHKARGS);
static int check_eq0(CHKARGS);
-static int check_ft(CHKARGS);
static int check_le1(CHKARGS);
static int check_ge2(CHKARGS);
static int check_le5(CHKARGS);
static int check_par(CHKARGS);
static int check_part(CHKARGS);
static int check_root(CHKARGS);
-static int check_sec(CHKARGS);
static void check_text(CHKARGS);
static int post_AT(CHKARGS);
static int post_vs(CHKARGS);
static int post_fi(CHKARGS);
+static int post_ft(CHKARGS);
static int post_nf(CHKARGS);
+static int post_sec(CHKARGS);
static int post_TH(CHKARGS);
static int post_UC(CHKARGS);
+static int pre_sec(CHKARGS);
static v_check posts_at[] = { post_AT, NULL };
static v_check posts_br[] = { post_vs, check_eq0, NULL };
static v_check posts_eq0[] = { check_eq0, NULL };
static v_check posts_fi[] = { check_eq0, post_fi, NULL };
-static v_check posts_ft[] = { check_ft, NULL };
+static v_check posts_ft[] = { post_ft, NULL };
static v_check posts_nf[] = { check_eq0, post_nf, NULL };
static v_check posts_par[] = { check_par, NULL };
static v_check posts_part[] = { check_part, NULL };
-static v_check posts_sec[] = { check_sec, NULL };
+static v_check posts_sec[] = { post_sec, NULL };
static v_check posts_sp[] = { post_vs, check_le1, NULL };
static v_check posts_th[] = { check_ge2, check_le5, post_TH, NULL };
static v_check posts_uc[] = { post_UC, NULL };
static v_check pres_bline[] = { check_bline, NULL };
+static v_check pres_sec[] = { check_bline, pre_sec, NULL};
static const struct man_valid man_valids[MAN_MAX] = {
{ NULL, posts_br }, /* br */
{ pres_bline, posts_th }, /* TH */
- { pres_bline, posts_sec }, /* SH */
- { pres_bline, posts_sec }, /* SS */
+ { pres_sec, posts_sec }, /* SH */
+ { pres_sec, posts_sec }, /* SS */
{ pres_bline, NULL }, /* TP */
{ pres_bline, posts_par }, /* LP */
{ pres_bline, posts_par }, /* PP */
@@ -203,45 +205,15 @@ check_root(CHKARGS)
}
static void
-check_text(CHKARGS)
+check_text(CHKARGS)
{
- char *p, *pp, *cpp;
- int pos;
- size_t sz;
+ char *cp, *p;
- p = n->string;
- pos = n->pos + 1;
-
- while ('\0' != *p) {
- sz = strcspn(p, "\t\\");
-
- p += (int)sz;
- pos += (int)sz;
-
- if ('\t' == *p) {
- if ( ! (MAN_LITERAL & m->flags))
- man_pmsg(m, n->line, pos, MANDOCERR_BADTAB);
- p++;
- pos++;
+ cp = p = n->string;
+ for (cp = p; NULL != (p = strchr(p, '\t')); p++) {
+ if (MAN_LITERAL & m->flags)
continue;
- } else if ('\0' == *p)
- break;
-
- pos++;
- pp = ++p;
-
- if (ESCAPE_ERROR == mandoc_escape
- ((const char **)&pp, NULL, NULL)) {
- man_pmsg(m, n->line, pos, MANDOCERR_BADESCAPE);
- break;
- }
-
- cpp = p;
- while (NULL != (cpp = memchr(cpp, ASCII_HYPH, pp - cpp)))
- *cpp = '-';
-
- pos += pp - p;
- p = pp;
+ man_pmsg(m, n->line, (int)(p - cp), MANDOCERR_BADTAB);
}
}
@@ -263,7 +235,7 @@ INEQ_DEFINE(2, >=, ge2)
INEQ_DEFINE(5, <=, le5)
static int
-check_ft(CHKARGS)
+post_ft(CHKARGS)
{
char *cp;
int ok;
@@ -319,7 +291,16 @@ check_ft(CHKARGS)
}
static int
-check_sec(CHKARGS)
+pre_sec(CHKARGS)
+{
+
+ if (MAN_BLOCK == n->type)
+ m->flags &= ~MAN_LITERAL;
+ return(1);
+}
+
+static int
+post_sec(CHKARGS)
{
if ( ! (MAN_HEAD == n->type && 0 == n->nchild))
@@ -329,7 +310,6 @@ check_sec(CHKARGS)
return(0);
}
-
static int
check_part(CHKARGS)
{
@@ -408,7 +388,8 @@ post_TH(CHKARGS)
if (n && n->string) {
for (p = n->string; '\0' != *p; p++) {
/* Only warn about this once... */
- if (isalpha((u_char)*p) && ! isupper((u_char)*p)) {
+ if (isalpha((unsigned char)*p) &&
+ ! isupper((unsigned char)*p)) {
man_nmsg(m, n, MANDOCERR_UPPERCASE);
break;
}
diff --git a/usr.bin/mandoc/mandoc.c b/usr.bin/mandoc/mandoc.c
index 20ddc72def4..e816496638b 100644
--- a/usr.bin/mandoc/mandoc.c
+++ b/usr.bin/mandoc/mandoc.c
@@ -1,4 +1,4 @@
-/* $Id: mandoc.c,v 1.27 2011/09/18 10:25:28 schwarze Exp $ */
+/* $Id: mandoc.c,v 1.28 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -550,12 +550,12 @@ a2time(time_t *t, const char *fmt, const char *p)
static char *
time2a(time_t t)
{
- struct tm tm;
+ struct tm *tm;
char *buf, *p;
size_t ssz;
int isz;
- localtime_r(&t, &tm);
+ tm = localtime(&t);
/*
* Reserve space:
@@ -565,15 +565,15 @@ time2a(time_t t)
*/
p = buf = mandoc_malloc(10 + 4 + 4 + 1);
- if (0 == (ssz = strftime(p, 10 + 1, "%B ", &tm)))
+ if (0 == (ssz = strftime(p, 10 + 1, "%B ", tm)))
goto fail;
p += (int)ssz;
- if (-1 == (isz = snprintf(p, 4 + 1, "%d, ", tm.tm_mday)))
+ if (-1 == (isz = snprintf(p, 4 + 1, "%d, ", tm->tm_mday)))
goto fail;
p += isz;
- if (0 == strftime(p, 4 + 1, "%Y", &tm))
+ if (0 == strftime(p, 4 + 1, "%Y", tm))
goto fail;
return(buf);
@@ -646,33 +646,6 @@ mandoc_eos(const char *p, size_t sz, int enclosed)
return(found && !enclosed);
}
-int
-mandoc_hyph(const char *start, const char *c)
-{
-
- /*
- * Choose whether to break at a hyphenated character. We only
- * do this if it's free-standing within a word.
- */
-
- /* Skip first/last character of buffer. */
- if (c == start || '\0' == *(c + 1))
- return(0);
- /* Skip first/last character of word. */
- if ('\t' == *(c + 1) || '\t' == *(c - 1))
- return(0);
- if (' ' == *(c + 1) || ' ' == *(c - 1))
- return(0);
- /* Skip double invocations. */
- if ('-' == *(c + 1) || '-' == *(c - 1))
- return(0);
- /* Skip escapes. */
- if ('\\' == *(c - 1))
- return(0);
-
- return(1);
-}
-
/*
* Find out whether a line is a macro line or not. If it is, adjust the
* current position and return one; if it isn't, return zero and don't
diff --git a/usr.bin/mandoc/mdoc.c b/usr.bin/mandoc/mdoc.c
index 6946e04fcf0..b02b169bb92 100644
--- a/usr.bin/mandoc/mdoc.c
+++ b/usr.bin/mandoc/mdoc.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc.c,v 1.84 2011/09/18 10:25:28 schwarze Exp $ */
+/* $Id: mdoc.c,v 1.85 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -564,16 +564,9 @@ int
mdoc_word_alloc(struct mdoc *m, int line, int pos, const char *p)
{
struct mdoc_node *n;
- size_t sv, len;
-
- len = strlen(p);
n = node_alloc(m, line, pos, MDOC_MAX, MDOC_TEXT);
- n->string = mandoc_malloc(len + 1);
- sv = strlcpy(n->string, p, len + 1);
-
- /* Prohibit truncation. */
- assert(sv < len + 1);
+ n->string = roff_strdup(m->roff, p);
if ( ! node_append(m, n))
return(0);
@@ -755,11 +748,6 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
ws = NULL;
for (c = end = buf + offs; *c; c++) {
switch (*c) {
- case '-':
- if (mandoc_hyph(buf + offs, c))
- *c = ASCII_HYPH;
- ws = NULL;
- break;
case ' ':
if (NULL == ws)
ws = c;
diff --git a/usr.bin/mandoc/mdoc_hash.c b/usr.bin/mandoc/mdoc_hash.c
index 0f959709f93..f0b75358cb3 100644
--- a/usr.bin/mandoc/mdoc_hash.c
+++ b/usr.bin/mandoc/mdoc_hash.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_hash.c,v 1.12 2011/04/24 16:22:02 schwarze Exp $ */
+/* $Id: mdoc_hash.c,v 1.13 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -27,7 +27,7 @@
#include "mandoc.h"
#include "libmdoc.h"
-static u_char table[27 * 13];
+static unsigned char table[27 * 12];
/*
* XXX - this hash has global scope, so if intended for use as a library
@@ -44,18 +44,18 @@ mdoc_hash_init(void)
for (i = 0; i < (int)MDOC_MAX; i++) {
p = mdoc_macronames[i];
- if (isalpha((u_char)p[1]))
- major = 13 * (tolower((u_char)p[1]) - 97);
+ if (isalpha((unsigned char)p[1]))
+ major = 12 * (tolower((unsigned char)p[1]) - 97);
else
- major = 13 * 26;
+ major = 12 * 26;
- for (j = 0; j < 13; j++)
+ for (j = 0; j < 12; j++)
if (UCHAR_MAX == table[major + j]) {
- table[major + j] = (u_char)i;
+ table[major + j] = (unsigned char)i;
break;
}
- assert(j < 13);
+ assert(j < 12);
}
}
@@ -66,20 +66,20 @@ mdoc_hash_find(const char *p)
if (0 == p[0])
return(MDOC_MAX);
- if ( ! isalpha((u_char)p[0]) && '%' != p[0])
+ if ( ! isalpha((unsigned char)p[0]) && '%' != p[0])
return(MDOC_MAX);
- if (isalpha((u_char)p[1]))
- major = 13 * (tolower((u_char)p[1]) - 97);
+ if (isalpha((unsigned char)p[1]))
+ major = 12 * (tolower((unsigned char)p[1]) - 97);
else if ('1' == p[1])
- major = 13 * 26;
+ major = 12 * 26;
else
return(MDOC_MAX);
if (p[2] && p[3])
return(MDOC_MAX);
- for (j = 0; j < 13; j++) {
+ for (j = 0; j < 12; j++) {
if (UCHAR_MAX == (i = table[major + j]))
break;
if (0 == strcmp(p, mdoc_macronames[i]))
diff --git a/usr.bin/mandoc/mdoc_html.c b/usr.bin/mandoc/mdoc_html.c
index c9fa7a4fa16..c3ab375ce1b 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.60 2011/09/18 10:25:28 schwarze Exp $ */
+/* $Id: mdoc_html.c,v 1.61 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -30,7 +30,6 @@
#include "main.h"
#define INDENT 5
-#define HALFINDENT 3
#define MDOC_ARGS const struct mdoc_meta *m, \
const struct mdoc_node *n, \
@@ -349,10 +348,8 @@ a2offs(const char *p, struct roffsu *su)
SCALE_HS_INIT(su, INDENT);
else if (0 == strcmp(p, "indent-two"))
SCALE_HS_INIT(su, INDENT * 2);
- else if ( ! a2roffsu(p, su, SCALE_MAX)) {
- su->unit = SCALE_BU;
- su->scale = html_strlen(p);
- }
+ else if ( ! a2roffsu(p, su, SCALE_MAX))
+ SCALE_HS_INIT(su, html_strlen(p));
}
@@ -604,18 +601,22 @@ mdoc_sh_pre(MDOC_ARGS)
bufinit(h);
bufcat(h, "x");
- for (n = n->child; n; n = n->next) {
+
+ for (n = n->child; n && MDOC_TEXT == n->type; ) {
bufcat_id(h, n->string);
- if (n->next)
+ if (NULL != (n = n->next))
bufcat_id(h, " ");
}
- PAIR_ID_INIT(&tag, h->buf);
- print_otag(h, TAG_H1, 1, &tag);
+ if (NULL == n) {
+ PAIR_ID_INIT(&tag, h->buf);
+ print_otag(h, TAG_H1, 1, &tag);
+ } else
+ print_otag(h, TAG_H1, 0, NULL);
+
return(1);
}
-
/* ARGSUSED */
static int
mdoc_ss_pre(MDOC_ARGS)
@@ -631,14 +632,19 @@ mdoc_ss_pre(MDOC_ARGS)
bufinit(h);
bufcat(h, "x");
- for (n = n->child; n; n = n->next) {
+
+ for (n = n->child; n && MDOC_TEXT == n->type; ) {
bufcat_id(h, n->string);
- if (n->next)
+ if (NULL != (n = n->next))
bufcat_id(h, " ");
}
- PAIR_ID_INIT(&tag, h->buf);
- print_otag(h, TAG_H2, 1, &tag);
+ if (NULL == n) {
+ PAIR_ID_INIT(&tag, h->buf);
+ print_otag(h, TAG_H2, 1, &tag);
+ } else
+ print_otag(h, TAG_H2, 0, NULL);
+
return(1);
}
@@ -1167,9 +1173,10 @@ mdoc_sx_pre(MDOC_ARGS)
bufinit(h);
bufcat(h, "#x");
- for (n = n->child; n; n = n->next) {
+
+ for (n = n->child; n; ) {
bufcat_id(h, n->string);
- if (n->next)
+ if (NULL != (n = n->next))
bufcat_id(h, " ");
}
@@ -1980,7 +1987,7 @@ mdoc_li_pre(MDOC_ARGS)
struct htmlpair tag;
PAIR_CLASS_INIT(&tag, "lit");
- print_otag(h, TAG_SPAN, 1, &tag);
+ print_otag(h, TAG_CODE, 1, &tag);
return(1);
}
@@ -2208,7 +2215,11 @@ mdoc_quote_pre(MDOC_ARGS)
print_text(h, "(");
break;
case (MDOC_Ql):
- /* FALLTHROUGH */
+ print_text(h, "\\(oq");
+ h->flags |= HTML_NOSPACE;
+ PAIR_CLASS_INIT(&tag, "lit");
+ print_otag(h, TAG_CODE, 1, &tag);
+ break;
case (MDOC_So):
/* FALLTHROUGH */
case (MDOC_Sq):
diff --git a/usr.bin/mandoc/mdoc_macro.c b/usr.bin/mandoc/mdoc_macro.c
index bc22ce7330a..b3bc766c3d3 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.68 2011/05/29 21:22:18 schwarze Exp $ */
+/* $Id: mdoc_macro.c,v 1.69 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -70,8 +70,8 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
{ in_line_eoln, MDOC_PROLOGUE }, /* Dd */
{ in_line_eoln, MDOC_PROLOGUE }, /* Dt */
{ in_line_eoln, MDOC_PROLOGUE }, /* Os */
- { blk_full, 0 }, /* Sh */
- { blk_full, 0 }, /* Ss */
+ { blk_full, MDOC_PARSED }, /* Sh */
+ { blk_full, MDOC_PARSED }, /* Ss */
{ in_line_eoln, 0 }, /* Pp */
{ blk_part_imp, MDOC_PARSED }, /* D1 */
{ blk_part_imp, MDOC_PARSED }, /* Dl */
diff --git a/usr.bin/mandoc/mdoc_validate.c b/usr.bin/mandoc/mdoc_validate.c
index 5a8dc53c275..98643446e00 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.94 2011/09/18 10:25:28 schwarze Exp $ */
+/* $Id: mdoc_validate.c,v 1.95 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -68,9 +68,7 @@ static void check_text(struct mdoc *, int, int, char *);
static void check_argv(struct mdoc *,
struct mdoc_node *, struct mdoc_argv *);
static void check_args(struct mdoc *, struct mdoc_node *);
-
-static int concat(struct mdoc *, char *,
- const struct mdoc_node *, size_t);
+static int concat(char *, const struct mdoc_node *, size_t);
static enum mdoc_sec a2sec(const char *);
static size_t macro2len(enum mdoct);
@@ -541,39 +539,13 @@ check_argv(struct mdoc *m, struct mdoc_node *n, struct mdoc_argv *v)
static void
check_text(struct mdoc *m, int ln, int pos, char *p)
{
- char *cpp, *pp;
- size_t sz;
-
- while ('\0' != *p) {
- sz = strcspn(p, "\t\\");
-
- p += (int)sz;
- pos += (int)sz;
+ char *cp;
- if ('\t' == *p) {
- if ( ! (MDOC_LITERAL & m->flags))
- mdoc_pmsg(m, ln, pos, MANDOCERR_BADTAB);
- p++;
- pos++;
+ cp = p;
+ for (cp = p; NULL != (p = strchr(p, '\t')); p++) {
+ if (MDOC_LITERAL & m->flags)
continue;
- } else if ('\0' == *p)
- break;
-
- pos++;
- pp = ++p;
-
- if (ESCAPE_ERROR == mandoc_escape
- ((const char **)&pp, NULL, NULL)) {
- mdoc_pmsg(m, ln, pos, MANDOCERR_BADESCAPE);
- break;
- }
-
- cpp = p;
- while (NULL != (cpp = memchr(cpp, ASCII_HYPH, pp - cpp)))
- *cpp = '-';
-
- pos += pp - p;
- p = pp;
+ mdoc_pmsg(m, ln, pos + (int)(p - cp), MANDOCERR_BADTAB);
}
}
@@ -727,7 +699,7 @@ pre_bl(PRE_ARGS)
if (LIST_column == lt) {
n->norm->Bl.ncols =
n->args->argv[i].sz;
- n->norm->Bl.cols = (const char **)
+ n->norm->Bl.cols = (void *)
n->args->argv[i].value;
}
}
@@ -1129,6 +1101,7 @@ static int
post_nm(POST_ARGS)
{
char buf[BUFSIZ];
+ int c;
/* If no child specified, make sure we have the meta name. */
@@ -1140,11 +1113,14 @@ post_nm(POST_ARGS)
/* If no meta name, set it from the child. */
- if ( ! concat(mdoc, buf, mdoc->last->child, BUFSIZ))
+ buf[0] = '\0';
+ if (-1 == (c = concat(buf, mdoc->last->child, BUFSIZ))) {
+ mdoc_nmsg(mdoc, mdoc->last->child, MANDOCERR_MEM);
return(0);
+ }
+ assert(c);
mdoc->meta.name = mandoc_strdup(buf);
-
return(1);
}
@@ -1415,7 +1391,7 @@ post_bl_block_width(POST_ARGS)
assert(i < (int)n->args->argc);
- snprintf(buf, NUMSIZ, "%zun", width);
+ snprintf(buf, NUMSIZ, "%un", (unsigned int)width);
free(n->args->argv[i].value[0]);
n->args->argv[i].value[0] = mandoc_strdup(buf);
@@ -1465,7 +1441,7 @@ post_bl_block_tag(POST_ARGS)
/* Defaults to ten ens. */
- snprintf(buf, NUMSIZ, "%zun", sz);
+ snprintf(buf, NUMSIZ, "%un", (unsigned int)sz);
/*
* We have to dynamically add this to the macro's argument list.
@@ -1541,7 +1517,7 @@ post_bl_head(POST_ARGS)
((size_t)mdoc->last->nchild * sizeof(char *));
mdoc->last->norm->Bl.ncols = np->args->argv[j].sz;
- mdoc->last->norm->Bl.cols = (const char **)np->args->argv[j].value;
+ mdoc->last->norm->Bl.cols = (void *)np->args->argv[j].value;
for (i = 0, nn = mdoc->last->child; nn; i++) {
np->args->argv[j].value[i] = nn->string;
@@ -1840,6 +1816,7 @@ post_sh_head(POST_ARGS)
{
char buf[BUFSIZ];
enum mdoc_sec sec;
+ int c;
/*
* Process a new section. Sections are either "named" or
@@ -1848,10 +1825,13 @@ post_sh_head(POST_ARGS)
* manual sections.
*/
- if ( ! concat(mdoc, buf, mdoc->last->child, BUFSIZ))
+ sec = SEC_CUSTOM;
+ buf[0] = '\0';
+ if (-1 == (c = concat(buf, mdoc->last->child, BUFSIZ))) {
+ mdoc_nmsg(mdoc, mdoc->last->child, MANDOCERR_MEM);
return(0);
-
- sec = a2sec(buf);
+ } else if (1 == c)
+ sec = a2sec(buf);
/* The NAME should be first. */
@@ -2000,6 +1980,7 @@ post_dd(POST_ARGS)
{
char buf[DATESIZE];
struct mdoc_node *n;
+ int c;
if (mdoc->meta.date)
free(mdoc->meta.date);
@@ -2011,9 +1992,13 @@ post_dd(POST_ARGS)
return(1);
}
- if ( ! concat(mdoc, buf, n->child, DATESIZE))
+ buf[0] = '\0';
+ if (-1 == (c = concat(buf, n->child, DATESIZE))) {
+ mdoc_nmsg(mdoc, n->child, MANDOCERR_MEM);
return(0);
+ }
+ assert(c);
mdoc->meta.date = mandoc_normdate
(mdoc->parse, buf, n->line, n->pos);
@@ -2042,7 +2027,7 @@ post_dt(POST_ARGS)
if (NULL != (nn = n->child))
for (p = nn->string; *p; p++) {
- if (toupper((u_char)*p) == *p)
+ if (toupper((unsigned char)*p) == *p)
continue;
/*
@@ -2168,6 +2153,7 @@ post_os(POST_ARGS)
{
struct mdoc_node *n;
char buf[BUFSIZ];
+ int c;
#ifndef OSNAME
struct utsname utsname;
#endif
@@ -2184,8 +2170,13 @@ post_os(POST_ARGS)
if (mdoc->meta.os)
free(mdoc->meta.os);
- if ( ! concat(mdoc, buf, n->child, BUFSIZ))
+ buf[0] = '\0';
+ if (-1 == (c = concat(buf, n->child, BUFSIZ))) {
+ mdoc_nmsg(mdoc, n->child, MANDOCERR_MEM);
return(0);
+ }
+
+ assert(c);
/* XXX: yes, these can all be dynamically-adjusted buffers, but
* it's really not worth the extra hackery.
@@ -2252,34 +2243,24 @@ post_std(POST_ARGS)
return(1);
}
+/*
+ * Concatenate a node, stopping at the first non-text.
+ * Concatenation is separated by a single whitespace.
+ * Returns -1 on fatal (string overrun) error, 0 if child nodes were
+ * encountered, 1 otherwise.
+ */
static int
-concat(struct mdoc *m, char *p, const struct mdoc_node *n, size_t sz)
+concat(char *p, const struct mdoc_node *n, size_t sz)
{
- p[0] = '\0';
-
- /*
- * Concatenate sibling nodes together. All siblings must be of
- * type MDOC_TEXT or an assertion is raised. Concatenation is
- * separated by a single whitespace. Returns 0 on fatal (string
- * overrun) error.
- */
-
- for ( ; n; n = n->next) {
- assert(MDOC_TEXT == n->type);
-
- if (strlcat(p, n->string, sz) >= sz) {
- mdoc_nmsg(m, n, MANDOCERR_MEM);
- return(0);
- }
-
- if (NULL == n->next)
- continue;
-
- if (strlcat(p, " ", sz) >= sz) {
- mdoc_nmsg(m, n, MANDOCERR_MEM);
+ for ( ; NULL != n; n = n->next) {
+ if (MDOC_TEXT != n->type)
return(0);
- }
+ if ('\0' != p[0] && strlcat(p, " ", sz) >= sz)
+ return(-1);
+ if (strlcat(p, n->string, sz) >= sz)
+ return(-1);
+ concat(p, n->child, sz);
}
return(1);
diff --git a/usr.bin/mandoc/out.c b/usr.bin/mandoc/out.c
index eaebdc4a697..33b19d466b4 100644
--- a/usr.bin/mandoc/out.c
+++ b/usr.bin/mandoc/out.c
@@ -1,4 +1,4 @@
-/* $Id: out.c,v 1.14 2011/05/29 21:22:18 schwarze Exp $ */
+/* $Id: out.c,v 1.15 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -65,7 +65,7 @@ a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
return(0);
while (i < BUFSIZ) {
- if ( ! isdigit((u_char)*src)) {
+ if ( ! isdigit((unsigned char)*src)) {
if ('.' != *src)
break;
else if (hasd)
@@ -128,48 +128,6 @@ a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
return(1);
}
-
-/*
- * Correctly writes the time in nroff form, which differs from standard
- * form in that a space isn't printed in lieu of the extra %e field for
- * single-digit dates.
- */
-void
-time2a(time_t t, char *dst, size_t sz)
-{
- struct tm tm;
- char buf[5];
- char *p;
- size_t nsz;
-
- assert(sz > 1);
- localtime_r(&t, &tm);
-
- p = dst;
- nsz = 0;
-
- dst[0] = '\0';
-
- if (0 == (nsz = strftime(p, sz, "%B ", &tm)))
- return;
-
- p += (int)nsz;
- sz -= nsz;
-
- if (0 == strftime(buf, sizeof(buf), "%e, ", &tm))
- return;
-
- nsz = strlcat(p, buf + (' ' == buf[0] ? 1 : 0), sz);
-
- if (nsz >= sz)
- return;
-
- p += (int)nsz;
- sz -= nsz;
-
- (void)strftime(p, sz, "%Y", &tm);
-}
-
/*
* Calculate the abstract widths and decimal positions of columns in a
* table. This routine allocates the columns structures then runs over
diff --git a/usr.bin/mandoc/out.h b/usr.bin/mandoc/out.h
index 76f6bafe040..f60479552a7 100644
--- a/usr.bin/mandoc/out.h
+++ b/usr.bin/mandoc/out.h
@@ -1,4 +1,4 @@
-/* $Id: out.h,v 1.11 2011/05/29 21:22:18 schwarze Exp $ */
+/* $Id: out.h,v 1.12 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -64,7 +64,6 @@ __BEGIN_DECLS
while (/* CONSTCOND */ 0)
int a2roffsu(const char *, struct roffsu *, enum roffscale);
-void time2a(time_t, char *, size_t);
void tblcalc(struct rofftbl *tbl, const struct tbl_span *);
__END_DECLS
diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c
index 9efb8fd385b..5921a141785 100644
--- a/usr.bin/mandoc/roff.c
+++ b/usr.bin/mandoc/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.41 2011/09/18 10:25:28 schwarze Exp $ */
+/* $Id: roff.c,v 1.42 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -73,14 +73,25 @@ enum roffrule {
* Registers are assumed to be unsigned ints for now.
*/
struct reg {
- int set; /* whether set or not */
- unsigned int u; /* unsigned integer */
+ int set; /* whether set or not */
+ unsigned int u; /* unsigned integer */
};
+/*
+ * An incredibly-simple string buffer.
+ */
struct roffstr {
- char *name; /* key of symbol */
- char *string; /* current value */
- struct roffstr *next; /* next in list */
+ char *p; /* nil-terminated buffer */
+ size_t sz; /* saved strlen(p) */
+};
+
+/*
+ * A key-value roffstr pair as part of a singly-linked list.
+ */
+struct roffkv {
+ struct roffstr key;
+ struct roffstr val;
+ struct roffkv *next; /* next in list */
};
struct roff {
@@ -89,7 +100,9 @@ struct roff {
enum roffrule rstack[RSTACK_MAX]; /* stack of !`ie' rules */
int rstackpos; /* position in rstack */
struct reg regs[REG__MAX];
- struct roffstr *first_string; /* user-defined strings & macros */
+ struct roffkv *strtab; /* user-defined strings & macros */
+ struct roffkv *xmbtab; /* multi-byte trans table (`tr') */
+ struct roffstr *xtab; /* single-byte trans table (`tr') */
const char *current_string; /* value of last called user macro */
struct tbl_node *first_tbl; /* first table parsed */
struct tbl_node *last_tbl; /* last table parsed */
@@ -139,6 +152,12 @@ struct predef {
#define PREDEF(__name, __str) \
{ (__name), (__str) },
+static enum rofft roffhash_find(const char *, size_t);
+static void roffhash_init(void);
+static void roffnode_cleanscope(struct roff *);
+static void roffnode_pop(struct roff *);
+static void roffnode_push(struct roff *, enum rofft,
+ const char *, int, int);
static enum rofferr roff_block(ROFF_ARGS);
static enum rofferr roff_block_text(ROFF_ARGS);
static enum rofferr roff_block_sub(ROFF_ARGS);
@@ -149,7 +168,8 @@ static enum rofferr roff_cond_text(ROFF_ARGS);
static enum rofferr roff_cond_sub(ROFF_ARGS);
static enum rofferr roff_ds(ROFF_ARGS);
static enum roffrule roff_evalcond(const char *, int *);
-static void roff_freestr(struct roff *);
+static void roff_free1(struct roff *);
+static void roff_freestr(struct roffkv *);
static char *roff_getname(struct roff *, char **, int, int);
static const char *roff_getstrn(const struct roff *,
const char *, size_t);
@@ -157,12 +177,17 @@ static enum rofferr roff_line_ignore(ROFF_ARGS);
static enum rofferr roff_nr(ROFF_ARGS);
static void roff_openeqn(struct roff *, const char *,
int, int, const char *);
-static int roff_res(struct roff *,
+static enum rofft roff_parse(struct roff *, const char *, int *);
+static enum rofferr roff_parsetext(char *);
+static void roff_res(struct roff *,
char **, size_t *, int, int);
static enum rofferr roff_rm(ROFF_ARGS);
static void roff_setstr(struct roff *,
const char *, const char *, int);
+static void roff_setstrn(struct roffkv **, const char *,
+ size_t, const char *, size_t, int);
static enum rofferr roff_so(ROFF_ARGS);
+static enum rofferr roff_tr(ROFF_ARGS);
static enum rofferr roff_TE(ROFF_ARGS);
static enum rofferr roff_TS(ROFF_ARGS);
static enum rofferr roff_EQ(ROFF_ARGS);
@@ -170,7 +195,7 @@ static enum rofferr roff_EN(ROFF_ARGS);
static enum rofferr roff_T_(ROFF_ARGS);
static enum rofferr roff_userdef(ROFF_ARGS);
-/* See roff_hash_find() */
+/* See roffhash_find() */
#define ASCII_HI 126
#define ASCII_LO 33
@@ -201,7 +226,7 @@ static struct roffmac roffs[ROFF_MAX] = {
{ "rm", roff_rm, NULL, NULL, 0, NULL },
{ "so", roff_so, NULL, NULL, 0, NULL },
{ "ta", roff_line_ignore, NULL, NULL, 0, NULL },
- { "tr", roff_line_ignore, NULL, NULL, 0, NULL },
+ { "tr", roff_tr, NULL, NULL, 0, NULL },
{ "TS", roff_TS, NULL, NULL, 0, NULL },
{ "TE", roff_TE, NULL, NULL, 0, NULL },
{ "T&", roff_T_, NULL, NULL, 0, NULL },
@@ -218,20 +243,11 @@ static const struct predef predefs[PREDEFS_MAX] = {
#include "predefs.in"
};
-static void roff_free1(struct roff *);
-static enum rofft roff_hash_find(const char *, size_t);
-static void roff_hash_init(void);
-static void roffnode_cleanscope(struct roff *);
-static void roffnode_push(struct roff *, enum rofft,
- const char *, int, int);
-static void roffnode_pop(struct roff *);
-static enum rofft roff_parse(struct roff *, const char *, int *);
-
-/* See roff_hash_find() */
+/* See roffhash_find() */
#define ROFF_HASH(p) (p[0] - ASCII_LO)
static void
-roff_hash_init(void)
+roffhash_init(void)
{
struct roffmac *n;
int buc, i;
@@ -256,7 +272,7 @@ roff_hash_init(void)
* the nil-terminated string name could be found.
*/
static enum rofft
-roff_hash_find(const char *p, size_t s)
+roffhash_find(const char *p, size_t s)
{
int buc;
struct roffmac *n;
@@ -330,6 +346,7 @@ roff_free1(struct roff *r)
{
struct tbl_node *t;
struct eqn_node *e;
+ int i;
while (NULL != (t = r->first_tbl)) {
r->first_tbl = t->next;
@@ -348,9 +365,18 @@ roff_free1(struct roff *r)
while (r->last)
roffnode_pop(r);
- roff_freestr(r);
-}
+ roff_freestr(r->strtab);
+ roff_freestr(r->xmbtab);
+ r->strtab = r->xmbtab = NULL;
+
+ if (r->xtab)
+ for (i = 0; i < 128; i++)
+ free(r->xtab[i].p);
+
+ free(r->xtab);
+ r->xtab = NULL;
+}
void
roff_reset(struct roff *r)
@@ -385,7 +411,7 @@ roff_alloc(struct mparse *parse)
r->parse = parse;
r->rstackpos = -1;
- roff_hash_init();
+ roffhash_init();
for (i = 0; i < PREDEFS_MAX; i++)
roff_setstr(r, predefs[i].name, predefs[i].str, 0);
@@ -393,15 +419,16 @@ roff_alloc(struct mparse *parse)
return(r);
}
-
/*
* Pre-filter each and every line for reserved words (one beginning with
* `\*', e.g., `\*(ab'). These must be handled before the actual line
* is processed.
+ * This also checks the syntax of regular escapes.
*/
-static int
+static void
roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
{
+ enum mandoc_esc esc;
const char *stesc; /* start of an escape sequence ('\\') */
const char *stnam; /* start of the name, after "[(*" */
const char *cp; /* end of the name, e.g. before ']' */
@@ -410,8 +437,7 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
size_t nsz;
char *n;
- /* Search for a leading backslash and save a pointer to it. */
-
+again:
cp = *bufp + pos;
while (NULL != (cp = strchr(cp, '\\'))) {
stesc = cp++;
@@ -423,9 +449,21 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
*/
if ('\0' == *cp)
- return(1);
- if ('*' != *cp++)
- continue;
+ return;
+
+ if ('*' != *cp) {
+ res = cp;
+ esc = mandoc_escape(&cp, NULL, NULL);
+ if (ESCAPE_ERROR != esc)
+ continue;
+ cp = res;
+ mandoc_msg
+ (MANDOCERR_BADESCAPE, r->parse,
+ ln, (int)(stesc - *bufp), NULL);
+ return;
+ }
+
+ cp++;
/*
* The third character decides the length
@@ -435,7 +473,7 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
switch (*cp) {
case ('\0'):
- return(1);
+ return;
case ('('):
cp++;
maxl = 2;
@@ -453,8 +491,13 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
/* Advance to the end of the name. */
for (i = 0; 0 == maxl || i < maxl; i++, cp++) {
- if ('\0' == *cp)
- return(1); /* Error. */
+ if ('\0' == *cp) {
+ mandoc_msg
+ (MANDOCERR_BADESCAPE,
+ r->parse, ln,
+ (int)(stesc - *bufp), NULL);
+ return;
+ }
if (0 == maxl && ']' == *cp)
break;
}
@@ -467,13 +510,16 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
res = roff_getstrn(r, stnam, (size_t)i);
if (NULL == res) {
- /* TODO: keep track of the correct position. */
- mandoc_msg(MANDOCERR_BADESCAPE, r->parse, ln, pos, NULL);
+ mandoc_msg
+ (MANDOCERR_BADESCAPE, r->parse,
+ ln, (int)(stesc - *bufp), NULL);
res = "";
}
/* Replace the escape sequence by the string. */
+ pos = stesc - *bufp;
+
nsz = *szp + strlen(res) + 1;
n = mandoc_malloc(nsz);
@@ -485,12 +531,57 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
*bufp = n;
*szp = nsz;
- return(0);
+ goto again;
}
-
- return(1);
}
+/*
+ * Process text streams: convert all breakable hyphens into ASCII_HYPH.
+ */
+static enum rofferr
+roff_parsetext(char *p)
+{
+ char l, r;
+ size_t sz;
+ const char *start;
+ enum mandoc_esc esc;
+
+ start = p;
+
+ while ('\0' != *p) {
+ sz = strcspn(p, "-\\");
+ p += sz;
+
+ if ('\0' == *p)
+ break;
+
+ if ('\\' == *p) {
+ /* Skip over escapes. */
+ p++;
+ esc = mandoc_escape
+ ((const char **)&p, NULL, NULL);
+ if (ESCAPE_ERROR == esc)
+ break;
+ continue;
+ } else if (p == start) {
+ p++;
+ continue;
+ }
+
+ l = *(p - 1);
+ r = *(p + 1);
+ if ('\\' != l &&
+ '\t' != r && '\t' != l &&
+ ' ' != r && ' ' != l &&
+ '-' != r && '-' != l &&
+ ! isdigit((unsigned char)l) &&
+ ! isdigit((unsigned char)r))
+ *p = ASCII_HYPH;
+ p++;
+ }
+
+ return(ROFF_CONT);
+}
enum rofferr
roff_parseln(struct roff *r, int ln, char **bufp,
@@ -505,8 +596,7 @@ roff_parseln(struct roff *r, int ln, char **bufp,
* words to fill in.
*/
- if (r->first_string && ! roff_res(r, bufp, szp, ln, pos))
- return(ROFF_REPARSE);
+ roff_res(r, bufp, szp, ln, pos);
ppos = pos;
ctl = mandoc_getcontrol(*bufp, &pos);
@@ -531,13 +621,13 @@ roff_parseln(struct roff *r, int ln, char **bufp,
return(eqn_read(&r->eqn, ln, *bufp, pos, offs));
if (r->tbl)
return(tbl_read(r->tbl, ln, *bufp, pos));
- return(ROFF_CONT);
+ return(roff_parsetext(*bufp + pos));
} else if ( ! ctl) {
if (r->eqn)
return(eqn_read(&r->eqn, ln, *bufp, pos, offs));
if (r->tbl)
return(tbl_read(r->tbl, ln, *bufp, pos));
- return(ROFF_CONT);
+ return(roff_parsetext(*bufp + pos));
} else if (r->eqn)
return(eqn_read(&r->eqn, ln, *bufp, ppos, offs));
@@ -617,7 +707,7 @@ roff_parse(struct roff *r, const char *buf, int *pos)
maclen = strcspn(mac + 1, " \\\t\0") + 1;
t = (r->current_string = roff_getstrn(r, mac, maclen))
- ? ROFF_USERDEF : roff_hash_find(mac, maclen);
+ ? ROFF_USERDEF : roffhash_find(mac, maclen);
*pos += (int)maclen;
@@ -1270,6 +1360,71 @@ roff_TS(ROFF_ARGS)
/* ARGSUSED */
static enum rofferr
+roff_tr(ROFF_ARGS)
+{
+ const char *p, *first, *second;
+ size_t fsz, ssz;
+ enum mandoc_esc esc;
+
+ p = *bufp + pos;
+
+ if ('\0' == *p) {
+ mandoc_msg(MANDOCERR_ARGCOUNT, r->parse, ln, ppos, NULL);
+ return(ROFF_IGN);
+ }
+
+ while ('\0' != *p) {
+ fsz = ssz = 1;
+
+ first = p++;
+ if ('\\' == *first) {
+ esc = mandoc_escape(&p, NULL, NULL);
+ if (ESCAPE_ERROR == esc) {
+ mandoc_msg
+ (MANDOCERR_BADESCAPE, r->parse,
+ ln, (int)(p - *bufp), NULL);
+ return(ROFF_IGN);
+ }
+ fsz = (size_t)(p - first);
+ }
+
+ second = p++;
+ if ('\\' == *second) {
+ esc = mandoc_escape(&p, NULL, NULL);
+ if (ESCAPE_ERROR == esc) {
+ mandoc_msg
+ (MANDOCERR_BADESCAPE, r->parse,
+ ln, (int)(p - *bufp), NULL);
+ return(ROFF_IGN);
+ }
+ ssz = (size_t)(p - second);
+ } else if ('\0' == *second) {
+ mandoc_msg(MANDOCERR_ARGCOUNT, r->parse,
+ ln, (int)(p - *bufp), NULL);
+ second = " ";
+ p--;
+ }
+
+ if (fsz > 1) {
+ roff_setstrn(&r->xmbtab, first,
+ fsz, second, ssz, 0);
+ continue;
+ }
+
+ if (NULL == r->xtab)
+ r->xtab = mandoc_calloc
+ (128, sizeof(struct roffstr));
+
+ free(r->xtab[(int)*first].p);
+ r->xtab[(int)*first].p = mandoc_strndup(second, ssz);
+ r->xtab[(int)*first].sz = ssz;
+ }
+
+ return(ROFF_IGN);
+}
+
+/* ARGSUSED */
+static enum rofferr
roff_so(ROFF_ARGS)
{
char *name;
@@ -1391,32 +1546,40 @@ static void
roff_setstr(struct roff *r, const char *name, const char *string,
int multiline)
{
- struct roffstr *n;
- char *c;
- size_t oldch, newch;
-
- /* XXX workaround for the Perl preamble until we get .tr */
- if ( ! strcmp(name, "--")) {
- string = "--";
- multiline = 0;
- }
+
+ roff_setstrn(&r->strtab, name, strlen(name), string,
+ string ? strlen(string) : 0, multiline);
+}
+
+static void
+roff_setstrn(struct roffkv **r, const char *name, size_t namesz,
+ const char *string, size_t stringsz, int multiline)
+{
+ struct roffkv *n;
+ char *c;
+ int i;
+ size_t oldch, newch;
/* Search for an existing string with the same name. */
- n = r->first_string;
- while (n && strcmp(name, n->name))
+ n = *r;
+
+ while (n && strcmp(name, n->key.p))
n = n->next;
if (NULL == n) {
/* Create a new string table entry. */
- n = mandoc_malloc(sizeof(struct roffstr));
- n->name = mandoc_strdup(name);
- n->string = NULL;
- n->next = r->first_string;
- r->first_string = n;
+ n = mandoc_malloc(sizeof(struct roffkv));
+ n->key.p = mandoc_strndup(name, namesz);
+ n->key.sz = namesz;
+ n->val.p = NULL;
+ n->val.sz = 0;
+ n->next = *r;
+ *r = n;
} else if (0 == multiline) {
/* In multiline mode, append; else replace. */
- free(n->string);
- n->string = NULL;
+ free(n->val.p);
+ n->val.p = NULL;
+ n->val.sz = 0;
}
if (NULL == string)
@@ -1426,61 +1589,64 @@ roff_setstr(struct roff *r, const char *name, const char *string,
* One additional byte for the '\n' in multiline mode,
* and one for the terminating '\0'.
*/
- newch = strlen(string) + (multiline ? 2u : 1u);
- if (NULL == n->string) {
- n->string = mandoc_malloc(newch);
- *n->string = '\0';
+ newch = stringsz + (multiline ? 2u : 1u);
+
+ if (NULL == n->val.p) {
+ n->val.p = mandoc_malloc(newch);
+ *n->val.p = '\0';
oldch = 0;
} else {
- oldch = strlen(n->string);
- n->string = mandoc_realloc(n->string, oldch + newch);
+ oldch = n->val.sz;
+ n->val.p = mandoc_realloc(n->val.p, oldch + newch);
}
/* Skip existing content in the destination buffer. */
- c = n->string + (int)oldch;
+ c = n->val.p + (int)oldch;
/* Append new content to the destination buffer. */
- while (*string) {
+ i = 0;
+ while (i < (int)stringsz) {
/*
* Rudimentary roff copy mode:
* Handle escaped backslashes.
*/
- if ('\\' == *string && '\\' == *(string + 1))
- string++;
- *c++ = *string++;
+ if ('\\' == string[i] && '\\' == string[i + 1])
+ i++;
+ *c++ = string[i++];
}
/* Append terminating bytes. */
if (multiline)
*c++ = '\n';
+
*c = '\0';
+ n->val.sz = (int)(c - n->val.p);
}
static const char *
roff_getstrn(const struct roff *r, const char *name, size_t len)
{
- const struct roffstr *n;
+ const struct roffkv *n;
- n = r->first_string;
- while (n && (strncmp(name, n->name, len) || '\0' != n->name[(int)len]))
- n = n->next;
+ for (n = r->strtab; n; n = n->next)
+ if (0 == strncmp(name, n->key.p, len) &&
+ '\0' == n->key.p[(int)len])
+ return(n->val.p);
- return(n ? n->string : NULL);
+ return(NULL);
}
static void
-roff_freestr(struct roff *r)
+roff_freestr(struct roffkv *r)
{
- struct roffstr *n, *nn;
+ struct roffkv *n, *nn;
- for (n = r->first_string; n; n = nn) {
- free(n->name);
- free(n->string);
+ for (n = r; n; n = nn) {
+ free(n->key.p);
+ free(n->val.p);
nn = n->next;
free(n);
}
-
- r->first_string = NULL;
}
const struct tbl_span *
@@ -1496,3 +1662,95 @@ roff_eqn(const struct roff *r)
return(r->last_eqn ? &r->last_eqn->eqn : NULL);
}
+
+/*
+ * Duplicate an input string, making the appropriate character
+ * conversations (as stipulated by `tr') along the way.
+ * Returns a heap-allocated string with all the replacements made.
+ */
+char *
+roff_strdup(const struct roff *r, const char *p)
+{
+ const struct roffkv *cp;
+ char *res;
+ const char *pp;
+ size_t ssz, sz;
+ enum mandoc_esc esc;
+
+ if (NULL == r->xmbtab && NULL == r->xtab)
+ return(mandoc_strdup(p));
+ else if ('\0' == *p)
+ return(mandoc_strdup(""));
+
+ /*
+ * Step through each character looking for term matches
+ * (remember that a `tr' can be invoked with an escape, which is
+ * a glyph but the escape is multi-character).
+ * We only do this if the character hash has been initialised
+ * and the string is >0 length.
+ */
+
+ res = NULL;
+ ssz = 0;
+
+ while ('\0' != *p) {
+ if ('\\' != *p && r->xtab && r->xtab[(int)*p].p) {
+ sz = r->xtab[(int)*p].sz;
+ res = mandoc_realloc(res, ssz + sz + 1);
+ memcpy(res + ssz, r->xtab[(int)*p].p, sz);
+ ssz += sz;
+ p++;
+ continue;
+ } else if ('\\' != *p) {
+ res = mandoc_realloc(res, ssz + 2);
+ res[ssz++] = *p++;
+ continue;
+ }
+
+ /* Search for term matches. */
+ for (cp = r->xmbtab; cp; cp = cp->next)
+ if (0 == strncmp(p, cp->key.p, cp->key.sz))
+ break;
+
+ if (NULL != cp) {
+ /*
+ * A match has been found.
+ * Append the match to the array and move
+ * forward by its keysize.
+ */
+ res = mandoc_realloc
+ (res, ssz + cp->val.sz + 1);
+ memcpy(res + ssz, cp->val.p, cp->val.sz);
+ ssz += cp->val.sz;
+ p += (int)cp->key.sz;
+ continue;
+ }
+
+ /*
+ * Handle escapes carefully: we need to copy
+ * over just the escape itself, or else we might
+ * do replacements within the escape itself.
+ * Make sure to pass along the bogus string.
+ */
+ pp = p++;
+ esc = mandoc_escape(&p, NULL, NULL);
+ if (ESCAPE_ERROR == esc) {
+ sz = strlen(pp);
+ res = mandoc_realloc(res, ssz + sz + 1);
+ memcpy(res + ssz, pp, sz);
+ break;
+ }
+ /*
+ * We bail out on bad escapes.
+ * No need to warn: we already did so when
+ * roff_res() was called.
+ */
+ sz = (int)(p - pp);
+ res = mandoc_realloc(res, ssz + sz + 1);
+ memcpy(res + ssz, pp, sz);
+ ssz += sz;
+ }
+
+ res[(int)ssz] = '\0';
+ return(res);
+}
diff --git a/usr.bin/mandoc/tbl_html.c b/usr.bin/mandoc/tbl_html.c
index 7398ad4f777..5cb4f943bd1 100644
--- a/usr.bin/mandoc/tbl_html.c
+++ b/usr.bin/mandoc/tbl_html.c
@@ -1,6 +1,6 @@
-/* $Id: tbl_html.c,v 1.4 2011/01/16 19:41:16 schwarze Exp $ */
+/* $Id: tbl_html.c,v 1.5 2011/09/18 15:54:48 schwarze Exp $ */
/*
- * Copyright (c) 2011 Kristaps Dzonsons <kristaps@kth.se>
+ * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
diff --git a/usr.bin/mandoc/tbl_layout.c b/usr.bin/mandoc/tbl_layout.c
index 2d1989fa4e8..679b223faba 100644
--- a/usr.bin/mandoc/tbl_layout.c
+++ b/usr.bin/mandoc/tbl_layout.c
@@ -1,4 +1,4 @@
-/* $Id: tbl_layout.c,v 1.9 2011/05/29 21:22:18 schwarze Exp $ */
+/* $Id: tbl_layout.c,v 1.10 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -169,6 +169,8 @@ mod:
goto mod;
case ('f'):
break;
+ case ('r'):
+ /* FALLTHROUGH */
case ('b'):
/* FALLTHROUGH */
case ('i'):
@@ -181,12 +183,20 @@ mod:
}
switch (tolower((unsigned char)p[(*pos)++])) {
+ case ('3'):
+ /* FALLTHROUGH */
case ('b'):
cp->flags |= TBL_CELL_BOLD;
goto mod;
+ case ('2'):
+ /* FALLTHROUGH */
case ('i'):
cp->flags |= TBL_CELL_ITALIC;
goto mod;
+ case ('1'):
+ /* FALLTHROUGH */
+ case ('r'):
+ goto mod;
default:
break;
}
diff --git a/usr.bin/mandoc/tbl_term.c b/usr.bin/mandoc/tbl_term.c
index c481e50fe60..e5e9ed2991d 100644
--- a/usr.bin/mandoc/tbl_term.c
+++ b/usr.bin/mandoc/tbl_term.c
@@ -1,6 +1,6 @@
-/* $Id: tbl_term.c,v 1.8 2011/01/25 12:07:26 schwarze Exp $ */
+/* $Id: tbl_term.c,v 1.9 2011/09/18 15:54:48 schwarze Exp $ */
/*
- * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@kth.se>
+ * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
diff --git a/usr.bin/mandoc/term_ps.c b/usr.bin/mandoc/term_ps.c
index 761dc1b0423..9d04a917e97 100644
--- a/usr.bin/mandoc/term_ps.c
+++ b/usr.bin/mandoc/term_ps.c
@@ -1,4 +1,4 @@
-/* $Id: term_ps.c,v 1.17 2011/05/29 21:22:18 schwarze Exp $ */
+/* $Id: term_ps.c,v 1.18 2011/09/18 15:54:48 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -429,7 +429,8 @@ static struct termp *
pspdf_alloc(char *outopts)
{
struct termp *p;
- size_t pagex, pagey, marginx, marginy, lineheight;
+ unsigned int pagex, pagey;
+ size_t marginx, marginy, lineheight;
const char *toks[2];
const char *pp;
char *v;
@@ -485,7 +486,7 @@ pspdf_alloc(char *outopts)
} else if (0 == strcasecmp(pp, "legal")) {
pagex = 216;
pagey = 356;
- } else if (2 != sscanf(pp, "%zux%zu", &pagex, &pagey))
+ } else if (2 != sscanf(pp, "%ux%u", &pagex, &pagey))
fprintf(stderr, "%s: Unknown paper\n", pp);
} else if (NULL == pp)
pp = "letter";
@@ -513,8 +514,8 @@ pspdf_alloc(char *outopts)
lineheight = PNT2AFM(p, ((double)p->ps->scale * 1.4));
- p->ps->width = pagex;
- p->ps->height = pagey;
+ p->ps->width = (size_t)pagex;
+ p->ps->height = (size_t)pagey;
p->ps->header = pagey - (marginy / 2) - (lineheight / 2);
p->ps->top = pagey - marginy;
p->ps->footer = (marginy / 2) - (lineheight / 2);