]> sourceware.org Git - glibc.git/commitdiff
vfprintf: Introduce printf_positional function
authorFlorian Weimer <fweimer@redhat.com>
Thu, 21 May 2015 14:46:46 +0000 (15:46 +0100)
committerFlorian Weimer <fweimer@redhat.com>
Thu, 21 May 2015 14:46:46 +0000 (16:46 +0200)
This splits a considerable chunk of code from the main vfprintf
function.  This will make it easier to remove the use of extend_alloca
from the positional argument handling code.

ChangeLog
stdio-common/vfprintf.c

index 2c606bcfbb4fba27318d81f283903808bef4501e..48311f55584c820c09cd3ee9d8407b075dd1876e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2015-05-21  Florian Weimer  <fweimer@redhat.com>
+
+       * stdio-common/vfprintf.c (vfprintf): Move local variables
+       args_malloced, specs, specs_malloced, and the code after
+       do_positional to the printf_positional function.
+       (printf_positional): New function.
+
 2015-05-21  Florian Weimer  <fweimer@redhat.com>
 
        * stdio-common/vfprintf.c (jump_table): Move out of the vfprintf
index 83b4b008acf93d8b6ab458bba9f7b1b79edd6415..4753cbf9544a7452a1fe90e6ce6137fcb5bf910e 100644 (file)
@@ -1209,6 +1209,14 @@ static const uint8_t jump_table[] =
 static int buffered_vfprintf (FILE *stream, const CHAR_T *fmt, va_list)
      __THROW __attribute__ ((noinline)) internal_function;
 
+/* Handle positional format specifiers.  */
+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, const UCHAR_T *lead_str_end,
+                             CHAR_T *work_buffer, int save_errno,
+                             const char *grouping, THOUSANDS_SEP_T);
+
 /* Handle unknown format specifier.  */
 static int printf_unknown (FILE *, const struct printf_info *,
                           const void *const *) __THROW;
@@ -1257,15 +1265,6 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
      0 if unknown.  */
   int readonly_format = 0;
 
-  /* For the argument descriptions, which may be allocated on the heap.  */
-  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;
-
   /* Orient the stream.  */
 #ifdef ORIENT
   ORIENT;
@@ -1670,232 +1669,265 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
   /* Unlock stream and return.  */
   goto all_done;
 
-  /* Here starts the more complex loop to handle positional parameters.  */
+  /* Hand off processing for positional parameters.  */
 do_positional:
-  {
-    /* 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.  */
-    size_t nargs = 0;
-    size_t bytes_per_arg;
-    union printf_arg *args_value;
-    int *args_size;
-    int *args_type;
-
-    /* Positional parameters refer to arguments directly.  This could
-       also determine the maximum number of arguments.  Track the
-       maximum number.  */
-    size_t max_ref_arg = 0;
-
-    /* Just a counter.  */
-    size_t cnt;
-
-    if (__glibc_unlikely (workstart != NULL))
+  if (__glibc_unlikely (workstart != NULL))
+    {
       free (workstart);
-    workstart = NULL;
+      workstart = NULL;
+    }
+  done = printf_positional (s, format, readonly_format, ap, &ap_save,
+                           done, nspecs_done, lead_str_end, work_buffer,
+                           save_errno, grouping, thousands_sep);
 
-    if (grouping == (const char *) -1)
-      {
+ all_done:
+  if (__glibc_unlikely (workstart != NULL))
+    free (workstart);
+  /* Unlock the stream.  */
+  _IO_funlockfile (s);
+  _IO_cleanup_region_end (0);
+
+  return done;
+}
+\f
+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,
+                  const UCHAR_T *lead_str_end,
+                  CHAR_T *work_buffer, int save_errno,
+                  const char *grouping, THOUSANDS_SEP_T thousands_sep)
+{
+  /* For the argument descriptions, which may be allocated on the heap.  */
+  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;
+
+  /* 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.  */
+  size_t nargs = 0;
+  size_t bytes_per_arg;
+  union printf_arg *args_value;
+  int *args_size;
+  int *args_type;
+
+  /* Positional parameters refer to arguments directly.  This could
+     also determine the maximum number of arguments.  Track the
+     maximum number.  */
+  size_t max_ref_arg = 0;
+
+  /* Just a counter.  */
+  size_t cnt;
+
+  CHAR_T *workstart = NULL;
+
+  if (grouping == (const char *) -1)
+    {
 #ifdef COMPILE_WPRINTF
-       thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
-                                         _NL_NUMERIC_THOUSANDS_SEP_WC);
+      thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
+                                       _NL_NUMERIC_THOUSANDS_SEP_WC);
 #else
