~ubuntu-branches/ubuntu/dapper/gnupg2/dapper

« back to all changes in this revision

Viewing changes to util/strgutil.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-03-29 10:30:32 UTC
  • Revision ID: james.westby@ubuntu.com-20050329103032-sj42n2ain3ipx310
Tags: upstream-1.9.15
ImportĀ upstreamĀ versionĀ 1.9.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#include <errno.h>
 
27
#ifdef HAVE_LANGINFO_CODESET
 
28
#include <langinfo.h>
 
29
#endif
 
30
 
 
31
/* For W32 we use dynamic loading of the iconv dll and don't need any
 
32
 * iconv headers at all. */
 
33
#ifndef _WIN32
 
34
# ifndef HAVE_ICONV
 
35
#  undef USE_GNUPG_ICONV
 
36
# endif
 
37
#endif
 
38
 
 
39
#ifdef USE_GNUPG_ICONV
 
40
# include <limits.h>
 
41
# ifndef _WIN32
 
42
#  include <iconv.h>
 
43
# endif
 
44
#endif
 
45
 
 
46
#include "types.h"
 
47
#include "util.h"
 
48
#include "memory.h"
 
49
#include "i18n.h"
 
50
#include "dynload.h"
 
51
 
 
52
 
 
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
 
71
};
 
72
 
 
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
 
90
};
 
91
#endif /*!USE_GNUPG_ICONV*/
 
92
 
 
93
 
 
94
#ifndef MB_LEN_MAX
 
95
#define MB_LEN_MAX 16
 
96
#endif
 
97
 
 
98
 
 
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;
 
103
 
 
104
 
 
105
#ifdef _WIN32
 
106
typedef void* iconv_t;
 
107
#ifndef ICONV_CONST
 
108
#define ICONV_CONST const 
 
109
#endif
 
110
 
 
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);
 
116
 
 
117
#endif /*_WIN32*/
 
118
 
 
119
 
 
120
 
 
121
#ifdef _WIN32
 
122
static int 
 
123
load_libiconv (void)
 
124
{
 
125
  static int done;
 
126
  
 
127
  if (!done)
 
128
    {
 
129
      void *handle;
 
130
 
 
131
      done = 1; /* Do it right now because we might get called recursivly
 
132
                   through gettext.  */
 
133
    
 
134
      handle = dlopen ("iconv.dll", RTLD_LAZY);
 
135
      if (handle)
 
136
        {
 
137
          iconv_open  = dlsym (handle, "libiconv_open");
 
138
          if (iconv_open)
 
139
            iconv      = dlsym (handle, "libiconv");
 
140
          if (iconv)    
 
141
            iconv_close = dlsym (handle, "libiconv_close");
 
142
        }
 
143
      if (!handle || !iconv_close)
 
144
        {
 
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"));
 
149
          iconv_open = NULL;
 
150
          iconv = NULL;
 
151
          iconv_close = NULL;
 
152
          if (handle)
 
153
              dlclose (handle);
 
154
        }
 
155
    }
 
156
  return iconv_open? 0: -1;
 
157
}    
 
158
#endif /* _WIN32 */
 
159
 
 
160
 
 
161
 
 
162
 
 
163
void
 
164
free_strlist( STRLIST sl )
 
165
{
 
166
    STRLIST sl2;
 
167
 
 
168
    for(; sl; sl = sl2 ) {
 
169
        sl2 = sl->next;
 
170
        m_free(sl);
 
171
    }
 
172
}
 
173
 
 
174
 
 
175
STRLIST
 
176
add_to_strlist( STRLIST *list, const char *string )
 
177
{
 
178
    STRLIST sl;
 
179
 
 
180
    sl = m_alloc( sizeof *sl + strlen(string));
 
181
    sl->flags = 0;
 
182
    strcpy(sl->d, string);
 
183
    sl->next = *list;
 
184
    *list = sl;
 
185
    return sl;
 
186
}
 
187
 
 
188
/****************
 
189
 * Same as add_to_strlist() but if is_utf8 is *not* set a conversion
 
190
 * to UTF8 is done
 
191
 */
 
192
STRLIST
 
193
add_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
 
194
{
 
195
    STRLIST sl;
 
196
 
 
197
    if( is_utf8 )
 
198
        sl = add_to_strlist( list, string );
 
199
    else {
 
200
        char *p = native_to_utf8( string );
 
201
        sl = add_to_strlist( list, p );
 
202
        m_free( p );
 
203
    }
 
204
    return sl;
 
205
}
 
206
 
 
207
STRLIST
 
208
append_to_strlist( STRLIST *list, const char *string )
 
209
{
 
210
    STRLIST r, sl;
 
211
 
 
212
    sl = m_alloc( sizeof *sl + strlen(string));
 
213
    sl->flags = 0;
 
214
    strcpy(sl->d, string);
 
215
    sl->next = NULL;
 
216
    if( !*list )
 
217
        *list = sl;
 
218
    else {
 
219
        for( r = *list; r->next; r = r->next )
 
220
            ;
 
221
        r->next = sl;
 
222
    }
 
223
    return sl;
 
224
}
 
