printf.c 8.2 KB

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