* basic.c (check_digests): Add CRC.
[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 #include <ctype.h>
25
26 #include "g10lib.h"
27
28
29 #ifndef HAVE_STPCPY
30 char *
31 stpcpy(char *a,const char *b)
32 {
33     while( *b )
34         *a++ = *b++;
35     *a = 0;
36
37     return (char*)a;
38 }
39 #endif
40
41
42 #ifndef HAVE_STRSEP
43 /* code taken from glibc-2.2.1/sysdeps/generic/strsep.c */
44 char *
45 strsep (char **stringp, const char *delim)
46 {
47   char *begin, *end;
48
49   begin = *stringp;
50   if (begin == NULL)
51     return NULL;
52
53   /* A frequent case is when the delimiter string contains only one
54      character.  Here we don't need to call the expensive `strpbrk'
55      function and instead work using `strchr'.  */
56   if (delim[0] == '\0' || delim[1] == '\0')
57     {
58       char ch = delim[0];
59
60       if (ch == '\0')
61         end = NULL;
62       else
63         {
64           if (*begin == ch)
65             end = begin;
66           else if (*begin == '\0')
67             end = NULL;
68           else
69             end = strchr (begin + 1, ch);
70         }
71     }
72   else
73     /* Find the end of the token.  */
74     end = strpbrk (begin, delim);
75
76   if (end)
77     {
78       /* Terminate the token and set *STRINGP past NUL character.  */
79       *end++ = '\0';
80       *stringp = end;
81     }
82   else
83     /* No more delimiters; this is the last token.  */
84     *stringp = NULL;
85
86   return begin;
87 }
88 #endif /*HAVE_STRSEP*/
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 (gcry_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 = gcry_malloc (total_width);
202   if (*result != NULL)
203     return vsprintf (*result, format, args);
204   else
205     return 0;
206 }
207
208 #endif /*__MINGW32__*/
209