printf.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /*
  2. * This file based on printf.c from 'Dlibs' on the atari ST (RdeBath)
  3. *
  4. * 19-OCT-88: Dale Schumacher
  5. * > John Stanley has again been a great help in debugging, particularly
  6. * > with the printf/scanf functions which are his creation.
  7. *
  8. * Dale Schumacher 399 Beacon Ave.
  9. * (alias: Dalnefre') St. Paul, MN 55104
  10. * dal@syntel.UUCP United States of America
  11. * "It's not reality that's important, but how you perceive things."
  12. *
  13. */
  14. /* Altered to use stdarg, made the core function vfprintf.
  15. * Hooked into the stdio package using 'inside information'
  16. * Altered sizeof() assumptions, now assumes all integers except chars
  17. * will be either
  18. * sizeof(xxx) == sizeof(long) or sizeof(xxx) == sizeof(short)
  19. *
  20. * -RDB
  21. */
  22. #include <sys/types.h>
  23. #include <fcntl.h>
  24. #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__)
  25. #include <stdarg.h>
  26. #define va_strt va_start
  27. #else
  28. #include <varargs.h>
  29. #define va_strt(p,i) va_start(p)
  30. #endif
  31. #include "stdio.h"
  32. #ifdef L_printf
  33. #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__)
  34. int printf(const char * fmt, ...)
  35. #else
  36. int printf(fmt, va_alist)
  37. __const char *fmt;
  38. va_dcl
  39. #endif
  40. {
  41. va_list ptr;
  42. int rv;
  43. va_strt(ptr, fmt);
  44. rv = vfprintf(stdout,fmt,ptr);
  45. va_end(ptr);
  46. return rv;
  47. }
  48. #endif
  49. #ifdef L_sprintf
  50. #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__)
  51. int sprintf(char * sp, const char * fmt, ...)
  52. #else
  53. int sprintf(sp, fmt, va_alist)
  54. char * sp;
  55. __const char *fmt;
  56. va_dcl
  57. #endif
  58. {
  59. static FILE string[1] =
  60. {
  61. {0, 0, (char*)(unsigned) -1, 0, (char*) (unsigned) -1, -1,
  62. _IOFBF | __MODE_WRITE}
  63. };
  64. va_list ptr;
  65. int rv;
  66. va_strt(ptr, fmt);
  67. string->bufpos = sp;
  68. rv = vfprintf(string,fmt,ptr);
  69. va_end(ptr);
  70. *(string->bufpos) = 0;
  71. return rv;
  72. }
  73. #endif
  74. #ifdef L_fprintf
  75. #if defined(__STDC__) && !defined(__FIRST_ARG_IN_AX__)
  76. int fprintf(FILE * fp, const char * fmt, ...)
  77. #else
  78. int fprintf(fp, fmt, va_alist)
  79. FILE * fp;
  80. __const char *fmt;
  81. va_dcl
  82. #endif
  83. {
  84. va_list ptr;
  85. int rv;
  86. va_strt(ptr, fmt);
  87. rv = vfprintf(fp,fmt,ptr);
  88. va_end(ptr);
  89. return rv;
  90. }
  91. #endif
  92. #ifdef L_vprintf
  93. int vprintf(fmt, ap)
  94. __const char *fmt;
  95. va_list ap;
  96. {
  97. return vfprintf(stdout,fmt,ap);
  98. }
  99. #endif
  100. #ifdef L_vsprintf
  101. int vsprintf(sp, fmt, ap)
  102. char * sp;
  103. __const char *fmt;
  104. va_list ap;
  105. {
  106. static FILE string[1] =
  107. {
  108. {0, 0, (char*)(unsigned) -1, 0, (char*) (unsigned) -1, -1,
  109. _IOFBF | __MODE_WRITE}
  110. };
  111. int rv;
  112. string->bufpos = sp;
  113. rv = vfprintf(string,fmt,ap);
  114. *(string->bufpos) = 0;
  115. return rv;
  116. }
  117. #endif
  118. #ifdef L_vfprintf
  119. #ifdef FLOATS
  120. int (*__fp_print)() = 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);
  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);
  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. if ( __fp_print )
  313. {
  314. (*__fp_print)(&va_arg(ap, double), *fmt, preci, ptmp);
  315. preci = -1;
  316. goto printit;
  317. }
  318. /* FALLTHROUGH if no floating printf available */
  319. #endif
  320. default: /* unknown character */
  321. goto charout;
  322. }
  323. }
  324. else
  325. {
  326. charout:
  327. putc(*fmt, op); /* normal char out */
  328. ++cnt;
  329. if( *fmt == '\n' && buffer_mode == _IOLBF ) fflush(op);
  330. }
  331. ++fmt;
  332. }
  333. op->mode |= buffer_mode;
  334. if( buffer_mode == _IONBF ) fflush(op);
  335. if( buffer_mode == _IOLBF ) op->bufwrite = op->bufstart;
  336. return (cnt);
  337. }
  338. #endif