* tsexp.c (back_and_forth): Very minimal test of the new functions.
[libgcrypt.git] / src / missing-string.c
1 /* missing-string.c - missing string utilities
2  * Copyright (C) 1994, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "g10lib.h"
26
27
28 #ifndef HAVE_STPCPY
29 char *
30 stpcpy(char *a,const char *b)
31 {
32     while( *b )
33         *a++ = *b++;
34     *a = 0;
35
36     return (char*)a;
37 }
38 #endif
39
40
41 #ifndef HAVE_STRSEP
42 /* code taken from glibc-2.2.1/sysdeps/generic/strsep.c */
43 char *
44 strsep (char **stringp, const char *delim)
45 {
46   char *begin, *end;
47
48   begin = *stringp;
49   if (begin == NULL)
50     return NULL;
51
52   /* A frequent case is when the delimiter string contains only one
53      character.  Here we don't need to call the expensive `strpbrk'
54      function and instead work using `strchr'.  */
55   if (delim[0] == '\0' || delim[1] == '\0')
56     {
57       char ch = delim[0];
58
59       if (ch == '\0')
60         end = NULL;
61       else
62         {
63           if (*begin == ch)
64             end = begin;
65           else if (*begin == '\0')
66             end = NULL;
67           else
68             end = strchr (begin + 1, ch);
69         }
70     }
71   else
72     /* Find the end of the token.  */
73     end = strpbrk (begin, delim);
74
75   if (end)
76     {
77       /* Terminate the token and set *STRINGP past NUL character.  */
78       *end++ = '\0';
79       *stringp = end;
80     }
81   else
82     /* No more delimiters; this is the last token.  */
83     *stringp = NULL;
84
85   return begin;
86 }
87 #endif /*HAVE_STRSEP*/
88
89
90 #ifndef HAVE_STRLWR
91 char *
92 strlwr(char *s)
93 {
94     char *p;
95     for(p=s; *p; p++ )
96         *p = tolower(*p);
97     return s;
98 }
99 #endif
100
101 #ifndef HAVE_STRCASECMP
102 int
103 strcasecmp( const char *a, const char *b )
104 {
105     for( ; *a && *b; a++, b++ ) {
106         if( *a != *b && toupper(*a) != toupper(*b) )
107             break;
108     }
109     return *(const byte*)a - *(const byte*)b;
110 }
111 #endif
112
113
114 #ifdef __MINGW32__
115 /* 
116  * Like vsprintf but provides a pointer to malloc'd storage, which
117  * must be freed by the caller (m_free).  Taken from libiberty as
118  * found in gcc-2.95.2 and a little bit modernized.
119  * FIXME: Write a new CRT for W32.
120  */
121 int
122 vasprintf ( char **result, const char *format, va_list args)
123 {
124   const char *p = format;
125   /* Add one to make sure that it is never zero, which might cause malloc
126      to return NULL.  */
127   int total_width = strlen (format) + 1;
128   va_list ap;
129
130   /* this is not really portable but works under Windows */
131   memcpy ( &ap, &args, sizeof (va_list));
132
133   while (*p != '\0')
134     {
135       if (*p++ == '%')
136         {
137           while (strchr ("-+ #0", *p))
138             ++p;
139           if (*p == '*')
140             {
141               ++p;
142               total_width += abs (va_arg (ap, int));
143             }
144           else
145             {
146               char *endp;  
147               total_width += strtoul (p, &endp, 10);
148               p = endp;
149             }
150           if (*p == '.')
151             {
152               ++p;
153               if (*p == '*')
154                 {
155                   ++p;
156                   total_width += abs (va_arg (ap, int));
157                 }
158               else
159                 {
160                   char *endp;
161                   total_width += strtoul (p, &endp, 10);
162                   p = endp;
163                 }
164             }
165           while (strchr ("hlL", *p))
166             ++p;
167           /* Should be big enough for any format specifier except %s
168              and floats.  */
169           total_width += 30;
170           switch (*p)
171             {
172             case 'd':
173             case 'i':
174             case 'o':
175             case 'u':
176             case 'x':
177             case 'X':
178             case 'c':
179               (void) va_arg (ap, int);
180               break;
181             case 'f':
182             case 'e':
183             case 'E':
184             case 'g':
185             case 'G':
186               (void) va_arg (ap, double);
187               /* Since an ieee double can have an exponent of 307, we'll
188                  make the buffer wide enough to cover the gross case. */
189               total_width += 307;
190             
191             case 's':
192               total_width += strlen (va_arg (ap, char *));
193               break;
194             case 'p':
195             case 'n':
196               (void) va_arg (ap, char *);
197               break;
198             }
199         }
200     }
201   *result = m_alloc (total_width);
202   if (*result != NULL)
203     return vsprintf (*result, format, args);
204   else
205     return 0;
206 }
207
208 #endif /*__MINGW32__*/
209