mirror of
https://github.com/LIV2/libnix.git
synced 2025-12-06 00:23:08 +00:00
add swprintf and vswprintf
This commit is contained in:
parent
4c900dc9d0
commit
fa23696515
34
sources/nix/stdio/__ulldivus.c
Normal file
34
sources/nix/stdio/__ulldivus.c
Normal file
@ -0,0 +1,34 @@
|
||||
unsigned __ulldivus(unsigned long long * llp, unsigned short n) {
|
||||
struct LL {
|
||||
unsigned long hi;
|
||||
union {
|
||||
unsigned long lo;
|
||||
struct {
|
||||
unsigned short exponent;
|
||||
unsigned short y;
|
||||
} s;
|
||||
} u;
|
||||
}* hl = (struct LL *) llp;
|
||||
|
||||
unsigned r;
|
||||
unsigned long h = hl->hi;
|
||||
if (h) {
|
||||
unsigned l = hl->u.s.exponent;
|
||||
unsigned k = hl->u.s.y;
|
||||
unsigned c = h % n;
|
||||
h = h / n;
|
||||
l = l + (c << 16);
|
||||
c = l % n;
|
||||
l = l / n;
|
||||
k = k + (c << 16);
|
||||
r = k % n;
|
||||
k = k / n;
|
||||
hl->u.lo = (l << 16) + k;
|
||||
hl->hi = h + (l >> 16);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = hl->u.lo % n;
|
||||
hl->u.lo /= n;
|
||||
return r;
|
||||
}
|
||||
@ -107,40 +107,7 @@ static int ___vfprintf_total_size(FILE *stream, const char *format,
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned __ulldivus(unsigned long long * llp, unsigned short n) {
|
||||
struct LL {
|
||||
unsigned long hi;
|
||||
union {
|
||||
unsigned long lo;
|
||||
struct {
|
||||
unsigned short exponent;
|
||||
unsigned short y;
|
||||
} s;
|
||||
} u;
|
||||
}* hl = (struct LL *) llp;
|
||||
|
||||
unsigned r;
|
||||
unsigned long h = hl->hi;
|
||||
if (h) {
|
||||
unsigned l = hl->u.s.exponent;
|
||||
unsigned k = hl->u.s.y;
|
||||
unsigned c = h % n;
|
||||
h = h / n;
|
||||
l = l + (c << 16);
|
||||
c = l % n;
|
||||
l = l / n;
|
||||
k = k + (c << 16);
|
||||
r = k % n;
|
||||
k = k / n;
|
||||
hl->u.lo = (l << 16) + k;
|
||||
hl->hi = h + (l >> 16);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = hl->u.lo % n;
|
||||
hl->u.lo /= n;
|
||||
return r;
|
||||
}
|
||||
extern unsigned __ulldivus(unsigned long long * llp, unsigned short n);
|
||||
|
||||
/**
|
||||
* Differs from vfprintf such that it returns total number of bytes that
|
||||
|
||||
718
sources/nix/stdio/__vwfprintf_total_size.c
Normal file
718
sources/nix/stdio/__vwfprintf_total_size.c
Normal file
@ -0,0 +1,718 @@
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include "stdio.h"
|
||||
|
||||
// a union to handle the
|
||||
union _d_bits {
|
||||
double d;
|
||||
struct {
|
||||
unsigned sign :1;
|
||||
unsigned exp :11;
|
||||
unsigned frac0 :20;
|
||||
unsigned frac1 :32;
|
||||
} b;
|
||||
unsigned u;
|
||||
};
|
||||
|
||||
#ifdef FULL_SPECIFIERS
|
||||
extern unsigned char *__decimalpoint;
|
||||
#endif
|
||||
|
||||
extern int __vwfprintf_total_size(FILE *stream, const wchar_t *fmt, va_list args);
|
||||
|
||||
/* a little macro to make life easier */
|
||||
|
||||
#define OUT(c) do { \
|
||||
putc((c >> 24),stream); \
|
||||
putc((c >> 16),stream); \
|
||||
putc((c >> 8),stream); \
|
||||
putc((c ),stream); \
|
||||
outcount += 4; \
|
||||
}while(0)
|
||||
|
||||
#define MINFLOATSIZE (DBL_DIG+3)
|
||||
#define MININTSIZE (sizeof(unsigned long long)*CHAR_BIT/3+1)
|
||||
#define MINPOINTSIZE (sizeof(void *)*CHAR_BIT/4+1)
|
||||
#define REQUIREDBUFFER (MININTSIZE>MINPOINTSIZE? \
|
||||
(MININTSIZE>MINFLOATSIZE?MININTSIZE:MINFLOATSIZE): \
|
||||
(MINPOINTSIZE>MINFLOATSIZE?MINPOINTSIZE:MINFLOATSIZE))
|
||||
|
||||
/**
|
||||
* '#'
|
||||
* Used with o, exponent or X specifiers the value is preceeded with 0, 0x or 0X
|
||||
* respectively for values different than zero.
|
||||
* Used with a, A, e, E, f, F, g or G it forces the written output
|
||||
* to contain a decimal point even if no more digits follow.
|
||||
* By default, if no digits follow, no decimal point is written.
|
||||
*/
|
||||
#define ALTERNATEFLAG 1 /* '#' is set */
|
||||
|
||||
/**
|
||||
* '0'
|
||||
* Left-pads the number with zeroes (0) instead of spaces when padding is specified
|
||||
* (see width sub-specifier).
|
||||
*/
|
||||
#define ZEROPADFLAG 2 /* '0' is set */
|
||||
|
||||
/**
|
||||
* '-'
|
||||
* Left-justify within the given field width;
|
||||
* Right justification is the default (see width sub-specifier).
|
||||
*/
|
||||
#define LALIGNFLAG 4 /* '-' is set */
|
||||
|
||||
/**
|
||||
* ' '
|
||||
* If no sign is going to be written, a blank space is inserted before the value.
|
||||
*/
|
||||
#define BLANKFLAG 8 /* ' ' is set */
|
||||
|
||||
/**
|
||||
* '+'
|
||||
* Forces to preceed the result with a plus or minus sign (+ or -) even for positive numbers.
|
||||
* By default, only negative numbers are preceded with a - sign.
|
||||
*/
|
||||
#define SIGNFLAG 16 /* '+' is set */
|
||||
|
||||
static const char flagc[] = { '#', '0', '-', ' ', '+' };
|
||||
|
||||
/**
|
||||
* Set if an explicit precision is given.
|
||||
*/
|
||||
#define HAS_PRECI 32
|
||||
|
||||
|
||||
extern unsigned __ulldivus(unsigned long long * llp, unsigned short n);
|
||||
|
||||
/**
|
||||
* Differs from vfprintf such that it returns total number of bytes that
|
||||
* would've been written if there were sufficient space in file.
|
||||
* Required for vsnprintf
|
||||
*/
|
||||
int __vwfprintf_total_size(FILE *stream, const wchar_t *format, va_list args) {
|
||||
size_t outcount = 0;
|
||||
|
||||
__STDIO_LOCK(stream);
|
||||
|
||||
// /* optimize unbuffered write-only files */
|
||||
// if ((stream->_flags & (__SWO | __SNBF)) == (__SWO | __SNBF)) {
|
||||
// return ___vfprintf_total_size(stream, format, args);
|
||||
// }
|
||||
|
||||
while (*format) {
|
||||
if (*format == '%') {
|
||||
static const char lowertabel[] = { '0', '1', '2', '3', '4', '5',
|
||||
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
static const char uppertabel[] = { '0', '1', '2', '3', '4', '5',
|
||||
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
short width = 0;
|
||||
unsigned short preci = 0x7fff;
|
||||
short flags = 0; /* Specifications */
|
||||
char type, subtype = 'i';
|
||||
char buffer1[2]; /* Signs and that like */
|
||||
char buffer[REQUIREDBUFFER]; /* The body */
|
||||
char *buffer2 = buffer; /* So we can set this to any other strings */
|
||||
size_t size1 = 0, size2 = 0; /* How many chars in buffer? */
|
||||
const wchar_t *ptr = format + 1; /* pointer to format string */
|
||||
unsigned short i, pad; /* Some temporary variables */
|
||||
|
||||
do /* read flags */
|
||||
for (i = 0; i < sizeof(flagc); i++)
|
||||
if (flagc[i] == *ptr) {
|
||||
flags |= 1 << i;
|
||||
ptr++;
|
||||
break;
|
||||
} while (i < sizeof(flagc));
|
||||
|
||||
if (*ptr == '*') /* read width from arguments */
|
||||
{
|
||||
signed int a;
|
||||
ptr++;
|
||||
a = va_arg(args, signed int);
|
||||
if (a < 0) {
|
||||
flags |= LALIGNFLAG;
|
||||
width = -a;
|
||||
} else
|
||||
width = a;
|
||||
} else {
|
||||
while (isdigit(*ptr))
|
||||
width = width * 10 + (*ptr++ - '0');
|
||||
}
|
||||
|
||||
if (*ptr == '.') {
|
||||
flags |= HAS_PRECI;
|
||||
ptr++;
|
||||
if (*ptr == '*') /* read precision from arguments */
|
||||
{
|
||||
signed int a;
|
||||
ptr++;
|
||||
a = va_arg(args, signed int);
|
||||
if (a >= 0)
|
||||
preci = a;
|
||||
} else {
|
||||
preci = 0;
|
||||
while (isdigit(*ptr))
|
||||
preci = preci * 10 + (*ptr++ - '0');
|
||||
}
|
||||
}
|
||||
|
||||
if (*ptr == 'h' || *ptr == 'l' || *ptr == 'L' || *ptr == 'j'
|
||||
|| *ptr == 'z' || *ptr == 't') {
|
||||
subtype = *ptr++;
|
||||
if (*ptr == 'h' || *ptr == 'l')
|
||||
++ptr, ++subtype;
|
||||
} else
|
||||
subtype = 0;
|
||||
|
||||
type = *ptr++;
|
||||
|
||||
switch (type) {
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X': {
|
||||
unsigned long long v;
|
||||
const char *tabel;
|
||||
int base;
|
||||
|
||||
if (type == 'p') {
|
||||
subtype = 'l'; /* This is written as %#lx */
|
||||
type = 'x';
|
||||
flags |= ALTERNATEFLAG;
|
||||
}
|
||||
|
||||
if (type == 'd' || type == 'i') /* These are signed */
|
||||
{
|
||||
signed long long v2;
|
||||
if (subtype == 'l')
|
||||
v2 = va_arg(args, signed long);
|
||||
else if (subtype == 'm' || subtype == 'j')
|
||||
v2 = va_arg(args, signed long long);
|
||||
else
|
||||
v2 = va_arg(args, signed int);
|
||||
if (subtype == 'h')
|
||||
v2 &= 0xffff;
|
||||
else if (subtype == 'i')
|
||||
v2 &= 0xff;
|
||||
if (v2 < 0 || (subtype == 'h' && (short)v2 < 0) || (subtype == 'i' && (char)v2 < 0)) {
|
||||
buffer1[size1++] = '-';
|
||||
v = -v2;
|
||||
} else {
|
||||
if (flags & SIGNFLAG)
|
||||
buffer1[size1++] = '+';
|
||||
else if (flags & BLANKFLAG)
|
||||
buffer1[size1++] = ' ';
|
||||
v = v2;
|
||||
}
|
||||
} else /* These are unsigned */
|
||||
{
|
||||
if (subtype == 'l')
|
||||
v = va_arg(args, unsigned long);
|
||||
else if (subtype == 'm' || subtype == 'j')
|
||||
v = va_arg(args, unsigned long long);
|
||||
else
|
||||
v = va_arg(args, unsigned int);
|
||||
if (subtype == 'h')
|
||||
v &= 0xffff;
|
||||
else if (subtype == 'i')
|
||||
v &= 0xff;
|
||||
if (flags & ALTERNATEFLAG) {
|
||||
if (type == 'o') {
|
||||
if (!preci || v)
|
||||
buffer1[size1++] = '0';
|
||||
} else if ((type == 'x' || type == 'X') && v) {
|
||||
buffer1[size1++] = '0';
|
||||
buffer1[size1++] = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buffer2 = &buffer[sizeof(buffer)]; /* Calculate body string */
|
||||
base = type == 'x' || type == 'X' ? 16 : (type == 'o' ? 8 : 10);
|
||||
tabel = type != 'X' ? lowertabel : uppertabel;
|
||||
do {
|
||||
*--buffer2 = tabel[__ulldivus(&v, base)];
|
||||
size2++;
|
||||
} while (v);
|
||||
if (preci == 0x7fff) /* default */
|
||||
preci = 0;
|
||||
else
|
||||
flags &= ~ZEROPADFLAG;
|
||||
break;
|
||||
}
|
||||
case 'c':
|
||||
if (subtype == 'l')
|
||||
*buffer2 = va_arg(args, long);
|
||||
else
|
||||
*buffer2 = va_arg(args, int);
|
||||
size2 = 1;
|
||||
preci = 0;
|
||||
break;
|
||||
case 's':
|
||||
buffer2 = va_arg(args, char *);
|
||||
size2 = strlen(buffer2);
|
||||
size2 = size2 <= preci ? size2 : preci;
|
||||
preci = 0;
|
||||
break;
|
||||
|
||||
#ifdef FULL_SPECIFIERS
|
||||
|
||||
|
||||
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'f':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G': {
|
||||
union _d_bits d;
|
||||
short exponent = 0;
|
||||
char sign = 0;
|
||||
const char * infnan = 0;
|
||||
char pad = (flags & ZEROPADFLAG) ? '0' : ' ';
|
||||
|
||||
if (type == 'f' || type == 'F')
|
||||
type = 0;
|
||||
|
||||
d = va_arg(args, union _d_bits);
|
||||
|
||||
// check for negative number and set the sign char if necessary
|
||||
if (d.b.sign) {
|
||||
d.b.sign = 0;
|
||||
sign = '-';
|
||||
} else if (flags & SIGNFLAG)
|
||||
sign = '+';
|
||||
else if (flags & BLANKFLAG)
|
||||
sign = ' ';
|
||||
|
||||
// check for inf/nan
|
||||
if (d.b.exp == 0x7ff) {
|
||||
if (d.b.frac0 || d.b.frac1) {
|
||||
infnan = "NaN";
|
||||
sign = 0;
|
||||
} else {
|
||||
infnan = "inf";
|
||||
}
|
||||
width -= 3;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
short pos;
|
||||
unsigned x, y;
|
||||
|
||||
// count of digts:
|
||||
// f, F : all digits before dot, preci digits behind. = 1 + preci, add exponent if > 0
|
||||
// e, E : one digit before dot, preci digits behind dot = 1 + preci
|
||||
// g, G : preci digits total
|
||||
int startPos = 1; // first digit
|
||||
short stopPos; // behind last digit
|
||||
short leading = 1; // digits until dot is inserted
|
||||
short dotZero = 0; // insert zeroes after dot
|
||||
short postZero = 0; // append zeroes at end
|
||||
short killZero = 0; // kill trailing zeroes
|
||||
|
||||
// real number
|
||||
if (!infnan) {
|
||||
if (type != 'a' && type != 'A') {
|
||||
|
||||
if (preci == 0x7fff) /* old default */
|
||||
preci = 6; /* new default */
|
||||
stopPos = preci + 1;
|
||||
|
||||
// compute exponent - a tad slow but ok
|
||||
if (d.u || d.b.frac1) {
|
||||
if (d.d >= 1) {
|
||||
while (d.d >= 10000000000) {
|
||||
d.d *= 0.0000000001;
|
||||
exponent += 10;
|
||||
}
|
||||
while (d.d >= 10) {
|
||||
d.d *= 0.1;
|
||||
++exponent;
|
||||
}
|
||||
} else {
|
||||
while (d.d < 0.0000000001) {
|
||||
d.d *= 10000000000;
|
||||
exponent -= 10;
|
||||
}
|
||||
while (d.d < 1) {
|
||||
d.d *= 10;
|
||||
--exponent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ((int) d.d > 9) {
|
||||
d.d /= 10;
|
||||
++exponent;
|
||||
}
|
||||
|
||||
// convert g into e or f
|
||||
if (type == 'g' || type == 'G') {
|
||||
int limit = preci + 4;
|
||||
--preci;
|
||||
if (preci >= exponent && exponent >= 0) {
|
||||
type = 0;
|
||||
preci -= exponent;
|
||||
} else if (exponent < 0
|
||||
&& limit + exponent + 1 > preci) {
|
||||
type = 0;
|
||||
preci -= exponent;
|
||||
} else {
|
||||
type = 'e';
|
||||
}
|
||||
stopPos = preci + 1;
|
||||
if (!(flags & ALTERNATEFLAG))
|
||||
killZero = 1;
|
||||
}
|
||||
|
||||
// fill it with digits
|
||||
buffer[0] = '0';
|
||||
pos = 1;
|
||||
if (type == 0) { // f, F
|
||||
if (exponent >= 0) {
|
||||
leading += exponent;
|
||||
stopPos += exponent + 1;
|
||||
} else {
|
||||
dotZero = -exponent - 1;
|
||||
buffer[1] = '0';
|
||||
if (dotZero > preci) {
|
||||
dotZero = preci;
|
||||
buffer[2] = '0'; // mandatory - uninitialized values may break rounding
|
||||
pos = 3;
|
||||
} else
|
||||
pos = 2;
|
||||
stopPos -= dotZero - 1;
|
||||
}
|
||||
} else {
|
||||
++stopPos; // add one for leading digit
|
||||
}
|
||||
if (stopPos >= REQUIREDBUFFER) {
|
||||
postZero = stopPos - REQUIREDBUFFER + 1;
|
||||
if (type == 0 && postZero > preci)
|
||||
postZero = preci;
|
||||
stopPos = REQUIREDBUFFER - 1;
|
||||
}
|
||||
|
||||
// compute the digits + one more for rounding
|
||||
for (; pos < stopPos; ++pos) {
|
||||
int z = (int) d.d;
|
||||
if (z) {
|
||||
d.d = (d.d - z) * 10;
|
||||
if (d.d <= -0.1) {
|
||||
--z;
|
||||
d.d += 10;
|
||||
}
|
||||
} else
|
||||
d.d *= 10;
|
||||
buffer[pos] = (char) ('0' + z);
|
||||
}
|
||||
|
||||
// round up
|
||||
if (d.d >= 5.) {
|
||||
--pos;
|
||||
for (; pos >= startPos; --pos) {
|
||||
if (++buffer[pos] <= '9')
|
||||
break;
|
||||
buffer[pos] = '0';
|
||||
}
|
||||
// overflow
|
||||
if (pos <= startPos) {
|
||||
if (type != 0) {
|
||||
if (pos < startPos) {
|
||||
startPos = pos;
|
||||
buffer[pos] = '1';
|
||||
}
|
||||
++exponent;
|
||||
--stopPos;
|
||||
} else if (type == 0) {
|
||||
if (exponent < 0) {
|
||||
if (dotZero > 0) {
|
||||
startPos = 0;
|
||||
--dotZero;
|
||||
}
|
||||
} else if (pos < startPos ){
|
||||
startPos = pos;
|
||||
buffer[pos] = '1';
|
||||
++leading;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (preci == 0x7fff) /* old default */
|
||||
preci = 0; /* new default */
|
||||
if (!(flags & HAS_PRECI)) killZero = 1;
|
||||
|
||||
// 'a' 'A'
|
||||
OUT('0');
|
||||
OUT(type + 'X' - 'A');
|
||||
|
||||
if (!d.b.exp) {
|
||||
exponent = x = y = 0;
|
||||
} else {
|
||||
exponent = d.b.exp - 1023;
|
||||
x = d.b.frac0;
|
||||
y = d.b.frac1;
|
||||
buffer[0] = '1';
|
||||
startPos = 0;
|
||||
if (HAS_PRECI)
|
||||
++preci;
|
||||
}
|
||||
stopPos = 1;
|
||||
|
||||
{unsigned j; for (j = 16;j <= 28; j += 12) {
|
||||
{int i; for (i = j; i >= 0; i -= 4) {
|
||||
unsigned c = (x >> i) & 0xf;
|
||||
x -= c << i;
|
||||
if (c > 9)
|
||||
c += type - 10;
|
||||
else
|
||||
c += '0';
|
||||
buffer[stopPos++] = c;
|
||||
if (!x && !y && stopPos >= preci)
|
||||
break;
|
||||
}}
|
||||
if (!y && stopPos >= preci)
|
||||
break;
|
||||
x = y;
|
||||
y = 0;
|
||||
}}
|
||||
|
||||
type += 'P' - 'A';
|
||||
}
|
||||
|
||||
// kill trailing zeroes
|
||||
if (killZero != 0) {
|
||||
int stop = stopPos - 1;
|
||||
while (stop > startPos) {
|
||||
if (buffer[stop] != '0')
|
||||
break;
|
||||
if (type == 0 && stop - startPos == exponent)
|
||||
break;
|
||||
--stop;
|
||||
}
|
||||
if (type != 0 && stop - startPos + 5 < width)
|
||||
width = stop - startPos + preci + 5;
|
||||
else if (type == 0) {
|
||||
if (stop + 1 != stopPos
|
||||
&& stop - startPos == exponent)
|
||||
++width;
|
||||
}
|
||||
stopPos = stop + 1;
|
||||
}
|
||||
|
||||
// calculate width
|
||||
if (type != 0) {
|
||||
// 1e+00
|
||||
width -= 5 + stopPos - startPos + postZero;
|
||||
|
||||
if (exponent < -99) {
|
||||
--width;
|
||||
if (exponent < -999)
|
||||
--width;
|
||||
} else if (exponent > 99) {
|
||||
--width;
|
||||
if (exponent > 999)
|
||||
--width;
|
||||
}
|
||||
} else {
|
||||
// 123.456 -> exponent = 2, preci = 3
|
||||
if (leading > stopPos - startPos)
|
||||
width -= leading + dotZero + postZero;
|
||||
else
|
||||
width -= stopPos - startPos + dotZero
|
||||
+ postZero;
|
||||
}
|
||||
|
||||
// dot?
|
||||
if (preci > 0 || (flags & ALTERNATEFLAG) != 0)
|
||||
--width;
|
||||
}
|
||||
if (sign != 0)
|
||||
--width;
|
||||
|
||||
// pad on left side
|
||||
if ((flags & LALIGNFLAG) == 0)
|
||||
while (--width >= 0)
|
||||
OUT(pad);
|
||||
|
||||
// output sign if set
|
||||
if (sign != 0)
|
||||
OUT(sign);
|
||||
|
||||
if (infnan) {
|
||||
// output inf/nan
|
||||
OUT(infnan[0]);
|
||||
OUT(infnan[1]);
|
||||
OUT(infnan[2]);
|
||||
} else {
|
||||
// leading digits
|
||||
while (leading-- > 0 && startPos < stopPos)
|
||||
OUT(buffer[startPos++]);
|
||||
|
||||
// more leading digits than buffer size
|
||||
while (leading-- >= 0)
|
||||
OUT('0');
|
||||
|
||||
// output dot
|
||||
if (startPos < stopPos || dotZero != 0 || postZero != 0
|
||||
|| (flags & ALTERNATEFLAG) != 0)
|
||||
OUT(__decimalpoint[0]);
|
||||
|
||||
// output zeroes behind dot not in buffer
|
||||
while (dotZero-- > 0)
|
||||
OUT('0');
|
||||
|
||||
// digits somewhere behind dot
|
||||
for (; startPos < stopPos; ++startPos)
|
||||
OUT(buffer[startPos]);
|
||||
|
||||
// output trailing zeroes not in buffer
|
||||
while (postZero-- > 0)
|
||||
OUT('0');
|
||||
|
||||
if (type != 0) {
|
||||
int xout;
|
||||
|
||||
OUT(type);
|
||||
if (exponent < 0) {
|
||||
OUT('-');
|
||||
exponent = -exponent;
|
||||
} else
|
||||
OUT('+');
|
||||
--width;
|
||||
|
||||
xout = 0;
|
||||
if (exponent > 999) {
|
||||
int z = exponent / 1000;
|
||||
OUT('0' + z);
|
||||
exponent -= z * 1000;
|
||||
--width;
|
||||
xout = 1;
|
||||
}
|
||||
if (xout || exponent > 99) {
|
||||
int z = exponent / 100;
|
||||
OUT('0' + z);
|
||||
exponent -= z * 100;
|
||||
--width;
|
||||
xout = 1;
|
||||
}
|
||||
if (xout || exponent > 9 || (type | 0x20) != 'p' ) {
|
||||
int z = exponent / 10;
|
||||
OUT('0' + z);
|
||||
exponent -= z * 10;
|
||||
--width;
|
||||
}
|
||||
OUT('0' + exponent);
|
||||
--width;
|
||||
}
|
||||
}
|
||||
|
||||
// pad on right side
|
||||
if ((flags & LALIGNFLAG) != 0)
|
||||
while (--width >= 0)
|
||||
OUT(' ');
|
||||
/* Everything already done */
|
||||
format = ptr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
case '%':
|
||||
buffer2 = "%";
|
||||
size2 = 1;
|
||||
preci = 0;
|
||||
break;
|
||||
case 'n':
|
||||
*va_arg(args, int *) = outcount;
|
||||
width = preci = 0;
|
||||
break;
|
||||
default:
|
||||
if (!type)
|
||||
ptr--; /* We've gone too far - step one back */
|
||||
buffer2 = (char *) format;
|
||||
size2 = ptr - format;
|
||||
width = preci = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & HAS_PRECI) {
|
||||
if (size2 == 1 && !preci && buffer2[0] == '0')
|
||||
size2 = 0;
|
||||
}
|
||||
|
||||
pad = size1 + (size2 >= preci ? size2 : preci); /* Calculate the number of characters */
|
||||
pad = pad >= width ? 0 : width - pad; /* and the number of resulting pad bytes */
|
||||
|
||||
if (flags & ZEROPADFLAG) /* print sign and that like */
|
||||
for (i = 0; i < size1; i++)
|
||||
OUT(buffer1[i]);
|
||||
|
||||
if (!(flags & LALIGNFLAG)) /* Pad left */
|
||||
for (i = 0; i < pad; i++)
|
||||
OUT(flags&ZEROPADFLAG?'0':' ');
|
||||
|
||||
if (!(flags & ZEROPADFLAG)) /* print sign if not zero padded */
|
||||
for (i = 0; i < size1; i++)
|
||||
OUT(buffer1[i]);
|
||||
|
||||
for (i = size2; i < preci; i++) /* extend to precision */
|
||||
OUT('0');
|
||||
|
||||
for (i = 0; i < size2; i++) /* print body */
|
||||
OUT(buffer2[i]);
|
||||
|
||||
if (flags & LALIGNFLAG) /* Pad right */
|
||||
for (i = 0; i < pad; i++)
|
||||
OUT(' ');
|
||||
|
||||
format = ptr;
|
||||
} else
|
||||
OUT(*format++);
|
||||
}
|
||||
__STDIO_UNLOCK(stream);
|
||||
|
||||
return outcount;
|
||||
}
|
||||
|
||||
#ifdef TESTME
|
||||
int main(int argc, char ** argv) {
|
||||
double d;
|
||||
printf("%-20.0f|\n", 0.0);
|
||||
printf("%-20.0e\n", 0.0);
|
||||
printf("%-20.1g\n", 0.0);
|
||||
printf("%#20.0f\n", 0.0);
|
||||
printf("%#20.0e\n", 0.0);
|
||||
printf("%#20.1g\n", 0.0);
|
||||
|
||||
d = 1.2345678902468e-13;
|
||||
for (int i = 0; i < 24; ++i) {
|
||||
d *= 10;
|
||||
printf("%20.7f\n", d);
|
||||
}
|
||||
|
||||
d = 1.2345678902468e-13;
|
||||
for (int i = 0; i < 24; ++i) {
|
||||
d *= 10;
|
||||
printf("%20.7g\n", d);
|
||||
}
|
||||
|
||||
d = 1.2345678902468e-13;
|
||||
for (int i = 0; i < 24; ++i) {
|
||||
d *= 10;
|
||||
printf("%20.7e\n", d);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
10
sources/nix/stdio/swprintf.c
Executable file
10
sources/nix/stdio/swprintf.c
Executable file
@ -0,0 +1,10 @@
|
||||
#include "stdio.h"
|
||||
#include "wchar.h"
|
||||
int swprintf(wchar_t *s,size_t size,const wchar_t *format,...)
|
||||
{ int retval;
|
||||
va_list args;
|
||||
va_start(args,format);
|
||||
retval=vswprintf(s,size,format,args);
|
||||
va_end(args);
|
||||
return retval;
|
||||
}
|
||||
28
sources/nix/stdio/vswprintf.c
Normal file
28
sources/nix/stdio/vswprintf.c
Normal file
@ -0,0 +1,28 @@
|
||||
#include <stdarg.h>
|
||||
#include "stdio.h"
|
||||
#include "wchar.h"
|
||||
|
||||
extern int __vwfprintf_total_size(FILE *stream, const wchar_t *fmt, va_list args);
|
||||
|
||||
int vswprintf(wchar_t *s,size_t size,const wchar_t *format,va_list args) {
|
||||
size_t retval;
|
||||
FILE buffer;
|
||||
|
||||
if (!s && size )
|
||||
return EOF;
|
||||
|
||||
buffer._p=(unsigned char *)s;
|
||||
buffer._r=0;
|
||||
buffer._w= (size * sizeof(wchar_t)) - 1;
|
||||
buffer._flags=__SSTR|__SWR;
|
||||
buffer.linebufsize=0;
|
||||
#ifdef __posix_threads__
|
||||
buffer.__spinlock[0] = 0;
|
||||
#endif
|
||||
retval = __vwfprintf_total_size(&buffer,format,args) / sizeof(wchar_t);
|
||||
if (retval < size)
|
||||
s[retval] = 0;
|
||||
else if (size > 0)
|
||||
s[size - 1] = 0;
|
||||
return retval;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user