version 1.152, 2011/07/26 14:09:01 |
version 1.161, 2011/07/27 14:58:28 |
|
|
}; |
}; |
|
|
struct roffstr { |
struct roffstr { |
char *name; /* key of symbol */ |
char *key; /* key of symbol */ |
char *string; /* current value */ |
char *val; /* current value */ |
struct roffstr *next; /* next in list */ |
struct roffstr *next; /* next in list */ |
}; |
}; |
|
|
|
|
#define PREDEF(__name, __str) \ |
#define PREDEF(__name, __str) \ |
{ (__name), (__str) }, |
{ (__name), (__str) }, |
|
|
|
static enum rofft roffhash_find(const char *, size_t); |
|
static void roffhash_init(void); |
|
static void roffnode_cleanscope(struct roff *); |
|
static void roffnode_pop(struct roff *); |
|
static void roffnode_push(struct roff *, enum rofft, |
|
const char *, int, int); |
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 153 static enum rofferr roff_cond_text(ROFF_ARGS); |
|
Line 159 static enum rofferr roff_cond_text(ROFF_ARGS); |
|
static enum rofferr roff_cond_sub(ROFF_ARGS); |
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_freestr(struct roff *); |
static void roff_freestr(struct roff *); |
static char *roff_getname(struct roff *, char **, int, int); |
static char *roff_getname(struct roff *, char **, int, int); |
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_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 void roff_openeqn(struct roff *, const char *, |
|
int, int, const char *); |
|
static enum rofft roff_parse(struct roff *, const char *, int *); |
|
static enum rofferr roff_parsetext(char *); |
|
static void roff_res(struct roff *, |
char **, size_t *, int, 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 *, |
Line 172 static enum rofferr roff_EN(ROFF_ARGS); |
|
Line 183 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); |
|
|
/* See roff_hash_find() */ |
/* See roffhash_find() */ |
|
|
#define ASCII_HI 126 |
#define ASCII_HI 126 |
#define ASCII_LO 33 |
#define ASCII_LO 33 |
Line 220 static const struct predef predefs[PREDEFS_MAX] = { |
|
Line 231 static const struct predef predefs[PREDEFS_MAX] = { |
|
#include "predefs.in" |
#include "predefs.in" |
}; |
}; |
|
|
static void roff_free1(struct roff *); |
/* See roffhash_find() */ |
static enum rofft roff_hash_find(const char *, size_t); |
|
static void roff_hash_init(void); |
|
static void roffnode_cleanscope(struct roff *); |
|
static void roffnode_push(struct roff *, enum rofft, |
|
const char *, int, int); |
|
static void roffnode_pop(struct roff *); |
|
static enum rofft roff_parse(struct roff *, const char *, int *); |
|
|
|
/* See roff_hash_find() */ |
|
#define ROFF_HASH(p) (p[0] - ASCII_LO) |
#define ROFF_HASH(p) (p[0] - ASCII_LO) |
|
|
static void |
static void |
roff_hash_init(void) |
roffhash_init(void) |
{ |
{ |
struct roffmac *n; |
struct roffmac *n; |
int buc, i; |
int buc, i; |
Line 258 roff_hash_init(void) |
|
Line 260 roff_hash_init(void) |
|
* the nil-terminated string name could be found. |
* the nil-terminated string name could be found. |
*/ |
*/ |
static enum rofft |
static enum rofft |
roff_hash_find(const char *p, size_t s) |
roffhash_find(const char *p, size_t s) |
{ |
{ |
int buc; |
int buc; |
struct roffmac *n; |
struct roffmac *n; |
Line 387 roff_alloc(struct mparse *parse) |
|
Line 389 roff_alloc(struct mparse *parse) |
|
r->parse = parse; |
r->parse = parse; |
r->rstackpos = -1; |
r->rstackpos = -1; |
|
|
roff_hash_init(); |
roffhash_init(); |
|
|
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 395 roff_alloc(struct mparse *parse) |
|
Line 397 roff_alloc(struct mparse *parse) |
|
return(r); |
return(r); |
} |
} |
|
|
|
|
/* |
/* |
* Pre-filter each and every line for reserved words (one beginning with |
* Pre-filter each and every line for reserved words (one beginning with |
* `\*', e.g., `\*(ab'). These must be handled before the actual line |
* `\*', e.g., `\*(ab'). These must be handled before the actual line |
* is processed. |
* is processed. |
|
* This also checks the syntax of regular escapes. |
*/ |
*/ |
static int |
static void |
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; |
enum mandoc_esc esc; |
Line 413 roff_res(struct roff *r, char **bufp, size_t *szp, int |
|
Line 415 roff_res(struct roff *r, char **bufp, size_t *szp, int |
|
size_t nsz; |
size_t nsz; |
char *n; |
char *n; |
|
|
/* Search for a leading backslash and save a pointer to it. */ |
again: |
|
|
cp = *bufp + pos; |
cp = *bufp + pos; |
while (NULL != (cp = strchr(cp, '\\'))) { |
while (NULL != (cp = strchr(cp, '\\'))) { |
stesc = cp++; |
stesc = cp++; |
Line 426 roff_res(struct roff *r, char **bufp, size_t *szp, int |
|
Line 427 roff_res(struct roff *r, char **bufp, size_t *szp, int |
|
*/ |
*/ |
|
|
if ('\0' == *cp) |
if ('\0' == *cp) |
return(1); |
return; |
|
|
if ('*' != *cp) { |
if ('*' != *cp) { |
res = cp; |
res = cp; |
esc = mandoc_escape(&cp, NULL, NULL); |
esc = mandoc_escape(&cp, NULL, NULL); |
if (ESCAPE_ERROR != esc) |
if (ESCAPE_ERROR != esc) |
continue; |
continue; |
mandoc_msg(MANDOCERR_BADESCAPE, |
|
r->parse, ln, pos, NULL); |
|
cp = res; |
cp = res; |
continue; |
mandoc_msg |
|
(MANDOCERR_BADESCAPE, r->parse, |
|
ln, (int)(stesc - *bufp), NULL); |
|
return; |
} |
} |
|
|
cp++; |
cp++; |
Line 449 roff_res(struct roff *r, char **bufp, size_t *szp, int |
|
Line 451 roff_res(struct roff *r, char **bufp, size_t *szp, int |
|
|
|
switch (*cp) { |
switch (*cp) { |
case ('\0'): |
case ('\0'): |
return(1); |
return; |
case ('('): |
case ('('): |
cp++; |
cp++; |
maxl = 2; |
maxl = 2; |
Line 467 roff_res(struct roff *r, char **bufp, size_t *szp, int |
|
Line 469 roff_res(struct roff *r, char **bufp, size_t *szp, int |
|
/* Advance to the end of the name. */ |
/* Advance to the end of the name. */ |
|
|
for (i = 0; 0 == maxl || i < maxl; i++, cp++) { |
for (i = 0; 0 == maxl || i < maxl; i++, cp++) { |
if ('\0' == *cp) |
if ('\0' == *cp) { |
return(1); /* Error. */ |
mandoc_msg |
|
(MANDOCERR_BADESCAPE, |
|
r->parse, ln, |
|
(int)(stesc - *bufp), NULL); |
|
return; |
|
} |
if (0 == maxl && ']' == *cp) |
if (0 == maxl && ']' == *cp) |
break; |
break; |
} |
} |
Line 481 roff_res(struct roff *r, char **bufp, size_t *szp, int |
|
Line 488 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) { |
/* TODO: keep track of the correct position. */ |
mandoc_msg |
mandoc_msg(MANDOCERR_BADESCAPE, r->parse, ln, pos, NULL); |
(MANDOCERR_BADESCAPE, r->parse, |
|
ln, (int)(stesc - *bufp), NULL); |
res = ""; |
res = ""; |
} |
} |
|
|
/* Replace the escape sequence by the string. */ |
/* Replace the escape sequence by the string. */ |
|
|
|
pos = stesc - *bufp; |
|
|
nsz = *szp + strlen(res) + 1; |
nsz = *szp + strlen(res) + 1; |
n = mandoc_malloc(nsz); |
n = mandoc_malloc(nsz); |
|
|
Line 499 roff_res(struct roff *r, char **bufp, size_t *szp, int |
|
Line 509 roff_res(struct roff *r, char **bufp, size_t *szp, int |
|
|
|
*bufp = n; |
*bufp = n; |
*szp = nsz; |
*szp = nsz; |
return(0); |
goto again; |
} |
} |
|
|
return(1); |
|
} |
} |
|
|
|
/* |
|
* Process text streams: convert all breakable hyphens into ASCII_HYPH. |
|
*/ |
|
static enum rofferr |
|
roff_parsetext(char *p) |
|
{ |
|
char l, r; |
|
size_t sz; |
|
const char *start; |
|
enum mandoc_esc esc; |
|
|
|
start = p; |
|
|
|
while ('\0' != *p) { |
|
sz = strcspn(p, "-\\"); |
|
p += sz; |
|
|
|
if ('\0' == *p) |
|
break; |
|
|
|
if ('\\' == *p) { |
|
/* Skip over escapes. */ |
|
p++; |
|
esc = mandoc_escape |
|
((const char **)&p, NULL, NULL); |
|
if (ESCAPE_ERROR == esc) |
|
break; |
|
continue; |
|
} else if (p == start) { |
|
p++; |
|
continue; |
|
} |
|
|
|
l = *(p - 1); |
|
r = *(p + 1); |
|
if ('\\' != l && |
|
'\t' != r && '\t' != l && |
|
' ' != r && ' ' != l && |
|
'-' != r && '-' != l && |
|
! isdigit((unsigned char)l) && |
|
! isdigit((unsigned char)r)) |
|
*p = ASCII_HYPH; |
|
p++; |
|
} |
|
|
|
return(ROFF_CONT); |
|
} |
|
|
enum rofferr |
enum rofferr |
roff_parseln(struct roff *r, int ln, char **bufp, |
roff_parseln(struct roff *r, int ln, char **bufp, |
size_t *szp, int pos, int *offs) |
size_t *szp, int pos, int *offs) |
Line 519 roff_parseln(struct roff *r, int ln, char **bufp, |
|
Line 574 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, ln, pos)) |
roff_res(r, bufp, szp, ln, pos); |
return(ROFF_REPARSE); |
|
|
|
ppos = pos; |
ppos = pos; |
ctl = mandoc_getcontrol(*bufp, &pos); |
ctl = mandoc_getcontrol(*bufp, &pos); |
Line 545 roff_parseln(struct roff *r, int ln, char **bufp, |
|
Line 599 roff_parseln(struct roff *r, int ln, char **bufp, |
|
return(eqn_read(&r->eqn, ln, *bufp, pos, offs)); |
return(eqn_read(&r->eqn, ln, *bufp, pos, offs)); |
if (r->tbl) |
if (r->tbl) |
return(tbl_read(r->tbl, ln, *bufp, pos)); |
return(tbl_read(r->tbl, ln, *bufp, pos)); |
return(ROFF_CONT); |
return(roff_parsetext(*bufp + pos)); |
} else if ( ! ctl) { |
} else if ( ! ctl) { |
if (r->eqn) |
if (r->eqn) |
return(eqn_read(&r->eqn, ln, *bufp, pos, offs)); |
return(eqn_read(&r->eqn, ln, *bufp, pos, offs)); |
if (r->tbl) |
if (r->tbl) |
return(tbl_read(r->tbl, ln, *bufp, pos)); |
return(tbl_read(r->tbl, ln, *bufp, pos)); |
return(ROFF_CONT); |
return(roff_parsetext(*bufp + pos)); |
} else if (r->eqn) |
} else if (r->eqn) |
return(eqn_read(&r->eqn, ln, *bufp, ppos, offs)); |
return(eqn_read(&r->eqn, ln, *bufp, ppos, offs)); |
|
|
Line 631 roff_parse(struct roff *r, const char *buf, int *pos) |
|
Line 685 roff_parse(struct roff *r, const char *buf, int *pos) |
|
maclen = strcspn(mac + 1, " \\\t\0") + 1; |
maclen = strcspn(mac + 1, " \\\t\0") + 1; |
|
|
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 : roffhash_find(mac, maclen); |
|
|
*pos += (int)maclen; |
*pos += (int)maclen; |
|
|
Line 1210 roff_T_(ROFF_ARGS) |
|
Line 1264 roff_T_(ROFF_ARGS) |
|
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
|
|
int |
#if 0 |
|
static int |
roff_closeeqn(struct roff *r) |
roff_closeeqn(struct roff *r) |
{ |
{ |
|
|
return(r->eqn && ROFF_EQN == eqn_end(&r->eqn) ? 1 : 0); |
return(r->eqn && ROFF_EQN == eqn_end(&r->eqn) ? 1 : 0); |
} |
} |
|
#endif |
|
|
void |
static void |
roff_openeqn(struct roff *r, const char *name, int line, |
roff_openeqn(struct roff *r, const char *name, int line, |
int offs, const char *buf) |
int offs, const char *buf) |
{ |
{ |
Line 1409 roff_setstr(struct roff *r, const char *name, const ch |
|
Line 1465 roff_setstr(struct roff *r, const char *name, const ch |
|
|
|
/* Search for an existing string with the same name. */ |
/* Search for an existing string with the same name. */ |
n = r->first_string; |
n = r->first_string; |
while (n && strcmp(name, n->name)) |
while (n && strcmp(name, n->key)) |
n = n->next; |
n = n->next; |
|
|
if (NULL == n) { |
if (NULL == n) { |
/* Create a new string table entry. */ |
/* Create a new string table entry. */ |
n = mandoc_malloc(sizeof(struct roffstr)); |
n = mandoc_malloc(sizeof(struct roffstr)); |
n->name = mandoc_strdup(name); |
n->key = mandoc_strdup(name); |
n->string = NULL; |
n->val = NULL; |
n->next = r->first_string; |
n->next = r->first_string; |
r->first_string = n; |
r->first_string = n; |
} else if (0 == multiline) { |
} else if (0 == multiline) { |
/* In multiline mode, append; else replace. */ |
/* In multiline mode, append; else replace. */ |
free(n->string); |
free(n->val); |
n->string = NULL; |
n->val = NULL; |
} |
} |
|
|
if (NULL == string) |
if (NULL == string) |
Line 1433 roff_setstr(struct roff *r, const char *name, const ch |
|
Line 1489 roff_setstr(struct roff *r, const char *name, const ch |
|
* and one for the terminating '\0'. |
* and one for the terminating '\0'. |
*/ |
*/ |
newch = strlen(string) + (multiline ? 2u : 1u); |
newch = strlen(string) + (multiline ? 2u : 1u); |
if (NULL == n->string) { |
if (NULL == n->val) { |
n->string = mandoc_malloc(newch); |
n->val = mandoc_malloc(newch); |
*n->string = '\0'; |
*n->val = '\0'; |
oldch = 0; |
oldch = 0; |
} else { |
} else { |
oldch = strlen(n->string); |
oldch = strlen(n->val); |
n->string = mandoc_realloc(n->string, oldch + newch); |
n->val = mandoc_realloc(n->val, oldch + newch); |
} |
} |
|
|
/* Skip existing content in the destination buffer. */ |
/* Skip existing content in the destination buffer. */ |
c = n->string + (int)oldch; |
c = n->val + (int)oldch; |
|
|
/* Append new content to the destination buffer. */ |
/* Append new content to the destination buffer. */ |
while (*string) { |
while (*string) { |
Line 1467 roff_getstrn(const struct roff *r, const char *name, s |
|
Line 1523 roff_getstrn(const struct roff *r, const char *name, s |
|
{ |
{ |
const struct roffstr *n; |
const struct roffstr *n; |
|
|
n = r->first_string; |
for (n = r->first_string; n; n = n->next) |
while (n && (strncmp(name, n->name, len) || '\0' != n->name[(int)len])) |
if (0 == strncmp(name, n->key, len) && |
n = n->next; |
'\0' == n->key[(int)len]) |
|
return(n->val); |
|
|
return(n ? n->string : NULL); |
return(NULL); |
} |
} |
|
|
static void |
static void |
Line 1480 roff_freestr(struct roff *r) |
|
Line 1537 roff_freestr(struct roff *r) |
|
struct roffstr *n, *nn; |
struct roffstr *n, *nn; |
|
|
for (n = r->first_string; n; n = nn) { |
for (n = r->first_string; n; n = nn) { |
free(n->name); |
free(n->key); |
free(n->string); |
free(n->val); |
nn = n->next; |
nn = n->next; |
free(n); |
free(n); |
} |
} |