aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2011-02-06 20:36:36 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2011-02-06 20:36:36 +0000
commit91ab27befd54e154790aa66b308e8be09659b580 (patch)
tree24cae421e50218e0c183605b729798a0146b75f0
parent1a6d2f41dc5d79b1f83a510dbb34a2ac3357a651 (diff)
downloadmandoc-91ab27befd54e154790aa66b308e8be09659b580.tar.gz
mandoc-91ab27befd54e154790aa66b308e8be09659b580.tar.zst
mandoc-91ab27befd54e154790aa66b308e8be09659b580.zip
Add initial EQN support to mandoc. This parses, then throws away, data
between EQ and EN roff blocks. EQN is different from TBL in that data after .EQ is unilaterally considered an equation until an .EN. Thus, there's no need to jump through hoops in having table spans and so on. This is ONLY the parse code framework in libroff. EQN is not yet passed into the backends.
-rw-r--r--Makefile6
-rw-r--r--eqn.c81
-rw-r--r--libroff.h13
-rw-r--r--main.c4
-rw-r--r--mandoc.h7
-rw-r--r--roff.c83
-rw-r--r--roff.h3
7 files changed, 180 insertions, 17 deletions
diff --git a/Makefile b/Makefile
index a50054b6..9a5cd801 100644
--- a/Makefile
+++ b/Makefile
@@ -31,11 +31,11 @@ CFLAGS += -g $(WFLAGS) $(VFLAGS) -DHAVE_CONFIG_H
LINTFLAGS += $(VFLAGS)
-ROFFLNS = roff.ln tbl.ln tbl_opts.ln tbl_layout.ln tbl_data.ln
+ROFFLNS = roff.ln tbl.ln tbl_opts.ln tbl_layout.ln tbl_data.ln eqn.ln
-ROFFSRCS = roff.c tbl.c tbl_opts.c tbl_layout.c tbl_data.c
+ROFFSRCS = roff.c tbl.c tbl_opts.c tbl_layout.c tbl_data.c eqn.c
-ROFFOBJS = roff.o tbl.o tbl_opts.o tbl_layout.o tbl_data.o
+ROFFOBJS = roff.o tbl.o tbl_opts.o tbl_layout.o tbl_data.o eqn.o
MANDOCLNS = mandoc.ln
diff --git a/eqn.c b/eqn.c
new file mode 100644
index 00000000..64511a8b
--- /dev/null
+++ b/eqn.c
@@ -0,0 +1,81 @@
+/* $Id: eqn.c,v 1.1 2011/02/06 20:36:36 kristaps Exp $ */
+/*
+ * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * 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 <time.h>
+
+#include "mandoc.h"
+#include "roff.h"
+#include "libmandoc.h"
+#include "libroff.h"
+
+/* ARGSUSED */
+enum rofferr
+eqn_read(struct eqn_node **epp, int ln, const char *p, int offs)
+{
+ size_t sz;
+ struct eqn_node *ep;
+
+ if (0 == strcmp(p, ".EN")) {
+ *epp = NULL;
+ return(ROFF_EQN);
+ }
+
+ ep = *epp;
+
+ sz = strlen(&p[offs]);
+ ep->eqn.data = mandoc_realloc(ep->eqn.data, ep->eqn.sz + sz + 1);
+ if (0 == ep->eqn.sz)
+ *ep->eqn.data = '\0';
+
+ ep->eqn.sz += sz;
+ strlcat(ep->eqn.data, &p[offs], ep->eqn.sz + 1);
+ return(ROFF_IGN);
+}
+
+struct eqn_node *
+eqn_alloc(int pos, int line)
+{
+ struct eqn_node *p;
+
+ p = mandoc_calloc(1, sizeof(struct eqn_node));
+ p->line = line;
+ p->pos = pos;
+
+ return(p);
+}
+
+void
+eqn_end(struct eqn_node *e)
+{
+
+ /* Nothing to do. */
+}
+
+void
+eqn_free(struct eqn_node *p)
+{
+
+ free(p->eqn.data);
+ free(p);
+}
diff --git a/libroff.h b/libroff.h
index 500479e0..b03873a2 100644
--- a/libroff.h
+++ b/libroff.h
@@ -1,4 +1,4 @@
-/* $Id: libroff.h,v 1.17 2011/01/25 12:24:27 schwarze Exp $ */
+/* $Id: libroff.h,v 1.18 2011/02/06 20:36:36 kristaps Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -43,6 +43,13 @@ struct tbl_node {
struct tbl_node *next;
};
+struct eqn_node {
+ int pos; /* invocation column */
+ int line; /* invocation line */
+ struct eqn eqn;
+ struct eqn_node *next;
+};
+
#define TBL_MSG(tblp, type, line, col) \
(*(tblp)->msg)((type), (tblp)->data, (line), (col), NULL)
@@ -57,6 +64,10 @@ int tbl_data(struct tbl_node *, int, const char *);
int tbl_cdata(struct tbl_node *, int, const char *);
const struct tbl_span *tbl_span(struct tbl_node *);
void tbl_end(struct tbl_node *);
+struct eqn_node *eqn_alloc(int, int);
+void eqn_end(struct eqn_node *);
+void eqn_free(struct eqn_node *);
+enum rofferr eqn_read(struct eqn_node **, int, const char *, int);
__END_DECLS
diff --git a/main.c b/main.c
index 5896d5ff..2daea890 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.142 2011/02/02 21:40:45 kristaps Exp $ */
+/* $Id: main.c,v 1.143 2011/02/06 20:36:36 kristaps Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -863,6 +863,8 @@ rerun:
else
mdoc_addspan(curp->mdoc, span);
}
+ } else if (ROFF_EQN == rr) {
+ assert(curp->man || curp->mdoc);
} else if (curp->man || curp->mdoc) {
rc = curp->man ?
man_parseln(curp->man,
diff --git a/mandoc.h b/mandoc.h
index acef6815..746b20d6 100644
--- a/mandoc.h
+++ b/mandoc.h
@@ -1,4 +1,4 @@
-/* $Id: mandoc.h,v 1.54 2011/02/02 21:40:45 kristaps Exp $ */
+/* $Id: mandoc.h,v 1.55 2011/02/06 20:36:36 kristaps Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -267,6 +267,11 @@ struct tbl_span {
struct tbl_span *next;
};
+struct eqn {
+ size_t sz;
+ char *data;
+};
+
/*
* Available registers (set in libroff, accessed elsewhere).
*/
diff --git a/roff.c b/roff.c
index 5d3f1062..7d76fb56 100644
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.124 2011/01/25 01:12:02 schwarze Exp $ */
+/* $Id: roff.c,v 1.125 2011/02/06 20:36:36 kristaps Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -64,6 +64,8 @@ enum rofft {
ROFF_TS,
ROFF_TE,
ROFF_T_,
+ ROFF_EQ,
+ ROFF_EN,
ROFF_cblock,
ROFF_ccond, /* FIXME: remove this. */
ROFF_USERDEF,
@@ -93,6 +95,9 @@ struct roff {
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 eqn_node *last_eqn; /* last equation parsed */
+ struct eqn_node *first_eqn; /* first equation parsed */
+ struct eqn_node *eqn; /* current equation being parsed */
};
struct roffnode {
@@ -151,6 +156,8 @@ static void roff_setstr(struct roff *,
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_EQ(ROFF_ARGS);
+static enum rofferr roff_EN(ROFF_ARGS);
static enum rofferr roff_T_(ROFF_ARGS);
static enum rofferr roff_userdef(ROFF_ARGS);
@@ -189,6 +196,8 @@ static struct roffmac roffs[ROFF_MAX] = {
{ "TS", roff_TS, NULL, NULL, 0, NULL },
{ "TE", roff_TE, NULL, NULL, 0, NULL },
{ "T&", roff_T_, NULL, NULL, 0, NULL },
+ { "EQ", roff_EQ, NULL, NULL, 0, NULL },
+ { "EN", roff_EN, NULL, NULL, 0, NULL },
{ ".", roff_cblock, NULL, NULL, 0, NULL },
{ "\\}", roff_ccond, NULL, NULL, 0, NULL },
{ NULL, roff_userdef, NULL, NULL, 0, NULL },
@@ -311,15 +320,22 @@ static void
roff_free1(struct roff *r)
{
struct tbl_node *t;
+ struct eqn_node *e;
- while (r->first_tbl) {
- t = r->first_tbl;
+ while (NULL != (t = r->first_tbl)) {
r->first_tbl = t->next;
tbl_free(t);
}
r->first_tbl = r->last_tbl = r->tbl = NULL;
+ while (NULL != (e = r->first_eqn)) {
+ r->first_eqn = e->next;
+ eqn_free(e);
+ }
+
+ r->first_eqn = r->last_eqn = r->eqn = NULL;
+
while (r->last)
roffnode_pop(r);
@@ -477,6 +493,8 @@ roff_parseln(struct roff *r, int ln, char **bufp,
* First, if a scope is open and we're not a macro, pass the
* text through the macro's filter. If a scope isn't open and
* we're not a macro, just let it through.
+ * Finally, if there's an equation scope open, divert it into it
+ * no matter our state.
*/
if (r->last && ! ROFF_CTL((*bufp)[pos])) {
@@ -485,18 +503,26 @@ roff_parseln(struct roff *r, int ln, char **bufp,
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)
+ if (ROFF_CONT != e)
+ return(e);
+ if (r->eqn)
+ return(eqn_read(&r->eqn, ln, *bufp, *offs));
+ if (r->tbl)
return(tbl_read(r->tbl, ln, *bufp, *offs));
- return(e);
+ return(ROFF_CONT);
} else if ( ! ROFF_CTL((*bufp)[pos])) {
+ if (r->eqn)
+ return(eqn_read(&r->eqn, ln, *bufp, *offs));
if (r->tbl)
return(tbl_read(r->tbl, ln, *bufp, *offs));
return(ROFF_CONT);
- }
+ } else if (r->eqn)
+ return(eqn_read(&r->eqn, ln, *bufp, *offs));
/*
* If a scope is open, go to the child handler for that macro,
* as it may want to preprocess before doing anything with it.
+ * Don't do so if an equation is open.
*/
if (r->last) {
@@ -532,6 +558,13 @@ roff_endparse(struct roff *r)
(*r->msg)(MANDOCERR_SCOPEEXIT, r->data,
r->last->line, r->last->col, NULL);
+ if (r->eqn) {
+ (*r->msg)(MANDOCERR_SCOPEEXIT, r->data,
+ r->eqn->line, r->eqn->pos, NULL);
+ eqn_end(r->eqn);
+ r->eqn = NULL;
+ }
+
if (r->tbl) {
(*r->msg)(MANDOCERR_SCOPEEXIT, r->data,
r->tbl->line, r->tbl->pos, NULL);
@@ -1140,6 +1173,33 @@ roff_T_(ROFF_ARGS)
/* ARGSUSED */
static enum rofferr
+roff_EQ(ROFF_ARGS)
+{
+ struct eqn_node *e;
+
+ assert(NULL == r->eqn);
+ e = eqn_alloc(ppos, ln);
+
+ if (r->last_eqn)
+ r->last_eqn->next = e;
+ else
+ r->first_eqn = r->last_eqn = e;
+
+ r->eqn = r->last_eqn = e;
+ return(ROFF_IGN);
+}
+
+/* ARGSUSED */
+static enum rofferr
+roff_EN(ROFF_ARGS)
+{
+
+ (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
+ return(ROFF_IGN);
+}
+
+/* ARGSUSED */
+static enum rofferr
roff_TS(ROFF_ARGS)
{
struct tbl_node *t;
@@ -1240,7 +1300,6 @@ roff_userdef(ROFF_ARGS)
ROFF_REPARSE : ROFF_APPEND);
}
-
static char *
roff_getname(struct roff *r, char **cpp, int ln, int pos)
{
@@ -1274,7 +1333,6 @@ roff_getname(struct roff *r, char **cpp, int ln, int pos)
return(name);
}
-
/*
* Store *string into the user-defined string called *name.
* In multiline mode, append to an existing entry and append '\n';
@@ -1344,7 +1402,6 @@ roff_setstr(struct roff *r, const char *name, const char *string,
*c = '\0';
}
-
static const char *
roff_getstrn(const struct roff *r, const char *name, size_t len)
{
@@ -1357,7 +1414,6 @@ roff_getstrn(const struct roff *r, const char *name, size_t len)
return(n ? n->string : NULL);
}
-
static void
roff_freestr(struct roff *r)
{
@@ -1379,3 +1435,10 @@ roff_span(const struct roff *r)
return(r->tbl ? tbl_span(r->tbl) : NULL);
}
+
+const struct eqn *
+roff_eqn(const struct roff *r)
+{
+
+ return(r->last_eqn ? &r->last_eqn->eqn : NULL);
+}
diff --git a/roff.h b/roff.h
index 141a469a..baa1361f 100644
--- a/roff.h
+++ b/roff.h
@@ -1,4 +1,4 @@
-/* $Id: roff.h,v 1.22 2011/01/01 16:18:39 kristaps Exp $ */
+/* $Id: roff.h,v 1.23 2011/02/06 20:36:36 kristaps Exp $ */
/*
* Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -25,6 +25,7 @@ enum rofferr {
ROFF_SO, /* include another file */
ROFF_IGN, /* ignore current line */
ROFF_TBL, /* a table row was successfully parsed */
+ ROFF_EQN, /* an equation was successfully parsed */
ROFF_ERR /* badness: puke and stop */
};