From 5803da553ca354362f3673503988745b7eb60607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sun, 7 Apr 2013 16:41:40 +0100 Subject: [PATCH] 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 --- gst/printf/printf-args.c | 1 + gst/printf/printf-args.h | 5 +++++ gst/printf/printf-parse.c | 19 +++++++++++++--- gst/printf/printf-parse.h | 7 ++++++ gst/printf/vasnprintf.c | 46 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 75 insertions(+), 3 deletions(-) diff --git a/gst/printf/printf-args.c b/gst/printf/printf-args.c index 5ca693cc51..1177ddbc09 100644 --- a/gst/printf/printf-args.c +++ b/gst/printf/printf-args.c @@ -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: diff --git a/gst/printf/printf-args.h b/gst/printf/printf-args.h index 082567568a..12a3c18838 100644 --- a/gst/printf/printf-args.h +++ b/gst/printf/printf-args.h @@ -32,6 +32,7 @@ /* Get va_list. */ #include +#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; diff --git a/gst/printf/printf-parse.c b/gst/printf/printf-parse.c index 933867b397..150205358a 100644 --- a/gst/printf/printf-parse.c +++ b/gst/printf/printf-parse.c @@ -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 diff --git a/gst/printf/printf-parse.h b/gst/printf/printf-parse.h index a76cecf5d0..96c246288e 100644 --- a/gst/printf/printf-parse.h +++ b/gst/printf/printf-parse.h @@ -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; diff --git a/gst/printf/vasnprintf.c b/gst/printf/vasnprintf.c index ef6a9e13d6..315688c2b7 100644 --- a/gst/printf/vasnprintf.c +++ b/gst/printf/vasnprintf.c @@ -41,6 +41,7 @@ #include /* CHAR_BIT */ #include /* 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: @@ -879,6 +913,18 @@ vasnprintf (char *resultbuf, size_t * lengthp, const char *format, va_list args) case TYPE_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); } break;