3 * $Id: misc.c,v 1.23 2006/09/04 18:29:25 cduval Exp $
5 * by JH <jheinonen@users.sourceforge.net>
7 * Copyright (C) Jaakko Heinonen
8 * getaline() Copyright (C) Lars Wirzenius
9 * sprintf and snprintf copyright is owned by various people
41 while( ( *str
= tolower ( *str
) ) )
54 for(t
= s
; isspace(*t
); t
++);
56 memmove(s
, t
, strlen(t
)+1);
58 for (tt
= t
= s
; *t
!= '\0'; t
++)
70 if(!p
|| !*p
|| (*p
== '-' && !*++p
))
81 strcasestr(char *haystack
, char *needle
)
86 assert(haystack
!= NULL
);
87 assert(needle
!= NULL
);
89 for(i
=0; i
<strlen(haystack
)-strlen(needle
)+1; i
++) {
90 for(k
=0; k
<strlen(needle
); k
++, i
++) {
91 if (tolower(haystack
[i
]) != tolower(needle
[k
]))
93 else if ((k
+1) == strlen(needle
))
106 /* varargs declarations: */
109 # define MY_VA_LOCAL_DECL va_list ap
110 # define MY_VA_START(f) va_start(ap, f)
111 # define MY_VA_SHIFT(v,t) v = va_arg(ap, t)
112 # define MY_VA_END va_end(ap)
114 # error HAVE_STDARG_H not defined
118 strdup_printf (const char *format
, ... )
122 char *buffer
= xmalloc (size
);
124 assert(format
!= NULL
);
129 n
= vsnprintf (buffer
, size
,
133 if (n
> -1 && n
< size
)
141 buffer
= xrealloc(buffer
, size
);
147 strconcat (const char *str
, ...)
155 l
= 1 + strlen (str
);
157 MY_VA_SHIFT(s
, char*);
160 MY_VA_SHIFT(s
, char*);
166 strcpy (concat
, str
);
168 MY_VA_SHIFT(s
, char*);
171 MY_VA_SHIFT(s
, char*);
180 safe_strcmp(const char *s1
, const char *s2
)
182 if (s1
== NULL
&& s2
== NULL
) return 0;
183 if (s1
== NULL
) return -1;
184 if (s2
== NULL
) return 1;
186 return strcmp(s1
, s2
);
190 safe_strcoll(const char *s1
, const char *s2
)
193 if (s1
== NULL
&& s2
== NULL
) return 0;
194 if (s1
== NULL
) return -1;
195 if (s2
== NULL
) return 1;
197 return strcoll(s1
, s2
);
198 #else /* fall back to strcmp */
199 return safe_strcmp(s1
, s2
);
209 if( (dir
= xmalloc(size
)) == NULL
)
214 while( getcwd(dir
, size
) == NULL
&& errno
== ERANGE
)
215 if( (dir
= xrealloc(dir
, size
*=2)) == NULL
)
224 * Copyright (c) 1994 Lars Wirzenius
225 * All rights reserved.
227 * Redistribution and use in source and binary forms, with or without
228 * modification, are permitted provided that the following conditions
230 * 1. Redistributions of source code must retain the above copyright
231 * notice, this list of conditions and the following disclaimer
232 * in this position and unchanged.
233 * 2. Redistributions in binary form must reproduce the above copyright
234 * notice, this list of conditions and the following disclaimer in the
235 * documentation and/or other materials provided with the distribution.
237 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
238 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
239 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
240 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
241 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
242 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
243 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
244 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
245 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
246 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
252 char *buf
; /* buffer for line */
253 size_t size
; /* size of buffer */
254 size_t inc
; /* how much to enlarge buffer */
255 size_t len
; /* # of chars stored into buf before '\0' */
257 const size_t thres
= 128; /* initial buffer size (most lines should
258 fit into this size, so think of this as
259 the "long line threshold"). */
260 const size_t mucho
= 128; /* if there is at least this much wasted
261 space when the whole buffer has been
262 read, try to reclaim it. Don't make
263 this too small, else there is too much
264 time wasted trying to reclaim a couple
266 const size_t mininc
= 64; /* minimum number of bytes by which
267 to increase the allocated memory */
273 while (fgets(buf
+len
, size
-len
, f
) != NULL
) {
274 len
+= strlen(buf
+len
);
275 if (len
> 0 && buf
[len
-1] == '\n')
276 break; /* the whole line has been read */
278 for (inc
= size
, p
= NULL
; inc
> mininc
; inc
/= 2)
279 if ((p
= xrealloc_inc(buf
, size
, inc
)) !=
289 return NULL
; /* nothing read (eof or error) */
292 if (buf
[len
-1] == '\n') /* remove newline, if there */
295 if (size
- len
> mucho
) { /* a plenitude of unused memory? */
296 p
= xrealloc_inc(buf
, len
, 1);
307 strwidth(const char *s
)
310 return mbswidth(s
, 0);
314 bytes2width(const char *s
, int width
)
317 #ifdef HANDLE_MULTIBYTE
318 return mbsnbytes(s
, strlen(s
), width
, 0);
324 /**************************************************************
326 * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
327 * A bombproof version of doprnt (dopr) included.
328 * Sigh. This sort of thing is always nasty do deal with. Note that
329 * the version here does not include floating point...
331 * snprintf() is used instead of sprintf() as it does limit checks
332 * for string length. This covers a nasty loophole.
334 * The other functions are there to prevent NULL pointers from
335 * causing nast effects.
338 * Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
339 * This was ugly. It is still ugly. I opted out of floating point
340 * numbers, but the formatter understands just about everything
341 * from the normal C string format, at least as far as I can tell from
342 * the Solaris 2.5 printf(3S) man page.
344 * Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
345 * Ok, added some minimal floating point support, which means this
346 * probably requires libm on most operating systems. Don't yet
347 * support the exponent (e,E) and sigfig (g,G). Also, fmtint()
348 * was pretty badly broken, it just wasn't being exercised in ways
349 * which showed it, so that's been fixed. Also, formated the code
350 * to mutt conventions, and removed dead code left over from the
351 * original. Also, there is now a builtin-test, just compile with:
352 * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
353 * and run snprintf for results.
355 * Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
356 * The PGP code was using unsigned hexadecimal formats.
357 * Unfortunately, unsigned formats simply didn't work.
359 * Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
360 * The original code assumed that both snprintf() and vsnprintf() were
361 * missing. Some systems only have snprintf() but not vsnprintf(), so
362 * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
364 **************************************************************/
368 #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
372 #include <sys/types.h>
374 /* Define this as a fall through, HAVE_STDARG_H is probably already set */
376 #if !defined(HAVE_STDARG_H) && !defined(HAVE_VARARGS_H)
377 # define HAVE_VARARGS_H 1
380 /* varargs declarations: */
382 #if defined(HAVE_STDARG_H)
383 /*# include <stdarg.h>*/
384 # define HAVE_STDARGS /* let's hope that works everywhere (mj) */
385 # define VA_LOCAL_DECL va_list ap
386 # define VA_START(f) va_start(ap, f)
387 # define VA_SHIFT(v,t) ; /* no-op for ANSI */
388 # define VA_END va_end(ap)
390 # if defined(HAVE_VARARGS_H)
391 # include <varargs.h>
393 # define VA_LOCAL_DECL va_list ap
394 # define VA_START(f) va_start(ap) /* f is ignored! */
395 # define VA_SHIFT(v,t) v = va_arg(ap,t)
396 # define VA_END va_end(ap)
398 /*XX ** NO VARARGS ** XX*/
402 /*int snprintf (char *str, size_t count, const char *fmt, ...);*/
403 /*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/
405 static void dopr (char *buffer
, size_t maxlen
, const char *format
,
407 static void fmtstr (char *buffer
, size_t *currlen
, size_t maxlen
,
408 char *value
, int flags
, int min
, int max
);
409 static void fmtint (char *buffer
, size_t *currlen
, size_t maxlen
,
410 long value
, int base
, int min
, int max
, int flags
);
411 static void fmtfp (char *buffer
, size_t *currlen
, size_t maxlen
,
412 long double fvalue
, int min
, int max
, int flags
);
413 static void dopr_outch (char *buffer
, size_t *currlen
, size_t maxlen
, char c
);
416 * dopr(): poor man's version of doprintf
419 /* format read states */
420 #define DP_S_DEFAULT 0
429 /* format flags - Bits */
430 #define DP_F_MINUS (1 << 0)
431 #define DP_F_PLUS (1 << 1)
432 #define DP_F_SPACE (1 << 2)
433 #define DP_F_NUM (1 << 3)
434 #define DP_F_ZERO (1 << 4)
435 #define DP_F_UP (1 << 5)
436 #define DP_F_UNSIGNED (1 << 6)
438 /* Conversion Flags */
441 #define DP_C_LDOUBLE 3
443 #define char_to_int(p) (p - '0')
444 #define MAX(p,q) ((p >= q) ? p : q)
446 static void dopr (char *buffer
, size_t maxlen
, const char *format
, va_list args
)
459 state
= DP_S_DEFAULT
;
460 currlen
= flags
= cflags
= min
= 0;
464 while (state
!= DP_S_DONE
)
466 if ((ch
== '\0') || (currlen
>= maxlen
))
475 dopr_outch (buffer
, &currlen
, maxlen
, ch
);
507 if (isdigit((unsigned char)ch
))
509 min
= 10*min
+ char_to_int (ch
);
514 min
= va_arg (args
, int);
531 if (isdigit((unsigned char)ch
))
535 max
= 10*max
+ char_to_int (ch
);
540 max
= va_arg (args
, int);
548 /* Currently, we don't support Long Long, bummer */
560 cflags
= DP_C_LDOUBLE
;
573 if (cflags
== DP_C_SHORT
)
574 value
= va_arg (args
, short int);
575 else if (cflags
== DP_C_LONG
)
576 value
= va_arg (args
, long int);
578 value
= va_arg (args
, int);
579 fmtint (buffer
, &currlen
, maxlen
, value
, 10, min
, max
, flags
);
582 flags
|= DP_F_UNSIGNED
;
583 if (cflags
== DP_C_SHORT
)
584 value
= va_arg (args
, unsigned short int);
585 else if (cflags
== DP_C_LONG
)
586 value
= va_arg (args
, unsigned long int);
588 value
= va_arg (args
, unsigned int);
589 fmtint (buffer
, &currlen
, maxlen
, value
, 8, min
, max
, flags
);
592 flags
|= DP_F_UNSIGNED
;
593 if (cflags
== DP_C_SHORT
)
594 value
= va_arg (args
, unsigned short int);
595 else if (cflags
== DP_C_LONG
)
596 value
= va_arg (args
, unsigned long int);
598 value
= va_arg (args
, unsigned int);
599 fmtint (buffer
, &currlen
, maxlen
, value
, 10, min
, max
, flags
);
604 flags
|= DP_F_UNSIGNED
;
605 if (cflags
== DP_C_SHORT
)
606 value
= va_arg (args
, unsigned short int);
607 else if (cflags
== DP_C_LONG
)
608 value
= va_arg (args
, unsigned long int);
610 value
= va_arg (args
, unsigned int);
611 fmtint (buffer
, &currlen
, maxlen
, value
, 16, min
, max
, flags
);
614 if (cflags
== DP_C_LDOUBLE
)
615 fvalue
= va_arg (args
, long double);
617 fvalue
= va_arg (args
, double);
618 /* um, floating point? */
619 fmtfp (buffer
, &currlen
, maxlen
, fvalue
, min
, max
, flags
);
624 if (cflags
== DP_C_LDOUBLE
)
625 fvalue
= va_arg (args
, long double);
627 fvalue
= va_arg (args
, double);
632 if (cflags
== DP_C_LDOUBLE
)
633 fvalue
= va_arg (args
, long double);
635 fvalue
= va_arg (args
, double);
638 dopr_outch (buffer
, &currlen
, maxlen
, va_arg (args
, int));
641 strvalue
= va_arg (args
, char *);
643 max
= maxlen
; /* ie, no max */
644 fmtstr (buffer
, &currlen
, maxlen
, strvalue
, flags
, min
, max
);
647 strvalue
= va_arg (args
, void *);
648 fmtint (buffer
, &currlen
, maxlen
, (long) strvalue
, 16, min
, max
, flags
);
651 if (cflags
== DP_C_SHORT
)
654 num
= va_arg (args
, short int *);
657 else if (cflags
== DP_C_LONG
)
660 num
= va_arg (args
, long int *);
666 num
= va_arg (args
, int *);
671 dopr_outch (buffer
, &currlen
, maxlen
, ch
);
674 /* not supported yet, treat as next char */
682 state
= DP_S_DEFAULT
;
683 flags
= cflags
= min
= 0;
690 break; /* some picky compilers need this */
693 if (currlen
< maxlen
- 1)
694 buffer
[currlen
] = '\0';
696 buffer
[maxlen
- 1] = '\0';
699 static void fmtstr (char *buffer
, size_t *currlen
, size_t maxlen
,
700 char *value
, int flags
, int min
, int max
)
702 int padlen
, strln
; /* amount to pad */
710 for (strln
= 0; value
[strln
]; ++strln
); /* strlen */
711 padlen
= min
- strln
;
714 if (flags
& DP_F_MINUS
)
715 padlen
= -padlen
; /* Left Justify */
717 while ((padlen
> 0) && (cnt
< max
))
719 dopr_outch (buffer
, currlen
, maxlen
, ' ');
723 while (*value
&& (cnt
< max
))
725 dopr_outch (buffer
, currlen
, maxlen
, *value
++);
728 while ((padlen
< 0) && (cnt
< max
))
730 dopr_outch (buffer
, currlen
, maxlen
, ' ');
736 /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
738 static void fmtint (char *buffer
, size_t *currlen
, size_t maxlen
,
739 long value
, int base
, int min
, int max
, int flags
)
742 unsigned long uvalue
;
745 int spadlen
= 0; /* amount to space pad */
746 int zpadlen
= 0; /* amount to zero pad */
754 if(!(flags
& DP_F_UNSIGNED
))
761 if (flags
& DP_F_PLUS
) /* Do a sign (+/i) */
764 if (flags
& DP_F_SPACE
)
768 if (flags
& DP_F_UP
) caps
= 1; /* Should characters be upper case? */
772 (caps
? "0123456789ABCDEF":"0123456789abcdef")
773 [uvalue
% (unsigned)base
];
774 uvalue
= (uvalue
/ (unsigned)base
);
775 } while(uvalue
&& (place
< 20));
776 if (place
== 20) place
--;
779 zpadlen
= max
- place
;
780 spadlen
= min
- MAX (max
, place
) - (signvalue
? 1 : 0);
781 if (zpadlen
< 0) zpadlen
= 0;
782 if (spadlen
< 0) spadlen
= 0;
783 if (flags
& DP_F_ZERO
)
785 zpadlen
= MAX(zpadlen
, spadlen
);
788 if (flags
& DP_F_MINUS
)
789 spadlen
= -spadlen
; /* Left Justifty */
791 #ifdef DEBUG_SNPRINTF
792 dprint (1, (debugfile
, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
793 zpadlen
, spadlen
, min
, max
, place
));
799 dopr_outch (buffer
, currlen
, maxlen
, ' ');
805 dopr_outch (buffer
, currlen
, maxlen
, signvalue
);
812 dopr_outch (buffer
, currlen
, maxlen
, '0');
819 dopr_outch (buffer
, currlen
, maxlen
, convert
[--place
]);
821 /* Left Justified spaces */
822 while (spadlen
< 0) {
823 dopr_outch (buffer
, currlen
, maxlen
, ' ');
828 static long double abs_val (long double value
)
830 long double result
= value
;
838 static long double pow10 (int exp
)
840 long double result
= 1;
851 static long round (long double value
)
856 value
= value
- intpart
;
863 static void fmtfp (char *buffer
, size_t *currlen
, size_t maxlen
,
864 long double fvalue
, int min
, int max
, int flags
)
872 int padlen
= 0; /* amount to pad */
879 * AIX manpage says the default is 0, but Solaris says the default
880 * is 6, and sprintf on AIX defaults to 6
885 ufvalue
= abs_val (fvalue
);
890 if (flags
& DP_F_PLUS
) /* Do a sign (+/i) */
893 if (flags
& DP_F_SPACE
)
897 if (flags
& DP_F_UP
) caps
= 1; /* Should characters be upper case? */
903 * Sorry, we only support 9 digits past the decimal because of our
909 /* We "cheat" by converting the fractional part to integer by
910 * multiplying by a factor of 10
912 fracpart
= round ((pow10 (max
)) * (ufvalue
- intpart
));
914 if (fracpart
>= pow10 (max
))
917 fracpart
-= pow10 (max
);
920 #ifdef DEBUG_SNPRINTF
921 dprint (1, (debugfile
, "fmtfp: %f =? %d.%d\n", fvalue
, intpart
, fracpart
));
924 /* Convert integer part */
927 (caps
? "0123456789ABCDEF":"0123456789abcdef")[intpart
% 10];
928 intpart
= (intpart
/ 10);
929 } while(intpart
&& (iplace
< 20));
930 if (iplace
== 20) iplace
--;
931 iconvert
[iplace
] = 0;
933 /* Convert fractional part */
936 (caps
? "0123456789ABCDEF":"0123456789abcdef")[fracpart
% 10];
937 fracpart
= (fracpart
/ 10);
938 } while(fracpart
&& (fplace
< 20));
939 if (fplace
== 20) fplace
--;
940 fconvert
[fplace
] = 0;
942 /* -1 for decimal point, another -1 if we are printing a sign */
943 padlen
= min
- iplace
- max
- 1 - ((signvalue
) ? 1 : 0);
944 zpadlen
= max
- fplace
;
949 if (flags
& DP_F_MINUS
)
950 padlen
= -padlen
; /* Left Justifty */
952 if ((flags
& DP_F_ZERO
) && (padlen
> 0))
956 dopr_outch (buffer
, currlen
, maxlen
, signvalue
);
962 dopr_outch (buffer
, currlen
, maxlen
, '0');
968 dopr_outch (buffer
, currlen
, maxlen
, ' ');
972 dopr_outch (buffer
, currlen
, maxlen
, signvalue
);
975 dopr_outch (buffer
, currlen
, maxlen
, iconvert
[--iplace
]);
978 * Decimal point. This should probably use locale to find the correct
981 dopr_outch (buffer
, currlen
, maxlen
, '.');
984 dopr_outch (buffer
, currlen
, maxlen
, fconvert
[--fplace
]);
988 dopr_outch (buffer
, currlen
, maxlen
, '0');
994 dopr_outch (buffer
, currlen
, maxlen
, ' ');
999 static void dopr_outch (char *buffer
, size_t *currlen
, size_t maxlen
, char c
)
1001 if (*currlen
< maxlen
)
1002 buffer
[(*currlen
)++] = c
;
1004 #endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
1006 #ifndef HAVE_VSNPRINTF
1007 int vsnprintf (char *str
, size_t count
, const char *fmt
, va_list args
)
1010 dopr(str
, count
, fmt
, args
);
1011 return(strlen(str
));
1013 #endif /* !HAVE_VSNPRINTF */
1015 #ifndef HAVE_SNPRINTF
1018 int snprintf (char *str
,size_t count
,const char *fmt
,...)
1020 int snprintf (va_alist
) va_dcl
1023 #ifndef HAVE_STDARGS
1031 VA_SHIFT (str
, char *);
1032 VA_SHIFT (count
, size_t );
1033 VA_SHIFT (fmt
, char *);
1034 (void) vsnprintf(str
, count
, fmt
, ap
);
1036 return(strlen(str
));
1039 #ifdef TEST_SNPRINTF
1041 #define LONG_STRING 1024
1045 char buf1
[LONG_STRING
];
1046 char buf2
[LONG_STRING
];
1061 double fp_nums
[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
1062 0.9996, 1.996, 4.136, 0};
1075 long int_nums
[] = { -1, 134, 91340, 341, 0203, 0};
1080 printf ("Testing snprintf format codes against system sprintf...\n");
1082 for (x
= 0; fp_fmt
[x
] != NULL
; x
++)
1083 for (y
= 0; fp_nums
[y
] != 0 ; y
++)
1085 snprintf (buf1
, sizeof (buf1
), fp_fmt
[x
], fp_nums
[y
]);
1086 sprintf (buf2
, fp_fmt
[x
], fp_nums
[y
]);
1087 if (strcmp (buf1
, buf2
))
1089 printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
1090 fp_fmt
[x
], buf1
, buf2
);
1096 for (x
= 0; int_fmt
[x
] != NULL
; x
++)
1097 for (y
= 0; int_nums
[y
] != 0 ; y
++)
1099 snprintf (buf1
, sizeof (buf1
), int_fmt
[x
], int_nums
[y
]);
1100 sprintf (buf2
, int_fmt
[x
], int_nums
[y
]);
1101 if (strcmp (buf1
, buf2
))
1103 printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
1104 int_fmt
[x
], buf1
, buf2
);
1109 printf ("%d tests failed out of %d.\n", fail
, num
);
1111 #endif /* SNPRINTF_TEST */
1113 #endif /* !HAVE_SNPRINTF */
1119 * List handling functions
1123 abook_list_append(abook_list
**list
, char *str
)
1130 for(tmp
= *list
; tmp
&& tmp
->next
; tmp
= tmp
->next
)
1134 tmp
->next
= xmalloc(sizeof(abook_list
));
1137 tmp
= *list
= xmalloc(sizeof(abook_list
));
1139 tmp
->data
= xstrdup(str
);
1144 abook_list_free(abook_list
**list
)
1146 abook_list
*prev
= NULL
, *tmp
= *list
;
1162 csv_to_abook_list(char *str
)
1164 char *start
, *p
= str
, *end
;
1165 abook_list
*list
= NULL
;
1174 if(!strchr(", ", *p
)) {
1179 if((*p
== ',') && (end
- start
)) {
1180 abook_list_append(&list
, xstrndup(start
, end
- start
));
1190 abook_list_append(&list
, xstrndup(start
, end
- start
));
1196 abook_list_to_csv(abook_list
*list
)
1201 for(tmp
= list
; tmp
; tmp
= tmp
->next
) {
1203 res
= xstrdup(tmp
->data
);
1205 res
= xrealloc(res
, strlen(res
)+strlen(tmp
->data
)+2);
1207 strcat(res
, tmp
->data
);
1215 abook_list_rotate(abook_list
**list
, enum rotate_dir dir
)
1217 abook_list
*tmp
= *list
;
1219 if(!tmp
|| !tmp
->next
)
1224 for(; tmp
&& tmp
->next
; tmp
= tmp
->next
)
1229 *list
= (*list
)->next
;
1233 for(; tmp
&& tmp
->next
&& tmp
->next
->next
;
1237 tmp
->next
->next
= *list
;
1246 /* if str == NULL, deleting the list element */
1248 abook_list_replace(abook_list
**list
, int index
, char *str
)
1250 abook_list
*cur
, *prev
;
1255 if((index
== 0) && !str
) {
1276 cur
->data
= xstrdup(str
);
1278 prev
->next
= cur
->next
;
1285 abook_list_get(abook_list
*list
, int index
)