summaryrefslogtreecommitdiffstats
path: root/roff.c
diff options
context:
space:
mode:
Diffstat (limited to 'roff.c')
-rw-r--r--roff.c86
1 files changed, 54 insertions, 32 deletions
diff --git a/roff.c b/roff.c
index d8d59fa5..8153b69e 100644
--- a/roff.c
+++ b/roff.c
@@ -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);