diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2022-05-31 20:23:05 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2022-05-31 20:23:05 +0000 |
commit | 91d4baecc6f10b6b8b7119f78bfec0721659961d (patch) | |
tree | b0f0dc2950dbc8a97fcef44482127a53fc2e8cc8 /roff_escape.c | |
parent | afaba3e78072edb0c5149a491c9709b57f31745a (diff) | |
download | mandoc-91d4baecc6f10b6b8b7119f78bfec0721659961d.tar.gz |
Rudimentary implementation of the \A escape sequence, following groff
semantics (test identifier for syntactical validity), not at all
following the completely unrelated Heirloom semantics (define
hyperlink target position).
The main motivation for providing this implementation is to get \A
into the parsing class ESCAPE_EXPAND that corresponds to groff parsing
behaviour, which is quite similar to the \B escape sequence (test
numerical expression for syntactical validity). This is likely
to improve parsing of nested escape sequences in the future.
Validation isn't perfect yet. In particular, this implementation
rejects \A arguments containing some escape sequences that groff
allows to slip through. But that is unlikely to cause trouble even
in documents using \A for non-trivial purposes. Rejecting the nested
escapes in question might even improve robustnest because the rejected
names are unlikely to really be usable for practical purposes - no
matter that groff dubiously considers them syntactically valid.
Diffstat (limited to 'roff_escape.c')
-rw-r--r-- | roff_escape.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/roff_escape.c b/roff_escape.c index 3c38ced7..20e5267a 100644 --- a/roff_escape.c +++ b/roff_escape.c @@ -73,6 +73,7 @@ roff_escape(const char *buf, const int ln, const int aesc, int maxl; /* expected length of the argument */ int argl; /* actual length of the argument */ int c, i; /* for \[char...] parsing */ + int valid_A; /* for \A parsing */ enum mandoc_esc rval; /* return value */ enum mandocerr err; /* diagnostic code */ char esc_name; @@ -181,12 +182,12 @@ roff_escape(const char *buf, const int ln, const int aesc, /* Quoted arguments */ + case 'A': case 'B': case 'w': rval = ESCAPE_EXPAND; term = '\b'; break; - case 'A': case 'D': case 'H': case 'L': @@ -301,6 +302,7 @@ roff_escape(const char *buf, const int ln, const int aesc, /* Advance to the end of the argument. */ + valid_A = 1; iendarg = iarg; while (maxl > 0) { if (buf[iendarg] == '\0') { @@ -319,11 +321,20 @@ roff_escape(const char *buf, const int ln, const int aesc, break; } if (buf[iendarg] == buf[iesc]) { - if (roff_escape(buf, ln, iendarg, - &sesc, &sarg, &sendarg, &send) == ESCAPE_EXPAND) + switch (roff_escape(buf, ln, iendarg, + &sesc, &sarg, &sendarg, &send)) { + case ESCAPE_EXPAND: goto out_sub; + case ESCAPE_UNDEF: + break; + default: + valid_A = 0; + break; + } iendarg = iend = send; } else { + if (buf[iendarg] == ' ' || buf[iendarg] == '\t') + valid_A = 0; if (maxl != INT_MAX) maxl--; iend = ++iendarg; @@ -342,6 +353,10 @@ roff_escape(const char *buf, const int ln, const int aesc, buf[iarg] == '.' && buf[iarg + 1] == 'T') rval = ESCAPE_DEVICE; break; + case 'A': + if (valid_A == 0) + iendarg = iarg; + break; case 'O': switch (buf[iarg]) { case '0': |