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