225
 
 
226
STRLIST
 
227
append_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
 
228
{
 
229
    STRLIST sl;
 
230
 
 
231
    if( is_utf8 )
 
232
        sl = append_to_strlist( list, string );
 
233
    else {
 
234
        char *p = native_to_utf8( string );
 
235
        sl = append_to_strlist( list, p );
 
236
        m_free( p );
 
237
    }
 
238
    return sl;
 
239
}
 
240
 
 
241
 
 
242
STRLIST
 
243
strlist_prev( STRLIST head, STRLIST node )
 
244
{
 
245
    STRLIST n;
 
246
 
 
247
    for(n=NULL; head && head != node; head = head->next )
 
248
        n = head;
 
249
    return n;
 
250
}
 
251
 
 
252
STRLIST
 
253
strlist_last( STRLIST node )
 
254
{
 
255
    if( node )
 
256
        for( ; node->next ; node = node->next )
 
257
            ;
 
258
    return node;
 
259
}
 
260
 
 
261
char *
 
262
pop_strlist( STRLIST *list )
 
263
{
 
264
  char *str=NULL;
 
265
  STRLIST sl=*list;
 
266
 
 
267
  if(sl)
 
268
    {
 
269
      str=m_alloc(strlen(sl->d)+1);
 
270
      strcpy(str,sl->d);
 
271
 
 
272
      *list=sl->next;
 
273
      m_free(sl);
 
274
    }
 
275
 
 
276
  return str;
 
277
}
 
278
 
 
279
/****************
 
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.
 
283
 */
 
284
const char *
 
285
memistr( const char *buf, size_t buflen, const char *sub )
 
286
{
 
287
    const byte *t, *s ;
 
288
    size_t n;
 
289
 
 
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-- )
 
294
                ;
 
295
            if( !*s )
 
296
                return buf;
 
297
            t = buf; n = buflen; s = sub ;
 
298
        }
 
299
 
 
300
    return NULL ;
 
301
}
 
302
 
 
303
const char *
 
304
ascii_memistr( const char *buf, size_t buflen, const char *sub )
 
305
{
 
306
    const byte *t, *s ;
 
307
    size_t n;
 
308
 
 
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-- )
 
313
                ;
 
314
            if( !*s )
 
315
                return buf;
 
316
            t = buf; n = buflen; s = sub ;
 
317
        }
 
318
 
 
319
    return NULL ;
 
320
}
 
321
 
 
322
 
 
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).  */
 
327
char *
 
328
mem2str( char *dest , const void *src , size_t n )
 
329
{
 
330
    char *d;
 
331
    const char *s;
 
332
 
 
333
    if( n ) {
 
334
        if( !dest )
 
335
            dest = m_alloc( n ) ;
 
336
        d = dest;
 
337
        s = src ;
 
338
        for(n--; n && *s; n-- )
 
339
            *d++ = *s++;
 
340
        *d = '\0' ;
 
341
    }
 
342
 
 
343
    return dest ;
 
344
}
 
345
 
 
346
 
 
347
/*
 
348
 * Remove leading and trailing white spaces
 
349
 */
 
350
char *
 
351
trim_spaces( char *str )
 
352
{
 
353
    char *string, *p, *mark;
 
354
 
 
355
    string = str;
 
356
    /* Find first non space character. */
 
357
    for( p=string; *p && isspace( *(byte*)p ) ; p++ )
 
358
        ;
 
359
    /* Move characters. */
 
360
    for( (mark = NULL); (*string = *p); string++, p++ )
 
361
        if( isspace( *(byte*)p ) ) {
 
362
            if( !mark )
 
363
                mark = string ;
 
364
        }
 
365
        else
 
366
            mark = NULL ;
 
367
    if( mark )
 
368
        *mark = '\0' ;  /* Remove trailing spaces.  */
 
369
 
 
370
    return str ;
 
371
}
 
372
 
 
373
 
 
374
 
 
375
unsigned int
 
376
trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
 
377
{
 
378
    byte *p, *mark;
 
379
    unsigned n;
 
380
 
 
381
    for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
 
382
        if( strchr(trimchars, *p ) ) {
 
383
            if( !mark )
 
384
                mark = p;
 
385
        }
 
386
        else
 
387
            mark = NULL;
 
388
    }
 
389
 
 
390
    if( mark ) {
 
391
        *mark = 0;
 
392
        return mark - line;
 
393
    }
 
394
    return len;
 
395
}
 
396
 
 
397
/****************
 
398
 * Remove trailing white spaces and return the length of the buffer
 
399
 */
 
400
unsigned
 
401
trim_trailing_ws( byte *line, unsigned len )
 
402
{
 
403
    return trim_trailing_chars( line, len, " \t\r\n" );
 
404
}
 
