From patchwork Fri Jun 2 12:00:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 20696 Received: (qmail 91708 invoked by alias); 2 Jun 2017 12:00:59 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 90915 invoked by uid 89); 2 Jun 2017 12:00:24 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com DD58FC04B93D Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=fweimer@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com DD58FC04B93D Date: Fri, 02 Jun 2017 14:00:09 +0200 To: libc-alpha@sourceware.org Subject: [PATCH] vfprintf: Replace scratch buffer with dynamic array User-Agent: Heirloom mailx 12.5 7/5/10 MIME-Version: 1.0 Message-Id: <20170602120009.A0209400EA94D@oldenburg.str.redhat.com> From: fweimer@redhat.com (Florian Weimer) 2017-06-02 Florian Weimer * stdio-common/vfprintf.c (struct specs_array): Define using . (printf_positional): Replace struct scratch_buffer with struct specs_array. diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index 2cf7c8a..c1aaa11 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -29,7 +29,6 @@ #include <_itoa.h> #include #include -#include /* This code is shared between the standard stdio implementation found in GNU C library and the libio implementation originally found in @@ -1695,6 +1694,13 @@ do_positional: return done; } +/* Parsed format specifiers. */ +#define DYNARRAY_STRUCT specs_array +#define DYNARRAY_ELEMENT struct printf_spec +#define DYNARRAY_PREFIX specs_array_ +#define DYNARRAY_INITIAL_SIZE 15 +#include + static int printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, va_list ap, va_list *ap_savep, int done, int nspecs_done, @@ -1705,15 +1711,9 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, /* For the argument descriptions, which may be allocated on the heap. */ void *args_malloced = NULL; - /* For positional argument handling. */ - struct scratch_buffer specsbuf; - scratch_buffer_init (&specsbuf); - struct printf_spec *specs = specsbuf.data; - size_t specs_limit = specsbuf.length / sizeof (specs[0]); - - /* Array with information about the needed arguments. This has to - be dynamically extensible. */ - size_t nspecs = 0; + /* Parsed format specifiers found in the format string. */ + struct specs_array specs; + specs_array_init (&specs); /* The number of arguments the format string requests. This will determine the size of the array needed to store the argument @@ -1748,26 +1748,22 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, grouping = NULL; } - for (const UCHAR_T *f = lead_str_end; *f != L_('\0'); - f = specs[nspecs++].next_fmt) + for (const UCHAR_T *f = lead_str_end; *f != L_('\0'); ) { - if (nspecs == specs_limit) + struct printf_spec *new_spec = specs_array_emplace (&specs); + if (new_spec == NULL) { - if (!scratch_buffer_grow_preserve (&specsbuf)) - { - done = -1; - goto all_done; - } - specs = specsbuf.data; - specs_limit = specsbuf.length / sizeof (specs[0]); + done = -1; + goto all_done; } /* Parse the format specifier. */ #ifdef COMPILE_WPRINTF - nargs += __parse_one_specwc (f, nargs, &specs[nspecs], &max_ref_arg); + nargs += __parse_one_specwc (f, nargs, new_spec, &max_ref_arg); #else - nargs += __parse_one_specmb (f, nargs, &specs[nspecs], &max_ref_arg); + nargs += __parse_one_specmb (f, nargs, new_spec, &max_ref_arg); #endif + f = new_spec->next_fmt; } /* Determine the number of arguments the format string consumes. */ @@ -1810,33 +1806,34 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, simply use 0 as the value. */ /* Fill in the types of all the arguments. */ + size_t nspecs = specs_array_size (&specs); for (cnt = 0; cnt < nspecs; ++cnt) { + struct printf_spec *spec = specs_array_at (&specs, cnt); /* If the width is determined by an argument this is an int. */ - if (specs[cnt].width_arg != -1) - args_type[specs[cnt].width_arg] = PA_INT; + if (spec->width_arg != -1) + args_type[spec->width_arg] = PA_INT; /* If the precision is determined by an argument this is an int. */ - if (specs[cnt].prec_arg != -1) - args_type[specs[cnt].prec_arg] = PA_INT; + if (spec->prec_arg != -1) + args_type[spec->prec_arg] = PA_INT; - switch (specs[cnt].ndata_args) + switch (spec->ndata_args) { case 0: /* No arguments. */ break; case 1: /* One argument; we already have the type and size. */ - args_type[specs[cnt].data_arg] = specs[cnt].data_arg_type; - args_size[specs[cnt].data_arg] = specs[cnt].size; + args_type[spec->data_arg] = spec->data_arg_type; + args_size[spec->data_arg] = spec->size; break; default: /* We have more than one argument for this format spec. We must call the arginfo function again to determine all the types. */ - (void) (*__printf_arginfo_table[specs[cnt].info.spec]) - (&specs[cnt].info, - specs[cnt].ndata_args, &args_type[specs[cnt].data_arg], - &args_size[specs[cnt].data_arg]); + (void) (*__printf_arginfo_table[spec->info.spec]) + (&spec->info, spec->ndata_args, &args_type[spec->data_arg], + &args_size[spec->data_arg]); break; } } @@ -1916,53 +1913,52 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, CHAR_T *string; /* Pointer to argument string. */ /* Fill variables from values in struct. */ - int alt = specs[nspecs_done].info.alt; - int space = specs[nspecs_done].info.space; - int left = specs[nspecs_done].info.left; - int showsign = specs[nspecs_done].info.showsign; - int group = specs[nspecs_done].info.group; - int is_long_double = specs[nspecs_done].info.is_long_double; - int is_short = specs[nspecs_done].info.is_short; - int is_char = specs[nspecs_done].info.is_char; - int is_long = specs[nspecs_done].info.is_long; - int width = specs[nspecs_done].info.width; - int prec = specs[nspecs_done].info.prec; - int use_outdigits = specs[nspecs_done].info.i18n; - char pad = specs[nspecs_done].info.pad; - CHAR_T spec = specs[nspecs_done].info.spec; + struct printf_spec *pspec = specs_array_at (&specs, nspecs_done); + int alt = pspec->info.alt; + int space = pspec->info.space; + int left = pspec->info.left; + int showsign = pspec->info.showsign; + int group = pspec->info.group; + int is_long_double = pspec->info.is_long_double; + int is_short = pspec->info.is_short; + int is_char = pspec->info.is_char; + int is_long = pspec->info.is_long; + int width = pspec->info.width; + int prec = pspec->info.prec; + int use_outdigits = pspec->info.i18n; + char pad = pspec->info.pad; + CHAR_T spec = pspec->info.spec; workstart = NULL; CHAR_T *workend = work_buffer + WORK_BUFFER_SIZE; /* Fill in last information. */ - if (specs[nspecs_done].width_arg != -1) + if (pspec->width_arg != -1) { /* Extract the field width from an argument. */ - specs[nspecs_done].info.width = - args_value[specs[nspecs_done].width_arg].pa_int; + pspec->info.width = args_value[pspec->width_arg].pa_int; - if (specs[nspecs_done].info.width < 0) + if (pspec->info.width < 0) /* If the width value is negative left justification is selected and the value is taken as being positive. */ { - specs[nspecs_done].info.width *= -1; - left = specs[nspecs_done].info.left = 1; + pspec->info.width *= -1; + left = pspec->info.left = 1; } - width = specs[nspecs_done].info.width; + width = pspec->info.width; } - if (specs[nspecs_done].prec_arg != -1) + if (pspec->prec_arg != -1) { /* Extract the precision from an argument. */ - specs[nspecs_done].info.prec = - args_value[specs[nspecs_done].prec_arg].pa_int; + pspec->info.prec = args_value[pspec->prec_arg].pa_int; - if (specs[nspecs_done].info.prec < 0) + if (pspec->info.prec < 0) /* If the precision is negative the precision is omitted. */ - specs[nspecs_done].info.prec = -1; + pspec->info.prec = -1; - prec = specs[nspecs_done].info.prec; + prec = pspec->info.prec; } /* Maybe the buffer is too small. */ @@ -1996,17 +1992,17 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, && __printf_function_table != NULL && __printf_function_table[(size_t) spec] != NULL) { - const void **ptr = alloca (specs[nspecs_done].ndata_args + const void **ptr = alloca (pspec->ndata_args * sizeof (const void *)); /* Fill in an array of pointers to the argument values. */ - for (unsigned int i = 0; i < specs[nspecs_done].ndata_args; + for (unsigned int i = 0; i < pspec->ndata_args; ++i) - ptr[i] = &args_value[specs[nspecs_done].data_arg + i]; + ptr[i] = &args_value[pspec->data_arg + i]; /* Call the function. */ function_done = __printf_function_table[(size_t) spec] - (s, &specs[nspecs_done].info, ptr); + (s, &pspec->info, ptr); if (function_done != -2) { @@ -2026,24 +2022,22 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, JUMP (spec, step4_jumps); - process_arg ((&specs[nspecs_done])); - process_string_arg ((&specs[nspecs_done])); + process_arg (pspec); + process_string_arg (pspec); LABEL (form_unknown): { unsigned int i; const void **ptr; - ptr = alloca (specs[nspecs_done].ndata_args - * sizeof (const void *)); + ptr = alloca (pspec->ndata_args * sizeof (const void *)); /* Fill in an array of pointers to the argument values. */ - for (i = 0; i < specs[nspecs_done].ndata_args; ++i) - ptr[i] = &args_value[specs[nspecs_done].data_arg + i]; + for (i = 0; i < pspec->ndata_args; ++i) + ptr[i] = &args_value[pspec->data_arg + i]; /* Call the function. */ - function_done = printf_unknown (s, &specs[nspecs_done].info, - ptr); + function_done = printf_unknown (s, &pspec->info, ptr); /* If an error occurred we don't have information about # of chars. */ @@ -2064,16 +2058,14 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, workstart = NULL; /* Write the following constant string. */ - outstring (specs[nspecs_done].end_of_fmt, - specs[nspecs_done].next_fmt - - specs[nspecs_done].end_of_fmt); + outstring (pspec->end_of_fmt, pspec->next_fmt - pspec->end_of_fmt); } all_done: if (__glibc_unlikely (args_malloced != NULL)) free (args_malloced); if (__glibc_unlikely (workstart != NULL)) free (workstart); - scratch_buffer_free (&specsbuf); + specs_array_free (&specs); return done; }