1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * _doprnt: common code for printf, fprintf, sprintf 32 */ 33 34 #include "lint.h" 35 #include "mtlib.h" 36 #include "print.h" /* parameters & macros for doprnt */ 37 #include <wchar.h> 38 #include "libc.h" 39 #include <stdlib.h> 40 #include <limits.h> 41 #include <ctype.h> 42 #include <stdarg.h> 43 #include <values.h> 44 #include <memory.h> 45 #include <string.h> 46 #include <locale.h> 47 #include <widec.h> 48 #include "../i18n/_locale.h" 49 #include <errno.h> 50 #include <sys/types.h> 51 #include <libw.h> 52 #include "mse.h" 53 #include "xpg6.h" 54 55 static const char nullstr[] = "(null)"; 56 static const wchar_t widenullstr[] = L"(null)"; 57 58 #if defined(__i386) || defined(__amd64) || defined(__sparcv9) 59 #define GETQVAL(arg) (va_arg(arg, long double)) 60 #else /* !defined(__i386) && !defined(__sparcv9) */ 61 #define GETQVAL(arg) *(va_arg(arg, long double *)) 62 #endif /* !defined(__i386) && !defined(__sparcv9) */ 63 64 #ifdef _WIDE 65 #define STRCHR wcschr 66 #define STRSPN wcsspn 67 #define ATOI(x) _watoi((wchar_t *)x) 68 #define _P_HYPHEN L"-" 69 #define _P_PLUS L"+" 70 #define _P_BLANK L" " 71 #define _P_ZEROx L"0x" 72 #define _P_ZEROX L"0X" 73 #define _M_ISDIGIT(c) (((c) >= 0) && ((c) < 256) && isdigit((c))) 74 #define _M_ISUPPER(c) (((c) >= 0) && ((c) < 256) && isupper((c))) 75 #else /* _WIDE */ 76 #define STRCHR strchr 77 #define STRSPN strspn 78 #define ATOI(x) atoi(x) 79 #define _P_HYPHEN "-" 80 #define _P_PLUS "+" 81 #define _P_BLANK " " 82 #define _P_ZEROx "0x" 83 #define _P_ZEROX "0X" 84 #define _M_ISDIGIT(c) isdigit((c)) 85 #define _M_ISUPPER(c) isupper((c)) 86 #endif /* _WIDE */ 87 88 #ifdef _WIDE 89 #define PUT(p, n) \ 90 { \ 91 int retp; \ 92 retp = put_wide(iop, &bufptr, bufferend, p, n, sflag); \ 93 if (retp == EOF) { \ 94 return ((ssize_t)EOF); \ 95 } \ 96 } 97 98 #define PAD(s, n) \ 99 { \ 100 int retp; \ 101 retp = pad_wide(iop, &bufptr, bufferend, s, n, sflag); \ 102 if (retp == EOF) { \ 103 return ((ssize_t)EOF); \ 104 } \ 105 } 106 107 #define FPCONV(func, val, prec, decpt, sign, cvtbuf) \ 108 { \ 109 char cb[DECIMAL_STRING_LENGTH]; \ 110 wchar_t *wp; \ 111 char *cp; \ 112 (void) func(val, prec, decpt, sign, cb); \ 113 wp = cvtbuf; \ 114 cp = cb; \ 115 while (*cp) { \ 116 *wp++ = (wchar_t)*cp++; \ 117 } \ 118 *wp = L'\0'; \ 119 } 120 121 #else /* _WIDE */ 122 #define PUT(p, n) \ 123 {\ 124 /*\ 125 * When _doprnt() is called by [v]snprintf, we need to \ 126 * always call _dowrite(). We also need to call _dowrite() \ 127 * if the bufptr lies beyond the end of the buffer. This \ 128 * is possible due to known off-by-one errors in __flsbuf() \ 129 * and _fwrite_unlocked(). See 1235867 and 1231720 for the \ 130 * sordid details. \ 131 */\ 132 if (snflag || bufptr > bufferend ||\ 133 (unsigned long)(bufferend - bufptr) < (n)) {\ 134 if (!_dowrite(p, n, iop, &bufptr)) {\ 135 return (EOF);\ 136 }\ 137 } else {\ 138 unsigned char *fbp = bufptr;\ 139 switch (n) {\ 140 case 4:\ 141 *fbp = *p;\ 142 *(fbp + 1) = *(p + 1);\ 143 *(fbp + 2) = *(p + 2);\ 144 *(fbp + 3) = *(p + 3);\ 145 bufptr += 4;\ 146 break;\ 147 case 3:\ 148 *fbp = *p;\ 149 *(fbp + 1) = *(p + 1);\ 150 *(fbp + 2) = *(p + 2);\ 151 bufptr += 3;\ 152 break;\ 153 case 2:\ 154 *fbp = *p;\ 155 *(fbp + 1) = *(p + 1);\ 156 bufptr += 2;\ 157 break;\ 158 case 1:\ 159 *bufptr++ = *p;\ 160 break;\ 161 default:\ 162 bufptr = (unsigned char *)memcpy(fbp, p, n)\ 163 + (n);\ 164 }\ 165 }\ 166 } 167 168 #define PAD(s, n) { ssize_t nn; \ 169 for (nn = n; nn > PAD_LEN; nn -= PAD_LEN) \ 170 if (!_dowrite(s, PAD_LEN, iop, &bufptr)) \ 171 return (EOF); \ 172 PUT(s, nn); \ 173 } 174 175 #define FPCONV(func, val, prec, decpt, sign, cvtbuf) \ 176 (void) func(val, prec, decpt, sign, cvtbuf); 177 178 #endif /* _WIDE */ 179 180 /* bit positions for flags used in doprnt */ 181 182 #define LENGTH 0x1 /* l */ 183 #define FPLUS 0x2 /* + */ 184 #define FMINUS 0x4 /* - */ 185 #define FBLANK 0x8 /* blank */ 186 #define FSHARP 0x10 /* # */ 187 #define PADZERO 0x20 /* padding zeroes requested via '0' */ 188 #define DOTSEEN 0x40 /* dot appeared in format specification */ 189 #define SUFFIX 0x80 /* a suffix is to appear in the output */ 190 #define RZERO 0x100 /* there will be trailing zeros in output */ 191 #define LZERO 0x200 /* there will be leading zeroes in output */ 192 #define SHORT 0x400 /* h */ 193 #define QUAD 0x800 /* Q for long double */ 194 #define XLONG 0x1000 /* ll for long long */ 195 #define CHAR 0x2000 /* hh for char */ 196 197 #ifdef _WIDE 198 static wchar_t * 199 insert_thousands_sep(wchar_t *bp, wchar_t *ep); 200 #else /* _WIDE */ 201 static char * 202 insert_thousands_sep(char *bp, char *ep); 203 #endif /* _WIDE */ 204 205 static int _rec_scrswidth(wchar_t *, ssize_t); 206 207 /* 208 * Positional Parameter information 209 */ 210 #define MAXARGS 30 /* max. number of args for fast positional paramters */ 211 212 static ssize_t 213 _dowrite(const char *p, ssize_t n, FILE *iop, unsigned char **ptrptr); 214 215 /* 216 * stva_list is used to subvert C's restriction that a variable with an 217 * array type can not appear on the left hand side of an assignment operator. 218 * By putting the array inside a structure, the functionality of assigning to 219 * the whole array through a simple assignment is achieved.. 220 */ 221 typedef struct stva_list { 222 va_list ap; 223 } stva_list; 224 225 #ifdef _WIDE 226 static void _wmkarglst(wchar_t *, stva_list, stva_list [], int); 227 static void _wgetarg(wchar_t *, stva_list *, long, int); 228 #else /* _WIDE */ 229 static void _mkarglst(char *, stva_list, stva_list [], int); 230 void _getarg(char *, stva_list *, long, int); 231 #endif /* _WIDE */ 232 233 234 235 236 static int 237 _lowdigit(ssize_t *valptr) 238 { 239 /* This function computes the decimal low-order digit of the number */ 240 /* pointed to by valptr, and returns this digit after dividing */ 241 /* *valptr by ten. This function is called ONLY to compute the */ 242 /* low-order digit of a long whose high-order bit is set. */ 243 244 ssize_t lowbit = *valptr & 1; 245 long value = (*valptr >> 1) & ~HIBITL; 246 247 *valptr = value / 5; 248 value = value % 5 * 2 + lowbit + '0'; 249 return ((int)value); 250 } 251 252 static int 253 _lowlldigit(long long *valptr) 254 { 255 ssize_t lowbit = *valptr & 1; 256 long long value = (*valptr >> 1) & ~HIBITLL; 257 *valptr = value / 5; 258 value = value % 5 * 2 + lowbit + '0'; 259 return ((int)value); 260 } 261 262 /* The function _dowrite carries out buffer pointer bookkeeping surrounding */ 263 /* a call to fwrite. It is called only when the end of the file output */ 264 /* buffer is approached or in other unusual situations. */ 265 266 static ssize_t 267 _dowrite(const char *p, ssize_t n, FILE *iop, unsigned char **ptrptr) 268 { 269 if (!(iop->_flag & _IOREAD)) { 270 iop->_cnt -= (*ptrptr - iop->_ptr); 271 iop->_ptr = *ptrptr; 272 _bufsync(iop, _bufend(iop)); 273 if (_FWRITE(p, 1, n, iop) != n) { 274 return (0); 275 } 276 *ptrptr = iop->_ptr; 277 } else { 278 if (n > iop->_cnt) 279 n = iop->_cnt; 280 iop->_cnt -= n; 281 *ptrptr = (unsigned char *)memcpy((char *)*ptrptr, p, n) + n; 282 iop->_ptr = *ptrptr; 283 } 284 return (1); 285 } 286 287 #define PAD_LEN 20 288 static const char _blanks[] = " "; 289 static const char _zeroes[] = "00000000000000000000"; 290 #ifdef _WIDE 291 static const wchar_t uc_digs[] = L"0123456789ABCDEF"; 292 static const wchar_t lc_digs[] = L"0123456789abcdef"; 293 #else /* _WIDE */ 294 static const char uc_digs[] = "0123456789ABCDEF"; 295 static const char lc_digs[] = "0123456789abcdef"; 296 #endif /* _WIDE */ 297 298 #ifdef _WIDE 299 static int 300 put_wide(FILE *iop, unsigned char **bufptr, 301 unsigned char *bufferend, wchar_t *p, size_t n, 302 int sflag) 303 { 304 unsigned char *newbufptr; 305 wchar_t *q; 306 int r; 307 size_t len, i; 308 309 if (sflag) { 310 len = (wchar_t *)bufferend - (wchar_t *)*bufptr; 311 if (n > len) { 312 (void) wmemcpy((wchar_t *)*bufptr, p, len); 313 iop->_ptr = bufferend; 314 return (EOF); 315 } else { 316 (void) wmemcpy((wchar_t *)*bufptr, p, n); 317 *bufptr = (unsigned char *)((wchar_t *)*bufptr + n); 318 return (0); 319 } 320 } else { 321 char *tmpp, *tmpq; 322 size_t tsize; 323 324 tsize = (n + 1) * MB_LEN_MAX; 325 tmpp = lmalloc(tsize); 326 if (tmpp == NULL) { 327 errno = ENOMEM; 328 return (EOF); 329 } 330 q = p; 331 tmpq = tmpp; 332 for (len = 0, i = 0; i < n; i++) { 333 r = wctomb(tmpq, *q++); 334 if (r == -1) { 335 lfree(tmpp, tsize); 336 errno = EILSEQ; 337 return (EOF); 338 } 339 len += r; 340 tmpq += r; 341 } 342 tmpq = tmpp; 343 newbufptr = *bufptr + len; 344 if (newbufptr > bufferend) { 345 if (!_dowrite(tmpp, len, iop, bufptr)) { 346 lfree(tmpp, tsize); 347 return (EOF); 348 } 349 } else { 350 (void) memcpy(*bufptr, tmpp, len); 351 *bufptr = newbufptr; 352 } 353 lfree(tmpp, tsize); 354 return (0); 355 } 356 } 357 358 static int 359 pad_wide(FILE *iop, unsigned char **bufptr, 360 unsigned char *bufferend, const char *s, size_t n, 361 int sflag) 362 { 363 unsigned char *newbufptr; 364 ssize_t nn; 365 size_t len; 366 wchar_t ps; 367 368 if (sflag) { 369 /* for swprintf */ 370 ps = (wchar_t)s[0]; 371 len = (wchar_t *)bufferend - (wchar_t *)*bufptr; 372 if (n > len) { 373 (void) wmemset((wchar_t *)*bufptr, ps, len); 374 iop->_ptr = bufferend; 375 return (EOF); 376 } else { 377 (void) wmemset((wchar_t *)*bufptr, ps, n); 378 *bufptr = (unsigned char *)((wchar_t *)*bufptr + n); 379 return (0); 380 } 381 } else { 382 for (nn = n; nn > PAD_LEN; nn -= PAD_LEN) { 383 if (!_dowrite(s, PAD_LEN, iop, bufptr)) 384 return (EOF); 385 } 386 newbufptr = *bufptr + nn; 387 if (newbufptr > bufferend) { 388 if (!_dowrite(s, nn, iop, bufptr)) 389 return (EOF); 390 } else { 391 (void) memcpy(*bufptr, s, nn); 392 *bufptr = newbufptr; 393 } 394 return (0); 395 } 396 } 397 #endif /* _WIDE */ 398 399 #ifdef _WIDE 400 ssize_t 401 _wdoprnt(const wchar_t *format, va_list in_args, FILE *iop) 402 { 403 return (_wndoprnt(format, in_args, iop, 0)); 404 } 405 #else /* _WIDE */ 406 ssize_t 407 _doprnt(const char *format, va_list in_args, FILE *iop) 408 { 409 return (_ndoprnt(format, in_args, iop, 0)); 410 } 411 #endif /* _WIDE */ 412 413 414 #ifdef _WIDE 415 ssize_t 416 _wndoprnt(const wchar_t *format, va_list in_args, FILE *iop, int prflag) 417 #else /* _WIDE */ 418 ssize_t 419 _ndoprnt(const char *format, va_list in_args, FILE *iop, int prflag) 420 #endif /* _WIDE */ 421 { 422 423 #ifdef _WIDE 424 int sflag = 0; 425 size_t maxcount; 426 #else 427 int snflag = 0; 428 #endif /* _WIDE */ 429 /* bufptr is used inside of doprnt instead of iop->_ptr; */ 430 /* bufferend is a copy of _bufend(iop), if it exists. For */ 431 /* dummy file descriptors (iop->_flag & _IOREAD), bufferend */ 432 /* may be meaningless. Dummy file descriptors are used so that */ 433 /* sprintf and vsprintf may share the _doprnt routine with the */ 434 /* rest of the printf family. */ 435 436 unsigned char *bufptr; 437 unsigned char *bufferend; 438 439 #ifdef _WIDE 440 /* This variable counts output characters. */ 441 size_t count = 0; 442 #else /* _WIDE */ 443 /* This variable counts output characters. */ 444 int count = 0; 445 #endif /* _WIDE */ 446 447 #ifdef _WIDE 448 wchar_t *bp; 449 size_t bpsize; 450 wchar_t *p; 451 char *cbp; 452 char *cp; 453 454 #else /* _WIDE */ 455 /* Starting and ending points for value to be printed */ 456 char *bp; 457 char *p; 458 #endif /* _WIDE */ 459 /* Field width and precision */ 460 int prec = 0; 461 ssize_t width; 462 ssize_t num; 463 ssize_t sec_display; 464 wchar_t *wp; 465 ssize_t preco; 466 ssize_t wcount = 0; 467 char tmpbuf[10]; 468 char wflag; 469 char lflag; 470 int quote; /* ' */ 471 int retcode; 472 473 474 #ifdef _WIDE 475 /* Format code */ 476 wchar_t fcode; 477 #else /* _WIDE */ 478 /* Format code */ 479 char fcode; 480 #endif /* _WIDE */ 481 482 /* Number of padding zeroes required on the left and right */ 483 ssize_t lzero, rzero, rz, leadzeroes; 484 485 486 /* Flags - bit positions defined by LENGTH, FPLUS, FMINUS, FBLANK, */ 487 /* and FSHARP are set if corresponding character is in format */ 488 /* Bit position defined by PADZERO means extra space in the field */ 489 /* should be padded with leading zeroes rather than with blanks */ 490 491 ssize_t flagword; 492 493 #ifdef _WIDE 494 /* Values are developed in this buffer */ 495 wchar_t buf[max(MAXLLDIGS, 1034)]; 496 wchar_t cvtbuf[512 + DECIMAL_STRING_LENGTH]; 497 498 /* Pointer to sign, "0x", "0X", or empty */ 499 wchar_t *prefix; 500 wchar_t prefixbuf[4]; 501 502 /* Exponent or empty */ 503 wchar_t *suffix; 504 505 /* Buffer to create exponent */ 506 wchar_t expbuf[MAXESIZ + 1]; 507 #else /* _WIDE */ 508 /* Values are developed in this buffer */ 509 char buf[max(MAXLLDIGS, 1034)]; 510 char cvtbuf[512 + DECIMAL_STRING_LENGTH]; 511 512 /* Pointer to sign, "0x", "0X", or empty */ 513 char *prefix; 514 char prefixbuf[4]; 515 516 /* Exponent or empty */ 517 char *suffix; 518 519 /* Buffer to create exponent */ 520 char expbuf[MAXESIZ + 1]; 521 #endif /* _WIDE */ 522 523 /* Length of prefix and of suffix */ 524 ssize_t prefixlength, suffixlength; 525 526 /* Combined length of leading zeroes, trailing zeroes, and suffix */ 527 ssize_t otherlength; 528 529 /* The value being converted, if integer */ 530 ssize_t val; 531 532 /* The value being converted, if long long */ 533 long long ll = 0LL; 534 535 /* Output value from aconvert */ 536 int exp; 537 538 /* Output values from fcvt and ecvt */ 539 int decpt, sign; 540 541 #ifdef _WIDE 542 /* Pointer to a translate table for digits of whatever radix */ 543 const wchar_t *tab; 544 #else /* _WIDE */ 545 /* Pointer to a translate table for digits of whatever radix */ 546 const char *tab; 547 #endif /* _WIDE */ 548 549 /* Work variables */ 550 ssize_t k, lradix, mradix; 551 552 int inf_nan = 0; 553 int inf_nan_mixed_case = 0; 554 555 #ifdef _WIDE 556 /* variables for positional parameters */ 557 /* save the beginning of the format */ 558 wchar_t *sformat = (wchar_t *)format; 559 #else /* _WIDE */ 560 /* variables for positional parameters */ 561 char *sformat = (char *)format; /* save the beginning of the format */ 562 #endif 563 564 int fpos = 1; /* 1 if first positional parameter */ 565 stva_list args, /* used to step through the argument list */ 566 sargs; /* used to save the start of the arg list */ 567 stva_list bargs; /* used to restore args if positional width */ 568 /* or precision */ 569 stva_list arglst[MAXARGS]; /* array giving appropriate values */ 570 /* for va_arg() to retrieve the */ 571 /* corresponding argument: */ 572 /* arglst[0] is the first arg */ 573 /* arglst[1] is the second arg, etc */ 574 575 int starflg = 0; /* set to 1 if * format specifier seen */ 576 struct lconv *locptr = localeconv(); 577 char decimal_point = *locptr->decimal_point; 578 579 /* 580 * Initialize args and sargs to the start of the argument list. 581 * We don't know any portable way to copy an arbitrary C object 582 * so we use a system-specific routine (probably a macro) from 583 * stdarg.h. (Remember that if va_list is an array, in_args will 584 * be a pointer and &in_args won't be what we would want for 585 * memcpy.) 586 */ 587 va_copy(args.ap, in_args); 588 sargs = args; 589 590 #ifdef _WIDE 591 if (iop->_flag == _IOREAD) 592 sflag = 1; 593 594 if (!sflag) { 595 #endif /* _WIDE */ 596 /* if first I/O to the stream get a buffer */ 597 /* Note that iop->_base should not equal 0 for sprintf and vsprintf */ 598 if (iop->_base == 0) { 599 if (_findbuf(iop) == 0) 600 return (EOF); 601 /* _findbuf leaves _cnt set to 0 which is the wrong thing to do */ 602 /* for fully buffered files */ 603 if (!(iop->_flag & (_IOLBF|_IONBF))) 604 iop->_cnt = _bufend(iop) - iop->_base; 605 } 606 #ifdef _WIDE 607 } 608 #endif /* _WIDE */ 609 610 #ifdef _WIDE 611 bufptr = iop->_ptr; 612 if (sflag) { 613 maxcount = (size_t)iop->_cnt; 614 bufferend = (unsigned char *)(((wchar_t *)iop->_ptr) + 615 maxcount); 616 } else { 617 bufferend = _bufend(iop); 618 } 619 #else /* _WIDE */ 620 /* initialize buffer pointer and buffer end pointer */ 621 bufptr = iop->_ptr; 622 if (iop->_flag & _IOREAD) { 623 /* 624 * [v]sprintf or [v]snprintf 625 */ 626 if (iop->_cnt == MAXINT) { 627 /* 628 * [v]sprintf (no boundschecking) 629 */ 630 bufferend = 631 (unsigned char *)((long)bufptr | (-1L & ~HIBITL)); 632 } else { 633 /* 634 * [v]snprintf (with boundschecking) or 635 * iop with _IORW has been read. 636 */ 637 bufferend = _bufend(iop); 638 if (bufferend == NULL) { 639 /* 640 * [v]snprintf 641 * 642 * [v]snprint() needs to be always handled by 643 * _dowrite(). 644 */ 645 snflag = 1; 646 } 647 } 648 } else { 649 /* 650 * [v]printf or [v]fprintf 651 */ 652 bufferend = _bufend(iop); 653 } 654 #endif /* _WIDE */ 655 656 /* 657 * The main loop -- this loop goes through one iteration 658 * for each string of ordinary characters or format specification. 659 */ 660 for (; ; ) { 661 ssize_t n; 662 663 if ((fcode = *format) != '\0' && fcode != '%') { 664 #ifdef _WIDE 665 bp = (wchar_t *)format; 666 #else /* _WIDE */ 667 bp = (char *)format; 668 #endif /* _WIDE */ 669 do { 670 format++; 671 } while ((fcode = *format) != '\0' && fcode != '%'); 672 673 count += (n = format - bp); /* n = no. of non-% chars */ 674 PUT(bp, n); 675 } 676 if (fcode == '\0') { /* end of format; return */ 677 ssize_t nn = bufptr - iop->_ptr; 678 679 #ifdef _WIDE 680 if (sflag) { 681 iop->_ptr = bufptr; 682 return ((ssize_t)count); 683 } 684 #endif /* _WIDE */ 685 686 iop->_cnt -= nn; 687 iop->_ptr = bufptr; 688 /* in case of interrupt during last several lines */ 689 if ((bufptr + iop->_cnt) > bufferend && !(iop->_flag \ 690 & _IOREAD)) 691 _bufsync(iop, bufferend); 692 if (iop->_flag & (_IONBF | _IOLBF) && \ 693 (iop->_flag & _IONBF || \ 694 memchr((char *)(bufptr+iop->_cnt), \ 695 '\n', -iop->_cnt) != NULL)) 696 (void) _xflsbuf(iop); 697 #ifdef _WIDE 698 return (FERROR(iop) ? EOF : (ssize_t)count); 699 #else /* _WIDE */ 700 return (FERROR(iop) ? EOF : (int)count); 701 #endif /* _WIDE */ 702 } 703 704 /* 705 * % has been found. 706 * The following switch is used to parse the format 707 * specification and to perform the operation specified 708 * by the format letter. The program repeatedly goes 709 * back to this switch until the format letter is 710 * encountered. 711 */ 712 width = prefixlength = otherlength = 0; 713 flagword = suffixlength = 0; 714 format++; 715 wflag = 0; 716 lflag = 0; 717 sec_display = 0; 718 quote = 0; 719 720 charswitch: 721 722 switch (fcode = *format++) { 723 724 case '+': 725 flagword |= FPLUS; 726 goto charswitch; 727 case '-': 728 flagword |= FMINUS; 729 flagword &= ~PADZERO; /* ignore 0 flag */ 730 goto charswitch; 731 case ' ': 732 flagword |= FBLANK; 733 goto charswitch; 734 case '\'': /* XSH4 */ 735 quote++; 736 goto charswitch; 737 case '#': 738 flagword |= FSHARP; 739 goto charswitch; 740 741 /* Scan the field width and precision */ 742 case '.': 743 flagword |= DOTSEEN; 744 prec = 0; 745 goto charswitch; 746 747 case '*': 748 if (_M_ISDIGIT(*format)) { 749 starflg = 1; 750 bargs = args; 751 goto charswitch; 752 } 753 if (!(flagword & DOTSEEN)) { 754 width = va_arg(args.ap, int); 755 if (width < 0) { 756 width = -width; 757 flagword |= FMINUS; 758 } 759 } else { 760 prec = va_arg(args.ap, int); 761 if (prec < 0) { 762 prec = 0; 763 flagword ^= DOTSEEN; /* ANSI sez so */ 764 } 765 } 766 goto charswitch; 767 768 case '$': 769 { 770 ssize_t position; 771 stva_list targs; 772 if (fpos) { 773 #ifdef _WIDE 774 _wmkarglst(sformat, sargs, arglst, prflag); 775 #else /* _WIDE */ 776 _mkarglst(sformat, sargs, arglst, prflag); 777 #endif /* _WIDE */ 778 fpos = 0; 779 } 780 if (flagword & DOTSEEN) { 781 position = prec; 782 prec = 0; 783 } else { 784 position = width; 785 width = 0; 786 } 787 if (position <= 0) { 788 /* illegal position */ 789 format--; 790 continue; 791 } 792 if (position <= MAXARGS) { 793 targs = arglst[position - 1]; 794 } else { 795 targs = arglst[MAXARGS - 1]; 796 #ifdef _WIDE 797 _wgetarg(sformat, &targs, position, prflag); 798 #else /* _WIDE */ 799 _getarg(sformat, &targs, position, prflag); 800 #endif /* _WIDE */ 801 } 802 if (!starflg) 803 args = targs; 804 else { 805 starflg = 0; 806 args = bargs; 807 if (flagword & DOTSEEN) { 808 prec = va_arg(targs.ap, int); 809 if (prec < 0) { 810 prec = 0; 811 flagword ^= DOTSEEN; /* XSH */ 812 } 813 } else { 814 width = va_arg(targs.ap, int); 815 if (width < 0) { 816 width = -width; 817 flagword |= FMINUS; 818 } 819 } 820 } 821 goto charswitch; 822 } 823 824 case '0': /* obsolescent spec: leading zero in width */ 825 /* means pad with leading zeros */ 826 if (!(flagword & (DOTSEEN | FMINUS))) 827 flagword |= PADZERO; 828 /* FALLTHROUGH */ 829 case '1': 830 case '2': 831 case '3': 832 case '4': 833 case '5': 834 case '6': 835 case '7': 836 case '8': 837 case '9': 838 { num = fcode - '0'; 839 while (_M_ISDIGIT(fcode = *format)) { 840 num = num * 10 + fcode - '0'; 841 format++; 842 } 843 if (flagword & DOTSEEN) 844 prec = num; 845 else 846 width = num; 847 goto charswitch; 848 } 849 850 /* Scan the length modifier */ 851 case 'l': 852 if (!(flagword & XLONG)) { 853 if (lflag) { 854 /* long long */ 855 flagword &= ~LENGTH; 856 flagword |= XLONG; 857 } else { 858 /* long */ 859 flagword |= LENGTH; 860 } 861 } 862 lflag++; 863 goto charswitch; 864 865 case 'L': /* long double */ 866 flagword |= QUAD; 867 goto charswitch; 868 869 case 'h': 870 if (!(flagword & CHAR)) { 871 if (flagword & SHORT) { 872 /* char - hh */ 873 flagword &= ~SHORT; 874 flagword |= CHAR; 875 } else { 876 /* short */ 877 flagword |= SHORT; 878 } 879 } 880 goto charswitch; 881 case 'j': 882 #ifndef _LP64 883 /* 884 * *printf_c89() in 32-bit libc uses 885 * 32-bit intmax_t; otherwise intmax_t 886 * is 64-bits. 887 */ 888 if (!(prflag & _F_INTMAX32)) { 889 #endif 890 flagword |= XLONG; /* [u]intmax_t (64) */ 891 #ifndef _LP64 892 } 893 #endif 894 goto charswitch; 895 896 case 't': 897 /* 898 * LENGTH is shared by l, t, z specifiers; protect 899 * against (destructive) undefined behavior (eg: 900 * avoid %llt setting XLONG and LENGTH) with invalid 901 * combinations of specifiers 902 */ 903 if (!(flagword & XLONG)) { 904 flagword |= LENGTH; /* ptrdiff_t */ 905 } 906 goto charswitch; 907 908 case 'z': 909 if (!(flagword & XLONG)) { 910 flagword |= LENGTH; /* [s]size_t */ 911 } 912 goto charswitch; 913 914 /* 915 * The character addressed by format must be 916 * the format letter -- there is nothing 917 * left for it to be. 918 * 919 * The status of the +, -, #, and blank 920 * flags are reflected in the variable 921 * "flagword". "width" and "prec" contain 922 * numbers corresponding to the digit 923 * strings before and after the decimal 924 * point, respectively. If there was no 925 * decimal point, then flagword & DOTSEEN 926 * is false and the value of prec is meaningless. 927 * 928 * The following switch cases set things up 929 * for printing. What ultimately gets 930 * printed will be padding blanks, a 931 * prefix, left padding zeroes, a value, 932 * right padding zeroes, a suffix, and 933 * more padding blanks. Padding blanks 934 * will not appear simultaneously on both 935 * the left and the right. Each case in 936 * this switch will compute the value, and 937 * leave in several variables the informa- 938 * tion necessary to construct what is to 939 * be printed. 940 * 941 * The prefix is a sign, a blank, "0x", 942 * "0X", a sign or a blank followed by "0x" 943 * or "0X", or nothing, and is addressed by 944 * "prefix". 945 * 946 * The suffix is either null or an 947 * exponent, and is addressed by "suffix". 948 * If there is a suffix, the flagword bit 949 * SUFFIX will be set. 950 * 951 * The value to be printed starts at "bp" 952 * and continues up to and not including 953 * "p". 954 * 955 * "lzero" and "rzero" will contain the 956 * number of padding zeroes required on 957 * the left and right, respectively. 958 * The flagword bits LZERO and RZERO tell 959 * whether padding zeros are required. 960 * 961 * The number of padding blanks, and 962 * whether they go on the left or the 963 * right, will be computed on exit from 964 * the switch. 965 */ 966 967 968 969 /* 970 * decimal fixed point representations 971 * 972 * HIBITL is 100...000 973 * binary, and is equal to the maximum 974 * negative number. 975 * We assume a 2's complement machine 976 */ 977 case 'i': 978 case 'd': 979 if ((flagword & PADZERO) && (flagword & DOTSEEN)) 980 flagword &= ~PADZERO; /* ignore 0 flag */ 981 /* Set buffer pointer to last digit */ 982 p = bp = buf + MAXLLDIGS; 983 984 /* Fetch the argument to be printed */ 985 if (flagword & XLONG) { /* long long */ 986 ll = va_arg(args.ap, long long); 987 988 /* If signed conversion, make sign */ 989 if (ll < 0) { 990 prefix = _P_HYPHEN; 991 prefixlength = 1; 992 /* 993 * Negate, checking in advance for 994 * possible overflow. 995 */ 996 if (ll != HIBITLL) 997 ll = -ll; 998 else 999 /* number is -HIBITLL; convert last */ 1000 /* digit now and get positive number */ 1001 *--bp = _lowlldigit(&ll); 1002 } else if (flagword & FPLUS) { 1003 prefix = _P_PLUS; 1004 prefixlength = 1; 1005 } else if (flagword & FBLANK) { 1006 prefix = _P_BLANK; 1007 prefixlength = 1; 1008 } 1009 } else { /* not long long */ 1010 if (flagword & LENGTH) 1011 val = va_arg(args.ap, long); 1012 else 1013 val = va_arg(args.ap, int); 1014 1015 if (flagword & SHORT) 1016 val = (short)val; 1017 else if (flagword & CHAR) 1018 val = (char)val; 1019 1020 /* If signed conversion, make sign */ 1021 if (val < 0) { 1022 prefix = _P_HYPHEN; 1023 prefixlength = 1; 1024 /* 1025 * Negate, checking in advance 1026 * for possible overflow. 1027 */ 1028 if (val != HIBITL) 1029 val = -val; 1030 /* 1031 * number is -HIBITL; convert 1032 * last digit now and get 1033 * positive number 1034 */ 1035 else 1036 *--bp = _lowdigit(&val); 1037 } else if (flagword & FPLUS) { 1038 prefix = _P_PLUS; 1039 prefixlength = 1; 1040 } else if (flagword & FBLANK) { 1041 prefix = _P_BLANK; 1042 prefixlength = 1; 1043 } 1044 } 1045 1046 decimal: 1047 { 1048 long qval = val; 1049 long long lll = ll; 1050 long long tll; 1051 if (flagword & XLONG) { 1052 if (lll < 10LL) { 1053 #ifdef _WIDE 1054 if (lll != 0LL || !(flagword & DOTSEEN)) 1055 *--bp = (wchar_t)lll + L'0'; 1056 #else /* _WIDE */ 1057 if (lll != 0LL || !(flagword & DOTSEEN)) 1058 *--bp = (char)lll + '0'; 1059 #endif /* _WIDE */ 1060 } else { 1061 do { 1062 tll = lll; 1063 lll /= 10; 1064 #ifdef _WIDE 1065 *--bp = (wchar_t) 1066 (tll - lll * 10 + '0'); 1067 #else /* _WIDE */ 1068 *--bp = (char) \ 1069 (tll - lll * 10 + '0'); 1070 #endif /* _WIDE */ 1071 } while (lll >= 10); 1072 #ifdef _WIDE 1073 *--bp = (wchar_t)lll + '0'; 1074 #else /* _WIDE */ 1075 *--bp = (char)lll + '0'; 1076 #endif /* _WIDE */ 1077 } 1078 } else { 1079 if (qval <= 9) { 1080 #ifdef _WIDE 1081 if (qval != 0 || !(flagword & DOTSEEN)) 1082 *--bp = (wchar_t)qval + '0'; 1083 #else /* _WIDE */ 1084 if (qval != 0 || !(flagword & DOTSEEN)) 1085 *--bp = (char)qval + '0'; 1086 #endif /* _WIDE */ 1087 } else { 1088 do { 1089 n = qval; 1090 qval /= 10; 1091 #ifdef _WIDE 1092 *--bp = (wchar_t) \ 1093 (n - qval * 10 + '0'); 1094 #else /* _WIDE */ 1095 *--bp = (char) \ 1096 (n - qval * 10 + '0'); 1097 #endif /* _WIDE */ 1098 } while (qval > 9); 1099 #ifdef _WIDE 1100 *--bp = (wchar_t)qval + '0'; 1101 #else /* _WIDE */ 1102 *--bp = (char)qval + '0'; 1103 #endif /* _WIDE */ 1104 } 1105 } 1106 } 1107 /* Handle the ' flag */ 1108 if (quote) { 1109 p = insert_thousands_sep(bp, p); 1110 } 1111 1112 /* Calculate minimum padding zero requirement */ 1113 if (flagword & DOTSEEN) { 1114 leadzeroes = prec - (p - bp); 1115 if (leadzeroes > 0) { 1116 otherlength = lzero = leadzeroes; 1117 flagword |= LZERO; 1118 } 1119 } 1120 break; 1121 1122 case 'u': 1123 if ((flagword & PADZERO) && (flagword & DOTSEEN)) 1124 flagword &= ~PADZERO; /* ignore 0 flag */ 1125 p = bp = buf + MAXLLDIGS; 1126 1127 /* Fetch the argument to be printed */ 1128 if (flagword & XLONG) { 1129 ll = va_arg(args.ap, long long); 1130 1131 if (ll & HIBITLL) 1132 *--bp = _lowlldigit(&ll); 1133 } else { 1134 if (flagword & LENGTH) 1135 val = va_arg(args.ap, long); 1136 else 1137 val = va_arg(args.ap, unsigned); 1138 1139 if (flagword & SHORT) 1140 val = (unsigned short)val; 1141 else if (flagword & CHAR) 1142 val = (unsigned char)val; 1143 1144 if (val & HIBITL) 1145 *--bp = _lowdigit(&val); 1146 } 1147 1148 goto decimal; 1149 1150 /* 1151 * non-decimal fixed point representations 1152 * for radix equal to a power of two 1153 * 1154 * "mradix" is one less than the radix for the conversion. 1155 * "lradix" is one less than the base 2 log 1156 * of the radix for the conversion. Conversion is unsigned. 1157 * HIBITL is 100...000 1158 * binary, and is equal to the maximum 1159 * negative number. 1160 * We assume a 2's complement machine 1161 */ 1162 1163 case 'o': 1164 mradix = 7; 1165 lradix = 2; 1166 /* 1167 * DR151 and clarification in C90 1168 * presence of '#' increases precision to first 1169 * digit of the result to be zero 1170 */ 1171 if ((flagword & DOTSEEN) && (flagword & FSHARP) && 1172 prec == 0) 1173 prec = 1; 1174 1175 goto fixed; 1176 1177 case 'p': 1178 flagword &= ~(XLONG | SHORT); 1179 flagword |= LENGTH; 1180 1181 /* FALLTHRU */ 1182 case 'X': 1183 case 'x': 1184 mradix = 15; 1185 lradix = 3; 1186 1187 fixed: 1188 if ((flagword & PADZERO) && (flagword & DOTSEEN)) 1189 flagword &= ~PADZERO; /* ignore 0 flag */ 1190 1191 #ifdef _WIDE 1192 /* Set translate table for digits */ 1193 tab = (wchar_t *)((fcode == 'X') ? uc_digs : lc_digs); 1194 #else /* _WIDE */ 1195 /* Set translate table for digits */ 1196 tab = (fcode == 'X') ? uc_digs : lc_digs; 1197 #endif /* _WIDE */ 1198 1199 /* Fetch the argument to be printed */ 1200 if (flagword & XLONG) { 1201 ll = va_arg(args.ap, long long); 1202 } else { 1203 if (flagword & LENGTH) 1204 val = va_arg(args.ap, long); 1205 else 1206 val = va_arg(args.ap, unsigned); 1207 1208 if (flagword & SHORT) 1209 val = (unsigned short) val; 1210 else if (flagword & CHAR) 1211 val = (unsigned char) val; 1212 } 1213 p = bp = buf + MAXLLDIGS; 1214 1215 /* Develop the digits of the value */ 1216 if (flagword & XLONG) { 1217 long long lll = ll; 1218 1219 if (lll == 0LL) { 1220 if (!(flagword & DOTSEEN)) { 1221 otherlength = lzero = 1; 1222 flagword |= LZERO; 1223 } 1224 } else do { 1225 *--bp = tab[(ssize_t)(lll & mradix)]; 1226 lll = ((lll >> 1) & ~HIBITLL) \ 1227 >> lradix; 1228 } while (lll != 0LL); 1229 } else { 1230 long qval = val; 1231 1232 if (qval == 0) { 1233 if (!(flagword & DOTSEEN)) { 1234 otherlength = lzero = 1; 1235 flagword |= LZERO; 1236 } 1237 } else do { 1238 *--bp = tab[qval & mradix]; 1239 qval = ((qval >> 1) & ~HIBITL) \ 1240 >> lradix; 1241 } while (qval != 0); 1242 } 1243 1244 /* Calculate minimum padding zero requirement */ 1245 if (flagword & DOTSEEN) { 1246 leadzeroes = prec - (p - bp); 1247 if (leadzeroes > 0) { 1248 otherlength = lzero = leadzeroes; 1249 flagword |= LZERO; 1250 } 1251 } 1252 1253 /* Handle the # flag, (val != 0) for int and long */ 1254 /* (ll!= 0) handles long long case */ 1255 if ((flagword & FSHARP) && 1256 (((flagword & XLONG) == 0 && val != 0) || 1257 ((flagword & XLONG) == XLONG && ll != 0))) 1258 switch (fcode) { 1259 case 'o': 1260 if (!(flagword & LZERO)) { 1261 otherlength = lzero = 1; 1262 flagword |= LZERO; 1263 } 1264 break; 1265 case 'x': 1266 prefix = _P_ZEROx; 1267 prefixlength = 2; 1268 break; 1269 case 'X': 1270 prefix = _P_ZEROX; 1271 prefixlength = 2; 1272 break; 1273 } 1274 1275 break; 1276 1277 case 'A': 1278 case 'a': 1279 /* A format */ 1280 if (flagword & QUAD) { 1281 long double qval = GETQVAL(args.ap); 1282 1283 /* establish default precision */ 1284 if (!(flagword & DOTSEEN)) 1285 #if defined(__sparc) 1286 prec = HEXFP_QUAD_DIG - 1; 1287 #elif defined(__i386) || defined(__amd64) 1288 prec = HEXFP_EXTENDED_DIG - 1; 1289 #else 1290 #error Unknown architecture 1291 #endif 1292 1293 FPCONV(__qaconvert, &qval, 1294 min(prec + 1, MAXECVT), &exp, &sign, 1295 cvtbuf); 1296 } else { 1297 double dval = va_arg(args.ap, double); 1298 1299 /* establish default precision */ 1300 if (!(flagword & DOTSEEN)) 1301 prec = HEXFP_DOUBLE_DIG - 1; 1302 1303 FPCONV(__aconvert, dval, 1304 min(prec + 1, MAXECVT), &exp, &sign, 1305 cvtbuf); 1306 } 1307 bp = cvtbuf; 1308 1309 /* 1310 * The following is wide-character safe because 1311 * __aconvert and __qaconvert only produce ASCII 1312 * characters. 1313 */ 1314 if (!isxdigit((unsigned char)*bp)) { 1315 inf_nan = 1; 1316 break; 1317 } 1318 1319 /* 1320 * Create the prefix. We ought to use the strings 1321 * defined above (_P_HYPHEN, etc.), but that would 1322 * be awkward: we'd either have to define six more 1323 * of them or we'd have to use strcpy/strcat to 1324 * assemble the ones already defined. So instead, 1325 * we just build the prefix character by character. 1326 */ 1327 p = prefix = prefixbuf; 1328 if (sign) { 1329 *p++ = '-'; 1330 prefixlength = 1; 1331 } else if (flagword & FPLUS) { 1332 *p++ = '+'; 1333 prefixlength = 1; 1334 } else if (flagword & FBLANK) { 1335 *p++ = ' '; 1336 prefixlength = 1; 1337 } 1338 *p++ = '0'; 1339 *p++ = (fcode == 'A') ? 'X' : 'x'; 1340 *p = '\0'; 1341 prefixlength += 2; 1342 1343 /* put the first digit in the buffer */ 1344 p = &buf[0]; 1345 *p++ = (*bp != '\0') ? *bp++ : '0'; 1346 1347 /* put in a decimal point if needed */ 1348 if (prec != 0 || (flagword & FSHARP)) 1349 *p++ = decimal_point; 1350 1351 /* create the rest of the mantissa */ 1352 rz = prec; 1353 if (fcode == 'A') { 1354 for (; rz > 0 && *bp != '\0'; --rz) { 1355 *p++ = ('a' <= *bp && *bp <= 'f')? 1356 *bp - 32 : *bp; 1357 bp++; 1358 } 1359 } else { 1360 for (; rz > 0 && *bp != '\0'; --rz) 1361 *p++ = *bp++; 1362 } 1363 if (rz > 0) { 1364 otherlength = rzero = rz; 1365 flagword |= RZERO; 1366 } 1367 1368 bp = &buf[0]; 1369 1370 /* 1371 * Create the exponent in right-to-left order. 1372 * buf[0] == '0' if and only if the value being 1373 * converted is exactly zero, in which case the 1374 * exponent should be +0 regardless of exp. 1375 */ 1376 suffix = &expbuf[MAXESIZ]; 1377 *suffix = '\0'; 1378 if (buf[0] != '0') { 1379 int nn; 1380 1381 nn = exp; 1382 if (nn < 0) 1383 nn = -nn; 1384 for (; nn > 9; nn /= 10) 1385 *--suffix = todigit(nn % 10); 1386 *--suffix = todigit(nn); 1387 *--suffix = (exp >= 0) ? '+' : '-'; 1388 } else { 1389 *--suffix = '0'; 1390 *--suffix = '+'; 1391 } 1392 1393 /* put in the p */ 1394 *--suffix = (fcode == 'A') ? 'P' : 'p'; 1395 1396 /* compute size of suffix */ 1397 suffixlength = &expbuf[MAXESIZ] - suffix; 1398 otherlength += suffixlength; 1399 flagword |= SUFFIX; 1400 break; 1401 1402 case 'E': 1403 case 'e': 1404 /* 1405 * E-format. The general strategy 1406 * here is fairly easy: we take what 1407 * econvert gives us and re-format it. 1408 * (qeconvert for long double) 1409 */ 1410 1411 /* Establish default precision */ 1412 if (!(flagword & DOTSEEN)) 1413 prec = 6; 1414 1415 if (flagword & QUAD) { /* long double */ 1416 long double qval = GETQVAL(args.ap); 1417 1418 FPCONV(qeconvert, &qval, 1419 min(prec + 1, MAXECVT), &decpt, &sign, 1420 cvtbuf); 1421 } else { /* double */ 1422 double dval = va_arg(args.ap, double); 1423 1424 FPCONV(econvert, dval, 1425 min(prec + 1, MAXECVT), &decpt, &sign, 1426 cvtbuf); 1427 } 1428 bp = cvtbuf; 1429 if (*bp > '9') { 1430 inf_nan = 1; 1431 inf_nan_mixed_case = (__xpg6 & 1432 _C99SUSv3_mixed_case_Inf_and_NaN); 1433 break; 1434 } 1435 1436 /* Determine the prefix */ 1437 e_merge: 1438 if (sign) { 1439 prefix = _P_HYPHEN; 1440 prefixlength = 1; 1441 } else if (flagword & FPLUS) { 1442 prefix = _P_PLUS; 1443 prefixlength = 1; 1444 } else if (flagword & FBLANK) { 1445 prefix = _P_BLANK; 1446 prefixlength = 1; 1447 } 1448 1449 /* Place the first digit in the buffer */ 1450 p = &buf[0]; 1451 *p++ = (*bp != '\0') ? *bp++ : '0'; 1452 1453 /* Put in a decimal point if needed */ 1454 if (prec != 0 || (flagword & FSHARP)) 1455 *p++ = decimal_point; 1456 1457 /* Create the rest of the mantissa */ 1458 rz = prec; 1459 for (; rz > 0 && *bp != '\0'; --rz) 1460 *p++ = *bp++; 1461 if (rz > 0) { 1462 otherlength = rzero = rz; 1463 flagword |= RZERO; 1464 } 1465 1466 bp = &buf[0]; 1467 1468 /* 1469 * Create the exponent. buf[0] == '0' if and 1470 * only if the value being converted is exactly 1471 * zero, in which case the exponent should be 1472 * +0 regardless of decpt. 1473 */ 1474 *(suffix = &expbuf[MAXESIZ]) = '\0'; 1475 if (buf[0] != '0') { 1476 int nn = decpt - 1; 1477 if (nn < 0) 1478 nn = -nn; 1479 for (; nn > 9; nn /= 10) 1480 *--suffix = todigit(nn % 10); 1481 *--suffix = todigit(nn); 1482 } 1483 1484 /* Prepend leading zeroes to the exponent */ 1485 while (suffix > &expbuf[MAXESIZ - 2]) 1486 *--suffix = '0'; 1487 1488 /* Put in the exponent sign */ 1489 *--suffix = (decpt > 0 || buf[0] == '0') ? '+' : '-'; 1490 1491 /* Put in the e */ 1492 *--suffix = _M_ISUPPER(fcode) ? 'E' : 'e'; 1493 1494 /* compute size of suffix */ 1495 otherlength += (suffixlength = &expbuf[MAXESIZ] \ 1496 - suffix); 1497 flagword |= SUFFIX; 1498 break; 1499 1500 case 'F': 1501 case 'f': 1502 /* 1503 * F-format floating point. This is a 1504 * good deal less simple than E-format. 1505 * The overall strategy will be to call 1506 * fconvert, reformat its result into buf, 1507 * and calculate how many trailing 1508 * zeroes will be required. There will 1509 * never be any leading zeroes needed. 1510 * (qfconvert for long double) 1511 */ 1512 1513 /* Establish default precision */ 1514 if (!(flagword & DOTSEEN)) 1515 prec = 6; 1516 1517 if (flagword & QUAD) { /* long double */ 1518 long double qval = GETQVAL(args.ap); 1519 1520 FPCONV(qfconvert, &qval, min(prec, MAXFCVT), 1521 &decpt, &sign, cvtbuf); 1522 bp = cvtbuf; 1523 if (*bp == 0) { 1524 /* 1525 * qfconvert would have required 1526 * too many characters; use qeconvert 1527 * instead 1528 */ 1529 FPCONV(qeconvert, &qval, 1530 min(prec + 1, MAXECVT), &decpt, 1531 &sign, cvtbuf); 1532 goto e_merge; 1533 } 1534 } else { /* double */ 1535 double dval = va_arg(args.ap, double); 1536 1537 FPCONV(fconvert, dval, min(prec, MAXFCVT), 1538 &decpt, &sign, cvtbuf); 1539 } 1540 bp = cvtbuf; 1541 if (*bp > '9') { 1542 inf_nan = 1; 1543 if (fcode == 'f') 1544 inf_nan_mixed_case = (__xpg6 & 1545 _C99SUSv3_mixed_case_Inf_and_NaN); 1546 break; 1547 } 1548 1549 /* Determine the prefix */ 1550 f_merge: 1551 if (sign) { 1552 prefix = _P_HYPHEN; 1553 prefixlength = 1; 1554 } else if (flagword & FPLUS) { 1555 prefix = _P_PLUS; 1556 prefixlength = 1; 1557 } else if (flagword & FBLANK) { 1558 prefix = _P_BLANK; 1559 prefixlength = 1; 1560 } 1561 1562 /* Initialize buffer pointer */ 1563 p = &buf[0]; 1564 1565 { 1566 ssize_t nn = decpt; 1567 1568 /* Emit the digits before the decimal point */ 1569 k = 0; 1570 do { 1571 *p++ = (nn <= 0 || *bp == '\0' || \ 1572 k >= MAXFSIG) ? '0' : (k++, *bp++); 1573 } while (--nn > 0); 1574 1575 if (quote) 1576 p = insert_thousands_sep(buf, p); 1577 1578 /* Decide whether we need a decimal point */ 1579 if ((flagword & FSHARP) || prec > 0) 1580 *p++ = decimal_point; 1581 1582 /* Digits (if any) after the decimal point */ 1583 nn = min(prec, MAXFCVT); 1584 if (prec > nn) { 1585 flagword |= RZERO; 1586 otherlength = rzero = prec - nn; 1587 } 1588 while (--nn >= 0) 1589 *p++ = (++decpt <= 0 || *bp == '\0' || \ 1590 k >= MAXFSIG) ? '0' : (k++, *bp++); 1591 } 1592 1593 bp = &buf[0]; 1594 1595 break; 1596 1597 case 'G': 1598 case 'g': 1599 /* 1600 * g-format. We play around a bit 1601 * and then jump into e or f, as needed. 1602 */ 1603 1604 /* Establish default precision */ 1605 if (!(flagword & DOTSEEN)) 1606 prec = 6; 1607 else if (prec == 0) 1608 prec = 1; 1609 1610 if (flagword & QUAD) { /* long double */ 1611 long double qval = GETQVAL(args.ap); 1612 1613 FPCONV(qeconvert, &qval, min(prec, MAXECVT), 1614 &decpt, &sign, cvtbuf); 1615 } else { /* double */ 1616 double dval = va_arg(args.ap, double); 1617 1618 FPCONV(econvert, dval, min(prec, MAXECVT), 1619 &decpt, &sign, cvtbuf); 1620 } 1621 bp = cvtbuf; 1622 if (*bp > '9') { 1623 inf_nan = 1; 1624 inf_nan_mixed_case = (__xpg6 & 1625 _C99SUSv3_mixed_case_Inf_and_NaN); 1626 break; 1627 } 1628 if (*bp == '0') /* the value converted is zero */ 1629 decpt = 1; 1630 1631 { 1632 int kk = prec; 1633 if (!(flagword & FSHARP)) { 1634 #ifdef _WIDE 1635 n = wcslen(bp); 1636 #else /* _WIDE */ 1637 n = strlen(bp); 1638 #endif /* _WIDE */ 1639 if (n < kk) 1640 kk = (int)n; 1641 while (kk >= 1 && bp[kk-1] == '0') 1642 --kk; 1643 } 1644 if (decpt < -3 || decpt > prec) { 1645 prec = kk - 1; 1646 goto e_merge; 1647 } 1648 prec = kk - decpt; 1649 goto f_merge; 1650 } 1651 1652 case '%': 1653 buf[0] = fcode; 1654 goto c_merge; 1655 1656 #ifndef _WIDE 1657 case 'w': 1658 wflag = 1; 1659 goto charswitch; 1660 #endif /* _WIDE */ 1661 1662 1663 case 'C': /* XPG XSH4 extention */ 1664 wide_C: 1665 { 1666 wchar_t temp; 1667 1668 temp = va_arg(args.ap, wchar_t); 1669 #ifdef _WIDE 1670 if (temp) { 1671 buf[0] = temp; 1672 p = (bp = buf) + 1; 1673 } else { 1674 buf[0] = 0; 1675 p = (bp = buf) + 1; 1676 } 1677 wcount = 1; 1678 wflag = 1; 1679 #else /* _WIDE */ 1680 if (temp) { 1681 if ((retcode = wctomb(buf, temp)) 1682 == -1) { 1683 errno = EILSEQ; 1684 return (EOF); 1685 } else { 1686 p = (bp = buf) + retcode; 1687 } 1688 } else { /* NULL character */ 1689 buf[0] = 0; 1690 p = (bp = buf) + 1; 1691 } 1692 wcount = p - bp; 1693 #endif /* _WIDE */ 1694 } 1695 break; 1696 case 'c': 1697 if (lflag) { 1698 goto wide_C; 1699 } 1700 #ifndef _WIDE 1701 if (wflag) { 1702 wchar_t temp; 1703 1704 temp = va_arg(args.ap, wchar_t); 1705 if (temp) { 1706 if ((retcode = wctomb(buf, temp)) 1707 == -1) { 1708 p = (bp = buf) + 1; 1709 } else { 1710 p = (bp = buf) + retcode; 1711 } 1712 } else { /* NULL character */ 1713 buf[0] = 0; 1714 p = (bp = buf) + 1; 1715 } 1716 wcount = p - bp; 1717 } else { 1718 #endif /* _WIDE */ 1719 if (flagword & XLONG) { 1720 long long temp; 1721 temp = va_arg(args.ap, long long); 1722 #ifdef _WIDE 1723 buf[0] = (wchar_t)temp; 1724 #else /* _WIDE */ 1725 buf[0] = (char)temp; 1726 #endif /* _WIDE */ 1727 } else 1728 buf[0] = va_arg(args.ap, int); 1729 c_merge: 1730 p = (bp = &buf[0]) + 1; 1731 #ifdef _WIDE 1732 wcount = 1; 1733 wflag = 1; 1734 #endif /* _WIDE */ 1735 #ifndef _WIDE 1736 } 1737 #endif /* _WIDE */ 1738 break; 1739 1740 case 'S': /* XPG XSH4 extention */ 1741 wide_S: 1742 #ifdef _WIDE 1743 if (!lflag) { 1744 lflag++; 1745 } 1746 bp = va_arg(args.ap, wchar_t *); 1747 if (bp == NULL) 1748 bp = (wchar_t *)widenullstr; 1749 if (!(flagword & DOTSEEN)) { 1750 /* wide character handling */ 1751 prec = MAXINT; 1752 } 1753 1754 wp = bp; 1755 wcount = 0; 1756 while (*wp) { 1757 if ((prec - wcount - 1) >= 0) { 1758 wcount++; 1759 wp++; 1760 } else { 1761 break; 1762 } 1763 } 1764 p = wp; 1765 wflag = 1; 1766 break; 1767 #else /* _WIDE */ 1768 if (!wflag) 1769 wflag++; 1770 bp = va_arg(args.ap, char *); 1771 if (bp == NULL) 1772 bp = (char *)widenullstr; 1773 if (!(flagword & DOTSEEN)) { 1774 /* wide character handling */ 1775 prec = MAXINT; 1776 } 1777 1778 wp = (wchar_t *)(uintptr_t)bp; 1779 wcount = 0; 1780 while (*wp) { 1781 int nbytes; 1782 1783 nbytes = wctomb(tmpbuf, *wp); 1784 if (nbytes < 0) { 1785 errno = EILSEQ; 1786 return (EOF); 1787 } 1788 if ((prec - (wcount + nbytes)) >= 0) { 1789 wcount += nbytes; 1790 wp++; 1791 } else { 1792 break; 1793 } 1794 } 1795 sec_display = wcount; 1796 p = (char *)wp; 1797 break; 1798 #endif /* _WIDE */ 1799 case 's': 1800 if (lflag) { 1801 goto wide_S; 1802 } 1803 #ifdef _WIDE 1804 cbp = va_arg(args.ap, char *); 1805 if (cbp == NULL) 1806 cbp = (char *)nullstr; 1807 if (!(flagword & DOTSEEN)) { 1808 size_t nwc; 1809 wchar_t *wstr; 1810 1811 nwc = mbstowcs(NULL, cbp, 0); 1812 if (nwc == (size_t)-1) { 1813 errno = EILSEQ; 1814 return (EOF); 1815 } 1816 bpsize = sizeof (wchar_t) * (nwc + 1); 1817 wstr = (wchar_t *)lmalloc(bpsize); 1818 if (wstr == NULL) { 1819 errno = EILSEQ; 1820 return (EOF); 1821 } 1822 nwc = mbstowcs(wstr, cbp, MAXINT); 1823 wcount = nwc; 1824 bp = wstr; 1825 p = wstr + nwc; 1826 } else { 1827 size_t nwc; 1828 wchar_t *wstr; 1829 1830 nwc = mbstowcs(NULL, cbp, 0); 1831 if (nwc == (size_t)-1) { 1832 errno = EILSEQ; 1833 return (EOF); 1834 } 1835 if (prec > nwc) { 1836 bpsize = sizeof (wchar_t) * nwc; 1837 wstr = (wchar_t *)lmalloc(bpsize); 1838 if (wstr == NULL) { 1839 errno = ENOMEM; 1840 return (EOF); 1841 } 1842 nwc = mbstowcs(wstr, cbp, nwc); 1843 cp = cbp + strlen(cbp); 1844 wcount = nwc; 1845 bp = wstr; 1846 p = wstr + nwc; 1847 } else { 1848 size_t nnwc; 1849 int len; 1850 char *s; 1851 wchar_t *wstr; 1852 1853 bpsize = sizeof (wchar_t) * prec; 1854 wstr = (wchar_t *)lmalloc(bpsize); 1855 if (wstr == NULL) { 1856 errno = ENOMEM; 1857 return (EOF); 1858 } 1859 nwc = mbstowcs(wstr, cbp, prec); 1860 wcount = prec; 1861 bp = wstr; 1862 p = wstr + nwc; 1863 } 1864 } 1865 wflag = 1; 1866 #else /* _WIDE */ 1867 bp = va_arg(args.ap, char *); 1868 if (bp == NULL) 1869 bp = (char *)nullstr; 1870 if (!(flagword & DOTSEEN)) { 1871 if (wflag) { 1872 /* wide character handling */ 1873 prec = MAXINT; 1874 goto wide_hand; 1875 } 1876 1877 1878 p = bp + strlen(bp); 1879 1880 /* 1881 * sec_display only needed if width 1882 * is specified (ie, "%<width>s") 1883 * Solaris behavior counts <width> in 1884 * screen column width. (If XPG4 behavior, 1885 * <width> is counted in bytes.) 1886 */ 1887 if (width > 0 && __xpg4 == 0 && 1888 MB_CUR_MAX > 1) { 1889 #define NW 256 1890 wchar_t wbuff[NW]; 1891 wchar_t *wp, *wptr; 1892 size_t wpsize; 1893 size_t nwc; 1894 1895 wp = NULL; 1896 if ((nwc = mbstowcs(wbuff, bp, 1897 NW)) == (size_t)-1) { 1898 /* Estimate width */ 1899 sec_display = strlen(bp); 1900 goto mbs_err; 1901 } 1902 if (nwc < NW) { 1903 wptr = wbuff; 1904 } else { 1905 /* 1906 * If widechar does not fit into 1907 * wbuff, allocate larger buffer 1908 */ 1909 if ((nwc = 1910 mbstowcs(NULL, bp, NULL)) == 1911 (size_t)-1) { 1912 sec_display = 1913 strlen(bp); 1914 goto mbs_err; 1915 } 1916 wpsize = (nwc + 1) * 1917 sizeof (wchar_t); 1918 if ((wp = lmalloc(wpsize)) 1919 == NULL) { 1920 errno = ENOMEM; 1921 return (EOF); 1922 } 1923 if ((nwc = mbstowcs(wp, 1924 bp, nwc)) == (size_t)-1) { 1925 sec_display = \ 1926 strlen(bp); 1927 goto mbs_err; 1928 } 1929 wptr = wp; 1930 } 1931 if ((sec_display = wcswidth(wptr, nwc)) 1932 == -1) { 1933 sec_display = 1934 _rec_scrswidth 1935 (wptr, nwc); 1936 } 1937 mbs_err: 1938 if (wp) 1939 lfree(wp, wpsize); 1940 } 1941 } else { /* a strnlen function would be useful here! */ 1942 /* 1943 * If we've seen a dot, and count has been set 1944 * to 0, then we don't output in any cases 1945 * below. prec should be always >= 0. So we only 1946 * check to see if it's zero. 1947 */ 1948 if (prec == 0) { 1949 p = bp; 1950 break; 1951 } 1952 1953 if (wflag) { 1954 /* wide character handling */ 1955 1956 wide_hand: 1957 wp = (wchar_t *)(uintptr_t)bp; 1958 preco = prec; 1959 wcount = 0; 1960 while (*wp && 1961 (prec -= _scrwidth(*wp)) >= 0) { 1962 if ((retcode = 1963 wctomb(tmpbuf, *wp)) < 0) 1964 wcount++; 1965 else 1966 wcount += retcode; 1967 wp++; 1968 } 1969 if (*wp) 1970 prec += _scrwidth(*wp); 1971 p = (char *)wp; 1972 sec_display = preco - prec; 1973 } else if (__xpg4 == 0 && MB_CUR_MAX > 1) { 1974 /* 1975 * Solaris behavior - count 1976 * precision as screen column width 1977 */ 1978 char *qp = bp; 1979 int ncol, nbytes; 1980 wchar_t wc; 1981 1982 ncol = 0; 1983 preco = prec; 1984 while (*qp) { 1985 if (isascii(*qp)) { 1986 qp++; 1987 if (--prec == 0) 1988 break; 1989 continue; 1990 } 1991 if ((nbytes = mbtowc(&wc, qp, 1992 MB_LEN_MAX)) == -1) { 1993 /* print illegal char */ 1994 nbytes = 1; 1995 ncol = 1; 1996 } else { 1997 if ((ncol = 1998 _scrwidth(wc)) 1999 == 0) { 2000 ncol = 1; 2001 } 2002 } 2003 2004 if ((prec -= ncol) >= 0) { 2005 qp += nbytes; 2006 if (prec == 0) 2007 break; 2008 } else { 2009 break; 2010 } 2011 } 2012 if (prec < 0) 2013 prec += ncol; 2014 p = qp; 2015 sec_display = preco - prec; 2016 } else { 2017 /* 2018 * XPG4 behavior - count 2019 * precision as bytes. 2020 * We don't use strlen() because 2021 * the given char string may not 2022 * be null-terminated. 2023 */ 2024 char *qp; 2025 2026 qp = memchr(bp, '\0', prec); 2027 if (qp == NULL) { 2028 p = bp + prec; 2029 } else { 2030 p = qp; 2031 } 2032 } 2033 } 2034 #endif /* _WIDE */ 2035 break; 2036 2037 case 'n': 2038 { 2039 if (flagword & XLONG) { 2040 long long *svcount; 2041 svcount = va_arg(args.ap, long long *); 2042 *svcount = (long long)count; 2043 } else if (flagword & LENGTH) { 2044 long *svcount; 2045 svcount = va_arg(args.ap, long *); 2046 *svcount = (long)count; 2047 } else if (flagword & SHORT) { 2048 short *svcount; 2049 svcount = va_arg(args.ap, short *); 2050 *svcount = (short)count; 2051 } else if (flagword & CHAR) { 2052 char *svcount; 2053 svcount = va_arg(args.ap, char *); 2054 *svcount = (char)count; 2055 } else { 2056 int *svcount; 2057 svcount = va_arg(args.ap, int *); 2058 *svcount = count; 2059 } 2060 continue; 2061 } 2062 default: /* this is technically an error; what we do is to */ 2063 /* back up the format pointer to the offending char */ 2064 /* and continue with the format scan */ 2065 format--; 2066 continue; 2067 } 2068 2069 if (inf_nan) { 2070 if (inf_nan_mixed_case) { 2071 /* advance p */ 2072 for (p = bp + 1; *p != '\0'; p++) 2073 ; 2074 } else { 2075 int upper; 2076 2077 /* advance p and make output all one case */ 2078 upper = _M_ISUPPER(fcode); 2079 for (p = bp; *p != '\0'; p++) 2080 *p = upper? toupper(*p) : tolower(*p); 2081 } 2082 if (sign) { 2083 prefix = _P_HYPHEN; 2084 prefixlength = 1; 2085 } else if (flagword & FPLUS) { 2086 prefix = _P_PLUS; 2087 prefixlength = 1; 2088 } else if (flagword & FBLANK) { 2089 prefix = _P_BLANK; 2090 prefixlength = 1; 2091 } 2092 inf_nan = 0; 2093 inf_nan_mixed_case = 0; 2094 flagword &= ~PADZERO; /* ignore 0 flag */ 2095 } 2096 2097 /* Calculate number of padding blanks */ 2098 n = p - bp; /* n == size of the converted value (in bytes) */ 2099 2100 #ifdef _WIDE 2101 k = n; 2102 #else /* _WIDE */ 2103 if (sec_display) /* when format is %s or %ws or %S */ 2104 k = sec_display; 2105 else 2106 k = n; 2107 #endif /* _WIDE */ 2108 /* 2109 * k is the (screen) width or # of bytes of the converted value 2110 */ 2111 k += prefixlength + otherlength; 2112 2113 #ifdef _WIDE 2114 if (wflag) { 2115 count += wcount; 2116 } else { 2117 count += n; 2118 } 2119 #else /* _WIDE */ 2120 /* 2121 * update count which is the overall size of the output data 2122 * and passed to memchr() 2123 */ 2124 if (wflag) 2125 /* 2126 * when wflag != 0 (i.e. %ws or %wc), the size of the 2127 * converted value is wcount bytes 2128 */ 2129 count += wcount; 2130 else 2131 /* 2132 * when wflag == 0, the size of the converted 2133 * value is n (= p-bp) bytes 2134 */ 2135 count += n; 2136 #endif /* _WIDE */ 2137 count += prefixlength + otherlength; 2138 2139 if (width > k) { 2140 count += (width - k); 2141 /* 2142 * Set up for padding zeroes if requested 2143 * Otherwise emit padding blanks unless output is 2144 * to be left-justified. 2145 */ 2146 2147 if (flagword & PADZERO) { 2148 if (!(flagword & LZERO)) { 2149 flagword |= LZERO; 2150 lzero = width - k; 2151 } else 2152 lzero += width - k; 2153 k = width; /* cancel padding blanks */ 2154 } else 2155 /* Blanks on left if required */ 2156 if (!(flagword & FMINUS)) 2157 PAD(_blanks, width - k); 2158 } 2159 2160 /* Prefix, if any */ 2161 if (prefixlength != 0) 2162 PUT(prefix, prefixlength); 2163 2164 /* Zeroes on the left */ 2165 if ((flagword & LZERO)) /* && */ 2166 /* (!(flagword & SHORT) || !(flagword & FMINUS)) */ 2167 PAD(_zeroes, lzero); 2168 2169 #ifdef _WIDE 2170 if (n > 0) 2171 PUT(bp, n); 2172 if ((fcode == 's') && !lflag) { 2173 if (bp) 2174 lfree(bp, bpsize); 2175 } 2176 #else /* _WIDE */ 2177 /* The value itself */ 2178 if ((fcode == 's' || fcode == 'S') && wflag) { 2179 /* wide character handling */ 2180 wchar_t *wp = (wchar_t *)(uintptr_t)bp; 2181 int cnt; 2182 char *bufp; 2183 long printn; 2184 printn = (wchar_t *)(uintptr_t)p - 2185 (wchar_t *)(uintptr_t)bp; 2186 bufp = buf; 2187 while (printn > 0) { 2188 if ((cnt = wctomb(buf, *wp)) < 0) 2189 cnt = 1; 2190 PUT(bufp, cnt); 2191 wp++; 2192 printn--; 2193 } 2194 } else { /* non wide character value */ 2195 if (n > 0) 2196 PUT(bp, n); 2197 } 2198 #endif /* _WIDE */ 2199 2200 if (flagword & (RZERO | SUFFIX | FMINUS)) { 2201 /* Zeroes on the right */ 2202 if (flagword & RZERO) 2203 PAD(_zeroes, rzero); 2204 2205 /* The suffix */ 2206 if (flagword & SUFFIX) 2207 PUT(suffix, suffixlength); 2208 2209 /* Blanks on the right if required */ 2210 if (flagword & FMINUS && width > k) 2211 PAD(_blanks, width - k); 2212 } 2213 } 2214 } 2215 2216 #ifdef _WIDE 2217 static int 2218 _watoi(wchar_t *fmt) 2219 { 2220 int n = 0; 2221 wchar_t ch; 2222 2223 ch = *fmt; 2224 if (_M_ISDIGIT(ch)) { 2225 n = ch - '0'; 2226 ch = *++fmt; 2227 while (_M_ISDIGIT(ch)) { 2228 n *= 10; 2229 n += ch - '0'; 2230 ch = *++fmt; 2231 } 2232 } 2233 return (n); 2234 } 2235 #endif /* _WIDE */ 2236 2237 /* 2238 * This function initializes arglst, to contain the appropriate va_list values 2239 * for the first MAXARGS arguments. 2240 */ 2241 2242 /* 2243 * Type modifier flags: 2244 * 0x01 for long 2245 * 0x02 for int 2246 * 0x04 for long long 2247 * 0x08 for long double 2248 */ 2249 2250 #define FLAG_LONG 0x01 2251 #define FLAG_INT 0x02 2252 #define FLAG_LONG_LONG 0x04 2253 #define FLAG_LONG_DBL 0x08 2254 2255 /* ARGSUSED3 */ 2256 #ifdef _WIDE 2257 static void 2258 _wmkarglst(wchar_t *fmt, stva_list args, stva_list arglst[], int prflag) 2259 #else /* _WIDE */ 2260 static void 2261 _mkarglst(char *fmt, stva_list args, stva_list arglst[], int prflag) 2262 #endif /* _WIDE */ 2263 { 2264 #ifdef _WIDE 2265 static const wchar_t digits[] = L"01234567890"; 2266 static const wchar_t skips[] = L"# +-.'0123456789h$"; 2267 #else /* _WIDE */ 2268 static const char digits[] = "01234567890"; 2269 static const char skips[] = "# +-.'0123456789h$"; 2270 #endif /* _WIDE */ 2271 enum types {INT = 1, LONG, CHAR_PTR, DOUBLE, LONG_DOUBLE, VOID_PTR, 2272 LONG_PTR, INT_PTR, LONG_LONG, LONG_LONG_PTR}; 2273 enum types typelst[MAXARGS], curtype; 2274 ssize_t n; 2275 int maxnum, curargno, flags; 2276 2277 /* 2278 * Algorithm 1. set all argument types to zero. 2279 * 2. walk through fmt putting arg types in typelst[]. 2280 * 3. walk through args using va_arg(args.ap, typelst[n]) 2281 * and set arglst[] to the appropriate values. 2282 * Assumptions: Cannot use %*$... to specify variable position. 2283 */ 2284 2285 (void) memset((void *) typelst, 0, sizeof (typelst)); 2286 maxnum = -1; 2287 curargno = 0; 2288 while ((fmt = STRCHR(fmt, '%')) != 0) { 2289 fmt++; /* skip % */ 2290 if (fmt[n = STRSPN(fmt, digits)] == '$') { 2291 /* convert to zero base */ 2292 curargno = ATOI(fmt) - 1; 2293 if (curargno < 0) 2294 continue; 2295 fmt += n + 1; 2296 } 2297 flags = 0; 2298 again:; 2299 fmt += STRSPN(fmt, skips); 2300 switch (*fmt++) { 2301 case '%': /* there is no argument! */ 2302 continue; 2303 case 'l': 2304 if (flags & (FLAG_LONG | FLAG_LONG_LONG)) { 2305 flags |= FLAG_LONG_LONG; 2306 flags &= ~FLAG_LONG; 2307 } else { 2308 flags |= FLAG_LONG; 2309 } 2310 goto again; 2311 case 'j': 2312 #ifndef _LP64 2313 /* 2314 * *printf_c89() in 32-bit libc uses 2315 * 32-bit intmax_t; otherwise intmax_t 2316 * is 64-bits. 2317 */ 2318 if (!(prflag & _F_INTMAX32)) { 2319 #endif 2320 flags |= FLAG_LONG_LONG; /* 64-bit */ 2321 #ifndef _LP64 2322 } 2323 #endif 2324 goto again; 2325 case 't': 2326 flags |= FLAG_LONG; 2327 goto again; 2328 case 'z': 2329 flags |= FLAG_LONG; 2330 goto again; 2331 case 'L': 2332 flags |= FLAG_LONG_DBL; 2333 goto again; 2334 case '*': /* int argument used for value */ 2335 /* check if there is a positional parameter */ 2336 #ifdef _WIDE 2337 if ((*fmt >= 0) && (*fmt < 256) && 2338 isdigit(*fmt)) 2339 #else /* _WIDE */ 2340 if (isdigit(*fmt)) 2341 #endif /* _WIDE */ 2342 { 2343 int targno; 2344 targno = ATOI(fmt) - 1; 2345 fmt += STRSPN(fmt, digits); 2346 if (*fmt == '$') 2347 fmt++; /* skip '$' */ 2348 if (targno >= 0 && targno < MAXARGS) { 2349 typelst[targno] = INT; 2350 if (maxnum < targno) 2351 maxnum = targno; 2352 } 2353 goto again; 2354 } 2355 flags |= FLAG_INT; 2356 curtype = INT; 2357 break; 2358 case 'a': 2359 case 'A': 2360 case 'e': 2361 case 'E': 2362 case 'f': 2363 case 'F': 2364 case 'g': 2365 case 'G': 2366 if (flags & FLAG_LONG_DBL) 2367 curtype = LONG_DOUBLE; 2368 else 2369 curtype = DOUBLE; 2370 break; 2371 case 's': 2372 curtype = CHAR_PTR; 2373 break; 2374 case 'p': 2375 curtype = VOID_PTR; 2376 break; 2377 case 'n': 2378 if (flags & FLAG_LONG_LONG) 2379 curtype = LONG_LONG_PTR; 2380 else if (flags & FLAG_LONG) 2381 curtype = LONG_PTR; 2382 else 2383 curtype = INT_PTR; 2384 break; 2385 default: 2386 if (flags & FLAG_LONG_LONG) 2387 curtype = LONG_LONG; 2388 else if (flags & FLAG_LONG) 2389 curtype = LONG; 2390 else 2391 curtype = INT; 2392 break; 2393 } 2394 if (curargno >= 0 && curargno < MAXARGS) { 2395 typelst[curargno] = curtype; 2396 if (maxnum < curargno) 2397 maxnum = curargno; 2398 } 2399 curargno++; /* default to next in list */ 2400 if (flags & FLAG_INT) /* took care of *, keep going */ 2401 { 2402 flags ^= FLAG_INT; 2403 goto again; 2404 } 2405 } 2406 for (n = 0; n <= maxnum; n++) { 2407 arglst[n] = args; 2408 if (typelst[n] == 0) 2409 typelst[n] = INT; 2410 2411 switch (typelst[n]) { 2412 case INT: 2413 (void) va_arg(args.ap, int); 2414 break; 2415 case LONG: 2416 (void) va_arg(args.ap, long); 2417 break; 2418 case CHAR_PTR: 2419 (void) va_arg(args.ap, char *); 2420 break; 2421 case DOUBLE: 2422 (void) va_arg(args.ap, double); 2423 break; 2424 case LONG_DOUBLE: 2425 (void) GETQVAL(args.ap); 2426 break; 2427 case VOID_PTR: 2428 (void) va_arg(args.ap, void *); 2429 break; 2430 case LONG_PTR: 2431 (void) va_arg(args.ap, long *); 2432 break; 2433 case INT_PTR: 2434 (void) va_arg(args.ap, int *); 2435 break; 2436 case LONG_LONG: 2437 (void) va_arg(args.ap, long long); 2438 break; 2439 case LONG_LONG_PTR: 2440 (void) va_arg(args.ap, long long *); 2441 break; 2442 } 2443 } 2444 } 2445 2446 /* 2447 * This function is used to find the va_list value for arguments whose 2448 * position is greater than MAXARGS. This function is slow, so hopefully 2449 * MAXARGS will be big enough so that this function need only be called in 2450 * unusual circumstances. 2451 * pargs is assumed to contain the value of arglst[MAXARGS - 1]. 2452 */ 2453 /* ARGSUSED3 */ 2454 #ifdef _WIDE 2455 static void 2456 _wgetarg(wchar_t *fmt, stva_list *pargs, long argno, int prflag) 2457 #else /* _WIDE */ 2458 void 2459 _getarg(char *fmt, stva_list *pargs, long argno, int prflag) 2460 #endif /* _WIDE */ 2461 { 2462 2463 #ifdef _WIDE 2464 static const wchar_t digits[] = L"01234567890"; 2465 static const wchar_t skips[] = L"# +-.'0123456789h$"; 2466 wchar_t *sfmt = fmt; 2467 #else /* _WIDE */ 2468 static const char digits[] = "01234567890"; 2469 static const char skips[] = "# +-.'0123456789h$"; 2470 char *sfmt = fmt; 2471 #endif /* _WIDE */ 2472 ssize_t n; 2473 int i, curargno, flags; 2474 int found = 1; 2475 2476 i = MAXARGS; 2477 curargno = 1; 2478 while (found) { 2479 fmt = sfmt; 2480 found = 0; 2481 while ((i != argno) && (fmt = STRCHR(fmt, '%')) != 0) { 2482 fmt++; /* skip % */ 2483 if (fmt[n = STRSPN(fmt, digits)] == '$') { 2484 curargno = ATOI(fmt); 2485 if (curargno <= 0) 2486 continue; 2487 fmt += n + 1; 2488 } 2489 2490 /* find conversion specifier for next argument */ 2491 if (i != curargno) { 2492 curargno++; 2493 continue; 2494 } else 2495 found = 1; 2496 flags = 0; 2497 again:; 2498 fmt += STRSPN(fmt, skips); 2499 switch (*fmt++) { 2500 case '%': /* there is no argument! */ 2501 continue; 2502 case 'l': 2503 if (flags & (FLAG_LONG | FLAG_LONG_LONG)) { 2504 flags |= FLAG_LONG_LONG; 2505 flags &= ~FLAG_LONG; 2506 } else { 2507 flags |= FLAG_LONG; 2508 } 2509 goto again; 2510 case 'j': 2511 #ifndef _LP64 2512 /* 2513 * *printf_c89() in 32-bit libc uses 2514 * 32-bit intmax_t; otherwise intmax_t 2515 * is 64-bits. 2516 */ 2517 if (!(prflag & _F_INTMAX32)) { 2518 #endif 2519 flags |= FLAG_LONG_LONG; /* 64-bit */ 2520 #ifndef _LP64 2521 } 2522 #endif 2523 goto again; 2524 case 't': 2525 flags |= FLAG_LONG; 2526 goto again; 2527 case 'z': 2528 flags |= FLAG_LONG; 2529 goto again; 2530 case 'L': 2531 flags |= FLAG_LONG_DBL; 2532 goto again; 2533 case '*': /* int argument used for value */ 2534 /* 2535 * check if there is a positional parameter; 2536 * if so, just skip it; its size will be 2537 * correctly determined by default 2538 */ 2539 if (_M_ISDIGIT(*fmt)) { 2540 fmt += STRSPN(fmt, digits); 2541 if (*fmt == '$') 2542 fmt++; /* skip '$' */ 2543 goto again; 2544 } 2545 flags |= FLAG_INT; 2546 (void) va_arg((*pargs).ap, int); 2547 break; 2548 case 'a': 2549 case 'A': 2550 case 'e': 2551 case 'E': 2552 case 'f': 2553 case 'F': 2554 case 'g': 2555 case 'G': 2556 if (flags & FLAG_LONG_DBL) 2557 (void) GETQVAL((*pargs).ap); 2558 else 2559 (void) va_arg((*pargs).ap, double); 2560 break; 2561 case 's': 2562 (void) va_arg((*pargs).ap, char *); 2563 break; 2564 case 'p': 2565 (void) va_arg((*pargs).ap, void *); 2566 break; 2567 case 'n': 2568 if (flags & FLAG_LONG_LONG) 2569 (void) va_arg((*pargs).ap, long long *); 2570 else if (flags & FLAG_LONG) 2571 (void) va_arg((*pargs).ap, long *); 2572 else 2573 (void) va_arg((*pargs).ap, int *); 2574 break; 2575 default: 2576 if (flags & FLAG_LONG_LONG) 2577 (void) va_arg((*pargs).ap, long long); 2578 else if (flags & FLAG_LONG) 2579 (void) va_arg((*pargs).ap, long int); 2580 else 2581 (void) va_arg((*pargs).ap, int); 2582 break; 2583 } 2584 i++; 2585 curargno++; /* default to next in list */ 2586 if (flags & FLAG_INT) /* took care of *, keep going */ 2587 { 2588 flags ^= FLAG_INT; 2589 goto again; 2590 } 2591 } 2592 2593 /* missing specifier for parameter, assume param is an int */ 2594 if (!found && i != argno) { 2595 (void) va_arg((*pargs).ap, int); 2596 i++; 2597 curargno = i; 2598 found = 1; 2599 } 2600 } 2601 } 2602 2603 #ifdef _WIDE 2604 static wchar_t * 2605 insert_thousands_sep(wchar_t *bp, wchar_t *ep) 2606 #else /* _WIDE */ 2607 static char * 2608 insert_thousands_sep(char *bp, char *ep) 2609 #endif /* _WIDE */ 2610 { 2611 char thousep; 2612 struct lconv *locptr; 2613 ssize_t buf_index; 2614 int i; 2615 #ifdef _WIDE 2616 wchar_t *obp = bp; 2617 wchar_t buf[371]; 2618 wchar_t *bufptr = buf; 2619 #else /* _WIDE */ 2620 char *obp = bp; 2621 char buf[371]; 2622 char *bufptr = buf; 2623 #endif /* _WIDE */ 2624 char *grp_ptr; 2625 2626 /* get the thousands sep. from the current locale */ 2627 locptr = localeconv(); 2628 thousep = *locptr->thousands_sep; 2629 grp_ptr = locptr->grouping; 2630 2631 /* thousands sep. not use in this locale or no grouping required */ 2632 if (!thousep || (*grp_ptr == '\0')) 2633 return (ep); 2634 2635 buf_index = ep - bp; 2636 for (;;) { 2637 if (*grp_ptr == CHAR_MAX) { 2638 for (i = 0; i < buf_index--; i++) 2639 *bufptr++ = *(bp + buf_index); 2640 break; 2641 } 2642 for (i = 0; i < *grp_ptr && buf_index-- > 0; i++) 2643 *bufptr++ = *(bp + buf_index); 2644 2645 if (buf_index > 0) { 2646 #ifdef _WIDE 2647 *bufptr++ = (wchar_t)thousep; 2648 #else /* _WIDE */ 2649 *bufptr++ = thousep; 2650 #endif /* _WIDE */ 2651 ep++; 2652 } 2653 else 2654 break; 2655 if (*(grp_ptr + 1) != '\0') 2656 ++grp_ptr; 2657 } 2658 2659 /* put the string in the caller's buffer in reverse order */ 2660 --bufptr; 2661 while (buf <= bufptr) 2662 *obp++ = *bufptr--; 2663 return (ep); 2664 } 2665 2666 2667 /* 2668 * Recovery scrswidth function - 2669 * this variant of wcswidth() accepts non-printable or illegal 2670 * widechar characters. 2671 */ 2672 static int 2673 _rec_scrswidth(wchar_t *wp, ssize_t n) 2674 { 2675 int col; 2676 int i; 2677 2678 col = 0; 2679 while (*wp && (n-- > 0)) { 2680 if ((i = _scrwidth(*wp++)) == 0) 2681 i = 1; 2682 col += i; 2683 } 2684 return (col); 2685 } 2686