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