-/* $Id: roff.c,v 1.122 2011/01/16 04:00:34 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>
ROFF_ie,
ROFF_if,
ROFF_ig,
+ ROFF_it,
ROFF_ne,
ROFF_nh,
ROFF_nr,
+ ROFF_ns,
+ ROFF_ps,
ROFF_rm,
ROFF_so,
+ ROFF_ta,
ROFF_tr,
ROFF_TS,
ROFF_TE,
ROFF_T_,
+ ROFF_EQ,
+ ROFF_EN,
ROFF_cblock,
ROFF_ccond, /* FIXME: remove this. */
ROFF_USERDEF,
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 {
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);
{ "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
{ "if", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
{ "ig", roff_block, roff_block_text, roff_block_sub, 0, NULL },
+ { "it", roff_line_ignore, NULL, NULL, 0, NULL },
{ "ne", roff_line_ignore, NULL, NULL, 0, NULL },
{ "nh", roff_line_ignore, NULL, NULL, 0, NULL },
{ "nr", roff_nr, NULL, NULL, 0, NULL },
+ { "ns", roff_line_ignore, NULL, NULL, 0, NULL },
+ { "ps", roff_line_ignore, NULL, NULL, 0, NULL },
{ "rm", roff_rm, NULL, NULL, 0, NULL },
{ "so", roff_so, NULL, NULL, 0, NULL },
+ { "ta", roff_line_ignore, NULL, NULL, 0, NULL },
{ "tr", roff_line_ignore, NULL, NULL, 0, NULL },
{ "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 },
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);
* 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])) {
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) {
(*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);
roff_line_ignore(ROFF_ARGS)
{
+ if (ROFF_it == tok)
+ (*r->msg)(MANDOCERR_REQUEST, r->data, ln, ppos, "it");
+
return(ROFF_IGN);
}
return(ROFF_IGN);
}
+/* 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)
ROFF_REPARSE : ROFF_APPEND);
}
-
static char *
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';
*c = '\0';
}
-
static const char *
roff_getstrn(const struct roff *r, const char *name, size_t len)
{
return(n ? n->string : NULL);
}
-
static void
roff_freestr(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);
+}