version 1.139, 2011/05/24 14:00:39 |
version 1.142, 2011/05/26 11:58:25 |
|
|
#include "libroff.h" |
#include "libroff.h" |
#include "libmandoc.h" |
#include "libmandoc.h" |
|
|
|
/* Maximum number of nested if-else conditionals. */ |
#define RSTACK_MAX 128 |
#define RSTACK_MAX 128 |
|
|
enum rofft { |
enum rofft { |
|
|
ROFF_EQ, |
ROFF_EQ, |
ROFF_EN, |
ROFF_EN, |
ROFF_cblock, |
ROFF_cblock, |
ROFF_ccond, /* FIXME: remove this. */ |
ROFF_ccond, |
ROFF_USERDEF, |
ROFF_USERDEF, |
ROFF_MAX |
ROFF_MAX |
}; |
}; |
Line 124 struct roffmac { |
|
Line 125 struct roffmac { |
|
struct roffmac *next; |
struct roffmac *next; |
}; |
}; |
|
|
|
struct predef { |
|
const char *name; /* predefined input name */ |
|
const char *str; /* replacement symbol */ |
|
}; |
|
|
|
#define PREDEF(__name, __str) \ |
|
{ (__name), (__str) }, |
|
|
static enum rofferr roff_block(ROFF_ARGS); |
static enum rofferr roff_block(ROFF_ARGS); |
static enum rofferr roff_block_text(ROFF_ARGS); |
static enum rofferr roff_block_text(ROFF_ARGS); |
static enum rofferr roff_block_sub(ROFF_ARGS); |
static enum rofferr roff_block_sub(ROFF_ARGS); |
Line 141 static const char *roff_getstrn(const struct roff *, |
|
Line 150 static const char *roff_getstrn(const struct roff *, |
|
static enum rofferr roff_line_ignore(ROFF_ARGS); |
static enum rofferr roff_line_ignore(ROFF_ARGS); |
static enum rofferr roff_nr(ROFF_ARGS); |
static enum rofferr roff_nr(ROFF_ARGS); |
static int roff_res(struct roff *, |
static int roff_res(struct roff *, |
char **, size_t *, int); |
char **, size_t *, int, int); |
static enum rofferr roff_rm(ROFF_ARGS); |
static enum rofferr roff_rm(ROFF_ARGS); |
static void roff_setstr(struct roff *, |
static void roff_setstr(struct roff *, |
const char *, const char *, int); |
const char *, const char *, int); |
Line 195 static struct roffmac roffs[ROFF_MAX] = { |
|
Line 204 static struct roffmac roffs[ROFF_MAX] = { |
|
{ NULL, roff_userdef, NULL, NULL, 0, NULL }, |
{ NULL, roff_userdef, NULL, NULL, 0, NULL }, |
}; |
}; |
|
|
|
/* Array of injected predefined strings. */ |
|
#define PREDEFS_MAX 38 |
|
static const struct predef predefs[PREDEFS_MAX] = { |
|
#include "predefs.in" |
|
}; |
|
|
static void roff_free1(struct roff *); |
static void roff_free1(struct roff *); |
static enum rofft roff_hash_find(const char *, size_t); |
static enum rofft roff_hash_find(const char *, size_t); |
static void roff_hash_init(void); |
static void roff_hash_init(void); |
Line 228 roff_hash_init(void) |
|
Line 243 roff_hash_init(void) |
|
} |
} |
} |
} |
|
|
|
|
/* |
/* |
* Look up a roff token by its name. Returns ROFF_MAX if no macro by |
* Look up a roff token by its name. Returns ROFF_MAX if no macro by |
* the nil-terminated string name could be found. |
* the nil-terminated string name could be found. |
|
|
roff_alloc(struct regset *regs, struct mparse *parse) |
roff_alloc(struct regset *regs, struct mparse *parse) |
{ |
{ |
struct roff *r; |
struct roff *r; |
|
int i; |
|
|
r = mandoc_calloc(1, sizeof(struct roff)); |
r = mandoc_calloc(1, sizeof(struct roff)); |
r->regs = regs; |
r->regs = regs; |
Line 358 roff_alloc(struct regset *regs, struct mparse *parse) |
|
Line 373 roff_alloc(struct regset *regs, struct mparse *parse) |
|
r->rstackpos = -1; |
r->rstackpos = -1; |
|
|
roff_hash_init(); |
roff_hash_init(); |
|
|
|
for (i = 0; i < PREDEFS_MAX; i++) |
|
roff_setstr(r, predefs[i].name, predefs[i].str, 0); |
|
|
return(r); |
return(r); |
} |
} |
|
|
Line 368 roff_alloc(struct regset *regs, struct mparse *parse) |
|
Line 387 roff_alloc(struct regset *regs, struct mparse *parse) |
|
* is processed. |
* is processed. |
*/ |
*/ |
static int |
static int |
roff_res(struct roff *r, char **bufp, size_t *szp, int pos) |
roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos) |
{ |
{ |
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 "[(*" */ |
Line 435 roff_res(struct roff *r, char **bufp, size_t *szp, int |
|
Line 454 roff_res(struct roff *r, char **bufp, size_t *szp, int |
|
res = roff_getstrn(r, stnam, (size_t)i); |
res = roff_getstrn(r, stnam, (size_t)i); |
|
|
if (NULL == res) { |
if (NULL == res) { |
cp -= maxl ? 1 : 0; |
/* TODO: keep track of the correct position. */ |
continue; |
mandoc_msg(MANDOCERR_BADESCAPE, r->parse, ln, pos, NULL); |
|
res = ""; |
} |
} |
|
|
/* Replace the escape sequence by the string. */ |
/* Replace the escape sequence by the string. */ |
Line 472 roff_parseln(struct roff *r, int ln, char **bufp, |
|
Line 492 roff_parseln(struct roff *r, int ln, char **bufp, |
|
* words to fill in. |
* words to fill in. |
*/ |
*/ |
|
|
if (r->first_string && ! roff_res(r, bufp, szp, pos)) |
if (r->first_string && ! roff_res(r, bufp, szp, ln, pos)) |
return(ROFF_REPARSE); |
return(ROFF_REPARSE); |
|
|
ppos = pos; |
ppos = pos; |
Line 853 roff_cond_sub(ROFF_ARGS) |
|
Line 873 roff_cond_sub(ROFF_ARGS) |
|
*/ |
*/ |
|
|
if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos))) { |
if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos))) { |
/* |
|
* Jump through hoops to detect a \}, because it could |
|
* be (say) \\}, which is something completely |
|
* different. |
|
*/ |
|
ep = &(*bufp)[pos]; |
ep = &(*bufp)[pos]; |
for ( ; NULL != (ep = strchr(ep, '\\')); ep++) { |
for ( ; NULL != (ep = strchr(ep, '\\')); ep++) { |
ep++; |
ep++; |
if ('}' != *ep) |
if ('}' != *ep) |
continue; |
continue; |
*--ep = '\0'; |
*ep = '&'; |
roff_ccond(r, ROFF_ccond, bufp, szp, |
roff_ccond(r, ROFF_ccond, bufp, szp, |
ln, pos, pos + 2, offs); |
ln, pos, pos + 2, offs); |
break; |
break; |
Line 887 roff_cond_sub(ROFF_ARGS) |
|
Line 902 roff_cond_sub(ROFF_ARGS) |
|
ln, ppos, pos, offs)); |
ln, ppos, pos, offs)); |
} |
} |
|
|
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
static enum rofferr |
static enum rofferr |
roff_cond_text(ROFF_ARGS) |
roff_cond_text(ROFF_ARGS) |
{ |
{ |
char *ep, *st; |
char *ep; |
enum roffrule rr; |
enum roffrule rr; |
|
|
rr = r->last->rule; |
rr = r->last->rule; |
|
roffnode_cleanscope(r); |
|
|
/* |
ep = &(*bufp)[pos]; |
* We display the value of the text if out current evaluation |
for ( ; NULL != (ep = strchr(ep, '\\')); ep++) { |
* scope permits us to do so. |
ep++; |
*/ |
if ('}' != *ep) |
|
continue; |
/* FIXME: use roff_ccond? */ |
*ep = '&'; |
|
roff_ccond(r, ROFF_ccond, bufp, szp, |
st = &(*bufp)[pos]; |
ln, pos, pos + 2, offs); |
if (NULL == (ep = strstr(st, "\\}"))) { |
|
roffnode_cleanscope(r); |
|
return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); |
|
} |
} |
|
|
if (ep == st || (ep > st && '\\' != *(ep - 1))) |
|
roffnode_pop(r); |
|
|
|
roffnode_cleanscope(r); |
|
return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); |
return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); |
} |
} |
|
|
|
|
static enum roffrule |
static enum roffrule |
roff_evalcond(const char *v, int *pos) |
roff_evalcond(const char *v, int *pos) |