|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: ! 4: enum ! 5: { ! 6: SIZE = 1024, ! 7: IDIGIT = 30, ! 8: MAXCONV = 40, ! 9: FDIGIT = 30, ! 10: FDEFLT = 6, ! 11: NONE = -1000, ! 12: MAXFMT = 512, ! 13: ! 14: FPLUS = (1<<0), ! 15: FMINUS = (1<<1), ! 16: FSHARP = (1<<2), ! 17: FLONG = (1<<3), ! 18: FSHORT = (1<<4), ! 19: FUNSIGN = (1<<5), ! 20: FVLONG = (1<<6), ! 21: }; ! 22: ! 23: #define PTR sizeof(char*) ! 24: #define SHORT sizeof(int) ! 25: #define INT sizeof(int) ! 26: #define LONG sizeof(long) ! 27: #define VLONG sizeof(vlong) ! 28: ! 29: int printcol; ! 30: ! 31: static int convcount; ! 32: static char fmtindex[MAXFMT]; ! 33: ! 34: static int noconv(void*, Fconv*); ! 35: static int flags(void*, Fconv*); ! 36: ! 37: static int cconv(void*, Fconv*); ! 38: static int sconv(void*, Fconv*); ! 39: static int percent(void*, Fconv*); ! 40: ! 41: int numbconv(void*, Fconv*); ! 42: ! 43: static ! 44: int (*fmtconv[MAXCONV])(void*, Fconv*) = ! 45: { ! 46: noconv ! 47: }; ! 48: ! 49: static ! 50: void ! 51: initfmt(void) ! 52: { ! 53: int cc; ! 54: ! 55: cc = 0; ! 56: fmtconv[cc] = noconv; ! 57: cc++; ! 58: ! 59: fmtconv[cc] = flags; ! 60: fmtindex['+'] = cc; ! 61: fmtindex['-'] = cc; ! 62: fmtindex['#'] = cc; ! 63: fmtindex['h'] = cc; ! 64: fmtindex['l'] = cc; ! 65: fmtindex['u'] = cc; ! 66: cc++; ! 67: ! 68: fmtconv[cc] = numbconv; ! 69: fmtindex['d'] = cc; ! 70: fmtindex['o'] = cc; ! 71: fmtindex['x'] = cc; ! 72: fmtindex['X'] = cc; ! 73: cc++; ! 74: ! 75: fmtconv[cc] = cconv; ! 76: fmtindex['c'] = cc; ! 77: fmtindex['C'] = cc; ! 78: cc++; ! 79: ! 80: fmtconv[cc] = sconv; ! 81: fmtindex['s'] = cc; ! 82: fmtindex['S'] = cc; ! 83: cc++; ! 84: ! 85: fmtconv[cc] = percent; ! 86: fmtindex['%'] = cc; ! 87: cc++; ! 88: ! 89: convcount = cc; ! 90: } ! 91: ! 92: int ! 93: fmtinstall(int c, int (*f)(void*, Fconv*)) ! 94: { ! 95: ! 96: if(convcount == 0) ! 97: initfmt(); ! 98: if(c < 0 || c >= MAXFMT) ! 99: return 1; ! 100: if(convcount >= MAXCONV) ! 101: return 1; ! 102: fmtconv[convcount] = f; ! 103: fmtindex[c] = convcount; ! 104: convcount++; ! 105: return 0; ! 106: } ! 107: ! 108: char* ! 109: doprint(char *s, char *es, char *fmt, void *argp) ! 110: { ! 111: int n, c; ! 112: Rune rune; ! 113: Fconv local; ! 114: ! 115: local.out = s; ! 116: local.eout = es-4; /* room for multi-byte character and 0 */ ! 117: ! 118: loop: ! 119: c = *fmt & 0xff; ! 120: if(c >= Runeself) { ! 121: n = chartorune(&rune, fmt); ! 122: fmt += n; ! 123: c = rune; ! 124: } else ! 125: fmt++; ! 126: switch(c) { ! 127: case 0: ! 128: *local.out = 0; ! 129: return local.out; ! 130: ! 131: default: ! 132: printcol++; ! 133: goto common; ! 134: ! 135: case '\n': ! 136: printcol = 0; ! 137: goto common; ! 138: ! 139: case '\t': ! 140: printcol = (printcol+8) & ~7; ! 141: goto common; ! 142: ! 143: common: ! 144: if(local.out < local.eout) ! 145: if(c >= Runeself) { ! 146: rune = c; ! 147: n = runetochar(local.out, &rune); /* BUG */ ! 148: local.out += n; ! 149: } else ! 150: *local.out++ = c; ! 151: goto loop; ! 152: ! 153: case '%': ! 154: break; ! 155: } ! 156: local.f1 = NONE; ! 157: local.f2 = NONE; ! 158: local.f3 = 0; ! 159: ! 160: /* ! 161: * read one of the following ! 162: * 1. number, => f1, f2 in order. ! 163: * 2. '*' same as number (from args) ! 164: * 3. '.' ignored (separates numbers) ! 165: * 4. flag => f3 ! 166: * 5. verb and terminate ! 167: */ ! 168: l0: ! 169: c = *fmt & 0xff; ! 170: if(c >= Runeself) { ! 171: n = chartorune(&rune, fmt); ! 172: fmt += n; ! 173: c = rune; ! 174: } else ! 175: fmt++; ! 176: ! 177: l1: ! 178: if(c == 0) { ! 179: fmt--; ! 180: goto loop; ! 181: } ! 182: if(c == '.') { ! 183: if(local.f1 == NONE) ! 184: local.f1 = 0; ! 185: local.f2 = 0; ! 186: goto l0; ! 187: } ! 188: if((c >= '1' && c <= '9') || ! 189: (c == '0' && local.f1 != NONE)) { /* '0' is a digit for f2 */ ! 190: n = 0; ! 191: while(c >= '0' && c <= '9') { ! 192: n = n*10 + c-'0'; ! 193: c = *fmt++; ! 194: } ! 195: if(local.f1 == NONE) ! 196: local.f1 = n; ! 197: else ! 198: local.f2 = n; ! 199: goto l1; ! 200: } ! 201: if(c == '*') { ! 202: n = *(int*)argp; ! 203: argp = (char*)argp + INT; ! 204: if(local.f1 == NONE) ! 205: local.f1 = n; ! 206: else ! 207: local.f2 = n; ! 208: goto l0; ! 209: } ! 210: n = 0; ! 211: if(c >= 0 && c < MAXFMT) ! 212: n = fmtindex[c]; ! 213: local.chr = c; ! 214: n = (*fmtconv[n])(argp, &local); ! 215: if(n < 0) { ! 216: local.f3 |= -n; ! 217: goto l0; ! 218: } ! 219: argp = (char*)argp + n; ! 220: goto loop; ! 221: } ! 222: ! 223: int ! 224: numbconv(void *o, Fconv *fp) ! 225: { ! 226: char s[IDIGIT]; ! 227: int i, f, n, r, b, ucase; ! 228: short h; ! 229: long v; ! 230: vlong vl; ! 231: ! 232: SET(v); ! 233: SET(vl); ! 234: ! 235: ucase = 0; ! 236: b = fp->chr; ! 237: switch(fp->chr) { ! 238: case 'u': ! 239: fp->f3 |= FUNSIGN; ! 240: case 'd': ! 241: b = 10; ! 242: break; ! 243: ! 244: case 'o': ! 245: b = 8; ! 246: break; ! 247: ! 248: case 'X': ! 249: ucase = 1; ! 250: case 'x': ! 251: b = 16; ! 252: break; ! 253: } ! 254: ! 255: f = 0; ! 256: switch(fp->f3 & (FVLONG|FLONG|FSHORT|FUNSIGN)) { ! 257: case FVLONG|FLONG: ! 258: vl = *(vlong*)o; ! 259: r = VLONG; ! 260: break; ! 261: ! 262: case FLONG: ! 263: v = *(long*)o; ! 264: r = LONG; ! 265: break; ! 266: ! 267: case FUNSIGN|FLONG: ! 268: v = *(ulong*)o; ! 269: r = LONG; ! 270: break; ! 271: ! 272: case FSHORT: ! 273: h = *(int*)o; ! 274: v = h; ! 275: r = SHORT; ! 276: break; ! 277: ! 278: case FUNSIGN|FSHORT: ! 279: h = *(int*)o; ! 280: v = (ushort)h; ! 281: r = SHORT; ! 282: break; ! 283: ! 284: default: ! 285: v = *(int*)o; ! 286: r = INT; ! 287: break; ! 288: ! 289: case FUNSIGN: ! 290: v = *(unsigned*)o; ! 291: r = INT; ! 292: break; ! 293: } ! 294: if(!(fp->f3 & FUNSIGN) && v < 0) { ! 295: v = -v; ! 296: f = 1; ! 297: } ! 298: s[IDIGIT-1] = 0; ! 299: for(i = IDIGIT-2;; i--) { ! 300: if(fp->f3 & FVLONG) ! 301: n = vl % b; ! 302: else ! 303: n = (ulong)v % b; ! 304: n += '0'; ! 305: if(n > '9') { ! 306: n += 'a' - ('9'+1); ! 307: if(ucase) ! 308: n += 'A'-'a'; ! 309: } ! 310: s[i] = n; ! 311: if(i < 2) ! 312: break; ! 313: if(fp->f3 & FVLONG) ! 314: vl = vl / b; ! 315: else ! 316: v = (ulong)v / b; ! 317: if(fp->f2 != NONE && i >= IDIGIT-fp->f2) ! 318: continue; ! 319: if(fp->f3 & FVLONG) ! 320: if(vl <= 0) ! 321: break; ! 322: if(v <= 0) ! 323: break; ! 324: } ! 325: if(fp->f3 & FSHARP) ! 326: if(s[i] != '0') { ! 327: if(b == 8) ! 328: s[--i] = '0'; ! 329: else ! 330: if(b == 16) { ! 331: if(ucase) ! 332: s[--i] = 'X'; ! 333: else ! 334: s[--i] = 'x'; ! 335: s[--i] = '0'; ! 336: } ! 337: } ! 338: if(f) ! 339: s[--i] = '-'; ! 340: fp->f2 = NONE; ! 341: strconv(s+i, fp); ! 342: return r; ! 343: } ! 344: ! 345: void ! 346: Strconv(Rune *s, Fconv *fp) ! 347: { ! 348: int n, c, i; ! 349: Rune rune; ! 350: ! 351: if(fp->f3 & FMINUS) ! 352: fp->f1 = -fp->f1; ! 353: n = 0; ! 354: if(fp->f1 != NONE && fp->f1 >= 0) { ! 355: for(; s[n]; n++) ! 356: ; ! 357: while(n < fp->f1) { ! 358: if(fp->out < fp->eout) ! 359: *fp->out++ = ' '; ! 360: printcol++; ! 361: n++; ! 362: } ! 363: } ! 364: for(;;) { ! 365: c = *s++; ! 366: if(c == 0) ! 367: break; ! 368: n++; ! 369: if(fp->f2 == NONE || fp->f2 > 0) { ! 370: if(fp->out < fp->eout) ! 371: if(c >= Runeself) { ! 372: rune = c; ! 373: i = runetochar(fp->out, &rune); ! 374: fp->out += i; ! 375: } else ! 376: *fp->out++ = c; ! 377: if(fp->f2 != NONE) ! 378: fp->f2--; ! 379: switch(c) { ! 380: default: ! 381: printcol++; ! 382: break; ! 383: case '\n': ! 384: printcol = 0; ! 385: break; ! 386: case '\t': ! 387: printcol = (printcol+8) & ~7; ! 388: break; ! 389: } ! 390: } ! 391: } ! 392: if(fp->f1 != NONE && fp->f1 < 0) { ! 393: fp->f1 = -fp->f1; ! 394: while(n < fp->f1) { ! 395: if(fp->out < fp->eout) ! 396: *fp->out++ = ' '; ! 397: printcol++; ! 398: n++; ! 399: } ! 400: } ! 401: } ! 402: ! 403: void ! 404: strconv(char *s, Fconv *fp) ! 405: { ! 406: int n, c, i; ! 407: Rune rune; ! 408: ! 409: if(fp->f3 & FMINUS) ! 410: fp->f1 = -fp->f1; ! 411: n = 0; ! 412: if(fp->f1 != NONE && fp->f1 >= 0) { ! 413: n = utflen(s); ! 414: while(n < fp->f1) { ! 415: if(fp->out < fp->eout) ! 416: *fp->out++ = ' '; ! 417: printcol++; ! 418: n++; ! 419: } ! 420: } ! 421: for(;;) { ! 422: c = *s & 0xff; ! 423: if(c >= Runeself) { ! 424: i = chartorune(&rune, s); ! 425: s += i; ! 426: c = rune; ! 427: } else ! 428: s++; ! 429: if(c == 0) ! 430: break; ! 431: n++; ! 432: if(fp->f2 == NONE || fp->f2 > 0) { ! 433: if(fp->out < fp->eout) ! 434: if(c >= Runeself) { ! 435: rune = c; ! 436: i = runetochar(fp->out, &rune); ! 437: fp->out += i; ! 438: } else ! 439: *fp->out++ = c; ! 440: if(fp->f2 != NONE) ! 441: fp->f2--; ! 442: switch(c) { ! 443: default: ! 444: printcol++; ! 445: break; ! 446: case '\n': ! 447: printcol = 0; ! 448: break; ! 449: case '\t': ! 450: printcol = (printcol+8) & ~7; ! 451: break; ! 452: } ! 453: } ! 454: } ! 455: if(fp->f1 != NONE && fp->f1 < 0) { ! 456: fp->f1 = -fp->f1; ! 457: while(n < fp->f1) { ! 458: if(fp->out < fp->eout) ! 459: *fp->out++ = ' '; ! 460: printcol++; ! 461: n++; ! 462: } ! 463: } ! 464: } ! 465: ! 466: static ! 467: int ! 468: noconv(void *o, Fconv *fp) ! 469: { ! 470: int n; ! 471: char s[10]; ! 472: ! 473: if(convcount == 0) { ! 474: initfmt(); ! 475: n = 0; ! 476: if(fp->chr >= 0 && fp->chr < MAXFMT) ! 477: n = fmtindex[fp->chr]; ! 478: return (*fmtconv[n])(o, fp); ! 479: } ! 480: sprint(s, "*%c*", fp->chr); ! 481: fp->f1 = 0; ! 482: fp->f2 = NONE; ! 483: fp->f3 = 0; ! 484: strconv(s, fp); ! 485: return 0; ! 486: } ! 487: ! 488: static ! 489: int ! 490: cconv(void *o, Fconv *fp) ! 491: { ! 492: char s[10]; ! 493: Rune rune; ! 494: ! 495: rune = *(int*)o; ! 496: if(fp->chr == 'c') ! 497: rune &= 0xff; ! 498: s[runetochar(s, &rune)] = 0; ! 499: ! 500: fp->f2 = NONE; ! 501: strconv(s, fp); ! 502: return INT; ! 503: } ! 504: ! 505: static ! 506: int ! 507: sconv(void *o, Fconv *fp) ! 508: { ! 509: char *s; ! 510: Rune *r; ! 511: ! 512: if(fp->chr == 's') { ! 513: s = *(char**)o; ! 514: if(s == 0) ! 515: s = "<null>"; ! 516: strconv(s, fp); ! 517: } else { ! 518: r = *(Rune**)o; ! 519: if(r == 0) ! 520: r = L"<null>"; ! 521: Strconv(r, fp); ! 522: } ! 523: return PTR; ! 524: } ! 525: ! 526: static ! 527: int ! 528: percent(void *o, Fconv *fp) ! 529: { ! 530: ! 531: USED(o); ! 532: if(fp->out < fp->eout) ! 533: *fp->out++ = '%'; ! 534: return 0; ! 535: } ! 536: ! 537: static ! 538: int ! 539: flags(void *o, Fconv *fp) ! 540: { ! 541: int f; ! 542: ! 543: USED(o); ! 544: ! 545: f = 0; ! 546: switch(fp->chr) { ! 547: case '+': ! 548: f = FPLUS; ! 549: break; ! 550: ! 551: case '-': ! 552: f = FMINUS; ! 553: break; ! 554: ! 555: case '#': ! 556: f = FSHARP; ! 557: break; ! 558: ! 559: case 'h': ! 560: f = FSHORT; ! 561: break; ! 562: ! 563: case 'l': ! 564: f = FLONG; ! 565: if(fp->f3 & FLONG) ! 566: f = FVLONG; ! 567: break; ! 568: ! 569: case 'u': ! 570: f = FUNSIGN; ! 571: break; ! 572: } ! 573: return -f; ! 574: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.