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.diff -r1.10 -r1.11 src/lib/libterminfo/term_private.h
(roy)
--- 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,17 +1,17 @@ | @@ -1,17 +1,17 @@ | |||
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 | * | |
@@ -147,14 +147,17 @@ typedef struct { | @@ -147,14 +147,17 @@ typedef struct { | |||
147 | TBUF strs; | 147 | TBUF strs; | |
148 | TBUF extras; | 148 | TBUF extras; | |
149 | } TIC; | 149 | } TIC; | |
150 | 150 | |||
151 | char *_ti_grow_tbuf(TBUF *, size_t); | 151 | char *_ti_grow_tbuf(TBUF *, size_t); | |
152 | char *_ti_get_token(char **, char); | 152 | char *_ti_get_token(char **, char); | |
153 | char *_ti_find_cap(TBUF *, char, short); | 153 | char *_ti_find_cap(TBUF *, char, short); | |
154 | char *_ti_find_extra(TBUF *, const char *); | 154 | char *_ti_find_extra(TBUF *, const char *); | |
155 | size_t _ti_store_extra(TIC *, int, char *, char, char, short, | 155 | size_t _ti_store_extra(TIC *, int, char *, char, char, short, | |
156 | char *, size_t, int); | 156 | char *, size_t, int); | |
157 | TIC *_ti_compile(char *, int); | 157 | TIC *_ti_compile(char *, int); | |
158 | ssize_t _ti_flatten(uint8_t **, const TIC *); | 158 | ssize_t _ti_flatten(uint8_t **, const TIC *); | |
159 | void _ti_freetic(TIC *); | 159 | void _ti_freetic(TIC *); | |
160 | ||||
161 | #define TPARM_MAX 9 /* not likely to change */ | |||
162 | int _ti_parm_analyse(const char *, int *, int); | |||
160 | #endif | 163 | #endif |
--- 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,58 +1,58 @@ | @@ -1,58 +1,58 @@ | |||
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 | |||
47 | static TERMINAL *dumbterm; /* For non thread safe functions */ | 47 | static TERMINAL *dumbterm; /* For non thread safe functions */ | |
48 | 48 | |||
49 | typedef struct { | 49 | typedef 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 | |||
55 | typedef struct { | 55 | typedef struct { | |
56 | long num; | 56 | long num; | |
57 | char *string; | 57 | char *string; | |
58 | } TPVAR; | 58 | } TPVAR; | |
@@ -121,38 +121,83 @@ static size_t | @@ -121,38 +121,83 @@ static size_t | |||
121 | onum(TERMINAL *term, const char *fmt, int num, unsigned int len) | 121 | onum(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 | */ | |||
139 | int | |||
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 | ||||
134 | static char * | 180 | static 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)); | |
@@ -162,60 +207,28 @@ _ti_tiparm(TERMINAL *term, const char *s | @@ -162,60 +207,28 @@ _ti_tiparm(TERMINAL *term, const char *s | |||
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(¶ms, 0, sizeof(params)); | 224 | memset(¶ms, 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)); |
--- 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 | |||
4 | PROG= tput | 4 | PROG= tput | |
5 | DPADD= ${LIBTERMINFO} | 5 | DPADD= ${LIBTERMINFO} | |
6 | LDADD= -lterminfo | 6 | LDADD= -lterminfo | |
7 | MLINKS= tput.1 clear.1 | 7 | MLINKS= tput.1 clear.1 | |
8 | SCRIPTS=clear.sh | 8 | SCRIPTS=clear.sh | |
9 | 9 | |||
10 | CPPFLAGS+= -I${.CURDIR}/../../lib/libterminfo | |||
11 | ||||
10 | .include <bsd.prog.mk> | 12 | .include <bsd.prog.mk> |
--- 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,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
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. | |
@@ -29,37 +29,39 @@ | @@ -29,37 +29,39 @@ | |||
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 | |
40 | static char sccsid[] = "@(#)tput.c 8.3 (Berkeley) 4/28/95"; | 40 | static 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 | |||
55 | static int outc(int); | 57 | static int outc(int); | |
56 | static void usage(void) __dead; | 58 | static void usage(void) __dead; | |
57 | static char **process(const char *, const char *, char **); | 59 | static char **process(const char *, const char *, char **); | |
58 | 60 | |||
59 | int | 61 | int | |
60 | main(int argc, char **argv) | 62 | main(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; | |
@@ -130,104 +132,67 @@ main(int argc, char **argv) | @@ -130,104 +132,67 @@ main(int argc, char **argv) | |||
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 | |||
137 | static char ** | 139 | static char ** | |
138 | process(const char *cap, const char *str, char **argv) | 140 | process(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 | |||
224 | static int | 189 | static int | |
225 | outc(int c) | 190 | outc(int c) | |
226 | { | 191 | { | |
227 | return putchar(c); | 192 | return putchar(c); | |
228 | } | 193 | } | |
229 | 194 | |||
230 | static void | 195 | static void | |
231 | usage(void) | 196 | usage(void) | |
232 | { | 197 | { | |
233 | (void)fprintf(stderr, | 198 | (void)fprintf(stderr, |