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 (switch to unified 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,160 +1,163 @@ @@ -1,160 +1,163 @@
1/* $NetBSD: term_private.h,v 1.10 2012/06/03 23:19:10 joerg Exp $ */ 1/* $NetBSD: term_private.h,v 1.11 2013/01/24 10:41:28 roy Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc. 4 * Copyright (c) 2009, 2010, 2013 The NetBSD Foundation, Inc.
5 * 5 *
6 * This code is derived from software contributed to The NetBSD Foundation 6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Roy Marples. 7 * by Roy Marples.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30#ifndef _TERM_PRIVATE_H_ 30#ifndef _TERM_PRIVATE_H_
31#define _TERM_PRIVATE_H_ 31#define _TERM_PRIVATE_H_
32 32
33/* This header should only be used by libterminfo, tic and infocmp. */ 33/* This header should only be used by libterminfo, tic and infocmp. */
34 34
35/* The terminfo database structure is private to us, 35/* The terminfo database structure is private to us,
36 * so it's documented here. 36 * so it's documented here.
37 * terminfo defines the largest number as 32767 and the largest 37 * terminfo defines the largest number as 32767 and the largest
38 * compiled entry as 4093 bytes long. 38 * compiled entry as 4093 bytes long.
39 * Thus, we store all numbers as uint16_t, including string length. 39 * Thus, we store all numbers as uint16_t, including string length.
40 * All strings are prefixed by length, including the null terminator. 40 * All strings are prefixed by length, including the null terminator.
41 * The largest string length we can handle is 65535 bytes, 41 * The largest string length we can handle is 65535 bytes,
42 * including the null terminator. 42 * including the null terminator.
43 * The largest capability block we can handle is 65535 bytes. 43 * The largest capability block we can handle is 65535 bytes.
44 * This means that we exceed the current terminfo defined limits. 44 * This means that we exceed the current terminfo defined limits.
45 * 45 *
46 * Version 1 capabilities are defined as: 46 * Version 1 capabilities are defined as:
47 * header byte (always 1) 47 * header byte (always 1)
48 * name 48 * name
49 * description, 49 * description,
50 * cap length, num flags, index, char, 50 * cap length, num flags, index, char,
51 * cap length, num numbers, index, number, 51 * cap length, num numbers, index, number,
52 * cap length, num strings, index, string, 52 * cap length, num strings, index, string,
53 * cap length, num undefined caps, name, type (char), flag, number, string 53 * cap length, num undefined caps, name, type (char), flag, number, string
54 * 54 *
55 * Version 2 entries are aliases and defined as: 55 * Version 2 entries are aliases and defined as:
56 * header byte (always 2) 56 * header byte (always 2)
57 * 32bit id of the corresponding terminal in the file 57 * 32bit id of the corresponding terminal in the file
58 * name 58 * name
59 * 59 *
60 * The database itself is created using cdbw(3) and the numbers are 60 * The database itself is created using cdbw(3) and the numbers are
61 * always stored as little endian. 61 * always stored as little endian.
62 */ 62 */
63 63
64#include <sys/types.h> 64#include <sys/types.h>
65 65
66#define _TERMINFO 66#define _TERMINFO
67 67
68/* We use the same ncurses tic macros so that our data is identical 68/* We use the same ncurses tic macros so that our data is identical
69 * when a caller uses the long name macros to access te terminfo data 69 * when a caller uses the long name macros to access te terminfo data
70 * directly. */ 70 * directly. */
71#define ABSENT_BOOLEAN ((signed char)-1) /* 255 */ 71#define ABSENT_BOOLEAN ((signed char)-1) /* 255 */
72#define ABSENT_NUMERIC (-1) 72#define ABSENT_NUMERIC (-1)
73#define ABSENT_STRING (char *)0 73#define ABSENT_STRING (char *)0
74#define CANCELLED_BOOLEAN ((signed char)-2) /* 254 */ 74#define CANCELLED_BOOLEAN ((signed char)-2) /* 254 */
75#define CANCELLED_NUMERIC (-2) 75#define CANCELLED_NUMERIC (-2)
76#define CANCELLED_STRING (char *)(-1) 76#define CANCELLED_STRING (char *)(-1)
77#define VALID_BOOLEAN(s) ((unsigned char)(s) <= 1) /* reject "-1" */ 77#define VALID_BOOLEAN(s) ((unsigned char)(s) <= 1) /* reject "-1" */
78#define VALID_NUMERIC(s) ((s) >= 0) 78#define VALID_NUMERIC(s) ((s) >= 0)
79#define VALID_STRING(s) ((s) != CANCELLED_STRING && (s) != ABSENT_STRING) 79#define VALID_STRING(s) ((s) != CANCELLED_STRING && (s) != ABSENT_STRING)
80 80
81typedef struct { 81typedef struct {
82 const char *id; 82 const char *id;
83 char type; 83 char type;
84 char flag; 84 char flag;
85 short num; 85 short num;
86 const char *str; 86 const char *str;
87} TERMUSERDEF; 87} TERMUSERDEF;
88 88
89typedef struct { 89typedef struct {
90 int fildes; 90 int fildes;
91 /* We need to expose these so that the macros work */ 91 /* We need to expose these so that the macros work */
92 const char *name; 92 const char *name;
93 const char *desc; 93 const char *desc;
94 signed char *flags; 94 signed char *flags;
95 short *nums; 95 short *nums;
96 const char **strs; 96 const char **strs;
97 /* Storage area for terminfo data */ 97 /* Storage area for terminfo data */
98 char *_area; 98 char *_area;
99 size_t _arealen; 99 size_t _arealen;
100 size_t _nuserdefs; 100 size_t _nuserdefs;
101 TERMUSERDEF *_userdefs; 101 TERMUSERDEF *_userdefs;
102 /* So we don't rely on the global ospeed */ 102 /* So we don't rely on the global ospeed */
103 short _ospeed; 103 short _ospeed;
104 /* Output buffer for tparm */ 104 /* Output buffer for tparm */
105 char *_buf; 105 char *_buf;
106 size_t _buflen; 106 size_t _buflen;
107 size_t _bufpos; 107 size_t _bufpos;
108 /* A-Z static variables for tparm */ 108 /* A-Z static variables for tparm */
109 long _snums[26]; 109 long _snums[26];
110 /* aliases of the terminal, | separated */ 110 /* aliases of the terminal, | separated */
111 const char *_alias; 111 const char *_alias;
112} TERMINAL; 112} TERMINAL;
113 113
114extern const char * _ti_database; 114extern const char * _ti_database;
115 115
116ssize_t _ti_flagindex(const char *); 116ssize_t _ti_flagindex(const char *);
117ssize_t _ti_numindex(const char *); 117ssize_t _ti_numindex(const char *);
118ssize_t _ti_strindex(const char *); 118ssize_t _ti_strindex(const char *);
119const char * _ti_flagid(ssize_t); 119const char * _ti_flagid(ssize_t);
120const char * _ti_numid(ssize_t); 120const char * _ti_numid(ssize_t);
121const char * _ti_strid(ssize_t); 121const char * _ti_strid(ssize_t);
122int _ti_getterm(TERMINAL *, const char *, int); 122int _ti_getterm(TERMINAL *, const char *, int);
123void _ti_setospeed(TERMINAL *); 123void _ti_setospeed(TERMINAL *);
124 124
125/* libterminfo can compile terminfo strings too */ 125/* libterminfo can compile terminfo strings too */
126#define TIC_WARNING (1 << 0) 126#define TIC_WARNING (1 << 0)
127#define TIC_DESCRIPTION (1 << 1) 127#define TIC_DESCRIPTION (1 << 1)
128#define TIC_ALIAS (1 << 2) 128#define TIC_ALIAS (1 << 2)
129#define TIC_COMMENT (1 << 3) 129#define TIC_COMMENT (1 << 3)
130#define TIC_EXTRA (1 << 4) 130#define TIC_EXTRA (1 << 4)
131 131
132#define UINT16_T_MAX 0xffff 132#define UINT16_T_MAX 0xffff
133 133
134typedef struct { 134typedef struct {
135 char *buf; 135 char *buf;
136 size_t buflen; 136 size_t buflen;
137 size_t bufpos; 137 size_t bufpos;
138 size_t entries; 138 size_t entries;
139} TBUF; 139} TBUF;
140 140
141typedef struct { 141typedef struct {
142 char *name; 142 char *name;
143 char *alias; 143 char *alias;
144 char *desc; 144 char *desc;
145 TBUF flags; 145 TBUF flags;
146 TBUF nums; 146 TBUF nums;
147 TBUF strs; 147 TBUF strs;
148 TBUF extras; 148 TBUF extras;
149} TIC; 149} TIC;
150 150
151char *_ti_grow_tbuf(TBUF *, size_t); 151char *_ti_grow_tbuf(TBUF *, size_t);
152char *_ti_get_token(char **, char); 152char *_ti_get_token(char **, char);
153char *_ti_find_cap(TBUF *, char, short); 153char *_ti_find_cap(TBUF *, char, short);
154char *_ti_find_extra(TBUF *, const char *); 154char *_ti_find_extra(TBUF *, const char *);
155size_t _ti_store_extra(TIC *, int, char *, char, char, short, 155size_t _ti_store_extra(TIC *, int, char *, char, char, short,
156 char *, size_t, int); 156 char *, size_t, int);
157TIC *_ti_compile(char *, int); 157TIC *_ti_compile(char *, int);
158ssize_t _ti_flatten(uint8_t **, const TIC *); 158ssize_t _ti_flatten(uint8_t **, const TIC *);
159void _ti_freetic(TIC *); 159void _ti_freetic(TIC *);
 160
 161#define TPARM_MAX 9 /* not likely to change */
 162int _ti_parm_analyse(const char *, int *, int);
160#endif 163#endif

cvs diff -r1.11 -r1.12 src/lib/libterminfo/tparm.c (switch to unified 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,569 +1,582 @@ @@ -1,569 +1,582 @@
1/* $NetBSD: tparm.c,v 1.11 2013/01/24 10:28:28 roy Exp $ */ 1/* $NetBSD: tparm.c,v 1.12 2013/01/24 10:41:28 roy Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2009, 2011 The NetBSD Foundation, Inc. 4 * Copyright (c) 2009, 2011, 2013 The NetBSD Foundation, Inc.
5 * 5 *
6 * This code is derived from software contributed to The NetBSD Foundation 6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Roy Marples. 7 * by Roy Marples.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31__RCSID("$NetBSD: tparm.c,v 1.11 2013/01/24 10:28:28 roy Exp $"); 31__RCSID("$NetBSD: tparm.c,v 1.12 2013/01/24 10:41:28 roy Exp $");
32#include <sys/param.h> 32#include <sys/param.h>
33 33
34#include <assert.h> 34#include <assert.h>
35#include <ctype.h> 35#include <ctype.h>
36#include <errno.h> 36#include <errno.h>
37#include <stdarg.h> 37#include <stdarg.h>
38#include <stdio.h> 38#include <stdio.h>
39#include <stdlib.h> 39#include <stdlib.h>
40#include <string.h> 40#include <string.h>
41#include <term_private.h> 41#include <term_private.h>
42#include <term.h> 42#include <term.h>
43 43
44#define LONG_STR_MAX ((CHAR_BIT * sizeof(long)) / 3) 44#define LONG_STR_MAX ((CHAR_BIT * sizeof(long)) / 3)
45#define BUFINC 128 /* Size to increament the terminal buffer by */ 45#define BUFINC 128 /* Size to increament the terminal buffer by */
46 46
47static TERMINAL *dumbterm; /* For non thread safe functions */ 47static TERMINAL *dumbterm; /* For non thread safe functions */
48 48
49typedef struct { 49typedef struct {
50 long nums[20]; 50 long nums[20];
51 char *strings[20]; 51 char *strings[20];
52 size_t offset; 52 size_t offset;
53} TPSTACK; 53} TPSTACK;
54 54
55typedef struct { 55typedef struct {
56 long num; 56 long num;
57 char *string; 57 char *string;
58} TPVAR; 58} TPVAR;
59 59
60static int 60static int
61push(long num, char *string, TPSTACK *stack) 61push(long num, char *string, TPSTACK *stack)
62{ 62{
63 if (stack->offset >= sizeof(stack->nums)) { 63 if (stack->offset >= sizeof(stack->nums)) {
64 errno = E2BIG; 64 errno = E2BIG;
65 return -1; 65 return -1;
66 } 66 }
67 stack->nums[stack->offset] = num; 67 stack->nums[stack->offset] = num;
68 stack->strings[stack->offset] = string; 68 stack->strings[stack->offset] = string;
69 stack->offset++; 69 stack->offset++;
70 return 0; 70 return 0;
71} 71}
72 72
73static int 73static int
74pop(long *num, char **string, TPSTACK *stack) 74pop(long *num, char **string, TPSTACK *stack)
75{ 75{
76 if (stack->offset == 0) { 76 if (stack->offset == 0) {
77 if (num) 77 if (num)
78 *num = 0; 78 *num = 0;
79 if (string) 79 if (string)
80 *string = NULL; 80 *string = NULL;
81 errno = E2BIG; 81 errno = E2BIG;
82 return -1; 82 return -1;
83 } 83 }
84 stack->offset--; 84 stack->offset--;
85 if (num) 85 if (num)
86 *num = stack->nums[stack->offset]; 86 *num = stack->nums[stack->offset];
87 if (string) 87 if (string)
88 *string = stack->strings[stack->offset]; 88 *string = stack->strings[stack->offset];
89 return 0; 89 return 0;
90} 90}
91 91
92static char * 92static char *
93checkbuf(TERMINAL *term, size_t len) 93checkbuf(TERMINAL *term, size_t len)
94{ 94{
95 char *buf; 95 char *buf;
96  96
97 if (term->_bufpos + len >= term->_buflen) { 97 if (term->_bufpos + len >= term->_buflen) {
98 len = term->_buflen + MAX(len, BUFINC); 98 len = term->_buflen + MAX(len, BUFINC);
99 buf = realloc(term->_buf, len); 99 buf = realloc(term->_buf, len);
100 if (buf == NULL) 100 if (buf == NULL)
101 return NULL; 101 return NULL;
102 term->_buf = buf; 102 term->_buf = buf;
103 term->_buflen = len; 103 term->_buflen = len;
104 } 104 }
105 return term->_buf; 105 return term->_buf;
106} 106}
107 107
108static size_t 108static size_t
109ochar(TERMINAL *term, int c) 109ochar(TERMINAL *term, int c)
110{ 110{
111 if (c == 0) 111 if (c == 0)
112 c = 0200; 112 c = 0200;
113 /* Check we have space and a terminator */ 113 /* Check we have space and a terminator */
114 if (checkbuf(term, 2) == NULL) 114 if (checkbuf(term, 2) == NULL)
115 return 0; 115 return 0;
116 term->_buf[term->_bufpos++] = (char)c; 116 term->_buf[term->_bufpos++] = (char)c;
117 return 1; 117 return 1;
118} 118}
119 119
120static size_t 120static size_t
121onum(TERMINAL *term, const char *fmt, int num, unsigned int len) 121onum(TERMINAL *term, const char *fmt, int num, unsigned int len)
122{ 122{
123 size_t l; 123 size_t l;
124 124
125 if (len < LONG_STR_MAX) 125 if (len < LONG_STR_MAX)
126 len = LONG_STR_MAX; 126 len = LONG_STR_MAX;
127 if (checkbuf(term, len + 2) == NULL) 127 if (checkbuf(term, len + 2) == NULL)
128 return 0; 128 return 0;
129 l = sprintf(term->_buf + term->_bufpos, fmt, num); 129 l = sprintf(term->_buf + term->_bufpos, fmt, num);
130 term->_bufpos += l; 130 term->_bufpos += l;
131 return l; 131 return l;
132} 132}
133 133
 134/*
 135 Make a pass through the string so we can work out
 136 which parameters are ints and which are char *.
 137 Basically we only use char * if %p[1-9] is followed by %l or %s.
 138*/
 139int
 140_ti_parm_analyse(const char *str, int *piss, int piss_len)
 141{
 142 int nparm, lpop;
 143 char c;
 144
 145 nparm = 0;
 146 lpop = -1;
 147 while ((c = *str++) != '\0') {
 148 if (c != '%')
 149 continue;
 150 c = *str++;
 151 switch (c) {
 152 case 'l': /* FALLTHROUGH */
 153 case 's':
 154 if (lpop > 0) {
 155 if (lpop <= piss_len)
 156 piss[lpop - 1] = 1;
 157 else if (piss)
 158 errno = E2BIG;
 159 }
 160 break;
 161 case 'p':
 162 c = *str++;
 163 if (c < '1' || c > '9') {
 164 errno = EINVAL;
 165 continue;
 166 } else {
 167 lpop = c - '0';
 168 if (lpop > nparm)
 169 nparm = lpop;
 170 }
 171 break;
 172 default:
 173 lpop = -1;
 174 }
 175 }
 176
 177 return nparm;
 178}
 179
134static char * 180static char *
135_ti_tiparm(TERMINAL *term, const char *str, int va_long, va_list parms) 181_ti_tiparm(TERMINAL *term, const char *str, int va_long, va_list parms)
136{ 182{
137 const char *sp; 
138 char c, fmt[64], *fp, *ostr; 183 char c, fmt[64], *fp, *ostr;
139 long val, val2; 184 long val, val2;
140 long dnums[26]; /* dynamic variables a-z, not preserved */ 185 long dnums[26]; /* dynamic variables a-z, not preserved */
141 size_t l, max; 186 size_t l, max;
142 TPSTACK stack; 187 TPSTACK stack;
143 TPVAR params[9]; 188 TPVAR params[TPARM_MAX];
144 unsigned int done, dot, minus, width, precision, olen; 189 unsigned int done, dot, minus, width, precision, olen;
145 int piss[9]; /* Parameter IS String - piss ;) */ 190 int piss[TPARM_MAX]; /* Parameter IS String - piss ;) */
146 191
147 if (str == NULL) 192 if (str == NULL)
148 return NULL; 193 return NULL;
149 194
150 /* 195 /*
151 If not passed a terminal, malloc a dummy one. 196 If not passed a terminal, malloc a dummy one.
152 This means we can preserve buffers and variables per terminal and 197 This means we can preserve buffers and variables per terminal and
153 still work with non thread safe functions (which sadly are still the 198 still work with non thread safe functions (which sadly are still the
154 norm and standard). 199 norm and standard).
155 */ 200 */
156 if (term == NULL) { 201 if (term == NULL) {
157 if (dumbterm == NULL) { 202 if (dumbterm == NULL) {
158 dumbterm = malloc(sizeof(*dumbterm)); 203 dumbterm = malloc(sizeof(*dumbterm));
159 if (dumbterm == NULL) 204 if (dumbterm == NULL)
160 return NULL; 205 return NULL;
161 dumbterm->_buflen = 0; 206 dumbterm->_buflen = 0;
162 } 207 }
163 term = dumbterm; 208 term = dumbterm;
164 } 209 }
165 210
166 term->_bufpos = 0; 211 term->_bufpos = 0;
167 /* Ensure we have an initial buffer */ 212 /* Ensure we have an initial buffer */
168 if (term->_buflen == 0) { 213 if (term->_buflen == 0) {
169 term->_buf = malloc(BUFINC); 214 term->_buf = malloc(BUFINC);
170 if (term->_buf == NULL) 215 if (term->_buf == NULL)
171 return NULL; 216 return NULL;
172 term->_buflen = BUFINC; 217 term->_buflen = BUFINC;
173 } 218 }
174 219
175 /* 
176 Make a first pass through the string so we can work out 
177 which parameters are ints and which are char *. 
178 Basically we only use char * if %p[1-9] is followed by %l or %s. 
179 */ 
180 memset(&piss, 0, sizeof(piss)); 220 memset(&piss, 0, sizeof(piss));
181 max = 0; 221 max = _ti_parm_analyse(str, piss, TPARM_MAX);
182 sp = str; 
183 while ((c = *sp++) != '\0') { 
184 if (c != '%') 
185 continue; 
186 c = *sp++; 
187 if (c == '\0') 
188 break; 
189 if (c != 'p') 
190 continue; 
191 c = *sp++; 
192 if (c < '1' || c > '9') { 
193 errno = EINVAL; 
194 continue; 
195 } 
196 l = c - '0'; 
197 if (l > max) 
198 max = l; 
199 if (*sp != '%') 
200 continue; 
201 /* Skip formatting */ 
202 sp++; 
203 while (*sp == '.' || *sp == '#' || *sp == ' ' || *sp == ':' || 
204 *sp == '-' || isdigit((unsigned char)*sp)) 
205 sp++; 
206 if (*sp == 'l' || *sp == 's') 
207 piss[l - 1] = 1; 
208 } 
209 222
210 /* Put our parameters into variables */ 223 /* Put our parameters into variables */
211 memset(&params, 0, sizeof(params)); 224 memset(&params, 0, sizeof(params));
212 for (l = 0; l < max; l++) { 225 for (l = 0; l < max; l++) {
213 if (piss[l]) 226 if (piss[l])
214 params[l].string = va_arg(parms, char *); 227 params[l].string = va_arg(parms, char *);
215 else if (va_long) 228 else if (va_long)
216 params[l].num = va_arg(parms, long); 229 params[l].num = va_arg(parms, long);
217 else 230 else
218 params[l].num = (long)va_arg(parms, int); 231 params[l].num = (long)va_arg(parms, int);
219 } 232 }
220 233
221 memset(&stack, 0, sizeof(stack)); 234 memset(&stack, 0, sizeof(stack));
222 while ((c = *str++) != '\0') { 235 while ((c = *str++) != '\0') {
223 if (c != '%' || (c = *str++) == '%') { 236 if (c != '%' || (c = *str++) == '%') {
224 if (c == '\0') 237 if (c == '\0')
225 break; 238 break;
226 if (ochar(term, c) == 0) 239 if (ochar(term, c) == 0)
227 return NULL; 240 return NULL;
228 continue; 241 continue;
229 } 242 }
230 243
231 /* Handle formatting. */ 244 /* Handle formatting. */
232 fp = fmt; 245 fp = fmt;
233 *fp++ = '%'; 246 *fp++ = '%';
234 done = dot = minus = width = precision = 0; 247 done = dot = minus = width = precision = 0;
235 val = 0; 248 val = 0;
236 while (done == 0 && (size_t)(fp - fmt) < sizeof(fmt)) { 249 while (done == 0 && (size_t)(fp - fmt) < sizeof(fmt)) {
237 switch (c) { 250 switch (c) {
238 case 'c': /* FALLTHROUGH */ 251 case 'c': /* FALLTHROUGH */
239 case 's': 252 case 's':
240 *fp++ = c; 253 *fp++ = c;
241 done = 1; 254 done = 1;
242 break; 255 break;
243 case 'd': /* FALLTHROUGH */ 256 case 'd': /* FALLTHROUGH */
244 case 'o': /* FALLTHROUGH */ 257 case 'o': /* FALLTHROUGH */
245 case 'x': /* FALLTHROUGH */ 258 case 'x': /* FALLTHROUGH */
246 case 'X': /* FALLTHROUGH */ 259 case 'X': /* FALLTHROUGH */
247 *fp++ = 'l'; 260 *fp++ = 'l';
248 *fp++ = c; 261 *fp++ = c;
249 done = 1; 262 done = 1;
250 break; 263 break;
251 case '#': /* FALLTHROUGH */ 264 case '#': /* FALLTHROUGH */
252 case ' ': 265 case ' ':
253 *fp++ = c; 266 *fp++ = c;
254 break; 267 break;
255 case '.': 268 case '.':
256 *fp++ = c; 269 *fp++ = c;
257 if (dot == 0) { 270 if (dot == 0) {
258 dot = 1; 271 dot = 1;
259 width = val; 272 width = val;
260 } else 273 } else
261 done = 2; 274 done = 2;
262 val = 0; 275 val = 0;
263 break; 276 break;
264 case ':': 277 case ':':
265 minus = 1; 278 minus = 1;
266 break; 279 break;
267 case '-': 280 case '-':
268 if (minus) 281 if (minus)
269 *fp++ = c; 282 *fp++ = c;
270 else 283 else
271 done = 1; 284 done = 1;
272 break; 285 break;
273 default: 286 default:
274 if (isdigit((unsigned char)c)) { 287 if (isdigit((unsigned char)c)) {
275 val = (val * 10) + (c - '0'); 288 val = (val * 10) + (c - '0');
276 if (val > 10000) 289 if (val > 10000)
277 done = 2; 290 done = 2;
278 else 291 else
279 *fp++ = c; 292 *fp++ = c;
280 } else 293 } else
281 done = 1; 294 done = 1;
282 } 295 }
283 if (done == 0) 296 if (done == 0)
284 c = *str++; 297 c = *str++;
285 } 298 }
286 if (done == 2) { 299 if (done == 2) {
287 /* Found an error in the format */ 300 /* Found an error in the format */
288 fp = fmt + 1; 301 fp = fmt + 1;
289 *fp = *str; 302 *fp = *str;
290 olen = 0; 303 olen = 0;
291 } else { 304 } else {
292 if (dot == 0) 305 if (dot == 0)
293 width = val; 306 width = val;
294 else 307 else
295 precision = val; 308 precision = val;
296 olen = MAX(width, precision); 309 olen = MAX(width, precision);
297 } 310 }
298 *fp++ = '\0'; 311 *fp++ = '\0';
299 312
300 /* Handle commands */ 313 /* Handle commands */
301 switch (c) { 314 switch (c) {
302 case 'c': 315 case 'c':
303 pop(&val, NULL, &stack); 316 pop(&val, NULL, &stack);
304 if (ochar(term, (unsigned char)val) == 0) 317 if (ochar(term, (unsigned char)val) == 0)
305 return NULL; 318 return NULL;
306 break; 319 break;
307 case 's': 320 case 's':
308 pop(NULL, &ostr, &stack); 321 pop(NULL, &ostr, &stack);
309 if (ostr != NULL) { 322 if (ostr != NULL) {
310 l = strlen(ostr); 323 l = strlen(ostr);
311 if (l < (size_t)olen) 324 if (l < (size_t)olen)
312 l = olen; 325 l = olen;
313 if (checkbuf(term, (size_t)(l + 1)) == NULL) 326 if (checkbuf(term, (size_t)(l + 1)) == NULL)
314 return NULL; 327 return NULL;
315 l = sprintf(term->_buf + term->_bufpos, 328 l = sprintf(term->_buf + term->_bufpos,
316 fmt, ostr); 329 fmt, ostr);
317 term->_bufpos += l; 330 term->_bufpos += l;
318 } 331 }
319 break; 332 break;
320 case 'l': 333 case 'l':
321 pop(NULL, &ostr, &stack); 334 pop(NULL, &ostr, &stack);
322 if (ostr == NULL) 335 if (ostr == NULL)
323 l = 0; 336 l = 0;
324 else 337 else
325 l = strlen(ostr); 338 l = strlen(ostr);
326#ifdef NCURSES_COMPAT_57 339#ifdef NCURSES_COMPAT_57
327 if (onum(term, "%ld", (long)l, 0) == 0) 340 if (onum(term, "%ld", (long)l, 0) == 0)
328 return NULL; 341 return NULL;
329#else 342#else
330 push((long)l, NULL, &stack); 343 push((long)l, NULL, &stack);
331#endif 344#endif
332 break; 345 break;
333 case 'd': /* FALLTHROUGH */ 346 case 'd': /* FALLTHROUGH */
334 case 'o': /* FALLTHROUGH */ 347 case 'o': /* FALLTHROUGH */
335 case 'x': /* FALLTHROUGH */ 348 case 'x': /* FALLTHROUGH */
336 case 'X': 349 case 'X':
337 pop(&val, NULL, &stack); 350 pop(&val, NULL, &stack);
338 if (onum(term, fmt, (int)val, olen) == 0) 351 if (onum(term, fmt, (int)val, olen) == 0)
339 return NULL; 352 return NULL;
340 break; 353 break;
341 case 'p': 354 case 'p':
342 if (*str < '1' || *str > '9') 355 if (*str < '1' || *str > '9')
343 break; 356 break;
344 l = *str++ - '1'; 357 l = *str++ - '1';
345 if (push(params[l].num, params[l].string, &stack)) 358 if (push(params[l].num, params[l].string, &stack))
346 return NULL; 359 return NULL;
347 break; 360 break;
348 case 'P': 361 case 'P':
349 pop(&val, NULL, &stack); 362 pop(&val, NULL, &stack);
350 if (*str >= 'a' && *str <= 'z') 363 if (*str >= 'a' && *str <= 'z')
351 dnums[*str - 'a'] = val; 364 dnums[*str - 'a'] = val;
352 else if (*str >= 'A' && *str <= 'Z') 365 else if (*str >= 'A' && *str <= 'Z')
353 term->_snums[*str - 'A'] = val; 366 term->_snums[*str - 'A'] = val;
354 break; 367 break;
355 case 'g': 368 case 'g':
356 if (*str >= 'a' && *str <= 'z') { 369 if (*str >= 'a' && *str <= 'z') {
357 if (push(dnums[*str - 'a'], NULL, &stack)) 370 if (push(dnums[*str - 'a'], NULL, &stack))
358 return NULL; 371 return NULL;
359 } else if (*str >= 'A' && *str <= 'Z') { 372 } else if (*str >= 'A' && *str <= 'Z') {
360 if (push(term->_snums[*str - 'A'], 373 if (push(term->_snums[*str - 'A'],
361 NULL, &stack)) 374 NULL, &stack))
362 return NULL; 375 return NULL;
363 } 376 }
364 break; 377 break;
365 case 'i': 378 case 'i':
366 if (piss[0] == 0) 379 if (piss[0] == 0)
367 params[0].num++; 380 params[0].num++;
368 if (piss[1] == 0) 381 if (piss[1] == 0)
369 params[1].num++; 382 params[1].num++;
370 break; 383 break;
371 case '\'': 384 case '\'':
372 if (push((long)(unsigned char)*str++, NULL, &stack)) 385 if (push((long)(unsigned char)*str++, NULL, &stack))
373 return NULL; 386 return NULL;
374 while (*str != '\0' && *str != '\'') 387 while (*str != '\0' && *str != '\'')
375 str++; 388 str++;
376 if (*str == '\'') 389 if (*str == '\'')
377 str++; 390 str++;
378 break; 391 break;
379 case '{': 392 case '{':
380 val = 0; 393 val = 0;
381 for (; isdigit((unsigned char)*str); str++) 394 for (; isdigit((unsigned char)*str); str++)
382 val = (val * 10) + (*str - '0'); 395 val = (val * 10) + (*str - '0');
383 if (push(val, NULL, &stack)) 396 if (push(val, NULL, &stack))
384 return NULL; 397 return NULL;
385 while (*str != '\0' && *str != '}') 398 while (*str != '\0' && *str != '}')
386 str++; 399 str++;
387 if (*str == '}') 400 if (*str == '}')
388 str++; 401 str++;
389 break; 402 break;
390 case '+': /* FALLTHROUGH */ 403 case '+': /* FALLTHROUGH */
391 case '-': /* FALLTHROUGH */ 404 case '-': /* FALLTHROUGH */
392 case '*': /* FALLTHROUGH */ 405 case '*': /* FALLTHROUGH */
393 case '/': /* FALLTHROUGH */ 406 case '/': /* FALLTHROUGH */
394 case 'm': /* FALLTHROUGH */ 407 case 'm': /* FALLTHROUGH */
395 case 'A': /* FALLTHROUGH */ 408 case 'A': /* FALLTHROUGH */
396 case 'O': /* FALLTHROUGH */ 409 case 'O': /* FALLTHROUGH */
397 case '&': /* FALLTHROUGH */ 410 case '&': /* FALLTHROUGH */
398 case '|': /* FALLTHROUGH */ 411 case '|': /* FALLTHROUGH */
399 case '^': /* FALLTHROUGH */ 412 case '^': /* FALLTHROUGH */
400 case '=': /* FALLTHROUGH */ 413 case '=': /* FALLTHROUGH */
401 case '<': /* FALLTHROUGH */ 414 case '<': /* FALLTHROUGH */
402 case '>': 415 case '>':
403 pop(&val, NULL, &stack); 416 pop(&val, NULL, &stack);
404 pop(&val2, NULL, &stack); 417 pop(&val2, NULL, &stack);
405 switch (c) { 418 switch (c) {
406 case '+': 419 case '+':
407 val = val + val2; 420 val = val + val2;
408 break; 421 break;
409 case '-': 422 case '-':
410 val = val2 - val; 423 val = val2 - val;
411 break; 424 break;
412 case '*': 425 case '*':
413 val = val * val2; 426 val = val * val2;
414 break; 427 break;
415 case '/': 428 case '/':
416 val = val ? val2 / val : 0; 429 val = val ? val2 / val : 0;
417 break; 430 break;
418 case 'm': 431 case 'm':
419 val = val ? val2 % val : 0; 432 val = val ? val2 % val : 0;
420 break; 433 break;
421 case 'A': 434 case 'A':
422 val = val && val2; 435 val = val && val2;
423 break; 436 break;
424 case 'O': 437 case 'O':
425 val = val || val2; 438 val = val || val2;
426 break; 439 break;
427 case '&': 440 case '&':
428 val = val & val2; 441 val = val & val2;
429 break; 442 break;
430 case '|': 443 case '|':
431 val = val | val2; 444 val = val | val2;
432 break; 445 break;
433 case '^': 446 case '^':
434 val = val ^ val2; 447 val = val ^ val2;
435 break; 448 break;
436 case '=': 449 case '=':
437 val = val == val2; 450 val = val == val2;
438 break; 451 break;
439 case '<': 452 case '<':
440 val = val2 < val; 453 val = val2 < val;
441 break; 454 break;
442 case '>': 455 case '>':
443 val = val2 > val; 456 val = val2 > val;
444 break; 457 break;
445 } 458 }
446 if (push(val, NULL, &stack)) 459 if (push(val, NULL, &stack))
447 return NULL; 460 return NULL;
448 break; 461 break;
449 case '!': 462 case '!':
450 case '~': 463 case '~':
451 pop(&val, NULL, &stack); 464 pop(&val, NULL, &stack);
452 switch (c) { 465 switch (c) {
453 case '!': 466 case '!':
454 val = !val; 467 val = !val;
455 break; 468 break;
456 case '~': 469 case '~':
457 val = ~val; 470 val = ~val;
458 break; 471 break;
459 } 472 }
460 if (push(val, NULL, &stack)) 473 if (push(val, NULL, &stack))
461 return NULL; 474 return NULL;
462 break; 475 break;
463 case '?': /* if */ 476 case '?': /* if */
464 break; 477 break;
465 case 't': /* then */ 478 case 't': /* then */
466 pop(&val, NULL, &stack); 479 pop(&val, NULL, &stack);
467 if (val == 0) { 480 if (val == 0) {
468 l = 0; 481 l = 0;
469 for (; *str != '\0'; str++) { 482 for (; *str != '\0'; str++) {
470 if (*str != '%') 483 if (*str != '%')
471 continue; 484 continue;
472 str++; 485 str++;
473 if (*str == '?') 486 if (*str == '?')
474 l++; 487 l++;
475 else if (*str == ';') { 488 else if (*str == ';') {
476 if (l > 0) 489 if (l > 0)
477 l--; 490 l--;
478 else { 491 else {
479 str++; 492 str++;
480 break; 493 break;
481 } 494 }
482 } else if (*str == 'e' && l == 0) { 495 } else if (*str == 'e' && l == 0) {
483 str++; 496 str++;
484 break; 497 break;
485 } 498 }
486 } 499 }
487 } 500 }
488 break; 501 break;
489 case 'e': /* else */ 502 case 'e': /* else */
490 l = 0; 503 l = 0;
491 for (; *str != '\0'; str++) { 504 for (; *str != '\0'; str++) {
492 if (*str != '%') 505 if (*str != '%')
493 continue; 506 continue;
494 str++; 507 str++;
495 if (*str == '?') 508 if (*str == '?')
496 l++; 509 l++;
497 else if (*str == ';') { 510 else if (*str == ';') {
498 if (l > 0) 511 if (l > 0)
499 l--; 512 l--;
500 else { 513 else {
501 str++; 514 str++;
502 break; 515 break;
503 } 516 }
504 } 517 }
505 } 518 }
506 break; 519 break;
507 case ';': /* fi */ 520 case ';': /* fi */
508 break; 521 break;
509 } 522 }
510 } 523 }
511 term->_buf[term->_bufpos] = '\0'; 524 term->_buf[term->_bufpos] = '\0';
512 return term->_buf; 525 return term->_buf;
513} 526}
514 527
515char * 528char *
516ti_tiparm(TERMINAL *term, const char *str, ...) 529ti_tiparm(TERMINAL *term, const char *str, ...)
517{ 530{
518 va_list va; 531 va_list va;
519 char *ret; 532 char *ret;
520 533
521 _DIAGASSERT(term != NULL); 534 _DIAGASSERT(term != NULL);
522 _DIAGASSERT(str != NULL); 535 _DIAGASSERT(str != NULL);
523 536
524 va_start(va, str); 537 va_start(va, str);
525 ret = _ti_tiparm(term, str, 0, va); 538 ret = _ti_tiparm(term, str, 0, va);
526 va_end(va); 539 va_end(va);
527 return ret; 540 return ret;
528} 541}
529 542
530char * 543char *
531tiparm(const char *str, ...) 544tiparm(const char *str, ...)
532{ 545{
533 va_list va; 546 va_list va;
534 char *ret; 547 char *ret;
535  548
536 _DIAGASSERT(str != NULL); 549 _DIAGASSERT(str != NULL);
537 550
538 va_start(va, str); 551 va_start(va, str);
539 ret = _ti_tiparm(NULL, str, 0, va); 552 ret = _ti_tiparm(NULL, str, 0, va);
540 va_end(va); 553 va_end(va);
541 return ret; 554 return ret;
542} 555}
543 556
544/* Same as tiparm, but accepts long instead of int for the numeric params. 557/* Same as tiparm, but accepts long instead of int for the numeric params.
545 * Currently there is no need for this to be a public interface and is only 558 * Currently there is no need for this to be a public interface and is only
546 * consumed by tparm. If we need this to be public, and I really cannot 559 * consumed by tparm. If we need this to be public, and I really cannot
547 * imagine why, then we would need ti_tlparm() as well. */ 560 * imagine why, then we would need ti_tlparm() as well. */
548static char * 561static char *
549tlparm(const char *str, ...) 562tlparm(const char *str, ...)
550{ 563{
551 va_list va; 564 va_list va;
552 char *ret; 565 char *ret;
553  566
554 _DIAGASSERT(str != NULL); 567 _DIAGASSERT(str != NULL);
555 568
556 va_start(va, str); 569 va_start(va, str);
557 ret = _ti_tiparm(NULL, str, 1, va); 570 ret = _ti_tiparm(NULL, str, 1, va);
558 va_end(va); 571 va_end(va);
559 return ret; 572 return ret;
560} 573}
561 574
562char * 575char *
563tparm(const char *str, 576tparm(const char *str,
564 long p1, long p2, long p3, long p4, long p5, 577 long p1, long p2, long p3, long p4, long p5,
565 long p6, long p7, long p8, long p9) 578 long p6, long p7, long p8, long p9)
566{ 579{
567 580
568 return tlparm(str, p1, p2, p3, p4, p5, p6, p7, p8, p9); 581 return tlparm(str, p1, p2, p3, p4, p5, p6, p7, p8, p9);
569} 582}

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

cvs diff -r1.22 -r1.23 src/usr.bin/tput/tput.c (switch to unified 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,237 +1,202 @@ @@ -1,237 +1,202 @@
1/* $NetBSD: tput.c,v 1.22 2011/10/04 12:23:14 roy Exp $ */ 1/* $NetBSD: tput.c,v 1.23 2013/01/24 10:41:29 roy Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1980, 1988, 1993 4 * Copyright (c) 1980, 1988, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors 15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software 16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission. 17 * without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33#ifndef lint 33#ifndef lint
34__COPYRIGHT("@(#) Copyright (c) 1980, 1988, 1993\ 34__COPYRIGHT("@(#) Copyright (c) 1980, 1988, 1993\
35 The Regents of the University of California. All rights reserved."); 35 The Regents of the University of California. All rights reserved.");
36#endif /* not lint */ 36#endif /* not lint */
37 37
38#ifndef lint 38#ifndef lint
39#if 0 39#if 0
40static char sccsid[] = "@(#)tput.c 8.3 (Berkeley) 4/28/95"; 40static char sccsid[] = "@(#)tput.c 8.3 (Berkeley) 4/28/95";
41#endif 41#endif
42__RCSID("$NetBSD: tput.c,v 1.22 2011/10/04 12:23:14 roy Exp $"); 42__RCSID("$NetBSD: tput.c,v 1.23 2013/01/24 10:41:29 roy Exp $");
43#endif /* not lint */ 43#endif /* not lint */
44 44
45#include <termios.h> 45#include <termios.h>
46 46
47#include <err.h> 47#include <err.h>
 48#include <errno.h>
 49#include <limits.h>
48#include <stdio.h> 50#include <stdio.h>
49#include <stdlib.h> 51#include <stdlib.h>
50#include <string.h> 52#include <string.h>
 53#include <term_private.h>
51#include <term.h> 54#include <term.h>
52#include <termcap.h> 
53#include <unistd.h> 55#include <unistd.h>
54 56
55static int outc(int); 57static int outc(int);
56static void usage(void) __dead; 58static void usage(void) __dead;
57static char **process(const char *, const char *, char **); 59static char **process(const char *, const char *, char **);
58 60
59int 61int
60main(int argc, char **argv) 62main(int argc, char **argv)
61{ 63{
62 int ch, exitval, n; 64 int ch, exitval, n;
63 char *term; 65 char *term;
64 const char *p, *s; 66 const char *p, *s;
65 size_t pl; 67 size_t pl;
66 68
67 term = NULL; 69 term = NULL;
68 while ((ch = getopt(argc, argv, "T:")) != -1) 70 while ((ch = getopt(argc, argv, "T:")) != -1)
69 switch(ch) { 71 switch(ch) {
70 case 'T': 72 case 'T':
71 term = optarg; 73 term = optarg;
72 break; 74 break;
73 case '?': 75 case '?':
74 default: 76 default:
75 usage(); 77 usage();
76 } 78 }
77 argc -= optind; 79 argc -= optind;
78 argv += optind; 80 argv += optind;
79 81
80 if (!term && !(term = getenv("TERM"))) 82 if (!term && !(term = getenv("TERM")))
81 errx(2, "No terminal type specified and no TERM " 83 errx(2, "No terminal type specified and no TERM "
82 "variable set in the environment."); 84 "variable set in the environment.");
83 setupterm(term, 0, NULL); 85 setupterm(term, 0, NULL);
84 for (exitval = 0; (p = *argv) != NULL; ++argv) { 86 for (exitval = 0; (p = *argv) != NULL; ++argv) {
85 switch (*p) { 87 switch (*p) {
86 case 'c': 88 case 'c':
87 if (!strcmp(p, "clear")) 89 if (!strcmp(p, "clear"))
88 p = "clear"; 90 p = "clear";
89 break; 91 break;
90 case 'i': 92 case 'i':
91 if (!strcmp(p, "init")) { 93 if (!strcmp(p, "init")) {
92 s = tigetstr("is1"); 94 s = tigetstr("is1");
93 if (s != NULL) 95 if (s != NULL)
94 tputs(s, 0, outc); 96 tputs(s, 0, outc);
95 p = "is2"; 97 p = "is2";
96 } 98 }
97 break; 99 break;
98 case 'l': 100 case 'l':
99 if (!strcmp(p, "longname")) { 101 if (!strcmp(p, "longname")) {
100 (void)printf("%s\n", longname()); 102 (void)printf("%s\n", longname());
101 continue; 103 continue;
102 } 104 }
103 break; 105 break;
104 case 'r': 106 case 'r':
105 if (!strcmp(p, "reset")) { 107 if (!strcmp(p, "reset")) {
106 s = tigetstr("rs1"); 108 s = tigetstr("rs1");
107 if (s != NULL) 109 if (s != NULL)
108 tputs(s, 0, outc); 110 tputs(s, 0, outc);
109 p = "rs2"; 111 p = "rs2";
110 } 112 }
111 break; 113 break;
112 } 114 }
113 pl = strlen(p); 115 pl = strlen(p);
114 if (((s = tigetstr(p)) != NULL && s != (char *)-1) || 116 if (((s = tigetstr(p)) != NULL && s != (char *)-1) ||
115 (pl <= 2 && (s = tgetstr(p, NULL)) != NULL)) 117 (pl <= 2 && (s = tgetstr(p, NULL)) != NULL))
116 argv = process(p, s, argv); 118 argv = process(p, s, argv);
117 else if ((((n = tigetnum(p)) != -1 && n != -2 ) || 119 else if ((((n = tigetnum(p)) != -1 && n != -2 ) ||
118 (pl <= 2 && (n = tgetnum(p)) != -1))) 120 (pl <= 2 && (n = tgetnum(p)) != -1)))
119 (void)printf("%d\n", n); 121 (void)printf("%d\n", n);
120 else { 122 else {
121 exitval = tigetflag(p); 123 exitval = tigetflag(p);
122 if (exitval == -1) { 124 if (exitval == -1) {
123 if (pl <= 2) 125 if (pl <= 2)
124 exitval = !tgetflag(p); 126 exitval = !tgetflag(p);
125 else 127 else
126 exitval = 1; 128 exitval = 1;
127 } else 129 } else
128 exitval = !exitval; 130 exitval = !exitval;
129 } 131 }
130 132
131 if (argv == NULL) 133 if (argv == NULL)
132 break; 134 break;
133 } 135 }
134 return argv ? exitval : 2; 136 return argv ? exitval : 2;
135} 137}
136 138
137static char ** 139static char **
138process(const char *cap, const char *str, char **argv) 140process(const char *cap, const char *str, char **argv)
139{ 141{
140 static const char errfew[] = 142 static const char errfew[] =
141 "Not enough arguments (%d) for capability `%s'"; 143 "Not enough arguments (%d) for capability `%s'";
142 static const char erresc[] = 144 static const char erresc[] =
143 "Unknown %% escape `%c' for capability `%s'"; 145 "Unknown %% escape (%s) for capability `%s'";
144 char c, l; 146 static const char errnum[] =
145 const char *p; 147 "Expected a numeric argument [%d] (%s) for capability `%s'";
146 int arg_need, p1, p2, p3, p4, p5, p6, p7, p8, p9; 148 int i, nparams, piss[TPARM_MAX];
 149 long nums[TPARM_MAX];
 150 char *strs[TPARM_MAX], *tmp;
147 151
148 /* Count how many values we need for this capability. */ 152 /* Count how many values we need for this capability. */
149 arg_need = 0; 153 errno = 0;
150 p = str; 154 memset(&piss, 0, sizeof(piss));
151 while ((c = *p++) != '\0') { 155 nparams = _ti_parm_analyse(str, piss, TPARM_MAX);
152 if (c != '%') 156 if (errno == EINVAL)
153 continue; 157 errx(2, erresc, str, cap);
154 c = *p++; 158
155 if (c == '\0') 159 /* Create our arrays of integers and strings */
156 break; 160 for (i = 0; i < nparams; i++) {
157 if (c != 'p') 161 if (*++argv == NULL || *argv[0] == '\0')
158 continue; 162 errx(2, errfew, nparams, cap);
159 c = *p++; 163 if (piss[i])
160 if (c < '1' || c > '9') 164 strs[i] = *argv;
161 errx(2, erresc, c, cap); 165 else {
162 l = c - '0'; 166 errno = 0;
163 if (l > arg_need) 167 nums[i] = strtol(*argv, &tmp, 0);
164 arg_need = l; 168 if ((errno == ERANGE &&
165 } 169 (nums[i] == LONG_MIN || nums[i] == LONG_MAX)) ||
166  170 (errno != 0 && nums[i] == 0) ||
167#define NEXT_ARG \ 171 tmp == str ||
168 { \ 172 *tmp != '\0')
169 if (*++argv == NULL || *argv[0] == '\0') \ 173 errx(2, errnum, i + 1, *argv, cap);
170 errx(2, errfew, 1, cap); \ 174 }
 175 if (piss[i])
 176 printf ("str %d %s\n", i, strs[i]);
 177 else
 178 printf ("num %d %ld\n", i, nums[i]);
171 } 179 }
172 180
173 if (arg_need > 0) { 181 /* And output */
174 NEXT_ARG; 182#define p(i) (i <= nparams ? \
175 p1 = atoi(*argv); 183 (piss[i - 1] ? (long)strs[i - 1] : nums[i - 1]) : 0)
176 } else 184 puts(tparm(str, p(1), p(2), p(3), p(4), p(5), p(6), p(7), p(8), p(9)));
177 p1 = 0; 
178 if (arg_need > 1) { 
179 NEXT_ARG; 
180 p2 = atoi(*argv); 
181 } else 
182 p2 = 0; 
183 if (arg_need > 2) { 
184 NEXT_ARG; 
185 p3 = atoi(*argv); 
186 } else 
187 p3 = 0; 
188 if (arg_need > 3) { 
189 NEXT_ARG; 
190 p4 = atoi(*argv); 
191 } else 
192 p4 = 0; 
193 if (arg_need > 4) { 
194 NEXT_ARG; 
195 p5 = atoi(*argv); 
196 } else 
197 p5 = 0; 
198 if (arg_need > 5) { 
199 NEXT_ARG; 
200 p6 = atoi(*argv); 
201 } else 
202 p6 = 0; 
203 if (arg_need > 6) { 
204 NEXT_ARG; 
205 p7 = atoi(*argv); 
206 } else 
207 p7 = 0; 
208 if (arg_need > 7) { 
209 NEXT_ARG; 
210 p8 = atoi(*argv); 
211 } else 
212 p8 = 0; 
213 if (arg_need > 8) { 
214 NEXT_ARG; 
215 p9 = atoi(*argv); 
216 } else 
217 p9 = 0; 
218 185
219 /* And print them. */ 
220 (void)tputs(tparm(str, p1, p2, p3, p4, p5, p6, p7, p8, p9), 0, outc); 
221 return argv; 186 return argv;
222} 187}
223 188
224static int 189static int
225outc(int c) 190outc(int c)
226{ 191{
227 return putchar(c); 192 return putchar(c);
228} 193}
229 194
230static void 195static void
231usage(void) 196usage(void)
232{ 197{
233 (void)fprintf(stderr, 198 (void)fprintf(stderr,
234 "Usage: %s [-T term] attribute [attribute-args] ...\n", 199 "Usage: %s [-T term] attribute [attribute-args] ...\n",
235 getprogname()); 200 getprogname());
236 exit(2); 201 exit(2);
237} 202}