/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
/*
* _doprnt: common code for printf, fprintf, sprintf
*/
#include "lint.h"
#include "mtlib.h"
#include "print.h" /* parameters & macros for doprnt */
#include <wchar.h>
#include "libc.h"
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include <stdarg.h>
#include <values.h>
#include <memory.h>
#include <string.h>
#include <locale.h>
#include <widec.h>
#include "../i18n/_locale.h"
#include <errno.h>
#include <libw.h>
#include "mse.h"
#include "xpg6.h"
#include "float.h"
#else /* !defined(__i386) && !defined(__sparcv9) */
#endif /* !defined(__i386) && !defined(__sparcv9) */
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
#ifdef _WIDE
#define PUT(p, n) \
{ \
int retp; \
} \
}
#define PAD(s, n) \
{ \
int retp; \
} \
}
{ \
char *cp; \
while (*cp) { \
} \
*wp = L'\0'; \
}
#else /* _WIDE */
#define PUT(p, n) \
{\
/*\
* When _doprnt() is called by [v]snprintf, we need to \
* always call _dowrite(). We also need to call _dowrite() \
* if the bufptr lies beyond the end of the buffer. This \
* is possible due to known off-by-one errors in __flsbuf() \
* and _fwrite_unlocked(). See 1235867 and 1231720 for the \
* sordid details. \
*/\
return (EOF);\
}\
} else {\
switch (n) {\
case 4:\
*fbp = *p;\
bufptr += 4;\
break;\
case 3:\
*fbp = *p;\
bufptr += 3;\
break;\
case 2:\
*fbp = *p;\
bufptr += 2;\
break;\
case 1:\
*bufptr++ = *p;\
break;\
default:\
+ (n);\
}\
}\
}
return (EOF); \
}
#endif /* _WIDE */
/* bit positions for flags used in doprnt */
#ifdef _WIDE
static wchar_t *
#else /* _WIDE */
static char *
#endif /* _WIDE */
/*
* Positional Parameter information
*/
static ssize_t
/*
* stva_list is used to subvert C's restriction that a variable with an
* array type can not appear on the left hand side of an assignment operator.
* By putting the array inside a structure, the functionality of assigning to
* the whole array through a simple assignment is achieved..
*/
typedef struct stva_list {
} stva_list;
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
static int
{
/* This function computes the decimal low-order digit of the number */
/* pointed to by valptr, and returns this digit after dividing */
/* *valptr by ten. This function is called ONLY to compute the */
/* low-order digit of a long whose high-order bit is set. */
return ((int)value);
}
static int
{
return ((int)value);
}
/* The function _dowrite carries out buffer pointer bookkeeping surrounding */
/* a call to fwrite. It is called only when the end of the file output */
/* buffer is approached or in other unusual situations. */
static ssize_t
{
return (0);
}
} else {
}
return (1);
}
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
#ifdef _WIDE
static int
{
unsigned char *newbufptr;
wchar_t *q;
int r;
if (sflag) {
if (n > len) {
return (EOF);
} else {
return (0);
}
} else {
return (EOF);
}
q = p;
for (len = 0, i = 0; i < n; i++) {
if (r == -1) {
return (EOF);
}
len += r;
tmpq += r;
}
return (EOF);
}
} else {
}
return (0);
}
}
static int
int sflag)
{
unsigned char *newbufptr;
if (sflag) {
/* for swprintf */
if (n > len) {
return (EOF);
} else {
return (0);
}
} else {
return (EOF);
}
return (EOF);
} else {
}
return (0);
}
}
#endif /* _WIDE */
#ifdef _WIDE
{
}
#else /* _WIDE */
{
}
#endif /* _WIDE */
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
{
#ifdef _WIDE
int sflag = 0;
void *lc;
#else
int snflag = 0;
#endif /* _WIDE */
/* bufptr is used inside of doprnt instead of iop->_ptr; */
/* bufferend is a copy of _bufend(iop), if it exists. For */
/* dummy file descriptors (iop->_flag & _IOREAD), bufferend */
/* may be meaningless. Dummy file descriptors are used so that */
/* sprintf and vsprintf may share the _doprnt routine with the */
/* rest of the printf family. */
unsigned char *bufptr;
unsigned char *bufferend;
#ifdef _WIDE
/* This variable counts output characters. */
#else /* _WIDE */
/* This variable counts output characters. */
int count = 0;
#endif /* _WIDE */
#ifdef _WIDE
wchar_t *p;
char *cbp;
char *cp;
#else /* _WIDE */
/* Starting and ending points for value to be printed */
char *bp;
char *p;
#endif /* _WIDE */
/* Field width and precision */
int prec = 0;
char wflag;
char lflag;
int retcode;
#ifdef _WIDE
/* Format code */
#else /* _WIDE */
/* Format code */
char fcode;
#endif /* _WIDE */
/* Number of padding zeroes required on the left and right */
/* Flags - bit positions defined by LENGTH, FPLUS, FMINUS, FBLANK, */
/* and FSHARP are set if corresponding character is in format */
/* Bit position defined by PADZERO means extra space in the field */
/* should be padded with leading zeroes rather than with blanks */
#ifdef _WIDE
/* Values are developed in this buffer */
/* Pointer to sign, "0x", "0X", or empty */
/* Exponent or empty */
/* Buffer to create exponent */
#else /* _WIDE */
/* Values are developed in this buffer */
/* Pointer to sign, "0x", "0X", or empty */
char *prefix;
/* Exponent or empty */
char *suffix;
/* Buffer to create exponent */
#endif /* _WIDE */
/* Length of prefix and of suffix */
/* Combined length of leading zeroes, trailing zeroes, and suffix */
/* The value being converted, if integer */
/* The value being converted, if long long */
/* Output value from aconvert */
int exp;
/* Output values from fcvt and ecvt */
#ifdef _WIDE
/* Pointer to a translate table for digits of whatever radix */
#else /* _WIDE */
/* Pointer to a translate table for digits of whatever radix */
const char *tab;
#endif /* _WIDE */
/* Work variables */
int inf_nan = 0;
int inf_nan_mixed_case = 0;
#ifdef _WIDE
/* variables for positional parameters */
/* save the beginning of the format */
#else /* _WIDE */
/* variables for positional parameters */
#endif
/* or precision */
/* for va_arg() to retrieve the */
/* corresponding argument: */
/* arglst[0] is the first arg */
/* arglst[1] is the second arg, etc */
/*
* Initialize args and sargs to the start of the argument list.
* We don't know any portable way to copy an arbitrary C object
* so we use a system-specific routine (probably a macro) from
* stdarg.h. (Remember that if va_list is an array, in_args will
* be a pointer and &in_args won't be what we would want for
* memcpy.)
*/
#ifdef _WIDE
sflag = 1;
if (!sflag) {
return (EOF);
}
#endif /* _WIDE */
/* if first I/O to the stream get a buffer */
/* Note that iop->_base should not equal 0 for sprintf and vsprintf */
return (EOF);
/* _findbuf leaves _cnt set to 0 which is the wrong thing to do */
/* for fully buffered files */
}
#ifdef _WIDE
}
#endif /* _WIDE */
#ifdef _WIDE
if (sflag) {
maxcount);
} else {
}
#else /* _WIDE */
/* initialize buffer pointer and buffer end pointer */
/*
* [v]sprintf or [v]snprintf
*/
/*
* [v]sprintf (no boundschecking)
*/
} else {
/*
* [v]snprintf (with boundschecking) or
* iop with _IORW has been read.
*/
/*
* [v]snprintf
*
* [v]snprint() needs to be always handled by
* _dowrite().
*/
snflag = 1;
}
}
} else {
/*
* [v]printf or [v]fprintf
*/
}
#endif /* _WIDE */
/*
* The main loop -- this loop goes through one iteration
* for each string of ordinary characters or format specification.
*/
for (; ; ) {
ssize_t n;
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
do {
format++;
}
#ifdef _WIDE
if (sflag) {
}
#endif /* _WIDE */
/* in case of interrupt during last several lines */
& _IOREAD))
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
}
/*
* % has been found.
* The following switch is used to parse the format
* specification and to perform the operation specified
* by the format letter. The program repeatedly goes
* back to this switch until the format letter is
* encountered.
*/
flagword = suffixlength = 0;
format++;
wflag = 0;
lflag = 0;
sec_display = 0;
quote = 0;
case '+':
goto charswitch;
case '-':
goto charswitch;
case ' ':
goto charswitch;
case '\'': /* XSH4 */
quote++;
goto charswitch;
case '#':
goto charswitch;
/* Scan the field width and precision */
case '.':
prec = 0;
goto charswitch;
case '*':
if (_M_ISDIGIT(*format)) {
starflg = 1;
goto charswitch;
}
if (width < 0) {
}
} else {
if (prec < 0) {
prec = 0;
}
}
goto charswitch;
case '$':
{
if (fpos) {
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
fpos = 0;
}
prec = 0;
} else {
width = 0;
}
if (position <= 0) {
/* illegal position */
format--;
continue;
}
} else {
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
}
if (!starflg)
else {
starflg = 0;
if (prec < 0) {
prec = 0;
}
} else {
if (width < 0) {
}
}
}
goto charswitch;
}
case '0': /* obsolescent spec: leading zero in width */
/* means pad with leading zeros */
/* FALLTHROUGH */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
format++;
}
else
goto charswitch;
}
/* Scan the length modifier */
case 'l':
if (lflag) {
/* long long */
} else {
/* long */
}
}
lflag++;
goto charswitch;
case 'L': /* long double */
goto charswitch;
case 'h':
/* char - hh */
} else {
/* short */
}
}
goto charswitch;
case 'j':
#ifndef _LP64
/*
* *printf_c89() in 32-bit libc uses
* 32-bit intmax_t; otherwise intmax_t
* is 64-bits.
*/
if (!(prflag & _F_INTMAX32)) {
#endif
#ifndef _LP64
}
#endif
goto charswitch;
case 't':
/*
* LENGTH is shared by l, t, z specifiers; protect
* against (destructive) undefined behavior (eg:
* avoid %llt setting XLONG and LENGTH) with invalid
* combinations of specifiers
*/
}
goto charswitch;
case 'z':
}
goto charswitch;
/*
* The character addressed by format must be
* the format letter -- there is nothing
* left for it to be.
*
* The status of the +, -, #, and blank
* flags are reflected in the variable
* "flagword". "width" and "prec" contain
* numbers corresponding to the digit
* strings before and after the decimal
* point, respectively. If there was no
* decimal point, then flagword & DOTSEEN
* is false and the value of prec is meaningless.
*
* The following switch cases set things up
* for printing. What ultimately gets
* printed will be padding blanks, a
* prefix, left padding zeroes, a value,
* right padding zeroes, a suffix, and
* more padding blanks. Padding blanks
* will not appear simultaneously on both
* the left and the right. Each case in
* this switch will compute the value, and
* leave in several variables the informa-
* tion necessary to construct what is to
* be printed.
*
* The prefix is a sign, a blank, "0x",
* "0X", a sign or a blank followed by "0x"
* or "0X", or nothing, and is addressed by
* "prefix".
*
* The suffix is either null or an
* exponent, and is addressed by "suffix".
* If there is a suffix, the flagword bit
* SUFFIX will be set.
*
* The value to be printed starts at "bp"
* and continues up to and not including
* "p".
*
* "lzero" and "rzero" will contain the
* number of padding zeroes required on
* the left and right, respectively.
* The flagword bits LZERO and RZERO tell
* whether padding zeros are required.
*
* The number of padding blanks, and
* whether they go on the left or the
* right, will be computed on exit from
* the switch.
*/
/*
* decimal fixed point representations
*
* HIBITL is 100...000
* binary, and is equal to the maximum
* negative number.
* We assume a 2's complement machine
*/
case 'i':
case 'd':
/* Set buffer pointer to last digit */
/* Fetch the argument to be printed */
/* If signed conversion, make sign */
if (ll < 0) {
prefixlength = 1;
/*
* Negate, checking in advance for
* possible overflow.
*/
else
/* number is -HIBITLL; convert last */
/* digit now and get positive number */
prefixlength = 1;
prefixlength = 1;
}
} else { /* not long long */
else
/* If signed conversion, make sign */
if (val < 0) {
prefixlength = 1;
/*
* Negate, checking in advance
* for possible overflow.
*/
/*
* number is -HIBITL; convert
* last digit now and get
* positive number
*/
else
prefixlength = 1;
prefixlength = 1;
}
}
{
long long tll;
if (lll < 10LL) {
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
} else {
do {
lll /= 10;
#ifdef _WIDE
#else /* _WIDE */
*--bp = (char) \
#endif /* _WIDE */
} while (lll >= 10);
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
}
} else {
if (qval <= 9) {
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
} else {
do {
n = qval;
qval /= 10;
#ifdef _WIDE
#else /* _WIDE */
*--bp = (char) \
#endif /* _WIDE */
} while (qval > 9);
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
}
}
}
/* Handle the ' flag */
if (quote) {
p = insert_thousands_sep(bp, p);
}
/* Calculate minimum padding zero requirement */
if (leadzeroes > 0) {
}
}
break;
case 'u':
/* Fetch the argument to be printed */
} else {
else
}
goto decimal;
/*
* non-decimal fixed point representations
* for radix equal to a power of two
*
* "mradix" is one less than the radix for the conversion.
* "lradix" is one less than the base 2 log
* of the radix for the conversion. Conversion is unsigned.
* HIBITL is 100...000
* binary, and is equal to the maximum
* negative number.
* We assume a 2's complement machine
*/
case 'o':
mradix = 7;
lradix = 2;
/*
* DR151 and clarification in C90
* presence of '#' increases precision to first
* digit of the result to be zero
*/
prec == 0)
prec = 1;
goto fixed;
case 'p':
/* FALLTHRU */
case 'X':
case 'x':
mradix = 15;
lradix = 3;
#ifdef _WIDE
/* Set translate table for digits */
#else /* _WIDE */
/* Set translate table for digits */
#endif /* _WIDE */
/* Fetch the argument to be printed */
} else {
else
}
/* Develop the digits of the value */
}
} else do {
>> lradix;
} else {
if (qval == 0) {
}
} else do {
>> lradix;
} while (qval != 0);
}
/* Calculate minimum padding zero requirement */
if (leadzeroes > 0) {
}
}
/* Handle the # flag, (val != 0) for int and long */
/* (ll!= 0) handles long long case */
switch (fcode) {
case 'o':
}
break;
case 'x':
prefixlength = 2;
break;
case 'X':
prefixlength = 2;
break;
}
break;
case 'A':
case 'a':
/* A format */
/* establish default precision */
#if defined(__sparc)
#else
#endif
cvtbuf);
} else {
/* establish default precision */
cvtbuf);
}
/*
* The following is wide-character safe because
* __aconvert and __qaconvert only produce ASCII
* characters.
*/
inf_nan = 1;
break;
}
/*
* Create the prefix. We ought to use the strings
* defined above (_P_HYPHEN, etc.), but that would
* be awkward: we'd either have to define six more
* assemble the ones already defined. So instead,
* we just build the prefix character by character.
*/
if (sign) {
*p++ = '-';
prefixlength = 1;
*p++ = '+';
prefixlength = 1;
*p++ = ' ';
prefixlength = 1;
}
*p++ = '0';
*p = '\0';
prefixlength += 2;
/* put the first digit in the buffer */
p = &buf[0];
/* put in a decimal point if needed */
*p++ = _numeric[0];
/* create the rest of the mantissa */
if (fcode == 'A') {
bp++;
}
} else {
*p++ = *bp++;
}
if (rz > 0) {
}
/*
* Create the exponent in right-to-left order.
* buf[0] == '0' if and only if the value being
* converted is exactly zero, in which case the
* exponent should be +0 regardless of exp.
*/
*suffix = '\0';
if (buf[0] != '0') {
int nn;
if (nn < 0)
} else {
*--suffix = '0';
*--suffix = '+';
}
/* put in the p */
/* compute size of suffix */
break;
case 'E':
case 'e':
/*
* E-format. The general strategy
* here is fairly easy: we take what
* econvert gives us and re-format it.
* (qeconvert for long double)
*/
/* Establish default precision */
prec = 6;
cvtbuf);
} else { /* double */
cvtbuf);
}
if (*bp > '9') {
inf_nan = 1;
inf_nan_mixed_case = (__xpg6 &
break;
}
/* Determine the prefix */
if (sign) {
prefixlength = 1;
prefixlength = 1;
prefixlength = 1;
}
/* Place the first digit in the buffer */
p = &buf[0];
/* Put in a decimal point if needed */
*p++ = _numeric[0];
/* Create the rest of the mantissa */
*p++ = *bp++;
if (rz > 0) {
}
/*
* Create the exponent. buf[0] == '0' if and
* only if the value being converted is exactly
* zero, in which case the exponent should be
* +0 regardless of decpt.
*/
if (buf[0] != '0') {
if (nn < 0)
}
/* Prepend leading zeroes to the exponent */
*--suffix = '0';
/* Put in the exponent sign */
/* Put in the e */
/* compute size of suffix */
- suffix);
break;
case 'F':
case 'f':
/*
* F-format floating point. This is a
* good deal less simple than E-format.
* The overall strategy will be to call
* fconvert, reformat its result into buf,
* and calculate how many trailing
* zeroes will be required. There will
* never be any leading zeroes needed.
* (qfconvert for long double)
*/
/* Establish default precision */
prec = 6;
if (*bp == 0) {
/*
* qfconvert would have required
* too many characters; use qeconvert
* instead
*/
goto e_merge;
}
} else { /* double */
}
if (*bp > '9') {
inf_nan = 1;
if (fcode == 'f')
inf_nan_mixed_case = (__xpg6 &
break;
}
/* Determine the prefix */
if (sign) {
prefixlength = 1;
prefixlength = 1;
prefixlength = 1;
}
/* Initialize buffer pointer */
p = &buf[0];
{
/* Emit the digits before the decimal point */
k = 0;
do {
} while (--nn > 0);
if (quote)
p = insert_thousands_sep(buf, p);
/* Decide whether we need a decimal point */
*p++ = _numeric[0];
/* Digits (if any) after the decimal point */
}
while (--nn >= 0)
}
break;
case 'G':
case 'g':
/*
* g-format. We play around a bit
* and then jump into e or f, as needed.
*/
/* Establish default precision */
prec = 6;
else if (prec == 0)
prec = 1;
} else { /* double */
}
if (*bp > '9') {
inf_nan = 1;
inf_nan_mixed_case = (__xpg6 &
break;
}
decpt = 1;
{
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
if (n < kk)
kk = (int)n;
--kk;
}
goto e_merge;
}
goto f_merge;
}
case '%':
goto c_merge;
#ifndef _WIDE
case 'w':
wflag = 1;
goto charswitch;
#endif /* _WIDE */
case 'C': /* XPG XSH4 extention */
{
#ifdef _WIDE
if (temp) {
} else {
buf[0] = 0;
}
wcount = 1;
wflag = 1;
#else /* _WIDE */
if (temp) {
== -1) {
return (EOF);
} else {
}
} else { /* NULL character */
buf[0] = 0;
}
#endif /* _WIDE */
}
break;
case 'c':
if (lflag) {
goto wide_C;
}
#ifndef _WIDE
if (wflag) {
if (temp) {
== -1) {
} else {
}
} else { /* NULL character */
buf[0] = 0;
}
} else {
#endif /* _WIDE */
long long temp;
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
} else
#ifdef _WIDE
wcount = 1;
wflag = 1;
#endif /* _WIDE */
#ifndef _WIDE
}
#endif /* _WIDE */
break;
case 'S': /* XPG XSH4 extention */
#ifdef _WIDE
if (!lflag) {
lflag++;
}
/* wide character handling */
}
wcount = 0;
while (*wp) {
wcount++;
wp++;
} else {
break;
}
}
p = wp;
wflag = 1;
break;
#else /* _WIDE */
if (!wflag)
wflag++;
bp = (char *)widenullstr;
/* wide character handling */
}
wcount = 0;
while (*wp) {
int nbytes;
if (nbytes < 0) {
return (EOF);
}
wp++;
} else {
break;
}
}
p = (char *)wp;
break;
#endif /* _WIDE */
case 's':
if (lflag) {
goto wide_S;
}
#ifdef _WIDE
return (EOF);
}
return (EOF);
}
} else {
return (EOF);
}
return (EOF);
}
} else {
int len;
char *s;
return (EOF);
}
}
}
wflag = 1;
#else /* _WIDE */
if (wflag) {
/* wide character handling */
goto wide_hand;
}
/*
* sec_display only needed if width
* is specified (ie, "%<width>s")
* Solaris behavior counts <width> in
* screen column width. (If XPG4 behavior,
* <width> is counted in bytes.)
*/
MB_CUR_MAX > 1) {
/* Estimate width */
goto mbs_err;
}
} else {
/*
* If widechar does not fit into
* wbuff, allocate larger buffer
*/
if ((nwc =
(size_t)-1) {
goto mbs_err;
}
sizeof (wchar_t);
== NULL) {
return (EOF);
}
sec_display = \
goto mbs_err;
}
}
== -1) {
}
if (wp)
}
} else { /* a strnlen function would be useful here! */
/*
* If we've seen a dot, and count has been set
* to 0, then we don't output in any cases
* below. prec should be always >= 0. So we only
* check to see if it's zero.
*/
if (prec == 0) {
p = bp;
break;
}
if (wflag) {
/* wide character handling */
wcount = 0;
while (*wp &&
if ((retcode =
wcount++;
else
wp++;
}
if (*wp)
p = (char *)wp;
/*
* Solaris behavior - count
* precision as screen column width
*/
ncol = 0;
while (*qp) {
qp++;
if (--prec == 0)
break;
continue;
}
MB_LEN_MAX)) == -1) {
/* print illegal char */
nbytes = 1;
ncol = 1;
} else {
if ((ncol =
== 0) {
ncol = 1;
}
}
if (prec == 0)
break;
} else {
break;
}
}
if (prec < 0)
p = qp;
} else {
/*
* XPG4 behavior - count
* precision as bytes.
* We don't use strlen() because
* the given char string may not
* be null-terminated.
*/
char *qp;
} else {
p = qp;
}
}
}
#endif /* _WIDE */
break;
case 'n':
{
long long *svcount;
long *svcount;
short *svcount;
char *svcount;
} else {
int *svcount;
}
continue;
}
default: /* this is technically an error; what we do is to */
/* back up the format pointer to the offending char */
/* and continue with the format scan */
format--;
continue;
}
if (inf_nan) {
if (inf_nan_mixed_case) {
/* advance p */
;
} else {
int upper;
/* advance p and make output all one case */
for (p = bp; *p != '\0'; p++)
}
if (sign) {
prefixlength = 1;
prefixlength = 1;
prefixlength = 1;
}
inf_nan = 0;
inf_nan_mixed_case = 0;
}
/* Calculate number of padding blanks */
n = p - bp; /* n == size of the converted value (in bytes) */
#ifdef _WIDE
k = n;
#else /* _WIDE */
if (sec_display) /* when format is %s or %ws or %S */
k = sec_display;
else
k = n;
#endif /* _WIDE */
/*
* k is the (screen) width or # of bytes of the converted value
*/
k += prefixlength + otherlength;
#ifdef _WIDE
if (wflag) {
} else {
count += n;
}
#else /* _WIDE */
/*
* update count which is the overall size of the output data
* and passed to memchr()
*/
if (wflag)
/*
* when wflag != 0 (i.e. %ws or %wc), the size of the
* converted value is wcount bytes
*/
else
/*
* when wflag == 0, the size of the converted
* value is n (= p-bp) bytes
*/
count += n;
#endif /* _WIDE */
if (width > k) {
/*
* Set up for padding zeroes if requested
* Otherwise emit padding blanks unless output is
* to be left-justified.
*/
} else
k = width; /* cancel padding blanks */
} else
/* Blanks on left if required */
}
/* Prefix, if any */
if (prefixlength != 0)
/* Zeroes on the left */
/* (!(flagword & SHORT) || !(flagword & FMINUS)) */
#ifdef _WIDE
if (n > 0)
if (bp)
}
#else /* _WIDE */
/* The value itself */
/* wide character handling */
int cnt;
char *bufp;
long printn;
while (printn > 0) {
cnt = 1;
wp++;
printn--;
}
} else { /* non wide character value */
if (n > 0)
}
#endif /* _WIDE */
/* Zeroes on the right */
/* The suffix */
/* Blanks on the right if required */
}
}
}
#ifdef _WIDE
static int
{
int n = 0;
if (_M_ISDIGIT(ch)) {
n = ch - '0';
while (_M_ISDIGIT(ch)) {
n *= 10;
n += ch - '0';
}
}
return (n);
}
#endif /* _WIDE */
/*
* This function initializes arglst, to contain the appropriate va_list values
* for the first MAXARGS arguments.
*/
/*
* Type modifier flags:
* 0x01 for long
* 0x02 for int
* 0x04 for long long
* 0x08 for long double
*/
/* ARGSUSED3 */
#ifdef _WIDE
static void
#else /* _WIDE */
static void
#endif /* _WIDE */
{
#ifdef _WIDE
#else /* _WIDE */
static const char digits[] = "01234567890";
static const char skips[] = "# +-.'0123456789h$";
#endif /* _WIDE */
ssize_t n;
/*
* Algorithm 1. set all argument types to zero.
* 2. walk through fmt putting arg types in typelst[].
* 3. walk through args using va_arg(args.ap, typelst[n])
* and set arglst[] to the appropriate values.
* Assumptions: Cannot use %*$... to specify variable position.
*/
maxnum = -1;
curargno = 0;
fmt++; /* skip % */
/* convert to zero base */
if (curargno < 0)
continue;
fmt += n + 1;
}
flags = 0;
again:;
switch (*fmt++) {
case '%': /* there is no argument! */
continue;
case 'l':
flags |= FLAG_LONG_LONG;
} else {
}
goto again;
case 'j':
#ifndef _LP64
/*
* *printf_c89() in 32-bit libc uses
* 32-bit intmax_t; otherwise intmax_t
* is 64-bits.
*/
if (!(prflag & _F_INTMAX32)) {
#endif
#ifndef _LP64
}
#endif
goto again;
case 't':
goto again;
case 'z':
goto again;
case 'L':
flags |= FLAG_LONG_DBL;
goto again;
case '*': /* int argument used for value */
/* check if there is a positional parameter */
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
{
int targno;
if (*fmt == '$')
fmt++; /* skip '$' */
}
goto again;
}
break;
case 'a':
case 'A':
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
if (flags & FLAG_LONG_DBL)
else
break;
case 's':
break;
case 'p':
break;
case 'n':
if (flags & FLAG_LONG_LONG)
else
break;
default:
if (flags & FLAG_LONG_LONG)
else
break;
}
}
curargno++; /* default to next in list */
{
goto again;
}
}
for (n = 0; n <= maxnum; n++) {
if (typelst[n] == 0)
switch (typelst[n]) {
case INT:
break;
case LONG:
break;
case CHAR_PTR:
break;
case DOUBLE:
break;
case LONG_DOUBLE:
break;
case VOID_PTR:
break;
case LONG_PTR:
break;
case INT_PTR:
break;
case LONG_LONG:
break;
case LONG_LONG_PTR:
break;
}
}
}
/*
* This function is used to find the va_list value for arguments whose
* position is greater than MAXARGS. This function is slow, so hopefully
* MAXARGS will be big enough so that this function need only be called in
* unusual circumstances.
* pargs is assumed to contain the value of arglst[MAXARGS - 1].
*/
/* ARGSUSED3 */
#ifdef _WIDE
static void
#else /* _WIDE */
void
#endif /* _WIDE */
{
#ifdef _WIDE
#else /* _WIDE */
static const char digits[] = "01234567890";
static const char skips[] = "# +-.'0123456789h$";
#endif /* _WIDE */
ssize_t n;
i = MAXARGS;
curargno = 1;
while (found) {
found = 0;
fmt++; /* skip % */
if (curargno <= 0)
continue;
fmt += n + 1;
}
/* find conversion specifier for next argument */
if (i != curargno) {
curargno++;
continue;
} else
found = 1;
flags = 0;
again:;
switch (*fmt++) {
case '%': /* there is no argument! */
continue;
case 'l':
flags |= FLAG_LONG_LONG;
} else {
}
goto again;
case 'j':
#ifndef _LP64
/*
* *printf_c89() in 32-bit libc uses
* 32-bit intmax_t; otherwise intmax_t
* is 64-bits.
*/
if (!(prflag & _F_INTMAX32)) {
#endif
#ifndef _LP64
}
#endif
goto again;
case 't':
goto again;
case 'z':
goto again;
case 'L':
flags |= FLAG_LONG_DBL;
goto again;
case '*': /* int argument used for value */
/*
* check if there is a positional parameter;
* if so, just skip it; its size will be
* correctly determined by default
*/
if (_M_ISDIGIT(*fmt)) {
if (*fmt == '$')
fmt++; /* skip '$' */
goto again;
}
break;
case 'a':
case 'A':
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
if (flags & FLAG_LONG_DBL)
else
break;
case 's':
break;
case 'p':
break;
case 'n':
if (flags & FLAG_LONG_LONG)
else
break;
default:
if (flags & FLAG_LONG_LONG)
else
break;
}
i++;
curargno++; /* default to next in list */
{
goto again;
}
}
/* missing specifier for parameter, assume param is an int */
i++;
curargno = i;
found = 1;
}
}
}
#ifdef _WIDE
static wchar_t *
#else /* _WIDE */
static char *
#endif /* _WIDE */
{
char thousep;
int i;
/*
* buf size should be calculated on the basis of *grp_ptr which
* is 3 for most countries but few have separators at 2 as well
* thus buf size should be able to contain maximum possible number
* as well as the separator character. Currently we don't support
* quad word so this size is DBL_MAX_10_EXP + (DBL_MAX_10_EXP / 2).
* With the support of quad words it should be changed.
*/
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
char *grp_ptr;
/* get the thousands sep. from the current locale */
locptr = localeconv();
/* thousands sep. not use in this locale or no grouping required */
return (ep);
for (;;) {
for (i = 0; i < buf_index--; i++)
break;
}
if (buf_index > 0) {
#ifdef _WIDE
#else /* _WIDE */
#endif /* _WIDE */
ep++;
}
else
break;
++grp_ptr;
}
/* put the string in the caller's buffer in reverse order */
--bufptr;
return (ep);
}
/*
* Recovery scrswidth function -
* this variant of wcswidth() accepts non-printable or illegal
* widechar characters.
*/
static int
{
int col;
int i;
col = 0;
while (*wp && (n-- > 0)) {
i = 1;
col += i;
}
return (col);
}