-       thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
+      thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
 #endif
 
-       grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
-       if (*grouping == '\0' || *grouping == CHAR_MAX)
-         grouping = NULL;
-      }
+      grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
+      if (*grouping == '\0' || *grouping == CHAR_MAX)
+       grouping = NULL;
+    }
 
-    for (f = lead_str_end; *f != L_('\0'); f = specs[nspecs++].next_fmt)
-      {
-       if (nspecs * sizeof (*specs) >= nspecs_size)
-         {
-           /* Extend the array of format specifiers.  */
-           if (nspecs_size * 2 < nspecs_size)
-             {
-               __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;
-                 }
-             }
+  for (const UCHAR_T *f = lead_str_end; *f != L_('\0');
+       f = specs[nspecs++].next_fmt)
+    {
+      if (nspecs * sizeof (*specs) >= nspecs_size)
+       {
+         /* Extend the array of format specifiers.  */
+         if (nspecs_size * 2 < nspecs_size)
+           {
+             __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));
+         /* 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);
+         /* 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;
-         }
+         /* Now set SPECS_MALLOCED if needed.  */
+         if (!__libc_use_alloca (nspecs_size))
+           specs_malloced = true;
+       }
 
-       /* Parse the format specifier.  */
+      /* Parse the format specifier.  */
 #ifdef COMPILE_WPRINTF
-       nargs += __parse_one_specwc (f, nargs, &specs[nspecs], &max_ref_arg);
+      nargs += __parse_one_specwc (f, nargs, &specs[nspecs], &max_ref_arg);
 #else
-       nargs += __parse_one_specmb (f, nargs, &specs[nspecs], &max_ref_arg);
+      nargs += __parse_one_specmb (f, nargs, &specs[nspecs], &max_ref_arg);
 #endif
-      }
-
-    /* Determine the number of arguments the format string consumes.  */
-    nargs = MAX (nargs, max_ref_arg);
-    /* Calculate total size needed to represent a single argument across
-       all three argument-related arrays.  */
-    bytes_per_arg = (sizeof (*args_value) + sizeof (*args_size)
-                    + sizeof (*args_type));
+    }
 
-    /* Check for potential integer overflow.  */
-    if (__glibc_unlikely (nargs > INT_MAX / bytes_per_arg))
-      {
-        __set_errno (EOVERFLOW);
-        done = -1;
-        goto all_done;
-      }
+  /* Determine the number of arguments the format string consumes.  */
+  nargs = MAX (nargs, max_ref_arg);
+  /* Calculate total size needed to represent a single argument across
+     all three argument-related arrays.  */
+  bytes_per_arg = (sizeof (*args_value) + sizeof (*args_size)
+                  + sizeof (*args_type));
 
-    /* Allocate memory for all three argument arrays.  */
-    if (__libc_use_alloca (nargs * bytes_per_arg))
-       args_value = alloca (nargs * bytes_per_arg);
-    else
-      {
-       args_value = args_malloced = malloc (nargs * bytes_per_arg);
-       if (args_value == NULL)
-         {
-           done = -1;
-           goto all_done;
-         }
-      }
+  /* Check for potential integer overflow.  */
+  if (__glibc_unlikely (nargs > INT_MAX / bytes_per_arg))
+    {
+      __set_errno (EOVERFLOW);
+      done = -1;
+      goto all_done;
+    }
 