405
 
 
406
 
 
407
unsigned int
 
408
check_trailing_chars( const byte *line, unsigned int len,
 
409
                      const char *trimchars )
 
410
{
 
411
    const byte *p, *mark;
 
412
    unsigned int n;
 
413
 
 
414
    for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
 
415
        if( strchr(trimchars, *p ) ) {
 
416
            if( !mark )
 
417
                mark = p;
 
418
        }
 
419
        else
 
420
            mark = NULL;
 
421
    }
 
422
 
 
423
    if( mark ) {
 
424
        return mark - line;
 
425
    }
 
426
    return len;
 
427
}
 
428
 
 
429
 
 
430
/****************
 
431
 * Remove trailing white spaces and return the length of the buffer
 
432
 */
 
433
unsigned int
 
434
check_trailing_ws( const byte *line, unsigned int len )
 
435
{
 
436
    return check_trailing_chars( line, len, " \t\r\n" );
 
437
}
 
438
 
 
439
 
 
440
 
 
441
int
 
442
string_count_chr( const char *string, int c )
 
443
{
 
444
    int count;
 
445
    for(count=0; *string; string++ )
 
446
        if( *string == c )
 
447
            count++;
 
448
    return count;
 
449
}
 
450
 
 
451
#ifdef USE_GNUPG_ICONV
 
452
static void
 
453
handle_iconv_error (const char *to, const char *from, int use_fallback)
 
454
{
 
455
  if (errno == EINVAL)
 
456
    log_info (_("conversion from `%s' to `%s' not available\n"),
 
457
               from, to);
 
458
  else
 
459
    log_info (_("iconv_open failed: %s\n"), strerror (errno));
 
460
 
 
461
  if (use_fallback)
 
462
    {
 
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
 
467
         default.  */
 
468
      active_charset_name = "iso-8859-1";
 
469
      no_translation = 0;
 
470
      active_charset = NULL;
 
471
      use_iconv = 0;
 
472
    }
 
473
}
 
474
#endif /*USE_GNUPG_ICONV*/
 
475
 
 
476
int
 
477
set_native_charset( const char *newset )
 
478
{
 
479
    const char *full_newset;
 
480
 
 
481
    if (!newset) {
 
482
#ifdef _WIN32
 
483
        static char codepage[30];
 
484
        unsigned int cpno;
 
485
 
 
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 ();
 
494
        if (!cpno)
 
495
          cpno = GetACP ();
 
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
 
500
           for it. */
 
501
        if (!strcmp (codepage, "CP1252"))
 
502
            newset = "iso-8859-1";
 
503
        else
 
504
            newset = codepage;
 
505
#else
 
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;
 
512
 
 
513
        strcpy (codepage, "iso-8859-1");
 
514
        lc = getenv ("LC_ALL");
 
515
        if (!lc || !*lc) {
 
516
            lc = getenv ("LC_CTYPE");
 
517
            if (!lc || !*lc)
 
518
                lc = getenv ("LANG");
 
519
        }
 
520
        if (lc && *lc) {
 
521
            dot = strchr (lc, '.');
 
522
            if (dot) {
 
523
                mod = strchr (++dot, '@');
 
524
                if (!mod)
 
525
                    mod = dot + strlen (dot);
 
526
                if (mod - dot < sizeof codepage && dot != mod) {
 
527
                    memcpy (codepage, dot, mod - dot);
 
528
                    codepage [mod - dot] = 0;
 
529
                }
 
530
            }
 
531
        }
 
532
        newset = codepage;
 
533
#endif  /* !HAVE_LANGINFO_CODESET */
 
534
#endif
 
535
    }
 
536
 
 
537
    full_newset = newset;
 
538
    if (strlen (newset) > 3 && !ascii_memcasecmp (newset, "iso", 3)) {
 
539
        newset += 3;
 
540
        if (*newset == '-' || *newset == '_')
 
541
            newset++;
 
542
    }
 
543
 
 
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. */
 
550
    if( !*newset
 
551
        || !ascii_strcasecmp (newset, "8859-1" )
 
552
        || !ascii_strcasecmp (newset, "646" )
 
553
        || !ascii_strcasecmp (newset, "ASCII" )
 
554
        || !ascii_strcasecmp (newset, "ANSI_X3.4-1968" )
 
555
        ) {
 
556
        active_charset_name = "iso-8859-1";
 
557
        no_translation = 0;
 
558
        active_charset = NULL;
 
559
        use_iconv = 0;
 
560
    }
 
561
    else if( !ascii_strcasecmp (newset, "utf8" )
 
562
             || !ascii_strcasecmp(newset, "utf-8") ) {
 
563
        active_charset_name = "utf-8";
 
564
        no_translation = 1;
 
565
        active_charset = NULL;
 
566
        use_iconv = 0;
 
567
    }
 
568
#ifdef USE_GNUPG_ICONV
 
569
    else {
 
570
      iconv_t cd;
 
571
 
 
572
#ifdef _WIN32
 
573
      if (load_libiconv ())
 
574
          return G10ERR_GENERAL;
 
575
#endif /*_WIN32*/      
 
576
 
 
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;
 
581
      }
 
582
      iconv_close (cd);
 
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;
 
587
      }
 
