summaryrefslogtreecommitdiff
path: root/usr.bin/mandoc
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2011-01-04 22:28:18 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2011-01-04 22:28:18 +0000
commit3f808e58f9b1e56a31e679de60386c10cefbe115 (patch)
treebc87b62f89cfcead15638c92e75e667be76752d5 /usr.bin/mandoc
parent520623cefde5dd43125b0e3bd121266079514407 (diff)
Merge kristaps@' cleaner tbl integration, removing mine;
there are still a few bugs, but fixing these will be easier in tree.
Diffstat (limited to 'usr.bin/mandoc')
-rw-r--r--usr.bin/mandoc/Makefile7
-rw-r--r--usr.bin/mandoc/chars.c24
-rw-r--r--usr.bin/mandoc/html.h3
-rw-r--r--usr.bin/mandoc/libroff.h62
-rw-r--r--usr.bin/mandoc/main.c37
-rw-r--r--usr.bin/mandoc/man.314
-rw-r--r--usr.bin/mandoc/man.c103
-rw-r--r--usr.bin/mandoc/man.h17
-rw-r--r--usr.bin/mandoc/man_html.c13
-rw-r--r--usr.bin/mandoc/man_macro.c7
-rw-r--r--usr.bin/mandoc/man_term.c36
-rw-r--r--usr.bin/mandoc/man_validate.c36
-rw-r--r--usr.bin/mandoc/mandoc.h135
-rw-r--r--usr.bin/mandoc/mdoc.314
-rw-r--r--usr.bin/mandoc/mdoc.c66
-rw-r--r--usr.bin/mandoc/mdoc.h11
-rw-r--r--usr.bin/mandoc/mdoc_html.c9
-rw-r--r--usr.bin/mandoc/mdoc_macro.c6
-rw-r--r--usr.bin/mandoc/mdoc_term.c53
-rw-r--r--usr.bin/mandoc/mdoc_validate.c41
-rw-r--r--usr.bin/mandoc/roff.321
-rw-r--r--usr.bin/mandoc/roff.c140
-rw-r--r--usr.bin/mandoc/roff.h6
-rw-r--r--usr.bin/mandoc/tbl.c571
-rw-r--r--usr.bin/mandoc/tbl.h34
-rw-r--r--usr.bin/mandoc/tbl_data.c215
-rw-r--r--usr.bin/mandoc/tbl_extern.h183
-rw-r--r--usr.bin/mandoc/tbl_html.c73
-rw-r--r--usr.bin/mandoc/tbl_layout.c382
-rw-r--r--usr.bin/mandoc/tbl_option.c197
-rw-r--r--usr.bin/mandoc/tbl_opts.c260
-rw-r--r--usr.bin/mandoc/tbl_term.c681
-rw-r--r--usr.bin/mandoc/tbl_tree.c88
-rw-r--r--usr.bin/mandoc/term.c8
-rw-r--r--usr.bin/mandoc/term.h13
-rw-r--r--usr.bin/mandoc/term_ascii.c7
-rw-r--r--usr.bin/mandoc/tree.c115
37 files changed, 1859 insertions, 1829 deletions
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile
index 4c469a34fe5..0df572bdefe 100644
--- a/usr.bin/mandoc/Makefile
+++ b/usr.bin/mandoc/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.50 2010/12/25 13:23:03 schwarze Exp $
+# $OpenBSD: Makefile,v 1.51 2011/01/04 22:28:17 schwarze Exp $
.include <bsd.own.mk>
@@ -10,15 +10,14 @@ CFLAGS+=-W -Wall -Wstrict-prototypes
CFLAGS+=-Wno-unused-parameter
.endif
-SRCS= roff.c mandoc.c
+SRCS= roff.c tbl.c tbl_opts.c tbl_layout.c tbl_data.c mandoc.c
SRCS+= mdoc_macro.c mdoc.c mdoc_hash.c mdoc_strings.c \
mdoc_argv.c mdoc_validate.c lib.c att.c \
arch.c vol.c msec.c st.c
SRCS+= man_macro.c man.c man_hash.c man_validate.c man_argv.c
SRCS+= main.c mdoc_term.c chars.c term.c tree.c man_term.c
SRCS+= html.c mdoc_html.c man_html.c out.c
-SRCS+= term_ps.c term_ascii.c
-SRCS+= tbl.c tbl_data.c tbl_layout.c tbl_option.c tbl_term.c tbl_tree.c
+SRCS+= term_ps.c term_ascii.c tbl_term.c tbl_html.c
PROG= mandoc
diff --git a/usr.bin/mandoc/chars.c b/usr.bin/mandoc/chars.c
index e3fe1a44d76..e3b192e6d70 100644
--- a/usr.bin/mandoc/chars.c
+++ b/usr.bin/mandoc/chars.c
@@ -1,4 +1,4 @@
-/* $Id: chars.c,v 1.14 2010/09/20 20:43:38 schwarze Exp $ */
+/* $Id: chars.c,v 1.15 2011/01/04 22:28:17 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -50,22 +50,22 @@ struct ln {
#include "chars.in"
-struct tbl {
+struct ctab {
enum chars type;
struct ln **htab;
};
static inline int match(const struct ln *,
const char *, size_t, int);
-static const struct ln *find(struct tbl *, const char *, size_t, int);
+static const struct ln *find(struct ctab *, const char *, size_t, int);
void
chars_free(void *arg)
{
- struct tbl *tab;
+ struct ctab *tab;
- tab = (struct tbl *)arg;
+ tab = (struct ctab *)arg;
free(tab->htab);
free(tab);
@@ -75,7 +75,7 @@ chars_free(void *arg)
void *
chars_init(enum chars type)
{
- struct tbl *tab;
+ struct ctab *tab;
struct ln **htab;
struct ln *pp;
int i, hash;
@@ -87,7 +87,7 @@ chars_init(enum chars type)
* (they're in-line re-ordered during lookup).
*/
- tab = malloc(sizeof(struct tbl));
+ tab = malloc(sizeof(struct ctab));
if (NULL == tab) {
perror(NULL);
exit((int)MANDOCLEVEL_SYSERR);
@@ -126,7 +126,7 @@ chars_spec2cp(void *arg, const char *p, size_t sz)
{
const struct ln *ln;
- ln = find((struct tbl *)arg, p, sz, CHARS_CHAR);
+ ln = find((struct ctab *)arg, p, sz, CHARS_CHAR);
if (NULL == ln)
return(-1);
return(ln->unicode);
@@ -141,7 +141,7 @@ chars_res2cp(void *arg, const char *p, size_t sz)
{
const struct ln *ln;
- ln = find((struct tbl *)arg, p, sz, CHARS_STRING);
+ ln = find((struct ctab *)arg, p, sz, CHARS_STRING);
if (NULL == ln)
return(-1);
return(ln->unicode);
@@ -156,7 +156,7 @@ chars_spec2str(void *arg, const char *p, size_t sz, size_t *rsz)
{
const struct ln *ln;
- ln = find((struct tbl *)arg, p, sz, CHARS_CHAR);
+ ln = find((struct ctab *)arg, p, sz, CHARS_CHAR);
if (NULL == ln)
return(NULL);
@@ -173,7 +173,7 @@ chars_res2str(void *arg, const char *p, size_t sz, size_t *rsz)
{
const struct ln *ln;
- ln = find((struct tbl *)arg, p, sz, CHARS_STRING);
+ ln = find((struct ctab *)arg, p, sz, CHARS_STRING);
if (NULL == ln)
return(NULL);
@@ -183,7 +183,7 @@ chars_res2str(void *arg, const char *p, size_t sz, size_t *rsz)
static const struct ln *
-find(struct tbl *tab, const char *p, size_t sz, int type)
+find(struct ctab *tab, const char *p, size_t sz, int type)
{
struct ln *pp, *prev;
struct ln **htab;
diff --git a/usr.bin/mandoc/html.h b/usr.bin/mandoc/html.h
index 61c66b7865e..8ae7bd7db92 100644
--- a/usr.bin/mandoc/html.h
+++ b/usr.bin/mandoc/html.h
@@ -1,4 +1,4 @@
-/* $Id: html.h,v 1.11 2010/12/25 13:23:03 schwarze Exp $ */
+/* $Id: html.h,v 1.12 2011/01/04 22:28:17 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -138,6 +138,7 @@ struct tag *print_otag(struct html *, enum htmltag,
void print_tagq(struct html *, const struct tag *);
void print_stagq(struct html *, const struct tag *);
void print_text(struct html *, const char *);
+void print_tbl(struct html *, const struct tbl_span *);
void bufcat_su(struct html *, const char *,
const struct roffsu *);
diff --git a/usr.bin/mandoc/libroff.h b/usr.bin/mandoc/libroff.h
new file mode 100644
index 00000000000..17e4f8fef69
--- /dev/null
+++ b/usr.bin/mandoc/libroff.h
@@ -0,0 +1,62 @@
+/* $Id: libroff.h,v 1.1 2011/01/04 22:28:17 schwarze Exp $ */
+/*
+ * Copyright (c) 2009, 2010, 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
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef LIBROFF_H
+#define LIBROFF_H
+
+__BEGIN_DECLS
+
+enum tbl_part {
+ TBL_PART_OPTS, /* in options (first line) */
+ TBL_PART_LAYOUT, /* describing layout */
+ TBL_PART_DATA, /* creating data rows */
+ TBL_PART_CDATA /* continue previous row */
+};
+
+struct tbl_node {
+ mandocmsg msg; /* status messages */
+ void *data; /* privdata for messages */
+ int pos; /* invocation column */
+ int line; /* invocation line */
+ enum tbl_part part;
+ struct tbl opts;
+ struct tbl_row *first_row;
+ struct tbl_row *last_row;
+ struct tbl_span *first_span;
+ struct tbl_span *last_span;
+ struct tbl_head *first_head;
+ struct tbl_head *last_head;
+ struct tbl_node *next;
+};
+
+#define TBL_MSG(tblp, type, line, col) \
+ (*(tblp)->msg)((type), (tblp)->data, (line), (col), NULL)
+
+struct tbl_node *tbl_alloc(int, int, void *, mandocmsg);
+void tbl_restart(int, int, struct tbl_node *);
+void tbl_free(struct tbl_node *);
+void tbl_reset(struct tbl_node *);
+enum rofferr tbl_read(struct tbl_node *, int, const char *, int);
+int tbl_option(struct tbl_node *, int, const char *);
+int tbl_layout(struct tbl_node *, int, const char *);
+int tbl_data(struct tbl_node *, int, const char *);
+int tbl_cdata(struct tbl_node *, int, const char *);
+const struct tbl_span *tbl_span(const struct tbl_node *);
+void tbl_end(struct tbl_node *);
+
+__END_DECLS
+
+#endif /*LIBROFF_H*/
diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c
index 116d051262c..9715f047c89 100644
--- a/usr.bin/mandoc/main.c
+++ b/usr.bin/mandoc/main.c
@@ -1,6 +1,6 @@
-/* $Id: main.c,v 1.63 2011/01/03 23:39:27 schwarze Exp $ */
+/* $Id: main.c,v 1.64 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -162,9 +162,21 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
"bad comment style",
"unknown escape sequence",
"unterminated quoted string",
+
+ /* related to tables */
+ "extra data cells",
"generic error",
+ /* related to tables */
+ "bad table syntax",
+ "bad table option",
+ "bad table layout",
+ "no table layout cells specified",
+ "no table data cells specified",
+ "ignore data in cell",
+ "data block still open",
+
"input stack limit exceeded, infinite loop?",
"skipping bad character",
"skipping text before the first section header",
@@ -182,7 +194,6 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
"missing list type",
"line argument(s) will be lost",
"body argument(s) will be lost",
- "tbl(1) error",
"generic fatal error",
@@ -509,10 +520,7 @@ fdesc(struct curparse *curp)
}
assert(curp->roff);
- if ( ! roff_endparse(curp->roff)) {
- assert(MANDOCLEVEL_FATAL <= file_status);
- goto cleanup;
- }
+ roff_endparse(curp->roff);
/*
* With -Wstop and warnings or errors of at least
@@ -781,7 +789,7 @@ rerun:
continue;
} else
break;
- case (ROFF_CONT):
+ default:
break;
}
@@ -799,9 +807,20 @@ rerun:
* Lastly, push down into the parsers themselves. One
* of these will have already been set in the pset()
* routine.
+ * If libroff returns ROFF_TBL, then add it to the
+ * currently open parse. Since we only get here if
+ * there does exist data (see tbl_data.c), we're
+ * guaranteed that something's been allocated.
*/
- if (curp->man || curp->mdoc) {
+ if (ROFF_TBL == rr) {
+ assert(curp->man || curp->mdoc);
+ if (curp->man)
+ man_addspan(curp->man, roff_span(curp->roff));
+ else
+ mdoc_addspan(curp->mdoc, roff_span(curp->roff));
+
+ } else if (curp->man || curp->mdoc) {
rc = curp->man ?
man_parseln(curp->man,
curp->line, ln.buf, of) :
diff --git a/usr.bin/mandoc/man.3 b/usr.bin/mandoc/man.3
index aff3499eb12..a1a9ea08640 100644
--- a/usr.bin/mandoc/man.3
+++ b/usr.bin/mandoc/man.3
@@ -1,6 +1,6 @@
-.\" $Id: man.3,v 1.19 2010/12/22 00:33:25 schwarze Exp $
+.\" $Id: man.3,v 1.20 2011/01/04 22:28:17 schwarze Exp $
.\"
-.\" Copyright (c) 2009-2010 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2009, 2010, 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
@@ -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: December 22 2010 $
+.Dd $Mdocdate: January 4 2011 $
.Dt MAN 3
.Os
.Sh NAME
@@ -31,6 +31,11 @@
.In mandoc.h
.In man.h
.Vt extern const char * const * man_macronames;
+.Ft int
+.Fo man_addspan
+.Fa "struct man *man"
+.Fa "const struct tbl_span *span"
+.Fc
.Ft "struct man *"
.Fo man_alloc
.Fa "struct regset *regs"
@@ -101,6 +106,9 @@ for details.
.El
.Ss Functions
.Bl -ohang
+.It Fn man_addspan
+Add a table span to the parsing stream.
+Returns 0 on failure, 1 on success.
.It Fn man_alloc
Allocates a parsing structure.
The
diff --git a/usr.bin/mandoc/man.c b/usr.bin/mandoc/man.c
index c0c6e34d119..2f534e1d9d1 100644
--- a/usr.bin/mandoc/man.c
+++ b/usr.bin/mandoc/man.c
@@ -1,6 +1,6 @@
-/* $Id: man.c,v 1.51 2011/01/01 17:38:11 schwarze Exp $ */
+/* $Id: man.c,v 1.52 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 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
@@ -26,10 +26,6 @@
#include "libman.h"
#include "libmandoc.h"
-#include "out.h"
-#include "term.h"
-#include "tbl.h"
-
const char *const __man_macronames[MAN_MAX] = {
"br", "TH", "SH", "SS",
"TP", "LP", "PP", "P",
@@ -39,7 +35,7 @@ const char *const __man_macronames[MAN_MAX] = {
"RI", "na", "sp", "nf",
"fi", "RE", "RS", "DT",
"UC", "PD", "AT", "in",
- "TS", "TE", "ft",
+ "ft"
};
const char * const *man_macronames = __man_macronames;
@@ -48,6 +44,8 @@ static struct man_node *man_node_alloc(int, int,
enum man_type, enum mant);
static int man_node_append(struct man *,
struct man_node *);
+static int man_span_alloc(struct man *,
+ const struct tbl_span *);
static void man_node_free(struct man_node *);
static void man_node_unlink(struct man *,
struct man_node *);
@@ -55,6 +53,7 @@ static int man_ptext(struct man *, int, char *, int);
static int man_pmacro(struct man *, int, char *, int);
static void man_free1(struct man *);
static void man_alloc1(struct man *);
+static int man_descope(struct man *, int, int);
const struct man_node *
@@ -124,22 +123,10 @@ man_endparse(struct man *m)
int
man_parseln(struct man *m, int ln, char *buf, int offs)
{
- struct man_node *n;
if (MAN_HALT & m->flags)
return(0);
- n = m->last;
-
- if (n && MAN_TS == n->tok && MAN_BODY == n->type &&
- strncmp(buf+offs, ".TE", 3)) {
- n = n->parent;
- if ( ! tbl_read(n->data.TS, "man tbl parser",
- ln, buf+offs, strlen(buf+offs)))
- man_nmsg(m, n, MANDOCERR_TBL);
- return(1);
- }
-
return(('.' == buf[offs] || '\'' == buf[offs]) ?
man_pmacro(m, ln, buf, offs) :
man_ptext(m, ln, buf, offs));
@@ -224,6 +211,8 @@ man_node_append(struct man *man, struct man_node *p)
man->last = p;
switch (p->type) {
+ case (MAN_TBL):
+ /* FALLTHROUGH */
case (MAN_TEXT):
if ( ! man_valid_post(man))
return(0);
@@ -301,6 +290,21 @@ man_block_alloc(struct man *m, int line, int pos, enum mant tok)
return(1);
}
+static int
+man_span_alloc(struct man *m, const struct tbl_span *span)
+{
+ struct man_node *n;
+
+ /* FIXME: grab from span */
+ n = man_node_alloc(0, 0, MAN_TBL, MAN_MAX);
+ n->span = span;
+
+ if ( ! man_node_append(m, n))
+ return(0);
+
+ m->next = MAN_NEXT_SIBLING;
+ return(1);
+}
int
man_word_alloc(struct man *m, int line, int pos, const char *word)
@@ -335,8 +339,6 @@ man_node_free(struct man_node *p)
if (p->string)
free(p->string);
- if (p->data.TS)
- tbl_free(p->data.TS);
free(p);
}
@@ -353,6 +355,40 @@ man_node_delete(struct man *m, struct man_node *p)
}
+int
+man_addspan(struct man *m, const struct tbl_span *sp)
+{
+
+ if ( ! man_span_alloc(m, sp))
+ return(0);
+ return(man_descope(m, 0, 0));
+}
+
+static int
+man_descope(struct man *m, int line, int offs)
+{
+ /*
+ * Co-ordinate what happens with having a next-line scope open:
+ * first close out the element scope (if applicable), then close
+ * out the block scope (also if applicable).
+ */
+
+ if (MAN_ELINE & m->flags) {
+ m->flags &= ~MAN_ELINE;
+ if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
+ return(0);
+ }
+
+ if ( ! (MAN_BLINE & m->flags))
+ return(1);
+ m->flags &= ~MAN_BLINE;
+
+ if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
+ return(0);
+ return(man_body_alloc(m, line, offs, m->last->tok));
+}
+
+
static int
man_ptext(struct man *m, int line, char *buf, int offs)
{
@@ -372,7 +408,7 @@ man_ptext(struct man *m, int line, char *buf, int offs)
if (MAN_LITERAL & m->flags) {
if ( ! man_word_alloc(m, line, offs, buf + offs))
return(0);
- goto descope;
+ return(man_descope(m, line, offs));
}
/* Pump blank lines directly into the backend. */
@@ -384,7 +420,7 @@ man_ptext(struct man *m, int line, char *buf, int offs)
/* Allocate a blank entry. */
if ( ! man_word_alloc(m, line, offs, ""))
return(0);
- goto descope;
+ return(man_descope(m, line, offs));
}
/*
@@ -421,26 +457,7 @@ man_ptext(struct man *m, int line, char *buf, int offs)
if (mandoc_eos(buf, (size_t)i, 0))
m->last->flags |= MAN_EOS;
-descope:
- /*
- * Co-ordinate what happens with having a next-line scope open:
- * first close out the element scope (if applicable), then close
- * out the block scope (also if applicable).
- */
-
- if (MAN_ELINE & m->flags) {
- m->flags &= ~MAN_ELINE;
- if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
- return(0);
- }
-
- if ( ! (MAN_BLINE & m->flags))
- return(1);
- m->flags &= ~MAN_BLINE;
-
- if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
- return(0);
- return(man_body_alloc(m, line, offs, m->last->tok));
+ return(man_descope(m, line, offs));
}
diff --git a/usr.bin/mandoc/man.h b/usr.bin/mandoc/man.h
index 7daa88a4153..f459db294f3 100644
--- a/usr.bin/mandoc/man.h
+++ b/usr.bin/mandoc/man.h
@@ -1,6 +1,6 @@
-/* $Id: man.h,v 1.32 2010/12/27 23:57:13 schwarze Exp $ */
+/* $Id: man.h,v 1.33 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2009, 2010, 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
@@ -53,8 +53,6 @@ enum mant {
MAN_PD,
MAN_AT,
MAN_in,
- MAN_TS,
- MAN_TE,
MAN_ft,
MAN_MAX
};
@@ -68,7 +66,8 @@ enum man_type {
MAN_ROOT,
MAN_BLOCK,
MAN_HEAD,
- MAN_BODY
+ MAN_BODY,
+ MAN_TBL
};
/*
@@ -83,10 +82,6 @@ struct man_meta {
char *source; /* `TH' source (e.g., GNU) */
};
-union man_data {
- struct tbl *TS;
-};
-
/*
* Single node in tree-linked AST.
*/
@@ -106,7 +101,7 @@ struct man_node {
char *string; /* TEXT node argument */
struct man_node *head; /* BLOCK node HEAD ptr */
struct man_node *body; /* BLOCK node BODY ptr */
- union man_data data;
+ const struct tbl_span *span; /* TBL */
};
/*
@@ -124,6 +119,8 @@ struct man *man_alloc(struct regset *, void *, mandocmsg);
void man_reset(struct man *);
int man_parseln(struct man *, int, char *, int);
int man_endparse(struct man *);
+int man_addspan(struct man *,
+ const struct tbl_span *);
const struct man_node *man_node(const struct man *);
const struct man_meta *man_meta(const struct man *);
diff --git a/usr.bin/mandoc/man_html.c b/usr.bin/mandoc/man_html.c
index 919bda0d2a4..075f7ddd187 100644
--- a/usr.bin/mandoc/man_html.c
+++ b/usr.bin/mandoc/man_html.c
@@ -1,6 +1,6 @@
-/* $Id: man_html.c,v 1.28 2011/01/04 01:15:39 schwarze Exp $ */
+/* $Id: man_html.c,v 1.29 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 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
@@ -107,8 +107,6 @@ static const struct htmlman mans[MAN_MAX] = {
{ man_ign_pre, NULL }, /* PD */
{ man_ign_pre, NULL }, /* AT */
{ man_in_pre, NULL }, /* in */
- { NULL, NULL }, /* TS */
- { NULL, NULL }, /* TE */
{ man_ign_pre, NULL }, /* ft */
};
@@ -196,11 +194,12 @@ print_man_node(MAN_ARGS)
break;
case (MAN_TEXT):
print_text(h, n->string);
-
if (MANH_LITERAL & mh->fl)
print_otag(h, TAG_BR, 0, NULL);
-
return;
+ case (MAN_TBL):
+ print_tbl(h, n->span);
+ break;
default:
/*
* Close out scope of font prior to opening a macro
@@ -228,7 +227,7 @@ print_man_node(MAN_ARGS)
case (MAN_ROOT):
man_root_post(m, n, mh, h);
break;
- case (MAN_TEXT):
+ case (MAN_TBL):
break;
default:
if (mans[n->tok].post)
diff --git a/usr.bin/mandoc/man_macro.c b/usr.bin/mandoc/man_macro.c
index cb467dd6f2c..a30b585b91a 100644
--- a/usr.bin/mandoc/man_macro.c
+++ b/usr.bin/mandoc/man_macro.c
@@ -1,4 +1,4 @@
-/* $Id: man_macro.c,v 1.25 2010/12/19 07:53:12 schwarze Exp $ */
+/* $Id: man_macro.c,v 1.26 2011/01/04 22:28:17 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -75,8 +75,6 @@ const struct man_macro __man_macros[MAN_MAX] = {
{ in_line_eoln, 0 }, /* PD */
{ in_line_eoln, 0 }, /* AT */
{ in_line_eoln, 0 }, /* in */
- { blk_exp, MAN_EXPLICIT }, /* TS */
- { blk_close, 0 }, /* TE */
{ in_line_eoln, 0 }, /* ft */
};
@@ -259,9 +257,6 @@ blk_close(MACRO_PROT_ARGS)
case (MAN_RE):
ntok = MAN_RS;
break;
- case (MAN_TE):
- ntok = MAN_TS;
- break;
default:
abort();
/* NOTREACHED */
diff --git a/usr.bin/mandoc/man_term.c b/usr.bin/mandoc/man_term.c
index 49bac5b5943..27abd27c91b 100644
--- a/usr.bin/mandoc/man_term.c
+++ b/usr.bin/mandoc/man_term.c
@@ -1,6 +1,6 @@
-/* $Id: man_term.c,v 1.57 2011/01/04 01:15:39 schwarze Exp $ */
+/* $Id: man_term.c,v 1.58 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -29,7 +29,6 @@
#include "term.h"
#include "chars.h"
#include "main.h"
-#include "tbl.h"
#define INDENT 7
#define HALFINDENT 3
@@ -92,7 +91,6 @@ static int pre_ign(DECL_ARGS);
static int pre_in(DECL_ARGS);
static int pre_literal(DECL_ARGS);
static int pre_sp(DECL_ARGS);
-static int pre_TS(DECL_ARGS);
static int pre_ft(DECL_ARGS);
static void post_IP(DECL_ARGS);
@@ -135,8 +133,6 @@ static const struct termact termacts[MAN_MAX] = {
{ pre_ign, NULL, 0 }, /* PD */
{ pre_ign, NULL, 0 }, /* AT */
{ pre_in, NULL, MAN_NOTEXT }, /* in */
- { pre_TS, NULL, 0 }, /* TS */
- { NULL, NULL, 0 }, /* TE */
{ pre_ft, NULL, MAN_NOTEXT }, /* ft */
};
@@ -844,21 +840,6 @@ post_RS(DECL_ARGS)
}
-/* ARGSUSED */
-static int
-pre_TS(DECL_ARGS)
-{
-
- if (MAN_BLOCK != n->type)
- return(0);
-
- if (tbl_close(p, n->data.TS, "man tbl postprocess", n->line))
- tbl_write(p, n->data.TS);
-
- return(0);
-}
-
-
static void
print_man_node(DECL_ARGS)
{
@@ -889,6 +870,11 @@ print_man_node(DECL_ARGS)
p->maxrmargin = rmax;
}
break;
+ case (MAN_TBL):
+ if (TBL_SPAN_FIRST & n->span->flags)
+ term_newln(p);
+ term_tbl(p, n->span);
+ break;
default:
if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
term_fontrepl(p, TERMFONT_NONE);
@@ -900,11 +886,17 @@ print_man_node(DECL_ARGS)
if (c && n->child)
print_man_nodelist(p, mt, n->child, m);
- if (MAN_TEXT != n->type) {
+ switch (n->type) {
+ case (MAN_TEXT):
+ /* FALLTHROUGH */
+ case (MAN_TBL):
+ break;
+ default:
if (termacts[n->tok].post)
(*termacts[n->tok].post)(p, mt, n, m);
if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
term_fontrepl(p, TERMFONT_NONE);
+ break;
}
if (MAN_EOS & n->flags)
diff --git a/usr.bin/mandoc/man_validate.c b/usr.bin/mandoc/man_validate.c
index 776d1ac1d64..6da4350a1f0 100644
--- a/usr.bin/mandoc/man_validate.c
+++ b/usr.bin/mandoc/man_validate.c
@@ -1,6 +1,6 @@
-/* $Id: man_validate.c,v 1.37 2010/12/19 07:53:12 schwarze Exp $ */
+/* $Id: man_validate.c,v 1.38 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -30,10 +30,6 @@
#include "libman.h"
#include "libmandoc.h"
-#include "out.h"
-#include "term.h"
-#include "tbl.h"
-
#define CHKARGS struct man *m, struct man_node *n
typedef int (*v_check)(CHKARGS);
@@ -60,7 +56,6 @@ static int post_AT(CHKARGS);
static int post_fi(CHKARGS);
static int post_nf(CHKARGS);
static int post_TH(CHKARGS);
-static int post_TS(CHKARGS);
static int post_UC(CHKARGS);
static v_check posts_at[] = { post_AT, NULL };
@@ -73,7 +68,6 @@ 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_th[] = { check_ge2, check_le5, check_title, post_TH, NULL };
-static v_check posts_ts[] = { post_TS, NULL };
static v_check posts_uc[] = { post_UC, NULL };
static v_check pres_bline[] = { check_bline, NULL };
@@ -111,8 +105,6 @@ static const struct man_valid man_valids[MAN_MAX] = {
{ NULL, NULL }, /* PD */
{ NULL, posts_at }, /* AT */
{ NULL, NULL }, /* in */
- { NULL, posts_ts }, /* TS */
- { NULL, NULL }, /* TE */
{ NULL, posts_ft }, /* ft */
};
@@ -122,10 +114,16 @@ man_valid_pre(struct man *m, struct man_node *n)
{
v_check *cp;
- if (MAN_TEXT == n->type)
- return(1);
- if (MAN_ROOT == n->type)
+ switch (n->type) {
+ case (MAN_TEXT):
+ /* FALLTHROUGH */
+ case (MAN_ROOT):
+ /* FALLTHROUGH */
+ case (MAN_TBL):
return(1);
+ default:
+ break;
+ }
if (NULL == (cp = man_valids[n->tok].pres))
return(1);
@@ -150,6 +148,8 @@ man_valid_post(struct man *m)
return(check_text(m, m->last));
case (MAN_ROOT):
return(check_root(m, m->last));
+ case (MAN_TBL):
+ return(1);
default:
break;
}
@@ -572,13 +572,3 @@ post_AT(CHKARGS)
m->meta.source = mandoc_strdup(p);
return(1);
}
-
-static int
-post_TS(CHKARGS)
-{
-
- if (MAN_HEAD == n->type)
- n->parent->data.TS = tbl_alloc();
-
- return(1);
-}
diff --git a/usr.bin/mandoc/mandoc.h b/usr.bin/mandoc/mandoc.h
index e30929c9521..366614ef138 100644
--- a/usr.bin/mandoc/mandoc.h
+++ b/usr.bin/mandoc/mandoc.h
@@ -1,6 +1,6 @@
-/* $Id: mandoc.h,v 1.26 2011/01/03 23:39:27 schwarze Exp $ */
+/* $Id: mandoc.h,v 1.27 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010, 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
@@ -100,8 +100,20 @@ enum mandocerr {
MANDOCERR_BADESCAPE, /* unknown escape sequence */
MANDOCERR_BADQUOTE, /* unterminated quoted string */
+ /* related to tables */
+ MANDOCERR_TBLEXTRADAT, /* extra data cells */
+
MANDOCERR_ERROR, /* ===== start of errors ===== */
+ /* related to tables */
+ MANDOCERR_TBL, /* bad table syntax */
+ MANDOCERR_TBLOPT, /* bad table option */
+ MANDOCERR_TBLLAYOUT, /* bad table layout */
+ MANDOCERR_TBLNOLAYOUT, /* no table layout cells specified */
+ MANDOCERR_TBLNODATA, /* no table data cells specified */
+ MANDOCERR_TBLIGNDATA, /* ignore data in cell */
+ MANDOCERR_TBLBLOCK, /* data block still open */
+
MANDOCERR_ROFFLOOP, /* input stack limit exceeded, infinite loop? */
MANDOCERR_BADCHAR, /* skipping bad character */
MANDOCERR_NOTEXT, /* skipping text before the first section header */
@@ -120,7 +132,6 @@ enum mandocerr {
MANDOCERR_LISTTYPE, /* missing list type */
MANDOCERR_ARGSLOST, /* line argument(s) will be lost */
MANDOCERR_BODYLOST, /* body argument(s) will be lost */
- MANDOCERR_TBL, /* tbl(1) error */
MANDOCERR_FATAL, /* ===== start of fatal errors ===== */
@@ -137,6 +148,124 @@ enum mandocerr {
MANDOCERR_MAX
};
+struct tbl {
+ char tab; /* cell-separator */
+ char decimal; /* decimal point */
+ int linesize;
+ char delims[2]; /* FIXME: deprecate */
+ int opts;
+#define TBL_OPT_CENTRE (1 << 0)
+#define TBL_OPT_EXPAND (1 << 1)
+#define TBL_OPT_BOX (1 << 2)
+#define TBL_OPT_DBOX (1 << 3)
+#define TBL_OPT_ALLBOX (1 << 4)
+#define TBL_OPT_NOKEEP (1 << 5)
+#define TBL_OPT_NOSPACE (1 << 6)
+ int cols; /* number of columns */
+};
+
+enum tbl_headt {
+ TBL_HEAD_DATA, /* plug in data from tbl_dat */
+ TBL_HEAD_VERT, /* vertical spacer */
+ TBL_HEAD_DVERT /* double-vertical spacer */
+};
+
+/*
+ * The head of a table specifies all of its columns. When formatting a
+ * tbl_span, iterate over these and plug in data from the tbl_span when
+ * appropriate, using tbl_cell as a guide to placement.
+ */
+struct tbl_head {
+ enum tbl_headt pos;
+ int ident; /* 0 <= unique id < cols */
+ struct tbl_head *next;
+ struct tbl_head *prev;
+};
+
+enum tbl_cellt {
+ TBL_CELL_CENTRE, /* c, C */
+ TBL_CELL_RIGHT, /* r, R */
+ TBL_CELL_LEFT, /* l, L */
+ TBL_CELL_NUMBER, /* n, N */
+ TBL_CELL_SPAN, /* s, S */
+ TBL_CELL_LONG, /* a, A */
+ TBL_CELL_DOWN, /* ^ */
+ TBL_CELL_HORIZ, /* _, - */
+ TBL_CELL_DHORIZ, /* = */
+ TBL_CELL_VERT, /* | */
+ TBL_CELL_DVERT, /* || */
+ TBL_CELL_MAX
+};
+
+/*
+ * A cell in a layout row.
+ */
+struct tbl_cell {
+ struct tbl_cell *next;
+ enum tbl_cellt pos;
+ int spacing;
+ int flags;
+#define TBL_CELL_TALIGN (1 << 0) /* t, T */
+#define TBL_CELL_BALIGN (1 << 1) /* d, D */
+#define TBL_CELL_BOLD (1 << 2) /* fB, B, b */
+#define TBL_CELL_ITALIC (1 << 3) /* fI, I, i */
+#define TBL_CELL_EQUAL (1 << 4) /* e, E */
+#define TBL_CELL_UP (1 << 5) /* u, U */
+#define TBL_CELL_WIGN (1 << 6) /* z, Z */
+ struct tbl_head *head;
+};
+
+/*
+ * A layout row.
+ */
+struct tbl_row {
+ struct tbl_row *next;
+ struct tbl_cell *first;
+ struct tbl_cell *last;
+};
+
+enum tbl_datt {
+ TBL_DATA_NONE,
+ TBL_DATA_DATA,
+ TBL_DATA_HORIZ,
+ TBL_DATA_DHORIZ,
+ TBL_DATA_NHORIZ,
+ TBL_DATA_NDHORIZ
+};
+
+/*
+ * A cell within a row of data. The "string" field contains the actual
+ * string value that's in the cell. The rest is layout.
+ */
+struct tbl_dat {
+ struct tbl_cell *layout; /* layout cell: CAN BE NULL */
+ struct tbl_dat *next;
+ char *string;
+ enum tbl_datt pos;
+};
+
+enum tbl_spant {
+ TBL_SPAN_DATA, /* span consists of data */
+ TBL_SPAN_HORIZ, /* span is horizontal line */
+ TBL_SPAN_DHORIZ /* span is double horizontal line */
+};
+
+/*
+ * A row of data in a table.
+ */
+struct tbl_span {
+ struct tbl *tbl;
+ struct tbl_head *head;
+ struct tbl_row *layout; /* layout row: CAN BE NULL */
+ struct tbl_dat *first;
+ struct tbl_dat *last;
+ int flags;
+#define TBL_SPAN_FIRST (1 << 0)
+#define TBL_SPAN_LAST (1 << 1)
+ enum tbl_spant pos;
+ struct tbl_span *next;
+};
+
/*
* Available registers (set in libroff, accessed elsewhere).
*/
diff --git a/usr.bin/mandoc/mdoc.3 b/usr.bin/mandoc/mdoc.3
index 58c2116cd21..556b5792546 100644
--- a/usr.bin/mandoc/mdoc.3
+++ b/usr.bin/mandoc/mdoc.3
@@ -1,6 +1,6 @@
-.\" $Id: mdoc.3,v 1.14 2010/12/22 00:33:25 schwarze Exp $
+.\" $Id: mdoc.3,v 1.15 2011/01/04 22:28:17 schwarze Exp $
.\"
-.\" Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
@@ -15,7 +15,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: December 22 2010 $
+.Dd $Mdocdate: January 4 2011 $
.Dt MDOC 3
.Os
.Sh NAME
@@ -33,6 +33,11 @@
.In mdoc.h
.Vt extern const char * const * mdoc_macronames;
.Vt extern const char * const * mdoc_argnames;
+.Ft int
+.Fo mdoc_addspan
+.Fa "struct mdoc *mdoc"
+.Fa "const struct tbl_span *span"
+.Fc
.Ft "struct mdoc *"
.Fo mdoc_alloc
.Fa "struct regset *regs"
@@ -92,6 +97,9 @@ for details.
.El
.Ss Functions
.Bl -ohang
+.It Fn mdoc_addspan
+Add a table span to the parsing stream.
+Returns 0 on failure, 1 on success.
.It Fn mdoc_alloc
Allocates a parsing structure.
The
diff --git a/usr.bin/mandoc/mdoc.c b/usr.bin/mandoc/mdoc.c
index 1060aa53fc1..51386a989ab 100644
--- a/usr.bin/mandoc/mdoc.c
+++ b/usr.bin/mandoc/mdoc.c
@@ -1,6 +1,6 @@
-/* $Id: mdoc.c,v 1.76 2011/01/01 17:38:11 schwarze Exp $ */
+/* $Id: mdoc.c,v 1.77 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -28,10 +28,6 @@
#include "libmdoc.h"
#include "libmandoc.h"
-#include "out.h"
-#include "term.h"
-#include "tbl.h"
-
const char *const __mdoc_macronames[MDOC_MAX] = {
"Ap", "Dd", "Dt", "Os",
"Sh", "Ss", "Pp", "D1",
@@ -69,7 +65,7 @@ const char *const __mdoc_macronames[MDOC_MAX] = {
/* LINTED */
"Dx", "%Q", "br", "sp",
/* LINTED */
- "%U", "Ta", "TS", "TE"
+ "%U", "Ta"
};
const char *const __mdoc_argnames[MDOC_ARG_MAX] = {
@@ -98,6 +94,8 @@ static int node_append(struct mdoc *,
struct mdoc_node *);
static int mdoc_ptext(struct mdoc *, int, char *, int);
static int mdoc_pmacro(struct mdoc *, int, char *, int);
+static int mdoc_span_alloc(struct mdoc *,
+ const struct tbl_span *);
const struct mdoc_node *
@@ -221,6 +219,24 @@ mdoc_endparse(struct mdoc *m)
return(0);
}
+int
+mdoc_addspan(struct mdoc *m, const struct tbl_span *sp)
+{
+
+ if (MDOC_HALT & m->flags)
+ return(0);
+
+ /* No text before an initial macro. */
+
+ if (SEC_NONE == m->lastnamed) {
+ /* FIXME: grab from span. */
+ mdoc_pmsg(m, 0, 0, MANDOCERR_NOTEXT);
+ return(1);
+ }
+
+ return(mdoc_span_alloc(m, sp));
+}
+
/*
* Main parse routine. Parses a single line -- really just hands off to
@@ -229,24 +245,12 @@ mdoc_endparse(struct mdoc *m)
int
mdoc_parseln(struct mdoc *m, int ln, char *buf, int offs)
{
- struct mdoc_node *n;
if (MDOC_HALT & m->flags)
return(0);
m->flags |= MDOC_NEWLINE;
- n = m->last;
-
- if (n && MDOC_TS == n->tok && MDOC_BODY == n->type &&
- strncmp(buf+offs, ".TE", 3)) {
- n = n->parent;
- if ( ! tbl_read(n->norm->TS, "mdoc tbl parser",
- ln, buf+offs, strlen(buf+offs)))
- mdoc_nmsg(m, n, MANDOCERR_TBL);
- return(1);
- }
-
/*
* Let the roff nS register switch SYNOPSIS mode early,
* such that the parser knows at all times
@@ -383,6 +387,8 @@ node_append(struct mdoc *mdoc, struct mdoc_node *p)
mdoc->last = p;
switch (p->type) {
+ case (MDOC_TBL):
+ /* FALLTHROUGH */
case (MDOC_TEXT):
if ( ! mdoc_valid_post(mdoc))
return(0);
@@ -499,8 +505,6 @@ mdoc_block_alloc(struct mdoc *m, int line, int pos,
case (MDOC_Bl):
/* FALLTHROUGH */
case (MDOC_Rs):
- /* FALLTHROUGH */
- case (MDOC_TS):
p->norm = mandoc_calloc(1, sizeof(union mdoc_data));
break;
default:
@@ -539,6 +543,22 @@ mdoc_elem_alloc(struct mdoc *m, int line, int pos,
return(1);
}
+static int
+mdoc_span_alloc(struct mdoc *m, const struct tbl_span *sp)
+{
+ struct mdoc_node *n;
+
+ /* FIXME: grab from tbl_span. */
+ n = node_alloc(m, 0, 0, MDOC_MAX, MDOC_TBL);
+ n->span = sp;
+
+ if ( ! node_append(m, n))
+ return(0);
+
+ m->next = MDOC_NEXT_SIBLING;
+ return(1);
+}
+
int
mdoc_word_alloc(struct mdoc *m, int line, int pos, const char *p)
@@ -567,10 +587,6 @@ static void
mdoc_node_free(struct mdoc_node *p)
{
- if (MDOC_TS == p->tok && MDOC_BLOCK == p->type)
- if (p->norm->TS)
- tbl_free(p->norm->TS);
-
if (MDOC_BLOCK == p->type || MDOC_ELEM == p->type)
free(p->norm);
if (p->string)
diff --git a/usr.bin/mandoc/mdoc.h b/usr.bin/mandoc/mdoc.h
index a74b2ebc8d1..b24ac1a0b5e 100644
--- a/usr.bin/mandoc/mdoc.h
+++ b/usr.bin/mandoc/mdoc.h
@@ -1,6 +1,6 @@
-/* $Id: mdoc.h,v 1.41 2010/12/29 00:47:30 schwarze Exp $ */
+/* $Id: mdoc.h,v 1.42 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 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
@@ -143,8 +143,6 @@ enum mdoct {
MDOC_sp,
MDOC__U,
MDOC_Ta,
- MDOC_TS,
- MDOC_TE,
MDOC_MAX
};
@@ -192,6 +190,7 @@ enum mdoc_type {
MDOC_TAIL,
MDOC_BODY,
MDOC_BLOCK,
+ MDOC_TBL,
MDOC_ROOT
};
@@ -370,7 +369,6 @@ union mdoc_data {
struct mdoc_bf Bf;
struct mdoc_bl Bl;
struct mdoc_rs Rs;
- struct tbl *TS;
};
/*
@@ -402,6 +400,7 @@ struct mdoc_node {
struct mdoc_node *body; /* BLOCK */
struct mdoc_node *tail; /* BLOCK */
char *string; /* TEXT */
+ const struct tbl_span *span; /* TBL */
enum mdoc_endbody end; /* BODY */
};
@@ -429,6 +428,8 @@ int mdoc_parseln(struct mdoc *, int, char *, int);
const struct mdoc_node *mdoc_node(const struct mdoc *);
const struct mdoc_meta *mdoc_meta(const struct mdoc *);
int mdoc_endparse(struct mdoc *);
+int mdoc_addspan(struct mdoc *,
+ const struct tbl_span *);
__END_DECLS
diff --git a/usr.bin/mandoc/mdoc_html.c b/usr.bin/mandoc/mdoc_html.c
index 26bda0d55fc..427583b9711 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.44 2010/12/29 00:47:31 schwarze Exp $ */
+/* $Id: mdoc_html.c,v 1.45 2011/01/04 22:28:17 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -239,8 +239,6 @@ static const struct htmlmdoc mdocs[MDOC_MAX] = {
{mdoc_sp_pre, NULL}, /* sp */
{mdoc__x_pre, mdoc__x_post}, /* %U */
{NULL, NULL}, /* Ta */
- {NULL, NULL}, /* TS */
- {NULL, NULL}, /* TE */
};
static const char * const lists[LIST_MAX] = {
@@ -420,6 +418,9 @@ print_mdoc_node(MDOC_ARGS)
case (MDOC_TEXT):
print_text(h, n->string);
return;
+ case (MDOC_TBL):
+ print_tbl(h, n->span);
+ break;
default:
if (mdocs[n->tok].pre && ENDBODY_NOT == n->end)
child = (*mdocs[n->tok].pre)(m, n, h);
@@ -448,6 +449,8 @@ print_mdoc_node(MDOC_ARGS)
case (MDOC_ROOT):
mdoc_root_post(m, n, h);
break;
+ case (MDOC_TBL):
+ break;
default:
if (mdocs[n->tok].post && ENDBODY_NOT == n->end)
(*mdocs[n->tok].post)(m, n, h);
diff --git a/usr.bin/mandoc/mdoc_macro.c b/usr.bin/mandoc/mdoc_macro.c
index 77c4d3d25cf..699ebbb92f6 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.61 2010/12/21 23:46:18 schwarze Exp $ */
+/* $Id: mdoc_macro.c,v 1.62 2011/01/04 22:28:17 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -185,8 +185,6 @@ const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
{ in_line_eoln, 0 }, /* sp */
{ in_line_eoln, 0 }, /* %U */
{ phrase_ta, MDOC_CALLABLE | MDOC_PARSED }, /* Ta */
- { blk_part_exp, MDOC_EXPLICIT }, /* TS */
- { blk_exp_close, MDOC_EXPLICIT }, /* TE */
};
const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
@@ -309,8 +307,6 @@ rew_alt(enum mdoct tok)
return(MDOC_So);
case (MDOC_Xc):
return(MDOC_Xo);
- case (MDOC_TE):
- return(MDOC_TS);
default:
return(tok);
}
diff --git a/usr.bin/mandoc/mdoc_term.c b/usr.bin/mandoc/mdoc_term.c
index 4ee3ee6160f..b97de215fc6 100644
--- a/usr.bin/mandoc/mdoc_term.c
+++ b/usr.bin/mandoc/mdoc_term.c
@@ -1,6 +1,6 @@
-/* $Id: mdoc_term.c,v 1.121 2010/12/29 00:47:31 schwarze Exp $ */
+/* $Id: mdoc_term.c,v 1.122 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -30,7 +30,6 @@
#include "mdoc.h"
#include "chars.h"
#include "main.h"
-#include "tbl.h"
#define INDENT 5
#define HALFINDENT 3
@@ -116,7 +115,6 @@ static int termp_sh_pre(DECL_ARGS);
static int termp_sm_pre(DECL_ARGS);
static int termp_sp_pre(DECL_ARGS);
static int termp_ss_pre(DECL_ARGS);
-static int termp_ts_pre(DECL_ARGS);
static int termp_under_pre(DECL_ARGS);
static int termp_ud_pre(DECL_ARGS);
static int termp_vt_pre(DECL_ARGS);
@@ -246,8 +244,6 @@ static const struct termact termacts[MDOC_MAX] = {
{ termp_sp_pre, NULL }, /* sp */
{ termp_under_pre, termp____post }, /* %U */
{ NULL, NULL }, /* Ta */
- { termp_ts_pre, NULL }, /* TS */
- { NULL, NULL }, /* TE */
};
@@ -312,11 +308,20 @@ print_mdoc_node(DECL_ARGS)
memset(&npair, 0, sizeof(struct termpair));
npair.ppair = pair;
-
- if (MDOC_TEXT == n->type)
- term_word(p, n->string);
- else if (termacts[n->tok].pre && ENDBODY_NOT == n->end)
- chld = (*termacts[n->tok].pre)(p, &npair, m, n);
+
+ switch (n->type) {
+ case (MDOC_TEXT):
+ term_word(p, n->string);
+ break;
+ case (MDOC_TBL):
+ term_tbl(p, n->span);
+ break;
+ default:
+ if (termacts[n->tok].pre && ENDBODY_NOT == n->end)
+ chld = (*termacts[n->tok].pre)
+ (p, &npair, m, n);
+ break;
+ }
/*
* Keeps only work until the end of a line. If a keep was
@@ -353,8 +358,14 @@ print_mdoc_node(DECL_ARGS)
term_fontpopq(p, font);
- if (MDOC_TEXT != n->type && termacts[n->tok].post &&
- ! (MDOC_ENDED & n->flags)) {
+ switch (n->type) {
+ case (MDOC_TEXT):
+ break;
+ case (MDOC_TBL):
+ break;
+ default:
+ if ( ! termacts[n->tok].post || MDOC_ENDED & n->flags)
+ break;
(void)(*termacts[n->tok].post)(p, &npair, m, n);
/*
@@ -372,6 +383,7 @@ print_mdoc_node(DECL_ARGS)
*/
if (ENDBODY_NOSPACE == n->end)
p->flags |= TERMP_NOSPACE;
+ break;
}
if (MDOC_EOS & n->flags)
@@ -2109,21 +2121,6 @@ termp_lk_pre(DECL_ARGS)
/* ARGSUSED */
static int
-termp_ts_pre(DECL_ARGS)
-{
-
- if (MDOC_BLOCK != n->type)
- return(0);
-
- if (tbl_close(p, n->norm->TS, "mdoc tbl postprocess", n->line))
- tbl_write(p, n->norm->TS);
-
- return(0);
-}
-
-
-/* ARGSUSED */
-static int
termp_bk_pre(DECL_ARGS)
{
diff --git a/usr.bin/mandoc/mdoc_validate.c b/usr.bin/mandoc/mdoc_validate.c
index 6cab7c65ca7..b5556f1755b 100644
--- a/usr.bin/mandoc/mdoc_validate.c
+++ b/usr.bin/mandoc/mdoc_validate.c
@@ -1,6 +1,6 @@
-/* $Id: mdoc_validate.c,v 1.83 2011/01/03 23:39:27 schwarze Exp $ */
+/* $Id: mdoc_validate.c,v 1.84 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 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
@@ -32,10 +32,6 @@
#include "libmdoc.h"
#include "libmandoc.h"
-#include "out.h"
-#include "term.h"
-#include "tbl.h"
-
/* FIXME: .Bl -diag can't have non-text children in HEAD. */
#define PRE_ARGS struct mdoc *mdoc, struct mdoc_node *n
@@ -127,7 +123,6 @@ static int pre_par(PRE_ARGS);
static int pre_sh(PRE_ARGS);
static int pre_ss(PRE_ARGS);
static int pre_std(PRE_ARGS);
-static int pre_ts(PRE_ARGS);
static v_post posts_an[] = { post_an, NULL };
static v_post posts_at[] = { post_at, post_defaults, NULL };
@@ -174,7 +169,6 @@ static v_pre pres_pp[] = { pre_par, NULL };
static v_pre pres_sh[] = { pre_sh, NULL };
static v_pre pres_ss[] = { pre_ss, NULL };
static v_pre pres_std[] = { pre_std, NULL };
-static v_pre pres_ts[] = { pre_ts, NULL };
const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* Ap */
@@ -299,8 +293,6 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ pres_pp, posts_sp }, /* sp */
{ NULL, posts_text1 }, /* %U */
{ NULL, NULL }, /* Ta */
- { pres_ts, NULL }, /* TS */
- { NULL, NULL }, /* TE */
};
#define RSORD_MAX 14 /* Number of `Rs' blocks. */
@@ -330,12 +322,19 @@ mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *n)
int line, pos;
char *tp;
- if (MDOC_TEXT == n->type) {
+ switch (n->type) {
+ case (MDOC_TEXT):
tp = n->string;
line = n->line;
pos = n->pos;
check_text(mdoc, line, pos, tp);
+ /* FALLTHROUGH */
+ case (MDOC_TBL):
+ /* FALLTHROUGH */
+ case (MDOC_ROOT):
return(1);
+ default:
+ break;
}
check_args(mdoc, n);
@@ -358,10 +357,16 @@ mdoc_valid_post(struct mdoc *mdoc)
return(1);
mdoc->last->flags |= MDOC_VALID;
- if (MDOC_TEXT == mdoc->last->type)
+ switch (mdoc->last->type) {
+ case (MDOC_TEXT):
+ /* FALLTHROUGH */
+ case (MDOC_TBL):
return(1);
- if (MDOC_ROOT == mdoc->last->type)
+ case (MDOC_ROOT):
return(post_root(mdoc));
+ default:
+ break;
+ }
if (NULL == mdoc_valids[mdoc->last->tok].post)
return(1);
@@ -1897,16 +1902,6 @@ post_ignpar(POST_ARGS)
}
static int
-pre_ts(PRE_ARGS)
-{
-
- if (MDOC_BLOCK == mdoc->last->type)
- mdoc->last->norm->TS = tbl_alloc();
-
- return(1);
-}
-
-static int
pre_par(PRE_ARGS)
{
diff --git a/usr.bin/mandoc/roff.3 b/usr.bin/mandoc/roff.3
index f8cb1622c69..58843b605d0 100644
--- a/usr.bin/mandoc/roff.3
+++ b/usr.bin/mandoc/roff.3
@@ -1,6 +1,6 @@
-.\" $Id: roff.3,v 1.5 2010/08/20 00:53:35 schwarze Exp $
+.\" $Id: roff.3,v 1.6 2011/01/04 22:28:17 schwarze Exp $
.\"
-.\" Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2010, 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
@@ -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: August 20 2010 $
+.Dd $Mdocdate: January 4 2011 $
.Dt ROFF 3
.Os
.Sh NAME
@@ -23,7 +23,8 @@
.Nm roff_endparse ,
.Nm roff_free ,
.Nm roff_parseln ,
-.Nm roff_reset
+.Nm roff_reset ,
+.Nm roff_span
.Nd roff macro compiler library
.Sh SYNOPSIS
.In mandoc.h
@@ -34,7 +35,7 @@
.Fa "void *data"
.Fa "mandocmsg msgs"
.Fc
-.Ft int
+.Ft void
.Fn roff_endparse "struct roff *roff"
.Ft void
.Fn roff_free "struct roff *roff"
@@ -49,6 +50,8 @@
.Fc
.Ft void
.Fn roff_reset "struct roff *roff"
+.Ft "const struct tbl_span *"
+.Fn roff_span "const struct roff *roff"
.Sh DESCRIPTION
The
.Nm
@@ -138,7 +141,13 @@ This line should not contain the trailing newline.
Returns 0 on failure, 1 on success.
.It Fn roff_endparse
Signals that the parse is complete.
-Returns 0 on failure, 1 on success.
+.It Fn roff_span
+If
+.Fn roff_parseln
+returned
+.Va ROFF_TBL ,
+return the last parsed table row.
+Returns NULL otherwise.
.El
.Sh EXAMPLES
See
diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c
index d25041cb8df..f4bc46244b7 100644
--- a/usr.bin/mandoc/roff.c
+++ b/usr.bin/mandoc/roff.c
@@ -1,6 +1,6 @@
-/* $Id: roff.c,v 1.26 2011/01/03 23:19:33 schwarze Exp $ */
+/* $Id: roff.c,v 1.27 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -15,10 +15,6 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include <assert.h>
#include <errno.h>
#include <ctype.h>
@@ -29,6 +25,7 @@
#include "mandoc.h"
#include "roff.h"
+#include "libroff.h"
#include "libmandoc.h"
#define RSTACK_MAX 128
@@ -56,6 +53,9 @@ enum rofft {
ROFF_rm,
ROFF_so,
ROFF_tr,
+ ROFF_TS,
+ ROFF_TE,
+ ROFF_T_,
ROFF_cblock,
ROFF_ccond, /* FIXME: remove this. */
ROFF_USERDEF,
@@ -67,7 +67,6 @@ enum roffrule {
ROFFRULE_DENY
};
-
struct roffstr {
char *name; /* key of symbol */
char *string; /* current value */
@@ -83,6 +82,9 @@ struct roff {
struct regset *regs; /* read/writable registers */
struct roffstr *first_string; /* user-defined strings & macros */
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 */
+ struct tbl_node *tbl; /* current table being parsed */
};
struct roffnode {
@@ -138,6 +140,9 @@ static int roff_res(struct roff *,
static void roff_setstr(struct roff *,
const char *, const char *, int);
static enum rofferr roff_so(ROFF_ARGS);
+static enum rofferr roff_TE(ROFF_ARGS);
+static enum rofferr roff_TS(ROFF_ARGS);
+static enum rofferr roff_T_(ROFF_ARGS);
static enum rofferr roff_userdef(ROFF_ARGS);
/* See roff_hash_find() */
@@ -168,6 +173,9 @@ static struct roffmac roffs[ROFF_MAX] = {
{ "rm", roff_line_error, NULL, NULL, 0, NULL },
{ "so", roff_so, NULL, NULL, 0, NULL },
{ "tr", roff_line_ignore, 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 },
{ ".", roff_cblock, NULL, NULL, 0, NULL },
{ "\\}", roff_ccond, NULL, NULL, 0, NULL },
{ NULL, roff_userdef, NULL, NULL, 0, NULL },
@@ -289,9 +297,19 @@ roffnode_push(struct roff *r, enum rofft tok, const char *name,
static void
roff_free1(struct roff *r)
{
+ struct tbl_node *t;
+
+ while (r->first_tbl) {
+ t = r->first_tbl;
+ r->first_tbl = t->next;
+ tbl_free(t);
+ }
+
+ r->first_tbl = r->last_tbl = r->tbl = NULL;
while (r->last)
roffnode_pop(r);
+
roff_freestr(r);
}
@@ -431,6 +449,7 @@ roff_parseln(struct roff *r, int ln, char **bufp,
size_t *szp, int pos, int *offs)
{
enum rofft t;
+ enum rofferr e;
int ppos;
/*
@@ -450,11 +469,17 @@ roff_parseln(struct roff *r, int ln, char **bufp,
if (r->last && ! ROFF_CTL((*bufp)[pos])) {
t = r->last->tok;
assert(roffs[t].text);
- return((*roffs[t].text)
- (r, t, bufp, szp,
- ln, pos, pos, offs));
- } else if ( ! ROFF_CTL((*bufp)[pos]))
+ e = (*roffs[t].text)
+ (r, t, bufp, szp, ln, pos, pos, offs);
+ assert(ROFF_IGN == e || ROFF_CONT == e);
+ if (ROFF_CONT == e && r->tbl)
+ return(tbl_read(r->tbl, ln, *bufp, *offs));
+ return(e);
+ } else if ( ! ROFF_CTL((*bufp)[pos])) {
+ if (r->tbl)
+ return(tbl_read(r->tbl, ln, *bufp, *offs));
return(ROFF_CONT);
+ }
/*
* If a scope is open, go to the child handler for that macro,
@@ -486,14 +511,20 @@ roff_parseln(struct roff *r, int ln, char **bufp,
}
-int
+void
roff_endparse(struct roff *r)
{
- if (NULL == r->last)
- return(1);
- return((*r->msg)(MANDOCERR_SCOPEEXIT, r->data, r->last->line,
- r->last->col, NULL));
+ if (r->last)
+ (*r->msg)(MANDOCERR_SCOPEEXIT, r->data,
+ r->last->line, r->last->col, NULL);
+
+ if (r->tbl) {
+ (*r->msg)(MANDOCERR_SCOPEEXIT, r->data,
+ r->tbl->line, r->tbl->pos, NULL);
+ tbl_end(r->tbl);
+ r->tbl = NULL;
+ }
}
@@ -562,8 +593,7 @@ roff_cblock(ROFF_ARGS)
*/
if (NULL == r->last) {
- if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL))
- return(ROFF_ERR);
+ (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
return(ROFF_IGN);
}
@@ -582,14 +612,12 @@ roff_cblock(ROFF_ARGS)
case (ROFF_ig):
break;
default:
- if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL))
- return(ROFF_ERR);
+ (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
return(ROFF_IGN);
}
if ((*bufp)[pos])
- if ( ! (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL))
- return(ROFF_ERR);
+ (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL);
roffnode_pop(r);
roffnode_cleanscope(r);
@@ -616,8 +644,7 @@ roff_ccond(ROFF_ARGS)
{
if (NULL == r->last) {
- if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL))
- return(ROFF_ERR);
+ (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
return(ROFF_IGN);
}
@@ -629,20 +656,17 @@ roff_ccond(ROFF_ARGS)
case (ROFF_if):
break;
default:
- if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL))
- return(ROFF_ERR);
+ (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
return(ROFF_IGN);
}
if (r->last->endspan > -1) {
- if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL))
- return(ROFF_ERR);
+ (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
return(ROFF_IGN);
}
if ((*bufp)[pos])
- if ( ! (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL))
- return(ROFF_ERR);
+ (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL);
roffnode_pop(r);
roffnode_cleanscope(r);
@@ -1095,6 +1119,55 @@ roff_nr(ROFF_ARGS)
/* ARGSUSED */
static enum rofferr
+roff_TE(ROFF_ARGS)
+{
+
+ if (NULL == r->tbl)
+ (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
+ else
+ tbl_end(r->tbl);
+
+ r->tbl = NULL;
+ return(ROFF_IGN);
+}
+
+/* ARGSUSED */
+static enum rofferr
+roff_T_(ROFF_ARGS)
+{
+
+ if (NULL == r->tbl)
+ (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
+ else
+ tbl_restart(ppos, ln, r->tbl);
+
+ return(ROFF_IGN);
+}
+
+/* ARGSUSED */
+static enum rofferr
+roff_TS(ROFF_ARGS)
+{
+ struct tbl_node *t;
+
+ if (r->tbl) {
+ (*r->msg)(MANDOCERR_SCOPEBROKEN, r->data, ln, ppos, NULL);
+ tbl_end(r->tbl);
+ }
+
+ t = tbl_alloc(ppos, ln, r->data, r->msg);
+
+ if (r->last_tbl)
+ r->last_tbl->next = t;
+ else
+ r->first_tbl = r->last_tbl = t;
+
+ r->tbl = r->last_tbl = t;
+ return(ROFF_IGN);
+}
+
+/* ARGSUSED */
+static enum rofferr
roff_so(ROFF_ARGS)
{
char *name;
@@ -1270,3 +1343,10 @@ roff_freestr(struct roff *r)
r->first_string = NULL;
}
+
+const struct tbl_span *
+roff_span(const struct roff *r)
+{
+
+ return(r->tbl ? tbl_span(r->tbl) : NULL);
+}
diff --git a/usr.bin/mandoc/roff.h b/usr.bin/mandoc/roff.h
index 938c300f32f..1e533701a50 100644
--- a/usr.bin/mandoc/roff.h
+++ b/usr.bin/mandoc/roff.h
@@ -1,4 +1,4 @@
-/* $Id: roff.h,v 1.6 2010/11/25 22:23:31 schwarze Exp $ */
+/* $Id: roff.h,v 1.7 2011/01/04 22:28:17 schwarze Exp $ */
/*
* Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -24,6 +24,7 @@ enum rofferr {
ROFF_REPARSE, /* re-run main parser on the result */
ROFF_SO, /* include another file */
ROFF_IGN, /* ignore current line */
+ ROFF_TBL, /* a table row was successfully parsed */
ROFF_ERR /* badness: puke and stop */
};
@@ -36,7 +37,8 @@ struct roff *roff_alloc(struct regset *, void *, mandocmsg);
void roff_reset(struct roff *);
enum rofferr roff_parseln(struct roff *, int,
char **, size_t *, int, int *);
-int roff_endparse(struct roff *);
+void roff_endparse(struct roff *);
+const struct tbl_span *roff_span(const struct roff *);
__END_DECLS
diff --git a/usr.bin/mandoc/tbl.c b/usr.bin/mandoc/tbl.c
index 57d3da90880..56369368098 100644
--- a/usr.bin/mandoc/tbl.c
+++ b/usr.bin/mandoc/tbl.c
@@ -1,6 +1,6 @@
-/* $Id: tbl.c,v 1.3 2010/10/15 22:07:12 schwarze Exp $ */
+/* $Id: tbl.c,v 1.4 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * Copyright (c) 2009, 2010, 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
@@ -14,533 +14,146 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/queue.h>
-
#include <assert.h>
-#include <errno.h>
-#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
-#include "out.h"
-#include "term.h"
-#include "tbl.h"
-#include "tbl_extern.h"
-
-
-const char *const errnames[ERR_MAX] = {
- "bad syntax", /* ERR_SYNTAX */
- "bad option" /* ERR_OPTION */
-};
-
-static char buf[1024]; /* XXX */
-
-static enum tbl_tok tbl_next_char(char);
-static void tbl_init(struct tbl *);
-static void tbl_clear(struct tbl *);
-static struct tbl_head *tbl_head_alloc(struct tbl *);
-static void tbl_span_free(struct tbl_span *);
-static void tbl_data_free(struct tbl_data *);
-static void tbl_row_free(struct tbl_row *);
-
-static void headadj(const struct tbl_cell *,
- struct tbl_head *);
+#include "mandoc.h"
+#include "roff.h"
+#include "libmandoc.h"
+#include "libroff.h"
-static void
-tbl_init(struct tbl *tbl)
+enum rofferr
+tbl_read(struct tbl_node *tbl, int ln, const char *p, int offs)
{
+ int len;
+ const char *cp;
- bzero(tbl, sizeof(struct tbl));
-
- tbl->part = TBL_PART_OPTS;
- tbl->tab = '\t';
- tbl->linesize = 12;
- tbl->decimal = '.';
-
- TAILQ_INIT(&tbl->span);
- TAILQ_INIT(&tbl->row);
- TAILQ_INIT(&tbl->head);
-}
+ cp = &p[offs];
+ len = (int)strlen(cp);
+ /*
+ * If we're in the options section and we don't have a
+ * terminating semicolon, assume we've moved directly into the
+ * layout section. No need to report a warning: this is,
+ * apparently, standard behaviour.
+ */
-int
-tbl_read(struct tbl *tbl, const char *f, int ln, const char *p, int len)
-{
-
- if (len && TBL_PART_OPTS == tbl->part)
- if (';' != p[len - 1])
+ if (TBL_PART_OPTS == tbl->part && len)
+ if (';' != cp[len - 1])
tbl->part = TBL_PART_LAYOUT;
+ /* Now process each logical section of the table. */
+
switch (tbl->part) {
case (TBL_PART_OPTS):
- return(tbl_option(tbl, f, ln, p));
- case (TBL_PART_CLAYOUT):
- /* FALLTHROUGH */
+ return(tbl_option(tbl, ln, p) ? ROFF_IGN : ROFF_ERR);
case (TBL_PART_LAYOUT):
- return(tbl_layout(tbl, f, ln, p));
- case (TBL_PART_DATA):
- return(tbl_data(tbl, f, ln, p));
- case (TBL_PART_ERROR):
- break;
- }
-
- return(0);
-}
-
-
-int
-tbl_close(struct termp *p, struct tbl *tbl, const char *f, int ln)
-{
-
- if (TBL_PART_DATA != tbl->part)
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, 0));
- if ( ! tbl_data_close(tbl, f, ln))
- return(0);
-#if 1
- return(tbl_calc_term(p, tbl));
-#else
- return(tbl_calc_tree(tbl));
-#endif
-}
-
-
-int
-tbl_write(struct termp *p, const struct tbl *tbl)
-{
-
-#if 1
- return(tbl_write_term(p, tbl));
-#else
- return(tbl_write_tree(tbl));
-#endif
-}
-
-
-static enum tbl_tok
-tbl_next_char(char c)
-{
-
- /*
- * These are delimiting tokens. They separate out words in the
- * token stream.
- */
-
- switch (c) {
- case ('('):
- return(TBL_TOK_OPENPAREN);
- case (')'):
- return(TBL_TOK_CLOSEPAREN);
- case (' '):
- return(TBL_TOK_SPACE);
- case ('\t'):
- return(TBL_TOK_TAB);
- case (';'):
- return(TBL_TOK_SEMICOLON);
- case ('.'):
- return(TBL_TOK_PERIOD);
- case (','):
- return(TBL_TOK_COMMA);
- case (0):
- return(TBL_TOK_NIL);
+ return(tbl_layout(tbl, ln, p) ? ROFF_IGN : ROFF_ERR);
+ case (TBL_PART_CDATA):
+ return(tbl_cdata(tbl, ln, p) ? ROFF_TBL : ROFF_IGN);
default:
break;
}
- return(TBL_TOK_WORD);
-}
-
-
-const char *
-tbl_last(void)
-{
-
- return(buf);
-}
-
-
-int
-tbl_last_uint(void)
-{
- char *ep;
- long lval;
-
- /* From OpenBSD's strtol(3). Gross. */
-
- errno = 0;
- lval = strtol(buf, &ep, 10);
- if (buf[0] == 0 || *ep != 0)
- return(-1);
- if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
- return(-1);
- if (lval < 0 || lval > INT_MAX)
- return(-1);
-
- return((int)lval);
-}
-
-
-enum tbl_tok
-tbl_next(const char *p, int *pos)
-{
- int i;
- enum tbl_tok c;
-
- buf[0] = 0;
-
- if (TBL_TOK_WORD != (c = tbl_next_char(p[*pos]))) {
- if (TBL_TOK_NIL != c) {
- buf[0] = p[*pos];
- buf[1] = 0;
- (*pos)++;
- }
- return(c);
- }
-
/*
- * Copy words into a nil-terminated buffer. For now, we use a
- * static buffer. Eventually this should be made into a dynamic
- * one living in struct tbl.
+ * This only returns zero if the line is empty, so we ignore it
+ * and continue on.
*/
-
- for (i = 0; i < 1023; i++, (*pos)++)
- if (TBL_TOK_WORD == tbl_next_char(p[*pos]))
- buf[i] = p[*pos];
- else
- break;
-
- assert(i < 1023);
- buf[i] = 0;
-
- return(TBL_TOK_WORD);
-}
-
-
-int
-tbl_err(struct tbl *tbl)
-{
-
- (void)fprintf(stderr, "%s\n", strerror(errno));
- tbl->part = TBL_PART_ERROR;
- return(0);
+ return(tbl_data(tbl, ln, p) ? ROFF_TBL : ROFF_IGN);
}
-
-/* ARGSUSED */
-int
-tbl_warnx(struct tbl *tbl, enum tbl_err tok,
- const char *f, int line, int pos)
+struct tbl_node *
+tbl_alloc(int pos, int line, void *data, const mandocmsg msg)
{
+ struct tbl_node *p;
- (void)fprintf(stderr, "%s:%d:%d: %s\n",
- f, line, pos + 1, errnames[tok]);
-
- /* TODO: -Werror */
- return(1);
-}
-
-
-int
-tbl_errx(struct tbl *tbl, enum tbl_err tok,
- const char *f, int line, int pos)
-{
-
- (void)fprintf(stderr, "%s:%d:%d: %s\n",
- f, line, pos + 1, errnames[tok]);
-
- tbl->part = TBL_PART_ERROR;
- return(0);
-}
-
-
-struct tbl *
-tbl_alloc(void)
-{
- struct tbl *p;
-
- if (NULL == (p = malloc(sizeof(struct tbl))))
- return(NULL);
-
- tbl_init(p);
+ p = mandoc_calloc(1, sizeof(struct tbl_node));
+ p->line = line;
+ p->pos = pos;
+ p->data = data;
+ p->msg = msg;
+ p->part = TBL_PART_OPTS;
+ p->opts.tab = '\t';
+ p->opts.linesize = 12;
+ p->opts.decimal = '.';
return(p);
}
-
-void
-tbl_free(struct tbl *p)
-{
-
- tbl_clear(p);
- free(p);
-}
-
-
void
-tbl_reset(struct tbl *tbl)
-{
-
- tbl_clear(tbl);
- tbl_init(tbl);
-}
-
-
-struct tbl_span *
-tbl_span_alloc(struct tbl *tbl)
-{
- struct tbl_span *p, *pp;
- struct tbl_row *row;
-
- if (NULL == (p = calloc(1, sizeof(struct tbl_span)))) {
- (void)tbl_err(tbl);
- return(NULL);
- }
-
- TAILQ_INIT(&p->data);
- TAILQ_INSERT_TAIL(&tbl->span, p, entries);
-
- /* LINTED */
- pp = TAILQ_PREV(p, tbl_spanh, entries);
-
- if (pp) {
- row = TAILQ_NEXT(pp->row, entries);
- if (NULL == row)
- row = pp->row;
- } else {
- row = TAILQ_FIRST(&tbl->row);
- }
-
- assert(row);
- p->row = row;
- p->tbl = tbl;
- return(p);
-}
-
-
-struct tbl_row *
-tbl_row_alloc(struct tbl *tbl)
-{
- struct tbl_row *p;
-
- if (NULL == (p = calloc(1, sizeof(struct tbl_row)))) {
- (void)tbl_err(tbl);
- return(NULL);
- }
-
- TAILQ_INIT(&p->cell);
- TAILQ_INSERT_TAIL(&tbl->row, p, entries);
- p->tbl = tbl;
- return(p);
-}
-
-
-static void
-headadj(const struct tbl_cell *cell, struct tbl_head *head)
-{
- if (TBL_CELL_VERT != cell->pos &&
- TBL_CELL_DVERT != cell->pos) {
- head->pos = TBL_HEAD_DATA;
- return;
- }
- if (TBL_CELL_VERT == cell->pos)
- if (TBL_HEAD_DVERT != head->pos)
- head->pos = TBL_HEAD_VERT;
- if (TBL_CELL_DVERT == cell->pos)
- head->pos = TBL_HEAD_DVERT;
-}
-
-
-static struct tbl_head *
-tbl_head_alloc(struct tbl *tbl)
+tbl_free(struct tbl_node *p)
{
- struct tbl_head *p;
-
- if (NULL == (p = calloc(1, sizeof(struct tbl_head)))) {
- (void)tbl_err(tbl);
- return(NULL);
- }
- p->tbl = tbl;
- return(p);
-}
-
-
-struct tbl_cell *
-tbl_cell_alloc(struct tbl_row *rp, enum tbl_cellt pos)
-{
- struct tbl_cell *p, *pp;
- struct tbl_head *h, *hp;
-
- if (NULL == (p = calloc(1, sizeof(struct tbl_cell)))) {
- (void)tbl_err(rp->tbl);
- return(NULL);
- }
-
- TAILQ_INSERT_TAIL(&rp->cell, p, entries);
- p->pos = pos;
- p->row = rp;
-
- /*
- * This is a little bit complicated. Here we determine the
- * header the corresponds to a cell. We add headers dynamically
- * when need be or re-use them, otherwise. As an example, given
- * the following:
- *
- * 1 c || l
- * 2 | c | l
- * 3 l l
- * 3 || c | l |.
- *
- * We first add the new headers (as there are none) in (1); then
- * in (2) we insert the first spanner (as it doesn't match up
- * with the header); then we re-use the prior data headers,
- * skipping over the spanners; then we re-use everything and add
- * a last spanner. Note that VERT headers are made into DVERT
- * ones.
- */
-
- /* LINTED */
- pp = TAILQ_PREV(p, tbl_cellh, entries);
-
- h = pp ? TAILQ_NEXT(pp->head, entries) :
- TAILQ_FIRST(&rp->tbl->head);
-
- if (h) {
- /* Re-use data header. */
- if (TBL_HEAD_DATA == h->pos &&
- (TBL_CELL_VERT != p->pos &&
- TBL_CELL_DVERT != p->pos)) {
- p->head = h;
- return(p);
- }
-
- /* Re-use spanner header. */
- if (TBL_HEAD_DATA != h->pos &&
- (TBL_CELL_VERT == p->pos ||
- TBL_CELL_DVERT == p->pos)) {
- headadj(p, h);
- p->head = h;
- return(p);
- }
-
- /* Right-shift headers with a new spanner. */
- if (TBL_HEAD_DATA == h->pos &&
- (TBL_CELL_VERT == p->pos ||
- TBL_CELL_DVERT == p->pos)) {
- if (NULL == (hp = tbl_head_alloc(rp->tbl)))
- return(NULL);
- TAILQ_INSERT_BEFORE(h, hp, entries);
- headadj(p, hp);
- p->head = hp;
- return(p);
+ struct tbl_row *rp;
+ struct tbl_cell *cp;
+ struct tbl_span *sp;
+ struct tbl_dat *dp;
+ struct tbl_head *hp;
+
+ while (NULL != (rp = p->first_row)) {
+ p->first_row = rp->next;
+ while (rp->first) {
+ cp = rp->first;
+ rp->first = cp->next;
+ free(cp);
}
+ free(rp);
+ }
- h = TAILQ_NEXT(h, entries);
- if (h) {
- headadj(p, h);
- p->head = h;
- return(p);
+ while (NULL != (sp = p->first_span)) {
+ p->first_span = sp->next;
+ while (sp->first) {
+ dp = sp->first;
+ sp->first = dp->next;
+ if (dp->string)
+ free(dp->string);
+ free(dp);
}
+ free(sp);
+ }
- /* Fall through to default case... */
+ while (NULL != (hp = p->first_head)) {
+ p->first_head = hp->next;
+ free(hp);
}
- if (NULL == (hp = tbl_head_alloc(rp->tbl)))
- return(NULL);
- TAILQ_INSERT_TAIL(&rp->tbl->head, hp, entries);
- headadj(p, hp);
- p->head = hp;
- return(p);
+ free(p);
}
-
-struct tbl_data *
-tbl_data_alloc(struct tbl_span *sp)
+void
+tbl_restart(int line, int pos, struct tbl_node *tbl)
{
- struct tbl_data *p;
- struct tbl_cell *cp;
- struct tbl_data *dp;
-
- if (NULL == (p = calloc(1, sizeof(struct tbl_data)))) {
- (void)tbl_err(sp->row->tbl);
- return(NULL);
- }
+ if (TBL_PART_CDATA == tbl->part)
+ TBL_MSG(tbl, MANDOCERR_TBLBLOCK, tbl->line, tbl->pos);
- cp = NULL;
- /* LINTED */
- if (NULL == (dp = TAILQ_LAST(&sp->data, tbl_datah)))
- cp = TAILQ_FIRST(&sp->row->cell);
- else if (dp->cell)
- cp = TAILQ_NEXT(dp->cell, entries);
+ tbl->part = TBL_PART_LAYOUT;
+ tbl->line = line;
+ tbl->pos = pos;
- TAILQ_INSERT_TAIL(&sp->data, p, entries);
-
- if (cp && (TBL_CELL_VERT == cp->pos ||
- TBL_CELL_DVERT == cp->pos))
- cp = TAILQ_NEXT(cp, entries);
-
- p->span = sp;
- p->cell = cp;
- return(p);
+ if (NULL == tbl->first_span || NULL == tbl->first_span->first)
+ TBL_MSG(tbl, MANDOCERR_TBLNODATA, tbl->line, tbl->pos);
}
-
-static void
-tbl_clear(struct tbl *p)
+const struct tbl_span *
+tbl_span(const struct tbl_node *tbl)
{
- struct tbl_span *span;
- struct tbl_head *head;
- struct tbl_row *row;
- /* LINTED */
- while ((span = TAILQ_FIRST(&p->span))) {
- TAILQ_REMOVE(&p->span, span, entries);
- tbl_span_free(span);
- }
- /* LINTED */
- while ((row = TAILQ_FIRST(&p->row))) {
- TAILQ_REMOVE(&p->row, row, entries);
- tbl_row_free(row);
- }
- /* LINTED */
- while ((head = TAILQ_FIRST(&p->head))) {
- TAILQ_REMOVE(&p->head, head, entries);
- free(head);
- }
+ assert(tbl);
+ return(tbl->last_span);
}
-
-static void
-tbl_span_free(struct tbl_span *p)
+void
+tbl_end(struct tbl_node *tbl)
{
- struct tbl_data *data;
-
- /* LINTED */
- while ((data = TAILQ_FIRST(&p->data))) {
- TAILQ_REMOVE(&p->data, data, entries);
- tbl_data_free(data);
- }
- free(p);
-}
+ if (NULL == tbl->first_span || NULL == tbl->first_span->first)
+ TBL_MSG(tbl, MANDOCERR_TBLNODATA, tbl->line, tbl->pos);
-static void
-tbl_data_free(struct tbl_data *p)
-{
+ if (tbl->last_span)
+ tbl->last_span->flags |= TBL_SPAN_LAST;
- if (p->string)
- free(p->string);
- free(p);
+ if (TBL_PART_CDATA == tbl->part)
+ TBL_MSG(tbl, MANDOCERR_TBLBLOCK, tbl->line, tbl->pos);
}
-
-static void
-tbl_row_free(struct tbl_row *p)
-{
- struct tbl_cell *cell;
-
- /* LINTED */
- while ((cell = TAILQ_FIRST(&p->cell))) {
- TAILQ_REMOVE(&p->cell, cell, entries);
- free(cell);
- }
- free(p);
-}
diff --git a/usr.bin/mandoc/tbl.h b/usr.bin/mandoc/tbl.h
deleted file mode 100644
index 29ac777496f..00000000000
--- a/usr.bin/mandoc/tbl.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* $Id: tbl.h,v 1.3 2010/10/15 22:07:12 schwarze Exp $ */
-/*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#ifndef TBL_H
-#define TBL_H
-
-__BEGIN_DECLS
-
-struct tbl;
-
-struct tbl *tbl_alloc(void);
-void tbl_free(struct tbl *);
-void tbl_reset(struct tbl *);
-
-int tbl_read(struct tbl *, const char *, int, const char *, int);
-int tbl_close(struct termp *, struct tbl *, const char *, int);
-int tbl_write(struct termp *, const struct tbl *);
-
-__END_DECLS
-
-#endif /*TBL_H*/
diff --git a/usr.bin/mandoc/tbl_data.c b/usr.bin/mandoc/tbl_data.c
index 09bfbebcda5..a10404df38a 100644
--- a/usr.bin/mandoc/tbl_data.c
+++ b/usr.bin/mandoc/tbl_data.c
@@ -1,6 +1,6 @@
-/* $Id: tbl_data.c,v 1.3 2010/10/15 23:19:40 schwarze Exp $ */
+/* $Id: tbl_data.c,v 1.4 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * Copyright (c) 2009, 2010, 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
@@ -14,119 +14,178 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/queue.h>
-#include <sys/types.h>
-
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
-#include "out.h"
-#include "term.h"
-#include "tbl_extern.h"
-
-/* FIXME: warn about losing data contents if cell is HORIZ. */
-
-static int data(struct tbl *, struct tbl_span *,
- const char *, int, int,
- const char *, int, int);
+#include "mandoc.h"
+#include "libmandoc.h"
+#include "libroff.h"
+static int data(struct tbl_node *, struct tbl_span *,
+ int, const char *, int *);
-int
-data(struct tbl *tbl, struct tbl_span *dp,
- const char *f, int ln, int pos,
- const char *p, int start, int end)
+static int
+data(struct tbl_node *tbl, struct tbl_span *dp,
+ int ln, const char *p, int *pos)
{
- struct tbl_data *dat;
-
- if (NULL == (dat = tbl_data_alloc(dp)))
+ struct tbl_dat *dat;
+ struct tbl_cell *cp;
+ int sv;
+
+ cp = NULL;
+ if (dp->last && dp->last->layout)
+ cp = dp->last->layout->next;
+ else if (NULL == dp->last)
+ cp = dp->layout->first;
+
+ /* Skip over spanners to data formats. */
+
+ while (cp && (TBL_CELL_VERT == cp->pos ||
+ TBL_CELL_DVERT == cp->pos))
+ cp = cp->next;
+
+ dat = mandoc_calloc(1, sizeof(struct tbl_dat));
+ dat->layout = cp;
+ dat->pos = TBL_DATA_NONE;
+
+ if (NULL == dat->layout)
+ TBL_MSG(tbl, MANDOCERR_TBLEXTRADAT, ln, *pos);
+
+ if (dp->last) {
+ dp->last->next = dat;
+ dp->last = dat;
+ } else
+ dp->last = dp->first = dat;
+
+ sv = *pos;
+ while (p[*pos] && p[*pos] != tbl->opts.tab)
+ (*pos)++;
+
+ /*
+ * Check for a continued-data scope opening. This consists of a
+ * trailing `T{' at the end of the line. Subsequent lines,
+ * until a standalone `T}', are included in our cell.
+ */
+
+ if (*pos - sv == 2 && 'T' == p[sv] && '{' == p[sv + 1]) {
+ tbl->part = TBL_PART_CDATA;
return(0);
+ }
- if (NULL == dat->cell)
- if ( ! tbl_warnx(tbl, ERR_SYNTAX, f, ln, pos))
- return(0);
-
- assert(end >= start);
- if (NULL == (dat->string = malloc((size_t)(end - start + 1))))
- return(tbl_err(tbl));
-
- (void)memcpy(dat->string, &p[start], (size_t)(end - start));
- dat->string[end - start] = 0;
+ dat->string = mandoc_malloc(*pos - sv + 1);
+ memcpy(dat->string, &p[sv], *pos - sv);
+ dat->string[*pos - sv] = '\0';
- /* XXX: do the strcmps, then malloc(). */
+ if (p[*pos])
+ (*pos)++;
if ( ! strcmp(dat->string, "_"))
- dat->flags |= TBL_DATA_HORIZ;
+ dat->pos = TBL_DATA_HORIZ;
else if ( ! strcmp(dat->string, "="))
- dat->flags |= TBL_DATA_DHORIZ;
+ dat->pos = TBL_DATA_DHORIZ;
else if ( ! strcmp(dat->string, "\\_"))
- dat->flags |= TBL_DATA_NHORIZ;
+ dat->pos = TBL_DATA_NHORIZ;
else if ( ! strcmp(dat->string, "\\="))
- dat->flags |= TBL_DATA_NDHORIZ;
+ dat->pos = TBL_DATA_NDHORIZ;
else
+ dat->pos = TBL_DATA_DATA;
+
+ if (NULL == dat->layout)
return(1);
- free(dat->string);
- dat->string = NULL;
+ if (TBL_CELL_HORIZ == dat->layout->pos ||
+ TBL_CELL_DHORIZ == dat->layout->pos)
+ if (TBL_DATA_DATA == dat->pos && '\0' != *dat->string)
+ TBL_MSG(tbl, MANDOCERR_TBLIGNDATA, ln, sv);
+
return(1);
}
+int
+tbl_cdata(struct tbl_node *tbl, int ln, const char *p)
+{
+ struct tbl_dat *dat;
+ size_t sz;
+
+ if (0 == strcmp(p, "T}")) {
+ tbl->part = TBL_PART_DATA;
+ return(1);
+ }
+
+ dat = tbl->last_span->last;
+ dat->pos = TBL_DATA_DATA;
+
+ if (dat->string) {
+ sz = strlen(p) + strlen(dat->string) + 2;
+ dat->string = mandoc_realloc(dat->string, sz);
+ strlcat(dat->string, " ", sz);
+ strlcat(dat->string, p, sz);
+ } else
+ dat->string = mandoc_strdup(p);
+
+ return(0);
+}
int
-tbl_data(struct tbl *tbl, const char *f, int ln, const char *p)
+tbl_data(struct tbl_node *tbl, int ln, const char *p)
{
struct tbl_span *dp;
- int i, j;
-
- if ('.' == p[0] && ! isdigit((u_char)p[1])) {
- /* Comment lines end up here with just a dot. */
- if ('\0' == p[1])
- return(1);
- /*
- * XXX: departs from tbl convention in that we disallow
- * macros in the data body.
- */
- if (strncasecmp(p, ".T&", 3))
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, 0));
- return(tbl_data_close(tbl, f, ln));
- }
+ struct tbl_row *rp;
+ int pos;
- if (NULL == (dp = tbl_span_alloc(tbl)))
+ pos = 0;
+
+ if ('\0' == p[pos]) {
+ TBL_MSG(tbl, MANDOCERR_TBL, ln, pos);
return(0);
+ }
+
+ /*
+ * Choose a layout row: take the one following the last parsed
+ * span's. If that doesn't exist, use the last parsed span's.
+ * If there's no last parsed span, use the first row. This can
+ * be NULL!
+ */
+
+ if (tbl->last_span) {
+ assert(tbl->last_span->layout);
+ rp = tbl->last_span->layout->next;
+ if (NULL == rp)
+ rp = tbl->last_span->layout;
+ } else
+ rp = tbl->first_row;
+
+ dp = mandoc_calloc(1, sizeof(struct tbl_span));
+ dp->tbl = &tbl->opts;
+ dp->layout = rp;
+ dp->head = tbl->first_head;
+
+ if (tbl->last_span) {
+ tbl->last_span->next = dp;
+ tbl->last_span = dp;
+ } else {
+ tbl->last_span = tbl->first_span = dp;
+ dp->flags |= TBL_SPAN_FIRST;
+ }
if ( ! strcmp(p, "_")) {
- dp->flags |= TBL_SPAN_HORIZ;
+ dp->pos = TBL_SPAN_HORIZ;
return(1);
} else if ( ! strcmp(p, "=")) {
- dp->flags |= TBL_SPAN_DHORIZ;
+ dp->pos = TBL_SPAN_DHORIZ;
return(1);
}
- for (j = i = 0; p[i]; i++) {
- if (p[i] != tbl->tab)
- continue;
- if ( ! data(tbl, dp, f, ln, i, p, j, i))
- return(0);
- j = i + 1;
- }
-
- return(data(tbl, dp, f, ln, i, p, j, i));
-}
+ dp->pos = TBL_SPAN_DATA;
+ /* This returns 0 when TBL_PART_CDATA is entered. */
-int
-tbl_data_close(struct tbl *tbl, const char *f, int ln)
-{
- struct tbl_span *span;
-
- /* LINTED */
- span = TAILQ_LAST(&tbl->span, tbl_spanh);
- if (NULL == span)
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, 0));
- if (TAILQ_NEXT(span->row, entries))
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, 0));
+ while ('\0' != p[pos])
+ if ( ! data(tbl, dp, ln, p, &pos))
+ return(0);
- tbl->part = TBL_PART_LAYOUT;
return(1);
}
diff --git a/usr.bin/mandoc/tbl_extern.h b/usr.bin/mandoc/tbl_extern.h
deleted file mode 100644
index 1c73041c92b..00000000000
--- a/usr.bin/mandoc/tbl_extern.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/* $Id: tbl_extern.h,v 1.3 2010/10/15 22:07:12 schwarze Exp $ */
-/*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#ifndef TBL_EXTERN_H
-#define TBL_EXTERN_H
-
-enum tbl_err {
- ERR_SYNTAX,
- ERR_OPTION,
- ERR_MAX
-};
-
-enum tbl_tok {
- TBL_TOK_WORD,
- TBL_TOK_OPENPAREN,
- TBL_TOK_CLOSEPAREN,
- TBL_TOK_COMMA,
- TBL_TOK_SEMICOLON,
- TBL_TOK_PERIOD,
- TBL_TOK_SPACE,
- TBL_TOK_TAB,
- TBL_TOK_NIL
-};
-
-enum tbl_part {
- TBL_PART_OPTS,
- TBL_PART_LAYOUT,
- TBL_PART_CLAYOUT,
- TBL_PART_DATA,
- TBL_PART_ERROR
-};
-
-struct tbl;
-struct tbl_head;
-struct tbl_row;
-struct tbl_cell;
-struct tbl_span;
-struct tbl_data;
-
-TAILQ_HEAD(tbl_rowh, tbl_row);
-TAILQ_HEAD(tbl_cellh, tbl_cell);
-TAILQ_HEAD(tbl_headh, tbl_head);
-TAILQ_HEAD(tbl_spanh, tbl_span);
-TAILQ_HEAD(tbl_datah, tbl_data);
-
-struct tbl {
- enum tbl_part part;
- int opts;
-#define TBL_OPT_CENTRE (1 << 0)
-#define TBL_OPT_EXPAND (1 << 1)
-#define TBL_OPT_BOX (1 << 2)
-#define TBL_OPT_DBOX (1 << 3)
-#define TBL_OPT_ALLBOX (1 << 4)
-#define TBL_OPT_NOKEEP (1 << 5)
-#define TBL_OPT_NOSPACE (1 << 6)
- char tab;
- char decimal;
- int linesize;
- char delims[2];
- struct tbl_spanh span;
- struct tbl_headh head;
- struct tbl_rowh row;
-};
-
-enum tbl_headt {
- TBL_HEAD_DATA,
- TBL_HEAD_VERT,
- TBL_HEAD_DVERT,
- TBL_HEAD_MAX
-};
-
-struct tbl_head {
- struct tbl *tbl;
- enum tbl_headt pos;
- int width;
- int decimal;
- TAILQ_ENTRY(tbl_head) entries;
-};
-
-struct tbl_row {
- struct tbl *tbl;
- struct tbl_cellh cell;
- TAILQ_ENTRY(tbl_row) entries;
-};
-
-enum tbl_cellt {
- TBL_CELL_CENTRE, /* c, C */
- TBL_CELL_RIGHT, /* r, R */
- TBL_CELL_LEFT, /* l, L */
- TBL_CELL_NUMBER, /* n, N */
- TBL_CELL_SPAN, /* s, S */
- TBL_CELL_LONG, /* a, A */
- TBL_CELL_DOWN, /* ^ */
- TBL_CELL_HORIZ, /* _, - */
- TBL_CELL_DHORIZ, /* = */
- TBL_CELL_VERT, /* | */
- TBL_CELL_DVERT, /* || */
- TBL_CELL_MAX
-};
-
-struct tbl_cell {
- struct tbl_row *row;
- struct tbl_head *head;
- enum tbl_cellt pos;
- int spacing;
- int flags;
-#define TBL_CELL_TALIGN (1 << 0) /* t, T */
-#define TBL_CELL_BALIGN (1 << 1) /* d, D */
-#define TBL_CELL_BOLD (1 << 2) /* fB, B, b */
-#define TBL_CELL_ITALIC (1 << 3) /* fI, I, i */
-#define TBL_CELL_EQUAL (1 << 4) /* e, E */
-#define TBL_CELL_UP (1 << 5) /* u, U */
-#define TBL_CELL_WIGN (1 << 6) /* z, Z */
- TAILQ_ENTRY(tbl_cell) entries;
-};
-
-struct tbl_data {
- struct tbl_span *span;
- struct tbl_cell *cell;
- int flags;
-#define TBL_DATA_HORIZ (1 << 0)
-#define TBL_DATA_DHORIZ (1 << 1)
-#define TBL_DATA_NHORIZ (1 << 2)
-#define TBL_DATA_NDHORIZ (1 << 3)
- char *string;
- TAILQ_ENTRY(tbl_data) entries;
-};
-
-struct tbl_span {
- struct tbl_row *row;
- struct tbl *tbl;
- int flags;
-#define TBL_SPAN_HORIZ (1 << 0)
-#define TBL_SPAN_DHORIZ (1 << 1)
- struct tbl_datah data;
- TAILQ_ENTRY(tbl_span) entries;
-};
-
-__BEGIN_DECLS
-
-int tbl_option(struct tbl *,
- const char *, int, const char *);
-int tbl_layout(struct tbl *,
- const char *, int, const char *);
-int tbl_data(struct tbl *,
- const char *, int, const char *);
-int tbl_data_close(struct tbl *, const char *, int);
-
-enum tbl_tok tbl_next(const char *, int *);
-const char *tbl_last(void);
-int tbl_last_uint(void);
-int tbl_errx(struct tbl *, enum tbl_err,
- const char *, int, int);
-int tbl_warnx(struct tbl *, enum tbl_err,
- const char *, int, int);
-int tbl_err(struct tbl *);
-
-struct tbl_row *tbl_row_alloc(struct tbl *);
-struct tbl_cell *tbl_cell_alloc(struct tbl_row *, enum tbl_cellt);
-struct tbl_span *tbl_span_alloc(struct tbl *);
-struct tbl_data *tbl_data_alloc(struct tbl_span *);
-
-int tbl_write_term(struct termp *, const struct tbl *);
-int tbl_calc_term(struct termp *, struct tbl *);
-int tbl_write_tree(const struct tbl *);
-int tbl_calc_tree(struct tbl *);
-
-__END_DECLS
-
-#endif /*TBL_EXTERN_H*/
diff --git a/usr.bin/mandoc/tbl_html.c b/usr.bin/mandoc/tbl_html.c
new file mode 100644
index 00000000000..b5ca990b274
--- /dev/null
+++ b/usr.bin/mandoc/tbl_html.c
@@ -0,0 +1,73 @@
+/* $Id: tbl_html.c,v 1.1 2011/01/04 22:28:17 schwarze Exp $ */
+/*
+ * Copyright (c) 2011 Kristaps Dzonsons <kristaps@kth.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mandoc.h"
+#include "out.h"
+#include "html.h"
+
+void
+print_tbl(struct html *h, const struct tbl_span *sp)
+{
+ const struct tbl_head *hp;
+ const struct tbl_dat *dp;
+ struct tag *tt;
+
+ switch (sp->pos) {
+ case (TBL_SPAN_HORIZ):
+ /* FALLTHROUGH */
+ case (TBL_SPAN_DHORIZ):
+ return;
+ default:
+ break;
+ }
+
+ /* Inhibit printing of spaces: we do padding ourselves. */
+
+ h->flags |= HTML_NONOSPACE;
+ h->flags |= HTML_NOSPACE;
+
+ print_otag(h, TAG_TABLE, 0, NULL);
+ print_otag(h, TAG_TR, 0, NULL);
+
+ dp = sp->first;
+ for (hp = sp->head; hp; hp = hp->next) {
+ switch (hp->pos) {
+ case (TBL_HEAD_VERT):
+ /* FALLTHROUGH */
+ case (TBL_HEAD_DVERT):
+ continue;
+ case (TBL_HEAD_DATA):
+ break;
+ }
+ tt = print_otag(h, TAG_TD, 0, NULL);
+ if (dp) {
+ if (dp->string)
+ print_text(h, dp->string);
+ dp = dp->next;
+ }
+ print_tagq(h, tt);
+ }
+ h->flags &= ~HTML_NONOSPACE;
+}
diff --git a/usr.bin/mandoc/tbl_layout.c b/usr.bin/mandoc/tbl_layout.c
index 7fa9610e864..6b27e4873b0 100644
--- a/usr.bin/mandoc/tbl_layout.c
+++ b/usr.bin/mandoc/tbl_layout.c
@@ -1,6 +1,6 @@
-/* $Id: tbl_layout.c,v 1.3 2010/10/15 22:50:28 schwarze Exp $ */
+/* $Id: tbl_layout.c,v 1.4 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * Copyright (c) 2009, 2010, 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
@@ -14,38 +14,30 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/queue.h>
-#include <sys/types.h>
-
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
-#include "out.h"
-#include "term.h"
-#include "tbl_extern.h"
+#include "mandoc.h"
+#include "libmandoc.h"
+#include "libroff.h"
struct tbl_phrase {
char name;
enum tbl_cellt key;
};
-#define KEYS_MAX 17
+#define KEYS_MAX 11
static const struct tbl_phrase keys[KEYS_MAX] = {
{ 'c', TBL_CELL_CENTRE },
- { 'C', TBL_CELL_CENTRE },
{ 'r', TBL_CELL_RIGHT },
- { 'R', TBL_CELL_RIGHT },
{ 'l', TBL_CELL_LEFT },
- { 'L', TBL_CELL_LEFT },
{ 'n', TBL_CELL_NUMBER },
- { 'N', TBL_CELL_NUMBER },
{ 's', TBL_CELL_SPAN },
- { 'S', TBL_CELL_SPAN },
{ 'a', TBL_CELL_LONG },
- { 'A', TBL_CELL_LONG },
{ '^', TBL_CELL_DOWN },
{ '-', TBL_CELL_HORIZ },
{ '_', TBL_CELL_HORIZ },
@@ -53,191 +45,163 @@ static const struct tbl_phrase keys[KEYS_MAX] = {
{ '|', TBL_CELL_VERT }
};
-static int mods(struct tbl *, struct tbl_cell *,
- const char *, int,
- const char *, int, int);
-static int cell(struct tbl *, struct tbl_row *,
- const char *, int, int);
-static int row(struct tbl *, const char *,
+static int mods(struct tbl_node *, struct tbl_cell *,
int, const char *, int *);
-
+static int cell(struct tbl_node *, struct tbl_row *,
+ int, const char *, int *);
+static void row(struct tbl_node *, int, const char *, int *);
+static struct tbl_cell *cell_alloc(struct tbl_node *,
+ struct tbl_row *, enum tbl_cellt);
+static void head_adjust(const struct tbl_cell *,
+ struct tbl_head *);
static int
-mods(struct tbl *tbl, struct tbl_cell *cp, const char *p,
- int pp, const char *f, int ln, int pos)
+mods(struct tbl_node *tbl, struct tbl_cell *cp,
+ int ln, const char *p, int *pos)
{
char buf[5];
int i;
+mod:
/*
* XXX: since, at least for now, modifiers are non-conflicting
* (are separable by value, regardless of position), we let
* modifiers come in any order. The existing tbl doesn't let
* this happen.
*/
-
- if (0 == p[pp])
+ switch (p[*pos]) {
+ case ('\0'):
+ /* FALLTHROUGH */
+ case (' '):
+ /* FALLTHROUGH */
+ case ('\t'):
+ /* FALLTHROUGH */
+ case (','):
+ /* FALLTHROUGH */
+ case ('.'):
return(1);
+ default:
+ break;
+ }
/* Parse numerical spacing from modifier string. */
- if (isdigit((u_char)p[pp])) {
+ if (isdigit((unsigned char)p[*pos])) {
for (i = 0; i < 4; i++) {
- if ( ! isdigit((u_char)p[pp + i]))
+ if ( ! isdigit((unsigned char)p[*pos + i]))
break;
- buf[i] = p[pp + i];
+ buf[i] = p[*pos + i];
}
- buf[i] = 0;
+ buf[i] = '\0';
/* No greater than 4 digits. */
- if (4 == i)
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, pos + pp));
-
- /*
- * We can't change the spacing in any subsequent layout
- * definitions. FIXME: I don't think we can change the
- * spacing for a column at all, after it's already been
- * initialised.
- */
-
- if (TBL_PART_CLAYOUT != tbl->part)
- cp->spacing = atoi(buf);
- else if ( ! tbl_warnx(tbl, ERR_SYNTAX, f, ln, pos + pp))
+ if (4 == i) {
+ TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos);
return(0);
-
- /* Continue parsing modifiers. */
+ }
+
+ *pos += i;
+ cp->spacing = atoi(buf);
- return(mods(tbl, cp, p, pp + i, f, ln, pos));
+ goto mod;
+ /* NOTREACHED */
}
/* TODO: GNU has many more extensions. */
- switch (p[pp]) {
+ switch (tolower(p[(*pos)++])) {
case ('z'):
- /* FALLTHROUGH */
- case ('Z'):
cp->flags |= TBL_CELL_WIGN;
- return(mods(tbl, cp, p, pp + 1, f, ln, pos));
- case ('w'):
- /* FALLTHROUGH */
- case ('W'): /* XXX for now, ignore minimal column width */
- while (isdigit((u_char)p[++pp]));
- return(mods(tbl, cp, p, pp, f, ln, pos));
+ goto mod;
case ('u'):
- /* FALLTHROUGH */
- case ('U'):
cp->flags |= TBL_CELL_UP;
- return(mods(tbl, cp, p, pp + 1, f, ln, pos));
+ goto mod;
case ('e'):
- /* FALLTHROUGH */
- case ('E'):
cp->flags |= TBL_CELL_EQUAL;
- return(mods(tbl, cp, p, pp + 1, f, ln, pos));
+ goto mod;
case ('t'):
- /* FALLTHROUGH */
- case ('T'):
cp->flags |= TBL_CELL_TALIGN;
- return(mods(tbl, cp, p, pp + 1, f, ln, pos));
+ goto mod;
case ('d'):
- /* FALLTHROUGH */
- case ('D'):
cp->flags |= TBL_CELL_BALIGN;
- return(mods(tbl, cp, p, pp + 1, f, ln, pos));
+ goto mod;
case ('f'):
- pp++;
- /* FALLTHROUGH */
- case ('B'):
- /* FALLTHROUGH */
- case ('I'):
- /* FALLTHROUGH */
+ break;
case ('b'):
/* FALLTHROUGH */
case ('i'):
+ (*pos)--;
break;
default:
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, pos + pp));
+ TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos - 1);
+ return(0);
}
- switch (p[pp]) {
+ switch (tolower(p[(*pos)++])) {
case ('b'):
- /* FALLTHROUGH */
- case ('B'):
cp->flags |= TBL_CELL_BOLD;
- return(mods(tbl, cp, p, pp + 1, f, ln, pos));
+ goto mod;
case ('i'):
- /* FALLTHROUGH */
- case ('I'):
cp->flags |= TBL_CELL_ITALIC;
- return(mods(tbl, cp, p, pp + 1, f, ln, pos));
+ goto mod;
default:
break;
}
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, pos + pp));
+ TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos - 1);
+ return(0);
}
-
static int
-cell(struct tbl *tbl, struct tbl_row *rp,
- const char *f, int ln, int pos)
+cell(struct tbl_node *tbl, struct tbl_row *rp,
+ int ln, const char *p, int *pos)
{
- struct tbl_cell *cp;
- const char *p;
- int j, i;
+ int i;
enum tbl_cellt c;
/* Parse the column position (`r', `R', `|', ...). */
- c = TBL_CELL_MAX;
- for (p = tbl_last(), i = 0; i < KEYS_MAX; i++) {
- if (keys[i].name != p[0])
- continue;
- c = keys[i].key;
- break;
+ for (i = 0; i < KEYS_MAX; i++)
+ if (tolower(p[*pos]) == keys[i].name)
+ break;
+
+ if (KEYS_MAX == i) {
+ TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos);
+ return(0);
}
- if (i == KEYS_MAX)
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, pos));
+ (*pos)++;
+ c = keys[i].key;
/* Extra check for the double-vertical. */
- if (TBL_CELL_VERT == c && '|' == p[1]) {
- j = 2;
+ if (TBL_CELL_VERT == c && '|' == p[*pos]) {
+ (*pos)++;
c = TBL_CELL_DVERT;
- } else
- j = 1;
+ }
- /* Disallow subsequent spacers. */
+ /* Disallow adjacent spacers. */
- /* LINTED */
- cp = TAILQ_LAST(&rp->cell, tbl_cellh);
-
- if (cp && (TBL_CELL_VERT == c || TBL_CELL_DVERT == c) &&
- (TBL_CELL_VERT == cp->pos ||
- TBL_CELL_DVERT == cp->pos))
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, pos));
+ if (rp->last && (TBL_CELL_VERT == c || TBL_CELL_DVERT == c) &&
+ (TBL_CELL_VERT == rp->last->pos ||
+ TBL_CELL_DVERT == rp->last->pos)) {
+ TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos - 1);
+ return(0);
+ }
/* Allocate cell then parse its modifiers. */
- if (NULL == (cp = tbl_cell_alloc(rp, c)))
- return(0);
- return(mods(tbl, cp, p, j, f, ln, pos));
+ return(mods(tbl, cell_alloc(tbl, rp, c), ln, p, pos));
}
-static int
-row(struct tbl *tbl, const char *f, int ln,
- const char *p, int *pos)
+static void
+row(struct tbl_node *tbl, int ln, const char *p, int *pos)
{
struct tbl_row *rp;
- int sv;
-
- rp = tbl_row_alloc(tbl);
-again:
- sv = *pos;
- /*
+row: /*
* EBNF describing this section:
*
* row ::= row_list [:space:]* [.]?[\n]
@@ -247,41 +211,165 @@ again:
* row_elem ::= [\t\ ]*[:alpha:]+
*/
- switch (tbl_next(p, pos)) {
- case (TBL_TOK_TAB):
- /* FALLTHROUGH */
- case (TBL_TOK_SPACE):
- goto again;
- case (TBL_TOK_WORD):
- if ( ! cell(tbl, rp, f, ln, sv))
- return(0);
- goto again;
- case (TBL_TOK_COMMA):
- if (NULL == TAILQ_FIRST(&rp->cell))
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
- return(row(tbl, f, ln, p, pos));
- case (TBL_TOK_PERIOD):
- if (NULL == TAILQ_FIRST(&rp->cell))
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
+ rp = mandoc_calloc(1, sizeof(struct tbl_row));
+ if (tbl->last_row) {
+ tbl->last_row->next = rp;
+ tbl->last_row = rp;
+ } else
+ tbl->last_row = tbl->first_row = rp;
+
+cell:
+ while (isspace((unsigned char)p[*pos]))
+ (*pos)++;
+
+ /* Safely exit layout context. */
+
+ if ('.' == p[*pos]) {
tbl->part = TBL_PART_DATA;
- break;
- case (TBL_TOK_NIL):
- if (NULL == TAILQ_FIRST(&rp->cell))
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
- break;
- default:
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
+ if (NULL == tbl->first_row)
+ TBL_MSG(tbl, MANDOCERR_TBLNOLAYOUT, ln, *pos);
+ (*pos)++;
+ return;
}
- return(1);
-}
+ /* End (and possibly restart) a row. */
+
+ if (',' == p[*pos]) {
+ (*pos)++;
+ goto row;
+ } else if ('\0' == p[*pos])
+ return;
+
+ if ( ! cell(tbl, rp, ln, p, pos))
+ return;
+ goto cell;
+ /* NOTREACHED */
+}
int
-tbl_layout(struct tbl *tbl, const char *f, int ln, const char *p)
+tbl_layout(struct tbl_node *tbl, int ln, const char *p)
{
int pos;
pos = 0;
- return(row(tbl, f, ln, p, &pos));
+ row(tbl, ln, p, &pos);
+
+ /* Always succeed. */
+ return(1);
+}
+
+static struct tbl_cell *
+cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos)
+{
+ struct tbl_cell *p, *pp;
+ struct tbl_head *h, *hp;
+
+ p = mandoc_calloc(1, sizeof(struct tbl_cell));
+
+ if (NULL != (pp = rp->last)) {
+ rp->last->next = p;
+ rp->last = p;
+ } else
+ rp->last = rp->first = p;
+
+ p->pos = pos;
+
+ /*
+ * This is a little bit complicated. Here we determine the
+ * header the corresponds to a cell. We add headers dynamically
+ * when need be or re-use them, otherwise. As an example, given
+ * the following:
+ *
+ * 1 c || l
+ * 2 | c | l
+ * 3 l l
+ * 3 || c | l |.
+ *
+ * We first add the new headers (as there are none) in (1); then
+ * in (2) we insert the first spanner (as it doesn't match up
+ * with the header); then we re-use the prior data headers,
+ * skipping over the spanners; then we re-use everything and add
+ * a last spanner. Note that VERT headers are made into DVERT
+ * ones.
+ */
+
+ h = pp ? pp->head->next : tbl->first_head;
+
+ if (h) {
+ /* Re-use data header. */
+ if (TBL_HEAD_DATA == h->pos &&
+ (TBL_CELL_VERT != p->pos &&
+ TBL_CELL_DVERT != p->pos)) {
+ p->head = h;
+ return(p);
+ }
+
+ /* Re-use spanner header. */
+ if (TBL_HEAD_DATA != h->pos &&
+ (TBL_CELL_VERT == p->pos ||
+ TBL_CELL_DVERT == p->pos)) {
+ head_adjust(p, h);
+ p->head = h;
+ return(p);
+ }
+
+ /* Right-shift headers with a new spanner. */
+ if (TBL_HEAD_DATA == h->pos &&
+ (TBL_CELL_VERT == p->pos ||
+ TBL_CELL_DVERT == p->pos)) {
+ hp = mandoc_calloc(1, sizeof(struct tbl_head));
+ hp->ident = tbl->opts.cols++;
+ hp->prev = h->prev;
+ if (h->prev)
+ h->prev->next = hp;
+ if (h == tbl->first_head)
+ tbl->first_head = hp;
+ h->prev = hp;
+ hp->next = h;
+ head_adjust(p, hp);
+ p->head = hp;
+ return(p);
+ }
+
+ if (NULL != (h = h->next)) {
+ head_adjust(p, h);
+ p->head = h;
+ return(p);
+ }
+
+ /* Fall through to default case... */
+ }
+
+ hp = mandoc_calloc(1, sizeof(struct tbl_head));
+ hp->ident = tbl->opts.cols++;
+
+ if (tbl->last_head) {
+ hp->prev = tbl->last_head;
+ tbl->last_head->next = hp;
+ tbl->last_head = hp;
+ } else
+ tbl->last_head = tbl->first_head = hp;
+
+ head_adjust(p, hp);
+ p->head = hp;
+ return(p);
}
+
+static void
+head_adjust(const struct tbl_cell *cell, struct tbl_head *head)
+{
+ if (TBL_CELL_VERT != cell->pos &&
+ TBL_CELL_DVERT != cell->pos) {
+ head->pos = TBL_HEAD_DATA;
+ return;
+ }
+
+ if (TBL_CELL_VERT == cell->pos)
+ if (TBL_HEAD_DVERT != head->pos)
+ head->pos = TBL_HEAD_VERT;
+
+ if (TBL_CELL_DVERT == cell->pos)
+ head->pos = TBL_HEAD_DVERT;
+}
+
diff --git a/usr.bin/mandoc/tbl_option.c b/usr.bin/mandoc/tbl_option.c
deleted file mode 100644
index 09cd3afd680..00000000000
--- a/usr.bin/mandoc/tbl_option.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/* $Id: tbl_option.c,v 1.2 2010/10/15 21:33:47 schwarze Exp $ */
-/*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <sys/queue.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "out.h"
-#include "term.h"
-#include "tbl_extern.h"
-
-struct tbl_phrase {
- char *name;
- int key;
- int ident;
-#define KEY_CENTRE 0
-#define KEY_DELIM 1
-#define KEY_EXPAND 2
-#define KEY_BOX 3
-#define KEY_DBOX 4
-#define KEY_ALLBOX 5
-#define KEY_TAB 6
-#define KEY_LINESIZE 7
-#define KEY_NOKEEP 8
-#define KEY_DPOINT 9
-#define KEY_NOSPACE 10
-#define KEY_FRAME 11
-#define KEY_DFRAME 12
-};
-
-#define KEY_MAXKEYS 14
-
-static const struct tbl_phrase keys[KEY_MAXKEYS] = {
- { "center", TBL_OPT_CENTRE, KEY_CENTRE},
- { "centre", TBL_OPT_CENTRE, KEY_CENTRE},
- { "delim", 0, KEY_DELIM},
- { "expand", TBL_OPT_EXPAND, KEY_EXPAND},
- { "box", TBL_OPT_BOX, KEY_BOX},
- { "doublebox", TBL_OPT_DBOX, KEY_DBOX},
- { "allbox", TBL_OPT_ALLBOX, KEY_ALLBOX},
- { "frame", TBL_OPT_BOX, KEY_FRAME},
- { "doubleframe", TBL_OPT_DBOX, KEY_DFRAME},
- { "tab", 0, KEY_TAB},
- { "linesize", 0, KEY_LINESIZE},
- { "nokeep", TBL_OPT_NOKEEP, KEY_NOKEEP},
- { "decimalpoint", 0, KEY_DPOINT},
- { "nospaces", TBL_OPT_NOSPACE, KEY_NOSPACE},
-};
-
-static int arg(struct tbl *, const char *,
- int, const char *, int *, int);
-static int opt(struct tbl *, const char *,
- int, const char *, int *);
-
-static int
-arg(struct tbl *tbl, const char *f, int ln,
- const char *p, int *pos, int key)
-{
- const char *buf;
- int sv;
-
-again:
- sv = *pos;
-
- switch (tbl_next(p, pos)) {
- case (TBL_TOK_OPENPAREN):
- break;
- case (TBL_TOK_SPACE):
- /* FALLTHROUGH */
- case (TBL_TOK_TAB):
- goto again;
- default:
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
- }
-
- sv = *pos;
-
- switch (tbl_next(p, pos)) {
- case (TBL_TOK_WORD):
- break;
- default:
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
- }
-
- buf = tbl_last();
-
- switch (key) {
- case (KEY_DELIM):
- if (2 != strlen(buf))
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
- tbl->delims[0] = buf[0];
- tbl->delims[1] = buf[1];
- break;
- case (KEY_TAB):
- if (1 != strlen(buf))
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
- tbl->tab = buf[0];
- break;
- case (KEY_LINESIZE):
- if (-1 == (tbl->linesize = tbl_last_uint()))
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
- break;
- case (KEY_DPOINT):
- if (1 != strlen(buf))
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
- tbl->decimal = buf[0];
- break;
- default:
- abort();
- }
-
- sv = *pos;
-
- switch (tbl_next(p, pos)) {
- case (TBL_TOK_CLOSEPAREN):
- break;
- default:
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
- }
-
- return(1);
-}
-
-
-static int
-opt(struct tbl *tbl, const char *f, int ln, const char *p, int *pos)
-{
- int i, sv;
-
-again:
- sv = *pos;
-
- /*
- * EBNF describing this section:
- *
- * options ::= option_list [:space:]* [;][\n]
- * option_list ::= option option_tail
- * option_tail ::= [:space:]+ option_list |
- * ::= epsilon
- * option ::= [:alpha:]+ args
- * args ::= [:space:]* [(] [:alpha:]+ [)]
- */
-
- switch (tbl_next(p, pos)) {
- case (TBL_TOK_WORD):
- break;
- case (TBL_TOK_SPACE):
- /* FALLTHROUGH */
- case (TBL_TOK_TAB):
- goto again;
- case (TBL_TOK_SEMICOLON):
- tbl->part = TBL_PART_LAYOUT;
- return(1);
- default:
- return(tbl_errx(tbl, ERR_SYNTAX, f, ln, sv));
- }
-
- for (i = 0; i < KEY_MAXKEYS; i++) {
- if (strcasecmp(tbl_last(), keys[i].name))
- continue;
- if (keys[i].key)
- tbl->opts |= keys[i].key;
- else if ( ! arg(tbl, f, ln, p, pos, keys[i].ident))
- return(0);
-
- break;
- }
-
- if (KEY_MAXKEYS == i)
- return(tbl_errx(tbl, ERR_OPTION, f, ln, sv));
-
- return(opt(tbl, f, ln, p, pos));
-}
-
-
-int
-tbl_option(struct tbl *tbl, const char *f, int ln, const char *p)
-{
- int pos;
-
- pos = 0;
- return(opt(tbl, f, ln, p, &pos));
-}
diff --git a/usr.bin/mandoc/tbl_opts.c b/usr.bin/mandoc/tbl_opts.c
new file mode 100644
index 00000000000..9a8f0aba620
--- /dev/null
+++ b/usr.bin/mandoc/tbl_opts.c
@@ -0,0 +1,260 @@
+/* $Id: tbl_opts.c,v 1.1 2011/01/04 22:28:17 schwarze Exp $ */
+/*
+ * Copyright (c) 2009, 2010 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
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mandoc.h"
+#include "libroff.h"
+
+enum tbl_ident {
+ KEY_CENTRE = 0,
+ KEY_DELIM,
+ KEY_EXPAND,
+ KEY_BOX,
+ KEY_DBOX,
+ KEY_ALLBOX,
+ KEY_TAB,
+ KEY_LINESIZE,
+ KEY_NOKEEP,
+ KEY_DPOINT,
+ KEY_NOSPACE,
+ KEY_FRAME,
+ KEY_DFRAME,
+ KEY_MAX
+};
+
+struct tbl_phrase {
+ const char *name;
+ int key;
+ enum tbl_ident ident;
+};
+
+/* Handle Commonwealth/American spellings. */
+#define KEY_MAXKEYS 14
+
+/* Maximum length of key name string. */
+#define KEY_MAXNAME 13
+
+/* Maximum length of key number size. */
+#define KEY_MAXNUMSZ 10
+
+static const struct tbl_phrase keys[KEY_MAXKEYS] = {
+ { "center", TBL_OPT_CENTRE, KEY_CENTRE},
+ { "centre", TBL_OPT_CENTRE, KEY_CENTRE},
+ { "delim", 0, KEY_DELIM},
+ { "expand", TBL_OPT_EXPAND, KEY_EXPAND},
+ { "box", TBL_OPT_BOX, KEY_BOX},
+ { "doublebox", TBL_OPT_DBOX, KEY_DBOX},
+ { "allbox", TBL_OPT_ALLBOX, KEY_ALLBOX},
+ { "frame", TBL_OPT_BOX, KEY_FRAME},
+ { "doubleframe", TBL_OPT_DBOX, KEY_DFRAME},
+ { "tab", 0, KEY_TAB},
+ { "linesize", 0, KEY_LINESIZE},
+ { "nokeep", TBL_OPT_NOKEEP, KEY_NOKEEP},
+ { "decimalpoint", 0, KEY_DPOINT},
+ { "nospaces", TBL_OPT_NOSPACE, KEY_NOSPACE},
+};
+
+static int arg(struct tbl_node *, int,
+ const char *, int *, int);
+static void opt(struct tbl_node *, int,
+ const char *, int *);
+
+static int
+arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key)
+{
+ int i;
+ char buf[KEY_MAXNUMSZ];
+
+ while (isspace((unsigned char)p[*pos]))
+ (*pos)++;
+
+ /* Arguments always begin with a parenthesis. */
+
+ if ('(' != p[*pos]) {
+ TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos);
+ return(0);
+ }
+
+ (*pos)++;
+
+ /*
+ * The arguments can be ANY value, so we can't just stop at the
+ * next close parenthesis (the argument can be a closed
+ * parenthesis itself).
+ */
+
+ switch (key) {
+ case (KEY_DELIM):
+ if ('\0' == (tbl->opts.delims[0] = p[(*pos)++])) {
+ TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
+ return(0);
+ }
+
+ if ('\0' == (tbl->opts.delims[1] = p[(*pos)++])) {
+ TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
+ return(0);
+ }
+ break;
+ case (KEY_TAB):
+ if ('\0' != (tbl->opts.tab = p[(*pos)++]))
+ break;
+
+ TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
+ return(0);
+ case (KEY_LINESIZE):
+ for (i = 0; i < KEY_MAXNUMSZ && p[*pos]; i++, (*pos)++) {
+ buf[i] = p[*pos];
+ if ( ! isdigit((unsigned char)buf[i]))
+ break;
+ }
+
+ if (i < KEY_MAXNUMSZ) {
+ buf[i] = '\0';
+ tbl->opts.linesize = atoi(buf);
+ break;
+ }
+
+ (*tbl->msg)(MANDOCERR_TBL, tbl->data, ln, *pos, NULL);
+ return(0);
+ case (KEY_DPOINT):
+ if ('\0' != (tbl->opts.decimal = p[(*pos)++]))
+ break;
+
+ TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
+ return(0);
+ default:
+ abort();
+ /* NOTREACHED */
+ }
+
+ /* End with a close parenthesis. */
+
+ if (')' == p[(*pos)++])
+ return(1);
+
+ TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
+ return(0);
+}
+
+static void
+opt(struct tbl_node *tbl, int ln, const char *p, int *pos)
+{
+ int i, sv;
+ char buf[KEY_MAXNAME];
+
+ /*
+ * Parse individual options from the stream as surrounded by
+ * this goto. Each pass through the routine parses out a single
+ * option and registers it. Option arguments are processed in
+ * the arg() function.
+ */
+
+again: /*
+ * EBNF describing this section:
+ *
+ * options ::= option_list [:space:]* [;][\n]
+ * option_list ::= option option_tail
+ * option_tail ::= [:space:]+ option_list |
+ * ::= epsilon
+ * option ::= [:alpha:]+ args
+ * args ::= [:space:]* [(] [:alpha:]+ [)]
+ */
+
+ while (isspace((unsigned char)p[*pos]))
+ (*pos)++;
+
+ /* Safe exit point. */
+
+ if (';' == p[*pos])
+ return;
+
+ /* Copy up to first non-alpha character. */
+
+ for (sv = *pos, i = 0; i < KEY_MAXNAME; i++, (*pos)++) {
+ buf[i] = tolower(p[*pos]);
+ if ( ! isalpha((unsigned char)buf[i]))
+ break;
+ }
+
+ /* Exit if buffer is empty (or overrun). */
+
+ if (KEY_MAXNAME == i || 0 == i) {
+ TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos);
+ return;
+ }
+
+ buf[i] = '\0';
+
+ while (isspace((unsigned char)p[*pos]))
+ (*pos)++;
+
+ /*
+ * Look through all of the available keys to find one that
+ * matches the input. FIXME: hashtable this.
+ */
+
+ for (i = 0; i < KEY_MAXKEYS; i++) {
+ if (strcmp(buf, keys[i].name))
+ continue;
+
+ /*
+ * Note: this is more difficult to recover from, as we
+ * can be anywhere in the option sequence and it's
+ * harder to jump to the next. Meanwhile, just bail out
+ * of the sequence altogether.
+ */
+
+ if (keys[i].key)
+ tbl->opts.opts |= keys[i].key;
+ else if ( ! arg(tbl, ln, p, pos, keys[i].ident))
+ return;
+
+ break;
+ }
+
+ /*
+ * Allow us to recover from bad options by continuing to another
+ * parse sequence.
+ */
+
+ if (KEY_MAXKEYS == i)
+ TBL_MSG(tbl, MANDOCERR_TBLOPT, ln, sv);
+
+ goto again;
+ /* NOTREACHED */
+}
+
+int
+tbl_option(struct tbl_node *tbl, int ln, const char *p)
+{
+ int pos;
+
+ /*
+ * Table options are always on just one line, so automatically
+ * switch into the next input mode here.
+ */
+ tbl->part = TBL_PART_LAYOUT;
+
+ pos = 0;
+ opt(tbl, ln, p, &pos);
+
+ /* Always succeed. */
+ return(1);
+}
diff --git a/usr.bin/mandoc/tbl_term.c b/usr.bin/mandoc/tbl_term.c
index af5d54557c3..7b7a056ea3c 100644
--- a/usr.bin/mandoc/tbl_term.c
+++ b/usr.bin/mandoc/tbl_term.c
@@ -1,7 +1,6 @@
-/* $Id: tbl_term.c,v 1.4 2010/10/15 22:16:51 schwarze Exp $ */
+/* $Id: tbl_term.c,v 1.5 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
- * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@kth.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -15,154 +14,152 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/queue.h>
-
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "mandoc.h"
#include "out.h"
#include "term.h"
-#include "tbl_extern.h"
/* FIXME: `n' modifier doesn't always do the right thing. */
/* FIXME: `n' modifier doesn't use the cell-spacing buffer. */
-static void calc_data(struct termp *, struct tbl_data *);
-static void calc_data_literal(struct termp *, struct tbl_data *);
-static void calc_data_number(struct termp *, struct tbl_data *);
-static void calc_data_spanner(struct termp *, struct tbl_data *);
-static inline void write_char(struct termp *, char, int);
-static void write_data(struct termp *,
- const struct tbl_data *, int);
-static void write_data_literal(struct termp *,
- const struct tbl_data *, int);
-static void write_data_number(struct termp *,
- const struct tbl_data *, int);
-static void write_data_spanner(struct termp *,
- const struct tbl_data *, int);
-static void write_hframe(struct termp *, const struct tbl *);
-static void write_hrule(struct termp *, const struct tbl_span *);
-static void write_spanner(struct termp *, const struct tbl_head *);
-static void write_vframe(struct termp *, const struct tbl *);
-
-
-int
-tbl_write_term(struct termp *p, const struct tbl *tbl)
+static inline void tbl_char(struct termp *, char, int);
+static void tbl_hframe(struct termp *,
+ const struct tbl_span *);
+static void tbl_data_number(struct termp *,
+ const struct tbl *,
+ const struct tbl_dat *,
+ const struct termp_tbl *);
+static void tbl_data_literal(struct termp *,
+ const struct tbl_dat *,
+ const struct termp_tbl *);
+static void tbl_data(struct termp *, const struct tbl *,
+ const struct tbl_dat *,
+ const struct termp_tbl *);
+static void tbl_spanner(struct termp *,
+ const struct tbl_head *);
+static void tbl_hrule(struct termp *,
+ const struct tbl_span *);
+static void tbl_vframe(struct termp *,
+ const struct tbl *);
+static void tbl_calc(struct termp *,
+ const struct tbl_span *);
+static void tbl_calc_data(struct termp *,
+ const struct tbl *,
+ const struct tbl_dat *,
+ struct termp_tbl *);
+static void tbl_calc_data_literal(struct termp *,
+ const struct tbl_dat *,
+ struct termp_tbl *);
+static void tbl_calc_data_number(struct termp *,
+ const struct tbl *,
+ const struct tbl_dat *,
+ struct termp_tbl *);
+
+void
+term_tbl(struct termp *tp, const struct tbl_span *sp)
{
- const struct tbl_span *span;
- const struct tbl_data *data;
- const struct tbl_head *head;
+ const struct tbl_head *hp;
+ const struct tbl_dat *dp;
+
+ /* Inhibit printing of spaces: we do padding ourselves. */
+
+ tp->flags |= TERMP_NONOSPACE;
+ tp->flags |= TERMP_NOSPACE;
/*
- * Note that the absolute widths and decimal places for headers
- * were set when tbl_calc_term was called.
+ * The first time we're invoked for a given table block, create
+ * the termp_tbl structure. This contains the column
+ * configuration for the entire table, e.g., table-wide column
+ * width, decimal point, etc.
*/
- term_newln(p);
- p->flags |= TERMP_NOSPACE | TERMP_NONOSPACE;
+ if (TBL_SPAN_FIRST & sp->flags) {
+ assert(NULL == tp->tbl);
+ tp->tbl = calloc
+ (sp->tbl->cols, sizeof(struct termp_tbl));
+ if (NULL == tp->tbl) {
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ tbl_calc(tp, sp);
- /* First, write out our head horizontal frame. */
+ /* Flush out any preceding data. */
+ term_flushln(tp);
+ }
- write_hframe(p, tbl);
+ /* Horizontal frame at the start of boxed tables. */
- /*
- * Iterate through each span, and inside, through the global
- * headers. If the global header's a spanner, print it
- * directly; if it's data, use the corresponding data in the
- * span as the object to print.
- */
+ if (TBL_SPAN_FIRST & sp->flags)
+ tbl_hframe(tp, sp);
- TAILQ_FOREACH(span, &tbl->span, entries) {
- write_vframe(p, tbl);
+ /* Vertical frame at the start of each row. */
- /* Accomodate for the horizontal rule. */
- if (TBL_DATA_DHORIZ & span->flags ||
- TBL_DATA_HORIZ & span->flags) {
- write_hrule(p, span);
- write_vframe(p, tbl);
- term_flushln(p);
- continue;
- }
+ tbl_vframe(tp, sp->tbl);
+
+ /*
+ * Now print the actual data itself depending on the span type.
+ * Spanner spans get a horizontal rule; data spanners have their
+ * data printed by matching data to header.
+ */
- data = TAILQ_FIRST(&span->data);
- TAILQ_FOREACH(head, &tbl->head, entries) {
- switch (head->pos) {
+ switch (sp->pos) {
+ case (TBL_SPAN_HORIZ):
+ /* FALLTHROUGH */
+ case (TBL_SPAN_DHORIZ):
+ tbl_hrule(tp, sp);
+ break;
+ case (TBL_SPAN_DATA):
+ /* Iterate over template headers. */
+ dp = sp->first;
+ for (hp = sp->head; hp; hp = hp->next) {
+ switch (hp->pos) {
case (TBL_HEAD_VERT):
/* FALLTHROUGH */
case (TBL_HEAD_DVERT):
- write_spanner(p, head);
- break;
+ tbl_spanner(tp, hp);
+ continue;
case (TBL_HEAD_DATA):
- write_data(p, data, head->width);
- if (data)
- data = TAILQ_NEXT(data, entries);
break;
- default:
- abort();
- /* NOTREACHED */
}
+ tbl_data(tp, sp->tbl, dp,
+ &tp->tbl[hp->ident]);
+
+ /* Go to the next data cell. */
+ if (dp)
+ dp = dp->next;
}
- write_vframe(p, tbl);
- term_flushln(p);
+ break;
}
- /* Last, write out our tail horizontal frame. */
+ tbl_vframe(tp, sp->tbl);
+ term_flushln(tp);
- write_hframe(p, tbl);
-
- p->flags &= ~TERMP_NONOSPACE;
-
- return(1);
-}
-
-
-int
-tbl_calc_term(struct termp *p, struct tbl *tbl)
-{
- struct tbl_span *span;
- struct tbl_data *data;
- struct tbl_head *head;
-
- /* Calculate width as the max of column cells' widths. */
+ /*
+ * If we're the last row, clean up after ourselves: clear the
+ * existing table configuration and set it to NULL.
+ */
- TAILQ_FOREACH(span, &tbl->span, entries) {
- if (TBL_DATA_HORIZ & span->flags)
- continue;
- if (TBL_DATA_DHORIZ & span->flags)
- continue;
- if (TBL_DATA_NHORIZ & span->flags)
- continue;
- if (TBL_DATA_NDHORIZ & span->flags)
- continue;
- TAILQ_FOREACH(data, &span->data, entries)
- calc_data(p, data);
+ if (TBL_SPAN_LAST & sp->flags) {
+ tbl_hframe(tp, sp);
+ assert(tp->tbl);
+ free(tp->tbl);
+ tp->tbl = NULL;
}
- /* Calculate width as the simple spanner value. */
-
- TAILQ_FOREACH(head, &tbl->head, entries)
- switch (head->pos) {
- case (TBL_HEAD_VERT):
- head->width = term_len(p, 1);
- break;
- case (TBL_HEAD_DVERT):
- head->width = term_len(p, 2);
- break;
- default:
- break;
- }
+ tp->flags &= ~TERMP_NONOSPACE;
- return(1);
}
-
static void
-write_hrule(struct termp *p, const struct tbl_span *span)
+tbl_hrule(struct termp *tp, const struct tbl_span *sp)
{
- const struct tbl_head *head;
- char c;
+ const struct tbl_head *hp;
+ char c;
+ int width;
/*
* An hrule extends across the entire table and is demarked by a
@@ -171,21 +168,22 @@ write_hrule(struct termp *p, const struct tbl_span *span)
*/
c = '-';
- if (TBL_SPAN_DHORIZ & span->flags)
+ if (TBL_SPAN_DHORIZ == sp->pos)
c = '=';
/* FIXME: don't use `+' between data and a spanner! */
- TAILQ_FOREACH(head, &span->tbl->head, entries) {
- switch (head->pos) {
+ for (hp = sp->head; hp; hp = hp->next) {
+ width = tp->tbl[hp->ident].width;
+ switch (hp->pos) {
case (TBL_HEAD_DATA):
- write_char(p, c, head->width);
+ tbl_char(tp, c, width);
break;
case (TBL_HEAD_DVERT):
- write_char(p, '+', head->width);
+ tbl_char(tp, '+', width);
/* FALLTHROUGH */
case (TBL_HEAD_VERT):
- write_char(p, '+', head->width);
+ tbl_char(tp, '+', width);
break;
default:
abort();
@@ -194,13 +192,14 @@ write_hrule(struct termp *p, const struct tbl_span *span)
}
}
-
static void
-write_hframe(struct termp *p, const struct tbl *tbl)
+tbl_hframe(struct termp *tp, const struct tbl_span *sp)
{
- const struct tbl_head *head;
+ const struct tbl_head *hp;
+ int width;
- if ( ! (TBL_OPT_BOX & tbl->opts || TBL_OPT_DBOX & tbl->opts))
+ if ( ! (TBL_OPT_BOX & sp->tbl->opts ||
+ TBL_OPT_DBOX & sp->tbl->opts))
return;
/*
@@ -211,135 +210,70 @@ write_hframe(struct termp *p, const struct tbl *tbl)
* by `+' whenever a span is encountered.
*/
- if (TBL_OPT_DBOX & tbl->opts) {
- term_word(p, "+");
- TAILQ_FOREACH(head, &tbl->head, entries)
- write_char(p, '-', head->width);
- term_word(p, "+");
- term_flushln(p);
+ if (TBL_OPT_DBOX & sp->tbl->opts) {
+ term_word(tp, "+");
+ for (hp = sp->head; hp; hp = hp->next) {
+ width = tp->tbl[hp->ident].width;
+ tbl_char(tp, '-', width);
+ }
+ term_word(tp, "+");
+ term_flushln(tp);
}
- term_word(p, "+");
- TAILQ_FOREACH(head, &tbl->head, entries) {
- switch (head->pos) {
+ term_word(tp, "+");
+ for (hp = sp->head; hp; hp = hp->next) {
+ width = tp->tbl[hp->ident].width;
+ switch (hp->pos) {
case (TBL_HEAD_DATA):
- write_char(p, '-', head->width);
+ tbl_char(tp, '-', width);
break;
default:
- write_char(p, '+', head->width);
+ tbl_char(tp, '+', width);
break;
}
}
- term_word(p, "+");
- term_flushln(p);
+ term_word(tp, "+");
+ term_flushln(tp);
}
-
static void
-write_vframe(struct termp *p, const struct tbl *tbl)
+tbl_data(struct termp *tp, const struct tbl *tbl,
+ const struct tbl_dat *dp,
+ const struct termp_tbl *tbp)
{
- /* Always just a single vertical line. */
+ enum tbl_cellt pos;
- if ( ! (TBL_OPT_BOX & tbl->opts || TBL_OPT_DBOX & tbl->opts))
+ if (NULL == dp) {
+ tbl_char(tp, ASCII_NBRSP, tbp->width);
return;
- term_word(p, "|");
-}
-
-
-static void
-calc_data_spanner(struct termp *p, struct tbl_data *data)
-{
-
- /* N.B., these are horiz spanners (not vert) so always 1. */
- data->cell->head->width = term_len(p, 1);
-}
-
-
-static void
-calc_data_number(struct termp *p, struct tbl_data *data)
-{
- int sz, d;
- char *dp, pnt;
-
- /*
- * First calculate number width and decimal place (last + 1 for
- * no-decimal numbers). If the stored decimal is subsequent
- * ours, make our size longer by that difference
- * (right-"shifting"); similarly, if ours is subsequent the
- * stored, then extend the stored size by the difference.
- * Finally, re-assign the stored values.
- */
-
- /* TODO: use spacing modifier. */
-
- assert(data->string);
- sz = (int)term_strlen(p, data->string);
- pnt = data->span->tbl->decimal;
-
- dp = strchr(data->string, pnt);
- d = dp ? sz - (int)term_strlen(p, dp) : sz;
- d += term_len(p, 1);
-
- sz += term_len(p, 2);
-
- if (data->cell->head->decimal > d) {
- sz += data->cell->head->decimal - d;
- d = data->cell->head->decimal;
- } else
- data->cell->head->width +=
- d - data->cell->head->decimal;
-
- if (sz > data->cell->head->width)
- data->cell->head->width = sz;
- if (d > data->cell->head->decimal)
- data->cell->head->decimal = d;
-}
-
-
-static void
-calc_data_literal(struct termp *p, struct tbl_data *data)
-{
- int sz, bufsz;
-
- /*
- * Calculate our width and use the spacing, with a minimum
- * spacing dictated by position (centre, e.g,. gets a space on
- * either side, while right/left get a single adjacent space).
- */
-
- assert(data->string);
- sz = (int)term_strlen(p, data->string);
+ }
- switch (data->cell->pos) {
- case (TBL_CELL_LONG):
+ switch (dp->pos) {
+ case (TBL_DATA_NONE):
+ tbl_char(tp, ASCII_NBRSP, tbp->width);
+ return;
+ case (TBL_DATA_HORIZ):
/* FALLTHROUGH */
- case (TBL_CELL_CENTRE):
- bufsz = 2;
- break;
+ case (TBL_DATA_NHORIZ):
+ tbl_char(tp, '-', tbp->width);
+ return;
+ case (TBL_DATA_NDHORIZ):
+ /* FALLTHROUGH */
+ case (TBL_DATA_DHORIZ):
+ tbl_char(tp, '=', tbp->width);
+ return;
default:
- bufsz = 1;
break;
}
+
+ pos = dp->layout ? dp->layout->pos : TBL_CELL_LEFT;
- if (data->cell->spacing)
- bufsz = bufsz > data->cell->spacing ?
- bufsz : data->cell->spacing;
-
- sz += term_len(p, bufsz);
- if (data->cell->head->width < sz)
- data->cell->head->width = sz;
-}
-
-
-static void
-calc_data(struct termp *p, struct tbl_data *data)
-{
-
- switch (data->cell->pos) {
+ switch (pos) {
case (TBL_CELL_HORIZ):
- /* FALLTHROUGH */
+ tbl_char(tp, '-', tbp->width);
+ break;
case (TBL_CELL_DHORIZ):
- calc_data_spanner(p, data);
+ tbl_char(tp, '=', tbp->width);
break;
case (TBL_CELL_LONG):
/* FALLTHROUGH */
@@ -348,126 +282,184 @@ calc_data(struct termp *p, struct tbl_data *data)
case (TBL_CELL_LEFT):
/* FALLTHROUGH */
case (TBL_CELL_RIGHT):
- calc_data_literal(p, data);
+ tbl_data_literal(tp, dp, tbp);
break;
case (TBL_CELL_NUMBER):
- calc_data_number(p, data);
- break;
- case (TBL_CELL_SPAN):
- data->cell->head->width = 0;
+ tbl_data_number(tp, tbl, dp, tbp);
break;
default:
abort();
/* NOTREACHED */
}
}
-
-
static void
-write_data_spanner(struct termp *p, const struct tbl_data *data, int width)
+tbl_spanner(struct termp *tp, const struct tbl_head *hp)
{
- /*
- * Write spanners dictated by both our cell designation (in the
- * layout) or as data.
- */
- if (TBL_DATA_HORIZ & data->flags)
- write_char(p, '-', width);
- else if (TBL_DATA_DHORIZ & data->flags)
- write_char(p, '=', width);
- else if (TBL_CELL_HORIZ == data->cell->pos)
- write_char(p, '-', width);
- else if (TBL_CELL_DHORIZ == data->cell->pos)
- write_char(p, '=', width);
+ switch (hp->pos) {
+ case (TBL_HEAD_VERT):
+ term_word(tp, "|");
+ break;
+ case (TBL_HEAD_DVERT):
+ term_word(tp, "||");
+ break;
+ default:
+ break;
+ }
}
-
static void
-write_data_number(struct termp *p, const struct tbl_data *data, int width)
+tbl_vframe(struct termp *tp, const struct tbl *tbl)
{
- char *dp, pnt;
- int d, padl, sz;
-
- /*
- * See calc_data_number(). Left-pad by taking the offset of our
- * and the maximum decimal; right-pad by the remaining amount.
- */
+ /* Always just a single vertical line. */
- sz = (int)term_strlen(p, data->string);
- pnt = data->span->tbl->decimal;
+ if (TBL_OPT_BOX & tbl->opts || TBL_OPT_DBOX & tbl->opts)
+ term_word(tp, "|");
+}
- if (NULL == (dp = strchr(data->string, pnt))) {
- d = sz + 1;
- } else {
- d = (int)(dp - data->string) + 1;
- }
+static inline void
+tbl_char(struct termp *tp, char c, int len)
+{
+ int i, sz;
+ char cp[2];
- assert(d <= data->cell->head->decimal);
- assert(sz - d <= data->cell->head->width -
- data->cell->head->decimal);
+ cp[0] = c;
+ cp[1] = '\0';
- padl = data->cell->head->decimal - d + 1;
- assert(width - sz - padl);
+ sz = term_strlen(tp, cp);
- write_char(p, ' ', padl);
- term_word(p, data->string);
- write_char(p, ' ', width - sz - padl);
+ for (i = 0; i < len; i += sz)
+ term_word(tp, cp);
}
-
static void
-write_data_literal(struct termp *p, const struct tbl_data *data, int width)
+tbl_data_literal(struct termp *tp,
+ const struct tbl_dat *dp,
+ const struct termp_tbl *tblp)
{
- int padl, padr;
+ int padl, padr, ssz;
+ enum tbl_cellt pos;
padl = padr = 0;
- switch (data->cell->pos) {
+ pos = dp->layout ? dp->layout->pos : TBL_CELL_LEFT;
+ ssz = term_len(tp, 1);
+
+ switch (pos) {
case (TBL_CELL_LONG):
- padl = 1;
- padr = width - (int)term_strlen(p, data->string) - 1;
+ padl = ssz;
+ padr = tblp->width - term_strlen(tp, dp->string) - ssz;
break;
case (TBL_CELL_CENTRE):
- padl = width - (int)term_strlen(p, data->string);
+ padl = tblp->width - term_strlen(tp, dp->string);
if (padl % 2)
padr++;
padl /= 2;
padr += padl;
break;
case (TBL_CELL_RIGHT):
- padl = width - (int)term_strlen(p, data->string);
+ padl = tblp->width - term_strlen(tp, dp->string);
break;
default:
- padr = width - (int)term_strlen(p, data->string);
+ padr = tblp->width - term_strlen(tp, dp->string);
break;
}
- write_char(p, ' ', padl);
- term_word(p, data->string);
- write_char(p, ' ', padr);
+ tbl_char(tp, ASCII_NBRSP, padl);
+ term_word(tp, dp->string);
+ tbl_char(tp, ASCII_NBRSP, padr);
}
+static void
+tbl_data_number(struct termp *tp, const struct tbl *tbl,
+ const struct tbl_dat *dp,
+ const struct termp_tbl *tblp)
+{
+ char *decp, buf[2];
+ int d, padl, sz, psz, ssz, i;
+
+ /*
+ * See calc_data_number(). Left-pad by taking the offset of our
+ * and the maximum decimal; right-pad by the remaining amount.
+ */
+
+ sz = term_strlen(tp, dp->string);
+ psz = term_strlen(tp, ".");
+
+ if (NULL != (decp = strchr(dp->string, tbl->decimal))) {
+ buf[1] = '\0';
+ for (ssz = i = 0; decp != &dp->string[i]; i++) {
+ buf[0] = dp->string[i];
+ ssz += term_strlen(tp, buf);
+ }
+ d = ssz + psz;
+ } else
+ d = sz + psz;
+
+ assert(d <= tblp->decimal);
+ assert(sz - d <= tblp->width - tblp->decimal);
+
+ padl = tblp->decimal - d + term_len(tp, 1);
+ assert(tblp->width - sz - padl);
+
+ tbl_char(tp, ASCII_NBRSP, padl);
+ term_word(tp, dp->string);
+ tbl_char(tp, ASCII_NBRSP, tblp->width - sz - padl);
+}
static void
-write_data(struct termp *p, const struct tbl_data *data, int width)
+tbl_calc(struct termp *tp, const struct tbl_span *sp)
{
+ const struct tbl_dat *dp;
+ const struct tbl_head *hp;
+ struct termp_tbl *p;
- if (NULL == data) {
- write_char(p, ' ', width);
- return;
- }
+ /* Calculate width as the max of column cells' widths. */
- if (TBL_DATA_HORIZ & data->flags ||
- TBL_DATA_DHORIZ & data->flags) {
- write_data_spanner(p, data, width);
- return;
+ hp = sp->head;
+
+ for ( ; sp; sp = sp->next) {
+ if (TBL_SPAN_DATA != sp->pos)
+ continue;
+
+ for (dp = sp->first; dp; dp = dp->next) {
+ if (NULL == dp->layout)
+ continue;
+ p = &tp->tbl[dp->layout->head->ident];
+ tbl_calc_data(tp, sp->tbl, dp, p);
+ }
}
- switch (data->cell->pos) {
+ /* Calculate width as the simple spanner value. */
+
+ for ( ; hp; hp = hp->next)
+ switch (hp->pos) {
+ case (TBL_HEAD_VERT):
+ tp->tbl[hp->ident].width = term_len(tp, 1);
+ break;
+ case (TBL_HEAD_DVERT):
+ tp->tbl[hp->ident].width = term_len(tp, 2);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+tbl_calc_data(struct termp *tp, const struct tbl *tbl,
+ const struct tbl_dat *dp, struct termp_tbl *tblp)
+{
+ int sz;
+
+ /* Branch down into data sub-types. */
+
+ switch (dp->layout->pos) {
case (TBL_CELL_HORIZ):
/* FALLTHROUGH */
case (TBL_CELL_DHORIZ):
- write_data_spanner(p, data, width);
+ sz = term_len(tp, 1);
+ if (tblp->width < sz)
+ tblp->width = sz;
break;
case (TBL_CELL_LONG):
/* FALLTHROUGH */
@@ -476,12 +468,10 @@ write_data(struct termp *p, const struct tbl_data *data, int width)
case (TBL_CELL_LEFT):
/* FALLTHROUGH */
case (TBL_CELL_RIGHT):
- write_data_literal(p, data, width);
+ tbl_calc_data_literal(tp, dp, tblp);
break;
case (TBL_CELL_NUMBER):
- write_data_number(p, data, width);
- break;
- case (TBL_CELL_SPAN):
+ tbl_calc_data_number(tp, tbl, dp, tblp);
break;
default:
abort();
@@ -489,36 +479,87 @@ write_data(struct termp *p, const struct tbl_data *data, int width)
}
}
+static void
+tbl_calc_data_number(struct termp *tp, const struct tbl *tbl,
+ const struct tbl_dat *dp, struct termp_tbl *tblp)
+{
+ int sz, d, psz, i, ssz;
+ char *cp, buf[2];
+
+ /*
+ * First calculate number width and decimal place (last + 1 for
+ * no-decimal numbers). If the stored decimal is subsequent
+ * ours, make our size longer by that difference
+ * (right-"shifting"); similarly, if ours is subsequent the
+ * stored, then extend the stored size by the difference.
+ * Finally, re-assign the stored values.
+ */
+
+ /* TODO: use spacing modifier. */
+
+ assert(dp->string);
+ sz = term_strlen(tp, dp->string);
+ psz = term_strlen(tp, ".");
+
+ if (NULL != (cp = strchr(dp->string, tbl->decimal))) {
+ buf[1] = '\0';
+ for (ssz = i = 0; cp != &dp->string[i]; i++) {
+ buf[0] = dp->string[i];
+ ssz += term_strlen(tp, buf);
+ }
+ d = ssz + psz;
+ } else
+ d = sz + psz;
+
+ sz += term_len(tp, 2);
+
+ if (tblp->decimal > d) {
+ sz += tblp->decimal - d;
+ d = tblp->decimal;
+ } else
+ tblp->width += d - tblp->decimal;
+
+ if (sz > tblp->width)
+ tblp->width = sz;
+ if (d > tblp->decimal)
+ tblp->decimal = d;
+}
static void
-write_spanner(struct termp *p, const struct tbl_head *head)
+tbl_calc_data_literal(struct termp *tp,
+ const struct tbl_dat *dp,
+ struct termp_tbl *tblp)
{
- char *w;
+ int sz, bufsz, spsz;
- w = NULL;
- switch (head->pos) {
- case (TBL_HEAD_VERT):
- w = "|";
- break;
- case (TBL_HEAD_DVERT):
- w = "||";
+ /*
+ * Calculate our width and use the spacing, with a minimum
+ * spacing dictated by position (centre, e.g,. gets a space on
+ * either side, while right/left get a single adjacent space).
+ */
+
+ assert(dp->string);
+ sz = term_strlen(tp, dp->string);
+
+ switch (dp->layout->pos) {
+ case (TBL_CELL_LONG):
+ /* FALLTHROUGH */
+ case (TBL_CELL_CENTRE):
+ bufsz = term_len(tp, 2);
break;
default:
+ bufsz = term_len(tp, 1);
break;
}
- assert(p);
- term_word(p, w);
-}
-
+ spsz = 0;
+ if (dp->layout->spacing)
+ spsz = term_len(tp, dp->layout->spacing);
-static inline void
-write_char(struct termp *p, char c, int len)
-{
- int i;
- static char w[2];
+ if (spsz)
+ bufsz = bufsz > spsz ? bufsz : spsz;
- w[0] = c;
- for (i = 0; i < len; i++)
- term_word(p, w);
+ sz += bufsz;
+ if (tblp->width < sz)
+ tblp->width = sz;
}
diff --git a/usr.bin/mandoc/tbl_tree.c b/usr.bin/mandoc/tbl_tree.c
deleted file mode 100644
index e073c66aa2f..00000000000
--- a/usr.bin/mandoc/tbl_tree.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/* $Id: tbl_tree.c,v 1.2 2010/10/15 21:33:47 schwarze Exp $ */
-/*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <sys/queue.h>
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "out.h"
-#include "term.h"
-#include "tbl_extern.h"
-
-static const char * const htypes[TBL_HEAD_MAX] = {
- "data",
- "vert",
- "dvert",
-};
-
-static const char * const ctypes[TBL_CELL_MAX] = {
- "centre",
- "right",
- "left",
- "number",
- "span",
- "long",
- "down",
- "horiz",
- "dhoriz",
- "vert",
- "dvert",
-};
-
-
-/* ARGSUSED */
-int
-tbl_calc_tree(struct tbl *tbl)
-{
-
- return(1);
-}
-
-
-int
-tbl_write_tree(const struct tbl *tbl)
-{
- struct tbl_row *row;
- struct tbl_cell *cell;
- struct tbl_span *span;
- struct tbl_data *data;
- struct tbl_head *head;
-
- (void)printf("header\n");
- TAILQ_FOREACH(head, &tbl->head, entries)
- (void)printf("\t%s (=%p)\n", htypes[head->pos], head);
-
- (void)printf("layout\n");
- TAILQ_FOREACH(row, &tbl->row, entries) {
- (void)printf("\trow (=%p)\n", row);
- TAILQ_FOREACH(cell, &row->cell, entries)
- (void)printf("\t\t%s (=%p) >%p\n",
- ctypes[cell->pos],
- cell, cell->head);
- }
-
- (void)printf("data\n");
- TAILQ_FOREACH(span, &tbl->span, entries) {
- (void)printf("\tspan >%p\n", span->row);
- TAILQ_FOREACH(data, &span->data, entries)
- (void)printf("\t\tdata >%p\n", data->cell);
- }
-
- return(1);
-}
diff --git a/usr.bin/mandoc/term.c b/usr.bin/mandoc/term.c
index 8ecc5e5c774..e2d136a1cca 100644
--- a/usr.bin/mandoc/term.c
+++ b/usr.bin/mandoc/term.c
@@ -1,4 +1,4 @@
-/* $Id: term.c,v 1.54 2010/10/27 19:27:30 schwarze Exp $ */
+/* $Id: term.c,v 1.55 2011/01/04 22:28:17 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -673,6 +673,12 @@ term_strlen(const struct termp *p, const char *cp)
if (rhs)
for (i = 0; i < rsz; i++)
sz += (*p->width)(p, *rhs++);
+ } else if (ASCII_NBRSP == *cp) {
+ sz += (*p->width)(p, ' ');
+ cp++;
+ } else if (ASCII_HYPH == *cp) {
+ sz += (*p->width)(p, '-');
+ cp++;
} else
sz += (*p->width)(p, *cp++);
diff --git a/usr.bin/mandoc/term.h b/usr.bin/mandoc/term.h
index 102cb18fa22..dd22b426ec8 100644
--- a/usr.bin/mandoc/term.h
+++ b/usr.bin/mandoc/term.h
@@ -1,6 +1,6 @@
-/* $Id: term.h,v 1.27 2010/07/31 21:43:07 schwarze Exp $ */
+/* $Id: term.h,v 1.28 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 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
@@ -71,9 +71,15 @@ struct termp_ps {
size_t pdfobjsz; /* size of pdfobjs */
};
+struct termp_tbl {
+ int width; /* width in fixed chars */
+ int decimal; /* decimal point position */
+};
+
struct termp {
enum termtype type;
- size_t defrmargin; /* Right margin of the device.. */
+ struct termp_tbl *tbl; /* table configuration */
+ size_t defrmargin; /* Right margin of the device. */
size_t rmargin; /* Current right margin. */
size_t maxrmargin; /* Max right margin. */
size_t maxcols; /* Max size of buf. */
@@ -120,6 +126,7 @@ struct termp {
};
struct termp *term_alloc(enum termenc);
+void term_tbl(struct termp *, const struct tbl_span *);
void term_free(struct termp *);
void term_newln(struct termp *);
void term_vspace(struct termp *);
diff --git a/usr.bin/mandoc/term_ascii.c b/usr.bin/mandoc/term_ascii.c
index 21b1abbe226..a31e1327a96 100644
--- a/usr.bin/mandoc/term_ascii.c
+++ b/usr.bin/mandoc/term_ascii.c
@@ -1,4 +1,4 @@
-/* $Id: term_ascii.c,v 1.3 2010/07/13 01:09:13 schwarze Exp $ */
+/* $Id: term_ascii.c,v 1.4 2011/01/04 22:28:17 schwarze Exp $ */
/*
* Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -14,10 +14,6 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include <sys/types.h>
#include <assert.h>
@@ -26,6 +22,7 @@
#include <stdlib.h>
#include <unistd.h>
+#include "mandoc.h"
#include "out.h"
#include "term.h"
#include "main.h"
diff --git a/usr.bin/mandoc/tree.c b/usr.bin/mandoc/tree.c
index b775ca1edc7..959b0a5b744 100644
--- a/usr.bin/mandoc/tree.c
+++ b/usr.bin/mandoc/tree.c
@@ -1,6 +1,6 @@
-/* $Id: tree.c,v 1.10 2010/07/13 01:09:13 schwarze Exp $ */
+/* $Id: tree.c,v 1.11 2011/01/04 22:28:17 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 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
@@ -26,6 +26,7 @@
static void print_mdoc(const struct mdoc_node *, int);
static void print_man(const struct man_node *, int);
+static void print_span(const struct tbl_span *, int);
/* ARGSUSED */
@@ -84,11 +85,16 @@ print_mdoc(const struct mdoc_node *n, int indent)
case (MDOC_TEXT):
t = "text";
break;
+ case (MDOC_TBL):
+ t = "tbl";
+ break;
default:
abort();
/* NOTREACHED */
}
+ p = NULL;
+
switch (n->type) {
case (MDOC_TEXT):
p = n->string;
@@ -116,6 +122,8 @@ print_mdoc(const struct mdoc_node *n, int indent)
argc = n->args->argc;
}
break;
+ case (MDOC_TBL):
+ break;
case (MDOC_ROOT):
p = "root";
break;
@@ -124,24 +132,32 @@ print_mdoc(const struct mdoc_node *n, int indent)
/* NOTREACHED */
}
- for (i = 0; i < indent; i++)
- (void)printf(" ");
- (void)printf("%s (%s)", p, t);
-
- for (i = 0; i < (int)argc; i++) {
- (void)printf(" -%s", mdoc_argnames[argv[i].arg]);
- if (argv[i].sz > 0)
- (void)printf(" [");
- for (j = 0; j < (int)argv[i].sz; j++)
- (void)printf(" [%s]", argv[i].value[j]);
- if (argv[i].sz > 0)
- (void)printf(" ]");
- }
+ if (n->span) {
+ assert(NULL == p);
+ print_span(n->span, indent);
+ } else {
+ for (i = 0; i < indent; i++)
+ putchar('\t');
+
+ printf("%s (%s)", p, t);
- for (i = 0; i < (int)sz; i++)
- (void)printf(" [%s]", params[i]);
+ for (i = 0; i < (int)argc; i++) {
+ printf(" -%s", mdoc_argnames[argv[i].arg]);
+ if (argv[i].sz > 0)
+ printf(" [");
+ for (j = 0; j < (int)argv[i].sz; j++)
+ printf(" [%s]", argv[i].value[j]);
+ if (argv[i].sz > 0)
+ printf(" ]");
+ }
+
+ for (i = 0; i < (int)sz; i++)
+ printf(" [%s]", params[i]);
- (void)printf(" %d:%d\n", n->line, n->pos);
+ printf(" %d:%d", n->line, n->pos);
+ }
+
+ putchar('\n');
if (n->child)
print_mdoc(n->child, indent + 1);
@@ -175,11 +191,16 @@ print_man(const struct man_node *n, int indent)
case (MAN_BODY):
t = "block-body";
break;
+ case (MAN_TBL):
+ t = "tbl";
+ break;
default:
abort();
/* NOTREACHED */
}
+ p = NULL;
+
switch (n->type) {
case (MAN_TEXT):
p = n->string;
@@ -196,17 +217,69 @@ print_man(const struct man_node *n, int indent)
case (MAN_ROOT):
p = "root";
break;
+ case (MAN_TBL):
+ break;
default:
abort();
/* NOTREACHED */
}
- for (i = 0; i < indent; i++)
- (void)printf(" ");
- (void)printf("%s (%s) %d:%d\n", p, t, n->line, n->pos);
+ if (n->span) {
+ assert(NULL == p);
+ print_span(n->span, indent);
+ } else {
+ for (i = 0; i < indent; i++)
+ putchar('\t');
+ printf("%s (%s) %d:%d", p, t, n->line, n->pos);
+ }
+
+ putchar('\n');
if (n->child)
print_man(n->child, indent + 1);
if (n->next)
print_man(n->next, indent);
}
+
+static void
+print_span(const struct tbl_span *sp, int indent)
+{
+ const struct tbl_dat *dp;
+ int i;
+
+ for (i = 0; i < indent; i++)
+ putchar('\t');
+
+ printf("tbl: ");
+
+ switch (sp->pos) {
+ case (TBL_SPAN_HORIZ):
+ putchar('-');
+ return;
+ case (TBL_SPAN_DHORIZ):
+ putchar('=');
+ return;
+ default:
+ break;
+ }
+
+ for (dp = sp->first; dp; dp = dp->next) {
+ switch (dp->pos) {
+ case (TBL_DATA_HORIZ):
+ /* FALLTHROUGH */
+ case (TBL_DATA_NHORIZ):
+ putchar('-');
+ continue;
+ case (TBL_DATA_DHORIZ):
+ /* FALLTHROUGH */
+ case (TBL_DATA_NDHORIZ):
+ putchar('=');
+ continue;
+ default:
+ break;
+ }
+ printf("[%s%s]", dp->string, dp->layout ? "" : "*");
+ if (dp->next)
+ putchar(' ');
+ }
+}