vasprintf.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
  2. *
  3. * GNU Library General Public License (LGPL) version 2 or later.
  4. *
  5. * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
  6. */
  7. #include "_stdio.h"
  8. #include <stdarg.h>
  9. #ifdef __UCLIBC_MJN3_ONLY__
  10. /* Do the memstream stuff inline to avoid fclose and the openlist? */
  11. #warning CONSIDER: avoid open_memstream call?
  12. #endif
  13. #ifndef __STDIO_HAS_VSNPRINTF
  14. #warning Skipping vasprintf since no vsnprintf!
  15. #else
  16. /* Deal with pre-C99 compilers. */
  17. #ifndef va_copy
  18. #ifdef __va_copy
  19. #define va_copy(A,B) __va_copy(A,B)
  20. #else
  21. #warning Neither va_copy (C99/SUSv3) nor __va_copy is defined. Using a simple copy instead. But you should really check that this is appropriate...
  22. #define va_copy(A,B) A = B
  23. #endif
  24. #endif /* va_copy */
  25. int vasprintf(char **__restrict buf, const char * __restrict format,
  26. va_list arg)
  27. {
  28. #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
  29. FILE *f;
  30. size_t size;
  31. int rv = -1;
  32. *buf = NULL;
  33. if ((f = open_memstream(buf, &size)) != NULL) {
  34. rv = vfprintf(f, format, arg);
  35. fclose(f);
  36. if (rv < 0) {
  37. free(*buf);
  38. *buf = NULL;
  39. }
  40. }
  41. assert(rv >= -1);
  42. return rv;
  43. #else /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
  44. /* This implementation actually calls the printf machinery twice, but only
  45. * only does one malloc. This can be a problem though when custom printf
  46. * specs or the %m specifier are involved because the results of the
  47. * second call might be different from the first. */
  48. va_list arg2;
  49. int rv;
  50. va_copy(arg2, arg);
  51. rv = vsnprintf(NULL, 0, format, arg2);
  52. va_end(arg2);
  53. *buf = NULL;
  54. if (rv >= 0) {
  55. if ((*buf = malloc(++rv)) != NULL) {
  56. if ((rv = vsnprintf(*buf, rv, format, arg)) < 0) {
  57. free(*buf);
  58. *buf = NULL;
  59. }
  60. }
  61. }
  62. assert(rv >= -1);
  63. return rv;
  64. #endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
  65. }
  66. #endif