version 1.68, 2010/05/15 18:43:59 |
version 1.71, 2010/05/15 21:53:11 |
|
|
struct roffnode { |
struct roffnode { |
enum rofft tok; /* type of node */ |
enum rofft tok; /* type of node */ |
struct roffnode *parent; /* up one in stack */ |
struct roffnode *parent; /* up one in stack */ |
|
char *end; /* custom end-token */ |
int line; /* parse line */ |
int line; /* parse line */ |
int col; /* parse col */ |
int col; /* parse col */ |
}; |
}; |
Line 76 const struct roffmac roffs[ROFF_MAX] = { |
|
Line 77 const struct roffmac roffs[ROFF_MAX] = { |
|
{ ".", NULL, roff_new_close }, |
{ ".", NULL, roff_new_close }, |
}; |
}; |
|
|
static void roff_alloc1(struct roff *); |
|
static void roff_free1(struct roff *); |
static void roff_free1(struct roff *); |
static enum rofft roff_hash_find(const char *); |
static enum rofft roff_hash_find(const char *); |
static int roffnode_push(struct roff *, |
static int roffnode_push(struct roff *, |
Line 153 roff_free1(struct roff *r) |
|
Line 153 roff_free1(struct roff *r) |
|
} |
} |
|
|
|
|
static void |
|
roff_alloc1(struct roff *r) |
|
{ |
|
|
|
/* Do nothing for now. */ |
|
} |
|
|
|
|
|
void |
void |
roff_reset(struct roff *r) |
roff_reset(struct roff *r) |
{ |
{ |
|
|
roff_free1(r); |
roff_free1(r); |
roff_alloc1(r); |
|
} |
} |
|
|
|
|
Line 277 roff_ignore(ROFF_ARGS) |
|
Line 268 roff_ignore(ROFF_ARGS) |
|
static enum rofferr |
static enum rofferr |
roff_sub_ig(ROFF_ARGS) |
roff_sub_ig(ROFF_ARGS) |
{ |
{ |
enum rofft t; |
int i, j; |
int pos; |
|
|
|
/* Ignore free-text lines. */ |
/* Ignore free-text lines. */ |
|
|
if ('.' != (*bufp)[ppos]) |
if ('.' != (*bufp)[ppos]) |
return(ROFF_IGN); |
return(ROFF_IGN); |
|
|
/* Ignore macros unless it's a closing macro. */ |
if (r->last->end) { |
|
/* |
|
* Allow a macro to break us, if we've defined a special |
|
* one for the case. Old groff didn't allow spaces to |
|
* buffer the macro, but new groff does. Whee! |
|
*/ |
|
i = ppos + 1; |
|
while ((*bufp)[i] && ' ' == (*bufp)[i]) |
|
i++; |
|
|
t = roff_parse(*bufp, &pos); |
if ('\0' == (*bufp)[i]) |
if (ROFF_close != t) |
return(ROFF_IGN); |
|
|
|
for (j = 0; r->last->end[j]; i++, j++) |
|
if ((*bufp)[i] != r->last->end[j]) |
|
return(ROFF_IGN); |
|
|
|
if (r->last->end[j]) |
|
return(ROFF_IGN); |
|
if ((*bufp)[i] && ' ' != (*bufp)[i]) |
|
return(ROFF_IGN); |
|
|
|
while (' ' == (*bufp)[i]) |
|
i++; |
|
} else if (ROFF_close != roff_parse(*bufp, &i)) |
return(ROFF_IGN); |
return(ROFF_IGN); |
|
|
|
/* |
|
* Pop off the ignoring context and warn if we're going to lose |
|
* any of our remaining arguments. |
|
*/ |
|
|
roffnode_pop(r); |
roffnode_pop(r); |
|
|
|
if ('\0' == (*bufp)[i]) |
|
return(ROFF_IGN); |
|
if ( ! (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, i, NULL)) |
|
return(ROFF_ERR); |
|
|
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
|
|
Line 305 roff_new_close(ROFF_ARGS) |
|
Line 327 roff_new_close(ROFF_ARGS) |
|
if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL)) |
if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL)) |
return(ROFF_ERR); |
return(ROFF_ERR); |
*/ |
*/ |
return(ROFF_CONT); |
return(ROFF_IGN); |
} |
} |
|
|
|
|
Line 313 roff_new_close(ROFF_ARGS) |
|
Line 335 roff_new_close(ROFF_ARGS) |
|
static enum rofferr |
static enum rofferr |
roff_new_ig(ROFF_ARGS) |
roff_new_ig(ROFF_ARGS) |
{ |
{ |
|
int i; |
|
|
return(roffnode_push(r, ROFF_ig, ln, ppos) ? |
if ( ! roffnode_push(r, ROFF_ig, ln, ppos)) |
ROFF_IGN : ROFF_ERR); |
return(ROFF_ERR); |
|
|
|
i = (int)ppos; |
|
while ((*bufp)[i] && ' ' != (*bufp)[i]) |
|
i++; |
|
|
|
if (i == (int)ppos) |
|
return(ROFF_IGN); |
|
if ((*bufp)[i]) |
|
if ( ! (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, i, NULL)) |
|
return(ROFF_ERR); |
|
|
|
/* |
|
* If `.ig' has arguments, the first argument (up to the next |
|
* whitespace) is interpreted as an argument marking the macro |
|
* close. Thus, `.ig foo' will close at `.foo'. |
|
* |
|
* NOTE: the closing macro `.foo' in the above case is not |
|
* allowed to have leading spaces with old groff! Thus `.foo' |
|
* != `. foo'. Oh yeah, everything after the `.foo' is lost. |
|
* Merry fucking Christmas. |
|
*/ |
|
|
|
r->last->end = malloc((size_t)i - ppos + 1); |
|
if (NULL == r->last->end) { |
|
(*r->msg)(MANDOCERR_MEM, r->data, ln, ppos, NULL); |
|
return(ROFF_ERR); |
|
} |
|
|
|
memcpy(r->last->end, &(*bufp)[ppos], (size_t)i - ppos); |
|
r->last->end[(size_t)i - ppos] = '\0'; |
|
|
|
return(ROFF_IGN); |
} |
} |
|
|
|
|