From: schwarze@mdocml.bsd.lv
To: source@mdocml.bsd.lv
Subject: mdocml: Fully implement the \B (validate numerical expression) and
Date: Mon, 7 Apr 2014 21:37:27 -0400 (EDT) [thread overview]
Message-ID: <201404080137.s381bRap031185@krisdoz.my.domain> (raw)
Log Message:
-----------
Fully implement the \B (validate numerical expression) and
partially implement the \w (measure text width) escape sequence
in a way that makes them usable in numerical expressions and in
conditional requests, similar to how \n (interpolate number register)
and \* (expand user-defined string) are implemented.
This lets mandoc(1) handle the baroque low-level roff code
found at the beginning of the ggrep(1) manual.
Thanks to pascal@ for the report.
Modified Files:
--------------
mdocml:
mandoc.c
roff.7
roff.c
Revision Data
-------------
Index: mandoc.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mandoc.c,v
retrieving revision 1.77
retrieving revision 1.78
diff -Lmandoc.c -Lmandoc.c -u -p -r1.77 -r1.78
--- mandoc.c
+++ mandoc.c
@@ -1,7 +1,7 @@
/* $Id$ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011, 2012, 2013, 2014 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
@@ -161,20 +161,17 @@ mandoc_escape(const char **end, const ch
/*
* These escapes are of the form \X'Y', where 'X' is the trigger
* and 'Y' is any string. These have opaque sub-strings.
+ * The \B and \w escapes are handled in roff.c, roff_res().
*/
case ('A'):
/* FALLTHROUGH */
case ('b'):
/* FALLTHROUGH */
- case ('B'):
- /* FALLTHROUGH */
case ('D'):
/* FALLTHROUGH */
case ('o'):
/* FALLTHROUGH */
case ('R'):
- /* FALLTHROUGH */
- case ('w'):
/* FALLTHROUGH */
case ('X'):
/* FALLTHROUGH */
Index: roff.7
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/roff.7,v
retrieving revision 1.53
retrieving revision 1.54
diff -Lroff.7 -Lroff.7 -u -p -r1.53 -r1.54
--- roff.7
+++ roff.7
@@ -1172,10 +1172,15 @@ Digit width space character.
Anchor definition; ignored by
.Xr mandoc 1 .
.Ss \eB\(aq Ns Ar string Ns \(aq
-Test whether
+Interpolate
+.Sq 1
+if
.Ar string
-is a numerical expession; ignored by
-.Xr mandoc 1 .
+conforms to the syntax of
+.Sx Numerical expressions
+explained above and
+.Sq 0
+otherwise.
.Ss \eb\(aq Ns Ar string Ns \(aq
Bracket building function; ignored by
.Xr mandoc 1 .
@@ -1299,9 +1304,13 @@ Vertical motion; ignored by
.Xr mandoc 1 .
.Ss \ew\(aq Ns Ar string Ns \(aq
Interpolate the width of the
-.Ar string ;
-ignored by
-.Xr mandoc 1 .
+.Ar string .
+The
+.Xr mandoc 1
+implementation assumes that after expansion of user-defined strings, the
+.Ar string
+only contains normal characters, no escape sequences, and that each
+character has a width of 24 basic units.
.Ss \eX\(aq Ns Ar string Ns \(aq
Output
.Ar string
Index: roff.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/roff.c,v
retrieving revision 1.205
retrieving revision 1.206
diff -Lroff.c -Lroff.c -u -p -r1.205 -r1.206
--- roff.c
+++ roff.c
@@ -485,9 +485,9 @@ roff_alloc(struct mparse *parse, int opt
}
/*
- * In the current line, expand user-defined strings ("\*")
- * and references to number registers ("\n").
- * Also check the syntax of other escape sequences.
+ * In the current line, expand escape sequences that tend to get
+ * used in numerical expressions and conditional requests.
+ * Also check the syntax of the remaining escape sequences.
*/
static enum rofferr
roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
@@ -503,6 +503,9 @@ roff_res(struct roff *r, char **bufp, si
size_t naml; /* actual length of the escape name */
size_t ressz; /* size of the replacement string */
int expand_count; /* to avoid infinite loops */
+ int npos; /* position in numeric expression */
+ int irc; /* return code from roff_evalnum() */
+ char term; /* character terminating the escape */
expand_count = 0;
start = *bufp + pos;
@@ -525,16 +528,19 @@ roff_res(struct roff *r, char **bufp, si
continue;
}
- /*
- * Everything except user-defined strings and number
- * registers is only checked, not expanded.
- */
+ /* Decide whether to expand or to check only. */
+ term = '\0';
cp = stesc + 1;
switch (*cp) {
case ('*'):
res = NULL;
break;
+ case ('B'):
+ /* FALLTHROUGH */
+ case ('w'):
+ term = cp[1];
+ /* FALLTHROUGH */
case ('n'):
res = ubuf;
break;
@@ -557,20 +563,27 @@ roff_res(struct roff *r, char **bufp, si
* Save a pointer to the name.
*/
- switch (*++cp) {
- case ('\0'):
- continue;
- case ('('):
- cp++;
- maxl = 2;
- break;
- case ('['):
- cp++;
+ if ('\0' == term) {
+ switch (*++cp) {
+ case ('\0'):
+ maxl = 0;
+ break;
+ case ('('):
+ cp++;
+ maxl = 2;
+ break;
+ case ('['):
+ cp++;
+ term = ']';
+ maxl = 0;
+ break;
+ default:
+ maxl = 1;
+ break;
+ }
+ } else {
+ cp += 2;
maxl = 0;
- break;
- default:
- maxl = 1;
- break;
}
stnam = cp;
@@ -582,10 +595,12 @@ roff_res(struct roff *r, char **bufp, si
(MANDOCERR_BADESCAPE,
r->parse, ln,
(int)(stesc - *bufp), NULL);
- continue;
+ break;
}
- if (0 == maxl && ']' == *cp)
+ if (0 == maxl && *cp == term) {
+ cp++;
break;
+ }
}
/*
@@ -593,11 +608,26 @@ roff_res(struct roff *r, char **bufp, si
* undefined, resume searching for escapes.
*/
- if (NULL == res)
+ switch (stesc[1]) {
+ case ('*'):
res = roff_getstrn(r, stnam, naml);
- else
+ break;
+ case ('B'):
+ npos = 0;
+ irc = roff_evalnum(stnam, &npos, NULL, 0);
+ ubuf[0] = irc && stnam + npos + 1 == cp
+ ? '1' : '0';
+ ubuf[1] = '\0';
+ break;
+ case ('n'):
snprintf(ubuf, sizeof(ubuf), "%d",
roff_getregn(r, stnam, naml));
+ break;
+ case ('w'):
+ snprintf(ubuf, sizeof(ubuf), "%d",
+ 24 * (int)naml);
+ break;
+ }
if (NULL == res) {
mandoc_msg
@@ -614,7 +644,7 @@ roff_res(struct roff *r, char **bufp, si
strlcpy(nbuf, *bufp, (size_t)(stesc - *bufp + 1));
strlcat(nbuf, res, *szp);
- strlcat(nbuf, cp + (maxl ? 0 : 1), *szp);
+ strlcat(nbuf, cp, *szp);
/* Prepare for the next replacement. */
@@ -1126,7 +1156,10 @@ roff_cond_text(ROFF_ARGS)
static int
roff_getnum(const char *v, int *pos, int *res)
{
- int p, n;
+ int myres, n, p;
+
+ if (NULL == res)
+ res = &myres;
p = *pos;
n = v[p] == '-';
@@ -1430,9 +1463,16 @@ roff_evalpar(const char *v, int *pos, in
if ( ! roff_evalnum(v, pos, res, 1))
return(0);
- /* If the trailing parenthesis is missing, ignore the error. */
+ /*
+ * Omission of the closing parenthesis
+ * is an error in validation mode,
+ * but ignored in evaluation mode.
+ */
+
if (')' == v[*pos])
(*pos)++;
+ else if (NULL == res)
+ return(0);
return(1);
}
@@ -1477,6 +1517,9 @@ roff_evalnum(const char *v, int *pos, in
if (skipwhite)
while (isspace((unsigned char)v[*pos]))
(*pos)++;
+
+ if (NULL == res)
+ continue;
switch (operator) {
case ('+'):
--
To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv
reply other threads:[~2014-04-08 1:37 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201404080137.s381bRap031185@krisdoz.my.domain \
--to=schwarze@mdocml.bsd.lv \
--cc=source@mdocml.bsd.lv \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).