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