summaryrefslogtreecommitdiff
path: root/usr.bin/mandoc/roff.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/mandoc/roff.c')
-rw-r--r--usr.bin/mandoc/roff.c97
1 files changed, 66 insertions, 31 deletions
diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c
index 1169b559bad..b20c3a98d9d 100644
--- a/usr.bin/mandoc/roff.c
+++ b/usr.bin/mandoc/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.4 2010/06/06 20:30:08 schwarze Exp $ */
+/* $Id: roff.c,v 1.5 2010/06/26 17:56:43 schwarze Exp $ */
/*
* Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -103,6 +103,7 @@ static enum rofferr roff_ccond(ROFF_ARGS);
static enum rofferr roff_cond(ROFF_ARGS);
static enum rofferr roff_cond_text(ROFF_ARGS);
static enum rofferr roff_cond_sub(ROFF_ARGS);
+static enum roffrule roff_evalcond(const char *, int *);
static enum rofferr roff_line(ROFF_ARGS);
/* See roff_hash_find() */
@@ -621,11 +622,21 @@ roff_cond_sub(ROFF_ARGS)
{
enum rofft t;
enum roffrule rr;
+ struct roffnode *l;
ppos = pos;
rr = r->last->rule;
- roff_cond_text(r, tok, bufp, szp, ln, ppos, pos, offs);
+ /*
+ * 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);
@@ -674,12 +685,37 @@ roff_cond_text(ROFF_ARGS)
}
+static enum roffrule
+roff_evalcond(const char *v, int *pos)
+{
+
+ switch (v[*pos]) {
+ case ('n'):
+ (*pos)++;
+ return(ROFFRULE_ALLOW);
+ case ('e'):
+ /* FALLTHROUGH */
+ case ('o'):
+ /* FALLTHROUGH */
+ case ('t'):
+ (*pos)++;
+ return(ROFFRULE_DENY);
+ default:
+ break;
+ }
+
+ while (v[*pos] && ' ' != v[*pos])
+ (*pos)++;
+ return(ROFFRULE_DENY);
+}
+
+
/* ARGSUSED */
static enum rofferr
roff_cond(ROFF_ARGS)
{
- int cpos; /* position of the condition */
int sv;
+ enum roffrule rule;
/* Stack overflow! */
@@ -688,20 +724,22 @@ roff_cond(ROFF_ARGS)
return(ROFF_ERR);
}
- cpos = pos;
+ /* First, evaluate the conditional. */
- if (ROFF_if == tok || ROFF_ie == tok) {
- /*
- * Read ahead past the conditional. FIXME: this does
- * not work, as conditionals don't end on whitespace,
- * but are parsed according to a formal grammar. It's
- * good enough for now, however.
- */
- while ((*bufp)[pos] && ' ' != (*bufp)[pos])
- pos++;
- }
+ if (ROFF_el == tok) {
+ /*
+ * An `.el' will get the value of the current rstack
+ * entry set in prior `ie' calls or defaults to DENY.
+ */
+ if (r->rstackpos < 0)
+ rule = ROFFRULE_DENY;
+ else
+ rule = r->rstack[r->rstackpos];
+ } else
+ rule = roff_evalcond(*bufp, &pos);
sv = pos;
+
while (' ' == (*bufp)[pos])
pos++;
@@ -711,30 +749,18 @@ roff_cond(ROFF_ARGS)
* really doing anything. Warn about this. It's probably
* wrong.
*/
+
if ('\0' == (*bufp)[pos] && sv != pos) {
- if ( ! (*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL))
- return(ROFF_ERR);
- return(ROFF_IGN);
+ if ((*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL))
+ return(ROFF_IGN);
+ return(ROFF_ERR);
}
if ( ! roffnode_push(r, tok, ln, ppos))
return(ROFF_ERR);
- /* XXX: Implement more conditionals. */
+ r->last->rule = rule;
- if (ROFF_if == tok || ROFF_ie == tok)
- r->last->rule = 'n' == (*bufp)[cpos] ?
- ROFFRULE_ALLOW : ROFFRULE_DENY;
- else if (ROFF_el == tok) {
- /*
- * An `.el' will get the value of the current rstack
- * entry set in prior `ie' calls or defaults to DENY.
- */
- if (r->rstackpos < 0)
- r->last->rule = ROFFRULE_DENY;
- else
- r->last->rule = r->rstack[r->rstackpos];
- }
if (ROFF_ie == tok) {
/*
* An if-else will put the NEGATION of the current
@@ -746,9 +772,18 @@ roff_cond(ROFF_ARGS)
else
r->rstack[r->rstackpos] = ROFFRULE_DENY;
}
+
+ /* If the parent has false as its rule, then so do we. */
+
if (r->last->parent && ROFFRULE_DENY == r->last->parent->rule)
r->last->rule = ROFFRULE_DENY;
+ /*
+ * Determine scope. If we're invoked with "\{" trailing the
+ * conditional, then we're in a multiline scope. Else our scope
+ * expires on the next line.
+ */
+
r->last->endspan = 1;
if ('\\' == (*bufp)[pos] && '{' == (*bufp)[pos + 1]) {