588
      iconv_close (cd);
 
589
      active_charset_name = full_newset;
 
590
      no_translation = 0;
 
591
      active_charset = NULL; 
 
592
      use_iconv = 1;
 
593
    }
 
594
#else /*!USE_GNUPG_ICONV*/
 
595
    else if( !ascii_strcasecmp( newset, "8859-2" ) ) {
 
596
        active_charset_name = "iso-8859-2";
 
597
        no_translation = 0;
 
598
        active_charset = latin2_unicode;
 
599
        use_iconv = 0;
 
600
    }
 
601
    else if( !ascii_strcasecmp( newset, "koi8-r" ) ) {
 
602
        active_charset_name = "koi8-r";
 
603
        no_translation = 0;
 
604
        active_charset = koi8_unicode;
 
605
        use_iconv = 0;
 
606
    }
 
607
    else
 
608
        return G10ERR_GENERAL;
 
609
#endif /*!USE_GNUPG_ICONV*/
 
610
    return 0;
 
611
}
 
612
 
 
613
const char*
 
614
get_native_charset()
 
615
{
 
616
    return active_charset_name;
 
617
}
 
618
 
 
619
/****************
 
620
 * Convert string, which is in native encoding to UTF8 and return the
 
621
 * new allocated UTF8 string.
 
622
 */
 
623
char *
 
624
native_to_utf8( const char *string )
 
625
{
 
626
  const byte *s;
 
627
  char *buffer;
 
628
  byte *p;
 
629
  size_t length=0;
 
630
  
 
631
  if (no_translation)
 
632
    { /* Already utf-8 encoded. */
 
633
      buffer = m_strdup (string);
 
634
    }
 
635
  else if( !active_charset && !use_iconv) /* Shortcut implementation
 
636
                                             for Latin-1.  */
 
637
    { 
 
638
      for(s=string; *s; s++ ) 
 
639
        {
 
640
          length++;
 
641
          if( *s & 0x80 )
 
642
            length++;
 
643
        }
 
644
      buffer = m_alloc( length + 1 );
 
645
      for(p=buffer, s=string; *s; s++ )
 
646
        {
 
647
          if( *s & 0x80 )
 
648
            {
 
649
              *p++ = 0xc0 | ((*s >> 6) & 3);
 
650
              *p++ = 0x80 | ( *s & 0x3f );
 
651
            }
 
652
          else
 
653
            *p++ = *s;
 
654
        }
 
655
      *p = 0;
 
656
    }
 
657
  else       /* Need to use a translation table. */
 
658
    { 
 
659
#ifdef USE_GNUPG_ICONV
 
660
      iconv_t cd;
 
661
      const char *inptr;
 
662
      char *outptr;
 
663
      size_t inbytes, outbytes;
 
664
     
 
665
      cd = iconv_open ("utf-8", active_charset_name);
 
666
      if (cd == (iconv_t)-1)
 
667
        {
 
668
          handle_iconv_error ("utf-8", active_charset_name, 1);
 
669
          return native_to_utf8 (string);
 
670
        }
 
671
 
 
672
      for (s=string; *s; s++ ) 
 
673
        {
 
674
          length++;
 
675
          if ((*s & 0x80))
 
676
            length += 5; /* We may need up to 6 bytes for the utf8 output. */
 
677
        }
 
678
      buffer = m_alloc (length + 1);
 
679
 
 
680
      inptr = string;
 
681
      inbytes = strlen (string);
 
682
      outptr = buffer;
 
683
      outbytes = length;
 
684
      if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
 
685
                  &outptr, &outbytes) == (size_t)-1)
 
686
        {
 
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);
 
691
        }
 
692
      else /* Success.  */
 
693
        {
 
694
          *outptr = 0;
 
695
          /* We could realloc the buffer now but I doubt that it makes
 
696
             much sense given that it will get freed anyway soon
 
697
             after.  */
 
698
        }
 
699
      iconv_close (cd);
 
700
 
 
701
#else /*!USE_GNUPG_ICONV*/
 
702
      for(s=string; *s; s++ ) 
 
703
        {
 
704
          length++;
 
705
          if( *s & 0x80 )
 
706
            length += 2; /* We may need up to 3 bytes. */
 
707
        }
 
708
      buffer = m_alloc( length + 1 );
 
