Updated by gnulib-sync
Showing
32 changed files
with
2563 additions
and
2930 deletions
1 | /* Copyright (C) 1992, 1995, 1996, 1997, 2001 Free Software Foundation, Inc. | 1 | /* Copyright (C) 1992,1995-1999,2000-2004 Free Software Foundation, Inc. |
2 | This file based on setenv.c in the GNU C Library. | 2 | This file is part of the GNU C Library. |
3 | 3 | ||
4 | The GNU C Library is free software; you can redistribute it and/or | 4 | This program is free software; you can redistribute it and/or modify |
5 | modify it under the terms of the GNU Library General Public License as | 5 | it under the terms of the GNU General Public License as published by |
6 | published by the Free Software Foundation; either version 2 of the | 6 | the Free Software Foundation; either version 2, or (at your option) |
7 | License, or (at your option) any later version. | 7 | any later version. |
8 | 8 | ||
9 | The GNU C Library is distributed in the hope that it will be useful, | 9 | This program is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | Library General Public License for more details. | 12 | GNU General Public License for more details. |
13 | 13 | ||
14 | You should have received a copy of the GNU Library General Public | 14 | You should have received a copy of the GNU General Public License along |
15 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 15 | with this program; if not, write to the Free Software Foundation, |
16 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 16 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
17 | Boston, MA 02111-1307, USA. */ | ||
18 | 17 | ||
19 | #if HAVE_CONFIG_H | 18 | #if HAVE_CONFIG_H |
20 | # include <config.h> | 19 | # include <config.h> |
21 | #endif | 20 | #endif |
21 | #include <alloca.h> | ||
22 | 22 | ||
23 | #include <errno.h> | 23 | #include <errno.h> |
24 | 24 | #ifndef __set_errno | |
25 | #if HAVE_STDLIB_H | 25 | # define __set_errno(ev) ((errno) = (ev)) |
26 | # include <stdlib.h> | ||
27 | #else | ||
28 | #include <sys/types.h> /* For `size_t' */ | ||
29 | #include <stdio.h> /* For `NULL' */ | ||
30 | #endif | ||
31 | #if HAVE_STRING_H | ||
32 | # include <string.h> | ||
33 | #endif | 26 | #endif |
34 | #if HAVE_UNISTD_H | 27 | |
28 | #include <stdlib.h> | ||
29 | #include <string.h> | ||
30 | #if _LIBC || HAVE_UNISTD_H | ||
35 | # include <unistd.h> | 31 | # include <unistd.h> |
36 | #endif | 32 | #endif |
37 | 33 | ||
38 | #define __environ environ | 34 | #if !_LIBC |
35 | # include "allocsa.h" | ||
36 | #endif | ||
37 | |||
38 | #if !_LIBC | ||
39 | # define __environ environ | ||
40 | # ifndef HAVE_ENVIRON_DECL | ||
39 | extern char **environ; | 41 | extern char **environ; |
42 | # endif | ||
43 | #endif | ||
40 | 44 | ||
41 | /* LOCK and UNLOCK are defined as no-ops. This makes the libiberty | 45 | #if _LIBC |
42 | * implementation MT-Unsafe. */ | 46 | /* This lock protects against simultaneous modifications of `environ'. */ |
43 | #define LOCK | 47 | # include <bits/libc-lock.h> |
44 | #define UNLOCK | 48 | __libc_lock_define_initialized (static, envlock) |
49 | # define LOCK __libc_lock_lock (envlock) | ||
50 | # define UNLOCK __libc_lock_unlock (envlock) | ||
51 | #else | ||
52 | # define LOCK | ||
53 | # define UNLOCK | ||
54 | #endif | ||
55 | |||
56 | /* In the GNU C library we must keep the namespace clean. */ | ||
57 | #ifdef _LIBC | ||
58 | # define setenv __setenv | ||
59 | # define clearenv __clearenv | ||
60 | # define tfind __tfind | ||
61 | # define tsearch __tsearch | ||
62 | #endif | ||
63 | |||
64 | /* In the GNU C library implementation we try to be more clever and | ||
65 | allow arbitrarily many changes of the environment given that the used | ||
66 | values are from a small set. Outside glibc this will eat up all | ||
67 | memory after a while. */ | ||
68 | #if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH \ | ||
69 | && defined __GNUC__) | ||
70 | # define USE_TSEARCH 1 | ||
71 | # include <search.h> | ||
72 | typedef int (*compar_fn_t) (const void *, const void *); | ||
73 | |||
74 | /* This is a pointer to the root of the search tree with the known | ||
75 | values. */ | ||
76 | static void *known_values; | ||
77 | |||
78 | # define KNOWN_VALUE(Str) \ | ||
79 | ({ \ | ||
80 | void *value = tfind (Str, &known_values, (compar_fn_t) strcmp); \ | ||
81 | value != NULL ? *(char **) value : NULL; \ | ||
82 | }) | ||
83 | # define STORE_VALUE(Str) \ | ||
84 | tsearch (Str, &known_values, (compar_fn_t) strcmp) | ||
85 | |||
86 | #else | ||
87 | # undef USE_TSEARCH | ||
88 | |||
89 | # define KNOWN_VALUE(Str) NULL | ||
90 | # define STORE_VALUE(Str) do { } while (0) | ||
91 | |||
92 | #endif | ||
45 | 93 | ||
46 | /* Below this point, it's verbatim code from the glibc-2.0 implementation */ | ||
47 | 94 | ||
48 | /* If this variable is not a null pointer we allocated the current | 95 | /* If this variable is not a null pointer we allocated the current |
49 | environment. */ | 96 | environment. */ |
50 | static char **last_environ; | 97 | static char **last_environ; |
51 | 98 | ||
52 | 99 | ||
100 | /* This function is used by `setenv' and `putenv'. The difference between | ||
101 | the two functions is that for the former must create a new string which | ||
102 | is then placed in the environment, while the argument of `putenv' | ||
103 | must be used directly. This is all complicated by the fact that we try | ||
104 | to reuse values once generated for a `setenv' call since we can never | ||
105 | free the strings. */ | ||
53 | int | 106 | int |
54 | setenv (name, value, replace) | 107 | __add_to_environ (const char *name, const char *value, const char *combined, |
55 | const char *name; | 108 | int replace) |
56 | const char *value; | ||
57 | int replace; | ||
58 | { | 109 | { |
59 | register char **ep; | 110 | register char **ep; |
60 | register size_t size; | 111 | register size_t size; |
61 | const size_t namelen = strlen (name); | 112 | const size_t namelen = strlen (name); |
62 | const size_t vallen = strlen (value) + 1; | 113 | const size_t vallen = value != NULL ? strlen (value) + 1 : 0; |
63 | 114 | ||
64 | LOCK; | 115 | LOCK; |
65 | 116 | ||
117 | /* We have to get the pointer now that we have the lock and not earlier | ||
118 | since another thread might have created a new environment. */ | ||
119 | ep = __environ; | ||
120 | |||
66 | size = 0; | 121 | size = 0; |
67 | if (__environ != NULL) | 122 | if (ep != NULL) |
68 | for (ep = __environ; *ep != NULL; ++ep) | 123 | { |
124 | for (; *ep != NULL; ++ep) | ||
69 | if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') | 125 | if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') |
70 | break; | 126 | break; |
71 | else | 127 | else |
72 | ++size; | 128 | ++size; |
129 | } | ||
73 | 130 | ||
74 | if (__environ == NULL || *ep == NULL) | 131 | if (ep == NULL || *ep == NULL) |
75 | { | 132 | { |
76 | char **new_environ; | 133 | char **new_environ; |
77 | if (__environ == last_environ && __environ != NULL) | 134 | #ifdef USE_TSEARCH |
78 | /* We allocated this space; we can extend it. */ | 135 | char *new_value; |
79 | new_environ = (char **) realloc (last_environ, | 136 | #endif |
80 | (size + 2) * sizeof (char *)); | ||
81 | else | ||
82 | new_environ = (char **) malloc ((size + 2) * sizeof (char *)); | ||
83 | 137 | ||
138 | /* We allocated this space; we can extend it. */ | ||
139 | new_environ = | ||
140 | (char **) (last_environ == NULL | ||
141 | ? malloc ((size + 2) * sizeof (char *)) | ||
142 | : realloc (last_environ, (size + 2) * sizeof (char *))); | ||
84 | if (new_environ == NULL) | 143 | if (new_environ == NULL) |
85 | { | 144 | { |
86 | UNLOCK; | 145 | UNLOCK; |
87 | return -1; | 146 | return -1; |
88 | } | 147 | } |
89 | 148 | ||
90 | new_environ[size] = malloc (namelen + 1 + vallen); | 149 | /* If the whole entry is given add it. */ |
91 | if (new_environ[size] == NULL) | 150 | if (combined != NULL) |
151 | /* We must not add the string to the search tree since it belongs | ||
152 | to the user. */ | ||
153 | new_environ[size] = (char *) combined; | ||
154 | else | ||
92 | { | 155 | { |
93 | free ((char *) new_environ); | 156 | /* See whether the value is already known. */ |
94 | errno = ENOMEM; | 157 | #ifdef USE_TSEARCH |
158 | # ifdef _LIBC | ||
159 | new_value = (char *) alloca (namelen + 1 + vallen); | ||
160 | __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), | ||
161 | value, vallen); | ||
162 | # else | ||
163 | new_value = (char *) allocsa (namelen + 1 + vallen); | ||
164 | if (new_value == NULL) | ||
165 | { | ||
166 | __set_errno (ENOMEM); | ||
95 | UNLOCK; | 167 | UNLOCK; |
96 | return -1; | 168 | return -1; |
97 | } | 169 | } |
170 | memcpy (new_value, name, namelen); | ||
171 | new_value[namelen] = '='; | ||
172 | memcpy (&new_value[namelen + 1], value, vallen); | ||
173 | # endif | ||
98 | 174 | ||
99 | if (__environ != last_environ) | 175 | new_environ[size] = KNOWN_VALUE (new_value); |
100 | memcpy ((char *) new_environ, (char *) __environ, | 176 | if (new_environ[size] == NULL) |
101 | size * sizeof (char *)); | 177 | #endif |
178 | { | ||
179 | new_environ[size] = (char *) malloc (namelen + 1 + vallen); | ||
180 | if (new_environ[size] == NULL) | ||
181 | { | ||
182 | #if defined USE_TSEARCH && !defined _LIBC | ||
183 | freesa (new_value); | ||
184 | #endif | ||
185 | __set_errno (ENOMEM); | ||
186 | UNLOCK; | ||
187 | return -1; | ||
188 | } | ||
102 | 189 | ||
190 | #ifdef USE_TSEARCH | ||
191 | memcpy (new_environ[size], new_value, namelen + 1 + vallen); | ||
192 | #else | ||
103 | memcpy (new_environ[size], name, namelen); | 193 | memcpy (new_environ[size], name, namelen); |
104 | new_environ[size][namelen] = '='; | 194 | new_environ[size][namelen] = '='; |
105 | memcpy (&new_environ[size][namelen + 1], value, vallen); | 195 | memcpy (&new_environ[size][namelen + 1], value, vallen); |
196 | #endif | ||
197 | /* And save the value now. We cannot do this when we remove | ||
198 | the string since then we cannot decide whether it is a | ||
199 | user string or not. */ | ||
200 | STORE_VALUE (new_environ[size]); | ||
201 | } | ||
202 | #if defined USE_TSEARCH && !defined _LIBC | ||
203 | freesa (new_value); | ||
204 | #endif | ||
205 | } | ||
206 | |||
207 | if (__environ != last_environ) | ||
208 | memcpy ((char *) new_environ, (char *) __environ, | ||
209 | size * sizeof (char *)); | ||
106 | 210 | ||
107 | new_environ[size + 1] = NULL; | 211 | new_environ[size + 1] = NULL; |
108 | 212 | ||
... | @@ -110,21 +214,63 @@ setenv (name, value, replace) | ... | @@ -110,21 +214,63 @@ setenv (name, value, replace) |
110 | } | 214 | } |
111 | else if (replace) | 215 | else if (replace) |
112 | { | 216 | { |
113 | size_t len = strlen (*ep); | 217 | char *np; |
114 | if (len + 1 < namelen + 1 + vallen) | 218 | |
219 | /* Use the user string if given. */ | ||
220 | if (combined != NULL) | ||
221 | np = (char *) combined; | ||
222 | else | ||
115 | { | 223 | { |
116 | /* The existing string is too short; malloc a new one. */ | 224 | #ifdef USE_TSEARCH |
117 | char *new = malloc (namelen + 1 + vallen); | 225 | char *new_value; |
118 | if (new == NULL) | 226 | # ifdef _LIBC |
227 | new_value = alloca (namelen + 1 + vallen); | ||
228 | __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1), | ||
229 | value, vallen); | ||
230 | # else | ||
231 | new_value = allocsa (namelen + 1 + vallen); | ||
232 | if (new_value == NULL) | ||
119 | { | 233 | { |
234 | __set_errno (ENOMEM); | ||
120 | UNLOCK; | 235 | UNLOCK; |
121 | return -1; | 236 | return -1; |
122 | } | 237 | } |
123 | *ep = new; | 238 | memcpy (new_value, name, namelen); |
239 | new_value[namelen] = '='; | ||
240 | memcpy (&new_value[namelen + 1], value, vallen); | ||
241 | # endif | ||
242 | |||
243 | np = KNOWN_VALUE (new_value); | ||
244 | if (np == NULL) | ||
245 | #endif | ||
246 | { | ||
247 | np = malloc (namelen + 1 + vallen); | ||
248 | if (np == NULL) | ||
249 | { | ||
250 | #if defined USE_TSEARCH && !defined _LIBC | ||
251 | freesa (new_value); | ||
252 | #endif | ||
253 | __set_errno (ENOMEM); | ||
254 | UNLOCK; | ||
255 | return -1; | ||
124 | } | 256 | } |
125 | memcpy (*ep, name, namelen); | 257 | |
126 | (*ep)[namelen] = '='; | 258 | #ifdef USE_TSEARCH |
127 | memcpy (&(*ep)[namelen + 1], value, vallen); | 259 | memcpy (np, new_value, namelen + 1 + vallen); |
260 | #else | ||
261 | memcpy (np, name, namelen); | ||
262 | np[namelen] = '='; | ||
263 | memcpy (&np[namelen + 1], value, vallen); | ||
264 | #endif | ||
265 | /* And remember the value. */ | ||
266 | STORE_VALUE (np); | ||
267 | } | ||
268 | #if defined USE_TSEARCH && !defined _LIBC | ||
269 | freesa (new_value); | ||
270 | #endif | ||
271 | } | ||
272 | |||
273 | *ep = np; | ||
128 | } | 274 | } |
129 | 275 | ||
130 | UNLOCK; | 276 | UNLOCK; |
... | @@ -132,25 +278,51 @@ setenv (name, value, replace) | ... | @@ -132,25 +278,51 @@ setenv (name, value, replace) |
132 | return 0; | 278 | return 0; |
133 | } | 279 | } |
134 | 280 | ||
135 | void | 281 | int |
136 | unsetenv (name) | 282 | setenv (const char *name, const char *value, int replace) |
137 | const char *name; | ||
138 | { | 283 | { |
139 | const size_t len = strlen (name); | 284 | return __add_to_environ (name, value, NULL, replace); |
140 | char **ep; | 285 | } |
141 | 286 | ||
287 | /* The `clearenv' was planned to be added to POSIX.1 but probably | ||
288 | never made it. Nevertheless the POSIX.9 standard (POSIX bindings | ||
289 | for Fortran 77) requires this function. */ | ||
290 | int | ||
291 | clearenv (void) | ||
292 | { | ||
142 | LOCK; | 293 | LOCK; |
143 | 294 | ||
144 | for (ep = __environ; *ep; ++ep) | 295 | if (__environ == last_environ && __environ != NULL) |
145 | if (!strncmp (*ep, name, len) && (*ep)[len] == '=') | ||
146 | { | 296 | { |
147 | /* Found it. Remove this pointer by moving later ones back. */ | 297 | /* We allocated this environment so we can free it. */ |
148 | char **dp = ep; | 298 | free (__environ); |
149 | do | 299 | last_environ = NULL; |
150 | dp[0] = dp[1]; | ||
151 | while (*dp++); | ||
152 | /* Continue the loop in case NAME appears again. */ | ||
153 | } | 300 | } |
154 | 301 | ||
302 | /* Clear the environment pointer removes the whole environment. */ | ||
303 | __environ = NULL; | ||
304 | |||
155 | UNLOCK; | 305 | UNLOCK; |
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | #ifdef _LIBC | ||
311 | static void | ||
312 | free_mem (void) | ||
313 | { | ||
314 | /* Remove all traces. */ | ||
315 | clearenv (); | ||
316 | |||
317 | /* Now remove the search tree. */ | ||
318 | __tdestroy (known_values, free); | ||
319 | known_values = NULL; | ||
156 | } | 320 | } |
321 | text_set_element (__libc_subfreeres, free_mem); | ||
322 | |||
323 | |||
324 | # undef setenv | ||
325 | # undef clearenv | ||
326 | weak_alias (__setenv, setenv) | ||
327 | weak_alias (__clearenv, clearenv) | ||
328 | #endif | ... | ... |
1 | 1 | /* Formatted output to strings. | |
2 | /* | 2 | Copyright (C) 2004 Free Software Foundation, Inc. |
3 | Unix snprintf implementation. | 3 | Written by Simon Josefsson. |
4 | Version 1.3 | ||
5 | 4 | ||
6 | This program is free software; you can redistribute it and/or modify | 5 | This program is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU Library General Public License as published by | 6 | it under the terms of the GNU General Public License as published by |
8 | the Free Software Foundation; either version 2 of the License, or | 7 | the Free Software Foundation; either version 2, or (at your option) |
9 | (at your option) any later version. | 8 | any later version. |
10 | 9 | ||
11 | This program is distributed in the hope that it will be useful, | 10 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | GNU Library General Public License for more details. | 13 | GNU General Public License for more details. |
15 | |||
16 | You should have received a copy of the GNU Library General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | |||
20 | Revision History: | ||
21 | |||
22 | 1.3: | ||
23 | * add #include <config.h> ifdef HAVE_CONFIG_H | ||
24 | * cosmetic change, when exponent is 0 print xxxE+00 | ||
25 | instead of xxxE-00 | ||
26 | 1.2: | ||
27 | * put the program under LGPL. | ||
28 | 1.1: | ||
29 | * added changes from Miles Bader | ||
30 | * corrected a bug with %f | ||
31 | * added support for %#g | ||
32 | * added more comments :-) | ||
33 | 1.0: | ||
34 | * supporting must ANSI syntaxic_sugars | ||
35 | 0.0: | ||
36 | * suppot %s %c %d | ||
37 | |||
38 | THANKS(for the patches and ideas): | ||
39 | Miles Bader | ||
40 | Cyrille Rustom | ||
41 | Jacek Slabocewiz | ||
42 | Mike Parker(mouse) | ||
43 | |||
44 | */ | ||
45 | |||
46 | #include "snprintf.h" | ||
47 | |||
48 | /* | ||
49 | * Find the nth power of 10 | ||
50 | */ | ||
51 | PRIVATE double | ||
52 | #ifdef __STDC__ | ||
53 | pow_10(int n) | ||
54 | #else | ||
55 | pow_10(n) | ||
56 | int n; | ||
57 | #endif | ||
58 | { | ||
59 | int i; | ||
60 | double P; | ||
61 | |||
62 | if (n < 0) | ||
63 | for (i = 1, P = 1., n = -n ; i <= n ; i++) {P *= .1;} | ||
64 | else | ||
65 | for (i = 1, P = 1. ; i <= n ; i++) {P *= 10.0;} | ||
66 | return P; | ||
67 | } | ||
68 | |||
69 | /* | ||
70 | * Find the integral part of the log in base 10 | ||
71 | * Note: this not a real log10() | ||
72 | I just need and approximation(integerpart) of x in: | ||
73 | 10^x ~= r | ||
74 | * log_10(200) = 2; | ||
75 | * log_10(250) = 2; | ||
76 | */ | ||
77 | PRIVATE int | ||
78 | #ifdef __STDC__ | ||
79 | log_10(double r) | ||
80 | #else | ||
81 | log_10(r) | ||
82 | double r; | ||
83 | #endif | ||
84 | { | ||
85 | int i = 0; | ||
86 | double result = 1.; | ||
87 | |||
88 | if (r < 0.) | ||
89 | r = -r; | ||
90 | |||
91 | if (r < 1.) { | ||
92 | while (result >= r) {result *= .1; i++;} | ||
93 | return (-i); | ||
94 | } else { | ||
95 | while (result <= r) {result *= 10.; i++;} | ||
96 | return (i - 1); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * This function return the fraction part of a double | ||
102 | * and set in ip the integral part. | ||
103 | * In many ways it resemble the modf() found on most Un*x | ||
104 | */ | ||
105 | PRIVATE double | ||
106 | #ifdef __STDC__ | ||
107 | integral(double real, double * ip) | ||
108 | #else | ||
109 | integral(real, ip) | ||
110 | double real; | ||
111 | double * ip; | ||
112 | #endif | ||
113 | { | ||
114 | int j; | ||
115 | double i, s, p; | ||
116 | double real_integral = 0.; | ||
117 | |||
118 | /* take care of the obvious */ | ||
119 | /* equal to zero ? */ | ||
120 | if (real == 0.) { | ||
121 | *ip = 0.; | ||
122 | return (0.); | ||
123 | } | ||
124 | |||
125 | /* negative number ? */ | ||
126 | if (real < 0.) | ||
127 | real = -real; | ||
128 | |||
129 | /* a fraction ? */ | ||
130 | if ( real < 1.) { | ||
131 | *ip = 0.; | ||
132 | return real; | ||
133 | } | ||
134 | /* the real work :-) */ | ||
135 | for (j = log_10(real); j >= 0; j--) { | ||
136 | p = pow_10(j); | ||
137 | s = (real - real_integral)/p; | ||
138 | i = 0.; | ||
139 | while (i + 1. <= s) {i++;} | ||
140 | real_integral += i*p; | ||
141 | } | ||
142 | *ip = real_integral; | ||
143 | return (real - real_integral); | ||
144 | } | ||
145 | |||
146 | #define PRECISION 1.e-6 | ||
147 | /* | ||
148 | * return an ascii representation of the integral part of the number | ||
149 | * and set fract to be an ascii representation of the fraction part | ||
150 | * the container for the fraction and the integral part or staticly | ||
151 | * declare with fix size | ||
152 | */ | ||
153 | PRIVATE char * | ||
154 | #ifdef __STDC__ | ||
155 | numtoa(double number, int base, int precision, char ** fract) | ||
156 | #else | ||
157 | numtoa(number, base, precision, fract) | ||
158 | double number; | ||
159 | int base; | ||
160 | int precision; | ||
161 | char ** fract; | ||
162 | #endif | ||
163 | { | ||
164 | register int i, j; | ||
165 | double ip, fp; /* integer and fraction part */ | ||
166 | double fraction; | ||
167 | int digits = MAX_INT - 1; | ||
168 | static char integral_part[MAX_INT]; | ||
169 | static char fraction_part[MAX_FRACT]; | ||
170 | double sign; | ||
171 | int ch; | ||
172 | |||
173 | /* taking care of the obvious case: 0.0 */ | ||
174 | if (number == 0.) { | ||
175 | integral_part[0] = '0'; | ||
176 | integral_part[1] = '\0'; | ||
177 | fraction_part[0] = '0'; | ||
178 | fraction_part[1] = '\0'; | ||
179 | return integral_part; | ||
180 | } | ||
181 | |||
182 | /* for negative numbers */ | ||
183 | if ((sign = number) < 0.) { | ||
184 | number = -number; | ||
185 | digits--; /* sign consume one digit */ | ||
186 | } | ||
187 | |||
188 | fraction = integral(number, &ip); | ||
189 | number = ip; | ||
190 | /* do the integral part */ | ||
191 | if ( ip == 0.) { | ||
192 | integral_part[0] = '0'; | ||
193 | i = 1; | ||
194 | } else { | ||
195 | for ( i = 0; i < digits && number != 0.; ++i) { | ||
196 | number /= base; | ||
197 | fp = integral(number, &ip); | ||
198 | ch = (int)((fp + PRECISION)*base); /* force to round */ | ||
199 | integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10; | ||
200 | if (! isxdigit(integral_part[i])) /* bail out overflow !! */ | ||
201 | break; | ||
202 | number = ip; | ||
203 | } | ||
204 | } | ||
205 | |||
206 | /* Oh No !! out of bound, ho well fill it up ! */ | ||
207 | if (number != 0.) | ||
208 | for (i = 0; i < digits; ++i) | ||
209 | integral_part[i] = '9'; | ||
210 | 14 | ||
211 | /* put the sign ? */ | 15 | You should have received a copy of the GNU General Public License along |
212 | if (sign < 0.) | 16 | with this program; if not, write to the Free Software Foundation, |
213 | integral_part[i++] = '-'; | 17 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
214 | 18 | ||
215 | integral_part[i] = '\0'; | 19 | #ifdef HAVE_CONFIG_H |
216 | 20 | # include <config.h> | |
217 | /* reverse every thing */ | ||
218 | for ( i--, j = 0; j < i; j++, i--) | ||
219 | SWAP_INT(integral_part[i], integral_part[j]); | ||
220 | |||
221 | /* the fractionnal part */ | ||
222 | for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision-- ) { | ||
223 | fraction_part[i] = (int)((fp + PRECISION)*10. + '0'); | ||
224 | if (! isdigit(fraction_part[i])) /* underflow ? */ | ||
225 | break; | ||
226 | fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.); | ||
227 | } | ||
228 | fraction_part[i] = '\0'; | ||
229 | |||
230 | if (fract != (char **)0) | ||
231 | *fract = fraction_part; | ||
232 | |||
233 | return integral_part; | ||
234 | |||
235 | } | ||
236 | |||
237 | /* for %d and friends, it puts in holder | ||
238 | * the representation with the right padding | ||
239 | */ | ||
240 | PRIVATE void | ||
241 | #ifdef __STDC__ | ||
242 | decimal(struct DATA *p, double d) | ||
243 | #else | ||
244 | decimal(p, d) | ||
245 | struct DATA *p; | ||
246 | double d; | ||
247 | #endif | 21 | #endif |
248 | { | ||
249 | char *tmp; | ||
250 | 22 | ||
251 | tmp = itoa(d); | 23 | #include "snprintf.h" |
252 | p->width -= strlen(tmp); | ||
253 | PAD_RIGHT(p); | ||
254 | PUT_PLUS(d, p); | ||
255 | PUT_SPACE(d, p); | ||
256 | while (*tmp) { /* the integral */ | ||
257 | PUT_CHAR(*tmp, p); | ||
258 | tmp++; | ||
259 | } | ||
260 | PAD_LEFT(p); | ||
261 | } | ||
262 | |||
263 | /* for %o octal representation */ | ||
264 | PRIVATE void | ||
265 | #ifdef __STDC__ | ||
266 | octal(struct DATA *p, double d) | ||
267 | #else | ||
268 | octal(p, d) | ||
269 | struct DATA *p; | ||
270 | double d; | ||
271 | #endif | ||
272 | { | ||
273 | char *tmp; | ||
274 | |||
275 | tmp = otoa(d); | ||
276 | p->width -= strlen(tmp); | ||
277 | PAD_RIGHT(p); | ||
278 | if (p->square == FOUND) /* had prefix '0' for octal */ | ||
279 | PUT_CHAR('0', p); | ||
280 | while (*tmp) { /* octal */ | ||
281 | PUT_CHAR(*tmp, p); | ||
282 | tmp++; | ||
283 | } | ||
284 | PAD_LEFT(p); | ||
285 | } | ||
286 | |||
287 | /* for %x %X hexadecimal representation */ | ||
288 | PRIVATE void | ||
289 | #ifdef __STDC__ | ||
290 | hexa(struct DATA *p, double d) | ||
291 | #else | ||
292 | hexa(p, d) | ||
293 | struct DATA *p; | ||
294 | double d; | ||
295 | #endif | ||
296 | { | ||
297 | char *tmp; | ||
298 | |||
299 | tmp = htoa(d); | ||
300 | p->width -= strlen(tmp); | ||
301 | PAD_RIGHT(p); | ||
302 | if (p->square == FOUND) { /* prefix '0x' for hexa */ | ||
303 | PUT_CHAR('0', p); PUT_CHAR(*p->pf, p); | ||
304 | } | ||
305 | while (*tmp) { /* hexa */ | ||
306 | PUT_CHAR((*p->pf == 'X' ? toupper(*tmp) : *tmp), p); | ||
307 | tmp++; | ||
308 | } | ||
309 | PAD_LEFT(p); | ||
310 | } | ||
311 | |||
312 | /* %s strings */ | ||
313 | PRIVATE void | ||
314 | #ifdef __STDC__ | ||
315 | strings(struct DATA *p, char *tmp) | ||
316 | #else | ||
317 | strings(p, tmp) | ||
318 | struct DATA *p; | ||
319 | char *tmp; | ||
320 | #endif | ||
321 | { | ||
322 | int i; | ||
323 | |||
324 | i = strlen(tmp); | ||
325 | if (p->precision != NOT_FOUND) /* the smallest number */ | ||
326 | i = (i < p->precision ? i : p->precision); | ||
327 | p->width -= i; | ||
328 | PAD_RIGHT(p); | ||
329 | while (i-- > 0) { /* put the sting */ | ||
330 | PUT_CHAR(*tmp, p); | ||
331 | tmp++; | ||
332 | } | ||
333 | PAD_LEFT(p); | ||
334 | } | ||
335 | |||
336 | /* %f or %g floating point representation */ | ||
337 | PRIVATE void | ||
338 | #ifdef __STDC__ | ||
339 | floating(struct DATA *p, double d) | ||
340 | #else | ||
341 | floating(p, d) | ||
342 | struct DATA *p; | ||
343 | double d; | ||
344 | #endif | ||
345 | { | ||
346 | char *tmp, *tmp2; | ||
347 | int i; | ||
348 | |||
349 | DEF_PREC(p); | ||
350 | d = ROUND(d, p); | ||
351 | tmp = dtoa(d, p->precision, &tmp2); | ||
352 | /* calculate the padding. 1 for the dot */ | ||
353 | p->width = p->width - | ||
354 | ((d > 0. && p->justify == RIGHT) ? 1:0) - | ||
355 | ((p->space == FOUND) ? 1:0) - | ||
356 | strlen(tmp) - p->precision - 1; | ||
357 | PAD_RIGHT(p); | ||
358 | PUT_PLUS(d, p); | ||
359 | PUT_SPACE(d, p); | ||
360 | while (*tmp) { /* the integral */ | ||
361 | PUT_CHAR(*tmp, p); | ||
362 | tmp++; | ||
363 | } | ||
364 | if (p->precision != 0 || p->square == FOUND) | ||
365 | PUT_CHAR('.', p); /* put the '.' */ | ||
366 | if (*p->pf == 'g' || *p->pf == 'G') /* smash the trailing zeros */ | ||
367 | for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--) | ||
368 | tmp2[i] = '\0'; | ||
369 | for (; *tmp2; tmp2++) | ||
370 | PUT_CHAR(*tmp2, p); /* the fraction */ | ||
371 | |||
372 | PAD_LEFT(p); | ||
373 | } | ||
374 | |||
375 | /* %e %E %g exponent representation */ | ||
376 | PRIVATE void | ||
377 | #ifdef __STDC__ | ||
378 | exponent(struct DATA *p, double d) | ||
379 | #else | ||
380 | exponent(p, d) | ||
381 | struct DATA *p; | ||
382 | double d; | ||
383 | #endif | ||
384 | { | ||
385 | char *tmp, *tmp2; | ||
386 | int j, i; | ||
387 | |||
388 | DEF_PREC(p); | ||
389 | j = log_10(d); | ||
390 | d = d / pow_10(j); /* get the Mantissa */ | ||
391 | d = ROUND(d, p); | ||
392 | tmp = dtoa(d, p->precision, &tmp2); | ||
393 | /* 1 for unit, 1 for the '.', 1 for 'e|E', | ||
394 | * 1 for '+|-', 3 for 'exp' */ | ||
395 | /* calculate how much padding need */ | ||
396 | p->width = p->width - | ||
397 | ((d > 0. && p->justify == RIGHT) ? 1:0) - | ||
398 | ((p->space == FOUND) ? 1:0) - p->precision - 7; | ||
399 | PAD_RIGHT(p); | ||
400 | PUT_PLUS(d, p); | ||
401 | PUT_SPACE(d, p); | ||
402 | while (*tmp) {/* the integral */ | ||
403 | PUT_CHAR(*tmp, p); | ||
404 | tmp++; | ||
405 | } | ||
406 | if (p->precision != 0 || p->square == FOUND) | ||
407 | PUT_CHAR('.', p); /* the '.' */ | ||
408 | if (*p->pf == 'g' || *p->pf == 'G') /* smash the trailing zeros */ | ||
409 | for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--) | ||
410 | tmp2[i] = '\0'; | ||
411 | for (; *tmp2; tmp2++) | ||
412 | PUT_CHAR(*tmp2, p); /* the fraction */ | ||
413 | |||
414 | if (*p->pf == 'g' || *p->pf == 'e') { /* the exponent put the 'e|E' */ | ||
415 | PUT_CHAR('e', p); | ||
416 | } else | ||
417 | PUT_CHAR('E', p); | ||
418 | if (j >= 0) { /* the sign of the exp */ | ||
419 | PUT_CHAR('+', p); | ||
420 | } else { | ||
421 | PUT_CHAR('-', p); | ||
422 | j = -j; | ||
423 | } | ||
424 | tmp = itoa((double)j); | ||
425 | if (j < 9) { /* need to pad the exponent with 0 '000' */ | ||
426 | PUT_CHAR('0', p); PUT_CHAR('0', p); | ||
427 | } else if (j < 99) | ||
428 | PUT_CHAR('0', p); | ||
429 | while (*tmp) { /* the exponent */ | ||
430 | PUT_CHAR(*tmp, p); | ||
431 | tmp++; | ||
432 | } | ||
433 | PAD_LEFT(p); | ||
434 | } | ||
435 | |||
436 | /* initialize the conversion specifiers */ | ||
437 | PRIVATE void | ||
438 | #ifdef __STDC__ | ||
439 | conv_flag(char * s, struct DATA * p) | ||
440 | #else | ||
441 | conv_flag(s, p) | ||
442 | char * s; | ||
443 | struct DATA * p; | ||
444 | #endif | ||
445 | { | ||
446 | char number[MAX_FIELD/2]; | ||
447 | int i; | ||
448 | |||
449 | /* reset the flags. */ | ||
450 | p->precision = p->width = NOT_FOUND; | ||
451 | p->star_w = p->star_p = NOT_FOUND; | ||
452 | p->square = p->space = NOT_FOUND; | ||
453 | p->a_long = p->justify = NOT_FOUND; | ||
454 | p->a_longlong = NOT_FOUND; | ||
455 | p->pad = ' '; | ||
456 | |||
457 | for(;s && *s ;s++) { | ||
458 | switch(*s) { | ||
459 | case ' ': p->space = FOUND; break; | ||
460 | case '#': p->square = FOUND; break; | ||
461 | case '*': if (p->width == NOT_FOUND) | ||
462 | p->width = p->star_w = FOUND; | ||
463 | else | ||
464 | p->precision = p->star_p = FOUND; | ||
465 | break; | ||
466 | case '+': p->justify = RIGHT; break; | ||
467 | case '-': p->justify = LEFT; break; | ||
468 | case '.': if (p->width == NOT_FOUND) | ||
469 | p->width = 0; | ||
470 | break; | ||
471 | case '0': p->pad = '0'; break; | ||
472 | case '1': case '2': case '3': | ||
473 | case '4': case '5': case '6': | ||
474 | case '7': case '8': case '9': /* gob all the digits */ | ||
475 | for (i = 0; isdigit(*s); i++, s++) | ||
476 | if (i < MAX_FIELD/2 - 1) | ||
477 | number[i] = *s; | ||
478 | number[i] = '\0'; | ||
479 | if (p->width == NOT_FOUND) | ||
480 | p->width = atoi(number); | ||
481 | else | ||
482 | p->precision = atoi(number); | ||
483 | s--; /* went to far go back */ | ||
484 | break; | ||
485 | } | ||
486 | } | ||
487 | } | ||
488 | |||
489 | PUBLIC int | ||
490 | #ifdef __STDC__ | ||
491 | vsnprintf(char *string, size_t length, const char * format, va_list args) | ||
492 | #else | ||
493 | vsnprintf(string, length, format, args) | ||
494 | char *string; | ||
495 | size_t length; | ||
496 | char * format; | ||
497 | va_list args; | ||
498 | #endif | ||
499 | { | ||
500 | struct DATA data; | ||
501 | char conv_field[MAX_FIELD]; | ||
502 | double d; /* temporary holder */ | ||
503 | int state; | ||
504 | int i; | ||
505 | |||
506 | data.length = length - 1; /* leave room for '\0' */ | ||
507 | data.holder = string; | ||
508 | data.pf = format; | ||
509 | data.counter = 0; | ||
510 | |||
511 | |||
512 | /* sanity check, the string must be > 1 */ | ||
513 | if (length < 1) | ||
514 | return -1; | ||
515 | |||
516 | |||
517 | for (; *data.pf && (data.counter < data.length); data.pf++) { | ||
518 | if ( *data.pf == '%' ) { /* we got a magic % cookie */ | ||
519 | conv_flag((char *)0, &data); /* initialise format flags */ | ||
520 | for (state = 1; *data.pf && state;) { | ||
521 | switch (*(++data.pf)) { | ||
522 | case '\0': /* a NULL here ? ? bail out */ | ||
523 | *data.holder = '\0'; | ||
524 | return data.counter; | ||
525 | break; | ||
526 | case 'f': /* float, double */ | ||
527 | STAR_ARGS(&data); | ||
528 | if (data.a_long == FOUND) | ||
529 | d = va_arg(args, LONG_DOUBLE); | ||
530 | else | ||
531 | d = va_arg(args, double); | ||
532 | floating(&data, d); | ||
533 | state = 0; | ||
534 | break; | ||
535 | case 'g': | ||
536 | case 'G': | ||
537 | STAR_ARGS(&data); | ||
538 | DEF_PREC(&data); | ||
539 | if (data.a_long == FOUND) | ||
540 | d = va_arg(args, LONG_DOUBLE); | ||
541 | else | ||
542 | d = va_arg(args, double); | ||
543 | i = log_10(d); | ||
544 | /* | ||
545 | * for '%g|%G' ANSI: use f if exponent | ||
546 | * is in the range or [-4,p] exclusively | ||
547 | * else use %e|%E | ||
548 | */ | ||
549 | if (-4 < i && i < data.precision) | ||
550 | floating(&data, d); | ||
551 | else | ||
552 | exponent(&data, d); | ||
553 | state = 0; | ||
554 | break; | ||
555 | case 'e': | ||
556 | case 'E': /* Exponent double */ | ||
557 | STAR_ARGS(&data); | ||
558 | if (data.a_long == FOUND) | ||
559 | d = va_arg(args, LONG_DOUBLE); | ||
560 | else | ||
561 | d = va_arg(args, double); | ||
562 | exponent(&data, d); | ||
563 | state = 0; | ||
564 | break; | ||
565 | case 'u': /* unsigned decimal */ | ||
566 | STAR_ARGS(&data); | ||
567 | if (data.a_longlong == FOUND) | ||
568 | d = va_arg(args, unsigned LONG_LONG); | ||
569 | else if (data.a_long == FOUND) | ||
570 | d = va_arg(args, unsigned long); | ||
571 | else | ||
572 | d = va_arg(args, unsigned int); | ||
573 | decimal(&data, d); | ||
574 | state = 0; | ||
575 | break; | ||
576 | case 'd': /* decimal */ | ||
577 | STAR_ARGS(&data); | ||
578 | if (data.a_longlong == FOUND) | ||
579 | d = va_arg(args, LONG_LONG); | ||
580 | else if (data.a_long == FOUND) | ||
581 | d = va_arg(args, long); | ||
582 | else | ||
583 | d = va_arg(args, int); | ||
584 | decimal(&data, d); | ||
585 | state = 0; | ||
586 | break; | ||
587 | case 'o': /* octal */ | ||
588 | STAR_ARGS(&data); | ||
589 | if (data.a_longlong == FOUND) | ||
590 | d = va_arg(args, LONG_LONG); | ||
591 | else if (data.a_long == FOUND) | ||
592 | d = va_arg(args, long); | ||
593 | else | ||
594 | d = va_arg(args, int); | ||
595 | octal(&data, d); | ||
596 | state = 0; | ||
597 | break; | ||
598 | case 'x': | ||
599 | case 'X': /* hexadecimal */ | ||
600 | STAR_ARGS(&data); | ||
601 | if (data.a_longlong == FOUND) | ||
602 | d = va_arg(args, LONG_LONG); | ||
603 | else if (data.a_long == FOUND) | ||
604 | d = va_arg(args, long); | ||
605 | else | ||
606 | d = va_arg(args, int); | ||
607 | hexa(&data, d); | ||
608 | state = 0; | ||
609 | break; | ||
610 | case 'c': /* character */ | ||
611 | d = va_arg(args, int); | ||
612 | PUT_CHAR(d, &data); | ||
613 | state = 0; | ||
614 | break; | ||
615 | case 's': /* string */ | ||
616 | STAR_ARGS(&data); | ||
617 | strings(&data, va_arg(args, char *)); | ||
618 | state = 0; | ||
619 | break; | ||
620 | case 'n': | ||
621 | *(va_arg(args, int *)) = data.counter; /* what's the count ? */ | ||
622 | state = 0; | ||
623 | break; | ||
624 | case 'q': | ||
625 | data.a_longlong = FOUND; | ||
626 | break; | ||
627 | case 'L': | ||
628 | case 'l': | ||
629 | if (data.a_long == FOUND) | ||
630 | data.a_longlong = FOUND; | ||
631 | else | ||
632 | data.a_long = FOUND; | ||
633 | break; | ||
634 | case 'h': | ||
635 | break; | ||
636 | case '%': /* nothing just % */ | ||
637 | PUT_CHAR('%', &data); | ||
638 | state = 0; | ||
639 | break; | ||
640 | case '#': case ' ': case '+': case '*': | ||
641 | case '-': case '.': case '0': case '1': | ||
642 | case '2': case '3': case '4': case '5': | ||
643 | case '6': case '7': case '8': case '9': | ||
644 | /* initialize width and precision */ | ||
645 | for (i = 0; isflag(*data.pf); i++, data.pf++) | ||
646 | if (i < MAX_FIELD - 1) | ||
647 | conv_field[i] = *data.pf; | ||
648 | conv_field[i] = '\0'; | ||
649 | conv_flag(conv_field, &data); | ||
650 | data.pf--; /* went to far go back */ | ||
651 | break; | ||
652 | default: | ||
653 | /* is this an error ? maybe bail out */ | ||
654 | state = 0; | ||
655 | break; | ||
656 | } /* end switch */ | ||
657 | } /* end of for state */ | ||
658 | } else { /* not % */ | ||
659 | PUT_CHAR(*data.pf, &data); /* add the char the string */ | ||
660 | } | ||
661 | } | ||
662 | |||
663 | *data.holder = '\0'; /* the end ye ! */ | ||
664 | 24 | ||
665 | return data.counter; | 25 | #include <stdarg.h> |
666 | } | 26 | #include <stdlib.h> |
27 | #include <string.h> | ||
667 | 28 | ||
668 | #ifndef HAVE_SNPRINTF | 29 | #include "minmax.h" |
30 | #include "vasnprintf.h" | ||
669 | 31 | ||
670 | PUBLIC int | 32 | /* Print formatted output to string STR. Similar to sprintf, but |
671 | #if __STDC__ | 33 | additional length SIZE limit how much is written into STR. Returns |
672 | snprintf(char *string, size_t length, const char * format, ...) | 34 | string length of formatted string (which may be larger than SIZE). |
673 | #else | 35 | STR may be NULL, in which case nothing will be written. On error, |
674 | snprintf(string, length, format, va_alist) | 36 | return a negative value. */ |
675 | char *string; | 37 | int |
676 | size_t length; | 38 | snprintf (char *str, size_t size, const char *format, ...) |
677 | char * format; | ||
678 | va_dcl | ||
679 | #endif | ||
680 | { | 39 | { |
681 | int rval; | 40 | char *output; |
41 | size_t len; | ||
682 | va_list args; | 42 | va_list args; |
683 | 43 | ||
684 | #if __STDC__ | 44 | va_start (args, format); |
685 | va_start(args, format); | 45 | len = size; |
686 | #else | 46 | output = vasnprintf (str, &len, format, args); |
687 | va_start(args); | 47 | va_end (args); |
688 | #endif | ||
689 | |||
690 | rval = vsnprintf (string, length, format, args); | ||
691 | |||
692 | va_end(args); | ||
693 | |||
694 | return rval; | ||
695 | } | ||
696 | |||
697 | #endif /* HAVE_SNPRINTF */ | ||
698 | |||
699 | |||
700 | #ifdef DRIVER | ||
701 | |||
702 | #include <stdio.h> | ||
703 | |||
704 | /* set of small tests for snprintf() */ | ||
705 | int main() | ||
706 | { | ||
707 | char holder[100]; | ||
708 | int i; | ||
709 | 48 | ||
710 | /* | 49 | if (!output) |
711 | printf("Suite of test for snprintf:\n"); | 50 | return -1; |
712 | printf("a_format\n"); | ||
713 | printf("printf() format\n"); | ||
714 | printf("snprintf() format\n\n"); | ||
715 | */ | ||
716 | /* Checking the field widths */ | ||
717 | |||
718 | printf("/%%d/, 336\n"); | ||
719 | snprintf(holder, sizeof holder, "/%d/\n", 336); | ||
720 | printf("/%d/\n", 336); | ||
721 | printf("%s\n", holder); | ||
722 | |||
723 | printf("/%%2d/, 336\n"); | ||
724 | snprintf(holder, sizeof holder, "/%2d/\n", 336); | ||
725 | printf("/%2d/\n", 336); | ||
726 | printf("%s\n", holder); | ||
727 | |||
728 | printf("/%%10d/, 336\n"); | ||
729 | snprintf(holder, sizeof holder, "/%10d/\n", 336); | ||
730 | printf("/%10d/\n", 336); | ||
731 | printf("%s\n", holder); | ||
732 | |||
733 | printf("/%%-10d/, 336\n"); | ||
734 | snprintf(holder, sizeof holder, "/%-10d/\n", 336); | ||
735 | printf("/%-10d/\n", 336); | ||
736 | printf("%s\n", holder); | ||
737 | |||
738 | /* long long */ | ||
739 | |||
740 | printf("/%%lld/, 336\n"); | ||
741 | snprintf(holder, sizeof holder, "/%lld/\n", (LONG_LONG)336); | ||
742 | printf("/%lld/\n", (LONG_LONG)336); | ||
743 | printf("%s\n", holder); | ||
744 | |||
745 | printf("/%%2qd/, 336\n"); | ||
746 | snprintf(holder, sizeof holder, "/%2qd/\n", (LONG_LONG)336); | ||
747 | printf("/%2qd/\n", (LONG_LONG)336); | ||
748 | printf("%s\n", holder); | ||
749 | |||
750 | /* floating points */ | ||
751 | |||
752 | printf("/%%f/, 1234.56\n"); | ||
753 | snprintf(holder, sizeof holder, "/%f/\n", 1234.56); | ||
754 | printf("/%f/\n", 1234.56); | ||
755 | printf("%s\n", holder); | ||
756 | |||
757 | printf("/%%e/, 1234.56\n"); | ||
758 | snprintf(holder, sizeof holder, "/%e/\n", 1234.56); | ||
759 | printf("/%e/\n", 1234.56); | ||
760 | printf("%s\n", holder); | ||
761 | |||
762 | printf("/%%4.2f/, 1234.56\n"); | ||
763 | snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56); | ||
764 | printf("/%4.2f/\n", 1234.56); | ||
765 | printf("%s\n", holder); | ||
766 | |||
767 | printf("/%%3.1f/, 1234.56\n"); | ||
768 | snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56); | ||
769 | printf("/%3.1f/\n", 1234.56); | ||
770 | printf("%s\n", holder); | ||
771 | |||
772 | printf("/%%10.3f/, 1234.56\n"); | ||
773 | snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56); | ||
774 | printf("/%10.3f/\n", 1234.56); | ||
775 | printf("%s\n", holder); | ||
776 | |||
777 | printf("/%%10.3e/, 1234.56\n"); | ||
778 | snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56); | ||
779 | printf("/%10.3e/\n", 1234.56); | ||
780 | printf("%s\n", holder); | ||
781 | |||
782 | printf("/%%+4.2f/, 1234.56\n"); | ||
783 | snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56); | ||
784 | printf("/%+4.2f/\n", 1234.56); | ||
785 | printf("%s\n", holder); | ||
786 | |||
787 | printf("/%%010.2f/, 1234.56\n"); | ||
788 | snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56); | ||
789 | printf("/%010.2f/\n", 1234.56); | ||
790 | printf("%s\n", holder); | ||
791 | |||
792 | #define BLURB "Outstanding acting !" | ||
793 | /* strings precisions */ | ||
794 | |||
795 | printf("/%%2s/, \"%s\"\n", BLURB); | ||
796 | snprintf(holder, sizeof holder, "/%2s/\n", BLURB); | ||
797 | printf("/%2s/\n", BLURB); | ||
798 | printf("%s\n", holder); | ||
799 | |||
800 | printf("/%%22s/ %s\n", BLURB); | ||
801 | snprintf(holder, sizeof holder, "/%22s/\n", BLURB); | ||
802 | printf("/%22s/\n", BLURB); | ||
803 | printf("%s\n", holder); | ||
804 | |||
805 | printf("/%%22.5s/ %s\n", BLURB); | ||
806 | snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB); | ||
807 | printf("/%22.5s/\n", BLURB); | ||
808 | printf("%s\n", holder); | ||
809 | |||
810 | printf("/%%-22.5s/ %s\n", BLURB); | ||
811 | snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB); | ||
812 | printf("/%-22.5s/\n", BLURB); | ||
813 | printf("%s\n", holder); | ||
814 | |||
815 | /* see some flags */ | ||
816 | |||
817 | printf("%%x %%X %%#x, 31, 31, 31\n"); | ||
818 | snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31); | ||
819 | printf("%x %X %#x\n", 31, 31, 31); | ||
820 | printf("%s\n", holder); | ||
821 | |||
822 | printf("**%%d**%% d**%% d**, 42, 42, -42\n"); | ||
823 | snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42); | ||
824 | printf("**%d**% d**% d**\n", 42, 42, -42); | ||
825 | printf("%s\n", holder); | ||
826 | |||
827 | /* other flags */ | ||
828 | |||
829 | printf("/%%g/, 31.4\n"); | ||
830 | snprintf(holder, sizeof holder, "/%g/\n", 31.4); | ||
831 | printf("/%g/\n", 31.4); | ||
832 | printf("%s\n", holder); | ||
833 | |||
834 | printf("/%%.6g/, 31.4\n"); | ||
835 | snprintf(holder, sizeof holder, "/%.6g/\n", 31.4); | ||
836 | printf("/%.6g/\n", 31.4); | ||
837 | printf("%s\n", holder); | ||
838 | |||
839 | printf("/%%.1G/, 31.4\n"); | ||
840 | snprintf(holder, sizeof holder, "/%.1G/\n", 31.4); | ||
841 | printf("/%.1G/\n", 31.4); | ||
842 | printf("%s\n", holder); | ||
843 | |||
844 | printf("abc%%n\n"); | ||
845 | printf("abc%n", &i); printf("%d\n", i); | ||
846 | snprintf(holder, sizeof holder, "abc%n", &i); | ||
847 | printf("%s", holder); printf("%d\n\n", i); | ||
848 | |||
849 | printf("%%*.*s --> 10.10\n"); | ||
850 | snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB); | ||
851 | printf("%*.*s\n", 10, 10, BLURB); | ||
852 | printf("%s\n", holder); | ||
853 | 51 | ||
854 | printf("%%%%%%%%\n"); | 52 | if (str != NULL) |
855 | snprintf(holder, sizeof holder, "%%%%\n"); | 53 | if (len > size - 1) /* equivalent to: (size > 0 && len >= size) */ |
856 | printf("%%%%\n"); | 54 | str[size - 1] = '\0'; |
857 | printf("%s\n", holder); | ||
858 | 55 | ||
859 | #define BIG "Hello this is a too big string for the buffer" | 56 | if (output != str) |
860 | /* printf("A buffer to small of 10, trying to put this:\n");*/ | 57 | free (output); |
861 | printf("<%%>, %s\n", BIG); | ||
862 | i = snprintf(holder, 10, "%s\n", BIG); | ||
863 | printf("<%s>\n", BIG); | ||
864 | printf("<%s>\n", holder); | ||
865 | 58 | ||
866 | return 0; | 59 | return len; |
867 | } | 60 | } |
868 | #endif | ... | ... |
1 | /* | 1 | /* Formatted output to strings. |
2 | Unix snprintf implementation. | 2 | Copyright (C) 2004 Free Software Foundation, Inc. |
3 | Version 1.3 | 3 | Written by Simon Josefsson. |
4 | 4 | ||
5 | This program is free software; you can redistribute it and/or modify | 5 | This program is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU Library General Public License as published by | 6 | it under the terms of the GNU General Public License as published by |
7 | the Free Software Foundation; either version 2 of the License, or | 7 | the Free Software Foundation; either version 2, or (at your option) |
8 | (at your option) any later version. | 8 | any later version. |
9 | 9 | ||
10 | This program is distributed in the hope that it will be useful, | 10 | This program is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | GNU Library General Public License for more details. | 13 | GNU General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU Library General Public License | 15 | You should have received a copy of the GNU General Public License along |
16 | along with this program; if not, write to the Free Software | 16 | with this program; if not, write to the Free Software Foundation, |
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 17 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
18 | 18 | ||
19 | Revision History: | 19 | #ifndef SNPRINTF_H |
20 | see header of snprintf.c. | 20 | #define SNPRINTF_H |
21 | 21 | ||
22 | format: | 22 | /* Get snprintf declaration, if available. */ |
23 | int snprintf(holder, sizeof_holder, format, ...) | 23 | #include <stdio.h> |
24 | 24 | ||
25 | Return values: | 25 | #if defined HAVE_DECL_SNPRINTF && !HAVE_DECL_SNPRINTF |
26 | (sizeof_holder - 1) | 26 | int snprintf (char *str, size_t size, const char *format, ...); |
27 | |||
28 | |||
29 | THANKS(for the patches and ideas): | ||
30 | Miles Bader | ||
31 | Cyrille Rustom | ||
32 | Jacek Slabocewiz | ||
33 | Mike Parker(mouse) | ||
34 | |||
35 | Alain Magloire: alainm@rcsm.ee.mcgill.ca | ||
36 | */ | ||
37 | |||
38 | #ifdef HAVE_CONFIG_H | ||
39 | #include <config.h> | ||
40 | #endif | ||
41 | |||
42 | #if __STDC__ | ||
43 | #include <stdarg.h> | ||
44 | #else | ||
45 | #include <varargs.h> | ||
46 | #endif | ||
47 | |||
48 | #include <stdlib.h> /* for atoi() */ | ||
49 | #include <ctype.h> | ||
50 | |||
51 | |||
52 | /* | ||
53 | * For the FLOATING POINT FORMAT : | ||
54 | * the challenge was finding a way to | ||
55 | * manipulate the Real numbers without having | ||
56 | * to resort to mathematical function(it | ||
57 | * would require to link with -lm) and not | ||
58 | * going down to the bit pattern(not portable) | ||
59 | * | ||
60 | * so a number, a real is: | ||
61 | |||
62 | real = integral + fraction | ||
63 | |||
64 | integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0 | ||
65 | fraction = b(1)*10^-1 + b(2)*10^-2 + ... | ||
66 | |||
67 | where: | ||
68 | 0 <= a(i) => 9 | ||
69 | 0 <= b(i) => 9 | ||
70 | |||
71 | from then it was simple math | ||
72 | */ | ||
73 | |||
74 | /* | ||
75 | * size of the buffer for the integral part | ||
76 | * and the fraction part | ||
77 | */ | ||
78 | #define MAX_INT 99 + 1 /* 1 for the null */ | ||
79 | #define MAX_FRACT 29 + 1 | ||
80 | |||
81 | /* | ||
82 | * If the compiler supports (long long) | ||
83 | */ | ||
84 | #ifndef LONG_LONG | ||
85 | # define LONG_LONG long long | ||
86 | /*# define LONG_LONG int64_t*/ | ||
87 | #endif | ||
88 | |||
89 | /* | ||
90 | * If the compiler supports (long double) | ||
91 | */ | ||
92 | #ifndef LONG_DOUBLE | ||
93 | # define LONG_DOUBLE long double | ||
94 | /*# define LONG_DOUBLE double*/ | ||
95 | #endif | 27 | #endif |
96 | 28 | ||
97 | /* | 29 | #endif /* SNPRINTF_H */ |
98 | * numtoa() uses PRIVATE buffers to store the results, | ||
99 | * So this function is not reentrant | ||
100 | */ | ||
101 | #define itoa(n) numtoa(n, 10, 0, (char **)0) | ||
102 | #define otoa(n) numtoa(n, 8, 0, (char **)0) | ||
103 | #define htoa(n) numtoa(n, 16, 0, (char **)0) | ||
104 | #define dtoa(n, p, f) numtoa(n, 10, p, f) | ||
105 | |||
106 | #define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;} | ||
107 | |||
108 | /* this struct holds everything we need */ | ||
109 | struct DATA { | ||
110 | int length; | ||
111 | char *holder; | ||
112 | int counter; | ||
113 | #ifdef __STDC__ | ||
114 | const char *pf; | ||
115 | #else | ||
116 | char *pf; | ||
117 | #endif | ||
118 | /* FLAGS */ | ||
119 | int width, precision; | ||
120 | int justify; char pad; | ||
121 | int square, space, star_w, star_p, a_long, a_longlong; | ||
122 | }; | ||
123 | |||
124 | #define PRIVATE static | ||
125 | #define PUBLIC | ||
126 | /* signature of the functions */ | ||
127 | #ifdef __STDC__ | ||
128 | /* the floating point stuff */ | ||
129 | PRIVATE double pow_10(int); | ||
130 | PRIVATE int log_10(double); | ||
131 | PRIVATE double integral(double, double *); | ||
132 | PRIVATE char * numtoa(double, int, int, char **); | ||
133 | |||
134 | /* for the format */ | ||
135 | PRIVATE void conv_flag(char *, struct DATA *); | ||
136 | PRIVATE void floating(struct DATA *, double); | ||
137 | PRIVATE void exponent(struct DATA *, double); | ||
138 | PRIVATE void decimal(struct DATA *, double); | ||
139 | PRIVATE void octal(struct DATA *, double); | ||
140 | PRIVATE void hexa(struct DATA *, double); | ||
141 | PRIVATE void strings(struct DATA *, char *); | ||
142 | |||
143 | #else | ||
144 | /* the floating point stuff */ | ||
145 | PRIVATE double pow_10(); | ||
146 | PRIVATE int log_10(); | ||
147 | PRIVATE double integral(); | ||
148 | PRIVATE char * numtoa(); | ||
149 | |||
150 | /* for the format */ | ||
151 | PRIVATE void conv_flag(); | ||
152 | PRIVATE void floating(); | ||
153 | PRIVATE void exponent(); | ||
154 | PRIVATE void decimal(); | ||
155 | PRIVATE void octal(); | ||
156 | PRIVATE void hexa(); | ||
157 | PRIVATE void strings(); | ||
158 | #endif | ||
159 | |||
160 | /* those are defines specific to snprintf to hopefully | ||
161 | * make the code clearer :-) | ||
162 | */ | ||
163 | #define RIGHT 1 | ||
164 | #define LEFT 0 | ||
165 | #define NOT_FOUND -1 | ||
166 | #define FOUND 1 | ||
167 | #define MAX_FIELD 15 | ||
168 | |||
169 | /* the conversion flags */ | ||
170 | #define isflag(c) ((c) == '#' || (c) == ' ' || \ | ||
171 | (c) == '*' || (c) == '+' || \ | ||
172 | (c) == '-' || (c) == '.' || \ | ||
173 | isdigit(c)) | ||
174 | |||
175 | /* round off to the precision */ | ||
176 | #define ROUND(d, p) \ | ||
177 | (d < 0.) ? \ | ||
178 | d - pow_10(-(p)->precision) * 0.5 : \ | ||
179 | d + pow_10(-(p)->precision) * 0.5 | ||
180 | |||
181 | /* set default precision */ | ||
182 | #define DEF_PREC(p) \ | ||
183 | if ((p)->precision == NOT_FOUND) \ | ||
184 | (p)->precision = 6 | ||
185 | |||
186 | /* put a char */ | ||
187 | #define PUT_CHAR(c, p) \ | ||
188 | if ((p)->counter < (p)->length) { \ | ||
189 | *(p)->holder++ = (c); \ | ||
190 | (p)->counter++; \ | ||
191 | } | ||
192 | |||
193 | #define PUT_PLUS(d, p) \ | ||
194 | if ((d) > 0. && (p)->justify == RIGHT) \ | ||
195 | PUT_CHAR('+', p) | ||
196 | |||
197 | #define PUT_SPACE(d, p) \ | ||
198 | if ((p)->space == FOUND && (d) > 0.) \ | ||
199 | PUT_CHAR(' ', p) | ||
200 | |||
201 | /* pad right */ | ||
202 | #define PAD_RIGHT(p) \ | ||
203 | if ((p)->width > 0 && (p)->justify != LEFT) \ | ||
204 | for (; (p)->width > 0; (p)->width--) \ | ||
205 | PUT_CHAR((p)->pad, p) | ||
206 | |||
207 | /* pad left */ | ||
208 | #define PAD_LEFT(p) \ | ||
209 | if ((p)->width > 0 && (p)->justify == LEFT) \ | ||
210 | for (; (p)->width > 0; (p)->width--) \ | ||
211 | PUT_CHAR((p)->pad, p) | ||
212 | |||
213 | /* if width and prec. in the args */ | ||
214 | #define STAR_ARGS(p) \ | ||
215 | if ((p)->star_w == FOUND) \ | ||
216 | (p)->width = va_arg(args, int); \ | ||
217 | if ((p)->star_p == FOUND) \ | ||
218 | (p)->precision = va_arg(args, int) | ... | ... |
1 | /* Like vsprintf but provides a pointer to malloc'd storage, which must | 1 | /* Formatted output to strings. |
2 | be freed by the caller. | 2 | Copyright (C) 1999, 2002-2004 Free Software Foundation, Inc. |
3 | Copyright (C) 1994 Free Software Foundation, Inc. | ||
4 | 3 | ||
5 | This program is free software; you can redistribute it and/or modify | 4 | This program is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by | 5 | it under the terms of the GNU General Public License as published by |
7 | the Free Software Foundation; either version 2, or (at your option) | 6 | the Free Software Foundation; either version 2, or (at your option) |
8 | any later version. | 7 | any later version. |
9 | 8 | ||
10 | This program is distributed in the hope that it will be useful, | 9 | This program is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | GNU General Public License for more details. | 12 | GNU General Public License for more details. |
14 | 13 | ||
15 | You should have received a copy of the GNU General Public License | 14 | You should have received a copy of the GNU General Public License along |
16 | along with this program; if not, write to the Free Software | 15 | with this program; if not, write to the Free Software Foundation, |
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | 16 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
18 | 17 | ||
19 | #ifdef HAVE_CONFIG_H | 18 | #ifdef HAVE_CONFIG_H |
20 | # include <config.h> | 19 | # include <config.h> |
21 | #endif | 20 | #endif |
22 | 21 | ||
23 | #include <stdio.h> | 22 | /* Specification. */ |
24 | #include <string.h> | 23 | #include "vasprintf.h" |
25 | 24 | ||
26 | #if __STDC__ | 25 | #include <stdlib.h> |
27 | # include <stdarg.h> | ||
28 | #else | ||
29 | # include <varargs.h> | ||
30 | #endif | ||
31 | |||
32 | #ifdef TEST | ||
33 | int global_total_width; | ||
34 | #endif | ||
35 | |||
36 | unsigned long strtoul (); | ||
37 | char *malloc (); | ||
38 | |||
39 | static int | ||
40 | int_vasprintf (result, format, args) | ||
41 | char **result; | ||
42 | const char *format; | ||
43 | va_list *args; | ||
44 | { | ||
45 | const char *p = format; | ||
46 | /* Add one to make sure that it is never zero, which might cause malloc | ||
47 | to return NULL. */ | ||
48 | int total_width = strlen (format) + 1; | ||
49 | va_list ap; | ||
50 | |||
51 | memcpy (&ap, args, sizeof (va_list)); | ||
52 | |||
53 | while (*p != '\0') | ||
54 | { | ||
55 | if (*p++ == '%') | ||
56 | { | ||
57 | while (strchr ("-+ #0", *p)) | ||
58 | ++p; | ||
59 | if (*p == '*') | ||
60 | { | ||
61 | ++p; | ||
62 | total_width += abs (va_arg (ap, int)); | ||
63 | } | ||
64 | else | ||
65 | total_width += strtoul (p, &p, 10); | ||
66 | if (*p == '.') | ||
67 | { | ||
68 | ++p; | ||
69 | if (*p == '*') | ||
70 | { | ||
71 | ++p; | ||
72 | total_width += abs (va_arg (ap, int)); | ||
73 | } | ||
74 | else | ||
75 | total_width += strtoul (p, &p, 10); | ||
76 | } | ||
77 | while (strchr ("hlL", *p)) | ||
78 | ++p; | ||
79 | /* Should be big enough for any format specifier except %s. */ | ||
80 | total_width += 30; | ||
81 | switch (*p) | ||
82 | { | ||
83 | case 'd': | ||
84 | case 'i': | ||
85 | case 'o': | ||
86 | case 'u': | ||
87 | case 'x': | ||
88 | case 'X': | ||
89 | case 'c': | ||
90 | (void) va_arg (ap, int); | ||
91 | break; | ||
92 | case 'f': | ||
93 | case 'e': | ||
94 | case 'E': | ||
95 | case 'g': | ||
96 | case 'G': | ||
97 | (void) va_arg (ap, double); | ||
98 | break; | ||
99 | case 's': | ||
100 | total_width += strlen (va_arg (ap, char *)); | ||
101 | break; | ||
102 | case 'p': | ||
103 | case 'n': | ||
104 | (void) va_arg (ap, char *); | ||
105 | break; | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | #ifdef TEST | ||
110 | global_total_width = total_width; | ||
111 | #endif | ||
112 | *result = malloc (total_width); | ||
113 | if (*result != NULL) | ||
114 | return vsprintf (*result, format, *args); | ||
115 | else | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | int | ||
120 | vasprintf (result, format, args) | ||
121 | char **result; | ||
122 | const char *format; | ||
123 | va_list args; | ||
124 | { | ||
125 | return int_vasprintf (result, format, &args); | ||
126 | } | ||
127 | 26 | ||
128 | int | 27 | #include "vasnprintf.h" |
129 | asprintf | ||
130 | #if __STDC__ | ||
131 | (char **result, const char *format, ...) | ||
132 | #else | ||
133 | (result, va_alist) | ||
134 | char **result; | ||
135 | va_dcl | ||
136 | #endif | ||
137 | { | ||
138 | va_list args; | ||
139 | int done; | ||
140 | |||
141 | #if __STDC__ | ||
142 | va_start (args, format); | ||
143 | #else | ||
144 | char *format; | ||
145 | va_start (args); | ||
146 | format = va_arg (args, char *); | ||
147 | #endif | ||
148 | done = vasprintf (result, format, args); | ||
149 | va_end (args); | ||
150 | |||
151 | return done; | ||
152 | } | ||
153 | |||
154 | #ifdef TEST | ||
155 | void | ||
156 | checkit | ||
157 | #if __STDC__ | ||
158 | (const char* format, ...) | ||
159 | #else | ||
160 | (va_alist) | ||
161 | va_dcl | ||
162 | #endif | ||
163 | { | ||
164 | va_list args; | ||
165 | char *result; | ||
166 | |||
167 | #if __STDC__ | ||
168 | va_start (args, format); | ||
169 | #else | ||
170 | char *format; | ||
171 | va_start (args); | ||
172 | format = va_arg (args, char *); | ||
173 | #endif | ||
174 | vasprintf (&result, format, args); | ||
175 | va_end (args); | ||
176 | if (strlen (result) < global_total_width) | ||
177 | printf ("PASS: "); | ||
178 | else | ||
179 | printf ("FAIL: "); | ||
180 | printf ("%d %s\n", global_total_width, result); | ||
181 | } | ||
182 | 28 | ||
183 | int | 29 | int |
184 | main () | 30 | vasprintf (char **resultp, const char *format, va_list args) |
185 | { | 31 | { |
186 | checkit ("%d", 0x12345678); | 32 | size_t length; |
187 | checkit ("%200d", 5); | 33 | char *result = vasnprintf (NULL, &length, format, args); |
188 | checkit ("%.300d", 6); | 34 | if (result == NULL) |
189 | checkit ("%100.150d", 7); | 35 | return -1; |
190 | checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\ | 36 | |
191 | 777777777777777777333333333333366666666666622222222222777777777777733333"); | 37 | *resultp = result; |
192 | checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"); | 38 | /* Return the number of resulting bytes, excluding the trailing NUL. |
39 | If it wouldn't fit in an 'int', vasnprintf() would have returned NULL | ||
40 | and set errno to EOVERFLOW. */ | ||
41 | return length; | ||
193 | } | 42 | } |
194 | #endif /* TEST */ | ... | ... |
1 | /* xalloc.h -- malloc with out-of-memory checking | 1 | /* xalloc.h -- malloc with out-of-memory checking |
2 | Copyright (C) 1990-1998, 1999 Free Software Foundation, Inc. | 2 | |
3 | Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, | ||
4 | 1999, 2000, 2003, 2004 Free Software Foundation, Inc. | ||
3 | 5 | ||
4 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Public License as published by | 7 | it under the terms of the GNU General Public License as published by |
... | @@ -18,14 +20,14 @@ | ... | @@ -18,14 +20,14 @@ |
18 | #ifndef XALLOC_H_ | 20 | #ifndef XALLOC_H_ |
19 | # define XALLOC_H_ | 21 | # define XALLOC_H_ |
20 | 22 | ||
21 | # ifndef PARAMS | 23 | # include <stddef.h> |
22 | # if defined PROTOTYPES || (defined __STDC__ && __STDC__) | 24 | |
23 | # define PARAMS(Args) Args | 25 | |
24 | # else | 26 | # ifdef __cplusplus |
25 | # define PARAMS(Args) () | 27 | extern "C" { |
26 | # endif | ||
27 | # endif | 28 | # endif |
28 | 29 | ||
30 | |||
29 | # ifndef __attribute__ | 31 | # ifndef __attribute__ |
30 | # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ | 32 | # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ |
31 | # define __attribute__(x) | 33 | # define __attribute__(x) |
... | @@ -36,52 +38,42 @@ | ... | @@ -36,52 +38,42 @@ |
36 | # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) | 38 | # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) |
37 | # endif | 39 | # endif |
38 | 40 | ||
39 | /* Exit value when the requested amount of memory is not available. | 41 | /* This function is always triggered when memory is exhausted. |
40 | It is initialized to EXIT_FAILURE, but the caller may set it to | 42 | It must be defined by the application, either explicitly |
41 | some other value. */ | 43 | or by using gnulib's xalloc-die module. This is the |
42 | extern int xalloc_exit_failure; | ||
43 | |||
44 | /* If this pointer is non-zero, run the specified function upon each | ||
45 | allocation failure. It is initialized to zero. */ | ||
46 | extern void (*xalloc_fail_func) PARAMS ((void)); | ||
47 | |||
48 | /* If XALLOC_FAIL_FUNC is undefined or a function that returns, this | ||
49 | message must be non-NULL. It is translated via gettext. | ||
50 | The default value is "Memory exhausted". */ | ||
51 | extern char *const xalloc_msg_memory_exhausted; | ||
52 | |||
53 | /* This function is always triggered when memory is exhausted. It is | ||
54 | in charge of honoring the three previous items. This is the | ||
55 | function to call when one wants the program to die because of a | 44 | function to call when one wants the program to die because of a |
56 | memory allocation failure. */ | 45 | memory allocation failure. */ |
57 | extern void xalloc_die PARAMS ((void)) ATTRIBUTE_NORETURN; | 46 | extern void xalloc_die (void) ATTRIBUTE_NORETURN; |
58 | 47 | ||
59 | void *xmalloc PARAMS ((size_t n)); | 48 | void *xmalloc (size_t s); |
60 | void *xcalloc PARAMS ((size_t n, size_t s)); | 49 | void *xnmalloc (size_t n, size_t s); |
61 | void *xrealloc PARAMS ((void *p, size_t n)); | 50 | void *xzalloc (size_t s); |
62 | char *xstrdup PARAMS ((const char *str)); | 51 | void *xcalloc (size_t n, size_t s); |
63 | 52 | void *xrealloc (void *p, size_t s); | |
64 | # define XMALLOC(Type, N_items) ((Type *) xmalloc (sizeof (Type) * (N_items))) | 53 | void *xnrealloc (void *p, size_t n, size_t s); |
65 | # define XCALLOC(Type, N_items) ((Type *) xcalloc (sizeof (Type), (N_items))) | 54 | void *x2realloc (void *p, size_t *pn); |
66 | # define XREALLOC(Ptr, Type, N_items) \ | 55 | void *x2nrealloc (void *p, size_t *pn, size_t s); |
67 | ((Type *) xrealloc ((void *) (Ptr), sizeof (Type) * (N_items))) | 56 | void *xmemdup (void const *p, size_t s); |
68 | 57 | char *xstrdup (char const *str); | |
69 | /* Declare and alloc memory for VAR of type TYPE. */ | 58 | |
70 | # define NEW(Type, Var) Type *(Var) = XMALLOC (Type, 1) | 59 | /* Return 1 if an array of N objects, each of size S, cannot exist due |
71 | 60 | to size arithmetic overflow. S must be positive and N must be | |
72 | /* Free VAR only if non NULL. */ | 61 | nonnegative. This is a macro, not an inline function, so that it |
73 | # define XFREE(Var) \ | 62 | works correctly even when SIZE_MAX < N. |
74 | do { \ | 63 | |
75 | if (Var) \ | 64 | By gnulib convention, SIZE_MAX represents overflow in size |
76 | free (Var); \ | 65 | calculations, so the conservative dividend to use here is |
77 | } while (0) | 66 | SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. |
78 | 67 | However, malloc (SIZE_MAX) fails on all known hosts where | |
79 | /* Return a pointer to a malloc'ed copy of the array SRC of NUM elements. */ | 68 | sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for |
80 | # define CCLONE(Src, Num) \ | 69 | exactly-SIZE_MAX allocations on such hosts; this avoids a test and |
81 | (memcpy (xmalloc (sizeof (*Src) * (Num)), (Src), sizeof (*Src) * (Num))) | 70 | branch when S is known to be 1. */ |
82 | 71 | # define xalloc_oversized(n, s) \ | |
83 | /* Return a malloc'ed copy of SRC. */ | 72 | ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) |
84 | # define CLONE(Src) CCLONE (Src, 1) | 73 | |
74 | # ifdef __cplusplus | ||
75 | } | ||
76 | # endif | ||
85 | 77 | ||
86 | 78 | ||
87 | #endif /* !XALLOC_H_ */ | 79 | #endif /* !XALLOC_H_ */ | ... | ... |
1 | /* xmalloc.c -- malloc with out of memory checking | 1 | /* xmalloc.c -- malloc with out of memory checking |
2 | Copyright (C) 1990-1997, 98, 99 Free Software Foundation, Inc. | 2 | |
3 | Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, | ||
4 | 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. | ||
3 | 5 | ||
4 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Public License as published by | 7 | it under the terms of the GNU General Public License as published by |
... | @@ -19,64 +21,31 @@ | ... | @@ -19,64 +21,31 @@ |
19 | # include <config.h> | 21 | # include <config.h> |
20 | #endif | 22 | #endif |
21 | 23 | ||
22 | #include <sys/types.h> | ||
23 | |||
24 | #include <mailutils/error.h> | ||
25 | |||
26 | #if STDC_HEADERS | ||
27 | # include <stdlib.h> | ||
28 | #else | ||
29 | void *calloc (); | ||
30 | void *malloc (); | ||
31 | void *realloc (); | ||
32 | void free (); | ||
33 | #endif | ||
34 | |||
35 | #if ENABLE_NLS | ||
36 | # include <libintl.h> | ||
37 | # define _(Text) gettext (Text) | ||
38 | #else | ||
39 | # define textdomain(Domain) | ||
40 | # define _(Text) Text | ||
41 | #endif | ||
42 | #define N_(Text) Text | ||
43 | |||
44 | #include "error.h" | ||
45 | #include "xalloc.h" | 24 | #include "xalloc.h" |
46 | 25 | ||
47 | #ifndef EXIT_FAILURE | 26 | #include <stdlib.h> |
48 | # define EXIT_FAILURE 1 | 27 | #include <string.h> |
49 | #endif | ||
50 | |||
51 | #ifndef HAVE_MALLOC | ||
52 | # error "you must run the autoconf test for a properly working malloc -- see malloc.m4" | ||
53 | #endif | ||
54 | 28 | ||
55 | #ifndef HAVE_REALLOC | 29 | #ifndef SIZE_MAX |
56 | # error "you must run the autoconf test for a properly working realloc -- see realloc.m4" | 30 | # define SIZE_MAX ((size_t) -1) |
57 | #endif | 31 | #endif |
58 | 32 | ||
59 | /* Exit value when the requested amount of memory is not available. | 33 | /* Allocate an array of N objects, each with S bytes of memory, |
60 | The caller may set it to some other value. */ | 34 | dynamically, with error checking. S must be nonzero. */ |
61 | int xalloc_exit_failure = EXIT_FAILURE; | ||
62 | |||
63 | /* If non NULL, call this function when memory is exhausted. */ | ||
64 | void (*xalloc_fail_func) PARAMS ((void)) = 0; | ||
65 | 35 | ||
66 | /* If XALLOC_FAIL_FUNC is NULL, or does return, display this message | 36 | static inline void * |
67 | before exiting when memory is exhausted. Goes through gettext. */ | 37 | xnmalloc_inline (size_t n, size_t s) |
68 | char *const xalloc_msg_memory_exhausted = N_("Memory exhausted"); | 38 | { |
39 | void *p; | ||
40 | if (xalloc_oversized (n, s) || (! (p = malloc (n * s)) && n != 0)) | ||
41 | xalloc_die (); | ||
42 | return p; | ||
43 | } | ||
69 | 44 | ||
70 | void | 45 | void * |
71 | xalloc_die (void) | 46 | xnmalloc (size_t n, size_t s) |
72 | { | 47 | { |
73 | if (xalloc_fail_func) | 48 | return xnmalloc_inline (n, s); |
74 | (*xalloc_fail_func) (); | ||
75 | mu_error ("%s", _(xalloc_msg_memory_exhausted)); | ||
76 | /* The `noreturn' cannot be given to error, since it may return if | ||
77 | its first argument is 0. To help compilers understand the | ||
78 | xalloc_die does terminate, call exit. */ | ||
79 | exit (xalloc_exit_failure); | ||
80 | } | 49 | } |
81 | 50 | ||
82 | /* Allocate N bytes of memory dynamically, with error checking. */ | 51 | /* Allocate N bytes of memory dynamically, with error checking. */ |
... | @@ -84,36 +53,177 @@ xalloc_die (void) | ... | @@ -84,36 +53,177 @@ xalloc_die (void) |
84 | void * | 53 | void * |
85 | xmalloc (size_t n) | 54 | xmalloc (size_t n) |
86 | { | 55 | { |
87 | void *p; | 56 | return xnmalloc_inline (n, 1); |
57 | } | ||
58 | |||
59 | /* Change the size of an allocated block of memory P to an array of N | ||
60 | objects each of S bytes, with error checking. S must be nonzero. */ | ||
88 | 61 | ||
89 | p = malloc (n); | 62 | static inline void * |
90 | if (p == 0) | 63 | xnrealloc_inline (void *p, size_t n, size_t s) |
64 | { | ||
65 | if (xalloc_oversized (n, s) || (! (p = realloc (p, n * s)) && n != 0)) | ||
91 | xalloc_die (); | 66 | xalloc_die (); |
92 | return p; | 67 | return p; |
93 | } | 68 | } |
94 | 69 | ||
70 | void * | ||
71 | xnrealloc (void *p, size_t n, size_t s) | ||
72 | { | ||
73 | return xnrealloc_inline (p, n, s); | ||
74 | } | ||
75 | |||
95 | /* Change the size of an allocated block of memory P to N bytes, | 76 | /* Change the size of an allocated block of memory P to N bytes, |
96 | with error checking. | 77 | with error checking. */ |
97 | If P is NULL, run xmalloc. */ | ||
98 | 78 | ||
99 | void * | 79 | void * |
100 | xrealloc (void *p, size_t n) | 80 | xrealloc (void *p, size_t n) |
101 | { | 81 | { |
102 | p = realloc (p, n); | 82 | return xnrealloc_inline (p, n, 1); |
103 | if (p == 0) | 83 | } |
84 | |||
85 | |||
86 | /* If P is null, allocate a block of at least *PN such objects; | ||
87 | otherwise, reallocate P so that it contains more than *PN objects | ||
88 | each of S bytes. *PN must be nonzero unless P is null, and S must | ||
89 | be nonzero. Set *PN to the new number of objects, and return the | ||
90 | pointer to the new block. *PN is never set to zero, and the | ||
91 | returned pointer is never null. | ||
92 | |||
93 | Repeated reallocations are guaranteed to make progress, either by | ||
94 | allocating an initial block with a nonzero size, or by allocating a | ||
95 | larger block. | ||
96 | |||
97 | In the following implementation, nonzero sizes are doubled so that | ||
98 | repeated reallocations have O(N log N) overall cost rather than | ||
99 | O(N**2) cost, but the specification for this function does not | ||
100 | guarantee that sizes are doubled. | ||
101 | |||
102 | Here is an example of use: | ||
103 | |||
104 | int *p = NULL; | ||
105 | size_t used = 0; | ||
106 | size_t allocated = 0; | ||
107 | |||
108 | void | ||
109 | append_int (int value) | ||
110 | { | ||
111 | if (used == allocated) | ||
112 | p = x2nrealloc (p, &allocated, sizeof *p); | ||
113 | p[used++] = value; | ||
114 | } | ||
115 | |||
116 | This causes x2nrealloc to allocate a block of some nonzero size the | ||
117 | first time it is called. | ||
118 | |||
119 | To have finer-grained control over the initial size, set *PN to a | ||
120 | nonzero value before calling this function with P == NULL. For | ||
121 | example: | ||
122 | |||
123 | int *p = NULL; | ||
124 | size_t used = 0; | ||
125 | size_t allocated = 0; | ||
126 | size_t allocated1 = 1000; | ||
127 | |||
128 | void | ||
129 | append_int (int value) | ||
130 | { | ||
131 | if (used == allocated) | ||
132 | { | ||
133 | p = x2nrealloc (p, &allocated1, sizeof *p); | ||
134 | allocated = allocated1; | ||
135 | } | ||
136 | p[used++] = value; | ||
137 | } | ||
138 | |||
139 | */ | ||
140 | |||
141 | static inline void * | ||
142 | x2nrealloc_inline (void *p, size_t *pn, size_t s) | ||
143 | { | ||
144 | size_t n = *pn; | ||
145 | |||
146 | if (! p) | ||
147 | { | ||
148 | if (! n) | ||
149 | { | ||
150 | /* The approximate size to use for initial small allocation | ||
151 | requests, when the invoking code specifies an old size of | ||
152 | zero. 64 bytes is the largest "small" request for the | ||
153 | GNU C library malloc. */ | ||
154 | enum { DEFAULT_MXFAST = 64 }; | ||
155 | |||
156 | n = DEFAULT_MXFAST / s; | ||
157 | n += !n; | ||
158 | } | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | if (SIZE_MAX / 2 / s < n) | ||
104 | xalloc_die (); | 163 | xalloc_die (); |
105 | return p; | 164 | n *= 2; |
165 | } | ||
166 | |||
167 | *pn = n; | ||
168 | return xrealloc (p, n * s); | ||
169 | } | ||
170 | |||
171 | void * | ||
172 | x2nrealloc (void *p, size_t *pn, size_t s) | ||
173 | { | ||
174 | return x2nrealloc_inline (p, pn, s); | ||
106 | } | 175 | } |
107 | 176 | ||
108 | /* Allocate memory for N elements of S bytes, with error checking. */ | 177 | /* If P is null, allocate a block of at least *PN bytes; otherwise, |
178 | reallocate P so that it contains more than *PN bytes. *PN must be | ||
179 | nonzero unless P is null. Set *PN to the new block's size, and | ||
180 | return the pointer to the new block. *PN is never set to zero, and | ||
181 | the returned pointer is never null. */ | ||
182 | |||
183 | void * | ||
184 | x2realloc (void *p, size_t *pn) | ||
185 | { | ||
186 | return x2nrealloc_inline (p, pn, 1); | ||
187 | } | ||
188 | |||
189 | /* Allocate S bytes of zeroed memory dynamically, with error checking. | ||
190 | There's no need for xnzalloc (N, S), since it would be equivalent | ||
191 | to xcalloc (N, S). */ | ||
192 | |||
193 | void * | ||
194 | xzalloc (size_t s) | ||
195 | { | ||
196 | return memset (xmalloc (s), 0, s); | ||
197 | } | ||
198 | |||
199 | /* Allocate zeroed memory for N elements of S bytes, with error | ||
200 | checking. S must be nonzero. */ | ||
109 | 201 | ||
110 | void * | 202 | void * |
111 | xcalloc (size_t n, size_t s) | 203 | xcalloc (size_t n, size_t s) |
112 | { | 204 | { |
113 | void *p; | 205 | void *p; |
114 | 206 | /* Test for overflow, since some calloc implementations don't have | |
115 | p = calloc (n, s); | 207 | proper overflow checks. */ |
116 | if (p == 0) | 208 | if (xalloc_oversized (n, s) || (! (p = calloc (n, s)) && n != 0)) |
117 | xalloc_die (); | 209 | xalloc_die (); |
118 | return p; | 210 | return p; |
119 | } | 211 | } |
212 | |||
213 | /* Clone an object P of size S, with error checking. There's no need | ||
214 | for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any | ||
215 | need for an arithmetic overflow check. */ | ||
216 | |||
217 | void * | ||
218 | xmemdup (void const *p, size_t s) | ||
219 | { | ||
220 | return memcpy (xmalloc (s), p, s); | ||
221 | } | ||
222 | |||
223 | /* Clone STRING. */ | ||
224 | |||
225 | char * | ||
226 | xstrdup (char const *string) | ||
227 | { | ||
228 | return xmemdup (string, strlen (string) + 1); | ||
229 | } | ... | ... |
1 | /* A more useful interface to strtol. | 1 | /* A more useful interface to strtol. |
2 | Copyright 1995, 1996, 1998, 1999 Free Software Foundation, Inc. | 2 | |
3 | Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2003, 2004 Free | ||
4 | Software Foundation, Inc. | ||
3 | 5 | ||
4 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Public License as published by | 7 | it under the terms of the GNU General Public License as published by |
... | @@ -25,48 +27,32 @@ | ... | @@ -25,48 +27,32 @@ |
25 | # define __strtol strtol | 27 | # define __strtol strtol |
26 | # define __strtol_t long int | 28 | # define __strtol_t long int |
27 | # define __xstrtol xstrtol | 29 | # define __xstrtol xstrtol |
30 | # define STRTOL_T_MINIMUM LONG_MIN | ||
31 | # define STRTOL_T_MAXIMUM LONG_MAX | ||
28 | #endif | 32 | #endif |
29 | 33 | ||
30 | /* Some pre-ANSI implementations (e.g. SunOS 4) | 34 | /* Some pre-ANSI implementations (e.g. SunOS 4) |
31 | need stderr defined if assertion checking is enabled. */ | 35 | need stderr defined if assertion checking is enabled. */ |
32 | #include <stdio.h> | 36 | #include <stdio.h> |
33 | 37 | ||
34 | #if STDC_HEADERS | ||
35 | # include <stdlib.h> | ||
36 | #endif | ||
37 | |||
38 | #if HAVE_STRING_H | ||
39 | # include <string.h> | ||
40 | #else | ||
41 | # include <strings.h> | ||
42 | # ifndef strchr | ||
43 | # define strchr index | ||
44 | # endif | ||
45 | #endif | ||
46 | |||
47 | #include <assert.h> | 38 | #include <assert.h> |
48 | #include <ctype.h> | 39 | #include <ctype.h> |
49 | |||
50 | #include <errno.h> | 40 | #include <errno.h> |
51 | #ifndef errno | 41 | #include <limits.h> |
52 | extern int errno; | 42 | #include <stdlib.h> |
53 | #endif | 43 | #include <string.h> |
54 | |||
55 | #if HAVE_LIMITS_H | ||
56 | # include <limits.h> | ||
57 | #endif | ||
58 | |||
59 | #ifndef CHAR_BIT | ||
60 | # define CHAR_BIT 8 | ||
61 | #endif | ||
62 | 44 | ||
63 | /* The extra casts work around common compiler bugs. */ | 45 | /* The extra casts work around common compiler bugs. */ |
64 | #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) | 46 | #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) |
65 | /* The outer cast is needed to work around a bug in Cray C 5.0.3.0. | ||
66 | It is necessary at least when t == time_t. */ | ||
67 | #define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ | 47 | #define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ |
68 | ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0)) | 48 | ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \ |
69 | #define TYPE_MAXIMUM(t) (~ (t) 0 - TYPE_MINIMUM (t)) | 49 | : (t) 0)) |
50 | #define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t))) | ||
51 | |||
52 | #ifndef STRTOL_T_MINIMUM | ||
53 | # define STRTOL_T_MINIMUM TYPE_MINIMUM (__strtol_t) | ||
54 | # define STRTOL_T_MAXIMUM TYPE_MAXIMUM (__strtol_t) | ||
55 | #endif | ||
70 | 56 | ||
71 | #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) | 57 | #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) |
72 | # define IN_CTYPE_DOMAIN(c) 1 | 58 | # define IN_CTYPE_DOMAIN(c) 1 |
... | @@ -78,36 +64,38 @@ extern int errno; | ... | @@ -78,36 +64,38 @@ extern int errno; |
78 | 64 | ||
79 | #include "xstrtol.h" | 65 | #include "xstrtol.h" |
80 | 66 | ||
81 | #ifndef strtol | 67 | #if !HAVE_DECL_STRTOIMAX && !defined strtoimax |
82 | long int strtol (); | 68 | intmax_t strtoimax (); |
83 | #endif | ||
84 | |||
85 | #ifndef strtoul | ||
86 | unsigned long int strtoul (); | ||
87 | #endif | 69 | #endif |
88 | 70 | ||
89 | #ifndef strtoumax | 71 | #if !HAVE_DECL_STRTOUMAX && !defined strtoumax |
90 | uintmax_t strtoumax (); | 72 | uintmax_t strtoumax (); |
91 | #endif | 73 | #endif |
92 | 74 | ||
93 | static int | 75 | static strtol_error |
94 | bkm_scale (__strtol_t *x, int scale_factor) | 76 | bkm_scale (__strtol_t *x, int scale_factor) |
95 | { | 77 | { |
96 | __strtol_t product = *x * scale_factor; | 78 | if (TYPE_SIGNED (__strtol_t) && *x < STRTOL_T_MINIMUM / scale_factor) |
97 | if (*x != product / scale_factor) | 79 | { |
98 | return 1; | 80 | *x = STRTOL_T_MINIMUM; |
99 | *x = product; | 81 | return LONGINT_OVERFLOW; |
100 | return 0; | 82 | } |
83 | if (STRTOL_T_MAXIMUM / scale_factor < *x) | ||
84 | { | ||
85 | *x = STRTOL_T_MAXIMUM; | ||
86 | return LONGINT_OVERFLOW; | ||
87 | } | ||
88 | *x *= scale_factor; | ||
89 | return LONGINT_OK; | ||
101 | } | 90 | } |
102 | 91 | ||
103 | static int | 92 | static strtol_error |
104 | bkm_scale_by_power (__strtol_t *x, int base, int power) | 93 | bkm_scale_by_power (__strtol_t *x, int base, int power) |
105 | { | 94 | { |
95 | strtol_error err = LONGINT_OK; | ||
106 | while (power--) | 96 | while (power--) |
107 | if (bkm_scale (x, base)) | 97 | err |= bkm_scale (x, base); |
108 | return 1; | 98 | return err; |
109 | |||
110 | return 0; | ||
111 | } | 99 | } |
112 | 100 | ||
113 | /* FIXME: comment. */ | 101 | /* FIXME: comment. */ |
... | @@ -119,6 +107,7 @@ __xstrtol (const char *s, char **ptr, int strtol_base, | ... | @@ -119,6 +107,7 @@ __xstrtol (const char *s, char **ptr, int strtol_base, |
119 | char *t_ptr; | 107 | char *t_ptr; |
120 | char **p; | 108 | char **p; |
121 | __strtol_t tmp; | 109 | __strtol_t tmp; |
110 | strtol_error err = LONGINT_OK; | ||
122 | 111 | ||
123 | assert (0 <= strtol_base && strtol_base <= 36); | 112 | assert (0 <= strtol_base && strtol_base <= 36); |
124 | 113 | ||
... | @@ -127,18 +116,31 @@ __xstrtol (const char *s, char **ptr, int strtol_base, | ... | @@ -127,18 +116,31 @@ __xstrtol (const char *s, char **ptr, int strtol_base, |
127 | if (! TYPE_SIGNED (__strtol_t)) | 116 | if (! TYPE_SIGNED (__strtol_t)) |
128 | { | 117 | { |
129 | const char *q = s; | 118 | const char *q = s; |
130 | while (ISSPACE ((unsigned char) *q)) | 119 | unsigned char ch = *q; |
131 | ++q; | 120 | while (ISSPACE (ch)) |
132 | if (*q == '-') | 121 | ch = *++q; |
122 | if (ch == '-') | ||
133 | return LONGINT_INVALID; | 123 | return LONGINT_INVALID; |
134 | } | 124 | } |
135 | 125 | ||
136 | errno = 0; | 126 | errno = 0; |
137 | tmp = __strtol (s, p, strtol_base); | 127 | tmp = __strtol (s, p, strtol_base); |
138 | if (errno != 0) | 128 | |
139 | return LONGINT_OVERFLOW; | ||
140 | if (*p == s) | 129 | if (*p == s) |
130 | { | ||
131 | /* If there is no number but there is a valid suffix, assume the | ||
132 | number is 1. The string is invalid otherwise. */ | ||
133 | if (valid_suffixes && **p && strchr (valid_suffixes, **p)) | ||
134 | tmp = 1; | ||
135 | else | ||
136 | return LONGINT_INVALID; | ||
137 | } | ||
138 | else if (errno != 0) | ||
139 | { | ||
140 | if (errno != ERANGE) | ||
141 | return LONGINT_INVALID; | 141 | return LONGINT_INVALID; |
142 | err = LONGINT_OVERFLOW; | ||
143 | } | ||
142 | 144 | ||
143 | /* Let valid_suffixes == NULL mean `allow any suffix'. */ | 145 | /* Let valid_suffixes == NULL mean `allow any suffix'. */ |
144 | /* FIXME: update all callers except the ones that allow suffixes | 146 | /* FIXME: update all callers except the ones that allow suffixes |
... | @@ -146,34 +148,39 @@ __xstrtol (const char *s, char **ptr, int strtol_base, | ... | @@ -146,34 +148,39 @@ __xstrtol (const char *s, char **ptr, int strtol_base, |
146 | if (!valid_suffixes) | 148 | if (!valid_suffixes) |
147 | { | 149 | { |
148 | *val = tmp; | 150 | *val = tmp; |
149 | return LONGINT_OK; | 151 | return err; |
150 | } | 152 | } |
151 | 153 | ||
152 | if (**p != '\0') | 154 | if (**p != '\0') |
153 | { | 155 | { |
154 | int base = 1024; | 156 | int base = 1024; |
155 | int suffixes = 1; | 157 | int suffixes = 1; |
156 | int overflow; | 158 | strtol_error overflow; |
157 | 159 | ||
158 | if (!strchr (valid_suffixes, **p)) | 160 | if (!strchr (valid_suffixes, **p)) |
159 | { | 161 | { |
160 | *val = tmp; | 162 | *val = tmp; |
161 | return LONGINT_INVALID_SUFFIX_CHAR; | 163 | return err | LONGINT_INVALID_SUFFIX_CHAR; |
162 | } | 164 | } |
163 | 165 | ||
164 | if (strchr (valid_suffixes, '0')) | 166 | if (strchr (valid_suffixes, '0')) |
165 | { | 167 | { |
166 | /* The ``valid suffix'' '0' is a special flag meaning that | 168 | /* The ``valid suffix'' '0' is a special flag meaning that |
167 | an optional second suffix is allowed, which can change | 169 | an optional second suffix is allowed, which can change |
168 | the base, e.g. "100MD" for 100 megabytes decimal. */ | 170 | the base. A suffix "B" (e.g. "100MB") stands for a power |
171 | of 1000, whereas a suffix "iB" (e.g. "100MiB") stands for | ||
172 | a power of 1024. If no suffix (e.g. "100M"), assume | ||
173 | power-of-1024. */ | ||
169 | 174 | ||
170 | switch (p[0][1]) | 175 | switch (p[0][1]) |
171 | { | 176 | { |
172 | case 'B': | 177 | case 'i': |
173 | suffixes++; | 178 | if (p[0][2] == 'B') |
179 | suffixes += 2; | ||
174 | break; | 180 | break; |
175 | 181 | ||
176 | case 'D': | 182 | case 'B': |
183 | case 'D': /* 'D' is obsolescent */ | ||
177 | base = 1000; | 184 | base = 1000; |
178 | suffixes++; | 185 | suffixes++; |
179 | break; | 186 | break; |
... | @@ -194,28 +201,31 @@ __xstrtol (const char *s, char **ptr, int strtol_base, | ... | @@ -194,28 +201,31 @@ __xstrtol (const char *s, char **ptr, int strtol_base, |
194 | overflow = 0; | 201 | overflow = 0; |
195 | break; | 202 | break; |
196 | 203 | ||
197 | case 'E': /* Exa */ | 204 | case 'E': /* exa or exbi */ |
198 | overflow = bkm_scale_by_power (&tmp, base, 6); | 205 | overflow = bkm_scale_by_power (&tmp, base, 6); |
199 | break; | 206 | break; |
200 | 207 | ||
201 | case 'G': /* Giga */ | 208 | case 'G': /* giga or gibi */ |
209 | case 'g': /* 'g' is undocumented; for compatibility only */ | ||
202 | overflow = bkm_scale_by_power (&tmp, base, 3); | 210 | overflow = bkm_scale_by_power (&tmp, base, 3); |
203 | break; | 211 | break; |
204 | 212 | ||
205 | case 'k': /* kilo */ | 213 | case 'k': /* kilo */ |
214 | case 'K': /* kibi */ | ||
206 | overflow = bkm_scale_by_power (&tmp, base, 1); | 215 | overflow = bkm_scale_by_power (&tmp, base, 1); |
207 | break; | 216 | break; |
208 | 217 | ||
209 | case 'M': /* Mega */ | 218 | case 'M': /* mega or mebi */ |
210 | case 'm': /* 'm' is undocumented; for backward compatibility only */ | 219 | case 'm': /* 'm' is undocumented; for compatibility only */ |
211 | overflow = bkm_scale_by_power (&tmp, base, 2); | 220 | overflow = bkm_scale_by_power (&tmp, base, 2); |
212 | break; | 221 | break; |
213 | 222 | ||
214 | case 'P': /* Peta */ | 223 | case 'P': /* peta or pebi */ |
215 | overflow = bkm_scale_by_power (&tmp, base, 5); | 224 | overflow = bkm_scale_by_power (&tmp, base, 5); |
216 | break; | 225 | break; |
217 | 226 | ||
218 | case 'T': /* Tera */ | 227 | case 'T': /* tera or tebi */ |
228 | case 't': /* 't' is undocumented; for compatibility only */ | ||
219 | overflow = bkm_scale_by_power (&tmp, base, 4); | 229 | overflow = bkm_scale_by_power (&tmp, base, 4); |
220 | break; | 230 | break; |
221 | 231 | ||
... | @@ -223,28 +233,27 @@ __xstrtol (const char *s, char **ptr, int strtol_base, | ... | @@ -223,28 +233,27 @@ __xstrtol (const char *s, char **ptr, int strtol_base, |
223 | overflow = bkm_scale (&tmp, 2); | 233 | overflow = bkm_scale (&tmp, 2); |
224 | break; | 234 | break; |
225 | 235 | ||
226 | case 'Y': /* Yotta */ | 236 | case 'Y': /* yotta or 2**80 */ |
227 | overflow = bkm_scale_by_power (&tmp, base, 8); | 237 | overflow = bkm_scale_by_power (&tmp, base, 8); |
228 | break; | 238 | break; |
229 | 239 | ||
230 | case 'Z': /* Zetta */ | 240 | case 'Z': /* zetta or 2**70 */ |
231 | overflow = bkm_scale_by_power (&tmp, base, 7); | 241 | overflow = bkm_scale_by_power (&tmp, base, 7); |
232 | break; | 242 | break; |
233 | 243 | ||
234 | default: | 244 | default: |
235 | *val = tmp; | 245 | *val = tmp; |
236 | return LONGINT_INVALID_SUFFIX_CHAR; | 246 | return err | LONGINT_INVALID_SUFFIX_CHAR; |
237 | break; | ||
238 | } | 247 | } |
239 | 248 | ||
240 | if (overflow) | 249 | err |= overflow; |
241 | return LONGINT_OVERFLOW; | 250 | *p += suffixes; |
242 | 251 | if (**p) | |
243 | (*p) += suffixes; | 252 | err |= LONGINT_INVALID_SUFFIX_CHAR; |
244 | } | 253 | } |
245 | 254 | ||
246 | *val = tmp; | 255 | *val = tmp; |
247 | return LONGINT_OK; | 256 | return err; |
248 | } | 257 | } |
249 | 258 | ||
250 | #ifdef TESTING_XSTRTO | 259 | #ifdef TESTING_XSTRTO |
... | @@ -255,7 +264,7 @@ __xstrtol (const char *s, char **ptr, int strtol_base, | ... | @@ -255,7 +264,7 @@ __xstrtol (const char *s, char **ptr, int strtol_base, |
255 | char *program_name; | 264 | char *program_name; |
256 | 265 | ||
257 | int | 266 | int |
258 | main (int argc, char** argv) | 267 | main (int argc, char **argv) |
259 | { | 268 | { |
260 | strtol_error s_err; | 269 | strtol_error s_err; |
261 | int i; | 270 | int i; | ... | ... |
1 | /* A more useful interface to strtol. | ||
2 | |||
3 | Copyright (C) 1995, 1996, 1998, 1999, 2001, 2002, 2003, 2004 Free | ||
4 | Software Foundation, Inc. | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2, or (at your option) | ||
9 | any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software Foundation, | ||
18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
19 | |||
1 | #ifndef XSTRTOL_H_ | 20 | #ifndef XSTRTOL_H_ |
2 | # define XSTRTOL_H_ 1 | 21 | # define XSTRTOL_H_ 1 |
3 | 22 | ||
4 | # if HAVE_INTTYPES_H | 23 | # include "exitfail.h" |
5 | # include <inttypes.h> /* for uintmax_t */ | ||
6 | # endif | ||
7 | 24 | ||
8 | # ifndef PARAMS | 25 | # if HAVE_INTTYPES_H |
9 | # if defined PROTOTYPES || (defined __STDC__ && __STDC__) | 26 | # include <inttypes.h> |
10 | # define PARAMS(Args) Args | ||
11 | # else | ||
12 | # define PARAMS(Args) () | ||
13 | # endif | 27 | # endif |
28 | # if HAVE_STDINT_H | ||
29 | # include <stdint.h> | ||
14 | # endif | 30 | # endif |
15 | 31 | ||
16 | # ifndef _STRTOL_ERROR | 32 | # ifndef _STRTOL_ERROR |
17 | enum strtol_error | 33 | enum strtol_error |
18 | { | 34 | { |
19 | LONGINT_OK, LONGINT_INVALID, LONGINT_INVALID_SUFFIX_CHAR, LONGINT_OVERFLOW | 35 | LONGINT_OK = 0, |
36 | |||
37 | /* These two values can be ORed together, to indicate that both | ||
38 | errors occurred. */ | ||
39 | LONGINT_OVERFLOW = 1, | ||
40 | LONGINT_INVALID_SUFFIX_CHAR = 2, | ||
41 | |||
42 | LONGINT_INVALID_SUFFIX_CHAR_WITH_OVERFLOW = (LONGINT_INVALID_SUFFIX_CHAR | ||
43 | | LONGINT_OVERFLOW), | ||
44 | LONGINT_INVALID = 4 | ||
20 | }; | 45 | }; |
21 | typedef enum strtol_error strtol_error; | 46 | typedef enum strtol_error strtol_error; |
22 | # endif | 47 | # endif |
23 | 48 | ||
24 | # define _DECLARE_XSTRTOL(name, type) \ | 49 | # define _DECLARE_XSTRTOL(name, type) \ |
25 | strtol_error \ | 50 | strtol_error name (const char *, char **, int, type *, const char *); |
26 | name PARAMS ((const char *s, char **ptr, int base, \ | ||
27 | type *val, const char *valid_suffixes)); | ||
28 | _DECLARE_XSTRTOL (xstrtol, long int) | 51 | _DECLARE_XSTRTOL (xstrtol, long int) |
29 | _DECLARE_XSTRTOL (xstrtoul, unsigned long int) | 52 | _DECLARE_XSTRTOL (xstrtoul, unsigned long int) |
53 | _DECLARE_XSTRTOL (xstrtoimax, intmax_t) | ||
30 | _DECLARE_XSTRTOL (xstrtoumax, uintmax_t) | 54 | _DECLARE_XSTRTOL (xstrtoumax, uintmax_t) |
31 | 55 | ||
32 | # define _STRTOL_ERROR(Exit_code, Str, Argument_type_string, Err) \ | 56 | # define _STRTOL_ERROR(Exit_code, Str, Argument_type_string, Err) \ |
... | @@ -34,7 +58,7 @@ _DECLARE_XSTRTOL (xstrtoumax, uintmax_t) | ... | @@ -34,7 +58,7 @@ _DECLARE_XSTRTOL (xstrtoumax, uintmax_t) |
34 | { \ | 58 | { \ |
35 | switch ((Err)) \ | 59 | switch ((Err)) \ |
36 | { \ | 60 | { \ |
37 | case LONGINT_OK: \ | 61 | default: \ |
38 | abort (); \ | 62 | abort (); \ |
39 | \ | 63 | \ |
40 | case LONGINT_INVALID: \ | 64 | case LONGINT_INVALID: \ |
... | @@ -43,7 +67,8 @@ _DECLARE_XSTRTOL (xstrtoumax, uintmax_t) | ... | @@ -43,7 +67,8 @@ _DECLARE_XSTRTOL (xstrtoumax, uintmax_t) |
43 | break; \ | 67 | break; \ |
44 | \ | 68 | \ |
45 | case LONGINT_INVALID_SUFFIX_CHAR: \ | 69 | case LONGINT_INVALID_SUFFIX_CHAR: \ |
46 | error ((Exit_code), 0, "invalid character following %s `%s'", \ | 70 | case LONGINT_INVALID_SUFFIX_CHAR | LONGINT_OVERFLOW: \ |
71 | error ((Exit_code), 0, "invalid character following %s in `%s'", \ | ||
47 | (Argument_type_string), (Str)); \ | 72 | (Argument_type_string), (Str)); \ |
48 | break; \ | 73 | break; \ |
49 | \ | 74 | \ |
... | @@ -56,7 +81,7 @@ _DECLARE_XSTRTOL (xstrtoumax, uintmax_t) | ... | @@ -56,7 +81,7 @@ _DECLARE_XSTRTOL (xstrtoumax, uintmax_t) |
56 | while (0) | 81 | while (0) |
57 | 82 | ||
58 | # define STRTOL_FATAL_ERROR(Str, Argument_type_string, Err) \ | 83 | # define STRTOL_FATAL_ERROR(Str, Argument_type_string, Err) \ |
59 | _STRTOL_ERROR (2, Str, Argument_type_string, Err) | 84 | _STRTOL_ERROR (exit_failure, Str, Argument_type_string, Err) |
60 | 85 | ||
61 | # define STRTOL_FAIL_WARN(Str, Argument_type_string, Err) \ | 86 | # define STRTOL_FAIL_WARN(Str, Argument_type_string, Err) \ |
62 | _STRTOL_ERROR (0, Str, Argument_type_string, Err) | 87 | _STRTOL_ERROR (0, Str, Argument_type_string, Err) | ... | ... |
1 | ## $Id$ | 1 | # getopt.m4 serial 7 |
2 | dnl Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. | ||
3 | dnl This file is free software; the Free Software Foundation | ||
4 | dnl gives unlimited permission to copy and/or distribute it, | ||
5 | dnl with or without modifications, as long as this notice is preserved. | ||
2 | 6 | ||
3 | ## Check for getopt_long. This can't be done in AC_CHECK_FUNCS since | 7 | # The getopt module assume you want GNU getopt, with getopt_long etc, |
4 | ## the function can be present in different libraries (namely, libmysqlclient) | 8 | # rather than vanilla POSIX getopt. This means your your code should |
5 | ## but the necessary header files may be absent, thus AC_CHECK_FUNCS will | 9 | # always include <getopt.h> for the getopt prototypes. |
6 | ## mark function as existent, whereas the compilation will bail out. | ||
7 | 10 | ||
8 | AH_TEMPLATE(HAVE_GNU_GETOPT, [Define if your system has GNU getopt functions]) | 11 | AC_DEFUN([gl_GETOPT_SUBSTITUTE], |
12 | [ | ||
13 | GETOPT_H=getopt.h | ||
14 | MU_LIBOBJ([getopt]) | ||
15 | MU_LIBOBJ([getopt1]) | ||
16 | AC_DEFINE([__GETOPT_PREFIX], [[rpl_]], | ||
17 | [Define to rpl_ if the getopt replacement functions and variables | ||
18 | should be used.]) | ||
19 | AC_SUBST([GETOPT_H]) | ||
20 | ]) | ||
9 | 21 | ||
10 | AC_DEFUN([MU_REPLACE_GNU_GETOPT], | 22 | AC_DEFUN([gl_GETOPT], |
11 | [ | 23 | [ |
12 | AC_CHECK_HEADER([getopt.h], | 24 | gl_PREREQ_GETOPT |
13 | mu_cv_have_getopt_h=yes | ||
14 | AC_DEFINE(HAVE_GETOPT_H,1,[Define if the system has getopt.h]), | ||
15 | mu_cv_have_getopt_h=no) | ||
16 | AC_CACHE_CHECK([for GNU getopt], mu_cv_have_gnu_getopt, | ||
17 | [ | ||
18 | AC_TRY_RUN([ | ||
19 | #include <unistd.h> | ||
20 | #ifdef HAVE_GETOPT_H | ||
21 | # include <getopt.h> | ||
22 | #endif | ||
23 | 25 | ||
24 | struct option longopt[] = { | 26 | if test -z "$GETOPT_H"; then |
25 | "help", no_argument, 0, 'h', | 27 | GETOPT_H= |
26 | (char*)0 | 28 | AC_CHECK_HEADERS([getopt.h], [], [GETOPT_H=getopt.h]) |
27 | }; | 29 | AC_CHECK_FUNCS([getopt_long_only], [], [GETOPT_H=getopt.h]) |
28 | 30 | ||
29 | main(argc, argv) | 31 | dnl BSD getopt_long uses an incompatible method to reset option processing, |
30 | int argc; char **argv; | 32 | dnl and (as of 2004-10-15) mishandles optional option-arguments. |
31 | { | 33 | AC_CHECK_DECL([optreset], [GETOPT_H=getopt.h], [], [#include <getopt.h>]) |
32 | getopt_long_only(argc, argv, "h", longopt, (int*)0); | ||
33 | return 0; | ||
34 | } ], | ||
35 | mu_cv_have_gnu_getopt=yes, | ||
36 | mu_cv_have_gnu_getopt=no, | ||
37 | mu_cv_have_gnu_getopt=no)]) | ||
38 | 34 | ||
39 | if test x"$mu_cv_have_gnu_getopt" != xyes ; then | 35 | if test -n "$GETOPT_H"; then |
40 | mu_cv_have_getopt_h=no | 36 | gl_GETOPT_SUBSTITUTE |
41 | MU_LIBOBJ(getopt) | ||
42 | MU_LIBOBJ(getopt1) | ||
43 | else | ||
44 | AC_DEFINE(HAVE_GNU_GETOPT) | ||
45 | fi | 37 | fi |
46 | if test "$mu_cv_have_getopt_h" = no; then | ||
47 | MU_HEADER(getopt.h) | ||
48 | fi | 38 | fi |
49 | ]) | 39 | ]) |
50 | 40 | ||
51 | 41 | # Prerequisites of lib/getopt*. | |
52 | 42 | AC_DEFUN([gl_PREREQ_GETOPT], [:]) | |
53 | ... | ... |
1 | #serial 12 | 1 | #serial 22 |
2 | |||
3 | # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004 Free | ||
4 | # Software Foundation, Inc. | ||
5 | # | ||
6 | # This file is free software; the Free Software Foundation | ||
7 | # gives unlimited permission to copy and/or distribute it, | ||
8 | # with or without modifications, as long as this notice is preserved. | ||
2 | 9 | ||
3 | dnl Initially derived from code in GNU grep. | 10 | dnl Initially derived from code in GNU grep. |
4 | dnl Mostly written by Jim Meyering. | 11 | dnl Mostly written by Jim Meyering. |
5 | 12 | ||
6 | dnl Usage: jm_INCLUDED_REGEX([lib/regex.c]) | 13 | AC_DEFUN([gl_REGEX], |
14 | [ | ||
15 | gl_INCLUDED_REGEX([lib/regex.c]) | ||
16 | ]) | ||
17 | |||
18 | dnl Usage: gl_INCLUDED_REGEX([lib/regex.c]) | ||
7 | dnl | 19 | dnl |
8 | AC_DEFUN([jm_INCLUDED_REGEX], | 20 | AC_DEFUN([gl_INCLUDED_REGEX], |
9 | [ | 21 | [ |
10 | dnl Even packages that don't use regex.c can use this macro. | 22 | dnl Even packages that don't use regex.c can use this macro. |
11 | dnl Of course, for them it doesn't do anything. | 23 | dnl Of course, for them it doesn't do anything. |
... | @@ -22,6 +34,7 @@ AC_DEFUN([jm_INCLUDED_REGEX], | ... | @@ -22,6 +34,7 @@ AC_DEFUN([jm_INCLUDED_REGEX], |
22 | jm_cv_func_working_re_compile_pattern, | 34 | jm_cv_func_working_re_compile_pattern, |
23 | AC_TRY_RUN( | 35 | AC_TRY_RUN( |
24 | [#include <stdio.h> | 36 | [#include <stdio.h> |
37 | #include <string.h> | ||
25 | #include <regex.h> | 38 | #include <regex.h> |
26 | int | 39 | int |
27 | main () | 40 | main () |
... | @@ -30,12 +43,14 @@ AC_DEFUN([jm_INCLUDED_REGEX], | ... | @@ -30,12 +43,14 @@ AC_DEFUN([jm_INCLUDED_REGEX], |
30 | const char *s; | 43 | const char *s; |
31 | struct re_registers regs; | 44 | struct re_registers regs; |
32 | re_set_syntax (RE_SYNTAX_POSIX_EGREP); | 45 | re_set_syntax (RE_SYNTAX_POSIX_EGREP); |
46 | memset (®ex, 0, sizeof (regex)); | ||
33 | [s = re_compile_pattern ("a[[:@:>@:]]b\n", 9, ®ex);] | 47 | [s = re_compile_pattern ("a[[:@:>@:]]b\n", 9, ®ex);] |
34 | /* This should fail with _Invalid character class name_ error. */ | 48 | /* This should fail with _Invalid character class name_ error. */ |
35 | if (!s) | 49 | if (!s) |
36 | exit (1); | 50 | exit (1); |
37 | 51 | ||
38 | /* This should succeed, but doesn't for e.g. glibc-2.1.3. */ | 52 | /* This should succeed, but doesn't for e.g. glibc-2.1.3. */ |
53 | memset (®ex, 0, sizeof (regex)); | ||
39 | s = re_compile_pattern ("{1", 2, ®ex); | 54 | s = re_compile_pattern ("{1", 2, ®ex); |
40 | 55 | ||
41 | if (s) | 56 | if (s) |
... | @@ -43,7 +58,8 @@ AC_DEFUN([jm_INCLUDED_REGEX], | ... | @@ -43,7 +58,8 @@ AC_DEFUN([jm_INCLUDED_REGEX], |
43 | 58 | ||
44 | /* The following example is derived from a problem report | 59 | /* The following example is derived from a problem report |
45 | against gawk from Jorge Stolfi <stolfi@ic.unicamp.br>. */ | 60 | against gawk from Jorge Stolfi <stolfi@ic.unicamp.br>. */ |
46 | s = re_compile_pattern ("[[anù]]*n", 7, ®ex); | 61 | memset (®ex, 0, sizeof (regex)); |
62 | s = re_compile_pattern ("[[an\371]]*n", 7, ®ex); | ||
47 | if (s) | 63 | if (s) |
48 | exit (1); | 64 | exit (1); |
49 | 65 | ||
... | @@ -51,6 +67,16 @@ AC_DEFUN([jm_INCLUDED_REGEX], | ... | @@ -51,6 +67,16 @@ AC_DEFUN([jm_INCLUDED_REGEX], |
51 | if (re_match (®ex, "an", 2, 0, ®s) != 2) | 67 | if (re_match (®ex, "an", 2, 0, ®s) != 2) |
52 | exit (1); | 68 | exit (1); |
53 | 69 | ||
70 | memset (®ex, 0, sizeof (regex)); | ||
71 | s = re_compile_pattern ("x", 1, ®ex); | ||
72 | if (s) | ||
73 | exit (1); | ||
74 | |||
75 | /* The version of regex.c in e.g. GNU libc-2.2.93 didn't | ||
76 | work with a negative RANGE argument. */ | ||
77 | if (re_search (®ex, "wxy", 3, 2, -2, ®s) != 1) | ||
78 | exit (1); | ||
79 | |||
54 | exit (0); | 80 | exit (0); |
55 | } | 81 | } |
56 | ], | 82 | ], |
... | @@ -67,16 +93,34 @@ AC_DEFUN([jm_INCLUDED_REGEX], | ... | @@ -67,16 +93,34 @@ AC_DEFUN([jm_INCLUDED_REGEX], |
67 | ifelse(m4_sysval, 0, | 93 | ifelse(m4_sysval, 0, |
68 | [ | 94 | [ |
69 | AC_ARG_WITH(included-regex, | 95 | AC_ARG_WITH(included-regex, |
70 | AC_HELP_STRING([--without-included-regex], | 96 | [ --without-included-regex don't compile regex; this is the default on |
71 | [don't compile regex; this is the default on systems with version 2 of the GNU C library (use with caution on other system)]), | 97 | systems with version 2 of the GNU C library |
98 | (use with caution on other system)], | ||
72 | jm_with_regex=$withval, | 99 | jm_with_regex=$withval, |
73 | jm_with_regex=$ac_use_included_regex) | 100 | jm_with_regex=$ac_use_included_regex) |
74 | if test "$jm_with_regex" = yes; then | 101 | if test "$jm_with_regex" = yes; then |
75 | MU_LIBOBJ(regex) | 102 | MU_LIBOBJ(regex) |
76 | MU_HEADER(regex.h) | 103 | gl_PREREQ_REGEX |
77 | MU_HEADER(posix/regex.h) | ||
78 | fi | 104 | fi |
79 | ], | 105 | ], |
80 | ) | 106 | ) |
81 | ] | 107 | ] |
82 | ) | 108 | ) |
109 | |||
110 | # Prerequisites of lib/regex.c. | ||
111 | AC_DEFUN([gl_PREREQ_REGEX], | ||
112 | [ | ||
113 | dnl FIXME: Maybe provide a btowc replacement someday: Solaris 2.5.1 lacks it. | ||
114 | dnl FIXME: Check for wctype and iswctype, and and add -lw if necessary | ||
115 | dnl to get them. | ||
116 | |||
117 | dnl Persuade glibc <string.h> to declare mempcpy(). | ||
118 | AC_REQUIRE([AC_GNU_SOURCE]) | ||
119 | |||
120 | AC_REQUIRE([gl_C_RESTRICT]) | ||
121 | AC_REQUIRE([AC_FUNC_ALLOCA]) | ||
122 | AC_REQUIRE([AC_HEADER_STDC]) | ||
123 | AC_CHECK_HEADERS_ONCE(wchar.h wctype.h) | ||
124 | AC_CHECK_FUNCS_ONCE(isascii mempcpy) | ||
125 | AC_CHECK_FUNCS(btowc) | ||
126 | ]) | ... | ... |
... | @@ -3,20 +3,19 @@ | ... | @@ -3,20 +3,19 @@ |
3 | This file is part of the GNU C Library. | 3 | This file is part of the GNU C Library. |
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | 4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. |
5 | 5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | 6 | This program is free software; you can redistribute it and/or modify |
7 | modify it under the terms of the GNU Library General Public License as | 7 | it under the terms of the GNU General Public License as published by |
8 | published by the Free Software Foundation; either version 2 of the | 8 | the Free Software Foundation; either version 2, or (at your option) |
9 | License, or (at your option) any later version. | 9 | any later version. |
10 | 10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | 11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | Library General Public License for more details. | 14 | GNU General Public License for more details. |
15 | 15 | ||
16 | You should have received a copy of the GNU Library General Public | 16 | You should have received a copy of the GNU General Public License along |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 17 | with this program; if not, write to the Free Software Foundation, |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
19 | Boston, MA 02111-1307, USA. */ | ||
20 | 19 | ||
21 | /* If set by the user program, it should point to string that is the | 20 | /* If set by the user program, it should point to string that is the |
22 | bug-reporting address for the program. It will be printed by argp_help if | 21 | bug-reporting address for the program. It will be printed by argp_help if | ... | ... |
1 | /* Default definition for ARGP_ERR_EXIT_STATUS | 1 | /* Default definition for ARGP_ERR_EXIT_STATUS |
2 | Copyright (C) 1997, 2001 Free Software Foundation, Inc. | 2 | Copyright (C) 1997 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. | 3 | This file is part of the GNU C Library. |
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | 4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. |
5 | 5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | 6 | This program is free software; you can redistribute it and/or modify |
7 | modify it under the terms of the GNU Library General Public License as | 7 | it under the terms of the GNU General Public License as published by |
8 | published by the Free Software Foundation; either version 2 of the | 8 | the Free Software Foundation; either version 2, or (at your option) |
9 | License, or (at your option) any later version. | 9 | any later version. |
10 | 10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | 11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | Library General Public License for more details. | 14 | GNU General Public License for more details. |
15 | 15 | ||
16 | You should have received a copy of the GNU Library General Public | 16 | You should have received a copy of the GNU General Public License along |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 17 | with this program; if not, write to the Free Software Foundation, |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
19 | Boston, MA 02111-1307, USA. */ | ||
20 | 19 | ||
21 | #ifdef HAVE_CONFIG_H | 20 | #ifdef HAVE_CONFIG_H |
22 | #include <config.h> | 21 | #include <config.h> |
23 | #endif | 22 | #endif |
24 | 23 | ||
25 | #ifdef HAVE_SYSEXITS_H | ||
26 | #include <sysexits.h> | 24 | #include <sysexits.h> |
27 | #endif | ||
28 | |||
29 | #ifndef EX_USAGE | ||
30 | #define EX_USAGE 64 | ||
31 | #endif | ||
32 | 25 | ||
33 | #include "argp.h" | 26 | #include "argp.h" |
34 | 27 | ... | ... |
1 | /* Word-wrapping and line-truncating streams | 1 | /* Word-wrapping and line-truncating streams |
2 | Copyright (C) 1997, 1998, 1999, 2001 Free Software Foundation, Inc. | 2 | Copyright (C) 1997,1998,1999,2001,2002,2003 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. | 3 | This file is part of the GNU C Library. |
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | 4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. |
5 | 5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | 6 | This program is free software; you can redistribute it and/or modify |
7 | modify it under the terms of the GNU Library General Public License as | 7 | it under the terms of the GNU General Public License as published by |
8 | published by the Free Software Foundation; either version 2 of the | 8 | the Free Software Foundation; either version 2, or (at your option) |
9 | License, or (at your option) any later version. | 9 | any later version. |
10 | 10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | 11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | Library General Public License for more details. | 14 | GNU General Public License for more details. |
15 | 15 | ||
16 | You should have received a copy of the GNU Library General Public | 16 | You should have received a copy of the GNU General Public License along |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 17 | with this program; if not, write to the Free Software Foundation, |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
19 | Boston, MA 02111-1307, USA. */ | ||
20 | 19 | ||
21 | /* This package emulates glibc `line_wrap_stream' semantics for systems that | 20 | /* This package emulates glibc `line_wrap_stream' semantics for systems that |
22 | don't have that. */ | 21 | don't have that. */ |
... | @@ -40,6 +39,12 @@ | ... | @@ -40,6 +39,12 @@ |
40 | #define isblank(ch) ((ch)==' ' || (ch)=='\t') | 39 | #define isblank(ch) ((ch)==' ' || (ch)=='\t') |
41 | #endif | 40 | #endif |
42 | 41 | ||
42 | #if defined _LIBC && defined USE_IN_LIBIO | ||
43 | # include <wchar.h> | ||
44 | # include <libio/libioP.h> | ||
45 | # define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a) | ||
46 | #endif | ||
47 | |||
43 | #define INIT_BUF_SIZE 200 | 48 | #define INIT_BUF_SIZE 200 |
44 | #define PRINTF_SIZE_GUESS 150 | 49 | #define PRINTF_SIZE_GUESS 150 |
45 | 50 | ||
... | @@ -53,8 +58,10 @@ argp_fmtstream_t | ... | @@ -53,8 +58,10 @@ argp_fmtstream_t |
53 | __argp_make_fmtstream (FILE *stream, | 58 | __argp_make_fmtstream (FILE *stream, |
54 | size_t lmargin, size_t rmargin, ssize_t wmargin) | 59 | size_t lmargin, size_t rmargin, ssize_t wmargin) |
55 | { | 60 | { |
56 | argp_fmtstream_t fs = malloc (sizeof (struct argp_fmtstream)); | 61 | argp_fmtstream_t fs; |
57 | if (fs) | 62 | |
63 | fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream)); | ||
64 | if (fs != NULL) | ||
58 | { | 65 | { |
59 | fs->stream = stream; | 66 | fs->stream = stream; |
60 | 67 | ||
... | @@ -64,7 +71,7 @@ __argp_make_fmtstream (FILE *stream, | ... | @@ -64,7 +71,7 @@ __argp_make_fmtstream (FILE *stream, |
64 | fs->point_col = 0; | 71 | fs->point_col = 0; |
65 | fs->point_offs = 0; | 72 | fs->point_offs = 0; |
66 | 73 | ||
67 | fs->buf = malloc (INIT_BUF_SIZE); | 74 | fs->buf = (char *) malloc (INIT_BUF_SIZE); |
68 | if (! fs->buf) | 75 | if (! fs->buf) |
69 | { | 76 | { |
70 | free (fs); | 77 | free (fs); |
... | @@ -79,9 +86,12 @@ __argp_make_fmtstream (FILE *stream, | ... | @@ -79,9 +86,12 @@ __argp_make_fmtstream (FILE *stream, |
79 | 86 | ||
80 | return fs; | 87 | return fs; |
81 | } | 88 | } |
89 | #if 0 | ||
90 | /* Not exported. */ | ||
82 | #ifdef weak_alias | 91 | #ifdef weak_alias |
83 | weak_alias (__argp_make_fmtstream, argp_make_fmtstream) | 92 | weak_alias (__argp_make_fmtstream, argp_make_fmtstream) |
84 | #endif | 93 | #endif |
94 | #endif | ||
85 | 95 | ||
86 | /* Flush FS to its stream, and free it (but don't close the stream). */ | 96 | /* Flush FS to its stream, and free it (but don't close the stream). */ |
87 | void | 97 | void |
... | @@ -89,13 +99,23 @@ __argp_fmtstream_free (argp_fmtstream_t fs) | ... | @@ -89,13 +99,23 @@ __argp_fmtstream_free (argp_fmtstream_t fs) |
89 | { | 99 | { |
90 | __argp_fmtstream_update (fs); | 100 | __argp_fmtstream_update (fs); |
91 | if (fs->p > fs->buf) | 101 | if (fs->p > fs->buf) |
92 | fwrite (fs->buf, 1, fs->p - fs->buf, fs->stream); | 102 | { |
103 | #ifdef USE_IN_LIBIO | ||
104 | if (_IO_fwide (fs->stream, 0) > 0) | ||
105 | __fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf); | ||
106 | else | ||
107 | #endif | ||
108 | fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream); | ||
109 | } | ||
93 | free (fs->buf); | 110 | free (fs->buf); |
94 | free (fs); | 111 | free (fs); |
95 | } | 112 | } |
113 | #if 0 | ||
114 | /* Not exported. */ | ||
96 | #ifdef weak_alias | 115 | #ifdef weak_alias |
97 | weak_alias (__argp_fmtstream_free, argp_fmtstream_free) | 116 | weak_alias (__argp_fmtstream_free, argp_fmtstream_free) |
98 | #endif | 117 | #endif |
118 | #endif | ||
99 | 119 | ||
100 | /* Process FS's buffer so that line wrapping is done from POINT_OFFS to the | 120 | /* Process FS's buffer so that line wrapping is done from POINT_OFFS to the |
101 | end of its buffer. This code is mostly from glibc stdio/linewrap.c. */ | 121 | end of its buffer. This code is mostly from glibc stdio/linewrap.c. */ |
... | @@ -129,7 +149,14 @@ __argp_fmtstream_update (argp_fmtstream_t fs) | ... | @@ -129,7 +149,14 @@ __argp_fmtstream_update (argp_fmtstream_t fs) |
129 | /* No buffer space for spaces. Must flush. */ | 149 | /* No buffer space for spaces. Must flush. */ |
130 | size_t i; | 150 | size_t i; |
131 | for (i = 0; i < pad; i++) | 151 | for (i = 0; i < pad; i++) |
132 | putc (' ', fs->stream); | 152 | { |
153 | #ifdef USE_IN_LIBIO | ||
154 | if (_IO_fwide (fs->stream, 0) > 0) | ||
155 | putwc_unlocked (L' ', fs->stream); | ||
156 | else | ||
157 | #endif | ||
158 | putc_unlocked (' ', fs->stream); | ||
159 | } | ||
133 | } | 160 | } |
134 | fs->point_col = pad; | 161 | fs->point_col = pad; |
135 | } | 162 | } |
... | @@ -245,9 +272,10 @@ __argp_fmtstream_update (argp_fmtstream_t fs) | ... | @@ -245,9 +272,10 @@ __argp_fmtstream_update (argp_fmtstream_t fs) |
245 | at the end of the buffer, and NEXTLINE is in fact empty (and so | 272 | at the end of the buffer, and NEXTLINE is in fact empty (and so |
246 | we need not be careful to maintain its contents). */ | 273 | we need not be careful to maintain its contents). */ |
247 | 274 | ||
248 | if (nextline == buf + len + 1 | 275 | if ((nextline == buf + len + 1 |
249 | ? fs->end - nl < fs->wmargin + 1 | 276 | ? fs->end - nl < fs->wmargin + 1 |
250 | : nextline - (nl + 1) < fs->wmargin) | 277 | : nextline - (nl + 1) < fs->wmargin) |
278 | && fs->p > nextline) | ||
251 | { | 279 | { |
252 | /* The margin needs more blanks than we removed. */ | 280 | /* The margin needs more blanks than we removed. */ |
253 | if (fs->end - fs->p > fs->wmargin + 1) | 281 | if (fs->end - fs->p > fs->wmargin + 1) |
... | @@ -262,9 +290,17 @@ __argp_fmtstream_update (argp_fmtstream_t fs) | ... | @@ -262,9 +290,17 @@ __argp_fmtstream_update (argp_fmtstream_t fs) |
262 | else | 290 | else |
263 | /* Output the first line so we can use the space. */ | 291 | /* Output the first line so we can use the space. */ |
264 | { | 292 | { |
293 | #ifdef USE_IN_LIBIO | ||
294 | if (_IO_fwide (fs->stream, 0) > 0) | ||
295 | __fwprintf (fs->stream, L"%.*s\n", | ||
296 | (int) (nl - fs->buf), fs->buf); | ||
297 | else | ||
298 | #endif | ||
299 | { | ||
265 | if (nl > fs->buf) | 300 | if (nl > fs->buf) |
266 | fwrite (fs->buf, 1, nl - fs->buf, fs->stream); | 301 | fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream); |
267 | putc ('\n', fs->stream); | 302 | putc_unlocked ('\n', fs->stream); |
303 | } | ||
268 | len += buf - fs->buf; | 304 | len += buf - fs->buf; |
269 | nl = buf = fs->buf; | 305 | nl = buf = fs->buf; |
270 | } | 306 | } |
... | @@ -281,7 +317,12 @@ __argp_fmtstream_update (argp_fmtstream_t fs) | ... | @@ -281,7 +317,12 @@ __argp_fmtstream_update (argp_fmtstream_t fs) |
281 | *nl++ = ' '; | 317 | *nl++ = ' '; |
282 | else | 318 | else |
283 | for (i = 0; i < fs->wmargin; ++i) | 319 | for (i = 0; i < fs->wmargin; ++i) |
284 | putc (' ', fs->stream); | 320 | #ifdef USE_IN_LIBIO |
321 | if (_IO_fwide (fs->stream, 0) > 0) | ||
322 | putwc_unlocked (L' ', fs->stream); | ||
323 | else | ||
324 | #endif | ||
325 | putc_unlocked (' ', fs->stream); | ||
285 | 326 | ||
286 | /* Copy the tail of the original buffer into the current buffer | 327 | /* Copy the tail of the original buffer into the current buffer |
287 | position. */ | 328 | position. */ |
... | @@ -318,7 +359,15 @@ __argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount) | ... | @@ -318,7 +359,15 @@ __argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount) |
318 | /* Flush FS's buffer. */ | 359 | /* Flush FS's buffer. */ |
319 | __argp_fmtstream_update (fs); | 360 | __argp_fmtstream_update (fs); |
320 | 361 | ||
321 | wrote = fwrite (fs->buf, 1, fs->p - fs->buf, fs->stream); | 362 | #ifdef USE_IN_LIBIO |
363 | if (_IO_fwide (fs->stream, 0) > 0) | ||
364 | { | ||
365 | __fwprintf (fs->stream, L"%.*s", (int) (fs->p - fs->buf), fs->buf); | ||
366 | wrote = fs->p - fs->buf; | ||
367 | } | ||
368 | else | ||
369 | #endif | ||
370 | wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream); | ||
322 | if (wrote == fs->p - fs->buf) | 371 | if (wrote == fs->p - fs->buf) |
323 | { | 372 | { |
324 | fs->p = fs->buf; | 373 | fs->p = fs->buf; |
... | @@ -335,12 +384,13 @@ __argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount) | ... | @@ -335,12 +384,13 @@ __argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount) |
335 | if ((size_t) (fs->end - fs->buf) < amount) | 384 | if ((size_t) (fs->end - fs->buf) < amount) |
336 | /* Gotta grow the buffer. */ | 385 | /* Gotta grow the buffer. */ |
337 | { | 386 | { |
338 | size_t new_size = fs->end - fs->buf + amount; | 387 | size_t old_size = fs->end - fs->buf; |
339 | char *new_buf = realloc (fs->buf, new_size); | 388 | size_t new_size = old_size + amount; |
389 | char *new_buf; | ||
340 | 390 | ||
341 | if (! new_buf) | 391 | if (new_size < old_size || ! (new_buf = realloc (fs->buf, new_size))) |
342 | { | 392 | { |
343 | errno = ENOMEM; | 393 | __set_errno (ENOMEM); |
344 | return 0; | 394 | return 0; |
345 | } | 395 | } |
346 | 396 | ||
... | @@ -369,19 +419,22 @@ __argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...) | ... | @@ -369,19 +419,22 @@ __argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...) |
369 | 419 | ||
370 | va_start (args, fmt); | 420 | va_start (args, fmt); |
371 | avail = fs->end - fs->p; | 421 | avail = fs->end - fs->p; |
372 | out = vsnprintf (fs->p, avail, fmt, args); | 422 | out = __vsnprintf (fs->p, avail, fmt, args); |
373 | va_end (args); | 423 | va_end (args); |
374 | if (out >= avail) | 424 | if ((size_t) out >= avail) |
375 | size_guess = out + 1; | 425 | size_guess = out + 1; |
376 | } | 426 | } |
377 | while (out >= avail); | 427 | while ((size_t) out >= avail); |
378 | 428 | ||
379 | fs->p += out; | 429 | fs->p += out; |
380 | 430 | ||
381 | return out; | 431 | return out; |
382 | } | 432 | } |
433 | #if 0 | ||
434 | /* Not exported. */ | ||
383 | #ifdef weak_alias | 435 | #ifdef weak_alias |
384 | weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf) | 436 | weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf) |
385 | #endif | 437 | #endif |
438 | #endif | ||
386 | 439 | ||
387 | #endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */ | 440 | #endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */ | ... | ... |
1 | /* Word-wrapping and line-truncating streams. | 1 | /* Word-wrapping and line-truncating streams. |
2 | Copyright (C) 1997, 2001 Free Software Foundation, Inc. | 2 | Copyright (C) 1997 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. | 3 | This file is part of the GNU C Library. |
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | 4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. |
5 | 5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | 6 | This program is free software; you can redistribute it and/or modify |
7 | modify it under the terms of the GNU Library General Public License as | 7 | it under the terms of the GNU General Public License as published by |
8 | published by the Free Software Foundation; either version 2 of the | 8 | the Free Software Foundation; either version 2, or (at your option) |
9 | License, or (at your option) any later version. | 9 | any later version. |
10 | 10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | 11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | Library General Public License for more details. | 14 | GNU General Public License for more details. |
15 | 15 | ||
16 | You should have received a copy of the GNU Library General Public | 16 | You should have received a copy of the GNU General Public License along |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 17 | with this program; if not, write to the Free Software Foundation, |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
19 | Boston, MA 02111-1307, USA. */ | ||
20 | 19 | ||
21 | /* This package emulates glibc `line_wrap_stream' semantics for systems that | 20 | /* This package emulates glibc `line_wrap_stream' semantics for systems that |
22 | don't have that. If the system does have it, it is just a wrapper for | 21 | don't have that. If the system does have it, it is just a wrapper for |
... | @@ -34,6 +33,19 @@ | ... | @@ -34,6 +33,19 @@ |
34 | #include <string.h> | 33 | #include <string.h> |
35 | #include <unistd.h> | 34 | #include <unistd.h> |
36 | 35 | ||
36 | #ifndef __attribute__ | ||
37 | /* This feature is available in gcc versions 2.5 and later. */ | ||
38 | # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ | ||
39 | # define __attribute__(Spec) /* empty */ | ||
40 | # endif | ||
41 | /* The __-protected variants of `format' and `printf' attributes | ||
42 | are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ | ||
43 | # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || __STRICT_ANSI__ | ||
44 | # define __format__ format | ||
45 | # define __printf__ printf | ||
46 | # endif | ||
47 | #endif | ||
48 | |||
37 | #if (_LIBC - 0 && !defined (USE_IN_LIBIO)) \ | 49 | #if (_LIBC - 0 && !defined (USE_IN_LIBIO)) \ |
38 | || (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H)) | 50 | || (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H)) |
39 | /* line_wrap_stream is available, so use that. */ | 51 | /* line_wrap_stream is available, so use that. */ |
... | @@ -82,6 +94,9 @@ typedef FILE *argp_fmtstream_t; | ... | @@ -82,6 +94,9 @@ typedef FILE *argp_fmtstream_t; |
82 | #else /* !ARGP_FMTSTREAM_USE_LINEWRAP */ | 94 | #else /* !ARGP_FMTSTREAM_USE_LINEWRAP */ |
83 | /* Guess we have to define our own version. */ | 95 | /* Guess we have to define our own version. */ |
84 | 96 | ||
97 | #ifndef __const | ||
98 | #define __const const | ||
99 | #endif | ||
85 | 100 | ||
86 | struct argp_fmtstream | 101 | struct argp_fmtstream |
87 | { | 102 | { |
... | @@ -122,20 +137,22 @@ extern void __argp_fmtstream_free (argp_fmtstream_t __fs); | ... | @@ -122,20 +137,22 @@ extern void __argp_fmtstream_free (argp_fmtstream_t __fs); |
122 | extern void argp_fmtstream_free (argp_fmtstream_t __fs); | 137 | extern void argp_fmtstream_free (argp_fmtstream_t __fs); |
123 | 138 | ||
124 | extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs, | 139 | extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs, |
125 | const char *__fmt, ...); | 140 | __const char *__fmt, ...) |
141 | __attribute__ ((__format__ (printf, 2, 3))); | ||
126 | extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs, | 142 | extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs, |
127 | const char *__fmt, ...); | 143 | __const char *__fmt, ...) |
144 | __attribute__ ((__format__ (printf, 2, 3))); | ||
128 | 145 | ||
129 | extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); | 146 | extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); |
130 | extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); | 147 | extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); |
131 | 148 | ||
132 | extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str); | 149 | extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str); |
133 | extern int argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str); | 150 | extern int argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str); |
134 | 151 | ||
135 | extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs, | 152 | extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs, |
136 | const char *__str, size_t __len); | 153 | __const char *__str, size_t __len); |
137 | extern size_t argp_fmtstream_write (argp_fmtstream_t __fs, | 154 | extern size_t argp_fmtstream_write (argp_fmtstream_t __fs, |
138 | const char *__str, size_t __len); | 155 | __const char *__str, size_t __len); |
139 | 156 | ||
140 | /* Access macros for various bits of state. */ | 157 | /* Access macros for various bits of state. */ |
141 | #define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin) | 158 | #define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin) |
... | @@ -194,7 +211,7 @@ extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); | ... | @@ -194,7 +211,7 @@ extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); |
194 | 211 | ||
195 | ARGP_FS_EI size_t | 212 | ARGP_FS_EI size_t |
196 | __argp_fmtstream_write (argp_fmtstream_t __fs, | 213 | __argp_fmtstream_write (argp_fmtstream_t __fs, |
197 | const char *__str, size_t __len) | 214 | __const char *__str, size_t __len) |
198 | { | 215 | { |
199 | if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len)) | 216 | if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len)) |
200 | { | 217 | { |
... | @@ -207,7 +224,7 @@ __argp_fmtstream_write (argp_fmtstream_t __fs, | ... | @@ -207,7 +224,7 @@ __argp_fmtstream_write (argp_fmtstream_t __fs, |
207 | } | 224 | } |
208 | 225 | ||
209 | ARGP_FS_EI int | 226 | ARGP_FS_EI int |
210 | __argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str) | 227 | __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str) |
211 | { | 228 | { |
212 | size_t __len = strlen (__str); | 229 | size_t __len = strlen (__str); |
213 | if (__len) | 230 | if (__len) | ... | ... |
1 | /* Real definitions for extern inline functions in argp-fmtstream.h | 1 | /* Real definitions for extern inline functions in argp-fmtstream.h |
2 | Copyright (C) 1997 Free Software Foundation, Inc. | 2 | Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. | 3 | This file is part of the GNU C Library. |
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | 4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. |
5 | 5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | 6 | This program is free software; you can redistribute it and/or modify |
7 | modify it under the terms of the GNU Library General Public License as | 7 | it under the terms of the GNU General Public License as published by |
8 | published by the Free Software Foundation; either version 2 of the | 8 | the Free Software Foundation; either version 2, or (at your option) |
9 | License, or (at your option) any later version. | 9 | any later version. |
10 | 10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | 11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | Library General Public License for more details. | 14 | GNU General Public License for more details. |
15 | 15 | ||
16 | You should have received a copy of the GNU Library General Public | 16 | You should have received a copy of the GNU General Public License along |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 17 | with this program; if not, write to the Free Software Foundation, |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
19 | Boston, MA 02111-1307, USA. */ | ||
20 | 19 | ||
21 | #ifdef HAVE_CONFIG_H | 20 | #ifdef HAVE_CONFIG_H |
22 | #include <config.h> | 21 | #include <config.h> |
... | @@ -24,9 +23,11 @@ | ... | @@ -24,9 +23,11 @@ |
24 | 23 | ||
25 | #define ARGP_FS_EI | 24 | #define ARGP_FS_EI |
26 | #undef __OPTIMIZE__ | 25 | #undef __OPTIMIZE__ |
27 | #define __OPTIMIZE__ | 26 | #define __OPTIMIZE__ 1 |
28 | #include "argp-fmtstream.h" | 27 | #include "argp-fmtstream.h" |
29 | 28 | ||
29 | #if 0 | ||
30 | /* Not exported. */ | ||
30 | /* Add weak aliases. */ | 31 | /* Add weak aliases. */ |
31 | #if _LIBC - 0 && !defined (ARGP_FMTSTREAM_USE_LINEWRAP) && defined (weak_alias) | 32 | #if _LIBC - 0 && !defined (ARGP_FMTSTREAM_USE_LINEWRAP) && defined (weak_alias) |
32 | 33 | ||
... | @@ -39,3 +40,4 @@ weak_alias (__argp_fmtstream_set_wmargin, argp_fmtstream_set_wmargin) | ... | @@ -39,3 +40,4 @@ weak_alias (__argp_fmtstream_set_wmargin, argp_fmtstream_set_wmargin) |
39 | weak_alias (__argp_fmtstream_point, argp_fmtstream_point) | 40 | weak_alias (__argp_fmtstream_point, argp_fmtstream_point) |
40 | 41 | ||
41 | #endif | 42 | #endif |
43 | #endif | ... | ... |
1 | /* Hierarchial argument parsing help output | 1 | /* Hierarchial argument parsing help output |
2 | Copyright (C) 1995,1996,1997,1998,1999,2000, 2001 Free Software Foundation, Inc. | 2 | Copyright (C) 1995-2003, 2004, 2005 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. | 3 | This file is part of the GNU C Library. |
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | 4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. |
5 | 5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | 6 | This program is free software; you can redistribute it and/or modify |
7 | modify it under the terms of the GNU Library General Public License as | 7 | it under the terms of the GNU General Public License as published by |
8 | published by the Free Software Foundation; either version 2 of the | 8 | the Free Software Foundation; either version 2, or (at your option) |
9 | License, or (at your option) any later version. | 9 | any later version. |
10 | 10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | 11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | Library General Public License for more details. | 14 | GNU General Public License for more details. |
15 | 15 | ||
16 | You should have received a copy of the GNU Library General Public | 16 | You should have received a copy of the GNU General Public License along |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 17 | with this program; if not, write to the Free Software Foundation, |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
19 | Boston, MA 02111-1307, USA. */ | ||
20 | 19 | ||
21 | #ifndef _GNU_SOURCE | 20 | #ifndef _GNU_SOURCE |
22 | # define _GNU_SOURCE 1 | 21 | # define _GNU_SOURCE 1 |
... | @@ -26,73 +25,35 @@ | ... | @@ -26,73 +25,35 @@ |
26 | #include <config.h> | 25 | #include <config.h> |
27 | #endif | 26 | #endif |
28 | 27 | ||
29 | #include <mailutils/nls.h> | 28 | #include <alloca.h> |
30 | 29 | #include <errno.h> | |
31 | #ifndef alloca | ||
32 | # ifdef __GNUC__ | ||
33 | # define alloca __builtin_alloca | ||
34 | # define HAVE_ALLOCA 1 | ||
35 | # else | ||
36 | # if defined HAVE_ALLOCA_H || defined _LIBC | ||
37 | # include <alloca.h> | ||
38 | # else | ||
39 | # ifdef _AIX | ||
40 | #pragma alloca | ||
41 | # else | ||
42 | # ifndef alloca | ||
43 | char *alloca (); | ||
44 | # endif | ||
45 | # endif | ||
46 | # endif | ||
47 | # endif | ||
48 | #endif | ||
49 | |||
50 | #include <stddef.h> | 30 | #include <stddef.h> |
51 | #include <stdlib.h> | 31 | #include <stdlib.h> |
52 | #include <string.h> | 32 | #include <string.h> |
53 | #include <assert.h> | 33 | #include <assert.h> |
54 | #include <stdarg.h> | 34 | #include <stdarg.h> |
55 | #ifdef HAVE_MALLOC_H | ||
56 | # include <malloc.h> | ||
57 | #endif | ||
58 | #include <ctype.h> | 35 | #include <ctype.h> |
59 | 36 | #include <limits.h> | |
60 | #ifdef HAVE_STRINGS_H | 37 | #ifdef USE_IN_LIBIO |
61 | # include <strings.h> | 38 | # include <wchar.h> |
62 | #endif | 39 | #endif |
63 | 40 | ||
64 | #ifndef _ | 41 | #ifdef _LIBC |
65 | /* This is for other GNU distributions with internationalized messages. */ | ||
66 | # if defined HAVE_LIBINTL_H || defined _LIBC | ||
67 | # include <libintl.h> | 42 | # include <libintl.h> |
68 | # ifdef _LIBC | ||
69 | # undef dgettext | 43 | # undef dgettext |
70 | # define dgettext(domain, msgid) __dcgettext (domain, msgid, LC_MESSAGES) | 44 | # define dgettext(domain, msgid) \ |
71 | # endif | 45 | INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES) |
72 | # else | 46 | #else |
73 | # define dgettext(domain, msgid) (msgid) | 47 | # include "gettext.h" |
74 | # endif | ||
75 | #endif | 48 | #endif |
76 | 49 | ||
77 | #include "argp.h" | 50 | #include "argp.h" |
78 | #include "argp-fmtstream.h" | 51 | #include "argp-fmtstream.h" |
79 | #include "argp-namefrob.h" | 52 | #include "argp-namefrob.h" |
80 | 53 | ||
81 | #ifndef __P | 54 | #ifndef SIZE_MAX |
82 | # if defined PROTOTYPES || (defined __STDC__ && __STDC__) | 55 | # define SIZE_MAX ((size_t) -1) |
83 | # define __P(Args) Args | ||
84 | # else | ||
85 | # define __P(Args) () | ||
86 | # endif | ||
87 | #endif | ||
88 | |||
89 | #if !HAVE_DECL_STRCHRNUL | ||
90 | extern char *strchrnul __P((const char *s, int c_in)); | ||
91 | #endif | 56 | #endif |
92 | #if !HAVE_DECL_STRNDUP | ||
93 | extern char *strndup __P((const char *s, size_t n)); | ||
94 | #endif | ||
95 | |||
96 | 57 | ||
97 | /* User-selectable (using an environment variable) formatting parameters. | 58 | /* User-selectable (using an environment variable) formatting parameters. |
98 | 59 | ||
... | @@ -267,6 +228,9 @@ fill_in_uparams (const struct argp_state *state) | ... | @@ -267,6 +228,9 @@ fill_in_uparams (const struct argp_state *state) |
267 | /* Returns true if OPT is an documentation-only entry. */ | 228 | /* Returns true if OPT is an documentation-only entry. */ |
268 | #define odoc(opt) ((opt)->flags & OPTION_DOC) | 229 | #define odoc(opt) ((opt)->flags & OPTION_DOC) |
269 | 230 | ||
231 | /* Returns true if OPT should not be translated */ | ||
232 | #define onotrans(opt) ((opt)->flags & OPTION_NO_TRANS) | ||
233 | |||
270 | /* Returns true if OPT is the end-of-list marker for a list of options. */ | 234 | /* Returns true if OPT is the end-of-list marker for a list of options. */ |
271 | #define oend(opt) __option_is_end (opt) | 235 | #define oend(opt) __option_is_end (opt) |
272 | 236 | ||
... | @@ -462,6 +426,8 @@ make_hol (const struct argp *argp, struct hol_cluster *cluster) | ... | @@ -462,6 +426,8 @@ make_hol (const struct argp *argp, struct hol_cluster *cluster) |
462 | hol->short_options = malloc (num_short_options + 1); | 426 | hol->short_options = malloc (num_short_options + 1); |
463 | 427 | ||
464 | assert (hol->entries && hol->short_options); | 428 | assert (hol->entries && hol->short_options); |
429 | if (SIZE_MAX <= UINT_MAX) | ||
430 | assert (hol->num_entries <= SIZE_MAX / sizeof (struct hol_entry)); | ||
465 | 431 | ||
466 | /* Fill in the entries. */ | 432 | /* Fill in the entries. */ |
467 | so = hol->short_options; | 433 | so = hol->short_options; |
... | @@ -566,7 +532,8 @@ hol_entry_short_iterate (const struct hol_entry *entry, | ... | @@ -566,7 +532,8 @@ hol_entry_short_iterate (const struct hol_entry *entry, |
566 | return val; | 532 | return val; |
567 | } | 533 | } |
568 | 534 | ||
569 | static int | 535 | static inline int |
536 | __attribute__ ((always_inline)) | ||
570 | hol_entry_long_iterate (const struct hol_entry *entry, | 537 | hol_entry_long_iterate (const struct hol_entry *entry, |
571 | int (*func)(const struct argp_option *opt, | 538 | int (*func)(const struct argp_option *opt, |
572 | const struct argp_option *real, | 539 | const struct argp_option *real, |
... | @@ -590,7 +557,7 @@ hol_entry_long_iterate (const struct hol_entry *entry, | ... | @@ -590,7 +557,7 @@ hol_entry_long_iterate (const struct hol_entry *entry, |
590 | } | 557 | } |
591 | 558 | ||
592 | /* Iterator that returns true for the first short option. */ | 559 | /* Iterator that returns true for the first short option. */ |
593 | static int | 560 | static inline int |
594 | until_short (const struct argp_option *opt, const struct argp_option *real, | 561 | until_short (const struct argp_option *opt, const struct argp_option *real, |
595 | const char *domain, void *cookie) | 562 | const char *domain, void *cookie) |
596 | { | 563 | { |
... | @@ -712,6 +679,11 @@ static int | ... | @@ -712,6 +679,11 @@ static int |
712 | canon_doc_option (const char **name) | 679 | canon_doc_option (const char **name) |
713 | { | 680 | { |
714 | int non_opt; | 681 | int non_opt; |
682 | |||
683 | if (!*name) | ||
684 | non_opt = 1; | ||
685 | else | ||
686 | { | ||
715 | /* Skip initial whitespace. */ | 687 | /* Skip initial whitespace. */ |
716 | while (isspace (**name)) | 688 | while (isspace (**name)) |
717 | (*name)++; | 689 | (*name)++; |
... | @@ -720,6 +692,7 @@ canon_doc_option (const char **name) | ... | @@ -720,6 +692,7 @@ canon_doc_option (const char **name) |
720 | /* Skip until part of name used for sorting. */ | 692 | /* Skip until part of name used for sorting. */ |
721 | while (**name && !isalnum (**name)) | 693 | while (**name && !isalnum (**name)) |
722 | (*name)++; | 694 | (*name)++; |
695 | } | ||
723 | return non_opt; | 696 | return non_opt; |
724 | } | 697 | } |
725 | 698 | ||
... | @@ -772,7 +745,7 @@ hol_entry_cmp (const struct hol_entry *entry1, | ... | @@ -772,7 +745,7 @@ hol_entry_cmp (const struct hol_entry *entry1, |
772 | return doc1 - doc2; | 745 | return doc1 - doc2; |
773 | else if (!short1 && !short2 && long1 && long2) | 746 | else if (!short1 && !short2 && long1 && long2) |
774 | /* Only long options. */ | 747 | /* Only long options. */ |
775 | return strcasecmp (long1, long2); | 748 | return __strcasecmp (long1, long2); |
776 | else | 749 | else |
777 | /* Compare short/short, long/short, short/long, using the first | 750 | /* Compare short/short, long/short, short/long, using the first |
778 | character of long options. Entries without *any* valid | 751 | character of long options. Entries without *any* valid |
... | @@ -853,12 +826,16 @@ hol_append (struct hol *hol, struct hol *more) | ... | @@ -853,12 +826,16 @@ hol_append (struct hol *hol, struct hol *more) |
853 | char *short_options = | 826 | char *short_options = |
854 | malloc (hol_so_len + strlen (more->short_options) + 1); | 827 | malloc (hol_so_len + strlen (more->short_options) + 1); |
855 | 828 | ||
856 | memcpy (entries, hol->entries, | 829 | assert (entries && short_options); |
857 | hol->num_entries * sizeof (struct hol_entry)); | 830 | if (SIZE_MAX <= UINT_MAX) |
858 | memcpy (entries + hol->num_entries, more->entries, | 831 | assert (num_entries <= SIZE_MAX / sizeof (struct hol_entry)); |
832 | |||
833 | __mempcpy (__mempcpy (entries, hol->entries, | ||
834 | hol->num_entries * sizeof (struct hol_entry)), | ||
835 | more->entries, | ||
859 | more->num_entries * sizeof (struct hol_entry)); | 836 | more->num_entries * sizeof (struct hol_entry)); |
860 | 837 | ||
861 | memcpy (short_options, hol->short_options, hol_so_len); | 838 | __mempcpy (short_options, hol->short_options, hol_so_len); |
862 | 839 | ||
863 | /* Fix up the short options pointers from HOL. */ | 840 | /* Fix up the short options pointers from HOL. */ |
864 | for (e = entries, left = hol->num_entries; left > 0; e++, left--) | 841 | for (e = entries, left = hol->num_entries; left > 0; e++, left--) |
... | @@ -1078,9 +1055,8 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, | ... | @@ -1078,9 +1055,8 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, |
1078 | int old_wm = __argp_fmtstream_wmargin (stream); | 1055 | int old_wm = __argp_fmtstream_wmargin (stream); |
1079 | /* PEST is a state block holding some of our variables that we'd like to | 1056 | /* PEST is a state block holding some of our variables that we'd like to |
1080 | share with helper functions. */ | 1057 | share with helper functions. */ |
1081 | /* Some loosing compiler can not handle this ... lets play nice. */ | ||
1082 | /* struct pentry_state pest = { entry, stream, hhstate, 1, state }; */ | ||
1083 | struct pentry_state pest; | 1058 | struct pentry_state pest; |
1059 | |||
1084 | pest.entry = entry; | 1060 | pest.entry = entry; |
1085 | pest.stream = stream; | 1061 | pest.stream = stream; |
1086 | pest.hhstate = hhstate; | 1062 | pest.hhstate = hhstate; |
... | @@ -1120,13 +1096,15 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, | ... | @@ -1120,13 +1096,15 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state, |
1120 | { | 1096 | { |
1121 | __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col); | 1097 | __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col); |
1122 | for (opt = real, num = entry->num; num > 0; opt++, num--) | 1098 | for (opt = real, num = entry->num; num > 0; opt++, num--) |
1123 | if (opt->name && ovisible (opt)) | 1099 | if (opt->name && *opt->name && ovisible (opt)) |
1124 | { | 1100 | { |
1125 | comma (uparams.doc_opt_col, &pest); | 1101 | comma (uparams.doc_opt_col, &pest); |
1126 | /* Calling gettext here isn't quite right, since sorting will | 1102 | /* Calling dgettext here isn't quite right, since sorting will |
1127 | have been done on the original; but documentation options | 1103 | have been done on the original; but documentation options |
1128 | should be pretty rare anyway... */ | 1104 | should be pretty rare anyway... */ |
1129 | __argp_fmtstream_puts (stream, | 1105 | __argp_fmtstream_puts (stream, |
1106 | onotrans (opt) ? | ||
1107 | opt->name : | ||
1130 | dgettext (state->root_argp->argp_domain, | 1108 | dgettext (state->root_argp->argp_domain, |
1131 | opt->name)); | 1109 | opt->name)); |
1132 | } | 1110 | } |
... | @@ -1406,7 +1384,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, | ... | @@ -1406,7 +1384,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, |
1406 | if (fdoc) | 1384 | if (fdoc) |
1407 | { | 1385 | { |
1408 | const char *cp = fdoc; | 1386 | const char *cp = fdoc; |
1409 | nl = strchrnul (cp, '\n'); | 1387 | nl = __strchrnul (cp, '\n'); |
1410 | if (*nl != '\0') | 1388 | if (*nl != '\0') |
1411 | /* This is a `multi-level' args doc; advance to the correct position | 1389 | /* This is a `multi-level' args doc; advance to the correct position |
1412 | as determined by our state in LEVELS, and update LEVELS. */ | 1390 | as determined by our state in LEVELS, and update LEVELS. */ |
... | @@ -1414,7 +1392,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, | ... | @@ -1414,7 +1392,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, |
1414 | int i; | 1392 | int i; |
1415 | multiple = 1; | 1393 | multiple = 1; |
1416 | for (i = 0; i < *our_level; i++) | 1394 | for (i = 0; i < *our_level; i++) |
1417 | cp = nl + 1, nl = strchrnul (cp, '\n'); | 1395 | cp = nl + 1, nl = __strchrnul (cp, '\n'); |
1418 | (*levels)++; | 1396 | (*levels)++; |
1419 | } | 1397 | } |
1420 | 1398 | ||
... | @@ -1482,7 +1460,7 @@ argp_doc (const struct argp *argp, const struct argp_state *state, | ... | @@ -1482,7 +1460,7 @@ argp_doc (const struct argp *argp, const struct argp_state *state, |
1482 | { | 1460 | { |
1483 | if (inp_text_limit) | 1461 | if (inp_text_limit) |
1484 | /* Copy INP_TEXT so that it's nul-terminated. */ | 1462 | /* Copy INP_TEXT so that it's nul-terminated. */ |
1485 | inp_text = strndup (inp_text, inp_text_limit); | 1463 | inp_text = __strndup (inp_text, inp_text_limit); |
1486 | input = __argp_input (argp, state); | 1464 | input = __argp_input (argp, state); |
1487 | text = | 1465 | text = |
1488 | (*argp->help_filter) (post | 1466 | (*argp->help_filter) (post |
... | @@ -1556,12 +1534,19 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, | ... | @@ -1556,12 +1534,19 @@ _help (const struct argp *argp, const struct argp_state *state, FILE *stream, |
1556 | if (! stream) | 1534 | if (! stream) |
1557 | return; | 1535 | return; |
1558 | 1536 | ||
1537 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) | ||
1538 | __flockfile (stream); | ||
1539 | #endif | ||
1540 | |||
1559 | if (! uparams.valid) | 1541 | if (! uparams.valid) |
1560 | fill_in_uparams (state); | 1542 | fill_in_uparams (state); |
1561 | 1543 | ||
1562 | fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0); | 1544 | fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0); |
1563 | if (! fs) | 1545 | if (! fs) |
1564 | { | 1546 | { |
1547 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) | ||
1548 | __funlockfile (stream); | ||
1549 | #endif | ||
1565 | return; | 1550 | return; |
1566 | } | 1551 | } |
1567 | 1552 | ||
... | @@ -1669,6 +1654,10 @@ Try `%s --help' or `%s --usage' for more information.\n"), | ... | @@ -1669,6 +1654,10 @@ Try `%s --help' or `%s --usage' for more information.\n"), |
1669 | anything = 1; | 1654 | anything = 1; |
1670 | } | 1655 | } |
1671 | 1656 | ||
1657 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) | ||
1658 | __funlockfile (stream); | ||
1659 | #endif | ||
1660 | |||
1672 | if (hol) | 1661 | if (hol) |
1673 | hol_free (hol); | 1662 | hol_free (hol); |
1674 | 1663 | ||
... | @@ -1680,12 +1669,34 @@ Try `%s --help' or `%s --usage' for more information.\n"), | ... | @@ -1680,12 +1669,34 @@ Try `%s --help' or `%s --usage' for more information.\n"), |
1680 | void __argp_help (const struct argp *argp, FILE *stream, | 1669 | void __argp_help (const struct argp *argp, FILE *stream, |
1681 | unsigned flags, char *name) | 1670 | unsigned flags, char *name) |
1682 | { | 1671 | { |
1683 | _help (argp, 0, stream, flags, name); | 1672 | struct argp_state state; |
1673 | memset (&state, 0, sizeof state); | ||
1674 | state.root_argp = argp; | ||
1675 | _help (argp, &state, stream, flags, name); | ||
1684 | } | 1676 | } |
1685 | #ifdef weak_alias | 1677 | #ifdef weak_alias |
1686 | weak_alias (__argp_help, argp_help) | 1678 | weak_alias (__argp_help, argp_help) |
1687 | #endif | 1679 | #endif |
1688 | 1680 | ||
1681 | #if ! (defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME) | ||
1682 | char * | ||
1683 | __argp_short_program_name (void) | ||
1684 | { | ||
1685 | # if HAVE_DECL_PROGRAM_INVOCATION_NAME | ||
1686 | char *name = strrchr (program_invocation_name, '/'); | ||
1687 | return name ? name + 1 : program_invocation_name; | ||
1688 | # else | ||
1689 | /* FIXME: What now? Miles suggests that it is better to use NULL, | ||
1690 | but currently the value is passed on directly to fputs_unlocked, | ||
1691 | so that requires more changes. */ | ||
1692 | # if __GNUC__ | ||
1693 | # warning No reasonable value to return | ||
1694 | # endif /* __GNUC__ */ | ||
1695 | return ""; | ||
1696 | # endif | ||
1697 | } | ||
1698 | #endif | ||
1699 | |||
1689 | /* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are | 1700 | /* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are |
1690 | from the set ARGP_HELP_*. */ | 1701 | from the set ARGP_HELP_*. */ |
1691 | void | 1702 | void |
... | @@ -1697,7 +1708,7 @@ __argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags) | ... | @@ -1697,7 +1708,7 @@ __argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags) |
1697 | flags |= ARGP_HELP_LONG_ONLY; | 1708 | flags |= ARGP_HELP_LONG_ONLY; |
1698 | 1709 | ||
1699 | _help (state ? state->root_argp : 0, state, stream, flags, | 1710 | _help (state ? state->root_argp : 0, state, stream, flags, |
1700 | state ? state->name : program_invocation_short_name); | 1711 | state ? state->name : __argp_short_program_name ()); |
1701 | 1712 | ||
1702 | if (!state || ! (state->flags & ARGP_NO_EXIT)) | 1713 | if (!state || ! (state->flags & ARGP_NO_EXIT)) |
1703 | { | 1714 | { |
... | @@ -1726,19 +1737,47 @@ __argp_error (const struct argp_state *state, const char *fmt, ...) | ... | @@ -1726,19 +1737,47 @@ __argp_error (const struct argp_state *state, const char *fmt, ...) |
1726 | { | 1737 | { |
1727 | va_list ap; | 1738 | va_list ap; |
1728 | 1739 | ||
1729 | fputs (state ? state->name : program_invocation_short_name, | 1740 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) |
1730 | stream); | 1741 | __flockfile (stream); |
1731 | putc (':', stream); | 1742 | #endif |
1732 | putc (' ', stream); | ||
1733 | 1743 | ||
1734 | va_start (ap, fmt); | 1744 | va_start (ap, fmt); |
1745 | |||
1746 | #ifdef USE_IN_LIBIO | ||
1747 | if (_IO_fwide (stream, 0) > 0) | ||
1748 | { | ||
1749 | char *buf; | ||
1750 | |||
1751 | if (__asprintf (&buf, fmt, ap) < 0) | ||
1752 | buf = NULL; | ||
1753 | |||
1754 | __fwprintf (stream, L"%s: %s\n", | ||
1755 | state ? state->name : __argp_short_program_name (), | ||
1756 | buf); | ||
1757 | |||
1758 | free (buf); | ||
1759 | } | ||
1760 | else | ||
1761 | #endif | ||
1762 | { | ||
1763 | fputs_unlocked (state | ||
1764 | ? state->name : __argp_short_program_name (), | ||
1765 | stream); | ||
1766 | putc_unlocked (':', stream); | ||
1767 | putc_unlocked (' ', stream); | ||
1768 | |||
1735 | vfprintf (stream, fmt, ap); | 1769 | vfprintf (stream, fmt, ap); |
1736 | va_end (ap); | ||
1737 | 1770 | ||
1738 | putc ('\n', stream); | 1771 | putc_unlocked ('\n', stream); |
1772 | } | ||
1739 | 1773 | ||
1740 | __argp_state_help (state, stream, ARGP_HELP_STD_ERR); | 1774 | __argp_state_help (state, stream, ARGP_HELP_STD_ERR); |
1741 | 1775 | ||
1776 | va_end (ap); | ||
1777 | |||
1778 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) | ||
1779 | __funlockfile (stream); | ||
1780 | #endif | ||
1742 | } | 1781 | } |
1743 | } | 1782 | } |
1744 | } | 1783 | } |
... | @@ -1764,29 +1803,88 @@ __argp_failure (const struct argp_state *state, int status, int errnum, | ... | @@ -1764,29 +1803,88 @@ __argp_failure (const struct argp_state *state, int status, int errnum, |
1764 | 1803 | ||
1765 | if (stream) | 1804 | if (stream) |
1766 | { | 1805 | { |
1767 | fputs (state ? state->name : program_invocation_short_name, | 1806 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) |
1807 | __flockfile (stream); | ||
1808 | #endif | ||
1809 | |||
1810 | #ifdef USE_IN_LIBIO | ||
1811 | if (_IO_fwide (stream, 0) > 0) | ||
1812 | __fwprintf (stream, L"%s", | ||
1813 | state ? state->name : __argp_short_program_name ()); | ||
1814 | else | ||
1815 | #endif | ||
1816 | fputs_unlocked (state | ||
1817 | ? state->name : __argp_short_program_name (), | ||
1768 | stream); | 1818 | stream); |
1769 | 1819 | ||
1770 | if (fmt) | 1820 | if (fmt) |
1771 | { | 1821 | { |
1772 | va_list ap; | 1822 | va_list ap; |
1773 | 1823 | ||
1774 | putc (':', stream); | ||
1775 | putc (' ', stream); | ||
1776 | |||
1777 | va_start (ap, fmt); | 1824 | va_start (ap, fmt); |
1825 | #ifdef USE_IN_LIBIO | ||
1826 | if (_IO_fwide (stream, 0) > 0) | ||
1827 | { | ||
1828 | char *buf; | ||
1829 | |||
1830 | if (__asprintf (&buf, fmt, ap) < 0) | ||
1831 | buf = NULL; | ||
1832 | |||
1833 | __fwprintf (stream, L": %s", buf); | ||
1834 | |||
1835 | free (buf); | ||
1836 | } | ||
1837 | else | ||
1838 | #endif | ||
1839 | { | ||
1840 | putc_unlocked (':', stream); | ||
1841 | putc_unlocked (' ', stream); | ||
1842 | |||
1778 | vfprintf (stream, fmt, ap); | 1843 | vfprintf (stream, fmt, ap); |
1844 | } | ||
1845 | |||
1779 | va_end (ap); | 1846 | va_end (ap); |
1780 | } | 1847 | } |
1781 | 1848 | ||
1782 | if (errnum) | 1849 | if (errnum) |
1783 | { | 1850 | { |
1784 | putc (':', stream); | 1851 | char buf[200]; |
1785 | putc (' ', stream); | 1852 | |
1786 | fputs (strerror (errnum), stream); | 1853 | #ifdef USE_IN_LIBIO |
1854 | if (_IO_fwide (stream, 0) > 0) | ||
1855 | __fwprintf (stream, L": %s", | ||
1856 | __strerror_r (errnum, buf, sizeof (buf))); | ||
1857 | else | ||
1858 | #endif | ||
1859 | { | ||
1860 | char const *s = NULL; | ||
1861 | putc_unlocked (':', stream); | ||
1862 | putc_unlocked (' ', stream); | ||
1863 | #if _LIBC || (HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P) | ||
1864 | s = __strerror_r (errnum, buf, sizeof buf); | ||
1865 | #elif HAVE_DECL_STRERROR_R | ||
1866 | if (__strerror_r (errnum, buf, sizeof buf) == 0) | ||
1867 | s = buf; | ||
1868 | #endif | ||
1869 | #if !_LIBC | ||
1870 | if (! s && ! (s = strerror (errnum))) | ||
1871 | s = dgettext (state->root_argp->argp_domain, | ||
1872 | "Unknown system error"); | ||
1873 | #endif | ||
1874 | fputs (s, stream); | ||
1875 | } | ||
1787 | } | 1876 | } |
1788 | 1877 | ||
1789 | putc ('\n', stream); | 1878 | #ifdef USE_IN_LIBIO |
1879 | if (_IO_fwide (stream, 0) > 0) | ||
1880 | putwc_unlocked (L'\n', stream); | ||
1881 | else | ||
1882 | #endif | ||
1883 | putc_unlocked ('\n', stream); | ||
1884 | |||
1885 | #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) | ||
1886 | __funlockfile (stream); | ||
1887 | #endif | ||
1790 | 1888 | ||
1791 | if (status && (!state || !(state->flags & ARGP_NO_EXIT))) | 1889 | if (status && (!state || !(state->flags & ARGP_NO_EXIT))) |
1792 | exit (status); | 1890 | exit (status); | ... | ... |
1 | /* Name frobnication for compiling argp outside of glibc | 1 | /* Name frobnication for compiling argp outside of glibc |
2 | Copyright (C) 1997, 2001 Free Software Foundation, Inc. | 2 | Copyright (C) 1997, 2003 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. | 3 | This file is part of the GNU C Library. |
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | 4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. |
5 | 5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | 6 | This program is free software; you can redistribute it and/or modify |
7 | modify it under the terms of the GNU Library General Public License as | 7 | it under the terms of the GNU General Public License as published by |
8 | published by the Free Software Foundation; either version 2 of the | 8 | the Free Software Foundation; either version 2, or (at your option) |
9 | License, or (at your option) any later version. | 9 | any later version. |
10 | 10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | 11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | Library General Public License for more details. | 14 | GNU General Public License for more details. |
15 | 15 | ||
16 | You should have received a copy of the GNU Library General Public | 16 | You should have received a copy of the GNU General Public License along |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 17 | with this program; if not, write to the Free Software Foundation, |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
19 | Boston, MA 02111-1307, USA. */ | ||
20 | 19 | ||
21 | #if !_LIBC | 20 | #if !_LIBC |
22 | /* This code is written for inclusion in gnu-libc, and uses names in the | 21 | /* This code is written for inclusion in gnu-libc, and uses names in the |
... | @@ -77,12 +76,81 @@ | ... | @@ -77,12 +76,81 @@ |
77 | #undef __argp_fmtstream_wmargin | 76 | #undef __argp_fmtstream_wmargin |
78 | #define __argp_fmtstream_wmargin argp_fmtstream_wmargin | 77 | #define __argp_fmtstream_wmargin argp_fmtstream_wmargin |
79 | 78 | ||
79 | #include "mempcpy.h" | ||
80 | #include "strcase.h" | ||
81 | #include "strchrnul.h" | ||
82 | #include "strndup.h" | ||
83 | |||
80 | /* normal libc functions we call */ | 84 | /* normal libc functions we call */ |
85 | #undef __flockfile | ||
86 | #define __flockfile flockfile | ||
87 | #undef __funlockfile | ||
88 | #define __funlockfile funlockfile | ||
89 | #undef __mempcpy | ||
90 | #define __mempcpy mempcpy | ||
81 | #undef __sleep | 91 | #undef __sleep |
82 | #define __sleep sleep | 92 | #define __sleep sleep |
83 | #undef __strcasecmp | 93 | #undef __strcasecmp |
84 | #define __strcasecmp strcasecmp | 94 | #define __strcasecmp strcasecmp |
95 | #undef __strchrnul | ||
96 | #define __strchrnul strchrnul | ||
97 | #undef __strerror_r | ||
98 | #define __strerror_r strerror_r | ||
99 | #undef __strndup | ||
100 | #define __strndup strndup | ||
85 | #undef __vsnprintf | 101 | #undef __vsnprintf |
86 | #define __vsnprintf vsnprintf | 102 | #define __vsnprintf vsnprintf |
87 | 103 | ||
104 | #if defined(HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED | ||
105 | # define clearerr_unlocked(x) clearerr (x) | ||
106 | #endif | ||
107 | #if defined(HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED | ||
108 | # define feof_unlocked(x) feof (x) | ||
109 | # endif | ||
110 | #if defined(HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED | ||
111 | # define ferror_unlocked(x) ferror (x) | ||
112 | # endif | ||
113 | #if defined(HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED | ||
114 | # define fflush_unlocked(x) fflush (x) | ||
115 | # endif | ||
116 | #if defined(HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED | ||
117 | # define fgets_unlocked(x,y,z) fgets (x,y,z) | ||
118 | # endif | ||
119 | #if defined(HAVE_DECL_FPUTC_UNLOCKED) && !HAVE_DECL_FPUTC_UNLOCKED | ||
120 | # define fputc_unlocked(x,y) fputc (x,y) | ||
121 | # endif | ||
122 | #if defined(HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED | ||
123 | # define fputs_unlocked(x,y) fputs (x,y) | ||
124 | # endif | ||
125 | #if defined(HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED | ||
126 | # define fread_unlocked(w,x,y,z) fread (w,x,y,z) | ||
127 | # endif | ||
128 | #if defined(HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED | ||
129 | # define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) | ||
130 | # endif | ||
131 | #if defined(HAVE_DECL_GETC_UNLOCKED) && !HAVE_DECL_GETC_UNLOCKED | ||
132 | # define getc_unlocked(x) getc (x) | ||
133 | # endif | ||
134 | #if defined(HAVE_DECL_GETCHAR_UNLOCKED) && !HAVE_DECL_GETCHAR_UNLOCKED | ||
135 | # define getchar_unlocked() getchar () | ||
136 | # endif | ||
137 | #if defined(HAVE_DECL_PUTC_UNLOCKED) && !HAVE_DECL_PUTC_UNLOCKED | ||
138 | # define putc_unlocked(x,y) putc (x,y) | ||
139 | # endif | ||
140 | #if defined(HAVE_DECL_PUTCHAR_UNLOCKED) && !HAVE_DECL_PUTCHAR_UNLOCKED | ||
141 | # define putchar_unlocked(x) putchar (x) | ||
142 | # endif | ||
143 | |||
144 | extern char *__argp_basename (char *name); | ||
145 | |||
88 | #endif /* !_LIBC */ | 146 | #endif /* !_LIBC */ |
147 | |||
148 | #ifndef __set_errno | ||
149 | #define __set_errno(e) (errno = (e)) | ||
150 | #endif | ||
151 | |||
152 | #if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME | ||
153 | # define __argp_short_program_name() (program_invocation_short_name) | ||
154 | #else | ||
155 | extern char *__argp_short_program_name (void); | ||
156 | #endif | ... | ... |
1 | /* Hierarchial argument parsing, layered over getopt | 1 | /* Hierarchial argument parsing, layered over getopt |
2 | Copyright (C) 1995, 96, 97, 98, 99, 2000, 2001 Free Software Foundation, Inc. | 2 | Copyright (C) 1995-2000, 2002, 2003, 2004 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. | 3 | This file is part of the GNU C Library. |
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | 4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. |
5 | 5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | 6 | This program is free software; you can redistribute it and/or modify |
7 | modify it under the terms of the GNU Library General Public License as | 7 | it under the terms of the GNU General Public License as published by |
8 | published by the Free Software Foundation; either version 2 of the | 8 | the Free Software Foundation; either version 2, or (at your option) |
9 | License, or (at your option) any later version. | 9 | any later version. |
10 | 10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | 11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | Library General Public License for more details. | 14 | GNU General Public License for more details. |
15 | 15 | ||
16 | You should have received a copy of the GNU Library General Public | 16 | You should have received a copy of the GNU General Public License along |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 17 | with this program; if not, write to the Free Software Foundation, |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
19 | Boston, MA 02111-1307, USA. */ | ||
20 | 19 | ||
21 | #ifdef HAVE_CONFIG_H | 20 | #ifdef HAVE_CONFIG_H |
22 | #include <config.h> | 21 | #include <config.h> |
23 | #endif | 22 | #endif |
24 | 23 | ||
24 | #include <alloca.h> | ||
25 | #include <stddef.h> | ||
25 | #include <stdlib.h> | 26 | #include <stdlib.h> |
26 | #include <string.h> | 27 | #include <string.h> |
27 | #include <unistd.h> | 28 | #include <unistd.h> |
28 | #include <limits.h> | 29 | #include <limits.h> |
29 | #include <getopt.h> | 30 | #include <getopt.h> |
31 | #include <getopt_int.h> | ||
30 | 32 | ||
31 | #ifdef HAVE_STRINGS_H | 33 | #ifdef _LIBC |
32 | # include <strings.h> | ||
33 | #endif | ||
34 | |||
35 | #ifdef HAVE_ALLOCA_H | ||
36 | # include <alloca.h> | ||
37 | #endif | ||
38 | |||
39 | #include <mailutils/nls.h> | ||
40 | |||
41 | #ifndef _ | ||
42 | /* This is for other GNU distributions with internationalized messages. | ||
43 | When compiling libc, the _ macro is predefined. */ | ||
44 | # if defined HAVE_LIBINTL_H || defined _LIBC | ||
45 | # include <libintl.h> | 34 | # include <libintl.h> |
46 | # ifdef _LIBC | ||
47 | # undef dgettext | 35 | # undef dgettext |
48 | # define dgettext(domain, msgid) __dcgettext (domain, msgid, LC_MESSAGES) | 36 | # define dgettext(domain, msgid) \ |
49 | # endif | 37 | INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES) |
50 | # else | ||
51 | # define dgettext(domain, msgid) (msgid) | ||
52 | # define gettext(msgid) (msgid) | ||
53 | # endif | ||
54 | #endif | ||
55 | #ifndef N_ | ||
56 | # define N_(msgid) msgid | ||
57 | #endif | ||
58 | |||
59 | #if _LIBC - 0 | ||
60 | #include <bits/libc-lock.h> | ||
61 | #else | 38 | #else |
62 | #ifdef HAVE_CTHREADS_H | 39 | # include "gettext.h" |
63 | #include <cthreads.h> | ||
64 | #endif | 40 | #endif |
65 | #endif /* _LIBC */ | 41 | #define N_(msgid) msgid |
66 | 42 | ||
67 | #include "argp.h" | 43 | #include "argp.h" |
68 | #include "argp-namefrob.h" | 44 | #include "argp-namefrob.h" |
69 | 45 | ||
46 | #define alignof(type) offsetof (struct { char c; type x; }, x) | ||
47 | #define alignto(n, d) ((((n) + (d) - 1) / (d)) * (d)) | ||
48 | |||
70 | /* Getopt return values. */ | 49 | /* Getopt return values. */ |
71 | #define KEY_END (-1) /* The end of the options. */ | 50 | #define KEY_END (-1) /* The end of the options. */ |
72 | #define KEY_ARG 1 /* A non-option argument. */ | 51 | #define KEY_ARG 1 /* A non-option argument. */ |
... | @@ -92,7 +71,7 @@ | ... | @@ -92,7 +71,7 @@ |
92 | for one second intervals, decrementing _ARGP_HANG until it's zero. Thus | 71 | for one second intervals, decrementing _ARGP_HANG until it's zero. Thus |
93 | you can force the program to continue by attaching a debugger and setting | 72 | you can force the program to continue by attaching a debugger and setting |
94 | it to 0 yourself. */ | 73 | it to 0 yourself. */ |
95 | volatile int _argp_hang; | 74 | static volatile int _argp_hang; |
96 | 75 | ||
97 | #define OPT_PROGNAME -2 | 76 | #define OPT_PROGNAME -2 |
98 | #define OPT_USAGE -3 | 77 | #define OPT_USAGE -3 |
... | @@ -101,11 +80,11 @@ volatile int _argp_hang; | ... | @@ -101,11 +80,11 @@ volatile int _argp_hang; |
101 | static const struct argp_option argp_default_options[] = | 80 | static const struct argp_option argp_default_options[] = |
102 | { | 81 | { |
103 | {"help", '?', 0, 0, N_("Give this help list"), -1}, | 82 | {"help", '?', 0, 0, N_("Give this help list"), -1}, |
104 | {"usage", OPT_USAGE, 0, 0, N_("Give a short usage message")}, | 83 | {"usage", OPT_USAGE, 0, 0, N_("Give a short usage message"), 0}, |
105 | {"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, N_("Set the program name")}, | 84 | {"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, N_("Set the program name"), 0}, |
106 | {"HANG", OPT_HANG, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN, | 85 | {"HANG", OPT_HANG, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN, |
107 | N_("Hang for SECS seconds (default 3600)")}, | 86 | N_("Hang for SECS seconds (default 3600)"), 0}, |
108 | {0, 0} | 87 | {NULL, 0, 0, 0, NULL, 0} |
109 | }; | 88 | }; |
110 | 89 | ||
111 | static error_t | 90 | static error_t |
... | @@ -122,31 +101,35 @@ argp_default_parser (int key, char *arg, struct argp_state *state) | ... | @@ -122,31 +101,35 @@ argp_default_parser (int key, char *arg, struct argp_state *state) |
122 | break; | 101 | break; |
123 | 102 | ||
124 | case OPT_PROGNAME: /* Set the program name. */ | 103 | case OPT_PROGNAME: /* Set the program name. */ |
104 | #if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_NAME | ||
125 | program_invocation_name = arg; | 105 | program_invocation_name = arg; |
126 | 106 | #endif | |
127 | /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka | 107 | /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka |
128 | __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined | 108 | __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined |
129 | to be that, so we have to be a bit careful here.] */ | 109 | to be that, so we have to be a bit careful here.] */ |
130 | arg = strrchr (arg, '/'); | ||
131 | if (arg) | ||
132 | program_invocation_short_name = arg + 1; | ||
133 | else | ||
134 | program_invocation_short_name = program_invocation_name; | ||
135 | 110 | ||
136 | /* Update what we use for messages. */ | 111 | /* Update what we use for messages. */ |
137 | state->name = program_invocation_short_name; | 112 | state->name = strrchr (arg, '/'); |
113 | if (state->name) | ||
114 | state->name++; | ||
115 | else | ||
116 | state->name = arg; | ||
117 | |||
118 | #if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME | ||
119 | program_invocation_short_name = state->name; | ||
120 | #endif | ||
138 | 121 | ||
139 | if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS)) | 122 | if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS)) |
140 | == ARGP_PARSE_ARGV0) | 123 | == ARGP_PARSE_ARGV0) |
141 | /* Update what getopt uses too. */ | 124 | /* Update what getopt uses too. */ |
142 | state->argv[0] = program_invocation_name; | 125 | state->argv[0] = arg; |
143 | 126 | ||
144 | break; | 127 | break; |
145 | 128 | ||
146 | case OPT_HANG: | 129 | case OPT_HANG: |
147 | _argp_hang = atoi (arg ? arg : "3600"); | 130 | _argp_hang = atoi (arg ? arg : "3600"); |
148 | while (_argp_hang-- > 0) | 131 | while (_argp_hang-- > 0) |
149 | sleep (1); | 132 | __sleep (1); |
150 | break; | 133 | break; |
151 | 134 | ||
152 | default: | 135 | default: |
... | @@ -162,7 +145,7 @@ static const struct argp argp_default_argp = | ... | @@ -162,7 +145,7 @@ static const struct argp argp_default_argp = |
162 | static const struct argp_option argp_version_options[] = | 145 | static const struct argp_option argp_version_options[] = |
163 | { | 146 | { |
164 | {"version", 'V', 0, 0, N_("Print program version"), -1}, | 147 | {"version", 'V', 0, 0, N_("Print program version"), -1}, |
165 | {0, 0} | 148 | {NULL, 0, 0, 0, NULL, 0} |
166 | }; | 149 | }; |
167 | 150 | ||
168 | static error_t | 151 | static error_t |
... | @@ -208,41 +191,6 @@ find_long_option (struct option *long_options, const char *name) | ... | @@ -208,41 +191,6 @@ find_long_option (struct option *long_options, const char *name) |
208 | return -1; | 191 | return -1; |
209 | } | 192 | } |
210 | 193 | ||
211 | /* If we can, we regulate access to getopt, which is non-reentrant, with a | ||
212 | mutex. Since the case we're trying to guard against is two different | ||
213 | threads interfering, and it's possible that someone might want to call | ||
214 | argp_parse recursively (they're careful), we use a recursive lock if | ||
215 | possible. */ | ||
216 | |||
217 | #if _LIBC - 0 | ||
218 | |||
219 | __libc_lock_define_initialized_recursive (static, getopt_lock) | ||
220 | #define LOCK_GETOPT __libc_lock_lock_recursive (getopt_lock) | ||
221 | #define UNLOCK_GETOPT __libc_lock_unlock_recursive (getopt_lock) | ||
222 | |||
223 | #else /* !_LIBC */ | ||
224 | #if defined(HAVE_CTHREADS_H) | ||
225 | |||
226 | static struct mutex getopt_lock = MUTEX_INITIALIZER; | ||
227 | #define LOCK_GETOPT mutex_lock (&getopt_lock) | ||
228 | #define UNLOCK_GETOPT mutex_unlock (&getopt_lock) | ||
229 | |||
230 | #else /* !HAVE_CTHREADS_H */ | ||
231 | |||
232 | #define LOCK_GETOPT (void)0 | ||
233 | #define UNLOCK_GETOPT (void)0 | ||
234 | |||
235 | #endif /* HAVE_CTHREADS_H */ | ||
236 | #endif /* _LIBC */ | ||
237 | |||
238 | /* This hack to allow programs that know what's going on to call argp | ||
239 | recursively. If someday argp is changed not to use the non-reentrant | ||
240 | getopt interface, we can get rid of this shit. XXX */ | ||
241 | void | ||
242 | _argp_unlock_xxx (void) | ||
243 | { | ||
244 | UNLOCK_GETOPT; | ||
245 | } | ||
246 | 194 | ||
247 | /* The state of a `group' during parsing. Each group corresponds to a | 195 | /* The state of a `group' during parsing. Each group corresponds to a |
248 | particular argp structure from the tree of such descending from the top | 196 | particular argp structure from the tree of such descending from the top |
... | @@ -304,6 +252,8 @@ struct parser | ... | @@ -304,6 +252,8 @@ struct parser |
304 | /* LONG_OPTS is the array of getop long option structures for the union of | 252 | /* LONG_OPTS is the array of getop long option structures for the union of |
305 | all the groups of options. */ | 253 | all the groups of options. */ |
306 | struct option *long_opts; | 254 | struct option *long_opts; |
255 | /* OPT_DATA is the getopt data used for the re-entrant getopt. */ | ||
256 | struct _getopt_data opt_data; | ||
307 | 257 | ||
308 | /* States of the various parsing groups. */ | 258 | /* States of the various parsing groups. */ |
309 | struct group *groups; | 259 | struct group *groups; |
... | @@ -515,6 +465,12 @@ parser_init (struct parser *parser, const struct argp *argp, | ... | @@ -515,6 +465,12 @@ parser_init (struct parser *parser, const struct argp *argp, |
515 | error_t err = 0; | 465 | error_t err = 0; |
516 | struct group *group; | 466 | struct group *group; |
517 | struct parser_sizes szs; | 467 | struct parser_sizes szs; |
468 | struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER; | ||
469 | char *storage; | ||
470 | size_t glen, gsum; | ||
471 | size_t clen, csum; | ||
472 | size_t llen, lsum; | ||
473 | size_t slen, ssum; | ||
518 | 474 | ||
519 | szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1; | 475 | szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1; |
520 | szs.long_len = 0; | 476 | szs.long_len = 0; |
... | @@ -525,26 +481,33 @@ parser_init (struct parser *parser, const struct argp *argp, | ... | @@ -525,26 +481,33 @@ parser_init (struct parser *parser, const struct argp *argp, |
525 | calc_sizes (argp, &szs); | 481 | calc_sizes (argp, &szs); |
526 | 482 | ||
527 | /* Lengths of the various bits of storage used by PARSER. */ | 483 | /* Lengths of the various bits of storage used by PARSER. */ |
528 | #define GLEN (szs.num_groups + 1) * sizeof (struct group) | 484 | glen = (szs.num_groups + 1) * sizeof (struct group); |
529 | #define CLEN (szs.num_child_inputs * sizeof (void *)) | 485 | clen = szs.num_child_inputs * sizeof (void *); |
530 | #define LLEN ((szs.long_len + 1) * sizeof (struct option)) | 486 | llen = (szs.long_len + 1) * sizeof (struct option); |
531 | #define SLEN (szs.short_len + 1) | 487 | slen = szs.short_len + 1; |
532 | 488 | ||
533 | parser->storage = malloc (GLEN + CLEN + LLEN + SLEN); | 489 | /* Sums of previous lengths, properly aligned. There's no need to |
490 | align gsum, since struct group is aligned at least as strictly as | ||
491 | void * (since it contains a void * member). And there's no need | ||
492 | to align lsum, since struct option is aligned at least as | ||
493 | strictly as char. */ | ||
494 | gsum = glen; | ||
495 | csum = alignto (gsum + clen, alignof (struct option)); | ||
496 | lsum = csum + llen; | ||
497 | ssum = lsum + slen; | ||
498 | |||
499 | parser->storage = malloc (ssum); | ||
534 | if (! parser->storage) | 500 | if (! parser->storage) |
535 | return ENOMEM; | 501 | return ENOMEM; |
536 | 502 | ||
537 | parser->groups = (struct group *) parser->storage; | 503 | storage = parser->storage; |
538 | /* To please Watcom CC | 504 | parser->groups = parser->storage; |
539 | parser->child_inputs = parser->storage + GLEN; | 505 | parser->child_inputs = (void **) (storage + gsum); |
540 | parser->long_opts = parser->storage + GLEN + CLEN; | 506 | parser->long_opts = (struct option *) (storage + csum); |
541 | parser->short_opts = parser->storage + GLEN + CLEN + LLEN; | 507 | parser->short_opts = storage + lsum; |
542 | */ | 508 | parser->opt_data = opt_data; |
543 | parser->child_inputs = (void **)((char*) parser->storage + GLEN); | 509 | |
544 | parser->long_opts = (struct option *)((char*) parser->storage + GLEN + CLEN); | 510 | memset (parser->child_inputs, 0, clen); |
545 | parser->short_opts = (char*) parser->storage + GLEN + CLEN + LLEN; | ||
546 | |||
547 | memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *)); | ||
548 | parser_convert (parser, argp, flags); | 511 | parser_convert (parser, argp, flags); |
549 | 512 | ||
550 | memset (&parser->state, 0, sizeof (struct argp_state)); | 513 | memset (&parser->state, 0, sizeof (struct argp_state)); |
... | @@ -586,19 +549,16 @@ parser_init (struct parser *parser, const struct argp *argp, | ... | @@ -586,19 +549,16 @@ parser_init (struct parser *parser, const struct argp *argp, |
586 | if (err) | 549 | if (err) |
587 | return err; | 550 | return err; |
588 | 551 | ||
589 | /* Getopt is (currently) non-reentrant. */ | ||
590 | LOCK_GETOPT; | ||
591 | |||
592 | if (parser->state.flags & ARGP_NO_ERRS) | 552 | if (parser->state.flags & ARGP_NO_ERRS) |
593 | { | 553 | { |
594 | opterr = 0; | 554 | parser->opt_data.opterr = 0; |
595 | if (parser->state.flags & ARGP_PARSE_ARGV0) | 555 | if (parser->state.flags & ARGP_PARSE_ARGV0) |
596 | /* getopt always skips ARGV[0], so we have to fake it out. As long | 556 | /* getopt always skips ARGV[0], so we have to fake it out. As long |
597 | as OPTERR is 0, then it shouldn't actually try to access it. */ | 557 | as OPTERR is 0, then it shouldn't actually try to access it. */ |
598 | parser->state.argv--, parser->state.argc++; | 558 | parser->state.argv--, parser->state.argc++; |
599 | } | 559 | } |
600 | else | 560 | else |
601 | opterr = 1; /* Print error messages. */ | 561 | parser->opt_data.opterr = 1; /* Print error messages. */ |
602 | 562 | ||
603 | if (parser->state.argv == argv && argv[0]) | 563 | if (parser->state.argv == argv && argv[0]) |
604 | /* There's an argv[0]; use it for messages. */ | 564 | /* There's an argv[0]; use it for messages. */ |
... | @@ -607,7 +567,7 @@ parser_init (struct parser *parser, const struct argp *argp, | ... | @@ -607,7 +567,7 @@ parser_init (struct parser *parser, const struct argp *argp, |
607 | parser->state.name = short_name ? short_name + 1 : argv[0]; | 567 | parser->state.name = short_name ? short_name + 1 : argv[0]; |
608 | } | 568 | } |
609 | else | 569 | else |
610 | parser->state.name = program_invocation_short_name; | 570 | parser->state.name = __argp_short_program_name (); |
611 | 571 | ||
612 | return 0; | 572 | return 0; |
613 | } | 573 | } |
... | @@ -619,8 +579,6 @@ parser_finalize (struct parser *parser, | ... | @@ -619,8 +579,6 @@ parser_finalize (struct parser *parser, |
619 | { | 579 | { |
620 | struct group *group; | 580 | struct group *group; |
621 | 581 | ||
622 | UNLOCK_GETOPT; | ||
623 | |||
624 | if (err == EBADKEY && arg_ebadkey) | 582 | if (err == EBADKEY && arg_ebadkey) |
625 | /* Suppress errors generated by unparsed arguments. */ | 583 | /* Suppress errors generated by unparsed arguments. */ |
626 | err = 0; | 584 | err = 0; |
... | @@ -782,7 +740,8 @@ parser_parse_opt (struct parser *parser, int opt, char *val) | ... | @@ -782,7 +740,8 @@ parser_parse_opt (struct parser *parser, int opt, char *val) |
782 | for (group = parser->groups; group < parser->egroup; group++) | 740 | for (group = parser->groups; group < parser->egroup; group++) |
783 | if (group->short_end > short_index) | 741 | if (group->short_end > short_index) |
784 | { | 742 | { |
785 | err = group_parse (group, &parser->state, opt, optarg); | 743 | err = group_parse (group, &parser->state, opt, |
744 | parser->opt_data.optarg); | ||
786 | break; | 745 | break; |
787 | } | 746 | } |
788 | } | 747 | } |
... | @@ -791,7 +750,8 @@ parser_parse_opt (struct parser *parser, int opt, char *val) | ... | @@ -791,7 +750,8 @@ parser_parse_opt (struct parser *parser, int opt, char *val) |
791 | the user value in order to preserve the sign. */ | 750 | the user value in order to preserve the sign. */ |
792 | err = | 751 | err = |
793 | group_parse (&parser->groups[group_key - 1], &parser->state, | 752 | group_parse (&parser->groups[group_key - 1], &parser->state, |
794 | (opt << GROUP_BITS) >> GROUP_BITS, optarg); | 753 | (opt << GROUP_BITS) >> GROUP_BITS, |
754 | parser->opt_data.optarg); | ||
795 | 755 | ||
796 | if (err == EBADKEY) | 756 | if (err == EBADKEY) |
797 | /* At least currently, an option not recognized is an error in the | 757 | /* At least currently, an option not recognized is an error in the |
... | @@ -837,15 +797,20 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) | ... | @@ -837,15 +797,20 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) |
837 | if (parser->try_getopt && !parser->state.quoted) | 797 | if (parser->try_getopt && !parser->state.quoted) |
838 | /* Give getopt a chance to parse this. */ | 798 | /* Give getopt a chance to parse this. */ |
839 | { | 799 | { |
840 | optind = parser->state.next; /* Put it back in OPTIND for getopt. */ | 800 | /* Put it back in OPTIND for getopt. */ |
841 | optopt = KEY_END; /* Distinguish KEY_ERR from a real option. */ | 801 | parser->opt_data.optind = parser->state.next; |
802 | /* Distinguish KEY_ERR from a real option. */ | ||
803 | parser->opt_data.optopt = KEY_END; | ||
842 | if (parser->state.flags & ARGP_LONG_ONLY) | 804 | if (parser->state.flags & ARGP_LONG_ONLY) |
843 | opt = getopt_long_only (parser->state.argc, parser->state.argv, | 805 | opt = _getopt_long_only_r (parser->state.argc, parser->state.argv, |
844 | parser->short_opts, parser->long_opts, 0); | 806 | parser->short_opts, parser->long_opts, 0, |
807 | &parser->opt_data); | ||
845 | else | 808 | else |
846 | opt = getopt_long (parser->state.argc, parser->state.argv, | 809 | opt = _getopt_long_r (parser->state.argc, parser->state.argv, |
847 | parser->short_opts, parser->long_opts, 0); | 810 | parser->short_opts, parser->long_opts, 0, |
848 | parser->state.next = optind; /* And see what getopt did. */ | 811 | &parser->opt_data); |
812 | /* And see what getopt did. */ | ||
813 | parser->state.next = parser->opt_data.optind; | ||
849 | 814 | ||
850 | if (opt == KEY_END) | 815 | if (opt == KEY_END) |
851 | /* Getopt says there are no more options, so stop using | 816 | /* Getopt says there are no more options, so stop using |
... | @@ -861,7 +826,7 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) | ... | @@ -861,7 +826,7 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) |
861 | here, whatever happens. */ | 826 | here, whatever happens. */ |
862 | parser->state.quoted = parser->state.next; | 827 | parser->state.quoted = parser->state.next; |
863 | } | 828 | } |
864 | else if (opt == KEY_ERR && optopt != KEY_END) | 829 | else if (opt == KEY_ERR && parser->opt_data.optopt != KEY_END) |
865 | /* KEY_ERR can have the same value as a valid user short | 830 | /* KEY_ERR can have the same value as a valid user short |
866 | option, but in the case of a real error, getopt sets OPTOPT | 831 | option, but in the case of a real error, getopt sets OPTOPT |
867 | to the offending character, which can never be KEY_END. */ | 832 | to the offending character, which can never be KEY_END. */ |
... | @@ -887,15 +852,15 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) | ... | @@ -887,15 +852,15 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) |
887 | /* A non-option arg; simulate what getopt might have done. */ | 852 | /* A non-option arg; simulate what getopt might have done. */ |
888 | { | 853 | { |
889 | opt = KEY_ARG; | 854 | opt = KEY_ARG; |
890 | optarg = parser->state.argv[parser->state.next++]; | 855 | parser->opt_data.optarg = parser->state.argv[parser->state.next++]; |
891 | } | 856 | } |
892 | } | 857 | } |
893 | 858 | ||
894 | if (opt == KEY_ARG) | 859 | if (opt == KEY_ARG) |
895 | /* A non-option argument; try each parser in turn. */ | 860 | /* A non-option argument; try each parser in turn. */ |
896 | err = parser_parse_arg (parser, optarg); | 861 | err = parser_parse_arg (parser, parser->opt_data.optarg); |
897 | else | 862 | else |
898 | err = parser_parse_opt (parser, opt, optarg); | 863 | err = parser_parse_opt (parser, opt, parser->opt_data.optarg); |
899 | 864 | ||
900 | if (err == EBADKEY) | 865 | if (err == EBADKEY) |
901 | *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG); | 866 | *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG); | ... | ... |
... | @@ -3,20 +3,19 @@ | ... | @@ -3,20 +3,19 @@ |
3 | This file is part of the GNU C Library. | 3 | This file is part of the GNU C Library. |
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | 4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. |
5 | 5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | 6 | This program is free software; you can redistribute it and/or modify |
7 | modify it under the terms of the GNU Library General Public License as | 7 | it under the terms of the GNU General Public License as published by |
8 | published by the Free Software Foundation; either version 2 of the | 8 | the Free Software Foundation; either version 2, or (at your option) |
9 | License, or (at your option) any later version. | 9 | any later version. |
10 | 10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | 11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | Library General Public License for more details. | 14 | GNU General Public License for more details. |
15 | 15 | ||
16 | You should have received a copy of the GNU Library General Public | 16 | You should have received a copy of the GNU General Public License along |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 17 | with this program; if not, write to the Free Software Foundation, |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
19 | Boston, MA 02111-1307, USA. */ | ||
20 | 19 | ||
21 | /* If set by the user program to a non-zero value, then a default option | 20 | /* If set by the user program to a non-zero value, then a default option |
22 | --version is added (unless the ARGP_NO_HELP flag is used), which will | 21 | --version is added (unless the ARGP_NO_HELP flag is used), which will | ... | ... |
1 | /* Default definition for ARGP_PROGRAM_VERSION_HOOK. | 1 | /* Default definition for ARGP_PROGRAM_VERSION_HOOK. |
2 | Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. | 2 | Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. | 3 | This file is part of the GNU C Library. |
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | 4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. |
5 | 5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | 6 | This program is free software; you can redistribute it and/or modify |
7 | modify it under the terms of the GNU Library General Public License as | 7 | it under the terms of the GNU General Public License as published by |
8 | published by the Free Software Foundation; either version 2 of the | 8 | the Free Software Foundation; either version 2, or (at your option) |
9 | License, or (at your option) any later version. | 9 | any later version. |
10 | 10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | 11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | Library General Public License for more details. | 14 | GNU General Public License for more details. |
15 | 15 | ||
16 | You should have received a copy of the GNU Library General Public | 16 | You should have received a copy of the GNU General Public License along |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 17 | with this program; if not, write to the Free Software Foundation, |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
19 | Boston, MA 02111-1307, USA. */ | ||
20 | 19 | ||
21 | #ifdef HAVE_CONFIG_H | 20 | #ifdef HAVE_CONFIG_H |
22 | #include <config.h> | 21 | #include <config.h> |
... | @@ -29,4 +28,4 @@ | ... | @@ -29,4 +28,4 @@ |
29 | this function with a stream to print the version to and a pointer to the | 28 | this function with a stream to print the version to and a pointer to the |
30 | current parsing state, and then exits (unless the ARGP_NO_EXIT flag is | 29 | current parsing state, and then exits (unless the ARGP_NO_EXIT flag is |
31 | used). This variable takes precedent over ARGP_PROGRAM_VERSION. */ | 30 | used). This variable takes precedent over ARGP_PROGRAM_VERSION. */ |
32 | void (*argp_program_version_hook) (FILE *stream, struct argp_state *state); | 31 | void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) = NULL; | ... | ... |
1 | /* Real definitions for extern inline functions in argp.h | 1 | /* Real definitions for extern inline functions in argp.h |
2 | Copyright (C) 1997, 1998, 2001 Free Software Foundation, Inc. | 2 | Copyright (C) 1997, 1998, 2004 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. | 3 | This file is part of the GNU C Library. |
4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. | 4 | Written by Miles Bader <miles@gnu.ai.mit.edu>. |
5 | 5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | 6 | This program is free software; you can redistribute it and/or modify |
7 | modify it under the terms of the GNU Library General Public License as | 7 | it under the terms of the GNU General Public License as published by |
8 | published by the Free Software Foundation; either version 2 of the | 8 | the Free Software Foundation; either version 2, or (at your option) |
9 | License, or (at your option) any later version. | 9 | any later version. |
10 | 10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | 11 | This program is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | Library General Public License for more details. | 14 | GNU General Public License for more details. |
15 | 15 | ||
16 | You should have received a copy of the GNU Library General Public | 16 | You should have received a copy of the GNU General Public License along |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 17 | with this program; if not, write to the Free Software Foundation, |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
19 | Boston, MA 02111-1307, USA. */ | ||
20 | 19 | ||
21 | #ifdef HAVE_CONFIG_H | 20 | #ifdef HAVE_CONFIG_H |
22 | #include <config.h> | 21 | #include <config.h> |
23 | #endif | 22 | #endif |
24 | 23 | ||
24 | #if defined _LIBC || defined HAVE_FEATURES_H | ||
25 | # include <features.h> | ||
26 | #endif | ||
27 | |||
25 | #ifndef __USE_EXTERN_INLINES | 28 | #ifndef __USE_EXTERN_INLINES |
26 | # define __USE_EXTERN_INLINES 1 | 29 | # define __USE_EXTERN_INLINES 1 |
27 | #endif | 30 | #endif |
28 | #define ARGP_EI | 31 | #define ARGP_EI |
29 | #undef __OPTIMIZE__ | 32 | #undef __OPTIMIZE__ |
30 | #define __OPTIMIZE__ | 33 | #define __OPTIMIZE__ 1 |
31 | #include "argp.h" | 34 | #include "argp.h" |
32 | 35 | ||
33 | /* Add weak aliases. */ | 36 | /* Add weak aliases. */ | ... | ... |
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | 1 | /* getline.c -- Replacement for GNU C library function getline |
2 | Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. | ||
3 | 2 | ||
4 | This library is free software; you can redistribute it and/or | 3 | Copyright (C) 1993, 1996, 1997, 1998, 2000, 2003, 2004 Free |
5 | modify it under the terms of the GNU Lesser General Public | 4 | Software Foundation, Inc. |
6 | License as published by the Free Software Foundation; either | ||
7 | version 2 of the License, or (at your option) any later version. | ||
8 | 5 | ||
9 | This library is distributed in the hope that it will be useful, | 6 | This program is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2, or (at your option) | ||
9 | any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | Lesser General Public License for more details. | 14 | GNU General Public License for more details. |
13 | 15 | ||
14 | You should have received a copy of the GNU Lesser General Public | 16 | You should have received a copy of the GNU General Public License |
15 | License along with this library; if not, write to the Free Software | 17 | along with this program; if not, write to the Free Software Foundation, |
16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | 18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
17 | 19 | ||
18 | /* First implementation by Alain Magloire */ | 20 | /* Written by Jan Brittenson, bson@gnu.ai.mit.edu. */ |
19 | 21 | ||
20 | #ifdef HAVE_CONFIG_H | 22 | #if HAVE_CONFIG_H |
21 | # include <config.h> | 23 | # include <config.h> |
22 | #endif | 24 | #endif |
23 | 25 | ||
24 | #include <unistd.h> | 26 | #include "getline.h" |
25 | #include <stdio.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <string.h> | ||
28 | |||
29 | ssize_t | ||
30 | getline (char **lineptr, size_t *n, FILE *stream) | ||
31 | { | ||
32 | return getdelim (lineptr, n, '\n', stream); | ||
33 | } | ||
34 | 27 | ||
35 | #ifndef HAVE_GETDELIM | 28 | #if ! (defined __GNU_LIBRARY__ && HAVE_GETDELIM) |
36 | 29 | ||
37 | /* Default value for line length. */ | 30 | # include "getndelim2.h" |
38 | static const int line_size = 128; | ||
39 | 31 | ||
40 | ssize_t | 32 | ssize_t |
41 | getdelim (char **lineptr, size_t *n, int delim, FILE *stream) | 33 | getdelim (char **lineptr, size_t *linesize, int delimiter, FILE *stream) |
42 | { | 34 | { |
43 | int indx = 0; | 35 | return getndelim2 (lineptr, linesize, 0, GETNLINE_NO_LIMIT, delimiter, EOF, |
44 | int c; | 36 | stream); |
45 | |||
46 | /* Sanity checks. */ | ||
47 | if (lineptr == NULL || n == NULL || stream == NULL) | ||
48 | return -1; | ||
49 | |||
50 | /* Allocate the line the first time. */ | ||
51 | if (*lineptr == NULL) | ||
52 | { | ||
53 | *lineptr = malloc (line_size); | ||
54 | if (*lineptr == NULL) | ||
55 | return -1; | ||
56 | *n = line_size; | ||
57 | } | ||
58 | |||
59 | while ((c = getc (stream)) != EOF) | ||
60 | { | ||
61 | /* Check if more memory is needed. */ | ||
62 | if (indx >= *n) | ||
63 | { | ||
64 | *lineptr = realloc (*lineptr, *n + line_size); | ||
65 | if (*lineptr == NULL) | ||
66 | return -1; | ||
67 | *n += line_size; | ||
68 | } | ||
69 | |||
70 | /* Push the result in the line. */ | ||
71 | (*lineptr)[indx++] = c; | ||
72 | |||
73 | /* Bail out. */ | ||
74 | if (c == delim) | ||
75 | break; | ||
76 | } | ||
77 | |||
78 | /* Make room for the null character. */ | ||
79 | if (indx >= *n) | ||
80 | { | ||
81 | *lineptr = realloc (*lineptr, *n + line_size); | ||
82 | if (*lineptr == NULL) | ||
83 | return -1; | ||
84 | *n += line_size; | ||
85 | } | ||
86 | |||
87 | /* Null terminate the buffer. */ | ||
88 | (*lineptr)[indx++] = 0; | ||
89 | |||
90 | /* The last line may not have the delimiter, we have to | ||
91 | * return what we got and the error will be seen on the | ||
92 | * next iteration. */ | ||
93 | return (c == EOF && (indx - 1) == 0) ? -1 : indx - 1; | ||
94 | } | 37 | } |
38 | #endif | ||
95 | 39 | ||
96 | #endif /* HAVE_GETDELIM */ | 40 | ssize_t |
97 | 41 | getline (char **lineptr, size_t *linesize, FILE *stream) | |
98 | |||
99 | #ifdef STANDALONE | ||
100 | int main(void) | ||
101 | { | 42 | { |
102 | FILE * fp; | 43 | return getdelim (lineptr, linesize, '\n', stream); |
103 | char * line = NULL; | ||
104 | size_t len = 0; | ||
105 | ssize_t read; | ||
106 | fp = fopen("/etc/passwd", "r"); | ||
107 | if (fp == NULL) | ||
108 | exit(EXIT_FAILURE); | ||
109 | while ((read = getline(&line, &len, fp)) != -1) { | ||
110 | printf("Retrieved line of length %zu :\n", read); | ||
111 | printf("%s", line); | ||
112 | } | ||
113 | if (line) | ||
114 | free(line); | ||
115 | return EXIT_SUCCESS; | ||
116 | } | 44 | } |
117 | #endif | ... | ... |
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | 1 | /* Replacement for GNU C library function getline |
2 | Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. | ||
3 | 2 | ||
4 | This library is free software; you can redistribute it and/or | 3 | Copyright (C) 1995, 1997, 1999, 2000, 2001, 2002, 2003 Free |
5 | modify it under the terms of the GNU Lesser General Public | 4 | Software Foundation, Inc. |
6 | License as published by the Free Software Foundation; either | ||
7 | version 2 of the License, or (at your option) any later version. | ||
8 | 5 | ||
9 | This library is distributed in the hope that it will be useful, | 6 | This program is free software; you can redistribute it and/or modify |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 7 | it under the terms of the GNU General Public License as published by |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 8 | the Free Software Foundation; either version 2, or (at your option) |
12 | Lesser General Public License for more details. | 9 | any later version. |
13 | 10 | ||
14 | You should have received a copy of the GNU Lesser General Public | 11 | This program is distributed in the hope that it will be useful, |
15 | License along with this library; if not, write to the Free Software | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | GNU General Public License for more details. | ||
17 | 15 | ||
18 | #ifndef _GETLINE_H_ | 16 | You should have received a copy of the GNU General Public License |
19 | # define _GETLINE_H_ 1 | 17 | along with this program; if not, write to the Free Software |
18 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
20 | 19 | ||
20 | #ifndef GETLINE_H_ | ||
21 | # define GETLINE_H_ 1 | ||
22 | |||
23 | # include <stddef.h> | ||
21 | # include <stdio.h> | 24 | # include <stdio.h> |
22 | 25 | ||
23 | # ifndef PARAMS | 26 | /* Get ssize_t. */ |
24 | # if defined (__GNUC__) || __STDC__ | 27 | # include <sys/types.h> |
25 | # define PARAMS(args) args | ||
26 | # else | ||
27 | # define PARAMS(args) () | ||
28 | # endif | ||
29 | # endif | ||
30 | 28 | ||
31 | extern int getline PARAMS ((char **_lineptr, size_t *_n, FILE *_stream)); | 29 | /* glibc2 has these functions declared in <stdio.h>. Avoid redeclarations. */ |
30 | # if __GLIBC__ < 2 | ||
32 | 31 | ||
33 | extern int getdelim PARAMS ((char **_lineptr, size_t *_n, int _delimiter, FILE *_stream)); | 32 | extern ssize_t getline (char **_lineptr, size_t *_linesize, FILE *_stream); |
33 | |||
34 | extern ssize_t getdelim (char **_lineptr, size_t *_linesize, int _delimiter, | ||
35 | FILE *_stream); | ||
36 | |||
37 | # endif | ||
34 | 38 | ||
35 | #endif /* ! _GETLINE_H_ */ | 39 | #endif /* not GETLINE_H_ */ | ... | ... |
1 | /* Getopt for GNU. | 1 | /* Getopt for GNU. |
2 | NOTE: The canonical source of this file is maintained with the GNU | 2 | NOTE: getopt is now part of the C library, so if you don't know what |
3 | C Library. Bugs can be reported to bug-glibc@gnu.org. | 3 | "Keep this file name-space clean" means, talk to drepper@gnu.org |
4 | 4 | before changing it! | |
5 | Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000 | 5 | Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004 |
6 | Free Software Foundation, Inc. | 6 | Free Software Foundation, Inc. |
7 | This file is part of the GNU C Library. | ||
7 | 8 | ||
8 | This program is free software; you can redistribute it and/or modify it | 9 | This program is free software; you can redistribute it and/or modify |
9 | under the terms of the GNU General Public License as published by the | 10 | it under the terms of the GNU General Public License as published by |
10 | Free Software Foundation; either version 2, or (at your option) any | 11 | the Free Software Foundation; either version 2, or (at your option) |
11 | later version. | 12 | any later version. |
12 | 13 | ||
13 | This program is distributed in the hope that it will be useful, | 14 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. | 17 | GNU General Public License for more details. |
17 | 18 | ||
18 | You should have received a copy of the GNU General Public License | 19 | You should have received a copy of the GNU General Public License along |
19 | along with this program; if not, write to the Free Software Foundation, | 20 | with this program; if not, write to the Free Software Foundation, |
20 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | 21 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
21 | 22 | ||
22 | /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. | 23 | /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. |
... | @@ -29,35 +30,8 @@ | ... | @@ -29,35 +30,8 @@ |
29 | # include <config.h> | 30 | # include <config.h> |
30 | #endif | 31 | #endif |
31 | 32 | ||
32 | #if !defined __STDC__ || !__STDC__ | ||
33 | /* This is a separate conditional since some stdc systems | ||
34 | reject `defined (const)'. */ | ||
35 | # ifndef const | ||
36 | # define const | ||
37 | # endif | ||
38 | #endif | ||
39 | |||
40 | #include <stdio.h> | 33 | #include <stdio.h> |
41 | 34 | ||
42 | /* Comment out all this code if we are using the GNU C Library, and are not | ||
43 | actually compiling the library itself. This code is part of the GNU C | ||
44 | Library, but also included in many other GNU distributions. Compiling | ||
45 | and linking in this code is a waste when using the GNU C library | ||
46 | (especially if it is a shared library). Rather than having every GNU | ||
47 | program understand `configure --with-gnu-libc' and omit the object files, | ||
48 | it is simpler to just do this in the source for each such file. */ | ||
49 | |||
50 | #define GETOPT_INTERFACE_VERSION 2 | ||
51 | #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 | ||
52 | # include <gnu-versions.h> | ||
53 | # if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION | ||
54 | # define ELIDE_CODE | ||
55 | # endif | ||
56 | #endif | ||
57 | |||
58 | #ifndef ELIDE_CODE | ||
59 | |||
60 | |||
61 | /* This needs to come after some library #include | 35 | /* This needs to come after some library #include |
62 | to get __GNU_LIBRARY__ defined. */ | 36 | to get __GNU_LIBRARY__ defined. */ |
63 | #ifdef __GNU_LIBRARY__ | 37 | #ifdef __GNU_LIBRARY__ |
... | @@ -67,40 +41,43 @@ | ... | @@ -67,40 +41,43 @@ |
67 | # include <unistd.h> | 41 | # include <unistd.h> |
68 | #endif /* GNU C library. */ | 42 | #endif /* GNU C library. */ |
69 | 43 | ||
44 | #include <string.h> | ||
45 | |||
70 | #ifdef VMS | 46 | #ifdef VMS |
71 | # include <unixlib.h> | 47 | # include <unixlib.h> |
72 | # if HAVE_STRING_H - 0 | ||
73 | # include <string.h> | ||
74 | # endif | ||
75 | #endif | 48 | #endif |
76 | 49 | ||
77 | #ifndef _ | 50 | #ifdef _LIBC |
78 | /* This is for other GNU distributions with internationalized messages. */ | ||
79 | # if defined HAVE_LIBINTL_H || defined _LIBC | ||
80 | # include <libintl.h> | 51 | # include <libintl.h> |
81 | # ifndef _ | 52 | #else |
53 | # include "gettext.h" | ||
82 | # define _(msgid) gettext (msgid) | 54 | # define _(msgid) gettext (msgid) |
83 | # endif | ||
84 | # else | ||
85 | # define _(msgid) (msgid) | ||
86 | # endif | ||
87 | #endif | 55 | #endif |
88 | 56 | ||
89 | /* This version of `getopt' appears to the caller like standard Unix `getopt' | 57 | #if defined _LIBC && defined USE_IN_LIBIO |
90 | but it behaves differently for the user, since it allows the user | 58 | # include <wchar.h> |
91 | to intersperse the options with the other arguments. | 59 | #endif |
60 | |||
61 | #ifndef attribute_hidden | ||
62 | # define attribute_hidden | ||
63 | #endif | ||
92 | 64 | ||
93 | As `getopt' works, it permutes the elements of ARGV so that, | 65 | /* Unlike standard Unix `getopt', functions like `getopt_long' |
66 | let the user intersperse the options with the other arguments. | ||
67 | |||
68 | As `getopt_long' works, it permutes the elements of ARGV so that, | ||
94 | when it is done, all the options precede everything else. Thus | 69 | when it is done, all the options precede everything else. Thus |
95 | all application programs are extended to handle flexible argument order. | 70 | all application programs are extended to handle flexible argument order. |
96 | 71 | ||
97 | Setting the environment variable POSIXLY_CORRECT disables permutation. | 72 | Using `getopt' or setting the environment variable POSIXLY_CORRECT |
98 | Then the behavior is completely standard. | 73 | disables permutation. |
74 | Then the application's behavior is completely standard. | ||
99 | 75 | ||
100 | GNU application programs can use a third alternative mode in which | 76 | GNU application programs can use a third alternative mode in which |
101 | they can distinguish the relative order of options and other arguments. */ | 77 | they can distinguish the relative order of options and other arguments. */ |
102 | 78 | ||
103 | #include "getopt.h" | 79 | #include "getopt.h" |
80 | #include "getopt_int.h" | ||
104 | 81 | ||
105 | /* For communication from `getopt' to the caller. | 82 | /* For communication from `getopt' to the caller. |
106 | When `getopt' finds an option that takes an argument, | 83 | When `getopt' finds an option that takes an argument, |
... | @@ -125,21 +102,6 @@ char *optarg; | ... | @@ -125,21 +102,6 @@ char *optarg; |
125 | /* 1003.2 says this must be 1 before any call. */ | 102 | /* 1003.2 says this must be 1 before any call. */ |
126 | int optind = 1; | 103 | int optind = 1; |
127 | 104 | ||
128 | /* Formerly, initialization of getopt depended on optind==0, which | ||
129 | causes problems with re-calling getopt as programs generally don't | ||
130 | know that. */ | ||
131 | |||
132 | int __getopt_initialized; | ||
133 | |||
134 | /* The next char to be scanned in the option-element | ||
135 | in which the last option character we returned was found. | ||
136 | This allows us to pick up the scan where we left off. | ||
137 | |||
138 | If this is zero, or a null string, it means resume the scan | ||
139 | by advancing to the next ARGV-element. */ | ||
140 | |||
141 | static char *nextchar; | ||
142 | |||
143 | /* Callers store zero here to inhibit the error message | 105 | /* Callers store zero here to inhibit the error message |
144 | for unrecognized options. */ | 106 | for unrecognized options. */ |
145 | 107 | ||
... | @@ -151,57 +113,12 @@ int opterr = 1; | ... | @@ -151,57 +113,12 @@ int opterr = 1; |
151 | 113 | ||
152 | int optopt = '?'; | 114 | int optopt = '?'; |
153 | 115 | ||
154 | /* Describe how to deal with options that follow non-option ARGV-elements. | 116 | /* Keep a global copy of all internal members of getopt_data. */ |
155 | |||
156 | If the caller did not specify anything, | ||
157 | the default is REQUIRE_ORDER if the environment variable | ||
158 | POSIXLY_CORRECT is defined, PERMUTE otherwise. | ||
159 | 117 | ||
160 | REQUIRE_ORDER means don't recognize them as options; | 118 | static struct _getopt_data getopt_data; |
161 | stop option processing when the first non-option is seen. | ||
162 | This is what Unix does. | ||
163 | This mode of operation is selected by either setting the environment | ||
164 | variable POSIXLY_CORRECT, or using `+' as the first character | ||
165 | of the list of option characters. | ||
166 | 119 | ||
167 | PERMUTE is the default. We permute the contents of ARGV as we scan, | ||
168 | so that eventually all the non-options are at the end. This allows options | ||
169 | to be given in any order, even with programs that were not written to | ||
170 | expect this. | ||
171 | 120 | ||
172 | RETURN_IN_ORDER is an option available to programs that were written | 121 | #ifndef __GNU_LIBRARY__ |
173 | to expect options and other ARGV-elements in any order and that care about | ||
174 | the ordering of the two. We describe each non-option ARGV-element | ||
175 | as if it were the argument of an option with character code 1. | ||
176 | Using `-' as the first character of the list of option characters | ||
177 | selects this mode of operation. | ||
178 | |||
179 | The special argument `--' forces an end of option-scanning regardless | ||
180 | of the value of `ordering'. In the case of RETURN_IN_ORDER, only | ||
181 | `--' can cause `getopt' to return -1 with `optind' != ARGC. */ | ||
182 | |||
183 | static enum | ||
184 | { | ||
185 | REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER | ||
186 | } ordering; | ||
187 | |||
188 | /* Value of POSIXLY_CORRECT environment variable. */ | ||
189 | static char *posixly_correct; | ||
190 | |||
191 | #ifdef __GNU_LIBRARY__ | ||
192 | /* We want to avoid inclusion of string.h with non-GNU libraries | ||
193 | because there are many ways it can cause trouble. | ||
194 | On some systems, it contains special magic macros that don't work | ||
195 | in GCC. */ | ||
196 | # include <string.h> | ||
197 | # define my_index strchr | ||
198 | #else | ||
199 | |||
200 | # if HAVE_STRING_H | ||
201 | # include <string.h> | ||
202 | # else | ||
203 | # include <strings.h> | ||
204 | # endif | ||
205 | 122 | ||
206 | /* Avoid depending on library functions or files | 123 | /* Avoid depending on library functions or files |
207 | whose names are inconsistent. */ | 124 | whose names are inconsistent. */ |
... | @@ -210,79 +127,34 @@ static char *posixly_correct; | ... | @@ -210,79 +127,34 @@ static char *posixly_correct; |
210 | extern char *getenv (); | 127 | extern char *getenv (); |
211 | #endif | 128 | #endif |
212 | 129 | ||
213 | static char * | ||
214 | my_index (str, chr) | ||
215 | const char *str; | ||
216 | int chr; | ||
217 | { | ||
218 | while (*str) | ||
219 | { | ||
220 | if (*str == chr) | ||
221 | return (char *) str; | ||
222 | str++; | ||
223 | } | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | /* If using GCC, we can safely declare strlen this way. | ||
228 | If not using GCC, it is ok not to declare it. */ | ||
229 | #ifdef __GNUC__ | ||
230 | /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. | ||
231 | That was relevant to code that was here before. */ | ||
232 | # if (!defined __STDC__ || !__STDC__) && !defined strlen | ||
233 | /* gcc with -traditional declares the built-in strlen to return int, | ||
234 | and has done so at least since version 2.4.5. -- rms. */ | ||
235 | extern int strlen (const char *); | ||
236 | # endif /* not __STDC__ */ | ||
237 | #endif /* __GNUC__ */ | ||
238 | |||
239 | #endif /* not __GNU_LIBRARY__ */ | 130 | #endif /* not __GNU_LIBRARY__ */ |
240 | 131 | ||
241 | /* Handle permutation of arguments. */ | ||
242 | |||
243 | /* Describe the part of ARGV that contains non-options that have | ||
244 | been skipped. `first_nonopt' is the index in ARGV of the first of them; | ||
245 | `last_nonopt' is the index after the last of them. */ | ||
246 | |||
247 | static int first_nonopt; | ||
248 | static int last_nonopt; | ||
249 | |||
250 | #ifdef _LIBC | 132 | #ifdef _LIBC |
133 | /* Stored original parameters. | ||
134 | XXX This is no good solution. We should rather copy the args so | ||
135 | that we can compare them later. But we must not use malloc(3). */ | ||
136 | extern int __libc_argc; | ||
137 | extern char **__libc_argv; | ||
138 | |||
251 | /* Bash 2.0 gives us an environment variable containing flags | 139 | /* Bash 2.0 gives us an environment variable containing flags |
252 | indicating ARGV elements that should not be considered arguments. */ | 140 | indicating ARGV elements that should not be considered arguments. */ |
253 | 141 | ||
142 | # ifdef USE_NONOPTION_FLAGS | ||
254 | /* Defined in getopt_init.c */ | 143 | /* Defined in getopt_init.c */ |
255 | extern char *__getopt_nonoption_flags; | 144 | extern char *__getopt_nonoption_flags; |
145 | # endif | ||
256 | 146 | ||
257 | static int nonoption_flags_max_len; | 147 | # ifdef USE_NONOPTION_FLAGS |
258 | static int nonoption_flags_len; | ||
259 | |||
260 | static int original_argc; | ||
261 | static char *const *original_argv; | ||
262 | |||
263 | /* Make sure the environment variable bash 2.0 puts in the environment | ||
264 | is valid for the getopt call we must make sure that the ARGV passed | ||
265 | to getopt is that one passed to the process. */ | ||
266 | static void | ||
267 | __attribute__ ((unused)) | ||
268 | store_args_and_env (int argc, char *const *argv) | ||
269 | { | ||
270 | /* XXX This is no good solution. We should rather copy the args so | ||
271 | that we can compare them later. But we must not use malloc(3). */ | ||
272 | original_argc = argc; | ||
273 | original_argv = argv; | ||
274 | } | ||
275 | # ifdef text_set_element | ||
276 | text_set_element (__libc_subinit, store_args_and_env); | ||
277 | # endif /* text_set_element */ | ||
278 | |||
279 | # define SWAP_FLAGS(ch1, ch2) \ | 148 | # define SWAP_FLAGS(ch1, ch2) \ |
280 | if (nonoption_flags_len > 0) \ | 149 | if (d->__nonoption_flags_len > 0) \ |
281 | { \ | 150 | { \ |
282 | char __tmp = __getopt_nonoption_flags[ch1]; \ | 151 | char __tmp = __getopt_nonoption_flags[ch1]; \ |
283 | __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ | 152 | __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ |
284 | __getopt_nonoption_flags[ch2] = __tmp; \ | 153 | __getopt_nonoption_flags[ch2] = __tmp; \ |
285 | } | 154 | } |
155 | # else | ||
156 | # define SWAP_FLAGS(ch1, ch2) | ||
157 | # endif | ||
286 | #else /* !_LIBC */ | 158 | #else /* !_LIBC */ |
287 | # define SWAP_FLAGS(ch1, ch2) | 159 | # define SWAP_FLAGS(ch1, ch2) |
288 | #endif /* _LIBC */ | 160 | #endif /* _LIBC */ |
... | @@ -296,17 +168,12 @@ text_set_element (__libc_subinit, store_args_and_env); | ... | @@ -296,17 +168,12 @@ text_set_element (__libc_subinit, store_args_and_env); |
296 | `first_nonopt' and `last_nonopt' are relocated so that they describe | 168 | `first_nonopt' and `last_nonopt' are relocated so that they describe |
297 | the new indices of the non-options in ARGV after they are moved. */ | 169 | the new indices of the non-options in ARGV after they are moved. */ |
298 | 170 | ||
299 | #if defined __STDC__ && __STDC__ | ||
300 | static void exchange (char **); | ||
301 | #endif | ||
302 | |||
303 | static void | 171 | static void |
304 | exchange (argv) | 172 | exchange (char **argv, struct _getopt_data *d) |
305 | char **argv; | ||
306 | { | 173 | { |
307 | int bottom = first_nonopt; | 174 | int bottom = d->__first_nonopt; |
308 | int middle = last_nonopt; | 175 | int middle = d->__last_nonopt; |
309 | int top = optind; | 176 | int top = d->optind; |
310 | char *tem; | 177 | char *tem; |
311 | 178 | ||
312 | /* Exchange the shorter segment with the far end of the longer segment. | 179 | /* Exchange the shorter segment with the far end of the longer segment. |
... | @@ -314,23 +181,23 @@ exchange (argv) | ... | @@ -314,23 +181,23 @@ exchange (argv) |
314 | It leaves the longer segment in the right place overall, | 181 | It leaves the longer segment in the right place overall, |
315 | but it consists of two parts that need to be swapped next. */ | 182 | but it consists of two parts that need to be swapped next. */ |
316 | 183 | ||
317 | #ifdef _LIBC | 184 | #if defined _LIBC && defined USE_NONOPTION_FLAGS |
318 | /* First make sure the handling of the `__getopt_nonoption_flags' | 185 | /* First make sure the handling of the `__getopt_nonoption_flags' |
319 | string can work normally. Our top argument must be in the range | 186 | string can work normally. Our top argument must be in the range |
320 | of the string. */ | 187 | of the string. */ |
321 | if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) | 188 | if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) |
322 | { | 189 | { |
323 | /* We must extend the array. The user plays games with us and | 190 | /* We must extend the array. The user plays games with us and |
324 | presents new arguments. */ | 191 | presents new arguments. */ |
325 | char *new_str = malloc (top + 1); | 192 | char *new_str = malloc (top + 1); |
326 | if (new_str == NULL) | 193 | if (new_str == NULL) |
327 | nonoption_flags_len = nonoption_flags_max_len = 0; | 194 | d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0; |
328 | else | 195 | else |
329 | { | 196 | { |
330 | memset (__mempcpy (new_str, __getopt_nonoption_flags, | 197 | memset (__mempcpy (new_str, __getopt_nonoption_flags, |
331 | nonoption_flags_max_len), | 198 | d->__nonoption_flags_max_len), |
332 | '\0', top + 1 - nonoption_flags_max_len); | 199 | '\0', top + 1 - d->__nonoption_flags_max_len); |
333 | nonoption_flags_max_len = top + 1; | 200 | d->__nonoption_flags_max_len = top + 1; |
334 | __getopt_nonoption_flags = new_str; | 201 | __getopt_nonoption_flags = new_str; |
335 | } | 202 | } |
336 | } | 203 | } |
... | @@ -376,76 +243,71 @@ exchange (argv) | ... | @@ -376,76 +243,71 @@ exchange (argv) |
376 | 243 | ||
377 | /* Update records for the slots the non-options now occupy. */ | 244 | /* Update records for the slots the non-options now occupy. */ |
378 | 245 | ||
379 | first_nonopt += (optind - last_nonopt); | 246 | d->__first_nonopt += (d->optind - d->__last_nonopt); |
380 | last_nonopt = optind; | 247 | d->__last_nonopt = d->optind; |
381 | } | 248 | } |
382 | 249 | ||
383 | /* Initialize the internal data when the first call is made. */ | 250 | /* Initialize the internal data when the first call is made. */ |
384 | 251 | ||
385 | #if defined __STDC__ && __STDC__ | ||
386 | static const char *_getopt_initialize (int, char *const *, const char *); | ||
387 | #endif | ||
388 | static const char * | 252 | static const char * |
389 | _getopt_initialize (argc, argv, optstring) | 253 | _getopt_initialize (int argc, char **argv, const char *optstring, |
390 | int argc; | 254 | int posixly_correct, struct _getopt_data *d) |
391 | char *const *argv; | ||
392 | const char *optstring; | ||
393 | { | 255 | { |
394 | /* Start processing options with ARGV-element 1 (since ARGV-element 0 | 256 | /* Start processing options with ARGV-element 1 (since ARGV-element 0 |
395 | is the program name); the sequence of previously skipped | 257 | is the program name); the sequence of previously skipped |
396 | non-option ARGV-elements is empty. */ | 258 | non-option ARGV-elements is empty. */ |
397 | 259 | ||
398 | first_nonopt = last_nonopt = optind; | 260 | d->__first_nonopt = d->__last_nonopt = d->optind; |
399 | 261 | ||
400 | nextchar = NULL; | 262 | d->__nextchar = NULL; |
401 | 263 | ||
402 | posixly_correct = getenv ("POSIXLY_CORRECT"); | 264 | d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT"); |
403 | 265 | ||
404 | /* Determine how to handle the ordering of options and nonoptions. */ | 266 | /* Determine how to handle the ordering of options and nonoptions. */ |
405 | 267 | ||
406 | if (optstring[0] == '-') | 268 | if (optstring[0] == '-') |
407 | { | 269 | { |
408 | ordering = RETURN_IN_ORDER; | 270 | d->__ordering = RETURN_IN_ORDER; |
409 | ++optstring; | 271 | ++optstring; |
410 | } | 272 | } |
411 | else if (optstring[0] == '+') | 273 | else if (optstring[0] == '+') |
412 | { | 274 | { |
413 | ordering = REQUIRE_ORDER; | 275 | d->__ordering = REQUIRE_ORDER; |
414 | ++optstring; | 276 | ++optstring; |
415 | } | 277 | } |
416 | else if (posixly_correct != NULL) | 278 | else if (d->__posixly_correct) |
417 | ordering = REQUIRE_ORDER; | 279 | d->__ordering = REQUIRE_ORDER; |
418 | else | 280 | else |
419 | ordering = PERMUTE; | 281 | d->__ordering = PERMUTE; |
420 | 282 | ||
421 | #ifdef _LIBC | 283 | #if defined _LIBC && defined USE_NONOPTION_FLAGS |
422 | if (posixly_correct == NULL | 284 | if (!d->__posixly_correct |
423 | && argc == original_argc && argv == original_argv) | 285 | && argc == __libc_argc && argv == __libc_argv) |
424 | { | 286 | { |
425 | if (nonoption_flags_max_len == 0) | 287 | if (d->__nonoption_flags_max_len == 0) |
426 | { | 288 | { |
427 | if (__getopt_nonoption_flags == NULL | 289 | if (__getopt_nonoption_flags == NULL |
428 | || __getopt_nonoption_flags[0] == '\0') | 290 | || __getopt_nonoption_flags[0] == '\0') |
429 | nonoption_flags_max_len = -1; | 291 | d->__nonoption_flags_max_len = -1; |
430 | else | 292 | else |
431 | { | 293 | { |
432 | const char *orig_str = __getopt_nonoption_flags; | 294 | const char *orig_str = __getopt_nonoption_flags; |
433 | int len = nonoption_flags_max_len = strlen (orig_str); | 295 | int len = d->__nonoption_flags_max_len = strlen (orig_str); |
434 | if (nonoption_flags_max_len < argc) | 296 | if (d->__nonoption_flags_max_len < argc) |
435 | nonoption_flags_max_len = argc; | 297 | d->__nonoption_flags_max_len = argc; |
436 | __getopt_nonoption_flags = | 298 | __getopt_nonoption_flags = |
437 | (char *) malloc (nonoption_flags_max_len); | 299 | (char *) malloc (d->__nonoption_flags_max_len); |
438 | if (__getopt_nonoption_flags == NULL) | 300 | if (__getopt_nonoption_flags == NULL) |
439 | nonoption_flags_max_len = -1; | 301 | d->__nonoption_flags_max_len = -1; |
440 | else | 302 | else |
441 | memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), | 303 | memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), |
442 | '\0', nonoption_flags_max_len - len); | 304 | '\0', d->__nonoption_flags_max_len - len); |
443 | } | 305 | } |
444 | } | 306 | } |
445 | nonoption_flags_len = nonoption_flags_max_len; | 307 | d->__nonoption_flags_len = d->__nonoption_flags_max_len; |
446 | } | 308 | } |
447 | else | 309 | else |
448 | nonoption_flags_len = 0; | 310 | d->__nonoption_flags_len = 0; |
449 | #endif | 311 | #endif |
450 | 312 | ||
451 | return optstring; | 313 | return optstring; |
... | @@ -493,10 +355,6 @@ _getopt_initialize (argc, argv, optstring) | ... | @@ -493,10 +355,6 @@ _getopt_initialize (argc, argv, optstring) |
493 | `flag' field is nonzero, the value of the option's `val' field | 355 | `flag' field is nonzero, the value of the option's `val' field |
494 | if the `flag' field is zero. | 356 | if the `flag' field is zero. |
495 | 357 | ||
496 | The elements of ARGV aren't really const, because we permute them. | ||
497 | But we pretend they're const in the prototype to be compatible | ||
498 | with other systems. | ||
499 | |||
500 | LONGOPTS is a vector of `struct option' terminated by an | 358 | LONGOPTS is a vector of `struct option' terminated by an |
501 | element containing a name which is zero. | 359 | element containing a name which is zero. |
502 | 360 | ||
... | @@ -505,73 +363,74 @@ _getopt_initialize (argc, argv, optstring) | ... | @@ -505,73 +363,74 @@ _getopt_initialize (argc, argv, optstring) |
505 | recent call. | 363 | recent call. |
506 | 364 | ||
507 | If LONG_ONLY is nonzero, '-' as well as '--' can introduce | 365 | If LONG_ONLY is nonzero, '-' as well as '--' can introduce |
508 | long-named options. */ | 366 | long-named options. |
367 | |||
368 | If POSIXLY_CORRECT is nonzero, behave as if the POSIXLY_CORRECT | ||
369 | environment variable were set. */ | ||
509 | 370 | ||
510 | int | 371 | int |
511 | _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | 372 | _getopt_internal_r (int argc, char **argv, const char *optstring, |
512 | int argc; | 373 | const struct option *longopts, int *longind, |
513 | char *const *argv; | 374 | int long_only, int posixly_correct, struct _getopt_data *d) |
514 | const char *optstring; | ||
515 | const struct option *longopts; | ||
516 | int *longind; | ||
517 | int long_only; | ||
518 | { | 375 | { |
519 | int print_errors = opterr; | 376 | int print_errors = d->opterr; |
520 | if (optstring[0] == ':') | 377 | if (optstring[0] == ':') |
521 | print_errors = 0; | 378 | print_errors = 0; |
522 | 379 | ||
523 | if (argc < 1) | 380 | if (argc < 1) |
524 | return -1; | 381 | return -1; |
525 | 382 | ||
526 | optarg = NULL; | 383 | d->optarg = NULL; |
527 | 384 | ||
528 | if (optind == 0 || !__getopt_initialized) | 385 | if (d->optind == 0 || !d->__initialized) |
529 | { | 386 | { |
530 | if (optind == 0) | 387 | if (d->optind == 0) |
531 | optind = 1; /* Don't scan ARGV[0], the program name. */ | 388 | d->optind = 1; /* Don't scan ARGV[0], the program name. */ |
532 | optstring = _getopt_initialize (argc, argv, optstring); | 389 | optstring = _getopt_initialize (argc, argv, optstring, |
533 | __getopt_initialized = 1; | 390 | posixly_correct, d); |
391 | d->__initialized = 1; | ||
534 | } | 392 | } |
535 | 393 | ||
536 | /* Test whether ARGV[optind] points to a non-option argument. | 394 | /* Test whether ARGV[optind] points to a non-option argument. |
537 | Either it does not have option syntax, or there is an environment flag | 395 | Either it does not have option syntax, or there is an environment flag |
538 | from the shell indicating it is not an option. The later information | 396 | from the shell indicating it is not an option. The later information |
539 | is only used when the used in the GNU libc. */ | 397 | is only used when the used in the GNU libc. */ |
540 | #ifdef _LIBC | 398 | #if defined _LIBC && defined USE_NONOPTION_FLAGS |
541 | # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ | 399 | # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \ |
542 | || (optind < nonoption_flags_len \ | 400 | || (d->optind < d->__nonoption_flags_len \ |
543 | && __getopt_nonoption_flags[optind] == '1')) | 401 | && __getopt_nonoption_flags[d->optind] == '1')) |
544 | #else | 402 | #else |
545 | # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') | 403 | # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') |
546 | #endif | 404 | #endif |
547 | 405 | ||
548 | if (nextchar == NULL || *nextchar == '\0') | 406 | if (d->__nextchar == NULL || *d->__nextchar == '\0') |
549 | { | 407 | { |
550 | /* Advance to the next ARGV-element. */ | 408 | /* Advance to the next ARGV-element. */ |
551 | 409 | ||
552 | /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been | 410 | /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been |
553 | moved back by the user (who may also have changed the arguments). */ | 411 | moved back by the user (who may also have changed the arguments). */ |
554 | if (last_nonopt > optind) | 412 | if (d->__last_nonopt > d->optind) |
555 | last_nonopt = optind; | 413 | d->__last_nonopt = d->optind; |
556 | if (first_nonopt > optind) | 414 | if (d->__first_nonopt > d->optind) |
557 | first_nonopt = optind; | 415 | d->__first_nonopt = d->optind; |
558 | 416 | ||
559 | if (ordering == PERMUTE) | 417 | if (d->__ordering == PERMUTE) |
560 | { | 418 | { |
561 | /* If we have just processed some options following some non-options, | 419 | /* If we have just processed some options following some non-options, |
562 | exchange them so that the options come first. */ | 420 | exchange them so that the options come first. */ |
563 | 421 | ||
564 | if (first_nonopt != last_nonopt && last_nonopt != optind) | 422 | if (d->__first_nonopt != d->__last_nonopt |
565 | exchange ((char **) argv); | 423 | && d->__last_nonopt != d->optind) |
566 | else if (last_nonopt != optind) | 424 | exchange ((char **) argv, d); |
567 | first_nonopt = optind; | 425 | else if (d->__last_nonopt != d->optind) |
426 | d->__first_nonopt = d->optind; | ||
568 | 427 | ||
569 | /* Skip any additional non-options | 428 | /* Skip any additional non-options |
570 | and extend the range of non-options previously skipped. */ | 429 | and extend the range of non-options previously skipped. */ |
571 | 430 | ||
572 | while (optind < argc && NONOPTION_P) | 431 | while (d->optind < argc && NONOPTION_P) |
573 | optind++; | 432 | d->optind++; |
574 | last_nonopt = optind; | 433 | d->__last_nonopt = d->optind; |
575 | } | 434 | } |
576 | 435 | ||
577 | /* The special ARGV-element `--' means premature end of options. | 436 | /* The special ARGV-element `--' means premature end of options. |
... | @@ -579,28 +438,29 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -579,28 +438,29 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
579 | then exchange with previous non-options as if it were an option, | 438 | then exchange with previous non-options as if it were an option, |
580 | then skip everything else like a non-option. */ | 439 | then skip everything else like a non-option. */ |
581 | 440 | ||
582 | if (optind != argc && !strcmp (argv[optind], "--")) | 441 | if (d->optind != argc && !strcmp (argv[d->optind], "--")) |
583 | { | 442 | { |
584 | optind++; | 443 | d->optind++; |
585 | 444 | ||
586 | if (first_nonopt != last_nonopt && last_nonopt != optind) | 445 | if (d->__first_nonopt != d->__last_nonopt |
587 | exchange ((char **) argv); | 446 | && d->__last_nonopt != d->optind) |
588 | else if (first_nonopt == last_nonopt) | 447 | exchange ((char **) argv, d); |
589 | first_nonopt = optind; | 448 | else if (d->__first_nonopt == d->__last_nonopt) |
590 | last_nonopt = argc; | 449 | d->__first_nonopt = d->optind; |
450 | d->__last_nonopt = argc; | ||
591 | 451 | ||
592 | optind = argc; | 452 | d->optind = argc; |
593 | } | 453 | } |
594 | 454 | ||
595 | /* If we have done all the ARGV-elements, stop the scan | 455 | /* If we have done all the ARGV-elements, stop the scan |
596 | and back over any non-options that we skipped and permuted. */ | 456 | and back over any non-options that we skipped and permuted. */ |
597 | 457 | ||
598 | if (optind == argc) | 458 | if (d->optind == argc) |
599 | { | 459 | { |
600 | /* Set the next-arg-index to point at the non-options | 460 | /* Set the next-arg-index to point at the non-options |
601 | that we previously skipped, so the caller will digest them. */ | 461 | that we previously skipped, so the caller will digest them. */ |
602 | if (first_nonopt != last_nonopt) | 462 | if (d->__first_nonopt != d->__last_nonopt) |
603 | optind = first_nonopt; | 463 | d->optind = d->__first_nonopt; |
604 | return -1; | 464 | return -1; |
605 | } | 465 | } |
606 | 466 | ||
... | @@ -609,17 +469,17 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -609,17 +469,17 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
609 | 469 | ||
610 | if (NONOPTION_P) | 470 | if (NONOPTION_P) |
611 | { | 471 | { |
612 | if (ordering == REQUIRE_ORDER) | 472 | if (d->__ordering == REQUIRE_ORDER) |
613 | return -1; | 473 | return -1; |
614 | optarg = argv[optind++]; | 474 | d->optarg = argv[d->optind++]; |
615 | return 1; | 475 | return 1; |
616 | } | 476 | } |
617 | 477 | ||
618 | /* We have found another option-ARGV-element. | 478 | /* We have found another option-ARGV-element. |
619 | Skip the initial punctuation. */ | 479 | Skip the initial punctuation. */ |
620 | 480 | ||
621 | nextchar = (argv[optind] + 1 | 481 | d->__nextchar = (argv[d->optind] + 1 |
622 | + (longopts != NULL && argv[optind][1] == '-')); | 482 | + (longopts != NULL && argv[d->optind][1] == '-')); |
623 | } | 483 | } |
624 | 484 | ||
625 | /* Decode the current option-ARGV-element. */ | 485 | /* Decode the current option-ARGV-element. */ |
... | @@ -638,8 +498,9 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -638,8 +498,9 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
638 | This distinction seems to be the most useful approach. */ | 498 | This distinction seems to be the most useful approach. */ |
639 | 499 | ||
640 | if (longopts != NULL | 500 | if (longopts != NULL |
641 | && (argv[optind][1] == '-' | 501 | && (argv[d->optind][1] == '-' |
642 | || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) | 502 | || (long_only && (argv[d->optind][2] |
503 | || !strchr (optstring, argv[d->optind][1]))))) | ||
643 | { | 504 | { |
644 | char *nameend; | 505 | char *nameend; |
645 | const struct option *p; | 506 | const struct option *p; |
... | @@ -649,15 +510,15 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -649,15 +510,15 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
649 | int indfound = -1; | 510 | int indfound = -1; |
650 | int option_index; | 511 | int option_index; |
651 | 512 | ||
652 | for (nameend = nextchar; *nameend && *nameend != '='; nameend++) | 513 | for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) |
653 | /* Do nothing. */ ; | 514 | /* Do nothing. */ ; |
654 | 515 | ||
655 | /* Test all long options for either exact match | 516 | /* Test all long options for either exact match |
656 | or abbreviated matches. */ | 517 | or abbreviated matches. */ |
657 | for (p = longopts, option_index = 0; p->name; p++, option_index++) | 518 | for (p = longopts, option_index = 0; p->name; p++, option_index++) |
658 | if (!strncmp (p->name, nextchar, nameend - nextchar)) | 519 | if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) |
659 | { | 520 | { |
660 | if ((unsigned int) (nameend - nextchar) | 521 | if ((unsigned int) (nameend - d->__nextchar) |
661 | == (unsigned int) strlen (p->name)) | 522 | == (unsigned int) strlen (p->name)) |
662 | { | 523 | { |
663 | /* Exact match found. */ | 524 | /* Exact match found. */ |
... | @@ -683,62 +544,158 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -683,62 +544,158 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
683 | if (ambig && !exact) | 544 | if (ambig && !exact) |
684 | { | 545 | { |
685 | if (print_errors) | 546 | if (print_errors) |
547 | { | ||
548 | #if defined _LIBC && defined USE_IN_LIBIO | ||
549 | char *buf; | ||
550 | |||
551 | if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"), | ||
552 | argv[0], argv[d->optind]) >= 0) | ||
553 | { | ||
554 | _IO_flockfile (stderr); | ||
555 | |||
556 | int old_flags2 = ((_IO_FILE *) stderr)->_flags2; | ||
557 | ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; | ||
558 | |||
559 | if (_IO_fwide (stderr, 0) > 0) | ||
560 | __fwprintf (stderr, L"%s", buf); | ||
561 | else | ||
562 | fputs (buf, stderr); | ||
563 | |||
564 | ((_IO_FILE *) stderr)->_flags2 = old_flags2; | ||
565 | _IO_funlockfile (stderr); | ||
566 | |||
567 | free (buf); | ||
568 | } | ||
569 | #else | ||
686 | fprintf (stderr, _("%s: option `%s' is ambiguous\n"), | 570 | fprintf (stderr, _("%s: option `%s' is ambiguous\n"), |
687 | argv[0], argv[optind]); | 571 | argv[0], argv[d->optind]); |
688 | nextchar += strlen (nextchar); | 572 | #endif |
689 | optind++; | 573 | } |
690 | optopt = 0; | 574 | d->__nextchar += strlen (d->__nextchar); |
575 | d->optind++; | ||
576 | d->optopt = 0; | ||
691 | return '?'; | 577 | return '?'; |
692 | } | 578 | } |
693 | 579 | ||
694 | if (pfound != NULL) | 580 | if (pfound != NULL) |
695 | { | 581 | { |
696 | option_index = indfound; | 582 | option_index = indfound; |
697 | optind++; | 583 | d->optind++; |
698 | if (*nameend) | 584 | if (*nameend) |
699 | { | 585 | { |
700 | /* Don't test has_arg with >, because some C compilers don't | 586 | /* Don't test has_arg with >, because some C compilers don't |
701 | allow it to be used on enums. */ | 587 | allow it to be used on enums. */ |
702 | if (pfound->has_arg) | 588 | if (pfound->has_arg) |
703 | optarg = nameend + 1; | 589 | d->optarg = nameend + 1; |
704 | else | 590 | else |
705 | { | 591 | { |
706 | if (print_errors) | 592 | if (print_errors) |
707 | { | 593 | { |
708 | if (argv[optind - 1][1] == '-') | 594 | #if defined _LIBC && defined USE_IN_LIBIO |
595 | char *buf; | ||
596 | int n; | ||
597 | #endif | ||
598 | |||
599 | if (argv[d->optind - 1][1] == '-') | ||
600 | { | ||
709 | /* --option */ | 601 | /* --option */ |
710 | fprintf (stderr, | 602 | #if defined _LIBC && defined USE_IN_LIBIO |
711 | _("%s: option `--%s' doesn't allow an argument\n"), | 603 | n = __asprintf (&buf, _("\ |
604 | %s: option `--%s' doesn't allow an argument\n"), | ||
605 | argv[0], pfound->name); | ||
606 | #else | ||
607 | fprintf (stderr, _("\ | ||
608 | %s: option `--%s' doesn't allow an argument\n"), | ||
712 | argv[0], pfound->name); | 609 | argv[0], pfound->name); |
610 | #endif | ||
611 | } | ||
713 | else | 612 | else |
613 | { | ||
714 | /* +option or -option */ | 614 | /* +option or -option */ |
715 | fprintf (stderr, | 615 | #if defined _LIBC && defined USE_IN_LIBIO |
716 | _("%s: option `%c%s' doesn't allow an argument\n"), | 616 | n = __asprintf (&buf, _("\ |
717 | argv[0], argv[optind - 1][0], pfound->name); | 617 | %s: option `%c%s' doesn't allow an argument\n"), |
618 | argv[0], argv[d->optind - 1][0], | ||
619 | pfound->name); | ||
620 | #else | ||
621 | fprintf (stderr, _("\ | ||
622 | %s: option `%c%s' doesn't allow an argument\n"), | ||
623 | argv[0], argv[d->optind - 1][0], | ||
624 | pfound->name); | ||
625 | #endif | ||
626 | } | ||
627 | |||
628 | #if defined _LIBC && defined USE_IN_LIBIO | ||
629 | if (n >= 0) | ||
630 | { | ||
631 | _IO_flockfile (stderr); | ||
632 | |||
633 | int old_flags2 = ((_IO_FILE *) stderr)->_flags2; | ||
634 | ((_IO_FILE *) stderr)->_flags2 | ||
635 | |= _IO_FLAGS2_NOTCANCEL; | ||
636 | |||
637 | if (_IO_fwide (stderr, 0) > 0) | ||
638 | __fwprintf (stderr, L"%s", buf); | ||
639 | else | ||
640 | fputs (buf, stderr); | ||
641 | |||
642 | ((_IO_FILE *) stderr)->_flags2 = old_flags2; | ||
643 | _IO_funlockfile (stderr); | ||
644 | |||
645 | free (buf); | ||
646 | } | ||
647 | #endif | ||
718 | } | 648 | } |
719 | 649 | ||
720 | nextchar += strlen (nextchar); | 650 | d->__nextchar += strlen (d->__nextchar); |
721 | 651 | ||
722 | optopt = pfound->val; | 652 | d->optopt = pfound->val; |
723 | return '?'; | 653 | return '?'; |
724 | } | 654 | } |
725 | } | 655 | } |
726 | else if (pfound->has_arg == 1) | 656 | else if (pfound->has_arg == 1) |
727 | { | 657 | { |
728 | if (optind < argc) | 658 | if (d->optind < argc) |
729 | optarg = argv[optind++]; | 659 | d->optarg = argv[d->optind++]; |
730 | else | 660 | else |
731 | { | 661 | { |
732 | if (print_errors) | 662 | if (print_errors) |
663 | { | ||
664 | #if defined _LIBC && defined USE_IN_LIBIO | ||
665 | char *buf; | ||
666 | |||
667 | if (__asprintf (&buf, _("\ | ||
668 | %s: option `%s' requires an argument\n"), | ||
669 | argv[0], argv[d->optind - 1]) >= 0) | ||
670 | { | ||
671 | _IO_flockfile (stderr); | ||
672 | |||
673 | int old_flags2 = ((_IO_FILE *) stderr)->_flags2; | ||
674 | ((_IO_FILE *) stderr)->_flags2 | ||
675 | |= _IO_FLAGS2_NOTCANCEL; | ||
676 | |||
677 | if (_IO_fwide (stderr, 0) > 0) | ||
678 | __fwprintf (stderr, L"%s", buf); | ||
679 | else | ||
680 | fputs (buf, stderr); | ||
681 | |||
682 | ((_IO_FILE *) stderr)->_flags2 = old_flags2; | ||
683 | _IO_funlockfile (stderr); | ||
684 | |||
685 | free (buf); | ||
686 | } | ||
687 | #else | ||
733 | fprintf (stderr, | 688 | fprintf (stderr, |
734 | _("%s: option `%s' requires an argument\n"), | 689 | _("%s: option `%s' requires an argument\n"), |
735 | argv[0], argv[optind - 1]); | 690 | argv[0], argv[d->optind - 1]); |
736 | nextchar += strlen (nextchar); | 691 | #endif |
737 | optopt = pfound->val; | 692 | } |
693 | d->__nextchar += strlen (d->__nextchar); | ||
694 | d->optopt = pfound->val; | ||
738 | return optstring[0] == ':' ? ':' : '?'; | 695 | return optstring[0] == ':' ? ':' : '?'; |
739 | } | 696 | } |
740 | } | 697 | } |
741 | nextchar += strlen (nextchar); | 698 | d->__nextchar += strlen (d->__nextchar); |
742 | if (longind != NULL) | 699 | if (longind != NULL) |
743 | *longind = option_index; | 700 | *longind = option_index; |
744 | if (pfound->flag) | 701 | if (pfound->flag) |
... | @@ -753,23 +710,62 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -753,23 +710,62 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
753 | or the option starts with '--' or is not a valid short | 710 | or the option starts with '--' or is not a valid short |
754 | option, then it's an error. | 711 | option, then it's an error. |
755 | Otherwise interpret it as a short option. */ | 712 | Otherwise interpret it as a short option. */ |
756 | if (!long_only || argv[optind][1] == '-' | 713 | if (!long_only || argv[d->optind][1] == '-' |
757 | || my_index (optstring, *nextchar) == NULL) | 714 | || strchr (optstring, *d->__nextchar) == NULL) |
758 | { | 715 | { |
759 | if (print_errors) | 716 | if (print_errors) |
760 | { | 717 | { |
761 | if (argv[optind][1] == '-') | 718 | #if defined _LIBC && defined USE_IN_LIBIO |
719 | char *buf; | ||
720 | int n; | ||
721 | #endif | ||
722 | |||
723 | if (argv[d->optind][1] == '-') | ||
724 | { | ||
762 | /* --option */ | 725 | /* --option */ |
726 | #if defined _LIBC && defined USE_IN_LIBIO | ||
727 | n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), | ||
728 | argv[0], d->__nextchar); | ||
729 | #else | ||
763 | fprintf (stderr, _("%s: unrecognized option `--%s'\n"), | 730 | fprintf (stderr, _("%s: unrecognized option `--%s'\n"), |
764 | argv[0], nextchar); | 731 | argv[0], d->__nextchar); |
732 | #endif | ||
733 | } | ||
765 | else | 734 | else |
735 | { | ||
766 | /* +option or -option */ | 736 | /* +option or -option */ |
737 | #if defined _LIBC && defined USE_IN_LIBIO | ||
738 | n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), | ||
739 | argv[0], argv[d->optind][0], d->__nextchar); | ||
740 | #else | ||
767 | fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), | 741 | fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), |
768 | argv[0], argv[optind][0], nextchar); | 742 | argv[0], argv[d->optind][0], d->__nextchar); |
743 | #endif | ||
744 | } | ||
745 | |||
746 | #if defined _LIBC && defined USE_IN_LIBIO | ||
747 | if (n >= 0) | ||
748 | { | ||
749 | _IO_flockfile (stderr); | ||
750 | |||
751 | int old_flags2 = ((_IO_FILE *) stderr)->_flags2; | ||
752 | ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; | ||
753 | |||
754 | if (_IO_fwide (stderr, 0) > 0) | ||
755 | __fwprintf (stderr, L"%s", buf); | ||
756 | else | ||
757 | fputs (buf, stderr); | ||
758 | |||
759 | ((_IO_FILE *) stderr)->_flags2 = old_flags2; | ||
760 | _IO_funlockfile (stderr); | ||
761 | |||
762 | free (buf); | ||
763 | } | ||
764 | #endif | ||
769 | } | 765 | } |
770 | nextchar = (char *) ""; | 766 | d->__nextchar = (char *) ""; |
771 | optind++; | 767 | d->optind++; |
772 | optopt = 0; | 768 | d->optopt = 0; |
773 | return '?'; | 769 | return '?'; |
774 | } | 770 | } |
775 | } | 771 | } |
... | @@ -777,26 +773,63 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -777,26 +773,63 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
777 | /* Look at and handle the next short option-character. */ | 773 | /* Look at and handle the next short option-character. */ |
778 | 774 | ||
779 | { | 775 | { |
780 | char c = *nextchar++; | 776 | char c = *d->__nextchar++; |
781 | char *temp = my_index (optstring, c); | 777 | char *temp = strchr (optstring, c); |
782 | 778 | ||
783 | /* Increment `optind' when we start to process its last character. */ | 779 | /* Increment `optind' when we start to process its last character. */ |
784 | if (*nextchar == '\0') | 780 | if (*d->__nextchar == '\0') |
785 | ++optind; | 781 | ++d->optind; |
786 | 782 | ||
787 | if (temp == NULL || c == ':') | 783 | if (temp == NULL || c == ':') |
788 | { | 784 | { |
789 | if (print_errors) | 785 | if (print_errors) |
790 | { | 786 | { |
791 | if (posixly_correct) | 787 | #if defined _LIBC && defined USE_IN_LIBIO |
788 | char *buf; | ||
789 | int n; | ||
790 | #endif | ||
791 | |||
792 | if (d->__posixly_correct) | ||
793 | { | ||
792 | /* 1003.2 specifies the format of this message. */ | 794 | /* 1003.2 specifies the format of this message. */ |
793 | fprintf (stderr, _("%s: illegal option -- %c\n"), | 795 | #if defined _LIBC && defined USE_IN_LIBIO |
796 | n = __asprintf (&buf, _("%s: illegal option -- %c\n"), | ||
794 | argv[0], c); | 797 | argv[0], c); |
798 | #else | ||
799 | fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); | ||
800 | #endif | ||
801 | } | ||
795 | else | 802 | else |
796 | fprintf (stderr, _("%s: invalid option -- %c\n"), | 803 | { |
804 | #if defined _LIBC && defined USE_IN_LIBIO | ||
805 | n = __asprintf (&buf, _("%s: invalid option -- %c\n"), | ||
797 | argv[0], c); | 806 | argv[0], c); |
807 | #else | ||
808 | fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); | ||
809 | #endif | ||
810 | } | ||
811 | |||
812 | #if defined _LIBC && defined USE_IN_LIBIO | ||
813 | if (n >= 0) | ||
814 | { | ||
815 | _IO_flockfile (stderr); | ||
816 | |||
817 | int old_flags2 = ((_IO_FILE *) stderr)->_flags2; | ||
818 | ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; | ||
819 | |||
820 | if (_IO_fwide (stderr, 0) > 0) | ||
821 | __fwprintf (stderr, L"%s", buf); | ||
822 | else | ||
823 | fputs (buf, stderr); | ||
824 | |||
825 | ((_IO_FILE *) stderr)->_flags2 = old_flags2; | ||
826 | _IO_funlockfile (stderr); | ||
827 | |||
828 | free (buf); | ||
798 | } | 829 | } |
799 | optopt = c; | 830 | #endif |
831 | } | ||
832 | d->optopt = c; | ||
800 | return '?'; | 833 | return '?'; |
801 | } | 834 | } |
802 | /* Convenience. Treat POSIX -W foo same as long option --foo */ | 835 | /* Convenience. Treat POSIX -W foo same as long option --foo */ |
... | @@ -811,22 +844,46 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -811,22 +844,46 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
811 | int option_index; | 844 | int option_index; |
812 | 845 | ||
813 | /* This is an option that requires an argument. */ | 846 | /* This is an option that requires an argument. */ |
814 | if (*nextchar != '\0') | 847 | if (*d->__nextchar != '\0') |
815 | { | 848 | { |
816 | optarg = nextchar; | 849 | d->optarg = d->__nextchar; |
817 | /* If we end this ARGV-element by taking the rest as an arg, | 850 | /* If we end this ARGV-element by taking the rest as an arg, |
818 | we must advance to the next element now. */ | 851 | we must advance to the next element now. */ |
819 | optind++; | 852 | d->optind++; |
820 | } | 853 | } |
821 | else if (optind == argc) | 854 | else if (d->optind == argc) |
822 | { | 855 | { |
823 | if (print_errors) | 856 | if (print_errors) |
824 | { | 857 | { |
825 | /* 1003.2 specifies the format of this message. */ | 858 | /* 1003.2 specifies the format of this message. */ |
859 | #if defined _LIBC && defined USE_IN_LIBIO | ||
860 | char *buf; | ||
861 | |||
862 | if (__asprintf (&buf, | ||
863 | _("%s: option requires an argument -- %c\n"), | ||
864 | argv[0], c) >= 0) | ||
865 | { | ||
866 | _IO_flockfile (stderr); | ||
867 | |||
868 | int old_flags2 = ((_IO_FILE *) stderr)->_flags2; | ||
869 | ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; | ||
870 | |||
871 | if (_IO_fwide (stderr, 0) > 0) | ||
872 | __fwprintf (stderr, L"%s", buf); | ||
873 | else | ||
874 | fputs (buf, stderr); | ||
875 | |||
876 | ((_IO_FILE *) stderr)->_flags2 = old_flags2; | ||
877 | _IO_funlockfile (stderr); | ||
878 | |||
879 | free (buf); | ||
880 | } | ||
881 | #else | ||
826 | fprintf (stderr, _("%s: option requires an argument -- %c\n"), | 882 | fprintf (stderr, _("%s: option requires an argument -- %c\n"), |
827 | argv[0], c); | 883 | argv[0], c); |
884 | #endif | ||
828 | } | 885 | } |
829 | optopt = c; | 886 | d->optopt = c; |
830 | if (optstring[0] == ':') | 887 | if (optstring[0] == ':') |
831 | c = ':'; | 888 | c = ':'; |
832 | else | 889 | else |
... | @@ -834,22 +891,23 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -834,22 +891,23 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
834 | return c; | 891 | return c; |
835 | } | 892 | } |
836 | else | 893 | else |
837 | /* We already incremented `optind' once; | 894 | /* We already incremented `d->optind' once; |
838 | increment it again when taking next ARGV-elt as argument. */ | 895 | increment it again when taking next ARGV-elt as argument. */ |
839 | optarg = argv[optind++]; | 896 | d->optarg = argv[d->optind++]; |
840 | 897 | ||
841 | /* optarg is now the argument, see if it's in the | 898 | /* optarg is now the argument, see if it's in the |
842 | table of longopts. */ | 899 | table of longopts. */ |
843 | 900 | ||
844 | for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) | 901 | for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; |
902 | nameend++) | ||
845 | /* Do nothing. */ ; | 903 | /* Do nothing. */ ; |
846 | 904 | ||
847 | /* Test all long options for either exact match | 905 | /* Test all long options for either exact match |
848 | or abbreviated matches. */ | 906 | or abbreviated matches. */ |
849 | for (p = longopts, option_index = 0; p->name; p++, option_index++) | 907 | for (p = longopts, option_index = 0; p->name; p++, option_index++) |
850 | if (!strncmp (p->name, nextchar, nameend - nextchar)) | 908 | if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) |
851 | { | 909 | { |
852 | if ((unsigned int) (nameend - nextchar) == strlen (p->name)) | 910 | if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name)) |
853 | { | 911 | { |
854 | /* Exact match found. */ | 912 | /* Exact match found. */ |
855 | pfound = p; | 913 | pfound = p; |
... | @@ -870,10 +928,35 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -870,10 +928,35 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
870 | if (ambig && !exact) | 928 | if (ambig && !exact) |
871 | { | 929 | { |
872 | if (print_errors) | 930 | if (print_errors) |
931 | { | ||
932 | #if defined _LIBC && defined USE_IN_LIBIO | ||
933 | char *buf; | ||
934 | |||
935 | if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), | ||
936 | argv[0], argv[d->optind]) >= 0) | ||
937 | { | ||
938 | _IO_flockfile (stderr); | ||
939 | |||
940 | int old_flags2 = ((_IO_FILE *) stderr)->_flags2; | ||
941 | ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; | ||
942 | |||
943 | if (_IO_fwide (stderr, 0) > 0) | ||
944 | __fwprintf (stderr, L"%s", buf); | ||
945 | else | ||
946 | fputs (buf, stderr); | ||
947 | |||
948 | ((_IO_FILE *) stderr)->_flags2 = old_flags2; | ||
949 | _IO_funlockfile (stderr); | ||
950 | |||
951 | free (buf); | ||
952 | } | ||
953 | #else | ||
873 | fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), | 954 | fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), |
874 | argv[0], argv[optind]); | 955 | argv[0], argv[d->optind]); |
875 | nextchar += strlen (nextchar); | 956 | #endif |
876 | optind++; | 957 | } |
958 | d->__nextchar += strlen (d->__nextchar); | ||
959 | d->optind++; | ||
877 | return '?'; | 960 | return '?'; |
878 | } | 961 | } |
879 | if (pfound != NULL) | 962 | if (pfound != NULL) |
... | @@ -884,33 +967,87 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -884,33 +967,87 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
884 | /* Don't test has_arg with >, because some C compilers don't | 967 | /* Don't test has_arg with >, because some C compilers don't |
885 | allow it to be used on enums. */ | 968 | allow it to be used on enums. */ |
886 | if (pfound->has_arg) | 969 | if (pfound->has_arg) |
887 | optarg = nameend + 1; | 970 | d->optarg = nameend + 1; |
888 | else | 971 | else |
889 | { | 972 | { |
890 | if (print_errors) | 973 | if (print_errors) |
974 | { | ||
975 | #if defined _LIBC && defined USE_IN_LIBIO | ||
976 | char *buf; | ||
977 | |||
978 | if (__asprintf (&buf, _("\ | ||
979 | %s: option `-W %s' doesn't allow an argument\n"), | ||
980 | argv[0], pfound->name) >= 0) | ||
981 | { | ||
982 | _IO_flockfile (stderr); | ||
983 | |||
984 | int old_flags2 = ((_IO_FILE *) stderr)->_flags2; | ||
985 | ((_IO_FILE *) stderr)->_flags2 | ||
986 | |= _IO_FLAGS2_NOTCANCEL; | ||
987 | |||
988 | if (_IO_fwide (stderr, 0) > 0) | ||
989 | __fwprintf (stderr, L"%s", buf); | ||
990 | else | ||
991 | fputs (buf, stderr); | ||
992 | |||
993 | ((_IO_FILE *) stderr)->_flags2 = old_flags2; | ||
994 | _IO_funlockfile (stderr); | ||
995 | |||
996 | free (buf); | ||
997 | } | ||
998 | #else | ||
891 | fprintf (stderr, _("\ | 999 | fprintf (stderr, _("\ |
892 | %s: option `-W %s' doesn't allow an argument\n"), | 1000 | %s: option `-W %s' doesn't allow an argument\n"), |
893 | argv[0], pfound->name); | 1001 | argv[0], pfound->name); |
1002 | #endif | ||
1003 | } | ||
894 | 1004 | ||
895 | nextchar += strlen (nextchar); | 1005 | d->__nextchar += strlen (d->__nextchar); |
896 | return '?'; | 1006 | return '?'; |
897 | } | 1007 | } |
898 | } | 1008 | } |
899 | else if (pfound->has_arg == 1) | 1009 | else if (pfound->has_arg == 1) |
900 | { | 1010 | { |
901 | if (optind < argc) | 1011 | if (d->optind < argc) |
902 | optarg = argv[optind++]; | 1012 | d->optarg = argv[d->optind++]; |
903 | else | 1013 | else |
904 | { | 1014 | { |
905 | if (print_errors) | 1015 | if (print_errors) |
1016 | { | ||
1017 | #if defined _LIBC && defined USE_IN_LIBIO | ||
1018 | char *buf; | ||
1019 | |||
1020 | if (__asprintf (&buf, _("\ | ||
1021 | %s: option `%s' requires an argument\n"), | ||
1022 | argv[0], argv[d->optind - 1]) >= 0) | ||
1023 | { | ||
1024 | _IO_flockfile (stderr); | ||
1025 | |||
1026 | int old_flags2 = ((_IO_FILE *) stderr)->_flags2; | ||
1027 | ((_IO_FILE *) stderr)->_flags2 | ||
1028 | |= _IO_FLAGS2_NOTCANCEL; | ||
1029 | |||
1030 | if (_IO_fwide (stderr, 0) > 0) | ||
1031 | __fwprintf (stderr, L"%s", buf); | ||
1032 | else | ||
1033 | fputs (buf, stderr); | ||
1034 | |||
1035 | ((_IO_FILE *) stderr)->_flags2 = old_flags2; | ||
1036 | _IO_funlockfile (stderr); | ||
1037 | |||
1038 | free (buf); | ||
1039 | } | ||
1040 | #else | ||
906 | fprintf (stderr, | 1041 | fprintf (stderr, |
907 | _("%s: option `%s' requires an argument\n"), | 1042 | _("%s: option `%s' requires an argument\n"), |
908 | argv[0], argv[optind - 1]); | 1043 | argv[0], argv[d->optind - 1]); |
909 | nextchar += strlen (nextchar); | 1044 | #endif |
1045 | } | ||
1046 | d->__nextchar += strlen (d->__nextchar); | ||
910 | return optstring[0] == ':' ? ':' : '?'; | 1047 | return optstring[0] == ':' ? ':' : '?'; |
911 | } | 1048 | } |
912 | } | 1049 | } |
913 | nextchar += strlen (nextchar); | 1050 | d->__nextchar += strlen (d->__nextchar); |
914 | if (longind != NULL) | 1051 | if (longind != NULL) |
915 | *longind = option_index; | 1052 | *longind = option_index; |
916 | if (pfound->flag) | 1053 | if (pfound->flag) |
... | @@ -920,7 +1057,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -920,7 +1057,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
920 | } | 1057 | } |
921 | return pfound->val; | 1058 | return pfound->val; |
922 | } | 1059 | } |
923 | nextchar = NULL; | 1060 | d->__nextchar = NULL; |
924 | return 'W'; /* Let the application handle it. */ | 1061 | return 'W'; /* Let the application handle it. */ |
925 | } | 1062 | } |
926 | if (temp[1] == ':') | 1063 | if (temp[1] == ':') |
... | @@ -928,35 +1065,59 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -928,35 +1065,59 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
928 | if (temp[2] == ':') | 1065 | if (temp[2] == ':') |
929 | { | 1066 | { |
930 | /* This is an option that accepts an argument optionally. */ | 1067 | /* This is an option that accepts an argument optionally. */ |
931 | if (*nextchar != '\0') | 1068 | if (*d->__nextchar != '\0') |
932 | { | 1069 | { |
933 | optarg = nextchar; | 1070 | d->optarg = d->__nextchar; |
934 | optind++; | 1071 | d->optind++; |
935 | } | 1072 | } |
936 | else | 1073 | else |
937 | optarg = NULL; | 1074 | d->optarg = NULL; |
938 | nextchar = NULL; | 1075 | d->__nextchar = NULL; |
939 | } | 1076 | } |
940 | else | 1077 | else |
941 | { | 1078 | { |
942 | /* This is an option that requires an argument. */ | 1079 | /* This is an option that requires an argument. */ |
943 | if (*nextchar != '\0') | 1080 | if (*d->__nextchar != '\0') |
944 | { | 1081 | { |
945 | optarg = nextchar; | 1082 | d->optarg = d->__nextchar; |
946 | /* If we end this ARGV-element by taking the rest as an arg, | 1083 | /* If we end this ARGV-element by taking the rest as an arg, |
947 | we must advance to the next element now. */ | 1084 | we must advance to the next element now. */ |
948 | optind++; | 1085 | d->optind++; |
949 | } | 1086 | } |
950 | else if (optind == argc) | 1087 | else if (d->optind == argc) |
951 | { | 1088 | { |
952 | if (print_errors) | 1089 | if (print_errors) |
953 | { | 1090 | { |
954 | /* 1003.2 specifies the format of this message. */ | 1091 | /* 1003.2 specifies the format of this message. */ |
1092 | #if defined _LIBC && defined USE_IN_LIBIO | ||
1093 | char *buf; | ||
1094 | |||
1095 | if (__asprintf (&buf, _("\ | ||
1096 | %s: option requires an argument -- %c\n"), | ||
1097 | argv[0], c) >= 0) | ||
1098 | { | ||
1099 | _IO_flockfile (stderr); | ||
1100 | |||
1101 | int old_flags2 = ((_IO_FILE *) stderr)->_flags2; | ||
1102 | ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; | ||
1103 | |||
1104 | if (_IO_fwide (stderr, 0) > 0) | ||
1105 | __fwprintf (stderr, L"%s", buf); | ||
1106 | else | ||
1107 | fputs (buf, stderr); | ||
1108 | |||
1109 | ((_IO_FILE *) stderr)->_flags2 = old_flags2; | ||
1110 | _IO_funlockfile (stderr); | ||
1111 | |||
1112 | free (buf); | ||
1113 | } | ||
1114 | #else | ||
955 | fprintf (stderr, | 1115 | fprintf (stderr, |
956 | _("%s: option requires an argument -- %c\n"), | 1116 | _("%s: option requires an argument -- %c\n"), |
957 | argv[0], c); | 1117 | argv[0], c); |
1118 | #endif | ||
958 | } | 1119 | } |
959 | optopt = c; | 1120 | d->optopt = c; |
960 | if (optstring[0] == ':') | 1121 | if (optstring[0] == ':') |
961 | c = ':'; | 1122 | c = ':'; |
962 | else | 1123 | else |
... | @@ -965,8 +1126,8 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -965,8 +1126,8 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
965 | else | 1126 | else |
966 | /* We already incremented `optind' once; | 1127 | /* We already incremented `optind' once; |
967 | increment it again when taking next ARGV-elt as argument. */ | 1128 | increment it again when taking next ARGV-elt as argument. */ |
968 | optarg = argv[optind++]; | 1129 | d->optarg = argv[d->optind++]; |
969 | nextchar = NULL; | 1130 | d->__nextchar = NULL; |
970 | } | 1131 | } |
971 | } | 1132 | } |
972 | return c; | 1133 | return c; |
... | @@ -974,18 +1135,40 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | ... | @@ -974,18 +1135,40 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
974 | } | 1135 | } |
975 | 1136 | ||
976 | int | 1137 | int |
977 | getopt (argc, argv, optstring) | 1138 | _getopt_internal (int argc, char **argv, const char *optstring, |
978 | int argc; | 1139 | const struct option *longopts, int *longind, |
979 | char *const *argv; | 1140 | int long_only, int posixly_correct) |
980 | const char *optstring; | 1141 | { |
1142 | int result; | ||
1143 | |||
1144 | getopt_data.optind = optind; | ||
1145 | getopt_data.opterr = opterr; | ||
1146 | |||
1147 | result = _getopt_internal_r (argc, argv, optstring, longopts, longind, | ||
1148 | long_only, posixly_correct, &getopt_data); | ||
1149 | |||
1150 | optind = getopt_data.optind; | ||
1151 | optarg = getopt_data.optarg; | ||
1152 | optopt = getopt_data.optopt; | ||
1153 | |||
1154 | return result; | ||
1155 | } | ||
1156 | |||
1157 | /* glibc gets a LSB-compliant getopt. | ||
1158 | Standalone applications get a POSIX-compliant getopt. */ | ||
1159 | #if _LIBC | ||
1160 | enum { POSIXLY_CORRECT = 0 }; | ||
1161 | #else | ||
1162 | enum { POSIXLY_CORRECT = 1 }; | ||
1163 | #endif | ||
1164 | |||
1165 | int | ||
1166 | getopt (int argc, char *const *argv, const char *optstring) | ||
981 | { | 1167 | { |
982 | return _getopt_internal (argc, argv, optstring, | 1168 | return _getopt_internal (argc, (char **) argv, optstring, NULL, NULL, 0, |
983 | (const struct option *) 0, | 1169 | POSIXLY_CORRECT); |
984 | (int *) 0, | ||
985 | 0); | ||
986 | } | 1170 | } |
987 | 1171 | ||
988 | #endif /* Not ELIDE_CODE. */ | ||
989 | 1172 | ||
990 | #ifdef TEST | 1173 | #ifdef TEST |
991 | 1174 | ||
... | @@ -993,9 +1176,7 @@ getopt (argc, argv, optstring) | ... | @@ -993,9 +1176,7 @@ getopt (argc, argv, optstring) |
993 | the above definition of `getopt'. */ | 1176 | the above definition of `getopt'. */ |
994 | 1177 | ||
995 | int | 1178 | int |
996 | main (argc, argv) | 1179 | main (int argc, char **argv) |
997 | int argc; | ||
998 | char **argv; | ||
999 | { | 1180 | { |
1000 | int c; | 1181 | int c; |
1001 | int digit_optind = 0; | 1182 | int digit_optind = 0; | ... | ... |
1 | /* getopt_long and getopt_long_only entry points for GNU getopt. | 1 | /* getopt_long and getopt_long_only entry points for GNU getopt. |
2 | Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 | 2 | Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004 |
3 | Free Software Foundation, Inc. | 3 | Free Software Foundation, Inc. |
4 | NOTE: The canonical source of this file is maintained with the GNU C Library. | 4 | This file is part of the GNU C Library. |
5 | Bugs can be reported to bug-glibc@gnu.org. | ||
6 | 5 | ||
7 | This program is free software; you can redistribute it and/or modify it | 6 | This program is free software; you can redistribute it and/or modify |
8 | under the terms of the GNU General Public License as published by the | 7 | it under the terms of the GNU General Public License as published by |
9 | Free Software Foundation; either version 2, or (at your option) any | 8 | the Free Software Foundation; either version 2, or (at your option) |
10 | later version. | 9 | any later version. |
11 | 10 | ||
12 | This program is distributed in the hope that it will be useful, | 11 | This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | GNU General Public License for more details. | 14 | GNU General Public License for more details. |
16 | 15 | ||
17 | You should have received a copy of the GNU General Public License | 16 | You should have received a copy of the GNU General Public License along |
18 | along with this program; if not, write to the Free Software Foundation, | 17 | with this program; if not, write to the Free Software Foundation, |
19 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | 18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
20 | 19 | ||
21 | #ifdef HAVE_CONFIG_H | 20 | #ifdef HAVE_CONFIG_H |
22 | #include <config.h> | 21 | #include <config.h> |
23 | #endif | 22 | #endif |
24 | 23 | ||
25 | #include "getopt.h" | 24 | #ifdef _LIBC |
26 | 25 | # include <getopt.h> | |
27 | #if !defined __STDC__ || !__STDC__ | 26 | #else |
28 | /* This is a separate conditional since some stdc systems | 27 | # include "getopt.h" |
29 | reject `defined (const)'. */ | ||
30 | #ifndef const | ||
31 | #define const | ||
32 | #endif | ||
33 | #endif | 28 | #endif |
29 | #include "getopt_int.h" | ||
34 | 30 | ||
35 | #include <stdio.h> | 31 | #include <stdio.h> |
36 | 32 | ||
37 | /* Comment out all this code if we are using the GNU C Library, and are not | ||
38 | actually compiling the library itself. This code is part of the GNU C | ||
39 | Library, but also included in many other GNU distributions. Compiling | ||
40 | and linking in this code is a waste when using the GNU C library | ||
41 | (especially if it is a shared library). Rather than having every GNU | ||
42 | program understand `configure --with-gnu-libc' and omit the object files, | ||
43 | it is simpler to just do this in the source for each such file. */ | ||
44 | |||
45 | #define GETOPT_INTERFACE_VERSION 2 | ||
46 | #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 | ||
47 | #include <gnu-versions.h> | ||
48 | #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION | ||
49 | #define ELIDE_CODE | ||
50 | #endif | ||
51 | #endif | ||
52 | |||
53 | #ifndef ELIDE_CODE | ||
54 | |||
55 | |||
56 | /* This needs to come after some library #include | 33 | /* This needs to come after some library #include |
57 | to get __GNU_LIBRARY__ defined. */ | 34 | to get __GNU_LIBRARY__ defined. */ |
58 | #ifdef __GNU_LIBRARY__ | 35 | #ifdef __GNU_LIBRARY__ |
... | @@ -64,14 +41,20 @@ | ... | @@ -64,14 +41,20 @@ |
64 | #endif | 41 | #endif |
65 | 42 | ||
66 | int | 43 | int |
67 | getopt_long (argc, argv, options, long_options, opt_index) | 44 | getopt_long (int argc, char *__getopt_argv_const *argv, const char *options, |
68 | int argc; | 45 | const struct option *long_options, int *opt_index) |
69 | char *const *argv; | ||
70 | const char *options; | ||
71 | const struct option *long_options; | ||
72 | int *opt_index; | ||
73 | { | 46 | { |
74 | return _getopt_internal (argc, argv, options, long_options, opt_index, 0); | 47 | return _getopt_internal (argc, (char **) argv, options, long_options, |
48 | opt_index, 0, 0); | ||
49 | } | ||
50 | |||
51 | int | ||
52 | _getopt_long_r (int argc, char **argv, const char *options, | ||
53 | const struct option *long_options, int *opt_index, | ||
54 | struct _getopt_data *d) | ||
55 | { | ||
56 | return _getopt_internal_r (argc, argv, options, long_options, opt_index, | ||
57 | 0, 0, d); | ||
75 | } | 58 | } |
76 | 59 | ||
77 | /* Like getopt_long, but '-' as well as '--' can indicate a long option. | 60 | /* Like getopt_long, but '-' as well as '--' can indicate a long option. |
... | @@ -80,27 +63,30 @@ getopt_long (argc, argv, options, long_options, opt_index) | ... | @@ -80,27 +63,30 @@ getopt_long (argc, argv, options, long_options, opt_index) |
80 | instead. */ | 63 | instead. */ |
81 | 64 | ||
82 | int | 65 | int |
83 | getopt_long_only (argc, argv, options, long_options, opt_index) | 66 | getopt_long_only (int argc, char *__getopt_argv_const *argv, |
84 | int argc; | 67 | const char *options, |
85 | char *const *argv; | 68 | const struct option *long_options, int *opt_index) |
86 | const char *options; | ||
87 | const struct option *long_options; | ||
88 | int *opt_index; | ||
89 | { | 69 | { |
90 | return _getopt_internal (argc, argv, options, long_options, opt_index, 1); | 70 | return _getopt_internal (argc, (char **) argv, options, long_options, |
71 | opt_index, 1, 0); | ||
91 | } | 72 | } |
92 | 73 | ||
74 | int | ||
75 | _getopt_long_only_r (int argc, char **argv, const char *options, | ||
76 | const struct option *long_options, int *opt_index, | ||
77 | struct _getopt_data *d) | ||
78 | { | ||
79 | return _getopt_internal_r (argc, argv, options, long_options, opt_index, | ||
80 | 1, 0, d); | ||
81 | } | ||
93 | 82 | ||
94 | #endif /* Not ELIDE_CODE. */ | ||
95 | 83 | ||
96 | #ifdef TEST | 84 | #ifdef TEST |
97 | 85 | ||
98 | #include <stdio.h> | 86 | #include <stdio.h> |
99 | 87 | ||
100 | int | 88 | int |
101 | main (argc, argv) | 89 | main (int argc, char **argv) |
102 | int argc; | ||
103 | char **argv; | ||
104 | { | 90 | { |
105 | int c; | 91 | int c; |
106 | int digit_optind = 0; | 92 | int digit_optind = 0; | ... | ... |
1 | /* | 1 | /* md5.c - Functions to compute MD5 message digest of files or memory blocks |
2 | * This code implements the MD5 message-digest algorithm. | 2 | according to the definition of MD5 in RFC 1321 from April 1992. |
3 | * The algorithm is due to Ron Rivest. This code was | 3 | Copyright (C) 1995, 1996, 2001, 2003, 2004 Free Software Foundation, Inc. |
4 | * written by Colin Plumb in 1993, no copyright is claimed. | 4 | NOTE: The canonical source of this file is maintained with the GNU C |
5 | * This code is in the public domain; do with it what you wish. | 5 | Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. |
6 | * | 6 | |
7 | * Equivalent code is available from RSA Data Security, Inc. | 7 | This program is free software; you can redistribute it and/or modify it |
8 | * This code has been tested against that, and is equivalent, | 8 | under the terms of the GNU General Public License as published by the |
9 | * except that you don't need to include two pages of legalese | 9 | Free Software Foundation; either version 2, or (at your option) any |
10 | * with every copy. | 10 | later version. |
11 | * | 11 | |
12 | * To compute the message digest of a chunk of bytes, declare an | 12 | This program is distributed in the hope that it will be useful, |
13 | * MD5Context structure, pass it to MD5Init, call MD5Update as | 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * needed on buffers full of bytes, and then call MD5Final, which | 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * will fill a supplied 16-byte array with the digest. | 15 | GNU General Public License for more details. |
16 | */ | 16 | |
17 | /* | 17 | You should have received a copy of the GNU General Public License |
18 | * Modified (2001-01-31) to work on Sparcs <gray@Mirddin.farlep.net> | 18 | along with this program; if not, write to the Free Software Foundation, |
19 | */ | 19 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
20 | #if defined(HAVE_CONFIG_H) | 20 | |
21 | /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */ | ||
22 | |||
23 | #ifdef HAVE_CONFIG_H | ||
21 | # include <config.h> | 24 | # include <config.h> |
22 | #endif | 25 | #endif |
23 | 26 | ||
24 | #define MD5_CRYPT | 27 | #include "md5.h" |
28 | |||
29 | #include <stddef.h> | ||
30 | #include <string.h> | ||
31 | |||
32 | #if USE_UNLOCKED_IO | ||
33 | # include "unlocked-io.h" | ||
34 | #endif | ||
35 | |||
36 | #ifdef _LIBC | ||
37 | # include <endian.h> | ||
38 | # if __BYTE_ORDER == __BIG_ENDIAN | ||
39 | # define WORDS_BIGENDIAN 1 | ||
40 | # endif | ||
41 | /* We need to keep the namespace clean so define the MD5 function | ||
42 | protected using leading __ . */ | ||
43 | # define md5_init_ctx __md5_init_ctx | ||
44 | # define md5_process_block __md5_process_block | ||
45 | # define md5_process_bytes __md5_process_bytes | ||
46 | # define md5_finish_ctx __md5_finish_ctx | ||
47 | # define md5_read_ctx __md5_read_ctx | ||
48 | # define md5_stream __md5_stream | ||
49 | # define md5_buffer __md5_buffer | ||
50 | #endif | ||
51 | |||
52 | #ifdef WORDS_BIGENDIAN | ||
53 | # define SWAP(n) \ | ||
54 | (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) | ||
55 | #else | ||
56 | # define SWAP(n) (n) | ||
57 | #endif | ||
58 | |||
59 | #define BLOCKSIZE 4096 | ||
60 | /* Ensure that BLOCKSIZE is a multiple of 64. */ | ||
61 | #if BLOCKSIZE % 64 != 0 | ||
62 | /* FIXME-someday (soon?): use #error instead of this kludge. */ | ||
63 | "invalid BLOCKSIZE" | ||
64 | #endif | ||
65 | |||
66 | /* This array contains the bytes used to pad the buffer to the next | ||
67 | 64-byte boundary. (RFC 1321, 3.1: Step 1) */ | ||
68 | static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; | ||
25 | 69 | ||
26 | #ifdef MD5_CRYPT | ||
27 | #include <string.h> /* for memcpy() */ | ||
28 | #include <md5.h> | ||
29 | 70 | ||
71 | /* Initialize structure containing state of computation. | ||
72 | (RFC 1321, 3.3: Step 3) */ | ||
30 | void | 73 | void |
31 | md5_calc(unsigned char *output, unsigned char *input, unsigned int inlen) | 74 | md5_init_ctx (struct md5_ctx *ctx) |
32 | { | 75 | { |
33 | MD5_CTX context; | 76 | ctx->A = 0x67452301; |
77 | ctx->B = 0xefcdab89; | ||
78 | ctx->C = 0x98badcfe; | ||
79 | ctx->D = 0x10325476; | ||
34 | 80 | ||
35 | MD5Init(&context); | 81 | ctx->total[0] = ctx->total[1] = 0; |
36 | MD5Update(&context, input, inlen); | 82 | ctx->buflen = 0; |
37 | MD5Final(output, &context); | ||
38 | } | 83 | } |
39 | 84 | ||
85 | /* Put result from CTX in first 16 bytes following RESBUF. The result | ||
86 | must be in little endian byte order. | ||
40 | 87 | ||
41 | static void | 88 | IMPORTANT: On some systems it is required that RESBUF is correctly |
42 | bytes_encode(unsigned char *output, uint32 *input, unsigned int len) | 89 | aligned for a 32 bits value. */ |
90 | void * | ||
91 | md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) | ||
43 | { | 92 | { |
44 | unsigned int i, j; | 93 | ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); |
94 | ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); | ||
95 | ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); | ||
96 | ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); | ||
45 | 97 | ||
46 | for (i = 0, j = 0; j < len; i++, j += 4) { | 98 | return resbuf; |
47 | output[j] = (unsigned char)(input[i] & 0xff); | ||
48 | output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); | ||
49 | output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); | ||
50 | output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); | ||
51 | } | ||
52 | } | 99 | } |
53 | 100 | ||
54 | static void | 101 | /* Process the remaining bytes in the internal buffer and the usual |
55 | bytes_decode(uint32 *output, unsigned char *input, unsigned int len) | 102 | prolog according to the standard and write the result to RESBUF. |
103 | |||
104 | IMPORTANT: On some systems it is required that RESBUF is correctly | ||
105 | aligned for a 32 bits value. */ | ||
106 | void * | ||
107 | md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) | ||
56 | { | 108 | { |
57 | unsigned int i, j; | 109 | /* Take yet unprocessed bytes into account. */ |
110 | md5_uint32 bytes = ctx->buflen; | ||
111 | size_t pad; | ||
112 | |||
113 | /* Now count remaining bytes. */ | ||
114 | ctx->total[0] += bytes; | ||
115 | if (ctx->total[0] < bytes) | ||
116 | ++ctx->total[1]; | ||
117 | |||
118 | pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; | ||
119 | memcpy (&ctx->buffer[bytes], fillbuf, pad); | ||
120 | |||
121 | /* Put the 64-bit file length in *bits* at the end of the buffer. */ | ||
122 | *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); | ||
123 | *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | | ||
124 | (ctx->total[0] >> 29)); | ||
125 | |||
126 | /* Process last bytes. */ | ||
127 | md5_process_block (ctx->buffer, bytes + pad + 8, ctx); | ||
58 | 128 | ||
59 | for (i = 0, j = 0; j < len; i++, j += 4) | 129 | return md5_read_ctx (ctx, resbuf); |
60 | output[i] = ((uint32)input[j]) | | ||
61 | (((uint32)input[j+1]) << 8) | | ||
62 | (((uint32)input[j+2]) << 16) | | ||
63 | (((uint32)input[j+3]) << 24); | ||
64 | } | 130 | } |
65 | 131 | ||
66 | /* | 132 | /* Compute MD5 message digest for bytes read from STREAM. The |
67 | * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious | 133 | resulting message digest number will be written into the 16 bytes |
68 | * initialization constants. | 134 | beginning at RESBLOCK. */ |
69 | */ | 135 | int |
70 | void | 136 | md5_stream (FILE *stream, void *resblock) |
71 | MD5Init(struct MD5Context *ctx) | ||
72 | { | 137 | { |
73 | ctx->buf[0] = 0x67452301; | 138 | struct md5_ctx ctx; |
74 | ctx->buf[1] = 0xefcdab89; | 139 | char buffer[BLOCKSIZE + 72]; |
75 | ctx->buf[2] = 0x98badcfe; | 140 | size_t sum; |
76 | ctx->buf[3] = 0x10325476; | 141 | |
142 | /* Initialize the computation context. */ | ||
143 | md5_init_ctx (&ctx); | ||
144 | |||
145 | /* Iterate over full file contents. */ | ||
146 | while (1) | ||
147 | { | ||
148 | /* We read the file in blocks of BLOCKSIZE bytes. One call of the | ||
149 | computation function processes the whole buffer so that with the | ||
150 | next round of the loop another block can be read. */ | ||
151 | size_t n; | ||
152 | sum = 0; | ||
153 | |||
154 | /* Read block. Take care for partial reads. */ | ||
155 | while (1) | ||
156 | { | ||
157 | n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); | ||
158 | |||
159 | sum += n; | ||
160 | |||
161 | if (sum == BLOCKSIZE) | ||
162 | break; | ||
163 | |||
164 | if (n == 0) | ||
165 | { | ||
166 | /* Check for the error flag IFF N == 0, so that we don't | ||
167 | exit the loop after a partial read due to e.g., EAGAIN | ||
168 | or EWOULDBLOCK. */ | ||
169 | if (ferror (stream)) | ||
170 | return 1; | ||
171 | goto process_partial_block; | ||
172 | } | ||
77 | 173 | ||
78 | ctx->bits[0] = 0; | 174 | /* We've read at least one byte, so ignore errors. But always |
79 | ctx->bits[1] = 0; | 175 | check for EOF, since feof may be true even though N > 0. |
80 | } | 176 | Otherwise, we could end up calling fread after EOF. */ |
177 | if (feof (stream)) | ||
178 | goto process_partial_block; | ||
179 | } | ||
81 | 180 | ||
82 | /* | 181 | /* Process buffer with BLOCKSIZE bytes. Note that |
83 | * Update context to reflect the concatenation of another buffer full | 182 | BLOCKSIZE % 64 == 0 |
84 | * of bytes. | ||
85 | */ | 183 | */ |
86 | void | 184 | md5_process_block (buffer, BLOCKSIZE, &ctx); |
87 | MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) | 185 | } |
88 | { | ||
89 | uint32 t; | ||
90 | 186 | ||
91 | /* Update bitcount */ | 187 | process_partial_block:; |
92 | 188 | ||
93 | t = ctx->bits[0]; | 189 | /* Process any remaining bytes. */ |
94 | if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) | 190 | if (sum > 0) |
95 | ctx->bits[1]++; /* Carry from low to high */ | 191 | md5_process_bytes (buffer, sum, &ctx); |
96 | ctx->bits[1] += len >> 29; | ||
97 | 192 | ||
98 | t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ | 193 | /* Construct result in desired memory. */ |
99 | /* Handle any leading odd-sized chunks */ | 194 | md5_finish_ctx (&ctx, resblock); |
195 | return 0; | ||
196 | } | ||
100 | 197 | ||
101 | if (t) { | 198 | /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The |
102 | unsigned char *p = (unsigned char *) ctx->in + t; | 199 | result is always in little endian byte order, so that a byte-wise |
103 | t = 64 - t; | 200 | output yields to the wanted ASCII representation of the message |
104 | if (len < t) { | 201 | digest. */ |
105 | memcpy(p, buf, len); | 202 | void * |
106 | return; | 203 | md5_buffer (const char *buffer, size_t len, void *resblock) |
107 | } | 204 | { |
108 | memcpy(p, buf, t); | 205 | struct md5_ctx ctx; |
109 | MD5Transform(ctx->buf, (uint32 *) ctx->in); | ||
110 | buf += t; | ||
111 | len -= t; | ||
112 | } | ||
113 | /* Process data in 64-byte chunks */ | ||
114 | 206 | ||
115 | while (len >= 64) { | 207 | /* Initialize the computation context. */ |
116 | memcpy(ctx->in, buf, 64); | 208 | md5_init_ctx (&ctx); |
117 | MD5Transform(ctx->buf, (uint32 const *) buf); | ||
118 | buf += 64; | ||
119 | len -= 64; | ||
120 | } | ||
121 | 209 | ||
122 | /* Handle any remaining bytes of data. */ | 210 | /* Process whole buffer but last len % 64 bytes. */ |
211 | md5_process_bytes (buffer, len, &ctx); | ||
123 | 212 | ||
124 | memcpy(ctx->in, buf, len); | 213 | /* Put result in desired memory area. */ |
214 | return md5_finish_ctx (&ctx, resblock); | ||
125 | } | 215 | } |
126 | 216 | ||
127 | /* | 217 | |
128 | * Final wrapup - pad to 64-byte boundary with the bit pattern | ||
129 | * 1 0* (64-bit count of bits processed, MSB-first) | ||
130 | */ | ||
131 | void | 218 | void |
132 | MD5Final(unsigned char digest[16], struct MD5Context *ctx) | 219 | md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) |
133 | { | 220 | { |
134 | unsigned count; | 221 | /* When we already have some bits in our internal buffer concatenate |
135 | unsigned char *p; | 222 | both inputs first. */ |
136 | 223 | if (ctx->buflen != 0) | |
137 | /* Compute number of bytes mod 64 */ | 224 | { |
138 | count = (ctx->bits[0] >> 3) & 0x3F; | 225 | size_t left_over = ctx->buflen; |
139 | 226 | size_t add = 128 - left_over > len ? len : 128 - left_over; | |
140 | /* Set the first char of padding to 0x80. This is safe since there is | 227 | |
141 | always at least one byte free */ | 228 | memcpy (&ctx->buffer[left_over], buffer, add); |
142 | p = ctx->in + count; | 229 | ctx->buflen += add; |
143 | *p++ = 0x80; | 230 | |
144 | 231 | if (ctx->buflen > 64) | |
145 | /* Bytes of padding needed to make 64 bytes */ | 232 | { |
146 | count = 64 - 1 - count; | 233 | md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); |
147 | 234 | ||
148 | /* Pad out to 56 mod 64 */ | 235 | ctx->buflen &= 63; |
149 | if (count < 8) { | 236 | /* The regions in the following copy operation cannot overlap. */ |
150 | /* Two lots of padding: Pad the first block to 64 bytes */ | 237 | memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], |
151 | memset(p, 0, count); | 238 | ctx->buflen); |
152 | MD5Transform(ctx->buf, (uint32 *) ctx->in); | ||
153 | |||
154 | /* Now fill the next block with 56 bytes */ | ||
155 | memset(ctx->in, 0, 56); | ||
156 | } else { | ||
157 | /* Pad block to 56 bytes */ | ||
158 | memset(p, 0, count - 8); | ||
159 | } | 239 | } |
160 | 240 | ||
161 | /* Append length in bits and transform */ | 241 | buffer = (const char *) buffer + add; |
162 | bytes_encode((unsigned char*)((uint32 *) ctx->in + 14), ctx->bits, 8); | 242 | len -= add; |
163 | MD5Transform(ctx->buf, (uint32 *) ctx->in); | 243 | } |
164 | bytes_encode(digest,ctx->buf,16); | ||
165 | memset((char *) ctx, 0, sizeof(ctx)); /* In case it's sensitive */ | ||
166 | } | ||
167 | |||
168 | #ifndef ASM_MD5 | ||
169 | 244 | ||
170 | /* The four core functions - F1 is optimized somewhat */ | 245 | /* Process available complete blocks. */ |
246 | if (len >= 64) | ||
247 | { | ||
248 | #if !_STRING_ARCH_unaligned | ||
249 | # define alignof(type) offsetof (struct { char c; type x; }, x) | ||
250 | # define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0) | ||
251 | if (UNALIGNED_P (buffer)) | ||
252 | while (len > 64) | ||
253 | { | ||
254 | md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); | ||
255 | buffer = (const char *) buffer + 64; | ||
256 | len -= 64; | ||
257 | } | ||
258 | else | ||
259 | #endif | ||
260 | { | ||
261 | md5_process_block (buffer, len & ~63, ctx); | ||
262 | buffer = (const char *) buffer + (len & ~63); | ||
263 | len &= 63; | ||
264 | } | ||
265 | } | ||
171 | 266 | ||
172 | /*#define F1(x, y, z) (x & y | ~x & z) */ | 267 | /* Move remaining bytes in internal buffer. */ |
173 | #define F1(x, y, z) (z ^ (x & (y ^ z))) | 268 | if (len > 0) |
174 | #define F2(x, y, z) F1(z, x, y) | 269 | { |
175 | #define F3(x, y, z) (x ^ y ^ z) | 270 | size_t left_over = ctx->buflen; |
176 | #define F4(x, y, z) (y ^ (x | ~z)) | 271 | |
272 | memcpy (&ctx->buffer[left_over], buffer, len); | ||
273 | left_over += len; | ||
274 | if (left_over >= 64) | ||
275 | { | ||
276 | md5_process_block (ctx->buffer, 64, ctx); | ||
277 | left_over -= 64; | ||
278 | memcpy (ctx->buffer, &ctx->buffer[64], left_over); | ||
279 | } | ||
280 | ctx->buflen = left_over; | ||
281 | } | ||
282 | } | ||
177 | 283 | ||
178 | /* This is the central step in the MD5 algorithm. */ | ||
179 | #define MD5STEP(f, w, x, y, z, data, s) \ | ||
180 | ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ); | ||
181 | 284 | ||
182 | #if 0 | 285 | /* These are the four functions used in the four steps of the MD5 algorithm |
183 | dump(char *label,unsigned char *p, int len) | 286 | and defined in the RFC 1321. The first function is a little bit optimized |
184 | { | 287 | (as found in Colin Plumbs public domain implementation). */ |
185 | int i; | 288 | /* #define FF(b, c, d) ((b & c) | (~b & d)) */ |
186 | return; | 289 | #define FF(b, c, d) (d ^ (b & (c ^ d))) |
187 | printf("dump: %s\n", label); | 290 | #define FG(b, c, d) FF (d, b, c) |
188 | for (i=0; i<len; i++) | 291 | #define FH(b, c, d) (b ^ c ^ d) |
189 | printf("%x\n", p[i]); | 292 | #define FI(b, c, d) (c ^ (b | ~d)) |
190 | printf("--\n"); | ||
191 | 293 | ||
192 | } | 294 | /* Process LEN bytes of BUFFER, accumulating context into CTX. |
193 | #endif | 295 | It is assumed that LEN % 64 == 0. */ |
194 | 296 | ||
195 | /* | ||
196 | * The core of the MD5 algorithm, this alters an existing MD5 hash to | ||
197 | * reflect the addition of 16 longwords of new data. MD5Update blocks | ||
198 | * the data and converts bytes into longwords for this routine. | ||
199 | */ | ||
200 | void | 297 | void |
201 | MD5Transform(uint32 buf[4], uint32 const cin[16]) | 298 | md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) |
202 | { | 299 | { |
203 | register uint32 a, b, c, d; | 300 | md5_uint32 correct_words[16]; |
204 | uint32 in[16]; | 301 | const md5_uint32 *words = buffer; |
205 | 302 | size_t nwords = len / sizeof (md5_uint32); | |
206 | bytes_decode(in, (unsigned char *) cin, 64); | 303 | const md5_uint32 *endp = words + nwords; |
207 | 304 | md5_uint32 A = ctx->A; | |
208 | a = buf[0]; | 305 | md5_uint32 B = ctx->B; |
209 | b = buf[1]; | 306 | md5_uint32 C = ctx->C; |
210 | c = buf[2]; | 307 | md5_uint32 D = ctx->D; |
211 | d = buf[3]; | 308 | |
212 | 309 | /* First increment the byte count. RFC 1321 specifies the possible | |
213 | MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); | 310 | length of the file up to 2^64 bits. Here we only compute the |
214 | MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); | 311 | number of bytes. Do a double word increment. */ |
215 | MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); | 312 | ctx->total[0] += len; |
216 | MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); | 313 | if (ctx->total[0] < len) |
217 | MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); | 314 | ++ctx->total[1]; |
218 | MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); | 315 | |
219 | MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); | 316 | /* Process all bytes in the buffer with 64 bytes in each round of |
220 | MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); | 317 | the loop. */ |
221 | MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); | 318 | while (words < endp) |
222 | MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); | 319 | { |
223 | MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); | 320 | md5_uint32 *cwp = correct_words; |
224 | MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); | 321 | md5_uint32 A_save = A; |
225 | MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); | 322 | md5_uint32 B_save = B; |
226 | MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); | 323 | md5_uint32 C_save = C; |
227 | MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); | 324 | md5_uint32 D_save = D; |
228 | MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); | 325 | |
229 | 326 | /* First round: using the given function, the context and a constant | |
230 | MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); | 327 | the next context is computed. Because the algorithms processing |
231 | MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); | 328 | unit is a 32-bit word and it is determined to work on words in |
232 | MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); | 329 | little endian byte order we perhaps have to change the byte order |
233 | MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); | 330 | before the computation. To reduce the work for the next steps |
234 | MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); | 331 | we store the swapped words in the array CORRECT_WORDS. */ |
235 | MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); | 332 | |
236 | MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); | 333 | #define OP(a, b, c, d, s, T) \ |
237 | MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); | 334 | do \ |
238 | MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); | 335 | { \ |
239 | MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); | 336 | a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ |
240 | MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); | 337 | ++words; \ |
241 | MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); | 338 | a = rol (a, s); \ |
242 | MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); | 339 | a += b; \ |
243 | MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); | 340 | } \ |
244 | MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); | 341 | while (0) |
245 | MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); | 342 | |
246 | 343 | /* Before we start, one word to the strange constants. | |
247 | MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); | 344 | They are defined in RFC 1321 as |
248 | MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); | 345 | |
249 | MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); | 346 | T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64, or |
250 | MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); | 347 | perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' |
251 | MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); | 348 | */ |
252 | MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); | ||
253 | MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); | ||
254 | MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); | ||
255 | MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); | ||
256 | MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); | ||
257 | MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); | ||
258 | MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); | ||
259 | MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); | ||
260 | MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); | ||
261 | MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); | ||
262 | MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); | ||
263 | |||
264 | MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); | ||
265 | MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); | ||
266 | MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); | ||
267 | MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); | ||
268 | MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); | ||
269 | MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); | ||
270 | MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); | ||
271 | MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); | ||
272 | MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); | ||
273 | MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); | ||
274 | MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); | ||
275 | MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); | ||
276 | MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); | ||
277 | MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); | ||
278 | MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); | ||
279 | MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); | ||
280 | |||
281 | buf[0] += a; | ||
282 | buf[1] += b; | ||
283 | buf[2] += c; | ||
284 | buf[3] += d; | ||
285 | } | ||
286 | 349 | ||
287 | #endif | 350 | /* Round 1. */ |
288 | #endif /* MD5_CRYPT */ | 351 | OP (A, B, C, D, 7, 0xd76aa478); |
352 | OP (D, A, B, C, 12, 0xe8c7b756); | ||
353 | OP (C, D, A, B, 17, 0x242070db); | ||
354 | OP (B, C, D, A, 22, 0xc1bdceee); | ||
355 | OP (A, B, C, D, 7, 0xf57c0faf); | ||
356 | OP (D, A, B, C, 12, 0x4787c62a); | ||
357 | OP (C, D, A, B, 17, 0xa8304613); | ||
358 | OP (B, C, D, A, 22, 0xfd469501); | ||
359 | OP (A, B, C, D, 7, 0x698098d8); | ||
360 | OP (D, A, B, C, 12, 0x8b44f7af); | ||
361 | OP (C, D, A, B, 17, 0xffff5bb1); | ||
362 | OP (B, C, D, A, 22, 0x895cd7be); | ||
363 | OP (A, B, C, D, 7, 0x6b901122); | ||
364 | OP (D, A, B, C, 12, 0xfd987193); | ||
365 | OP (C, D, A, B, 17, 0xa679438e); | ||
366 | OP (B, C, D, A, 22, 0x49b40821); | ||
367 | |||
368 | /* For the second to fourth round we have the possibly swapped words | ||
369 | in CORRECT_WORDS. Redefine the macro to take an additional first | ||
370 | argument specifying the function to use. */ | ||
371 | #undef OP | ||
372 | #define OP(f, a, b, c, d, k, s, T) \ | ||
373 | do \ | ||
374 | { \ | ||
375 | a += f (b, c, d) + correct_words[k] + T; \ | ||
376 | a = rol (a, s); \ | ||
377 | a += b; \ | ||
378 | } \ | ||
379 | while (0) | ||
380 | |||
381 | /* Round 2. */ | ||
382 | OP (FG, A, B, C, D, 1, 5, 0xf61e2562); | ||
383 | OP (FG, D, A, B, C, 6, 9, 0xc040b340); | ||
384 | OP (FG, C, D, A, B, 11, 14, 0x265e5a51); | ||
385 | OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); | ||
386 | OP (FG, A, B, C, D, 5, 5, 0xd62f105d); | ||
387 | OP (FG, D, A, B, C, 10, 9, 0x02441453); | ||
388 | OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); | ||
389 | OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); | ||
390 | OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); | ||
391 | OP (FG, D, A, B, C, 14, 9, 0xc33707d6); | ||
392 | OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); | ||
393 | OP (FG, B, C, D, A, 8, 20, 0x455a14ed); | ||
394 | OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); | ||
395 | OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); | ||
396 | OP (FG, C, D, A, B, 7, 14, 0x676f02d9); | ||
397 | OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); | ||
398 | |||
399 | /* Round 3. */ | ||
400 | OP (FH, A, B, C, D, 5, 4, 0xfffa3942); | ||
401 | OP (FH, D, A, B, C, 8, 11, 0x8771f681); | ||
402 | OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); | ||
403 | OP (FH, B, C, D, A, 14, 23, 0xfde5380c); | ||
404 | OP (FH, A, B, C, D, 1, 4, 0xa4beea44); | ||
405 | OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); | ||
406 | OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); | ||
407 | OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); | ||
408 | OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); | ||
409 | OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); | ||
410 | OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); | ||
411 | OP (FH, B, C, D, A, 6, 23, 0x04881d05); | ||
412 | OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); | ||
413 | OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); | ||
414 | OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); | ||
415 | OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); | ||
416 | |||
417 | /* Round 4. */ | ||
418 | OP (FI, A, B, C, D, 0, 6, 0xf4292244); | ||
419 | OP (FI, D, A, B, C, 7, 10, 0x432aff97); | ||
420 | OP (FI, C, D, A, B, 14, 15, 0xab9423a7); | ||
421 | OP (FI, B, C, D, A, 5, 21, 0xfc93a039); | ||
422 | OP (FI, A, B, C, D, 12, 6, 0x655b59c3); | ||
423 | OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); | ||
424 | OP (FI, C, D, A, B, 10, 15, 0xffeff47d); | ||
425 | OP (FI, B, C, D, A, 1, 21, 0x85845dd1); | ||
426 | OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); | ||
427 | OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); | ||
428 | OP (FI, C, D, A, B, 6, 15, 0xa3014314); | ||
429 | OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); | ||
430 | OP (FI, A, B, C, D, 4, 6, 0xf7537e82); | ||
431 | OP (FI, D, A, B, C, 11, 10, 0xbd3af235); | ||
432 | OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); | ||
433 | OP (FI, B, C, D, A, 9, 21, 0xeb86d391); | ||
434 | |||
435 | /* Add the starting values of the context. */ | ||
436 | A += A_save; | ||
437 | B += B_save; | ||
438 | C += C_save; | ||
439 | D += D_save; | ||
440 | } | ||
441 | |||
442 | /* Put checksum in context given as argument. */ | ||
443 | ctx->A = A; | ||
444 | ctx->B = B; | ||
445 | ctx->C = C; | ||
446 | ctx->D = D; | ||
447 | } | ... | ... |
1 | #ifndef MD5_H | 1 | /* md5.h - Declaration of functions and data types used for MD5 sum |
2 | #define MD5_H | 2 | computing library functions. |
3 | 3 | ||
4 | #ifdef __alpha | 4 | Copyright (C) 1995, 1996, 1999, 2000, 2003, 2004 Free Software |
5 | typedef unsigned int uint32; | 5 | Foundation, Inc. |
6 | #else | 6 | |
7 | typedef unsigned long uint32; | 7 | NOTE: The canonical source of this file is maintained with the GNU C |
8 | Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. | ||
9 | |||
10 | This program is free software; you can redistribute it and/or modify it | ||
11 | under the terms of the GNU General Public License as published by the | ||
12 | Free Software Foundation; either version 2, or (at your option) any | ||
13 | later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with this program; if not, write to the Free Software Foundation, | ||
22 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
23 | |||
24 | #ifndef _MD5_H | ||
25 | #define _MD5_H 1 | ||
26 | |||
27 | #include <stdio.h> | ||
28 | |||
29 | #if HAVE_INTTYPES_H | ||
30 | # include <inttypes.h> | ||
31 | #endif | ||
32 | #if HAVE_STDINT_H || _LIBC | ||
33 | # include <stdint.h> | ||
8 | #endif | 34 | #endif |
9 | 35 | ||
10 | struct MD5Context { | 36 | typedef uint32_t md5_uint32; |
11 | uint32 buf[4]; | 37 | |
12 | uint32 bits[2]; | 38 | /* Structure to save state of computation between the single steps. */ |
13 | unsigned char in[64]; | 39 | struct md5_ctx |
40 | { | ||
41 | md5_uint32 A; | ||
42 | md5_uint32 B; | ||
43 | md5_uint32 C; | ||
44 | md5_uint32 D; | ||
45 | |||
46 | md5_uint32 total[2]; | ||
47 | md5_uint32 buflen; | ||
48 | char buffer[128]; | ||
14 | }; | 49 | }; |
15 | 50 | ||
16 | void MD5Init(struct MD5Context *context); | 51 | /* |
17 | void MD5Update(struct MD5Context *context, unsigned char const *buf, | 52 | * The following three functions are build up the low level used in |
18 | unsigned len); | 53 | * the functions `md5_stream' and `md5_buffer'. |
19 | void MD5Final(unsigned char digest[16], struct MD5Context *context); | 54 | */ |
20 | void MD5Transform(uint32 buf[4], uint32 const in[16]); | 55 | |
56 | /* Initialize structure containing state of computation. | ||
57 | (RFC 1321, 3.3: Step 3) */ | ||
58 | extern void md5_init_ctx (struct md5_ctx *ctx); | ||
21 | 59 | ||
22 | typedef struct MD5Context MD5_CTX; | 60 | /* Starting with the result of former calls of this function (or the |
61 | initialization function update the context for the next LEN bytes | ||
62 | starting at BUFFER. | ||
63 | It is necessary that LEN is a multiple of 64!!! */ | ||
64 | extern void md5_process_block (const void *buffer, size_t len, | ||
65 | struct md5_ctx *ctx); | ||
23 | 66 | ||
24 | #endif /* !MD5_H */ | 67 | /* Starting with the result of former calls of this function (or the |
68 | initialization function update the context for the next LEN bytes | ||
69 | starting at BUFFER. | ||
70 | It is NOT required that LEN is a multiple of 64. */ | ||
71 | extern void md5_process_bytes (const void *buffer, size_t len, | ||
72 | struct md5_ctx *ctx); | ||
73 | |||
74 | /* Process the remaining bytes in the buffer and put result from CTX | ||
75 | in first 16 bytes following RESBUF. The result is always in little | ||
76 | endian byte order, so that a byte-wise output yields to the wanted | ||
77 | ASCII representation of the message digest. | ||
78 | |||
79 | IMPORTANT: On some systems it is required that RESBUF be correctly | ||
80 | aligned for a 32 bits value. */ | ||
81 | extern void *md5_finish_ctx (struct md5_ctx *ctx, void *resbuf); | ||
82 | |||
83 | |||
84 | /* Put result from CTX in first 16 bytes following RESBUF. The result is | ||
85 | always in little endian byte order, so that a byte-wise output yields | ||
86 | to the wanted ASCII representation of the message digest. | ||
87 | |||
88 | IMPORTANT: On some systems it is required that RESBUF is correctly | ||
89 | aligned for a 32 bits value. */ | ||
90 | extern void *md5_read_ctx (const struct md5_ctx *ctx, void *resbuf); | ||
91 | |||
92 | |||
93 | /* Compute MD5 message digest for bytes read from STREAM. The | ||
94 | resulting message digest number will be written into the 16 bytes | ||
95 | beginning at RESBLOCK. */ | ||
96 | extern int md5_stream (FILE *stream, void *resblock); | ||
97 | |||
98 | /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The | ||
99 | result is always in little endian byte order, so that a byte-wise | ||
100 | output yields to the wanted ASCII representation of the message | ||
101 | digest. */ | ||
102 | extern void *md5_buffer (const char *buffer, size_t len, void *resblock); | ||
103 | |||
104 | #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) | ||
105 | |||
106 | #endif | ... | ... |
This diff could not be displayed because it is too large.
1 | /* Copyright (C) 1991,93,94,95,96,97,99,2000, 2001 Free Software Foundation, Inc. | 1 | /* Searching in a string. |
2 | Based on strlen implementation by Torbjorn Granlund (tege@sics.se), | 2 | Copyright (C) 2003 Free Software Foundation, Inc. |
3 | with help from Dan Sahlin (dan@sics.se) and | ||
4 | bug fix and commentary by Jim Blandy (jimb@ai.mit.edu); | ||
5 | adaptation to strchr suggested by Dick Karpinski (dick@cca.ucsf.edu), | ||
6 | and implemented by Roland McGrath (roland@ai.mit.edu). | ||
7 | 3 | ||
8 | The GNU C Library is free software; you can redistribute it and/or | 4 | This program is free software; you can redistribute it and/or modify |
9 | modify it under the terms of the GNU Library General Public License as | 5 | it under the terms of the GNU General Public License as published by |
10 | published by the Free Software Foundation; either version 2 of the | 6 | the Free Software Foundation; either version 2, or (at your option) |
11 | License, or (at your option) any later version. | 7 | any later version. |
12 | 8 | ||
13 | The GNU C Library is distributed in the hope that it will be useful, | 9 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | Library General Public License for more details. | 12 | GNU General Public License for more details. |
17 | 13 | ||
18 | You should have received a copy of the GNU Library General Public | 14 | You should have received a copy of the GNU General Public License |
19 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 15 | along with this program; if not, write to the Free Software Foundation, |
20 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 16 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
21 | Boston, MA 02111-1307, USA. */ | ||
22 | 17 | ||
23 | #include <string.h> | 18 | /* Specification. */ |
24 | #include <stdlib.h> | 19 | #include "strchrnul.h" |
25 | 20 | ||
26 | /* Find the first occurrence of C in S or the final NUL byte. */ | 21 | /* Find the first occurrence of C in S or the final NUL byte. */ |
27 | char * | 22 | char * |
28 | strchrnul (s, c_in) | 23 | strchrnul (const char *s, int c_in) |
29 | const char *s; | ||
30 | int c_in; | ||
31 | { | 24 | { |
32 | const char *char_ptr; | 25 | char c = c_in; |
33 | const unsigned long int *longword_ptr; | 26 | while (*s && (*s != c)) |
34 | unsigned long int longword, magic_bits, charmask; | 27 | s++; |
35 | unsigned char c; | ||
36 | 28 | ||
37 | c = (unsigned char) c_in; | 29 | return (char *) s; |
38 | |||
39 | /* Handle the first few characters by reading one character at a time. | ||
40 | Do this until CHAR_PTR is aligned on a longword boundary. */ | ||
41 | for (char_ptr = s; ((unsigned long int) char_ptr | ||
42 | & (sizeof (longword) - 1)) != 0; | ||
43 | ++char_ptr) | ||
44 | if (*char_ptr == c || *char_ptr == '\0') | ||
45 | return (void *) char_ptr; | ||
46 | |||
47 | /* All these elucidatory comments refer to 4-byte longwords, | ||
48 | but the theory applies equally well to 8-byte longwords. */ | ||
49 | |||
50 | longword_ptr = (unsigned long int *) char_ptr; | ||
51 | |||
52 | /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits | ||
53 | the "holes." Note that there is a hole just to the left of | ||
54 | each byte, with an extra at the end: | ||
55 | |||
56 | bits: 01111110 11111110 11111110 11111111 | ||
57 | bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD | ||
58 | |||
59 | The 1-bits make sure that carries propagate to the next 0-bit. | ||
60 | The 0-bits provide holes for carries to fall into. */ | ||
61 | switch (sizeof (longword)) | ||
62 | { | ||
63 | case 4: magic_bits = 0x7efefeffL; break; | ||
64 | case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break; | ||
65 | default: | ||
66 | abort (); | ||
67 | } | ||
68 | |||
69 | /* Set up a longword, each of whose bytes is C. */ | ||
70 | charmask = c | (c << 8); | ||
71 | charmask |= charmask << 16; | ||
72 | if (sizeof (longword) > 4) | ||
73 | /* Do the shift in two steps to avoid a warning if long has 32 bits. */ | ||
74 | charmask |= (charmask << 16) << 16; | ||
75 | if (sizeof (longword) > 8) | ||
76 | abort (); | ||
77 | |||
78 | /* Instead of the traditional loop which tests each character, | ||
79 | we will test a longword at a time. The tricky part is testing | ||
80 | if *any of the four* bytes in the longword in question are zero. */ | ||
81 | for (;;) | ||
82 | { | ||
83 | /* We tentatively exit the loop if adding MAGIC_BITS to | ||
84 | LONGWORD fails to change any of the hole bits of LONGWORD. | ||
85 | |||
86 | 1) Is this safe? Will it catch all the zero bytes? | ||
87 | Suppose there is a byte with all zeros. Any carry bits | ||
88 | propagating from its left will fall into the hole at its | ||
89 | least significant bit and stop. Since there will be no | ||
90 | carry from its most significant bit, the LSB of the | ||
91 | byte to the left will be unchanged, and the zero will be | ||
92 | detected. | ||
93 | |||
94 | 2) Is this worthwhile? Will it ignore everything except | ||
95 | zero bytes? Suppose every byte of LONGWORD has a bit set | ||
96 | somewhere. There will be a carry into bit 8. If bit 8 | ||
97 | is set, this will carry into bit 16. If bit 8 is clear, | ||
98 | one of bits 9-15 must be set, so there will be a carry | ||
99 | into bit 16. Similarly, there will be a carry into bit | ||
100 | 24. If one of bits 24-30 is set, there will be a carry | ||
101 | into bit 31, so all of the hole bits will be changed. | ||
102 | |||
103 | The one misfire occurs when bits 24-30 are clear and bit | ||
104 | 31 is set; in this case, the hole at bit 31 is not | ||
105 | changed. If we had access to the processor carry flag, | ||
106 | we could close this loophole by putting the fourth hole | ||
107 | at bit 32! | ||
108 | |||
109 | So it ignores everything except 128's, when they're aligned | ||
110 | properly. | ||
111 | |||
112 | 3) But wait! Aren't we looking for C as well as zero? | ||
113 | Good point. So what we do is XOR LONGWORD with a longword, | ||
114 | each of whose bytes is C. This turns each byte that is C | ||
115 | into a zero. */ | ||
116 | |||
117 | longword = *longword_ptr++; | ||
118 | |||
119 | /* Add MAGIC_BITS to LONGWORD. */ | ||
120 | if ((((longword + magic_bits) | ||
121 | |||
122 | /* Set those bits that were unchanged by the addition. */ | ||
123 | ^ ~longword) | ||
124 | |||
125 | /* Look at only the hole bits. If any of the hole bits | ||
126 | are unchanged, most likely one of the bytes was a | ||
127 | zero. */ | ||
128 | & ~magic_bits) != 0 || | ||
129 | |||
130 | /* That caught zeroes. Now test for C. */ | ||
131 | ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask)) | ||
132 | & ~magic_bits) != 0) | ||
133 | { | ||
134 | /* Which of the bytes was C or zero? | ||
135 | If none of them were, it was a misfire; continue the search. */ | ||
136 | |||
137 | const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); | ||
138 | |||
139 | if (*cp == c || *cp == '\0') | ||
140 | return (char *) cp; | ||
141 | if (*++cp == c || *cp == '\0') | ||
142 | return (char *) cp; | ||
143 | if (*++cp == c || *cp == '\0') | ||
144 | return (char *) cp; | ||
145 | if (*++cp == c || *cp == '\0') | ||
146 | return (char *) cp; | ||
147 | if (sizeof (longword) > 4) | ||
148 | { | ||
149 | if (*++cp == c || *cp == '\0') | ||
150 | return (char *) cp; | ||
151 | if (*++cp == c || *cp == '\0') | ||
152 | return (char *) cp; | ||
153 | if (*++cp == c || *cp == '\0') | ||
154 | return (char *) cp; | ||
155 | if (*++cp == c || *cp == '\0') | ||
156 | return (char *) cp; | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | |||
161 | /* This should never happen. */ | ||
162 | return NULL; | ||
163 | } | 30 | } | ... | ... |
1 | /* Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc. | 1 | /* Copyright (C) 1996, 1997, 1998, 2000, 2003 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. | ||
3 | 2 | ||
4 | The GNU C Library is free software; you can redistribute it and/or | 3 | NOTE: The canonical source of this file is maintained with the GNU C Library. |
5 | modify it under the terms of the GNU Library General Public License as | 4 | Bugs can be reported to bug-glibc@prep.ai.mit.edu. |
6 | published by the Free Software Foundation; either version 2 of the | ||
7 | License, or (at your option) any later version. | ||
8 | 5 | ||
9 | The GNU C Library is distributed in the hope that it will be useful, | 6 | This program is free software; you can redistribute it and/or modify it |
7 | under the terms of the GNU General Public License as published by the | ||
8 | Free Software Foundation; either version 2, or (at your option) any | ||
9 | later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | Library General Public License for more details. | 14 | GNU General Public License for more details. |
13 | 15 | ||
14 | You should have received a copy of the GNU Library General Public | 16 | You should have received a copy of the GNU General Public License |
15 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 17 | along with this program; if not, write to the Free Software Foundation, |
16 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
17 | Boston, MA 02111-1307, USA. */ | ||
18 | 19 | ||
19 | #ifdef HAVE_CONFIG_H | 20 | #ifdef HAVE_CONFIG_H |
20 | # include "config.h" | 21 | # include "config.h" |
21 | #endif | 22 | #endif |
22 | 23 | ||
23 | #include <stdio.h> | 24 | #include <stdlib.h> |
24 | #include <sys/types.h> | 25 | #include <string.h> |
26 | |||
27 | #ifndef HAVE_DECL_STRNLEN | ||
28 | "this configure-time declaration test was not run" | ||
29 | #endif | ||
30 | #if !HAVE_DECL_STRNLEN | ||
31 | size_t strnlen (); | ||
32 | #endif | ||
33 | |||
34 | #undef __strndup | ||
35 | #undef strndup | ||
25 | 36 | ||
26 | #if defined _LIBC || defined STDC_HEADERS | 37 | #ifndef weak_alias |
27 | # include <stdlib.h> | 38 | # define __strndup strndup |
28 | # include <string.h> | ||
29 | #else | ||
30 | char *malloc (); | ||
31 | #endif | 39 | #endif |
32 | 40 | ||
33 | char * | 41 | char * |
34 | strndup (s, n) | 42 | __strndup (const char *s, size_t n) |
35 | const char *s; | ||
36 | size_t n; | ||
37 | { | 43 | { |
38 | size_t len = strnlen (s, n); | 44 | size_t len = strnlen (s, n); |
39 | char *nouveau = malloc (len + 1); | 45 | char *new = malloc (len + 1); |
40 | 46 | ||
41 | if (nouveau == NULL) | 47 | if (new == NULL) |
42 | return NULL; | 48 | return NULL; |
43 | 49 | ||
44 | nouveau[len] = '\0'; | 50 | new[len] = '\0'; |
45 | return (char *) memcpy (nouveau, s, len); | 51 | return memcpy (new, s, len); |
46 | } | 52 | } |
53 | #ifdef weak_alias | ||
54 | weak_alias (__strndup, strndup) | ||
55 | #endif | ... | ... |
1 | /* Find the length of STRING, but scan at most MAXLEN characters. | 1 | /* Find the length of STRING, but scan at most MAXLEN characters. |
2 | Copyright (C) 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. | 2 | Copyright (C) 1996, 1997, 1998, 2000-2003 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. | 3 | This file is part of the GNU C Library. |
4 | 4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | 5 | This program is free software; you can redistribute it and/or modify |
6 | modify it under the terms of the GNU Library General Public License as | 6 | it under the terms of the GNU General Public License as published by |
7 | published by the Free Software Foundation; either version 2 of the | 7 | the Free Software Foundation; either version 2, or (at your option) |
8 | License, or (at your option) any later version. | 8 | any later version. |
9 | 9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | 10 | This program is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | Library General Public License for more details. | 13 | GNU General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU Library General Public | 15 | You should have received a copy of the GNU General Public License along |
16 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 16 | with this program; if not, write to the Free Software Foundation, |
17 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 17 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
18 | Boston, MA 02111-1307, USA. */ | 18 | |
19 | #if HAVE_CONFIG_H | ||
20 | # include <config.h> | ||
21 | #endif | ||
22 | #undef strnlen | ||
19 | 23 | ||
20 | #include <string.h> | 24 | #include <string.h> |
21 | 25 | ||
26 | #undef __strnlen | ||
27 | #undef strnlen | ||
28 | |||
29 | #ifndef _LIBC | ||
30 | # define strnlen rpl_strnlen | ||
31 | #endif | ||
32 | |||
33 | #ifndef weak_alias | ||
34 | # define __strnlen strnlen | ||
35 | #endif | ||
36 | |||
22 | /* Find the length of STRING, but scan at most MAXLEN characters. | 37 | /* Find the length of STRING, but scan at most MAXLEN characters. |
23 | If no '\0' terminator is found in that many characters, return MAXLEN. */ | 38 | If no '\0' terminator is found in that many characters, return MAXLEN. */ |
24 | 39 | ||
25 | size_t | 40 | size_t |
26 | strnlen (const char *string, size_t maxlen) | 41 | __strnlen (const char *string, size_t maxlen) |
27 | { | 42 | { |
28 | const char *end = memchr (string, '\0', maxlen); | 43 | const char *end = memchr (string, '\0', maxlen); |
29 | return end ? (size_t) (end - string) : maxlen; | 44 | return end ? (size_t) (end - string) : maxlen; |
30 | } | 45 | } |
46 | #ifdef weak_alias | ||
47 | weak_alias (__strnlen, strnlen) | ||
48 | #endif | ... | ... |
1 | /* Reentrant string tokenizer. Generic version. | 1 | /* Reentrant string tokenizer. Generic version. |
2 | Copyright (C) 1991, 1996, 1997, 1998, 1999, 2001 Free Software Foundation, Inc. | 2 | Copyright (C) 1991,1996-1999,2001,2004 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. | 3 | This file is part of the GNU C Library. |
4 | 4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | 5 | This program is free software; you can redistribute it and/or modify |
6 | modify it under the terms of the GNU Library General Public License as | 6 | it under the terms of the GNU General Public License as published by |
7 | published by the Free Software Foundation; either version 2 of the | 7 | the Free Software Foundation; either version 2, or (at your option) |
8 | License, or (at your option) any later version. | 8 | any later version. |
9 | 9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | 10 | This program is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | Library General Public License for more details. | 13 | GNU General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU Library General Public | 15 | You should have received a copy of the GNU General Public License along |
16 | License along with the GNU C Library; see the file COPYING.LIB. If not, | 16 | with this program; if not, write to the Free Software Foundation, |
17 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 17 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
18 | Boston, MA 02111-1307, USA. */ | 18 | |
19 | #ifdef HAVE_CONFIG_H | ||
20 | # include <config.h> | ||
21 | #endif | ||
19 | 22 | ||
20 | #include <string.h> | 23 | #include <string.h> |
21 | 24 | ||
25 | #undef strtok_r | ||
26 | #undef __strtok_r | ||
27 | |||
28 | #ifndef _LIBC | ||
29 | /* Get specification. */ | ||
30 | # include "strtok_r.h" | ||
31 | # define __strtok_r strtok_r | ||
32 | # define __rawmemchr strchr | ||
33 | #endif | ||
34 | |||
22 | /* Parse S into tokens separated by characters in DELIM. | 35 | /* Parse S into tokens separated by characters in DELIM. |
23 | If S is NULL, the saved pointer in SAVE_PTR is used as | 36 | If S is NULL, the saved pointer in SAVE_PTR is used as |
24 | the next starting point. For example: | 37 | the next starting point. For example: |
... | @@ -30,10 +43,7 @@ | ... | @@ -30,10 +43,7 @@ |
30 | // s = "abc\0-def\0" | 43 | // s = "abc\0-def\0" |
31 | */ | 44 | */ |
32 | char * | 45 | char * |
33 | strtok_r (s, delim, save_ptr) | 46 | __strtok_r (char *s, const char *delim, char **save_ptr) |
34 | char *s; | ||
35 | const char *delim; | ||
36 | char **save_ptr; | ||
37 | { | 47 | { |
38 | char *token; | 48 | char *token; |
39 | 49 | ||
... | @@ -53,8 +63,7 @@ strtok_r (s, delim, save_ptr) | ... | @@ -53,8 +63,7 @@ strtok_r (s, delim, save_ptr) |
53 | s = strpbrk (token, delim); | 63 | s = strpbrk (token, delim); |
54 | if (s == NULL) | 64 | if (s == NULL) |
55 | /* This token finishes the string. */ | 65 | /* This token finishes the string. */ |
56 | /* *save_ptr = __rawmemchr (token, '\0'); */ | 66 | *save_ptr = __rawmemchr (token, '\0'); |
57 | *save_ptr = token + strlen (token); | ||
58 | else | 67 | else |
59 | { | 68 | { |
60 | /* Terminate the token and make *SAVE_PTR point past it. */ | 69 | /* Terminate the token and make *SAVE_PTR point past it. */ |
... | @@ -63,4 +72,7 @@ strtok_r (s, delim, save_ptr) | ... | @@ -63,4 +72,7 @@ strtok_r (s, delim, save_ptr) |
63 | } | 72 | } |
64 | return token; | 73 | return token; |
65 | } | 74 | } |
66 | /* weak_alias (__strtok_r, strtok_r) */ | 75 | #ifdef weak_alias |
76 | libc_hidden_def (__strtok_r) | ||
77 | weak_alias (__strtok_r, strtok_r) | ||
78 | #endif | ... | ... |
-
Please register or sign in to post a comment