print.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. #include "all.h"
  2. #define PTR sizeof(char*)
  3. #define SHORT sizeof(int)
  4. #define INT sizeof(int)
  5. #define LONG sizeof(long)
  6. #define IDIGIT 30
  7. #define MAXCON 30
  8. static int convcount = { 10 };
  9. #define PUT(o, c) if((o)->p < (o)->ep) *(o)->p++ = c
  10. static int noconv(Op*);
  11. static int cconv(Op*);
  12. static int dconv(Op*);
  13. static int hconv(Op*);
  14. static int lconv(Op*);
  15. static int oconv(Op*);
  16. static int sconv(Op*);
  17. static int uconv(Op*);
  18. static int xconv(Op*);
  19. static int percent(Op*);
  20. static
  21. int (*fmtconv[MAXCON])(Op*) =
  22. {
  23. noconv,
  24. cconv, dconv, hconv, lconv,
  25. oconv, sconv, uconv, xconv,
  26. percent,
  27. };
  28. static
  29. char fmtindex[128] =
  30. {
  31. ['c'] 1,
  32. ['d'] 2,
  33. ['h'] 3,
  34. ['l'] 4,
  35. ['o'] 5,
  36. ['s'] 6,
  37. ['u'] 7,
  38. ['x'] 8,
  39. ['%'] 9,
  40. };
  41. int
  42. fmtinstall(char c, int (*f)(Op*))
  43. {
  44. c &= 0177;
  45. if(fmtindex[c] == 0) {
  46. if(convcount >= MAXCON)
  47. return 1;
  48. fmtindex[c] = convcount++;
  49. }
  50. fmtconv[fmtindex[c]] = f;
  51. return 0;
  52. }
  53. char*
  54. doprint(char *p, char *ep, char *fmt, void *argp)
  55. {
  56. int sf1, c;
  57. Op o;
  58. o.p = p;
  59. o.ep = ep;
  60. o.argp = argp;
  61. loop:
  62. c = *fmt++;
  63. if(c != '%') {
  64. if(c == 0) {
  65. if(o.p < o.ep)
  66. *o.p = 0;
  67. return o.p;
  68. }
  69. PUT(&o, c);
  70. goto loop;
  71. }
  72. o.f1 = 0;
  73. o.f2 = -1;
  74. o.f3 = 0;
  75. c = *fmt++;
  76. sf1 = 0;
  77. if(c == '-') {
  78. sf1 = 1;
  79. c = *fmt++;
  80. }
  81. while(c >= '0' && c <= '9') {
  82. o.f1 = o.f1*10 + c-'0';
  83. c = *fmt++;
  84. }
  85. if(sf1)
  86. o.f1 = -o.f1;
  87. if(c != '.')
  88. goto l1;
  89. c = *fmt++;
  90. while(c >= '0' && c <= '9') {
  91. if(o.f2 < 0)
  92. o.f2 = 0;
  93. o.f2 = o.f2*10 + c-'0';
  94. c = *fmt++;
  95. }
  96. l1:
  97. if(c == 0)
  98. fmt--;
  99. c = (*fmtconv[fmtindex[c&0177]])(&o);
  100. if(c < 0) {
  101. o.f3 |= -c;
  102. c = *fmt++;
  103. goto l1;
  104. }
  105. o.argp = (char*)o.argp + c;
  106. goto loop;
  107. }
  108. int
  109. numbconv(Op *op, int base)
  110. {
  111. char b[IDIGIT];
  112. int i, f, n, r;
  113. long v;
  114. short h;
  115. f = 0;
  116. switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
  117. case FLONG:
  118. v = *(long*)op->argp;
  119. r = LONG;
  120. break;
  121. case FUNSIGN|FLONG:
  122. v = *(ulong*)op->argp;
  123. r = LONG;
  124. break;
  125. case FSHORT:
  126. h = *(int*)op->argp;
  127. v = h;
  128. r = SHORT;
  129. break;
  130. case FUNSIGN|FSHORT:
  131. h = *(int*)op->argp;
  132. v = (ushort)h;
  133. r = SHORT;
  134. break;
  135. default:
  136. v = *(int*)op->argp;
  137. r = INT;
  138. break;
  139. case FUNSIGN:
  140. v = *(unsigned*)op->argp;
  141. r = INT;
  142. break;
  143. }
  144. if(!(op->f3 & FUNSIGN) && v < 0) {
  145. v = -v;
  146. f = 1;
  147. }
  148. b[IDIGIT-1] = 0;
  149. for(i = IDIGIT-2;; i--) {
  150. n = (ulong)v % base;
  151. n += '0';
  152. if(n > '9')
  153. n += 'a' - ('9'+1);
  154. b[i] = n;
  155. if(i < 2)
  156. break;
  157. v = (ulong)v / base;
  158. if(op->f2 >= 0 && i >= IDIGIT-op->f2)
  159. continue;
  160. if(v <= 0)
  161. break;
  162. }
  163. sout:
  164. if(f)
  165. b[--i] = '-';
  166. strconv(b+i, op, op->f1, -1);
  167. return r;
  168. }
  169. void
  170. strconv(char *o, Op *op, int f1, int f2)
  171. {
  172. int n, c;
  173. char *p;
  174. n = strlen(o);
  175. if(f1 >= 0)
  176. while(n < f1) {
  177. PUT(op, ' ');
  178. n++;
  179. }
  180. for(p=o; c = *p++;)
  181. if(f2 != 0) {
  182. PUT(op, c);
  183. f2--;
  184. }
  185. if(f1 < 0) {
  186. f1 = -f1;
  187. while(n < f1) {
  188. PUT(op, ' ');
  189. n++;
  190. }
  191. }
  192. }
  193. static int
  194. noconv(Op *op)
  195. {
  196. strconv("***", op, 0, -1);
  197. return 0;
  198. }
  199. static int
  200. cconv(Op *op)
  201. {
  202. char b[2];
  203. b[0] = *(int*)op->argp;
  204. b[1] = 0;
  205. strconv(b, op, op->f1, -1);
  206. return INT;
  207. }
  208. static int
  209. dconv(Op *op)
  210. {
  211. return numbconv(op, 10);
  212. }
  213. static int
  214. hconv(Op *op)
  215. {
  216. USED(op);
  217. return -FSHORT;
  218. }
  219. static int
  220. lconv(Op *op)
  221. {
  222. USED(op);
  223. return -FLONG;
  224. }
  225. static int
  226. oconv(Op *op)
  227. {
  228. USED(op);
  229. return numbconv(op, 8);
  230. }
  231. static int
  232. sconv(Op *op)
  233. {
  234. strconv(*(char**)op->argp, op, op->f1, op->f2);
  235. return PTR;
  236. }
  237. static int
  238. uconv(Op *op)
  239. {
  240. USED(op);
  241. return -FUNSIGN;
  242. }
  243. static int
  244. xconv(Op *op)
  245. {
  246. return numbconv(op, 16);
  247. }
  248. static int
  249. percent(Op *op)
  250. {
  251. PUT(op, '%');
  252. return 0;
  253. }