summaryrefslogtreecommitdiffstats
path: root/roff.c
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
commit858bb68c9059fe5b8f8f613dab2761233ff36ba7 (patch)
tree570b9749d9aa62c9ea90cef7bcc920ac1ed44829 /roff.c
parent07e8fdac90d41ba0de90ac17f5081f6feb4b4b99 (diff)
downloadmandoc-858bb68c9059fe5b8f8f613dab2761233ff36ba7.tar.gz
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.
Diffstat (limited to 'roff.c')
-rw-r--r--roff.c81
1 files changed, 72 insertions, 9 deletions
diff --git a/roff.c b/roff.c
index b885a5f2..91e4dcbd 100644
--- a/roff.c
+++ b/roff.c
@@ -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);
+}