dofmt.c (11644B)
1 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ 2 /* Copyright (c) 2004 Google Inc.; see LICENSE */ 3 4 #include "fmt.h" 5 #include "fmtdef.h" 6 #include "plan9.h" 7 8 #include <stdarg.h> 9 #include <string.h> 10 11 /* format the output into f->to and return the number of characters fmted */ 12 int dofmt(Fmt* f, char* fmt) { 13 Rune rune, *rt, *rs; 14 int r; 15 char *t, *s; 16 int n, nfmt; 17 18 nfmt = f->nfmt; 19 for (;;) { 20 if (f->runes) { 21 rt = (Rune*) f->to; 22 rs = (Rune*) f->stop; 23 while ((r = *(uchar*) fmt) && r != '%') { 24 if (r < Runeself) 25 fmt++; 26 else { 27 fmt += chartorune(&rune, fmt); 28 r = rune; 29 } 30 FMTRCHAR(f, rt, rs, r); 31 } 32 fmt++; 33 f->nfmt += rt - (Rune*) f->to; 34 f->to = rt; 35 if (!r) 36 return f->nfmt - nfmt; 37 f->stop = rs; 38 } else { 39 t = (char*) f->to; 40 s = (char*) f->stop; 41 while ((r = *(uchar*) fmt) && r != '%') { 42 if (r < Runeself) { 43 FMTCHAR(f, t, s, r); 44 fmt++; 45 } else { 46 n = chartorune(&rune, fmt); 47 if (t + n > s) { 48 t = (char*) __fmtflush(f, t, n); 49 if (t != nil) 50 s = (char*) f->stop; 51 else 52 return -1; 53 } 54 while (n--) 55 *t++ = *fmt++; 56 } 57 } 58 fmt++; 59 f->nfmt += t - (char*) f->to; 60 f->to = t; 61 if (!r) 62 return f->nfmt - nfmt; 63 f->stop = s; 64 } 65 66 fmt = (char*) __fmtdispatch(f, fmt, 0); 67 if (fmt == nil) 68 return -1; 69 } 70 } 71 72 void* __fmtflush(Fmt* f, void* t, int len) { 73 if (f->runes) 74 f->nfmt += (Rune*) t - (Rune*) f->to; 75 else 76 f->nfmt += (char*) t - (char*) f->to; 77 f->to = t; 78 if (f->flush == 0 || (*f->flush)(f) == 0 || (char*) f->to + len > (char*) f->stop) { 79 f->stop = f->to; 80 return nil; 81 } 82 return f->to; 83 } 84 85 /* 86 * put a formatted block of memory sz bytes long of n runes into the output buffer, 87 * left/right justified in a field of at least f->width characters (if FmtWidth is set) 88 */ 89 int __fmtpad(Fmt* f, int n) { 90 char *t, *s; 91 int i; 92 93 t = (char*) f->to; 94 s = (char*) f->stop; 95 for (i = 0; i < n; i++) 96 FMTCHAR(f, t, s, ' '); 97 f->nfmt += t - (char*) f->to; 98 f->to = t; 99 return 0; 100 } 101 102 int __rfmtpad(Fmt* f, int n) { 103 Rune *t, *s; 104 int i; 105 106 t = (Rune*) f->to; 107 s = (Rune*) f->stop; 108 for (i = 0; i < n; i++) 109 FMTRCHAR(f, t, s, ' '); 110 f->nfmt += t - (Rune*) f->to; 111 f->to = t; 112 return 0; 113 } 114 115 int __fmtcpy(Fmt* f, const void* vm, int n, int sz) { 116 Rune *rt, *rs, r; 117 char *t, *s, *m, *me; 118 ulong fl; 119 int nc, w; 120 121 m = (char*) vm; 122 me = m + sz; 123 fl = f->flags; 124 w = 0; 125 if (fl & FmtWidth) 126 w = f->width; 127 if ((fl & FmtPrec) && n > f->prec) 128 n = f->prec; 129 if (f->runes) { 130 if (!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0) 131 return -1; 132 rt = (Rune*) f->to; 133 rs = (Rune*) f->stop; 134 for (nc = n; nc > 0; nc--) { 135 r = *(uchar*) m; 136 if (r < Runeself) 137 m++; 138 else if ((me - m) >= UTFmax || fullrune(m, me - m)) 139 m += chartorune(&r, m); 140 else 141 break; 142 FMTRCHAR(f, rt, rs, r); 143 } 144 f->nfmt += rt - (Rune*) f->to; 145 f->to = rt; 146 if (fl & FmtLeft && __rfmtpad(f, w - n) < 0) 147 return -1; 148 } else { 149 if (!(fl & FmtLeft) && __fmtpad(f, w - n) < 0) 150 return -1; 151 t = (char*) f->to; 152 s = (char*) f->stop; 153 for (nc = n; nc > 0; nc--) { 154 r = *(uchar*) m; 155 if (r < Runeself) 156 m++; 157 else if ((me - m) >= UTFmax || fullrune(m, me - m)) 158 m += chartorune(&r, m); 159 else 160 break; 161 FMTRUNE(f, t, s, r); 162 } 163 f->nfmt += t - (char*) f->to; 164 f->to = t; 165 if (fl & FmtLeft && __fmtpad(f, w - n) < 0) 166 return -1; 167 } 168 return 0; 169 } 170 171 int __fmtrcpy(Fmt* f, const void* vm, int n) { 172 Rune r, *m, *me, *rt, *rs; 173 char *t, *s; 174 ulong fl; 175 int w; 176 177 m = (Rune*) vm; 178 fl = f->flags; 179 w = 0; 180 if (fl & FmtWidth) 181 w = f->width; 182 if ((fl & FmtPrec) && n > f->prec) 183 n = f->prec; 184 if (f->runes) { 185 if (!(fl & FmtLeft) && __rfmtpad(f, w - n) < 0) 186 return -1; 187 rt = (Rune*) f->to; 188 rs = (Rune*) f->stop; 189 for (me = m + n; m < me; m++) 190 FMTRCHAR(f, rt, rs, *m); 191 f->nfmt += rt - (Rune*) f->to; 192 f->to = rt; 193 if (fl & FmtLeft && __rfmtpad(f, w - n) < 0) 194 return -1; 195 } else { 196 if (!(fl & FmtLeft) && __fmtpad(f, w - n) < 0) 197 return -1; 198 t = (char*) f->to; 199 s = (char*) f->stop; 200 for (me = m + n; m < me; m++) { 201 r = *m; 202 FMTRUNE(f, t, s, r); 203 } 204 f->nfmt += t - (char*) f->to; 205 f->to = t; 206 if (fl & FmtLeft && __fmtpad(f, w - n) < 0) 207 return -1; 208 } 209 return 0; 210 } 211 212 /* fmt out one character */ 213 int __charfmt(Fmt* f) { 214 char x[1]; 215 216 x[0] = va_arg(f->args, int); 217 f->prec = 1; 218 return __fmtcpy(f, (const char*) x, 1, 1); 219 } 220 221 /* fmt out one rune */ 222 int __runefmt(Fmt* f) { 223 Rune x[1]; 224 225 x[0] = va_arg(f->args, int); 226 return __fmtrcpy(f, (const void*) x, 1); 227 } 228 229 /* public helper routine: fmt out a null terminated string already in hand */ 230 int fmtstrcpy(Fmt* f, char* s) { 231 int i, j; 232 233 if (!s) 234 return __fmtcpy(f, "<nil>", 5, 5); 235 /* if precision is specified, make sure we don't wander off the end */ 236 if (f->flags & FmtPrec) { 237 #ifdef PLAN9PORT 238 Rune r; 239 i = 0; 240 for (j = 0; j < f->prec && s[i]; j++) 241 i += chartorune(&r, s + i); 242 #else 243 /* ANSI requires precision in bytes, not Runes */ 244 for (i = 0; i < f->prec; i++) 245 if (s[i] == 0) 246 break; 247 j = utfnlen(s, i); /* won't print partial at end */ 248 #endif 249 return __fmtcpy(f, s, j, i); 250 } 251 return __fmtcpy(f, s, utflen(s), strlen(s)); 252 } 253 254 /* fmt out a null terminated utf string */ 255 int __strfmt(Fmt* f) { 256 char* s; 257 258 s = va_arg(f->args, char*); 259 return fmtstrcpy(f, s); 260 } 261 262 /* public helper routine: fmt out a null terminated rune string already in hand */ 263 int fmtrunestrcpy(Fmt* f, Rune* s) { 264 Rune* e; 265 int n, p; 266 267 if (!s) 268 return __fmtcpy(f, "<nil>", 5, 5); 269 /* if precision is specified, make sure we don't wander off the end */ 270 if (f->flags & FmtPrec) { 271 p = f->prec; 272 for (n = 0; n < p; n++) 273 if (s[n] == 0) 274 break; 275 } else { 276 for (e = s; *e; e++) 277 ; 278 n = e - s; 279 } 280 return __fmtrcpy(f, s, n); 281 } 282 283 /* fmt out a null terminated rune string */ 284 int __runesfmt(Fmt* f) { 285 Rune* s; 286 287 s = va_arg(f->args, Rune*); 288 return fmtrunestrcpy(f, s); 289 } 290 291 /* fmt a % */ 292 int __percentfmt(Fmt* f) { 293 Rune x[1]; 294 295 x[0] = f->r; 296 f->prec = 1; 297 return __fmtrcpy(f, (const void*) x, 1); 298 } 299 300 /* fmt an integer */ 301 int __ifmt(Fmt* f) { 302 char buf[140], *p, *conv; 303 /* 140: for 64 bits of binary + 3-byte sep every 4 digits */ 304 uvlong vu; 305 ulong u; 306 int neg, base, i, n, fl, w, isv; 307 int ndig, len, excess, bytelen; 308 char* grouping; 309 char* thousands; 310 311 neg = 0; 312 fl = f->flags; 313 isv = 0; 314 vu = 0; 315 u = 0; 316 #ifndef PLAN9PORT 317 /* 318 * Unsigned verbs for ANSI C 319 */ 320 switch (f->r) { 321 case 'o': 322 case 'p': 323 case 'u': 324 case 'x': 325 case 'X': 326 fl |= FmtUnsigned; 327 fl &= ~(FmtSign | FmtSpace); 328 break; 329 } 330 #endif 331 if (f->r == 'p') { 332 u = (ulong) va_arg(f->args, void*); 333 f->r = 'x'; 334 fl |= FmtUnsigned; 335 } else if (fl & FmtVLong) { 336 isv = 1; 337 if (fl & FmtUnsigned) 338 vu = va_arg(f->args, uvlong); 339 else 340 vu = va_arg(f->args, vlong); 341 } else if (fl & FmtLong) { 342 if (fl & FmtUnsigned) 343 u = va_arg(f->args, ulong); 344 else 345 u = va_arg(f->args, long); 346 } else if (fl & FmtByte) { 347 if (fl & FmtUnsigned) 348 u = (uchar) va_arg(f->args, int); 349 else 350 u = (char) va_arg(f->args, int); 351 } else if (fl & FmtShort) { 352 if (fl & FmtUnsigned) 353 u = (ushort) va_arg(f->args, int); 354 else 355 u = (short) va_arg(f->args, int); 356 } else { 357 if (fl & FmtUnsigned) 358 u = va_arg(f->args, uint); 359 else 360 u = va_arg(f->args, int); 361 } 362 conv = "0123456789abcdef"; 363 grouping = "\4"; /* for hex, octal etc. (undefined by spec but nice) */ 364 thousands = f->thousands; 365 switch (f->r) { 366 case 'd': 367 case 'i': 368 case 'u': 369 base = 10; 370 grouping = f->grouping; 371 break; 372 case 'X': 373 conv = "0123456789ABCDEF"; 374 /* fall through */ 375 case 'x': 376 base = 16; 377 thousands = ":"; 378 break; 379 case 'b': 380 base = 2; 381 thousands = ":"; 382 break; 383 case 'o': 384 base = 8; 385 break; 386 default: 387 return -1; 388 } 389 if (!(fl & FmtUnsigned)) { 390 if (isv && (vlong) vu < 0) { 391 vu = -(vlong) vu; 392 neg = 1; 393 } else if (!isv && (long) u < 0) { 394 u = -(long) u; 395 neg = 1; 396 } 397 } 398 p = buf + sizeof buf - 1; 399 n = 0; /* in runes */ 400 excess = 0; /* number of bytes > number runes */ 401 ndig = 0; 402 len = utflen(thousands); 403 bytelen = strlen(thousands); 404 if (isv) { 405 while (vu) { 406 i = vu % base; 407 vu /= base; 408 if ((fl & FmtComma) && n % 4 == 3) { 409 *p-- = ','; 410 n++; 411 } 412 if ((fl & FmtApost) && __needsep(&ndig, &grouping)) { 413 n += len; 414 excess += bytelen - len; 415 p -= bytelen; 416 memmove(p + 1, thousands, bytelen); 417 } 418 *p-- = conv[i]; 419 n++; 420 } 421 } else { 422 while (u) { 423 i = u % base; 424 u /= base; 425 if ((fl & FmtComma) && n % 4 == 3) { 426 *p-- = ','; 427 n++; 428 } 429 if ((fl & FmtApost) && __needsep(&ndig, &grouping)) { 430 n += len; 431 excess += bytelen - len; 432 p -= bytelen; 433 memmove(p + 1, thousands, bytelen); 434 } 435 *p-- = conv[i]; 436 n++; 437 } 438 } 439 if (n == 0) { 440 /* 441 * "The result of converting a zero value with 442 * a precision of zero is no characters." - ANSI 443 * 444 * "For o conversion, # increases the precision, if and only if 445 * necessary, to force the first digit of the result to be a zero 446 * (if the value and precision are both 0, a single 0 is printed)." - ANSI 447 */ 448 if (!(fl & FmtPrec) || f->prec != 0 || (f->r == 'o' && (fl & FmtSharp))) { 449 *p-- = '0'; 450 n = 1; 451 if (fl & FmtApost) 452 __needsep(&ndig, &grouping); 453 } 454 455 /* 456 * Zero values don't get 0x. 457 */ 458 if (f->r == 'x' || f->r == 'X') 459 fl &= ~FmtSharp; 460 } 461 for (w = f->prec; n < w && p > buf + 3; n++) { 462 if ((fl & FmtApost) && __needsep(&ndig, &grouping)) { 463 n += len; 464 excess += bytelen - len; 465 p -= bytelen; 466 memmove(p + 1, thousands, bytelen); 467 } 468 *p-- = '0'; 469 } 470 if (neg || (fl & (FmtSign | FmtSpace))) 471 n++; 472 if (fl & FmtSharp) { 473 if (base == 16) 474 n += 2; 475 else if (base == 8) { 476 if (p[1] == '0') 477 fl &= ~FmtSharp; 478 else 479 n++; 480 } 481 } 482 if ((fl & FmtZero) && !(fl & (FmtLeft | FmtPrec))) { 483 w = 0; 484 if (fl & FmtWidth) 485 w = f->width; 486 for (; n < w && p > buf + 3; n++) { 487 if ((fl & FmtApost) && __needsep(&ndig, &grouping)) { 488 n += len; 489 excess += bytelen - len; 490 p -= bytelen; 491 memmove(p + 1, thousands, bytelen); 492 } 493 *p-- = '0'; 494 } 495 f->flags &= ~FmtWidth; 496 } 497 if (fl & FmtSharp) { 498 if (base == 16) 499 *p-- = f->r; 500 if (base == 16 || base == 8) 501 *p-- = '0'; 502 } 503 if (neg) 504 *p-- = '-'; 505 else if (fl & FmtSign) 506 *p-- = '+'; 507 else if (fl & FmtSpace) 508 *p-- = ' '; 509 f->flags &= ~FmtPrec; 510 return __fmtcpy(f, p + 1, n, n + excess); 511 } 512 513 int __countfmt(Fmt* f) { 514 void* p; 515 ulong fl; 516 517 fl = f->flags; 518 p = va_arg(f->args, void*); 519 if (fl & FmtVLong) { 520 *(vlong*) p = f->nfmt; 521 } else if (fl & FmtLong) { 522 *(long*) p = f->nfmt; 523 } else if (fl & FmtByte) { 524 *(char*) p = f->nfmt; 525 } else if (fl & FmtShort) { 526 *(short*) p = f->nfmt; 527 } else { 528 *(int*) p = f->nfmt; 529 } 530 return 0; 531 } 532 533 int __flagfmt(Fmt* f) { 534 switch (f->r) { 535 case ',': 536 f->flags |= FmtComma; 537 break; 538 case '-': 539 f->flags |= FmtLeft; 540 break; 541 case '+': 542 f->flags |= FmtSign; 543 break; 544 case '#': 545 f->flags |= FmtSharp; 546 break; 547 case '\'': 548 f->flags |= FmtApost; 549 break; 550 case ' ': 551 f->flags |= FmtSpace; 552 break; 553 case 'u': 554 f->flags |= FmtUnsigned; 555 break; 556 case 'h': 557 if (f->flags & FmtShort) 558 f->flags |= FmtByte; 559 f->flags |= FmtShort; 560 break; 561 case 'L': 562 f->flags |= FmtLDouble; 563 break; 564 case 'l': 565 if (f->flags & FmtLong) 566 f->flags |= FmtVLong; 567 f->flags |= FmtLong; 568 break; 569 } 570 return 1; 571 } 572 573 /* default error format */ 574 int __badfmt(Fmt* f) { 575 char x[2 + UTFmax]; 576 int n; 577 578 x[0] = '%'; 579 n = 1 + runetochar(x + 1, &f->r); 580 x[n++] = '%'; 581 f->prec = n; 582 __fmtcpy(f, (const void*) x, n, n); 583 return 0; 584 }