709
      for(p=buffer, s=string; *s; s++ ) {
 
710
        if( *s & 0x80 ) {
 
711
          ushort val = active_charset[ *s & 0x7f ];
 
712
          if( val < 0x0800 ) {
 
713
            *p++ = 0xc0 | ( (val >> 6) & 0x1f );
 
714
            *p++ = 0x80 | (  val & 0x3f );
 
715
          }
 
716
          else {
 
717
            *p++ = 0xe0 | ( (val >> 12) & 0x0f );
 
718
            *p++ = 0x80 | ( (val >>  6) & 0x3f );
 
719
            *p++ = 0x80 | (  val & 0x3f );
 
720
          }
 
721
        }
 
722
        else
 
723
          *p++ = *s;
 
724
      }
 
725
      *p = 0;
 
726
#endif /*!USE_GNUPG_ICONV*/
 
727
 
 
728
    }
 
729
  return buffer;
 
730
}
 
731
 
 
732
 
 
733
/****************
 
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.
 
739
 */
 
740
char *
 
741
utf8_to_native( const char *string, size_t length, int delim )
 
742
{
 
743
    int nleft;
 
744
    int i;
 
745
    byte encbuf[8];
 
746
    int encidx;
 
747
    const byte *s;
 
748
    size_t n;
 
749
    byte *buffer = NULL, *p = NULL;
 
750
    unsigned long val = 0;
 
751
    size_t slen;
 
752
    int resync = 0;
 
753
 
 
754
    /* 1. pass (p==NULL): count the extended utf-8 characters */
 
755
    /* 2. pass (p!=NULL): create string */
 
756
    for( ;; ) {
 
757
        for( slen=length, nleft=encidx=0, n=0, s=string; slen; s++, slen-- ) {
 
758
            if( resync ) {
 
759
                if( !(*s < 128 || (*s >= 0xc0 && *s <= 0xfd)) ) {
 
760
                    /* still invalid */
 
761
                    if( p ) {
 
762
                        sprintf(p, "\\x%02x", *s );
 
763
                        p += 4;
 
764
                    }
 
765
                    n += 4;
 
766
                    continue;
 
767
                }
 
768
                resync = 0;
 
769
            }
 
770
            if( !nleft ) {
 
771
                if( !(*s & 0x80) ) { /* plain ascii */
 
772
                    if( delim != -1 
 
773
                        && (*s < 0x20 || *s == 0x7f || *s == delim
 
774
                            || (delim && *s=='\\'))) {
 
775
                        n++;
 
776
                        if( p )
 
777
                            *p++ = '\\';
 
778
                        switch( *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;
 
785
                          default:
 
786
                            n += 3;
 
787
                            if ( p ) {
 
788
                                sprintf( p, "x%02x", *s );
 
789
                                p += 3;
 
790
                            }
 
791
                            break;
 
792
                        }
 
793
                    }
 
794
                    else {
 
795
                        if( p ) *p++ = *s;
 
796
                        n++;
 
797
                    }
 
798
                }
 
799
                else if( (*s & 0xe0) == 0xc0 ) { /* 110x xxxx */
 
800
                    val = *s & 0x1f;
 
801
                    nleft = 1;
 
802
                    encidx = 0;
 
803
                    encbuf[encidx++] = *s;
 
804
                }
 
805
                else if( (*s & 0xf0) == 0xe0 ) { /* 1110 xxxx */
 
806
                    val = *s & 0x0f;
 
807
                    nleft = 2;
 
808
                    encidx = 0;
 
809
                    encbuf[encidx++] = *s;
 
810
                }
 
811
                else if( (*s & 0xf8) == 0xf0 ) { /* 1111 0xxx */
 
812
                    val = *s & 0x07;
 
813
                    nleft = 3;
 
814
                    encidx = 0;
 
815
                    encbuf[encidx++] = *s;
 
816
                }
 
817
                else if( (*s & 0xfc) == 0xf8 ) { /* 1111 10xx */
 
818
                    val = *s & 0x03;
 
819
                    nleft = 4;
 
820
                    encidx = 0;
 
821
                    encbuf[encidx++] = *s;
 
822
                }
 
823
                else if( (*s & 0xfe) == 0xfc ) { /* 1111 110x */
 
824
                    val = *s & 0x01;
 
825
                    nleft = 5;
 
826
                    encidx = 0;
 
827
                    encbuf[encidx++] = *s;
 
828
                }
 
829
                else {  /* invalid encoding: print as \xnn */
 
830
                    if( p ) {
 
831
                        sprintf(p, "\\x%02x", *s );
 
832
                        p += 4;
 
833
                    }
 
834
                    n += 4;
 
835
                    resync = 1;
 
836
                }
 
837
            }
 
838
            else if( *s < 0x80 || *s >= 0xc0 ) { /* invalid */
 
839
                if( p ) {
 
840
                    for(i=0; i < encidx; i++ ) {
 
841
                        sprintf(p, "\\x%02x", encbuf[i] );
 
842
                        p += 4;
 
843
                    }
 
844
                    sprintf(p, "\\x%02x", *s );
 
845
                    p += 4;
 
846
                }
 
847
                n += 4 + 4*encidx;
 
848
                nleft = 0;
 
849
                encidx = 0;
 
850
                resync = 1;
 
851
            }
 
852
            else {
 
853
                encbuf[encidx++] = *s;
 
854
                val <<= 6;
 
855
                val |= *s & 0x3f;
 
856
                if( !--nleft ) { /* ready */
 
857
                    if (no_translation) {
 
858
                        if( p ) {
 
859
                            for(i=0; i < encidx; i++ )
 
860
                                *p++ = encbuf[i];
 
861
                        }
 
862
                        n += encidx;
 
863
                        encidx = 0;
 
864
                    }
 
865
#ifdef USE_GNUPG_ICONV
 
866
                    else if(use_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
 
880
                         * platforms.  */
 
881
                        if( p ) {
 
882
                            for(i=0; i < encidx; i++ )
 
883
                                *p++ = encbuf[i];
 
884
                        }
 
885
                        n += encidx;
 
886
                        encidx = 0;
 
887
                    }
 
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 )
 
892
                                break;
 
893
                        }
 
894
                        if( i < 128 ) { /* we can print this one */
 
895
                            if( p ) *p++ = i+128;
 
896
                            n++;
 
897
                        }
 
898
                        else { /* we do not have a translation: print utf8 */
 
899
                            if( p ) {
 
900
                                for(i=0; i < encidx; i++ ) {
 
901
                                    sprintf(p, "\\x%02x", encbuf[i] );
 
902
                                    p += 4;
 
903
                                }
 
904
                            }
 
905
                            n += encidx*4;
 
906
                            encidx = 0;
 
907
                        }
 
908
                    }
 
909
                    else { /* native set */
 
910
                        if( val >= 0x80 && val < 256 ) {
 
911
                            n++;    /* we can simply print this character */
 
912
                            if( p ) *p++ = val;
 
913
                        }
 
914
                        else { /* we do not have a translation: print utf8 */
 
915
                            if( p ) {
 
916
                                for(i=0; i < encidx; i++ ) {
 
917
                                    sprintf(p, "\\x%02x", encbuf[i] );
 
918
                                    p += 4;
 
919
                                }
 
920
                            }
 
921
                            n += encidx*4;
 
922
                            encidx = 0;
 
923
                        }
 
924
                    }
 
925
                }
 
926
 
 
927
            }
 
