Thu Jan 24 10:41:29 2013 UTC ()
Move the strings vs long analysis to a private function, but allow
tput(1) to use it so we can work with string parameters to capabilities.


(roy)
diff -r1.10 -r1.11 src/lib/libterminfo/term_private.h
diff -r1.11 -r1.12 src/lib/libterminfo/tparm.c
diff -r1.10 -r1.11 src/usr.bin/tput/Makefile
diff -r1.22 -r1.23 src/usr.bin/tput/tput.c

cvs diff -r1.10 -r1.11 src/lib/libterminfo/term_private.h (expand / switch to context diff)
--- src/lib/libterminfo/term_private.h 2012/06/03 23:19:10 1.10
+++ src/lib/libterminfo/term_private.h 2013/01/24 10:41:28 1.11
@@ -1,7 +1,7 @@
-/* $NetBSD: term_private.h,v 1.10 2012/06/03 23:19:10 joerg Exp $ */
+/* $NetBSD: term_private.h,v 1.11 2013/01/24 10:41:28 roy Exp $ */
 
 /*
- * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009, 2010, 2013 The NetBSD Foundation, Inc.
  *
  * This code is derived from software contributed to The NetBSD Foundation
  * by Roy Marples.
@@ -157,4 +157,7 @@
 TIC *_ti_compile(char *, int);
 ssize_t _ti_flatten(uint8_t **, const TIC *);
 void _ti_freetic(TIC *);
+
+#define TPARM_MAX 9	/* not likely to change */
+int _ti_parm_analyse(const char *, int *, int);
 #endif

cvs diff -r1.11 -r1.12 src/lib/libterminfo/tparm.c (expand / switch to context diff)
--- src/lib/libterminfo/tparm.c 2013/01/24 10:28:28 1.11
+++ src/lib/libterminfo/tparm.c 2013/01/24 10:41:28 1.12
@@ -1,7 +1,7 @@
-/* $NetBSD: tparm.c,v 1.11 2013/01/24 10:28:28 roy Exp $ */
+/* $NetBSD: tparm.c,v 1.12 2013/01/24 10:41:28 roy Exp $ */
 
 /*
- * Copyright (c) 2009, 2011 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009, 2011, 2013 The NetBSD Foundation, Inc.
  *
  * This code is derived from software contributed to The NetBSD Foundation
  * by Roy Marples.
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: tparm.c,v 1.11 2013/01/24 10:28:28 roy Exp $");
+__RCSID("$NetBSD: tparm.c,v 1.12 2013/01/24 10:41:28 roy Exp $");
 #include <sys/param.h>
 
 #include <assert.h>
@@ -42,7 +42,7 @@
 #include <term.h>
 
 #define LONG_STR_MAX ((CHAR_BIT * sizeof(long)) / 3)
-#define BUFINC 128 /* Size to increament the terminal buffer by */
+#define BUFINC 128	/* Size to increament the terminal buffer by */
 
 static TERMINAL *dumbterm; /* For non thread safe functions */
 
@@ -131,18 +131,63 @@
 	return l;
 }
 
+/*
+  Make a pass through the string so we can work out
+  which parameters are ints and which are char *.
+  Basically we only use char * if %p[1-9] is followed by %l or %s.
+*/
+int
+_ti_parm_analyse(const char *str, int *piss, int piss_len)
+{
+	int nparm, lpop;
+	char c;
+
+	nparm = 0;
+	lpop = -1;
+	while ((c = *str++) != '\0') {
+		if (c != '%')
+			continue;
+		c = *str++;
+		switch (c) {
+			case 'l': /* FALLTHROUGH */
+			case 's':
+				if (lpop > 0) {
+					if (lpop <= piss_len)
+						piss[lpop - 1] = 1;
+					else if (piss)
+						errno = E2BIG;
+				}
+				break;
+			case 'p':
+				c = *str++;
+				if (c < '1' || c > '9') {
+					errno = EINVAL;
+					continue;
+				} else {
+					lpop = c - '0';
+					if (lpop > nparm)
+						nparm = lpop;
+				}
+				break;
+			default:
+				lpop = -1;
+		}
+	}
+
+	return nparm;
+}
+
 static char *
 _ti_tiparm(TERMINAL *term, const char *str, int va_long, va_list parms)
 {
-	const char *sp;
 	char c, fmt[64], *fp, *ostr;
 	long val, val2;
 	long dnums[26]; /* dynamic variables a-z, not preserved */
 	size_t l, max;
 	TPSTACK stack;
-	TPVAR params[9];
+	TPVAR params[TPARM_MAX];
 	unsigned int done, dot, minus, width, precision, olen;
-	int piss[9]; /* Parameter IS String - piss ;) */
+	int piss[TPARM_MAX]; /* Parameter IS String - piss ;) */
 
 	if (str == NULL)
 		return NULL;
@@ -172,40 +217,8 @@
 		term->_buflen = BUFINC;
 	}
 
