vasprintf.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /* Like vsprintf but provides a pointer to malloc'd storage, which must
  2. be freed by the caller.
  3. Copyright (C) 1994-2022 Free Software Foundation, Inc.
  4. This file is part of the libiberty library.
  5. Libiberty is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public
  7. License as published by the Free Software Foundation; either
  8. version 2 of the License, or (at your option) any later version.
  9. Libiberty is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Library General Public License for more details.
  13. You should have received a copy of the GNU Library General Public
  14. License along with libiberty; see the file COPYING.LIB. If not, write
  15. to the Free Software Foundation, Inc., 51 Franklin Street - Fifth
  16. Floor, Boston, MA 02110-1301, USA. */
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include <ansidecl.h>
  21. #include <stdarg.h>
  22. #if !defined (va_copy) && defined (__va_copy)
  23. # define va_copy(d,s) __va_copy((d),(s))
  24. #endif
  25. #include <stdio.h>
  26. #ifdef HAVE_STRING_H
  27. #include <string.h>
  28. #endif
  29. #ifdef HAVE_STDLIB_H
  30. #include <stdlib.h>
  31. #else
  32. extern PTR malloc ();
  33. #endif
  34. #include "libiberty.h"
  35. #include "vprintf-support.h"
  36. #ifdef TEST
  37. int global_total_width;
  38. #endif
  39. /*
  40. @deftypefn Extension int vasprintf (char **@var{resptr}, @
  41. const char *@var{format}, va_list @var{args})
  42. Like @code{vsprintf}, but instead of passing a pointer to a buffer,
  43. you pass a pointer to a pointer. This function will compute the size
  44. of the buffer needed, allocate memory with @code{malloc}, and store a
  45. pointer to the allocated memory in @code{*@var{resptr}}. The value
  46. returned is the same as @code{vsprintf} would return. If memory could
  47. not be allocated, minus one is returned and @code{NULL} is stored in
  48. @code{*@var{resptr}}.
  49. @end deftypefn
  50. */
  51. static int int_vasprintf (char **, const char *, va_list);
  52. static int
  53. int_vasprintf (char **result, const char *format, va_list args)
  54. {
  55. int total_width = libiberty_vprintf_buffer_size (format, args);
  56. #ifdef TEST
  57. global_total_width = total_width;
  58. #endif
  59. *result = (char *) malloc (total_width);
  60. if (*result != NULL)
  61. return vsprintf (*result, format, args);
  62. else
  63. return -1;
  64. }
  65. int
  66. vasprintf (char **result, const char *format,
  67. #if defined (_BSD_VA_LIST_) && defined (__FreeBSD__)
  68. _BSD_VA_LIST_ args)
  69. #else
  70. va_list args)
  71. #endif
  72. {
  73. return int_vasprintf (result, format, args);
  74. }
  75. #ifdef TEST
  76. static void ATTRIBUTE_PRINTF_1
  77. checkit (const char *format, ...)
  78. {
  79. char *result;
  80. va_list args;
  81. va_start (args, format);
  82. vasprintf (&result, format, args);
  83. va_end (args);
  84. if (strlen (result) < (size_t) global_total_width)
  85. printf ("PASS: ");
  86. else
  87. printf ("FAIL: ");
  88. printf ("%d %s\n", global_total_width, result);
  89. free (result);
  90. }
  91. extern int main (void);
  92. int
  93. main (void)
  94. {
  95. checkit ("%d", 0x12345678);
  96. checkit ("%200d", 5);
  97. checkit ("%.300d", 6);
  98. checkit ("%100.150d", 7);
  99. checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
  100. 777777777777777777333333333333366666666666622222222222777777777777733333");
  101. checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
  102. return 0;
  103. }
  104. #endif /* TEST */