printf: make printf parser recognise our pointer extension format

and call the hook to get a string for the pointer instead.

https://bugzilla.gnome.org/show_bug.cgi?id=613081
This commit is contained in:
Tim-Philipp Müller 2013-04-07 16:41:40 +01:00 committed by Tim-Philipp Müller
parent fe7f7135e0
commit 5803da553c
5 changed files with 75 additions and 3 deletions

View file

@ -105,6 +105,7 @@ printf_fetchargs (va_list args, arguments * a)
break; break;
#endif #endif
case TYPE_POINTER: case TYPE_POINTER:
case TYPE_POINTER_EXT:
ap->a.a_pointer = va_arg (args, void *); ap->a.a_pointer = va_arg (args, void *);
break; break;
case TYPE_COUNT_SCHAR_POINTER: case TYPE_COUNT_SCHAR_POINTER:

View file

@ -32,6 +32,7 @@
/* Get va_list. */ /* Get va_list. */
#include <stdarg.h> #include <stdarg.h>
#define POINTER_EXT_SIGNIFIER_CHAR '\a'
/* Argument types */ /* Argument types */
typedef enum typedef enum
@ -66,6 +67,7 @@ typedef enum
TYPE_WIDE_STRING, TYPE_WIDE_STRING,
#endif #endif
TYPE_POINTER, TYPE_POINTER,
TYPE_POINTER_EXT,
TYPE_COUNT_SCHAR_POINTER, TYPE_COUNT_SCHAR_POINTER,
TYPE_COUNT_SHORT_POINTER, TYPE_COUNT_SHORT_POINTER,
TYPE_COUNT_INT_POINTER, TYPE_COUNT_INT_POINTER,
@ -120,6 +122,9 @@ typedef struct
#endif #endif
} }
a; a;
/* string to replace pointer argument with for TYPE_POINTER_EXT */
char *ext_string;
} }
argument; argument;

View file

@ -80,8 +80,11 @@ printf_parse (const char *format, char_directives * d, arguments * a)
goto error; \ goto error; \
a->arg = memory; \ a->arg = memory; \
} \ } \
while (a->count <= n) \ while (a->count <= n) { \
a->arg[a->count++].type = TYPE_NONE; \ a->arg[a->count].type = TYPE_NONE; \
a->arg[a->count].ext_string = (char *) 0; \
++a->count; \
} \
if (a->arg[n].type == TYPE_NONE) \ if (a->arg[n].type == TYPE_NONE) \
a->arg[n].type = (_type_); \ a->arg[n].type = (_type_); \
else if (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; break;
#endif #endif
case 'p': 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; break;
case 'n': case 'n':
#ifdef HAVE_LONG_LONG #ifdef HAVE_LONG_LONG

View file

@ -32,6 +32,8 @@
#define FLAG_ALT 16 /* # flag */ #define FLAG_ALT 16 /* # flag */
#define FLAG_ZERO 32 #define FLAG_ZERO 32
#define FLAG_PTR_EXT 1024
/* A parsed directive. */ /* A parsed directive. */
typedef struct typedef struct
{ {
@ -46,6 +48,11 @@ typedef struct
int precision_arg_index; 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 */ 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; 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; char_directive;

View file

@ -41,6 +41,7 @@
#include <limits.h> /* CHAR_BIT */ #include <limits.h> /* CHAR_BIT */
#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */ #include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
#include "printf-parse.h" #include "printf-parse.h"
#include "printf-extension.h"
#ifdef HAVE_WCHAR_T #ifdef HAVE_WCHAR_T
# ifdef HAVE_WCSLEN # ifdef HAVE_WCSLEN
@ -223,6 +224,32 @@ print_long_long (char *buf,
} }
#endif #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 * char *
vasnprintf (char *resultbuf, size_t * lengthp, const char *format, va_list args) 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; return NULL;
} }
/* collect TYPE_POINTER_EXT argument strings */
printf_postprocess_args (&d, &a);
{ {
char *buf = char *buf =
(char *) alloca (7 + d.max_width_length + d.max_precision_length + 6); (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 */ + 1 /* turn floor into ceil */
+ 2; /* account for leading 0x */ + 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; break;
default: default:
@ -879,6 +913,18 @@ vasnprintf (char *resultbuf, size_t * lengthp, const char *format, va_list args)
case TYPE_POINTER: case TYPE_POINTER:
{ {
void *arg = a.arg[dp->arg_index].a.a_pointer; void *arg = a.arg[dp->arg_index].a.a_pointer;
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); SNPRINTF_BUF (arg);
} }
break; break;