printf.c 7.2 KB

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