1 /* 2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7 /* All Rights Reserved */ 8 9 /* 10 * Copyright (c) 1980 Regents of the University of California. 11 * All rights reserved. The Berkeley Software License Agreement 12 * specifies the terms and conditions for redistribution. 13 */ 14 15 /* 16 * Hacked "printf" which prints through putbyte and Putchar. 17 * putbyte() is used to send a pure byte, which might be a part 18 * of a mutlibyte character, mainly for %s. A control character 19 * for putbyte() may be QUOTE'd meaning not to convert it to ^x 20 * sequence. In all other cases Putchar() is used to send a character 21 * in tchar (== wchar_t + * optional QUOE.) 22 * DONT USE WITH STDIO! 23 * This printf has been hacked again so that it understands tchar string 24 * when the format specifier %t is used. Also %c has been expanded 25 * to take a tchar character as well as normal int. 26 * %t is supported in its simplest form; no width or precision will 27 * be understood. 28 * Assumption here is that sizeof(tchar)<=sizeof(int) so that tchar is 29 * passed as int. Otherwise, %T must be specified instead of %c to 30 * print a character in tchar. 31 */ 32 33 #include <stdarg.h> 34 #include <values.h> 35 #include "sh.h" /* For tchar. */ 36 37 #define HIBITLL (1ULL << 63) 38 39 void _print(char *format, va_list *args); 40 41 static char *p; 42 43 int 44 printf(const char *format, ...) 45 { 46 va_list stupid; 47 48 p = (char *)gettext(format); 49 va_start(stupid, format); 50 _print(p, &stupid); 51 va_end(stupid); 52 53 return (0); 54 } 55 56 /* 57 * Floating-point code is included or not, depending 58 * on whether the preprocessor variable FLOAT is 1 or 0. 59 */ 60 61 /* Maximum number of digits in any integer (long) representation */ 62 #define MAXDIGS 20 63 64 /* Convert a digit character to the corresponding number */ 65 #define tonumber(x) ((x) - '0') 66 67 /* Convert a number between 0 and 9 to the corresponding digit */ 68 #define todigit(x) ((x) + '0') 69 70 /* Maximum total number of digits in E format */ 71 #define MAXECVT 17 72 73 /* Maximum number of digits after decimal point in F format */ 74 #define MAXFCVT 60 75 76 /* Maximum significant figures in a floating-point number */ 77 #define MAXFSIG 17 78 79 /* Maximum number of characters in an exponent */ 80 #define MAXESIZ 4 81 82 /* Maximum (positive) exponent or greater */ 83 #define MAXEXP 40 84 85 86 87 #define max(a, b) ((a) > (b) ? (a) : (b)) 88 #define min(a, b) ((a) < (b) ? (a) : (b)) 89 90 /* If this symbol is nonzero, allow '0' as a flag */ 91 #define FZERO 1 92 93 #if FLOAT 94 /* 95 * System-supplied routines for floating conversion 96 */ 97 char *fcvt(); 98 char *ecvt(); 99 #endif 100 101 void 102 _print(char *format, va_list *args) 103 { 104 /* Current position in format */ 105 char *cp; 106 107 /* Starting and ending points for value to be printed */ 108 char *bp, *p; 109 tchar *tbp, *tep; /* For "%t". */ 110 tchar tcbuf[2]; /* For "%c" or "%T". */ 111 112 /* Field width and precision */ 113 int width, prec; 114 115 /* Format code */ 116 char fcode; 117 118 /* Number of padding zeroes required on the left */ 119 int lzero; 120 121 /* Flags - nonzero if corresponding character appears in format */ 122 bool length; /* l */ 123 bool double_length; /* ll */ 124 bool fplus; /* + */ 125 bool fminus; /* - */ 126 bool fblank; /* blank */ 127 bool fsharp; /* # */ 128 #if FZERO 129 bool fzero; /* 0 */ 130 #endif 131 132 /* Pointer to sign, "0x", "0X", or empty */ 133 char *prefix; 134 #if FLOAT 135 /* Exponent or empty */ 136 char *suffix; 137 138 /* Buffer to create exponent */ 139 char expbuf[MAXESIZ + 1]; 140 141 /* Number of padding zeroes required on the right */ 142 int rzero; 143 144 /* The value being converted, if real */ 145 double dval; 146 147 /* Output values from fcvt and ecvt */ 148 int decpt, sign; 149 150 /* Scratch */ 151 int k; 152 153 /* Values are developed in this buffer */ 154 char buf[max(MAXDIGS, max(MAXFCVT + DMAXEXP, MAXECVT) + 1)]; 155 #else 156 char buf[MAXDIGS]; 157 #endif 158 /* The value being converted, if integer */ 159 long long val; 160 161 /* Set to point to a translate table for digits of whatever radix */ 162 char *tab; 163 164 /* Work variables */ 165 int n, hradix, lowbit; 166 167 cp = format; 168 169 /* 170 * The main loop -- this loop goes through one iteration 171 * for each ordinary character or format specification. 172 */ 173 while (*cp) 174 if (*cp != '%') { 175 /* Ordinary (non-%) character */ 176 putbyte (*cp++); 177 } else { 178 /* 179 * % has been found. 180 * First, parse the format specification. 181 */ 182 183 /* Scan the <flags> */ 184 fplus = fminus = fblank = fsharp = 0; 185 #if FZERO 186 fzero = 0; 187 #endif 188 scan: 189 switch (*++cp) { 190 case '+': 191 fplus = 1; 192 goto scan; 193 case '-': 194 fminus = 1; 195 goto scan; 196 case ' ': 197 fblank = 1; 198 goto scan; 199 case '#': 200 fsharp = 1; 201 goto scan; 202 #if FZERO 203 case '0': 204 fzero = 1; 205 goto scan; 206 #endif 207 } 208 209 /* Scan the field width */ 210 if (*cp == '*') { 211 width = va_arg (*args, int); 212 if (width < 0) { 213 width = -width; 214 fminus = 1; 215 } 216 cp++; 217 } else { 218 width = 0; 219 while (isdigit(*cp)) { 220 n = tonumber(*cp++); 221 width = width * 10 + n; 222 } 223 } 224 225 /* Scan the precision */ 226 if (*cp == '.') { 227 228 /* '*' instead of digits? */ 229 if (*++cp == '*') { 230 prec = va_arg(*args, int); 231 cp++; 232 } else { 233 prec = 0; 234 while (isdigit(*cp)) { 235 n = tonumber(*cp++); 236 prec = prec * 10 + n; 237 } 238 } 239 } else { 240 prec = -1; 241 } 242 243 /* Scan the length modifier */ 244 double_length = length = 0; 245 switch (*cp) { 246 case 'l': 247 if (*(cp + 1) == 'l') { 248 cp++; 249 double_length = 1; 250 } else { 251 length = 1; 252 } 253 /* No break */ 254 case 'h': 255 cp++; 256 } 257 258 /* 259 * The character addressed by cp must be the 260 * format letter -- there is nothing left for 261 * it to be. 262 * 263 * The status of the +, -, #, blank, and 0 264 * flags are reflected in the variables 265 * "fplus", "fminus", "fsharp", "fblank", 266 * and "fzero", respectively. 267 * "width" and "prec" contain numbers 268 * corresponding to the digit strings 269 * before and after the decimal point, 270 * respectively. If there was no decimal 271 * point, "prec" is -1. 272 * 273 * The following switch sets things up 274 * for printing. What ultimately gets 275 * printed will be padding blanks, a prefix, 276 * left padding zeroes, a value, right padding 277 * zeroes, a suffix, and more padding 278 * blanks. Padding blanks will not appear 279 * simultaneously on both the left and the 280 * right. Each case in this switch will 281 * compute the value, and leave in several 282 * variables the information necessary to 283 * construct what is to be printed. 284 * 285 * The prefix is a sign, a blank, "0x", "0X", 286 * or null, and is addressed by "prefix". 287 * 288 * The suffix is either null or an exponent, 289 * and is addressed by "suffix". 290 * 291 * The value to be printed starts at "bp" 292 * and continues up to and not including "p". 293 * 294 * "lzero" and "rzero" will contain the number 295 * of padding zeroes required on the left 296 * and right, respectively. If either of 297 * these variables is negative, it will be 298 * treated as if it were zero. 299 * 300 * The number of padding blanks, and whether 301 * they go on the left or the right, will be 302 * computed on exit from the switch. 303 */ 304 305 lzero = 0; 306 prefix = ""; 307 #if FLOAT 308 rzero = lzero; 309 suffix = prefix; 310 #endif 311 switch (fcode = *cp++) { 312 313 /* 314 * fixed point representations 315 * 316 * "hradix" is half the radix for the conversion. 317 * Conversion is unsigned unless fcode is 'd'. 318 * HIBITLL is 1000...000 binary, and is equal to 319 * the maximum negative number. 320 * We assume a 2's complement machine 321 */ 322 323 case 'D': 324 case 'U': 325 length = 1; 326 case 'd': 327 case 'u': 328 hradix = 5; 329 goto fixed; 330 331 case 'O': 332 length = 1; 333 case 'o': 334 hradix = 4; 335 goto fixed; 336 337 case 'X': 338 case 'x': 339 hradix = 8; 340 341 fixed: 342 /* Establish default precision */ 343 if (prec < 0) { 344 prec = 1; 345 } 346 347 /* Fetch the argument to be printed */ 348 if (double_length) { 349 val = va_arg(*args, long long); 350 } else if (length) { 351 val = va_arg(*args, long); 352 } else if (fcode == 'd') { 353 val = va_arg(*args, int); 354 } else { 355 val = va_arg(*args, unsigned); 356 } 357 358 /* If signed conversion, establish sign */ 359 if (fcode == 'd' || fcode == 'D') { 360 if (val < 0) { 361 prefix = "-"; 362 /* 363 * Negate, checking in 364 * advance for possible 365 * overflow. 366 */ 367 if (val != HIBITLL) { 368 val = -val; 369 } 370 } else if (fplus) { 371 prefix = "+"; 372 } else if (fblank) { 373 prefix = " "; 374 } 375 } 376 #if FZERO 377 if (fzero) { 378 int n = width - strlen(prefix); 379 if (n > prec) { 380 prec = n; 381 } 382 } 383 #endif 384 /* Set translate table for digits */ 385 if (fcode == 'X') { 386 tab = "0123456789ABCDEF"; 387 } else { 388 tab = "0123456789abcdef"; 389 } 390 391 /* Develop the digits of the value */ 392 p = bp = buf + MAXDIGS; 393 while (val) { 394 lowbit = val & 1; 395 val = (val >> 1) & ~HIBITLL; 396 *--bp = tab[val % hradix * 2 + lowbit]; 397 val /= hradix; 398 } 399 400 /* Calculate padding zero requirement */ 401 lzero = bp - p + prec; 402 403 /* Handle the # flag */ 404 if (fsharp && bp != p) { 405 switch (fcode) { 406 case 'o': 407 if (lzero < 1) 408 lzero = 1; 409 break; 410 case 'x': 411 prefix = "0x"; 412 break; 413 case 'X': 414 prefix = "0X"; 415 break; 416 } 417 } 418 419 break; 420 #if FLOAT 421 case 'E': 422 case 'e': 423 /* 424 * E-format. The general strategy 425 * here is fairly easy: we take 426 * what ecvt gives us and re-format it. 427 */ 428 429 /* Establish default precision */ 430 if (prec < 0) { 431 prec = 6; 432 } 433 434 /* Fetch the value */ 435 dval = va_arg(*args, double); 436 437 /* Develop the mantissa */ 438 bp = ecvt(dval, 439 min(prec + 1, MAXECVT), 440 &decpt, 441 &sign); 442 443 /* Determine the prefix */ 444 e_merge: 445 if (sign) { 446 prefix = "-"; 447 } else if (fplus) { 448 prefix = "+"; 449 } else if (fblank) { 450 prefix = " "; 451 } 452 453 /* Place the first digit in the buffer */ 454 p = &buf[0]; 455 *p++ = *bp != '\0' ? *bp++ : '0'; 456 457 /* Put in a decimal point if needed */ 458 if (prec != 0 || fsharp) { 459 *p++ = '.'; 460 } 461 462 /* Create the rest of the mantissa */ 463 rzero = prec; 464 while (rzero > 0 && *bp != '\0') { 465 --rzero; 466 *p++ = *bp++; 467 } 468 469 bp = &buf[0]; 470 471 /* Create the exponent */ 472 suffix = &expbuf[MAXESIZ]; 473 *suffix = '\0'; 474 if (dval != 0) { 475 n = decpt - 1; 476 if (n < 0) { 477 n = -n; 478 } 479 while (n != 0) { 480 *--suffix = todigit(n % 10); 481 n /= 10; 482 } 483 } 484 485 /* Prepend leading zeroes to the exponent */ 486 while (suffix > &expbuf[MAXESIZ - 2]) { 487 *--suffix = '0'; 488 } 489 490 /* Put in the exponent sign */ 491 *--suffix = (decpt > 0 || dval == 0) ? 492 '+' : '-'; 493 494 /* Put in the e */ 495 *--suffix = isupper(fcode) ? 'E' : 'e'; 496 497 break; 498 499 case 'f': 500 /* 501 * F-format floating point. This is 502 * a good deal less simple than E-format. 503 * The overall strategy will be to call 504 * fcvt, reformat its result into buf, 505 * and calculate how many trailing 506 * zeroes will be required. There will 507 * never be any leading zeroes needed. 508 */ 509 510 /* Establish default precision */ 511 if (prec < 0) { 512 prec = 6; 513 } 514 515 /* Fetch the value */ 516 dval = va_arg(*args, double); 517 518 /* Do the conversion */ 519 bp = fcvt(dval, 520 min(prec, MAXFCVT), 521 &decpt, 522 &sign); 523 524 /* Determine the prefix */ 525 f_merge: 526 if (sign && decpt > -prec && 527 *bp != '\0' && *bp != '0') { 528 prefix = "-"; 529 } else if (fplus) { 530 prefix = "+"; 531 } else if (fblank) { 532 prefix = " "; 533 } 534 535 /* Initialize buffer pointer */ 536 p = &buf[0]; 537 538 /* Emit the digits before the decimal point */ 539 n = decpt; 540 k = 0; 541 if (n <= 0) { 542 *p++ = '0'; 543 } else { 544 do { 545 if (*bp == '\0' || 546 k >= MAXFSIG) { 547 *p++ = '0'; 548 } else { 549 *p++ = *bp++; 550 ++k; 551 } 552 } while (--n != 0); 553 } 554 555 /* Decide whether we need a decimal point */ 556 if (fsharp || prec > 0) { 557 *p++ = '.'; 558 } 559 560 /* Digits (if any) after the decimal point */ 561 n = min(prec, MAXFCVT); 562 rzero = prec - n; 563 while (--n >= 0) { 564 if (++decpt <= 0 || *bp == '\0' || 565 k >= MAXFSIG) { 566 *p++ = '0'; 567 } else { 568 *p++ = *bp++; 569 ++k; 570 } 571 } 572 573 bp = &buf[0]; 574 575 break; 576 577 case 'G': 578 case 'g': 579 /* 580 * g-format. We play around a bit 581 * and then jump into e or f, as needed. 582 */ 583 584 /* Establish default precision */ 585 if (prec < 0) { 586 prec = 6; 587 } 588 589 /* Fetch the value */ 590 dval = va_arg(*args, double); 591 592 /* Do the conversion */ 593 bp = ecvt(dval, 594 min(prec, MAXECVT), 595 &decpt, 596 &sign); 597 if (dval == 0) { 598 decpt = 1; 599 } 600 601 k = prec; 602 if (!fsharp) { 603 n = strlen(bp); 604 if (n < k) { 605 k = n; 606 } 607 while (k >= 1 && bp[k-1] == '0') { 608 --k; 609 } 610 } 611 612 if (decpt < -3 || decpt > prec) { 613 prec = k - 1; 614 goto e_merge; 615 } else { 616 prec = k - decpt; 617 goto f_merge; 618 } 619 620 #endif 621 case 'c': 622 #ifdef MBCHAR_1 /* sizeof(int)>=sizeof(tchar) */ 623 /* 624 * A tchar arg is passed as int so we used the normal %c to specify 625 * such an arugument. 626 */ 627 tcbuf[0] = va_arg(*args, int); 628 tbp = &tcbuf[0]; 629 tep = tbp + 1; 630 fcode = 't'; /* Fake the rest of code. */ 631 break; 632 #else 633 /* 634 * We would have to invent another new format speficier such as "%T" to 635 * take a tchar arg. Let's worry about when that time comes. 636 */ 637 /* 638 * Following code take care of a char arg 639 * only. 640 */ 641 buf[0] = va_arg(*args, int); 642 bp = &buf[0]; 643 p = bp + 1; 644 break; 645 case 'T': /* Corresponding arg is tchar. */ 646 tcbuf[0] = va_arg(*args, tchar); 647 tbp = &tcbuf[0]; 648 tep = tbp + 1; 649 fcode = 't'; /* Fake the rest of code. */ 650 break; 651 #endif 652 case 's': 653 bp = va_arg(*args, char *); 654 if (bp == 0) { 655 nullstr: bp = "(null)"; 656 p = bp + strlen("(null)"); 657 break; 658 } 659 if (prec < 0) { 660 prec = MAXINT; 661 } 662 for (n = 0; *bp++ != '\0' && n < prec; n++) 663 ; 664 p = --bp; 665 bp -= n; 666 break; 667 668 case 't': 669 /* 670 * Special format specifier "%t" tells 671 * printf() to print char strings written 672 * as tchar string. 673 */ 674 tbp = va_arg(*args, tchar *); 675 if (tbp == 0) { 676 fcode = 's'; /* Act as if it were %s. */ 677 goto nullstr; 678 } 679 if (prec < 0) { 680 prec = MAXINT; 681 } 682 for (n = 0; *tbp++ != 0 && n < prec; n++) 683 ; 684 tep = --tbp; 685 tbp -= n; 686 687 /* 688 * Just to make the following padding 689 * calculation not to go very crazy... 690 */ 691 bp = NULL; 692 p = bp + n; 693 break; 694 695 case '\0': 696 cp--; 697 break; 698 699 default: 700 p = bp = &fcode; 701 p++; 702 break; 703 704 } 705 if (fcode != '\0') { 706 /* Calculate number of padding blanks */ 707 int nblank; 708 nblank = width 709 #if FLOAT 710 - (rzero < 0 ? 0: rzero) 711 - strlen(suffix) 712 #endif 713 - (p - bp) 714 - (lzero < 0 ? 0 : lzero) 715 - strlen(prefix); 716 717 /* Blanks on left if required */ 718 if (!fminus) { 719 while (--nblank >= 0) { 720 Putchar(' '); 721 } 722 } 723 724 /* Prefix, if any */ 725 while (*prefix != '\0') { 726 Putchar(*prefix++); 727 } 728 729 /* Zeroes on the left */ 730 while (--lzero >= 0) { 731 Putchar('0'); 732 } 733 734 /* The value itself */ 735 if (fcode == 't') { /* %t is special. */ 736 while (tbp < tep) { 737 Putchar(*tbp++); 738 } 739 } else { /* For rest of the cases. */ 740 while (bp < p) { 741 putbyte(*bp++); 742 } 743 } 744 #if FLOAT 745 /* Zeroes on the right */ 746 while (--rzero >= 0) 747 Putchar('0'); 748 749 /* The suffix */ 750 while (*suffix != '\0') { 751 Putchar(*suffix++); 752 } 753 #endif 754 /* Blanks on the right if required */ 755 if (fminus) { 756 while (--nblank >= 0) { 757 Putchar(' '); 758 } 759 } 760 } 761 } 762 } 763