16ca2c52aSchristos /* Like vsprintf but provides a pointer to malloc'd storage, which must
26ca2c52aSchristos    be freed by the caller.
3*184b2d41Schristos    Copyright (C) 1994-2020 Free Software Foundation, Inc.
46ca2c52aSchristos 
56ca2c52aSchristos This file is part of the libiberty library.
66ca2c52aSchristos Libiberty is free software; you can redistribute it and/or
76ca2c52aSchristos modify it under the terms of the GNU Library General Public
86ca2c52aSchristos License as published by the Free Software Foundation; either
96ca2c52aSchristos version 2 of the License, or (at your option) any later version.
106ca2c52aSchristos 
116ca2c52aSchristos Libiberty is distributed in the hope that it will be useful,
126ca2c52aSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of
136ca2c52aSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
146ca2c52aSchristos Library General Public License for more details.
156ca2c52aSchristos 
166ca2c52aSchristos You should have received a copy of the GNU Library General Public
176ca2c52aSchristos License along with libiberty; see the file COPYING.LIB.  If not, write
186ca2c52aSchristos to the Free Software Foundation, Inc., 51 Franklin Street - Fifth
196ca2c52aSchristos Floor, Boston, MA 02110-1301, USA.  */
206ca2c52aSchristos 
216ca2c52aSchristos #ifdef HAVE_CONFIG_H
226ca2c52aSchristos #include "config.h"
236ca2c52aSchristos #endif
246ca2c52aSchristos #include <ansidecl.h>
256ca2c52aSchristos #include <stdarg.h>
266ca2c52aSchristos #if !defined (va_copy) && defined (__va_copy)
276ca2c52aSchristos # define va_copy(d,s)  __va_copy((d),(s))
286ca2c52aSchristos #endif
296ca2c52aSchristos #include <stdio.h>
306ca2c52aSchristos #ifdef HAVE_STRING_H
316ca2c52aSchristos #include <string.h>
326ca2c52aSchristos #endif
336ca2c52aSchristos #ifdef HAVE_STDLIB_H
346ca2c52aSchristos #include <stdlib.h>
356ca2c52aSchristos #else
366ca2c52aSchristos extern PTR malloc ();
376ca2c52aSchristos #endif
386ca2c52aSchristos #include "libiberty.h"
396ca2c52aSchristos #include "vprintf-support.h"
406ca2c52aSchristos 
416ca2c52aSchristos #ifdef TEST
426ca2c52aSchristos int global_total_width;
436ca2c52aSchristos #endif
446ca2c52aSchristos 
456ca2c52aSchristos /*
466ca2c52aSchristos 
476ca2c52aSchristos @deftypefn Extension int vasprintf (char **@var{resptr}, @
486ca2c52aSchristos   const char *@var{format}, va_list @var{args})
496ca2c52aSchristos 
506ca2c52aSchristos Like @code{vsprintf}, but instead of passing a pointer to a buffer,
516ca2c52aSchristos you pass a pointer to a pointer.  This function will compute the size
526ca2c52aSchristos of the buffer needed, allocate memory with @code{malloc}, and store a
536ca2c52aSchristos pointer to the allocated memory in @code{*@var{resptr}}.  The value
546ca2c52aSchristos returned is the same as @code{vsprintf} would return.  If memory could
556ca2c52aSchristos not be allocated, minus one is returned and @code{NULL} is stored in
566ca2c52aSchristos @code{*@var{resptr}}.
576ca2c52aSchristos 
586ca2c52aSchristos @end deftypefn
596ca2c52aSchristos 
606ca2c52aSchristos */
616ca2c52aSchristos 
626ca2c52aSchristos static int int_vasprintf (char **, const char *, va_list);
636ca2c52aSchristos 
646ca2c52aSchristos static int
int_vasprintf(char ** result,const char * format,va_list args)656ca2c52aSchristos int_vasprintf (char **result, const char *format, va_list args)
666ca2c52aSchristos {
676ca2c52aSchristos   int total_width = libiberty_vprintf_buffer_size (format, args);
686ca2c52aSchristos #ifdef TEST
696ca2c52aSchristos   global_total_width = total_width;
706ca2c52aSchristos #endif
716ca2c52aSchristos   *result = (char *) malloc (total_width);
726ca2c52aSchristos   if (*result != NULL)
736ca2c52aSchristos     return vsprintf (*result, format, args);
746ca2c52aSchristos   else
756ca2c52aSchristos     return -1;
766ca2c52aSchristos }
776ca2c52aSchristos 
786ca2c52aSchristos int
vasprintf(char ** result,const char * format,_BSD_VA_LIST_ args)796ca2c52aSchristos vasprintf (char **result, const char *format,
806ca2c52aSchristos #if defined (_BSD_VA_LIST_) && defined (__FreeBSD__)
816ca2c52aSchristos            _BSD_VA_LIST_ args)
826ca2c52aSchristos #else
836ca2c52aSchristos            va_list args)
846ca2c52aSchristos #endif
856ca2c52aSchristos {
866ca2c52aSchristos   return int_vasprintf (result, format, args);
876ca2c52aSchristos }
886ca2c52aSchristos 
896ca2c52aSchristos #ifdef TEST
906ca2c52aSchristos static void ATTRIBUTE_PRINTF_1
checkit(const char * format,...)916ca2c52aSchristos checkit (const char *format, ...)
926ca2c52aSchristos {
936ca2c52aSchristos   char *result;
946ca2c52aSchristos   va_list args;
956ca2c52aSchristos   va_start (args, format);
966ca2c52aSchristos   vasprintf (&result, format, args);
976ca2c52aSchristos   va_end (args);
986ca2c52aSchristos 
996ca2c52aSchristos   if (strlen (result) < (size_t) global_total_width)
1006ca2c52aSchristos     printf ("PASS: ");
1016ca2c52aSchristos   else
1026ca2c52aSchristos     printf ("FAIL: ");
1036ca2c52aSchristos   printf ("%d %s\n", global_total_width, result);
1046ca2c52aSchristos 
1056ca2c52aSchristos   free (result);
1066ca2c52aSchristos }
1076ca2c52aSchristos 
1086ca2c52aSchristos extern int main (void);
1096ca2c52aSchristos 
1106ca2c52aSchristos int
main(void)1116ca2c52aSchristos main (void)
1126ca2c52aSchristos {
1136ca2c52aSchristos   checkit ("%d", 0x12345678);
1146ca2c52aSchristos   checkit ("%200d", 5);
1156ca2c52aSchristos   checkit ("%.300d", 6);
1166ca2c52aSchristos   checkit ("%100.150d", 7);
1176ca2c52aSchristos   checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
1186ca2c52aSchristos 777777777777777777333333333333366666666666622222222222777777777777733333");
1196ca2c52aSchristos   checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
1206ca2c52aSchristos 
1216ca2c52aSchristos   return 0;
1226ca2c52aSchristos }
1236ca2c52aSchristos #endif /* TEST */
124