From patchwork Sun Mar 1 22:13:03 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 5393 Received: (qmail 78849 invoked by alias); 2 Mar 2015 08:40:37 -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 78763 invoked by uid 89); 2 Mar 2015 08:40:37 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=AWL, BAYES_00, DATE_IN_PAST_06_12, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Message-Id: <72d7d6b43ac665df4808dd3f352b067755a0f48b.1425285061.git.fweimer@redhat.com> In-Reply-To: References: From: Florian Weimer Date: Sun, 1 Mar 2015 23:13:03 +0100 Subject: [PATCH 23/25] vfprintf: Rewrite printf_positional to use struct scratch_buffer To: libc-alpha@sourceware.org --- stdio-common/vfprintf.c | 48 ++++++++++-------------------------------------- 1 file changed, 10 insertions(+), 38 deletions(-) diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index 6bf59ff..839de8e 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -29,6 +29,7 @@ #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 @@ -1698,18 +1699,15 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, void *args_malloced = NULL; /* For positional argument handling. */ - struct printf_spec *specs; - - /* Track if we malloced the SPECS array and thus must free it. */ - bool specs_malloced = false; + 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; - /* A more or less arbitrary start value. */ - size_t nspecs_size = 32 * sizeof (struct printf_spec); - specs = alloca (nspecs_size); /* The number of arguments the format string requests. This will determine the size of the array needed to store the argument attributes. */ @@ -1746,42 +1744,15 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, for (const UCHAR_T *f = lead_str_end; *f != L_('\0'); f = specs[nspecs++].next_fmt) { - if (nspecs * sizeof (*specs) >= nspecs_size) + if (nspecs == specs_limit) { - /* Extend the array of format specifiers. */ - if (nspecs_size * 2 < nspecs_size) + if (!scratch_buffer_grow_preserve (&specsbuf)) { - __set_errno (ENOMEM); done = -1; goto all_done; } - struct printf_spec *old = specs; - if (__libc_use_alloca (2 * nspecs_size)) - specs = extend_alloca (specs, nspecs_size, 2 * nspecs_size); - else - { - nspecs_size *= 2; - specs = malloc (nspecs_size); - if (specs == NULL) - { - __set_errno (ENOMEM); - specs = old; - done = -1; - goto all_done; - } - } - - /* Copy the old array's elements to the new space. */ - memmove (specs, old, nspecs * sizeof (*specs)); - - /* If we had previously malloc'd space for SPECS, then - release it after the copy is complete. */ - if (specs_malloced) - free (old); - - /* Now set SPECS_MALLOCED if needed. */ - if (!__libc_use_alloca (nspecs_size)) - specs_malloced = true; + specs = specsbuf.data; + specs_limit = specsbuf.length / sizeof (specs[0]); } /* Parse the format specifier. */ @@ -2093,6 +2064,7 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format, all_done: if (__glibc_unlikely (workstart != NULL)) free (workstart); + scratch_buffer_free (&specsbuf); return done; }