From: schwarze@mandoc.bsd.lv
To: source@mandoc.bsd.lv
Subject: mandoc: Add an additional argument to the functions implementing the
Date: Sun, 5 Jan 2025 16:58:52 +0000 (UTC) [thread overview]
Message-ID: <95009fa137dccb29@mandoc.bsd.lv> (raw)
Log Message:
-----------
Add an additional argument to the functions implementing the roff(7)
numerical parser to select the default scaling unit for numbers not
followed by a scaling unit, rather than always using basic units ('u').
Expose roff_evalnum() via the internal parser API such that, in addition
to the roff(7) parser, other parsers become able to parse numerical
expressions, too.
This commit implies no functional change yet,
but prepares for adding new functionality in future commits.
Modified Files:
--------------
mandoc:
libmandoc.h
roff.c
Revision Data
-------------
Index: roff.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/roff.c,v
diff -Lroff.c -Lroff.c -u -p -r1.402 -r1.403
--- roff.c
+++ roff.c
@@ -1,6 +1,6 @@
/* $Id$ */
/*
- * Copyright (c) 2010-2015, 2017-2024 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2015, 2017-2025 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -192,8 +192,8 @@ static int roff_ec(ROFF_ARGS);
static int roff_eo(ROFF_ARGS);
static int roff_eqndelim(struct roff *, struct buf *, int);
static int roff_evalcond(struct roff *, int, char *, int *);
-static int roff_evalnum(int, const char *, int *, int *, int);
-static int roff_evalpar(int, const char *, int *, int *, int);
+static int roff_evalpar(int, const char *, int *, int *,
+ char, int);
static int roff_evalstrcond(const char *, int *);
static int roff_expand(struct roff *, struct buf *,
int, int, char);
@@ -203,7 +203,7 @@ static void roff_free1(struct roff *);
static void roff_freereg(struct roffreg *);
static void roff_freestr(struct roffkv *);
static size_t roff_getname(char **, int, int);
-static int roff_getnum(const char *, int *, int *, int);
+static int roff_getnum(const char *, int *, int *, char, int);
static int roff_getop(const char *, int *, char *);
static int roff_getregn(struct roff *,
const char *, size_t, char);
@@ -256,9 +256,6 @@ static int roff_userdef(ROFF_ARGS);
/* --- constant data ------------------------------------------------------ */
-#define ROFFNUM_SCALE (1 << 0) /* Honour scaling in roff_getnum(). */
-#define ROFFNUM_WHITE (1 << 1) /* Skip whitespace in roff_evalnum(). */
-
const char *__roff_name[MAN_MAX + 1] = {
"br", "ce", "fi", "ft",
"ll", "mc", "nf",
@@ -1528,7 +1525,7 @@ roff_expand(struct roff *r, struct buf *
npos = 0;
ubuf[0] = iendarg > iarg && iend > iendarg &&
roff_evalnum(ln, buf->buf + iarg, &npos,
- NULL, ROFFNUM_SCALE) &&
+ NULL, 'u', 0) &&
npos == iendarg - iarg ? '1' : '0';
ubuf[1] = '\0';
res = ubuf;
@@ -2431,9 +2428,9 @@ roff_cond_text(ROFF_ARGS)
* Ignore overflows, treat them just like the C language.
*/
static int
-roff_getnum(const char *v, int *pos, int *res, int flags)
+roff_getnum(const char *v, int *pos, int *res, char unit, int skipspace)
{
- int myres, scaled, n, p;
+ int myres, n, p;
if (NULL == res)
res = &myres;
@@ -2443,7 +2440,7 @@ roff_getnum(const char *v, int *pos, int
if (n || v[p] == '+')
p++;
- if (flags & ROFFNUM_WHITE)
+ if (skipspace)
while (isspace((unsigned char)v[p]))
p++;
@@ -2457,42 +2454,45 @@ roff_getnum(const char *v, int *pos, int
/* Each number may be followed by one optional scaling unit. */
- switch (v[p]) {
+ if (v[p] != '\0' && strchr("ficvPmnpuM", v[p]) != NULL) {
+ if (unit != '\0')
+ unit = v[p];
+ p++;
+ }
+
+ switch (unit) {
case 'f':
- scaled = *res * 65536;
+ *res *= 65536;
break;
case 'i':
- scaled = *res * 240;
+ *res *= 240;
break;
case 'c':
- scaled = *res * 240 / 2.54;
+ *res *= 24000;
+ *res /= 254;
break;
case 'v':
case 'P':
- scaled = *res * 40;
+ *res *= 40;
break;
case 'm':
case 'n':
- scaled = *res * 24;
+ *res *= 24;
break;
case 'p':
- scaled = *res * 10 / 3;
+ *res *= 10;
+ *res /= 3;
break;
case 'u':
- scaled = *res;
break;
case 'M':
- scaled = *res * 6 / 25;
+ *res *= 6;
+ *res /= 25;
break;
default:
- scaled = *res;
- p--;
break;
}
- if (flags & ROFFNUM_SCALE)
- *res = scaled;
-
- *pos = p + 1;
+ *pos = p;
return 1;
}
@@ -2631,7 +2631,7 @@ roff_evalcond(struct roff *r, int ln, ch
}
savepos = *pos;
- if (roff_evalnum(ln, v, pos, &number, ROFFNUM_SCALE))
+ if (roff_evalnum(ln, v, pos, &number, 'u', 0))
return (number > 0) == wanttrue;
else if (*pos == savepos)
return roff_evalstrcond(v, pos) == wanttrue;
@@ -2860,14 +2860,15 @@ roff_getop(const char *v, int *pos, char
* or a single signed integer number.
*/
static int
-roff_evalpar(int ln, const char *v, int *pos, int *res, int flags)
+roff_evalpar(int ln, const char *v, int *pos, int *res, char unit,
+ int skipspace)
{
if ('(' != v[*pos])
- return roff_getnum(v, pos, res, flags);
+ return roff_getnum(v, pos, res, unit, skipspace);
(*pos)++;
- if ( ! roff_evalnum(ln, v, pos, res, flags | ROFFNUM_WHITE))
+ if ( ! roff_evalnum(ln, v, pos, res, unit, 1))
return 0;
/*
@@ -2888,8 +2889,9 @@ roff_evalpar(int ln, const char *v, int
* Evaluate a complete numeric expression.
* Proceed left to right, there is no concept of precedence.
*/
-static int
-roff_evalnum(int ln, const char *v, int *pos, int *res, int flags)
+int
+roff_evalnum(int ln, const char *v, int *pos, int *res, char unit,
+ int skipspace)
{
int mypos, operand2;
char operator;
@@ -2899,29 +2901,29 @@ roff_evalnum(int ln, const char *v, int
pos = &mypos;
}
- if (flags & ROFFNUM_WHITE)
+ if (skipspace)
while (isspace((unsigned char)v[*pos]))
(*pos)++;
- if ( ! roff_evalpar(ln, v, pos, res, flags))
+ if ( ! roff_evalpar(ln, v, pos, res, unit, skipspace))
return 0;
while (1) {
- if (flags & ROFFNUM_WHITE)
+ if (skipspace)
while (isspace((unsigned char)v[*pos]))
(*pos)++;
if ( ! roff_getop(v, pos, &operator))
break;
- if (flags & ROFFNUM_WHITE)
+ if (skipspace)
while (isspace((unsigned char)v[*pos]))
(*pos)++;
- if ( ! roff_evalpar(ln, v, pos, &operand2, flags))
+ if ( ! roff_evalpar(ln, v, pos, &operand2, unit, skipspace))
return 0;
- if (flags & ROFFNUM_WHITE)
+ if (skipspace)
while (isspace((unsigned char)v[*pos]))
(*pos)++;
@@ -3162,13 +3164,13 @@ roff_nr(ROFF_ARGS)
val++;
len = 0;
- if (roff_evalnum(ln, val, &len, &iv, ROFFNUM_SCALE) == 0)
+ if (roff_evalnum(ln, val, &len, &iv, 'u', 0) == 0)
return ROFF_IGN;
step = val + len;
while (isspace((unsigned char)*step))
step++;
- if (roff_evalnum(ln, step, NULL, &is, 0) == 0)
+ if (roff_evalnum(ln, step, NULL, &is, '\0', 0) == 0)
is = INT_MIN;
roff_setregn(r, key, keysz, iv, sign, is);
@@ -3231,7 +3233,7 @@ roff_it(ROFF_ARGS)
/* Parse the number of lines. */
- if ( ! roff_evalnum(ln, buf->buf, &pos, &iv, 0)) {
+ if ( ! roff_evalnum(ln, buf->buf, &pos, &iv, '\0', 0)) {
mandoc_msg(MANDOCERR_IT_NONUM,
ln, ppos, "%s", buf->buf + 1);
return ROFF_IGN;
@@ -3499,7 +3501,7 @@ roff_onearg(ROFF_ARGS)
}
npos = 0;
if (roff_evalnum(ln, r->man->last->string, &npos,
- &roffce_lines, 0) == 0) {
+ &roffce_lines, '\0', 0) == 0) {
mandoc_msg(MANDOCERR_CE_NONUM,
ln, pos, "ce %s", buf->buf + pos);
roffce_lines = 1;
@@ -3881,7 +3883,7 @@ roff_shift(ROFF_ARGS)
argpos = pos;
levels = 1;
if (buf->buf[pos] != '\0' &&
- roff_evalnum(ln, buf->buf, &pos, &levels, 0) == 0) {
+ roff_evalnum(ln, buf->buf, &pos, &levels, '\0', 0) == 0) {
mandoc_msg(MANDOCERR_CE_NONUM,
ln, pos, "shift %s", buf->buf + pos);
levels = 1;
Index: libmandoc.h
===================================================================
RCS file: /home/cvs/mandoc/mandoc/libmandoc.h,v
diff -Llibmandoc.h -Llibmandoc.h -u -p -r1.80 -r1.81
--- libmandoc.h
+++ libmandoc.h
@@ -78,6 +78,7 @@ void roff_userret(struct roff *);
void roff_endparse(struct roff *);
void roff_setreg(struct roff *, const char *, int, char);
int roff_getreg(struct roff *, const char *);
+int roff_evalnum(int, const char *, int *, int *, char, int);
char *roff_strdup(const struct roff *, const char *);
char *roff_getarg(struct roff *, char **, int, int *);
int roff_getcontrol(const struct roff *,
--
To unsubscribe send an email to source+unsubscribe@mandoc.bsd.lv
reply other threads:[~2025-01-05 16:58 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=95009fa137dccb29@mandoc.bsd.lv \
--to=schwarze@mandoc.bsd.lv \
--cc=source@mandoc.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).