928
        }
 
929
        if( !buffer ) { /* allocate the buffer after the first pass */
 
930
            buffer = p = m_alloc( n + 1 );
 
931
        }
 
932
#ifdef USE_GNUPG_ICONV
 
933
        else if(use_iconv) {
 
934
            /* Note: See above for comments.  */
 
935
            iconv_t cd;
 
936
            const char *inptr;
 
937
            char *outbuf, *outptr;
 
938
            size_t inbytes, outbytes;
 
939
            
 
940
            *p = 0;  /* Terminate the buffer. */
 
941
 
 
942
            cd = iconv_open (active_charset_name, "utf-8");
 
943
            if (cd == (iconv_t)-1)
 
944
                {
 
945
                    handle_iconv_error (active_charset_name, "utf-8", 1);
 
946
                    m_free (buffer);
 
947
                    return utf8_to_native (string, length, delim);
 
948
                }
 
949
 
 
950
            /* Allocate a new buffer large enough to hold all possible
 
951
             * encodings. */
 
952
            n = p - buffer + 1;
 
953
            inbytes = n - 1;;
 
954
            inptr = buffer;
 
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. */
 
965
                m_free (buffer);
 
966
                buffer = NULL;
 
967
                m_free (outbuf);
 
968
                use_iconv = 0;
 
969
                outbuf = utf8_to_native (string, length, delim);
 
970
                use_iconv = 1;
 
971
            }
 
972
            else { /* Success.  */
 
973
                *outptr = 0;
 
974
                /* We could realloc the buffer now but I doubt that it makes
 
975
                   much sense given that it will get freed anyway soon
 
976
                   after.  */
 
977
                m_free (buffer);
 
978
            }
 
979
            iconv_close (cd);
 
980
            return outbuf;
 
981
        }
 
982
#endif /*USE_GNUPG_ICONV*/
 
983
        else {
 
984
            *p = 0; /* make a string */
 
985
            return buffer;
 
986
        }
 
987
    }
 
988
}
 
989
 
 
990
/****************************************************
 
991
 ******** locale insensitive ctype functions ********
 
992
 ****************************************************/
 
993
/* FIXME: replace them by a table lookup and macros */
 
994
int
 
995
ascii_isupper (int c)
 
996
{
 
997
    return c >= 'A' && c <= 'Z';
 
998
}
 
999
 
 
1000
int
 
1001
ascii_islower (int c)
 
1002
{
 
1003
    return c >= 'a' && c <= 'z';
 
1004
}
 
1005
 
 
1006
int 
 
1007
ascii_toupper (int c)
 
