source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mandoc: Add an additional argument to the functions implementing the
@ 2025-01-05 16:58 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2025-01-05 16:58 UTC (permalink / raw)
  To: source

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


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2025-01-05 16:58 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-01-05 16:58 mandoc: Add an additional argument to the functions implementing the schwarze

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).