File: | build/../misc.c |
Location: | line 276, column 18 |
Description: | Array access (from variable 'buf') results in a null pointer dereference |
1 | ||||
2 | /* | |||
3 | * $Id$ | |||
4 | * | |||
5 | * by JH <jheinonen@users.sourceforge.net> | |||
6 | * | |||
7 | * Copyright (C) Jaakko Heinonen | |||
8 | * getaline() Copyright (C) Lars Wirzenius | |||
9 | * sprintf and snprintf copyright is owned by various people | |||
10 | */ | |||
11 | ||||
12 | #include <stdio.h> | |||
13 | #include <string.h> | |||
14 | #include <stdlib.h> | |||
15 | #include <ctype.h> | |||
16 | #include <unistd.h> | |||
17 | #include <errno(*__errno_location ()).h> | |||
18 | #ifdef HAVE_CONFIG_H1 | |||
19 | # include "config.h" | |||
20 | #endif | |||
21 | #include <mbswidthgnu_mbswidth.h> | |||
22 | #include "abook.h" | |||
23 | #include "misc.h" | |||
24 | #include "xmalloc.h" | |||
25 | ||||
26 | #ifndef DEBUG | |||
27 | # define NDEBUG1 1 | |||
28 | #else | |||
29 | # undef NDEBUG1 | |||
30 | #endif | |||
31 | ||||
32 | #include <assert.h> | |||
33 | ||||
34 | char * | |||
35 | strlower(char *str) | |||
36 | { | |||
37 | char *tmp = str; | |||
38 | ||||
39 | assert(str != NULL)((void) (0)); | |||
40 | ||||
41 | while( ( *str = tolower ( *str )(__extension__ ({ int __res; if (sizeof (*str) > 1) { if ( __builtin_constant_p (*str)) { int __c = (*str); __res = __c < -128 || __c > 255 ? __c : (*__ctype_tolower_loc ())[__c]; } else __res = tolower (*str); } else __res = (*__ctype_tolower_loc ())[(int) (*str)]; __res; })) ) ) | |||
42 | str++; | |||
43 | ||||
44 | return tmp; | |||
45 | } | |||
46 | ||||
47 | char * | |||
48 | strtrim(char *s) | |||
49 | { | |||
50 | char *t, *tt; | |||
51 | ||||
52 | assert(s != NULL)((void) (0)); | |||
53 | ||||
54 | for(t = s; isspace(*t)((*__ctype_b_loc ())[(int) ((*t))] & (unsigned short int) _ISspace); t++); | |||
55 | ||||
56 | memmove(s, t, strlen(t)+1); | |||
57 | ||||
58 | for (tt = t = s; *t != '\0'; t++) | |||
59 | if(!isspace(*t)((*__ctype_b_loc ())[(int) ((*t))] & (unsigned short int) _ISspace)) | |||
60 | tt = t+1; | |||
61 | ||||
62 | *tt = '\0'; | |||
63 | ||||
64 | return s; | |||
65 | } | |||
66 | ||||
67 | int | |||
68 | is_number(char *p) | |||
69 | { | |||
70 | if(!p || !*p || (*p == '-' && !*++p)) | |||
71 | return 0; | |||
72 | ||||
73 | for(; *p; p++) | |||
74 | if(!isdigit(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int) _ISdigit)) | |||
75 | return 0; | |||
76 | ||||
77 | return 1; | |||
78 | } | |||
79 | ||||
80 | #ifndef HAVE_STRCASESTR1 | |||
81 | char * | |||
82 | strcasestr(const char *haystack, const char *needle) | |||
83 | { | |||
84 | int i; | |||
85 | int k; | |||
86 | ||||
87 | assert(haystack != NULL)((void) (0)); | |||
88 | assert(needle != NULL)((void) (0)); | |||
89 | ||||
90 | for(i=0; i<strlen(haystack)-strlen(needle)+1; i++) { | |||
91 | for(k=0; k<strlen(needle); k++, i++) { | |||
92 | if (tolower(haystack[i])(__extension__ ({ int __res; if (sizeof (haystack[i]) > 1) { if (__builtin_constant_p (haystack[i])) { int __c = (haystack [i]); __res = __c < -128 || __c > 255 ? __c : (*__ctype_tolower_loc ())[__c]; } else __res = tolower (haystack[i]); } else __res = (*__ctype_tolower_loc ())[(int) (haystack[i])]; __res; })) != tolower(needle[k])(__extension__ ({ int __res; if (sizeof (needle[k]) > 1) { if (__builtin_constant_p (needle[k])) { int __c = (needle[k] ); __res = __c < -128 || __c > 255 ? __c : (*__ctype_tolower_loc ())[__c]; } else __res = tolower (needle[k]); } else __res = (*__ctype_tolower_loc ())[(int) (needle[k])]; __res; }))) | |||
93 | break; | |||
94 | else if ((k+1) == strlen(needle)) | |||
95 | return &haystack[i]; | |||
96 | } | |||
97 | } | |||
98 | ||||
99 | return NULL((void*)0); | |||
100 | } | |||
101 | #endif | |||
102 | ||||
103 | #ifdef HAVE_CONFIG_H1 | |||
104 | # include "config.h" | |||
105 | #endif | |||
106 | ||||
107 | /* varargs declarations: */ | |||
108 | ||||
109 | #ifdef HAVE_STDARG_H1 | |||
110 | # define MY_VA_LOCAL_DECLva_list ap va_list ap | |||
111 | # define MY_VA_START(f)__builtin_va_start(ap, f) va_start(ap, f)__builtin_va_start(ap, f) | |||
112 | # define MY_VA_SHIFT(v,t)v = __builtin_va_arg(ap, t) v = va_arg(ap, t)__builtin_va_arg(ap, t) | |||
113 | # define MY_VA_END__builtin_va_end(ap) va_end(ap)__builtin_va_end(ap) | |||
114 | #else | |||
115 | # error HAVE_STDARG_H1 not defined | |||
116 | #endif | |||
117 | ||||
118 | char * | |||
119 | strdup_printf (const char *format, ... ) | |||
120 | { | |||
121 | MY_VA_LOCAL_DECLva_list ap; | |||
122 | size_t size = 100; | |||
123 | char *buffer = xmalloc_xmalloc_xmalloc (size); | |||
124 | ||||
125 | assert(format != NULL)((void) (0)); | |||
126 | ||||
127 | for(;;) { | |||
128 | int n; | |||
129 | MY_VA_START(format)__builtin_va_start(ap, format); | |||
130 | n = vsnprintf (buffer, size, | |||
131 | format, ap); | |||
132 | MY_VA_END__builtin_va_end(ap); | |||
133 | ||||
134 | if (n > -1 && n < size) | |||
135 | return buffer; | |||
136 | ||||
137 | if (n > -1) | |||
138 | size = n + 1; | |||
139 | else | |||
140 | size *= 2; | |||
141 | ||||
142 | buffer = xrealloc_xmalloc_xrealloc(buffer, size); | |||
143 | } | |||
144 | } | |||
145 | ||||
146 | ||||
147 | char* | |||
148 | strconcat (const char *str, ...) | |||
149 | { | |||
150 | unsigned long l; | |||
151 | MY_VA_LOCAL_DECLva_list ap; | |||
152 | char *s, *concat; | |||
153 | ||||
154 | assert(str != NULL)((void) (0)); | |||
155 | ||||
156 | l = 1 + strlen (str); | |||
157 | MY_VA_START(str)__builtin_va_start(ap, str); | |||
158 | MY_VA_SHIFT(s, char*)s = __builtin_va_arg(ap, char*); | |||
159 | while (s) { | |||
160 | l += strlen (s); | |||
161 | MY_VA_SHIFT(s, char*)s = __builtin_va_arg(ap, char*); | |||
162 | } | |||
163 | MY_VA_END__builtin_va_end(ap); | |||
164 | ||||
165 | concat = xmalloc_xmalloc_xmalloc(l); | |||
166 | ||||
167 | strcpy (concat, str); | |||
168 | MY_VA_START(str)__builtin_va_start(ap, str); | |||
169 | MY_VA_SHIFT(s, char*)s = __builtin_va_arg(ap, char*); | |||
170 | while (s) { | |||
171 | strcat (concat, s); | |||
172 | MY_VA_SHIFT(s, char*)s = __builtin_va_arg(ap, char*); | |||
173 | } | |||
174 | MY_VA_END__builtin_va_end(ap); | |||
175 | ||||
176 | return concat; | |||
177 | } | |||
178 | ||||
179 | ||||
180 | int | |||
181 | safe_strcmp(const char *s1, const char *s2) | |||
182 | { | |||
183 | if (s1 == NULL((void*)0) && s2 == NULL((void*)0)) return 0; | |||
184 | if (s1 == NULL((void*)0)) return -1; | |||
185 | if (s2 == NULL((void*)0)) return 1; | |||
186 | ||||
187 | return strcmp(s1, s2)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (s1) && __builtin_constant_p (s2) && (__s1_len = strlen (s1), __s2_len = strlen (s2), (!((size_t)(const void *)((s1) + 1) - (size_t)(const void *)(s1) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((s2) + 1) - (size_t) (const void *)(s2) == 1) || __s2_len >= 4)) ? __builtin_strcmp (s1, s2) : (__builtin_constant_p (s1) && ((size_t)(const void *)((s1) + 1) - (size_t)(const void *)(s1) == 1) && (__s1_len = strlen (s1), __s1_len < 4) ? (__builtin_constant_p (s2) && ((size_t)(const void *)((s2) + 1) - (size_t) (const void *)(s2) == 1) ? __builtin_strcmp (s1, s2) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (s2); int __result = (((const unsigned char *) (const char *) (s1))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ( s1))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (s1 ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (s1))[3 ] - __s2[3]); } } __result; }))) : (__builtin_constant_p (s2) && ((size_t)(const void *)((s2) + 1) - (size_t)(const void *)(s2) == 1) && (__s2_len = strlen (s2), __s2_len < 4) ? (__builtin_constant_p (s1) && ((size_t)(const void *)((s1) + 1) - (size_t)(const void *)(s1) == 1) ? __builtin_strcmp (s1, s2) : (- (__extension__ ({ const unsigned char *__s2 = ( const unsigned char *) (const char *) (s1); int __result = (( (const unsigned char *) (const char *) (s2))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (s2))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (s2))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (s2))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (s1, s2)))); }); | |||
188 | } | |||
189 | ||||
190 | int | |||
191 | safe_strcoll(const char *s1, const char *s2) | |||
192 | { | |||
193 | #ifdef HAVE_STRCOLL1 | |||
194 | if (s1 == NULL((void*)0) && s2 == NULL((void*)0)) return 0; | |||
195 | if (s1 == NULL((void*)0)) return -1; | |||
196 | if (s2 == NULL((void*)0)) return 1; | |||
197 | ||||
198 | return strcoll(s1, s2); | |||
199 | #else /* fall back to strcmp */ | |||
200 | return safe_strcmp(s1, s2); | |||
201 | #endif | |||
202 | } | |||
203 | ||||
204 | char * | |||
205 | my_getcwd() | |||
206 | { | |||
207 | char *dir = NULL((void*)0); | |||
208 | size_t size = 100; | |||
209 | ||||
210 | if( (dir = xmalloc_xmalloc_xmalloc(size)) == NULL((void*)0)) | |||
211 | return NULL((void*)0); | |||
212 | ||||
213 | *dir = 0; | |||
214 | ||||
215 | while( getcwd(dir, size) == NULL((void*)0) && errno(*__errno_location ()) == ERANGE34 ) | |||
216 | if( (dir = xrealloc_xmalloc_xrealloc(dir, size *=2)) == NULL((void*)0)) | |||
217 | return NULL((void*)0); | |||
218 | ||||
219 | return dir; | |||
220 | } | |||
221 | ||||
222 | /* | |||
223 | * getaline() | |||
224 | * | |||
225 | * Copyright (c) 1994 Lars Wirzenius | |||
226 | * All rights reserved. | |||
227 | * | |||
228 | * Redistribution and use in source and binary forms, with or without | |||
229 | * modification, are permitted provided that the following conditions | |||
230 | * are met: | |||
231 | * 1. Redistributions of source code must retain the above copyright | |||
232 | * notice, this list of conditions and the following disclaimer | |||
233 | * in this position and unchanged. | |||
234 | * 2. Redistributions in binary form must reproduce the above copyright | |||
235 | * notice, this list of conditions and the following disclaimer in the | |||
236 | * documentation and/or other materials provided with the distribution. | |||
237 | * | |||
238 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR | |||
239 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
240 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
241 | * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
242 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
243 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
244 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
245 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
246 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
247 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
248 | */ | |||
249 | ||||
250 | char * | |||
251 | getaline(FILE *f) | |||
252 | { | |||
253 | char *buf; /* buffer for line */ | |||
254 | size_t size; /* size of buffer */ | |||
255 | size_t inc; /* how much to enlarge buffer */ | |||
256 | size_t len; /* # of chars stored into buf before '\0' */ | |||
257 | char *p; | |||
258 | const size_t thres = 128; /* initial buffer size (most lines should | |||
259 | fit into this size, so think of this as | |||
260 | the "long line threshold"). */ | |||
261 | const size_t mucho = 128; /* if there is at least this much wasted | |||
262 | space when the whole buffer has been | |||
263 | read, try to reclaim it. Don't make | |||
264 | this too small, else there is too much | |||
265 | time wasted trying to reclaim a couple | |||
266 | of bytes. */ | |||
267 | const size_t mininc = 64; /* minimum number of bytes by which | |||
268 | to increase the allocated memory */ | |||
269 | ||||
270 | len = 0; | |||
271 | size = thres; | |||
272 | buf = xmalloc_xmalloc_xmalloc(size); | |||
273 | ||||
274 | while (fgets(buf+len, size-len, f) != NULL((void*)0)) { | |||
| ||||
275 | len += strlen(buf+len); | |||
276 | if (len > 0 && buf[len-1] == '\n') | |||
| ||||
277 | break; /* the whole line has been read */ | |||
278 | ||||
279 | for (inc = size, p = NULL((void*)0); inc > mininc; inc /= 2) | |||
280 | if ((p = xrealloc_inc(buf, size, inc)) != | |||
281 | NULL((void*)0)) | |||
282 | break; | |||
283 | ||||
284 | size += inc; | |||
285 | buf = p; | |||
286 | } | |||
287 | ||||
288 | if (len == 0) { | |||
289 | xfree(buf)do { free(buf); buf = ((void*)0); } while(0); | |||
290 | return NULL((void*)0); /* nothing read (eof or error) */ | |||
291 | } | |||
292 | ||||
293 | if (buf[len-1] == '\n') /* remove newline, if there */ | |||
294 | buf[--len] = '\0'; | |||
295 | ||||
296 | if (size - len > mucho) { /* a plenitude of unused memory? */ | |||
297 | p = xrealloc_inc(buf, len, 1); | |||
298 | if (p != NULL((void*)0)) { | |||
299 | buf = p; | |||
300 | size = len+1; | |||
301 | } | |||
302 | } | |||
303 | ||||
304 | return buf; | |||
305 | } | |||
306 | ||||
307 | int | |||
308 | strwidth(const char *s) | |||
309 | { | |||
310 | assert(s)((void) (0)); | |||
311 | return mbswidthgnu_mbswidth(s, 0); | |||
312 | } | |||
313 | ||||
314 | int | |||
315 | bytes2width(const char *s, int width) | |||
316 | { | |||
317 | assert(s)((void) (0)); | |||
318 | #ifdef HANDLE_MULTIBYTE1 | |||
319 | return mbsnbytes(s, strlen(s), width, 0); | |||
320 | #else | |||
321 | return width; | |||
322 | #endif | |||
323 | } | |||
324 | ||||
325 | /************************************************************** | |||
326 | * Original: | |||
327 | * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 | |||
328 | * A bombproof version of doprnt (dopr) included. | |||
329 | * Sigh. This sort of thing is always nasty do deal with. Note that | |||
330 | * the version here does not include floating point... | |||
331 | * | |||
332 | * snprintf() is used instead of sprintf() as it does limit checks | |||
333 | * for string length. This covers a nasty loophole. | |||
334 | * | |||
335 | * The other functions are there to prevent NULL pointers from | |||
336 | * causing nast effects. | |||
337 | * | |||
338 | * More Recently: | |||
339 | * Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43 | |||
340 | * This was ugly. It is still ugly. I opted out of floating point | |||
341 | * numbers, but the formatter understands just about everything | |||
342 | * from the normal C string format, at least as far as I can tell from | |||
343 | * the Solaris 2.5 printf(3S) man page. | |||
344 | * | |||
345 | * Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1 | |||
346 | * Ok, added some minimal floating point support, which means this | |||
347 | * probably requires libm on most operating systems. Don't yet | |||
348 | * support the exponent (e,E) and sigfig (g,G). Also, fmtint() | |||
349 | * was pretty badly broken, it just wasn't being exercised in ways | |||
350 | * which showed it, so that's been fixed. Also, formated the code | |||
351 | * to mutt conventions, and removed dead code left over from the | |||
352 | * original. Also, there is now a builtin-test, just compile with: | |||
353 | * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm | |||
354 | * and run snprintf for results. | |||
355 | * | |||
356 | * Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i | |||
357 | * The PGP code was using unsigned hexadecimal formats. | |||
358 | * Unfortunately, unsigned formats simply didn't work. | |||
359 | * | |||
360 | * Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8 | |||
361 | * The original code assumed that both snprintf() and vsnprintf() were | |||
362 | * missing. Some systems only have snprintf() but not vsnprintf(), so | |||
363 | * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. | |||
364 | * | |||
365 | **************************************************************/ | |||
366 | ||||
367 | #include "config.h" | |||
368 | ||||
369 | #if !defined(HAVE_SNPRINTF1) || !defined(HAVE_VSNPRINTF1) | |||
370 | ||||
371 | #include <string.h> | |||
372 | # include <ctype.h> | |||
373 | #include <sys/types.h> | |||
374 | ||||
375 | /* Define this as a fall through, HAVE_STDARG_H is probably already set */ | |||
376 | ||||
377 | #if !defined(HAVE_STDARG_H1) && !defined(HAVE_VARARGS_H) | |||
378 | # define HAVE_VARARGS_H 1 | |||
379 | #endif | |||
380 | ||||
381 | /* varargs declarations: */ | |||
382 | ||||
383 | #if defined(HAVE_STDARG_H1) | |||
384 | /*# include <stdarg.h>*/ | |||
385 | # define HAVE_STDARGS /* let's hope that works everywhere (mj) */ | |||
386 | # define VA_LOCAL_DECL va_list ap | |||
387 | # define VA_START(f) va_start(ap, f)__builtin_va_start(ap, f) | |||
388 | # define VA_SHIFT(v,t) ; /* no-op for ANSI */ | |||
389 | # define VA_END va_end(ap)__builtin_va_end(ap) | |||
390 | #else | |||
391 | # if defined(HAVE_VARARGS_H) | |||
392 | # include <varargs.h> | |||
393 | # undef HAVE_STDARGS | |||
394 | # define VA_LOCAL_DECL va_list ap | |||
395 | # define VA_START(f) va_start(ap) /* f is ignored! */ | |||
396 | # define VA_SHIFT(v,t) v = va_arg(ap,t)__builtin_va_arg(ap, t) | |||
397 | # define VA_END va_end(ap)__builtin_va_end(ap) | |||
398 | # else | |||
399 | /*XX ** NO VARARGS ** XX*/ | |||
400 | # endif | |||
401 | #endif | |||
402 | ||||
403 | /*int snprintf (char *str, size_t count, const char *fmt, ...);*/ | |||
404 | /*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/ | |||
405 | ||||
406 | static void dopr (char *buffer, size_t maxlen, const char *format, | |||
407 | va_list args); | |||
408 | static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, | |||
409 | char *value, int flags, int min, int max); | |||
410 | static void fmtint (char *buffer, size_t *currlen, size_t maxlen, | |||
411 | long value, int base, int min, int max, int flags); | |||
412 | static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, | |||
413 | long double fvalue, int min, int max, int flags); | |||
414 | static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c ); | |||
415 | ||||
416 | /* | |||
417 | * dopr(): poor man's version of doprintf | |||
418 | */ | |||
419 | ||||
420 | /* format read states */ | |||
421 | #define DP_S_DEFAULT 0 | |||
422 | #define DP_S_FLAGS 1 | |||
423 | #define DP_S_MIN 2 | |||
424 | #define DP_S_DOT 3 | |||
425 | #define DP_S_MAX 4 | |||
426 | #define DP_S_MOD 5 | |||
427 | #define DP_S_CONV 6 | |||
428 | #define DP_S_DONE 7 | |||
429 | ||||
430 | /* format flags - Bits */ | |||
431 | #define DP_F_MINUS (1 << 0) | |||
432 | #define DP_F_PLUS (1 << 1) | |||
433 | #define DP_F_SPACE (1 << 2) | |||
434 | #define DP_F_NUM (1 << 3) | |||
435 | #define DP_F_ZERO (1 << 4) | |||
436 | #define DP_F_UP (1 << 5) | |||
437 | #define DP_F_UNSIGNED (1 << 6) | |||
438 | ||||
439 | /* Conversion Flags */ | |||
440 | #define DP_C_SHORT 1 | |||
441 | #define DP_C_LONG 2 | |||
442 | #define DP_C_LDOUBLE 3 | |||
443 | ||||
444 | #define char_to_int(p) (p - '0') | |||
445 | #define MAX(p,q) ((p >= q) ? p : q) | |||
446 | ||||
447 | static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) | |||
448 | { | |||
449 | char ch; | |||
450 | long value; | |||
451 | long double fvalue; | |||
452 | char *strvalue; | |||
453 | int min; | |||
454 | int max; | |||
455 | int state; | |||
456 | int flags; | |||
457 | int cflags; | |||
458 | size_t currlen; | |||
459 | ||||
460 | state = DP_S_DEFAULT; | |||
461 | currlen = flags = cflags = min = 0; | |||
462 | max = -1; | |||
463 | ch = *format++; | |||
464 | ||||
465 | while (state != DP_S_DONE) | |||
466 | { | |||
467 | if ((ch == '\0') || (currlen >= maxlen)) | |||
468 | state = DP_S_DONE; | |||
469 | ||||
470 | switch(state) | |||
471 | { | |||
472 | case DP_S_DEFAULT: | |||
473 | if (ch == '%') | |||
474 | state = DP_S_FLAGS; | |||
475 | else | |||
476 | dopr_outch (buffer, &currlen, maxlen, ch); | |||
477 | ch = *format++; | |||
478 | break; | |||
479 | case DP_S_FLAGS: | |||
480 | switch (ch) | |||
481 | { | |||
482 | case '-': | |||
483 | flags |= DP_F_MINUS; | |||
484 | ch = *format++; | |||
485 | break; | |||
486 | case '+': | |||
487 | flags |= DP_F_PLUS; | |||
488 | ch = *format++; | |||
489 | break; | |||
490 | case ' ': | |||
491 | flags |= DP_F_SPACE; | |||
492 | ch = *format++; | |||
493 | break; | |||
494 | case '#': | |||
495 | flags |= DP_F_NUM; | |||
496 | ch = *format++; | |||
497 | break; | |||
498 | case '0': | |||
499 | flags |= DP_F_ZERO; | |||
500 | ch = *format++; | |||
501 | break; | |||
502 | default: | |||
503 | state = DP_S_MIN; | |||
504 | break; | |||
505 | } | |||
506 | break; | |||
507 | case DP_S_MIN: | |||
508 | if (isdigit((unsigned char)ch)((*__ctype_b_loc ())[(int) (((unsigned char)ch))] & (unsigned short int) _ISdigit)) | |||
509 | { | |||
510 | min = 10*min + char_to_int (ch); | |||
511 | ch = *format++; | |||
512 | } | |||
513 | else if (ch == '*') | |||
514 | { | |||
515 | min = va_arg (args, int)__builtin_va_arg(args, int); | |||
516 | ch = *format++; | |||
517 | state = DP_S_DOT; | |||
518 | } | |||
519 | else | |||
520 | state = DP_S_DOT; | |||
521 | break; | |||
522 | case DP_S_DOT: | |||
523 | if (ch == '.') | |||
524 | { | |||
525 | state = DP_S_MAX; | |||
526 | ch = *format++; | |||
527 | } | |||
528 | else | |||
529 | state = DP_S_MOD; | |||
530 | break; | |||
531 | case DP_S_MAX: | |||
532 | if (isdigit((unsigned char)ch)((*__ctype_b_loc ())[(int) (((unsigned char)ch))] & (unsigned short int) _ISdigit)) | |||
533 | { | |||
534 | if (max < 0) | |||
535 | max = 0; | |||
536 | max = 10*max + char_to_int (ch); | |||
537 | ch = *format++; | |||
538 | } | |||
539 | else if (ch == '*') | |||
540 | { | |||
541 | max = va_arg (args, int)__builtin_va_arg(args, int); | |||
542 | ch = *format++; | |||
543 | state = DP_S_MOD; | |||
544 | } | |||
545 | else | |||
546 | state = DP_S_MOD; | |||
547 | break; | |||
548 | case DP_S_MOD: | |||
549 | /* Currently, we don't support Long Long, bummer */ | |||
550 | switch (ch) | |||
551 | { | |||
552 | case 'h': | |||
553 | cflags = DP_C_SHORT; | |||
554 | ch = *format++; | |||
555 | break; | |||
556 | case 'l': | |||
557 | cflags = DP_C_LONG; | |||
558 | ch = *format++; | |||
559 | break; | |||
560 | case 'L': | |||
561 | cflags = DP_C_LDOUBLE; | |||
562 | ch = *format++; | |||
563 | break; | |||
564 | default: | |||
565 | break; | |||
566 | } | |||
567 | state = DP_S_CONV; | |||
568 | break; | |||
569 | case DP_S_CONV: | |||
570 | switch (ch) | |||
571 | { | |||
572 | case 'd': | |||
573 | case 'i': | |||
574 | if (cflags == DP_C_SHORT) | |||
575 | value = va_arg (args, short int)__builtin_va_arg(args, short int); | |||
576 | else if (cflags == DP_C_LONG) | |||
577 | value = va_arg (args, long int)__builtin_va_arg(args, long int); | |||
578 | else | |||
579 | value = va_arg (args, int)__builtin_va_arg(args, int); | |||
580 | fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); | |||
581 | break; | |||
582 | case 'o': | |||
583 | flags |= DP_F_UNSIGNED; | |||
584 | if (cflags == DP_C_SHORT) | |||
585 | value = va_arg (args, unsigned short int)__builtin_va_arg(args, unsigned short int); | |||
586 | else if (cflags == DP_C_LONG) | |||
587 | value = va_arg (args, unsigned long int)__builtin_va_arg(args, unsigned long int); | |||
588 | else | |||
589 | value = va_arg (args, unsigned int)__builtin_va_arg(args, unsigned int); | |||
590 | fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); | |||
591 | break; | |||
592 | case 'u': | |||
593 | flags |= DP_F_UNSIGNED; | |||
594 | if (cflags == DP_C_SHORT) | |||
595 | value = va_arg (args, unsigned short int)__builtin_va_arg(args, unsigned short int); | |||
596 | else if (cflags == DP_C_LONG) | |||
597 | value = va_arg (args, unsigned long int)__builtin_va_arg(args, unsigned long int); | |||
598 | else | |||
599 | value = va_arg (args, unsigned int)__builtin_va_arg(args, unsigned int); | |||
600 | fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); | |||
601 | break; | |||
602 | case 'X': | |||
603 | flags |= DP_F_UP; | |||
604 | case 'x': | |||
605 | flags |= DP_F_UNSIGNED; | |||
606 | if (cflags == DP_C_SHORT) | |||
607 | value = va_arg (args, unsigned short int)__builtin_va_arg(args, unsigned short int); | |||
608 | else if (cflags == DP_C_LONG) | |||
609 | value = va_arg (args, unsigned long int)__builtin_va_arg(args, unsigned long int); | |||
610 | else | |||
611 | value = va_arg (args, unsigned int)__builtin_va_arg(args, unsigned int); | |||
612 | fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); | |||
613 | break; | |||
614 | case 'f': | |||
615 | if (cflags == DP_C_LDOUBLE) | |||
616 | fvalue = va_arg (args, long double)__builtin_va_arg(args, long double); | |||
617 | else | |||
618 | fvalue = va_arg (args, double)__builtin_va_arg(args, double); | |||
619 | /* um, floating point? */ | |||
620 | fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); | |||
621 | break; | |||
622 | case 'E': | |||
623 | flags |= DP_F_UP; | |||
624 | case 'e': | |||
625 | if (cflags == DP_C_LDOUBLE) | |||
626 | fvalue = va_arg (args, long double)__builtin_va_arg(args, long double); | |||
627 | else | |||
628 | fvalue = va_arg (args, double)__builtin_va_arg(args, double); | |||
629 | break; | |||
630 | case 'G': | |||
631 | flags |= DP_F_UP; | |||
632 | case 'g': | |||
633 | if (cflags == DP_C_LDOUBLE) | |||
634 | fvalue = va_arg (args, long double)__builtin_va_arg(args, long double); | |||
635 | else | |||
636 | fvalue = va_arg (args, double)__builtin_va_arg(args, double); | |||
637 | break; | |||
638 | case 'c': | |||
639 | dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)__builtin_va_arg(args, int)); | |||
640 | break; | |||
641 | case 's': | |||
642 | strvalue = va_arg (args, char *)__builtin_va_arg(args, char *); | |||
643 | if (max < 0) | |||
644 | max = maxlen; /* ie, no max */ | |||
645 | fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); | |||
646 | break; | |||
647 | case 'p': | |||
648 | strvalue = va_arg (args, void *)__builtin_va_arg(args, void *); | |||
649 | fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); | |||
650 | break; | |||
651 | case 'n': | |||
652 | if (cflags == DP_C_SHORT) | |||
653 | { | |||
654 | short int *num; | |||
655 | num = va_arg (args, short int *)__builtin_va_arg(args, short int *); | |||
656 | *num = currlen; | |||
657 | } | |||
658 | else if (cflags == DP_C_LONG) | |||
659 | { | |||
660 | long int *num; | |||
661 | num = va_arg (args, long int *)__builtin_va_arg(args, long int *); | |||
662 | *num = currlen; | |||
663 | } | |||
664 | else | |||
665 | { | |||
666 | int *num; | |||
667 | num = va_arg (args, int *)__builtin_va_arg(args, int *); | |||
668 | *num = currlen; | |||
669 | } | |||
670 | break; | |||
671 | case '%': | |||
672 | dopr_outch (buffer, &currlen, maxlen, ch); | |||
673 | break; | |||
674 | case 'w': | |||
675 | /* not supported yet, treat as next char */ | |||
676 | ch = *format++; | |||
677 | break; | |||
678 | default: | |||
679 | /* Unknown, skip */ | |||
680 | break; | |||
681 | } | |||
682 | ch = *format++; | |||
683 | state = DP_S_DEFAULT; | |||
684 | flags = cflags = min = 0; | |||
685 | max = -1; | |||
686 | break; | |||
687 | case DP_S_DONE: | |||
688 | break; | |||
689 | default: | |||
690 | /* hmm? */ | |||
691 | break; /* some picky compilers need this */ | |||
692 | } | |||
693 | } | |||
694 | if (currlen < maxlen - 1) | |||
695 | buffer[currlen] = '\0'; | |||
696 | else | |||
697 | buffer[maxlen - 1] = '\0'; | |||
698 | } | |||
699 | ||||
700 | static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, | |||
701 | char *value, int flags, int min, int max) | |||
702 | { | |||
703 | int padlen, strln; /* amount to pad */ | |||
704 | int cnt = 0; | |||
705 | ||||
706 | if (value == 0) | |||
707 | { | |||
708 | value = "<NULL>"; | |||
709 | } | |||
710 | ||||
711 | for (strln = 0; value[strln]; ++strln); /* strlen */ | |||
712 | padlen = min - strln; | |||
713 | if (padlen < 0) | |||
714 | padlen = 0; | |||
715 | if (flags & DP_F_MINUS) | |||
716 | padlen = -padlen; /* Left Justify */ | |||
717 | ||||
718 | while ((padlen > 0) && (cnt < max)) | |||
719 | { | |||
720 | dopr_outch (buffer, currlen, maxlen, ' '); | |||
721 | --padlen; | |||
722 | ++cnt; | |||
723 | } | |||
724 | while (*value && (cnt < max)) | |||
725 | { | |||
726 | dopr_outch (buffer, currlen, maxlen, *value++); | |||
727 | ++cnt; | |||
728 | } | |||
729 | while ((padlen < 0) && (cnt < max)) | |||
730 | { | |||
731 | dopr_outch (buffer, currlen, maxlen, ' '); | |||
732 | ++padlen; | |||
733 | ++cnt; | |||
734 | } | |||
735 | } | |||
736 | ||||
737 | /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ | |||
738 | ||||
739 | static void fmtint (char *buffer, size_t *currlen, size_t maxlen, | |||
740 | long value, int base, int min, int max, int flags) | |||
741 | { | |||
742 | int signvalue = 0; | |||
743 | unsigned long uvalue; | |||
744 | char convert[20]; | |||
745 | int place = 0; | |||
746 | int spadlen = 0; /* amount to space pad */ | |||
747 | int zpadlen = 0; /* amount to zero pad */ | |||
748 | int caps = 0; | |||
749 | ||||
750 | if (max < 0) | |||
751 | max = 0; | |||
752 | ||||
753 | uvalue = value; | |||
754 | ||||
755 | if(!(flags & DP_F_UNSIGNED)) | |||
756 | { | |||
757 | if( value < 0 ) { | |||
758 | signvalue = '-'; | |||
759 | uvalue = -value; | |||
760 | } | |||
761 | else | |||
762 | if (flags & DP_F_PLUS) /* Do a sign (+/i) */ | |||
763 | signvalue = '+'; | |||
764 | else | |||
765 | if (flags & DP_F_SPACE) | |||
766 | signvalue = ' '; | |||
767 | } | |||
768 | ||||
769 | if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ | |||
770 | ||||
771 | do { | |||
772 | convert[place++] = | |||
773 | (caps? "0123456789ABCDEF":"0123456789abcdef") | |||
774 | [uvalue % (unsigned)base ]; | |||
775 | uvalue = (uvalue / (unsigned)base ); | |||
776 | } while(uvalue && (place < 20)); | |||
777 | if (place == 20) place--; | |||
778 | convert[place] = 0; | |||
779 | ||||
780 | zpadlen = max - place; | |||
781 | spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); | |||
782 | if (zpadlen < 0) zpadlen = 0; | |||
783 | if (spadlen < 0) spadlen = 0; | |||
784 | if (flags & DP_F_ZERO) | |||
785 | { | |||
786 | zpadlen = MAX(zpadlen, spadlen); | |||
787 | spadlen = 0; | |||
788 | } | |||
789 | if (flags & DP_F_MINUS) | |||
790 | spadlen = -spadlen; /* Left Justifty */ | |||
791 | ||||
792 | #ifdef DEBUG_SNPRINTF | |||
793 | dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", | |||
794 | zpadlen, spadlen, min, max, place)); | |||
795 | #endif | |||
796 | ||||
797 | /* Spaces */ | |||
798 | while (spadlen > 0) | |||
799 | { | |||
800 | dopr_outch (buffer, currlen, maxlen, ' '); | |||
801 | --spadlen; | |||
802 | } | |||
803 | ||||
804 | /* Sign */ | |||
805 | if (signvalue) | |||
806 | dopr_outch (buffer, currlen, maxlen, signvalue); | |||
807 | ||||
808 | /* Zeros */ | |||
809 | if (zpadlen > 0) | |||
810 | { | |||
811 | while (zpadlen > 0) | |||
812 | { | |||
813 | dopr_outch (buffer, currlen, maxlen, '0'); | |||
814 | --zpadlen; | |||
815 | } | |||
816 | } | |||
817 | ||||
818 | /* Digits */ | |||
819 | while (place > 0) | |||
820 | dopr_outch (buffer, currlen, maxlen, convert[--place]); | |||
821 | ||||
822 | /* Left Justified spaces */ | |||
823 | while (spadlen < 0) { | |||
824 | dopr_outch (buffer, currlen, maxlen, ' '); | |||
825 | ++spadlen; | |||
826 | } | |||
827 | } | |||
828 | ||||
829 | static long double abs_val (long double value) | |||
830 | { | |||
831 | long double result = value; | |||
832 | ||||
833 | if (value < 0) | |||
834 | result = -value; | |||
835 | ||||
836 | return result; | |||
837 | } | |||
838 | ||||
839 | static long double pow10 (int exp) | |||
840 | { | |||
841 | long double result = 1; | |||
842 | ||||
843 | while (exp) | |||
844 | { | |||
845 | result *= 10; | |||
846 | exp--; | |||
847 | } | |||
848 | ||||
849 | return result; | |||
850 | } | |||
851 | ||||
852 | static long round (long double value) | |||
853 | { | |||
854 | long intpart; | |||
855 | ||||
856 | intpart = value; | |||
857 | value = value - intpart; | |||
858 | if (value >= 0.5) | |||
859 | intpart++; | |||
860 | ||||
861 | return intpart; | |||
862 | } | |||
863 | ||||
864 | static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, | |||
865 | long double fvalue, int min, int max, int flags) | |||
866 | { | |||
867 | int signvalue = 0; | |||
868 | long double ufvalue; | |||
869 | char iconvert[20]; | |||
870 | char fconvert[20]; | |||
871 | int iplace = 0; | |||
872 | int fplace = 0; | |||
873 | int padlen = 0; /* amount to pad */ | |||
874 | int zpadlen = 0; | |||
875 | int caps = 0; | |||
876 | long intpart; | |||
877 | long fracpart; | |||
878 | ||||
879 | /* | |||
880 | * AIX manpage says the default is 0, but Solaris says the default | |||
881 | * is 6, and sprintf on AIX defaults to 6 | |||
882 | */ | |||
883 | if (max < 0) | |||
884 | max = 6; | |||
885 | ||||
886 | ufvalue = abs_val (fvalue); | |||
887 | ||||
888 | if (fvalue < 0) | |||
889 | signvalue = '-'; | |||
890 | else | |||
891 | if (flags & DP_F_PLUS) /* Do a sign (+/i) */ | |||
892 | signvalue = '+'; | |||
893 | else | |||
894 | if (flags & DP_F_SPACE) | |||
895 | signvalue = ' '; | |||
896 | ||||
897 | #if 0 | |||
898 | if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ | |||
899 | #endif | |||
900 | ||||
901 | intpart = ufvalue; | |||
902 | ||||
903 | /* | |||
904 | * Sorry, we only support 9 digits past the decimal because of our | |||
905 | * conversion method | |||
906 | */ | |||
907 | if (max > 9) | |||
908 | max = 9; | |||
909 | ||||
910 | /* We "cheat" by converting the fractional part to integer by | |||
911 | * multiplying by a factor of 10 | |||
912 | */ | |||
913 | fracpart = round ((pow10 (max)) * (ufvalue - intpart)); | |||
914 | ||||
915 | if (fracpart >= pow10 (max)) | |||
916 | { | |||
917 | intpart++; | |||
918 | fracpart -= pow10 (max); | |||
919 | } | |||
920 | ||||
921 | #ifdef DEBUG_SNPRINTF | |||
922 | dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart)); | |||
923 | #endif | |||
924 | ||||
925 | /* Convert integer part */ | |||
926 | do { | |||
927 | iconvert[iplace++] = | |||
928 | (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10]; | |||
929 | intpart = (intpart / 10); | |||
930 | } while(intpart && (iplace < 20)); | |||
931 | if (iplace == 20) iplace--; | |||
932 | iconvert[iplace] = 0; | |||
933 | ||||
934 | /* Convert fractional part */ | |||
935 | do { | |||
936 | fconvert[fplace++] = | |||
937 | (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10]; | |||
938 | fracpart = (fracpart / 10); | |||
939 | } while(fracpart && (fplace < 20)); | |||
940 | if (fplace == 20) fplace--; | |||
941 | fconvert[fplace] = 0; | |||
942 | ||||
943 | /* -1 for decimal point, another -1 if we are printing a sign */ | |||
944 | padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); | |||
945 | zpadlen = max - fplace; | |||
946 | if (zpadlen < 0) | |||
947 | zpadlen = 0; | |||
948 | if (padlen < 0) | |||
949 | padlen = 0; | |||
950 | if (flags & DP_F_MINUS) | |||
951 | padlen = -padlen; /* Left Justifty */ | |||
952 | ||||
953 | if ((flags & DP_F_ZERO) && (padlen > 0)) | |||
954 | { | |||
955 | if (signvalue) | |||
956 | { | |||
957 | dopr_outch (buffer, currlen, maxlen, signvalue); | |||
958 | --padlen; | |||
959 | signvalue = 0; | |||
960 | } | |||
961 | while (padlen > 0) | |||
962 | { | |||
963 | dopr_outch (buffer, currlen, maxlen, '0'); | |||
964 | --padlen; | |||
965 | } | |||
966 | } | |||
967 | while (padlen > 0) | |||
968 | { | |||
969 | dopr_outch (buffer, currlen, maxlen, ' '); | |||
970 | --padlen; | |||
971 | } | |||
972 | if (signvalue) | |||
973 | dopr_outch (buffer, currlen, maxlen, signvalue); | |||
974 | ||||
975 | while (iplace > 0) | |||
976 | dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); | |||
977 | ||||
978 | /* | |||
979 | * Decimal point. This should probably use locale to find the correct | |||
980 | * char to print out. | |||
981 | */ | |||
982 | dopr_outch (buffer, currlen, maxlen, '.'); | |||
983 | ||||
984 | while (fplace > 0) | |||
985 | dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); | |||
986 | ||||
987 | while (zpadlen > 0) | |||
988 | { | |||
989 | dopr_outch (buffer, currlen, maxlen, '0'); | |||
990 | --zpadlen; | |||
991 | } | |||
992 | ||||
993 | while (padlen < 0) | |||
994 | { | |||
995 | dopr_outch (buffer, currlen, maxlen, ' '); | |||
996 | ++padlen; | |||
997 | } | |||
998 | } | |||
999 | ||||
1000 | static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c) | |||
1001 | { | |||
1002 | if (*currlen < maxlen) | |||
1003 | buffer[(*currlen)++] = c; | |||
1004 | } | |||
1005 | #endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */ | |||
1006 | ||||
1007 | #ifndef HAVE_VSNPRINTF1 | |||
1008 | int vsnprintf (char *str, size_t count, const char *fmt, va_list args) | |||
1009 | { | |||
1010 | str[0] = 0; | |||
1011 | dopr(str, count, fmt, args); | |||
1012 | return(strlen(str)); | |||
1013 | } | |||
1014 | #endif /* !HAVE_VSNPRINTF */ | |||
1015 | ||||
1016 | #ifndef HAVE_SNPRINTF1 | |||
1017 | /* VARARGS3 */ | |||
1018 | #ifdef HAVE_STDARGS | |||
1019 | int snprintf (char *str,size_t count,const char *fmt,...) | |||
1020 | #else | |||
1021 | int snprintf (va_alist) va_dcl | |||
1022 | #endif | |||
1023 | { | |||
1024 | #ifndef HAVE_STDARGS | |||
1025 | char *str; | |||
1026 | size_t count; | |||
1027 | char *fmt; | |||
1028 | #endif | |||
1029 | VA_LOCAL_DECL; | |||
1030 | ||||
1031 | VA_START (fmt); | |||
1032 | VA_SHIFT (str, char *); | |||
1033 | VA_SHIFT (count, size_t ); | |||
1034 | VA_SHIFT (fmt, char *); | |||
1035 | (void) vsnprintf(str, count, fmt, ap); | |||
1036 | VA_END; | |||
1037 | return(strlen(str)); | |||
1038 | } | |||
1039 | ||||
1040 | #ifdef TEST_SNPRINTF | |||
1041 | #ifndef LONG_STRING | |||
1042 | #define LONG_STRING 1024 | |||
1043 | #endif | |||
1044 | int main (void) | |||
1045 | { | |||
1046 | char buf1[LONG_STRING]; | |||
1047 | char buf2[LONG_STRING]; | |||
1048 | char *fp_fmt[] = { | |||
1049 | "%-1.5f", | |||
1050 | "%1.5f", | |||
1051 | "%123.9f", | |||
1052 | "%10.5f", | |||
1053 | "% 10.5f", | |||
1054 | "%+22.9f", | |||
1055 | "%+4.9f", | |||
1056 | "%01.3f", | |||
1057 | "%4f", | |||
1058 | "%3.1f", | |||
1059 | "%3.2f", | |||
1060 | NULL((void*)0) | |||
1061 | }; | |||
1062 | double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, | |||
1063 | 0.9996, 1.996, 4.136, 0}; | |||
1064 | char *int_fmt[] = { | |||
1065 | "%-1.5d", | |||
1066 | "%1.5d", | |||
1067 | "%123.9d", | |||
1068 | "%5.5d", | |||
1069 | "%10.5d", | |||
1070 | "% 10.5d", | |||
1071 | "%+22.33d", | |||
1072 | "%01.3d", | |||
1073 | "%4d", | |||
1074 | NULL((void*)0) | |||
1075 | }; | |||
1076 | long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; | |||
1077 | int x, y; | |||
1078 | int fail = 0; | |||
1079 | int num = 0; | |||
1080 | ||||
1081 | printf ("Testing snprintf format codes against system sprintf...\n"); | |||
1082 | ||||
1083 | for (x = 0; fp_fmt[x] != NULL((void*)0) ; x++) | |||
1084 | for (y = 0; fp_nums[y] != 0 ; y++) | |||
1085 | { | |||
1086 | snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]); | |||
1087 | sprintf (buf2, fp_fmt[x], fp_nums[y]); | |||
1088 | if (strcmp (buf1, buf2)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (buf1) && __builtin_constant_p (buf2) && (__s1_len = strlen (buf1), __s2_len = strlen (buf2), (!((size_t)(const void *)((buf1) + 1) - (size_t)(const void *)(buf1) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((buf2) + 1) - ( size_t)(const void *)(buf2) == 1) || __s2_len >= 4)) ? __builtin_strcmp (buf1, buf2) : (__builtin_constant_p (buf1) && ((size_t )(const void *)((buf1) + 1) - (size_t)(const void *)(buf1) == 1) && (__s1_len = strlen (buf1), __s1_len < 4) ? ( __builtin_constant_p (buf2) && ((size_t)(const void * )((buf2) + 1) - (size_t)(const void *)(buf2) == 1) ? __builtin_strcmp (buf1, buf2) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (buf2); int __result = (((const unsigned char *) (const char *) (buf1))[0] - __s2[0 ]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (buf1))[1] - __s2[1 ]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (buf1))[2] - __s2[2 ]); if (__s1_len > 2 && __result == 0) __result = ( ((const unsigned char *) (const char *) (buf1))[3] - __s2[3]) ; } } __result; }))) : (__builtin_constant_p (buf2) && ((size_t)(const void *)((buf2) + 1) - (size_t)(const void *) (buf2) == 1) && (__s2_len = strlen (buf2), __s2_len < 4) ? (__builtin_constant_p (buf1) && ((size_t)(const void *)((buf1) + 1) - (size_t)(const void *)(buf1) == 1) ? __builtin_strcmp (buf1, buf2) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (buf1); int __result = (((const unsigned char *) (const char *) (buf2))[0] - __s2 [0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (buf2))[1] - __s2 [1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (buf2))[2] - __s2 [2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (buf2))[3] - __s2[3 ]); } } __result; })))) : __builtin_strcmp (buf1, buf2)))); } )) | |||
1089 | { | |||
1090 | printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", | |||
1091 | fp_fmt[x], buf1, buf2); | |||
1092 | fail++; | |||
1093 | } | |||
1094 | num++; | |||
1095 | } | |||
1096 | ||||
1097 | for (x = 0; int_fmt[x] != NULL((void*)0) ; x++) | |||
1098 | for (y = 0; int_nums[y] != 0 ; y++) | |||
1099 | { | |||
1100 | snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]); | |||
1101 | sprintf (buf2, int_fmt[x], int_nums[y]); | |||
1102 | if (strcmp (buf1, buf2)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (buf1) && __builtin_constant_p (buf2) && (__s1_len = strlen (buf1), __s2_len = strlen (buf2), (!((size_t)(const void *)((buf1) + 1) - (size_t)(const void *)(buf1) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((buf2) + 1) - ( size_t)(const void *)(buf2) == 1) || __s2_len >= 4)) ? __builtin_strcmp (buf1, buf2) : (__builtin_constant_p (buf1) && ((size_t )(const void *)((buf1) + 1) - (size_t)(const void *)(buf1) == 1) && (__s1_len = strlen (buf1), __s1_len < 4) ? ( __builtin_constant_p (buf2) && ((size_t)(const void * )((buf2) + 1) - (size_t)(const void *)(buf2) == 1) ? __builtin_strcmp (buf1, buf2) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (buf2); int __result = (((const unsigned char *) (const char *) (buf1))[0] - __s2[0 ]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (buf1))[1] - __s2[1 ]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (buf1))[2] - __s2[2 ]); if (__s1_len > 2 && __result == 0) __result = ( ((const unsigned char *) (const char *) (buf1))[3] - __s2[3]) ; } } __result; }))) : (__builtin_constant_p (buf2) && ((size_t)(const void *)((buf2) + 1) - (size_t)(const void *) (buf2) == 1) && (__s2_len = strlen (buf2), __s2_len < 4) ? (__builtin_constant_p (buf1) && ((size_t)(const void *)((buf1) + 1) - (size_t)(const void *)(buf1) == 1) ? __builtin_strcmp (buf1, buf2) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (buf1); int __result = (((const unsigned char *) (const char *) (buf2))[0] - __s2 [0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (buf2))[1] - __s2 [1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (buf2))[2] - __s2 [2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (buf2))[3] - __s2[3 ]); } } __result; })))) : __builtin_strcmp (buf1, buf2)))); } )) | |||
1103 | { | |||
1104 | printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", | |||
1105 | int_fmt[x], buf1, buf2); | |||
1106 | fail++; | |||
1107 | } | |||
1108 | num++; | |||
1109 | } | |||
1110 | printf ("%d tests failed out of %d.\n", fail, num); | |||
1111 | } | |||
1112 | #endif /* SNPRINTF_TEST */ | |||
1113 | ||||
1114 | #endif /* !HAVE_SNPRINTF */ | |||
1115 | ||||
1116 | ||||
1117 | ||||
1118 | ||||
1119 | /* | |||
1120 | * List handling functions | |||
1121 | */ | |||
1122 | ||||
1123 | void | |||
1124 | abook_list_append(abook_list **list, char *str) | |||
1125 | { | |||
1126 | abook_list *tmp; | |||
1127 | ||||
1128 | if(!str) | |||
1129 | return; | |||
1130 | ||||
1131 | for(tmp = *list; tmp && tmp->next; tmp = tmp->next) | |||
1132 | ; | |||
1133 | ||||
1134 | if(tmp) { | |||
1135 | tmp->next = xmalloc_xmalloc_xmalloc(sizeof(abook_list)); | |||
1136 | tmp = tmp->next; | |||
1137 | } else | |||
1138 | tmp = *list = xmalloc_xmalloc_xmalloc(sizeof(abook_list)); | |||
1139 | ||||
1140 | tmp->data = xstrdup(str); | |||
1141 | tmp->next = NULL((void*)0); | |||
1142 | } | |||
1143 | ||||
1144 | void | |||
1145 | abook_list_free(abook_list **list) | |||
1146 | { | |||
1147 | abook_list *prev = NULL((void*)0), *tmp = *list; | |||
1148 | ||||
1149 | if(!list) | |||
1150 | return; | |||
1151 | ||||
1152 | while(tmp) { | |||
1153 | xfree(tmp->data)do { free(tmp->data); tmp->data = ((void*)0); } while(0 ); | |||
1154 | prev = tmp; | |||
1155 | tmp = tmp->next; | |||
1156 | xfree(prev)do { free(prev); prev = ((void*)0); } while(0); | |||
1157 | } | |||
1158 | ||||
1159 | *list = NULL((void*)0); | |||
1160 | } | |||
1161 | ||||
1162 | abook_list * | |||
1163 | csv_to_abook_list(char *str) | |||
1164 | { | |||
1165 | char *start, *p = str, *end; | |||
1166 | abook_list *list = NULL((void*)0); | |||
1167 | ||||
1168 | if(!str) | |||
1169 | return NULL((void*)0); | |||
1170 | ||||
1171 | SKIPWS(p)while(*(p) && ((*__ctype_b_loc ())[(int) (((unsigned char )*(p)))] & (unsigned short int) _ISspace)) p++; | |||
1172 | start = end = p; | |||
1173 | ||||
1174 | while(*p) { | |||
1175 | if(!strchr(", ", *p)(__extension__ (__builtin_constant_p (*p) && !__builtin_constant_p (", ") && (*p) == '\0' ? (char *) __rawmemchr (", ", *p) : __builtin_strchr (", ", *p)))) { | |||
1176 | end = ++p; | |||
1177 | continue; | |||
1178 | } | |||
1179 | ||||
1180 | if((*p == ',') && (end - start)) { | |||
1181 | abook_list_append(&list, xstrndup(start, end - start)); | |||
1182 | p++; | |||
1183 | SKIPWS(p)while(*(p) && ((*__ctype_b_loc ())[(int) (((unsigned char )*(p)))] & (unsigned short int) _ISspace)) p++; | |||
1184 | start = end = p; | |||
1185 | continue; | |||
1186 | } | |||
1187 | ||||
1188 | p++; | |||
1189 | } | |||
1190 | if(end - start) | |||
1191 | abook_list_append(&list, xstrndup(start, end - start)); | |||
1192 | ||||
1193 | return list; | |||
1194 | } | |||
1195 | ||||
1196 | char * | |||
1197 | abook_list_to_csv(abook_list *list) | |||
1198 | { | |||
1199 | abook_list *tmp; | |||
1200 | char *res = NULL((void*)0); | |||
1201 | ||||
1202 | for(tmp = list; tmp; tmp = tmp->next) { | |||
1203 | if(tmp == list) | |||
1204 | res = xstrdup(tmp->data); | |||
1205 | else { | |||
1206 | res = xrealloc_xmalloc_xrealloc(res, strlen(res)+strlen(tmp->data)+2); | |||
1207 | strcat(res, ","); | |||
1208 | strcat(res, tmp->data); | |||
1209 | } | |||
1210 | } | |||
1211 | ||||
1212 | return res; | |||
1213 | } | |||
1214 | ||||
1215 | void | |||
1216 | abook_list_rotate(abook_list **list, enum rotate_dir dir) | |||
1217 | { | |||
1218 | abook_list *tmp = *list; | |||
1219 | ||||
1220 | if(!tmp || !tmp->next) | |||
1221 | return; | |||
1222 | ||||
1223 | switch(dir) { | |||
1224 | case ROTATE_LEFT: | |||
1225 | for(; tmp && tmp->next; tmp = tmp->next) | |||
1226 | ; | |||
1227 | ||||
1228 | tmp->next = *list; | |||
1229 | tmp = *list; | |||
1230 | *list = (*list)->next; | |||
1231 | tmp->next = NULL((void*)0); | |||
1232 | break; | |||
1233 | case ROTATE_RIGHT: | |||
1234 | for(; tmp && tmp->next && tmp->next->next; | |||
1235 | tmp = tmp->next) | |||
1236 | ; | |||
1237 | ||||
1238 | tmp->next->next = *list; | |||
1239 | *list = tmp->next; | |||
1240 | tmp->next = NULL((void*)0); | |||
1241 | break; | |||
1242 | default: | |||
1243 | assert(0)((void) (0)); | |||
1244 | } | |||
1245 | } | |||
1246 | ||||
1247 | /* if str == NULL, deleting the list element */ | |||
1248 | void | |||
1249 | abook_list_replace(abook_list **list, int index, char *str) | |||
1250 | { | |||
1251 | abook_list *cur, *prev; | |||
1252 | int i = 0; | |||
1253 | ||||
1254 | cur = prev = *list; | |||
1255 | ||||
1256 | if((index == 0) && !str) { | |||
1257 | *list = cur->next; | |||
1258 | free(cur->data); | |||
1259 | free(cur); | |||
1260 | return; | |||
1261 | } | |||
1262 | ||||
1263 | while(1) { | |||
1264 | if(!cur) | |||
1265 | return; | |||
1266 | ||||
1267 | if(i == index) | |||
1268 | break; | |||
1269 | ||||
1270 | prev = cur; | |||
1271 | cur = cur->next; | |||
1272 | i++; | |||
1273 | } | |||
1274 | ||||
1275 | if(str) { | |||
1276 | free(cur->data); | |||
1277 | cur->data = xstrdup(str); | |||
1278 | } else { | |||
1279 | prev->next = cur->next; | |||
1280 | free(cur->data); | |||
1281 | free(cur); | |||
1282 | } | |||
1283 | } | |||
1284 | ||||
1285 | abook_list * | |||
1286 | abook_list_get(abook_list *list, int index) | |||
1287 | { | |||
1288 | int i = 0; | |||
1289 | ||||
1290 | while(1) { | |||
1291 | if(!list) | |||
1292 | return NULL((void*)0); | |||
1293 | ||||
1294 | if(i == index) | |||
1295 | return list; | |||
1296 | ||||
1297 | i++; | |||
1298 | list = list->next; | |||
1299 | } | |||
1300 | } |