summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--gst/Makefile.am10
-rw-r--r--gst/printf/Makefile.am18
-rw-r--r--gst/printf/README58
-rw-r--r--gst/printf/asnprintf.c40
-rw-r--r--gst/printf/gst-printf.h48
-rw-r--r--gst/printf/printf-args.c132
-rw-r--r--gst/printf/printf-args.h142
-rw-r--r--gst/printf/printf-parse.c449
-rw-r--r--gst/printf/printf-parse.h74
-rw-r--r--gst/printf/printf.c157
-rw-r--r--gst/printf/printf.h62
-rw-r--r--gst/printf/vasnprintf.c980
-rw-r--r--gst/printf/vasnprintf.h61
14 files changed, 2230 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index 34b7448b0..23a2055e7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -740,6 +740,7 @@ gst/Makefile
gst/gstconfig.h
gst/gstversion.h
gst/parse/Makefile
+gst/printf/Makefile
libs/Makefile
libs/gst/Makefile
libs/gst/base/Makefile
diff --git a/gst/Makefile.am b/gst/Makefile.am
index eb51dc142..032226513 100644
--- a/gst/Makefile.am
+++ b/gst/Makefile.am
@@ -26,9 +26,14 @@ else
GST_PLUGIN_SRC = gstplugin.c
endif
-SUBDIRS = $(SUBDIRS_PARSE)
+# FIXME: might not be needed if debug logging is disabled
+SUBDIRS_PRINTF = printf
+GST_PRINTF_LA = printf/libgstprintf.la
-DIST_SUBDIRS = parse
+
+SUBDIRS = $(SUBDIRS_PARSE) $(SUBDIRS_PRINTF)
+
+DIST_SUBDIRS = parse printf
# make variables for all generated source and header files to make the
# distinction clear
@@ -132,6 +137,7 @@ libgstreamer_@GST_API_VERSION@_la_CFLAGS = \
libgstreamer_@GST_API_VERSION@_la_LIBADD = \
$(GST_PARSE_LA) \
+ $(GST_PRINTF_LA) \
$(GST_ALL_LIBS) \
$(WIN32_LIBS) \
$(LIBM)
diff --git a/gst/printf/Makefile.am b/gst/printf/Makefile.am
new file mode 100644
index 000000000..d3f407aea
--- /dev/null
+++ b/gst/printf/Makefile.am
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = $(GLIB_CFLAGS)
+
+noinst_LTLIBRARIES = libgstprintf.la
+
+libgstprintf_la_CFLAGS =
+libgstprintf_la_SOURCES = \
+ asnprintf.c \
+ printf-args.c \
+ printf-args.h \
+ printf-parse.c \
+ printf-parse.h \
+ vasnprintf.c \
+ vasnprintf.h \
+ printf.c \
+ printf.h \
+ gst-printf.h
+
+EXTRA_DIST = README
diff --git a/gst/printf/README b/gst/printf/README
new file mode 100644
index 000000000..04ce64628
--- /dev/null
+++ b/gst/printf/README
@@ -0,0 +1,58 @@
+The files
+
+ asnprintf.c
+ printf-args.c
+ printf-args.h
+ printf-parse.c
+ printf-parse.h
+ vasnprintf.c
+ vasnprintf.h
+
+are taken from the vasnprintf module of the GNUlib package, which can
+be found at:
+
+ http://www.gnu.org/software/gnulib/
+
+All files have been modified to include g-gnulib.h.
+
+vasnprintf.c has also been modified to include support for long long
+printing if the system printf doesn't. This code is protected by
+#ifndef HAVE_LONG_LONG_FORMAT.
+
+Code has been added to printf-args.[ch], printf-parse.c and vasnprintf.c
+to support printing of __int64 values with the I64 format modifier. This
+is protected by #ifdef HAVE_INT64_AND_I64.
+
+The files
+
+ printf.h
+ printf.c
+ g-gnulib.h
+
+have been written by me. printf.[hc] contain implementations of the
+remaining functions in the printf family based on vasnprintf.
+g-gnulib.h is included by all source files in order to move all
+exported functions to the _g_gnulib namespace, replace malloc by
+g_malloc and make sure that snprintf is only used if it implements
+C99 return value semantics.
+
+Matthias Clasen
+November 1, 2003
+
+-----
+
+GStreamer modifications
+
+This was imported from GLib's gnulib subdirectory.
+
+g-gnulib.h and _g_gnulib namespace has been changed to gst-printf.h and
+__gst_printf namespace for GStreamer. Also #define HAVE_SNPRINTF 0 has
+been changed to #undef HAVE_SNPRINTF, and HAVE_ALLOCA has been changed to
+GLIB_HAVE_ALLOCA_H
+
+We will also add support for our custom printf format specifiers.
+
+Files have also been indented with gst-indent, so this is basically a
+permanent fork and any patches will have to be merged manually.
+
+March 30, 2013.
diff --git a/gst/printf/asnprintf.c b/gst/printf/asnprintf.c
new file mode 100644
index 000000000..d606d38d3
--- /dev/null
+++ b/gst/printf/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 "gst-printf.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/gst/printf/gst-printf.h b/gst/printf/gst-printf.h
new file mode 100644
index 000000000..8860003fd
--- /dev/null
+++ b/gst/printf/gst-printf.h
@@ -0,0 +1,48 @@
+/* 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.h>
+
+/* Private namespace for gnulib functions */
+#define asnprintf __gst_asnprintf
+#define vasnprintf __gst_vasnprintf
+#define printf_parse __gst_printf_parse
+#define printf_fetchargs __gst_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
+#undef HAVE_SNPRINTF
+#endif
+
+
+#endif /* __G_GNULIB_H__ */
diff --git a/gst/printf/printf-args.c b/gst/printf/printf-args.c
new file mode 100644
index 000000000..5ca693cc5
--- /dev/null
+++ b/gst/printf/printf-args.c
@@ -0,0 +1,132 @@
+/* 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 "gst-printf.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/gst/printf/printf-args.h b/gst/printf/printf-args.h
new file mode 100644
index 000000000..082567568
--- /dev/null
+++ b/gst/printf/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/gst/printf/printf-parse.c b/gst/printf/printf-parse.c
new file mode 100644
index 000000000..933867b39
--- /dev/null
+++ b/gst/printf/printf-parse.c
@@ -0,0 +1,449 @@
+/* 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 "gst-printf.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/gst/printf/printf-parse.h b/gst/printf/printf-parse.h
new file mode 100644
index 000000000..a76cecf5d
--- /dev/null
+++ b/gst/printf/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 __gst_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/gst/printf/printf.c b/gst/printf/printf.c
new file mode 100644
index 000000000..ea0b68089
--- /dev/null
+++ b/gst/printf/printf.c
@@ -0,0 +1,157 @@
+/* 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 "gst-printf.h"
+#include "vasnprintf.h"
+#include "printf.h"
+
+int
+__gst_printf (char const *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = __gst_vprintf (format, args);
+ va_end (args);
+
+ return retval;
+}
+
+int
+__gst_fprintf (FILE * file, char const *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = __gst_vfprintf (file, format, args);
+ va_end (args);
+
+ return retval;
+}
+
+int
+__gst_sprintf (char *string, char const *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = __gst_vsprintf (string, format, args);
+ va_end (args);
+
+ return retval;
+}
+
+int
+__gst_snprintf (char *string, size_t n, char const *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = __gst_vsnprintf (string, n, format, args);
+ va_end (args);
+
+ return retval;
+}
+
+int
+__gst_vprintf (char const *format, va_list args)
+{
+ return __gst_vfprintf (stdout, format, args);
+}
+
+int
+__gst_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
+__gst_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
+__gst_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
+__gst_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/gst/printf/printf.h b/gst/printf/printf.h
new file mode 100644
index 000000000..f39cf5432
--- /dev/null
+++ b/gst/printf/printf.h
@@ -0,0 +1,62 @@
+/* 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 __gst_printf (char const *format,
+ ...);
+
+int __gst_fprintf (FILE *file,
+ char const *format,
+ ...);
+
+int __gst_sprintf (char *string,
+ char const *format,
+ ...);
+
+int __gst_snprintf (char *string,
+ size_t n,
+ char const *format,
+ ...);
+
+int __gst_vprintf (char const *format,
+ va_list args);
+
+int __gst_vfprintf (FILE *file,
+ char const *format,
+ va_list args);
+
+int __gst_vsprintf (char *string,
+ char const *format,
+ va_list args);
+
+int __gst_vsnprintf (char *string,
+ size_t n,
+ char const *format,
+ va_list args);
+
+int __gst_vasprintf (char **result,
+ char const *format,
+ va_list args);
+
+
+#endif /* __GNULIB_PRINTF_H__ */
diff --git a/gst/printf/vasnprintf.c b/gst/printf/vasnprintf.c
new file mode 100644
index 000000000..ef6a9e13d
--- /dev/null
+++ b/gst/printf/vasnprintf.c
@@ -0,0 +1,980 @@
+/* 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 "gst-printf.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 GLIB_HAVE_ALLOCA_H
+# 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/gst/printf/vasnprintf.h b/gst/printf/vasnprintf.h
new file mode 100644
index 000000000..65f1bc13d
--- /dev/null
+++ b/gst/printf/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 */