vsnprintf.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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. #warning WISHLIST: Implement vsnprintf for non-buffered and no custom stream case.
  11. #endif /* __UCLIBC_MJN3_ONLY__ */
  12. #ifdef __STDIO_BUFFERS
  13. int attribute_hidden __vsnprintf(char *__restrict buf, size_t size,
  14. const char * __restrict format, va_list arg)
  15. {
  16. FILE f;
  17. int rv;
  18. /* __STDIO_STREAM_RESET_GCS(&f); */
  19. #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
  20. f.__cookie = &(f.__filedes);
  21. f.__gcs.read = NULL;
  22. f.__gcs.write = NULL;
  23. f.__gcs.seek = NULL;
  24. f.__gcs.close = NULL;
  25. #endif
  26. f.__filedes = __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES;
  27. f.__modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING);
  28. #ifdef __UCLIBC_HAS_WCHAR__
  29. f.__ungot_width[0] = 0;
  30. #endif /* __UCLIBC_HAS_WCHAR__ */
  31. #ifdef __STDIO_MBSTATE
  32. __INIT_MBSTATE(&(f.__state));
  33. #endif /* __STDIO_MBSTATE */
  34. #ifdef __UCLIBC_HAS_THREADS__
  35. f.__user_locking = 1; /* Set user locking. */
  36. __stdio_init_mutex(&f.__lock);
  37. #endif
  38. f.__nextopen = NULL;
  39. if (size > SIZE_MAX - (size_t) buf) {
  40. size = SIZE_MAX - (size_t) buf;
  41. }
  42. /* Set these last since __bufputc initialization depends on
  43. * __user_locking and only gets set if user locking is on. */
  44. f.__bufstart = buf;
  45. f.__bufend = buf + size;
  46. __STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f);
  47. __STDIO_STREAM_DISABLE_GETC(&f);
  48. __STDIO_STREAM_ENABLE_PUTC(&f);
  49. rv = __vfprintf(&f, format, arg);
  50. if (size) {
  51. if (f.__bufpos == f.__bufend) {
  52. --f.__bufpos;
  53. }
  54. *f.__bufpos = 0;
  55. }
  56. return rv;
  57. }
  58. strong_alias(__vsnprintf,vsnprintf)
  59. #elif defined(__USE_OLD_VFPRINTF__)
  60. typedef struct {
  61. FILE f;
  62. unsigned char *bufend; /* pointer to 1 past end of buffer */
  63. unsigned char *bufpos;
  64. } __FILE_vsnprintf;
  65. int attribute_hidden __vsnprintf(char *__restrict buf, size_t size,
  66. const char * __restrict format, va_list arg)
  67. {
  68. __FILE_vsnprintf f;
  69. int rv;
  70. f.bufpos = buf;
  71. if (size > SIZE_MAX - (size_t) buf) {
  72. size = SIZE_MAX - (size_t) buf;
  73. }
  74. f.bufend = buf + size;
  75. /* __STDIO_STREAM_RESET_GCS(&f.f); */
  76. #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
  77. f.f.__cookie = &(f.f.__filedes);
  78. f.f.__gcs.read = NULL;
  79. f.f.__gcs.write = NULL;
  80. f.f.__gcs.seek = NULL;
  81. f.f.__gcs.close = NULL;
  82. #endif
  83. f.f.__filedes = __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB;
  84. f.f.__modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING);
  85. #ifdef __UCLIBC_HAS_WCHAR__
  86. f.f.__ungot_width[0] = 0;
  87. #endif /* __UCLIBC_HAS_WCHAR__ */
  88. #ifdef __STDIO_MBSTATE
  89. __INIT_MBSTATE(&(f.f.__state));
  90. #endif /* __STDIO_MBSTATE */
  91. #ifdef __UCLIBC_HAS_THREADS__
  92. f.f.__user_locking = 1; /* Set user locking. */
  93. __stdio_init_mutex(&f.f.__lock);
  94. #endif
  95. f.f.__nextopen = NULL;
  96. rv = __vfprintf((FILE *) &f, format, arg);
  97. if (size) {
  98. if (f.bufpos == f.bufend) {
  99. --f.bufpos;
  100. }
  101. *f.bufpos = 0;
  102. }
  103. return rv;
  104. }
  105. strong_alias(__vsnprintf,vsnprintf)
  106. #elif defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__)
  107. typedef struct {
  108. size_t pos;
  109. size_t len;
  110. unsigned char *buf;
  111. FILE *fp;
  112. } __snpf_cookie;
  113. #define COOKIE ((__snpf_cookie *) cookie)
  114. static ssize_t snpf_write(register void *cookie, const char *buf,
  115. size_t bufsize)
  116. {
  117. size_t count;
  118. register char *p;
  119. /* Note: bufsize < SSIZE_MAX because of _stdio_WRITE. */
  120. if (COOKIE->len > COOKIE->pos) {
  121. count = COOKIE->len - COOKIE->pos - 1; /* Leave space for nul. */
  122. if (count > bufsize) {
  123. count = bufsize;
  124. }
  125. p = COOKIE->buf + COOKIE->pos;
  126. while (count) {
  127. *p++ = *buf++;
  128. --count;
  129. }
  130. *p = 0;
  131. }
  132. COOKIE->pos += bufsize;
  133. return bufsize;
  134. }
  135. #undef COOKIE
  136. int attribute_hidden __vsnprintf(char *__restrict buf, size_t size,
  137. const char * __restrict format, va_list arg)
  138. {
  139. FILE f;
  140. __snpf_cookie cookie;
  141. int rv;
  142. cookie.buf = buf;
  143. cookie.len = size;
  144. cookie.pos = 0;
  145. cookie.fp = &f;
  146. f.__cookie = &cookie;
  147. f.__gcs.write = snpf_write;
  148. f.__gcs.read = NULL;
  149. f.__gcs.seek = NULL;
  150. f.__gcs.close = NULL;
  151. f.__filedes = -1; /* For debugging. */
  152. f.__modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING);
  153. #ifdef __UCLIBC_HAS_WCHAR__
  154. f.__ungot_width[0] = 0;
  155. #endif /* __UCLIBC_HAS_WCHAR__ */
  156. #ifdef __STDIO_MBSTATE
  157. __INIT_MBSTATE(&(f.__state));
  158. #endif /* __STDIO_MBSTATE */
  159. #ifdef __UCLIBC_HAS_THREADS__
  160. f.__user_locking = 1; /* Set user locking. */
  161. __stdio_init_mutex(&f.__lock);
  162. #endif
  163. f.__nextopen = NULL;
  164. rv = __vfprintf(&f, format, arg);
  165. return rv;
  166. }
  167. strong_alias(__vsnprintf,vsnprintf)
  168. #else
  169. #warning Skipping vsnprintf since no buffering, no custom streams, and not old vfprintf!
  170. #ifdef __STDIO_HAS_VSNPRINTF
  171. #error WHOA! __STDIO_HAS_VSNPRINTF is defined!
  172. #endif
  173. #endif