summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile8
-rw-r--r--libroff.h31
-rw-r--r--roff.c122
-rw-r--r--roff.h1
-rw-r--r--tbl.c94
5 files changed, 195 insertions, 61 deletions
diff --git a/Makefile b/Makefile
index 862a541e..129930bc 100644
--- a/Makefile
+++ b/Makefile
@@ -31,11 +31,11 @@ CFLAGS += -g $(WFLAGS) $(VFLAGS) -DHAVE_CONFIG_H
LINTFLAGS += $(VFLAGS)
-ROFFLNS = roff.ln
+ROFFLNS = roff.ln tbl.ln
-ROFFSRCS = roff.c
+ROFFSRCS = roff.c tbl.c
-ROFFOBJS = roff.o
+ROFFOBJS = roff.o tbl.o
MANDOCLNS = mandoc.ln
@@ -94,7 +94,7 @@ DATAS = arch.in att.in lib.in msec.in st.in \
HEADS = mdoc.h libmdoc.h man.h libman.h term.h \
libmandoc.h html.h chars.h out.h main.h roff.h \
- mandoc.h
+ mandoc.h libroff.h
GSGMLS = mandoc.1.sgml mdoc.3.sgml mdoc.7.sgml \
mandoc_char.7.sgml man.7.sgml man.3.sgml roff.7.sgml \
diff --git a/libroff.h b/libroff.h
new file mode 100644
index 00000000..b9a153d2
--- /dev/null
+++ b/libroff.h
@@ -0,0 +1,31 @@
+/* $Id$ */
+/*
+ * 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.
+ */
+#ifndef LIBROFF_H
+#define LIBROFF_H
+
+__BEGIN_DECLS
+
+struct tbl;
+
+struct tbl *tbl_alloc(void);
+void tbl_free(struct tbl *);
+void tbl_reset(struct tbl *);
+enum rofferr tbl_read(struct tbl *, int, const char *, int);
+
+__END_DECLS
+
+#endif /*LIBROFF_H*/
diff --git a/roff.c b/roff.c
index dfa5ea30..d61e34fa 100644
--- a/roff.c
+++ b/roff.c
@@ -29,6 +29,7 @@
#include "mandoc.h"
#include "roff.h"
+#include "libroff.h"
#include "libmandoc.h"
#define RSTACK_MAX 128
@@ -36,14 +37,6 @@
#define ROFF_CTL(c) \
('.' == (c) || '\'' == (c))
-#if 1
-#define ROFF_DEBUG(fmt, args...) \
- do { /* Nothing. */ } while (/*CONSTCOND*/ 0)
-#else
-#define ROFF_DEBUG(fmt, args...) \
- do { fprintf(stderr, fmt , ##args); } while (/*CONSTCOND*/ 0)
-#endif
-
enum rofft {
ROFF_ad,
ROFF_am,
@@ -64,6 +57,8 @@ enum rofft {
ROFF_rm,
ROFF_so,
ROFF_tr,
+ ROFF_TS,
+ ROFF_TE,
ROFF_cblock,
ROFF_ccond, /* FIXME: remove this. */
ROFF_USERDEF,
@@ -75,7 +70,6 @@ enum roffrule {
ROFFRULE_DENY
};
-
struct roffstr {
char *name; /* key of symbol */
char *string; /* current value */
@@ -91,6 +85,7 @@ 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 *tbl;
};
struct roffnode {
@@ -146,6 +141,8 @@ 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_userdef(ROFF_ARGS);
/* See roff_hash_find() */
@@ -176,6 +173,8 @@ 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 },
{ ".", roff_cblock, NULL, NULL, 0, NULL },
{ "\\}", roff_ccond, NULL, NULL, 0, NULL },
{ NULL, roff_userdef, NULL, NULL, 0, NULL },
@@ -264,7 +263,6 @@ roffnode_pop(struct roff *r)
if (r->rstackpos > -1)
r->rstackpos--;
- ROFF_DEBUG("roff: popping scope\n");
r->last = r->last->parent;
free(p->name);
free(p->end);
@@ -299,8 +297,14 @@ static void
roff_free1(struct roff *r)
{
+ if (r->tbl) {
+ tbl_free(r->tbl);
+ r->tbl = NULL;
+ }
+
while (r->last)
roffnode_pop(r);
+
roff_freestr(r);
}
@@ -417,8 +421,6 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int pos)
/* Replace the escape sequence by the string. */
- ROFF_DEBUG("roff: splicing reserved: [%.*s]\n", i, st);
-
nsz = *szp + strlen(res) + 1;
n = mandoc_malloc(nsz);
@@ -442,6 +444,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;
/*
@@ -461,13 +464,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);
- ROFF_DEBUG("roff: intercept scoped text: %s, [%s]\n",
- roffs[t].name, &(*bufp)[pos]);
- 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,
@@ -477,8 +484,6 @@ roff_parseln(struct roff *r, int ln, char **bufp,
if (r->last) {
t = r->last->tok;
assert(roffs[t].sub);
- ROFF_DEBUG("roff: intercept scoped context: %s, [%s]\n",
- roffs[t].name, &(*bufp)[pos]);
return((*roffs[t].sub)
(r, t, bufp, szp,
ln, pos, pos, offs));
@@ -494,10 +499,6 @@ roff_parseln(struct roff *r, int ln, char **bufp,
if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos)))
return(ROFF_CONT);
- ROFF_DEBUG("roff: intercept new-scope: [%s], [%s]\n",
- ROFF_USERDEF == t ? r->current_string : roffs[t].name,
- &(*bufp)[pos]);
-
assert(roffs[t].proc);
return((*roffs[t].proc)
(r, t, bufp, szp,
@@ -509,10 +510,10 @@ int
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->tbl)
+ (*r->msg)(MANDOCERR_SCOPEEXIT, r->data,
+ r->last->line, r->last->col, NULL);
+ return(1);
}
@@ -581,8 +582,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);
}
@@ -601,14 +601,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);
@@ -635,8 +633,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);
}
@@ -648,20 +645,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);
@@ -986,9 +980,6 @@ roff_cond(ROFF_ARGS)
r->last->rule = rule;
- ROFF_DEBUG("roff: cond: %s -> %s\n", roffs[tok].name,
- ROFFRULE_ALLOW == rule ? "allow" : "deny");
-
if (ROFF_ie == tok) {
/*
* An if-else will put the NEGATION of the current
@@ -1003,11 +994,8 @@ roff_cond(ROFF_ARGS)
/* If the parent has false as its rule, then so do we. */
- if (r->last->parent && ROFFRULE_DENY == r->last->parent->rule) {
+ if (r->last->parent && ROFFRULE_DENY == r->last->parent->rule)
r->last->rule = ROFFRULE_DENY;
- ROFF_DEBUG("roff: cond override: %s -> deny\n",
- roffs[tok].name);
- }
/*
* Determine scope. If we're invoked with "\{" trailing the
@@ -1020,11 +1008,7 @@ roff_cond(ROFF_ARGS)
if ('\\' == (*bufp)[pos] && '{' == (*bufp)[pos + 1]) {
r->last->endspan = -1;
pos += 2;
- ROFF_DEBUG("roff: cond-scope: %s, multi-line\n",
- roffs[tok].name);
- } else
- ROFF_DEBUG("roff: cond-scope: %s, one-line\n",
- roffs[tok].name);
+ }
/*
* If there are no arguments on the line, the next-line scope is
@@ -1117,11 +1101,35 @@ roff_nr(ROFF_ARGS)
rg[(int)REG_nS].set = 1;
if ( ! roff_parse_nat(val, &rg[(int)REG_nS].v.u))
rg[(int)REG_nS].v.u = 0;
+ }
+
+ return(ROFF_IGN);
+}
+
+/* ARGSUSED */
+static enum rofferr
+roff_TE(ROFF_ARGS)
+{
+
+ if (NULL == r->tbl)
+ (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
+ else
+ tbl_free(r->tbl);
+
+ r->tbl = NULL;
+ return(ROFF_IGN);
+}
+
+/* ARGSUSED */
+static enum rofferr
+roff_TS(ROFF_ARGS)
+{
- ROFF_DEBUG("roff: register nS: %u\n",
- rg[(int)REG_nS].v.u);
+ if (r->tbl) {
+ (*r->msg)(MANDOCERR_SCOPEBROKEN, r->data, ln, ppos, NULL);
+ tbl_reset(r->tbl);
} else
- ROFF_DEBUG("roff: ignoring register: %s\n", key);
+ r->tbl = tbl_alloc();
return(ROFF_IGN);
}
diff --git a/roff.h b/roff.h
index bad27799..4c57e8e0 100644
--- a/roff.h
+++ b/roff.h
@@ -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 */
};
diff --git a/tbl.c b/tbl.c
new file mode 100644
index 00000000..b14308a5
--- /dev/null
+++ b/tbl.c
@@ -0,0 +1,94 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2009, 2010 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 <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "mandoc.h"
+#include "roff.h"
+#include "libmandoc.h"
+#include "libroff.h"
+
+enum tbl_part {
+ TBL_PART_OPTS, /* in options (first line) */
+ TBL_PART_LAYOUT, /* describing layout */
+ TBL_PART_DATA /* creating data rows */
+};
+
+
+struct tbl {
+ enum tbl_part part;
+};
+
+static void tbl_init(struct tbl *);
+static void tbl_clear(struct tbl *);
+
+static void
+tbl_clear(struct tbl *tbl)
+{
+
+}
+
+static void
+tbl_init(struct tbl *tbl)
+{
+
+ tbl->part = TBL_PART_OPTS;
+}
+
+enum rofferr
+tbl_read(struct tbl *tbl, int ln, const char *p, int offs)
+{
+ int len;
+ const char *cp;
+
+ cp = &p[offs];
+ len = (int)strlen(cp);
+
+ if (len && TBL_PART_OPTS == tbl->part)
+ if (';' != cp[len - 1])
+ tbl->part = TBL_PART_LAYOUT;
+
+ return(1);
+}
+
+struct tbl *
+tbl_alloc(void)
+{
+ struct tbl *p;
+
+ p = mandoc_malloc(sizeof(struct tbl));
+ tbl_init(p);
+ 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);
+}