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