printf.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*
  2. * This file based on printf.c from 'Dlibs' on the atari ST (RdeBath)
  3. *
  4. *
  5. * Dale Schumacher 399 Beacon Ave.
  6. * (alias: Dalnefre') St. Paul, MN 55104
  7. * dal@syntel.UUCP United States of America
  8. * "It's not reality that's important, but how you perceive things."
  9. */
  10. /* Altered to use stdarg, made the core function vfprintf.
  11. * Hooked into the stdio package using 'inside information'
  12. * Altered sizeof() assumptions, now assumes all integers except chars
  13. * will be either
  14. * sizeof(xxx) == sizeof(long) or sizeof(xxx) == sizeof(short)
  15. *
  16. * -RDB
  17. */
  18. #include <sys/types.h>
  19. #include <fcntl.h>
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #ifdef __STDC__
  23. #include <stdarg.h>
  24. #define va_strt va_start
  25. #else
  26. #include <varargs.h>
  27. #define va_strt(p,i) va_start(p)
  28. #endif
  29. #include "stdio.h"
  30. extern int vfnprintf(FILE * op, size_t max_size,
  31. register __const char *fmt, register va_list ap);
  32. #ifdef L_printf
  33. int printf(const char *fmt, ...)
  34. {
  35. va_list ptr;
  36. int rv;
  37. va_strt(ptr, fmt);
  38. rv = vfnprintf(stdout, -1, fmt, ptr);
  39. va_end(ptr);
  40. return rv;
  41. }
  42. #endif
  43. #ifdef L_sprintf
  44. int sprintf(char *sp, const char *fmt, ...)
  45. {
  46. static FILE string[1] = {
  47. {0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1,
  48. _IOFBF | __MODE_WRITE}
  49. };
  50. va_list ptr;
  51. int rv;
  52. va_strt(ptr, fmt);
  53. string->bufpos = sp;
  54. rv = vfnprintf(string, -1, fmt, ptr);
  55. va_end(ptr);
  56. *(string->bufpos) = 0;
  57. return rv;
  58. }
  59. #endif
  60. #ifdef L_snprintf
  61. int snprintf(char *sp, size_t size, const char *fmt, ...)
  62. {
  63. static FILE string[1] = {
  64. {0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1,
  65. _IOFBF | __MODE_WRITE}
  66. };
  67. va_list ptr;
  68. int rv;
  69. va_strt(ptr, fmt);
  70. string->bufpos = sp;
  71. rv = vfnprintf(string, size, fmt, ptr);
  72. va_end(ptr);
  73. *(string->bufpos) = 0;
  74. return rv;
  75. }
  76. #endif
  77. #ifdef L_fprintf
  78. int fprintf(FILE * fp, const char *fmt, ...)
  79. {
  80. va_list ptr;
  81. int rv;
  82. va_strt(ptr, fmt);
  83. rv = vfnprintf(fp, -1, fmt, ptr);
  84. va_end(ptr);
  85. return rv;
  86. }
  87. #endif
  88. #ifdef L_vprintf
  89. int vprintf(const char *fmt, va_list ap)
  90. {
  91. return vfprintf(stdout, fmt, ap);
  92. }
  93. #endif
  94. #ifdef L_vsprintf
  95. int vsprintf(char *sp, __const char *fmt, va_list ap)
  96. {
  97. static FILE string[1] = {
  98. {0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1,
  99. _IOFBF | __MODE_WRITE}
  100. };
  101. int rv;
  102. string->bufpos = sp;
  103. rv = vfnprintf(string, -1, fmt, ap);
  104. *(string->bufpos) = 0;
  105. return rv;
  106. }
  107. #endif
  108. #ifdef L_vsprintf
  109. int vsnprintf(char *sp, size_t size, __const char *fmt, va_list ap)
  110. {
  111. static FILE string[1] = {
  112. {0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1,
  113. _IOFBF | __MODE_WRITE}
  114. };
  115. int rv;
  116. string->bufpos = sp;
  117. rv = vfnprintf(string, size, fmt, ap);
  118. *(string->bufpos) = 0;
  119. return rv;
  120. }
  121. #endif
  122. #ifdef L_vfprintf
  123. #if FLOATS
  124. int _vfprintf_fp_ref = 1;
  125. #else
  126. int _vfprintf_fp_ref = 0;
  127. #endif
  128. static int
  129. printfield(op, buf, ljustf, sign, pad, width, preci, buffer_mode, max_size,
  130. current_size)
  131. register FILE *op;
  132. register unsigned char *buf;
  133. int ljustf;
  134. register char sign;
  135. char pad;
  136. register int width;
  137. int preci;
  138. int buffer_mode;
  139. size_t max_size;
  140. size_t current_size;
  141. /*
  142. * Output the given field in the manner specified by the arguments. Return
  143. * the number of characters output.
  144. */
  145. {
  146. register int cnt = 0, len;
  147. register unsigned char ch;
  148. len = strlen(buf);
  149. if (*buf == '-')
  150. sign = *buf++;
  151. else if (sign)
  152. len++;
  153. if ((preci != -1) && (len > preci)) /* limit max data width */
  154. len = preci;
  155. if (width < len) /* flexible field width or width overflow */
  156. width = len;
  157. /*
  158. * at this point: width = total field width len = actual data width
  159. * (including possible sign character)
  160. */
  161. cnt = width;
  162. width -= len;
  163. while (width || len) {
  164. if (!ljustf && width) { /* left padding */
  165. if (len && sign && (pad == '0'))
  166. goto showsign;
  167. ch = pad;
  168. --width;
  169. } else if (len) {
  170. if (sign) {
  171. showsign:ch = sign;
  172. /* sign */
  173. sign = '\0';
  174. } else
  175. ch = *buf++; /* main field */
  176. --len;
  177. } else {
  178. ch = pad; /* right padding */
  179. --width;
  180. }
  181. current_size++;
  182. if (max_size > 0 && current_size < max_size)
  183. putc(ch, op);
  184. if (ch == '\n' && buffer_mode == _IOLBF)
  185. fflush(op);
  186. }
  187. return (cnt);
  188. }
  189. int vfnprintf(FILE * op, size_t max_size, register __const char *fmt,
  190. register va_list ap)
  191. {
  192. register int i, cnt = 0, ljustf, lval;
  193. int preci, dpoint, width;
  194. char pad, sign, radix, hash;
  195. register char *ptmp;
  196. char tmp[64], *ltostr(), *ultostr();
  197. int buffer_mode;
  198. /* This speeds things up a bit for unbuffered */
  199. buffer_mode = (op->mode & __MODE_BUF);
  200. op->mode &= (~__MODE_BUF);
  201. while (*fmt) {
  202. if (*fmt == '%') {
  203. if (buffer_mode == _IONBF)
  204. fflush(op);
  205. ljustf = 0; /* left justify flag */
  206. sign = '\0'; /* sign char & status */
  207. pad = ' '; /* justification padding char */
  208. width = -1; /* min field width */
  209. dpoint = 0; /* found decimal point */
  210. preci = -1; /* max data width */
  211. radix = 10; /* number base */
  212. ptmp = tmp; /* pointer to area to print */
  213. hash = 0;
  214. lval = (sizeof(int) == sizeof(long)); /* long value flaged */
  215. fmtnxt:
  216. i = 0;
  217. for (;;) {
  218. ++fmt;
  219. if (*fmt < '0' || *fmt > '9')
  220. break;
  221. i = (i * 10) + (*fmt - '0');
  222. if (dpoint)
  223. preci = i;
  224. else if (!i && (pad == ' ')) {
  225. pad = '0';
  226. goto fmtnxt;
  227. } else
  228. width = i;
  229. }
  230. switch (*fmt) {
  231. case '\0': /* early EOS */
  232. --fmt;
  233. goto charout;
  234. case '-': /* left justification */
  235. ljustf = 1;
  236. goto fmtnxt;
  237. case ' ':
  238. case '+': /* leading sign flag */
  239. sign = *fmt;
  240. goto fmtnxt;
  241. case '*': /* parameter width value */
  242. i = va_arg(ap, int);
  243. if (dpoint)
  244. preci = i;
  245. else
  246. width = i;
  247. goto fmtnxt;
  248. case '.': /* secondary width field */
  249. dpoint = 1;
  250. goto fmtnxt;
  251. case 'l': /* long data */
  252. lval = 1;
  253. goto fmtnxt;
  254. case 'h': /* short data */
  255. lval = 0;
  256. goto fmtnxt;
  257. case 'd': /* Signed decimal */
  258. case 'i':
  259. ptmp = ltostr((long) ((lval)
  260. ? va_arg(ap, long)
  261. : va_arg(ap, short)), 10, 0);
  262. goto printit;
  263. case 'b': /* Unsigned binary */
  264. radix = 2;
  265. goto usproc;
  266. case 'o': /* Unsigned octal */
  267. radix = 8;
  268. goto usproc;
  269. case 'p': /* Pointer */
  270. lval = (sizeof(char *) == sizeof(long));
  271. pad = '0';
  272. width = 6;
  273. preci = 8;
  274. /* fall thru */
  275. case 'x': /* Unsigned hexadecimal */
  276. case 'X':
  277. radix = 16;
  278. /* fall thru */
  279. case 'u': /* Unsigned decimal */
  280. usproc:
  281. ptmp = ultostr((unsigned long) ((lval)
  282. ? va_arg(ap, unsigned long)
  283. : va_arg(ap,
  284. unsigned short)),
  285. radix, (*fmt == 'X') ? 1 : 0);
  286. if (hash && radix == 8) {
  287. width = strlen(ptmp) + 1;
  288. pad = '0';
  289. }
  290. goto printit;
  291. case '#':
  292. hash = 1;
  293. goto fmtnxt;
  294. case 'c': /* Character */
  295. ptmp[0] = va_arg(ap, int);
  296. ptmp[1] = '\0';
  297. goto nopad;
  298. case 's': /* String */
  299. ptmp = va_arg(ap, char *);
  300. nopad:
  301. sign = '\0';
  302. pad = ' ';
  303. printit:
  304. cnt += printfield(op, ptmp, ljustf, sign, pad, width,
  305. preci, buffer_mode, max_size, cnt);
  306. break;
  307. #if FLOATS
  308. case 'e': /* float */
  309. case 'f':
  310. case 'g':
  311. case 'E':
  312. case 'G':
  313. fprintf(stderr, "LIBM:PRINTF");
  314. gcvt(va_arg(ap, double), preci, ptmp);
  315. preci = -1;
  316. goto printit;
  317. #else
  318. case 'e': /* float */
  319. case 'f':
  320. case 'g':
  321. case 'E':
  322. case 'G':
  323. fprintf(stderr, "LIBC:PRINTF");
  324. exit(-1);
  325. #endif
  326. default: /* unknown character */
  327. goto charout;
  328. }
  329. } else {
  330. charout:
  331. if (max_size > 0 && ++cnt < max_size)
  332. putc(*fmt, op); /* normal char out */
  333. if (*fmt == '\n' && buffer_mode == _IOLBF)
  334. fflush(op);
  335. }
  336. ++fmt;
  337. }
  338. op->mode |= buffer_mode;
  339. if (buffer_mode == _IONBF)
  340. fflush(op);
  341. if (buffer_mode == _IOLBF)
  342. op->bufwrite = op->bufstart;
  343. return (cnt);
  344. }
  345. int vfprintf(FILE * op, register __const char *fmt, register va_list ap)
  346. {
  347. return (vfnprintf(op, -1, fmt, ap));
  348. }
  349. #endif