1008
{
 
1009
    if (c >= 'a' && c <= 'z')
 
1010
        c &= ~0x20;
 
1011
    return c;
 
1012
}
 
1013
 
 
1014
int 
 
1015
ascii_tolower (int c)
 
1016
{
 
1017
    if (c >= 'A' && c <= 'Z')
 
1018
        c |= 0x20;
 
1019
    return c;
 
1020
}
 
1021
 
 
1022
 
 
1023
int
 
1024
ascii_strcasecmp (const char *a, const char *b)
 
1025
{
 
1026
  const unsigned char *p1 = (const unsigned char *)a;
 
1027
  const unsigned char *p2 = (const unsigned char *)b;
 
1028
  unsigned char c1, c2;
 
1029
 
 
1030
  if (p1 == p2)
 
1031
    return 0;
 
1032
 
 
1033
  do
 
1034
    {
 
1035
      c1 = ascii_tolower (*p1);
 
1036
      c2 = ascii_tolower (*p2);
 
1037
 
 
1038
      if (c1 == '\0')
 
1039
        break;
 
1040
 
 
1041
      ++p1;
 
1042
      ++p2;
 
1043
    }
 
1044
  while (c1 == c2);
 
1045
  
 
1046
  return c1 - c2;
 
1047
}
 
1048
 
 
1049
int 
 
1050
ascii_strncasecmp (const char *a, const char *b, size_t n)
 
1051
{
 
1052
  const unsigned char *p1 = (const unsigned char *)a;
 
1053
  const unsigned char *p2 = (const unsigned char *)b;
 
1054
  unsigned char c1, c2;
 
1055
 
 
1056
  if (p1 == p2 || !n )
 
1057
    return 0;
 
1058
 
 
1059
  do
 
1060
    {
 
1061
      c1 = ascii_tolower (*p1);
 
1062
      c2 = ascii_tolower (*p2);
 
1063
 
 
1064
      if ( !--n || c1 == '\0')
 
1065
        break;
 
1066
 
 
1067
      ++p1;
 
1068
      ++p2;
 
1069
    }
 
1070
  while (c1 == c2);
 
1071
  
 
1072
  return c1 - c2;
 
1073
}
 
1074
 
 
1075
 
 
1076
int
 
1077
ascii_memcasecmp( const char *a, const char *b, size_t n )
 
1078
{
 
1079
    if (a == b)
 
1080
        return 0;
 
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));
 
1084
    }
 
1085
    return 0;
 
1086
}
 
1087
 
 
1088
 
 
1089
 
 
1090
/*********************************************
 
1091
 ********** missing string functions *********
 
1092
 *********************************************/
 
1093
 
 
1094
#ifndef HAVE_STPCPY
 
1095
char *
 
1096
stpcpy(char *a,const char *b)
 
1097
{
 
1098
    while( *b )
 
1099
        *a++ = *b++;
 
1100
    *a = 0;
 
1101
 
 
1102
    return (char*)a;
 
1103
}
 
1104
#endif
 
1105
 
 
1106
 
 
1107
#ifndef HAVE_STRSEP
 
1108
/* code taken from glibc-2.2.1/sysdeps/generic/strsep.c */
 
1109
char *
 
1110
strsep (char **stringp, const char *delim)
 
1111
{
 
1112
  char *begin, *end;
 
1113
 
 
1114
  begin = *stringp;
 
1115
  if (begin == NULL)
 
1116
    return NULL;
 
1117
 
 
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')
 
1122
    {
 
1123
      char ch = delim[0];
 
1124
 
 
1125
      if (ch == '\0')
 
1126
        end = NULL;
 
1127
      else
 
1128
        {
 
1129
          if (*begin == ch)
 
1130
            end = begin;
 
1131
          else if (*begin == '\0')
 
1132
            end = NULL;
 
1133
          else
 
1134
            end = strchr (begin + 1, ch);
 
1135
        }
 
1136
    }
 
1137
  else
 
1138
    /* Find the end of the token.  */
 
1139
    end = strpbrk (begin, delim);
 
1140
 
 
1141
  if (end)
 
1142
    {
 
1143
      /* Terminate the token and set *STRINGP past NUL character.  */
 
1144
      *end++ = '\0';
 
1145
      *stringp = end;
 
1146
    }
 
1147
  else
 
1148
    /* No more delimiters; this is the last token.  */
 
1149
    *stringp = NULL;
 
1150
 
 
1151
  return begin;
 
1152
}
 
1153
#endif /*HAVE_STRSEP*/
 
1154
 
 
1155
 
 
1156
#ifndef HAVE_STRLWR
 
1157
char *
 
1158
strlwr(char *s)
 
1159
{
 
1160
    char *p;
 
1161
    for(p=s; *p; p++ )
 
1162
        *p = tolower(*(unsigned char *)p);
 
1163
    return s;
 
1164
}
 
1165
#endif
 
1166
 
 
1167
#ifndef HAVE_STRCASECMP
 
