version 1.180, 2013/10/05 22:08:12 |
version 1.188, 2013/12/25 00:50:05 |
|
|
ROFF_de1, |
ROFF_de1, |
ROFF_ds, |
ROFF_ds, |
ROFF_el, |
ROFF_el, |
|
ROFF_fam, |
|
ROFF_hw, |
ROFF_hy, |
ROFF_hy, |
ROFF_ie, |
ROFF_ie, |
ROFF_if, |
ROFF_if, |
|
|
}; |
}; |
|
|
enum roffrule { |
enum roffrule { |
ROFFRULE_ALLOW, |
ROFFRULE_DENY, |
ROFFRULE_DENY |
ROFFRULE_ALLOW |
}; |
}; |
|
|
/* |
/* |
|
|
|
|
/* |
/* |
* A single number register as part of a singly-linked list. |
* A single number register as part of a singly-linked list. |
* Registers are assumed to be unsigned ints for now. |
|
*/ |
*/ |
struct roffreg { |
struct roffreg { |
struct roffstr key; |
struct roffstr key; |
unsigned int u; |
int val; |
struct roffreg *next; |
struct roffreg *next; |
}; |
}; |
|
|
Line 186 static void roff_free1(struct roff *); |
|
Line 187 static void roff_free1(struct roff *); |
|
static void roff_freereg(struct roffreg *); |
static void roff_freereg(struct roffreg *); |
static void roff_freestr(struct roffkv *); |
static void roff_freestr(struct roffkv *); |
static char *roff_getname(struct roff *, char **, int, int); |
static char *roff_getname(struct roff *, char **, int, int); |
|
static int roff_getnum(const char *, int *, int *); |
|
static int roff_getop(const char *, int *, char *); |
|
static int roff_getregn(const struct roff *, |
|
const char *, size_t); |
static const char *roff_getstrn(const struct roff *, |
static const char *roff_getstrn(const struct roff *, |
const char *, size_t); |
const char *, size_t); |
static enum rofferr roff_it(ROFF_ARGS); |
static enum rofferr roff_it(ROFF_ARGS); |
Line 232 static struct roffmac roffs[ROFF_MAX] = { |
|
Line 237 static struct roffmac roffs[ROFF_MAX] = { |
|
{ "de1", roff_block, roff_block_text, roff_block_sub, 0, NULL }, |
{ "de1", roff_block, roff_block_text, roff_block_sub, 0, NULL }, |
{ "ds", roff_ds, NULL, NULL, 0, NULL }, |
{ "ds", roff_ds, NULL, NULL, 0, NULL }, |
{ "el", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL }, |
{ "el", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL }, |
|
{ "fam", roff_line_ignore, NULL, NULL, 0, NULL }, |
|
{ "hw", roff_line_ignore, NULL, NULL, 0, NULL }, |
{ "hy", roff_line_ignore, NULL, NULL, 0, NULL }, |
{ "hy", roff_line_ignore, NULL, NULL, 0, NULL }, |
{ "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 }, |
Line 480 roff_alloc(enum mparset type, struct mparse *parse) |
|
Line 487 roff_alloc(enum mparset type, struct mparse *parse) |
|
} |
} |
|
|
/* |
/* |
* Pre-filter each and every line for reserved words (one beginning with |
* In the current line, expand user-defined strings ("\*") |
* `\*', e.g., `\*(ab'). These must be handled before the actual line |
* and references to number registers ("\n"). |
* is processed. |
* Also check the syntax of other escape sequences. |
* This also checks the syntax of regular escapes. |
|
*/ |
*/ |
static enum rofferr |
static enum rofferr |
roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos) |
roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos) |
{ |
{ |
enum mandoc_esc esc; |
char ubuf[12]; /* buffer to print the number */ |
const char *stesc; /* start of an escape sequence ('\\') */ |
const char *stesc; /* start of an escape sequence ('\\') */ |
const char *stnam; /* start of the name, after "[(*" */ |
const char *stnam; /* start of the name, after "[(*" */ |
const char *cp; /* end of the name, e.g. before ']' */ |
const char *cp; /* end of the name, e.g. before ']' */ |
const char *res; /* the string to be substituted */ |
const char *res; /* the string to be substituted */ |
int i, maxl, expand_count; |
char *nbuf; /* new buffer to copy bufp to */ |
size_t nsz; |
size_t nsz; /* size of the new buffer */ |
char *n; |
size_t maxl; /* expected length of the escape name */ |
|
size_t naml; /* actual length of the escape name */ |
|
int expand_count; /* to avoid infinite loops */ |
|
|
expand_count = 0; |
expand_count = 0; |
|
|
|
|
stesc = cp++; |
stesc = cp++; |
|
|
/* |
/* |
* The second character must be an asterisk. |
* The second character must be an asterisk or an n. |
* If it isn't, skip it anyway: It is escaped, |
* If it isn't, skip it anyway: It is escaped, |
* so it can't start another escape sequence. |
* so it can't start another escape sequence. |
*/ |
*/ |
|
|
if ('\0' == *cp) |
if ('\0' == *cp) |
return(ROFF_CONT); |
return(ROFF_CONT); |
|
|
if ('*' != *cp) { |
switch (*cp) { |
res = cp; |
case ('*'): |
esc = mandoc_escape(&cp, NULL, NULL); |
res = NULL; |
if (ESCAPE_ERROR != esc) |
break; |
|
case ('n'): |
|
res = ubuf; |
|
break; |
|
default: |
|
if (ESCAPE_ERROR != mandoc_escape(&cp, NULL, NULL)) |
continue; |
continue; |
cp = res; |
|
mandoc_msg |
mandoc_msg |
(MANDOCERR_BADESCAPE, r->parse, |
(MANDOCERR_BADESCAPE, r->parse, |
ln, (int)(stesc - *bufp), NULL); |
ln, (int)(stesc - *bufp), NULL); |
|
|
|
|
/* |
/* |
* The third character decides the length |
* The third character decides the length |
* of the name of the string. |
* of the name of the string or register. |
* Save a pointer to the name. |
* Save a pointer to the name. |
*/ |
*/ |
|
|
|
|
|
|
/* Advance to the end of the name. */ |
/* Advance to the end of the name. */ |
|
|
for (i = 0; 0 == maxl || i < maxl; i++, cp++) { |
for (naml = 0; 0 == maxl || naml < maxl; naml++, cp++) { |
if ('\0' == *cp) { |
if ('\0' == *cp) { |
mandoc_msg |
mandoc_msg |
(MANDOCERR_BADESCAPE, |
(MANDOCERR_BADESCAPE, |
|
|
* undefined, resume searching for escapes. |
* undefined, resume searching for escapes. |
*/ |
*/ |
|
|
res = roff_getstrn(r, stnam, (size_t)i); |
if (NULL == res) |
|
res = roff_getstrn(r, stnam, naml); |
|
else |
|
snprintf(ubuf, sizeof(ubuf), "%d", |
|
roff_getregn(r, stnam, naml)); |
|
|
if (NULL == res) { |
if (NULL == res) { |
mandoc_msg |
mandoc_msg |
|
|
pos = stesc - *bufp; |
pos = stesc - *bufp; |
|
|
nsz = *szp + strlen(res) + 1; |
nsz = *szp + strlen(res) + 1; |
n = mandoc_malloc(nsz); |
nbuf = mandoc_malloc(nsz); |
|
|
strlcpy(n, *bufp, (size_t)(stesc - *bufp + 1)); |
strlcpy(nbuf, *bufp, (size_t)(stesc - *bufp + 1)); |
strlcat(n, res, nsz); |
strlcat(nbuf, res, nsz); |
strlcat(n, cp + (maxl ? 0 : 1), nsz); |
strlcat(nbuf, cp + (maxl ? 0 : 1), nsz); |
|
|
free(*bufp); |
free(*bufp); |
|
|
*bufp = n; |
*bufp = nbuf; |
*szp = nsz; |
*szp = nsz; |
|
|
if (EXPAND_LIMIT >= ++expand_count) |
if (EXPAND_LIMIT >= ++expand_count) |
Line 702 roff_parseln(struct roff *r, int ln, char **bufp, |
|
Line 718 roff_parseln(struct roff *r, int ln, char **bufp, |
|
assert(ROFF_IGN == e || ROFF_CONT == e); |
assert(ROFF_IGN == e || ROFF_CONT == e); |
if (ROFF_CONT != e) |
if (ROFF_CONT != e) |
return(e); |
return(e); |
if (r->eqn) |
} |
return(eqn_read(&r->eqn, ln, *bufp, pos, offs)); |
if (r->eqn) |
|
return(eqn_read(&r->eqn, ln, *bufp, ppos, offs)); |
|
if ( ! ctl) { |
if (r->tbl) |
if (r->tbl) |
return(tbl_read(r->tbl, ln, *bufp, pos)); |
return(tbl_read(r->tbl, ln, *bufp, pos)); |
return(roff_parsetext(bufp, szp, pos, offs)); |
return(roff_parsetext(bufp, szp, pos, offs)); |
} else if ( ! ctl) { |
} |
if (r->eqn) |
|
return(eqn_read(&r->eqn, ln, *bufp, pos, offs)); |
|
if (r->tbl) |
|
return(tbl_read(r->tbl, ln, *bufp, pos)); |
|
return(roff_parsetext(bufp, szp, pos, offs)); |
|
} else if (r->eqn) |
|
return(eqn_read(&r->eqn, ln, *bufp, ppos, offs)); |
|
|
|
/* |
/* |
* 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, |
Line 1120 roff_cond_text(ROFF_ARGS) |
|
Line 1131 roff_cond_text(ROFF_ARGS) |
|
return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); |
return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); |
} |
} |
|
|
|
static int |
|
roff_getnum(const char *v, int *pos, int *res) |
|
{ |
|
int p, n; |
|
|
|
p = *pos; |
|
n = v[p] == '-'; |
|
if (n) |
|
p++; |
|
|
|
for (*res = 0; isdigit((unsigned char)v[p]); p++) |
|
*res += 10 * *res + v[p] - '0'; |
|
if (p == *pos + n) |
|
return 0; |
|
|
|
if (n) |
|
*res = -*res; |
|
|
|
*pos = p; |
|
return 1; |
|
} |
|
|
|
static int |
|
roff_getop(const char *v, int *pos, char *res) |
|
{ |
|
int e; |
|
|
|
*res = v[*pos]; |
|
e = v[*pos + 1] == '='; |
|
|
|
switch (*res) { |
|
case '=': |
|
break; |
|
case '>': |
|
if (e) |
|
*res = 'g'; |
|
break; |
|
case '<': |
|
if (e) |
|
*res = 'l'; |
|
break; |
|
default: |
|
return(0); |
|
} |
|
|
|
*pos += 1 + e; |
|
|
|
return(*res); |
|
} |
|
|
static enum roffrule |
static enum roffrule |
roff_evalcond(const char *v, int *pos) |
roff_evalcond(const char *v, int *pos) |
{ |
{ |
|
int not, lh, rh; |
|
char op; |
|
|
switch (v[*pos]) { |
switch (v[*pos]) { |
case ('n'): |
case ('n'): |
Line 1135 roff_evalcond(const char *v, int *pos) |
|
Line 1198 roff_evalcond(const char *v, int *pos) |
|
case ('t'): |
case ('t'): |
(*pos)++; |
(*pos)++; |
return(ROFFRULE_DENY); |
return(ROFFRULE_DENY); |
|
case ('!'): |
|
(*pos)++; |
|
not = 1; |
|
break; |
default: |
default: |
|
not = 0; |
break; |
break; |
} |
} |
|
|
while (v[*pos] && ' ' != v[*pos]) |
if (!roff_getnum(v, pos, &lh)) |
(*pos)++; |
return ROFFRULE_DENY; |
return(ROFFRULE_DENY); |
if (!roff_getop(v, pos, &op)) { |
|
if (lh < 0) |
|
lh = 0; |
|
goto out; |
|
} |
|
if (!roff_getnum(v, pos, &rh)) |
|
return ROFFRULE_DENY; |
|
switch (op) { |
|
case 'g': |
|
lh = lh >= rh; |
|
break; |
|
case 'l': |
|
lh = lh <= rh; |
|
break; |
|
case '=': |
|
lh = lh == rh; |
|
break; |
|
case '>': |
|
lh = lh > rh; |
|
break; |
|
case '<': |
|
lh = lh < rh; |
|
break; |
|
default: |
|
return ROFFRULE_DENY; |
|
} |
|
out: |
|
if (not) |
|
lh = !lh; |
|
return lh ? ROFFRULE_ALLOW : ROFFRULE_DENY; |
} |
} |
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
Line 1263 roff_ds(ROFF_ARGS) |
|
Line 1360 roff_ds(ROFF_ARGS) |
|
} |
} |
|
|
void |
void |
roff_setreg(struct roff *r, const char *name, unsigned int val) |
roff_setreg(struct roff *r, const char *name, int val, char sign) |
{ |
{ |
struct roffreg *reg; |
struct roffreg *reg; |
|
|
Line 1278 roff_setreg(struct roff *r, const char *name, unsigned |
|
Line 1375 roff_setreg(struct roff *r, const char *name, unsigned |
|
reg = mandoc_malloc(sizeof(struct roffreg)); |
reg = mandoc_malloc(sizeof(struct roffreg)); |
reg->key.p = mandoc_strdup(name); |
reg->key.p = mandoc_strdup(name); |
reg->key.sz = strlen(name); |
reg->key.sz = strlen(name); |
|
reg->val = 0; |
reg->next = r->regtab; |
reg->next = r->regtab; |
r->regtab = reg; |
r->regtab = reg; |
} |
} |
|
|
reg->u = val; |
if ('+' == sign) |
|
reg->val += val; |
|
else if ('-' == sign) |
|
reg->val -= val; |
|
else |
|
reg->val = val; |
} |
} |
|
|
unsigned int |
int |
roff_getreg(const struct roff *r, const char *name) |
roff_getreg(const struct roff *r, const char *name) |
{ |
{ |
struct roffreg *reg; |
struct roffreg *reg; |
|
|
for (reg = r->regtab; reg; reg = reg->next) |
for (reg = r->regtab; reg; reg = reg->next) |
if (0 == strcmp(name, reg->key.p)) |
if (0 == strcmp(name, reg->key.p)) |
return(reg->u); |
return(reg->val); |
|
|
return(0); |
return(0); |
} |
} |
|
|
|
static int |
|
roff_getregn(const struct roff *r, const char *name, size_t len) |
|
{ |
|
struct roffreg *reg; |
|
|
|
for (reg = r->regtab; reg; reg = reg->next) |
|
if (len == reg->key.sz && |
|
0 == strncmp(name, reg->key.p, len)) |
|
return(reg->val); |
|
|
|
return(0); |
|
} |
|
|
static void |
static void |
roff_freereg(struct roffreg *reg) |
roff_freereg(struct roffreg *reg) |
{ |
{ |
Line 1316 roff_nr(ROFF_ARGS) |
|
Line 1432 roff_nr(ROFF_ARGS) |
|
{ |
{ |
const char *key; |
const char *key; |
char *val; |
char *val; |
|
size_t sz; |
int iv; |
int iv; |
|
char sign; |
|
|
val = *bufp + pos; |
val = *bufp + pos; |
key = roff_getname(r, &val, ln, pos); |
key = roff_getname(r, &val, ln, pos); |
|
|
iv = mandoc_strntoi(val, strlen(val), 10); |
sign = *val; |
if (0 > iv) |
if ('+' == sign || '-' == sign) |
iv = 0; |
val++; |
|
|
roff_setreg(r, key, (unsigned)iv); |
sz = strspn(val, "0123456789"); |
|
iv = sz ? mandoc_strntoi(val, sz, 10) : 0; |
|
|
|
roff_setreg(r, key, iv, sign); |
|
|
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
|
|
Line 1612 roff_userdef(ROFF_ARGS) |
|
Line 1733 roff_userdef(ROFF_ARGS) |
|
|
|
/* |
/* |
* Collect pointers to macro argument strings |
* Collect pointers to macro argument strings |
* and null-terminate them. |
* and NUL-terminate them. |
*/ |
*/ |
cp = *bufp + pos; |
cp = *bufp + pos; |
for (i = 0; i < 9; i++) |
for (i = 0; i < 9; i++) |