version 1.179, 2013/10/05 20:30:05 |
version 1.182, 2013/10/05 22:19:10 |
|
|
}; |
}; |
|
|
/* |
/* |
* A single register entity. If "set" is zero, the value of the |
|
* register should be the default one, which is per-register. |
|
* Registers are assumed to be unsigned ints for now. |
|
*/ |
|
struct reg { |
|
int set; /* whether set or not */ |
|
unsigned int u; /* unsigned integer */ |
|
}; |
|
|
|
/* |
|
* An incredibly-simple string buffer. |
* An incredibly-simple string buffer. |
*/ |
*/ |
struct roffstr { |
struct roffstr { |
|
|
struct roffkv *next; /* next in list */ |
struct roffkv *next; /* next in list */ |
}; |
}; |
|
|
|
/* |
|
* A single number register as part of a singly-linked list. |
|
*/ |
|
struct roffreg { |
|
struct roffstr key; |
|
int val; |
|
struct roffreg *next; |
|
}; |
|
|
struct roff { |
struct roff { |
enum mparset parsetype; /* requested parse type */ |
enum mparset parsetype; /* requested parse type */ |
struct mparse *parse; /* parse point */ |
struct mparse *parse; /* parse point */ |
|
|
enum roffrule rstack[RSTACK_MAX]; /* stack of !`ie' rules */ |
enum roffrule rstack[RSTACK_MAX]; /* stack of !`ie' rules */ |
char control; /* control character */ |
char control; /* control character */ |
int rstackpos; /* position in rstack */ |
int rstackpos; /* position in rstack */ |
struct reg regs[REG__MAX]; |
struct roffreg *regtab; /* number registers */ |
struct roffkv *strtab; /* user-defined strings & macros */ |
struct roffkv *strtab; /* user-defined strings & macros */ |
struct roffkv *xmbtab; /* multi-byte trans table (`tr') */ |
struct roffkv *xmbtab; /* multi-byte trans table (`tr') */ |
struct roffstr *xtab; /* single-byte trans table (`tr') */ |
struct roffstr *xtab; /* single-byte trans table (`tr') */ |
Line 183 static enum rofferr roff_cond_sub(ROFF_ARGS); |
|
Line 182 static enum rofferr roff_cond_sub(ROFF_ARGS); |
|
static enum rofferr roff_ds(ROFF_ARGS); |
static enum rofferr roff_ds(ROFF_ARGS); |
static enum roffrule roff_evalcond(const char *, int *); |
static enum roffrule roff_evalcond(const char *, int *); |
static void roff_free1(struct roff *); |
static void roff_free1(struct roff *); |
|
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_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 424 roff_free1(struct roff *r) |
|
Line 426 roff_free1(struct roff *r) |
|
|
|
r->strtab = r->xmbtab = NULL; |
r->strtab = r->xmbtab = NULL; |
|
|
|
roff_freereg(r->regtab); |
|
|
|
r->regtab = NULL; |
|
|
if (r->xtab) |
if (r->xtab) |
for (i = 0; i < 128; i++) |
for (i = 0; i < 128; i++) |
free(r->xtab[i].p); |
free(r->xtab[i].p); |
Line 440 roff_reset(struct roff *r) |
|
Line 446 roff_reset(struct roff *r) |
|
roff_free1(r); |
roff_free1(r); |
|
|
r->control = 0; |
r->control = 0; |
memset(&r->regs, 0, sizeof(struct reg) * REG__MAX); |
|
|
|
for (i = 0; i < PREDEFS_MAX; i++) |
for (i = 0; i < PREDEFS_MAX; i++) |
roff_setstr(r, predefs[i].name, predefs[i].str, 0); |
roff_setstr(r, predefs[i].name, predefs[i].str, 0); |
Line 476 roff_alloc(enum mparset type, struct mparse *parse) |
|
Line 481 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 698 roff_parseln(struct roff *r, int ln, char **bufp, |
|
Line 712 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 1258 roff_ds(ROFF_ARGS) |
|
Line 1267 roff_ds(ROFF_ARGS) |
|
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
|
|
|
void |
|
roff_setreg(struct roff *r, const char *name, int val) |
|
{ |
|
struct roffreg *reg; |
|
|
|
/* Search for an existing register with the same name. */ |
|
reg = r->regtab; |
|
|
|
while (reg && strcmp(name, reg->key.p)) |
|
reg = reg->next; |
|
|
|
if (NULL == reg) { |
|
/* Create a new register. */ |
|
reg = mandoc_malloc(sizeof(struct roffreg)); |
|
reg->key.p = mandoc_strdup(name); |
|
reg->key.sz = strlen(name); |
|
reg->next = r->regtab; |
|
r->regtab = reg; |
|
} |
|
|
|
reg->val = val; |
|
} |
|
|
int |
int |
roff_regisset(const struct roff *r, enum regs reg) |
roff_getreg(const struct roff *r, const char *name) |
{ |
{ |
|
struct roffreg *reg; |
|
|
return(r->regs[(int)reg].set); |
for (reg = r->regtab; reg; reg = reg->next) |
|
if (0 == strcmp(name, reg->key.p)) |
|
return(reg->val); |
|
|
|
return(0); |
} |
} |
|
|
unsigned int |
static int |
roff_regget(const struct roff *r, enum regs reg) |
roff_getregn(const struct roff *r, const char *name, size_t len) |
{ |
{ |
|
struct roffreg *reg; |
|
|
return(r->regs[(int)reg].u); |
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); |
} |
} |
|
|
void |
static void |
roff_regunset(struct roff *r, enum regs reg) |
roff_freereg(struct roffreg *reg) |
{ |
{ |
|
struct roffreg *old_reg; |
|
|
r->regs[(int)reg].set = 0; |
while (NULL != reg) { |
|
free(reg->key.p); |
|
old_reg = reg; |
|
reg = reg->next; |
|
free(old_reg); |
|
} |
} |
} |
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
Line 1290 roff_nr(ROFF_ARGS) |
|
Line 1339 roff_nr(ROFF_ARGS) |
|
val = *bufp + pos; |
val = *bufp + pos; |
key = roff_getname(r, &val, ln, pos); |
key = roff_getname(r, &val, ln, pos); |
|
|
if (0 == strcmp(key, "nS")) { |
iv = mandoc_strntoi(val, strlen(val), 10); |
r->regs[(int)REG_nS].set = 1; |
|
if ((iv = mandoc_strntoi(val, strlen(val), 10)) >= 0) |
roff_setreg(r, key, iv); |
r->regs[(int)REG_nS].u = (unsigned)iv; |
|
else |
|
r->regs[(int)REG_nS].u = 0u; |
|
} |
|
|
|
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |