diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2018-08-19 17:43:40 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2018-08-19 17:43:40 +0000 |
commit | 084dacb8b29a3ef4d1659c3868884fcc3f679647 (patch) | |
tree | 57d87b184e4d41996d61f061bbc02ab71ac721e0 /usr.bin/mandoc/roff.c | |
parent | e77538779a0aca1191145424c658e42ef8a83e1b (diff) |
Mostly complete implementation of the 'c' (character available)
roff conditional, except that the .char request still isn't supported
and that behaviour differs from groff in many edge cases.
But at least valid character names and numbers are now distinguished
from invalid ones.
This also fixes the bug that parsing of the 'c' conditional was
incomplete, which resulted in leaking the tested character to the
input parser at the beginning of the body when the condition was
inverted.
Diffstat (limited to 'usr.bin/mandoc/roff.c')
-rw-r--r-- | usr.bin/mandoc/roff.c | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c index b889e9f4a91..c085475e901 100644 --- a/usr.bin/mandoc/roff.c +++ b/usr.bin/mandoc/roff.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roff.c,v 1.207 2018/08/18 22:04:32 schwarze Exp $ */ +/* $OpenBSD: roff.c,v 1.208 2018/08/19 17:43:39 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org> @@ -2166,9 +2166,10 @@ out: static int roff_evalcond(struct roff *r, int ln, char *v, int *pos) { - char *cp, *name; - size_t sz; - int deftype, number, savepos, istrue, wanttrue; + const char *start, *end; + char *cp, *name; + size_t sz; + int deftype, len, number, savepos, istrue, wanttrue; if ('!' == v[*pos]) { wanttrue = 0; @@ -2183,12 +2184,50 @@ roff_evalcond(struct roff *r, int ln, char *v, int *pos) case 'o': (*pos)++; return wanttrue; - case 'c': case 'e': case 't': case 'v': (*pos)++; return !wanttrue; + case 'c': + do { + (*pos)++; + } while (v[*pos] == ' '); + + /* + * Quirk for groff compatibility: + * The horizontal tab is neither available nor unavailable. + */ + + if (v[*pos] == '\t') { + (*pos)++; + return 0; + } + + /* Printable ASCII characters are available. */ + + if (v[*pos] != '\\') { + (*pos)++; + return wanttrue; + } + + end = v + ++*pos; + switch (mandoc_escape(&end, &start, &len)) { + case ESCAPE_SPECIAL: + istrue = mchars_spec2cp(start, len) != -1; + break; + case ESCAPE_UNICODE: + istrue = 1; + break; + case ESCAPE_NUMBERED: + istrue = mchars_num2char(start, len) != -1; + break; + default: + istrue = !wanttrue; + break; + } + *pos = end - v; + return istrue == wanttrue; case 'd': case 'r': cp = v + *pos + 1; |