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