e793fc1cee02294dca14274c83cddc87c3b2eb97
[gnupg.git] / util / strgutil.c
1 /* strgutil.c -  string utilities
2  * Copyright (C) 1994, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG 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 General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * 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 #ifdef HAVE_LANGINFO_CODESET
26 #include <langinfo.h>
27 #endif
28
29 #include "types.h"
30 #include "util.h"
31 #include "memory.h"
32
33
34 static ushort koi8_unicode[128] = {
35     0x2500,0x2502,0x250c,0x2510,0x2514,0x2518,0x251c,0x2524,
36     0x252c,0x2534,0x253c,0x2580,0x2584,0x2588,0x258c,0x2590,
37     0x2591,0x2592,0x2593,0x2320,0x25a0,0x2219,0x221a,0x2248,
38     0x2264,0x2265,0x00a0,0x2321,0x00b0,0x00b2,0x00b7,0x00f7,
39     0x2550,0x2551,0x2552,0x0451,0x2553,0x2554,0x2555,0x2556,
40     0x2557,0x2558,0x2559,0x255a,0x255b,0x255c,0x255d,0x255e,
41     0x255f,0x2560,0x2561,0x0401,0x2562,0x2563,0x2564,0x2565,
42     0x2566,0x2567,0x2568,0x2569,0x256a,0x256b,0x256c,0x00a9,
43     0x044e,0x0430,0x0431,0x0446,0x0434,0x0435,0x0444,0x0433,
44     0x0445,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,
45     0x043f,0x044f,0x0440,0x0441,0x0442,0x0443,0x0436,0x0432,
46     0x044c,0x044b,0x0437,0x0448,0x044d,0x0449,0x0447,0x044a,
47     0x042e,0x0410,0x0411,0x0426,0x0414,0x0415,0x0424,0x0413,
48     0x0425,0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,
49     0x041f,0x042f,0x0420,0x0421,0x0422,0x0423,0x0416,0x0412,
50     0x042c,0x042b,0x0417,0x0428,0x042d,0x0429,0x0427,0x042a
51 };
52
53 static ushort latin2_unicode[128] = {
54     0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
55     0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F,
56     0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
57     0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F,
58     0x00A0,0x0104,0x02D8,0x0141,0x00A4,0x013D,0x015A,0x00A7,
59     0x00A8,0x0160,0x015E,0x0164,0x0179,0x00AD,0x017D,0x017B,
60     0x00B0,0x0105,0x02DB,0x0142,0x00B4,0x013E,0x015B,0x02C7,
61     0x00B8,0x0161,0x015F,0x0165,0x017A,0x02DD,0x017E,0x017C,
62     0x0154,0x00C1,0x00C2,0x0102,0x00C4,0x0139,0x0106,0x00C7,
63     0x010C,0x00C9,0x0118,0x00CB,0x011A,0x00CD,0x00CE,0x010E,
64     0x0110,0x0143,0x0147,0x00D3,0x00D4,0x0150,0x00D6,0x00D7,
65     0x0158,0x016E,0x00DA,0x0170,0x00DC,0x00DD,0x0162,0x00DF,
66     0x0155,0x00E1,0x00E2,0x0103,0x00E4,0x013A,0x0107,0x00E7,
67     0x010D,0x00E9,0x0119,0x00EB,0x011B,0x00ED,0x00EE,0x010F,
68     0x0111,0x0144,0x0148,0x00F3,0x00F4,0x0151,0x00F6,0x00F7,
69     0x0159,0x016F,0x00FA,0x0171,0x00FC,0x00FD,0x0163,0x02D9
70 };
71
72
73 static const char *active_charset_name = "iso-8859-1";
74 static ushort *active_charset = NULL;
75 static int no_translation = 0;
76
77 void
78 free_strlist( STRLIST sl )
79 {
80     STRLIST sl2;
81
82     for(; sl; sl = sl2 ) {
83         sl2 = sl->next;
84         m_free(sl);
85     }
86 }
87
88
89 STRLIST
90 add_to_strlist( STRLIST *list, const char *string )
91 {
92     STRLIST sl;
93
94     sl = m_alloc( sizeof *sl + strlen(string));
95     sl->flags = 0;
96     strcpy(sl->d, string);
97     sl->next = *list;
98     *list = sl;
99     return sl;
100 }
101
102 /****************
103  * ame as add_to_strlist() but if is_utf8 is *not* set a conversion
104  * to UTF8 is done
105  */
106 STRLIST
107 add_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
108 {
109     STRLIST sl;
110
111     if( is_utf8 )
112         sl = add_to_strlist( list, string );
113     else {
114         char *p = native_to_utf8( string );
115         sl = add_to_strlist( list, p );
116         m_free( p );
117     }
118     return sl;
119 }
120
121 STRLIST
122 append_to_strlist( STRLIST *list, const char *string )
123 {
124     STRLIST r, sl;
125
126     sl = m_alloc( sizeof *sl + strlen(string));
127     sl->flags = 0;
128     strcpy(sl->d, string);
129     sl->next = NULL;
130     if( !*list )
131         *list = sl;
132     else {
133         for( r = *list; r->next; r = r->next )
134             ;
135         r->next = sl;
136     }
137     return sl;
138 }
139
140 STRLIST
141 append_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
142 {
143     STRLIST sl;
144
145     if( is_utf8 )
146         sl = append_to_strlist( list, string );
147     else {
148         char *p = native_to_utf8( string );
149         sl = append_to_strlist( list, p );
150         m_free( p );
151     }
152     return sl;
153 }
154
155
156 STRLIST
157 strlist_prev( STRLIST head, STRLIST node )
158 {
159     STRLIST n;
160
161     for(n=NULL; head && head != node; head = head->next )
162         n = head;
163     return n;
164 }
165
166 STRLIST
167 strlist_last( STRLIST node )
168 {
169     if( node )
170         for( ; node->next ; node = node->next )
171             ;
172     return node;
173 }
174
175 char *
176 pop_strlist( STRLIST *list )
177 {
178   char *str=NULL;
179   STRLIST sl=*list;
180
181   if(sl)
182     {
183       str=m_alloc(strlen(sl->d)+1);
184       strcpy(str,sl->d);
185
186       *list=sl->next;
187       m_free(sl);
188     }
189
190   return str;
191 }
192
193 /****************
194  * look for the substring SUB in buffer and return a pointer to that
195  * substring in BUF or NULL if not found.
196  * Comparison is case-insensitive.
197  */
198 const char *
199 memistr( const char *buf, size_t buflen, const char *sub )
200 {
201     const byte *t, *s ;
202     size_t n;
203
204     for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
205         if( toupper(*t) == toupper(*s) ) {
206             for( buf=t++, buflen = n--, s++;
207                  n && toupper(*t) == toupper(*s); t++, s++, n-- )
208                 ;
209             if( !*s )
210                 return buf;
211             t = buf; n = buflen; s = sub ;
212         }
213
214     return NULL ;
215 }
216
217 const char *
218 ascii_memistr( const char *buf, size_t buflen, const char *sub )
219 {
220     const byte *t, *s ;
221     size_t n;
222
223     for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
224         if( ascii_toupper(*t) == ascii_toupper(*s) ) {
225             for( buf=t++, buflen = n--, s++;
226                  n && ascii_toupper(*t) == ascii_toupper(*s); t++, s++, n-- )
227                 ;
228             if( !*s )
229                 return buf;
230             t = buf; n = buflen; s = sub ;
231         }
232
233     return NULL ;
234 }
235
236 /****************
237  * Wie strncpy(), aber es werden maximal n-1 zeichen kopiert und ein
238  * '\0' angehängt. Ist n = 0, so geschieht nichts, ist Destination
239  * gleich NULL, so wird via m_alloc Speicher besorgt, ist dann nicht
240  * genügend Speicher vorhanden, so bricht die funktion ab.
241  */
242 char *
243 mem2str( char *dest , const void *src , size_t n )
244 {
245     char *d;
246     const char *s;
247
248     if( n ) {
249         if( !dest )
250             dest = m_alloc( n ) ;
251         d = dest;
252         s = src ;
253         for(n--; n && *s; n-- )
254             *d++ = *s++;
255         *d = '\0' ;
256     }
257
258     return dest ;
259 }
260
261
262 /****************
263  * remove leading and trailing white spaces
264  */
265 char *
266 trim_spaces( char *str )
267 {
268     char *string, *p, *mark;
269
270     string = str;
271     /* find first non space character */
272     for( p=string; *p && isspace( *(byte*)p ) ; p++ )
273         ;
274     /* move characters */
275     for( (mark = NULL); (*string = *p); string++, p++ )
276         if( isspace( *(byte*)p ) ) {
277             if( !mark )
278                 mark = string ;
279         }
280         else
281             mark = NULL ;
282     if( mark )
283         *mark = '\0' ;  /* remove trailing spaces */
284
285     return str ;
286 }
287
288
289
290 unsigned int
291 trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
292 {
293     byte *p, *mark;
294     unsigned n;
295
296     for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
297         if( strchr(trimchars, *p ) ) {
298             if( !mark )
299                 mark = p;
300         }
301         else
302             mark = NULL;
303     }
304
305     if( mark ) {
306         *mark = 0;
307         return mark - line;
308     }
309     return len;
310 }
311
312 /****************
313  * remove trailing white spaces and return the length of the buffer
314  */
315 unsigned
316 trim_trailing_ws( byte *line, unsigned len )
317 {
318     return trim_trailing_chars( line, len, " \t\r\n" );
319 }
320
321 unsigned int
322 check_trailing_chars( const byte *line, unsigned int len,
323                       const char *trimchars )
324 {
325     const byte *p, *mark;
326     unsigned int n;
327
328     for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
329         if( strchr(trimchars, *p ) ) {
330             if( !mark )
331                 mark = p;
332         }
333         else
334             mark = NULL;
335     }
336
337     if( mark ) {
338         return mark - line;
339     }
340     return len;
341 }
342
343 /****************
344  * remove trailing white spaces and return the length of the buffer
345  */
346 unsigned int
347 check_trailing_ws( const byte *line, unsigned int len )
348 {
349     return check_trailing_chars( line, len, " \t\r\n" );
350 }
351
352
353
354 int
355 string_count_chr( const char *string, int c )
356 {
357     int count;
358     for(count=0; *string; string++ )
359         if( *string == c )
360             count++;
361     return count;
362 }
363
364
365 int
366 set_native_charset( const char *newset )
367 {
368     if (!newset) 
369 #ifdef HAVE_LANGINFO_CODESET
370         newset = nl_langinfo (CODESET);
371 #else
372         newset = "8859-1";
373 #endif
374
375     if (strlen (newset) > 3 && !ascii_memcasecmp (newset, "iso", 3)) {
376         newset += 3;
377         if (*newset == '-' || *newset == '_')
378             newset++;
379     }
380
381     if( !*newset
382         || !ascii_strcasecmp (newset, "8859-1" )
383         || !ascii_strcasecmp (newset, "8859-15" ) ) {
384         active_charset_name = "iso-8859-1";
385         no_translation = 0;
386         active_charset = NULL;
387     }
388     else if( !ascii_strcasecmp( newset, "8859-2" ) ) {
389         active_charset_name = "iso-8859-2";
390         no_translation = 0;
391         active_charset = latin2_unicode;
392     }
393     else if( !ascii_strcasecmp( newset, "koi8-r" ) ) {
394         active_charset_name = "koi8-r";
395         no_translation = 0;
396         active_charset = koi8_unicode;
397     }
398     else if( !ascii_strcasecmp (newset, "utf8" )
399              || !ascii_strcasecmp(newset, "utf-8") ) {
400         active_charset_name = "utf-8";
401         no_translation = 1;
402         active_charset = NULL;
403     }
404     else
405         return G10ERR_GENERAL;
406     return 0;
407 }
408
409 const char*
410 get_native_charset()
411 {
412     return active_charset_name;
413 }
414
415 /****************
416  * Convert string, which is in native encoding to UTF8 and return the
417  * new allocated UTF8 string.
418  */
419 char *
420 native_to_utf8( const char *string )
421 {
422     const byte *s;
423     char *buffer;
424     byte *p;
425     size_t length=0;
426
427     if (no_translation) {
428         buffer = m_strdup (string);
429     }
430     else if( active_charset ) {
431         for(s=string; *s; s++ ) {
432             length++;
433             if( *s & 0x80 )
434                 length += 2; /* we may need 3 bytes */
435         }
436         buffer = m_alloc( length + 1 );
437         for(p=buffer, s=string; *s; s++ ) {
438             if( *s & 0x80 ) {
439                 ushort val = active_charset[ *s & 0x7f ];
440                 if( val < 0x0800 ) {
441                     *p++ = 0xc0 | ( (val >> 6) & 0x1f );
442                     *p++ = 0x80 | (  val & 0x3f );
443                 }
444                 else {
445                     *p++ = 0xe0 | ( (val >> 12) & 0x0f );
446                     *p++ = 0x80 | ( (val >>  6) & 0x3f );
447                     *p++ = 0x80 | (  val & 0x3f );
448                 }
449             }
450             else
451                 *p++ = *s;
452         }
453         *p = 0;
454     }
455     else {
456         for(s=string; *s; s++ ) {
457             length++;
458             if( *s & 0x80 )
459                 length++;
460         }
461         buffer = m_alloc( length + 1 );
462         for(p=buffer, s=string; *s; s++ ) {
463             if( *s & 0x80 ) {
464                 *p++ = 0xc0 | ((*s >> 6) & 3);
465                 *p++ = 0x80 | ( *s & 0x3f );
466             }
467             else
468                 *p++ = *s;
469         }
470         *p = 0;
471     }
472     return buffer;
473 }
474
475
476 /****************
477  * Convert string, which is in UTF8 to native encoding.  illegal
478  * encodings by some "\xnn" and quote all control characters. A
479  * character with value DELIM will always be quoted, it must be a
480  * vanilla ASCII character.  
481   */
482 char *
483 utf8_to_native( const char *string, size_t length, int delim )
484 {
485     int nleft;
486     int i;
487     byte encbuf[8];
488     int encidx;
489     const byte *s;
490     size_t n;
491     byte *buffer = NULL, *p = NULL;
492     unsigned long val = 0;
493     size_t slen;
494     int resync = 0;
495
496     /* 1. pass (p==NULL): count the extended utf-8 characters */
497     /* 2. pass (p!=NULL): create string */
498     for( ;; ) {
499         for( slen=length, nleft=encidx=0, n=0, s=string; slen; s++, slen-- ) {
500             if( resync ) {
501                 if( !(*s < 128 || (*s >= 0xc0 && *s <= 0xfd)) ) {
502                     /* still invalid */
503                     if( p ) {
504                         sprintf(p, "\\x%02x", *s );
505                         p += 4;
506                     }
507                     n += 4;
508                     continue;
509                 }
510                 resync = 0;
511             }
512             if( !nleft ) {
513                 if( !(*s & 0x80) ) { /* plain ascii */
514                     if( *s < 0x20 || *s == 0x7f || *s == delim ||
515                         (delim && *s=='\\')) {
516                         n++;
517                         if( p )
518                             *p++ = '\\';
519                         switch( *s ) {
520                           case '\n': n++; if( p ) *p++ = 'n'; break;
521                           case '\r': n++; if( p ) *p++ = 'r'; break;
522                           case '\f': n++; if( p ) *p++ = 'f'; break;
523                           case '\v': n++; if( p ) *p++ = 'v'; break;
524                           case '\b': n++; if( p ) *p++ = 'b'; break;
525                           case   0 : n++; if( p ) *p++ = '0'; break;
526                           default:
527                             n += 3;
528                             if ( p ) {
529                                 sprintf( p, "x%02x", *s );
530                                 p += 3;
531                             }
532                             break;
533                         }
534                     }
535                     else {
536                         if( p ) *p++ = *s;
537                         n++;
538                     }
539                 }
540                 else if( (*s & 0xe0) == 0xc0 ) { /* 110x xxxx */
541                     val = *s & 0x1f;
542                     nleft = 1;
543                     encidx = 0;
544                     encbuf[encidx++] = *s;
545                 }
546                 else if( (*s & 0xf0) == 0xe0 ) { /* 1110 xxxx */
547                     val = *s & 0x0f;
548                     nleft = 2;
549                     encidx = 0;
550                     encbuf[encidx++] = *s;
551                 }
552                 else if( (*s & 0xf8) == 0xf0 ) { /* 1111 0xxx */
553                     val = *s & 0x07;
554                     nleft = 3;
555                     encidx = 0;
556                     encbuf[encidx++] = *s;
557                 }
558                 else if( (*s & 0xfc) == 0xf8 ) { /* 1111 10xx */
559                     val = *s & 0x03;
560                     nleft = 4;
561                     encidx = 0;
562                     encbuf[encidx++] = *s;
563                 }
564                 else if( (*s & 0xfe) == 0xfc ) { /* 1111 110x */
565                     val = *s & 0x01;
566                     nleft = 5;
567                     encidx = 0;
568                     encbuf[encidx++] = *s;
569                 }
570                 else {  /* invalid encoding: print as \xnn */
571                     if( p ) {
572                         sprintf(p, "\\x%02x", *s );
573                         p += 4;
574                     }
575                     n += 4;
576                     resync = 1;
577                 }
578             }
579             else if( *s < 0x80 || *s >= 0xc0 ) { /* invalid */
580                 if( p ) {
581                     for(i=0; i < encidx; i++ ) {
582                         sprintf(p, "\\x%02x", encbuf[i] );
583                         p += 4;
584                     }
585                     sprintf(p, "\\x%02x", *s );
586                     p += 4;
587                 }
588                 n += 4 + 4*encidx;
589                 nleft = 0;
590                 encidx = 0;
591                 resync = 1;
592             }
593             else {
594                 encbuf[encidx++] = *s;
595                 val <<= 6;
596                 val |= *s & 0x3f;
597                 if( !--nleft ) { /* ready */
598                     if (no_translation) {
599                         if( p ) {
600                             for(i=0; i < encidx; i++ )
601                                 *p++ = encbuf[i];
602                         }
603                         n += encidx;
604                         encidx = 0;
605                     }
606                     else if( active_charset ) { /* table lookup */
607                         for(i=0; i < 128; i++ ) {
608                             if( active_charset[i] == val )
609                                 break;
610                         }
611                         if( i < 128 ) { /* we can print this one */
612                             if( p ) *p++ = i+128;
613                             n++;
614                         }
615                         else { /* we do not have a translation: print utf8 */
616                             if( p ) {
617                                 for(i=0; i < encidx; i++ ) {
618                                     sprintf(p, "\\x%02x", encbuf[i] );
619                                     p += 4;
620                                 }
621                             }
622                             n += encidx*4;
623                             encidx = 0;
624                         }
625                     }
626                     else { /* native set */
627                         if( val >= 0x80 && val < 256 ) {
628                             n++;    /* we can simply print this character */
629                             if( p ) *p++ = val;
630                         }
631                         else { /* we do not have a translation: print utf8 */
632                             if( p ) {
633                                 for(i=0; i < encidx; i++ ) {
634                                     sprintf(p, "\\x%02x", encbuf[i] );
635                                     p += 4;
636                                 }
637                             }
638                             n += encidx*4;
639                             encidx = 0;
640                         }
641                     }
642                 }
643
644             }
645         }
646         if( !buffer ) { /* allocate the buffer after the first pass */
647             buffer = p = m_alloc( n + 1 );
648         }
649         else {
650             *p = 0; /* make a string */
651             return buffer;
652         }
653     }
654 }
655
656 /****************************************************
657  ******** locale insensitive ctype functions ********
658  ****************************************************/
659 /* FIXME: replace them by a table lookup and macros */
660 int
661 ascii_isupper (int c)
662 {
663     return c >= 'A' && c <= 'Z';
664 }
665
666 int
667 ascii_islower (int c)
668 {
669     return c >= 'a' && c <= 'z';
670 }
671
672 int 
673 ascii_toupper (int c)
674 {
675     if (c >= 'a' && c <= 'z')
676         c &= ~0x20;
677     return c;
678 }
679
680 int 
681 ascii_tolower (int c)
682 {
683     if (c >= 'A' && c <= 'Z')
684         c |= 0x20;
685     return c;
686 }
687
688
689 int
690 ascii_strcasecmp (const char *a, const char *b)
691 {
692   const unsigned char *p1 = (const unsigned char *)a;
693   const unsigned char *p2 = (const unsigned char *)b;
694   unsigned char c1, c2;
695
696   if (p1 == p2)
697     return 0;
698
699   do
700     {
701       c1 = ascii_tolower (*p1);
702       c2 = ascii_tolower (*p2);
703
704       if (c1 == '\0')
705         break;
706
707       ++p1;
708       ++p2;
709     }
710   while (c1 == c2);
711   
712   return c1 - c2;
713 }
714
715 int 
716 ascii_strncasecmp (const char *a, const char *b, size_t n)
717 {
718   const unsigned char *p1 = (const unsigned char *)a;
719   const unsigned char *p2 = (const unsigned char *)b;
720   unsigned char c1, c2;
721
722   if (p1 == p2 || !n )
723     return 0;
724
725   do
726     {
727       c1 = ascii_tolower (*p1);
728       c2 = ascii_tolower (*p2);
729
730       if ( !--n || c1 == '\0')
731         break;
732
733       ++p1;
734       ++p2;
735     }
736   while (c1 == c2);
737   
738   return c1 - c2;
739 }
740
741
742 int
743 ascii_memcasecmp( const char *a, const char *b, size_t n )
744 {
745     if (a == b)
746         return 0;
747     for ( ; n; n--, a++, b++ ) {
748         if( *a != *b  && ascii_toupper (*a) != ascii_toupper (*b) )
749             return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
750     }
751     return 0;
752 }
753
754
755
756 /*********************************************
757  ********** missing string functions *********
758  *********************************************/
759
760 #ifndef HAVE_STPCPY
761 char *
762 stpcpy(char *a,const char *b)
763 {
764     while( *b )
765         *a++ = *b++;
766     *a = 0;
767
768     return (char*)a;
769 }
770 #endif
771
772
773 #ifndef HAVE_STRSEP
774 /* code taken from glibc-2.2.1/sysdeps/generic/strsep.c */
775 char *
776 strsep (char **stringp, const char *delim)
777 {
778   char *begin, *end;
779
780   begin = *stringp;
781   if (begin == NULL)
782     return NULL;
783
784   /* A frequent case is when the delimiter string contains only one
785      character.  Here we don't need to call the expensive `strpbrk'
786      function and instead work using `strchr'.  */
787   if (delim[0] == '\0' || delim[1] == '\0')
788     {
789       char ch = delim[0];
790
791       if (ch == '\0')
792         end = NULL;
793       else
794         {
795           if (*begin == ch)
796             end = begin;
797           else if (*begin == '\0')
798             end = NULL;
799           else
800             end = strchr (begin + 1, ch);
801         }
802     }
803   else
804     /* Find the end of the token.  */
805     end = strpbrk (begin, delim);
806
807   if (end)
808     {
809       /* Terminate the token and set *STRINGP past NUL character.  */
810       *end++ = '\0';
811       *stringp = end;
812     }
813   else
814     /* No more delimiters; this is the last token.  */
815     *stringp = NULL;
816
817   return begin;
818 }
819 #endif /*HAVE_STRSEP*/
820
821
822 #ifndef HAVE_STRLWR
823 char *
824 strlwr(char *s)
825 {
826     char *p;
827     for(p=s; *p; p++ )
828         *p = tolower(*p);
829     return s;
830 }
831 #endif
832
833 #ifndef HAVE_STRCASECMP
834 int
835 strcasecmp( const char *a, const char *b )
836 {
837     for( ; *a && *b; a++, b++ ) {
838         if( *a != *b && toupper(*a) != toupper(*b) )
839             break;
840     }
841     return *(const byte*)a - *(const byte*)b;
842 }
843 #endif
844
845 #ifndef HAVE_STRNCASECMP
846 int
847 strncasecmp( const char *a, const char *b, size_t n )
848 {
849     for( ; n && *a && *b; a++, b++, n--) {
850         if( *a != *b && toupper(*a) != toupper(*b) )
851             break;
852     }
853     if (!n)
854       return 0;
855     return *(const byte*)a - *(const byte*)b;
856 }
857 #endif
858
859
860 #ifdef __MINGW32__
861 /* 
862  * Like vsprintf but provides a pointer to malloc'd storage, which
863  * must be freed by the caller (m_free).  Taken from libiberty as
864  * found in gcc-2.95.2 and a little bit modernized.
865  * FIXME: Write a new CRT for W32.
866  */
867 int
868 vasprintf ( char **result, const char *format, va_list args)
869 {
870   const char *p = format;
871   /* Add one to make sure that it is never zero, which might cause malloc
872      to return NULL.  */
873   int total_width = strlen (format) + 1;
874   va_list ap;
875
876   /* this is not really portable but works under Windows */
877   memcpy ( &ap, &args, sizeof (va_list));
878
879   while (*p != '\0')
880     {
881       if (*p++ == '%')
882         {
883           while (strchr ("-+ #0", *p))
884             ++p;
885           if (*p == '*')
886             {
887               ++p;
888               total_width += abs (va_arg (ap, int));
889             }
890           else
891             {
892               char *endp;  
893               total_width += strtoul (p, &endp, 10);
894               p = endp;
895             }
896           if (*p == '.')
897             {
898               ++p;
899               if (*p == '*')
900                 {
901                   ++p;
902                   total_width += abs (va_arg (ap, int));
903                 }
904               else
905                 {
906                   char *endp;
907                   total_width += strtoul (p, &endp, 10);
908                   p = endp;
909                 }
910             }
911           while (strchr ("hlL", *p))
912             ++p;
913           /* Should be big enough for any format specifier except %s
914              and floats.  */
915           total_width += 30;
916           switch (*p)
917             {
918             case 'd':
919             case 'i':
920             case 'o':
921             case 'u':
922             case 'x':
923             case 'X':
924             case 'c':
925               (void) va_arg (ap, int);
926               break;
927             case 'f':
928             case 'e':
929             case 'E':
930             case 'g':
931             case 'G':
932               (void) va_arg (ap, double);
933               /* Since an ieee double can have an exponent of 307, we'll
934                  make the buffer wide enough to cover the gross case. */
935               total_width += 307;
936             
937             case 's':
938               total_width += strlen (va_arg (ap, char *));
939               break;
940             case 'p':
941             case 'n':
942               (void) va_arg (ap, char *);
943               break;
944             }
945         }
946     }
947   *result = m_alloc (total_width);
948   if (*result != NULL)
949     return vsprintf (*result, format, args);
950   else
951     return 0;
952 }
953
954 #endif /*__MINGW32__*/
955