-	/*
-	  Make a first pass through the string so we can work out
-	  which parameters are ints and which are char *.
-	  Basically we only use char * if %p[1-9] is followed by %l or %s.
-	*/
 	memset(&piss, 0, sizeof(piss));
-	max = 0;
-	sp = str;
-	while ((c = *sp++) != '\0') {
-		if (c != '%')
-			continue;
-		c = *sp++;
-		if (c == '\0')
-			break;
-		if (c != 'p')
-			continue;
-		c = *sp++;
-		if (c < '1' || c > '9') {
-			errno = EINVAL;
-			continue;
-		}
-		l = c - '0';
-		if (l > max)
-			max = l;
-		if (*sp != '%')
-			continue;
-		/* Skip formatting */
-		sp++;
-		while (*sp == '.' || *sp == '#' || *sp == ' ' || *sp == ':' ||
-		    *sp == '-' || isdigit((unsigned char)*sp))
-			sp++;
-		if (*sp == 'l' || *sp == 's')
-			piss[l - 1] = 1;
-	}
+	max = _ti_parm_analyse(str, piss, TPARM_MAX);
 
 	/* Put our parameters into variables */
 	memset(&params, 0, sizeof(params));

cvs diff -r1.10 -r1.11 src/usr.bin/tput/Makefile (expand / switch to context diff)
--- src/usr.bin/tput/Makefile 2010/02/03 15:34:46 1.10
+++ src/usr.bin/tput/Makefile 2013/01/24 10:41:28 1.11
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.10 2010/02/03 15:34:46 roy Exp $
+#	$NetBSD: Makefile,v 1.11 2013/01/24 10:41:28 roy Exp $
 #	@(#)Makefile	8.1 (Berkeley) 6/6/93
 
 PROG=	tput
@@ -6,5 +6,7 @@
 LDADD=	-lterminfo
 MLINKS=	tput.1 clear.1
 SCRIPTS=clear.sh
+
+CPPFLAGS+=	-I${.CURDIR}/../../lib/libterminfo
 
 .include <bsd.prog.mk>

cvs diff -r1.22 -r1.23 src/usr.bin/tput/tput.c (expand / switch to context diff)
--- src/usr.bin/tput/tput.c 2011/10/04 12:23:14 1.22
+++ src/usr.bin/tput/tput.c 2013/01/24 10:41:29 1.23
@@ -1,4 +1,4 @@
-/*	$NetBSD: tput.c,v 1.22 2011/10/04 12:23:14 roy Exp $	*/
+/*	$NetBSD: tput.c,v 1.23 2013/01/24 10:41:29 roy Exp $	*/
 
 /*-
  * Copyright (c) 1980, 1988, 1993
@@ -39,17 +39,19 @@
 #if 0
 static char sccsid[] = "@(#)tput.c	8.3 (Berkeley) 4/28/95";
 #endif
-__RCSID("$NetBSD: tput.c,v 1.22 2011/10/04 12:23:14 roy Exp $");
+__RCSID("$NetBSD: tput.c,v 1.23 2013/01/24 10:41:29 roy Exp $");
 #endif /* not lint */
 
 #include <termios.h>
 
 #include <err.h>
+#include <errno.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <term_private.h>
 #include <term.h>
-#include <termcap.h>
 #include <unistd.h>
 
 static int    outc(int);
