=================================================================== RCS file: /cvs/mandoc/roff.c,v retrieving revision 1.171 retrieving revision 1.173 diff -u -p -r1.171 -r1.173 --- mandoc/roff.c 2011/09/19 08:34:45 1.171 +++ mandoc/roff.c 2012/05/31 22:41:19 1.173 @@ -1,7 +1,7 @@ -/* $Id: roff.c,v 1.171 2011/09/19 08:34:45 schwarze Exp $ */ +/* $Id: roff.c,v 1.173 2012/05/31 22:41:19 schwarze Exp $ */ /* * Copyright (c) 2010, 2011 Kristaps Dzonsons - * Copyright (c) 2010, 2011 Ingo Schwarze + * Copyright (c) 2010, 2011, 2012 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -186,7 +186,7 @@ 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 *, +static enum rofferr roff_res(struct roff *, char **, size_t *, int, int); static enum rofferr roff_rm(ROFF_ARGS); static void roff_setstr(struct roff *, @@ -432,7 +432,7 @@ roff_alloc(struct mparse *parse) * is processed. * This also checks the syntax of regular escapes. */ -static void +static enum rofferr roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos) { enum mandoc_esc esc; @@ -458,7 +458,7 @@ again: */ if ('\0' == *cp) - return; + return(ROFF_CONT); if ('*' != *cp) { res = cp; @@ -469,7 +469,7 @@ again: mandoc_msg (MANDOCERR_BADESCAPE, r->parse, ln, (int)(stesc - *bufp), NULL); - return; + return(ROFF_CONT); } cp++; @@ -482,7 +482,7 @@ again: switch (*cp) { case ('\0'): - return; + return(ROFF_CONT); case ('('): cp++; maxl = 2; @@ -505,7 +505,7 @@ again: (MANDOCERR_BADESCAPE, r->parse, ln, (int)(stesc - *bufp), NULL); - return; + return(ROFF_CONT); } if (0 == maxl && ']' == *cp) break; @@ -546,8 +546,9 @@ again: /* Just leave the string unexpanded. */ mandoc_msg(MANDOCERR_ROFFLOOP, r->parse, ln, pos, NULL); - return; + return(ROFF_IGN); } + return(ROFF_CONT); } /* @@ -604,7 +605,10 @@ roff_parseln(struct roff *r, int ln, char **bufp, * words to fill in. */ - roff_res(r, bufp, szp, ln, pos); + e = roff_res(r, bufp, szp, ln, pos); + if (ROFF_IGN == e) + return(e); + assert(ROFF_CONT == e); ppos = pos; ctl = mandoc_getcontrol(*bufp, &pos); @@ -774,7 +778,7 @@ roffnode_cleanscope(struct roff *r) { while (r->last) { - if (--r->last->endspan < 0) + if (--r->last->endspan != 0) break; roffnode_pop(r); } @@ -1094,9 +1098,9 @@ roff_line_ignore(ROFF_ARGS) static enum rofferr roff_cond(ROFF_ARGS) { - int sv; - enum roffrule rule; + roffnode_push(r, tok, NULL, ln, ppos); + /* * An `.el' has no conditional body: it will consume the value * of the current rstack entry set in prior `ie' calls or @@ -1105,32 +1109,12 @@ roff_cond(ROFF_ARGS) * If we're not an `el', however, then evaluate the conditional. */ - rule = ROFF_el == tok ? + r->last->rule = ROFF_el == tok ? (r->rstackpos < 0 ? ROFFRULE_DENY : r->rstack[r->rstackpos--]) : roff_evalcond(*bufp, &pos); - sv = pos; - while (' ' == (*bufp)[pos]) - pos++; - /* - * Roff is weird. If we have just white-space after the - * conditional, it's considered the BODY and we exit without - * really doing anything. Warn about this. It's probably - * wrong. - */ - - if ('\0' == (*bufp)[pos] && sv != pos) { - mandoc_msg(MANDOCERR_NOARGS, r->parse, ln, ppos, NULL); - return(ROFF_IGN); - } - - roffnode_push(r, tok, NULL, ln, ppos); - - r->last->rule = rule; - - /* * An if-else will put the NEGATION of the current evaluated * conditional into the stack of rules. */ @@ -1152,28 +1136,39 @@ roff_cond(ROFF_ARGS) r->last->rule = ROFFRULE_DENY; /* - * Determine scope. If we're invoked with "\{" trailing the - * conditional, then we're in a multiline scope. Else our scope - * expires on the next line. + * Determine scope. + * If there is nothing on the line after the conditional, + * not even whitespace, use next-line scope. */ - r->last->endspan = 1; + if ('\0' == (*bufp)[pos]) { + r->last->endspan = 2; + goto out; + } + while (' ' == (*bufp)[pos]) + pos++; + + /* An opening brace requests multiline scope. */ + if ('\\' == (*bufp)[pos] && '{' == (*bufp)[pos + 1]) { r->last->endspan = -1; pos += 2; + goto out; } /* - * If there are no arguments on the line, the next-line scope is - * assumed. + * Anything else following the conditional causes + * single-line scope. Warn if the scope contains + * nothing but trailing whitespace. */ if ('\0' == (*bufp)[pos]) - return(ROFF_IGN); + mandoc_msg(MANDOCERR_NOARGS, r->parse, ln, ppos, NULL); - /* Otherwise re-run the roff parser after recalculating. */ + r->last->endspan = 1; +out: *offs = pos; return(ROFF_RERUN); }