1168
int
 
1169
strcasecmp( const char *a, const char *b )
 
1170
{
 
1171
    for( ; *a && *b; a++, b++ ) {
 
1172
        if( *a != *b
 
1173
            && toupper(*(const byte *)a) != toupper(*(const byte *)b) )
 
1174
            break;
 
1175
    }
 
1176
    return *(const byte*)a - *(const byte*)b;
 
1177
}
 
1178
#endif
 
1179
 
 
1180
#ifndef HAVE_STRNCASECMP
 
1181
int
 
1182
strncasecmp( const char *a, const char *b, size_t n )
 
1183
{
 
1184
    for( ; n && *a && *b; a++, b++, n--) {
 
1185
        if( *a != *b
 
1186
            && toupper(*(const byte *)a) != toupper(*(const byte *)b) )
 
1187
            break;
 
1188
    }
 
1189
    if (!n)
 
1190
      return 0;
 
1191
    return *(const byte*)a - *(const byte*)b;
 
1192
}
 
1193
#endif
 
1194
 
 
1195
 
 
1196
#ifdef _WIN32
 
1197
/* 
 
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.
 
1202
 */
 
1203
int
 
1204
vasprintf (char **result, const char *format, va_list args)
 
1205
{
 
1206
  const char *p = format;
 
1207
  /* Add one to make sure that it is never zero, which might cause malloc
 
1208
     to return NULL.  */
 
1209
  int total_width = strlen (format) + 1;
 
1210
  va_list ap;
 
1211
 
 
1212
  /* this is not really portable but works under Windows */
 
1213
  memcpy ( &ap, &args, sizeof (va_list));
 
1214
 
 
1215
  while (*p != '\0')
 
1216
    {
 
1217
      if (*p++ == '%')
 
1218
        {
 
1219
          while (strchr ("-+ #0", *p))
 
1220
            ++p;
 
1221
          if (*p == '*')
 
1222
            {
 
1223
              ++p;
 
1224
              total_width += abs (va_arg (ap, int));
 
1225
            }
 
1226
          else
 
1227
            {
 
1228
              char *endp;  
 
1229
              total_width += strtoul (p, &endp, 10);
 
1230
              p = endp;
 
1231
            }
 
1232
          if (*p == '.')
 
1233
            {
 
1234
              ++p;
 
1235
              if (*p == '*')
 
1236
                {
 
1237
                  ++p;
 
1238
                  total_width += abs (va_arg (ap, int));
 
1239
                }
 
1240
              else
 
1241
                {
 
1242
                  char *endp;
 
1243
                  total_width += strtoul (p, &endp, 10);
 
1244
                  p = endp;
 
1245
                }
 
1246
            }
 
1247
          while (strchr ("hlL", *p))
 
1248
            ++p;
 
1249
          /* Should be big enough for any format specifier except %s
 
1250
             and floats.  */
 
1251
          total_width += 30;
 
1252
          switch (*p)
 
1253
            {
 
1254
            case 'd':
 
1255
            case 'i':
 
1256
            case 'o':
 
1257
            case 'u':
 
1258
            case 'x':
 
1259
            case 'X':
 
1260
            case 'c':
 
1261
              (void) va_arg (ap, int);
 
1262
              break;
 
1263
            case 'f':
 
1264
            case 'e':
 
1265
            case 'E':
 
1266
            case 'g':
 
1267
            case 'G':
 
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. */
 
1271
              total_width += 307;
 
1272
            
 
1273
            case 's':
 
1274
              total_width += strlen (va_arg (ap, char *));
 
1275
              break;
 
1276
            case 'p':
 
1277
            case 'n':
 
1278
              (void) va_arg (ap, char *);
 
1279
              break;
 
1280
            }
 
1281
        }
 
1282
    }
 
1283
  *result = m_alloc (total_width);
 
1284
  if (*result != NULL)
 
1285
    return vsprintf (*result, format, args);
 
1286
  else
 
1287
    return 0;
 
1288
}
 
1289
 
 
1290
int
 
1291
asprintf (char **buf, const char *fmt, ...)
 
1292
{
 
1293
  int status;
 
1294
  va_list ap;
 
1295
 
 
1296
  va_start (ap, fmt);
 
1297
  status = vasprintf (buf, fmt, ap);
 
1298
  va_end (ap);
 
1299
  return status;  
 
1300
}
 
1301
 
 
1302
const char *
 
1303
w32_strerror (int w32_errno)
 
1304
{
 
1305
  static char strerr[256];
 
1306
  int ec = (int)GetLastError ();
 
1307
  
 
1308
  if (w32_errno == 0)
 
1309
    w32_errno = ec;
 
1310
  FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, w32_errno,
 
1311
                 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
 
1312
                 strerr, DIM (strerr)-1, NULL);
 
1313
  return strerr;    
 
1314
}
 
1315
#endif /*_WIN32*/
 
1316
 
 
1317
 
 
1318