summaryrefslogtreecommitdiffstats
path: root/roff.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2013-06-27 09:49:47 +0000
committerIngo Schwarze <schwarze@openbsd.org>2013-06-27 09:49:47 +0000
commiteebb002141cb3a6a6a79df4159c6abb60b31df73 (patch)
tree51d48de842bf8c0047eaaf3435725625050a1984 /roff.c
parente8f3a9957341ce61806ce723cc23210b1d74961c (diff)
downloadmandoc-eebb002141cb3a6a6a79df4159c6abb60b31df73.tar.gz
Parse for the closing delimiter `\}' for conditionals
even when the conditional evaluated to false. While here, reshuffle the code to reduce indentation and make it more readable; that way, we can even trim down the comments because it becomes obvious what the code does. Found in zipinfo(1) - thanks to espie@ and naddy@ for making me look at that manual page.
Diffstat (limited to 'roff.c')
-rw-r--r--roff.c74
1 files changed, 31 insertions, 43 deletions
diff --git a/roff.c b/roff.c
index 38a3eaf5..d48668ab 100644
--- a/roff.c
+++ b/roff.c
@@ -1,7 +1,7 @@
/* $Id$ */
/*
* Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2011, 2012 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -1028,57 +1028,45 @@ roff_cond_sub(ROFF_ARGS)
rr = r->last->rule;
roffnode_cleanscope(r);
+ t = roff_parse(r, *bufp, &pos);
/*
- * 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.
+ * Fully handle known macros when they are structurally
+ * required or when the conditional evaluated to true.
*/
- 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 ((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));
+ }
- if ('\0' == *(ep + 1)) {
- *--ep = '\0';
- *szp -= 2;
- } else
- *(ep - 1) = *ep = ' ';
+ /* Always check for the closing delimiter `\}'. */
- roff_ccond(r, ROFF_ccond, bufp, szp,
- ln, pos, pos + 2, offs);
- break;
- }
- return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
- }
+ ep = &(*bufp)[pos];
+ while (NULL != (ep = strchr(ep, '\\'))) {
+ if ('}' != *(++ep))
+ continue;
- /*
- * 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 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 (ROFFRULE_DENY == rr)
- if ( ! (ROFFMAC_STRUCT & roffs[t].flags))
- if (ROFF_ccond != t)
- return(ROFF_IGN);
+ if ('\0' == *(ep + 1)) {
+ *--ep = '\0';
+ *szp -= 2;
+ } else
+ *(ep - 1) = *ep = ' ';
- assert(roffs[t].proc);
- return((*roffs[t].proc)(r, t, bufp, szp,
- ln, ppos, pos, offs));
+ roff_ccond(r, ROFF_ccond, bufp, szp,
+ ln, pos, pos + 2, offs);
+ break;
+ }
+ return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
}
/* ARGSUSED */