Bug Summary

File:build/../misc.c
Location:line 275, column 10
Description:Null pointer passed as an argument to a 'nonnull' parameter

Annotated Source Code

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
34char *
35strlower(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
47char *
48strtrim(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
67int
68is_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
81char *
82strcasestr(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
118char *
119strdup_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
147char*
148strconcat (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
180int
181safe_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
190int
191safe_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
204char *
205my_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
250char *
251getaline(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)) {
1
Loop condition is true. Entering loop body
6
Loop condition is true. Entering loop body
275 len += strlen(buf+len);
7
Null pointer passed as an argument to a 'nonnull' parameter
276 if (len > 0 && buf[len-1] == '\n')
2
Assuming 'len' is <= 0
277 break; /* the whole line has been read */
278
279 for (inc = size, p = NULL((void*)0); inc > mininc; inc /= 2)
3
Loop condition is true. Entering loop body
5
Loop condition is false. Execution continues on line 284
280 if ((p = xrealloc_inc(buf, size, inc)) !=
4
Taking false branch
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
307int
308strwidth(const char *s)
309{
310 assert(s)((void) (0));
311 return mbswidthgnu_mbswidth(s, 0);
312}
313
314int
315bytes2width(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
406static void dopr (char *buffer, size_t maxlen, const char *format,
407 va_list args);
408static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
409 char *value, int flags, int min, int max);
410static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
411 long value, int base, int min, int max, int flags);
412static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
413 long double fvalue, int min, int max, int flags);
414static 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
447static 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
700static 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
739static 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
829static 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
839static 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
852static 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
864static 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
1000static 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
1008int 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
1019int snprintf (char *str,size_t count,const char *fmt,...)
1020#else
1021int 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
1044int 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
1123void
1124abook_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
1144void
1145abook_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
1162abook_list *
1163csv_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
1196char *
1197abook_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
1215void
1216abook_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 */
1248void
1249abook_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
1285abook_list *
1286abook_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}