donprint.c 4.1 KB

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