/* 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); }
static void roff_free1(struct roff *r) { while (r->last) roffnode_pop(r); }
/* 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)); }
static void roffnode_cleanscope(struct roff *r) { while (r->last) { if (--r->last->endspan < 0) break; roffnode_pop(r); } }
/* 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_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); }
static void roff_free1(struct roff *r) { struct tbl_node *tbl; struct eqn_node *e; int i; while (NULL != (tbl = r->first_tbl)) { r->first_tbl = tbl->next; tbl_free(tbl); } r->first_tbl = r->last_tbl = r->tbl = NULL; while (NULL != (e = r->first_eqn)) { r->first_eqn = e->next; eqn_free(e); } r->first_eqn = r->last_eqn = r->eqn = NULL; while (r->last) roffnode_pop(r); roff_freestr(r->strtab); roff_freestr(r->xmbtab); r->strtab = r->xmbtab = NULL; roff_freereg(r->regtab); r->regtab = NULL; if (r->xtab) for (i = 0; i < 128; i++) free(r->xtab[i].p); free(r->xtab); r->xtab = NULL; }