1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * _doprnt: common code for printf, fprintf, sprintf 32 */ 33 34 #include "lint.h" 35 #include "mtlib.h" 36 #include "print.h" /* parameters & macros for doprnt */ 37 #include <wchar.h> 38 #include "libc.h" 39 #include <stdlib.h> 40 #include <limits.h> 41 #include <ctype.h> 42 #include <stdarg.h> 43 #include <values.h> 44 #include <memory.h> 45 #include <string.h> 46 #include <locale.h> 47 #include <widec.h> 48 #include "../i18n/_locale.h" 49 #include <errno.h> 50 #include <sys/types.h> 51 #include <libw.h> 52 #include "mse.h" 53 #include "xpg6.h" 54 55 static const char nullstr[] = "(null)"; 56 static const wchar_t widenullstr[] = L"(null)"; 57 58 #if defined(__i386) || defined(__amd64) || defined(__sparcv9) 59 #define GETQVAL(arg) (va_arg(arg, long double)) 60 #else /* !defined(__i386) && !defined(__sparcv9) */ 61 #define GETQVAL(arg) *(va_arg(arg, long double *)) 62 #endif /* !defined(__i386) && !defined(__sparcv9) */ 63 64 #ifdef _WIDE 65 #define STRCHR wcschr 66 #define STRSPN wcsspn 67 #define ATOI(x) _watoi((wchar_t *)x) 68 #define _P_HYPHEN L"-" 69 #define _P_PLUS L"+" 70 #define _P_BLANK L" " 71 #define _P_ZEROx L"0x" 72 #define _P_ZEROX L"0X" 73 #define _M_ISDIGIT(c) (((c) >= 0) && ((c) < 256) && isdigit((c))) 74 #define _M_ISUPPER(c) (((c) >= 0) && ((c) < 256) && isupper((c))) 75 #else /* _WIDE */ 76 #define STRCHR strchr 77 #define STRSPN strspn 78 #define ATOI(x) atoi(x) 79 #define _P_HYPHEN "-" 80 #define _P_PLUS "+" 81 #define _P_BLANK " " 82 #define _P_ZEROx "0x" 83 #define _P_ZEROX "0X" 84 #define _M_ISDIGIT(c) isdigit((c)) 85 #define _M_ISUPPER(c) isupper((c)) 86 #endif /* _WIDE */ 87 88 #ifdef _WIDE 89 #define PUT(p, n) \ 90 { \ 91 int retp; \ 92 retp = put_wide(iop, &bufptr, bufferend, p, n, sflag); \ 93 if (retp == EOF) { \ 94 return ((ssize_t)EOF); \ 95 } \ 96 } 97 98 #define PAD(s, n) \ 99 { \ 100 int retp; \ 101 retp = pad_wide(iop, &bufptr, bufferend, s, n, sflag); \ 102 if (retp == EOF) { \ 103 return ((ssize_t)EOF); \ 104 } \ 105 } 106 107 #define FPCONV(func, val, prec, decpt, sign, cvtbuf) \ 108 { \ 109 char cb[DECIMAL_STRING_LENGTH]; \ 110 wchar_t *wp; \ 111 char *cp; \ 112 (void) func(val, prec, decpt, sign, cb); \ 113 wp = cvtbuf; \ 114 cp = cb; \ 115 while (*cp) { \ 116 *wp++ = (wchar_t)*cp++; \ 117 } \ 118 *wp = L'\0'; \ 119 } 120 121 #else /* _WIDE */ 122 #define PUT(p, n) \ 123 {\ 124 /*\ 125 * When _doprnt() is called by [v]snprintf, we need to \ 126 * always call _dowrite(). We also need to call _dowrite() \ 127 * if the bufptr lies beyond the end of the buffer. This \ 128 * is possible due to known off-by-one errors in __flsbuf() \ 129 * and _fwrite_unlocked(). See 1235867 and 1231720 for the \ 130 * sordid details. \ 131 */\ 132 if (snflag || bufptr > bufferend ||\ 133 (unsigned long)(bufferend - bufptr) < (n)) {\ 134 if (!_dowrite(p, n, iop, &bufptr)) {\ 135 return (EOF);\ 136 }\ 137 } else {\ 138 unsigned char *fbp = bufptr;\ 139 switch (n) {\ 140 case 4:\ 141 *fbp = *p;\ 142 *(fbp + 1) = *(p + 1);\ 143 *(fbp + 2) = *(p + 2);\ 144 *(fbp + 3) = *(p + 3);\ 145 bufptr += 4;\ 146 break;\ 147 case 3:\ 148 *fbp = *p;\ 149 *(fbp + 1) = *(p + 1);\ 150 *(fbp + 2) = *(p + 2);\ 151 bufptr += 3;\ 152 break;\ 153 case 2:\ 154 *fbp = *p;\ 155 *(fbp + 1) = *(p + 1);\ 156 bufptr += 2;\ 157 break;\ 158 case 1:\ 159 *bufptr++ = *p;\ 160 break;\ 161 default:\ 162 bufptr = (unsigned char *)memcpy(fbp, p, n)\ 163 + (n);\ 164 }\ 165 }\ 166 } 167 168 #define PAD(s, n) { ssize_t nn; \ 169 for (nn = n; nn > PAD_LEN; nn -= PAD_LEN) \ 170 if (!_dowrite(s, PAD_LEN, iop, &bufptr)) \ 171 return (EOF); \ 172 PUT(s, nn); \ 173 } 174 175 #define FPCONV(func, val, prec, decpt, sign, cvtbuf) \ 176 (void) func(val, prec, decpt, sign, cvtbuf); 177 178 #endif /* _WIDE */ 179 180 /* bit positions for flags used in doprnt */ 181 182 #define LENGTH 0x1 /* l */ 183 #define FPLUS 0x2 /* + */ 184 #define FMINUS 0x4 /* - */ 185 #define FBLANK 0x8 /* blank */ 186 #define FSHARP 0x10 /* # */ 187 #define PADZERO 0x20 /* padding zeroes requested via '0' */ 188 #define DOTSEEN 0x40 /* dot appeared in format specification */ 189 #define SUFFIX 0x80 /* a suffix is to appear in the output */ 190 #define RZERO 0x100 /* there will be trailing zeros in output */ 191 #define LZERO 0x200 /* there will be leading zeroes in output */ 192 #define SHORT 0x400 /* h */ 193 #define QUAD 0x800 /* Q for long double */ 194 #define XLONG 0x1000 /* ll for long long */ 195 #define CHAR 0x2000 /* hh for char */ 196 197 #ifdef _WIDE 198 static wchar_t * 199 insert_thousands_sep(wchar_t *bp, wchar_t *ep); 200 #else /* _WIDE */ 201 static char * 202 insert_thousands_sep(char *bp, char *ep); 203 #endif /* _WIDE */ 204 205 static int _rec_scrswidth(wchar_t *, ssize_t); 206 207 /* 208 * Positional Parameter information 209 */ 210 #define MAXARGS 30 /* max. number of args for fast positional paramters */ 211 212 static ssize_t 213 _dowrite(const char *p, ssize_t n, FILE *iop, unsigned char **ptrptr); 214 215 /* 216 * stva_list is used to subvert C's restriction that a variable with an 217 * array type can not appear on the left hand side of an assignment operator. 218 * By putting the array inside a structure, the functionality of assigning to 219 * the whole array through a simple assignment is achieved.. 220 */ 221 typedef struct stva_list { 222 va_list ap; 223 } stva_list; 224 225 #ifdef _WIDE 226 static void _wmkarglst(wchar_t *, stva_list, stva_list [], int); 227 static void _wgetarg(wchar_t *, stva_list *, long, int); 228 #else /* _WIDE */ 229 static void _mkarglst(char *, stva_list, stva_list [], int); 230 void _getarg(char *, stva_list *, long, int); 231 #endif /* _WIDE */ 232 233 234 235 236 static int 237 _lowdigit(ssize_t *valptr) 238 { 239 /* This function computes the decimal low-order digit of the number */ 240 /* pointed to by valptr, and returns this digit after dividing */ 241 /* *valptr by ten. This function is called ONLY to compute the */ 242 /* low-order digit of a long whose high-order bit is set. */ 243 244 ssize_t lowbit = *valptr & 1; 245 long value = (*valptr >> 1) & ~HIBITL; 246 247 *valptr = value / 5; 248 value = value % 5 * 2 + lowbit + '0'; 249 return ((int)value); 250 } 251 252 static int 253 _lowlldigit(long long *valptr) 254 { 255 ssize_t lowbit = *valptr & 1; 256 long long value = (*valptr >> 1) & ~HIBITLL; 257 *valptr = value / 5; 258 value = value % 5 * 2 + lowbit + '0'; 259 return ((int)value); 260 } 261 262 /* The function _dowrite carries out buffer pointer bookkeeping surrounding */ 263 /* a call to fwrite. It is called only when the end of the file output */ 264 /* buffer is approached or in other unusual situations. */ 265 266 static ssize_t 267 _dowrite(const char *p, ssize_t n, FILE *iop, unsigned char **ptrptr) 268 { 269 if (!(iop->_flag & _IOREAD)) { 270 iop->_cnt -= (*ptrptr - iop->_ptr); 271 iop->_ptr = *ptrptr; 272 _bufsync(iop, _bufend(iop)); 273 if (_FWRITE(p, 1, n, iop) != n) { 274 return (0); 275 } 276 *ptrptr = iop->_ptr; 277 } else { 278 if (n > iop->_cnt) 279 n = iop->_cnt; 280 iop->_cnt -= n; 281 *ptrptr = (unsigned char *)memcpy((char *)*ptrptr, p, n) + n; 282 iop->_ptr = *ptrptr; 283 } 284 return (1); 285 } 286 287 #define PAD_LEN 20 288 static const char _blanks[] = " "; 289 static const char _zeroes[] = "00000000000000000000"; 290 #ifdef _WIDE 291 static const wchar_t uc_digs[] = L"0123456789ABCDEF"; 292 static const wchar_t lc_digs[] = L"0123456789abcdef"; 293 #else /* _WIDE */ 294 static const char uc_digs[] = "0123456789ABCDEF"; 295 static const char lc_digs[] = "0123456789abcdef"; 296 #endif /* _WIDE */ 297 298 #ifdef _WIDE 299 static int 300 put_wide(FILE *iop, unsigned char **bufptr, 301 unsigned char *bufferend, wchar_t *p, size_t n, 302 int sflag) 303 { 304 unsigned char *newbufptr; 305 wchar_t *q; 306 int r; 307 size_t len, i; 308 309 if (sflag) { 310 len = (wchar_t *)bufferend - (wchar_t *)*bufptr; 311 if (n > len) { 312 (void) wmemcpy((wchar_t *)*bufptr, p, len); 313 iop->_ptr = bufferend; 314 return (EOF); 315 } else { 316 (void) wmemcpy((wchar_t *)*bufptr, p, n); 317 *bufptr = (unsigned char *)((wchar_t *)*bufptr + n); 318 return (0); 319 } 320 } else { 321 char *tmpp, *tmpq; 322 size_t tsize; 323 324 tsize = (n + 1) * MB_LEN_MAX; 325 tmpp = lmalloc(tsize); 326 if (tmpp == NULL) { 327 errno = ENOMEM; 328 return (EOF); 329 } 330 q = p; 331 tmpq = tmpp; 332 for (len = 0, i = 0; i < n; i++) { 333 r = wctomb(tmpq, *q++); 334 if (r == -1) { 335 lfree(tmpp, tsize); 336 errno = EILSEQ; 337 return (EOF); 338 } 339 len += r; 340 tmpq += r; 341 } 342 tmpq = tmpp; 343 newbufptr = *bufptr + len; 344 if (newbufptr > bufferend) { 345 if (!_dowrite(tmpp, len, iop, bufptr)) { 346 lfree(tmpp, tsize); 347 return (EOF); 348 } 349 } else { 350 (void) memcpy(*bufptr, tmpp, len); 351 *bufptr = newbufptr; 352 } 353 lfree(tmpp, tsize); 354 return (0); 355 } 356 } 357 358 static int 359 pad_wide(FILE *iop, unsigned char **bufptr, 360 unsigned char *bufferend, const char *s, size_t n, 361 int sflag) 362 { 363 unsigned char *newbufptr; 364 ssize_t nn; 365 size_t len; 366 wchar_t ps; 367 368 if (sflag) { 369 /* for swprintf */ 370 ps = (wchar_t)s[0]; 371 len = (wchar_t *)bufferend - (wchar_t *)*bufptr; 372 if (n > len) { 373 (void) wmemset((wchar_t *)*bufptr, ps, len); 374 iop->_ptr = bufferend; 375 return (EOF); 376 } else { 377 (void) wmemset((wchar_t *)*bufptr, ps, n); 378 *bufptr = (unsigned char *)((wchar_t *)*bufptr + n); 379 return (0); 380 } 381 } else { 382 for (nn = n; nn > PAD_LEN; nn -= PAD_LEN) { 383 if (!_dowrite(s, PAD_LEN, iop, bufptr)) 384 return (EOF); 385 } 386 newbufptr = *bufptr + nn; 387 if (newbufptr > bufferend) { 388 if (!_dowrite(s, nn, iop, bufptr)) 389 return (EOF); 390 } else { 391 (void) memcpy(*bufptr, s, nn); 392 *bufptr = newbufptr; 393 } 394 return (0); 395 } 396 } 397 #endif /* _WIDE */ 398 399 #ifdef _WIDE 400 ssize_t 401 _wdoprnt(const wchar_t *format, va_list in_args, FILE *iop) 402 { 403 return (_wndoprnt(format, in_args, iop, 0)); 404 } 405 #else /* _WIDE */ 406 ssize_t 407 _doprnt(const char *format, va_list in_args, FILE *iop) 408 { 409 return (_ndoprnt(format, in_args, iop, 0)); 410 } 411 #endif /* _WIDE */ 412 413 414 #ifdef _WIDE 415 ssize_t 416 _wndoprnt(const wchar_t *format, va_list in_args, FILE *iop, int prflag) 417 #else /* _WIDE */ 418 ssize_t 419 _ndoprnt(const char *format, va_list in_args, FILE *iop, int prflag) 420 #endif /* _WIDE */ 421 { 422 423 #ifdef _WIDE 424 int sflag = 0; 425 size_t maxcount; 426 #else 427 int snflag = 0; 428 #endif /* _WIDE */ 429 /* bufptr is used inside of doprnt instead of iop->_ptr; */ 430 /* bufferend is a copy of _bufend(iop), if it exists. For */ 431 /* dummy file descriptors (iop->_flag & _IOREAD), bufferend */ 432 /* may be meaningless. Dummy file descriptors are used so that */ 433 /* sprintf and vsprintf may share the _doprnt routine with the */ 434 /* rest of the printf family. */ 435 436 unsigned char *bufptr; 437 unsigned char *bufferend; 438 439 #ifdef _WIDE 440 /* This variable counts output characters. */ 441 size_t count = 0; 442 #else /* _WIDE */ 443 /* This variable counts output characters. */ 444 int count = 0; 445 #endif /* _WIDE */ 446 447 #ifdef _WIDE 448 wchar_t *bp; 449 size_t bpsize; 450 wchar_t *p; 451 char *cbp; 452 char *cp; 453 454 #else /* _WIDE */ 455 /* Starting and ending points for value to be printed */ 456 char *bp; 457 char *p; 458 #endif /* _WIDE */ 459 /* Field width and precision */ 460 int prec = 0; 461 ssize_t width; 462 ssize_t num; 463 ssize_t sec_display; 464 wchar_t *wp; 465 ssize_t preco; 466 ssize_t wcount = 0; 467 char tmpbuf[10]; 468 char wflag; 469 char lflag; 470 int quote; /* ' */ 471 int retcode; 472 473 474 #ifdef _WIDE 475 /* Format code */ 476 wchar_t fcode; 477 #else /* _WIDE */ 478 /* Format code */ 479 char fcode; 480 #endif /* _WIDE */ 481 482 /* Number of padding zeroes required on the left and right */ 483 ssize_t lzero, rzero, rz, leadzeroes; 484 485 486 /* Flags - bit positions defined by LENGTH, FPLUS, FMINUS, FBLANK, */ 487 /* and FSHARP are set if corresponding character is in format */ 488 /* Bit position defined by PADZERO means extra space in the field */ 489 /* should be padded with leading zeroes rather than with blanks */ 490 491 ssize_t flagword; 492 493 #ifdef _WIDE 494 /* Values are developed in this buffer */ 495 wchar_t buf[max(MAXLLDIGS, 1034)]; 496 wchar_t cvtbuf[512 + DECIMAL_STRING_LENGTH]; 497 498 /* Pointer to sign, "0x", "0X", or empty */ 499 wchar_t *prefix; 500 wchar_t prefixbuf[4]; 501 502 /* Exponent or empty */ 503 wchar_t *suffix; 504 505 /* Buffer to create exponent */ 506 wchar_t expbuf[MAXESIZ + 1]; 507 #else /* _WIDE */ 508 /* Values are developed in this buffer */ 509 char buf[max(MAXLLDIGS, 1034)]; 510 char cvtbuf[512 + DECIMAL_STRING_LENGTH]; 511 512 /* Pointer to sign, "0x", "0X", or empty */ 513 char *prefix; 514 char prefixbuf[4]; 515 516 /* Exponent or empty */ 517 char *suffix; 518 519 /* Buffer to create exponent */ 520 char expbuf[MAXESIZ + 1]; 521 #endif /* _WIDE */ 522 523 /* Length of prefix and of suffix */ 524 ssize_t prefixlength, suffixlength; 525 526 /* Combined length of leading zeroes, trailing zeroes, and suffix */ 527 ssize_t otherlength; 528 529 /* The value being converted, if integer */ 530 ssize_t val; 531 532 /* The value being converted, if long long */ 533 long long ll = 0LL; 534 535 /* Output value from aconvert */ 536 int exp; 537 538 /* Output values from fcvt and ecvt */ 539 int decpt, sign; 540 541 #ifdef _WIDE 542 /* Pointer to a translate table for digits of whatever radix */ 543 const wchar_t *tab; 544 #else /* _WIDE */ 545 /* Pointer to a translate table for digits of whatever radix */ 546 const char *tab; 547 #endif /* _WIDE */ 548 549 /* Work variables */ 550 ssize_t k, lradix, mradix; 551 552 int inf_nan = 0; 553 int inf_nan_mixed_case = 0; 554 555 #ifdef _WIDE 556 /* variables for positional parameters */ 557 /* save the beginning of the format */ 558 wchar_t *sformat = (wchar_t *)format; 559 #else /* _WIDE */ 560 /* variables for positional parameters */ 561 char *sformat = (char *)format; /* save the beginning of the format */ 562 #endif 563 564 int fpos = 1; /* 1 if first positional parameter */ 565 stva_list args, /* used to step through the argument list */ 566 sargs; /* used to save the start of the arg list */ 567 stva_list bargs; /* used to restore args if positional width */ 568 /* or precision */ 569 stva_list arglst[MAXARGS]; /* array giving appropriate values */ 570 /* for va_arg() to retrieve the */ 571 /* corresponding argument: */ 572 /* arglst[0] is the first arg */ 573 /* arglst[1] is the second arg, etc */ 574 575 int starflg = 0; /* set to 1 if * format specifier seen */ 576 /* 577 * Initialize args and sargs to the start of the argument list. 578 * We don't know any portable way to copy an arbitrary C object 579 * so we use a system-specific routine (probably a macro) from 580 * stdarg.h. (Remember that if va_list is an array, in_args will 581 * be a pointer and &in_args won't be what we would want for 582 * memcpy.) 583 */ 584 va_copy(args.ap, in_args); 585 sargs = args; 586 587 #ifdef _WIDE 588 if (iop->_flag == _IOREAD) 589 sflag = 1; 590 591 if (!sflag) { 592 #endif /* _WIDE */ 593 /* if first I/O to the stream get a buffer */ 594 /* Note that iop->_base should not equal 0 for sprintf and vsprintf */ 595 if (iop->_base == 0) { 596 if (_findbuf(iop) == 0) 597 return (EOF); 598 /* _findbuf leaves _cnt set to 0 which is the wrong thing to do */ 599 /* for fully buffered files */ 600 if (!(iop->_flag & (_IOLBF|_IONBF))) 601 iop->_cnt = _bufend(iop) - iop->_base; 602 } 603 #ifdef _WIDE 604 } 605 #endif /* _WIDE */ 606 607 #ifdef _WIDE 608 bufptr = iop->_ptr; 609 if (sflag) { 610 maxcount = (size_t)iop->_cnt; 611 bufferend = (unsigned char *)(((wchar_t *)iop->_ptr) + 612 maxcount); 613 } else { 614 bufferend = _bufend(iop); 615 } 616 #else /* _WIDE */ 617 /* initialize buffer pointer and buffer end pointer */ 618 bufptr = iop->_ptr; 619 if (iop->_flag & _IOREAD) { 620 /* 621 * [v]sprintf or [v]snprintf 622 */ 623 if (iop->_cnt == MAXINT) { 624 /* 625 * [v]sprintf (no boundschecking) 626 */ 627 bufferend = 628 (unsigned char *)((long)bufptr | (-1L & ~HIBITL)); 629 } else { 630 /* 631 * [v]snprintf (with boundschecking) or 632 * iop with _IORW has been read. 633 */ 634 bufferend = _bufend(iop); 635 if (bufferend == NULL) { 636 /* 637 * [v]snprintf 638 * 639 * [v]snprint() needs to be always handled by 640 * _dowrite(). 641 */ 642 snflag = 1; 643 } 644 } 645 } else { 646 /* 647 * [v]printf or [v]fprintf 648 */ 649 bufferend = _bufend(iop); 650 } 651 #endif /* _WIDE */ 652 653 /* 654 * The main loop -- this loop goes through one iteration 655 * for each string of ordinary characters or format specification. 656 */ 657 for (; ; ) { 658 ssize_t n; 659 660 if ((fcode = *format) != '\0' && fcode != '%') { 661 #ifdef _WIDE 662 bp = (wchar_t *)format; 663 #else /* _WIDE */ 664 bp = (char *)format; 665 #endif /* _WIDE */ 666 do { 667 format++; 668 } while ((fcode = *format) != '\0' && fcode != '%'); 669 670 count += (n = format - bp); /* n = no. of non-% chars */ 671 PUT(bp, n); 672 } 673 if (fcode == '\0') { /* end of format; return */ 674 ssize_t nn = bufptr - iop->_ptr; 675 676 #ifdef _WIDE 677 if (sflag) { 678 iop->_ptr = bufptr; 679 return ((ssize_t)count); 680 } 681 #endif /* _WIDE */ 682 683 iop->_cnt -= nn; 684 iop->_ptr = bufptr; 685 /* in case of interrupt during last several lines */ 686 if ((bufptr + iop->_cnt) > bufferend && !(iop->_flag \ 687 & _IOREAD)) 688 _bufsync(iop, bufferend); 689 if (iop->_flag & (_IONBF | _IOLBF) && \ 690 (iop->_flag & _IONBF || \ 691 memchr((char *)(bufptr+iop->_cnt), \ 692 '\n', -iop->_cnt) != NULL)) 693 (void) _xflsbuf(iop); 694 #ifdef _WIDE 695 return (FERROR(iop) ? EOF : (ssize_t)count); 696 #else /* _WIDE */ 697 return (FERROR(iop) ? EOF : (int)count); 698 #endif /* _WIDE */ 699 } 700 701 /* 702 * % has been found. 703 * The following switch is used to parse the format 704 * specification and to perform the operation specified 705 * by the format letter. The program repeatedly goes 706 * back to this switch until the format letter is 707 * encountered. 708 */ 709 width = prefixlength = otherlength = 0; 710 flagword = suffixlength = 0; 711 format++; 712 wflag = 0; 713 lflag = 0; 714 sec_display = 0; 715 quote = 0; 716 717 charswitch: 718 719 switch (fcode = *format++) { 720 721 case '+': 722 flagword |= FPLUS; 723 goto charswitch; 724 case '-': 725 flagword |= FMINUS; 726 flagword &= ~PADZERO; /* ignore 0 flag */ 727 goto charswitch; 728 case ' ': 729 flagword |= FBLANK; 730 goto charswitch; 731 case '\'': /* XSH4 */ 732 quote++; 733 goto charswitch; 734 case '#': 735 flagword |= FSHARP; 736 goto charswitch; 737 738 /* Scan the field width and precision */ 739 case '.': 740 flagword |= DOTSEEN; 741 prec = 0; 742 goto charswitch; 743 744 case '*': 745 if (_M_ISDIGIT(*format)) { 746 starflg = 1; 747 bargs = args; 748 goto charswitch; 749 } 750 if (!(flagword & DOTSEEN)) { 751 width = va_arg(args.ap, int); 752 if (width < 0) { 753 width = -width; 754 flagword |= FMINUS; 755 } 756 } else { 757 prec = va_arg(args.ap, int); 758 if (prec < 0) { 759 prec = 0; 760 flagword ^= DOTSEEN; /* ANSI sez so */ 761 } 762 } 763 goto charswitch; 764 765 case '$': 766 { 767 ssize_t position; 768 stva_list targs; 769 if (fpos) { 770 #ifdef _WIDE 771 _wmkarglst(sformat, sargs, arglst, prflag); 772 #else /* _WIDE */ 773 _mkarglst(sformat, sargs, arglst, prflag); 774 #endif /* _WIDE */ 775 fpos = 0; 776 } 777 if (flagword & DOTSEEN) { 778 position = prec; 779 prec = 0; 780 } else { 781 position = width; 782 width = 0; 783 } 784 if (position <= 0) { 785 /* illegal position */ 786 format--; 787 continue; 788 } 789 if (position <= MAXARGS) { 790 targs = arglst[position - 1]; 791 } else { 792 targs = arglst[MAXARGS - 1]; 793 #ifdef _WIDE 794 _wgetarg(sformat, &targs, position, prflag); 795 #else /* _WIDE */ 796 _getarg(sformat, &targs, position, prflag); 797 #endif /* _WIDE */ 798 } 799 if (!starflg) 800 args = targs; 801 else { 802 starflg = 0; 803 args = bargs; 804 if (flagword & DOTSEEN) { 805 prec = va_arg(targs.ap, int); 806 if (prec < 0) { 807 prec = 0; 808 flagword ^= DOTSEEN; /* XSH */ 809 } 810 } else { 811 width = va_arg(targs.ap, int); 812 if (width < 0) { 813 width = -width; 814 flagword |= FMINUS; 815 } 816 } 817 } 818 goto charswitch; 819 } 820 821 case '0': /* obsolescent spec: leading zero in width */ 822 /* means pad with leading zeros */ 823 if (!(flagword & (DOTSEEN | FMINUS))) 824 flagword |= PADZERO; 825 /* FALLTHROUGH */ 826 case '1': 827 case '2': 828 case '3': 829 case '4': 830 case '5': 831 case '6': 832 case '7': 833 case '8': 834 case '9': 835 { num = fcode - '0'; 836 while (_M_ISDIGIT(fcode = *format)) { 837 num = num * 10 + fcode - '0'; 838 format++; 839 } 840 if (flagword & DOTSEEN) 841 prec = num; 842 else 843 width = num; 844 goto charswitch; 845 } 846 847 /* Scan the length modifier */ 848 case 'l': 849 if (!(flagword & XLONG)) { 850 if (lflag) { 851 /* long long */ 852 flagword &= ~LENGTH; 853 flagword |= XLONG; 854 } else { 855 /* long */ 856 flagword |= LENGTH; 857 } 858 } 859 lflag++; 860 goto charswitch; 861 862 case 'L': /* long double */ 863 flagword |= QUAD; 864 goto charswitch; 865 866 case 'h': 867 if (!(flagword & CHAR)) { 868 if (flagword & SHORT) { 869 /* char - hh */ 870 flagword &= ~SHORT; 871 flagword |= CHAR; 872 } else { 873 /* short */ 874 flagword |= SHORT; 875 } 876 } 877 goto charswitch; 878 case 'j': 879 #ifndef _LP64 880 /* 881 * *printf_c89() in 32-bit libc uses 882 * 32-bit intmax_t; otherwise intmax_t 883 * is 64-bits. 884 */ 885 if (!(prflag & _F_INTMAX32)) { 886 #endif 887 flagword |= XLONG; /* [u]intmax_t (64) */ 888 #ifndef _LP64 889 } 890 #endif 891 goto charswitch; 892 893 case 't': 894 /* 895 * LENGTH is shared by l, t, z specifiers; protect 896 * against (destructive) undefined behavior (eg: 897 * avoid %llt setting XLONG and LENGTH) with invalid 898 * combinations of specifiers 899 */ 900 if (!(flagword & XLONG)) { 901 flagword |= LENGTH; /* ptrdiff_t */ 902 } 903 goto charswitch; 904 905 case 'z': 906 if (!(flagword & XLONG)) { 907 flagword |= LENGTH; /* [s]size_t */ 908 } 909 goto charswitch; 910 911 /* 912 * The character addressed by format must be 913 * the format letter -- there is nothing 914 * left for it to be. 915 * 916 * The status of the +, -, #, and blank 917 * flags are reflected in the variable 918 * "flagword". "width" and "prec" contain 919 * numbers corresponding to the digit 920 * strings before and after the decimal 921 * point, respectively. If there was no 922 * decimal point, then flagword & DOTSEEN 923 * is false and the value of prec is meaningless. 924 * 925 * The following switch cases set things up 926 * for printing. What ultimately gets 927 * printed will be padding blanks, a 928 * prefix, left padding zeroes, a value, 929 * right padding zeroes, a suffix, and 930 * more padding blanks. Padding blanks 931 * will not appear simultaneously on both 932 * the left and the right. Each case in 933 * this switch will compute the value, and 934 * leave in several variables the informa- 935 * tion necessary to construct what is to 936 * be printed. 937 * 938 * The prefix is a sign, a blank, "0x", 939 * "0X", a sign or a blank followed by "0x" 940 * or "0X", or nothing, and is addressed by 941 * "prefix". 942 * 943 * The suffix is either null or an 944 * exponent, and is addressed by "suffix". 945 * If there is a suffix, the flagword bit 946 * SUFFIX will be set. 947 * 948 * The value to be printed starts at "bp" 949 * and continues up to and not including 950 * "p". 951 * 952 * "lzero" and "rzero" will contain the 953 * number of padding zeroes required on 954 * the left and right, respectively. 955 * The flagword bits LZERO and RZERO tell 956 * whether padding zeros are required. 957 * 958 * The number of padding blanks, and 959 * whether they go on the left or the 960 * right, will be computed on exit from 961 * the switch. 962 */ 963 964 965 966 /* 967 * decimal fixed point representations 968 * 969 * HIBITL is 100...000 970 * binary, and is equal to the maximum 971 * negative number. 972 * We assume a 2's complement machine 973 */ 974 case 'i': 975 case 'd': 976 if ((flagword & PADZERO) && (flagword & DOTSEEN)) 977 flagword &= ~PADZERO; /* ignore 0 flag */ 978 /* Set buffer pointer to last digit */ 979 p = bp = buf + MAXLLDIGS; 980 981 /* Fetch the argument to be printed */ 982 if (flagword & XLONG) { /* long long */ 983 ll = va_arg(args.ap, long long); 984 985 /* If signed conversion, make sign */ 986 if (ll < 0) { 987 prefix = _P_HYPHEN; 988 prefixlength = 1; 989 /* 990 * Negate, checking in advance for 991 * possible overflow. 992 */ 993 if (ll != HIBITLL) 994 ll = -ll; 995 else 996 /* number is -HIBITLL; convert last */ 997 /* digit now and get positive number */ 998 *--bp = _lowlldigit(&ll); 999 } else if (flagword & FPLUS) { 1000 prefix = _P_PLUS; 1001 prefixlength = 1; 1002 } else if (flagword & FBLANK) { 1003 prefix = _P_BLANK; 1004 prefixlength = 1; 1005 } 1006 } else { /* not long long */ 1007 if (flagword & LENGTH) 1008 val = va_arg(args.ap, long); 1009 else 1010 val = va_arg(args.ap, int); 1011 1012 if (flagword & SHORT) 1013 val = (short)val; 1014 else if (flagword & CHAR) 1015 val = (char)val; 1016 1017 /* If signed conversion, make sign */ 1018 if (val < 0) { 1019 prefix = _P_HYPHEN; 1020 prefixlength = 1; 1021 /* 1022 * Negate, checking in advance 1023 * for possible overflow. 1024 */ 1025 if (val != HIBITL) 1026 val = -val; 1027 /* 1028 * number is -HIBITL; convert 1029 * last digit now and get 1030 * positive number 1031 */ 1032 else 1033 *--bp = _lowdigit(&val); 1034 } else if (flagword & FPLUS) { 1035 prefix = _P_PLUS; 1036 prefixlength = 1; 1037 } else if (flagword & FBLANK) { 1038 prefix = _P_BLANK; 1039 prefixlength = 1; 1040 } 1041 } 1042 1043 decimal: 1044 { 1045 long qval = val; 1046 long long lll = ll; 1047 long long tll; 1048 if (flagword & XLONG) { 1049 if (lll < 10LL) { 1050 #ifdef _WIDE 1051 if (lll != 0LL || !(flagword & DOTSEEN)) 1052 *--bp = (wchar_t)lll + L'0'; 1053 #else /* _WIDE */ 1054 if (lll != 0LL || !(flagword & DOTSEEN)) 1055 *--bp = (char)lll + '0'; 1056 #endif /* _WIDE */ 1057 } else { 1058 do { 1059 tll = lll; 1060 lll /= 10; 1061 #ifdef _WIDE 1062 *--bp = (wchar_t) 1063 (tll - lll * 10 + '0'); 1064 #else /* _WIDE */ 1065 *--bp = (char) \ 1066 (tll - lll * 10 + '0'); 1067 #endif /* _WIDE */ 1068 } while (lll >= 10); 1069 #ifdef _WIDE 1070 *--bp = (wchar_t)lll + '0'; 1071 #else /* _WIDE */ 1072 *--bp = (char)lll + '0'; 1073 #endif /* _WIDE */ 1074 } 1075 } else { 1076 if (qval <= 9) { 1077 #ifdef _WIDE 1078 if (qval != 0 || !(flagword & DOTSEEN)) 1079 *--bp = (wchar_t)qval + '0'; 1080 #else /* _WIDE */ 1081 if (qval != 0 || !(flagword & DOTSEEN)) 1082 *--bp = (char)qval + '0'; 1083 #endif /* _WIDE */ 1084 } else { 1085 do { 1086 n = qval; 1087 qval /= 10; 1088 #ifdef _WIDE 1089 *--bp = (wchar_t) \ 1090 (n - qval * 10 + '0'); 1091 #else /* _WIDE */ 1092 *--bp = (char) \ 1093 (n - qval * 10 + '0'); 1094 #endif /* _WIDE */ 1095 } while (qval > 9); 1096 #ifdef _WIDE 1097 *--bp = (wchar_t)qval + '0'; 1098 #else /* _WIDE */ 1099 *--bp = (char)qval + '0'; 1100 #endif /* _WIDE */ 1101 } 1102 } 1103 } 1104 /* Handle the ' flag */ 1105 if (quote) { 1106 p = insert_thousands_sep(bp, p); 1107 } 1108 1109 /* Calculate minimum padding zero requirement */ 1110 if (flagword & DOTSEEN) { 1111 leadzeroes = prec - (p - bp); 1112 if (leadzeroes > 0) { 1113 otherlength = lzero = leadzeroes; 1114 flagword |= LZERO; 1115 } 1116 } 1117 break; 1118 1119 case 'u': 1120 if ((flagword & PADZERO) && (flagword & DOTSEEN)) 1121 flagword &= ~PADZERO; /* ignore 0 flag */ 1122 p = bp = buf + MAXLLDIGS; 1123 1124 /* Fetch the argument to be printed */ 1125 if (flagword & XLONG) { 1126 ll = va_arg(args.ap, long long); 1127 1128 if (ll & HIBITLL) 1129 *--bp = _lowlldigit(&ll); 1130 } else { 1131 if (flagword & LENGTH) 1132 val = va_arg(args.ap, long); 1133 else 1134 val = va_arg(args.ap, unsigned); 1135 1136 if (flagword & SHORT) 1137 val = (unsigned short)val; 1138 else if (flagword & CHAR) 1139 val = (unsigned char)val; 1140 1141 if (val & HIBITL) 1142 *--bp = _lowdigit(&val); 1143 } 1144 1145 goto decimal; 1146 1147 /* 1148 * non-decimal fixed point representations 1149 * for radix equal to a power of two 1150 * 1151 * "mradix" is one less than the radix for the conversion. 1152 * "lradix" is one less than the base 2 log 1153 * of the radix for the conversion. Conversion is unsigned. 1154 * HIBITL is 100...000 1155 * binary, and is equal to the maximum 1156 * negative number. 1157 * We assume a 2's complement machine 1158 */ 1159 1160 case 'o': 1161 mradix = 7; 1162 lradix = 2; 1163 /* 1164 * DR151 and clarification in C90 1165 * presence of '#' increases precision to first 1166 * digit of the result to be zero 1167 */ 1168 if ((flagword & DOTSEEN) && (flagword & FSHARP) && 1169 prec == 0) 1170 prec = 1; 1171 1172 goto fixed; 1173 1174 case 'p': 1175 flagword &= ~(XLONG | SHORT); 1176 flagword |= LENGTH; 1177 1178 /* FALLTHRU */ 1179 case 'X': 1180 case 'x': 1181 mradix = 15; 1182 lradix = 3; 1183 1184 fixed: 1185 if ((flagword & PADZERO) && (flagword & DOTSEEN)) 1186 flagword &= ~PADZERO; /* ignore 0 flag */ 1187 1188 #ifdef _WIDE 1189 /* Set translate table for digits */ 1190 tab = (wchar_t *)((fcode == 'X') ? uc_digs : lc_digs); 1191 #else /* _WIDE */ 1192 /* Set translate table for digits */ 1193 tab = (fcode == 'X') ? uc_digs : lc_digs; 1194 #endif /* _WIDE */ 1195 1196 /* Fetch the argument to be printed */ 1197 if (flagword & XLONG) { 1198 ll = va_arg(args.ap, long long); 1199 } else { 1200 if (flagword & LENGTH) 1201 val = va_arg(args.ap, long); 1202 else 1203 val = va_arg(args.ap, unsigned); 1204 1205 if (flagword & SHORT) 1206 val = (unsigned short) val; 1207 else if (flagword & CHAR) 1208 val = (unsigned char) val; 1209 } 1210 p = bp = buf + MAXLLDIGS; 1211 1212 /* Develop the digits of the value */ 1213 if (flagword & XLONG) { 1214 long long lll = ll; 1215 1216 if (lll == 0LL) { 1217 if (!(flagword & DOTSEEN)) { 1218 otherlength = lzero = 1; 1219 flagword |= LZERO; 1220 } 1221 } else do { 1222 *--bp = tab[(ssize_t)(lll & mradix)]; 1223 lll = ((lll >> 1) & ~HIBITLL) \ 1224 >> lradix; 1225 } while (lll != 0LL); 1226 } else { 1227 long qval = val; 1228 1229 if (qval == 0) { 1230 if (!(flagword & DOTSEEN)) { 1231 otherlength = lzero = 1; 1232 flagword |= LZERO; 1233 } 1234 } else do { 1235 *--bp = tab[qval & mradix]; 1236 qval = ((qval >> 1) & ~HIBITL) \ 1237 >> lradix; 1238 } while (qval != 0); 1239 } 1240 1241 /* Calculate minimum padding zero requirement */ 1242 if (flagword & DOTSEEN) { 1243 leadzeroes = prec - (p - bp); 1244 if (leadzeroes > 0) { 1245 otherlength = lzero = leadzeroes; 1246 flagword |= LZERO; 1247 } 1248 } 1249 1250 /* Handle the # flag, (val != 0) for int and long */ 1251 /* (ll!= 0) handles long long case */ 1252 if ((flagword & FSHARP) && 1253 (((flagword & XLONG) == 0 && val != 0) || 1254 ((flagword & XLONG) == XLONG && ll != 0))) 1255 switch (fcode) { 1256 case 'o': 1257 if (!(flagword & LZERO)) { 1258 otherlength = lzero = 1; 1259 flagword |= LZERO; 1260 } 1261 break; 1262 case 'x': 1263 prefix = _P_ZEROx; 1264 prefixlength = 2; 1265 break; 1266 case 'X': 1267 prefix = _P_ZEROX; 1268 prefixlength = 2; 1269 break; 1270 } 1271 1272 break; 1273 1274 case 'A': 1275 case 'a': 1276 /* A format */ 1277 if (flagword & QUAD) { 1278 long double qval = GETQVAL(args.ap); 1279 1280 /* establish default precision */ 1281 if (!(flagword & DOTSEEN)) 1282 #if defined(__sparc) 1283 prec = HEXFP_QUAD_DIG - 1; 1284 #elif defined(__i386) || defined(__amd64) 1285 prec = HEXFP_EXTENDED_DIG - 1; 1286 #else 1287 #error Unknown architecture 1288 #endif 1289 1290 FPCONV(__qaconvert, &qval, 1291 min(prec + 1, MAXECVT), &exp, &sign, 1292 cvtbuf); 1293 } else { 1294 double dval = va_arg(args.ap, double); 1295 1296 /* establish default precision */ 1297 if (!(flagword & DOTSEEN)) 1298 prec = HEXFP_DOUBLE_DIG - 1; 1299 1300 FPCONV(__aconvert, dval, 1301 min(prec + 1, MAXECVT), &exp, &sign, 1302 cvtbuf); 1303 } 1304 bp = cvtbuf; 1305 1306 /* 1307 * The following is wide-character safe because 1308 * __aconvert and __qaconvert only produce ASCII 1309 * characters. 1310 */ 1311 if (!isxdigit((unsigned char)*bp)) { 1312 inf_nan = 1; 1313 break; 1314 } 1315 1316 /* 1317 * Create the prefix. We ought to use the strings 1318 * defined above (_P_HYPHEN, etc.), but that would 1319 * be awkward: we'd either have to define six more 1320 * of them or we'd have to use strcpy/strcat to 1321 * assemble the ones already defined. So instead, 1322 * we just build the prefix character by character. 1323 */ 1324 p = prefix = prefixbuf; 1325 if (sign) { 1326 *p++ = '-'; 1327 prefixlength = 1; 1328 } else if (flagword & FPLUS) { 1329 *p++ = '+'; 1330 prefixlength = 1; 1331 } else if (flagword & FBLANK) { 1332 *p++ = ' '; 1333 prefixlength = 1; 1334 } 1335 *p++ = '0'; 1336 *p++ = (fcode == 'A') ? 'X' : 'x'; 1337 *p = '\0'; 1338 prefixlength += 2; 1339 1340 /* put the first digit in the buffer */ 1341 p = &buf[0]; 1342 *p++ = (*bp != '\0') ? *bp++ : '0'; 1343 1344 /* put in a decimal point if needed */ 1345 if (prec != 0 || (flagword & FSHARP)) 1346 *p++ = _numeric[0]; 1347 1348 /* create the rest of the mantissa */ 1349 rz = prec; 1350 if (fcode == 'A') { 1351 for (; rz > 0 && *bp != '\0'; --rz) { 1352 *p++ = ('a' <= *bp && *bp <= 'f')? 1353 *bp - 32 : *bp; 1354 bp++; 1355 } 1356 } else { 1357 for (; rz > 0 && *bp != '\0'; --rz) 1358 *p++ = *bp++; 1359 } 1360 if (rz > 0) { 1361 otherlength = rzero = rz; 1362 flagword |= RZERO; 1363 } 1364 1365 bp = &buf[0]; 1366 1367 /* 1368 * Create the exponent in right-to-left order. 1369 * buf[0] == '0' if and only if the value being 1370 * converted is exactly zero, in which case the 1371 * exponent should be +0 regardless of exp. 1372 */ 1373 suffix = &expbuf[MAXESIZ]; 1374 *suffix = '\0'; 1375 if (buf[0] != '0') { 1376 int nn; 1377 1378 nn = exp; 1379 if (nn < 0) 1380 nn = -nn; 1381 for (; nn > 9; nn /= 10) 1382 *--suffix = todigit(nn % 10); 1383 *--suffix = todigit(nn); 1384 *--suffix = (exp >= 0) ? '+' : '-'; 1385 } else { 1386 *--suffix = '0'; 1387 *--suffix = '+'; 1388 } 1389 1390 /* put in the p */ 1391 *--suffix = (fcode == 'A') ? 'P' : 'p'; 1392 1393 /* compute size of suffix */ 1394 suffixlength = &expbuf[MAXESIZ] - suffix; 1395 otherlength += suffixlength; 1396 flagword |= SUFFIX; 1397 break; 1398 1399 case 'E': 1400 case 'e': 1401 /* 1402 * E-format. The general strategy 1403 * here is fairly easy: we take what 1404 * econvert gives us and re-format it. 1405 * (qeconvert for long double) 1406 */ 1407 1408 /* Establish default precision */ 1409 if (!(flagword & DOTSEEN)) 1410 prec = 6; 1411 1412 if (flagword & QUAD) { /* long double */ 1413 long double qval = GETQVAL(args.ap); 1414 1415 FPCONV(qeconvert, &qval, 1416 min(prec + 1, MAXECVT), &decpt, &sign, 1417 cvtbuf); 1418 } else { /* double */ 1419 double dval = va_arg(args.ap, double); 1420 1421 FPCONV(econvert, dval, 1422 min(prec + 1, MAXECVT), &decpt, &sign, 1423 cvtbuf); 1424 } 1425 bp = cvtbuf; 1426 if (*bp > '9') { 1427 inf_nan = 1; 1428 inf_nan_mixed_case = (__xpg6 & 1429 _C99SUSv3_mixed_case_Inf_and_NaN); 1430 break; 1431 } 1432 1433 /* Determine the prefix */ 1434 e_merge: 1435 if (sign) { 1436 prefix = _P_HYPHEN; 1437 prefixlength = 1; 1438 } else if (flagword & FPLUS) { 1439 prefix = _P_PLUS; 1440 prefixlength = 1; 1441 } else if (flagword & FBLANK) { 1442 prefix = _P_BLANK; 1443 prefixlength = 1; 1444 } 1445 1446 /* Place the first digit in the buffer */ 1447 p = &buf[0]; 1448 *p++ = (*bp != '\0') ? *bp++ : '0'; 1449 1450 /* Put in a decimal point if needed */ 1451 if (prec != 0 || (flagword & FSHARP)) 1452 *p++ = _numeric[0]; 1453 1454 /* Create the rest of the mantissa */ 1455 rz = prec; 1456 for (; rz > 0 && *bp != '\0'; --rz) 1457 *p++ = *bp++; 1458 if (rz > 0) { 1459 otherlength = rzero = rz; 1460 flagword |= RZERO; 1461 } 1462 1463 bp = &buf[0]; 1464 1465 /* 1466 * Create the exponent. buf[0] == '0' if and 1467 * only if the value being converted is exactly 1468 * zero, in which case the exponent should be 1469 * +0 regardless of decpt. 1470 */ 1471 *(suffix = &expbuf[MAXESIZ]) = '\0'; 1472 if (buf[0] != '0') { 1473 int nn = decpt - 1; 1474 if (nn < 0) 1475 nn = -nn; 1476 for (; nn > 9; nn /= 10) 1477 *--suffix = todigit(nn % 10); 1478 *--suffix = todigit(nn); 1479 } 1480 1481 /* Prepend leading zeroes to the exponent */ 1482 while (suffix > &expbuf[MAXESIZ - 2]) 1483 *--suffix = '0'; 1484 1485 /* Put in the exponent sign */ 1486 *--suffix = (decpt > 0 || buf[0] == '0') ? '+' : '-'; 1487 1488 /* Put in the e */ 1489 *--suffix = _M_ISUPPER(fcode) ? 'E' : 'e'; 1490 1491 /* compute size of suffix */ 1492 otherlength += (suffixlength = &expbuf[MAXESIZ] \ 1493 - suffix); 1494 flagword |= SUFFIX; 1495 break; 1496 1497 case 'F': 1498 case 'f': 1499 /* 1500 * F-format floating point. This is a 1501 * good deal less simple than E-format. 1502 * The overall strategy will be to call 1503 * fconvert, reformat its result into buf, 1504 * and calculate how many trailing 1505 * zeroes will be required. There will 1506 * never be any leading zeroes needed. 1507 * (qfconvert for long double) 1508 */ 1509 1510 /* Establish default precision */ 1511 if (!(flagword & DOTSEEN)) 1512 prec = 6; 1513 1514 if (flagword & QUAD) { /* long double */ 1515 long double qval = GETQVAL(args.ap); 1516 1517 FPCONV(qfconvert, &qval, min(prec, MAXFCVT), 1518 &decpt, &sign, cvtbuf); 1519 bp = cvtbuf; 1520 if (*bp == 0) { 1521 /* 1522 * qfconvert would have required 1523 * too many characters; use qeconvert 1524 * instead 1525 */ 1526 FPCONV(qeconvert, &qval, 1527 min(prec + 1, MAXECVT), &decpt, 1528 &sign, cvtbuf); 1529 goto e_merge; 1530 } 1531 } else { /* double */ 1532 double dval = va_arg(args.ap, double); 1533 1534 FPCONV(fconvert, dval, min(prec, MAXFCVT), 1535 &decpt, &sign, cvtbuf); 1536 } 1537 bp = cvtbuf; 1538 if (*bp > '9') { 1539 inf_nan = 1; 1540 if (fcode == 'f') 1541 inf_nan_mixed_case = (__xpg6 & 1542 _C99SUSv3_mixed_case_Inf_and_NaN); 1543 break; 1544 } 1545 1546 /* Determine the prefix */ 1547 f_merge: 1548 if (sign) { 1549 prefix = _P_HYPHEN; 1550 prefixlength = 1; 1551 } else if (flagword & FPLUS) { 1552 prefix = _P_PLUS; 1553 prefixlength = 1; 1554 } else if (flagword & FBLANK) { 1555 prefix = _P_BLANK; 1556 prefixlength = 1; 1557 } 1558 1559 /* Initialize buffer pointer */ 1560 p = &buf[0]; 1561 1562 { 1563 ssize_t nn = decpt; 1564 1565 /* Emit the digits before the decimal point */ 1566 k = 0; 1567 do { 1568 *p++ = (nn <= 0 || *bp == '\0' || \ 1569 k >= MAXFSIG) ? '0' : (k++, *bp++); 1570 } while (--nn > 0); 1571 1572 if (quote) 1573 p = insert_thousands_sep(buf, p); 1574 1575 /* Decide whether we need a decimal point */ 1576 if ((flagword & FSHARP) || prec > 0) 1577 *p++ = _numeric[0]; 1578 1579 /* Digits (if any) after the decimal point */ 1580 nn = min(prec, MAXFCVT); 1581 if (prec > nn) { 1582 flagword |= RZERO; 1583 otherlength = rzero = prec - nn; 1584 } 1585 while (--nn >= 0) 1586 *p++ = (++decpt <= 0 || *bp == '\0' || \ 1587 k >= MAXFSIG) ? '0' : (k++, *bp++); 1588 } 1589 1590 bp = &buf[0]; 1591 1592 break; 1593 1594 case 'G': 1595 case 'g': 1596 /* 1597 * g-format. We play around a bit 1598 * and then jump into e or f, as needed. 1599 */ 1600 1601 /* Establish default precision */ 1602 if (!(flagword & DOTSEEN)) 1603 prec = 6; 1604 else if (prec == 0) 1605 prec = 1; 1606 1607 if (flagword & QUAD) { /* long double */ 1608 long double qval = GETQVAL(args.ap); 1609 1610 FPCONV(qeconvert, &qval, min(prec, MAXECVT), 1611 &decpt, &sign, cvtbuf); 1612 } else { /* double */ 1613 double dval = va_arg(args.ap, double); 1614 1615 FPCONV(econvert, dval, min(prec, MAXECVT), 1616 &decpt, &sign, cvtbuf); 1617 } 1618 bp = cvtbuf; 1619 if (*bp > '9') { 1620 inf_nan = 1; 1621 inf_nan_mixed_case = (__xpg6 & 1622 _C99SUSv3_mixed_case_Inf_and_NaN); 1623 break; 1624 } 1625 if (*bp == '0') /* the value converted is zero */ 1626 decpt = 1; 1627 1628 { 1629 int kk = prec; 1630 if (!(flagword & FSHARP)) { 1631 #ifdef _WIDE 1632 n = wcslen(bp); 1633 #else /* _WIDE */ 1634 n = strlen(bp); 1635 #endif /* _WIDE */ 1636 if (n < kk) 1637 kk = (int)n; 1638 while (kk >= 1 && bp[kk-1] == '0') 1639 --kk; 1640 } 1641 if (decpt < -3 || decpt > prec) { 1642 prec = kk - 1; 1643 goto e_merge; 1644 } 1645 prec = kk - decpt; 1646 goto f_merge; 1647 } 1648 1649 case '%': 1650 buf[0] = fcode; 1651 goto c_merge; 1652 1653 #ifndef _WIDE 1654 case 'w': 1655 wflag = 1; 1656 goto charswitch; 1657 #endif /* _WIDE */ 1658 1659 1660 case 'C': /* XPG XSH4 extention */ 1661 wide_C: 1662 { 1663 wchar_t temp; 1664 1665 temp = va_arg(args.ap, wchar_t); 1666 #ifdef _WIDE 1667 if (temp) { 1668 buf[0] = temp; 1669 p = (bp = buf) + 1; 1670 } else { 1671 buf[0] = 0; 1672 p = (bp = buf) + 1; 1673 } 1674 wcount = 1; 1675 wflag = 1; 1676 #else /* _WIDE */ 1677 if (temp) { 1678 if ((retcode = wctomb(buf, temp)) 1679 == -1) { 1680 errno = EILSEQ; 1681 return (EOF); 1682 } else { 1683 p = (bp = buf) + retcode; 1684 } 1685 } else { /* NULL character */ 1686 buf[0] = 0; 1687 p = (bp = buf) + 1; 1688 } 1689 wcount = p - bp; 1690 #endif /* _WIDE */ 1691 } 1692 break; 1693 case 'c': 1694 if (lflag) { 1695 goto wide_C; 1696 } 1697 #ifndef _WIDE 1698 if (wflag) { 1699 wchar_t temp; 1700 1701 temp = va_arg(args.ap, wchar_t); 1702 if (temp) { 1703 if ((retcode = wctomb(buf, temp)) 1704 == -1) { 1705 p = (bp = buf) + 1; 1706 } else { 1707 p = (bp = buf) + retcode; 1708 } 1709 } else { /* NULL character */ 1710 buf[0] = 0; 1711 p = (bp = buf) + 1; 1712 } 1713 wcount = p - bp; 1714 } else { 1715 #endif /* _WIDE */ 1716 if (flagword & XLONG) { 1717 long long temp; 1718 temp = va_arg(args.ap, long long); 1719 #ifdef _WIDE 1720 buf[0] = (wchar_t)temp; 1721 #else /* _WIDE */ 1722 buf[0] = (char)temp; 1723 #endif /* _WIDE */ 1724 } else 1725 buf[0] = va_arg(args.ap, int); 1726 c_merge: 1727 p = (bp = &buf[0]) + 1; 1728 #ifdef _WIDE 1729 wcount = 1; 1730 wflag = 1; 1731 #endif /* _WIDE */ 1732 #ifndef _WIDE 1733 } 1734 #endif /* _WIDE */ 1735 break; 1736 1737 case 'S': /* XPG XSH4 extention */ 1738 wide_S: 1739 #ifdef _WIDE 1740 if (!lflag) { 1741 lflag++; 1742 } 1743 bp = va_arg(args.ap, wchar_t *); 1744 if (bp == NULL) 1745 bp = (wchar_t *)widenullstr; 1746 if (!(flagword & DOTSEEN)) { 1747 /* wide character handling */ 1748 prec = MAXINT; 1749 } 1750 1751 wp = bp; 1752 wcount = 0; 1753 while (*wp) { 1754 if ((prec - wcount - 1) >= 0) { 1755 wcount++; 1756 wp++; 1757 } else { 1758 break; 1759 } 1760 } 1761 p = wp; 1762 wflag = 1; 1763 break; 1764 #else /* _WIDE */ 1765 if (!wflag) 1766 wflag++; 1767 bp = va_arg(args.ap, char *); 1768 if (bp == NULL) 1769 bp = (char *)widenullstr; 1770 if (!(flagword & DOTSEEN)) { 1771 /* wide character handling */ 1772 prec = MAXINT; 1773 } 1774 1775 wp = (wchar_t *)(uintptr_t)bp; 1776 wcount = 0; 1777 while (*wp) { 1778 int nbytes; 1779 1780 nbytes = wctomb(tmpbuf, *wp); 1781 if (nbytes < 0) { 1782 errno = EILSEQ; 1783 return (EOF); 1784 } 1785 if ((prec - (wcount + nbytes)) >= 0) { 1786 wcount += nbytes; 1787 wp++; 1788 } else { 1789 break; 1790 } 1791 } 1792 sec_display = wcount; 1793 p = (char *)wp; 1794 break; 1795 #endif /* _WIDE */ 1796 case 's': 1797 if (lflag) { 1798 goto wide_S; 1799 } 1800 #ifdef _WIDE 1801 cbp = va_arg(args.ap, char *); 1802 if (cbp == NULL) 1803 cbp = (char *)nullstr; 1804 if (!(flagword & DOTSEEN)) { 1805 size_t nwc; 1806 wchar_t *wstr; 1807 1808 nwc = mbstowcs(NULL, cbp, 0); 1809 if (nwc == (size_t)-1) { 1810 errno = EILSEQ; 1811 return (EOF); 1812 } 1813 bpsize = sizeof (wchar_t) * (nwc + 1); 1814 wstr = (wchar_t *)lmalloc(bpsize); 1815 if (wstr == NULL) { 1816 errno = EILSEQ; 1817 return (EOF); 1818 } 1819 nwc = mbstowcs(wstr, cbp, MAXINT); 1820 wcount = nwc; 1821 bp = wstr; 1822 p = wstr + nwc; 1823 } else { 1824 size_t nwc; 1825 wchar_t *wstr; 1826 1827 nwc = mbstowcs(NULL, cbp, 0); 1828 if (nwc == (size_t)-1) { 1829 errno = EILSEQ; 1830 return (EOF); 1831 } 1832 if (prec > nwc) { 1833 bpsize = sizeof (wchar_t) * nwc; 1834 wstr = (wchar_t *)lmalloc(bpsize); 1835 if (wstr == NULL) { 1836 errno = ENOMEM; 1837 return (EOF); 1838 } 1839 nwc = mbstowcs(wstr, cbp, nwc); 1840 cp = cbp + strlen(cbp); 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 2664 /* 2665 * Recovery scrswidth function - 2666 * this variant of wcswidth() accepts non-printable or illegal 2667 * widechar characters. 2668 */ 2669 static int 2670 _rec_scrswidth(wchar_t *wp, ssize_t n) 2671 { 2672 int col; 2673 int i; 2674 2675 col = 0; 2676 while (*wp && (n-- > 0)) { 2677 if ((i = _scrwidth(*wp++)) == 0) 2678 i = 1; 2679 col += i; 2680 } 2681 return (col); 2682 } 2683