1
/* strgutil.c - string utilities
2
* Copyright (C) 1994, 1998, 1999, 2000, 2001,
3
* 2003 Free Software Foundation, Inc.
5
* This file is part of GnuPG.
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.
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.
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
27
#ifdef HAVE_LANGINFO_CODESET
31
/* For W32 we use dynamic loading of the iconv dll and don't need any
32
* iconv headers at all. */
35
# undef USE_GNUPG_ICONV
39
#ifdef USE_GNUPG_ICONV
53
#ifndef USE_GNUPG_ICONV
54
static ushort koi8_unicode[128] = {
55
0x2500,0x2502,0x250c,0x2510,0x2514,0x2518,0x251c,0x2524,
56
0x252c,0x2534,0x253c,0x2580,0x2584,0x2588,0x258c,0x2590,
57
0x2591,0x2592,0x2593,0x2320,0x25a0,0x2219,0x221a,0x2248,
58
0x2264,0x2265,0x00a0,0x2321,0x00b0,0x00b2,0x00b7,0x00f7,
59
0x2550,0x2551,0x2552,0x0451,0x2553,0x2554,0x2555,0x2556,
60
0x2557,0x2558,0x2559,0x255a,0x255b,0x255c,0x255d,0x255e,
61
0x255f,0x2560,0x2561,0x0401,0x2562,0x2563,0x2564,0x2565,
62
0x2566,0x2567,0x2568,0x2569,0x256a,0x256b,0x256c,0x00a9,
63
0x044e,0x0430,0x0431,0x0446,0x0434,0x0435,0x0444,0x0433,
64
0x0445,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,
65
0x043f,0x044f,0x0440,0x0441,0x0442,0x0443,0x0436,0x0432,
66
0x044c,0x044b,0x0437,0x0448,0x044d,0x0449,0x0447,0x044a,
67
0x042e,0x0410,0x0411,0x0426,0x0414,0x0415,0x0424,0x0413,
68
0x0425,0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,
69
0x041f,0x042f,0x0420,0x0421,0x0422,0x0423,0x0416,0x0412,
70
0x042c,0x042b,0x0417,0x0428,0x042d,0x0429,0x0427,0x042a
73
static ushort latin2_unicode[128] = {
74
0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
75
0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F,
76
0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
77
0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F,
78
0x00A0,0x0104,0x02D8,0x0141,0x00A4,0x013D,0x015A,0x00A7,
79
0x00A8,0x0160,0x015E,0x0164,0x0179,0x00AD,0x017D,0x017B,
80
0x00B0,0x0105,0x02DB,0x0142,0x00B4,0x013E,0x015B,0x02C7,
81
0x00B8,0x0161,0x015F,0x0165,0x017A,0x02DD,0x017E,0x017C,
82
0x0154,0x00C1,0x00C2,0x0102,0x00C4,0x0139,0x0106,0x00C7,
83
0x010C,0x00C9,0x0118,0x00CB,0x011A,0x00CD,0x00CE,0x010E,
84
0x0110,0x0143,0x0147,0x00D3,0x00D4,0x0150,0x00D6,0x00D7,
85
0x0158,0x016E,0x00DA,0x0170,0x00DC,0x00DD,0x0162,0x00DF,
86
0x0155,0x00E1,0x00E2,0x0103,0x00E4,0x013A,0x0107,0x00E7,
87
0x010D,0x00E9,0x0119,0x00EB,0x011B,0x00ED,0x00EE,0x010F,
88
0x0111,0x0144,0x0148,0x00F3,0x00F4,0x0151,0x00F6,0x00F7,
89
0x0159,0x016F,0x00FA,0x0171,0x00FC,0x00FD,0x0163,0x02D9
91
#endif /*!USE_GNUPG_ICONV*/
99
static const char *active_charset_name = "iso-8859-1";
100
static ushort *active_charset = NULL;
101
static int no_translation = 0;
102
static int use_iconv = 0;
106
typedef void* iconv_t;
108
#define ICONV_CONST const
111
iconv_t (* __stdcall iconv_open) (const char *tocode, const char *fromcode);
112
size_t (* __stdcall iconv) (iconv_t cd,
113
const char **inbuf, size_t *inbytesleft,
114
char **outbuf, size_t *outbytesleft);
115
int (* __stdcall iconv_close) (iconv_t cd);
131
done = 1; /* Do it right now because we might get called recursivly
134
handle = dlopen ("iconv.dll", RTLD_LAZY);
137
iconv_open = dlsym (handle, "libiconv_open");
139
iconv = dlsym (handle, "libiconv");
141
iconv_close = dlsym (handle, "libiconv_close");
143
if (!handle || !iconv_close)
145
log_info (_("error loading `%s': %s\n"),
146
"iconv.dll", dlerror ());
147
log_info(_("please see http://www.gnupg.org/download/iconv.html "
148
"for more information\n"));
156
return iconv_open? 0: -1;
164
free_strlist( STRLIST sl )
168
for(; sl; sl = sl2 ) {
176
add_to_strlist( STRLIST *list, const char *string )
180
sl = m_alloc( sizeof *sl + strlen(string));
182
strcpy(sl->d, string);
189
* Same as add_to_strlist() but if is_utf8 is *not* set a conversion
193
add_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
198
sl = add_to_strlist( list, string );
200
char *p = native_to_utf8( string );
201
sl = add_to_strlist( list, p );
208
append_to_strlist( STRLIST *list, const char *string )
212
sl = m_alloc( sizeof *sl + strlen(string));
214
strcpy(sl->d, string);
219
for( r = *list; r->next; r = r->next )
227
append_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
232
sl = append_to_strlist( list, string );
234
char *p = native_to_utf8( string );
235
sl = append_to_strlist( list, p );
243
strlist_prev( STRLIST head, STRLIST node )
247
for(n=NULL; head && head != node; head = head->next )
253
strlist_last( STRLIST node )
256
for( ; node->next ; node = node->next )
262
pop_strlist( STRLIST *list )
269
str=m_alloc(strlen(sl->d)+1);
280
* Look for the substring SUB in buffer and return a pointer to that
281
* substring in BUF or NULL if not found.
282
* Comparison is case-insensitive.
285
memistr( const char *buf, size_t buflen, const char *sub )
290
for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
291
if( toupper(*t) == toupper(*s) ) {
292
for( buf=t++, buflen = n--, s++;
293
n && toupper(*t) == toupper(*s); t++, s++, n-- )
297
t = buf; n = buflen; s = sub ;
304
ascii_memistr( const char *buf, size_t buflen, const char *sub )
309
for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
310
if( ascii_toupper(*t) == ascii_toupper(*s) ) {
311
for( buf=t++, buflen = n--, s++;
312
n && ascii_toupper(*t) == ascii_toupper(*s); t++, s++, n-- )
316
t = buf; n = buflen; s = sub ;
323
/* Like strncpy() but copy at max N-1 bytes and append a '\0'. With
324
* N given as 0 nothing is copied at all. With DEST given as NULL
325
* sufficient memory is allocated using m_alloc (note that m_alloc is
326
* guaranteed to succeed or to abort the process). */
328
mem2str( char *dest , const void *src , size_t n )
335
dest = m_alloc( n ) ;
338
for(n--; n && *s; n-- )
348
* Remove leading and trailing white spaces
351
trim_spaces( char *str )
353
char *string, *p, *mark;
356
/* Find first non space character. */
357
for( p=string; *p && isspace( *(byte*)p ) ; p++ )
359
/* Move characters. */
360
for( (mark = NULL); (*string = *p); string++, p++ )
361
if( isspace( *(byte*)p ) ) {
368
*mark = '\0' ; /* Remove trailing spaces. */
376
trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
381
for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
382
if( strchr(trimchars, *p ) ) {
398
* Remove trailing white spaces and return the length of the buffer
401
trim_trailing_ws( byte *line, unsigned len )
403
return trim_trailing_chars( line, len, " \t\r\n" );
408
check_trailing_chars( const byte *line, unsigned int len,
409
const char *trimchars )
411
const byte *p, *mark;
414
for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
415
if( strchr(trimchars, *p ) ) {
431
* Remove trailing white spaces and return the length of the buffer
434
check_trailing_ws( const byte *line, unsigned int len )
436
return check_trailing_chars( line, len, " \t\r\n" );
442
string_count_chr( const char *string, int c )
445
for(count=0; *string; string++ )
451
#ifdef USE_GNUPG_ICONV
453
handle_iconv_error (const char *to, const char *from, int use_fallback)
456
log_info (_("conversion from `%s' to `%s' not available\n"),
459
log_info (_("iconv_open failed: %s\n"), strerror (errno));
463
/* To avoid further error messages we fallback to Latin-1 for the
464
native encoding. This is justified as one can expect that on a
465
utf-8 enabled system nl_langinfo() will work and thus we won't
466
never get to here. Thus Latin-1 seems to be a reasonable
468
active_charset_name = "iso-8859-1";
470
active_charset = NULL;
474
#endif /*USE_GNUPG_ICONV*/
477
set_native_charset( const char *newset )
479
const char *full_newset;
483
static char codepage[30];
486
/* We are a console program thus we need to use the
487
GetConsoleOutputCP function and not the the GetACP which
488
would give the codepage for a GUI program. Note this is
489
not a bulletproof detection because GetConsoleCP might
490
return a different one for console input. Not sure how to
491
cope with that. If the console Code page is not known we
492
fall back to the system code page. */
493
cpno = GetConsoleOutputCP ();
496
sprintf (codepage, "CP%u", cpno );
497
/* If it is the Windows name for Latin-1 we use the standard
498
name instead to avoid loading of iconv.dll. Unfortunately
499
it is often CP850 and we don't have a custom translation
501
if (!strcmp (codepage, "CP1252"))
502
newset = "iso-8859-1";
506
#ifdef HAVE_LANGINFO_CODESET
507
newset = nl_langinfo (CODESET);
508
#else /* !HAVE_LANGINFO_CODESET */
509
/* Try to get the used charset from environment variables. */
510
static char codepage[30];
511
const char *lc, *dot, *mod;
513
strcpy (codepage, "iso-8859-1");
514
lc = getenv ("LC_ALL");
516
lc = getenv ("LC_CTYPE");
518
lc = getenv ("LANG");
521
dot = strchr (lc, '.');
523
mod = strchr (++dot, '@');
525
mod = dot + strlen (dot);
526
if (mod - dot < sizeof codepage && dot != mod) {
527
memcpy (codepage, dot, mod - dot);
528
codepage [mod - dot] = 0;
533
#endif /* !HAVE_LANGINFO_CODESET */
537
full_newset = newset;
538
if (strlen (newset) > 3 && !ascii_memcasecmp (newset, "iso", 3)) {
540
if (*newset == '-' || *newset == '_')
544
/* Note that we silently assume that plain ASCII is actually meant
545
as Latin-1. This makes sense because many Unix system don't
546
have their locale set up properly and thus would get annoying
547
error messages and we have to handle all the "bug"
548
reports. Latin-1 has always been the character set used for 8
549
bit characters on Unix systems. */
551
|| !ascii_strcasecmp (newset, "8859-1" )
552
|| !ascii_strcasecmp (newset, "646" )
553
|| !ascii_strcasecmp (newset, "ASCII" )
554
|| !ascii_strcasecmp (newset, "ANSI_X3.4-1968" )
556
active_charset_name = "iso-8859-1";
558
active_charset = NULL;
561
else if( !ascii_strcasecmp (newset, "utf8" )
562
|| !ascii_strcasecmp(newset, "utf-8") ) {
563
active_charset_name = "utf-8";
565
active_charset = NULL;
568
#ifdef USE_GNUPG_ICONV
573
if (load_libiconv ())
574
return G10ERR_GENERAL;
577
cd = iconv_open (full_newset, "utf-8");
578
if (cd == (iconv_t)-1) {
579
handle_iconv_error (full_newset, "utf-8", 0);
580
return G10ERR_GENERAL;
583
cd = iconv_open ("utf-8", full_newset);
584
if (cd == (iconv_t)-1) {
585
handle_iconv_error ("utf-8", full_newset, 0);
586
return G10ERR_GENERAL;
589
active_charset_name = full_newset;
591
active_charset = NULL;
594
#else /*!USE_GNUPG_ICONV*/
595
else if( !ascii_strcasecmp( newset, "8859-2" ) ) {
596
active_charset_name = "iso-8859-2";
598
active_charset = latin2_unicode;
601
else if( !ascii_strcasecmp( newset, "koi8-r" ) ) {
602
active_charset_name = "koi8-r";
604
active_charset = koi8_unicode;
608
return G10ERR_GENERAL;
609
#endif /*!USE_GNUPG_ICONV*/
616
return active_charset_name;
620
* Convert string, which is in native encoding to UTF8 and return the
621
* new allocated UTF8 string.
624
native_to_utf8( const char *string )
632
{ /* Already utf-8 encoded. */
633
buffer = m_strdup (string);
635
else if( !active_charset && !use_iconv) /* Shortcut implementation
638
for(s=string; *s; s++ )
644
buffer = m_alloc( length + 1 );
645
for(p=buffer, s=string; *s; s++ )
649
*p++ = 0xc0 | ((*s >> 6) & 3);
650
*p++ = 0x80 | ( *s & 0x3f );
657
else /* Need to use a translation table. */
659
#ifdef USE_GNUPG_ICONV
663
size_t inbytes, outbytes;
665
cd = iconv_open ("utf-8", active_charset_name);
666
if (cd == (iconv_t)-1)
668
handle_iconv_error ("utf-8", active_charset_name, 1);
669
return native_to_utf8 (string);
672
for (s=string; *s; s++ )
676
length += 5; /* We may need up to 6 bytes for the utf8 output. */
678
buffer = m_alloc (length + 1);
681
inbytes = strlen (string);
684
if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
685
&outptr, &outbytes) == (size_t)-1)
687
log_info (_("conversion from `%s' to `%s' failed: %s\n"),
688
active_charset_name, "utf-8", strerror (errno));
689
/* We don't do any conversion at all but use the strings as is. */
690
strcpy (buffer, string);
695
/* We could realloc the buffer now but I doubt that it makes
696
much sense given that it will get freed anyway soon
701
#else /*!USE_GNUPG_ICONV*/
702
for(s=string; *s; s++ )
706
length += 2; /* We may need up to 3 bytes. */
708
buffer = m_alloc( length + 1 );
709
for(p=buffer, s=string; *s; s++ ) {
711
ushort val = active_charset[ *s & 0x7f ];
713
*p++ = 0xc0 | ( (val >> 6) & 0x1f );
714
*p++ = 0x80 | ( val & 0x3f );
717
*p++ = 0xe0 | ( (val >> 12) & 0x0f );
718
*p++ = 0x80 | ( (val >> 6) & 0x3f );
719
*p++ = 0x80 | ( val & 0x3f );
726
#endif /*!USE_GNUPG_ICONV*/
734
* Convert string, which is in UTF8 to native encoding. illegal
735
* encodings by some "\xnn" and quote all control characters. A
736
* character with value DELIM will always be quoted, it must be a
737
* vanilla ASCII character. A DELIM value of -1 is special: it disables
738
* all quoting of control characters.
741
utf8_to_native( const char *string, size_t length, int delim )
749
byte *buffer = NULL, *p = NULL;
750
unsigned long val = 0;
754
/* 1. pass (p==NULL): count the extended utf-8 characters */
755
/* 2. pass (p!=NULL): create string */
757
for( slen=length, nleft=encidx=0, n=0, s=string; slen; s++, slen-- ) {
759
if( !(*s < 128 || (*s >= 0xc0 && *s <= 0xfd)) ) {
762
sprintf(p, "\\x%02x", *s );
771
if( !(*s & 0x80) ) { /* plain ascii */
773
&& (*s < 0x20 || *s == 0x7f || *s == delim
774
|| (delim && *s=='\\'))) {
779
case '\n': n++; if( p ) *p++ = 'n'; break;
780
case '\r': n++; if( p ) *p++ = 'r'; break;
781
case '\f': n++; if( p ) *p++ = 'f'; break;
782
case '\v': n++; if( p ) *p++ = 'v'; break;
783
case '\b': n++; if( p ) *p++ = 'b'; break;
784
case 0 : n++; if( p ) *p++ = '0'; break;
788
sprintf( p, "x%02x", *s );
799
else if( (*s & 0xe0) == 0xc0 ) { /* 110x xxxx */
803
encbuf[encidx++] = *s;
805
else if( (*s & 0xf0) == 0xe0 ) { /* 1110 xxxx */
809
encbuf[encidx++] = *s;
811
else if( (*s & 0xf8) == 0xf0 ) { /* 1111 0xxx */
815
encbuf[encidx++] = *s;
817
else if( (*s & 0xfc) == 0xf8 ) { /* 1111 10xx */
821
encbuf[encidx++] = *s;
823
else if( (*s & 0xfe) == 0xfc ) { /* 1111 110x */
827
encbuf[encidx++] = *s;
829
else { /* invalid encoding: print as \xnn */
831
sprintf(p, "\\x%02x", *s );
838
else if( *s < 0x80 || *s >= 0xc0 ) { /* invalid */
840
for(i=0; i < encidx; i++ ) {
841
sprintf(p, "\\x%02x", encbuf[i] );
844
sprintf(p, "\\x%02x", *s );
853
encbuf[encidx++] = *s;
856
if( !--nleft ) { /* ready */
857
if (no_translation) {
859
for(i=0; i < encidx; i++ )
865
#ifdef USE_GNUPG_ICONV
867
/* Our strategy for using iconv is a bit
868
* strange but it better keeps compatibility
869
* with previous versions in regard to how
870
* invalid encodings are displayed. What we
871
* do is to keep the utf-8 as is and have the
872
* real translation step then at the end.
873
* Yes, I know that this is ugly. However we
874
* are short of the 1.4 release and for this
875
* branch we should not mee too much around
876
* with iconv things. One reason for this is
877
* that we don't know enough about non-GNU
878
* iconv implementation and want to minimize
879
* the risk of breaking the code on too many
882
for(i=0; i < encidx; i++ )
888
#endif /*USE_GNUPG_ICONV*/
889
else if( active_charset ) { /* table lookup */
890
for(i=0; i < 128; i++ ) {
891
if( active_charset[i] == val )
894
if( i < 128 ) { /* we can print this one */
895
if( p ) *p++ = i+128;
898
else { /* we do not have a translation: print utf8 */
900
for(i=0; i < encidx; i++ ) {
901
sprintf(p, "\\x%02x", encbuf[i] );
909
else { /* native set */
910
if( val >= 0x80 && val < 256 ) {
911
n++; /* we can simply print this character */
914
else { /* we do not have a translation: print utf8 */
916
for(i=0; i < encidx; i++ ) {
917
sprintf(p, "\\x%02x", encbuf[i] );
929
if( !buffer ) { /* allocate the buffer after the first pass */
930
buffer = p = m_alloc( n + 1 );
932
#ifdef USE_GNUPG_ICONV
934
/* Note: See above for comments. */
937
char *outbuf, *outptr;
938
size_t inbytes, outbytes;
940
*p = 0; /* Terminate the buffer. */
942
cd = iconv_open (active_charset_name, "utf-8");
943
if (cd == (iconv_t)-1)
945
handle_iconv_error (active_charset_name, "utf-8", 1);
947
return utf8_to_native (string, length, delim);
950
/* Allocate a new buffer large enough to hold all possible
955
outbytes = n * MB_LEN_MAX;
956
if (outbytes / MB_LEN_MAX != n)
957
BUG (); /* Actually an overflow. */
958
outbuf = outptr = m_alloc (outbytes);
959
if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
960
&outptr, &outbytes) == (size_t)-1) {
961
log_info (_("conversion from `%s' to `%s' failed: %s\n"),
962
"utf-8", active_charset_name, strerror (errno));
963
/* Didn't worked out. Temporary disable the use of
964
* iconv and fall back to our old code. */
969
outbuf = utf8_to_native (string, length, delim);
972
else { /* Success. */
974
/* We could realloc the buffer now but I doubt that it makes
975
much sense given that it will get freed anyway soon
982
#endif /*USE_GNUPG_ICONV*/
984
*p = 0; /* make a string */
990
/****************************************************
991
******** locale insensitive ctype functions ********
992
****************************************************/
993
/* FIXME: replace them by a table lookup and macros */
995
ascii_isupper (int c)
997
return c >= 'A' && c <= 'Z';
1001
ascii_islower (int c)
1003
return c >= 'a' && c <= 'z';
1007
ascii_toupper (int c)
1009
if (c >= 'a' && c <= 'z')
1015
ascii_tolower (int c)
1017
if (c >= 'A' && c <= 'Z')
1024
ascii_strcasecmp (const char *a, const char *b)
1026
const unsigned char *p1 = (const unsigned char *)a;
1027
const unsigned char *p2 = (const unsigned char *)b;
1028
unsigned char c1, c2;
1035
c1 = ascii_tolower (*p1);
1036
c2 = ascii_tolower (*p2);
1050
ascii_strncasecmp (const char *a, const char *b, size_t n)
1052
const unsigned char *p1 = (const unsigned char *)a;
1053
const unsigned char *p2 = (const unsigned char *)b;
1054
unsigned char c1, c2;
1056
if (p1 == p2 || !n )
1061
c1 = ascii_tolower (*p1);
1062
c2 = ascii_tolower (*p2);
1064
if ( !--n || c1 == '\0')
1077
ascii_memcasecmp( const char *a, const char *b, size_t n )
1081
for ( ; n; n--, a++, b++ ) {
1082
if( *a != *b && ascii_toupper (*a) != ascii_toupper (*b) )
1083
return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
1090
/*********************************************
1091
********** missing string functions *********
1092
*********************************************/
1096
stpcpy(char *a,const char *b)
1108
/* code taken from glibc-2.2.1/sysdeps/generic/strsep.c */
1110
strsep (char **stringp, const char *delim)
1118
/* A frequent case is when the delimiter string contains only one
1119
character. Here we don't need to call the expensive `strpbrk'
1120
function and instead work using `strchr'. */
1121
if (delim[0] == '\0' || delim[1] == '\0')
1131
else if (*begin == '\0')
1134
end = strchr (begin + 1, ch);
1138
/* Find the end of the token. */
1139
end = strpbrk (begin, delim);
1143
/* Terminate the token and set *STRINGP past NUL character. */
1148
/* No more delimiters; this is the last token. */
1153
#endif /*HAVE_STRSEP*/
1162
*p = tolower(*(unsigned char *)p);
1167
#ifndef HAVE_STRCASECMP
1169
strcasecmp( const char *a, const char *b )
1171
for( ; *a && *b; a++, b++ ) {
1173
&& toupper(*(const byte *)a) != toupper(*(const byte *)b) )
1176
return *(const byte*)a - *(const byte*)b;
1180
#ifndef HAVE_STRNCASECMP
1182
strncasecmp( const char *a, const char *b, size_t n )
1184
for( ; n && *a && *b; a++, b++, n--) {
1186
&& toupper(*(const byte *)a) != toupper(*(const byte *)b) )
1191
return *(const byte*)a - *(const byte*)b;
1198
* Like vsprintf but provides a pointer to malloc'd storage, which
1199
* must be freed by the caller (m_free). Taken from libiberty as
1200
* found in gcc-2.95.2 and a little bit modernized.
1201
* FIXME: Write a new CRT for W32.
1204
vasprintf (char **result, const char *format, va_list args)
1206
const char *p = format;
1207
/* Add one to make sure that it is never zero, which might cause malloc
1209
int total_width = strlen (format) + 1;
1212
/* this is not really portable but works under Windows */
1213
memcpy ( &ap, &args, sizeof (va_list));
1219
while (strchr ("-+ #0", *p))
1224
total_width += abs (va_arg (ap, int));
1229
total_width += strtoul (p, &endp, 10);
1238
total_width += abs (va_arg (ap, int));
1243
total_width += strtoul (p, &endp, 10);
1247
while (strchr ("hlL", *p))
1249
/* Should be big enough for any format specifier except %s
1261
(void) va_arg (ap, int);
1268
(void) va_arg (ap, double);
1269
/* Since an ieee double can have an exponent of 307, we'll
1270
make the buffer wide enough to cover the gross case. */
1274
total_width += strlen (va_arg (ap, char *));
1278
(void) va_arg (ap, char *);
1283
*result = m_alloc (total_width);
1284
if (*result != NULL)
1285
return vsprintf (*result, format, args);
1291
asprintf (char **buf, const char *fmt, ...)
1297
status = vasprintf (buf, fmt, ap);
1303
w32_strerror (int w32_errno)
1305
static char strerr[256];
1306
int ec = (int)GetLastError ();
1310
FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, w32_errno,
1311
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
1312
strerr, DIM (strerr)-1, NULL);