/* ARGSUSED */ static enum rofferr roff_cond(ROFF_ARGS) { 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 * defaults to DENY. * * If we're not an `el', however, then evaluate the conditional. */ r->last->rule = ROFF_el == tok ? (r->rstackpos < 0 ? ROFFRULE_DENY : r->rstack[r->rstackpos--]) : roff_evalcond(*bufp, &pos); /* * An if-else will put the NEGATION of the current evaluated * conditional into the stack of rules. */ if (ROFF_ie == tok) { if (r->rstackpos == RSTACK_MAX - 1) { mandoc_msg(MANDOCERR_MEM, r->parse, ln, ppos, NULL); return(ROFF_ERR); } r->rstack[++r->rstackpos] = ROFFRULE_DENY == r->last->rule ? ROFFRULE_ALLOW : ROFFRULE_DENY; } /* If the parent has false as its rule, then so do we. */ if (r->last->parent && ROFFRULE_DENY == r->last->parent->rule) r->last->rule = ROFFRULE_DENY; /* * Determine scope. * If there is nothing on the line after the conditional, * not even whitespace, use next-line scope. */ 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; } /* * Anything else following the conditional causes * single-line scope. Warn if the scope contains * nothing but trailing whitespace. */ if ('\0' == (*bufp)[pos]) mandoc_msg(MANDOCERR_NOARGS, r->parse, ln, ppos, NULL); r->last->endspan = 1; out: *offs = pos; return(ROFF_RERUN); }
/* ARGSUSED */ static enum rofferr roff_cond(ROFF_ARGS) { int sv; enum roffrule rule; /* Stack overflow! */ if (ROFF_ie == tok && r->rstackpos == RSTACK_MAX - 1) { (*r->msg)(MANDOCERR_MEM, r->data, ln, ppos, NULL); return(ROFF_ERR); } /* First, evaluate the conditional. */ if (ROFF_el == tok) { /* * An `.el' will get the value of the current rstack * entry set in prior `ie' calls or defaults to DENY. */ if (r->rstackpos < 0) rule = ROFFRULE_DENY; else rule = r->rstack[r->rstackpos]; } else rule = 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) { if ((*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL)) return(ROFF_IGN); return(ROFF_ERR); } if ( ! roffnode_push(r, tok, ln, ppos)) return(ROFF_ERR); r->last->rule = rule; ROFF_DEBUG("roff: cond: %s -> %s\n", roffs[tok].name, ROFFRULE_ALLOW == rule ? "allow" : "deny"); if (ROFF_ie == tok) { /* * An if-else will put the NEGATION of the current * evaluated conditional into the stack. */ r->rstackpos++; if (ROFFRULE_DENY == r->last->rule) r->rstack[r->rstackpos] = ROFFRULE_ALLOW; else r->rstack[r->rstackpos] = ROFFRULE_DENY; } /* If the parent has false as its rule, then so do we. */ if (r->last->parent && ROFFRULE_DENY == r->last->parent->rule) { r->last->rule = ROFFRULE_DENY; ROFF_DEBUG("roff: cond override: %s -> deny\n", roffs[tok].name); } /* * 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. */ r->last->endspan = 1; if ('\\' == (*bufp)[pos] && '{' == (*bufp)[pos + 1]) { r->last->endspan = -1; pos += 2; ROFF_DEBUG("roff: cond-scope: %s, multi-line\n", roffs[tok].name); } else ROFF_DEBUG("roff: cond-scope: %s, one-line\n", roffs[tok].name); /* * If there are no arguments on the line, the next-line scope is * assumed. */ if ('\0' == (*bufp)[pos]) return(ROFF_IGN); /* Otherwise re-run the roff parser after recalculating. */ *offs = pos; return(ROFF_RERUN); }
/* ARGSUSED */ static enum rofferr roff_cond(ROFF_ARGS) { int sv; enum roffrule rule; /* * An `.el' has no conditional body: it will consume the value * of the current rstack entry set in prior `ie' calls or * defaults to DENY. * * If we're not an `el', however, then evaluate the conditional. */ 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. */ if (ROFF_ie == tok) { if (r->rstackpos == RSTACK_MAX - 1) { mandoc_msg(MANDOCERR_MEM, r->parse, ln, ppos, NULL); return(ROFF_ERR); } r->rstack[++r->rstackpos] = ROFFRULE_DENY == r->last->rule ? ROFFRULE_ALLOW : ROFFRULE_DENY; } /* If the parent has false as its rule, then so do we. */ if (r->last->parent && ROFFRULE_DENY == r->last->parent->rule) 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. */ r->last->endspan = 1; if ('\\' == (*bufp)[pos] && '{' == (*bufp)[pos + 1]) { r->last->endspan = -1; pos += 2; } /* * If there are no arguments on the line, the next-line scope is * assumed. */ if ('\0' == (*bufp)[pos]) return(ROFF_IGN); /* Otherwise re-run the roff parser after recalculating. */ *offs = pos; return(ROFF_RERUN); }