printf.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * *printf implementations for busybox
  4. *
  5. * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. *
  21. */
  22. /* Mar 12, 2003 Manuel Novoa III
  23. *
  24. * While fwrite(), fputc(), fputs(), etc. all set the stream error flag
  25. * on failure, the *printf functions are unique in that they can fail
  26. * for reasons not related to the actual output itself. Among the possible
  27. * reasons for failure which don't set the streams error indicator,
  28. * SUSv3 lists EILSEQ, EINVAL, and ENOMEM.
  29. *
  30. * In some cases, it would be desirable to have a group of *printf()
  31. * functions available that _always_ set the stream error indicator on
  32. * failure. That would allow us to defer error checking until applet
  33. * exit. Unfortunately, there is no standard way of setting a streams
  34. * error indicator... even though we can clear it with clearerr().
  35. *
  36. * Therefore, we have to resort to implementation dependent code. Feel
  37. * free to send patches for stdio implementations where the following
  38. * fails.
  39. *
  40. * NOTE: None of this is thread safe. As busybox is a non-threaded app,
  41. * that isn't currently an issue.
  42. */
  43. #include <stdio.h>
  44. #include <stdarg.h>
  45. #include "libbb.h"
  46. #if defined(__UCLIBC__)
  47. # if defined(__FLAG_ERROR)
  48. /* Using my newer stdio implementation. Unlocked macros are:
  49. * #define __CLEARERR(stream) \
  50. ((stream)->modeflags &= ~(__FLAG_EOF|__FLAG_ERROR), (void)0)
  51. * #define __FEOF(stream) ((stream)->modeflags & __FLAG_EOF)
  52. * #define __FERROR(stream) ((stream)->modeflags & __FLAG_ERROR)
  53. */
  54. # if defined(__MASK_READING)
  55. # define SET_FERROR_UNLOCKED(S) ((S)->__modeflags |= __FLAG_ERROR)
  56. # else
  57. # define SET_FERROR_UNLOCKED(S) ((S)->modeflags |= __FLAG_ERROR)
  58. # endif
  59. # elif defined(__MODE_ERR)
  60. /* Using either the original stdio implementation (from dev86) or
  61. * my original stdio rewrite. Macros were:
  62. * #define ferror(fp) (((fp)->mode&__MODE_ERR) != 0)
  63. * #define feof(fp) (((fp)->mode&__MODE_EOF) != 0)
  64. * #define clearerr(fp) ((fp)->mode &= ~(__MODE_EOF|__MODE_ERR),0)
  65. */
  66. #define SET_FERROR_UNLOCKED(S) ((S)->mode |= __MODE_ERR)
  67. # else
  68. #error unknown uClibc stdio implemenation!
  69. # endif
  70. #elif defined(__GLIBC__)
  71. # if defined(_STDIO_USES_IOSTREAM)
  72. /* Apparently using the newer libio implementation, with associated defines:
  73. * #define _IO_feof_unlocked(__fp) (((__fp)->_flags & _IO_EOF_SEEN) != 0)
  74. * #define _IO_ferror_unlocked(__fp) (((__fp)->_flags & _IO_ERR_SEEN) != 0)
  75. */
  76. #define SET_FERROR_UNLOCKED(S) ((S)->_flags |= _IO_ERR_SEEN)
  77. # else
  78. /* Assume the older version of glibc which used a bitfield entry
  79. * as a stream error flag. The associated defines were:
  80. * #define __clearerr(stream) ((stream)->__error = (stream)->__eof = 0)
  81. * #define feof_unlocked(stream) ((stream)->__eof != 0)
  82. * #define ferror_unlocked(stream) ((stream)->__error != 0)
  83. */
  84. #define SET_FERROR_UNLOCKED(S) ((S)->__error = 1)
  85. # endif
  86. #elif defined(__NEWLIB_H__)
  87. /* I honestly don't know if there are different versions of stdio in
  88. * newlibs history. Anyway, here's what's current.
  89. * #define __sfeof(p) (((p)->_flags & __SEOF) != 0)
  90. * #define __sferror(p) (((p)->_flags & __SERR) != 0)
  91. * #define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF)))
  92. */
  93. #define SET_FERROR_UNLOCKED(S) ((S)->_flags |= __SERR)
  94. #elif defined(__dietlibc__)
  95. /*
  96. * WARNING!!! dietlibc is quite buggy. WARNING!!!
  97. *
  98. * Some example bugs as of March 12, 2003...
  99. * 1) fputc() doesn't set the error indicator on failure.
  100. * 2) freopen() doesn't maintain the same stream object, contrary to
  101. * standards. This makes it useless in its primary role of
  102. * reassociating stdin/stdout/stderr.
  103. * 3) printf() often fails to correctly format output when conversions
  104. * involve padding. It is also practically useless for floating
  105. * point output.
  106. *
  107. * But, if you're determined to use it anyway, (as of the current version)
  108. * you can extract the information you need from dietstdio.h. See the
  109. * other library implementations for examples.
  110. */
  111. #error dietlibc is currently not supported. Please see the commented source.
  112. #else /* some other lib */
  113. /* Please see the comments for the above supported libraries for examples
  114. * of what is required to support your stdio implementation.
  115. */
  116. #error Your stdio library is currently not supported. Please see the commented source.
  117. #endif
  118. #ifdef L_bb_vfprintf
  119. extern int bb_vfprintf(FILE * __restrict stream,
  120. const char * __restrict format,
  121. va_list arg)
  122. {
  123. int rv;
  124. if ((rv = vfprintf(stream, format, arg)) < 0) {
  125. SET_FERROR_UNLOCKED(stream);
  126. }
  127. return rv;
  128. }
  129. #endif
  130. #ifdef L_bb_vprintf
  131. extern int bb_vprintf(const char * __restrict format, va_list arg)
  132. {
  133. return bb_vfprintf(stdout, format, arg);
  134. }
  135. #endif
  136. #ifdef L_bb_fprintf
  137. extern int bb_fprintf(FILE * __restrict stream,
  138. const char * __restrict format, ...)
  139. {
  140. va_list arg;
  141. int rv;
  142. va_start(arg, format);
  143. rv = bb_vfprintf(stream, format, arg);
  144. va_end(arg);
  145. return rv;
  146. }
  147. #endif
  148. #ifdef L_bb_printf
  149. extern int bb_printf(const char * __restrict format, ...)
  150. {
  151. va_list arg;
  152. int rv;
  153. va_start(arg, format);
  154. rv = bb_vfprintf(stdout, format, arg);
  155. va_end(arg);
  156. return rv;
  157. }
  158. #endif