17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57257d1b4Sraf * Common Development and Distribution License (the "License"). 67257d1b4Sraf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217257d1b4Sraf 227c478bd9Sstevel@tonic-gate /* 239f773e28SDarren Moffat * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * _doprnt: common code for printf, fprintf, sprintf 327c478bd9Sstevel@tonic-gate */ 337c478bd9Sstevel@tonic-gate 347257d1b4Sraf #include "lint.h" 357c478bd9Sstevel@tonic-gate #include "mtlib.h" 367c478bd9Sstevel@tonic-gate #include "print.h" /* parameters & macros for doprnt */ 377c478bd9Sstevel@tonic-gate #include <wchar.h> 387c478bd9Sstevel@tonic-gate #include "libc.h" 397c478bd9Sstevel@tonic-gate #include <stdlib.h> 407c478bd9Sstevel@tonic-gate #include <limits.h> 417c478bd9Sstevel@tonic-gate #include <ctype.h> 427c478bd9Sstevel@tonic-gate #include <stdarg.h> 437c478bd9Sstevel@tonic-gate #include <values.h> 447c478bd9Sstevel@tonic-gate #include <memory.h> 457c478bd9Sstevel@tonic-gate #include <string.h> 467c478bd9Sstevel@tonic-gate #include <locale.h> 477c478bd9Sstevel@tonic-gate #include <widec.h> 487c478bd9Sstevel@tonic-gate #include "../i18n/_locale.h" 497c478bd9Sstevel@tonic-gate #include <errno.h> 507c478bd9Sstevel@tonic-gate #include <sys/types.h> 517c478bd9Sstevel@tonic-gate #include <libw.h> 527c478bd9Sstevel@tonic-gate #include "mse.h" 537c478bd9Sstevel@tonic-gate #include "xpg6.h" 547c478bd9Sstevel@tonic-gate 559f773e28SDarren Moffat static const char nullstr[] = "(null)"; 569f773e28SDarren Moffat static const wchar_t widenullstr[] = L"(null)"; 579f773e28SDarren Moffat 587c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) || defined(__sparcv9) 597c478bd9Sstevel@tonic-gate #define GETQVAL(arg) (va_arg(arg, long double)) 607c478bd9Sstevel@tonic-gate #else /* !defined(__i386) && !defined(__sparcv9) */ 617c478bd9Sstevel@tonic-gate #define GETQVAL(arg) *(va_arg(arg, long double *)) 627c478bd9Sstevel@tonic-gate #endif /* !defined(__i386) && !defined(__sparcv9) */ 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate #ifdef _WIDE 657c478bd9Sstevel@tonic-gate #define STRCHR wcschr 667c478bd9Sstevel@tonic-gate #define STRSPN wcsspn 677c478bd9Sstevel@tonic-gate #define ATOI(x) _watoi((wchar_t *)x) 687c478bd9Sstevel@tonic-gate #define _P_HYPHEN L"-" 697c478bd9Sstevel@tonic-gate #define _P_PLUS L"+" 707c478bd9Sstevel@tonic-gate #define _P_BLANK L" " 717c478bd9Sstevel@tonic-gate #define _P_ZEROx L"0x" 727c478bd9Sstevel@tonic-gate #define _P_ZEROX L"0X" 737c478bd9Sstevel@tonic-gate #define _M_ISDIGIT(c) (((c) >= 0) && ((c) < 256) && isdigit((c))) 747c478bd9Sstevel@tonic-gate #define _M_ISUPPER(c) (((c) >= 0) && ((c) < 256) && isupper((c))) 757c478bd9Sstevel@tonic-gate #else /* _WIDE */ 767c478bd9Sstevel@tonic-gate #define STRCHR strchr 777c478bd9Sstevel@tonic-gate #define STRSPN strspn 787c478bd9Sstevel@tonic-gate #define ATOI(x) atoi(x) 797c478bd9Sstevel@tonic-gate #define _P_HYPHEN "-" 807c478bd9Sstevel@tonic-gate #define _P_PLUS "+" 817c478bd9Sstevel@tonic-gate #define _P_BLANK " " 827c478bd9Sstevel@tonic-gate #define _P_ZEROx "0x" 837c478bd9Sstevel@tonic-gate #define _P_ZEROX "0X" 847c478bd9Sstevel@tonic-gate #define _M_ISDIGIT(c) isdigit((c)) 857c478bd9Sstevel@tonic-gate #define _M_ISUPPER(c) isupper((c)) 867c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate #ifdef _WIDE 897c478bd9Sstevel@tonic-gate #define PUT(p, n) \ 907c478bd9Sstevel@tonic-gate { \ 917c478bd9Sstevel@tonic-gate int retp; \ 924297a3b0SGarrett D'Amore retp = put_wide(iop, &bufptr, bufferend, p, n, sflag); \ 937c478bd9Sstevel@tonic-gate if (retp == EOF) { \ 947c478bd9Sstevel@tonic-gate return ((ssize_t)EOF); \ 957c478bd9Sstevel@tonic-gate } \ 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate #define PAD(s, n) \ 997c478bd9Sstevel@tonic-gate { \ 1007c478bd9Sstevel@tonic-gate int retp; \ 1017c478bd9Sstevel@tonic-gate retp = pad_wide(iop, &bufptr, bufferend, s, n, sflag); \ 1027c478bd9Sstevel@tonic-gate if (retp == EOF) { \ 1037c478bd9Sstevel@tonic-gate return ((ssize_t)EOF); \ 1047c478bd9Sstevel@tonic-gate } \ 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate #define FPCONV(func, val, prec, decpt, sign, cvtbuf) \ 1087c478bd9Sstevel@tonic-gate { \ 1097c478bd9Sstevel@tonic-gate char cb[DECIMAL_STRING_LENGTH]; \ 1107c478bd9Sstevel@tonic-gate wchar_t *wp; \ 1117c478bd9Sstevel@tonic-gate char *cp; \ 1127c478bd9Sstevel@tonic-gate (void) func(val, prec, decpt, sign, cb); \ 1137c478bd9Sstevel@tonic-gate wp = cvtbuf; \ 1147c478bd9Sstevel@tonic-gate cp = cb; \ 1157c478bd9Sstevel@tonic-gate while (*cp) { \ 1167c478bd9Sstevel@tonic-gate *wp++ = (wchar_t)*cp++; \ 1177c478bd9Sstevel@tonic-gate } \ 1187c478bd9Sstevel@tonic-gate *wp = L'\0'; \ 1197c478bd9Sstevel@tonic-gate } 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate #else /* _WIDE */ 1227c478bd9Sstevel@tonic-gate #define PUT(p, n) \ 1237c478bd9Sstevel@tonic-gate {\ 1247c478bd9Sstevel@tonic-gate /*\ 1257c478bd9Sstevel@tonic-gate * When _doprnt() is called by [v]snprintf, we need to \ 1267c478bd9Sstevel@tonic-gate * always call _dowrite(). We also need to call _dowrite() \ 1277c478bd9Sstevel@tonic-gate * if the bufptr lies beyond the end of the buffer. This \ 1287c478bd9Sstevel@tonic-gate * is possible due to known off-by-one errors in __flsbuf() \ 1297c478bd9Sstevel@tonic-gate * and _fwrite_unlocked(). See 1235867 and 1231720 for the \ 1307c478bd9Sstevel@tonic-gate * sordid details. \ 1317c478bd9Sstevel@tonic-gate */\ 1327c478bd9Sstevel@tonic-gate if (snflag || bufptr > bufferend ||\ 1337c478bd9Sstevel@tonic-gate (unsigned long)(bufferend - bufptr) < (n)) {\ 1347c478bd9Sstevel@tonic-gate if (!_dowrite(p, n, iop, &bufptr)) {\ 1357c478bd9Sstevel@tonic-gate return (EOF);\ 1367c478bd9Sstevel@tonic-gate }\ 1377c478bd9Sstevel@tonic-gate } else {\ 1387c478bd9Sstevel@tonic-gate unsigned char *fbp = bufptr;\ 1397c478bd9Sstevel@tonic-gate switch (n) {\ 1407c478bd9Sstevel@tonic-gate case 4:\ 1417c478bd9Sstevel@tonic-gate *fbp = *p;\ 1427c478bd9Sstevel@tonic-gate *(fbp + 1) = *(p + 1);\ 1437c478bd9Sstevel@tonic-gate *(fbp + 2) = *(p + 2);\ 1447c478bd9Sstevel@tonic-gate *(fbp + 3) = *(p + 3);\ 1457c478bd9Sstevel@tonic-gate bufptr += 4;\ 1467c478bd9Sstevel@tonic-gate break;\ 1477c478bd9Sstevel@tonic-gate case 3:\ 1487c478bd9Sstevel@tonic-gate *fbp = *p;\ 1497c478bd9Sstevel@tonic-gate *(fbp + 1) = *(p + 1);\ 1507c478bd9Sstevel@tonic-gate *(fbp + 2) = *(p + 2);\ 1517c478bd9Sstevel@tonic-gate bufptr += 3;\ 1527c478bd9Sstevel@tonic-gate break;\ 1537c478bd9Sstevel@tonic-gate case 2:\ 1547c478bd9Sstevel@tonic-gate *fbp = *p;\ 1557c478bd9Sstevel@tonic-gate *(fbp + 1) = *(p + 1);\ 1567c478bd9Sstevel@tonic-gate bufptr += 2;\ 1577c478bd9Sstevel@tonic-gate break;\ 1587c478bd9Sstevel@tonic-gate case 1:\ 1597c478bd9Sstevel@tonic-gate *bufptr++ = *p;\ 1607c478bd9Sstevel@tonic-gate break;\ 1617c478bd9Sstevel@tonic-gate default:\ 1627c478bd9Sstevel@tonic-gate bufptr = (unsigned char *)memcpy(fbp, p, n)\ 1637c478bd9Sstevel@tonic-gate + (n);\ 1647c478bd9Sstevel@tonic-gate }\ 1657c478bd9Sstevel@tonic-gate }\ 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate #define PAD(s, n) { ssize_t nn; \ 1697c478bd9Sstevel@tonic-gate for (nn = n; nn > PAD_LEN; nn -= PAD_LEN) \ 1707c478bd9Sstevel@tonic-gate if (!_dowrite(s, PAD_LEN, iop, &bufptr)) \ 1717c478bd9Sstevel@tonic-gate return (EOF); \ 1727c478bd9Sstevel@tonic-gate PUT(s, nn); \ 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate #define FPCONV(func, val, prec, decpt, sign, cvtbuf) \ 1767c478bd9Sstevel@tonic-gate (void) func(val, prec, decpt, sign, cvtbuf); 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /* bit positions for flags used in doprnt */ 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate #define LENGTH 0x1 /* l */ 1837c478bd9Sstevel@tonic-gate #define FPLUS 0x2 /* + */ 1847c478bd9Sstevel@tonic-gate #define FMINUS 0x4 /* - */ 1857c478bd9Sstevel@tonic-gate #define FBLANK 0x8 /* blank */ 1867c478bd9Sstevel@tonic-gate #define FSHARP 0x10 /* # */ 1877c478bd9Sstevel@tonic-gate #define PADZERO 0x20 /* padding zeroes requested via '0' */ 1887c478bd9Sstevel@tonic-gate #define DOTSEEN 0x40 /* dot appeared in format specification */ 1897c478bd9Sstevel@tonic-gate #define SUFFIX 0x80 /* a suffix is to appear in the output */ 1907c478bd9Sstevel@tonic-gate #define RZERO 0x100 /* there will be trailing zeros in output */ 1917c478bd9Sstevel@tonic-gate #define LZERO 0x200 /* there will be leading zeroes in output */ 1927c478bd9Sstevel@tonic-gate #define SHORT 0x400 /* h */ 1937c478bd9Sstevel@tonic-gate #define QUAD 0x800 /* Q for long double */ 1947c478bd9Sstevel@tonic-gate #define XLONG 0x1000 /* ll for long long */ 1957c478bd9Sstevel@tonic-gate #define CHAR 0x2000 /* hh for char */ 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate #ifdef _WIDE 1987c478bd9Sstevel@tonic-gate static wchar_t * 1997c478bd9Sstevel@tonic-gate insert_thousands_sep(wchar_t *bp, wchar_t *ep); 2007c478bd9Sstevel@tonic-gate #else /* _WIDE */ 2017c478bd9Sstevel@tonic-gate static char * 2027c478bd9Sstevel@tonic-gate insert_thousands_sep(char *bp, char *ep); 2037c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate static int _rec_scrswidth(wchar_t *, ssize_t); 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate /* 2087c478bd9Sstevel@tonic-gate * Positional Parameter information 2097c478bd9Sstevel@tonic-gate */ 2107c478bd9Sstevel@tonic-gate #define MAXARGS 30 /* max. number of args for fast positional paramters */ 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate static ssize_t 2137c478bd9Sstevel@tonic-gate _dowrite(const char *p, ssize_t n, FILE *iop, unsigned char **ptrptr); 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* 2167c478bd9Sstevel@tonic-gate * stva_list is used to subvert C's restriction that a variable with an 2177c478bd9Sstevel@tonic-gate * array type can not appear on the left hand side of an assignment operator. 2187c478bd9Sstevel@tonic-gate * By putting the array inside a structure, the functionality of assigning to 2197c478bd9Sstevel@tonic-gate * the whole array through a simple assignment is achieved.. 2207c478bd9Sstevel@tonic-gate */ 2217c478bd9Sstevel@tonic-gate typedef struct stva_list { 2227c478bd9Sstevel@tonic-gate va_list ap; 2237c478bd9Sstevel@tonic-gate } stva_list; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate #ifdef _WIDE 2267c478bd9Sstevel@tonic-gate static void _wmkarglst(wchar_t *, stva_list, stva_list [], int); 2277c478bd9Sstevel@tonic-gate static void _wgetarg(wchar_t *, stva_list *, long, int); 2287c478bd9Sstevel@tonic-gate #else /* _WIDE */ 2298793b36bSNick Todd static void _mkarglst(char *, stva_list, stva_list [], int); 2307c478bd9Sstevel@tonic-gate void _getarg(char *, stva_list *, long, int); 2317c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate static int 2377c478bd9Sstevel@tonic-gate _lowdigit(ssize_t *valptr) 2387c478bd9Sstevel@tonic-gate { 2397c478bd9Sstevel@tonic-gate /* This function computes the decimal low-order digit of the number */ 2407c478bd9Sstevel@tonic-gate /* pointed to by valptr, and returns this digit after dividing */ 2417c478bd9Sstevel@tonic-gate /* *valptr by ten. This function is called ONLY to compute the */ 2427c478bd9Sstevel@tonic-gate /* low-order digit of a long whose high-order bit is set. */ 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate ssize_t lowbit = *valptr & 1; 2457c478bd9Sstevel@tonic-gate long value = (*valptr >> 1) & ~HIBITL; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate *valptr = value / 5; 2487c478bd9Sstevel@tonic-gate value = value % 5 * 2 + lowbit + '0'; 2497c478bd9Sstevel@tonic-gate return ((int)value); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate static int 2537c478bd9Sstevel@tonic-gate _lowlldigit(long long *valptr) 2547c478bd9Sstevel@tonic-gate { 2557c478bd9Sstevel@tonic-gate ssize_t lowbit = *valptr & 1; 2567c478bd9Sstevel@tonic-gate long long value = (*valptr >> 1) & ~HIBITLL; 2577c478bd9Sstevel@tonic-gate *valptr = value / 5; 2587c478bd9Sstevel@tonic-gate value = value % 5 * 2 + lowbit + '0'; 2597c478bd9Sstevel@tonic-gate return ((int)value); 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate /* The function _dowrite carries out buffer pointer bookkeeping surrounding */ 2637c478bd9Sstevel@tonic-gate /* a call to fwrite. It is called only when the end of the file output */ 2647c478bd9Sstevel@tonic-gate /* buffer is approached or in other unusual situations. */ 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate static ssize_t 2677c478bd9Sstevel@tonic-gate _dowrite(const char *p, ssize_t n, FILE *iop, unsigned char **ptrptr) 2687c478bd9Sstevel@tonic-gate { 2697c478bd9Sstevel@tonic-gate if (!(iop->_flag & _IOREAD)) { 2707c478bd9Sstevel@tonic-gate iop->_cnt -= (*ptrptr - iop->_ptr); 2717c478bd9Sstevel@tonic-gate iop->_ptr = *ptrptr; 2727c478bd9Sstevel@tonic-gate _bufsync(iop, _bufend(iop)); 2737c478bd9Sstevel@tonic-gate if (_FWRITE(p, 1, n, iop) != n) { 2747c478bd9Sstevel@tonic-gate return (0); 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate *ptrptr = iop->_ptr; 2777c478bd9Sstevel@tonic-gate } else { 2787c478bd9Sstevel@tonic-gate if (n > iop->_cnt) 2797c478bd9Sstevel@tonic-gate n = iop->_cnt; 2807c478bd9Sstevel@tonic-gate iop->_cnt -= n; 2817c478bd9Sstevel@tonic-gate *ptrptr = (unsigned char *)memcpy((char *)*ptrptr, p, n) + n; 2827c478bd9Sstevel@tonic-gate iop->_ptr = *ptrptr; 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate return (1); 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate #define PAD_LEN 20 2887c478bd9Sstevel@tonic-gate static const char _blanks[] = " "; 2897c478bd9Sstevel@tonic-gate static const char _zeroes[] = "00000000000000000000"; 2907c478bd9Sstevel@tonic-gate #ifdef _WIDE 2917c478bd9Sstevel@tonic-gate static const wchar_t uc_digs[] = L"0123456789ABCDEF"; 2927c478bd9Sstevel@tonic-gate static const wchar_t lc_digs[] = L"0123456789abcdef"; 2937c478bd9Sstevel@tonic-gate #else /* _WIDE */ 2947c478bd9Sstevel@tonic-gate static const char uc_digs[] = "0123456789ABCDEF"; 2957c478bd9Sstevel@tonic-gate static const char lc_digs[] = "0123456789abcdef"; 2967c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate #ifdef _WIDE 2997c478bd9Sstevel@tonic-gate static int 3007c478bd9Sstevel@tonic-gate put_wide(FILE *iop, unsigned char **bufptr, 3017c478bd9Sstevel@tonic-gate unsigned char *bufferend, wchar_t *p, size_t n, 3024297a3b0SGarrett D'Amore int sflag) 3037c478bd9Sstevel@tonic-gate { 3047c478bd9Sstevel@tonic-gate unsigned char *newbufptr; 3057c478bd9Sstevel@tonic-gate wchar_t *q; 3067c478bd9Sstevel@tonic-gate int r; 3077c478bd9Sstevel@tonic-gate size_t len, i; 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate if (sflag) { 3107c478bd9Sstevel@tonic-gate len = (wchar_t *)bufferend - (wchar_t *)*bufptr; 3117c478bd9Sstevel@tonic-gate if (n > len) { 3127c478bd9Sstevel@tonic-gate (void) wmemcpy((wchar_t *)*bufptr, p, len); 3137c478bd9Sstevel@tonic-gate iop->_ptr = bufferend; 3147c478bd9Sstevel@tonic-gate return (EOF); 3157c478bd9Sstevel@tonic-gate } else { 3167c478bd9Sstevel@tonic-gate (void) wmemcpy((wchar_t *)*bufptr, p, n); 3177257d1b4Sraf *bufptr = (unsigned char *)((wchar_t *)*bufptr + n); 3187c478bd9Sstevel@tonic-gate return (0); 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate } else { 3217c478bd9Sstevel@tonic-gate char *tmpp, *tmpq; 3227c478bd9Sstevel@tonic-gate size_t tsize; 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate tsize = (n + 1) * MB_LEN_MAX; 3257c478bd9Sstevel@tonic-gate tmpp = lmalloc(tsize); 3267c478bd9Sstevel@tonic-gate if (tmpp == NULL) { 3277c478bd9Sstevel@tonic-gate errno = ENOMEM; 3287c478bd9Sstevel@tonic-gate return (EOF); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate q = p; 3317c478bd9Sstevel@tonic-gate tmpq = tmpp; 3327c478bd9Sstevel@tonic-gate for (len = 0, i = 0; i < n; i++) { 3334297a3b0SGarrett D'Amore r = wctomb(tmpq, *q++); 3347c478bd9Sstevel@tonic-gate if (r == -1) { 3357c478bd9Sstevel@tonic-gate lfree(tmpp, tsize); 3367c478bd9Sstevel@tonic-gate errno = EILSEQ; 3377c478bd9Sstevel@tonic-gate return (EOF); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate len += r; 3407c478bd9Sstevel@tonic-gate tmpq += r; 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate tmpq = tmpp; 3437c478bd9Sstevel@tonic-gate newbufptr = *bufptr + len; 3447c478bd9Sstevel@tonic-gate if (newbufptr > bufferend) { 3457c478bd9Sstevel@tonic-gate if (!_dowrite(tmpp, len, iop, bufptr)) { 3467c478bd9Sstevel@tonic-gate lfree(tmpp, tsize); 3477c478bd9Sstevel@tonic-gate return (EOF); 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate } else { 3507c478bd9Sstevel@tonic-gate (void) memcpy(*bufptr, tmpp, len); 3517c478bd9Sstevel@tonic-gate *bufptr = newbufptr; 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate lfree(tmpp, tsize); 3547c478bd9Sstevel@tonic-gate return (0); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate static int 3597c478bd9Sstevel@tonic-gate pad_wide(FILE *iop, unsigned char **bufptr, 3607c478bd9Sstevel@tonic-gate unsigned char *bufferend, const char *s, size_t n, 3617c478bd9Sstevel@tonic-gate int sflag) 3627c478bd9Sstevel@tonic-gate { 3637c478bd9Sstevel@tonic-gate unsigned char *newbufptr; 3647c478bd9Sstevel@tonic-gate ssize_t nn; 3657c478bd9Sstevel@tonic-gate size_t len; 3667c478bd9Sstevel@tonic-gate wchar_t ps; 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate if (sflag) { 3697c478bd9Sstevel@tonic-gate /* for swprintf */ 3707c478bd9Sstevel@tonic-gate ps = (wchar_t)s[0]; 3717c478bd9Sstevel@tonic-gate len = (wchar_t *)bufferend - (wchar_t *)*bufptr; 3727c478bd9Sstevel@tonic-gate if (n > len) { 3737c478bd9Sstevel@tonic-gate (void) wmemset((wchar_t *)*bufptr, ps, len); 3747c478bd9Sstevel@tonic-gate iop->_ptr = bufferend; 3757c478bd9Sstevel@tonic-gate return (EOF); 3767c478bd9Sstevel@tonic-gate } else { 3777c478bd9Sstevel@tonic-gate (void) wmemset((wchar_t *)*bufptr, ps, n); 3787257d1b4Sraf *bufptr = (unsigned char *)((wchar_t *)*bufptr + n); 3797c478bd9Sstevel@tonic-gate return (0); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate } else { 3827c478bd9Sstevel@tonic-gate for (nn = n; nn > PAD_LEN; nn -= PAD_LEN) { 3837c478bd9Sstevel@tonic-gate if (!_dowrite(s, PAD_LEN, iop, bufptr)) 3847c478bd9Sstevel@tonic-gate return (EOF); 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate newbufptr = *bufptr + nn; 3877c478bd9Sstevel@tonic-gate if (newbufptr > bufferend) { 3887c478bd9Sstevel@tonic-gate if (!_dowrite(s, nn, iop, bufptr)) 3897c478bd9Sstevel@tonic-gate return (EOF); 3907c478bd9Sstevel@tonic-gate } else { 3917c478bd9Sstevel@tonic-gate (void) memcpy(*bufptr, s, nn); 3927c478bd9Sstevel@tonic-gate *bufptr = newbufptr; 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate return (0); 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate } 3977c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate #ifdef _WIDE 4007c478bd9Sstevel@tonic-gate ssize_t 4017c478bd9Sstevel@tonic-gate _wdoprnt(const wchar_t *format, va_list in_args, FILE *iop) 4027c478bd9Sstevel@tonic-gate { 4037c478bd9Sstevel@tonic-gate return (_wndoprnt(format, in_args, iop, 0)); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate #else /* _WIDE */ 4067c478bd9Sstevel@tonic-gate ssize_t 4077c478bd9Sstevel@tonic-gate _doprnt(const char *format, va_list in_args, FILE *iop) 4087c478bd9Sstevel@tonic-gate { 4097c478bd9Sstevel@tonic-gate return (_ndoprnt(format, in_args, iop, 0)); 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate #ifdef _WIDE 4157c478bd9Sstevel@tonic-gate ssize_t 4167c478bd9Sstevel@tonic-gate _wndoprnt(const wchar_t *format, va_list in_args, FILE *iop, int prflag) 4177c478bd9Sstevel@tonic-gate #else /* _WIDE */ 4187c478bd9Sstevel@tonic-gate ssize_t 4197c478bd9Sstevel@tonic-gate _ndoprnt(const char *format, va_list in_args, FILE *iop, int prflag) 4207c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 4217c478bd9Sstevel@tonic-gate { 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate #ifdef _WIDE 4247c478bd9Sstevel@tonic-gate int sflag = 0; 4257c478bd9Sstevel@tonic-gate size_t maxcount; 4267c478bd9Sstevel@tonic-gate #else 4277c478bd9Sstevel@tonic-gate int snflag = 0; 4287c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 4297c478bd9Sstevel@tonic-gate /* bufptr is used inside of doprnt instead of iop->_ptr; */ 4307c478bd9Sstevel@tonic-gate /* bufferend is a copy of _bufend(iop), if it exists. For */ 4317c478bd9Sstevel@tonic-gate /* dummy file descriptors (iop->_flag & _IOREAD), bufferend */ 4327c478bd9Sstevel@tonic-gate /* may be meaningless. Dummy file descriptors are used so that */ 4337c478bd9Sstevel@tonic-gate /* sprintf and vsprintf may share the _doprnt routine with the */ 4347c478bd9Sstevel@tonic-gate /* rest of the printf family. */ 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate unsigned char *bufptr; 4377c478bd9Sstevel@tonic-gate unsigned char *bufferend; 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate #ifdef _WIDE 4407c478bd9Sstevel@tonic-gate /* This variable counts output characters. */ 4417c478bd9Sstevel@tonic-gate size_t count = 0; 4427c478bd9Sstevel@tonic-gate #else /* _WIDE */ 4437c478bd9Sstevel@tonic-gate /* This variable counts output characters. */ 4447c478bd9Sstevel@tonic-gate int count = 0; 4457c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate #ifdef _WIDE 4487c478bd9Sstevel@tonic-gate wchar_t *bp; 4497c478bd9Sstevel@tonic-gate size_t bpsize; 4507c478bd9Sstevel@tonic-gate wchar_t *p; 4517c478bd9Sstevel@tonic-gate char *cbp; 4527c478bd9Sstevel@tonic-gate char *cp; 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate #else /* _WIDE */ 4557c478bd9Sstevel@tonic-gate /* Starting and ending points for value to be printed */ 4567c478bd9Sstevel@tonic-gate char *bp; 4577c478bd9Sstevel@tonic-gate char *p; 4587c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 4597c478bd9Sstevel@tonic-gate /* Field width and precision */ 4607c478bd9Sstevel@tonic-gate int prec = 0; 4617c478bd9Sstevel@tonic-gate ssize_t width; 4627c478bd9Sstevel@tonic-gate ssize_t num; 4637c478bd9Sstevel@tonic-gate ssize_t sec_display; 4647c478bd9Sstevel@tonic-gate wchar_t *wp; 4657c478bd9Sstevel@tonic-gate ssize_t preco; 4667c478bd9Sstevel@tonic-gate ssize_t wcount = 0; 4677c478bd9Sstevel@tonic-gate char tmpbuf[10]; 4687c478bd9Sstevel@tonic-gate char wflag; 4697c478bd9Sstevel@tonic-gate char lflag; 4707c478bd9Sstevel@tonic-gate int quote; /* ' */ 4717c478bd9Sstevel@tonic-gate int retcode; 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate #ifdef _WIDE 4757c478bd9Sstevel@tonic-gate /* Format code */ 4767c478bd9Sstevel@tonic-gate wchar_t fcode; 4777c478bd9Sstevel@tonic-gate #else /* _WIDE */ 4787c478bd9Sstevel@tonic-gate /* Format code */ 4797c478bd9Sstevel@tonic-gate char fcode; 4807c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate /* Number of padding zeroes required on the left and right */ 4837c478bd9Sstevel@tonic-gate ssize_t lzero, rzero, rz, leadzeroes; 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate /* Flags - bit positions defined by LENGTH, FPLUS, FMINUS, FBLANK, */ 4877c478bd9Sstevel@tonic-gate /* and FSHARP are set if corresponding character is in format */ 4887c478bd9Sstevel@tonic-gate /* Bit position defined by PADZERO means extra space in the field */ 4897c478bd9Sstevel@tonic-gate /* should be padded with leading zeroes rather than with blanks */ 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate ssize_t flagword; 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate #ifdef _WIDE 4947c478bd9Sstevel@tonic-gate /* Values are developed in this buffer */ 4957c478bd9Sstevel@tonic-gate wchar_t buf[max(MAXLLDIGS, 1034)]; 4967c478bd9Sstevel@tonic-gate wchar_t cvtbuf[512 + DECIMAL_STRING_LENGTH]; 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate /* Pointer to sign, "0x", "0X", or empty */ 4997c478bd9Sstevel@tonic-gate wchar_t *prefix; 5007c478bd9Sstevel@tonic-gate wchar_t prefixbuf[4]; 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate /* Exponent or empty */ 5037c478bd9Sstevel@tonic-gate wchar_t *suffix; 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate /* Buffer to create exponent */ 5067c478bd9Sstevel@tonic-gate wchar_t expbuf[MAXESIZ + 1]; 5077c478bd9Sstevel@tonic-gate #else /* _WIDE */ 5087c478bd9Sstevel@tonic-gate /* Values are developed in this buffer */ 5097c478bd9Sstevel@tonic-gate char buf[max(MAXLLDIGS, 1034)]; 5107c478bd9Sstevel@tonic-gate char cvtbuf[512 + DECIMAL_STRING_LENGTH]; 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate /* Pointer to sign, "0x", "0X", or empty */ 5137c478bd9Sstevel@tonic-gate char *prefix; 5147c478bd9Sstevel@tonic-gate char prefixbuf[4]; 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate /* Exponent or empty */ 5177c478bd9Sstevel@tonic-gate char *suffix; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate /* Buffer to create exponent */ 5207c478bd9Sstevel@tonic-gate char expbuf[MAXESIZ + 1]; 5217c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate /* Length of prefix and of suffix */ 5247c478bd9Sstevel@tonic-gate ssize_t prefixlength, suffixlength; 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate /* Combined length of leading zeroes, trailing zeroes, and suffix */ 5277c478bd9Sstevel@tonic-gate ssize_t otherlength; 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate /* The value being converted, if integer */ 5307c478bd9Sstevel@tonic-gate ssize_t val; 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate /* The value being converted, if long long */ 5337c478bd9Sstevel@tonic-gate long long ll = 0LL; 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate /* Output value from aconvert */ 5367c478bd9Sstevel@tonic-gate int exp; 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate /* Output values from fcvt and ecvt */ 5397c478bd9Sstevel@tonic-gate int decpt, sign; 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate #ifdef _WIDE 5427c478bd9Sstevel@tonic-gate /* Pointer to a translate table for digits of whatever radix */ 5437c478bd9Sstevel@tonic-gate const wchar_t *tab; 5447c478bd9Sstevel@tonic-gate #else /* _WIDE */ 5457c478bd9Sstevel@tonic-gate /* Pointer to a translate table for digits of whatever radix */ 5467c478bd9Sstevel@tonic-gate const char *tab; 5477c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate /* Work variables */ 5507c478bd9Sstevel@tonic-gate ssize_t k, lradix, mradix; 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate int inf_nan = 0; 5537c478bd9Sstevel@tonic-gate int inf_nan_mixed_case = 0; 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate #ifdef _WIDE 5567c478bd9Sstevel@tonic-gate /* variables for positional parameters */ 5577c478bd9Sstevel@tonic-gate /* save the beginning of the format */ 5587c478bd9Sstevel@tonic-gate wchar_t *sformat = (wchar_t *)format; 5597c478bd9Sstevel@tonic-gate #else /* _WIDE */ 5607c478bd9Sstevel@tonic-gate /* variables for positional parameters */ 5617c478bd9Sstevel@tonic-gate char *sformat = (char *)format; /* save the beginning of the format */ 5627c478bd9Sstevel@tonic-gate #endif 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate int fpos = 1; /* 1 if first positional parameter */ 5657c478bd9Sstevel@tonic-gate stva_list args, /* used to step through the argument list */ 5667c478bd9Sstevel@tonic-gate sargs; /* used to save the start of the arg list */ 5677c478bd9Sstevel@tonic-gate stva_list bargs; /* used to restore args if positional width */ 5687c478bd9Sstevel@tonic-gate /* or precision */ 5697c478bd9Sstevel@tonic-gate stva_list arglst[MAXARGS]; /* array giving appropriate values */ 5707c478bd9Sstevel@tonic-gate /* for va_arg() to retrieve the */ 5717c478bd9Sstevel@tonic-gate /* corresponding argument: */ 5727c478bd9Sstevel@tonic-gate /* arglst[0] is the first arg */ 5737c478bd9Sstevel@tonic-gate /* arglst[1] is the second arg, etc */ 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate int starflg = 0; /* set to 1 if * format specifier seen */ 576*762f6727SJason King struct lconv *locptr = localeconv(); 577*762f6727SJason King char decimal_point = *locptr->decimal_point; 578*762f6727SJason King 5797c478bd9Sstevel@tonic-gate /* 5807c478bd9Sstevel@tonic-gate * Initialize args and sargs to the start of the argument list. 5817c478bd9Sstevel@tonic-gate * We don't know any portable way to copy an arbitrary C object 5827c478bd9Sstevel@tonic-gate * so we use a system-specific routine (probably a macro) from 5837c478bd9Sstevel@tonic-gate * stdarg.h. (Remember that if va_list is an array, in_args will 5847c478bd9Sstevel@tonic-gate * be a pointer and &in_args won't be what we would want for 5857c478bd9Sstevel@tonic-gate * memcpy.) 5867c478bd9Sstevel@tonic-gate */ 5877c478bd9Sstevel@tonic-gate va_copy(args.ap, in_args); 5887c478bd9Sstevel@tonic-gate sargs = args; 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate #ifdef _WIDE 5917c478bd9Sstevel@tonic-gate if (iop->_flag == _IOREAD) 5927c478bd9Sstevel@tonic-gate sflag = 1; 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate if (!sflag) { 5957c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 5967c478bd9Sstevel@tonic-gate /* if first I/O to the stream get a buffer */ 5977c478bd9Sstevel@tonic-gate /* Note that iop->_base should not equal 0 for sprintf and vsprintf */ 5987c478bd9Sstevel@tonic-gate if (iop->_base == 0) { 5997c478bd9Sstevel@tonic-gate if (_findbuf(iop) == 0) 6007c478bd9Sstevel@tonic-gate return (EOF); 6017c478bd9Sstevel@tonic-gate /* _findbuf leaves _cnt set to 0 which is the wrong thing to do */ 6027c478bd9Sstevel@tonic-gate /* for fully buffered files */ 6037c478bd9Sstevel@tonic-gate if (!(iop->_flag & (_IOLBF|_IONBF))) 6047c478bd9Sstevel@tonic-gate iop->_cnt = _bufend(iop) - iop->_base; 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate #ifdef _WIDE 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate #ifdef _WIDE 6117c478bd9Sstevel@tonic-gate bufptr = iop->_ptr; 6127c478bd9Sstevel@tonic-gate if (sflag) { 6137c478bd9Sstevel@tonic-gate maxcount = (size_t)iop->_cnt; 6147c478bd9Sstevel@tonic-gate bufferend = (unsigned char *)(((wchar_t *)iop->_ptr) + 6157c478bd9Sstevel@tonic-gate maxcount); 6167c478bd9Sstevel@tonic-gate } else { 6177c478bd9Sstevel@tonic-gate bufferend = _bufend(iop); 6187c478bd9Sstevel@tonic-gate } 6197c478bd9Sstevel@tonic-gate #else /* _WIDE */ 6207c478bd9Sstevel@tonic-gate /* initialize buffer pointer and buffer end pointer */ 6217c478bd9Sstevel@tonic-gate bufptr = iop->_ptr; 6227c478bd9Sstevel@tonic-gate if (iop->_flag & _IOREAD) { 6237c478bd9Sstevel@tonic-gate /* 6247c478bd9Sstevel@tonic-gate * [v]sprintf or [v]snprintf 6257c478bd9Sstevel@tonic-gate */ 6267c478bd9Sstevel@tonic-gate if (iop->_cnt == MAXINT) { 6277c478bd9Sstevel@tonic-gate /* 6287c478bd9Sstevel@tonic-gate * [v]sprintf (no boundschecking) 6297c478bd9Sstevel@tonic-gate */ 6307c478bd9Sstevel@tonic-gate bufferend = 6317c478bd9Sstevel@tonic-gate (unsigned char *)((long)bufptr | (-1L & ~HIBITL)); 6327c478bd9Sstevel@tonic-gate } else { 6337c478bd9Sstevel@tonic-gate /* 6347c478bd9Sstevel@tonic-gate * [v]snprintf (with boundschecking) or 6357c478bd9Sstevel@tonic-gate * iop with _IORW has been read. 6367c478bd9Sstevel@tonic-gate */ 6377c478bd9Sstevel@tonic-gate bufferend = _bufend(iop); 6387c478bd9Sstevel@tonic-gate if (bufferend == NULL) { 6397c478bd9Sstevel@tonic-gate /* 6407c478bd9Sstevel@tonic-gate * [v]snprintf 6417c478bd9Sstevel@tonic-gate * 6427c478bd9Sstevel@tonic-gate * [v]snprint() needs to be always handled by 6437c478bd9Sstevel@tonic-gate * _dowrite(). 6447c478bd9Sstevel@tonic-gate */ 6457c478bd9Sstevel@tonic-gate snflag = 1; 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate } else { 6497c478bd9Sstevel@tonic-gate /* 6507c478bd9Sstevel@tonic-gate * [v]printf or [v]fprintf 6517c478bd9Sstevel@tonic-gate */ 6527c478bd9Sstevel@tonic-gate bufferend = _bufend(iop); 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate /* 6577c478bd9Sstevel@tonic-gate * The main loop -- this loop goes through one iteration 6587c478bd9Sstevel@tonic-gate * for each string of ordinary characters or format specification. 6597c478bd9Sstevel@tonic-gate */ 6607c478bd9Sstevel@tonic-gate for (; ; ) { 6617c478bd9Sstevel@tonic-gate ssize_t n; 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate if ((fcode = *format) != '\0' && fcode != '%') { 6647c478bd9Sstevel@tonic-gate #ifdef _WIDE 6657c478bd9Sstevel@tonic-gate bp = (wchar_t *)format; 6667c478bd9Sstevel@tonic-gate #else /* _WIDE */ 6677c478bd9Sstevel@tonic-gate bp = (char *)format; 6687c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 6697c478bd9Sstevel@tonic-gate do { 6707c478bd9Sstevel@tonic-gate format++; 6717c478bd9Sstevel@tonic-gate } while ((fcode = *format) != '\0' && fcode != '%'); 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate count += (n = format - bp); /* n = no. of non-% chars */ 6747c478bd9Sstevel@tonic-gate PUT(bp, n); 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate if (fcode == '\0') { /* end of format; return */ 6777c478bd9Sstevel@tonic-gate ssize_t nn = bufptr - iop->_ptr; 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate #ifdef _WIDE 6807c478bd9Sstevel@tonic-gate if (sflag) { 6817c478bd9Sstevel@tonic-gate iop->_ptr = bufptr; 6827c478bd9Sstevel@tonic-gate return ((ssize_t)count); 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate iop->_cnt -= nn; 6877c478bd9Sstevel@tonic-gate iop->_ptr = bufptr; 6887c478bd9Sstevel@tonic-gate /* in case of interrupt during last several lines */ 6897c478bd9Sstevel@tonic-gate if ((bufptr + iop->_cnt) > bufferend && !(iop->_flag \ 6907c478bd9Sstevel@tonic-gate & _IOREAD)) 6917c478bd9Sstevel@tonic-gate _bufsync(iop, bufferend); 6927c478bd9Sstevel@tonic-gate if (iop->_flag & (_IONBF | _IOLBF) && \ 6937c478bd9Sstevel@tonic-gate (iop->_flag & _IONBF || \ 6947c478bd9Sstevel@tonic-gate memchr((char *)(bufptr+iop->_cnt), \ 6957c478bd9Sstevel@tonic-gate '\n', -iop->_cnt) != NULL)) 6967c478bd9Sstevel@tonic-gate (void) _xflsbuf(iop); 6977c478bd9Sstevel@tonic-gate #ifdef _WIDE 6987c478bd9Sstevel@tonic-gate return (FERROR(iop) ? EOF : (ssize_t)count); 6997c478bd9Sstevel@tonic-gate #else /* _WIDE */ 7007c478bd9Sstevel@tonic-gate return (FERROR(iop) ? EOF : (int)count); 7017c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate /* 7057c478bd9Sstevel@tonic-gate * % has been found. 7067c478bd9Sstevel@tonic-gate * The following switch is used to parse the format 7077c478bd9Sstevel@tonic-gate * specification and to perform the operation specified 7087c478bd9Sstevel@tonic-gate * by the format letter. The program repeatedly goes 7097c478bd9Sstevel@tonic-gate * back to this switch until the format letter is 7107c478bd9Sstevel@tonic-gate * encountered. 7117c478bd9Sstevel@tonic-gate */ 7127c478bd9Sstevel@tonic-gate width = prefixlength = otherlength = 0; 7137c478bd9Sstevel@tonic-gate flagword = suffixlength = 0; 7147c478bd9Sstevel@tonic-gate format++; 7157c478bd9Sstevel@tonic-gate wflag = 0; 7167c478bd9Sstevel@tonic-gate lflag = 0; 7177c478bd9Sstevel@tonic-gate sec_display = 0; 7187c478bd9Sstevel@tonic-gate quote = 0; 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate charswitch: 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate switch (fcode = *format++) { 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate case '+': 7257c478bd9Sstevel@tonic-gate flagword |= FPLUS; 7267c478bd9Sstevel@tonic-gate goto charswitch; 7277c478bd9Sstevel@tonic-gate case '-': 7287c478bd9Sstevel@tonic-gate flagword |= FMINUS; 7297c478bd9Sstevel@tonic-gate flagword &= ~PADZERO; /* ignore 0 flag */ 7307c478bd9Sstevel@tonic-gate goto charswitch; 7317c478bd9Sstevel@tonic-gate case ' ': 7327c478bd9Sstevel@tonic-gate flagword |= FBLANK; 7337c478bd9Sstevel@tonic-gate goto charswitch; 7347c478bd9Sstevel@tonic-gate case '\'': /* XSH4 */ 7357c478bd9Sstevel@tonic-gate quote++; 7367c478bd9Sstevel@tonic-gate goto charswitch; 7377c478bd9Sstevel@tonic-gate case '#': 7387c478bd9Sstevel@tonic-gate flagword |= FSHARP; 7397c478bd9Sstevel@tonic-gate goto charswitch; 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate /* Scan the field width and precision */ 7427c478bd9Sstevel@tonic-gate case '.': 7437c478bd9Sstevel@tonic-gate flagword |= DOTSEEN; 7447c478bd9Sstevel@tonic-gate prec = 0; 7457c478bd9Sstevel@tonic-gate goto charswitch; 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate case '*': 7487c478bd9Sstevel@tonic-gate if (_M_ISDIGIT(*format)) { 7497c478bd9Sstevel@tonic-gate starflg = 1; 7507c478bd9Sstevel@tonic-gate bargs = args; 7517c478bd9Sstevel@tonic-gate goto charswitch; 7527c478bd9Sstevel@tonic-gate } 7537c478bd9Sstevel@tonic-gate if (!(flagword & DOTSEEN)) { 7547c478bd9Sstevel@tonic-gate width = va_arg(args.ap, int); 7557c478bd9Sstevel@tonic-gate if (width < 0) { 7567c478bd9Sstevel@tonic-gate width = -width; 7577c478bd9Sstevel@tonic-gate flagword |= FMINUS; 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate } else { 7607c478bd9Sstevel@tonic-gate prec = va_arg(args.ap, int); 7617c478bd9Sstevel@tonic-gate if (prec < 0) { 7627c478bd9Sstevel@tonic-gate prec = 0; 7637c478bd9Sstevel@tonic-gate flagword ^= DOTSEEN; /* ANSI sez so */ 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate goto charswitch; 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate case '$': 7697c478bd9Sstevel@tonic-gate { 7707c478bd9Sstevel@tonic-gate ssize_t position; 7717c478bd9Sstevel@tonic-gate stva_list targs; 7727c478bd9Sstevel@tonic-gate if (fpos) { 7737c478bd9Sstevel@tonic-gate #ifdef _WIDE 7747c478bd9Sstevel@tonic-gate _wmkarglst(sformat, sargs, arglst, prflag); 7757c478bd9Sstevel@tonic-gate #else /* _WIDE */ 7767c478bd9Sstevel@tonic-gate _mkarglst(sformat, sargs, arglst, prflag); 7777c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 7787c478bd9Sstevel@tonic-gate fpos = 0; 7797c478bd9Sstevel@tonic-gate } 7807c478bd9Sstevel@tonic-gate if (flagword & DOTSEEN) { 7817c478bd9Sstevel@tonic-gate position = prec; 7827c478bd9Sstevel@tonic-gate prec = 0; 7837c478bd9Sstevel@tonic-gate } else { 7847c478bd9Sstevel@tonic-gate position = width; 7857c478bd9Sstevel@tonic-gate width = 0; 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate if (position <= 0) { 7887c478bd9Sstevel@tonic-gate /* illegal position */ 7897c478bd9Sstevel@tonic-gate format--; 7907c478bd9Sstevel@tonic-gate continue; 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate if (position <= MAXARGS) { 7937c478bd9Sstevel@tonic-gate targs = arglst[position - 1]; 7947c478bd9Sstevel@tonic-gate } else { 7957c478bd9Sstevel@tonic-gate targs = arglst[MAXARGS - 1]; 7967c478bd9Sstevel@tonic-gate #ifdef _WIDE 7977c478bd9Sstevel@tonic-gate _wgetarg(sformat, &targs, position, prflag); 7987c478bd9Sstevel@tonic-gate #else /* _WIDE */ 7997c478bd9Sstevel@tonic-gate _getarg(sformat, &targs, position, prflag); 8007c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate if (!starflg) 8037c478bd9Sstevel@tonic-gate args = targs; 8047c478bd9Sstevel@tonic-gate else { 8057c478bd9Sstevel@tonic-gate starflg = 0; 8067c478bd9Sstevel@tonic-gate args = bargs; 8077c478bd9Sstevel@tonic-gate if (flagword & DOTSEEN) { 8087c478bd9Sstevel@tonic-gate prec = va_arg(targs.ap, int); 8097c478bd9Sstevel@tonic-gate if (prec < 0) { 8107c478bd9Sstevel@tonic-gate prec = 0; 8117c478bd9Sstevel@tonic-gate flagword ^= DOTSEEN; /* XSH */ 8127c478bd9Sstevel@tonic-gate } 8137c478bd9Sstevel@tonic-gate } else { 8147c478bd9Sstevel@tonic-gate width = va_arg(targs.ap, int); 8157c478bd9Sstevel@tonic-gate if (width < 0) { 8167c478bd9Sstevel@tonic-gate width = -width; 8177c478bd9Sstevel@tonic-gate flagword |= FMINUS; 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate } 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate goto charswitch; 8227c478bd9Sstevel@tonic-gate } 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate case '0': /* obsolescent spec: leading zero in width */ 8257c478bd9Sstevel@tonic-gate /* means pad with leading zeros */ 8267c478bd9Sstevel@tonic-gate if (!(flagword & (DOTSEEN | FMINUS))) 8277c478bd9Sstevel@tonic-gate flagword |= PADZERO; 8287c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 8297c478bd9Sstevel@tonic-gate case '1': 8307c478bd9Sstevel@tonic-gate case '2': 8317c478bd9Sstevel@tonic-gate case '3': 8327c478bd9Sstevel@tonic-gate case '4': 8337c478bd9Sstevel@tonic-gate case '5': 8347c478bd9Sstevel@tonic-gate case '6': 8357c478bd9Sstevel@tonic-gate case '7': 8367c478bd9Sstevel@tonic-gate case '8': 8377c478bd9Sstevel@tonic-gate case '9': 8387c478bd9Sstevel@tonic-gate { num = fcode - '0'; 8397c478bd9Sstevel@tonic-gate while (_M_ISDIGIT(fcode = *format)) { 8407c478bd9Sstevel@tonic-gate num = num * 10 + fcode - '0'; 8417c478bd9Sstevel@tonic-gate format++; 8427c478bd9Sstevel@tonic-gate } 8437c478bd9Sstevel@tonic-gate if (flagword & DOTSEEN) 8447c478bd9Sstevel@tonic-gate prec = num; 8457c478bd9Sstevel@tonic-gate else 8467c478bd9Sstevel@tonic-gate width = num; 8477c478bd9Sstevel@tonic-gate goto charswitch; 8487c478bd9Sstevel@tonic-gate } 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate /* Scan the length modifier */ 8517c478bd9Sstevel@tonic-gate case 'l': 8527c478bd9Sstevel@tonic-gate if (!(flagword & XLONG)) { 8537c478bd9Sstevel@tonic-gate if (lflag) { 8547c478bd9Sstevel@tonic-gate /* long long */ 8557c478bd9Sstevel@tonic-gate flagword &= ~LENGTH; 8567c478bd9Sstevel@tonic-gate flagword |= XLONG; 8577c478bd9Sstevel@tonic-gate } else { 8587c478bd9Sstevel@tonic-gate /* long */ 8597c478bd9Sstevel@tonic-gate flagword |= LENGTH; 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate lflag++; 8637c478bd9Sstevel@tonic-gate goto charswitch; 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate case 'L': /* long double */ 8667c478bd9Sstevel@tonic-gate flagword |= QUAD; 8677c478bd9Sstevel@tonic-gate goto charswitch; 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate case 'h': 8707c478bd9Sstevel@tonic-gate if (!(flagword & CHAR)) { 8717c478bd9Sstevel@tonic-gate if (flagword & SHORT) { 8727c478bd9Sstevel@tonic-gate /* char - hh */ 8737c478bd9Sstevel@tonic-gate flagword &= ~SHORT; 8747c478bd9Sstevel@tonic-gate flagword |= CHAR; 8757c478bd9Sstevel@tonic-gate } else { 8767c478bd9Sstevel@tonic-gate /* short */ 8777c478bd9Sstevel@tonic-gate flagword |= SHORT; 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate goto charswitch; 8817c478bd9Sstevel@tonic-gate case 'j': 8827c478bd9Sstevel@tonic-gate #ifndef _LP64 8837c478bd9Sstevel@tonic-gate /* 8847c478bd9Sstevel@tonic-gate * *printf_c89() in 32-bit libc uses 8857c478bd9Sstevel@tonic-gate * 32-bit intmax_t; otherwise intmax_t 8867c478bd9Sstevel@tonic-gate * is 64-bits. 8877c478bd9Sstevel@tonic-gate */ 8887c478bd9Sstevel@tonic-gate if (!(prflag & _F_INTMAX32)) { 8897c478bd9Sstevel@tonic-gate #endif 8907c478bd9Sstevel@tonic-gate flagword |= XLONG; /* [u]intmax_t (64) */ 8917c478bd9Sstevel@tonic-gate #ifndef _LP64 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate #endif 8947c478bd9Sstevel@tonic-gate goto charswitch; 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate case 't': 8977c478bd9Sstevel@tonic-gate /* 8987c478bd9Sstevel@tonic-gate * LENGTH is shared by l, t, z specifiers; protect 8997c478bd9Sstevel@tonic-gate * against (destructive) undefined behavior (eg: 9007c478bd9Sstevel@tonic-gate * avoid %llt setting XLONG and LENGTH) with invalid 9017c478bd9Sstevel@tonic-gate * combinations of specifiers 9027c478bd9Sstevel@tonic-gate */ 9037c478bd9Sstevel@tonic-gate if (!(flagword & XLONG)) { 9047c478bd9Sstevel@tonic-gate flagword |= LENGTH; /* ptrdiff_t */ 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate goto charswitch; 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate case 'z': 9097c478bd9Sstevel@tonic-gate if (!(flagword & XLONG)) { 9107c478bd9Sstevel@tonic-gate flagword |= LENGTH; /* [s]size_t */ 9117c478bd9Sstevel@tonic-gate } 9127c478bd9Sstevel@tonic-gate goto charswitch; 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate /* 9157c478bd9Sstevel@tonic-gate * The character addressed by format must be 9167c478bd9Sstevel@tonic-gate * the format letter -- there is nothing 9177c478bd9Sstevel@tonic-gate * left for it to be. 9187c478bd9Sstevel@tonic-gate * 9197c478bd9Sstevel@tonic-gate * The status of the +, -, #, and blank 9207c478bd9Sstevel@tonic-gate * flags are reflected in the variable 9217c478bd9Sstevel@tonic-gate * "flagword". "width" and "prec" contain 9227c478bd9Sstevel@tonic-gate * numbers corresponding to the digit 9237c478bd9Sstevel@tonic-gate * strings before and after the decimal 9247c478bd9Sstevel@tonic-gate * point, respectively. If there was no 9257c478bd9Sstevel@tonic-gate * decimal point, then flagword & DOTSEEN 9267c478bd9Sstevel@tonic-gate * is false and the value of prec is meaningless. 9277c478bd9Sstevel@tonic-gate * 9287c478bd9Sstevel@tonic-gate * The following switch cases set things up 9297c478bd9Sstevel@tonic-gate * for printing. What ultimately gets 9307c478bd9Sstevel@tonic-gate * printed will be padding blanks, a 9317c478bd9Sstevel@tonic-gate * prefix, left padding zeroes, a value, 9327c478bd9Sstevel@tonic-gate * right padding zeroes, a suffix, and 9337c478bd9Sstevel@tonic-gate * more padding blanks. Padding blanks 9347c478bd9Sstevel@tonic-gate * will not appear simultaneously on both 9357c478bd9Sstevel@tonic-gate * the left and the right. Each case in 9367c478bd9Sstevel@tonic-gate * this switch will compute the value, and 9377c478bd9Sstevel@tonic-gate * leave in several variables the informa- 9387c478bd9Sstevel@tonic-gate * tion necessary to construct what is to 9397c478bd9Sstevel@tonic-gate * be printed. 9407c478bd9Sstevel@tonic-gate * 9417c478bd9Sstevel@tonic-gate * The prefix is a sign, a blank, "0x", 9427c478bd9Sstevel@tonic-gate * "0X", a sign or a blank followed by "0x" 9437c478bd9Sstevel@tonic-gate * or "0X", or nothing, and is addressed by 9447c478bd9Sstevel@tonic-gate * "prefix". 9457c478bd9Sstevel@tonic-gate * 9467c478bd9Sstevel@tonic-gate * The suffix is either null or an 9477c478bd9Sstevel@tonic-gate * exponent, and is addressed by "suffix". 9487c478bd9Sstevel@tonic-gate * If there is a suffix, the flagword bit 9497c478bd9Sstevel@tonic-gate * SUFFIX will be set. 9507c478bd9Sstevel@tonic-gate * 9517c478bd9Sstevel@tonic-gate * The value to be printed starts at "bp" 9527c478bd9Sstevel@tonic-gate * and continues up to and not including 9537c478bd9Sstevel@tonic-gate * "p". 9547c478bd9Sstevel@tonic-gate * 9557c478bd9Sstevel@tonic-gate * "lzero" and "rzero" will contain the 9567c478bd9Sstevel@tonic-gate * number of padding zeroes required on 9577c478bd9Sstevel@tonic-gate * the left and right, respectively. 9587c478bd9Sstevel@tonic-gate * The flagword bits LZERO and RZERO tell 9597c478bd9Sstevel@tonic-gate * whether padding zeros are required. 9607c478bd9Sstevel@tonic-gate * 9617c478bd9Sstevel@tonic-gate * The number of padding blanks, and 9627c478bd9Sstevel@tonic-gate * whether they go on the left or the 9637c478bd9Sstevel@tonic-gate * right, will be computed on exit from 9647c478bd9Sstevel@tonic-gate * the switch. 9657c478bd9Sstevel@tonic-gate */ 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate /* 9707c478bd9Sstevel@tonic-gate * decimal fixed point representations 9717c478bd9Sstevel@tonic-gate * 9727c478bd9Sstevel@tonic-gate * HIBITL is 100...000 9737c478bd9Sstevel@tonic-gate * binary, and is equal to the maximum 9747c478bd9Sstevel@tonic-gate * negative number. 9757c478bd9Sstevel@tonic-gate * We assume a 2's complement machine 9767c478bd9Sstevel@tonic-gate */ 9777c478bd9Sstevel@tonic-gate case 'i': 9787c478bd9Sstevel@tonic-gate case 'd': 9797c478bd9Sstevel@tonic-gate if ((flagword & PADZERO) && (flagword & DOTSEEN)) 9807c478bd9Sstevel@tonic-gate flagword &= ~PADZERO; /* ignore 0 flag */ 9817c478bd9Sstevel@tonic-gate /* Set buffer pointer to last digit */ 9827c478bd9Sstevel@tonic-gate p = bp = buf + MAXLLDIGS; 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate /* Fetch the argument to be printed */ 9857c478bd9Sstevel@tonic-gate if (flagword & XLONG) { /* long long */ 9867c478bd9Sstevel@tonic-gate ll = va_arg(args.ap, long long); 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate /* If signed conversion, make sign */ 9897c478bd9Sstevel@tonic-gate if (ll < 0) { 9907c478bd9Sstevel@tonic-gate prefix = _P_HYPHEN; 9917c478bd9Sstevel@tonic-gate prefixlength = 1; 9927c478bd9Sstevel@tonic-gate /* 9937c478bd9Sstevel@tonic-gate * Negate, checking in advance for 9947c478bd9Sstevel@tonic-gate * possible overflow. 9957c478bd9Sstevel@tonic-gate */ 9967c478bd9Sstevel@tonic-gate if (ll != HIBITLL) 9977c478bd9Sstevel@tonic-gate ll = -ll; 9987c478bd9Sstevel@tonic-gate else 9997c478bd9Sstevel@tonic-gate /* number is -HIBITLL; convert last */ 10007c478bd9Sstevel@tonic-gate /* digit now and get positive number */ 10017c478bd9Sstevel@tonic-gate *--bp = _lowlldigit(&ll); 10027c478bd9Sstevel@tonic-gate } else if (flagword & FPLUS) { 10037c478bd9Sstevel@tonic-gate prefix = _P_PLUS; 10047c478bd9Sstevel@tonic-gate prefixlength = 1; 10057c478bd9Sstevel@tonic-gate } else if (flagword & FBLANK) { 10067c478bd9Sstevel@tonic-gate prefix = _P_BLANK; 10077c478bd9Sstevel@tonic-gate prefixlength = 1; 10087c478bd9Sstevel@tonic-gate } 10097c478bd9Sstevel@tonic-gate } else { /* not long long */ 10107c478bd9Sstevel@tonic-gate if (flagword & LENGTH) 10117c478bd9Sstevel@tonic-gate val = va_arg(args.ap, long); 10127c478bd9Sstevel@tonic-gate else 10137c478bd9Sstevel@tonic-gate val = va_arg(args.ap, int); 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate if (flagword & SHORT) 10167c478bd9Sstevel@tonic-gate val = (short)val; 10177c478bd9Sstevel@tonic-gate else if (flagword & CHAR) 10187c478bd9Sstevel@tonic-gate val = (char)val; 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate /* If signed conversion, make sign */ 10217c478bd9Sstevel@tonic-gate if (val < 0) { 10227c478bd9Sstevel@tonic-gate prefix = _P_HYPHEN; 10237c478bd9Sstevel@tonic-gate prefixlength = 1; 10247c478bd9Sstevel@tonic-gate /* 10257c478bd9Sstevel@tonic-gate * Negate, checking in advance 10267c478bd9Sstevel@tonic-gate * for possible overflow. 10277c478bd9Sstevel@tonic-gate */ 10287c478bd9Sstevel@tonic-gate if (val != HIBITL) 10297c478bd9Sstevel@tonic-gate val = -val; 10307c478bd9Sstevel@tonic-gate /* 10317c478bd9Sstevel@tonic-gate * number is -HIBITL; convert 10327c478bd9Sstevel@tonic-gate * last digit now and get 10337c478bd9Sstevel@tonic-gate * positive number 10347c478bd9Sstevel@tonic-gate */ 10357c478bd9Sstevel@tonic-gate else 10367c478bd9Sstevel@tonic-gate *--bp = _lowdigit(&val); 10377c478bd9Sstevel@tonic-gate } else if (flagword & FPLUS) { 10387c478bd9Sstevel@tonic-gate prefix = _P_PLUS; 10397c478bd9Sstevel@tonic-gate prefixlength = 1; 10407c478bd9Sstevel@tonic-gate } else if (flagword & FBLANK) { 10417c478bd9Sstevel@tonic-gate prefix = _P_BLANK; 10427c478bd9Sstevel@tonic-gate prefixlength = 1; 10437c478bd9Sstevel@tonic-gate } 10447c478bd9Sstevel@tonic-gate } 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate decimal: 10477c478bd9Sstevel@tonic-gate { 10487c478bd9Sstevel@tonic-gate long qval = val; 10497c478bd9Sstevel@tonic-gate long long lll = ll; 10507c478bd9Sstevel@tonic-gate long long tll; 10517c478bd9Sstevel@tonic-gate if (flagword & XLONG) { 10527c478bd9Sstevel@tonic-gate if (lll < 10LL) { 10537c478bd9Sstevel@tonic-gate #ifdef _WIDE 10547c478bd9Sstevel@tonic-gate if (lll != 0LL || !(flagword & DOTSEEN)) 10557c478bd9Sstevel@tonic-gate *--bp = (wchar_t)lll + L'0'; 10567c478bd9Sstevel@tonic-gate #else /* _WIDE */ 10577c478bd9Sstevel@tonic-gate if (lll != 0LL || !(flagword & DOTSEEN)) 10587c478bd9Sstevel@tonic-gate *--bp = (char)lll + '0'; 10597c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 10607c478bd9Sstevel@tonic-gate } else { 10617c478bd9Sstevel@tonic-gate do { 10627c478bd9Sstevel@tonic-gate tll = lll; 10637c478bd9Sstevel@tonic-gate lll /= 10; 10647c478bd9Sstevel@tonic-gate #ifdef _WIDE 10657c478bd9Sstevel@tonic-gate *--bp = (wchar_t) 10667c478bd9Sstevel@tonic-gate (tll - lll * 10 + '0'); 10677c478bd9Sstevel@tonic-gate #else /* _WIDE */ 10687c478bd9Sstevel@tonic-gate *--bp = (char) \ 10697c478bd9Sstevel@tonic-gate (tll - lll * 10 + '0'); 10707c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 10717c478bd9Sstevel@tonic-gate } while (lll >= 10); 10727c478bd9Sstevel@tonic-gate #ifdef _WIDE 10737c478bd9Sstevel@tonic-gate *--bp = (wchar_t)lll + '0'; 10747c478bd9Sstevel@tonic-gate #else /* _WIDE */ 10757c478bd9Sstevel@tonic-gate *--bp = (char)lll + '0'; 10767c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate } else { 10797c478bd9Sstevel@tonic-gate if (qval <= 9) { 10807c478bd9Sstevel@tonic-gate #ifdef _WIDE 10817c478bd9Sstevel@tonic-gate if (qval != 0 || !(flagword & DOTSEEN)) 10827c478bd9Sstevel@tonic-gate *--bp = (wchar_t)qval + '0'; 10837c478bd9Sstevel@tonic-gate #else /* _WIDE */ 10847c478bd9Sstevel@tonic-gate if (qval != 0 || !(flagword & DOTSEEN)) 10857c478bd9Sstevel@tonic-gate *--bp = (char)qval + '0'; 10867c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 10877c478bd9Sstevel@tonic-gate } else { 10887c478bd9Sstevel@tonic-gate do { 10897c478bd9Sstevel@tonic-gate n = qval; 10907c478bd9Sstevel@tonic-gate qval /= 10; 10917c478bd9Sstevel@tonic-gate #ifdef _WIDE 10927c478bd9Sstevel@tonic-gate *--bp = (wchar_t) \ 10937c478bd9Sstevel@tonic-gate (n - qval * 10 + '0'); 10947c478bd9Sstevel@tonic-gate #else /* _WIDE */ 10957c478bd9Sstevel@tonic-gate *--bp = (char) \ 10967c478bd9Sstevel@tonic-gate (n - qval * 10 + '0'); 10977c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 10987c478bd9Sstevel@tonic-gate } while (qval > 9); 10997c478bd9Sstevel@tonic-gate #ifdef _WIDE 11007c478bd9Sstevel@tonic-gate *--bp = (wchar_t)qval + '0'; 11017c478bd9Sstevel@tonic-gate #else /* _WIDE */ 11027c478bd9Sstevel@tonic-gate *--bp = (char)qval + '0'; 11037c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 11047c478bd9Sstevel@tonic-gate } 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate } 11077c478bd9Sstevel@tonic-gate /* Handle the ' flag */ 11087c478bd9Sstevel@tonic-gate if (quote) { 11097c478bd9Sstevel@tonic-gate p = insert_thousands_sep(bp, p); 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate /* Calculate minimum padding zero requirement */ 11137c478bd9Sstevel@tonic-gate if (flagword & DOTSEEN) { 11147c478bd9Sstevel@tonic-gate leadzeroes = prec - (p - bp); 11157c478bd9Sstevel@tonic-gate if (leadzeroes > 0) { 11167c478bd9Sstevel@tonic-gate otherlength = lzero = leadzeroes; 11177c478bd9Sstevel@tonic-gate flagword |= LZERO; 11187c478bd9Sstevel@tonic-gate } 11197c478bd9Sstevel@tonic-gate } 11207c478bd9Sstevel@tonic-gate break; 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate case 'u': 11237c478bd9Sstevel@tonic-gate if ((flagword & PADZERO) && (flagword & DOTSEEN)) 11247c478bd9Sstevel@tonic-gate flagword &= ~PADZERO; /* ignore 0 flag */ 11257c478bd9Sstevel@tonic-gate p = bp = buf + MAXLLDIGS; 11267c478bd9Sstevel@tonic-gate 11277c478bd9Sstevel@tonic-gate /* Fetch the argument to be printed */ 11287c478bd9Sstevel@tonic-gate if (flagword & XLONG) { 11297c478bd9Sstevel@tonic-gate ll = va_arg(args.ap, long long); 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate if (ll & HIBITLL) 11327c478bd9Sstevel@tonic-gate *--bp = _lowlldigit(&ll); 11337c478bd9Sstevel@tonic-gate } else { 11347c478bd9Sstevel@tonic-gate if (flagword & LENGTH) 11357c478bd9Sstevel@tonic-gate val = va_arg(args.ap, long); 11367c478bd9Sstevel@tonic-gate else 11377c478bd9Sstevel@tonic-gate val = va_arg(args.ap, unsigned); 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gate if (flagword & SHORT) 11407c478bd9Sstevel@tonic-gate val = (unsigned short)val; 11417c478bd9Sstevel@tonic-gate else if (flagword & CHAR) 11427c478bd9Sstevel@tonic-gate val = (unsigned char)val; 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate if (val & HIBITL) 11457c478bd9Sstevel@tonic-gate *--bp = _lowdigit(&val); 11467c478bd9Sstevel@tonic-gate } 11477c478bd9Sstevel@tonic-gate 11487c478bd9Sstevel@tonic-gate goto decimal; 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate /* 11517c478bd9Sstevel@tonic-gate * non-decimal fixed point representations 11527c478bd9Sstevel@tonic-gate * for radix equal to a power of two 11537c478bd9Sstevel@tonic-gate * 11547c478bd9Sstevel@tonic-gate * "mradix" is one less than the radix for the conversion. 11557c478bd9Sstevel@tonic-gate * "lradix" is one less than the base 2 log 11567c478bd9Sstevel@tonic-gate * of the radix for the conversion. Conversion is unsigned. 11577c478bd9Sstevel@tonic-gate * HIBITL is 100...000 11587c478bd9Sstevel@tonic-gate * binary, and is equal to the maximum 11597c478bd9Sstevel@tonic-gate * negative number. 11607c478bd9Sstevel@tonic-gate * We assume a 2's complement machine 11617c478bd9Sstevel@tonic-gate */ 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate case 'o': 11647c478bd9Sstevel@tonic-gate mradix = 7; 11657c478bd9Sstevel@tonic-gate lradix = 2; 11667c478bd9Sstevel@tonic-gate /* 11677c478bd9Sstevel@tonic-gate * DR151 and clarification in C90 11687c478bd9Sstevel@tonic-gate * presence of '#' increases precision to first 11697c478bd9Sstevel@tonic-gate * digit of the result to be zero 11707c478bd9Sstevel@tonic-gate */ 11717c478bd9Sstevel@tonic-gate if ((flagword & DOTSEEN) && (flagword & FSHARP) && 11727c478bd9Sstevel@tonic-gate prec == 0) 11737c478bd9Sstevel@tonic-gate prec = 1; 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate goto fixed; 11767c478bd9Sstevel@tonic-gate 11777c478bd9Sstevel@tonic-gate case 'p': 11787c478bd9Sstevel@tonic-gate flagword &= ~(XLONG | SHORT); 11797c478bd9Sstevel@tonic-gate flagword |= LENGTH; 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate /* FALLTHRU */ 11827c478bd9Sstevel@tonic-gate case 'X': 11837c478bd9Sstevel@tonic-gate case 'x': 11847c478bd9Sstevel@tonic-gate mradix = 15; 11857c478bd9Sstevel@tonic-gate lradix = 3; 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate fixed: 11887c478bd9Sstevel@tonic-gate if ((flagword & PADZERO) && (flagword & DOTSEEN)) 11897c478bd9Sstevel@tonic-gate flagword &= ~PADZERO; /* ignore 0 flag */ 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate #ifdef _WIDE 11927c478bd9Sstevel@tonic-gate /* Set translate table for digits */ 11937c478bd9Sstevel@tonic-gate tab = (wchar_t *)((fcode == 'X') ? uc_digs : lc_digs); 11947c478bd9Sstevel@tonic-gate #else /* _WIDE */ 11957c478bd9Sstevel@tonic-gate /* Set translate table for digits */ 11967c478bd9Sstevel@tonic-gate tab = (fcode == 'X') ? uc_digs : lc_digs; 11977c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate /* Fetch the argument to be printed */ 12007c478bd9Sstevel@tonic-gate if (flagword & XLONG) { 12017c478bd9Sstevel@tonic-gate ll = va_arg(args.ap, long long); 12027c478bd9Sstevel@tonic-gate } else { 12037c478bd9Sstevel@tonic-gate if (flagword & LENGTH) 12047c478bd9Sstevel@tonic-gate val = va_arg(args.ap, long); 12057c478bd9Sstevel@tonic-gate else 12067c478bd9Sstevel@tonic-gate val = va_arg(args.ap, unsigned); 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate if (flagword & SHORT) 12097c478bd9Sstevel@tonic-gate val = (unsigned short) val; 12107c478bd9Sstevel@tonic-gate else if (flagword & CHAR) 12117c478bd9Sstevel@tonic-gate val = (unsigned char) val; 12127c478bd9Sstevel@tonic-gate } 12137c478bd9Sstevel@tonic-gate p = bp = buf + MAXLLDIGS; 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate /* Develop the digits of the value */ 12167c478bd9Sstevel@tonic-gate if (flagword & XLONG) { 12177c478bd9Sstevel@tonic-gate long long lll = ll; 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate if (lll == 0LL) { 12207c478bd9Sstevel@tonic-gate if (!(flagword & DOTSEEN)) { 12217c478bd9Sstevel@tonic-gate otherlength = lzero = 1; 12227c478bd9Sstevel@tonic-gate flagword |= LZERO; 12237c478bd9Sstevel@tonic-gate } 12247c478bd9Sstevel@tonic-gate } else do { 12257c478bd9Sstevel@tonic-gate *--bp = tab[(ssize_t)(lll & mradix)]; 12267c478bd9Sstevel@tonic-gate lll = ((lll >> 1) & ~HIBITLL) \ 12277c478bd9Sstevel@tonic-gate >> lradix; 12287c478bd9Sstevel@tonic-gate } while (lll != 0LL); 12297c478bd9Sstevel@tonic-gate } else { 12307c478bd9Sstevel@tonic-gate long qval = val; 12317c478bd9Sstevel@tonic-gate 12327c478bd9Sstevel@tonic-gate if (qval == 0) { 12337c478bd9Sstevel@tonic-gate if (!(flagword & DOTSEEN)) { 12347c478bd9Sstevel@tonic-gate otherlength = lzero = 1; 12357c478bd9Sstevel@tonic-gate flagword |= LZERO; 12367c478bd9Sstevel@tonic-gate } 12377c478bd9Sstevel@tonic-gate } else do { 12387c478bd9Sstevel@tonic-gate *--bp = tab[qval & mradix]; 12397c478bd9Sstevel@tonic-gate qval = ((qval >> 1) & ~HIBITL) \ 12407c478bd9Sstevel@tonic-gate >> lradix; 12417c478bd9Sstevel@tonic-gate } while (qval != 0); 12427c478bd9Sstevel@tonic-gate } 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate /* Calculate minimum padding zero requirement */ 12457c478bd9Sstevel@tonic-gate if (flagword & DOTSEEN) { 12467c478bd9Sstevel@tonic-gate leadzeroes = prec - (p - bp); 12477c478bd9Sstevel@tonic-gate if (leadzeroes > 0) { 12487c478bd9Sstevel@tonic-gate otherlength = lzero = leadzeroes; 12497c478bd9Sstevel@tonic-gate flagword |= LZERO; 12507c478bd9Sstevel@tonic-gate } 12517c478bd9Sstevel@tonic-gate } 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate /* Handle the # flag, (val != 0) for int and long */ 12547c478bd9Sstevel@tonic-gate /* (ll!= 0) handles long long case */ 12557c478bd9Sstevel@tonic-gate if ((flagword & FSHARP) && 12567c478bd9Sstevel@tonic-gate (((flagword & XLONG) == 0 && val != 0) || 12577c478bd9Sstevel@tonic-gate ((flagword & XLONG) == XLONG && ll != 0))) 12587c478bd9Sstevel@tonic-gate switch (fcode) { 12597c478bd9Sstevel@tonic-gate case 'o': 12607c478bd9Sstevel@tonic-gate if (!(flagword & LZERO)) { 12617c478bd9Sstevel@tonic-gate otherlength = lzero = 1; 12627c478bd9Sstevel@tonic-gate flagword |= LZERO; 12637c478bd9Sstevel@tonic-gate } 12647c478bd9Sstevel@tonic-gate break; 12657c478bd9Sstevel@tonic-gate case 'x': 12667c478bd9Sstevel@tonic-gate prefix = _P_ZEROx; 12677c478bd9Sstevel@tonic-gate prefixlength = 2; 12687c478bd9Sstevel@tonic-gate break; 12697c478bd9Sstevel@tonic-gate case 'X': 12707c478bd9Sstevel@tonic-gate prefix = _P_ZEROX; 12717c478bd9Sstevel@tonic-gate prefixlength = 2; 12727c478bd9Sstevel@tonic-gate break; 12737c478bd9Sstevel@tonic-gate } 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate break; 12767c478bd9Sstevel@tonic-gate 12777c478bd9Sstevel@tonic-gate case 'A': 12787c478bd9Sstevel@tonic-gate case 'a': 12797c478bd9Sstevel@tonic-gate /* A format */ 12807c478bd9Sstevel@tonic-gate if (flagword & QUAD) { 12817c478bd9Sstevel@tonic-gate long double qval = GETQVAL(args.ap); 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate /* establish default precision */ 12847c478bd9Sstevel@tonic-gate if (!(flagword & DOTSEEN)) 12857c478bd9Sstevel@tonic-gate #if defined(__sparc) 12867c478bd9Sstevel@tonic-gate prec = HEXFP_QUAD_DIG - 1; 12877c478bd9Sstevel@tonic-gate #elif defined(__i386) || defined(__amd64) 12887c478bd9Sstevel@tonic-gate prec = HEXFP_EXTENDED_DIG - 1; 12897c478bd9Sstevel@tonic-gate #else 12907c478bd9Sstevel@tonic-gate #error Unknown architecture 12917c478bd9Sstevel@tonic-gate #endif 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate FPCONV(__qaconvert, &qval, 12947c478bd9Sstevel@tonic-gate min(prec + 1, MAXECVT), &exp, &sign, 12957c478bd9Sstevel@tonic-gate cvtbuf); 12967c478bd9Sstevel@tonic-gate } else { 12977c478bd9Sstevel@tonic-gate double dval = va_arg(args.ap, double); 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate /* establish default precision */ 13007c478bd9Sstevel@tonic-gate if (!(flagword & DOTSEEN)) 13017c478bd9Sstevel@tonic-gate prec = HEXFP_DOUBLE_DIG - 1; 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate FPCONV(__aconvert, dval, 13047c478bd9Sstevel@tonic-gate min(prec + 1, MAXECVT), &exp, &sign, 13057c478bd9Sstevel@tonic-gate cvtbuf); 13067c478bd9Sstevel@tonic-gate } 13077c478bd9Sstevel@tonic-gate bp = cvtbuf; 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate /* 13107c478bd9Sstevel@tonic-gate * The following is wide-character safe because 13117c478bd9Sstevel@tonic-gate * __aconvert and __qaconvert only produce ASCII 13127c478bd9Sstevel@tonic-gate * characters. 13137c478bd9Sstevel@tonic-gate */ 13147c478bd9Sstevel@tonic-gate if (!isxdigit((unsigned char)*bp)) { 13157c478bd9Sstevel@tonic-gate inf_nan = 1; 13167c478bd9Sstevel@tonic-gate break; 13177c478bd9Sstevel@tonic-gate } 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate /* 13207c478bd9Sstevel@tonic-gate * Create the prefix. We ought to use the strings 13217c478bd9Sstevel@tonic-gate * defined above (_P_HYPHEN, etc.), but that would 13227c478bd9Sstevel@tonic-gate * be awkward: we'd either have to define six more 13237c478bd9Sstevel@tonic-gate * of them or we'd have to use strcpy/strcat to 13247c478bd9Sstevel@tonic-gate * assemble the ones already defined. So instead, 13257c478bd9Sstevel@tonic-gate * we just build the prefix character by character. 13267c478bd9Sstevel@tonic-gate */ 13277c478bd9Sstevel@tonic-gate p = prefix = prefixbuf; 13287c478bd9Sstevel@tonic-gate if (sign) { 13297c478bd9Sstevel@tonic-gate *p++ = '-'; 13307c478bd9Sstevel@tonic-gate prefixlength = 1; 13317c478bd9Sstevel@tonic-gate } else if (flagword & FPLUS) { 13327c478bd9Sstevel@tonic-gate *p++ = '+'; 13337c478bd9Sstevel@tonic-gate prefixlength = 1; 13347c478bd9Sstevel@tonic-gate } else if (flagword & FBLANK) { 13357c478bd9Sstevel@tonic-gate *p++ = ' '; 13367c478bd9Sstevel@tonic-gate prefixlength = 1; 13377c478bd9Sstevel@tonic-gate } 13387c478bd9Sstevel@tonic-gate *p++ = '0'; 13397c478bd9Sstevel@tonic-gate *p++ = (fcode == 'A') ? 'X' : 'x'; 13407c478bd9Sstevel@tonic-gate *p = '\0'; 13417c478bd9Sstevel@tonic-gate prefixlength += 2; 13427c478bd9Sstevel@tonic-gate 13437c478bd9Sstevel@tonic-gate /* put the first digit in the buffer */ 13447c478bd9Sstevel@tonic-gate p = &buf[0]; 13457c478bd9Sstevel@tonic-gate *p++ = (*bp != '\0') ? *bp++ : '0'; 13467c478bd9Sstevel@tonic-gate 13477c478bd9Sstevel@tonic-gate /* put in a decimal point if needed */ 13487c478bd9Sstevel@tonic-gate if (prec != 0 || (flagword & FSHARP)) 1349*762f6727SJason King *p++ = decimal_point; 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate /* create the rest of the mantissa */ 13527c478bd9Sstevel@tonic-gate rz = prec; 13537c478bd9Sstevel@tonic-gate if (fcode == 'A') { 13547c478bd9Sstevel@tonic-gate for (; rz > 0 && *bp != '\0'; --rz) { 13557c478bd9Sstevel@tonic-gate *p++ = ('a' <= *bp && *bp <= 'f')? 13567c478bd9Sstevel@tonic-gate *bp - 32 : *bp; 13577c478bd9Sstevel@tonic-gate bp++; 13587c478bd9Sstevel@tonic-gate } 13597c478bd9Sstevel@tonic-gate } else { 13607c478bd9Sstevel@tonic-gate for (; rz > 0 && *bp != '\0'; --rz) 13617c478bd9Sstevel@tonic-gate *p++ = *bp++; 13627c478bd9Sstevel@tonic-gate } 13637c478bd9Sstevel@tonic-gate if (rz > 0) { 13647c478bd9Sstevel@tonic-gate otherlength = rzero = rz; 13657c478bd9Sstevel@tonic-gate flagword |= RZERO; 13667c478bd9Sstevel@tonic-gate } 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate bp = &buf[0]; 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate /* 13717c478bd9Sstevel@tonic-gate * Create the exponent in right-to-left order. 13727c478bd9Sstevel@tonic-gate * buf[0] == '0' if and only if the value being 13737c478bd9Sstevel@tonic-gate * converted is exactly zero, in which case the 13747c478bd9Sstevel@tonic-gate * exponent should be +0 regardless of exp. 13757c478bd9Sstevel@tonic-gate */ 13767c478bd9Sstevel@tonic-gate suffix = &expbuf[MAXESIZ]; 13777c478bd9Sstevel@tonic-gate *suffix = '\0'; 13787c478bd9Sstevel@tonic-gate if (buf[0] != '0') { 13797c478bd9Sstevel@tonic-gate int nn; 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate nn = exp; 13827c478bd9Sstevel@tonic-gate if (nn < 0) 13837c478bd9Sstevel@tonic-gate nn = -nn; 13847c478bd9Sstevel@tonic-gate for (; nn > 9; nn /= 10) 13857c478bd9Sstevel@tonic-gate *--suffix = todigit(nn % 10); 13867c478bd9Sstevel@tonic-gate *--suffix = todigit(nn); 13877c478bd9Sstevel@tonic-gate *--suffix = (exp >= 0) ? '+' : '-'; 13887c478bd9Sstevel@tonic-gate } else { 13897c478bd9Sstevel@tonic-gate *--suffix = '0'; 13907c478bd9Sstevel@tonic-gate *--suffix = '+'; 13917c478bd9Sstevel@tonic-gate } 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate /* put in the p */ 13947c478bd9Sstevel@tonic-gate *--suffix = (fcode == 'A') ? 'P' : 'p'; 13957c478bd9Sstevel@tonic-gate 13967c478bd9Sstevel@tonic-gate /* compute size of suffix */ 13977c478bd9Sstevel@tonic-gate suffixlength = &expbuf[MAXESIZ] - suffix; 13987c478bd9Sstevel@tonic-gate otherlength += suffixlength; 13997c478bd9Sstevel@tonic-gate flagword |= SUFFIX; 14007c478bd9Sstevel@tonic-gate break; 14017c478bd9Sstevel@tonic-gate 14027c478bd9Sstevel@tonic-gate case 'E': 14037c478bd9Sstevel@tonic-gate case 'e': 14047c478bd9Sstevel@tonic-gate /* 14057c478bd9Sstevel@tonic-gate * E-format. The general strategy 14067c478bd9Sstevel@tonic-gate * here is fairly easy: we take what 14077c478bd9Sstevel@tonic-gate * econvert gives us and re-format it. 14087c478bd9Sstevel@tonic-gate * (qeconvert for long double) 14097c478bd9Sstevel@tonic-gate */ 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate /* Establish default precision */ 14127c478bd9Sstevel@tonic-gate if (!(flagword & DOTSEEN)) 14137c478bd9Sstevel@tonic-gate prec = 6; 14147c478bd9Sstevel@tonic-gate 14157c478bd9Sstevel@tonic-gate if (flagword & QUAD) { /* long double */ 14167c478bd9Sstevel@tonic-gate long double qval = GETQVAL(args.ap); 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate FPCONV(qeconvert, &qval, 14197c478bd9Sstevel@tonic-gate min(prec + 1, MAXECVT), &decpt, &sign, 14207c478bd9Sstevel@tonic-gate cvtbuf); 14217c478bd9Sstevel@tonic-gate } else { /* double */ 14227c478bd9Sstevel@tonic-gate double dval = va_arg(args.ap, double); 14237c478bd9Sstevel@tonic-gate 14247c478bd9Sstevel@tonic-gate FPCONV(econvert, dval, 14257c478bd9Sstevel@tonic-gate min(prec + 1, MAXECVT), &decpt, &sign, 14267c478bd9Sstevel@tonic-gate cvtbuf); 14277c478bd9Sstevel@tonic-gate } 14287c478bd9Sstevel@tonic-gate bp = cvtbuf; 14297c478bd9Sstevel@tonic-gate if (*bp > '9') { 14307c478bd9Sstevel@tonic-gate inf_nan = 1; 14317c478bd9Sstevel@tonic-gate inf_nan_mixed_case = (__xpg6 & 14327c478bd9Sstevel@tonic-gate _C99SUSv3_mixed_case_Inf_and_NaN); 14337c478bd9Sstevel@tonic-gate break; 14347c478bd9Sstevel@tonic-gate } 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate /* Determine the prefix */ 14377c478bd9Sstevel@tonic-gate e_merge: 14387c478bd9Sstevel@tonic-gate if (sign) { 14397c478bd9Sstevel@tonic-gate prefix = _P_HYPHEN; 14407c478bd9Sstevel@tonic-gate prefixlength = 1; 14417c478bd9Sstevel@tonic-gate } else if (flagword & FPLUS) { 14427c478bd9Sstevel@tonic-gate prefix = _P_PLUS; 14437c478bd9Sstevel@tonic-gate prefixlength = 1; 14447c478bd9Sstevel@tonic-gate } else if (flagword & FBLANK) { 14457c478bd9Sstevel@tonic-gate prefix = _P_BLANK; 14467c478bd9Sstevel@tonic-gate prefixlength = 1; 14477c478bd9Sstevel@tonic-gate } 14487c478bd9Sstevel@tonic-gate 14497c478bd9Sstevel@tonic-gate /* Place the first digit in the buffer */ 14507c478bd9Sstevel@tonic-gate p = &buf[0]; 14517c478bd9Sstevel@tonic-gate *p++ = (*bp != '\0') ? *bp++ : '0'; 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate /* Put in a decimal point if needed */ 14547c478bd9Sstevel@tonic-gate if (prec != 0 || (flagword & FSHARP)) 1455*762f6727SJason King *p++ = decimal_point; 14567c478bd9Sstevel@tonic-gate 14577c478bd9Sstevel@tonic-gate /* Create the rest of the mantissa */ 14587c478bd9Sstevel@tonic-gate rz = prec; 14597c478bd9Sstevel@tonic-gate for (; rz > 0 && *bp != '\0'; --rz) 14607c478bd9Sstevel@tonic-gate *p++ = *bp++; 14617c478bd9Sstevel@tonic-gate if (rz > 0) { 14627c478bd9Sstevel@tonic-gate otherlength = rzero = rz; 14637c478bd9Sstevel@tonic-gate flagword |= RZERO; 14647c478bd9Sstevel@tonic-gate } 14657c478bd9Sstevel@tonic-gate 14667c478bd9Sstevel@tonic-gate bp = &buf[0]; 14677c478bd9Sstevel@tonic-gate 14687c478bd9Sstevel@tonic-gate /* 14697c478bd9Sstevel@tonic-gate * Create the exponent. buf[0] == '0' if and 14707c478bd9Sstevel@tonic-gate * only if the value being converted is exactly 14717c478bd9Sstevel@tonic-gate * zero, in which case the exponent should be 14727c478bd9Sstevel@tonic-gate * +0 regardless of decpt. 14737c478bd9Sstevel@tonic-gate */ 14747c478bd9Sstevel@tonic-gate *(suffix = &expbuf[MAXESIZ]) = '\0'; 14757c478bd9Sstevel@tonic-gate if (buf[0] != '0') { 14767c478bd9Sstevel@tonic-gate int nn = decpt - 1; 14777c478bd9Sstevel@tonic-gate if (nn < 0) 14787c478bd9Sstevel@tonic-gate nn = -nn; 14797c478bd9Sstevel@tonic-gate for (; nn > 9; nn /= 10) 14807c478bd9Sstevel@tonic-gate *--suffix = todigit(nn % 10); 14817c478bd9Sstevel@tonic-gate *--suffix = todigit(nn); 14827c478bd9Sstevel@tonic-gate } 14837c478bd9Sstevel@tonic-gate 14847c478bd9Sstevel@tonic-gate /* Prepend leading zeroes to the exponent */ 14857c478bd9Sstevel@tonic-gate while (suffix > &expbuf[MAXESIZ - 2]) 14867c478bd9Sstevel@tonic-gate *--suffix = '0'; 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate /* Put in the exponent sign */ 14897c478bd9Sstevel@tonic-gate *--suffix = (decpt > 0 || buf[0] == '0') ? '+' : '-'; 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate /* Put in the e */ 14927c478bd9Sstevel@tonic-gate *--suffix = _M_ISUPPER(fcode) ? 'E' : 'e'; 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate /* compute size of suffix */ 14957c478bd9Sstevel@tonic-gate otherlength += (suffixlength = &expbuf[MAXESIZ] \ 14967c478bd9Sstevel@tonic-gate - suffix); 14977c478bd9Sstevel@tonic-gate flagword |= SUFFIX; 14987c478bd9Sstevel@tonic-gate break; 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate case 'F': 15017c478bd9Sstevel@tonic-gate case 'f': 15027c478bd9Sstevel@tonic-gate /* 15037c478bd9Sstevel@tonic-gate * F-format floating point. This is a 15047c478bd9Sstevel@tonic-gate * good deal less simple than E-format. 15057c478bd9Sstevel@tonic-gate * The overall strategy will be to call 15067c478bd9Sstevel@tonic-gate * fconvert, reformat its result into buf, 15077c478bd9Sstevel@tonic-gate * and calculate how many trailing 15087c478bd9Sstevel@tonic-gate * zeroes will be required. There will 15097c478bd9Sstevel@tonic-gate * never be any leading zeroes needed. 15107c478bd9Sstevel@tonic-gate * (qfconvert for long double) 15117c478bd9Sstevel@tonic-gate */ 15127c478bd9Sstevel@tonic-gate 15137c478bd9Sstevel@tonic-gate /* Establish default precision */ 15147c478bd9Sstevel@tonic-gate if (!(flagword & DOTSEEN)) 15157c478bd9Sstevel@tonic-gate prec = 6; 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate if (flagword & QUAD) { /* long double */ 15187c478bd9Sstevel@tonic-gate long double qval = GETQVAL(args.ap); 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate FPCONV(qfconvert, &qval, min(prec, MAXFCVT), 15217c478bd9Sstevel@tonic-gate &decpt, &sign, cvtbuf); 15227c478bd9Sstevel@tonic-gate bp = cvtbuf; 15237c478bd9Sstevel@tonic-gate if (*bp == 0) { 15247c478bd9Sstevel@tonic-gate /* 15257c478bd9Sstevel@tonic-gate * qfconvert would have required 15267c478bd9Sstevel@tonic-gate * too many characters; use qeconvert 15277c478bd9Sstevel@tonic-gate * instead 15287c478bd9Sstevel@tonic-gate */ 15297c478bd9Sstevel@tonic-gate FPCONV(qeconvert, &qval, 15307c478bd9Sstevel@tonic-gate min(prec + 1, MAXECVT), &decpt, 15317c478bd9Sstevel@tonic-gate &sign, cvtbuf); 15327c478bd9Sstevel@tonic-gate goto e_merge; 15337c478bd9Sstevel@tonic-gate } 15347c478bd9Sstevel@tonic-gate } else { /* double */ 15357c478bd9Sstevel@tonic-gate double dval = va_arg(args.ap, double); 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate FPCONV(fconvert, dval, min(prec, MAXFCVT), 15387c478bd9Sstevel@tonic-gate &decpt, &sign, cvtbuf); 15397c478bd9Sstevel@tonic-gate } 15407c478bd9Sstevel@tonic-gate bp = cvtbuf; 15417c478bd9Sstevel@tonic-gate if (*bp > '9') { 15427c478bd9Sstevel@tonic-gate inf_nan = 1; 15437c478bd9Sstevel@tonic-gate if (fcode == 'f') 15447c478bd9Sstevel@tonic-gate inf_nan_mixed_case = (__xpg6 & 15457c478bd9Sstevel@tonic-gate _C99SUSv3_mixed_case_Inf_and_NaN); 15467c478bd9Sstevel@tonic-gate break; 15477c478bd9Sstevel@tonic-gate } 15487c478bd9Sstevel@tonic-gate 15497c478bd9Sstevel@tonic-gate /* Determine the prefix */ 15507c478bd9Sstevel@tonic-gate f_merge: 15517c478bd9Sstevel@tonic-gate if (sign) { 15527c478bd9Sstevel@tonic-gate prefix = _P_HYPHEN; 15537c478bd9Sstevel@tonic-gate prefixlength = 1; 15547c478bd9Sstevel@tonic-gate } else if (flagword & FPLUS) { 15557c478bd9Sstevel@tonic-gate prefix = _P_PLUS; 15567c478bd9Sstevel@tonic-gate prefixlength = 1; 15577c478bd9Sstevel@tonic-gate } else if (flagword & FBLANK) { 15587c478bd9Sstevel@tonic-gate prefix = _P_BLANK; 15597c478bd9Sstevel@tonic-gate prefixlength = 1; 15607c478bd9Sstevel@tonic-gate } 15617c478bd9Sstevel@tonic-gate 15627c478bd9Sstevel@tonic-gate /* Initialize buffer pointer */ 15637c478bd9Sstevel@tonic-gate p = &buf[0]; 15647c478bd9Sstevel@tonic-gate 15657c478bd9Sstevel@tonic-gate { 15667c478bd9Sstevel@tonic-gate ssize_t nn = decpt; 15677c478bd9Sstevel@tonic-gate 15687c478bd9Sstevel@tonic-gate /* Emit the digits before the decimal point */ 15697c478bd9Sstevel@tonic-gate k = 0; 15707c478bd9Sstevel@tonic-gate do { 15717c478bd9Sstevel@tonic-gate *p++ = (nn <= 0 || *bp == '\0' || \ 15727c478bd9Sstevel@tonic-gate k >= MAXFSIG) ? '0' : (k++, *bp++); 15737c478bd9Sstevel@tonic-gate } while (--nn > 0); 15747c478bd9Sstevel@tonic-gate 15757c478bd9Sstevel@tonic-gate if (quote) 15767c478bd9Sstevel@tonic-gate p = insert_thousands_sep(buf, p); 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate /* Decide whether we need a decimal point */ 15797c478bd9Sstevel@tonic-gate if ((flagword & FSHARP) || prec > 0) 1580*762f6727SJason King *p++ = decimal_point; 15817c478bd9Sstevel@tonic-gate 15827c478bd9Sstevel@tonic-gate /* Digits (if any) after the decimal point */ 15837c478bd9Sstevel@tonic-gate nn = min(prec, MAXFCVT); 15847c478bd9Sstevel@tonic-gate if (prec > nn) { 15857c478bd9Sstevel@tonic-gate flagword |= RZERO; 15867c478bd9Sstevel@tonic-gate otherlength = rzero = prec - nn; 15877c478bd9Sstevel@tonic-gate } 15887c478bd9Sstevel@tonic-gate while (--nn >= 0) 15897c478bd9Sstevel@tonic-gate *p++ = (++decpt <= 0 || *bp == '\0' || \ 15907c478bd9Sstevel@tonic-gate k >= MAXFSIG) ? '0' : (k++, *bp++); 15917c478bd9Sstevel@tonic-gate } 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate bp = &buf[0]; 15947c478bd9Sstevel@tonic-gate 15957c478bd9Sstevel@tonic-gate break; 15967c478bd9Sstevel@tonic-gate 15977c478bd9Sstevel@tonic-gate case 'G': 15987c478bd9Sstevel@tonic-gate case 'g': 15997c478bd9Sstevel@tonic-gate /* 16007c478bd9Sstevel@tonic-gate * g-format. We play around a bit 16017c478bd9Sstevel@tonic-gate * and then jump into e or f, as needed. 16027c478bd9Sstevel@tonic-gate */ 16037c478bd9Sstevel@tonic-gate 16047c478bd9Sstevel@tonic-gate /* Establish default precision */ 16057c478bd9Sstevel@tonic-gate if (!(flagword & DOTSEEN)) 16067c478bd9Sstevel@tonic-gate prec = 6; 16077c478bd9Sstevel@tonic-gate else if (prec == 0) 16087c478bd9Sstevel@tonic-gate prec = 1; 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate if (flagword & QUAD) { /* long double */ 16117c478bd9Sstevel@tonic-gate long double qval = GETQVAL(args.ap); 16127c478bd9Sstevel@tonic-gate 16137c478bd9Sstevel@tonic-gate FPCONV(qeconvert, &qval, min(prec, MAXECVT), 16147c478bd9Sstevel@tonic-gate &decpt, &sign, cvtbuf); 16157c478bd9Sstevel@tonic-gate } else { /* double */ 16167c478bd9Sstevel@tonic-gate double dval = va_arg(args.ap, double); 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate FPCONV(econvert, dval, min(prec, MAXECVT), 16197c478bd9Sstevel@tonic-gate &decpt, &sign, cvtbuf); 16207c478bd9Sstevel@tonic-gate } 16217c478bd9Sstevel@tonic-gate bp = cvtbuf; 16227c478bd9Sstevel@tonic-gate if (*bp > '9') { 16237c478bd9Sstevel@tonic-gate inf_nan = 1; 16247c478bd9Sstevel@tonic-gate inf_nan_mixed_case = (__xpg6 & 16257c478bd9Sstevel@tonic-gate _C99SUSv3_mixed_case_Inf_and_NaN); 16267c478bd9Sstevel@tonic-gate break; 16277c478bd9Sstevel@tonic-gate } 16287c478bd9Sstevel@tonic-gate if (*bp == '0') /* the value converted is zero */ 16297c478bd9Sstevel@tonic-gate decpt = 1; 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate { 16327c478bd9Sstevel@tonic-gate int kk = prec; 16337c478bd9Sstevel@tonic-gate if (!(flagword & FSHARP)) { 16347c478bd9Sstevel@tonic-gate #ifdef _WIDE 16357c478bd9Sstevel@tonic-gate n = wcslen(bp); 16367c478bd9Sstevel@tonic-gate #else /* _WIDE */ 16377c478bd9Sstevel@tonic-gate n = strlen(bp); 16387c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 16397c478bd9Sstevel@tonic-gate if (n < kk) 16407c478bd9Sstevel@tonic-gate kk = (int)n; 16417c478bd9Sstevel@tonic-gate while (kk >= 1 && bp[kk-1] == '0') 16427c478bd9Sstevel@tonic-gate --kk; 16437c478bd9Sstevel@tonic-gate } 16447c478bd9Sstevel@tonic-gate if (decpt < -3 || decpt > prec) { 16457c478bd9Sstevel@tonic-gate prec = kk - 1; 16467c478bd9Sstevel@tonic-gate goto e_merge; 16477c478bd9Sstevel@tonic-gate } 16487c478bd9Sstevel@tonic-gate prec = kk - decpt; 16497c478bd9Sstevel@tonic-gate goto f_merge; 16507c478bd9Sstevel@tonic-gate } 16517c478bd9Sstevel@tonic-gate 16527c478bd9Sstevel@tonic-gate case '%': 16537c478bd9Sstevel@tonic-gate buf[0] = fcode; 16547c478bd9Sstevel@tonic-gate goto c_merge; 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate #ifndef _WIDE 16577c478bd9Sstevel@tonic-gate case 'w': 16587c478bd9Sstevel@tonic-gate wflag = 1; 16597c478bd9Sstevel@tonic-gate goto charswitch; 16607c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 16617c478bd9Sstevel@tonic-gate 16627c478bd9Sstevel@tonic-gate 16637c478bd9Sstevel@tonic-gate case 'C': /* XPG XSH4 extention */ 16647c478bd9Sstevel@tonic-gate wide_C: 16657c478bd9Sstevel@tonic-gate { 16667c478bd9Sstevel@tonic-gate wchar_t temp; 16677c478bd9Sstevel@tonic-gate 16687c478bd9Sstevel@tonic-gate temp = va_arg(args.ap, wchar_t); 16697c478bd9Sstevel@tonic-gate #ifdef _WIDE 16707c478bd9Sstevel@tonic-gate if (temp) { 16717c478bd9Sstevel@tonic-gate buf[0] = temp; 16727c478bd9Sstevel@tonic-gate p = (bp = buf) + 1; 16737c478bd9Sstevel@tonic-gate } else { 16747c478bd9Sstevel@tonic-gate buf[0] = 0; 16757c478bd9Sstevel@tonic-gate p = (bp = buf) + 1; 16767c478bd9Sstevel@tonic-gate } 16777c478bd9Sstevel@tonic-gate wcount = 1; 16787c478bd9Sstevel@tonic-gate wflag = 1; 16797c478bd9Sstevel@tonic-gate #else /* _WIDE */ 16807c478bd9Sstevel@tonic-gate if (temp) { 16817c478bd9Sstevel@tonic-gate if ((retcode = wctomb(buf, temp)) 16827c478bd9Sstevel@tonic-gate == -1) { 16837c478bd9Sstevel@tonic-gate errno = EILSEQ; 16847c478bd9Sstevel@tonic-gate return (EOF); 16857c478bd9Sstevel@tonic-gate } else { 16867c478bd9Sstevel@tonic-gate p = (bp = buf) + retcode; 16877c478bd9Sstevel@tonic-gate } 16887c478bd9Sstevel@tonic-gate } else { /* NULL character */ 16897c478bd9Sstevel@tonic-gate buf[0] = 0; 16907c478bd9Sstevel@tonic-gate p = (bp = buf) + 1; 16917c478bd9Sstevel@tonic-gate } 16927c478bd9Sstevel@tonic-gate wcount = p - bp; 16937c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 16947c478bd9Sstevel@tonic-gate } 16957c478bd9Sstevel@tonic-gate break; 16967c478bd9Sstevel@tonic-gate case 'c': 16977c478bd9Sstevel@tonic-gate if (lflag) { 16987c478bd9Sstevel@tonic-gate goto wide_C; 16997c478bd9Sstevel@tonic-gate } 17007c478bd9Sstevel@tonic-gate #ifndef _WIDE 17017c478bd9Sstevel@tonic-gate if (wflag) { 17027c478bd9Sstevel@tonic-gate wchar_t temp; 17037c478bd9Sstevel@tonic-gate 17047c478bd9Sstevel@tonic-gate temp = va_arg(args.ap, wchar_t); 17057c478bd9Sstevel@tonic-gate if (temp) { 17067c478bd9Sstevel@tonic-gate if ((retcode = wctomb(buf, temp)) 17077c478bd9Sstevel@tonic-gate == -1) { 17087c478bd9Sstevel@tonic-gate p = (bp = buf) + 1; 17097c478bd9Sstevel@tonic-gate } else { 17107c478bd9Sstevel@tonic-gate p = (bp = buf) + retcode; 17117c478bd9Sstevel@tonic-gate } 17127c478bd9Sstevel@tonic-gate } else { /* NULL character */ 17137c478bd9Sstevel@tonic-gate buf[0] = 0; 17147c478bd9Sstevel@tonic-gate p = (bp = buf) + 1; 17157c478bd9Sstevel@tonic-gate } 17167c478bd9Sstevel@tonic-gate wcount = p - bp; 17177c478bd9Sstevel@tonic-gate } else { 17187c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 17197c478bd9Sstevel@tonic-gate if (flagword & XLONG) { 17207c478bd9Sstevel@tonic-gate long long temp; 17217c478bd9Sstevel@tonic-gate temp = va_arg(args.ap, long long); 17227c478bd9Sstevel@tonic-gate #ifdef _WIDE 17237c478bd9Sstevel@tonic-gate buf[0] = (wchar_t)temp; 17247c478bd9Sstevel@tonic-gate #else /* _WIDE */ 17257c478bd9Sstevel@tonic-gate buf[0] = (char)temp; 17267c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 17277c478bd9Sstevel@tonic-gate } else 17287c478bd9Sstevel@tonic-gate buf[0] = va_arg(args.ap, int); 17297c478bd9Sstevel@tonic-gate c_merge: 17307c478bd9Sstevel@tonic-gate p = (bp = &buf[0]) + 1; 17317c478bd9Sstevel@tonic-gate #ifdef _WIDE 17327c478bd9Sstevel@tonic-gate wcount = 1; 17337c478bd9Sstevel@tonic-gate wflag = 1; 17347c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 17357c478bd9Sstevel@tonic-gate #ifndef _WIDE 17367c478bd9Sstevel@tonic-gate } 17377c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 17387c478bd9Sstevel@tonic-gate break; 17397c478bd9Sstevel@tonic-gate 17407c478bd9Sstevel@tonic-gate case 'S': /* XPG XSH4 extention */ 17417c478bd9Sstevel@tonic-gate wide_S: 17427c478bd9Sstevel@tonic-gate #ifdef _WIDE 17437c478bd9Sstevel@tonic-gate if (!lflag) { 17447c478bd9Sstevel@tonic-gate lflag++; 17457c478bd9Sstevel@tonic-gate } 17467c478bd9Sstevel@tonic-gate bp = va_arg(args.ap, wchar_t *); 17479f773e28SDarren Moffat if (bp == NULL) 17489f773e28SDarren Moffat bp = (wchar_t *)widenullstr; 17497c478bd9Sstevel@tonic-gate if (!(flagword & DOTSEEN)) { 17507c478bd9Sstevel@tonic-gate /* wide character handling */ 17517c478bd9Sstevel@tonic-gate prec = MAXINT; 17527c478bd9Sstevel@tonic-gate } 17537c478bd9Sstevel@tonic-gate 17547c478bd9Sstevel@tonic-gate wp = bp; 17557c478bd9Sstevel@tonic-gate wcount = 0; 17567c478bd9Sstevel@tonic-gate while (*wp) { 17577c478bd9Sstevel@tonic-gate if ((prec - wcount - 1) >= 0) { 17587c478bd9Sstevel@tonic-gate wcount++; 17597c478bd9Sstevel@tonic-gate wp++; 17607c478bd9Sstevel@tonic-gate } else { 17617c478bd9Sstevel@tonic-gate break; 17627c478bd9Sstevel@tonic-gate } 17637c478bd9Sstevel@tonic-gate } 17647c478bd9Sstevel@tonic-gate p = wp; 17657c478bd9Sstevel@tonic-gate wflag = 1; 17667c478bd9Sstevel@tonic-gate break; 17677c478bd9Sstevel@tonic-gate #else /* _WIDE */ 17687c478bd9Sstevel@tonic-gate if (!wflag) 17697c478bd9Sstevel@tonic-gate wflag++; 17707c478bd9Sstevel@tonic-gate bp = va_arg(args.ap, char *); 17719f773e28SDarren Moffat if (bp == NULL) 17729f773e28SDarren Moffat bp = (char *)widenullstr; 17737c478bd9Sstevel@tonic-gate if (!(flagword & DOTSEEN)) { 17747c478bd9Sstevel@tonic-gate /* wide character handling */ 17757c478bd9Sstevel@tonic-gate prec = MAXINT; 17767c478bd9Sstevel@tonic-gate } 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate wp = (wchar_t *)(uintptr_t)bp; 17797c478bd9Sstevel@tonic-gate wcount = 0; 17807c478bd9Sstevel@tonic-gate while (*wp) { 17817c478bd9Sstevel@tonic-gate int nbytes; 17827c478bd9Sstevel@tonic-gate 17837c478bd9Sstevel@tonic-gate nbytes = wctomb(tmpbuf, *wp); 17847c478bd9Sstevel@tonic-gate if (nbytes < 0) { 17857c478bd9Sstevel@tonic-gate errno = EILSEQ; 17867c478bd9Sstevel@tonic-gate return (EOF); 17877c478bd9Sstevel@tonic-gate } 17887c478bd9Sstevel@tonic-gate if ((prec - (wcount + nbytes)) >= 0) { 17897c478bd9Sstevel@tonic-gate wcount += nbytes; 17907c478bd9Sstevel@tonic-gate wp++; 17917c478bd9Sstevel@tonic-gate } else { 17927c478bd9Sstevel@tonic-gate break; 17937c478bd9Sstevel@tonic-gate } 17947c478bd9Sstevel@tonic-gate } 17957c478bd9Sstevel@tonic-gate sec_display = wcount; 17967c478bd9Sstevel@tonic-gate p = (char *)wp; 17977c478bd9Sstevel@tonic-gate break; 17987c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 17997c478bd9Sstevel@tonic-gate case 's': 18007c478bd9Sstevel@tonic-gate if (lflag) { 18017c478bd9Sstevel@tonic-gate goto wide_S; 18027c478bd9Sstevel@tonic-gate } 18037c478bd9Sstevel@tonic-gate #ifdef _WIDE 18047c478bd9Sstevel@tonic-gate cbp = va_arg(args.ap, char *); 18059f773e28SDarren Moffat if (cbp == NULL) 18069f773e28SDarren Moffat cbp = (char *)nullstr; 18077c478bd9Sstevel@tonic-gate if (!(flagword & DOTSEEN)) { 18087c478bd9Sstevel@tonic-gate size_t nwc; 18097c478bd9Sstevel@tonic-gate wchar_t *wstr; 18107c478bd9Sstevel@tonic-gate 18117c478bd9Sstevel@tonic-gate nwc = mbstowcs(NULL, cbp, 0); 18127c478bd9Sstevel@tonic-gate if (nwc == (size_t)-1) { 18137c478bd9Sstevel@tonic-gate errno = EILSEQ; 18147c478bd9Sstevel@tonic-gate return (EOF); 18157c478bd9Sstevel@tonic-gate } 18167c478bd9Sstevel@tonic-gate bpsize = sizeof (wchar_t) * (nwc + 1); 18177c478bd9Sstevel@tonic-gate wstr = (wchar_t *)lmalloc(bpsize); 18187c478bd9Sstevel@tonic-gate if (wstr == NULL) { 18197c478bd9Sstevel@tonic-gate errno = EILSEQ; 18207c478bd9Sstevel@tonic-gate return (EOF); 18217c478bd9Sstevel@tonic-gate } 18227c478bd9Sstevel@tonic-gate nwc = mbstowcs(wstr, cbp, MAXINT); 18237c478bd9Sstevel@tonic-gate wcount = nwc; 18247c478bd9Sstevel@tonic-gate bp = wstr; 18257c478bd9Sstevel@tonic-gate p = wstr + nwc; 18267c478bd9Sstevel@tonic-gate } else { 18277c478bd9Sstevel@tonic-gate size_t nwc; 18287c478bd9Sstevel@tonic-gate wchar_t *wstr; 18297c478bd9Sstevel@tonic-gate 18307c478bd9Sstevel@tonic-gate nwc = mbstowcs(NULL, cbp, 0); 18317c478bd9Sstevel@tonic-gate if (nwc == (size_t)-1) { 18327c478bd9Sstevel@tonic-gate errno = EILSEQ; 18337c478bd9Sstevel@tonic-gate return (EOF); 18347c478bd9Sstevel@tonic-gate } 18357c478bd9Sstevel@tonic-gate if (prec > nwc) { 18367c478bd9Sstevel@tonic-gate bpsize = sizeof (wchar_t) * nwc; 18377c478bd9Sstevel@tonic-gate wstr = (wchar_t *)lmalloc(bpsize); 18387c478bd9Sstevel@tonic-gate if (wstr == NULL) { 18397c478bd9Sstevel@tonic-gate errno = ENOMEM; 18407c478bd9Sstevel@tonic-gate return (EOF); 18417c478bd9Sstevel@tonic-gate } 18427c478bd9Sstevel@tonic-gate nwc = mbstowcs(wstr, cbp, nwc); 18437c478bd9Sstevel@tonic-gate cp = cbp + strlen(cbp); 18447c478bd9Sstevel@tonic-gate wcount = nwc; 18457c478bd9Sstevel@tonic-gate bp = wstr; 18467c478bd9Sstevel@tonic-gate p = wstr + nwc; 18477c478bd9Sstevel@tonic-gate } else { 18487c478bd9Sstevel@tonic-gate size_t nnwc; 18497c478bd9Sstevel@tonic-gate int len; 18507c478bd9Sstevel@tonic-gate char *s; 18517c478bd9Sstevel@tonic-gate wchar_t *wstr; 18527c478bd9Sstevel@tonic-gate 18537c478bd9Sstevel@tonic-gate bpsize = sizeof (wchar_t) * prec; 18547c478bd9Sstevel@tonic-gate wstr = (wchar_t *)lmalloc(bpsize); 18557c478bd9Sstevel@tonic-gate if (wstr == NULL) { 18567c478bd9Sstevel@tonic-gate errno = ENOMEM; 18577c478bd9Sstevel@tonic-gate return (EOF); 18587c478bd9Sstevel@tonic-gate } 18597c478bd9Sstevel@tonic-gate nwc = mbstowcs(wstr, cbp, prec); 18607c478bd9Sstevel@tonic-gate wcount = prec; 18617c478bd9Sstevel@tonic-gate bp = wstr; 18627c478bd9Sstevel@tonic-gate p = wstr + nwc; 18637c478bd9Sstevel@tonic-gate } 18647c478bd9Sstevel@tonic-gate } 18657c478bd9Sstevel@tonic-gate wflag = 1; 18667c478bd9Sstevel@tonic-gate #else /* _WIDE */ 18677c478bd9Sstevel@tonic-gate bp = va_arg(args.ap, char *); 18689f773e28SDarren Moffat if (bp == NULL) 18699f773e28SDarren Moffat bp = (char *)nullstr; 18707c478bd9Sstevel@tonic-gate if (!(flagword & DOTSEEN)) { 18717c478bd9Sstevel@tonic-gate if (wflag) { 18727c478bd9Sstevel@tonic-gate /* wide character handling */ 18737c478bd9Sstevel@tonic-gate prec = MAXINT; 18747c478bd9Sstevel@tonic-gate goto wide_hand; 18757c478bd9Sstevel@tonic-gate } 18767c478bd9Sstevel@tonic-gate 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate p = bp + strlen(bp); 18797c478bd9Sstevel@tonic-gate 18807c478bd9Sstevel@tonic-gate /* 18817c478bd9Sstevel@tonic-gate * sec_display only needed if width 18827c478bd9Sstevel@tonic-gate * is specified (ie, "%<width>s") 18837c478bd9Sstevel@tonic-gate * Solaris behavior counts <width> in 18847c478bd9Sstevel@tonic-gate * screen column width. (If XPG4 behavior, 18857c478bd9Sstevel@tonic-gate * <width> is counted in bytes.) 18867c478bd9Sstevel@tonic-gate */ 18877c478bd9Sstevel@tonic-gate if (width > 0 && __xpg4 == 0 && 18887c478bd9Sstevel@tonic-gate MB_CUR_MAX > 1) { 18897c478bd9Sstevel@tonic-gate #define NW 256 18907c478bd9Sstevel@tonic-gate wchar_t wbuff[NW]; 18917c478bd9Sstevel@tonic-gate wchar_t *wp, *wptr; 18927c478bd9Sstevel@tonic-gate size_t wpsize; 18937c478bd9Sstevel@tonic-gate size_t nwc; 18947c478bd9Sstevel@tonic-gate 18957c478bd9Sstevel@tonic-gate wp = NULL; 18967c478bd9Sstevel@tonic-gate if ((nwc = mbstowcs(wbuff, bp, 18977c478bd9Sstevel@tonic-gate NW)) == (size_t)-1) { 18987c478bd9Sstevel@tonic-gate /* Estimate width */ 18997c478bd9Sstevel@tonic-gate sec_display = strlen(bp); 19007c478bd9Sstevel@tonic-gate goto mbs_err; 19017c478bd9Sstevel@tonic-gate } 19027c478bd9Sstevel@tonic-gate if (nwc < NW) { 19037c478bd9Sstevel@tonic-gate wptr = wbuff; 19047c478bd9Sstevel@tonic-gate } else { 19057c478bd9Sstevel@tonic-gate /* 19067c478bd9Sstevel@tonic-gate * If widechar does not fit into 19077c478bd9Sstevel@tonic-gate * wbuff, allocate larger buffer 19087c478bd9Sstevel@tonic-gate */ 19097c478bd9Sstevel@tonic-gate if ((nwc = 19107c478bd9Sstevel@tonic-gate mbstowcs(NULL, bp, NULL)) == 19117c478bd9Sstevel@tonic-gate (size_t)-1) { 19127c478bd9Sstevel@tonic-gate sec_display = 19137c478bd9Sstevel@tonic-gate strlen(bp); 19147c478bd9Sstevel@tonic-gate goto mbs_err; 19157c478bd9Sstevel@tonic-gate } 19167c478bd9Sstevel@tonic-gate wpsize = (nwc + 1) * 19177c478bd9Sstevel@tonic-gate sizeof (wchar_t); 19187c478bd9Sstevel@tonic-gate if ((wp = lmalloc(wpsize)) 19197c478bd9Sstevel@tonic-gate == NULL) { 19207c478bd9Sstevel@tonic-gate errno = ENOMEM; 19217c478bd9Sstevel@tonic-gate return (EOF); 19227c478bd9Sstevel@tonic-gate } 19237c478bd9Sstevel@tonic-gate if ((nwc = mbstowcs(wp, 19247c478bd9Sstevel@tonic-gate bp, nwc)) == (size_t)-1) { 19257c478bd9Sstevel@tonic-gate sec_display = \ 19267c478bd9Sstevel@tonic-gate strlen(bp); 19277c478bd9Sstevel@tonic-gate goto mbs_err; 19287c478bd9Sstevel@tonic-gate } 19297c478bd9Sstevel@tonic-gate wptr = wp; 19307c478bd9Sstevel@tonic-gate } 19317c478bd9Sstevel@tonic-gate if ((sec_display = wcswidth(wptr, nwc)) 19327c478bd9Sstevel@tonic-gate == -1) { 19337c478bd9Sstevel@tonic-gate sec_display = 19347c478bd9Sstevel@tonic-gate _rec_scrswidth 19357c478bd9Sstevel@tonic-gate (wptr, nwc); 19367c478bd9Sstevel@tonic-gate } 19377c478bd9Sstevel@tonic-gate mbs_err: 19387c478bd9Sstevel@tonic-gate if (wp) 19397c478bd9Sstevel@tonic-gate lfree(wp, wpsize); 19407c478bd9Sstevel@tonic-gate } 19417c478bd9Sstevel@tonic-gate } else { /* a strnlen function would be useful here! */ 19427c478bd9Sstevel@tonic-gate /* 19437c478bd9Sstevel@tonic-gate * If we've seen a dot, and count has been set 19447c478bd9Sstevel@tonic-gate * to 0, then we don't output in any cases 19457c478bd9Sstevel@tonic-gate * below. prec should be always >= 0. So we only 19467c478bd9Sstevel@tonic-gate * check to see if it's zero. 19477c478bd9Sstevel@tonic-gate */ 19487c478bd9Sstevel@tonic-gate if (prec == 0) { 19497c478bd9Sstevel@tonic-gate p = bp; 19507c478bd9Sstevel@tonic-gate break; 19517c478bd9Sstevel@tonic-gate } 19527c478bd9Sstevel@tonic-gate 19537c478bd9Sstevel@tonic-gate if (wflag) { 19547c478bd9Sstevel@tonic-gate /* wide character handling */ 19557c478bd9Sstevel@tonic-gate 19567c478bd9Sstevel@tonic-gate wide_hand: 19577c478bd9Sstevel@tonic-gate wp = (wchar_t *)(uintptr_t)bp; 19587c478bd9Sstevel@tonic-gate preco = prec; 19597c478bd9Sstevel@tonic-gate wcount = 0; 19607c478bd9Sstevel@tonic-gate while (*wp && 19617c478bd9Sstevel@tonic-gate (prec -= _scrwidth(*wp)) >= 0) { 19627c478bd9Sstevel@tonic-gate if ((retcode = 19637c478bd9Sstevel@tonic-gate wctomb(tmpbuf, *wp)) < 0) 19647c478bd9Sstevel@tonic-gate wcount++; 19657c478bd9Sstevel@tonic-gate else 19667c478bd9Sstevel@tonic-gate wcount += retcode; 19677c478bd9Sstevel@tonic-gate wp++; 19687c478bd9Sstevel@tonic-gate } 19697c478bd9Sstevel@tonic-gate if (*wp) 19707c478bd9Sstevel@tonic-gate prec += _scrwidth(*wp); 19717c478bd9Sstevel@tonic-gate p = (char *)wp; 19727c478bd9Sstevel@tonic-gate sec_display = preco - prec; 19737c478bd9Sstevel@tonic-gate } else if (__xpg4 == 0 && MB_CUR_MAX > 1) { 19747c478bd9Sstevel@tonic-gate /* 19757c478bd9Sstevel@tonic-gate * Solaris behavior - count 19767c478bd9Sstevel@tonic-gate * precision as screen column width 19777c478bd9Sstevel@tonic-gate */ 19787c478bd9Sstevel@tonic-gate char *qp = bp; 19797c478bd9Sstevel@tonic-gate int ncol, nbytes; 19807c478bd9Sstevel@tonic-gate wchar_t wc; 19817c478bd9Sstevel@tonic-gate 19827c478bd9Sstevel@tonic-gate ncol = 0; 19837c478bd9Sstevel@tonic-gate preco = prec; 19847c478bd9Sstevel@tonic-gate while (*qp) { 19857c478bd9Sstevel@tonic-gate if (isascii(*qp)) { 19867c478bd9Sstevel@tonic-gate qp++; 19877c478bd9Sstevel@tonic-gate if (--prec == 0) 19887c478bd9Sstevel@tonic-gate break; 19897c478bd9Sstevel@tonic-gate continue; 19907c478bd9Sstevel@tonic-gate } 19917c478bd9Sstevel@tonic-gate if ((nbytes = mbtowc(&wc, qp, 19927c478bd9Sstevel@tonic-gate MB_LEN_MAX)) == -1) { 19937c478bd9Sstevel@tonic-gate /* print illegal char */ 19947c478bd9Sstevel@tonic-gate nbytes = 1; 19957c478bd9Sstevel@tonic-gate ncol = 1; 19967c478bd9Sstevel@tonic-gate } else { 19977c478bd9Sstevel@tonic-gate if ((ncol = 19987c478bd9Sstevel@tonic-gate _scrwidth(wc)) 19997c478bd9Sstevel@tonic-gate == 0) { 20007c478bd9Sstevel@tonic-gate ncol = 1; 20017c478bd9Sstevel@tonic-gate } 20027c478bd9Sstevel@tonic-gate } 20037c478bd9Sstevel@tonic-gate 20047c478bd9Sstevel@tonic-gate if ((prec -= ncol) >= 0) { 20057c478bd9Sstevel@tonic-gate qp += nbytes; 20067c478bd9Sstevel@tonic-gate if (prec == 0) 20077c478bd9Sstevel@tonic-gate break; 20087c478bd9Sstevel@tonic-gate } else { 20097c478bd9Sstevel@tonic-gate break; 20107c478bd9Sstevel@tonic-gate } 20117c478bd9Sstevel@tonic-gate } 20127c478bd9Sstevel@tonic-gate if (prec < 0) 20137c478bd9Sstevel@tonic-gate prec += ncol; 20147c478bd9Sstevel@tonic-gate p = qp; 20157c478bd9Sstevel@tonic-gate sec_display = preco - prec; 20167c478bd9Sstevel@tonic-gate } else { 20177c478bd9Sstevel@tonic-gate /* 20187c478bd9Sstevel@tonic-gate * XPG4 behavior - count 20197c478bd9Sstevel@tonic-gate * precision as bytes. 20207c478bd9Sstevel@tonic-gate * We don't use strlen() because 20217c478bd9Sstevel@tonic-gate * the given char string may not 20227c478bd9Sstevel@tonic-gate * be null-terminated. 20237c478bd9Sstevel@tonic-gate */ 20247c478bd9Sstevel@tonic-gate char *qp; 20257c478bd9Sstevel@tonic-gate 20267c478bd9Sstevel@tonic-gate qp = memchr(bp, '\0', prec); 20277c478bd9Sstevel@tonic-gate if (qp == NULL) { 20287c478bd9Sstevel@tonic-gate p = bp + prec; 20297c478bd9Sstevel@tonic-gate } else { 20307c478bd9Sstevel@tonic-gate p = qp; 20317c478bd9Sstevel@tonic-gate } 20327c478bd9Sstevel@tonic-gate } 20337c478bd9Sstevel@tonic-gate } 20347c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 20357c478bd9Sstevel@tonic-gate break; 20367c478bd9Sstevel@tonic-gate 20377c478bd9Sstevel@tonic-gate case 'n': 20387c478bd9Sstevel@tonic-gate { 20397c478bd9Sstevel@tonic-gate if (flagword & XLONG) { 20407c478bd9Sstevel@tonic-gate long long *svcount; 20417c478bd9Sstevel@tonic-gate svcount = va_arg(args.ap, long long *); 20427c478bd9Sstevel@tonic-gate *svcount = (long long)count; 20437c478bd9Sstevel@tonic-gate } else if (flagword & LENGTH) { 20447c478bd9Sstevel@tonic-gate long *svcount; 20457c478bd9Sstevel@tonic-gate svcount = va_arg(args.ap, long *); 20467c478bd9Sstevel@tonic-gate *svcount = (long)count; 20477c478bd9Sstevel@tonic-gate } else if (flagword & SHORT) { 20487c478bd9Sstevel@tonic-gate short *svcount; 20497c478bd9Sstevel@tonic-gate svcount = va_arg(args.ap, short *); 20507c478bd9Sstevel@tonic-gate *svcount = (short)count; 20517c478bd9Sstevel@tonic-gate } else if (flagword & CHAR) { 20527c478bd9Sstevel@tonic-gate char *svcount; 20537c478bd9Sstevel@tonic-gate svcount = va_arg(args.ap, char *); 20547c478bd9Sstevel@tonic-gate *svcount = (char)count; 20557c478bd9Sstevel@tonic-gate } else { 20567c478bd9Sstevel@tonic-gate int *svcount; 20577c478bd9Sstevel@tonic-gate svcount = va_arg(args.ap, int *); 20587c478bd9Sstevel@tonic-gate *svcount = count; 20597c478bd9Sstevel@tonic-gate } 20607c478bd9Sstevel@tonic-gate continue; 20617c478bd9Sstevel@tonic-gate } 20627c478bd9Sstevel@tonic-gate default: /* this is technically an error; what we do is to */ 20637c478bd9Sstevel@tonic-gate /* back up the format pointer to the offending char */ 20647c478bd9Sstevel@tonic-gate /* and continue with the format scan */ 20657c478bd9Sstevel@tonic-gate format--; 20667c478bd9Sstevel@tonic-gate continue; 20677c478bd9Sstevel@tonic-gate } 20687c478bd9Sstevel@tonic-gate 20697c478bd9Sstevel@tonic-gate if (inf_nan) { 20707c478bd9Sstevel@tonic-gate if (inf_nan_mixed_case) { 20717c478bd9Sstevel@tonic-gate /* advance p */ 20727c478bd9Sstevel@tonic-gate for (p = bp + 1; *p != '\0'; p++) 20737c478bd9Sstevel@tonic-gate ; 20747c478bd9Sstevel@tonic-gate } else { 20757c478bd9Sstevel@tonic-gate int upper; 20767c478bd9Sstevel@tonic-gate 20777c478bd9Sstevel@tonic-gate /* advance p and make output all one case */ 20787c478bd9Sstevel@tonic-gate upper = _M_ISUPPER(fcode); 20797c478bd9Sstevel@tonic-gate for (p = bp; *p != '\0'; p++) 20807c478bd9Sstevel@tonic-gate *p = upper? toupper(*p) : tolower(*p); 20817c478bd9Sstevel@tonic-gate } 20827c478bd9Sstevel@tonic-gate if (sign) { 20837c478bd9Sstevel@tonic-gate prefix = _P_HYPHEN; 20847c478bd9Sstevel@tonic-gate prefixlength = 1; 20857c478bd9Sstevel@tonic-gate } else if (flagword & FPLUS) { 20867c478bd9Sstevel@tonic-gate prefix = _P_PLUS; 20877c478bd9Sstevel@tonic-gate prefixlength = 1; 20887c478bd9Sstevel@tonic-gate } else if (flagword & FBLANK) { 20897c478bd9Sstevel@tonic-gate prefix = _P_BLANK; 20907c478bd9Sstevel@tonic-gate prefixlength = 1; 20917c478bd9Sstevel@tonic-gate } 20927c478bd9Sstevel@tonic-gate inf_nan = 0; 20937c478bd9Sstevel@tonic-gate inf_nan_mixed_case = 0; 2094146fa2c5SDouglas Priest flagword &= ~PADZERO; /* ignore 0 flag */ 20957c478bd9Sstevel@tonic-gate } 20967c478bd9Sstevel@tonic-gate 20977c478bd9Sstevel@tonic-gate /* Calculate number of padding blanks */ 20987c478bd9Sstevel@tonic-gate n = p - bp; /* n == size of the converted value (in bytes) */ 20997c478bd9Sstevel@tonic-gate 21007c478bd9Sstevel@tonic-gate #ifdef _WIDE 21017c478bd9Sstevel@tonic-gate k = n; 21027c478bd9Sstevel@tonic-gate #else /* _WIDE */ 21037c478bd9Sstevel@tonic-gate if (sec_display) /* when format is %s or %ws or %S */ 21047c478bd9Sstevel@tonic-gate k = sec_display; 21057c478bd9Sstevel@tonic-gate else 21067c478bd9Sstevel@tonic-gate k = n; 21077c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 21087c478bd9Sstevel@tonic-gate /* 21097c478bd9Sstevel@tonic-gate * k is the (screen) width or # of bytes of the converted value 21107c478bd9Sstevel@tonic-gate */ 21117c478bd9Sstevel@tonic-gate k += prefixlength + otherlength; 21127c478bd9Sstevel@tonic-gate 21137c478bd9Sstevel@tonic-gate #ifdef _WIDE 21147c478bd9Sstevel@tonic-gate if (wflag) { 21157c478bd9Sstevel@tonic-gate count += wcount; 21167c478bd9Sstevel@tonic-gate } else { 21177c478bd9Sstevel@tonic-gate count += n; 21187c478bd9Sstevel@tonic-gate } 21197c478bd9Sstevel@tonic-gate #else /* _WIDE */ 21207c478bd9Sstevel@tonic-gate /* 21217c478bd9Sstevel@tonic-gate * update count which is the overall size of the output data 21227c478bd9Sstevel@tonic-gate * and passed to memchr() 21237c478bd9Sstevel@tonic-gate */ 21247c478bd9Sstevel@tonic-gate if (wflag) 21257c478bd9Sstevel@tonic-gate /* 21267c478bd9Sstevel@tonic-gate * when wflag != 0 (i.e. %ws or %wc), the size of the 21277c478bd9Sstevel@tonic-gate * converted value is wcount bytes 21287c478bd9Sstevel@tonic-gate */ 21297c478bd9Sstevel@tonic-gate count += wcount; 21307c478bd9Sstevel@tonic-gate else 21317c478bd9Sstevel@tonic-gate /* 21327c478bd9Sstevel@tonic-gate * when wflag == 0, the size of the converted 21337c478bd9Sstevel@tonic-gate * value is n (= p-bp) bytes 21347c478bd9Sstevel@tonic-gate */ 21357c478bd9Sstevel@tonic-gate count += n; 21367c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 21377c478bd9Sstevel@tonic-gate count += prefixlength + otherlength; 21387c478bd9Sstevel@tonic-gate 21397c478bd9Sstevel@tonic-gate if (width > k) { 21407c478bd9Sstevel@tonic-gate count += (width - k); 21417c478bd9Sstevel@tonic-gate /* 21427c478bd9Sstevel@tonic-gate * Set up for padding zeroes if requested 21437c478bd9Sstevel@tonic-gate * Otherwise emit padding blanks unless output is 21447c478bd9Sstevel@tonic-gate * to be left-justified. 21457c478bd9Sstevel@tonic-gate */ 21467c478bd9Sstevel@tonic-gate 21477c478bd9Sstevel@tonic-gate if (flagword & PADZERO) { 21487c478bd9Sstevel@tonic-gate if (!(flagword & LZERO)) { 21497c478bd9Sstevel@tonic-gate flagword |= LZERO; 21507c478bd9Sstevel@tonic-gate lzero = width - k; 21517c478bd9Sstevel@tonic-gate } else 21527c478bd9Sstevel@tonic-gate lzero += width - k; 21537c478bd9Sstevel@tonic-gate k = width; /* cancel padding blanks */ 21547c478bd9Sstevel@tonic-gate } else 21557c478bd9Sstevel@tonic-gate /* Blanks on left if required */ 21567c478bd9Sstevel@tonic-gate if (!(flagword & FMINUS)) 21577c478bd9Sstevel@tonic-gate PAD(_blanks, width - k); 21587c478bd9Sstevel@tonic-gate } 21597c478bd9Sstevel@tonic-gate 21607c478bd9Sstevel@tonic-gate /* Prefix, if any */ 21617c478bd9Sstevel@tonic-gate if (prefixlength != 0) 21627c478bd9Sstevel@tonic-gate PUT(prefix, prefixlength); 21637c478bd9Sstevel@tonic-gate 21647c478bd9Sstevel@tonic-gate /* Zeroes on the left */ 21657c478bd9Sstevel@tonic-gate if ((flagword & LZERO)) /* && */ 21667c478bd9Sstevel@tonic-gate /* (!(flagword & SHORT) || !(flagword & FMINUS)) */ 21677c478bd9Sstevel@tonic-gate PAD(_zeroes, lzero); 21687c478bd9Sstevel@tonic-gate 21697c478bd9Sstevel@tonic-gate #ifdef _WIDE 21707c478bd9Sstevel@tonic-gate if (n > 0) 21717c478bd9Sstevel@tonic-gate PUT(bp, n); 21727c478bd9Sstevel@tonic-gate if ((fcode == 's') && !lflag) { 21737c478bd9Sstevel@tonic-gate if (bp) 21747c478bd9Sstevel@tonic-gate lfree(bp, bpsize); 21757c478bd9Sstevel@tonic-gate } 21767c478bd9Sstevel@tonic-gate #else /* _WIDE */ 21777c478bd9Sstevel@tonic-gate /* The value itself */ 21787c478bd9Sstevel@tonic-gate if ((fcode == 's' || fcode == 'S') && wflag) { 21797c478bd9Sstevel@tonic-gate /* wide character handling */ 21807c478bd9Sstevel@tonic-gate wchar_t *wp = (wchar_t *)(uintptr_t)bp; 21817c478bd9Sstevel@tonic-gate int cnt; 21827c478bd9Sstevel@tonic-gate char *bufp; 21837c478bd9Sstevel@tonic-gate long printn; 21847c478bd9Sstevel@tonic-gate printn = (wchar_t *)(uintptr_t)p - 21857c478bd9Sstevel@tonic-gate (wchar_t *)(uintptr_t)bp; 21867c478bd9Sstevel@tonic-gate bufp = buf; 21877c478bd9Sstevel@tonic-gate while (printn > 0) { 21887c478bd9Sstevel@tonic-gate if ((cnt = wctomb(buf, *wp)) < 0) 21897c478bd9Sstevel@tonic-gate cnt = 1; 21907c478bd9Sstevel@tonic-gate PUT(bufp, cnt); 21917c478bd9Sstevel@tonic-gate wp++; 21927c478bd9Sstevel@tonic-gate printn--; 21937c478bd9Sstevel@tonic-gate } 21947c478bd9Sstevel@tonic-gate } else { /* non wide character value */ 21957c478bd9Sstevel@tonic-gate if (n > 0) 21967c478bd9Sstevel@tonic-gate PUT(bp, n); 21977c478bd9Sstevel@tonic-gate } 21987c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 21997c478bd9Sstevel@tonic-gate 22007c478bd9Sstevel@tonic-gate if (flagword & (RZERO | SUFFIX | FMINUS)) { 22017c478bd9Sstevel@tonic-gate /* Zeroes on the right */ 22027c478bd9Sstevel@tonic-gate if (flagword & RZERO) 22037c478bd9Sstevel@tonic-gate PAD(_zeroes, rzero); 22047c478bd9Sstevel@tonic-gate 22057c478bd9Sstevel@tonic-gate /* The suffix */ 22067c478bd9Sstevel@tonic-gate if (flagword & SUFFIX) 22077c478bd9Sstevel@tonic-gate PUT(suffix, suffixlength); 22087c478bd9Sstevel@tonic-gate 22097c478bd9Sstevel@tonic-gate /* Blanks on the right if required */ 22107c478bd9Sstevel@tonic-gate if (flagword & FMINUS && width > k) 22117c478bd9Sstevel@tonic-gate PAD(_blanks, width - k); 22127c478bd9Sstevel@tonic-gate } 22137c478bd9Sstevel@tonic-gate } 22147c478bd9Sstevel@tonic-gate } 22157c478bd9Sstevel@tonic-gate 22167c478bd9Sstevel@tonic-gate #ifdef _WIDE 22177c478bd9Sstevel@tonic-gate static int 22187c478bd9Sstevel@tonic-gate _watoi(wchar_t *fmt) 22197c478bd9Sstevel@tonic-gate { 22207c478bd9Sstevel@tonic-gate int n = 0; 22217c478bd9Sstevel@tonic-gate wchar_t ch; 22227c478bd9Sstevel@tonic-gate 22237c478bd9Sstevel@tonic-gate ch = *fmt; 22247c478bd9Sstevel@tonic-gate if (_M_ISDIGIT(ch)) { 22257c478bd9Sstevel@tonic-gate n = ch - '0'; 22267c478bd9Sstevel@tonic-gate ch = *++fmt; 22277c478bd9Sstevel@tonic-gate while (_M_ISDIGIT(ch)) { 22287c478bd9Sstevel@tonic-gate n *= 10; 22297c478bd9Sstevel@tonic-gate n += ch - '0'; 22307c478bd9Sstevel@tonic-gate ch = *++fmt; 22317c478bd9Sstevel@tonic-gate } 22327c478bd9Sstevel@tonic-gate } 22337c478bd9Sstevel@tonic-gate return (n); 22347c478bd9Sstevel@tonic-gate } 22357c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 22367c478bd9Sstevel@tonic-gate 22377c478bd9Sstevel@tonic-gate /* 22387c478bd9Sstevel@tonic-gate * This function initializes arglst, to contain the appropriate va_list values 22397c478bd9Sstevel@tonic-gate * for the first MAXARGS arguments. 22407c478bd9Sstevel@tonic-gate */ 22417c478bd9Sstevel@tonic-gate 22427c478bd9Sstevel@tonic-gate /* 22437c478bd9Sstevel@tonic-gate * Type modifier flags: 22447c478bd9Sstevel@tonic-gate * 0x01 for long 22457c478bd9Sstevel@tonic-gate * 0x02 for int 22467c478bd9Sstevel@tonic-gate * 0x04 for long long 22477c478bd9Sstevel@tonic-gate * 0x08 for long double 22487c478bd9Sstevel@tonic-gate */ 22497c478bd9Sstevel@tonic-gate 22507c478bd9Sstevel@tonic-gate #define FLAG_LONG 0x01 22517c478bd9Sstevel@tonic-gate #define FLAG_INT 0x02 22527c478bd9Sstevel@tonic-gate #define FLAG_LONG_LONG 0x04 22537c478bd9Sstevel@tonic-gate #define FLAG_LONG_DBL 0x08 22547c478bd9Sstevel@tonic-gate 22557c478bd9Sstevel@tonic-gate /* ARGSUSED3 */ 22567c478bd9Sstevel@tonic-gate #ifdef _WIDE 22577c478bd9Sstevel@tonic-gate static void 22587c478bd9Sstevel@tonic-gate _wmkarglst(wchar_t *fmt, stva_list args, stva_list arglst[], int prflag) 22597c478bd9Sstevel@tonic-gate #else /* _WIDE */ 22608793b36bSNick Todd static void 22617c478bd9Sstevel@tonic-gate _mkarglst(char *fmt, stva_list args, stva_list arglst[], int prflag) 22627c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 22637c478bd9Sstevel@tonic-gate { 22647c478bd9Sstevel@tonic-gate #ifdef _WIDE 22657c478bd9Sstevel@tonic-gate static const wchar_t digits[] = L"01234567890"; 22667c478bd9Sstevel@tonic-gate static const wchar_t skips[] = L"# +-.'0123456789h$"; 22677c478bd9Sstevel@tonic-gate #else /* _WIDE */ 22687c478bd9Sstevel@tonic-gate static const char digits[] = "01234567890"; 22697c478bd9Sstevel@tonic-gate static const char skips[] = "# +-.'0123456789h$"; 22707c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 22717c478bd9Sstevel@tonic-gate enum types {INT = 1, LONG, CHAR_PTR, DOUBLE, LONG_DOUBLE, VOID_PTR, 22727c478bd9Sstevel@tonic-gate LONG_PTR, INT_PTR, LONG_LONG, LONG_LONG_PTR}; 22737c478bd9Sstevel@tonic-gate enum types typelst[MAXARGS], curtype; 22747c478bd9Sstevel@tonic-gate ssize_t n; 22757c478bd9Sstevel@tonic-gate int maxnum, curargno, flags; 22767c478bd9Sstevel@tonic-gate 22777c478bd9Sstevel@tonic-gate /* 22787c478bd9Sstevel@tonic-gate * Algorithm 1. set all argument types to zero. 22797c478bd9Sstevel@tonic-gate * 2. walk through fmt putting arg types in typelst[]. 22807c478bd9Sstevel@tonic-gate * 3. walk through args using va_arg(args.ap, typelst[n]) 22817c478bd9Sstevel@tonic-gate * and set arglst[] to the appropriate values. 22827c478bd9Sstevel@tonic-gate * Assumptions: Cannot use %*$... to specify variable position. 22837c478bd9Sstevel@tonic-gate */ 22847c478bd9Sstevel@tonic-gate 22857c478bd9Sstevel@tonic-gate (void) memset((void *) typelst, 0, sizeof (typelst)); 22867c478bd9Sstevel@tonic-gate maxnum = -1; 22877c478bd9Sstevel@tonic-gate curargno = 0; 22887c478bd9Sstevel@tonic-gate while ((fmt = STRCHR(fmt, '%')) != 0) { 22897c478bd9Sstevel@tonic-gate fmt++; /* skip % */ 22907c478bd9Sstevel@tonic-gate if (fmt[n = STRSPN(fmt, digits)] == '$') { 22917c478bd9Sstevel@tonic-gate /* convert to zero base */ 22927c478bd9Sstevel@tonic-gate curargno = ATOI(fmt) - 1; 22937c478bd9Sstevel@tonic-gate if (curargno < 0) 22947c478bd9Sstevel@tonic-gate continue; 22957c478bd9Sstevel@tonic-gate fmt += n + 1; 22967c478bd9Sstevel@tonic-gate } 22977c478bd9Sstevel@tonic-gate flags = 0; 22987c478bd9Sstevel@tonic-gate again:; 22997c478bd9Sstevel@tonic-gate fmt += STRSPN(fmt, skips); 23007c478bd9Sstevel@tonic-gate switch (*fmt++) { 23017c478bd9Sstevel@tonic-gate case '%': /* there is no argument! */ 23027c478bd9Sstevel@tonic-gate continue; 23037c478bd9Sstevel@tonic-gate case 'l': 23047c478bd9Sstevel@tonic-gate if (flags & (FLAG_LONG | FLAG_LONG_LONG)) { 23057c478bd9Sstevel@tonic-gate flags |= FLAG_LONG_LONG; 23067c478bd9Sstevel@tonic-gate flags &= ~FLAG_LONG; 23077c478bd9Sstevel@tonic-gate } else { 23087c478bd9Sstevel@tonic-gate flags |= FLAG_LONG; 23097c478bd9Sstevel@tonic-gate } 23107c478bd9Sstevel@tonic-gate goto again; 23117c478bd9Sstevel@tonic-gate case 'j': 23127c478bd9Sstevel@tonic-gate #ifndef _LP64 23137c478bd9Sstevel@tonic-gate /* 23147c478bd9Sstevel@tonic-gate * *printf_c89() in 32-bit libc uses 23157c478bd9Sstevel@tonic-gate * 32-bit intmax_t; otherwise intmax_t 23167c478bd9Sstevel@tonic-gate * is 64-bits. 23177c478bd9Sstevel@tonic-gate */ 23187c478bd9Sstevel@tonic-gate if (!(prflag & _F_INTMAX32)) { 23197c478bd9Sstevel@tonic-gate #endif 23207c478bd9Sstevel@tonic-gate flags |= FLAG_LONG_LONG; /* 64-bit */ 23217c478bd9Sstevel@tonic-gate #ifndef _LP64 23227c478bd9Sstevel@tonic-gate } 23237c478bd9Sstevel@tonic-gate #endif 23247c478bd9Sstevel@tonic-gate goto again; 23257c478bd9Sstevel@tonic-gate case 't': 23267c478bd9Sstevel@tonic-gate flags |= FLAG_LONG; 23277c478bd9Sstevel@tonic-gate goto again; 23287c478bd9Sstevel@tonic-gate case 'z': 23297c478bd9Sstevel@tonic-gate flags |= FLAG_LONG; 23307c478bd9Sstevel@tonic-gate goto again; 23317c478bd9Sstevel@tonic-gate case 'L': 23327c478bd9Sstevel@tonic-gate flags |= FLAG_LONG_DBL; 23337c478bd9Sstevel@tonic-gate goto again; 23347c478bd9Sstevel@tonic-gate case '*': /* int argument used for value */ 23357c478bd9Sstevel@tonic-gate /* check if there is a positional parameter */ 23367c478bd9Sstevel@tonic-gate #ifdef _WIDE 23377c478bd9Sstevel@tonic-gate if ((*fmt >= 0) && (*fmt < 256) && 23387c478bd9Sstevel@tonic-gate isdigit(*fmt)) 23397c478bd9Sstevel@tonic-gate #else /* _WIDE */ 23407c478bd9Sstevel@tonic-gate if (isdigit(*fmt)) 23417c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 23427c478bd9Sstevel@tonic-gate { 23437c478bd9Sstevel@tonic-gate int targno; 23447c478bd9Sstevel@tonic-gate targno = ATOI(fmt) - 1; 23457c478bd9Sstevel@tonic-gate fmt += STRSPN(fmt, digits); 23467c478bd9Sstevel@tonic-gate if (*fmt == '$') 23477c478bd9Sstevel@tonic-gate fmt++; /* skip '$' */ 23487c478bd9Sstevel@tonic-gate if (targno >= 0 && targno < MAXARGS) { 23497c478bd9Sstevel@tonic-gate typelst[targno] = INT; 23507c478bd9Sstevel@tonic-gate if (maxnum < targno) 23517c478bd9Sstevel@tonic-gate maxnum = targno; 23527c478bd9Sstevel@tonic-gate } 23537c478bd9Sstevel@tonic-gate goto again; 23547c478bd9Sstevel@tonic-gate } 23557c478bd9Sstevel@tonic-gate flags |= FLAG_INT; 23567c478bd9Sstevel@tonic-gate curtype = INT; 23577c478bd9Sstevel@tonic-gate break; 23587c478bd9Sstevel@tonic-gate case 'a': 23597c478bd9Sstevel@tonic-gate case 'A': 23607c478bd9Sstevel@tonic-gate case 'e': 23617c478bd9Sstevel@tonic-gate case 'E': 23627c478bd9Sstevel@tonic-gate case 'f': 23637c478bd9Sstevel@tonic-gate case 'F': 23647c478bd9Sstevel@tonic-gate case 'g': 23657c478bd9Sstevel@tonic-gate case 'G': 23667c478bd9Sstevel@tonic-gate if (flags & FLAG_LONG_DBL) 23677c478bd9Sstevel@tonic-gate curtype = LONG_DOUBLE; 23687c478bd9Sstevel@tonic-gate else 23697c478bd9Sstevel@tonic-gate curtype = DOUBLE; 23707c478bd9Sstevel@tonic-gate break; 23717c478bd9Sstevel@tonic-gate case 's': 23727c478bd9Sstevel@tonic-gate curtype = CHAR_PTR; 23737c478bd9Sstevel@tonic-gate break; 23747c478bd9Sstevel@tonic-gate case 'p': 23757c478bd9Sstevel@tonic-gate curtype = VOID_PTR; 23767c478bd9Sstevel@tonic-gate break; 23777c478bd9Sstevel@tonic-gate case 'n': 23787c478bd9Sstevel@tonic-gate if (flags & FLAG_LONG_LONG) 23797c478bd9Sstevel@tonic-gate curtype = LONG_LONG_PTR; 23807c478bd9Sstevel@tonic-gate else if (flags & FLAG_LONG) 23817c478bd9Sstevel@tonic-gate curtype = LONG_PTR; 23827c478bd9Sstevel@tonic-gate else 23837c478bd9Sstevel@tonic-gate curtype = INT_PTR; 23847c478bd9Sstevel@tonic-gate break; 23857c478bd9Sstevel@tonic-gate default: 23867c478bd9Sstevel@tonic-gate if (flags & FLAG_LONG_LONG) 23877c478bd9Sstevel@tonic-gate curtype = LONG_LONG; 23887c478bd9Sstevel@tonic-gate else if (flags & FLAG_LONG) 23897c478bd9Sstevel@tonic-gate curtype = LONG; 23907c478bd9Sstevel@tonic-gate else 23917c478bd9Sstevel@tonic-gate curtype = INT; 23927c478bd9Sstevel@tonic-gate break; 23937c478bd9Sstevel@tonic-gate } 23947c478bd9Sstevel@tonic-gate if (curargno >= 0 && curargno < MAXARGS) { 23957c478bd9Sstevel@tonic-gate typelst[curargno] = curtype; 23967c478bd9Sstevel@tonic-gate if (maxnum < curargno) 23977c478bd9Sstevel@tonic-gate maxnum = curargno; 23987c478bd9Sstevel@tonic-gate } 23997c478bd9Sstevel@tonic-gate curargno++; /* default to next in list */ 24007c478bd9Sstevel@tonic-gate if (flags & FLAG_INT) /* took care of *, keep going */ 24017c478bd9Sstevel@tonic-gate { 24027c478bd9Sstevel@tonic-gate flags ^= FLAG_INT; 24037c478bd9Sstevel@tonic-gate goto again; 24047c478bd9Sstevel@tonic-gate } 24057c478bd9Sstevel@tonic-gate } 24067c478bd9Sstevel@tonic-gate for (n = 0; n <= maxnum; n++) { 24077c478bd9Sstevel@tonic-gate arglst[n] = args; 24087c478bd9Sstevel@tonic-gate if (typelst[n] == 0) 24097c478bd9Sstevel@tonic-gate typelst[n] = INT; 24107c478bd9Sstevel@tonic-gate 24117c478bd9Sstevel@tonic-gate switch (typelst[n]) { 24127c478bd9Sstevel@tonic-gate case INT: 24137c478bd9Sstevel@tonic-gate (void) va_arg(args.ap, int); 24147c478bd9Sstevel@tonic-gate break; 24157c478bd9Sstevel@tonic-gate case LONG: 24167c478bd9Sstevel@tonic-gate (void) va_arg(args.ap, long); 24177c478bd9Sstevel@tonic-gate break; 24187c478bd9Sstevel@tonic-gate case CHAR_PTR: 24197c478bd9Sstevel@tonic-gate (void) va_arg(args.ap, char *); 24207c478bd9Sstevel@tonic-gate break; 24217c478bd9Sstevel@tonic-gate case DOUBLE: 24227c478bd9Sstevel@tonic-gate (void) va_arg(args.ap, double); 24237c478bd9Sstevel@tonic-gate break; 24247c478bd9Sstevel@tonic-gate case LONG_DOUBLE: 24257c478bd9Sstevel@tonic-gate (void) GETQVAL(args.ap); 24267c478bd9Sstevel@tonic-gate break; 24277c478bd9Sstevel@tonic-gate case VOID_PTR: 24287c478bd9Sstevel@tonic-gate (void) va_arg(args.ap, void *); 24297c478bd9Sstevel@tonic-gate break; 24307c478bd9Sstevel@tonic-gate case LONG_PTR: 24317c478bd9Sstevel@tonic-gate (void) va_arg(args.ap, long *); 24327c478bd9Sstevel@tonic-gate break; 24337c478bd9Sstevel@tonic-gate case INT_PTR: 24347c478bd9Sstevel@tonic-gate (void) va_arg(args.ap, int *); 24357c478bd9Sstevel@tonic-gate break; 24367c478bd9Sstevel@tonic-gate case LONG_LONG: 24377c478bd9Sstevel@tonic-gate (void) va_arg(args.ap, long long); 24387c478bd9Sstevel@tonic-gate break; 24397c478bd9Sstevel@tonic-gate case LONG_LONG_PTR: 24407c478bd9Sstevel@tonic-gate (void) va_arg(args.ap, long long *); 24417c478bd9Sstevel@tonic-gate break; 24427c478bd9Sstevel@tonic-gate } 24437c478bd9Sstevel@tonic-gate } 24447c478bd9Sstevel@tonic-gate } 24457c478bd9Sstevel@tonic-gate 24467c478bd9Sstevel@tonic-gate /* 24477c478bd9Sstevel@tonic-gate * This function is used to find the va_list value for arguments whose 24487c478bd9Sstevel@tonic-gate * position is greater than MAXARGS. This function is slow, so hopefully 24497c478bd9Sstevel@tonic-gate * MAXARGS will be big enough so that this function need only be called in 24507c478bd9Sstevel@tonic-gate * unusual circumstances. 24517c478bd9Sstevel@tonic-gate * pargs is assumed to contain the value of arglst[MAXARGS - 1]. 24527c478bd9Sstevel@tonic-gate */ 24537c478bd9Sstevel@tonic-gate /* ARGSUSED3 */ 24547c478bd9Sstevel@tonic-gate #ifdef _WIDE 24557c478bd9Sstevel@tonic-gate static void 24567c478bd9Sstevel@tonic-gate _wgetarg(wchar_t *fmt, stva_list *pargs, long argno, int prflag) 24577c478bd9Sstevel@tonic-gate #else /* _WIDE */ 24587c478bd9Sstevel@tonic-gate void 24597c478bd9Sstevel@tonic-gate _getarg(char *fmt, stva_list *pargs, long argno, int prflag) 24607c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 24617c478bd9Sstevel@tonic-gate { 24627c478bd9Sstevel@tonic-gate 24637c478bd9Sstevel@tonic-gate #ifdef _WIDE 24647c478bd9Sstevel@tonic-gate static const wchar_t digits[] = L"01234567890"; 24657c478bd9Sstevel@tonic-gate static const wchar_t skips[] = L"# +-.'0123456789h$"; 24667c478bd9Sstevel@tonic-gate wchar_t *sfmt = fmt; 24677c478bd9Sstevel@tonic-gate #else /* _WIDE */ 24687c478bd9Sstevel@tonic-gate static const char digits[] = "01234567890"; 24697c478bd9Sstevel@tonic-gate static const char skips[] = "# +-.'0123456789h$"; 24707c478bd9Sstevel@tonic-gate char *sfmt = fmt; 24717c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 24727c478bd9Sstevel@tonic-gate ssize_t n; 24737c478bd9Sstevel@tonic-gate int i, curargno, flags; 24747c478bd9Sstevel@tonic-gate int found = 1; 24757c478bd9Sstevel@tonic-gate 24767c478bd9Sstevel@tonic-gate i = MAXARGS; 24777c478bd9Sstevel@tonic-gate curargno = 1; 24787c478bd9Sstevel@tonic-gate while (found) { 24797c478bd9Sstevel@tonic-gate fmt = sfmt; 24807c478bd9Sstevel@tonic-gate found = 0; 24817c478bd9Sstevel@tonic-gate while ((i != argno) && (fmt = STRCHR(fmt, '%')) != 0) { 24827c478bd9Sstevel@tonic-gate fmt++; /* skip % */ 24837c478bd9Sstevel@tonic-gate if (fmt[n = STRSPN(fmt, digits)] == '$') { 24847c478bd9Sstevel@tonic-gate curargno = ATOI(fmt); 24857c478bd9Sstevel@tonic-gate if (curargno <= 0) 24867c478bd9Sstevel@tonic-gate continue; 24877c478bd9Sstevel@tonic-gate fmt += n + 1; 24887c478bd9Sstevel@tonic-gate } 24897c478bd9Sstevel@tonic-gate 24907c478bd9Sstevel@tonic-gate /* find conversion specifier for next argument */ 24917c478bd9Sstevel@tonic-gate if (i != curargno) { 24927c478bd9Sstevel@tonic-gate curargno++; 24937c478bd9Sstevel@tonic-gate continue; 24947c478bd9Sstevel@tonic-gate } else 24957c478bd9Sstevel@tonic-gate found = 1; 24967c478bd9Sstevel@tonic-gate flags = 0; 24977c478bd9Sstevel@tonic-gate again:; 24987c478bd9Sstevel@tonic-gate fmt += STRSPN(fmt, skips); 24997c478bd9Sstevel@tonic-gate switch (*fmt++) { 25007c478bd9Sstevel@tonic-gate case '%': /* there is no argument! */ 25017c478bd9Sstevel@tonic-gate continue; 25027c478bd9Sstevel@tonic-gate case 'l': 25037c478bd9Sstevel@tonic-gate if (flags & (FLAG_LONG | FLAG_LONG_LONG)) { 25047c478bd9Sstevel@tonic-gate flags |= FLAG_LONG_LONG; 25057c478bd9Sstevel@tonic-gate flags &= ~FLAG_LONG; 25067c478bd9Sstevel@tonic-gate } else { 25077c478bd9Sstevel@tonic-gate flags |= FLAG_LONG; 25087c478bd9Sstevel@tonic-gate } 25097c478bd9Sstevel@tonic-gate goto again; 25107c478bd9Sstevel@tonic-gate case 'j': 25117c478bd9Sstevel@tonic-gate #ifndef _LP64 25127c478bd9Sstevel@tonic-gate /* 25137c478bd9Sstevel@tonic-gate * *printf_c89() in 32-bit libc uses 25147c478bd9Sstevel@tonic-gate * 32-bit intmax_t; otherwise intmax_t 25157c478bd9Sstevel@tonic-gate * is 64-bits. 25167c478bd9Sstevel@tonic-gate */ 25177c478bd9Sstevel@tonic-gate if (!(prflag & _F_INTMAX32)) { 25187c478bd9Sstevel@tonic-gate #endif 25197c478bd9Sstevel@tonic-gate flags |= FLAG_LONG_LONG; /* 64-bit */ 25207c478bd9Sstevel@tonic-gate #ifndef _LP64 25217c478bd9Sstevel@tonic-gate } 25227c478bd9Sstevel@tonic-gate #endif 25237c478bd9Sstevel@tonic-gate goto again; 25247c478bd9Sstevel@tonic-gate case 't': 25257c478bd9Sstevel@tonic-gate flags |= FLAG_LONG; 25267c478bd9Sstevel@tonic-gate goto again; 25277c478bd9Sstevel@tonic-gate case 'z': 25287c478bd9Sstevel@tonic-gate flags |= FLAG_LONG; 25297c478bd9Sstevel@tonic-gate goto again; 25307c478bd9Sstevel@tonic-gate case 'L': 25317c478bd9Sstevel@tonic-gate flags |= FLAG_LONG_DBL; 25327c478bd9Sstevel@tonic-gate goto again; 25337c478bd9Sstevel@tonic-gate case '*': /* int argument used for value */ 25347c478bd9Sstevel@tonic-gate /* 25357c478bd9Sstevel@tonic-gate * check if there is a positional parameter; 25367c478bd9Sstevel@tonic-gate * if so, just skip it; its size will be 25377c478bd9Sstevel@tonic-gate * correctly determined by default 25387c478bd9Sstevel@tonic-gate */ 25397c478bd9Sstevel@tonic-gate if (_M_ISDIGIT(*fmt)) { 25407c478bd9Sstevel@tonic-gate fmt += STRSPN(fmt, digits); 25417c478bd9Sstevel@tonic-gate if (*fmt == '$') 25427c478bd9Sstevel@tonic-gate fmt++; /* skip '$' */ 25437c478bd9Sstevel@tonic-gate goto again; 25447c478bd9Sstevel@tonic-gate } 25457c478bd9Sstevel@tonic-gate flags |= FLAG_INT; 25467c478bd9Sstevel@tonic-gate (void) va_arg((*pargs).ap, int); 25477c478bd9Sstevel@tonic-gate break; 25487c478bd9Sstevel@tonic-gate case 'a': 25497c478bd9Sstevel@tonic-gate case 'A': 25507c478bd9Sstevel@tonic-gate case 'e': 25517c478bd9Sstevel@tonic-gate case 'E': 25527c478bd9Sstevel@tonic-gate case 'f': 25537c478bd9Sstevel@tonic-gate case 'F': 25547c478bd9Sstevel@tonic-gate case 'g': 25557c478bd9Sstevel@tonic-gate case 'G': 25567c478bd9Sstevel@tonic-gate if (flags & FLAG_LONG_DBL) 25577c478bd9Sstevel@tonic-gate (void) GETQVAL((*pargs).ap); 25587c478bd9Sstevel@tonic-gate else 25597c478bd9Sstevel@tonic-gate (void) va_arg((*pargs).ap, double); 25607c478bd9Sstevel@tonic-gate break; 25617c478bd9Sstevel@tonic-gate case 's': 25627c478bd9Sstevel@tonic-gate (void) va_arg((*pargs).ap, char *); 25637c478bd9Sstevel@tonic-gate break; 25647c478bd9Sstevel@tonic-gate case 'p': 25657c478bd9Sstevel@tonic-gate (void) va_arg((*pargs).ap, void *); 25667c478bd9Sstevel@tonic-gate break; 25677c478bd9Sstevel@tonic-gate case 'n': 25687c478bd9Sstevel@tonic-gate if (flags & FLAG_LONG_LONG) 25697c478bd9Sstevel@tonic-gate (void) va_arg((*pargs).ap, long long *); 25707c478bd9Sstevel@tonic-gate else if (flags & FLAG_LONG) 25717c478bd9Sstevel@tonic-gate (void) va_arg((*pargs).ap, long *); 25727c478bd9Sstevel@tonic-gate else 25737c478bd9Sstevel@tonic-gate (void) va_arg((*pargs).ap, int *); 25747c478bd9Sstevel@tonic-gate break; 25757c478bd9Sstevel@tonic-gate default: 25767c478bd9Sstevel@tonic-gate if (flags & FLAG_LONG_LONG) 25777c478bd9Sstevel@tonic-gate (void) va_arg((*pargs).ap, long long); 25787c478bd9Sstevel@tonic-gate else if (flags & FLAG_LONG) 25797c478bd9Sstevel@tonic-gate (void) va_arg((*pargs).ap, long int); 25807c478bd9Sstevel@tonic-gate else 25817c478bd9Sstevel@tonic-gate (void) va_arg((*pargs).ap, int); 25827c478bd9Sstevel@tonic-gate break; 25837c478bd9Sstevel@tonic-gate } 25847c478bd9Sstevel@tonic-gate i++; 25857c478bd9Sstevel@tonic-gate curargno++; /* default to next in list */ 25867c478bd9Sstevel@tonic-gate if (flags & FLAG_INT) /* took care of *, keep going */ 25877c478bd9Sstevel@tonic-gate { 25887c478bd9Sstevel@tonic-gate flags ^= FLAG_INT; 25897c478bd9Sstevel@tonic-gate goto again; 25907c478bd9Sstevel@tonic-gate } 25917c478bd9Sstevel@tonic-gate } 25927c478bd9Sstevel@tonic-gate 25937c478bd9Sstevel@tonic-gate /* missing specifier for parameter, assume param is an int */ 25947c478bd9Sstevel@tonic-gate if (!found && i != argno) { 25957c478bd9Sstevel@tonic-gate (void) va_arg((*pargs).ap, int); 25967c478bd9Sstevel@tonic-gate i++; 25977c478bd9Sstevel@tonic-gate curargno = i; 25987c478bd9Sstevel@tonic-gate found = 1; 25997c478bd9Sstevel@tonic-gate } 26007c478bd9Sstevel@tonic-gate } 26017c478bd9Sstevel@tonic-gate } 26027c478bd9Sstevel@tonic-gate 26037c478bd9Sstevel@tonic-gate #ifdef _WIDE 26047c478bd9Sstevel@tonic-gate static wchar_t * 26057c478bd9Sstevel@tonic-gate insert_thousands_sep(wchar_t *bp, wchar_t *ep) 26067c478bd9Sstevel@tonic-gate #else /* _WIDE */ 26077c478bd9Sstevel@tonic-gate static char * 26087c478bd9Sstevel@tonic-gate insert_thousands_sep(char *bp, char *ep) 26097c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 26107c478bd9Sstevel@tonic-gate { 26117c478bd9Sstevel@tonic-gate char thousep; 26127c478bd9Sstevel@tonic-gate struct lconv *locptr; 26137c478bd9Sstevel@tonic-gate ssize_t buf_index; 26147c478bd9Sstevel@tonic-gate int i; 26157c478bd9Sstevel@tonic-gate #ifdef _WIDE 26167c478bd9Sstevel@tonic-gate wchar_t *obp = bp; 26177c478bd9Sstevel@tonic-gate wchar_t buf[371]; 26187c478bd9Sstevel@tonic-gate wchar_t *bufptr = buf; 26197c478bd9Sstevel@tonic-gate #else /* _WIDE */ 26207c478bd9Sstevel@tonic-gate char *obp = bp; 26217c478bd9Sstevel@tonic-gate char buf[371]; 26227c478bd9Sstevel@tonic-gate char *bufptr = buf; 26237c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 26247c478bd9Sstevel@tonic-gate char *grp_ptr; 26257c478bd9Sstevel@tonic-gate 26267c478bd9Sstevel@tonic-gate /* get the thousands sep. from the current locale */ 26277c478bd9Sstevel@tonic-gate locptr = localeconv(); 26287c478bd9Sstevel@tonic-gate thousep = *locptr->thousands_sep; 26297c478bd9Sstevel@tonic-gate grp_ptr = locptr->grouping; 26307c478bd9Sstevel@tonic-gate 26317c478bd9Sstevel@tonic-gate /* thousands sep. not use in this locale or no grouping required */ 26327c478bd9Sstevel@tonic-gate if (!thousep || (*grp_ptr == '\0')) 26337c478bd9Sstevel@tonic-gate return (ep); 26347c478bd9Sstevel@tonic-gate 26357c478bd9Sstevel@tonic-gate buf_index = ep - bp; 26367c478bd9Sstevel@tonic-gate for (;;) { 26377c478bd9Sstevel@tonic-gate if (*grp_ptr == CHAR_MAX) { 26387c478bd9Sstevel@tonic-gate for (i = 0; i < buf_index--; i++) 26397c478bd9Sstevel@tonic-gate *bufptr++ = *(bp + buf_index); 26407c478bd9Sstevel@tonic-gate break; 26417c478bd9Sstevel@tonic-gate } 26427c478bd9Sstevel@tonic-gate for (i = 0; i < *grp_ptr && buf_index-- > 0; i++) 26437c478bd9Sstevel@tonic-gate *bufptr++ = *(bp + buf_index); 26447c478bd9Sstevel@tonic-gate 26457c478bd9Sstevel@tonic-gate if (buf_index > 0) { 26467c478bd9Sstevel@tonic-gate #ifdef _WIDE 26477c478bd9Sstevel@tonic-gate *bufptr++ = (wchar_t)thousep; 26487c478bd9Sstevel@tonic-gate #else /* _WIDE */ 26497c478bd9Sstevel@tonic-gate *bufptr++ = thousep; 26507c478bd9Sstevel@tonic-gate #endif /* _WIDE */ 26517c478bd9Sstevel@tonic-gate ep++; 26527c478bd9Sstevel@tonic-gate } 26537c478bd9Sstevel@tonic-gate else 26547c478bd9Sstevel@tonic-gate break; 26557c478bd9Sstevel@tonic-gate if (*(grp_ptr + 1) != '\0') 26567c478bd9Sstevel@tonic-gate ++grp_ptr; 26577c478bd9Sstevel@tonic-gate } 26587c478bd9Sstevel@tonic-gate 26597c478bd9Sstevel@tonic-gate /* put the string in the caller's buffer in reverse order */ 26607c478bd9Sstevel@tonic-gate --bufptr; 26617c478bd9Sstevel@tonic-gate while (buf <= bufptr) 26627c478bd9Sstevel@tonic-gate *obp++ = *bufptr--; 26637c478bd9Sstevel@tonic-gate return (ep); 26647c478bd9Sstevel@tonic-gate } 26657c478bd9Sstevel@tonic-gate 26667c478bd9Sstevel@tonic-gate 26677c478bd9Sstevel@tonic-gate /* 26687c478bd9Sstevel@tonic-gate * Recovery scrswidth function - 26697c478bd9Sstevel@tonic-gate * this variant of wcswidth() accepts non-printable or illegal 26707c478bd9Sstevel@tonic-gate * widechar characters. 26717c478bd9Sstevel@tonic-gate */ 26727c478bd9Sstevel@tonic-gate static int 26737c478bd9Sstevel@tonic-gate _rec_scrswidth(wchar_t *wp, ssize_t n) 26747c478bd9Sstevel@tonic-gate { 26757c478bd9Sstevel@tonic-gate int col; 26767c478bd9Sstevel@tonic-gate int i; 26777c478bd9Sstevel@tonic-gate 26787c478bd9Sstevel@tonic-gate col = 0; 26797c478bd9Sstevel@tonic-gate while (*wp && (n-- > 0)) { 26807c478bd9Sstevel@tonic-gate if ((i = _scrwidth(*wp++)) == 0) 26817c478bd9Sstevel@tonic-gate i = 1; 26827c478bd9Sstevel@tonic-gate col += i; 26837c478bd9Sstevel@tonic-gate } 26847c478bd9Sstevel@tonic-gate return (col); 26857c478bd9Sstevel@tonic-gate } 2686