donprint.c 4.0 KB

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