fmt.c
资源名称:c.rar [点击查看]
上传用户:shmaik
上传日期:2014-06-01
资源大小:45093k
文件大小:9k
源码类别:

VC书籍

开发平台:

C/C++

  1. static char rcsid[] = "$Id: H:/drh/idioms/book/RCS/fmt.doc,v 1.10 1996/06/26 23:02:01 drh Exp $";
  2. #include <stdarg.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <limits.h>
  7. #include <float.h>
  8. #include <ctype.h>
  9. #include <math.h>
  10. #include "assert.h"
  11. #include "except.h"
  12. #include "fmt.h"
  13. #include "mem.h"
  14. #define T Fmt_T
  15. struct buf {
  16. char *buf;
  17. char *bp;
  18. int size;
  19. };
  20. #define pad(n,c) do { int nn = (n); 
  21. while (nn-- > 0) 
  22. put((c), cl); } while (0)
  23. static void cvt_s(int code, va_list *app,
  24. int put(int c, void *cl), void *cl,
  25. unsigned char flags[], int width, int precision) {
  26. char *str = va_arg(*app, char *);
  27. assert(str);
  28. Fmt_puts(str, strlen(str), put, cl, flags,
  29. width, precision);
  30. }
  31. static void cvt_d(int code, va_list *app,
  32. int put(int c, void *cl), void *cl,
  33. unsigned char flags[], int width, int precision) {
  34. int val = va_arg(*app, int);
  35. unsigned m;
  36. char buf[43];
  37. char *p = buf + sizeof buf;
  38. if (val == INT_MIN)
  39. m = INT_MAX + 1U;
  40. else if (val < 0)
  41. m = -val;
  42. else
  43. m = val;
  44. do
  45. *--p = m%10 + '0';
  46. while ((m /= 10) > 0);
  47. if (val < 0)
  48. *--p = '-';
  49. Fmt_putd(p, (buf + sizeof buf) - p, put, cl, flags,
  50. width, precision);
  51. }
  52. static void cvt_u(int code, va_list *app,
  53. int put(int c, void *cl), void *cl,
  54. unsigned char flags[], int width, int precision) {
  55. unsigned m = va_arg(*app, unsigned);
  56. char buf[43];
  57. char *p = buf + sizeof buf;
  58. do
  59. *--p = m%10 + '0';
  60. while ((m /= 10) > 0);
  61. Fmt_putd(p, (buf + sizeof buf) - p, put, cl, flags,
  62. width, precision);
  63. }
  64. static void cvt_o(int code, va_list *app,
  65. int put(int c, void *cl), void *cl,
  66. unsigned char flags[], int width, int precision) {
  67. unsigned m = va_arg(*app, unsigned);
  68. char buf[43];
  69. char *p = buf + sizeof buf;
  70. do
  71. *--p = (m&0x7) + '0';
  72. while ((m>>= 3) != 0);
  73. Fmt_putd(p, (buf + sizeof buf) - p, put, cl, flags,
  74. width, precision);
  75. }
  76. static void cvt_x(int code, va_list *app,
  77. int put(int c, void *cl), void *cl,
  78. unsigned char flags[], int width, int precision) {
  79. unsigned m = va_arg(*app, unsigned);
  80. char buf[43];
  81. char *p = buf + sizeof buf;
  82. do
  83. *--p = "0123456789abcdef"[m&0xf];
  84. while ((m>>= 4) != 0);
  85. Fmt_putd(p, (buf + sizeof buf) - p, put, cl, flags,
  86. width, precision);
  87. }
  88. static void cvt_p(int code, va_list *app,
  89. int put(int c, void *cl), void *cl,
  90. unsigned char flags[], int width, int precision) {
  91. unsigned long m = (unsigned long)va_arg(*app, void*);
  92. char buf[43];
  93. char *p = buf + sizeof buf;
  94. precision = INT_MIN;
  95. do
  96. *--p = "0123456789abcdef"[m&0xf];
  97. while ((m>>= 4) != 0);
  98. Fmt_putd(p, (buf + sizeof buf) - p, put, cl, flags,
  99. width, precision);
  100. }
  101. static void cvt_c(int code, va_list *app,
  102. int put(int c, void *cl), void *cl,
  103. unsigned char flags[], int width, int precision) {
  104. if (width == INT_MIN)
  105. width = 0;
  106. if (width < 0) {
  107. flags['-'] = 1;
  108. width = -width;
  109. }
  110. if (!flags['-'])
  111. pad(width - 1, ' ');
  112. put((unsigned char)va_arg(*app, int), cl);
  113. if ( flags['-'])
  114. pad(width - 1, ' ');
  115. }
  116. static void cvt_f(int code, va_list *app,
  117. int put(int c, void *cl), void *cl,
  118. unsigned char flags[], int width, int precision) {
  119. char buf[DBL_MAX_10_EXP+1+1+99+1];
  120. if (precision < 0)
  121. precision = 6;
  122. if (code == 'g' && precision == 0)
  123. precision = 1;
  124. {
  125. static char fmt[] = "%.dd?";
  126. assert(precision <= 99);
  127. fmt[4] = code;
  128. fmt[3] =      precision%10 + '0';
  129. fmt[2] = (precision/10)%10 + '0';
  130. sprintf(buf, fmt, va_arg(*app, double));
  131. }
  132. Fmt_putd(buf, strlen(buf), put, cl, flags,
  133. width, precision);
  134. }
  135. const Except_T Fmt_Overflow = { "Formatting Overflow" };
  136. static T cvt[256] = {
  137.  /*   0-  7 */ 0,     0, 0,     0,     0,     0,     0,     0,
  138.  /*   8- 15 */ 0,     0, 0,     0,     0,     0,     0,     0,
  139.  /*  16- 23 */ 0,     0, 0,     0,     0,     0,     0,     0,
  140.  /*  24- 31 */ 0,     0, 0,     0,     0,     0,     0,     0,
  141.  /*  32- 39 */ 0,     0, 0,     0,     0,     0,     0,     0,
  142.  /*  40- 47 */ 0,     0, 0,     0,     0,     0,     0,     0,
  143.  /*  48- 55 */ 0,     0, 0,     0,     0,     0,     0,     0,
  144.  /*  56- 63 */ 0,     0, 0,     0,     0,     0,     0,     0,
  145.  /*  64- 71 */ 0,     0, 0,     0,     0,     0,     0,     0,
  146.  /*  72- 79 */ 0,     0, 0,     0,     0,     0,     0,     0,
  147.  /*  80- 87 */ 0,     0, 0,     0,     0,     0,     0,     0,
  148.  /*  88- 95 */ 0,     0, 0,     0,     0,     0,     0,     0,
  149.  /*  96-103 */ 0,     0, 0, cvt_c, cvt_d, cvt_f, cvt_f, cvt_f,
  150.  /* 104-111 */ 0,     0, 0,     0,     0,     0,     0, cvt_o,
  151.  /* 112-119 */ cvt_p, 0, 0, cvt_s,     0, cvt_u,     0,     0,
  152.  /* 120-127 */ cvt_x, 0, 0,     0,     0,     0,     0,     0
  153. };
  154. char *Fmt_flags = "-+ 0";
  155. static int outc(int c, void *cl) {
  156. FILE *f = cl;
  157. return putc(c, f);
  158. }
  159. static int insert(int c, void *cl) {
  160. struct buf *p = cl;
  161. if (p->bp >= p->buf + p->size)
  162. RAISE(Fmt_Overflow);
  163. *p->bp++ = c;
  164. return c;
  165. }
  166. static int append(int c, void *cl) {
  167. struct buf *p = cl;
  168. if (p->bp >= p->buf + p->size) {
  169. RESIZE(p->buf, 2*p->size);
  170. p->bp = p->buf + p->size;
  171. p->size *= 2;
  172. }
  173. *p->bp++ = c;
  174. return c;
  175. }
  176. void Fmt_puts(const char *str, int len,
  177. int put(int c, void *cl), void *cl,
  178. unsigned char flags[], int width, int precision) {
  179. assert(str);
  180. assert(len >= 0);
  181. assert(flags);
  182. if (width == INT_MIN)
  183. width = 0;
  184. if (width < 0) {
  185. flags['-'] = 1;
  186. width = -width;
  187. }
  188. if (precision >= 0)
  189. flags['0'] = 0;
  190. if (precision >= 0 && precision < len)
  191. len = precision;
  192. if (!flags['-'])
  193. pad(width - len, ' ');
  194. {
  195. int i;
  196. for (i = 0; i < len; i++)
  197. put((unsigned char)*str++, cl);
  198. }
  199. if ( flags['-'])
  200. pad(width - len, ' ');
  201. }
  202. void Fmt_fmt(int put(int c, void *), void *cl,
  203. const char *fmt, ...) {
  204. va_list ap;
  205. va_start(ap, fmt);
  206. Fmt_vfmt(put, cl, fmt, ap);
  207. va_end(ap);
  208. }
  209. void Fmt_print(const char *fmt, ...) {
  210. va_list ap;
  211. va_start(ap, fmt);
  212. Fmt_vfmt(outc, stdout, fmt, ap);
  213. va_end(ap);
  214. }
  215. void Fmt_fprint(FILE *stream, const char *fmt, ...) {
  216. va_list ap;
  217. va_start(ap, fmt);
  218. Fmt_vfmt(outc, stream, fmt, ap);
  219. va_end(ap);
  220. }
  221. int Fmt_sfmt(char *buf, int size, const char *fmt, ...) {
  222. va_list ap;
  223. int len;
  224. va_start(ap, fmt);
  225. len = Fmt_vsfmt(buf, size, fmt, ap);
  226. va_end(ap);
  227. return len;
  228. }
  229. int Fmt_vsfmt(char *buf, int size, const char *fmt,
  230. va_list ap) {
  231. struct buf cl;
  232. assert(buf);
  233. assert(size > 0);
  234. assert(fmt);
  235. cl.buf = cl.bp = buf;
  236. cl.size = size;
  237. Fmt_vfmt(insert, &cl, fmt, ap);
  238. insert(0, &cl);
  239. return cl.bp - cl.buf - 1;
  240. }
  241. char *Fmt_string(const char *fmt, ...) {
  242. char *str;
  243. va_list ap;
  244. assert(fmt);
  245. va_start(ap, fmt);
  246. str = Fmt_vstring(fmt, ap);
  247. va_end(ap);
  248. return str;
  249. }
  250. char *Fmt_vstring(const char *fmt, va_list ap) {
  251. struct buf cl;
  252. assert(fmt);
  253. cl.size = 256;
  254. cl.buf = cl.bp = ALLOC(cl.size);
  255. Fmt_vfmt(append, &cl, fmt, ap);
  256. append(0, &cl);
  257. return RESIZE(cl.buf, cl.bp - cl.buf);
  258. }
  259. void Fmt_vfmt(int put(int c, void *cl), void *cl,
  260. const char *fmt, va_list ap) {
  261. assert(put);
  262. assert(fmt);
  263. while (*fmt)
  264. if (*fmt != '%' || *++fmt == '%')
  265. put((unsigned char)*fmt++, cl);
  266. else
  267. {
  268. unsigned char c, flags[256];
  269. int width = INT_MIN, precision = INT_MIN;
  270. memset(flags, '', sizeof flags);
  271. if (Fmt_flags) {
  272. unsigned char c = *fmt;
  273. for ( ; c && strchr(Fmt_flags, c); c = *++fmt) {
  274. assert(flags[c] < 255);
  275. flags[c]++;
  276. }
  277. }
  278. if (*fmt == '*' || isdigit(*fmt)) {
  279. int n;
  280. if (*fmt == '*') {
  281. n = va_arg(ap, int);
  282. assert(n != INT_MIN);
  283. fmt++;
  284. } else
  285. for (n = 0; isdigit(*fmt); fmt++) {
  286. int d = *fmt - '0';
  287. assert(n <= (INT_MAX - d)/10);
  288. n = 10*n + d;
  289. }
  290. width = n;
  291. }
  292. if (*fmt == '.' && (*++fmt == '*' || isdigit(*fmt))) {
  293. int n;
  294. if (*fmt == '*') {
  295. n = va_arg(ap, int);
  296. assert(n != INT_MIN);
  297. fmt++;
  298. } else
  299. for (n = 0; isdigit(*fmt); fmt++) {
  300. int d = *fmt - '0';
  301. assert(n <= (INT_MAX - d)/10);
  302. n = 10*n + d;
  303. }
  304. precision = n;
  305. }
  306. c = *fmt++;
  307. assert(cvt[c]);
  308. (*cvt[c])(c, &ap, put, cl, flags, width, precision);
  309. }
  310. }
  311. T Fmt_register(int code, T newcvt) {
  312. T old;
  313. assert(0 < code
  314. && code < (int)(sizeof (cvt)/sizeof (cvt[0])));
  315. old = cvt[code];
  316. cvt[code] = newcvt;
  317. return old;
  318. }
  319. void Fmt_putd(const char *str, int len,
  320. int put(int c, void *cl), void *cl,
  321. unsigned char flags[], int width, int precision) {
  322. int sign;
  323. assert(str);
  324. assert(len >= 0);
  325. assert(flags);
  326. if (width == INT_MIN)
  327. width = 0;
  328. if (width < 0) {
  329. flags['-'] = 1;
  330. width = -width;
  331. }
  332. if (precision >= 0)
  333. flags['0'] = 0;
  334. if (len > 0 && (*str == '-' || *str == '+')) {
  335. sign = *str++;
  336. len--;
  337. } else if (flags['+'])
  338. sign = '+';
  339. else if (flags[' '])
  340. sign = ' ';
  341. else
  342. sign = 0;
  343. { int n;
  344.   if (precision < 0)
  345.    precision = 1;
  346.   if (len < precision)
  347.    n = precision;
  348.   else if (precision == 0 && len == 1 && str[0] == '0')
  349.    n = 0;
  350.   else
  351.    n = len;
  352.   if (sign)
  353.    n++;
  354.   if (flags['-']) {
  355.    if (sign)
  356. put(sign, cl);
  357.   } else if (flags['0']) {
  358.    if (sign)
  359. put(sign, cl);
  360.    pad(width - n, '0');
  361.   } else {
  362.    pad(width - n, ' ');
  363.    if (sign)
  364. put(sign, cl);
  365.   }
  366.   pad(precision - len, '0');
  367.   {
  368.    int i;
  369.    for (i = 0; i < len; i++)
  370.    put((unsigned char)*str++, cl);
  371.   }
  372.   if (flags['-'])
  373.    pad(width - n, ' '); }
  374. }