/* ARGSUSED */ static enum rofferr roff_cond_text(ROFF_ARGS) { char *ep, *st; enum roffrule rr; rr = r->last->rule; /* * We display the value of the text if out current evaluation * scope permits us to do so. */ st = &(*bufp)[pos]; 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); }
/* ARGSUSED */ static enum rofferr roff_ccond(ROFF_ARGS) { if (NULL == r->last) { mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL); return(ROFF_IGN); } switch (r->last->tok) { case (ROFF_el): /* FALLTHROUGH */ case (ROFF_ie): /* FALLTHROUGH */ case (ROFF_if): break; default: mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL); return(ROFF_IGN); } if (r->last->endspan > -1) { mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL); return(ROFF_IGN); } if ((*bufp)[pos]) mandoc_msg(MANDOCERR_ARGSLOST, r->parse, ln, pos, NULL); roffnode_pop(r); roffnode_cleanscope(r); return(ROFF_IGN); }
/* ARGSUSED */ static enum rofferr roff_block_sub(ROFF_ARGS) { enum rofft t; int i, j; /* * First check whether a custom macro exists at this level. If * it does, then check against it. This is some of groff's * stranger behaviours. If we encountered a custom end-scope * tag and that tag also happens to be a "real" macro, then we * need to try interpreting it again as a real macro. If it's * not, then return ignore. Else continue. */ if (r->last->end) { for (i = pos, j = 0; r->last->end[j]; j++, i++) if ((*bufp)[i] != r->last->end[j]) break; if ('\0' == r->last->end[j] && ('\0' == (*bufp)[i] || ' ' == (*bufp)[i] || '\t' == (*bufp)[i])) { roffnode_pop(r); roffnode_cleanscope(r); while (' ' == (*bufp)[i] || '\t' == (*bufp)[i]) i++; pos = i; if (ROFF_MAX != roff_parse(r, *bufp, &pos)) return(ROFF_RERUN); return(ROFF_IGN); } } /* * If we have no custom end-query or lookup failed, then try * pulling it out of the hashtable. */ t = roff_parse(r, *bufp, &pos); /* * Macros other than block-end are only significant * in `de' blocks; elsewhere, simply throw them away. */ if (ROFF_cblock != t) { if (ROFF_de == tok) roff_setstr(r, r->last->name, *bufp + ppos, 1); return(ROFF_IGN); } assert(roffs[t].proc); return((*roffs[t].proc)(r, t, bufp, szp, ln, ppos, pos, offs)); }
/* ARGSUSED */ static enum rofferr roff_block_sub(ROFF_ARGS) { enum rofft t; int i, j; /* * First check whether a custom macro exists at this level. If * it does, then check against it. This is some of groff's * stranger behaviours. If we encountered a custom end-scope * tag and that tag also happens to be a "real" macro, then we * need to try interpreting it again as a real macro. If it's * not, then return ignore. Else continue. */ if (r->last->end) { i = pos + 1; while (' ' == (*bufp)[i] || '\t' == (*bufp)[i]) i++; for (j = 0; r->last->end[j]; j++, i++) if ((*bufp)[i] != r->last->end[j]) break; if ('\0' == r->last->end[j] && ('\0' == (*bufp)[i] || ' ' == (*bufp)[i] || '\t' == (*bufp)[i])) { roffnode_pop(r); roffnode_cleanscope(r); if (ROFF_MAX != roff_parse(*bufp, &pos)) return(ROFF_RERUN); return(ROFF_IGN); } } /* * If we have no custom end-query or lookup failed, then try * pulling it out of the hashtable. */ ppos = pos; t = roff_parse(*bufp, &pos); /* If we're not a comment-end, then throw it away. */ if (ROFF_cblock != t) return(ROFF_IGN); assert(roffs[t].proc); return((*roffs[t].proc)(r, t, bufp, szp, ln, ppos, pos, offs)); }
/* ARGSUSED */ static enum rofferr roff_cond_sub(ROFF_ARGS) { enum rofft t; enum roffrule rr; char *ep; rr = r->last->rule; roffnode_cleanscope(r); t = roff_parse(r, *bufp, &pos); /* * Fully handle known macros when they are structurally * required or when the conditional evaluated to true. */ if ((ROFF_MAX != t) && (ROFF_ccond == t || ROFFRULE_ALLOW == rr || ROFFMAC_STRUCT & roffs[t].flags)) { assert(roffs[t].proc); return((*roffs[t].proc)(r, t, bufp, szp, ln, ppos, pos, offs)); } /* Always check for the closing delimiter `\}'. */ ep = &(*bufp)[pos]; while (NULL != (ep = strchr(ep, '\\'))) { if ('}' != *(++ep)) continue; /* * If we're at the end of line, then just chop * off the \} and resize the buffer. * If we aren't, then convert it to spaces. */ if ('\0' == *(ep + 1)) { *--ep = '\0'; *szp -= 2; } else *(ep - 1) = *ep = ' '; roff_ccond(r, ROFF_ccond, bufp, szp, ln, pos, pos + 2, offs); break; } return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); }
/* ARGSUSED */ static enum rofferr roff_cblock(ROFF_ARGS) { /* * A block-close `..' should only be invoked as a child of an * ignore macro, otherwise raise a warning and just ignore it. */ if (NULL == r->last) { if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL)) return(ROFF_ERR); return(ROFF_IGN); } switch (r->last->tok) { case (ROFF_am): /* FALLTHROUGH */ case (ROFF_ami): /* FALLTHROUGH */ case (ROFF_am1): /* FALLTHROUGH */ case (ROFF_de): /* FALLTHROUGH */ case (ROFF_dei): /* FALLTHROUGH */ case (ROFF_de1): /* FALLTHROUGH */ case (ROFF_ig): break; default: if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL)) return(ROFF_ERR); return(ROFF_IGN); } if ((*bufp)[pos]) if ( ! (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL)) return(ROFF_ERR); roffnode_pop(r); roffnode_cleanscope(r); return(ROFF_IGN); }
/* ARGSUSED */ static enum rofferr roff_cond_text(ROFF_ARGS) { char *ep; enum roffrule rr; rr = r->last->rule; roffnode_cleanscope(r); ep = &(*bufp)[pos]; for ( ; NULL != (ep = strchr(ep, '\\')); ep++) { ep++; if ('}' != *ep) continue; *ep = '&'; roff_ccond(r, ROFF_ccond, bufp, szp, ln, pos, pos + 2, offs); } return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); }
/* ARGSUSED */ static enum rofferr roff_cond_sub(ROFF_ARGS) { enum rofft t; enum roffrule rr; struct roffnode *l; ppos = pos; rr = r->last->rule; /* * Clean out scope. If we've closed ourselves, then don't * continue. */ l = r->last; roffnode_cleanscope(r); if (l != r->last) return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); if (ROFF_MAX == (t = roff_parse(*bufp, &pos))) return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); /* * A denied conditional must evaluate its children if and only * if they're either structurally required (such as loops and * conditionals) or a closing macro. */ if (ROFFRULE_DENY == rr) if ( ! (ROFFMAC_STRUCT & roffs[t].flags)) if (ROFF_ccond != t) return(ROFF_IGN); assert(roffs[t].proc); return((*roffs[t].proc) (r, t, bufp, szp, ln, ppos, pos, offs)); }
/* ARGSUSED */ static enum rofferr roff_cond_sub(ROFF_ARGS) { enum rofft t; enum roffrule rr; char *ep; rr = r->last->rule; roffnode_cleanscope(r); /* * If the macro is unknown, first check if it contains a closing * delimiter `\}'. If it does, close out our scope and return * the currently-scoped rule (ignore or continue). Else, drop * into the currently-scoped rule. */ if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos))) { ep = &(*bufp)[pos]; for ( ; NULL != (ep = strchr(ep, '\\')); ep++) { ep++; if ('}' != *ep) continue; /* * Make the \} go away. * This is a little haphazard, as it's not quite * clear how nroff does this. * If we're at the end of line, then just chop * off the \} and resize the buffer. * If we aren't, then conver it to spaces. */ if ('\0' == *(ep + 1)) { *--ep = '\0'; *szp -= 2; } else *(ep - 1) = *ep = ' '; roff_ccond(r, ROFF_ccond, bufp, szp, ln, pos, pos + 2, offs); break; } return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); } /* * A denied conditional must evaluate its children if and only * if they're either structurally required (such as loops and * conditionals) or a closing macro. */ if (ROFFRULE_DENY == rr) if ( ! (ROFFMAC_STRUCT & roffs[t].flags)) if (ROFF_ccond != t) return(ROFF_IGN); assert(roffs[t].proc); return((*roffs[t].proc)(r, t, bufp, szp, ln, ppos, pos, offs)); }