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