printf: make printf parser recognise our pointer extension format
authorTim-Philipp Müller <tim@centricular.net>
Sun, 7 Apr 2013 15:41:40 +0000 (16:41 +0100)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Fri, 12 Apr 2013 22:05:57 +0000 (23:05 +0100)
and call the hook to get a string for the pointer instead.

https://bugzilla.gnome.org/show_bug.cgi?id=613081

gst/printf/printf-args.c
gst/printf/printf-args.h
gst/printf/printf-parse.c
gst/printf/printf-parse.h
gst/printf/vasnprintf.c

index 5ca693c..1177ddb 100644 (file)
@@ -105,6 +105,7 @@ printf_fetchargs (va_list args, arguments * a)
         break;
 #endif
       case TYPE_POINTER:
+      case TYPE_POINTER_EXT:
         ap->a.a_pointer = va_arg (args, void *);
         break;
       case TYPE_COUNT_SCHAR_POINTER:
index 0825675..12a3c18 100644 (file)
@@ -32,6 +32,7 @@
 /* Get va_list.  */
 #include <stdarg.h>
 
+#define POINTER_EXT_SIGNIFIER_CHAR '\a'
 
 /* Argument types */
 typedef enum
@@ -66,6 +67,7 @@ typedef enum
   TYPE_WIDE_STRING,
 #endif
   TYPE_POINTER,
+  TYPE_POINTER_EXT,
   TYPE_COUNT_SCHAR_POINTER,
   TYPE_COUNT_SHORT_POINTER,
   TYPE_COUNT_INT_POINTER,
@@ -120,6 +122,9 @@ typedef struct
 #endif
   }
   a;
+
+  /* string to replace pointer argument with for TYPE_POINTER_EXT */
+  char *ext_string;
 }
 argument;
 
index 933867b..1502053 100644 (file)
@@ -80,8 +80,11 @@ printf_parse (const char *format, char_directives * d, arguments * a)
          goto error;                                                   \
        a->arg = memory;                                                \
       }                                                                        \
-    while (a->count <= n)                                              \
-      a->arg[a->count++].type = TYPE_NONE;                             \
+    while (a->count <= n) {                             \
+      a->arg[a->count].type = TYPE_NONE;                \
+      a->arg[a->count].ext_string = (char *) 0;         \
+      ++a->count;                                       \
+    }                                                   \
     if (a->arg[n].type == TYPE_NONE)                                   \
       a->arg[n].type = (_type_);                                       \
     else if (a->arg[n].type != (_type_))                               \
@@ -385,7 +388,17 @@ printf_parse (const char *format, char_directives * d, arguments * a)
               break;
 #endif
             case 'p':
-              type = TYPE_POINTER;
+              /* Note: cp points already to the char after the 'p' now */
+              if (cp[0] == POINTER_EXT_SIGNIFIER_CHAR && cp[1] != '\0') {
+                type = TYPE_POINTER_EXT;
+                dp->flags |= FLAG_PTR_EXT;
+                dp->ptr_ext_char = cp[1];
+                /* we do not use dp->conversion='s' on purpose here, so we
+                 * can fall back to printing just the pointer with %p if the
+                 * serialisation function returned NULL for some reason */
+              } else {
+                type = TYPE_POINTER;
+              }
               break;
             case 'n':
 #ifdef HAVE_LONG_LONG
index a76cecf..96c2462 100644 (file)
@@ -32,6 +32,8 @@
 #define FLAG_ALT       16      /* # flag */
 #define FLAG_ZERO      32
 
+#define FLAG_PTR_EXT 1024
+
 /* A parsed directive.  */
 typedef struct
 {
@@ -46,6 +48,11 @@ typedef struct
   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;
+
+  /* extension char in case of TYPE_POINTER_EXT. We need to store this so
+   * we can pass it back to __gst_printf_pointer_extension_serialize()
+   * so it knows which pointer extension it is */
+  char ptr_ext_char;
 }
 char_directive;
 
index ef6a9e1..315688c 100644 (file)
@@ -41,6 +41,7 @@
 #include <limits.h>             /* CHAR_BIT */
 #include <float.h>              /* DBL_MAX_EXP, LDBL_MAX_EXP */
 #include "printf-parse.h"
+#include "printf-extension.h"
 
 #ifdef HAVE_WCHAR_T
 # ifdef HAVE_WCSLEN
@@ -223,6 +224,32 @@ print_long_long (char *buf,
 }
 #endif
 
+static void
+printf_postprocess_args (char_directives * directives, arguments * arguments)
+{
+  int i;
+
+  for (i = 0; i < directives->count; ++i) {
+    char_directive *dp;
+    argument *a;
+
+    dp = &directives->dir[i];
+    a = &arguments->arg[dp->arg_index];
+
+    if (a->type == TYPE_POINTER_EXT) {
+      char fmt[4];
+
+      fmt[0] = 'p';
+      fmt[1] = POINTER_EXT_SIGNIFIER_CHAR;
+      fmt[2] = dp->ptr_ext_char;
+      fmt[3] = '\0';
+
+      a->ext_string =
+          __gst_printf_pointer_extension_serialize (fmt, a->a.a_pointer);
+    }
+  }
+}
+
 char *
 vasnprintf (char *resultbuf, size_t * lengthp, const char *format, va_list args)
 {
@@ -244,6 +271,9 @@ vasnprintf (char *resultbuf, size_t * lengthp, const char *format, va_list args)
     return NULL;
   }
 
+  /* collect TYPE_POINTER_EXT argument strings */
+  printf_postprocess_args (&d, &a);
+
   {
     char *buf =
         (char *) alloca (7 + d.max_width_length + d.max_precision_length + 6);
@@ -521,6 +551,10 @@ vasnprintf (char *resultbuf, size_t * lengthp, const char *format, va_list args)
                     )
                     + 1         /* turn floor into ceil */
                     + 2;        /* account for leading 0x */
+
+                /* make sure we always have enough space for a plain %p, so + */
+                if (dp->flags & FLAG_PTR_EXT && a.arg[dp->arg_index].ext_string)
+                  tmp_length += strlen (a.arg[dp->arg_index].ext_string);
                 break;
 
               default:
@@ -882,6 +916,18 @@ vasnprintf (char *resultbuf, size_t * lengthp, const char *format, va_list args)
                 SNPRINTF_BUF (arg);
               }
                 break;
+              case TYPE_POINTER_EXT:
+              {
+                void *arg = a.arg[dp->arg_index].a.a_pointer;
+
+                if (a.arg[dp->arg_index].ext_string != NULL) {
+                  arg = a.arg[dp->arg_index].ext_string;
+                  *p = 's';
+                }
+
+                SNPRINTF_BUF (arg);
+              }
+                break;
               default:
                 abort ();
             }