-    /* Set up the remaining two arrays to each point past the end of the
-       prior array, since space for all three has been allocated now.  */
-    args_size = &args_value[nargs].pa_int;
-    args_type = &args_size[nargs];
-    memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',
-           nargs * sizeof (*args_type));
+  /* Allocate memory for all three argument arrays.  */
+  if (__libc_use_alloca (nargs * bytes_per_arg))
+    args_value = alloca (nargs * bytes_per_arg);
+  else
+    {
+      args_value = args_malloced = malloc (nargs * bytes_per_arg);
+      if (args_value == NULL)
+       {
+         done = -1;
+         goto all_done;
+       }
+    }
 
-    /* XXX Could do sanity check here: If any element in ARGS_TYPE is
-       still zero after this loop, format is invalid.  For now we
-       simply use 0 as the value.  */
+  /* Set up the remaining two arrays to each point past the end of the
+     prior array, since space for all three has been allocated now.  */
+  args_size = &args_value[nargs].pa_int;
+  args_type = &args_size[nargs];
+  memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',
+         nargs * sizeof (*args_type));
 
-    /* Fill in the types of all the arguments.  */
-    for (cnt = 0; cnt < nspecs; ++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;
+  /* XXX Could do sanity check here: If any element in ARGS_TYPE is
+     still zero after this loop, format is invalid.  For now we
+     simply use 0 as the value.  */
 
-       /* 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;
+  /* Fill in the types of all the arguments.  */
+  for (cnt = 0; cnt < nspecs; ++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;
 
-       switch (specs[cnt].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;
-           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]);
-           break;
-         }
-      }
+      /* 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;
 
-    /* Now we know all the types and the order.  Fill in the argument
-       values.  */
-    for (cnt = 0; cnt < nargs; ++cnt)
-      switch (args_type[cnt])
+      switch (specs[cnt].ndata_args)
        {
-#define T(tag, mem, type)                                                    \
-       case tag:                                                             \
-         args_value[cnt].mem = va_arg (ap_save, type);                       \
+       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;
+         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]);
+         break;
+       }
+    }
+
+  /* Now we know all the types and the order.  Fill in the argument
+     values.  */
+  for (cnt = 0; cnt < nargs; ++cnt)
+    switch (args_type[cnt])
+      {
+#define T(tag, mem, type)                              \
+       case tag:                                       \
+         args_value[cnt].mem = va_arg (*ap_savep, type); \
          break
 
        T (PA_WCHAR, pa_wchar, wint_t);
-       case PA_CHAR:                           /* Promoted.  */
-       case PA_INT|PA_FLAG_SHORT:              /* Promoted.  */
+      case PA_CHAR:                            /* Promoted.  */
+      case PA_INT|PA_FLAG_SHORT:               /* Promoted.  */
 #if LONG_MAX == INT_MAX
-       case PA_INT|PA_FLAG_LONG:
+      case PA_INT|PA_FLAG_LONG:
 #endif
        T (PA_INT, pa_int, int);
 #if LONG_MAX == LONG_LONG_MAX
-       case PA_INT|PA_FLAG_LONG:
+      case PA_INT|PA_FLAG_LONG:
 #endif
        T (PA_INT|PA_FLAG_LONG_LONG, pa_long_long_int, long long int);
 #if LONG_MAX != INT_MAX && LONG_MAX != LONG_LONG_MAX
 # error "he?"
 #endif
-       case PA_FLOAT:                          /* Promoted.  */
+      case PA_FLOAT:                           /* Promoted.  */
        T (PA_DOUBLE, pa_double, double);
-       case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:
-         if (__ldbl_is_dbl)
-           {
-             args_value[cnt].pa_double = va_arg (ap_save, double);
-             args_type[cnt] &= ~PA_FLAG_LONG_DOUBLE;
-           }
-         else
-           args_value[cnt].pa_long_double = va_arg (ap_save, long double);
-         break;
-       case PA_STRING:                         /* All pointers are the same */
-       case PA_WSTRING:                        /* All pointers are the same */
+      case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:
+       if (__ldbl_is_dbl)
+         {
+           args_value[cnt].pa_double = va_arg (*ap_savep, double);
+           args_type[cnt] &= ~PA_FLAG_LONG_DOUBLE;
+         }
+       else
+         args_value[cnt].pa_long_double = va_arg (*ap_savep, long double);
+       break;
+      case PA_STRING:                          /* All pointers are the same */
+      case PA_WSTRING:                 /* All pointers are the same */
        T (PA_POINTER, pa_pointer, void *);
 #undef T
-       default:
-         if ((args_type[cnt] & PA_FLAG_PTR) != 0)
-           args_value[cnt].pa_pointer = va_arg (ap_save, void *);
-         else if (__glibc_unlikely (__printf_va_arg_table != NULL)
-                  && __printf_va_arg_table[args_type[cnt] - PA_LAST] != NULL)
-           {
-             args_value[cnt].pa_user = alloca (args_size[cnt]);
-             (*__printf_va_arg_table[args_type[cnt] - PA_LAST])
-               (args_value[cnt].pa_user, &ap_save);
-           }
-         else
-           args_value[cnt].pa_long_double = 0.0;
-         break;
-       case -1:
-         /* Error case.  Not all parameters appear in N$ format
-            strings.  We have no way to determine their type.  */
-         assert (s->_flags2 & _IO_FLAGS2_FORTIFY);
-         __libc_fatal ("*** invalid %N$ use detected ***\n");
-       }
+      default:
+       if ((args_type[cnt] & PA_FLAG_PTR) != 0)
+         args_value[cnt].pa_pointer = va_arg (*ap_savep, void *);
+       else if (__glibc_unlikely (__printf_va_arg_table != NULL)
+                && __printf_va_arg_table[args_type[cnt] - PA_LAST] != NULL)
+         {
+           args_value[cnt].pa_user = alloca (args_size[cnt]);
+           (*__printf_va_arg_table[args_type[cnt] - PA_LAST])
+             (args_value[cnt].pa_user, ap_savep);
+         }
+       else
+         args_value[cnt].pa_long_double = 0.0;
+       break;
+      case -1:
+       /* Error case.  Not all parameters appear in N$ format
+          strings.  We have no way to determine their type.  */
+       assert (s->_flags2 & _IO_FLAGS2_FORTIFY);
+       __libc_fatal ("*** invalid %N$ use detected ***\n");
+      }
 
