@@ -29,7 +29,6 @@
#include <_itoa.h>
#include <locale/localeinfo.h>
#include <stdio.h>
-#include <scratch_buffer.h>
/* 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 <malloc/dynarray-skeleton.c>
+
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;
}