vasprintf.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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. #include <bits/uClibc_va_copy.h>
  10. #ifdef __UCLIBC_MJN3_ONLY__
  11. /* Do the memstream stuff inline to avoid fclose and the openlist? */
  12. #warning CONSIDER: avoid open_memstream call?
  13. #endif
  14. #ifndef __STDIO_HAS_VSNPRINTF
  15. #warning Skipping vasprintf since no vsnprintf!
  16. #else
  17. #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
  18. libc_hidden_proto(open_memstream)
  19. libc_hidden_proto(fclose)
  20. libc_hidden_proto(vfprintf)
  21. #else
  22. libc_hidden_proto(vsnprintf)
  23. #endif
  24. int vasprintf(char **__restrict buf, const char * __restrict format,
  25. va_list arg)
  26. {
  27. #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
  28. FILE *f;
  29. size_t size;
  30. int rv = -1;
  31. *buf = NULL;
  32. if ((f = open_memstream(buf, &size)) != NULL) {
  33. rv = vfprintf(f, format, arg);
  34. fclose(f);
  35. if (rv < 0) {
  36. free(*buf);
  37. *buf = NULL;
  38. }
  39. }
  40. assert(rv >= -1);
  41. return rv;
  42. #else /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
  43. /* This implementation actually calls the printf machinery twice, but only
  44. * only does one malloc. This can be a problem though when custom printf
  45. * specs or the %m specifier are involved because the results of the
  46. * second call might be different from the first. */
  47. va_list arg2;
  48. int rv;
  49. va_copy(arg2, arg);
  50. rv = vsnprintf(NULL, 0, format, arg2);
  51. va_end(arg2);
  52. *buf = NULL;
  53. if (rv >= 0) {
  54. if ((*buf = malloc(++rv)) != NULL) {
  55. if ((rv = vsnprintf(*buf, rv, format, arg)) < 0) {
  56. free(*buf);
  57. *buf = NULL;
  58. }
  59. }
  60. }
  61. assert(rv >= -1);
  62. return rv;
  63. #endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
  64. }
  65. libc_hidden_proto(vasprintf)
  66. libc_hidden_def(vasprintf)
  67. #endif