@@ -140,84 +142,47 @@
 	static const char errfew[] =
 	    "Not enough arguments (%d) for capability `%s'";
 	static const char erresc[] =
-	    "Unknown %% escape `%c' for capability `%s'";
-	char c, l;
-	const char *p;
-	int arg_need, p1, p2, p3, p4, p5, p6, p7, p8, p9;
+	    "Unknown %% escape (%s) for capability `%s'";
+	static const char errnum[] =
+	    "Expected a numeric argument [%d] (%s) for capability `%s'";
+	int i, nparams, piss[TPARM_MAX];
+	long nums[TPARM_MAX];
+	char *strs[TPARM_MAX], *tmp;
 
 	/* Count how many values we need for this capability. */
-	arg_need = 0;
-	p = str;
-	while ((c = *p++) != '\0') {
-		if (c != '%')
-			continue;
-		c = *p++;
-		if (c == '\0')
-			break;
-		if (c != 'p')
-			continue;
-		c = *p++;
-		if (c < '1' || c > '9')
-			errx(2, erresc, c, cap);
-		l = c - '0';
-		if (l > arg_need)
-			arg_need = l;
+	errno = 0;
+	memset(&piss, 0, sizeof(piss));
+	nparams = _ti_parm_analyse(str, piss, TPARM_MAX);
+	if (errno == EINVAL)
+		errx(2, erresc, str, cap);
+
+	/* Create our arrays of integers and strings */
+	for (i = 0; i < nparams; i++) {
+		if (*++argv == NULL || *argv[0] == '\0')
+			errx(2, errfew, nparams, cap);
+		if (piss[i]) 
+			strs[i] = *argv;
+		else {
+			errno = 0;
+			nums[i] = strtol(*argv, &tmp, 0);
+			if ((errno == ERANGE && 
+			    (nums[i] == LONG_MIN || nums[i] == LONG_MAX)) ||
+			    (errno != 0 && nums[i] == 0) ||
+			    tmp == str ||
+			    *tmp != '\0')
+				errx(2, errnum, i + 1, *argv, cap);
+		}
+		if (piss[i])
+			printf ("str %d %s\n", i, strs[i]);
+		else
+			printf ("num %d %ld\n", i, nums[i]);
 	}
-	
-#define NEXT_ARG							      \
-	{								      \
-		if (*++argv == NULL || *argv[0] == '\0')		      \
-			errx(2, errfew, 1, cap);			      \
-	}
 
-	if (arg_need > 0) {
-		NEXT_ARG;
-		p1 = atoi(*argv);
-	} else
-		p1 = 0;
-	if (arg_need > 1) {
-		NEXT_ARG;
-		p2 = atoi(*argv);
-	} else
-		p2 = 0;
-	if (arg_need > 2) {
-		NEXT_ARG;
-		p3 = atoi(*argv);
-	} else
-		p3 = 0;
-	if (arg_need > 3) {
-		NEXT_ARG;
-		p4 = atoi(*argv);
-	} else
-		p4 = 0;
-	if (arg_need > 4) {
-		NEXT_ARG;
-		p5 = atoi(*argv);
-	} else
-		p5 = 0;
-	if (arg_need > 5) {
-		NEXT_ARG;
-		p6 = atoi(*argv);
-	} else
-		p6 = 0;
-	if (arg_need > 6) {
-		NEXT_ARG;
-		p7 = atoi(*argv);
-	} else
-		p7 = 0;
-	if (arg_need > 7) {
-		NEXT_ARG;
-		p8 = atoi(*argv);
-	} else
-		p8 = 0;
-	if (arg_need > 8) {
-		NEXT_ARG;
-		p9 = atoi(*argv);
-	} else
-		p9 = 0;
+	/* And output */
+#define p(i)	(i <= nparams ? \
+		    (piss[i - 1] ? (long)strs[i - 1] : nums[i - 1]) : 0)
+	puts(tparm(str, p(1), p(2), p(3), p(4), p(5), p(6), p(7), p(8), p(9)));
 
-	/* And print them. */
-	(void)tputs(tparm(str, p1, p2, p3, p4, p5, p6, p7, p8, p9), 0, outc);
 	return argv;
 }