Home | History | Annotate | Line # | Download | only in libiberty
vasprintf.c revision 1.1
      1  1.1  skrll /* Like vsprintf but provides a pointer to malloc'd storage, which must
      2  1.1  skrll    be freed by the caller.
      3  1.1  skrll    Copyright (C) 1994, 2003 Free Software Foundation, Inc.
      4  1.1  skrll 
      5  1.1  skrll This file is part of the libiberty library.
      6  1.1  skrll Libiberty is free software; you can redistribute it and/or
      7  1.1  skrll modify it under the terms of the GNU Library General Public
      8  1.1  skrll License as published by the Free Software Foundation; either
      9  1.1  skrll version 2 of the License, or (at your option) any later version.
     10  1.1  skrll 
     11  1.1  skrll Libiberty is distributed in the hope that it will be useful,
     12  1.1  skrll but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  1.1  skrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  1.1  skrll Library General Public License for more details.
     15  1.1  skrll 
     16  1.1  skrll You should have received a copy of the GNU Library General Public
     17  1.1  skrll License along with libiberty; see the file COPYING.LIB.  If
     18  1.1  skrll not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
     19  1.1  skrll Boston, MA 02110-1301, USA.  */
     20  1.1  skrll 
     21  1.1  skrll #ifdef HAVE_CONFIG_H
     22  1.1  skrll #include "config.h"
     23  1.1  skrll #endif
     24  1.1  skrll #include <ansidecl.h>
     25  1.1  skrll #include <stdarg.h>
     26  1.1  skrll #if !defined (va_copy) && defined (__va_copy)
     27  1.1  skrll # define va_copy(d,s)  __va_copy((d),(s))
     28  1.1  skrll #endif
     29  1.1  skrll #include <stdio.h>
     30  1.1  skrll #ifdef HAVE_STRING_H
     31  1.1  skrll #include <string.h>
     32  1.1  skrll #endif
     33  1.1  skrll #ifdef HAVE_STDLIB_H
     34  1.1  skrll #include <stdlib.h>
     35  1.1  skrll #else
     36  1.1  skrll extern unsigned long strtoul ();
     37  1.1  skrll extern PTR malloc ();
     38  1.1  skrll #endif
     39  1.1  skrll #include "libiberty.h"
     40  1.1  skrll 
     41  1.1  skrll #ifdef TEST
     42  1.1  skrll int global_total_width;
     43  1.1  skrll #endif
     44  1.1  skrll 
     45  1.1  skrll /*
     46  1.1  skrll 
     47  1.1  skrll @deftypefn Extension int vasprintf (char **@var{resptr}, const char *@var{format}, va_list @var{args})
     48  1.1  skrll 
     49  1.1  skrll Like @code{vsprintf}, but instead of passing a pointer to a buffer,
     50  1.1  skrll you pass a pointer to a pointer.  This function will compute the size
     51  1.1  skrll of the buffer needed, allocate memory with @code{malloc}, and store a
     52  1.1  skrll pointer to the allocated memory in @code{*@var{resptr}}.  The value
     53  1.1  skrll returned is the same as @code{vsprintf} would return.  If memory could
     54  1.1  skrll not be allocated, minus one is returned and @code{NULL} is stored in
     55  1.1  skrll @code{*@var{resptr}}.
     56  1.1  skrll 
     57  1.1  skrll @end deftypefn
     58  1.1  skrll 
     59  1.1  skrll */
     60  1.1  skrll 
     61  1.1  skrll static int int_vasprintf (char **, const char *, va_list);
     62  1.1  skrll 
     63  1.1  skrll static int
     64  1.1  skrll int_vasprintf (char **result, const char *format, va_list args)
     65  1.1  skrll {
     66  1.1  skrll   const char *p = format;
     67  1.1  skrll   /* Add one to make sure that it is never zero, which might cause malloc
     68  1.1  skrll      to return NULL.  */
     69  1.1  skrll   int total_width = strlen (format) + 1;
     70  1.1  skrll   va_list ap;
     71  1.1  skrll 
     72  1.1  skrll #ifdef va_copy
     73  1.1  skrll   va_copy (ap, args);
     74  1.1  skrll #else
     75  1.1  skrll   memcpy ((PTR) &ap, (PTR) &args, sizeof (va_list));
     76  1.1  skrll #endif
     77  1.1  skrll 
     78  1.1  skrll   while (*p != '\0')
     79  1.1  skrll     {
     80  1.1  skrll       if (*p++ == '%')
     81  1.1  skrll 	{
     82  1.1  skrll 	  while (strchr ("-+ #0", *p))
     83  1.1  skrll 	    ++p;
     84  1.1  skrll 	  if (*p == '*')
     85  1.1  skrll 	    {
     86  1.1  skrll 	      ++p;
     87  1.1  skrll 	      total_width += abs (va_arg (ap, int));
     88  1.1  skrll 	    }
     89  1.1  skrll 	  else
     90  1.1  skrll 	    total_width += strtoul (p, (char **) &p, 10);
     91  1.1  skrll 	  if (*p == '.')
     92  1.1  skrll 	    {
     93  1.1  skrll 	      ++p;
     94  1.1  skrll 	      if (*p == '*')
     95  1.1  skrll 		{
     96  1.1  skrll 		  ++p;
     97  1.1  skrll 		  total_width += abs (va_arg (ap, int));
     98  1.1  skrll 		}
     99  1.1  skrll 	      else
    100  1.1  skrll 	      total_width += strtoul (p, (char **) &p, 10);
    101  1.1  skrll 	    }
    102  1.1  skrll 	  while (strchr ("hlL", *p))
    103  1.1  skrll 	    ++p;
    104  1.1  skrll 	  /* Should be big enough for any format specifier except %s and floats.  */
    105  1.1  skrll 	  total_width += 30;
    106  1.1  skrll 	  switch (*p)
    107  1.1  skrll 	    {
    108  1.1  skrll 	    case 'd':
    109  1.1  skrll 	    case 'i':
    110  1.1  skrll 	    case 'o':
    111  1.1  skrll 	    case 'u':
    112  1.1  skrll 	    case 'x':
    113  1.1  skrll 	    case 'X':
    114  1.1  skrll 	    case 'c':
    115  1.1  skrll 	      (void) va_arg (ap, int);
    116  1.1  skrll 	      break;
    117  1.1  skrll 	    case 'f':
    118  1.1  skrll 	    case 'e':
    119  1.1  skrll 	    case 'E':
    120  1.1  skrll 	    case 'g':
    121  1.1  skrll 	    case 'G':
    122  1.1  skrll 	      (void) va_arg (ap, double);
    123  1.1  skrll 	      /* Since an ieee double can have an exponent of 307, we'll
    124  1.1  skrll 		 make the buffer wide enough to cover the gross case. */
    125  1.1  skrll 	      total_width += 307;
    126  1.1  skrll 	      break;
    127  1.1  skrll 	    case 's':
    128  1.1  skrll 	      total_width += strlen (va_arg (ap, char *));
    129  1.1  skrll 	      break;
    130  1.1  skrll 	    case 'p':
    131  1.1  skrll 	    case 'n':
    132  1.1  skrll 	      (void) va_arg (ap, char *);
    133  1.1  skrll 	      break;
    134  1.1  skrll 	    }
    135  1.1  skrll 	  p++;
    136  1.1  skrll 	}
    137  1.1  skrll     }
    138  1.1  skrll #ifdef va_copy
    139  1.1  skrll   va_end (ap);
    140  1.1  skrll #endif
    141  1.1  skrll #ifdef TEST
    142  1.1  skrll   global_total_width = total_width;
    143  1.1  skrll #endif
    144  1.1  skrll   *result = (char *) malloc (total_width);
    145  1.1  skrll   if (*result != NULL)
    146  1.1  skrll     return vsprintf (*result, format, args);
    147  1.1  skrll   else
    148  1.1  skrll     return -1;
    149  1.1  skrll }
    150  1.1  skrll 
    151  1.1  skrll int
    152  1.1  skrll vasprintf (char **result, const char *format,
    153  1.1  skrll #if defined (_BSD_VA_LIST_) && defined (__FreeBSD__)
    154  1.1  skrll            _BSD_VA_LIST_ args)
    155  1.1  skrll #else
    156  1.1  skrll            va_list args)
    157  1.1  skrll #endif
    158  1.1  skrll {
    159  1.1  skrll   return int_vasprintf (result, format, args);
    160  1.1  skrll }
    161  1.1  skrll 
    162  1.1  skrll #ifdef TEST
    163  1.1  skrll static void ATTRIBUTE_PRINTF_1
    164  1.1  skrll checkit (const char *format, ...)
    165  1.1  skrll {
    166  1.1  skrll   char *result;
    167  1.1  skrll   VA_OPEN (args, format);
    168  1.1  skrll   VA_FIXEDARG (args, const char *, format);
    169  1.1  skrll   vasprintf (&result, format, args);
    170  1.1  skrll   VA_CLOSE (args);
    171  1.1  skrll 
    172  1.1  skrll   if (strlen (result) < (size_t) global_total_width)
    173  1.1  skrll     printf ("PASS: ");
    174  1.1  skrll   else
    175  1.1  skrll     printf ("FAIL: ");
    176  1.1  skrll   printf ("%d %s\n", global_total_width, result);
    177  1.1  skrll 
    178  1.1  skrll   free (result);
    179  1.1  skrll }
    180  1.1  skrll 
    181  1.1  skrll extern int main (void);
    182  1.1  skrll 
    183  1.1  skrll int
    184  1.1  skrll main (void)
    185  1.1  skrll {
    186  1.1  skrll   checkit ("%d", 0x12345678);
    187  1.1  skrll   checkit ("%200d", 5);
    188  1.1  skrll   checkit ("%.300d", 6);
    189  1.1  skrll   checkit ("%100.150d", 7);
    190  1.1  skrll   checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
    191  1.1  skrll 777777777777777777333333333333366666666666622222222222777777777777733333");
    192  1.1  skrll   checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
    193  1.1  skrll 
    194  1.1  skrll   return 0;
    195  1.1  skrll }
    196  1.1  skrll #endif /* TEST */
    197