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