-    /* Now walk through all format specifiers and process them.  */
-    for (; (size_t) nspecs_done < nspecs; ++nspecs_done)
-      {
+  /* Now walk through all format specifiers and process them.  */
+  for (; (size_t) nspecs_done < nspecs; ++nspecs_done)
+    {
 #undef REF
 #ifdef SHARED
 # undef JUMP_TABLE_BASE_LABEL
@@ -1906,184 +1938,174 @@ do_positional:
 #endif
 #undef LABEL
 #define LABEL(Name) do2_##Name
-       STEP4_TABLE;
+      STEP4_TABLE;
 
-       int is_negative;
-       union
+      int is_negative;
+      union
+      {
+       unsigned long long int longlong;
+       unsigned long int word;
+      } number;
+      int base;
+      union printf_arg the_arg;
+      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;
+
+      workstart = NULL;
+      CHAR_T *workend = work_buffer + WORK_BUFFER_SIZE;
+
+      /* Fill in last information.  */
+      if (specs[nspecs_done].width_arg != -1)
        {
-         unsigned long long int longlong;
-         unsigned long int word;
-       } number;
-       int base;
-       union printf_arg the_arg;
-       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;
-
-       workstart = NULL;
-       workend = work_buffer + WORK_BUFFER_SIZE;
-
-       /* Fill in last information.  */
-       if (specs[nspecs_done].width_arg != -1)
-         {
-           /* Extract the field width from an argument.  */
-           specs[nspecs_done].info.width =
-             args_value[specs[nspecs_done].width_arg].pa_int;
+         /* Extract the field width from an argument.  */
+         specs[nspecs_done].info.width =
+           args_value[specs[nspecs_done].width_arg].pa_int;
 
-           if (specs[nspecs_done].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;
-             }
-           width = specs[nspecs_done].info.width;
-         }
+         if (specs[nspecs_done].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;
+           }
+         width = specs[nspecs_done].info.width;
+       }
 
-       if (specs[nspecs_done].prec_arg != -1)
-         {
-           /* Extract the precision from an argument.  */
-           specs[nspecs_done].info.prec =
-             args_value[specs[nspecs_done].prec_arg].pa_int;
+      if (specs[nspecs_done].prec_arg != -1)
+       {
+         /* Extract the precision from an argument.  */
+         specs[nspecs_done].info.prec =
+           args_value[specs[nspecs_done].prec_arg].pa_int;
 
-           if (specs[nspecs_done].info.prec < 0)
-             /* If the precision is negative the precision is
-                omitted.  */
-             specs[nspecs_done].info.prec = -1;
+         if (specs[nspecs_done].info.prec < 0)
+           /* If the precision is negative the precision is
+              omitted.  */
+           specs[nspecs_done].info.prec = -1;
 
-           prec = specs[nspecs_done].info.prec;
-         }
+         prec = specs[nspecs_done].info.prec;
+       }
 
-       /* Maybe the buffer is too small.  */
-       if (MAX (prec, width) + 32 > WORK_BUFFER_SIZE)
-         {
-           if (__libc_use_alloca ((MAX (prec, width) + 32)
-                                  * sizeof (CHAR_T)))
-             workend = ((CHAR_T *) alloca ((MAX (prec, width) + 32)
-                                           * sizeof (CHAR_T))
-                        + (MAX (prec, width) + 32));
-           else
-             {
-               workstart = (CHAR_T *) malloc ((MAX (prec, width) + 32)
-                                              * sizeof (CHAR_T));
-               if (workstart == NULL)
-                 {
-                   done = -1;
-                   goto all_done;
-                 }
-               workend = workstart + (MAX (prec, width) + 32);
-             }
-         }
+      /* Maybe the buffer is too small.  */
+      if (MAX (prec, width) + 32 > WORK_BUFFER_SIZE)
+       {
+         if (__libc_use_alloca ((MAX (prec, width) + 32)
+                                * sizeof (CHAR_T)))
+           workend = ((CHAR_T *) alloca ((MAX (prec, width) + 32)
+                                         * sizeof (CHAR_T))
+                      + (MAX (prec, width) + 32));
+         else
+           {
+             workstart = (CHAR_T *) malloc ((MAX (prec, width) + 32)
+                                            * sizeof (CHAR_T));
+             if (workstart == NULL)
+               {
+                 done = -1;
+                 goto all_done;
+               }
+             workend = workstart + (MAX (prec, width) + 32);
+           }
+       }
 
-       /* Process format specifiers.  */
-       while (1)
-         {
-           extern printf_function **__printf_function_table;
-           int function_done;
+      /* Process format specifiers.  */
+      while (1)
+       {
+         extern printf_function **__printf_function_table;
+         int function_done;
 
-           if (spec <= UCHAR_MAX
-               && __printf_function_table != NULL
-               && __printf_function_table[(size_t) spec] != NULL)
-             {
-               const void **ptr = alloca (specs[nspecs_done].ndata_args
-                                          * sizeof (const void *));
+         if (spec <= UCHAR_MAX
+             && __printf_function_table != NULL
+             && __printf_function_table[(size_t) spec] != NULL)
+           {
+             const void **ptr = alloca (specs[nspecs_done].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;
-                    ++i)
-                 ptr[i] = &args_value[specs[nspecs_done].data_arg + i];
+             /* Fill in an array of pointers to the argument values.  */
+             for (unsigned int i = 0; i < specs[nspecs_done].ndata_args;
+                  ++i)
+               ptr[i] = &args_value[specs[nspecs_done].data_arg + i];
 
-               /* Call the function.  */
-               function_done = __printf_function_table[(size_t) spec]
-                 (s, &specs[nspecs_done].info, ptr);
+             /* Call the function.  */
+             function_done = __printf_function_table[(size_t) spec]
+               (s, &specs[nspecs_done].info, ptr);
 
-               if (function_done != -2)
-                 {
-                   /* If an error occurred we don't have information
-                      about # of chars.  */
-                   if (function_done < 0)
-                     {
-                       /* Function has set errno.  */
-                       done = -1;
-                       goto all_done;
-                     }
-
-                   done_add (function_done);
-                   break;
-                 }
-             }
+             if (function_done != -2)
+               {
+                 /* If an error occurred we don't have information
+                    about # of chars.  */
+                 if (function_done < 0)
+                   {
+                     /* Function has set errno.  */
+                     done = -1;
+                     goto all_done;
+                   }
+
+                 done_add (function_done);
+                 break;
+               }
+           }
 
-           JUMP (spec, step4_jumps);
+         JUMP (spec, step4_jumps);
 
-           process_arg ((&specs[nspecs_done]));
-           process_string_arg ((&specs[nspecs_done]));
+         process_arg ((&specs[nspecs_done]));
+         process_string_arg ((&specs[nspecs_done]));
 
          LABEL (form_unknown):
-           {
-             unsigned int i;
-             const void **ptr;
+         {
+           unsigned int i;
+           const void **ptr;
 
-             ptr = alloca (specs[nspecs_done].ndata_args
-                           * sizeof (const void *));
+           ptr = alloca (specs[nspecs_done].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];
+           /* 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];
 
-             /* Call the function.  */
-             function_done = printf_unknown (s, &specs[nspecs_done].info,
-                                             ptr);
+           /* Call the function.  */
+           function_done = printf_unknown (s, &specs[nspecs_done].info,
+                                           ptr);
 
-             /* If an error occurred we don't have information about #
-                of chars.  */
-             if (function_done < 0)
-               {
-                 /* Function has set errno.  */
-                 done = -1;
-                 goto all_done;
-               }
+           /* If an error occurred we don't have information about #
+              of chars.  */
+           if (function_done < 0)
+             {
+               /* Function has set errno.  */
+               done = -1;
+               goto all_done;
+             }
 
-             done_add (function_done);
-           }
-           break;
+           done_add (function_done);
          }
+         break;
+       }
 
-       if (__glibc_unlikely (workstart != NULL))
-         free (workstart);
-       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);
-      }
-  }
+      if (__glibc_unlikely (workstart != NULL))
+       free (workstart);
+      workstart = NULL;
 
-all_done:
-  if (specs_malloced)
-    free (specs);
-  if (__glibc_unlikely (args_malloced != NULL))
-    free (args_malloced);
+      /* Write the following constant string.  */
+      outstring (specs[nspecs_done].end_of_fmt,
+                specs[nspecs_done].next_fmt
+                - specs[nspecs_done].end_of_fmt);
+    }
+ all_done:
   if (__glibc_unlikely (workstart != NULL))
     free (workstart);
-  /* Unlock the stream.  */
-  _IO_funlockfile (s);
-  _IO_cleanup_region_end (0);
-
   return done;
 }
 \f
This page took 0.140857 seconds and 5 git commands to generate.