* mpiutil.c (gcry_mpi_swap): New.
[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
91 #ifndef HAVE_STRLWR
92 char *
93 strlwr(char *s)
94 {
95     char *p;
96     for(p=s; *p; p++ )
97         *p = tolower(*p);
98     return s;
99 }
100 #endif
101
102 #ifndef HAVE_STRCASECMP
103 int
104 strcasecmp( const char *a, const char *b )
105 {
106     for( ; *a && *b; a++, b++ ) {
107         if( *a != *b && toupper(*a) != toupper(*b) )
108             break;
109     }
110     return *(const byte*)a - *(const byte*)b;
111 }
112 #endif
113
114
115 #ifdef __MINGW32__
116 /* 
117  * Like vsprintf but provides a pointer to malloc'd storage, which
118  * must be freed by the caller (gcry_free).  Taken from libiberty as
119  * found in gcc-2.95.2 and a little bit modernized.
120  * FIXME: Write a new CRT for W32.
121  */
122 int
123 vasprintf ( char **result, const char *format, va_list args)
124 {
125   const char *p = format;
126   /* Add one to make sure that it is never zero, which might cause malloc
127      to return NULL.  */
128   int total_width = strlen (format) + 1;
129   va_list ap;
130
131   /* this is not really portable but works under Windows */
132   memcpy ( &ap, &args, sizeof (va_list));
133
134   while (*p != '\0')
135     {
136       if (*p++ == '%')
137         {
138           while (strchr ("-+ #0", *p))
139             ++p;
140           if (*p == '*')
141             {
142               ++p;
143               total_width += abs (va_arg (ap, int));
144             }
145           else
146             {
147               char *endp;  
148               total_width += strtoul (p, &endp, 10);
149               p = endp;
150             }
151           if (*p == '.')
152             {
153               ++p;
154               if (*p == '*')
155                 {
156                   ++p;
157                   total_width += abs (va_arg (ap, int));
158                 }
159               else
160                 {
161                   char *endp;
162                   total_width += strtoul (p, &endp, 10);
163                   p = endp;
164                 }
165             }
166           while (strchr ("hlL", *p))
167             ++p;
168           /* Should be big enough for any format specifier except %s
169              and floats.  */
170           total_width += 30;
171           switch (*p)
172             {
173             case 'd':
174             case 'i':
175             case 'o':
176             case 'u':
177             case 'x':
178             case 'X':
179             case 'c':
180               (void) va_arg (ap, int);
181               break;
182             case 'f':
183             case 'e':
184             case 'E':
185             case 'g':
186             case 'G':
187               (void) va_arg (ap, double);
188               /* Since an ieee double can have an exponent of 307, we'll
189                  make the buffer wide enough to cover the gross case. */
190               total_width += 307;
191             
192             case 's':
193               total_width += strlen (va_arg (ap, char *));
194               break;
195             case 'p':
196             case 'n':
197               (void) va_arg (ap, char *);
198               break;
199             }
200         }
201     }
202   *result = gcry_malloc (total_width);
203   if (*result != NULL)
204     return vsprintf (*result, format, args);
205   else
206     return 0;
207 }
208
209 #endif /*__MINGW32__*/
210