summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormdankov <mdankov@ffa7fe5e-494d-0410-b361-a75ebd5db220>2013-06-16 21:39:56 +0000
committermdankov <mdankov@ffa7fe5e-494d-0410-b361-a75ebd5db220>2013-06-16 21:39:56 +0000
commit97e3081bd591001c5af33ed4919b1feb63af7c46 (patch)
treef36d8c85ec6f8f8b862e95f484412b695360929a
parentfdf7effdc12ab59590432f09a2dff797e854fb2f (diff)
downloadnavit-svn-97e3081bd591001c5af33ed4919b1feb63af7c46.tar.gz
Fix:port_win32:Fix "Dollar S" bugs in navigational messages by adding own versions of *printf functions to support/glib. Fixes #1123, #1114. |Thank you ftom for initial version of the patch.
git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit@5539 ffa7fe5e-494d-0410-b361-a75ebd5db220
-rwxr-xr-xCMakeLists.txt1
-rw-r--r--config.h.cmake1
-rw-r--r--configure.in5
-rw-r--r--navit/support/glib/CMakeLists.txt14
-rw-r--r--navit/support/glib/Makefile.am5
-rw-r--r--navit/support/glib/glibconfig.h5
-rw-r--r--navit/support/glib/gnulib/asnprintf.c40
-rw-r--r--navit/support/glib/gnulib/g-gnulib.h49
-rw-r--r--navit/support/glib/gnulib/printf-args.c133
-rw-r--r--navit/support/glib/gnulib/printf-args.h142
-rw-r--r--navit/support/glib/gnulib/printf-parse.c498
-rw-r--r--navit/support/glib/gnulib/printf-parse.h74
-rw-r--r--navit/support/glib/gnulib/printf.c154
-rw-r--r--navit/support/glib/gnulib/printf.h57
-rw-r--r--navit/support/glib/gnulib/vasnprintf.c1084
-rw-r--r--navit/support/glib/gnulib/vasnprintf.h61
16 files changed, 2320 insertions, 3 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 569ffa81..6e218d60 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -492,6 +492,7 @@ if(WIN32 OR WINCE)
enable_language(RC)
set(XSLTS "windows;${XSLTS}" CACHE STRING "define a semicolon seperated list of XSLTs to process")
+ set(GLIB_USE_OWN_PRINTF 1)
endif()
if (WIN32 AND NOT WINCE)
set(HAVE_PRAGMA_PACK 1)
diff --git a/config.h.cmake b/config.h.cmake
index abc3d0eb..63872d5b 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -7,6 +7,7 @@
#cmakedefine HAVE_API_WIN32 1
#cmakedefine HAVE_API_WIN32_CE 1
#cmakedefine HAVE_GLIB 1
+#cmakedefine GLIB_USE_OWN_PRINTF 1
#cmakedefine HAVE_GMODULE 1
#cmakedefine HAVE_GETCWD 1
#define CACHE_SIZE ${CACHE_SIZE}
diff --git a/configure.in b/configure.in
index 2361c413..d139d31e 100644
--- a/configure.in
+++ b/configure.in
@@ -295,6 +295,10 @@ else
if test "x${win32}" != "xyes" -a "x${android}" != "xyes"; then
GLIB_LIBS="$GLIB_LIBS -lpthread"
fi
+ if test "x${win32}" == "xyes"; then
+ glib_use_own_printf=yes; glib_use_own_printf_reason="Win32/WinCE detected"
+ AC_DEFINE(GLIB_USE_OWN_PRINTF, 1, [Undef to make internal glib use system printf implementation.])
+ fi
fi
# gmodule
@@ -347,6 +351,7 @@ AC_SUBST(LIBNAVIT)
AM_CONDITIONAL(EVENT_GLIB, [test "x$glib" = "xyes"])
AM_CONDITIONAL(SUPPORT_GLIB, [test "x$glib" = "xno"])
+AM_CONDITIONAL(GLIB_USE_OWN_PRINTF, [test "x$glib_use_own_printf" = "xyes"])
AM_CONDITIONAL(SUPPORT_EZXML, [test "x$glib" = "xno"])
AC_CHECK_HEADER([sys/time.h],
diff --git a/navit/support/glib/CMakeLists.txt b/navit/support/glib/CMakeLists.txt
index 322d5467..73103ae9 100644
--- a/navit/support/glib/CMakeLists.txt
+++ b/navit/support/glib/CMakeLists.txt
@@ -1,3 +1,13 @@
-supportlib_add_library(support_glib fake.c galiasdef.c gatomic.c gerror.c ghash.c
+set(SUPPORT_GLIB_SRC fake.c galiasdef.c gatomic.c gerror.c ghash.c
glib_init.c glist.c gmem.c gmessages.c gprimes.c gprintf.c gslice.c gslist.c
- gstrfuncs.c gstring.c gutf8.c gutils.c)
+ gstrfuncs.c gstring.c gutf8.c gutils.c)
+if(WIN32 OR WINCE)
+ list(APPEND SUPPORT_GLIB_SRC gnulib/asnprintf.c gnulib/printf.c gnulib/printf-args.c gnulib/printf-parse.c gnulib/vasnprintf.c)
+ set(GLIB_NEED_PRINTF 1)
+endif()
+supportlib_add_library(support_glib ${SUPPORT_GLIB_SRC})
+if(GLIB_USE_OWN_PRINTF)
+else(GLIB_USE_OWN_PRINTF)
+ GET_TARGET_PROPERTY(GLIB_DEFS support_glib COMPILE_DEFINITIONS)
+ SET_TARGET_PROPERTIES(support_glib PROPERTIES COMPILE_DEFINITIONS "HAVE_GOOD_PRINTF;${GLIB_DEFS}")
+endif(GLIB_USE_OWN_PRINTF)
diff --git a/navit/support/glib/Makefile.am b/navit/support/glib/Makefile.am
index c268053f..784680bf 100644
--- a/navit/support/glib/Makefile.am
+++ b/navit/support/glib/Makefile.am
@@ -7,3 +7,8 @@ libsupport_glib_la_SOURCES = fake.c galiasdef.c gatomic.c gerror.c \
fake.h galias.h gerror.h ghash.h glib.h glibconfig.h glibintl.h glist.h \
gmacros.h gmem.h gmessages.h gprintf.h gprintfint.h gquark.h gslice.h \
gslist.h gstrfuncs.h gthreadprivate.h gtypes.h
+if GLIB_USE_OWN_PRINTF
+ libsupport_glib_la_SOURCES += gnulib/asnprintf.c gnulib/printf-args.c gnulib/printf-args.h \
+ gnulib/printf-parse.c gnulib/printf-parse.h gnulib/vasnprintf.c gnulib/vasnprintf.h gnulib/printf.c \
+ gnulib/printf.h gnulib/g-gnulib.h
+endif
diff --git a/navit/support/glib/glibconfig.h b/navit/support/glib/glibconfig.h
index de0d9ded..9cdf6a0b 100644
--- a/navit/support/glib/glibconfig.h
+++ b/navit/support/glib/glibconfig.h
@@ -244,7 +244,10 @@ union _GSystemThread
#define G_MODULE_SUFFIX "dll"
-#define HAVE_GOOD_PRINTF
+#ifndef GLIB_USE_OWN_PRINTF
+# define HAVE_GOOD_PRINTF
+#endif
+#define HAVE_ALLOCA
#define NO_SYS_SIGLIST_DECL
#define GLIB_STATIC_COMPILATION
#define G_DISABLE_CHECKS
diff --git a/navit/support/glib/gnulib/asnprintf.c b/navit/support/glib/gnulib/asnprintf.c
new file mode 100644
index 00000000..765d98ce
--- /dev/null
+++ b/navit/support/glib/gnulib/asnprintf.c
@@ -0,0 +1,40 @@
+/* Formatted output to strings.
+ Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "g-gnulib.h"
+
+/* Specification. */
+#include "vasnprintf.h"
+
+#include <stdarg.h>
+
+char *
+asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
+{
+ va_list args;
+ char *result;
+
+ va_start (args, format);
+ result = vasnprintf (resultbuf, lengthp, format, args);
+ va_end (args);
+ return result;
+}
diff --git a/navit/support/glib/gnulib/g-gnulib.h b/navit/support/glib/gnulib/g-gnulib.h
new file mode 100644
index 00000000..88f3e0eb
--- /dev/null
+++ b/navit/support/glib/gnulib/g-gnulib.h
@@ -0,0 +1,49 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 2003 Matthias Clasen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __G_GNULIB_H__
+
+#include "config.h"
+#include <stdlib.h>
+#include "glib/glib.h"
+
+/* Private namespace for gnulib functions */
+#define asnprintf _g_gnulib_asnprintf
+#define vasnprintf _g_gnulib_vasnprintf
+#define printf_parse _g_gnulib_printf_parse
+#define printf_fetchargs _g_gnulib_printf_fetchargs
+
+/* Use GLib memory allocation */
+#undef malloc
+#undef realloc
+#undef free
+#define malloc g_malloc
+#define realloc g_realloc
+#define free g_free
+
+/* Ensure only C99 snprintf gets used */
+#undef HAVE_SNPRINTF
+#ifdef HAVE_C99_SNPRINTF
+#define HAVE_SNPRINTF 1
+#else
+#define HAVE_SNPRINTF 0
+#endif
+
+
+#endif /* __G_GNULIB_H__ */
+
diff --git a/navit/support/glib/gnulib/printf-args.c b/navit/support/glib/gnulib/printf-args.c
new file mode 100644
index 00000000..75a2a549
--- /dev/null
+++ b/navit/support/glib/gnulib/printf-args.c
@@ -0,0 +1,133 @@
+/* Decomposed printf argument list.
+ Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "g-gnulib.h"
+
+/* Specification. */
+#include "printf-args.h"
+
+#ifdef STATIC
+STATIC
+#endif
+int
+printf_fetchargs (va_list args, arguments *a)
+{
+ unsigned int i;
+ argument *ap;
+
+ for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
+ switch (ap->type)
+ {
+ case TYPE_SCHAR:
+ ap->a.a_schar = va_arg (args, /*signed char*/ int);
+ break;
+ case TYPE_UCHAR:
+ ap->a.a_uchar = va_arg (args, /*unsigned char*/ int);
+ break;
+ case TYPE_SHORT:
+ ap->a.a_short = va_arg (args, /*short*/ int);
+ break;
+ case TYPE_USHORT:
+ ap->a.a_ushort = va_arg (args, /*unsigned short*/ int);
+ break;
+ case TYPE_INT:
+ ap->a.a_int = va_arg (args, int);
+ break;
+ case TYPE_UINT:
+ ap->a.a_uint = va_arg (args, unsigned int);
+ break;
+ case TYPE_LONGINT:
+ ap->a.a_longint = va_arg (args, long int);
+ break;
+ case TYPE_ULONGINT:
+ ap->a.a_ulongint = va_arg (args, unsigned long int);
+ break;
+#ifdef HAVE_LONG_LONG
+ case TYPE_LONGLONGINT:
+ ap->a.a_longlongint = va_arg (args, long long int);
+ break;
+ case TYPE_ULONGLONGINT:
+ ap->a.a_ulonglongint = va_arg (args, unsigned long long int);
+ break;
+#endif
+#ifdef HAVE_INT64_AND_I64
+ case TYPE_INT64:
+ ap->a.a_int64 = va_arg (args, __int64);
+ break;
+ case TYPE_UINT64:
+ ap->a.a_uint64 = va_arg (args, unsigned __int64);
+ break;
+#endif
+ case TYPE_DOUBLE:
+ ap->a.a_double = va_arg (args, double);
+ break;
+#ifdef HAVE_LONG_DOUBLE
+ case TYPE_LONGDOUBLE:
+ ap->a.a_longdouble = va_arg (args, long double);
+ break;
+#endif
+ case TYPE_CHAR:
+ ap->a.a_char = va_arg (args, int);
+ break;
+#ifdef HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+#ifdef _WIN32
+ ap->a.a_wide_char = va_arg (args, int);
+#else
+ ap->a.a_wide_char = va_arg (args, wint_t);
+#endif
+ break;
+#endif
+ case TYPE_STRING:
+ ap->a.a_string = va_arg (args, const char *);
+ break;
+#ifdef HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+ ap->a.a_wide_string = va_arg (args, const wchar_t *);
+ break;
+#endif
+ case TYPE_POINTER:
+ ap->a.a_pointer = va_arg (args, void *);
+ break;
+ case TYPE_COUNT_SCHAR_POINTER:
+ ap->a.a_count_schar_pointer = va_arg (args, signed char *);
+ break;
+ case TYPE_COUNT_SHORT_POINTER:
+ ap->a.a_count_short_pointer = va_arg (args, short *);
+ break;
+ case TYPE_COUNT_INT_POINTER:
+ ap->a.a_count_int_pointer = va_arg (args, int *);
+ break;
+ case TYPE_COUNT_LONGINT_POINTER:
+ ap->a.a_count_longint_pointer = va_arg (args, long int *);
+ break;
+#ifdef HAVE_LONG_LONG
+ case TYPE_COUNT_LONGLONGINT_POINTER:
+ ap->a.a_count_longlongint_pointer = va_arg (args, long long int *);
+ break;
+#endif
+ default:
+ /* Unknown type. */
+ return -1;
+ }
+ return 0;
+}
diff --git a/navit/support/glib/gnulib/printf-args.h b/navit/support/glib/gnulib/printf-args.h
new file mode 100644
index 00000000..08256756
--- /dev/null
+++ b/navit/support/glib/gnulib/printf-args.h
@@ -0,0 +1,142 @@
+/* Decomposed printf argument list.
+ Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifndef _PRINTF_ARGS_H
+#define _PRINTF_ARGS_H
+
+/* Get wchar_t. */
+#ifdef HAVE_WCHAR_T
+# include <stddef.h>
+#endif
+
+/* Get wint_t. */
+#ifdef HAVE_WINT_T
+# include <wchar.h>
+#endif
+
+/* Get va_list. */
+#include <stdarg.h>
+
+
+/* Argument types */
+typedef enum
+{
+ TYPE_NONE,
+ TYPE_SCHAR,
+ TYPE_UCHAR,
+ TYPE_SHORT,
+ TYPE_USHORT,
+ TYPE_INT,
+ TYPE_UINT,
+ TYPE_LONGINT,
+ TYPE_ULONGINT,
+#ifdef HAVE_LONG_LONG
+ TYPE_LONGLONGINT,
+ TYPE_ULONGLONGINT,
+#endif
+#ifdef HAVE_INT64_AND_I64
+ TYPE_INT64,
+ TYPE_UINT64,
+#endif
+ TYPE_DOUBLE,
+#ifdef HAVE_LONG_DOUBLE
+ TYPE_LONGDOUBLE,
+#endif
+ TYPE_CHAR,
+#ifdef HAVE_WINT_T
+ TYPE_WIDE_CHAR,
+#endif
+ TYPE_STRING,
+#ifdef HAVE_WCHAR_T
+ TYPE_WIDE_STRING,
+#endif
+ TYPE_POINTER,
+ TYPE_COUNT_SCHAR_POINTER,
+ TYPE_COUNT_SHORT_POINTER,
+ TYPE_COUNT_INT_POINTER,
+ TYPE_COUNT_LONGINT_POINTER
+#ifdef HAVE_LONG_LONG
+, TYPE_COUNT_LONGLONGINT_POINTER
+#endif
+} arg_type;
+
+/* Polymorphic argument */
+typedef struct
+{
+ arg_type type;
+ union
+ {
+ signed char a_schar;
+ unsigned char a_uchar;
+ short a_short;
+ unsigned short a_ushort;
+ int a_int;
+ unsigned int a_uint;
+ long int a_longint;
+ unsigned long int a_ulongint;
+#ifdef HAVE_LONG_LONG
+ long long int a_longlongint;
+ unsigned long long int a_ulonglongint;
+#endif
+#ifdef HAVE_INT64_AND_I64
+ __int64 a_int64;
+ unsigned __int64 a_uint64;
+#endif
+ float a_float;
+ double a_double;
+#ifdef HAVE_LONG_DOUBLE
+ long double a_longdouble;
+#endif
+ int a_char;
+#ifdef HAVE_WINT_T
+ wint_t a_wide_char;
+#endif
+ const char* a_string;
+#ifdef HAVE_WCHAR_T
+ const wchar_t* a_wide_string;
+#endif
+ void* a_pointer;
+ signed char * a_count_schar_pointer;
+ short * a_count_short_pointer;
+ int * a_count_int_pointer;
+ long int * a_count_longint_pointer;
+#ifdef HAVE_LONG_LONG
+ long long int * a_count_longlongint_pointer;
+#endif
+ }
+ a;
+}
+argument;
+
+typedef struct
+{
+ unsigned int count;
+ argument *arg;
+}
+arguments;
+
+
+/* Fetch the arguments, putting them into a. */
+#ifdef STATIC
+STATIC
+#else
+extern
+#endif
+int printf_fetchargs (va_list args, arguments *a);
+
+#endif /* _PRINTF_ARGS_H */
diff --git a/navit/support/glib/gnulib/printf-parse.c b/navit/support/glib/gnulib/printf-parse.c
new file mode 100644
index 00000000..961b0816
--- /dev/null
+++ b/navit/support/glib/gnulib/printf-parse.c
@@ -0,0 +1,498 @@
+/* Formatted output to strings.
+ Copyright (C) 1999-2000, 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "g-gnulib.h"
+
+/* Specification. */
+#include "printf-parse.h"
+
+/* Get size_t, NULL. */
+#include <stddef.h>
+
+/* Get intmax_t. */
+#if HAVE_STDINT_H_WITH_UINTMAX
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H_WITH_UINTMAX
+# include <inttypes.h>
+#endif
+
+/* malloc(), realloc(), free(). */
+#include <stdlib.h>
+
+#ifdef STATIC
+STATIC
+#endif
+int
+printf_parse (const char *format, char_directives *d, arguments *a)
+{
+ const char *cp = format; /* pointer into format */
+ int arg_posn = 0; /* number of regular arguments consumed */
+ unsigned int d_allocated; /* allocated elements of d->dir */
+ unsigned int a_allocated; /* allocated elements of a->arg */
+ unsigned int max_width_length = 0;
+ unsigned int max_precision_length = 0;
+
+ d->count = 0;
+ d_allocated = 1;
+ d->dir = malloc (d_allocated * sizeof (char_directive));
+ if (d->dir == NULL)
+ /* Out of memory. */
+ return -1;
+
+ a->count = 0;
+ a_allocated = 0;
+ a->arg = NULL;
+
+#define REGISTER_ARG(_index_,_type_) \
+ { \
+ unsigned int n = (_index_); \
+ if (n >= a_allocated) \
+ { \
+ argument *memory; \
+ a_allocated = 2 * a_allocated; \
+ if (a_allocated <= n) \
+ a_allocated = n + 1; \
+ memory = (a->arg \
+ ? realloc (a->arg, a_allocated * sizeof (argument)) \
+ : malloc (a_allocated * sizeof (argument))); \
+ if (memory == NULL) \
+ /* Out of memory. */ \
+ goto error; \
+ a->arg = memory; \
+ } \
+ while (a->count <= n) \
+ a->arg[a->count++].type = TYPE_NONE; \
+ if (a->arg[n].type == TYPE_NONE) \
+ a->arg[n].type = (_type_); \
+ else if (a->arg[n].type != (_type_)) \
+ /* Ambiguous type for positional argument. */ \
+ goto error; \
+ }
+
+ while (*cp != '\0')
+ {
+ char c = *cp++;
+ if (c == '%')
+ {
+ int arg_index = -1;
+ char_directive *dp = &d->dir[d->count];/* pointer to next directive */
+
+ /* Initialize the next directive. */
+ dp->dir_start = cp - 1;
+ dp->flags = 0;
+ dp->width_start = NULL;
+ dp->width_end = NULL;
+ dp->width_arg_index = -1;
+ dp->precision_start = NULL;
+ dp->precision_end = NULL;
+ dp->precision_arg_index = -1;
+ dp->arg_index = -1;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const char *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ unsigned int n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = 10 * n + (*np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+
+ /* Read the flags. */
+ for (;;)
+ {
+ if (*cp == '\'')
+ {
+ dp->flags |= FLAG_GROUP;
+ cp++;
+ }
+ else if (*cp == '-')
+ {
+ dp->flags |= FLAG_LEFT;
+ cp++;
+ }
+ else if (*cp == '+')
+ {
+ dp->flags |= FLAG_SHOWSIGN;
+ cp++;
+ }
+ else if (*cp == ' ')
+ {
+ dp->flags |= FLAG_SPACE;
+ cp++;
+ }
+ else if (*cp == '#')
+ {
+ dp->flags |= FLAG_ALT;
+ cp++;
+ }
+ else if (*cp == '0')
+ {
+ dp->flags |= FLAG_ZERO;
+ cp++;
+ }
+ else
+ break;
+ }
+
+ /* Parse the field width. */
+ if (*cp == '*')
+ {
+ dp->width_start = cp;
+ cp++;
+ dp->width_end = cp;
+ if (max_width_length < 1)
+ max_width_length = 1;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const char *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ unsigned int n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = 10 * n + (*np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ dp->width_arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+ if (dp->width_arg_index < 0)
+ dp->width_arg_index = arg_posn++;
+ REGISTER_ARG (dp->width_arg_index, TYPE_INT);
+ }
+ else if (*cp >= '0' && *cp <= '9')
+ {
+ unsigned int width_length;
+
+ dp->width_start = cp;
+ for (; *cp >= '0' && *cp <= '9'; cp++)
+ ;
+ dp->width_end = cp;
+ width_length = dp->width_end - dp->width_start;
+ if (max_width_length < width_length)
+ max_width_length = width_length;
+ }
+
+ /* Parse the precision. */
+ if (*cp == '.')
+ {
+ cp++;
+ if (*cp == '*')
+ {
+ dp->precision_start = cp - 1;
+ cp++;
+ dp->precision_end = cp;
+ if (max_precision_length < 2)
+ max_precision_length = 2;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const char *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ unsigned int n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = 10 * n + (*np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ dp->precision_arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+ if (dp->precision_arg_index < 0)
+ dp->precision_arg_index = arg_posn++;
+ REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
+ }
+ else
+ {
+ unsigned int precision_length;
+
+ dp->precision_start = cp - 1;
+ for (; *cp >= '0' && *cp <= '9'; cp++)
+ ;
+ dp->precision_end = cp;
+ precision_length = dp->precision_end - dp->precision_start;
+ if (max_precision_length < precision_length)
+ max_precision_length = precision_length;
+ }
+ }
+
+ {
+ arg_type type;
+
+ /* Parse argument type/size specifiers. */
+ {
+ int flags = 0;
+
+ for (;;)
+ {
+ if (*cp == 'h')
+ {
+ flags |= (1 << (flags & 1));
+ cp++;
+ }
+ else if (*cp == 'L')
+ {
+ flags |= 4;
+ cp++;
+ }
+ else if (*cp == 'l')
+ {
+ flags += 8;
+ cp++;
+ }
+#ifdef HAVE_INT64_AND_I64
+ else if (cp[0] == 'I' &&
+ cp[1] == '6' &&
+ cp[2] == '4')
+ {
+ flags = 64;
+ cp += 3;
+ }
+#endif
+#ifdef HAVE_INTMAX_T
+ else if (*cp == 'j')
+ {
+ if (sizeof (intmax_t) > sizeof (long))
+ {
+ /* intmax_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (intmax_t) > sizeof (int))
+ {
+ /* intmax_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+#endif
+ else if (*cp == 'z' || *cp == 'Z')
+ {
+ /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
+ because the warning facility in gcc-2.95.2 understands
+ only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
+ if (sizeof (size_t) > sizeof (long))
+ {
+ /* size_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (size_t) > sizeof (int))
+ {
+ /* size_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+ else if (*cp == 't')
+ {
+ if (sizeof (ptrdiff_t) > sizeof (long))
+ {
+ /* ptrdiff_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (ptrdiff_t) > sizeof (int))
+ {
+ /* ptrdiff_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+ else
+ break;
+ }
+
+ /* Read the conversion character. */
+ c = *cp++;
+ switch (c)
+ {
+ case 'd': case 'i':
+#ifdef HAVE_INT64_AND_I64
+ if (flags == 64)
+ type = TYPE_INT64;
+ else
+#endif
+#ifdef HAVE_LONG_LONG
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_LONGLONGINT;
+ else
+#endif
+ if (flags >= 8)
+ type = TYPE_LONGINT;
+ else if (flags & 2)
+ type = TYPE_SCHAR;
+ else if (flags & 1)
+ type = TYPE_SHORT;
+ else
+ type = TYPE_INT;
+ break;
+ case 'o': case 'u': case 'x': case 'X':
+#ifdef HAVE_INT64_AND_I64
+ if (flags == 64)
+ type = TYPE_UINT64;
+ else
+#endif
+#ifdef HAVE_LONG_LONG
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_ULONGLONGINT;
+ else
+#endif
+ if (flags >= 8)
+ type = TYPE_ULONGINT;
+ else if (flags & 2)
+ type = TYPE_UCHAR;
+ else if (flags & 1)
+ type = TYPE_USHORT;
+ else
+ type = TYPE_UINT;
+ break;
+ case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
+ case 'a': case 'A':
+#ifdef HAVE_LONG_DOUBLE
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_LONGDOUBLE;
+ else
+#endif
+ type = TYPE_DOUBLE;
+ break;
+ case 'c':
+ if (flags >= 8)
+#ifdef HAVE_WINT_T
+ type = TYPE_WIDE_CHAR;
+#else
+ goto error;
+#endif
+ else
+ type = TYPE_CHAR;
+ break;
+#ifdef HAVE_WINT_T
+ case 'C':
+ type = TYPE_WIDE_CHAR;
+ c = 'c';
+ break;
+#endif
+ case 's':
+ if (flags >= 8)
+#ifdef HAVE_WCHAR_T
+ type = TYPE_WIDE_STRING;
+#else
+ goto error;
+#endif
+ else
+ type = TYPE_STRING;
+ break;
+#ifdef HAVE_WCHAR_T
+ case 'S':
+ type = TYPE_WIDE_STRING;
+ c = 's';
+ break;
+#endif
+ case 'p':
+ type = TYPE_POINTER;
+ break;
+ case 'n':
+#ifdef HAVE_LONG_LONG
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_COUNT_LONGLONGINT_POINTER;
+ else
+#endif
+ if (flags >= 8)
+ type = TYPE_COUNT_LONGINT_POINTER;
+ else if (flags & 2)
+ type = TYPE_COUNT_SCHAR_POINTER;
+ else if (flags & 1)
+ type = TYPE_COUNT_SHORT_POINTER;
+ else
+ type = TYPE_COUNT_INT_POINTER;
+ break;
+ case '%':
+ type = TYPE_NONE;
+ break;
+ default:
+ /* Unknown conversion character. */
+ goto error;
+ }
+ }
+
+ if (type != TYPE_NONE)
+ {
+ dp->arg_index = arg_index;
+ if (dp->arg_index < 0)
+ dp->arg_index = arg_posn++;
+ REGISTER_ARG (dp->arg_index, type);
+ }
+ dp->conversion = c;
+ dp->dir_end = cp;
+ }
+
+ d->count++;
+ if (d->count >= d_allocated)
+ {
+ char_directive *memory;
+
+ d_allocated = 2 * d_allocated;
+ memory = realloc (d->dir, d_allocated * sizeof (char_directive));
+ if (memory == NULL)
+ /* Out of memory. */
+ goto error;
+ d->dir = memory;
+ }
+ }
+ }
+ d->dir[d->count].dir_start = cp;
+
+ d->max_width_length = max_width_length;
+ d->max_precision_length = max_precision_length;
+ return 0;
+
+error:
+ if (a->arg)
+ free (a->arg);
+ if (d->dir)
+ free (d->dir);
+ return -1;
+}
diff --git a/navit/support/glib/gnulib/printf-parse.h b/navit/support/glib/gnulib/printf-parse.h
new file mode 100644
index 00000000..ab414782
--- /dev/null
+++ b/navit/support/glib/gnulib/printf-parse.h
@@ -0,0 +1,74 @@
+/* Parse printf format string.
+ Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifndef _PRINTF_PARSE_H
+#define _PRINTF_PARSE_H
+
+#include "printf-args.h"
+
+/* Private namespace for gnulib functions */
+#define printf_parse _g_gnulib_printf_parse
+
+/* Flags */
+#define FLAG_GROUP 1 /* ' flag */
+#define FLAG_LEFT 2 /* - flag */
+#define FLAG_SHOWSIGN 4 /* + flag */
+#define FLAG_SPACE 8 /* space flag */
+#define FLAG_ALT 16 /* # flag */
+#define FLAG_ZERO 32
+
+/* A parsed directive. */
+typedef struct
+{
+ const char* dir_start;
+ const char* dir_end;
+ int flags;
+ const char* width_start;
+ const char* width_end;
+ int width_arg_index;
+ const char* precision_start;
+ const char* precision_end;
+ int precision_arg_index;
+ char conversion; /* d i o u x X f e E g G c s p n U % but not C S */
+ int arg_index;
+}
+char_directive;
+
+/* A parsed format string. */
+typedef struct
+{
+ unsigned int count;
+ char_directive *dir;
+ unsigned int max_width_length;
+ unsigned int max_precision_length;
+}
+char_directives;
+
+
+/* Parses the format string. Fills in the number N of directives, and fills
+ in directives[0], ..., directives[N-1], and sets directives[N].dir_start
+ to the end of the format string. Also fills in the arg_type fields of the
+ arguments and the needed count of arguments. */
+#ifdef STATIC
+STATIC
+#else
+extern
+#endif
+int printf_parse (const char *format, char_directives *d, arguments *a);
+
+#endif /* _PRINTF_PARSE_H */
diff --git a/navit/support/glib/gnulib/printf.c b/navit/support/glib/gnulib/printf.c
new file mode 100644
index 00000000..b3392999
--- /dev/null
+++ b/navit/support/glib/gnulib/printf.c
@@ -0,0 +1,154 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 2003 Matthias Clasen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 2003. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "g-gnulib.h"
+#include "vasnprintf.h"
+#include "printf.h"
+
+int _g_gnulib_printf (char const *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = _g_gnulib_vprintf (format, args);
+ va_end (args);
+
+ return retval;
+}
+
+int _g_gnulib_fprintf (FILE *file, char const *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = _g_gnulib_vfprintf (file, format, args);
+ va_end (args);
+
+ return retval;
+}
+
+int _g_gnulib_sprintf (char *string, char const *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = _g_gnulib_vsprintf (string, format, args);
+ va_end (args);
+
+ return retval;
+}
+
+int _g_gnulib_snprintf (char *string, size_t n, char const *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = _g_gnulib_vsnprintf (string, n, format, args);
+ va_end (args);
+
+ return retval;
+}
+
+int _g_gnulib_vprintf (char const *format, va_list args)
+{
+ return _g_gnulib_vfprintf (stdout, format, args);
+}
+
+int _g_gnulib_vfprintf (FILE *file, char const *format, va_list args)
+{
+ char *result;
+ size_t length;
+
+ result = vasnprintf (NULL, &length, format, args);
+ if (result == NULL)
+ return -1;
+
+ fwrite (result, 1, length, file);
+ free (result);
+
+ return length;
+}
+
+int _g_gnulib_vsprintf (char *string, char const *format, va_list args)
+{
+ char *result;
+ size_t length;
+
+ result = vasnprintf (NULL, &length, format, args);
+ if (result == NULL)
+ return -1;
+
+ memcpy (string, result, length + 1);
+ free (result);
+
+ return length;
+}
+
+int _g_gnulib_vsnprintf (char *string, size_t n, char const *format, va_list args)
+{
+ char *result;
+ size_t length;
+
+ result = vasnprintf (NULL, &length, format, args);
+ if (result == NULL)
+ return -1;
+
+ if (n > 0)
+ {
+ memcpy (string, result, MIN(length + 1, n));
+ string[n - 1] = 0;
+ }
+
+ free (result);
+
+ return length;
+}
+
+int _g_gnulib_vasprintf (char **result, char const *format, va_list args)
+{
+ size_t length;
+
+ *result = vasnprintf (NULL, &length, format, args);
+ if (*result == NULL)
+ return -1;
+
+ return length;
+}
+
+
+
+
+
diff --git a/navit/support/glib/gnulib/printf.h b/navit/support/glib/gnulib/printf.h
new file mode 100644
index 00000000..a7be56f4
--- /dev/null
+++ b/navit/support/glib/gnulib/printf.h
@@ -0,0 +1,57 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 2003 Matthias Clasen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GNULIB_PRINTF_H__
+#define __GNULIB_PRINTF_H__
+
+#include <stdarg.h>
+#include <stdio.h>
+
+int _g_gnulib_printf (char const *format,
+ ...);
+int _g_gnulib_fprintf (FILE *file,
+ char const *format,
+ ...);
+int _g_gnulib_sprintf (char *string,
+ char const *format,
+ ...);
+int _g_gnulib_snprintf (char *string,
+ size_t n,
+ char const *format,
+ ...);
+int _g_gnulib_vprintf (char const *format,
+ va_list args);
+int _g_gnulib_vfprintf (FILE *file,
+ char const *format,
+ va_list args);
+int _g_gnulib_vsprintf (char *string,
+ char const *format,
+ va_list args);
+int _g_gnulib_vsnprintf (char *string,
+ size_t n,
+ char const *format,
+ va_list args);
+int _g_gnulib_vasprintf (char **result,
+ char const *format,
+ va_list args);
+
+
+#endif /* __GNULIB_PRINTF_H__ */
+
+
+
diff --git a/navit/support/glib/gnulib/vasnprintf.c b/navit/support/glib/gnulib/vasnprintf.c
new file mode 100644
index 00000000..5ecc419b
--- /dev/null
+++ b/navit/support/glib/gnulib/vasnprintf.c
@@ -0,0 +1,1084 @@
+/* vsprintf with automatic memory allocation.
+ Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifndef _WIN32
+/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include "glib/galloca.h"
+
+#include "g-gnulib.h"
+
+/* Specification. */
+#include "vasnprintf.h"
+
+#include <stdio.h> /* snprintf(), sprintf() */
+#include <stdlib.h> /* abort(), malloc(), realloc(), free() */
+#include <string.h> /* memcpy(), strlen() */
+#include <errno.h> /* errno */
+#include <limits.h> /* CHAR_BIT */
+#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
+#include "printf-parse.h"
+
+#ifdef HAVE_WCHAR_T
+# ifdef HAVE_WCSLEN
+# define local_wcslen wcslen
+# else
+ /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
+ a dependency towards this library, here is a local substitute.
+ Define this substitute only once, even if this file is included
+ twice in the same compilation unit. */
+# ifndef local_wcslen_defined
+# define local_wcslen_defined 1
+static size_t
+local_wcslen (const wchar_t *s)
+{
+ const wchar_t *ptr;
+
+ for (ptr = s; *ptr != (wchar_t) 0; ptr++)
+ ;
+ return ptr - s;
+}
+# endif
+# endif
+#endif
+
+/* For those losing systems which don't have 'alloca' we have to add
+ some additional code emulating it. */
+#ifdef HAVE_ALLOCA
+# define freea(p) /* nothing */
+#else
+# define alloca(n) malloc (n)
+# define freea(p) free (p)
+#endif
+
+#ifndef HAVE_LONG_LONG_FORMAT
+static int
+print_long_long (char *buf,
+ int len,
+ int width,
+ int precision,
+ unsigned long flags,
+ char conversion,
+ unsigned long long number)
+{
+ int negative = FALSE;
+ char buffer[128];
+ char *bufferend;
+ char *pointer;
+ int base;
+ static const char *upper = "0123456789ABCDEFX";
+ static const char *lower = "0123456789abcdefx";
+ const char *digits;
+ int i;
+ char *p;
+ int count;
+
+#define EMIT(c) \
+ if (p - buf == len - 1) \
+ { \
+ *p++ = '\0'; \
+ return len; \
+ } \
+ else \
+ *p++ = c;
+
+ p = buf;
+
+ switch (conversion)
+ {
+ case 'o':
+ base = 8;
+ digits = lower;
+ negative = FALSE;
+ break;
+ case 'x':
+ base = 16;
+ digits = lower;
+ negative = FALSE;
+ break;
+ case 'X':
+ base = 16;
+ digits = upper;
+ negative = FALSE;
+ break;
+ default:
+ base = 10;
+ digits = lower;
+ negative = (long long)number < 0;
+ if (negative)
+ number = -((long long)number);
+ break;
+ }
+
+ /* Build number */
+ pointer = bufferend = &buffer[sizeof(buffer) - 1];
+ *pointer-- = '\0';
+ for (i = 1; i < (int)sizeof(buffer); i++)
+ {
+ *pointer-- = digits[number % base];
+ number /= base;
+ if (number == 0)
+ break;
+ }
+
+ /* Adjust width */
+ width -= (bufferend - pointer) - 1;
+
+ /* Adjust precision */
+ if (precision != -1)
+ {
+ precision -= (bufferend - pointer) - 1;
+ if (precision < 0)
+ precision = 0;
+ flags |= FLAG_ZERO;
+ }
+
+ /* Adjust width further */
+ if (negative || (flags & FLAG_SHOWSIGN) || (flags & FLAG_SPACE))
+ width--;
+ if (flags & FLAG_ALT)
+ {
+ switch (base)
+ {
+ case 16:
+ width -= 2;
+ break;
+ case 8:
+ width--;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Output prefixes spaces if needed */
+ if (! ((flags & FLAG_LEFT) ||
+ ((flags & FLAG_ZERO) && (precision == -1))))
+ {
+ count = (precision == -1) ? 0 : precision;
+ while (width-- > count)
+ *p++ = ' ';
+ }
+
+ /* width has been adjusted for signs and alternatives */
+ if (negative)
+ {
+ EMIT ('-');
+ }
+ else if (flags & FLAG_SHOWSIGN)
+ {
+ EMIT('+');
+ }
+ else if (flags & FLAG_SPACE)
+ {
+ EMIT(' ');
+ }
+
+ if (flags & FLAG_ALT)
+ {
+ switch (base)
+ {
+ case 8:
+ EMIT('0');
+ break;
+ case 16:
+ EMIT('0');
+ EMIT(digits[16]);
+ break;
+ default:
+ break;
+ } /* switch base */
+ }
+
+ /* Output prefixed zero padding if needed */
+ if (flags & FLAG_ZERO)
+ {
+ if (precision == -1)
+ precision = width;
+ while (precision-- > 0)
+ {
+ EMIT('0');
+ width--;
+ }
+ }
+
+ /* Output the number itself */
+ while (*(++pointer))
+ {
+ EMIT(*pointer);
+ }
+
+ /* Output trailing spaces if needed */
+ if (flags & FLAG_LEFT)
+ {
+ while (width-- > 0)
+ EMIT(' ');
+ }
+
+ EMIT('\0');
+
+ return p - buf - 1;
+}
+#endif
+
+char *
+vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
+{
+ char_directives d;
+ arguments a;
+
+ if (printf_parse (format, &d, &a) < 0)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+#define CLEANUP() \
+ free (d.dir); \
+ if (a.arg) \
+ free (a.arg);
+
+ if (printf_fetchargs (args, &a) < 0)
+ {
+ CLEANUP ();
+ errno = EINVAL;
+ return NULL;
+ }
+
+ {
+ char *buf =
+ (char *) alloca (7 + d.max_width_length + d.max_precision_length + 6);
+ const char *cp;
+ unsigned int i;
+ char_directive *dp;
+ /* Output string accumulator. */
+ char *result;
+ size_t allocated;
+ size_t length;
+
+ if (resultbuf != NULL)
+ {
+ result = resultbuf;
+ allocated = *lengthp;
+ }
+ else
+ {
+ result = NULL;
+ allocated = 0;
+ }
+ length = 0;
+ /* Invariants:
+ result is either == resultbuf or == NULL or malloc-allocated.
+ If length > 0, then result != NULL. */
+
+#define ENSURE_ALLOCATION(needed) \
+ if ((needed) > allocated) \
+ { \
+ char *memory; \
+ \
+ allocated = (allocated > 0 ? 2 * allocated : 12); \
+ if ((needed) > allocated) \
+ allocated = (needed); \
+ if (result == resultbuf || result == NULL) \
+ memory = (char *) malloc (allocated); \
+ else \
+ memory = (char *) realloc (result, allocated); \
+ \
+ if (memory == NULL) \
+ { \
+ if (!(result == resultbuf || result == NULL)) \
+ free (result); \
+ freea (buf); \
+ CLEANUP (); \
+ errno = ENOMEM; \
+ return NULL; \
+ } \
+ if (result == resultbuf && length > 0) \
+ memcpy (memory, result, length); \
+ result = memory; \
+ }
+
+ for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
+ {
+ if (cp != dp->dir_start)
+ {
+ size_t n = dp->dir_start - cp;
+
+ ENSURE_ALLOCATION (length + n);
+ memcpy (result + length, cp, n);
+ length += n;
+ }
+ if (i == d.count)
+ break;
+
+ /* Execute a single directive. */
+ if (dp->conversion == '%')
+ {
+ if (!(dp->arg_index < 0))
+ abort ();
+ ENSURE_ALLOCATION (length + 1);
+ result[length] = '%';
+ length += 1;
+ }
+ else
+ {
+ if (!(dp->arg_index >= 0))
+ abort ();
+
+ if (dp->conversion == 'n')
+ {
+ switch (a.arg[dp->arg_index].type)
+ {
+ case TYPE_COUNT_SCHAR_POINTER:
+ *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
+ break;
+ case TYPE_COUNT_SHORT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_short_pointer = length;
+ break;
+ case TYPE_COUNT_INT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_int_pointer = length;
+ break;
+ case TYPE_COUNT_LONGINT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
+ break;
+#ifdef HAVE_LONG_LONG
+ case TYPE_COUNT_LONGLONGINT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
+ break;
+#endif
+ default:
+ abort ();
+ }
+ }
+ else
+ {
+ arg_type type = a.arg[dp->arg_index].type;
+ char *p;
+ unsigned int prefix_count;
+ int prefixes[2];
+#if !HAVE_SNPRINTF
+ unsigned int tmp_length;
+ char tmpbuf[700];
+ char *tmp;
+
+ /* Allocate a temporary buffer of sufficient size for calling
+ sprintf. */
+ {
+ unsigned int width;
+ unsigned int precision;
+
+ width = 0;
+ if (dp->width_start != dp->width_end)
+ {
+ if (dp->width_arg_index >= 0)
+ {
+ int arg;
+
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->width_arg_index].a.a_int;
+ width = (arg < 0 ? -arg : arg);
+ }
+ else
+ {
+ const char *digitp = dp->width_start;
+
+ do
+ width = width * 10 + (*digitp++ - '0');
+ while (digitp != dp->width_end);
+ }
+ }
+
+ precision = 6;
+ if (dp->precision_start != dp->precision_end)
+ {
+ if (dp->precision_arg_index >= 0)
+ {
+ int arg;
+
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->precision_arg_index].a.a_int;
+ precision = (arg < 0 ? 0 : arg);
+ }
+ else
+ {
+ const char *digitp = dp->precision_start + 1;
+
+ precision = 0;
+ while (digitp != dp->precision_end)
+ precision = precision * 10 + (*digitp++ - '0');
+ }
+ }
+
+ switch (dp->conversion)
+ {
+ case 'd': case 'i': case 'u':
+# ifdef HAVE_LONG_LONG
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ break;
+
+ case 'o':
+# ifdef HAVE_LONG_LONG
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ break;
+
+ case 'x': case 'X':
+# ifdef HAVE_LONG_LONG
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading sign or alternate form */
+ else
+# endif
+# ifdef HAVE_INT64_AND_I64
+ if (type == TYPE_INT64 || type == TYPE_UINT64)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned __int64) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading sign or alternate form */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading sign or alternate form */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading sign or alternate form */
+ break;
+
+ case 'f': case 'F':
+# ifdef HAVE_LONG_DOUBLE
+ if (type == TYPE_LONGDOUBLE)
+ tmp_length =
+ (unsigned int) (LDBL_MAX_EXP
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + precision
+ + 10; /* sign, decimal point etc. */
+ else
+# endif
+ tmp_length =
+ (unsigned int) (DBL_MAX_EXP
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + precision
+ + 10; /* sign, decimal point etc. */
+ break;
+
+ case 'e': case 'E': case 'g': case 'G':
+ case 'a': case 'A':
+ tmp_length =
+ precision
+ + 12; /* sign, decimal point, exponent etc. */
+ break;
+
+ case 'c':
+# ifdef HAVE_WINT_T
+ if (type == TYPE_WIDE_CHAR)
+ tmp_length = MB_CUR_MAX;
+ else
+# endif
+ tmp_length = 1;
+ break;
+
+ case 's':
+# ifdef HAVE_WCHAR_T
+ if (type == TYPE_WIDE_STRING)
+ tmp_length =
+ (a.arg[dp->arg_index].a.a_wide_string == NULL
+ ? 6 /* wcslen(L"(null)") */
+ : local_wcslen (a.arg[dp->arg_index].a.a_wide_string))
+ * MB_CUR_MAX;
+ else
+# endif
+ tmp_length = a.arg[dp->arg_index].a.a_string == NULL
+ ? 6 /* strlen("(null)") */
+ : strlen (a.arg[dp->arg_index].a.a_string);
+ break;
+
+ case 'p':
+ tmp_length =
+ (unsigned int) (sizeof (void *) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading 0x */
+ break;
+
+ default:
+ abort ();
+ }
+
+ if (tmp_length < width)
+ tmp_length = width;
+
+ tmp_length++; /* account for trailing NUL */
+ }
+
+ if (tmp_length <= sizeof (tmpbuf))
+ tmp = tmpbuf;
+ else
+ {
+ tmp = (char *) malloc (tmp_length);
+ if (tmp == NULL)
+ {
+ /* Out of memory. */
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ freea (buf);
+ CLEANUP ();
+ errno = ENOMEM;
+ return NULL;
+ }
+ }
+#endif
+
+ /* Construct the format string for calling snprintf or
+ sprintf. */
+ p = buf;
+ *p++ = '%';
+ if (dp->flags & FLAG_GROUP)
+ *p++ = '\'';
+ if (dp->flags & FLAG_LEFT)
+ *p++ = '-';
+ if (dp->flags & FLAG_SHOWSIGN)
+ *p++ = '+';
+ if (dp->flags & FLAG_SPACE)
+ *p++ = ' ';
+ if (dp->flags & FLAG_ALT)
+ *p++ = '#';
+ if (dp->flags & FLAG_ZERO)
+ *p++ = '0';
+ if (dp->width_start != dp->width_end)
+ {
+ size_t n = dp->width_end - dp->width_start;
+ memcpy (p, dp->width_start, n);
+ p += n;
+ }
+ if (dp->precision_start != dp->precision_end)
+ {
+ size_t n = dp->precision_end - dp->precision_start;
+ memcpy (p, dp->precision_start, n);
+ p += n;
+ }
+
+ switch (type)
+ {
+#ifdef HAVE_INT64_AND_I64
+ case TYPE_INT64:
+ case TYPE_UINT64:
+ *p++ = 'I';
+ *p++ = '6';
+ *p++ = '4';
+ break;
+#endif
+#ifdef HAVE_LONG_LONG
+ case TYPE_LONGLONGINT:
+ case TYPE_ULONGLONGINT:
+#ifdef HAVE_INT64_AND_I64 /* The system (sn)printf uses %I64. Also assume
+ * that long long == __int64.
+ */
+ *p++ = 'I';
+ *p++ = '6';
+ *p++ = '4';
+ break;
+#else
+ *p++ = 'l';
+ /*FALLTHROUGH*/
+#endif
+#endif
+ case TYPE_LONGINT:
+ case TYPE_ULONGINT:
+#ifdef HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+#endif
+#ifdef HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+#endif
+ *p++ = 'l';
+ break;
+#ifdef HAVE_LONG_DOUBLE
+ case TYPE_LONGDOUBLE:
+ *p++ = 'L';
+ break;
+#endif
+ default:
+ break;
+ }
+ *p = dp->conversion;
+#if HAVE_SNPRINTF
+ p[1] = '%';
+ p[2] = 'n';
+ p[3] = '\0';
+#else
+ p[1] = '\0';
+#endif
+
+ /* Construct the arguments for calling snprintf or sprintf. */
+ prefix_count = 0;
+ if (dp->width_arg_index >= 0)
+ {
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
+ }
+ if (dp->precision_arg_index >= 0)
+ {
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
+ }
+
+#if HAVE_SNPRINTF
+ /* Prepare checking whether snprintf returns the count
+ via %n. */
+ ENSURE_ALLOCATION (length + 1);
+ result[length] = '\0';
+#endif
+
+ for (;;)
+ {
+ size_t maxlen;
+ int count;
+#if HAVE_SNPRINTF
+ int retcount;
+#endif
+
+ maxlen = allocated - length;
+ count = -1;
+
+#if HAVE_SNPRINTF
+ retcount = 0;
+
+#define SNPRINTF_BUF(arg) \
+ switch (prefix_count) \
+ { \
+ case 0: \
+ retcount = snprintf (result + length, maxlen, buf, \
+ arg, &count); \
+ break; \
+ case 1: \
+ retcount = snprintf (result + length, maxlen, buf, \
+ prefixes[0], arg, &count); \
+ break; \
+ case 2: \
+ retcount = snprintf (result + length, maxlen, buf, \
+ prefixes[0], prefixes[1], arg, \
+ &count); \
+ break; \
+ default: \
+ abort (); \
+ }
+#else
+#define SNPRINTF_BUF(arg) \
+ switch (prefix_count) \
+ { \
+ case 0: \
+ count = sprintf (tmp, buf, arg); \
+ break; \
+ case 1: \
+ count = sprintf (tmp, buf, prefixes[0], arg); \
+ break; \
+ case 2: \
+ count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
+ arg); \
+ break; \
+ default: \
+ abort (); \
+ }
+#endif
+
+ switch (type)
+ {
+ case TYPE_SCHAR:
+ {
+ int arg = a.arg[dp->arg_index].a.a_schar;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_UCHAR:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_SHORT:
+ {
+ int arg = a.arg[dp->arg_index].a.a_short;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_USHORT:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_INT:
+ {
+ int arg = a.arg[dp->arg_index].a.a_int;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_UINT:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_uint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_LONGINT:
+ {
+ long int arg = a.arg[dp->arg_index].a.a_longint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_ULONGINT:
+ {
+ unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#ifdef HAVE_INT64_AND_I64
+ case TYPE_INT64:
+ {
+ __int64 arg = a.arg[dp->arg_index].a.a_int64;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_UINT64:
+ {
+ unsigned __int64 arg = a.arg[dp->arg_index].a.a_uint64;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+#ifdef HAVE_LONG_LONG
+#ifndef HAVE_LONG_LONG_FORMAT
+ case TYPE_LONGLONGINT:
+ case TYPE_ULONGLONGINT:
+ {
+ unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
+ int width;
+ int precision;
+
+ width = 0;
+ if (dp->width_start != dp->width_end)
+ {
+ if (dp->width_arg_index >= 0)
+ {
+ int arg;
+
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->width_arg_index].a.a_int;
+ width = (arg < 0 ? -arg : arg);
+ }
+ else
+ {
+ const char *digitp = dp->width_start;
+
+ do
+ width = width * 10 + (*digitp++ - '0');
+ while (digitp != dp->width_end);
+ }
+ }
+
+ precision = -1;
+ if (dp->precision_start != dp->precision_end)
+ {
+ if (dp->precision_arg_index >= 0)
+ {
+ int arg;
+
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->precision_arg_index].a.a_int;
+ precision = (arg < 0 ? 0 : arg);
+ }
+ else
+ {
+ const char *digitp = dp->precision_start + 1;
+
+ precision = 0;
+ do
+ precision = precision * 10 + (*digitp++ - '0');
+ while (digitp != dp->precision_end);
+ }
+ }
+
+#if HAVE_SNPRINTF
+ count = print_long_long (result + length, maxlen,
+ width, precision,
+ dp->flags,
+ dp->conversion,
+ arg);
+#else
+ count = print_long_long (tmp, tmp_length,
+ width, precision,
+ dp->flags,
+ dp->conversion,
+ arg);
+#endif
+ }
+ break;
+#else
+ case TYPE_LONGLONGINT:
+ {
+ long long int arg = a.arg[dp->arg_index].a.a_longlongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_ULONGLONGINT:
+ {
+ unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+#endif
+ case TYPE_DOUBLE:
+ {
+ double arg = a.arg[dp->arg_index].a.a_double;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#ifdef HAVE_LONG_DOUBLE
+ case TYPE_LONGDOUBLE:
+ {
+ long double arg = a.arg[dp->arg_index].a.a_longdouble;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_CHAR:
+ {
+ int arg = a.arg[dp->arg_index].a.a_char;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#ifdef HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+ {
+ wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_STRING:
+ {
+ const char *arg = a.arg[dp->arg_index].a.a_string == NULL
+ ? "(null)"
+ : a.arg[dp->arg_index].a.a_string;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#ifdef HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+ {
+ const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string == NULL
+ ? L"(null)"
+ : a.arg[dp->arg_index].a.a_wide_string;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_POINTER:
+ {
+ void *arg = a.arg[dp->arg_index].a.a_pointer;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ default:
+ abort ();
+ }
+
+#if HAVE_SNPRINTF
+ /* Portability: Not all implementations of snprintf()
+ are ISO C 99 compliant. Determine the number of
+ bytes that snprintf() has produced or would have
+ produced. */
+ if (count >= 0)
+ {
+ /* Verify that snprintf() has NUL-terminated its
+ result. */
+ if (count < maxlen && result[length + count] != '\0')
+ abort ();
+ /* Portability hack. */
+ if (retcount > count)
+ count = retcount;
+ }
+ else
+ {
+ /* snprintf() doesn't understand the '%n'
+ directive. */
+ if (p[1] != '\0')
+ {
+ /* Don't use the '%n' directive; instead, look
+ at the snprintf() return value. */
+ p[1] = '\0';
+ continue;
+ }
+ count = retcount;
+ }
+#endif
+
+ /* Attempt to handle failure. */
+ if (count < 0)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ freea (buf);
+ CLEANUP ();
+ errno = EINVAL;
+ return NULL;
+ }
+
+#if !HAVE_SNPRINTF
+ if (count >= tmp_length)
+ /* tmp_length was incorrectly calculated - fix the
+ code above! */
+ abort ();
+#endif
+
+ /* Make room for the result. */
+ if (count >= maxlen)
+ {
+ /* Need at least count bytes. But allocate
+ proportionally, to avoid looping eternally if
+ snprintf() reports a too small count. */
+ size_t n = length + count;
+
+ if (n < 2 * allocated)
+ n = 2 * allocated;
+
+ ENSURE_ALLOCATION (n);
+#if HAVE_SNPRINTF
+ continue;
+#endif
+ }
+
+#if HAVE_SNPRINTF
+ /* The snprintf() result did fit. */
+#else
+ /* Append the sprintf() result. */
+ memcpy (result + length, tmp, count);
+ if (tmp != tmpbuf)
+ free (tmp);
+#endif
+
+ length += count;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Add the final NUL. */
+ ENSURE_ALLOCATION (length + 1);
+ result[length] = '\0';
+
+ if (result != resultbuf && length + 1 < allocated)
+ {
+ /* Shrink the allocated memory if possible. */
+ char *memory;
+
+ memory = (char *) realloc (result, length + 1);
+ if (memory != NULL)
+ result = memory;
+ }
+
+ freea (buf);
+ CLEANUP ();
+ *lengthp = length;
+ return result;
+ }
+}
diff --git a/navit/support/glib/gnulib/vasnprintf.h b/navit/support/glib/gnulib/vasnprintf.h
new file mode 100644
index 00000000..65f1bc13
--- /dev/null
+++ b/navit/support/glib/gnulib/vasnprintf.h
@@ -0,0 +1,61 @@
+/* vsprintf with automatic memory allocation.
+ Copyright (C) 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifndef _VASNPRINTF_H
+#define _VASNPRINTF_H
+
+/* Get va_list. */
+#include <stdarg.h>
+
+/* Get size_t. */
+#include <stddef.h>
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+# define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __format__ format
+# define __printf__ printf
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Write formatted output to a string dynamically allocated with malloc().
+ You can pass a preallocated buffer for the result in RESULTBUF and its
+ size in *LENGTHP; otherwise you pass RESULTBUF = NULL.
+ If successful, return the address of the string (this may be = RESULTBUF
+ if no dynamic memory allocation was necessary) and set *LENGTHP to the
+ number of resulting bytes, excluding the trailing NUL. Upon error, set
+ errno and return NULL. */
+extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
+ __attribute__ ((__format__ (__printf__, 3, 0)));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VASNPRINTF_H */