diff options
Diffstat (limited to 'roff.c')
-rw-r--r-- | roff.c | 86 |
1 files changed, 54 insertions, 32 deletions
@@ -847,11 +847,10 @@ roff_cblock(ROFF_ARGS) switch (r->last->tok) { case ROFF_am: + /* ROFF_am1 is remapped to ROFF_am in roff_block(). */ /* FALLTHROUGH */ case ROFF_ami: /* FALLTHROUGH */ - case ROFF_am1: - /* FALLTHROUGH */ case ROFF_de: /* ROFF_de1 is remapped to ROFF_de in roff_block(). */ /* FALLTHROUGH */ @@ -919,34 +918,47 @@ roff_ccond(struct roff *r, int ln, int ppos) static enum rofferr roff_block(ROFF_ARGS) { - char *name, *cp; + const char *name; + char *iname, *cp; size_t namesz; - name = cp = *bufp + pos; - namesz = 0; - - if (ROFF_ig != tok) { - if ('\0' == *cp) { - mandoc_msg(MANDOCERR_REQ_EMPTY, r->parse, - ln, ppos, roffs[tok].name); - return(ROFF_IGN); - } + /* Ignore groff compatibility mode for now. */ - /* - * Re-write `de1', since we don't really care about - * groff's strange compatibility mode, into `de'. - */ + if (ROFF_de1 == tok) + tok = ROFF_de; + else if (ROFF_am1 == tok) + tok = ROFF_am; - if (ROFF_de1 == tok) - tok = ROFF_de; - else if (ROFF_de != tok) - mandoc_msg(MANDOCERR_REQUEST, r->parse, ln, ppos, - roffs[tok].name); + /* Parse the macro name argument. */ + cp = *bufp + pos; + if (ROFF_ig == tok) { + iname = NULL; + namesz = 0; + } else { + iname = cp; namesz = roff_getname(r, &cp, ln, ppos); - name[namesz] = '\0'; + iname[namesz] = '\0'; + } + + /* Resolve the macro name argument if it is indirect. */ + + if (namesz && (ROFF_dei == tok || ROFF_ami == tok)) { + if (NULL == (name = roff_getstrn(r, iname, namesz))) { + mandoc_vmsg(MANDOCERR_STR_UNDEF, + r->parse, ln, (int)(iname - *bufp), + "%.*s", (int)namesz, iname); + namesz = 0; + } else + namesz = strlen(name); } else - name = NULL; + name = iname; + + if (0 == namesz && ROFF_ig != tok) { + mandoc_msg(MANDOCERR_REQ_EMPTY, r->parse, + ln, ppos, roffs[tok].name); + return(ROFF_IGN); + } roffnode_push(r, tok, name, ln, ppos); @@ -956,16 +968,30 @@ roff_block(ROFF_ARGS) * appended from roff_block_text() in multiline mode. */ - if (namesz && ROFF_de == tok) + if (ROFF_de == tok || ROFF_dei == tok) roff_setstrn(&r->strtab, name, namesz, "", 0, 0); if ('\0' == *cp) return(ROFF_IGN); - /* If present, process the custom end-of-line marker. */ + /* Get the custom end marker. */ - name = cp; + iname = cp; namesz = roff_getname(r, &cp, ln, ppos); + + /* Resolve the end marker if it is indirect. */ + + if (namesz && (ROFF_dei == tok || ROFF_ami == tok)) { + if (NULL == (name = roff_getstrn(r, iname, namesz))) { + mandoc_vmsg(MANDOCERR_STR_UNDEF, + r->parse, ln, (int)(iname - *bufp), + "%.*s", (int)namesz, iname); + namesz = 0; + } else + namesz = strlen(name); + } else + name = iname; + if (namesz) r->last->end = mandoc_strndup(name, namesz); @@ -1020,12 +1046,8 @@ roff_block_sub(ROFF_ARGS) t = roff_parse(r, *bufp, &pos, ln, ppos); - /* - * Macros other than block-end are only significant - * in `de' blocks; elsewhere, simply throw them away. - */ if (ROFF_cblock != t) { - if (ROFF_de == tok) + if (ROFF_ig != tok) roff_setstr(r, r->last->name, *bufp + ppos, 2); return(ROFF_IGN); } @@ -1038,7 +1060,7 @@ static enum rofferr roff_block_text(ROFF_ARGS) { - if (ROFF_de == tok) + if (ROFF_ig != tok) roff_setstr(r, r->last->name, *bufp + pos, 2); return(ROFF_IGN); |