version 1.122, 2011/01/16 04:00:34 |
version 1.137, 2011/04/24 23:51:17 |
|
|
#include <stdio.h> |
#include <stdio.h> |
|
|
#include "mandoc.h" |
#include "mandoc.h" |
#include "roff.h" |
|
#include "libroff.h" |
#include "libroff.h" |
#include "libmandoc.h" |
#include "libmandoc.h" |
|
|
#define RSTACK_MAX 128 |
#define RSTACK_MAX 128 |
|
|
#define ROFF_CTL(c) \ |
|
('.' == (c) || '\'' == (c)) |
|
|
|
enum rofft { |
enum rofft { |
ROFF_ad, |
ROFF_ad, |
ROFF_am, |
ROFF_am, |
|
|
ROFF_ie, |
ROFF_ie, |
ROFF_if, |
ROFF_if, |
ROFF_ig, |
ROFF_ig, |
|
ROFF_it, |
ROFF_ne, |
ROFF_ne, |
ROFF_nh, |
ROFF_nh, |
ROFF_nr, |
ROFF_nr, |
|
ROFF_ns, |
|
ROFF_ps, |
ROFF_rm, |
ROFF_rm, |
ROFF_so, |
ROFF_so, |
|
ROFF_ta, |
ROFF_tr, |
ROFF_tr, |
ROFF_TS, |
ROFF_TS, |
ROFF_TE, |
ROFF_TE, |
ROFF_T_, |
ROFF_T_, |
|
ROFF_EQ, |
|
ROFF_EN, |
ROFF_cblock, |
ROFF_cblock, |
ROFF_ccond, /* FIXME: remove this. */ |
ROFF_ccond, /* FIXME: remove this. */ |
ROFF_USERDEF, |
ROFF_USERDEF, |
|
|
}; |
}; |
|
|
struct roff { |
struct roff { |
|
struct mparse *parse; /* parse point */ |
struct roffnode *last; /* leaf of stack */ |
struct roffnode *last; /* leaf of stack */ |
mandocmsg msg; /* err/warn/fatal messages */ |
|
void *data; /* privdata for messages */ |
|
enum roffrule rstack[RSTACK_MAX]; /* stack of !`ie' rules */ |
enum roffrule rstack[RSTACK_MAX]; /* stack of !`ie' rules */ |
int rstackpos; /* position in rstack */ |
int rstackpos; /* position in rstack */ |
struct regset *regs; /* read/writable registers */ |
struct regset *regs; /* read/writable registers */ |
|
|
struct tbl_node *first_tbl; /* first table parsed */ |
struct tbl_node *first_tbl; /* first table parsed */ |
struct tbl_node *last_tbl; /* last table parsed */ |
struct tbl_node *last_tbl; /* last table parsed */ |
struct tbl_node *tbl; /* current table being 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 { |
struct roffnode { |
Line 147 static void roff_setstr(struct roff *, |
|
Line 151 static void roff_setstr(struct roff *, |
|
static enum rofferr roff_so(ROFF_ARGS); |
static enum rofferr roff_so(ROFF_ARGS); |
static enum rofferr roff_TE(ROFF_ARGS); |
static enum rofferr roff_TE(ROFF_ARGS); |
static enum rofferr roff_TS(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_T_(ROFF_ARGS); |
static enum rofferr roff_userdef(ROFF_ARGS); |
static enum rofferr roff_userdef(ROFF_ARGS); |
|
|
Line 172 static struct roffmac roffs[ROFF_MAX] = { |
|
Line 178 static struct roffmac roffs[ROFF_MAX] = { |
|
{ "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL }, |
{ "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL }, |
{ "if", 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 }, |
{ "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 }, |
{ "ne", roff_line_ignore, NULL, NULL, 0, NULL }, |
{ "nh", roff_line_ignore, NULL, NULL, 0, NULL }, |
{ "nh", roff_line_ignore, NULL, NULL, 0, NULL }, |
{ "nr", roff_nr, 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 }, |
{ "rm", roff_rm, NULL, NULL, 0, NULL }, |
{ "so", roff_so, 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 }, |
{ "tr", roff_line_ignore, NULL, NULL, 0, NULL }, |
{ "TS", roff_TS, NULL, NULL, 0, NULL }, |
{ "TS", roff_TS, NULL, NULL, 0, NULL }, |
{ "TE", roff_TE, NULL, NULL, 0, NULL }, |
{ "TE", roff_TE, NULL, NULL, 0, NULL }, |
{ "T&", roff_T_, 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_cblock, NULL, NULL, 0, NULL }, |
{ "\\}", roff_ccond, NULL, NULL, 0, NULL }, |
{ "\\}", roff_ccond, NULL, NULL, 0, NULL }, |
{ NULL, roff_userdef, NULL, NULL, 0, NULL }, |
{ NULL, roff_userdef, NULL, NULL, 0, NULL }, |
Line 265 roffnode_pop(struct roff *r) |
|
Line 277 roffnode_pop(struct roff *r) |
|
assert(r->last); |
assert(r->last); |
p = r->last; |
p = r->last; |
|
|
if (ROFF_el == p->tok) |
|
if (r->rstackpos > -1) |
|
r->rstackpos--; |
|
|
|
r->last = r->last->parent; |
r->last = r->last->parent; |
free(p->name); |
free(p->name); |
free(p->end); |
free(p->end); |
|
|
roff_free1(struct roff *r) |
roff_free1(struct roff *r) |
{ |
{ |
struct tbl_node *t; |
struct tbl_node *t; |
|
struct eqn_node *e; |
|
|
while (r->first_tbl) { |
while (NULL != (t = r->first_tbl)) { |
t = r->first_tbl; |
|
r->first_tbl = t->next; |
r->first_tbl = t->next; |
tbl_free(t); |
tbl_free(t); |
} |
} |
|
|
r->first_tbl = r->last_tbl = r->tbl = NULL; |
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) |
while (r->last) |
roffnode_pop(r); |
roffnode_pop(r); |
|
|
Line 337 roff_free(struct roff *r) |
|
Line 352 roff_free(struct roff *r) |
|
|
|
|
|
struct roff * |
struct roff * |
roff_alloc(struct regset *regs, void *data, const mandocmsg msg) |
roff_alloc(struct regset *regs, struct mparse *parse) |
{ |
{ |
struct roff *r; |
struct roff *r; |
|
|
r = mandoc_calloc(1, sizeof(struct roff)); |
r = mandoc_calloc(1, sizeof(struct roff)); |
r->regs = regs; |
r->regs = regs; |
r->msg = msg; |
r->parse = parse; |
r->data = data; |
|
r->rstackpos = -1; |
r->rstackpos = -1; |
|
|
roff_hash_init(); |
roff_hash_init(); |
Line 455 roff_parseln(struct roff *r, int ln, char **bufp, |
|
Line 469 roff_parseln(struct roff *r, int ln, char **bufp, |
|
{ |
{ |
enum rofft t; |
enum rofft t; |
enum rofferr e; |
enum rofferr e; |
int ppos; |
int ppos, ctl; |
|
|
/* |
/* |
* Run the reserved-word filter only if we have some reserved |
* Run the reserved-word filter only if we have some reserved |
Line 465 roff_parseln(struct roff *r, int ln, char **bufp, |
|
Line 479 roff_parseln(struct roff *r, int ln, char **bufp, |
|
if (r->first_string && ! roff_res(r, bufp, szp, pos)) |
if (r->first_string && ! roff_res(r, bufp, szp, pos)) |
return(ROFF_REPARSE); |
return(ROFF_REPARSE); |
|
|
|
ppos = pos; |
|
ctl = mandoc_getcontrol(*bufp, &pos); |
|
|
/* |
/* |
* First, if a scope is open and we're not a macro, pass the |
* 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 |
* text through the macro's filter. If a scope isn't open and |
* we're not a macro, just let it through. |
* 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])) { |
if (r->last && ! ctl) { |
t = r->last->tok; |
t = r->last->tok; |
assert(roffs[t].text); |
assert(roffs[t].text); |
e = (*roffs[t].text) |
e = (*roffs[t].text) |
(r, t, bufp, szp, ln, pos, pos, offs); |
(r, t, bufp, szp, ln, pos, pos, offs); |
assert(ROFF_IGN == e || ROFF_CONT == e); |
assert(ROFF_IGN == e || ROFF_CONT == e); |
if (ROFF_CONT == e && r->tbl) |
if (ROFF_CONT != e) |
return(tbl_read(r->tbl, ln, *bufp, *offs)); |
return(e); |
return(e); |
if (r->eqn) |
} else if ( ! ROFF_CTL((*bufp)[pos])) { |
return(eqn_read(&r->eqn, ln, *bufp, pos)); |
if (r->tbl) |
if (r->tbl) |
return(tbl_read(r->tbl, ln, *bufp, *offs)); |
return(tbl_read(r->tbl, ln, *bufp, pos)); |
return(ROFF_CONT); |
return(ROFF_CONT); |
} |
} else if ( ! ctl) { |
|
if (r->eqn) |
|
return(eqn_read(&r->eqn, ln, *bufp, pos)); |
|
if (r->tbl) |
|
return(tbl_read(r->tbl, ln, *bufp, pos)); |
|
return(ROFF_CONT); |
|
} else if (r->eqn) |
|
return(eqn_read(&r->eqn, ln, *bufp, ppos)); |
|
|
/* |
/* |
* If a scope is open, go to the child handler for that macro, |
* If a scope is open, go to the child handler for that macro, |
* as it may want to preprocess before doing anything with it. |
* as it may want to preprocess before doing anything with it. |
|
* Don't do so if an equation is open. |
*/ |
*/ |
|
|
if (r->last) { |
if (r->last) { |
Line 496 roff_parseln(struct roff *r, int ln, char **bufp, |
|
Line 523 roff_parseln(struct roff *r, int ln, char **bufp, |
|
assert(roffs[t].sub); |
assert(roffs[t].sub); |
return((*roffs[t].sub) |
return((*roffs[t].sub) |
(r, t, bufp, szp, |
(r, t, bufp, szp, |
ln, pos, pos, offs)); |
ln, ppos, pos, offs)); |
} |
} |
|
|
/* |
/* |
Line 505 roff_parseln(struct roff *r, int ln, char **bufp, |
|
Line 532 roff_parseln(struct roff *r, int ln, char **bufp, |
|
* the compilers handle it. |
* the compilers handle it. |
*/ |
*/ |
|
|
ppos = pos; |
|
if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos))) |
if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos))) |
return(ROFF_CONT); |
return(ROFF_CONT); |
|
|
Line 521 roff_endparse(struct roff *r) |
|
Line 547 roff_endparse(struct roff *r) |
|
{ |
{ |
|
|
if (r->last) |
if (r->last) |
(*r->msg)(MANDOCERR_SCOPEEXIT, r->data, |
mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse, |
r->last->line, r->last->col, NULL); |
r->last->line, r->last->col, NULL); |
|
|
|
if (r->eqn) { |
|
mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse, |
|
r->eqn->eqn.line, r->eqn->eqn.pos, NULL); |
|
eqn_end(r->eqn); |
|
r->eqn = NULL; |
|
} |
|
|
if (r->tbl) { |
if (r->tbl) { |
(*r->msg)(MANDOCERR_SCOPEEXIT, r->data, |
mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse, |
r->tbl->line, r->tbl->pos, NULL); |
r->tbl->line, r->tbl->pos, NULL); |
tbl_end(r->tbl); |
tbl_end(r->tbl); |
r->tbl = NULL; |
r->tbl = NULL; |
} |
} |
} |
} |
|
|
|
|
/* |
/* |
* Parse a roff node's type from the input buffer. This must be in the |
* Parse a roff node's type from the input buffer. This must be in the |
* form of ".foo xxx" in the usual way. |
* form of ".foo xxx" in the usual way. |
Line 544 roff_parse(struct roff *r, const char *buf, int *pos) |
|
Line 576 roff_parse(struct roff *r, const char *buf, int *pos) |
|
size_t maclen; |
size_t maclen; |
enum rofft t; |
enum rofft t; |
|
|
assert(ROFF_CTL(buf[*pos])); |
if ('\0' == buf[*pos] || '"' == buf[*pos]) |
(*pos)++; |
|
|
|
while (' ' == buf[*pos] || '\t' == buf[*pos]) |
|
(*pos)++; |
|
|
|
if ('\0' == buf[*pos]) |
|
return(ROFF_MAX); |
return(ROFF_MAX); |
|
|
mac = buf + *pos; |
mac = buf + *pos; |
Line 559 roff_parse(struct roff *r, const char *buf, int *pos) |
|
Line 585 roff_parse(struct roff *r, const char *buf, int *pos) |
|
t = (r->current_string = roff_getstrn(r, mac, maclen)) |
t = (r->current_string = roff_getstrn(r, mac, maclen)) |
? ROFF_USERDEF : roff_hash_find(mac, maclen); |
? ROFF_USERDEF : roff_hash_find(mac, maclen); |
|
|
*pos += maclen; |
*pos += (int)maclen; |
|
|
while (buf[*pos] && ' ' == buf[*pos]) |
while (buf[*pos] && ' ' == buf[*pos]) |
(*pos)++; |
(*pos)++; |
|
|
Line 598 roff_cblock(ROFF_ARGS) |
|
Line 625 roff_cblock(ROFF_ARGS) |
|
*/ |
*/ |
|
|
if (NULL == r->last) { |
if (NULL == r->last) { |
(*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL); |
mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL); |
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
|
|
Line 617 roff_cblock(ROFF_ARGS) |
|
Line 644 roff_cblock(ROFF_ARGS) |
|
case (ROFF_ig): |
case (ROFF_ig): |
break; |
break; |
default: |
default: |
(*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL); |
mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL); |
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
|
|
if ((*bufp)[pos]) |
if ((*bufp)[pos]) |
(*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL); |
mandoc_msg(MANDOCERR_ARGSLOST, r->parse, ln, pos, NULL); |
|
|
roffnode_pop(r); |
roffnode_pop(r); |
roffnode_cleanscope(r); |
roffnode_cleanscope(r); |
Line 649 roff_ccond(ROFF_ARGS) |
|
Line 676 roff_ccond(ROFF_ARGS) |
|
{ |
{ |
|
|
if (NULL == r->last) { |
if (NULL == r->last) { |
(*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL); |
mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL); |
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
|
|
Line 661 roff_ccond(ROFF_ARGS) |
|
Line 688 roff_ccond(ROFF_ARGS) |
|
case (ROFF_if): |
case (ROFF_if): |
break; |
break; |
default: |
default: |
(*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL); |
mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL); |
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
|
|
if (r->last->endspan > -1) { |
if (r->last->endspan > -1) { |
(*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL); |
mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL); |
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
|
|
if ((*bufp)[pos]) |
if ((*bufp)[pos]) |
(*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL); |
mandoc_msg(MANDOCERR_ARGSLOST, r->parse, ln, pos, NULL); |
|
|
roffnode_pop(r); |
roffnode_pop(r); |
roffnode_cleanscope(r); |
roffnode_cleanscope(r); |
Line 691 roff_block(ROFF_ARGS) |
|
Line 718 roff_block(ROFF_ARGS) |
|
|
|
if (ROFF_ig != tok) { |
if (ROFF_ig != tok) { |
if ('\0' == (*bufp)[pos]) { |
if ('\0' == (*bufp)[pos]) { |
(*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL); |
mandoc_msg(MANDOCERR_NOARGS, r->parse, ln, ppos, NULL); |
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
|
|
Line 705 roff_block(ROFF_ARGS) |
|
Line 732 roff_block(ROFF_ARGS) |
|
if (ROFF_de == tok) |
if (ROFF_de == tok) |
name = *bufp + pos; |
name = *bufp + pos; |
else |
else |
(*r->msg)(MANDOCERR_REQUEST, r->data, ln, ppos, |
mandoc_msg(MANDOCERR_REQUEST, r->parse, ln, ppos, |
roffs[tok].name); |
roffs[tok].name); |
|
|
while ((*bufp)[pos] && ' ' != (*bufp)[pos]) |
while ((*bufp)[pos] && ! isspace((unsigned char)(*bufp)[pos])) |
pos++; |
pos++; |
|
|
while (' ' == (*bufp)[pos]) |
while (isspace((unsigned char)(*bufp)[pos])) |
(*bufp)[pos++] = '\0'; |
(*bufp)[pos++] = '\0'; |
} |
} |
|
|
Line 732 roff_block(ROFF_ARGS) |
|
Line 759 roff_block(ROFF_ARGS) |
|
/* If present, process the custom end-of-line marker. */ |
/* If present, process the custom end-of-line marker. */ |
|
|
sv = pos; |
sv = pos; |
while ((*bufp)[pos] && |
while ((*bufp)[pos] && ! isspace((unsigned char)(*bufp)[pos])) |
' ' != (*bufp)[pos] && |
|
'\t' != (*bufp)[pos]) |
|
pos++; |
pos++; |
|
|
/* |
/* |
Line 755 roff_block(ROFF_ARGS) |
|
Line 780 roff_block(ROFF_ARGS) |
|
r->last->end[(int)sz] = '\0'; |
r->last->end[(int)sz] = '\0'; |
|
|
if ((*bufp)[pos]) |
if ((*bufp)[pos]) |
(*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL); |
mandoc_msg(MANDOCERR_ARGSLOST, r->parse, ln, pos, NULL); |
|
|
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
Line 778 roff_block_sub(ROFF_ARGS) |
|
Line 803 roff_block_sub(ROFF_ARGS) |
|
*/ |
*/ |
|
|
if (r->last->end) { |
if (r->last->end) { |
i = pos + 1; |
for (i = pos, j = 0; r->last->end[j]; j++, i++) |
while (' ' == (*bufp)[i] || '\t' == (*bufp)[i]) |
|
i++; |
|
|
|
for (j = 0; r->last->end[j]; j++, i++) |
|
if ((*bufp)[i] != r->last->end[j]) |
if ((*bufp)[i] != r->last->end[j]) |
break; |
break; |
|
|
Line 793 roff_block_sub(ROFF_ARGS) |
|
Line 814 roff_block_sub(ROFF_ARGS) |
|
roffnode_pop(r); |
roffnode_pop(r); |
roffnode_cleanscope(r); |
roffnode_cleanscope(r); |
|
|
|
while (' ' == (*bufp)[i] || '\t' == (*bufp)[i]) |
|
i++; |
|
|
|
pos = i; |
if (ROFF_MAX != roff_parse(r, *bufp, &pos)) |
if (ROFF_MAX != roff_parse(r, *bufp, &pos)) |
return(ROFF_RERUN); |
return(ROFF_RERUN); |
return(ROFF_IGN); |
return(ROFF_IGN); |
Line 804 roff_block_sub(ROFF_ARGS) |
|
Line 829 roff_block_sub(ROFF_ARGS) |
|
* pulling it out of the hashtable. |
* pulling it out of the hashtable. |
*/ |
*/ |
|
|
ppos = pos; |
|
t = roff_parse(r, *bufp, &pos); |
t = roff_parse(r, *bufp, &pos); |
|
|
/* |
/* |
Line 842 roff_cond_sub(ROFF_ARGS) |
|
Line 866 roff_cond_sub(ROFF_ARGS) |
|
enum rofft t; |
enum rofft t; |
enum roffrule rr; |
enum roffrule rr; |
|
|
ppos = pos; |
|
rr = r->last->rule; |
rr = r->last->rule; |
|
|
/* |
/* |
Line 935 static enum rofferr |
|
Line 958 static enum rofferr |
|
roff_line_ignore(ROFF_ARGS) |
roff_line_ignore(ROFF_ARGS) |
{ |
{ |
|
|
|
if (ROFF_it == tok) |
|
mandoc_msg(MANDOCERR_REQUEST, r->parse, ln, ppos, "it"); |
|
|
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
|
|
Line 945 roff_cond(ROFF_ARGS) |
|
Line 971 roff_cond(ROFF_ARGS) |
|
int sv; |
int sv; |
enum roffrule rule; |
enum roffrule rule; |
|
|
/* Stack overflow! */ |
/* |
|
* An `.el' has no conditional body: it will consume the value |
|
* of the current rstack entry set in prior `ie' calls or |
|
* defaults to DENY. |
|
* |
|
* If we're not an `el', however, then evaluate the conditional. |
|
*/ |
|
|
if (ROFF_ie == tok && r->rstackpos == RSTACK_MAX - 1) { |
rule = ROFF_el == tok ? |
(*r->msg)(MANDOCERR_MEM, r->data, ln, ppos, NULL); |
(r->rstackpos < 0 ? |
return(ROFF_ERR); |
ROFFRULE_DENY : r->rstack[r->rstackpos--]) : |
} |
roff_evalcond(*bufp, &pos); |
|
|
/* First, evaluate the conditional. */ |
|
|
|
if (ROFF_el == tok) { |
|
/* |
|
* An `.el' will get the value of the current rstack |
|
* entry set in prior `ie' calls or defaults to DENY. |
|
*/ |
|
if (r->rstackpos < 0) |
|
rule = ROFFRULE_DENY; |
|
else |
|
rule = r->rstack[r->rstackpos]; |
|
} else |
|
rule = roff_evalcond(*bufp, &pos); |
|
|
|
sv = pos; |
sv = pos; |
|
|
while (' ' == (*bufp)[pos]) |
while (' ' == (*bufp)[pos]) |
pos++; |
pos++; |
|
|
Line 979 roff_cond(ROFF_ARGS) |
|
Line 996 roff_cond(ROFF_ARGS) |
|
*/ |
*/ |
|
|
if ('\0' == (*bufp)[pos] && sv != pos) { |
if ('\0' == (*bufp)[pos] && sv != pos) { |
(*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL); |
mandoc_msg(MANDOCERR_NOARGS, r->parse, ln, ppos, NULL); |
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
|
|
Line 987 roff_cond(ROFF_ARGS) |
|
Line 1004 roff_cond(ROFF_ARGS) |
|
|
|
r->last->rule = rule; |
r->last->rule = rule; |
|
|
|
/* |
|
* An if-else will put the NEGATION of the current evaluated |
|
* conditional into the stack of rules. |
|
*/ |
|
|
if (ROFF_ie == tok) { |
if (ROFF_ie == tok) { |
/* |
if (r->rstackpos == RSTACK_MAX - 1) { |
* An if-else will put the NEGATION of the current |
mandoc_msg(MANDOCERR_MEM, |
* evaluated conditional into the stack. |
r->parse, ln, ppos, NULL); |
*/ |
return(ROFF_ERR); |
r->rstackpos++; |
} |
if (ROFFRULE_DENY == r->last->rule) |
r->rstack[++r->rstackpos] = |
r->rstack[r->rstackpos] = ROFFRULE_ALLOW; |
ROFFRULE_DENY == r->last->rule ? |
else |
ROFFRULE_ALLOW : ROFFRULE_DENY; |
r->rstack[r->rstackpos] = ROFFRULE_DENY; |
|
} |
} |
|
|
/* If the parent has false as its rule, then so do we. */ |
/* If the parent has false as its rule, then so do we. */ |
Line 1093 roff_rm(ROFF_ARGS) |
|
Line 1114 roff_rm(ROFF_ARGS) |
|
|
|
cp = *bufp + pos; |
cp = *bufp + pos; |
while ('\0' != *cp) { |
while ('\0' != *cp) { |
name = roff_getname(r, &cp, ln, cp - *bufp); |
name = roff_getname(r, &cp, ln, (int)(cp - *bufp)); |
if ('\0' != *name) |
if ('\0' != *name) |
roff_setstr(r, name, NULL, 0); |
roff_setstr(r, name, NULL, 0); |
} |
} |
Line 1106 roff_TE(ROFF_ARGS) |
|
Line 1127 roff_TE(ROFF_ARGS) |
|
{ |
{ |
|
|
if (NULL == r->tbl) |
if (NULL == r->tbl) |
(*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL); |
mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL); |
else |
else |
tbl_end(r->tbl); |
tbl_end(r->tbl); |
|
|
Line 1120 roff_T_(ROFF_ARGS) |
|
Line 1141 roff_T_(ROFF_ARGS) |
|
{ |
{ |
|
|
if (NULL == r->tbl) |
if (NULL == r->tbl) |
(*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL); |
mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL); |
else |
else |
tbl_restart(ppos, ln, r->tbl); |
tbl_restart(ppos, ln, r->tbl); |
|
|
Line 1129 roff_T_(ROFF_ARGS) |
|
Line 1150 roff_T_(ROFF_ARGS) |
|
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
static enum rofferr |
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) |
|
{ |
|
|
|
mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL); |
|
return(ROFF_IGN); |
|
} |
|
|
|
/* ARGSUSED */ |
|
static enum rofferr |
roff_TS(ROFF_ARGS) |
roff_TS(ROFF_ARGS) |
{ |
{ |
struct tbl_node *t; |
struct tbl_node *t; |
|
|
if (r->tbl) { |
if (r->tbl) { |
(*r->msg)(MANDOCERR_SCOPEBROKEN, r->data, ln, ppos, NULL); |
mandoc_msg(MANDOCERR_SCOPEBROKEN, r->parse, ln, ppos, NULL); |
tbl_end(r->tbl); |
tbl_end(r->tbl); |
} |
} |
|
|
t = tbl_alloc(ppos, ln, r->data, r->msg); |
t = tbl_alloc(ppos, ln, r->parse); |
|
|
if (r->last_tbl) |
if (r->last_tbl) |
r->last_tbl->next = t; |
r->last_tbl->next = t; |
Line 1155 roff_so(ROFF_ARGS) |
|
Line 1203 roff_so(ROFF_ARGS) |
|
{ |
{ |
char *name; |
char *name; |
|
|
(*r->msg)(MANDOCERR_SO, r->data, ln, ppos, NULL); |
mandoc_msg(MANDOCERR_SO, r->parse, ln, ppos, NULL); |
|
|
/* |
/* |
* Handle `so'. Be EXTREMELY careful, as we shouldn't be |
* Handle `so'. Be EXTREMELY careful, as we shouldn't be |
Line 1166 roff_so(ROFF_ARGS) |
|
Line 1214 roff_so(ROFF_ARGS) |
|
|
|
name = *bufp + pos; |
name = *bufp + pos; |
if ('/' == *name || strstr(name, "../") || strstr(name, "/..")) { |
if ('/' == *name || strstr(name, "../") || strstr(name, "/..")) { |
(*r->msg)(MANDOCERR_SOPATH, r->data, ln, pos, NULL); |
mandoc_msg(MANDOCERR_SOPATH, r->parse, ln, pos, NULL); |
return(ROFF_ERR); |
return(ROFF_ERR); |
} |
} |
|
|
Line 1189 roff_userdef(ROFF_ARGS) |
|
Line 1237 roff_userdef(ROFF_ARGS) |
|
cp = *bufp + pos; |
cp = *bufp + pos; |
for (i = 0; i < 9; i++) |
for (i = 0; i < 9; i++) |
arg[i] = '\0' == *cp ? "" : |
arg[i] = '\0' == *cp ? "" : |
mandoc_getarg(&cp, r->msg, r->data, ln, &pos); |
mandoc_getarg(r->parse, &cp, ln, &pos); |
|
|
/* |
/* |
* Expand macro arguments. |
* Expand macro arguments. |
Line 1229 roff_userdef(ROFF_ARGS) |
|
Line 1277 roff_userdef(ROFF_ARGS) |
|
ROFF_REPARSE : ROFF_APPEND); |
ROFF_REPARSE : ROFF_APPEND); |
} |
} |
|
|
|
|
static char * |
static char * |
roff_getname(struct roff *r, char **cpp, int ln, int pos) |
roff_getname(struct roff *r, char **cpp, int ln, int pos) |
{ |
{ |
Line 1246 roff_getname(struct roff *r, char **cpp, int ln, int p |
|
Line 1293 roff_getname(struct roff *r, char **cpp, int ln, int p |
|
cp++; |
cp++; |
if ('\\' == *cp) |
if ('\\' == *cp) |
continue; |
continue; |
(*r->msg)(MANDOCERR_NAMESC, r->data, ln, pos, NULL); |
mandoc_msg(MANDOCERR_NAMESC, r->parse, ln, pos, NULL); |
*cp = '\0'; |
*cp = '\0'; |
name = cp; |
name = cp; |
} |
} |
Line 1263 roff_getname(struct roff *r, char **cpp, int ln, int p |
|
Line 1310 roff_getname(struct roff *r, char **cpp, int ln, int p |
|
return(name); |
return(name); |
} |
} |
|
|
|
|
/* |
/* |
* Store *string into the user-defined string called *name. |
* Store *string into the user-defined string called *name. |
* In multiline mode, append to an existing entry and append '\n'; |
* In multiline mode, append to an existing entry and append '\n'; |
Line 1303 roff_setstr(struct roff *r, const char *name, const ch |
|
Line 1349 roff_setstr(struct roff *r, const char *name, const ch |
|
* One additional byte for the '\n' in multiline mode, |
* One additional byte for the '\n' in multiline mode, |
* and one for the terminating '\0'. |
* and one for the terminating '\0'. |
*/ |
*/ |
newch = strlen(string) + (multiline ? 2 : 1); |
newch = strlen(string) + (multiline ? 2u : 1u); |
if (NULL == n->string) { |
if (NULL == n->string) { |
n->string = mandoc_malloc(newch); |
n->string = mandoc_malloc(newch); |
*n->string = '\0'; |
*n->string = '\0'; |
Line 1314 roff_setstr(struct roff *r, const char *name, const ch |
|
Line 1360 roff_setstr(struct roff *r, const char *name, const ch |
|
} |
} |
|
|
/* Skip existing content in the destination buffer. */ |
/* Skip existing content in the destination buffer. */ |
c = n->string + oldch; |
c = n->string + (int)oldch; |
|
|
/* Append new content to the destination buffer. */ |
/* Append new content to the destination buffer. */ |
while (*string) { |
while (*string) { |
Line 1333 roff_setstr(struct roff *r, const char *name, const ch |
|
Line 1379 roff_setstr(struct roff *r, const char *name, const ch |
|
*c = '\0'; |
*c = '\0'; |
} |
} |
|
|
|
|
static const char * |
static const char * |
roff_getstrn(const struct roff *r, const char *name, size_t len) |
roff_getstrn(const struct roff *r, const char *name, size_t len) |
{ |
{ |
Line 1346 roff_getstrn(const struct roff *r, const char *name, s |
|
Line 1391 roff_getstrn(const struct roff *r, const char *name, s |
|
return(n ? n->string : NULL); |
return(n ? n->string : NULL); |
} |
} |
|
|
|
|
static void |
static void |
roff_freestr(struct roff *r) |
roff_freestr(struct roff *r) |
{ |
{ |
Line 1367 roff_span(const struct roff *r) |
|
Line 1411 roff_span(const struct roff *r) |
|
{ |
{ |
|
|
return(r->tbl ? tbl_span(r->tbl) : NULL); |
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); |
} |
} |