From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from krisdoz.my.domain (schwarze@localhost [127.0.0.1]) by krisdoz.my.domain (8.14.5/8.14.5) with ESMTP id s381bRAq001113 for ; Mon, 7 Apr 2014 21:37:27 -0400 (EDT) Received: (from schwarze@localhost) by krisdoz.my.domain (8.14.5/8.14.3/Submit) id s381bRap031185; Mon, 7 Apr 2014 21:37:27 -0400 (EDT) Date: Mon, 7 Apr 2014 21:37:27 -0400 (EDT) Message-Id: <201404080137.s381bRap031185@krisdoz.my.domain> X-Mailinglist: mdocml-source Reply-To: source@mdocml.bsd.lv MIME-Version: 1.0 From: schwarze@mdocml.bsd.lv To: source@mdocml.bsd.lv Subject: mdocml: Fully implement the \B (validate numerical expression) and X-Mailer: activitymail 1.26, http://search.cpan.org/dist/activitymail/ Content-Type: text/plain; charset=utf-8 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 - * Copyright (c) 2011, 2012, 2013 Ingo Schwarze + * Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze * * 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