summaryrefslogtreecommitdiff
path: root/src/lib/evil
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2015-04-19 08:28:56 +0200
committerCedric BAIL <cedric@osg.samsung.com>2015-04-19 09:51:41 +0200
commitd1722eb394216ff304ee8aa83146641057d99e72 (patch)
treeab1668e03b9c15784491fb27cad6e128ce504b34 /src/lib/evil
parent880310617e60728a8c2f6491affb7ccd9a77bb4c (diff)
evil: remove unused files (evil_p*) and uneeded evil_uuid.c file (managed by mingw-w64)
Just keeping up with latest mingw-w64.
Diffstat (limited to 'src/lib/evil')
-rw-r--r--src/lib/evil/evil_pformat.h61
-rw-r--r--src/lib/evil/evil_pformata.c2493
-rw-r--r--src/lib/evil/evil_pformatw.c9
-rw-r--r--src/lib/evil/evil_print.h37
-rw-r--r--src/lib/evil/evil_printa.c1768
-rw-r--r--src/lib/evil/evil_printw.c4
-rw-r--r--src/lib/evil/evil_uuid.c9
7 files changed, 0 insertions, 4381 deletions
diff --git a/src/lib/evil/evil_pformat.h b/src/lib/evil/evil_pformat.h
deleted file mode 100644
index ad9b61e024..0000000000
--- a/src/lib/evil/evil_pformat.h
+++ /dev/null
@@ -1,61 +0,0 @@
1#ifndef __EVIL_PRIVATE_H__
2#define __EVIL_PRIVATE_H__
3
4
5#include "evil_macro.h"
6
7
8#ifdef __BUILD_WIDEAPI
9#define APICHAR wchar_t
10#else
11#define APICHAR char
12#endif
13
14/* The following are the declarations specific to the `pformat' API...
15 */
16#define PFORMAT_TO_FILE 0x1000
17#define PFORMAT_NOLIMIT 0x2000
18
19
20#ifdef __cplusplus
21extern "C" {
22#endif
23
24
25#ifdef __BUILD_WIDEAPI
26# define __fputc(X,STR) fputwc((wchar_t) (X), (STR))
27# define _evil_pformat _evil_pformatw
28
29# define _evil_fprintf _evil_fprintfw
30# define _evil_printf _evil_printfw
31# define _evil_snprintf _evil_snprintfw
32# define _evil_sprintf _evil_sprintfw
33
34# define _evil_vfprintf _evil_vfprintfw
35# define _evil_vprintf _evil_vprintfw
36# define _evil_vsnprintf _evil_vsnprintfw
37# define _evil_vsprintf _evil_vsprintfw
38#else
39# define __fputc(X,STR) fputc((X), (STR))
40# define _evil_pformat _evil_pformata
41
42# define _evil_fprintf _evil_fprintfa
43# define _evil_printf _evil_printfa
44# define _evil_snprintf _evil_snprintfa
45# define _evil_sprintf _evil_sprintfa
46
47# define _evil_vfprintf _evil_vfprintfa
48# define _evil_vprintf _evil_vprintfa
49# define _evil_vsnprintf _evil_vsnprintfa
50# define _evil_vsprintf _evil_vsprintfa
51#endif
52
53int __cdecl _evil_pformat(int, void *, int, const APICHAR *, va_list) __EVIL_NOTHROW;
54
55
56#ifdef __cplusplus
57}
58#endif
59
60
61#endif /* __EVIL_PRIVATE_H__ */
diff --git a/src/lib/evil/evil_pformata.c b/src/lib/evil/evil_pformata.c
deleted file mode 100644
index ee1d68e772..0000000000
--- a/src/lib/evil/evil_pformata.c
+++ /dev/null
@@ -1,2493 +0,0 @@
1/* pformat.c
2 *
3 * $Id: pformat.c,v 1.9 2011/01/07 22:57:00 keithmarshall Exp $
4 *
5 * Provides a core implementation of the formatting capabilities
6 * common to the entire `printf()' family of functions; it conforms
7 * generally to C99 and SUSv3/POSIX specifications, with extensions
8 * to support Microsoft's non-standard format specifications.
9 *
10 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
11 *
12 * This is free software. You may redistribute and/or modify it as you
13 * see fit, without restriction of copyright.
14 *
15 * This software is provided "as is", in the hope that it may be useful,
16 * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of
17 * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no
18 * time will the author accept any form of liability for any damages,
19 * however caused, resulting from the use of this software.
20 *
21 * The elements of this implementation which deal with the formatting
22 * of floating point numbers, (i.e. the `%e', `%E', `%f', `%F', `%g'
23 * and `%G' format specifiers, but excluding the hexadecimal floating
24 * point `%a' and `%A' specifiers), make use of the `__gdtoa' function
25 * written by David M. Gay, and are modelled on his sample code, which
26 * has been deployed under its accompanying terms of use:--
27 *
28 ******************************************************************
29 * Copyright (C) 1997, 1999, 2001 Lucent Technologies
30 * All Rights Reserved
31 *
32 * Permission to use, copy, modify, and distribute this software and
33 * its documentation for any purpose and without fee is hereby
34 * granted, provided that the above copyright notice appear in all
35 * copies and that both that the copyright notice and this
36 * permission notice and warranty disclaimer appear in supporting
37 * documentation, and that the name of Lucent or any of its entities
38 * not be used in advertising or publicity pertaining to
39 * distribution of the software without specific, written prior
40 * permission.
41 *
42 * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
43 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
44 * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
45 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
47 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
48 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
49 * THIS SOFTWARE.
50 ******************************************************************
51 *
52 */
53#include <stdio.h>
54#include <stdarg.h>
55#include <stddef.h>
56#include <stdint.h>
57#include <stdlib.h>
58#include <string.h>
59#include <limits.h>
60#include <locale.h>
61#include <wchar.h>
62#include <math.h>
63
64/* FIXME: The following belongs in values.h, but current MinGW
65 * has nothing useful there! OTOH, values.h is not a standard
66 * header, and it's use may be considered obsolete; perhaps it
67 * is better to just keep these definitions here.
68 */
69#ifndef _VALUES_H
70/*
71 * values.h
72 *
73 */
74#define _VALUES_H
75
76#include <limits.h>
77
78#define _TYPEBITS(type) (sizeof(type) * CHAR_BIT)
79
80#define LLONGBITS _TYPEBITS(long long)
81
82#endif /* !defined _VALUES_H -- end of file */
83
84#include "evil_pformat.h"
85#include "gdtoa/gdtoa.h"
86
87/* Bit-map constants, defining the internal format control
88 * states, which propagate through the flags.
89 */
90#define PFORMAT_GROUPED 0x1000
91#define PFORMAT_HASHED 0x0800
92#define PFORMAT_LJUSTIFY 0x0400
93#define PFORMAT_ZEROFILL 0x0200
94
95#define PFORMAT_JUSTIFY (PFORMAT_LJUSTIFY | PFORMAT_ZEROFILL)
96#define PFORMAT_IGNORE -1
97
98#define PFORMAT_SIGNED 0x01C0
99#define PFORMAT_POSITIVE 0x0100
100#define PFORMAT_NEGATIVE 0x0080
101#define PFORMAT_ADDSPACE 0x0040
102
103#define PFORMAT_XCASE 0x0020
104
105#define PFORMAT_LDOUBLE 0x0004
106
107/* `%o' format digit extraction mask, and shift count...
108 * (These are constant, and do not propagate through the flags).
109 */
110#define PFORMAT_OMASK 0x0007
111#define PFORMAT_OSHIFT 0x0003
112
113/* `%x' and `%X' format digit extraction mask, and shift count...
114 * (These are constant, and do not propagate through the flags).
115 */
116#define PFORMAT_XMASK 0x000F
117#define PFORMAT_XSHIFT 0x0004
118
119/* The radix point character, used in floating point formats, is
120 * localised on the basis of the active LC_NUMERIC locale category.
121 * It is stored locally, as a `wchar_t' entity, which is converted
122 * to a (possibly multibyte) character on output. Initialisation
123 * of the stored `wchar_t' entity, together with a record of its
124 * effective multibyte character length, is required each time
125 * `__pformat()' is entered, (static storage would not be thread
126 * safe), but this initialisation is deferred until it is actually
127 * needed; on entry, the effective character length is first set to
128 * the following value, (and the `wchar_t' entity is zeroed), to
129 * indicate that a call of `localeconv()' is needed, to complete
130 * the initialisation.
131 */
132#define PFORMAT_RPINIT -3
133
134/* The floating point format handlers return the following value
135 * for the radix point position index, when the argument value is
136 * infinite, or not a number.
137 */
138#define PFORMAT_INFNAN -32768
139
140#ifdef _WIN32
141/*
142 * The Microsoft standard for printing `%e' format exponents is
143 * with a minimum of three digits, unless explicitly set otherwise,
144 * by a prior invocation of the `_set_output_format()' function.
145 *
146 * The following macro allows us to replicate this behaviour.
147 */
148# define PFORMAT_MINEXP __pformat_exponent_digits()
149 /*
150 * However, this feature is unsupported for versions of the
151 * MSVC runtime library prior to msvcr80.dll, and by default,
152 * MinGW uses an earlier version, (equivalent to msvcr60.dll),
153 * for which `_TWO_DIGIT_EXPONENT' will be undefined.
154 */
155# ifndef _TWO_DIGIT_EXPONENT
156 /*
157 * This hack works around the lack of the `_set_output_format()'
158 * feature, when supporting versions of the MSVC runtime library
159 * prior to msvcr80.dll; it simply enforces Microsoft's original
160 * convention, for all cases where the feature is unsupported.
161 */
162# define _get_output_format() 0
163# define _TWO_DIGIT_EXPONENT 1
164# endif
165/*
166 * Irrespective of the MSVCRT version supported, *we* will add
167 * an additional capability, through the following inline function,
168 * which will allow the user to choose his own preferred default
169 * for `PRINTF_EXPONENT_DIGITS', through the simple expedient
170 * of defining it as an environment variable.
171 */
172static
173int __pformat_exponent_digits( void )
174{
175 char *exponent_digits = getenv( "PRINTF_EXPONENT_DIGITS" );
176 return ((exponent_digits != NULL) && ((unsigned)(*exponent_digits - '0') < 3))
177 || (_get_output_format() & _TWO_DIGIT_EXPONENT)
178 ? 2
179 : 3
180 ;
181}
182#else
183/*
184 * When we don't care to mimic Microsoft's standard behaviour,
185 * we adopt the C99/POSIX standard of two digit exponents.
186 */
187# define PFORMAT_MINEXP 2
188#endif
189
190typedef union
191{
192 /* A data type agnostic representation,
193 * for printf arguments of any integral data type...
194 */
195 signed long __pformat_long_t;
196 signed long long __pformat_llong_t;
197 unsigned long __pformat_ulong_t;
198 unsigned long long __pformat_ullong_t;
199 unsigned short __pformat_ushort_t;
200 unsigned char __pformat_uchar_t;
201 signed short __pformat_short_t;
202 signed char __pformat_char_t;
203 void * __pformat_ptr_t;
204} __pformat_intarg_t;
205
206typedef enum
207{
208 /* Format interpreter state indices...
209 * (used to identify the active phase of format string parsing).
210 */
211 PFORMAT_INIT = 0,
212 PFORMAT_SET_WIDTH,
213 PFORMAT_GET_PRECISION,
214 PFORMAT_SET_PRECISION,
215 PFORMAT_END
216} __pformat_state_t;
217
218typedef enum
219{
220 /* Argument length classification indices...
221 * (used for arguments representing integer data types).
222 */
223 PFORMAT_LENGTH_INT = 0,
224 PFORMAT_LENGTH_SHORT,
225 PFORMAT_LENGTH_LONG,
226 PFORMAT_LENGTH_LLONG,
227 PFORMAT_LENGTH_CHAR
228} __pformat_length_t;
229/*
230 * And a macro to map any arbitrary data type to an appropriate
231 * matching index, selected from those above; the compiler should
232 * collapse this to a simple assignment.
233 */
234#define __pformat_arg_length( type ) \
235 sizeof( type ) == sizeof( long long ) ? PFORMAT_LENGTH_LLONG : \
236 sizeof( type ) == sizeof( long ) ? PFORMAT_LENGTH_LONG : \
237 sizeof( type ) == sizeof( short ) ? PFORMAT_LENGTH_SHORT : \
238 sizeof( type ) == sizeof( char ) ? PFORMAT_LENGTH_CHAR : \
239 /* should never need this default */ PFORMAT_LENGTH_INT
240
241typedef struct
242{
243 /* Formatting and output control data...
244 * An instance of this control block is created, (on the stack),
245 * for each call to `__pformat()', and is passed by reference to
246 * each of the output handlers, as required.
247 */
248 void * dest;
249 int flags;
250 int width;
251 int precision;
252 int rplen;
253 wchar_t rpchr;
254 int thousands_chr_len;
255 wchar_t thousands_chr;
256 int count;
257 int quota;
258 int expmin;
259} __pformat_t;
260
261static
262void __pformat_putc( int c, __pformat_t *stream )
263{
264 /* Place a single character into the `__pformat()' output queue,
265 * provided any specified output quota has not been exceeded.
266 */
267 if( (stream->flags & PFORMAT_NOLIMIT) || (stream->quota > stream->count) )
268 {
269 /* Either there was no quota specified,
270 * or the active quota has not yet been reached.
271 */
272 if( stream->flags & PFORMAT_TO_FILE )
273 /*
274 * This is single character output to a FILE stream...
275 */
276 __fputc(c, (FILE *)(stream->dest));
277
278 else
279 /* Whereas, this is to an internal memory buffer...
280 */
281 ((APICHAR *)(stream->dest))[stream->count] = c;
282 }
283 ++stream->count;
284}
285
286static
287void __pformat_putchars( const char *s, int count, __pformat_t *stream )
288{
289 /* Handler for `%c' and (indirectly) `%s' conversion specifications.
290 *
291 * Transfer characters from the string buffer at `s', character by
292 * character, up to the number of characters specified by `count', or
293 * if `precision' has been explicitly set to a value less than `count',
294 * stopping after the number of characters specified for `precision',
295 * to the `__pformat()' output stream.
296 *
297 * Characters to be emitted are passed through `__pformat_putc()', to
298 * ensure that any specified output quota is honoured.
299 */
300 if( (stream->precision >= 0) && (count > stream->precision) )
301 /*
302 * Ensure that the maximum number of characters transferred doesn't
303 * exceed any explicitly set `precision' specification.
304 */
305 count = stream->precision;
306
307 /* Establish the width of any field padding required...
308 */
309 if( stream->width > count )
310 /*
311 * as the number of spaces equivalent to the number of characters
312 * by which those to be emitted is fewer than the field width...
313 */
314 stream->width -= count;
315
316 else
317 /* ignoring any width specification which is insufficient.
318 */
319 stream->width = PFORMAT_IGNORE;
320
321 if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) )
322 /*
323 * When not doing flush left justification, (i.e. the `-' flag
324 * is not set), any residual unreserved field width must appear
325 * as blank padding, to the left of the output string.
326 */
327 while( stream->width-- )
328 __pformat_putc( '\x20', stream );
329
330 /* Emit the data...
331 */
332#ifdef __BUILD_WIDEAPI
333 {
334 /* mbrtowc */
335 size_t l;
336 wchar_t w[12], *p;
337 while( count > 0 )
338 {
339 mbstate_t ps;
340 memset(&ps, 0, sizeof(ps) );
341 --count;
342 p = &w[0];
343 l = mbrtowc (p, s, strlen (s), &ps);
344 if (!l)
345 break;
346 if ((ssize_t)l < 0)
347 {
348 l = 1;
349 w[0] = (wchar_t) *s;
350 }
351 s += l;
352 __pformat_putc((int)w[0], stream);
353 }
354 }
355#else
356 while( count-- )
357 /*
358 * copying the requisite number of characters from the input.
359 */
360 __pformat_putc( *s++, stream );
361#endif
362
363 /* If we still haven't consumed the entire specified field width,
364 * we must be doing flush left justification; any residual width
365 * must be filled with blanks, to the right of the output value.
366 */
367 while( stream->width-- > 0 )
368 __pformat_putc( '\x20', stream );
369}
370
371static
372void __pformat_puts( const char *s, __pformat_t *stream )
373{
374 /* Handler for `%s' conversion specifications.
375 *
376 * Transfer a NUL terminated character string, character by character,
377 * stopping when the end of the string is encountered, or if `precision'
378 * has been explicitly set, when the specified number of characters has
379 * been emitted, if that is less than the length of the input string,
380 * to the `__pformat()' output stream.
381 *
382 * This is implemented as a trivial call to `__pformat_putchars()',
383 * passing the length of the input string as the character count,
384 * (after first verifying that the input pointer is not NULL).
385 */
386 if( s == NULL ) s = "(null)";
387 __pformat_putchars( s, strlen( s ), stream );
388}
389
390static
391void __pformat_wputchars( const wchar_t *s, int count, __pformat_t *stream )
392{
393 /* Handler for `%C'(`%lc') and `%S'(`%ls') conversion specifications;
394 * (this is a wide character variant of `__pformat_putchars()').
395 *
396 * Each multibyte character sequence to be emitted is passed, byte
397 * by byte, through `__pformat_putc()', to ensure that any specified
398 * output quota is honoured.
399 */
400 char buf[16];
401 mbstate_t state;
402 int len = wcrtomb(buf, L'\0', &state);
403
404 if( (stream->precision >= 0) && (count > stream->precision) )
405 /*
406 * Ensure that the maximum number of characters transferred doesn't
407 * exceed any explicitly set `precision' specification.
408 */
409 count = stream->precision;
410
411 /* Establish the width of any field padding required...
412 */
413 if( stream->width > count )
414 /*
415 * as the number of spaces equivalent to the number of characters
416 * by which those to be emitted is fewer than the field width...
417 */
418 stream->width -= count;
419
420 else
421 /* ignoring any width specification which is insufficient.
422 */
423 stream->width = PFORMAT_IGNORE;
424
425 if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) )
426 /*
427 * When not doing flush left justification, (i.e. the `-' flag
428 * is not set), any residual unreserved field width must appear
429 * as blank padding, to the left of the output string.
430 */
431 while( stream->width-- )
432 __pformat_putc( '\x20', stream );
433
434 /* Emit the data, converting each character from the wide
435 * to the multibyte domain as we go...
436 */
437#ifdef __BUILD_WIDEAPI
438 len = count;
439 while(len-- > 0 && *s != 0)
440 {
441 __pformat_putc(*s++, stream);
442 }
443 count = len;
444#else
445 while( (count-- > 0) && ((len = wcrtomb( buf, *s++, &state )) > 0) )
446 {
447 char *p = buf;
448 while( len-- > 0 )
449 __pformat_putc( *p++, stream );
450 }
451#endif
452 /* If we still haven't consumed the entire specified field width,
453 * we must be doing flush left justification; any residual width
454 * must be filled with blanks, to the right of the output value.
455 */
456 while( stream->width-- > 0 )
457 __pformat_putc( '\x20', stream );
458}
459
460static
461void __pformat_wcputs( const wchar_t *s, __pformat_t *stream )
462{
463 /* Handler for `%S' (`%ls') conversion specifications.
464 *
465 * Transfer a NUL terminated wide character string, character by
466 * character, converting to its equivalent multibyte representation
467 * on output, and stopping when the end of the string is encountered,
468 * or if `precision' has been explicitly set, when the specified number
469 * of characters has been emitted, if that is less than the length of
470 * the input string, to the `__pformat()' output stream.
471 *
472 * This is implemented as a trivial call to `__pformat_wputchars()',
473 * passing the length of the input string as the character count,
474 * (after first verifying that the input pointer is not NULL).
475 */
476 if( s == NULL ) s = L"(null)";
477 __pformat_wputchars( s, wcslen( s ), stream );
478}
479
480static
481int __pformat_int_bufsiz( int bias, int size, __pformat_t *stream )
482{
483 /* Helper to establish the size of the internal buffer, which
484 * is required to queue the ASCII decomposition of an integral
485 * data value, prior to transfer to the output stream.
486 */
487 size = ((size - 1 + LLONGBITS) / size) + bias;
488 size += (stream->precision > 0) ? stream->precision : 0;
489 if ((stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0)
490 size += (size / 3);
491 return (size > stream->width) ? size : stream->width;
492}
493
494static
495void __pformat_int( __pformat_intarg_t value, __pformat_t *stream )
496{
497 /* Handler for `%d', `%i' and `%u' conversion specifications.
498 *
499 * Transfer the ASCII representation of an integer value parameter,
500 * formatted as a decimal number, to the `__pformat()' output queue;
501 * output will be truncated, if any specified quota is exceeded.
502 */
503 char buf[__pformat_int_bufsiz(1, PFORMAT_OSHIFT, stream)];
504 char *p = buf; int precision;
505
506 if( stream->flags & PFORMAT_NEGATIVE )
507 {
508 /* The input value might be negative, (i.e. it is a signed value)...
509 */
510 if( value.__pformat_llong_t < 0LL )
511 /*
512 * It IS negative, but we want to encode it as unsigned,
513 * displayed with a leading minus sign, so convert it...
514 */
515 value.__pformat_llong_t = -value.__pformat_llong_t;
516
517 else
518 /* It is unequivocally a POSITIVE value, so turn off the
519 * request to prefix it with a minus sign...
520 */
521 stream->flags &= ~PFORMAT_NEGATIVE;
522 }
523
524 /* Encode the input value for display...
525 */
526 while( value.__pformat_ullong_t )
527 {
528 /* decomposing it into its constituent decimal digits,
529 * in order from least significant to most significant, using
530 * the local buffer as a LIFO queue in which to store them.
531 */
532 if (p != buf && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0
533 && ((p - buf) % 4) == 3)
534 {
535 *p++ = ',';
536 }
537 *p++ = '0' + (unsigned char)(value.__pformat_ullong_t % 10LL);
538 value.__pformat_ullong_t /= 10LL;
539 }
540
541 if( (stream->precision > 0)
542 && ((precision = stream->precision - (p - buf)) > 0) )
543 /*
544 * We have not yet queued sufficient digits to fill the field width
545 * specified for minimum `precision'; pad with zeros to achieve this.
546 */
547 while( precision-- > 0 )
548 *p++ = '0';
549
550 if( (p == buf) && (stream->precision != 0) )
551 /*
552 * Input value was zero; make sure we print at least one digit,
553 * unless the precision is also explicitly zero.
554 */
555 *p++ = '0';
556
557 if( (stream->width > 0) && ((stream->width -= p - buf) > 0) )
558 {
559 /* We have now queued sufficient characters to display the input value,
560 * at the desired precision, but this will not fill the output field...
561 */
562 if( stream->flags & PFORMAT_SIGNED )
563 /*
564 * We will fill one additional space with a sign...
565 */
566 stream->width--;
567
568 if( (stream->precision < 0)
569 && ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) )
570 /*
571 * and the `0' flag is in effect, so we pad the remaining spaces,
572 * to the left of the displayed value, with zeros.
573 */
574 while( stream->width-- > 0 )
575 *p++ = '0';
576
577 else if( (stream->flags & PFORMAT_LJUSTIFY) == 0 )
578 /*
579 * the `0' flag is not in effect, and neither is the `-' flag,
580 * so we pad to the left of the displayed value with spaces, so that
581 * the value appears right justified within the output field.
582 */
583 while( stream->width-- > 0 )
584 __pformat_putc( '\x20', stream );
585 }
586
587 if( stream->flags & PFORMAT_NEGATIVE )
588 /*
589 * A negative value needs a sign...
590 */
591 *p++ = '-';
592
593 else if( stream->flags & PFORMAT_POSITIVE )
594 /*
595 * A positive value may have an optionally displayed sign...
596 */
597 *p++ = '+';
598
599 else if( stream->flags & PFORMAT_ADDSPACE )
600 /*
601 * Space was reserved for displaying a sign, but none was emitted...
602 */
603 *p++ = '\x20';
604
605 while( p > buf )
606 /*
607 * Emit the accumulated constituent digits,
608 * in order from most significant to least significant...
609 */
610 __pformat_putc( *--p, stream );
611
612 while( stream->width-- > 0 )
613 /*
614 * The specified output field has not yet been completely filled;
615 * the `-' flag must be in effect, resulting in a displayed value which
616 * appears left justified within the output field; we must pad the field
617 * to the right of the displayed value, by emitting additional spaces,
618 * until we reach the rightmost field boundary.
619 */
620 __pformat_putc( '\x20', stream );
621}
622
623static
624void __pformat_xint( int fmt, __pformat_intarg_t value, __pformat_t *stream )
625{
626 /* Handler for `%o', `%p', `%x' and `%X' conversions.
627 *
628 * These can be implemented using a simple `mask and shift' strategy;
629 * set up the mask and shift values appropriate to the conversion format,
630 * and allocate a suitably sized local buffer, in which to queue encoded
631 * digits of the formatted value, in preparation for output.
632 */
633 int width;
634 int mask = (fmt == 'o') ? PFORMAT_OMASK : PFORMAT_XMASK;
635 int shift = (fmt == 'o') ? PFORMAT_OSHIFT : PFORMAT_XSHIFT;
636 char buf[__pformat_int_bufsiz(2, shift, stream)];
637 char *p = buf;
638
639 while( value.__pformat_ullong_t )
640 {
641 /* Encode the specified non-zero input value as a sequence of digits,
642 * in the appropriate `base' encoding and in reverse digit order, each
643 * encoded in its printable ASCII form, with no leading zeros, using
644 * the local buffer as a LIFO queue in which to store them.
645 */
646 char *q;
647 if( (*(q = p++) = '0' + (value.__pformat_ullong_t & mask)) > '9' )
648 *q = (*q + 'A' - '9' - 1) | (fmt & PFORMAT_XCASE);
649 value.__pformat_ullong_t >>= shift;
650 }
651
652 if( p == buf )
653 /*
654 * Nothing was queued; input value must be zero, which should never be
655 * emitted in the `alternative' PFORMAT_HASHED style.
656 */
657 stream->flags &= ~PFORMAT_HASHED;
658
659 if( ((width = stream->precision) > 0) && ((width -= p - buf) > 0) )
660 /*
661 * We have not yet queued sufficient digits to fill the field width
662 * specified for minimum `precision'; pad with zeros to achieve this.
663 */
664 while( width-- > 0 )
665 *p++ = '0';
666
667 else if( (fmt == 'o') && (stream->flags & PFORMAT_HASHED) )
668 /*
669 * The field width specified for minimum `precision' has already
670 * been filled, but the `alternative' PFORMAT_HASHED style for octal
671 * output requires at least one initial zero; that will not have
672 * been queued, so add it now.
673 */
674 *p++ = '0';
675
676 if( (p == buf) && (stream->precision != 0) )
677 /*
678 * Still nothing queued for output, but the `precision' has not been
679 * explicitly specified as zero, (which is necessary if no output for
680 * an input value of zero is desired); queue exactly one zero digit.
681 */
682 *p++ = '0';
683
684 if( stream->width > (width = p - buf) )
685 /*
686 * Specified field width exceeds the minimum required...
687 * Adjust so that we retain only the additional padding width.
688 */
689 stream->width -= width;
690
691 else
692 /* Ignore any width specification which is insufficient.
693 */
694 stream->width = PFORMAT_IGNORE;
695
696 if( ((width = stream->width) > 0)
697 && (fmt != 'o') && (stream->flags & PFORMAT_HASHED) )
698 /*
699 * For `%#x' or `%#X' formats, (which have the `#' flag set),
700 * further reduce the padding width to accommodate the radix
701 * indicating prefix.
702 */
703 width -= 2;
704
705 if( (width > 0) && (stream->precision < 0)
706 && ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) )
707 /*
708 * When the `0' flag is set, and not overridden by the `-' flag,
709 * or by a specified precision, add sufficient leading zeros to
710 * consume the remaining field width.
711 */
712 while( width-- > 0 )
713 *p++ = '0';
714
715 if( (fmt != 'o') && (stream->flags & PFORMAT_HASHED) )
716 {
717 /* For formats other than octal, the PFORMAT_HASHED output style
718 * requires the addition of a two character radix indicator, as a
719 * prefix to the actual encoded numeric value.
720 */
721 *p++ = fmt;
722 *p++ = '0';
723 }
724
725 if( (width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) )
726 /*
727 * When not doing flush left justification, (i.e. the `-' flag
728 * is not set), any residual unreserved field width must appear
729 * as blank padding, to the left of the output value.
730 */
731 while( width-- > 0 )
732 __pformat_putc( '\x20', stream );
733
734 while( p > buf )
735 /*
736 * Move the queued output from the local buffer to the ultimate
737 * destination, in LIFO order.
738 */
739 __pformat_putc( *--p, stream );
740
741 /* If we still haven't consumed the entire specified field width,
742 * we must be doing flush left justification; any residual width
743 * must be filled with blanks, to the right of the output value.
744 */
745 while( width-- > 0 )
746 __pformat_putc( '\x20', stream );
747}
748
749typedef union
750{
751 /* A multifaceted representation of an IEEE extended precision,
752 * (80-bit), floating point number, facilitating access to its
753 * component parts.
754 */
755 double __pformat_fpreg_double_t;
756 long double __pformat_fpreg_ldouble_t;
757 struct
758 { unsigned long long __pformat_fpreg_mantissa;
759 signed short __pformat_fpreg_exponent;
760 };
761 unsigned short __pformat_fpreg_bitmap[5];
762 unsigned long __pformat_fpreg_bits;
763} __pformat_fpreg_t;
764
765
766static
767char *__pformat_cvt( int mode, __pformat_fpreg_t x, int nd, int *dp, int *sign )
768{
769 /* Helper function, derived from David M. Gay's `g_xfmt()', calling
770 * his `__gdtoa()' function in a manner to provide extended precision
771 * replacements for `ecvt()' and `fcvt()'.
772 */
773 int k; unsigned int e = 0; char *ep;
774 static FPI fpi = { 64, 1-16383-64+1, 32766-16383-64+1, FPI_Round_near, 0, 14 /* Int_max */ };
775
776 /* Classify the argument into an appropriate `__gdtoa()' category...
777 */
778 if( (k = __fpclassifyl( x.__pformat_fpreg_ldouble_t )) & FP_NAN )
779 /*
780 * identifying infinities or not-a-number...
781 */
782 k = (k & FP_NORMAL) ? STRTOG_Infinite : STRTOG_NaN;
783
784 else if( k & FP_NORMAL )
785 {
786 /* normal and near-zero `denormals'...
787 */
788 if( k & FP_ZERO )
789 {
790 /* with appropriate exponent adjustment for a `denormal'...
791 */
792 k = STRTOG_Denormal;
793 e = 1 - 0x3FFF - 63;
794 }
795 else
796 {
797 /* or with `normal' exponent adjustment...
798 */
799 k = STRTOG_Normal;
800 e = (x.__pformat_fpreg_exponent & 0x7FFF) - 0x3FFF - 63;
801 }
802 }
803
804 else
805 /* or, if none of the above, it's a zero, (positive or negative).
806 */
807 k = STRTOG_Zero;
808
809 /* Check for negative values, always treating NaN as unsigned...
810 * (return value is zero for positive/unsigned; non-zero for negative).
811 */
812 *sign = (k == STRTOG_NaN) ? 0 : x.__pformat_fpreg_exponent & 0x8000;
813
814 /* Finally, get the raw digit string, and radix point position index.
815 */
816 return __gdtoa( &fpi, e, &x.__pformat_fpreg_bits, &k, mode, nd, dp, &ep );
817}
818
819static
820char *__pformat_ecvt( long double x, int precision, int *dp, int *sign )
821{
822 /* A convenience wrapper for the above...
823 * it emulates `ecvt()', but takes a `long double' argument.
824 */
825 __pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x;
826 return __pformat_cvt( 2, z, precision, dp, sign );
827}
828
829static
830char *__pformat_fcvt( long double x, int precision, int *dp, int *sign )
831{
832 /* A convenience wrapper for the above...
833 * it emulates `fcvt()', but takes a `long double' argument.
834 */
835 __pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x;
836 return __pformat_cvt( 3, z, precision, dp, sign );
837}
838
839/* The following are required, to clean up the `__gdtoa()' memory pool,
840 * after processing the data returned by the above.
841 */
842#define __pformat_ecvt_release( value ) __freedtoa( value )
843#define __pformat_fcvt_release( value ) __freedtoa( value )
844
845static
846void __pformat_emit_radix_point( __pformat_t *stream )
847{
848 /* Helper to place a localised representation of the radix point
849 * character at the ultimate destination, when formatting fixed or
850 * floating point numbers.
851 */
852 if( stream->rplen == PFORMAT_RPINIT )
853 {
854 /* Radix point initialisation not yet completed;
855 * establish a multibyte to `wchar_t' converter...
856 */
857 int len; wchar_t rpchr; mbstate_t state;
858
859 /* Initialise the conversion state...
860 */
861 memset( &state, 0, sizeof( state ) );
862
863 /* Fetch and convert the localised radix point representation...
864 */
865 if( (len = mbrtowc( &rpchr, localeconv()->decimal_point, 16, &state )) > 0 )
866 /*
867 * and store it, if valid.
868 */
869 stream->rpchr = rpchr;
870
871 /* In any case, store the reported effective multibyte length,
872 * (or the error flag), marking initialisation as `done'.
873 */
874 stream->rplen = len;
875 }
876
877 if( stream->rpchr != (wchar_t)(0) )
878 {
879 /* We have a localised radix point mark;
880 * establish a converter to make it a multibyte character...
881 */
882#ifdef __BUILD_WIDEAPI
883 __pformat_putc (stream->rpchr, stream);
884#else
885 int len; char buf[len = stream->rplen]; mbstate_t state;
886
887 /* Initialise the conversion state...
888 */
889 memset( &state, 0, sizeof( state ) );
890
891 /* Convert the `wchar_t' representation to multibyte...
892 */
893 if( (len = wcrtomb( buf, stream->rpchr, &state )) > 0 )
894 {
895 /* and copy to the output destination, when valid...
896 */
897 char *p = buf;
898 while( len-- > 0 )
899 __pformat_putc( *p++, stream );
900 }
901
902 else
903 /* otherwise fall back to plain ASCII '.'...
904 */
905 __pformat_putc( '.', stream );
906#endif
907 }
908 else
909 /* No localisation: just use ASCII '.'...
910 */
911 __pformat_putc( '.', stream );
912}
913
914static
915void __pformat_emit_numeric_value( int c, __pformat_t *stream )
916{
917 /* Convenience helper to transfer numeric data from an internal
918 * formatting buffer to the ultimate destination...
919 */
920 if( c == '.' )
921 /*
922 * converting this internal representation of the the radix
923 * point to the appropriately localised representation...
924 */
925 __pformat_emit_radix_point( stream );
926 else if (c == ',')
927 {
928 wchar_t wcs;
929 if ((wcs = stream->thousands_chr) != 0)
930 __pformat_wputchars (&wcs, 1, stream);
931 }
932 else
933 /* and passing all other characters through, unmodified.
934 */
935 __pformat_putc( c, stream );
936}
937
938static
939void __pformat_emit_inf_or_nan( int sign, char *value, __pformat_t *stream )
940{
941 /* Helper to emit INF or NAN where a floating point value
942 * resolves to one of these special states.
943 */
944 int i;
945 char buf[4];
946 char *p = buf;
947
948 /* We use the string formatting helper to display INF/NAN,
949 * but we don't want truncation if the precision set for the
950 * original floating point output request was insufficient;
951 * ignore it!
952 */
953 stream->precision = PFORMAT_IGNORE;
954
955 if( sign )
956 /*
957 * Negative infinity: emit the sign...
958 */
959 *p++ = '-';
960
961 else if( stream->flags & PFORMAT_POSITIVE )
962 /*
963 * Not negative infinity, but '+' flag is in effect;
964 * thus, we emit a positive sign...
965 */
966 *p++ = '+';
967
968 else if( stream->flags & PFORMAT_ADDSPACE )
969 /*
970 * No sign required, but space was reserved for it...
971 */
972 *p++ = '\x20';
973
974 /* Copy the appropriate status indicator, up to a maximum of
975 * three characters, transforming to the case corresponding to
976 * the format specification...
977 */
978 for( i = 3; i > 0; --i )
979 *p++ = (*value++ & ~PFORMAT_XCASE) | (stream->flags & PFORMAT_XCASE);
980
981 /* and emit the result.
982 */
983 __pformat_putchars( buf, p - buf, stream );
984}
985
986static
987void __pformat_emit_float( int sign, char *value, int len, __pformat_t *stream )
988{
989 /* Helper to emit a fixed point representation of numeric data,
990 * as encoded by a prior call to `ecvt()' or `fcvt()'; (this does
991 * NOT include the exponent, for floating point format).
992 */
993 if( len > 0 )
994 {
995 /* The magnitude of `x' is greater than or equal to 1.0...
996 * reserve space in the output field, for the required number of
997 * decimal digits to be placed before the decimal point...
998 */
999 if( stream->width > len )
1000 /*
1001 * adjusting as appropriate, when width is sufficient...
1002 */
1003 stream->width -= len;
1004
1005 else
1006 /* or simply ignoring the width specification, if not.
1007 */
1008 stream->width = PFORMAT_IGNORE;
1009 }
1010
1011 else if( stream->width > 0 )
1012 /*
1013 * The magnitude of `x' is less than 1.0...
1014 * reserve space for exactly one zero before the decimal point.
1015 */
1016 stream->width--;
1017
1018 /* Reserve additional space for the digits which will follow the
1019 * decimal point...
1020 */
1021 if( (stream->width >= 0) && (stream->width > stream->precision) )
1022 /*
1023 * adjusting appropriately, when sufficient width remains...
1024 * (note that we must check both of these conditions, because
1025 * precision may be more negative than width, as a result of
1026 * adjustment to provide extra padding when trailing zeros
1027 * are to be discarded from "%g" format conversion with a
1028 * specified field width, but if width itself is negative,
1029 * then there is explicitly to be no padding anyway).
1030 */
1031 stream->width -= stream->precision;
1032
1033 else
1034 /* or again, ignoring the width specification, if not.
1035 */
1036 stream->width = PFORMAT_IGNORE;
1037
1038 /* Reserve space in the output field, for display of the decimal point,
1039 * unless the precision is explicity zero, with the `#' flag not set.
1040 */
1041 if ((stream->width > 0)
1042 && ((stream->precision > 0) || (stream->flags & PFORMAT_HASHED)))
1043 stream->width--;
1044
1045 if (len > 0 && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0)
1046 {
1047 int cths = ((len + 2) / 3) - 1;
1048 while (cths > 0 && stream->width > 0)
1049 {
1050 --cths; stream->width--;
1051 }
1052 }
1053
1054 /* Reserve space in the output field, for display of the sign of the
1055 * formatted value, if required; (i.e. if the value is negative, or if
1056 * either the `space' or `+' formatting flags are set).
1057 */
1058 if( (stream->width > 0) && (sign || (stream->flags & PFORMAT_SIGNED)) )
1059 stream->width--;
1060
1061 /* Emit any padding space, as required to correctly right justify
1062 * the output within the alloted field width.
1063 */
1064 if( (stream->width > 0) && ((stream->flags & PFORMAT_JUSTIFY) == 0) )
1065 while( stream->width-- > 0 )
1066 __pformat_putc( '\x20', stream );
1067
1068 /* Emit the sign indicator, as appropriate...
1069 */
1070 if( sign )
1071 /*
1072 * mandatory, for negative values...
1073 */
1074 __pformat_putc( '-', stream );
1075
1076 else if( stream->flags & PFORMAT_POSITIVE )
1077 /*
1078 * optional, for positive values...
1079 */
1080 __pformat_putc( '+', stream );
1081
1082 else if( stream->flags & PFORMAT_ADDSPACE )
1083 /*
1084 * or just fill reserved space, when the space flag is in effect.
1085 */
1086 __pformat_putc( '\x20', stream );
1087
1088 /* If the `0' flag is in effect, and not overridden by the `-' flag,
1089 * then zero padding, to fill out the field, goes here...
1090 */
1091 if( (stream->width > 0)
1092 && ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) )
1093 while( stream->width-- > 0 )
1094 __pformat_putc( '0', stream );
1095
1096 /* Emit the digits of the encoded numeric value...
1097 */
1098 if( len > 0 )
1099 {
1100 /*
1101 * ...beginning with those which precede the radix point,
1102 * and appending any necessary significant trailing zeros.
1103 */
1104 do {
1105 __pformat_putc( *value ? *value++ : '0', stream);
1106 --len;
1107 if (len != 0 && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0
1108 && (len % 3) == 0)
1109 __pformat_wputchars (&stream->thousands_chr, 1, stream);
1110 }
1111 while (len > 0);
1112 }
1113 else
1114 /* The magnitude of the encoded value is less than 1.0, so no
1115 * digits precede the radix point; we emit a mandatory initial
1116 * zero, followed immediately by the radix point.
1117 */
1118 __pformat_putc( '0', stream );
1119
1120 /* Unless the encoded value is integral, AND the radix point
1121 * is not expressly demanded by the `#' flag, we must insert
1122 * the appropriately localised radix point mark here...
1123 */
1124 if( (stream->precision > 0) || (stream->flags & PFORMAT_HASHED) )
1125 __pformat_emit_radix_point( stream );
1126
1127 /* When the radix point offset, `len', is negative, this implies
1128 * that additional zeros must appear, following the radix point,
1129 * and preceding the first significant digit...
1130 */
1131 if( len < 0 )
1132 {
1133 /* To accommodate these, we adjust the precision, (reducing it
1134 * by adding a negative value), and then we emit as many zeros
1135 * as are required.
1136 */
1137 stream->precision += len;
1138 do __pformat_putc( '0', stream );
1139 while( ++len < 0 );
1140 }
1141
1142 /* Now we emit any remaining significant digits, or trailing zeros,
1143 * until the required precision has been achieved.
1144 */
1145 while( stream->precision-- > 0 )
1146 __pformat_putc( *value ? *value++ : '0', stream );
1147}
1148
1149static
1150void __pformat_emit_efloat( int sign, char *value, int e, __pformat_t *stream )
1151{
1152 /* Helper to emit a floating point representation of numeric data,
1153 * as encoded by a prior call to `ecvt()' or `fcvt()'; (this DOES
1154 * include the following exponent).
1155 */
1156 int exp_width = 1;
1157 __pformat_intarg_t exponent; exponent.__pformat_llong_t = e -= 1;
1158
1159 /* Determine how many digit positions are required for the exponent.
1160 */
1161 while( (e /= 10) != 0 )
1162 exp_width++;
1163
1164 /* Ensure that this is at least as many as the standard requirement.
1165 */
1166 if( exp_width < stream->expmin )
1167 exp_width = stream->expmin;
1168
1169 /* Adjust the residual field width allocation, to allow for the
1170 * number of exponent digits to be emitted, together with a sign
1171 * and exponent separator...
1172 */
1173 if( stream->width > (exp_width += 2) )
1174 stream->width -= exp_width;
1175
1176 else
1177 /* ignoring the field width specification, if insufficient.
1178 */
1179 stream->width = PFORMAT_IGNORE;
1180
1181 /* Emit the significand, as a fixed point value with one digit
1182 * preceding the radix point.
1183 */
1184 __pformat_emit_float( sign, value, 1, stream );
1185
1186 /* Reset precision, to ensure the mandatory minimum number of
1187 * exponent digits will be emitted, and set the flags to ensure
1188 * the sign is displayed.
1189 */
1190 stream->precision = stream->expmin;
1191 stream->flags |= PFORMAT_SIGNED;
1192
1193 /* Emit the exponent separator.
1194 */
1195 __pformat_putc( ('E' | (stream->flags & PFORMAT_XCASE)), stream );
1196
1197 /* Readjust the field width setting, such that it again allows
1198 * for the digits of the exponent, (which had been discounted when
1199 * computing any left side padding requirement), so that they are
1200 * correctly included in the computation of any right side padding
1201 * requirement, (but here we exclude the exponent separator, which
1202 * has been emitted, and so counted already).
1203 */
1204 stream->width += exp_width - 1;
1205
1206 /* And finally, emit the exponent itself, as a signed integer,
1207 * with any padding required to achieve flush left justification,
1208 * (which will be added automatically, by `__pformat_int()').
1209 */
1210 __pformat_int( exponent, stream );
1211}
1212
1213static
1214void __pformat_float( long double x, __pformat_t *stream )
1215{
1216 /* Handler for `%f' and `%F' format specifiers.
1217 *
1218 * This wraps calls to `__pformat_cvt()', `__pformat_emit_float()'
1219 * and `__pformat_emit_inf_or_nan()', as appropriate, to achieve
1220 * output in fixed point format.
1221 */
1222 int sign, intlen; char *value;
1223
1224 /* Establish the precision for the displayed value, defaulting to six
1225 * digits following the decimal point, if not explicitly specified.
1226 */
1227 if( stream->precision < 0 )
1228 stream->precision = 6;
1229
1230 /* Encode the input value as ASCII, for display...
1231 */
1232 value = __pformat_fcvt( x, stream->precision, &intlen, &sign );
1233
1234 if( intlen == PFORMAT_INFNAN )
1235 /*
1236 * handle cases of `infinity' or `not-a-number'...
1237 */
1238 __pformat_emit_inf_or_nan( sign, value, stream );
1239
1240 else
1241 { /* or otherwise, emit the formatted result.
1242 */
1243 __pformat_emit_float( sign, value, intlen, stream );
1244
1245 /* and, if there is any residual field width as yet unfilled,
1246 * then we must be doing flush left justification, so pad out to
1247 * the right hand field boundary.
1248 */
1249 while( stream->width-- > 0 )
1250 __pformat_putc( '\x20', stream );
1251 }
1252
1253 /* Clean up `__pformat_fcvt()' memory allocation for `value'...
1254 */
1255 __pformat_fcvt_release( value );
1256}
1257
1258static
1259void __pformat_efloat( long double x, __pformat_t *stream )
1260{
1261 /* Handler for `%e' and `%E' format specifiers.
1262 *
1263 * This wraps calls to `__pformat_cvt()', `__pformat_emit_efloat()'
1264 * and `__pformat_emit_inf_or_nan()', as appropriate, to achieve
1265 * output in floating point format.
1266 */
1267 int sign, intlen; char *value;
1268
1269 /* Establish the precision for the displayed value, defaulting to six
1270 * digits following the decimal point, if not explicitly specified.
1271 */
1272 if( stream->precision < 0 )
1273 stream->precision = 6;
1274
1275 /* Encode the input value as ASCII, for display...
1276 */
1277 value = __pformat_ecvt( x, stream->precision + 1, &intlen, &sign );
1278
1279 if( intlen == PFORMAT_INFNAN )
1280 /*
1281 * handle cases of `infinity' or `not-a-number'...
1282 */
1283 __pformat_emit_inf_or_nan( sign, value, stream );
1284
1285 else
1286 /* or otherwise, emit the formatted result.
1287 */
1288 __pformat_emit_efloat( sign, value, intlen, stream );
1289
1290 /* Clean up `__pformat_ecvt()' memory allocation for `value'...
1291 */
1292 __pformat_ecvt_release( value );
1293}
1294
1295static
1296void __pformat_gfloat( long double x, __pformat_t *stream )
1297{
1298 /* Handler for `%g' and `%G' format specifiers.
1299 *
1300 * This wraps calls to `__pformat_cvt()', `__pformat_emit_float()',
1301 * `__pformat_emit_efloat()' and `__pformat_emit_inf_or_nan()', as
1302 * appropriate, to achieve output in the more suitable of either
1303 * fixed or floating point format.
1304 */
1305 int sign, intlen; char *value;
1306
1307 /* Establish the precision for the displayed value, defaulting to
1308 * six significant digits, if not explicitly specified...
1309 */
1310 if( stream->precision < 0 )
1311 stream->precision = 6;
1312
1313 /* or to a minimum of one digit, otherwise...
1314 */
1315 else if( stream->precision == 0 )
1316 stream->precision = 1;
1317
1318 /* Encode the input value as ASCII, for display.
1319 */
1320 value = __pformat_ecvt( x, stream->precision, &intlen, &sign );
1321
1322 if( intlen == PFORMAT_INFNAN )
1323 /*
1324 * Handle cases of `infinity' or `not-a-number'.
1325 */
1326 __pformat_emit_inf_or_nan( sign, value, stream );
1327
1328 else if( (-4 < intlen) && (intlen <= stream->precision) )
1329 {
1330 /* Value lies in the acceptable range for fixed point output,
1331 * (i.e. the exponent is no less than minus four, and the number
1332 * of significant digits which precede the radix point is fewer
1333 * than the least number which would overflow the field width,
1334 * specified or implied by the established precision).
1335 */
1336 if( (stream->flags & PFORMAT_HASHED) == PFORMAT_HASHED )
1337 /*
1338 * The `#' flag is in effect...
1339 * Adjust precision to retain the specified number of significant
1340 * digits, with the proper number preceding the radix point, and
1341 * the balance following it...
1342 */
1343 stream->precision -= intlen;
1344
1345 else
1346 /* The `#' flag is not in effect...
1347 * Here we adjust the precision to accommodate all digits which
1348 * precede the radix point, but we truncate any balance following
1349 * it, to suppress output of non-significant trailing zeros...
1350 */
1351 if( ((stream->precision = strlen( value ) - intlen) < 0)
1352 /*
1353 * This may require a compensating adjustment to the field
1354 * width, to accommodate significant trailing zeros, which
1355 * precede the radix point...
1356 */
1357 && (stream->width > 0) )
1358 stream->width += stream->precision;
1359
1360 /* Now, we format the result as any other fixed point value.
1361 */
1362 __pformat_emit_float( sign, value, intlen, stream );
1363
1364 /* If there is any residual field width as yet unfilled, then
1365 * we must be doing flush left justification, so pad out to the
1366 * right hand field boundary.
1367 */
1368 while( stream->width-- > 0 )
1369 __pformat_putc( '\x20', stream );
1370 }
1371
1372 else
1373 { /* Value lies outside the acceptable range for fixed point;
1374 * one significant digit will precede the radix point, so we
1375 * decrement the precision to retain only the appropriate number
1376 * of additional digits following it, when we emit the result
1377 * in floating point format.
1378 */
1379 if( (stream->flags & PFORMAT_HASHED) == PFORMAT_HASHED )
1380 /*
1381 * The `#' flag is in effect...
1382 * Adjust precision to emit the specified number of significant
1383 * digits, with one preceding the radix point, and the balance
1384 * following it, retaining any non-significant trailing zeros
1385 * which are required to exactly match the requested precision...
1386 */
1387 stream->precision--;
1388
1389 else
1390 /* The `#' flag is not in effect...
1391 * Adjust precision to emit only significant digits, with one
1392 * preceding the radix point, and any others following it, but
1393 * suppressing non-significant trailing zeros...
1394 */
1395 stream->precision = strlen( value ) - 1;
1396
1397 /* Now, we format the result as any other floating point value.
1398 */
1399 __pformat_emit_efloat( sign, value, intlen, stream );
1400 }
1401
1402 /* Clean up `__pformat_ecvt()' memory allocation for `value'.
1403 */
1404 __pformat_ecvt_release( value );
1405}
1406
1407static
1408void __pformat_emit_xfloat( __pformat_fpreg_t value, __pformat_t *stream )
1409{
1410 /* Helper for emitting floating point data, originating as
1411 * either `double' or `long double' type, as a hexadecimal
1412 * representation of the argument value.
1413 */
1414 char buf[18 + 6], *p = buf;
1415 __pformat_intarg_t exponent; short exp_width = 2;
1416
1417 /* The mantissa field of the argument value representation can
1418 * accommodate at most 16 hexadecimal digits, of which one will
1419 * be placed before the radix point, leaving at most 15 digits
1420 * to satisfy any requested precision; thus...
1421 */
1422 if( (stream->precision >= 0) && (stream->precision < 15) )
1423 {
1424 /* When the user specifies a precision within this range,
1425 * we want to adjust the mantissa, to retain just the number
1426 * of digits required, rounding up when the high bit of the
1427 * leftmost discarded digit is set; (mask of 0x08 accounts
1428 * for exactly one digit discarded, shifting 4 bits per
1429 * digit, with up to 14 additional digits, to consume the
1430 * full availability of 15 precision digits).
1431 *
1432 * However, before we perform the rounding operation, we
1433 * normalise the mantissa, shifting it to the left by as many
1434 * bit positions may be necessary, until its highest order bit
1435 * is set, thus preserving the maximum number of bits in the
1436 * rounded result as possible.
1437 */
1438 while( value.__pformat_fpreg_mantissa < (LLONG_MAX + 1ULL) )
1439 value.__pformat_fpreg_mantissa <<= 1;
1440
1441 /* We then shift the mantissa one bit position back to the
1442 * right, to guard against possible overflow when the rounding
1443 * adjustment is added.
1444 */
1445 value.__pformat_fpreg_mantissa >>= 1;
1446
1447 /* We now add the rounding adjustment, noting that to keep the
1448 * 0x08 mask aligned with the shifted mantissa, we also need to
1449 * shift it right by one bit initially, changing its starting
1450 * value to 0x04...
1451 */
1452 value.__pformat_fpreg_mantissa += 0x04LL << (4 * (14 - stream->precision));
1453 if( (value.__pformat_fpreg_mantissa & (LLONG_MAX + 1ULL)) == 0ULL )
1454 /*
1455 * When the rounding adjustment would not have overflowed,
1456 * then we shift back to the left again, to fill the vacated
1457 * bit we reserved to accommodate the carry.
1458 */
1459 value.__pformat_fpreg_mantissa <<= 1;
1460
1461 else
1462 /* Otherwise the rounding adjustment would have overflowed,
1463 * so the carry has already filled the vacated bit; the effect
1464 * of this is equivalent to an increment of the exponent.
1465 */
1466 value.__pformat_fpreg_exponent++;
1467
1468 /* We now complete the rounding to the required precision, by
1469 * shifting the unwanted digits out, from the right hand end of
1470 * the mantissa.
1471 */
1472 value.__pformat_fpreg_mantissa >>= 4 * (15 - stream->precision);
1473 }
1474
1475 /* Encode the significant digits of the mantissa in hexadecimal
1476 * ASCII notation, ready for transfer to the output stream...
1477 */
1478 while( value.__pformat_fpreg_mantissa )
1479 {
1480 /* taking the rightmost digit in each pass...
1481 */
1482 int c = value.__pformat_fpreg_mantissa & 0xF;
1483 if( c == (int) value.__pformat_fpreg_mantissa)
1484 {
1485 /* inserting the radix point, when we reach the last,
1486 * (i.e. the most significant digit), unless we found no
1487 * less significant digits, with no mandatory radix point
1488 * inclusion, and no additional required precision...
1489 */
1490 if( (p > buf)
1491 || (stream->flags & PFORMAT_HASHED) || (stream->precision > 0) )
1492 {
1493 /*
1494 * Internally, we represent the radix point as an ASCII '.';
1495 * we will replace it with any locale specific alternative,
1496 * at the time of transfer to the ultimate destination.
1497 */
1498 *p++ = '.';
1499 }
1500
1501 /* If the most significant hexadecimal digit of the encoded
1502 * output value is greater than one, then the indicated value
1503 * will appear too large, by an additional binary exponent
1504 * corresponding to the number of higher order bit positions
1505 * which it occupies...
1506 */
1507 while( value.__pformat_fpreg_mantissa > 1 )
1508 {
1509 /* so reduce the exponent value to compensate...
1510 */
1511 value.__pformat_fpreg_exponent--;
1512 value.__pformat_fpreg_mantissa >>= 1;
1513 }
1514 }
1515
1516 else if( stream->precision > 0 )
1517 /*
1518 * we have not yet fulfilled the desired precision,
1519 * and we have not yet found the most significant digit,
1520 * so account for the current digit, within the field
1521 * width required to meet the specified precision.
1522 */
1523 stream->precision--;
1524
1525 if( (c > 0) || (p > buf) || (stream->precision >= 0) )
1526 {
1527 /*
1528 * Ignoring insignificant trailing zeros, (unless required to
1529 * satisfy specified precision), store the current encoded digit
1530 * into the pending output buffer, in LIFO order, and using the
1531 * appropriate case for digits in the `A'..`F' range.
1532 */
1533 *p++ = c > 9 ? (c - 10 + 'A') | (stream->flags & PFORMAT_XCASE) : c + '0';
1534 }
1535 /* Shift out the current digit, (4-bit logical shift right),
1536 * to align the next more significant digit to be extracted,
1537 * and encoded in the next pass.
1538 */
1539 value.__pformat_fpreg_mantissa >>= 4;
1540 }
1541
1542 if( p == buf )
1543 {
1544 /* Nothing has been queued for output...
1545 * We need at least one zero, and possibly a radix point.
1546 */
1547 if( (stream->precision > 0) || (stream->flags & PFORMAT_HASHED) )
1548 *p++ = '.';
1549
1550 *p++ = '0';
1551 }
1552
1553 if( stream->width > 0 )
1554 {
1555 /* Adjust the user specified field width, to account for the
1556 * number of digits minimally required, to display the encoded
1557 * value, at the requested precision.
1558 *
1559 * FIXME: this uses the minimum number of digits possible for
1560 * representation of the binary exponent, in strict conformance
1561 * with C99 and POSIX specifications. Although there appears to
1562 * be no Microsoft precedent for doing otherwise, we may wish to
1563 * relate this to the `_get_output_format()' result, to maintain
1564 * consistency with `%e', `%f' and `%g' styles.
1565 */
1566 int min_width = p - buf;
1567 int exponent2 = value.__pformat_fpreg_exponent;
1568
1569 /* If we have not yet queued sufficient digits to fulfil the
1570 * requested precision, then we must adjust the minimum width
1571 * specification, to accommodate the additional digits which
1572 * are required to do so.
1573 */
1574 if( stream->precision > 0 )
1575 min_width += stream->precision;
1576
1577 /* Adjust the minimum width requirement, to accomodate the
1578 * sign, radix indicator and at least one exponent digit...
1579 */
1580 min_width += stream->flags & PFORMAT_SIGNED ? 6 : 5;
1581 while( (exponent2 = exponent2 / 10) != 0 )
1582 {
1583 /* and increase as required, if additional exponent digits
1584 * are needed, also saving the exponent field width adjustment,
1585 * for later use when that is emitted.
1586 */
1587 min_width++;
1588 exp_width++;
1589 }
1590
1591 if( stream->width > min_width )
1592 {
1593 /* When specified field width exceeds the minimum required,
1594 * adjust to retain only the excess...
1595 */
1596 stream->width -= min_width;
1597
1598 /* and then emit any required left side padding spaces.
1599 */
1600 if( (stream->flags & PFORMAT_JUSTIFY) == 0 )
1601 while( stream->width-- > 0 )
1602 __pformat_putc( '\x20', stream );
1603 }
1604
1605 else
1606 /* Specified field width is insufficient; just ignore it!
1607 */
1608 stream->width = PFORMAT_IGNORE;
1609 }
1610
1611 /* Emit the sign of the encoded value, as required...
1612 */
1613 if( stream->flags & PFORMAT_NEGATIVE )
1614 /*
1615 * this is mandatory, to indicate a negative value...
1616 */
1617 __pformat_putc( '-', stream );
1618
1619 else if( stream->flags & PFORMAT_POSITIVE )
1620 /*
1621 * but this is optional, for a positive value...
1622 */
1623 __pformat_putc( '+', stream );
1624
1625 else if( stream->flags & PFORMAT_ADDSPACE )
1626 /*
1627 * with this optional alternative.
1628 */
1629 __pformat_putc( '\x20', stream );
1630
1631 /* Prefix a `0x' or `0X' radix indicator to the encoded value,
1632 * with case appropriate to the format specification.
1633 */
1634 __pformat_putc( '0', stream );
1635 __pformat_putc( 'X' | (stream->flags & PFORMAT_XCASE), stream );
1636
1637 /* If the `0' flag is in effect...
1638 * Zero padding, to fill out the field, goes here...
1639 */
1640 if( (stream->width > 0) && (stream->flags & PFORMAT_ZEROFILL) )
1641 while( stream->width-- > 0 )
1642 __pformat_putc( '0', stream );
1643
1644 /* Next, we emit the encoded value, without its exponent...
1645 */
1646 while( p > buf )
1647 __pformat_emit_numeric_value( *--p, stream );
1648
1649 /* followed by any additional zeros needed to satisfy the
1650 * precision specification...
1651 */
1652 while( stream->precision-- > 0 )
1653 __pformat_putc( '0', stream );
1654
1655 /* then the exponent prefix, (C99 and POSIX specify `p'),
1656 * in the case appropriate to the format specification...
1657 */
1658 __pformat_putc( 'P' | (stream->flags & PFORMAT_XCASE), stream );
1659
1660 /* and finally, the decimal representation of the binary exponent,
1661 * as a signed value with mandatory sign displayed, in a field width
1662 * adjusted to accommodate it, LEFT justified, with any additional
1663 * right side padding remaining from the original field width.
1664 */
1665 stream->width += exp_width;
1666 stream->flags |= PFORMAT_SIGNED;
1667 exponent.__pformat_llong_t = value.__pformat_fpreg_exponent;
1668 __pformat_int( exponent, stream );
1669}
1670
1671static
1672void __pformat_xldouble( long double x, __pformat_t *stream )
1673{
1674 /* Handler for `%La' and `%LA' format specifiers, (with argument
1675 * value specified as `long double' type).
1676 */
1677 unsigned sign_bit = 0;
1678 __pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x;
1679
1680 /* First check for NaN; it is emitted unsigned...
1681 */
1682 if( isnan( x ) )
1683 __pformat_emit_inf_or_nan( sign_bit, "NaN", stream );
1684
1685 else
1686 { /* Capture the sign bit up-front, so we can show it correctly
1687 * even when the argument value is zero or infinite.
1688 */
1689 if( (sign_bit = (z.__pformat_fpreg_exponent & 0x8000)) != 0 )
1690 stream->flags |= PFORMAT_NEGATIVE;
1691
1692 /* Check for infinity, (positive or negative)...
1693 */
1694 if( isinf( x ) )
1695 /*
1696 * displaying the appropriately signed indicator,
1697 * when appropriate.
1698 */
1699 __pformat_emit_inf_or_nan( sign_bit, "Inf", stream );
1700
1701 else
1702 { /* The argument value is a representable number...
1703 * extract the effective value of the biased exponent...
1704 */
1705 z.__pformat_fpreg_exponent &= 0x7FFF;
1706 if( z.__pformat_fpreg_exponent == 0 )
1707 {
1708 /* A biased exponent value of zero means either a
1709 * true zero value, if the mantissa field also has
1710 * a zero value, otherwise...
1711 */
1712 if( z.__pformat_fpreg_mantissa != 0 )
1713 {
1714 /* ...this mantissa represents a subnormal value;
1715 * adjust the exponent, while shifting the mantissa
1716 * to the left, until its leading bit is 1.
1717 */
1718 z.__pformat_fpreg_exponent = 1-0x3FFF;
1719 while( (z.__pformat_fpreg_mantissa & (LLONG_MAX + 1ULL)) == 0 )
1720 {
1721 z.__pformat_fpreg_mantissa <<= 1;
1722 --z.__pformat_fpreg_exponent;
1723 }
1724 }
1725 }
1726 else
1727 /* This argument represents a non-zero normal number;
1728 * eliminate the bias from the exponent...
1729 */
1730 z.__pformat_fpreg_exponent -= 0x3FFF;
1731
1732 /* Finally, hand the adjusted representation off to the
1733 * generalised hexadecimal floating point format handler...
1734 */
1735 __pformat_emit_xfloat( z, stream );
1736 }
1737 }
1738}
1739
1740int __cdecl
1741_evil_pformat (int flags, void *dest, int max, const APICHAR *fmt, va_list argv)
1742{
1743 int c;
1744 int saved_errno = errno;
1745
1746 __pformat_t stream =
1747 {
1748 /* Create and initialise a format control block
1749 * for this output request.
1750 */
1751 dest, /* output goes to here */
1752 flags &= PFORMAT_TO_FILE | PFORMAT_NOLIMIT, /* only these valid initially */
1753 PFORMAT_IGNORE, /* no field width yet */
1754 PFORMAT_IGNORE, /* nor any precision spec */
1755 PFORMAT_RPINIT, /* radix point uninitialised */
1756 (wchar_t)(0), /* leave it unspecified */
1757 0,
1758 (wchar_t)(0), /* leave it unspecified */
1759 0, /* zero output char count */
1760 max, /* establish output limit */
1761 PFORMAT_MINEXP /* exponent chars preferred */
1762 };
1763
1764 format_scan: while( (c = *fmt++) != 0 )
1765 {
1766 /* Format string parsing loop...
1767 * The entry point is labelled, so that we can return to the start state
1768 * from within the inner `conversion specification' interpretation loop,
1769 * as soon as a conversion specification has been resolved.
1770 */
1771 if( c == '%' )
1772 {
1773 /* Initiate parsing of a `conversion specification'...
1774 */
1775 __pformat_intarg_t argval;
1776 __pformat_state_t state = PFORMAT_INIT;
1777 __pformat_length_t length = PFORMAT_LENGTH_INT;
1778
1779 /* Save the current format scan position, so that we can backtrack
1780 * in the event of encountering an invalid format specification...
1781 */
1782 const APICHAR *backtrack = fmt;
1783
1784 /* Restart capture for dynamic field width and precision specs...
1785 */
1786 int *width_spec = &stream.width;
1787
1788 /* Reset initial state for flags, width and precision specs...
1789 */
1790 stream.flags = flags;
1791 stream.width = stream.precision = PFORMAT_IGNORE;
1792
1793 while( *fmt )
1794 {
1795 switch( c = *fmt++ )
1796 {
1797 /* Data type specifiers...
1798 * All are terminal, so exit the conversion spec parsing loop
1799 * with a `goto format_scan', thus resuming at the outer level
1800 * in the regular format string parser.
1801 */
1802 case '%':
1803 /*
1804 * Not strictly a data type specifier...
1805 * it simply converts as a literal `%' character.
1806 *
1807 * FIXME: should we require this to IMMEDIATELY follow the
1808 * initial `%' of the "conversion spec"? (glibc `printf()'
1809 * on GNU/Linux does NOT appear to require this, but POSIX
1810 * and SUSv3 do seem to demand it).
1811 */
1812 __pformat_putc( c, &stream );
1813 goto format_scan;
1814
1815 case 'C':
1816 /*
1817 * Equivalent to `%lc'; set `length' accordingly,
1818 * and simply fall through.
1819 */
1820 length = PFORMAT_LENGTH_LONG;
1821
1822 case 'c':
1823 /*
1824 * Single, (or single multibyte), character output...
1825 *
1826 * We handle these by copying the argument into our local
1827 * `argval' buffer, and then we pass the address of that to
1828 * either `__pformat_putchars()' or `__pformat_wputchars()',
1829 * as appropriate, effectively formatting it as a string of
1830 * the appropriate type, with a length of one.
1831 *
1832 * A side effect of this method of handling character data
1833 * is that, if the user sets a precision of zero, then no
1834 * character is actually emitted; we don't want that, so we
1835 * forcibly override any user specified precision.
1836 */
1837 stream.precision = PFORMAT_IGNORE;
1838
1839 /* Now we invoke the appropriate format handler...
1840 */
1841 if( (length == PFORMAT_LENGTH_LONG)
1842 || (length == PFORMAT_LENGTH_LLONG) )
1843 {
1844 /* considering any `long' type modifier as a reference to
1845 * `wchar_t' data, (which is promoted to an `int' argument)...
1846 */
1847 wchar_t iargval = (wchar_t)(va_arg( argv, int ));
1848 __pformat_wputchars( &iargval, 1, &stream );
1849 }
1850 else
1851 { /* while anything else is simply taken as `char', (which
1852 * is also promoted to an `int' argument)...
1853 */
1854 argval.__pformat_uchar_t = (unsigned char)(va_arg( argv, int ));
1855 __pformat_putchars( (char *)(&argval), 1, &stream );
1856 }
1857 goto format_scan;
1858
1859 case 'S':
1860 /*
1861 * Equivalent to `%ls'; set `length' accordingly,
1862 * and simply fall through.
1863 */
1864 length = PFORMAT_LENGTH_LONG;
1865
1866 case 's':
1867 if( (length == PFORMAT_LENGTH_LONG)
1868 || (length == PFORMAT_LENGTH_LLONG))
1869 {
1870 /* considering any `long' type modifier as a reference to
1871 * a `wchar_t' string...
1872 */
1873 __pformat_wcputs( va_arg( argv, wchar_t * ), &stream );
1874 }
1875 else
1876 /* This is normal string output;
1877 * we simply invoke the appropriate handler...
1878 */
1879 __pformat_puts( va_arg( argv, char * ), &stream );
1880 goto format_scan;
1881 case 'm': /* strerror (errno) */
1882 __pformat_puts (strerror (saved_errno), &stream);
1883 goto format_scan;
1884
1885 case 'o':
1886 case 'u':
1887 case 'x':
1888 case 'X':
1889 /*
1890 * Unsigned integer values; octal, decimal or hexadecimal format...
1891 */
1892 if( length == PFORMAT_LENGTH_LLONG )
1893 /*
1894 * with an `unsigned long long' argument, which we
1895 * process `as is'...
1896 */
1897 argval.__pformat_ullong_t = va_arg( argv, unsigned long long );
1898
1899 else if( length == PFORMAT_LENGTH_LONG )
1900 /*
1901 * or with an `unsigned long', which we promote to
1902 * `unsigned long long'...
1903 */
1904 argval.__pformat_ullong_t = va_arg( argv, unsigned long );
1905
1906 else
1907 { /* or for any other size, which will have been promoted
1908 * to `unsigned int', we select only the appropriately sized
1909 * least significant segment, and again promote to the same
1910 * size as `unsigned long long'...
1911 */
1912 argval.__pformat_ullong_t = va_arg( argv, unsigned int );
1913 if( length == PFORMAT_LENGTH_SHORT )
1914 /*
1915 * from `unsigned short'...
1916 */
1917 argval.__pformat_ullong_t = argval.__pformat_ushort_t;
1918
1919 else if( length == PFORMAT_LENGTH_CHAR )
1920 /*
1921 * or even from `unsigned char'...
1922 */
1923 argval.__pformat_ullong_t = argval.__pformat_uchar_t;
1924 }
1925
1926 /* so we can pass any size of argument to either of two
1927 * common format handlers...
1928 */
1929 if( c == 'u' )
1930 /*
1931 * depending on whether output is to be encoded in
1932 * decimal format...
1933 */
1934 __pformat_int( argval, &stream );
1935
1936 else
1937 /* or in octal or hexadecimal format...
1938 */
1939 __pformat_xint( c, argval, &stream );
1940
1941 goto format_scan;
1942
1943 case 'd':
1944 case 'i':
1945 /*
1946 * Signed integer values; decimal format...
1947 * This is similar to `u', but must process `argval' as signed,
1948 * and be prepared to handle negative numbers.
1949 */
1950 stream.flags |= PFORMAT_NEGATIVE;
1951
1952 if( length == PFORMAT_LENGTH_LLONG )
1953 /*
1954 * The argument is a `long long' type...
1955 */
1956 argval.__pformat_llong_t = va_arg( argv, long long );
1957
1958 else if( length == PFORMAT_LENGTH_LONG )
1959 /*
1960 * or here, a `long' type...
1961 */
1962 argval.__pformat_llong_t = va_arg( argv, long );
1963
1964 else
1965 { /* otherwise, it's an `int' type...
1966 */
1967 argval.__pformat_llong_t = va_arg( argv, int );
1968 if( length == PFORMAT_LENGTH_SHORT )
1969 /*
1970 * but it was promoted from a `short' type...
1971 */
1972 argval.__pformat_llong_t = argval.__pformat_short_t;
1973 else if( length == PFORMAT_LENGTH_CHAR )
1974 /*
1975 * or even from a `char' type...
1976 */
1977 argval.__pformat_llong_t = argval.__pformat_char_t;
1978 }
1979
1980 /* In any case, all share a common handler...
1981 */
1982 __pformat_int( argval, &stream );
1983 goto format_scan;
1984
1985 case 'p':
1986 /*
1987 * Pointer argument; format as hexadecimal, subject to...
1988 */
1989 if( (state == PFORMAT_INIT) && (stream.flags == flags) )
1990 {
1991 /* Here, the user didn't specify any particular
1992 * formatting attributes. We must choose a default
1993 * which will be compatible with Microsoft's (broken)
1994 * scanf() implementation, (i.e. matching the default
1995 * used by MSVCRT's printf(), which appears to resemble
1996 * "%0.8X" for 32-bit pointers); in particular, we MUST
1997 * NOT adopt a GNU-like format resembling "%#x", because
1998 * Microsoft's scanf() will choke on the "0x" prefix.
1999 */
2000 stream.flags |= PFORMAT_ZEROFILL;
2001 stream.precision = 2 * sizeof( uintptr_t );
2002 }
2003 argval.__pformat_ullong_t = va_arg( argv, uintptr_t );
2004 __pformat_xint( 'x', argval, &stream );
2005 goto format_scan;
2006
2007 case 'e':
2008 /*
2009 * Floating point format, with lower case exponent indicator
2010 * and lower case `inf' or `nan' representation when required;
2011 * select lower case mode, and simply fall through...
2012 */
2013 stream.flags |= PFORMAT_XCASE;
2014
2015 case 'E':
2016 /*
2017 * Floating point format, with upper case exponent indicator
2018 * and upper case `INF' or `NAN' representation when required,
2019 * (or lower case for all of these, on fall through from above);
2020 * select lower case mode, and simply fall through...
2021 */
2022 if( stream.flags & PFORMAT_LDOUBLE )
2023 /*
2024 * for a `long double' argument...
2025 */
2026 __pformat_efloat( va_arg( argv, long double ), &stream );
2027
2028 else
2029 /* or just a `double', which we promote to `long double',
2030 * so the two may share a common format handler.
2031 */
2032 __pformat_efloat( (long double)(va_arg( argv, double )), &stream );
2033
2034 goto format_scan;
2035
2036 case 'f':
2037 /*
2038 * Fixed point format, using lower case for `inf' and
2039 * `nan', when appropriate; select lower case mode, and
2040 * simply fall through...
2041 */
2042 stream.flags |= PFORMAT_XCASE;
2043
2044 case 'F':
2045 /*
2046 * Fixed case format using upper case, or lower case on
2047 * fall through from above, for `INF' and `NAN'...
2048 */
2049 if( stream.flags & PFORMAT_LDOUBLE )
2050 /*
2051 * for a `long double' argument...
2052 */
2053 __pformat_float( va_arg( argv, long double ), &stream );
2054
2055 else
2056 /* or just a `double', which we promote to `long double',
2057 * so the two may share a common format handler.
2058 */
2059 __pformat_float( (long double)(va_arg( argv, double )), &stream );
2060
2061 goto format_scan;
2062
2063 case 'g':
2064 /*
2065 * Generalised floating point format, with lower case
2066 * exponent indicator when required; select lower case
2067 * mode, and simply fall through...
2068 */
2069 stream.flags |= PFORMAT_XCASE;
2070
2071 case 'G':
2072 /*
2073 * Generalised floating point format, with upper case,
2074 * or on fall through from above, with lower case exponent
2075 * indicator when required...
2076 */
2077 if( stream.flags & PFORMAT_LDOUBLE )
2078 /*
2079 * for a `long double' argument...
2080 */
2081 __pformat_gfloat( va_arg( argv, long double ), &stream );
2082
2083 else
2084 /* or just a `double', which we promote to `long double',
2085 * so the two may share a common format handler.
2086 */
2087 __pformat_gfloat( (long double)(va_arg( argv, double )), &stream );
2088
2089 goto format_scan;
2090
2091 case 'a':
2092 /*
2093 * Hexadecimal floating point format, with lower case radix
2094 * and exponent indicators; select the lower case mode, and
2095 * fall through...
2096 */
2097 stream.flags |= PFORMAT_XCASE;
2098
2099 case 'A':
2100 /*
2101 * Hexadecimal floating point format; handles radix and
2102 * exponent indicators in either upper or lower case...
2103 */
2104 if( stream.flags & PFORMAT_LDOUBLE )
2105 /*
2106 * with a `long double' argument...
2107 */
2108 __pformat_xldouble( va_arg( argv, long double ), &stream );
2109
2110 else
2111 /* or just a `double'.
2112 */
2113 __pformat_xldouble( (long double)(va_arg( argv, double )), &stream );
2114
2115 goto format_scan;
2116
2117 case 'n':
2118 /*
2119 * Save current output character count...
2120 */
2121 if( length == PFORMAT_LENGTH_CHAR )
2122 /*
2123 * to a signed `char' destination...
2124 */
2125 *va_arg( argv, char * ) = stream.count;
2126
2127 else if( length == PFORMAT_LENGTH_SHORT )
2128 /*
2129 * or to a signed `short'...
2130 */
2131 *va_arg( argv, short * ) = stream.count;
2132
2133 else if( length == PFORMAT_LENGTH_LONG )
2134 /*
2135 * or to a signed `long'...
2136 */
2137 *va_arg( argv, long * ) = stream.count;
2138
2139 else if( length == PFORMAT_LENGTH_LLONG )
2140 /*
2141 * or to a signed `long long'...
2142 */
2143 *va_arg( argv, long long * ) = stream.count;
2144
2145 else
2146 /*
2147 * or, by default, to a signed `int'.
2148 */
2149 *va_arg( argv, int * ) = stream.count;
2150
2151 goto format_scan;
2152
2153 /* Argument length modifiers...
2154 * These are non-terminal; each sets the format parser
2155 * into the PFORMAT_END state, and ends with a `break'.
2156 */
2157 case 'h':
2158 /*
2159 * Interpret the argument as explicitly of a `short'
2160 * or `char' data type, truncated from the standard
2161 * length defined for integer promotion.
2162 */
2163 if( *fmt == 'h' )
2164 {
2165 /* Modifier is `hh'; data type is `char' sized...
2166 * Skip the second `h', and set length accordingly.
2167 */
2168 ++fmt;
2169 length = PFORMAT_LENGTH_CHAR;
2170 }
2171
2172 else
2173 /* Modifier is `h'; data type is `short' sized...
2174 */
2175 length = PFORMAT_LENGTH_SHORT;
2176
2177 state = PFORMAT_END;
2178 break;
2179
2180 case 'j':
2181 /*
2182 * Interpret the argument as being of the same size as
2183 * a `intmax_t' entity...
2184 */
2185 length = __pformat_arg_length( intmax_t );
2186 state = PFORMAT_END;
2187 break;
2188
2189# ifdef _WIN32
2190
2191 case 'I':
2192 /*
2193 * The MSVCRT implementation of the printf() family of
2194 * functions explicitly uses...
2195 */
2196 if( (fmt[0] == '6') && (fmt[1] == '4') )
2197 {
2198 /* I64' instead of `ll',
2199 * when referring to `long long' integer types...
2200 */
2201 length = PFORMAT_LENGTH_LLONG;
2202 fmt += 2;
2203 }
2204
2205 else if( (fmt[0] == '3') && (fmt[1] == '2') )
2206 {
2207 /* and `I32' instead of `l',
2208 * when referring to `long' integer types...
2209 */
2210 length = PFORMAT_LENGTH_LONG;
2211 fmt += 2;
2212 }
2213
2214 else
2215 /* or unqualified `I' instead of `t' or `z',
2216 * when referring to `ptrdiff_t' or `size_t' entities;
2217 * (we will choose to map it to `ptrdiff_t').
2218 */
2219 length = __pformat_arg_length( ptrdiff_t );
2220
2221 state = PFORMAT_END;
2222 break;
2223
2224# endif
2225
2226 case 'l':
2227 /*
2228 * Interpret the argument as explicitly of a
2229 * `long' or `long long' data type.
2230 */
2231 if( *fmt == 'l' )
2232 {
2233 /* Modifier is `ll'; data type is `long long' sized...
2234 * Skip the second `l', and set length accordingly.
2235 */
2236 ++fmt;
2237 length = PFORMAT_LENGTH_LLONG;
2238 }
2239
2240 else
2241 /* Modifier is `l'; data type is `long' sized...
2242 */
2243 length = PFORMAT_LENGTH_LONG;
2244
2245 state = PFORMAT_END;
2246 break;
2247
2248 case 'L':
2249 /*
2250 * Identify the appropriate argument as a `long double',
2251 * when associated with `%a', `%A', `%e', `%E', `%f', `%F',
2252 * `%g' or `%G' format specifications.
2253 */
2254 stream.flags |= PFORMAT_LDOUBLE;
2255 state = PFORMAT_END;
2256 break;
2257
2258 case 't':
2259 /*
2260 * Interpret the argument as being of the same size as
2261 * a `ptrdiff_t' entity...
2262 */
2263 length = __pformat_arg_length( ptrdiff_t );
2264 state = PFORMAT_END;
2265 break;
2266
2267 case 'z':
2268 /*
2269 * Interpret the argument as being of the same size as
2270 * a `size_t' entity...
2271 */
2272 length = __pformat_arg_length( size_t );
2273 state = PFORMAT_END;
2274 break;
2275
2276 /* Precision indicator...
2277 * May appear once only; it must precede any modifier
2278 * for argument length, or any data type specifier.
2279 */
2280 case '.':
2281 if( state < PFORMAT_GET_PRECISION )
2282 {
2283 /* We haven't seen a precision specification yet,
2284 * so initialise it to zero, (in case no digits follow),
2285 * and accept any following digits as the precision.
2286 */
2287 stream.precision = 0;
2288 width_spec = &stream.precision;
2289 state = PFORMAT_GET_PRECISION;
2290 }
2291
2292 else
2293 /* We've already seen a precision specification,
2294 * so this is just junk; proceed to end game.
2295 */
2296 state = PFORMAT_END;
2297
2298 /* Either way, we must not fall through here.
2299 */
2300 break;
2301
2302 /* Variable field width, or precision specification,
2303 * derived from the argument list...
2304 */
2305 case '*':
2306 /*
2307 * When this appears...
2308 */
2309 if( width_spec
2310 && ((state == PFORMAT_INIT) || (state == PFORMAT_GET_PRECISION)) )
2311 {
2312 /* in proper context; assign to field width
2313 * or precision, as appropriate.
2314 */
2315 if( (*width_spec = va_arg( argv, int )) < 0 )
2316 {
2317 /* Assigned value was negative...
2318 */
2319 if( state == PFORMAT_INIT )
2320 {
2321 /* For field width, this is equivalent to
2322 * a positive value with the `-' flag...
2323 */
2324 stream.flags |= PFORMAT_LJUSTIFY;
2325 stream.width = -stream.width;
2326 }
2327
2328 else
2329 /* while as a precision specification,
2330 * it should simply be ignored.
2331 */
2332 stream.precision = PFORMAT_IGNORE;
2333 }
2334 }
2335
2336 else
2337 /* out of context; give up on width and precision
2338 * specifications for this conversion.
2339 */
2340 state = PFORMAT_END;
2341
2342 /* Mark as processed...
2343 * we must not see `*' again, in this context.
2344 */
2345 width_spec = NULL;
2346 break;
2347
2348 /* Formatting flags...
2349 * Must appear while in the PFORMAT_INIT state,
2350 * and are non-terminal, so again, end with `break'.
2351 */
2352 case '#':
2353 /*
2354 * Select alternate PFORMAT_HASHED output style.
2355 */
2356 if( state == PFORMAT_INIT )
2357 stream.flags |= PFORMAT_HASHED;
2358 break;
2359
2360 case '+':
2361 /*
2362 * Print a leading sign with numeric output,
2363 * for both positive and negative values.
2364 */
2365 if( state == PFORMAT_INIT )
2366 stream.flags |= PFORMAT_POSITIVE;
2367 break;
2368
2369 case '-':
2370 /*
2371 * Select left justification of displayed output
2372 * data, within the output field width, instead of
2373 * the default flush right justification.
2374 */
2375 if( state == PFORMAT_INIT )
2376 stream.flags |= PFORMAT_LJUSTIFY;
2377 break;
2378
2379 case '\'':
2380 /*
2381 * This is an XSI extension to the POSIX standard,
2382 * which we do not support, at present.
2383 */
2384 if (state == PFORMAT_INIT)
2385 {
2386 int len; wchar_t rpchr; mbstate_t cstate;
2387 stream.flags |= PFORMAT_GROUPED; /* $$$$ */
2388 memset (&cstate, 0, sizeof(state));
2389 if ((len = mbrtowc( &rpchr, localeconv()->thousands_sep, 16, &cstate)) > 0)
2390 stream.thousands_chr = rpchr;
2391 stream.thousands_chr_len = len;
2392 }
2393 break;
2394
2395 case '\x20':
2396 /*
2397 * Reserve a single space, within the output field,
2398 * for display of the sign of signed data; this will
2399 * be occupied by the minus sign, if the data value
2400 * is negative, or by a plus sign if the data value
2401 * is positive AND the `+' flag is also present, or
2402 * by a space otherwise. (Technically, this flag
2403 * is redundant, if the `+' flag is present).
2404 */
2405 if( state == PFORMAT_INIT )
2406 stream.flags |= PFORMAT_ADDSPACE;
2407 break;
2408
2409 case '0':
2410 /*
2411 * May represent a flag, to activate the `pad with zeros'
2412 * option, or it may simply be a digit in a width or in a
2413 * precision specification...
2414 */
2415 if( state == PFORMAT_INIT )
2416 {
2417 /* This is the flag usage...
2418 */
2419 stream.flags |= PFORMAT_ZEROFILL;
2420 break;
2421 }
2422
2423 default:
2424 /*
2425 * If we didn't match anything above, then we will check
2426 * for digits, which we may accumulate to generate field
2427 * width or precision specifications...
2428 */
2429 if( (state < PFORMAT_END) && ('9' >= c) && (c >= '0') )
2430 {
2431 if( state == PFORMAT_INIT )
2432 /*
2433 * Initial digits explicitly relate to field width...
2434 */
2435 state = PFORMAT_SET_WIDTH;
2436
2437 else if( state == PFORMAT_GET_PRECISION )
2438 /*
2439 * while those following a precision indicator
2440 * explicitly relate to precision.
2441 */
2442 state = PFORMAT_SET_PRECISION;
2443
2444 if( width_spec )
2445 {
2446 /* We are accepting a width or precision specification...
2447 */
2448 if( *width_spec < 0 )
2449 /*
2450 * and accumulation hasn't started yet; we simply
2451 * initialise the accumulator with the current digit
2452 * value, converting from ASCII to decimal.
2453 */
2454 *width_spec = c - '0';
2455
2456 else
2457 /* Accumulation has already started; we perform a
2458 * `leftwise decimal digit shift' on the accumulator,
2459 * (i.e. multiply it by ten), then add the decimal
2460 * equivalent value of the current digit.
2461 */
2462 *width_spec = *width_spec * 10 + c - '0';
2463 }
2464 }
2465
2466 else
2467 {
2468 /* We found a digit out of context, or some other character
2469 * with no designated meaning; reject this format specification,
2470 * backtrack, and emit it as literal text...
2471 */
2472 fmt = backtrack;
2473 __pformat_putc( '%', &stream );
2474 goto format_scan;
2475 }
2476 }
2477 }
2478 }
2479
2480 else
2481 /* We just parsed a character which is not included within any format
2482 * specification; we simply emit it as a literal.
2483 */
2484 __pformat_putc( c, &stream );
2485 }
2486
2487 /* When we have fully dispatched the format string, the return value is the
2488 * total number of bytes we transferred to the output destination.
2489 */
2490 return stream.count;
2491}
2492
2493/* $RCSfile: pformat.c,v $Revision: 1.9 $: end of file */
diff --git a/src/lib/evil/evil_pformatw.c b/src/lib/evil/evil_pformatw.c
deleted file mode 100644
index 592b56881c..0000000000
--- a/src/lib/evil/evil_pformatw.c
+++ /dev/null
@@ -1,9 +0,0 @@
1/**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the w64 mingw-runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6#define __BUILD_WIDEAPI 1
7
8#include "evil_pformata.c"
9
diff --git a/src/lib/evil/evil_print.h b/src/lib/evil/evil_print.h
deleted file mode 100644
index 511247bcbd..0000000000
--- a/src/lib/evil/evil_print.h
+++ /dev/null
@@ -1,37 +0,0 @@
1#ifndef __EVIL_PRINT_H__
2#define __EVIL_PRINT_H__
3
4
5#include "evil_macro.h"
6
7
8EAPI int __cdecl _evil_fprintfa(FILE *, const char *, ...) __EVIL_NOTHROW;
9EAPI int __cdecl _evil_printfa(const char *, ...) __EVIL_PRINTF(1, 2) __EVIL_NOTHROW;
10EAPI int __cdecl _evil_sprintfa(char *, const char *, ...) __EVIL_NOTHROW;
11EAPI int __cdecl _evil_snprintfa(char *, size_t, const char *, ...) __EVIL_PRINTF(3, 4) __EVIL_NOTHROW;
12EAPI int __cdecl _evil_vfprintfa(FILE *, const char *, va_list) __EVIL_NOTHROW;
13EAPI int __cdecl _evil_vprintfa(const char *, va_list) __EVIL_NOTHROW;
14EAPI int __cdecl _evil_vsprintfa(char *, const char *, va_list) __EVIL_NOTHROW;
15EAPI int __cdecl _evil_vsnprintfa(char *, size_t, const char *, va_list) __EVIL_NOTHROW;
16
17EAPI int __cdecl _evil_fscanf (FILE *, const char *, ...) __EVIL_NOTHROW;
18EAPI int __cdecl _evil_scanf (const char *, ...) __EVIL_NOTHROW;
19EAPI int __cdecl _evil_sscanf (const char *, const char *, ...) __EVIL_NOTHROW;
20EAPI int __cdecl _evil_vfscanf(FILE *, const char *, va_list) __EVIL_NOTHROW;
21EAPI int __cdecl _evil_vscanf (const char *, va_list) __EVIL_NOTHROW;
22EAPI int __cdecl _evil_vsscanf(const char *, const char *, va_list) __EVIL_NOTHROW;
23
24EAPI int __cdecl _evil_asprintf(char ** __restrict__, const char * __restrict__, ...) __EVIL_NOTHROW;
25EAPI int __cdecl _evil_vasprintf(char ** __restrict__, const char * __restrict__, va_list) __EVIL_NOTHROW;
26
27EAPI int __cdecl _evil_fprintfw(FILE *, const wchar_t *, ...) __EVIL_NOTHROW;
28EAPI int __cdecl _evil_printfw(const wchar_t *, ...) __EVIL_NOTHROW;
29EAPI int __cdecl _evil_sprintfw(wchar_t *, const wchar_t *, ...) __EVIL_NOTHROW;
30EAPI int __cdecl _evil_snprintfw(wchar_t *, size_t, const wchar_t *, ...) __EVIL_NOTHROW;
31EAPI int __cdecl _evil_vfprintfw(FILE *, const wchar_t *, va_list) __EVIL_NOTHROW;
32EAPI int __cdecl _evil_vprintfw(const wchar_t *, va_list) __EVIL_NOTHROW;
33EAPI int __cdecl _evil_vsprintfw(wchar_t *, const wchar_t *, va_list) __EVIL_NOTHROW;
34EAPI int __cdecl _evil_vsnprintfw(wchar_t *, size_t, const wchar_t *, va_list) __EVIL_NOTHROW;
35
36
37#endif /* __EVIL_PRINT_H__ */
diff --git a/src/lib/evil/evil_printa.c b/src/lib/evil/evil_printa.c
deleted file mode 100644
index a0f8593916..0000000000
--- a/src/lib/evil/evil_printa.c
+++ /dev/null
@@ -1,1768 +0,0 @@
1#define __CRT__NO_INLINE
2
3#include <errno.h>
4#include <limits.h>
5#include <stddef.h>
6#include <stdarg.h>
7#include <stdio.h>
8#include <stdint.h>
9#include <stdlib.h>
10#include <string.h>
11#include <wchar.h>
12#include <ctype.h>
13#include <wctype.h>
14#include <locale.h>
15
16#include "evil_pformat.h"
17#include "evil_print.h"
18#include "gdtoa/gdtoa.h"
19
20
21/*============================================================================*
22 * Local *
23 *============================================================================*/
24
25
26/* Helper flags for conversion. */
27#define IS_C 0x0001
28#define IS_S 0x0002
29#define IS_L 0x0004
30#define IS_LL 0x0008
31#define IS_SIGNED_NUM 0x0010
32#define IS_POINTER 0x0020
33#define IS_HEX_FLOAT 0x0040
34#define IS_SUPPRESSED 0x0080
35#define USE_GROUP 0x0100
36#define USE_GNU_ALLOC 0x0200
37#define USE_POSIX_ALLOC 0x0400
38
39#define IS_ALLOC_USED (USE_GNU_ALLOC | USE_POSIX_ALLOC)
40
41#ifndef __BUILD_WIDEAPI
42
43/* internal stream structure with back-buffer. */
44typedef struct _IFP
45{
46 __extension__ union {
47 void *fp;
48 const char *str;
49 };
50 int bch[1024];
51 int is_string : 1;
52 int back_top;
53 int seen_eof : 1;
54} _IFP;
55
56static void *
57get_va_nth (va_list argp, unsigned int n)
58{
59 va_list ap;
60 if (!n) abort ();
61 va_copy (ap, argp);
62 while (--n > 0)
63 (void) va_arg(ap, void *);
64 return va_arg (ap, void *);
65}
66
67static void
68optimize_alloc (char **p, char *end, size_t alloc_sz)
69{
70 size_t need_sz;
71 char *h;
72
73 if (!p || !*p)
74 return;
75
76 need_sz = end - *p;
77 if (need_sz == alloc_sz)
78 return;
79
80 if ((h = (char *) realloc (*p, need_sz)) != NULL)
81 *p = h;
82}
83
84static void
85back_ch (int c, _IFP *s, size_t *rin, int not_eof)
86{
87 if (!not_eof && c == EOF)
88 return;
89 if (s->is_string == 0)
90 {
91 FILE *fp = s->fp;
92 ungetc (c, fp);
93 rin[0] -= 1;
94 return;
95 }
96 rin[0] -= 1;
97 s->bch[s->back_top] = c;
98 s->back_top += 1;
99}
100
101static int
102in_ch (_IFP *s, size_t *rin)
103{
104 int r;
105 if (s->back_top)
106 {
107 s->back_top -= 1;
108 r = s->bch[s->back_top];
109 rin[0] += 1;
110 }
111 else if (s->seen_eof)
112 {
113 return EOF;
114 }
115 else if (s->is_string)
116 {
117 const char *ps = s->str;
118 r = ((int) *ps) & 0xff;
119 ps++;
120 if (r != 0)
121 {
122 rin[0] += 1;
123 s->str = ps;
124 return r;
125 }
126 s->seen_eof = 1;
127 return EOF;
128 }
129 else
130 {
131 FILE *fp = (FILE *) s->fp;
132 r = getc (fp);
133 if (r != EOF)
134 rin[0] += 1;
135 else s->seen_eof = 1;
136 }
137 return r;
138}
139
140static int
141match_string (_IFP *s, size_t *rin, int *c, const char *str)
142{
143 int ch = *c;
144
145 if (*str == 0)
146 return 1;
147
148 if (*str != (char) tolower (ch))
149 return 0;
150 ++str;
151 while (*str != 0)
152 {
153 if ((ch = in_ch (s, rin)) == EOF)
154 {
155 c[0] = ch;
156 return 0;
157 }
158
159 if (*str != (char) tolower (ch))
160 {
161 c[0] = ch;
162 return 0;
163 }
164 ++str;
165 }
166 c[0] = ch;
167 return 1;
168}
169
170struct gcollect
171{
172 size_t count;
173 struct gcollect *next;
174 char **ptrs[32];
175};
176
177static void
178release_ptrs (struct gcollect **pt, char **wbuf)
179{
180 struct gcollect *pf;
181 size_t cnt;
182
183 if (!pt || (pf = *pt) == NULL)
184 return;
185 while (pf != NULL)
186 {
187 struct gcollect *pf_sv = pf;
188 for (cnt = 0; cnt < pf->count; ++cnt)
189 {
190 free (*pf->ptrs[cnt]);
191 *pf->ptrs[cnt] = NULL;
192 }
193 pf = pf->next;
194 free (pf_sv);
195 }
196 *pt = NULL;
197 if (wbuf)
198 {
199 free (*wbuf);
200 *wbuf = NULL;
201 }
202}
203
204static int
205cleanup_return (int rval, struct gcollect **pfree, char **strp, char **wbuf)
206{
207 if (rval == EOF)
208 release_ptrs (pfree, wbuf);
209 else
210 {
211 if (pfree)
212 {
213 struct gcollect *pf = *pfree, *pf_sv;
214 while (pf != NULL)
215 {
216 pf_sv = pf;
217 pf = pf->next;
218 free (pf_sv);
219 }
220 *pfree = NULL;
221 }
222 if (strp != NULL)
223 {
224 free (*strp);
225 *strp = NULL;
226 }
227 if (wbuf)
228 {
229 free (*wbuf);
230 *wbuf = NULL;
231 }
232 }
233 return rval;
234}
235
236static struct gcollect *
237resize_gcollect (struct gcollect *pf)
238{
239 struct gcollect *np;
240 if (pf && pf->count < 32)
241 return pf;
242 np = malloc (sizeof (struct gcollect));
243 np->count = 0;
244 np->next = pf;
245 return np;
246}
247
248static char *
249resize_wbuf (size_t wpsz, size_t *wbuf_max_sz, char *old)
250{
251 char *wbuf;
252 size_t nsz;
253 if (*wbuf_max_sz != wpsz)
254 return old;
255 nsz = (256 > (2 * wbuf_max_sz[0]) ? 256 : (2 * wbuf_max_sz[0]));
256 if (!old)
257 wbuf = (char *) malloc (nsz);
258 else
259 wbuf = (char *) realloc (old, nsz);
260 if (!wbuf)
261 {
262 if (old)
263 free (old);
264 }
265 else
266 *wbuf_max_sz = nsz;
267 return wbuf;
268}
269
270static int
271_evil_sformat (_IFP *s, const char *format, va_list argp)
272{
273 const char *f = format;
274 struct gcollect *gcollect = NULL;
275 size_t read_in = 0, wbuf_max_sz = 0, cnt;
276 ssize_t str_sz = 0;
277 char *str = NULL, **pstr = NULL, *wbuf = NULL;
278 wchar_t *wstr = NULL;
279 int rval = 0, c = 0, ignore_ws = 0;
280 va_list arg;
281 unsigned char fc;
282 unsigned int npos;
283 int width, flags, base = 0, errno_sv;
284 size_t wbuf_cur_sz, read_in_sv, new_sz, n;
285 char seen_dot, seen_exp, is_neg, not_in;
286 char *tmp_wbuf_ptr, buf[MB_LEN_MAX];
287 const char *lc_decimal_point, *lc_thousands_sep;
288 mbstate_t state, cstate;
289 union {
290 unsigned long long ull;
291 unsigned long ul;
292 long long ll;
293 long l;
294 } cv_val;
295
296 arg = argp;
297
298 if (!s || s->fp == NULL || !format)
299 {
300 errno = EINVAL;
301 return EOF;
302 }
303
304 memset (&state, 0, sizeof (state));
305
306 lc_decimal_point = localeconv()->decimal_point;
307 lc_thousands_sep = localeconv()->thousands_sep;
308 if (lc_thousands_sep != NULL && *lc_thousands_sep == 0)
309 lc_thousands_sep = NULL;
310
311 while (*f != 0)
312 {
313 if (!isascii ((unsigned char) *f))
314 {
315 int len;
316
317 if ((len = mbrlen (f, strlen (f), &state)) > 0)
318 {
319 do
320 {
321 if ((c = in_ch (s, &read_in)) == EOF || c != (unsigned char) *f++)
322 {
323 back_ch (c, s, &read_in, 1);
324 return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
325 }
326 }
327 while (--len > 0);
328
329 continue;
330 }
331 }
332
333 fc = *f++;
334 if (fc != '%')
335 {
336 if (isspace (fc))
337 ignore_ws = 1;
338 else
339 {
340 if ((c = in_ch (s, &read_in)) == EOF)
341 return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
342
343 if (ignore_ws)
344 {
345 ignore_ws = 0;
346 if (isspace (c))
347 {
348 do
349 {
350 if ((c = in_ch (s, &read_in)) == EOF)
351 return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
352 }
353 while (isspace (c));
354 }
355 }
356
357 if (c != fc)
358 {
359 back_ch (c, s, &read_in, 0);
360 return cleanup_return (rval, &gcollect, pstr, &wbuf);
361 }
362 }
363
364 continue;
365 }
366
367 width = flags = 0;
368 npos = 0;
369 wbuf_cur_sz = 0;
370
371 if (isdigit ((unsigned char) *f))
372 {
373 const char *svf = f;
374 npos = (unsigned char) *f++ - '0';
375 while (isdigit ((unsigned char) *f))
376 npos = npos * 10 + ((unsigned char) *f++ - '0');
377 if (*f != '$')
378 {
379 npos = 0;
380 f = svf;
381 }
382 else
383 f++;
384 }
385
386 do
387 {
388 if (*f == '*')
389 flags |= IS_SUPPRESSED;
390 else if (*f == '\'')
391 {
392 if (lc_thousands_sep)
393 flags |= USE_GROUP;
394 }
395 else if (*f == 'I')
396 /* we don't support locale's digits (i18N), but ignore it for now silently. */
397 ;
398 else
399 break;
400 ++f;
401 }
402 while (1);
403
404 while (isdigit ((unsigned char) *f))
405 width = width * 10 + ((unsigned char) *f++ - '0');
406
407 if (!width)
408 width = -1;
409
410 switch (*f)
411 {
412 case 'h':
413 ++f;
414 flags |= (*f == 'h' ? IS_C : IS_S);
415 if (*f == 'h')
416 ++f;
417 break;
418 case 'l':
419 ++f;
420 flags |= (*f == 'l' ? IS_LL : 0) | IS_L;
421 if (*f == 'l')
422 ++f;
423 break;
424 case 'q': case 'L':
425 ++f;
426 flags |= IS_LL | IS_L;
427 break;
428 case 'a':
429 if (f[1] != 's' && f[1] != 'S' && f[1] != '[')
430 break;
431 ++f;
432 flags |= USE_GNU_ALLOC;
433 break;
434 case 'm':
435 flags |= USE_POSIX_ALLOC;
436 ++f;
437 if (*f == 'l')
438 {
439 flags |= IS_L;
440 f++;
441 }
442 break;
443 case 'z':
444#ifdef _WIN64
445 flags |= IS_LL;
446#else
447 flags |= IS_L;
448#endif
449 ++f;
450 break;
451 case 'j':
452 if (sizeof (uintmax_t) > sizeof (unsigned long))
453 flags |= IS_LL;
454 else if (sizeof (uintmax_t) > sizeof (unsigned int))
455 flags |= IS_L;
456 ++f;
457 break;
458 case 't':
459#ifdef _WIN64
460 flags |= IS_LL;
461#else
462 flags |= IS_L;
463#endif
464 ++f;
465 break;
466 case 0:
467 return cleanup_return (rval, &gcollect, pstr, &wbuf);
468 default:
469 break;
470 }
471
472 if (*f == 0)
473 return cleanup_return (rval, &gcollect, pstr, &wbuf);
474
475 fc = *f++;
476 if (ignore_ws || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n'))
477 {
478 errno_sv = errno;
479 errno = 0;
480 do
481 {
482 if ((c == EOF || (c = in_ch (s, &read_in)) == EOF)
483 && errno == EINTR)
484 return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
485 }
486 while (isspace (c));
487
488 ignore_ws = 0;
489 errno = errno_sv;
490 back_ch (c, s, &read_in, 0);
491 }
492
493 switch (fc)
494 {
495 case 'c':
496 if ((flags & IS_L) != 0)
497 fc = 'C';
498 break;
499 case 's':
500 if ((flags & IS_L) != 0)
501 fc = 'S';
502 break;
503 }
504
505 switch (fc)
506 {
507 case '%':
508 if ((c = in_ch (s, &read_in)) == EOF)
509 return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
510 if (c != fc)
511 {
512 back_ch (c, s, &read_in, 1);
513 return cleanup_return (rval, &gcollect, pstr, &wbuf);
514 }
515 break;
516
517 case 'n':
518 if ((flags & IS_SUPPRESSED) == 0)
519 {
520 if ((flags & IS_LL) != 0)
521 *(npos != 0 ? (long long *) get_va_nth (argp, npos) : va_arg (arg, long long *)) = read_in;
522 else if ((flags & IS_L) != 0)
523 *(npos != 0 ? (long *) get_va_nth (argp, npos) : va_arg (arg, long *)) = read_in;
524 else if ((flags & IS_S) != 0)
525 *(npos != 0 ? (short *) get_va_nth (argp, npos) : va_arg (arg, short *)) = read_in;
526 else if ((flags & IS_C) != 0)
527 *(npos != 0 ? (char *) get_va_nth (argp, npos) : va_arg (arg, char *)) = read_in;
528 else
529 *(npos != 0 ? (int *) get_va_nth (argp, npos) : va_arg (arg, int *)) = read_in;
530 }
531 break;
532
533 case 'c':
534 if (width == -1)
535 width = 1;
536
537 if ((flags & IS_SUPPRESSED) == 0)
538 {
539 if ((flags & IS_ALLOC_USED) != 0)
540 {
541 if (npos != 0)
542 pstr = (char **) get_va_nth (argp, npos);
543 else
544 pstr = va_arg (arg, char **);
545
546 if (!pstr)
547 return cleanup_return (rval, &gcollect, pstr, &wbuf);
548
549 str_sz = (width > 1024 ? 1024 : width);
550 if ((str = *pstr = (char *) malloc (str_sz)) == NULL)
551 return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf);
552
553 gcollect = resize_gcollect (gcollect);
554 gcollect->ptrs[gcollect->count++] = pstr;
555 }
556 else
557 {
558 if (npos != 0)
559 str = (char *) get_va_nth (argp, npos);
560 else
561 str = va_arg (arg, char *);
562 if (!str)
563 return cleanup_return (rval, &gcollect, pstr, &wbuf);
564 }
565 }
566
567 if ((c = in_ch (s, &read_in)) == EOF)
568 return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
569
570 if ((flags & IS_SUPPRESSED) == 0)
571 {
572 do
573 {
574 if ((flags & IS_ALLOC_USED) != 0 && str == (*pstr + str_sz))
575 {
576 new_sz = str_sz + (str_sz >= width ? width - 1 : str_sz);
577 while ((str = (char *) realloc (*pstr, new_sz)) == NULL
578 && new_sz > (size_t) (str_sz + 1))
579 new_sz = str_sz + 1;
580 if (!str)
581 {
582 release_ptrs (&gcollect, &wbuf);
583 return EOF;
584 }
585 *pstr = str;
586 str += str_sz;
587 str_sz = new_sz;
588 }
589 *str++ = c;
590 }
591 while (--width > 0 && (c = in_ch (s, &read_in)) != EOF);
592 }
593 else
594 while (--width > 0 && (c = in_ch (s, &read_in)) != EOF);
595
596 if ((flags & IS_SUPPRESSED) == 0)
597 {
598 optimize_alloc (pstr, str, str_sz);
599 pstr = NULL;
600 ++rval;
601 }
602
603 break;
604
605 case 'C':
606 if (width == -1)
607 width = 1;
608
609 if ((flags & IS_SUPPRESSED) == 0)
610 {
611 if ((flags & IS_ALLOC_USED) != 0)
612 {
613 if (npos != 0)
614 pstr = (char **) get_va_nth (argp, npos);
615 else
616 pstr = va_arg (arg, char **);
617
618 if (!pstr)
619 return cleanup_return (rval, &gcollect, pstr, &wbuf);
620 str_sz = (width > 1024 ? 1024 : width);
621 *pstr = (char *) malloc (str_sz * sizeof (wchar_t));
622 if ((wstr = (wchar_t *) *pstr) == NULL)
623 return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf);
624 gcollect = resize_gcollect (gcollect);
625 gcollect->ptrs[gcollect->count++] = pstr;
626 }
627 else
628 {
629 if (npos != 0)
630 wstr = (wchar_t *) get_va_nth (argp, npos);
631 else
632 wstr = va_arg (arg, wchar_t *);
633 if (!wstr)
634 return cleanup_return (rval, &gcollect, pstr, &wbuf);
635 }
636 }
637
638 if ((c = in_ch (s, &read_in)) == EOF)
639 return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
640
641 memset (&cstate, 0, sizeof (cstate));
642
643 do
644 {
645 buf[0] = c;
646
647 if ((flags & IS_SUPPRESSED) == 0 && (flags & IS_ALLOC_USED) != 0
648 && wstr == ((wchar_t *) *pstr + str_sz))
649 {
650 new_sz = str_sz + (str_sz > width ? width - 1 : str_sz);
651
652 while ((wstr = (wchar_t *) realloc (*pstr, new_sz * sizeof (wchar_t))) == NULL
653 && new_sz > (size_t) (str_sz + 1))
654 new_sz = str_sz + 1;
655 if (!wstr)
656 {
657 release_ptrs (&gcollect, &wbuf);
658 return EOF;
659 }
660 *pstr = (char *) wstr;
661 wstr += str_sz;
662 str_sz = new_sz;
663 }
664
665 while (1)
666 {
667 n = mbrtowc ((flags & IS_SUPPRESSED) == 0 ? wstr : NULL, buf, 1, &cstate);
668
669 if (n == (size_t) -2)
670 {
671 if ((c = in_ch (s, &read_in)) == EOF)
672 {
673 errno = EILSEQ;
674 return cleanup_return (rval, &gcollect, pstr, &wbuf);
675 }
676
677 buf[0] = c;
678 continue;
679 }
680
681 if (n != 1)
682 {
683 errno = EILSEQ;
684 return cleanup_return (rval, &gcollect, pstr, &wbuf);
685 }
686 break;
687 }
688
689 ++wstr;
690 }
691 while (--width > 0 && (c = in_ch (s, &read_in)) != EOF);
692
693 if ((flags & IS_SUPPRESSED) == 0)
694 {
695 optimize_alloc (pstr, (char *) wstr, str_sz * sizeof (wchar_t));
696 pstr = NULL;
697 ++rval;
698 }
699 break;
700
701 case 's':
702 if ((flags & IS_SUPPRESSED) == 0)
703 {
704 if ((flags & IS_ALLOC_USED) != 0)
705 {
706 if (npos != 0)
707 pstr = (char **) get_va_nth (argp, npos);
708 else
709 pstr = va_arg (arg, char **);
710
711 if (!pstr)
712 return cleanup_return (rval, &gcollect, pstr, &wbuf);
713
714 str_sz = 100;
715 if ((str = *pstr = (char *) malloc (100)) == NULL)
716 return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf);
717 gcollect = resize_gcollect (gcollect);
718 gcollect->ptrs[gcollect->count++] = pstr;
719 }
720 else
721 {
722 if (npos != 0)
723 str = (char *) get_va_nth (argp, npos);
724 else
725 str = va_arg (arg, char *);
726 if (!str)
727 return cleanup_return (rval, &gcollect, pstr, &wbuf);
728 }
729 }
730
731 if ((c = in_ch (s, &read_in)) == EOF)
732 return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
733
734 do
735 {
736 if (isspace (c))
737 {
738 back_ch (c, s, &read_in, 1);
739 break;
740 }
741
742 if ((flags & IS_SUPPRESSED) == 0)
743 {
744 *str++ = c;
745 if ((flags & IS_ALLOC_USED) != 0 && str == (*pstr + str_sz))
746 {
747 new_sz = str_sz * 2;
748
749 while ((str = (char *) realloc (*pstr, new_sz)) == NULL
750 && new_sz > (size_t) (str_sz + 1))
751 new_sz = str_sz + 1;
752 if (!str)
753 {
754 if ((flags & USE_POSIX_ALLOC) == 0)
755 {
756 (*pstr)[str_sz - 1] = 0;
757 pstr = NULL;
758 ++rval;
759 }
760 return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf);
761 }
762 *pstr = str;
763 str += str_sz;
764 str_sz = new_sz;
765 }
766 }
767 }
768 while ((width <= 0 || --width > 0) && (c = in_ch (s, &read_in)) != EOF);
769
770 if ((flags & IS_SUPPRESSED) == 0)
771 {
772 *str++ = 0;
773 optimize_alloc (pstr, str, str_sz);
774 pstr = NULL;
775 ++rval;
776 }
777 break;
778
779 case 'S':
780 if ((flags & IS_SUPPRESSED) == 0)
781 {
782 if ((flags & IS_ALLOC_USED) != 0)
783 {
784 if (npos != 0)
785 pstr = (char **) get_va_nth (argp, npos);
786 else
787 pstr = va_arg (arg, char **);
788
789 if (!pstr)
790 return cleanup_return (rval, &gcollect, pstr, &wbuf);
791
792 str_sz = 100;
793 *pstr = (char *) malloc (100 * sizeof (wchar_t));
794 if ((wstr = (wchar_t *) *pstr) == NULL)
795 return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf);
796 gcollect = resize_gcollect (gcollect);
797 gcollect->ptrs[gcollect->count++] = pstr;
798 }
799 else
800 {
801 if (npos != 0)
802 wstr = (wchar_t *) get_va_nth (argp, npos);
803 else
804 wstr = va_arg (arg, wchar_t *);
805 if (!wstr)
806 return cleanup_return (rval, &gcollect, pstr, &wbuf);
807 }
808 }
809
810 if ((c = in_ch (s, &read_in)) == EOF)
811 return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
812
813 memset (&cstate, 0, sizeof (cstate));
814
815 do
816 {
817 if (isspace (c))
818 {
819 back_ch (c, s, &read_in, 1);
820 break;
821 }
822
823 buf[0] = c;
824
825 while (1)
826 {
827 n = mbrtowc ((flags & IS_SUPPRESSED) == 0 ? wstr : NULL, buf, 1, &cstate);
828
829 if (n == (size_t) -2)
830 {
831 if ((c = in_ch (s, &read_in)) == EOF)
832 {
833 errno = EILSEQ;
834 return cleanup_return (rval, &gcollect, pstr, &wbuf);
835 }
836
837 buf[0] = c;
838 continue;
839 }
840
841 if (n != 1)
842 {
843 errno = EILSEQ;
844 return cleanup_return (rval, &gcollect, pstr, &wbuf);
845 }
846
847 ++wstr;
848 break;
849 }
850
851 if ((flags & IS_SUPPRESSED) == 0 && (flags & IS_ALLOC_USED) != 0
852 && wstr == ((wchar_t *) *pstr + str_sz))
853 {
854 new_sz = str_sz * 2;
855 while ((wstr = (wchar_t *) realloc (*pstr, new_sz * sizeof (wchar_t))) == NULL
856 && new_sz > (size_t) (str_sz + 1))
857 new_sz = str_sz + 1;
858 if (!wstr)
859 {
860 if ((flags & USE_POSIX_ALLOC) == 0)
861 {
862 ((wchar_t *) (*pstr))[str_sz - 1] = 0;
863 pstr = NULL;
864 ++rval;
865 }
866 return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf);
867 }
868 *pstr = (char *) wstr;
869 wstr += str_sz;
870 str_sz = new_sz;
871 }
872 }
873 while ((width <= 0 || --width > 0) && (c = in_ch (s, &read_in)) != EOF);
874
875 if ((flags & IS_SUPPRESSED) == 0)
876 {
877 *wstr++ = 0;
878 optimize_alloc (pstr, (char *) wstr, str_sz * sizeof (wchar_t));
879 pstr = NULL;
880 ++rval;
881 }
882 break;
883
884 case 'd': case 'i':
885 case 'o': case 'p':
886 case 'u':
887 case 'x': case 'X':
888 switch (fc)
889 {
890 case 'd':
891 flags |= IS_SIGNED_NUM;
892 base = 10;
893 break;
894 case 'i':
895 flags |= IS_SIGNED_NUM;
896 base = 0;
897 break;
898 case 'o':
899 base = 8;
900 break;
901 case 'p':
902 base = 16;
903 flags &= ~(IS_S | IS_LL | IS_L);
904 #ifdef _WIN64
905 flags |= IS_LL;
906 #endif
907 flags |= IS_L | IS_POINTER;
908 break;
909 case 'u':
910 base = 10;
911 break;
912 case 'x': case 'X':
913 base = 16;
914 break;
915 }
916
917 if ((c = in_ch (s, &read_in)) == EOF)
918 return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
919 if (c == '+' || c == '-')
920 {
921 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
922 wbuf[wbuf_cur_sz++] = c;
923 if (width > 0)
924 --width;
925 c = in_ch (s, &read_in);
926 }
927 if (width != 0 && c == '0')
928 {
929 if (width > 0)
930 --width;
931
932 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
933 wbuf[wbuf_cur_sz++] = c;
934 c = in_ch (s, &read_in);
935
936 if (width != 0 && tolower (c) == 'x')
937 {
938 if (!base)
939 base = 16;
940 if (base == 16)
941 {
942 if (width > 0)
943 --width;
944 c = in_ch (s, &read_in);
945 }
946 }
947 else if (!base)
948 base = 8;
949 }
950
951 if (!base)
952 base = 10;
953
954 while (c != EOF && width != 0)
955 {
956 if (base == 16)
957 {
958 if (!isxdigit (c))
959 break;
960 }
961 else if (!isdigit (c) || (int) (c - '0') >= base)
962 {
963 const char *p = lc_thousands_sep;
964 int remain;
965
966 if (base != 10 || (flags & USE_GROUP) == 0)
967 break;
968 remain = width > 0 ? width : INT_MAX;
969 while ((unsigned char) *p == c && remain >= 0)
970 {
971 /* As our conversion routines aren't supporting thousands
972 separators, we are filtering them here. */
973
974 ++p;
975 if (*p == 0 || !remain || (c = in_ch (s, &read_in)) == EOF)
976 break;
977 --remain;
978 }
979
980 if (*p != 0)
981 {
982 if (p > lc_thousands_sep)
983 {
984 back_ch (c, s, &read_in, 0);
985 while (--p > lc_thousands_sep)
986 back_ch ((unsigned char) *p, s, &read_in, 1);
987 c = (unsigned char) *p;
988 }
989 break;
990 }
991
992 if (width > 0)
993 width = remain;
994 --wbuf_cur_sz;
995 }
996 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
997 wbuf[wbuf_cur_sz++] = c;
998 if (width > 0)
999 --width;
1000
1001 c = in_ch (s, &read_in);
1002 }
1003
1004 if (!wbuf_cur_sz || (wbuf_cur_sz == 1 && (wbuf[0] == '+' || wbuf[0] == '-')))
1005 {
1006 if (!wbuf_cur_sz && (flags & IS_POINTER) != 0
1007 && match_string (s, &read_in, &c, "(nil)"))
1008 {
1009 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
1010 wbuf[wbuf_cur_sz++] = '0';
1011 }
1012 else
1013 {
1014 back_ch (c, s, &read_in, 0);
1015 return cleanup_return (rval, &gcollect, pstr, &wbuf);
1016 }
1017 }
1018 else
1019 back_ch (c, s, &read_in, 0);
1020
1021 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
1022 wbuf[wbuf_cur_sz++] = 0;
1023
1024 if ((flags & IS_LL))
1025 {
1026 if (flags & IS_SIGNED_NUM)
1027 cv_val.ll = strtoll (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/);
1028 else
1029 cv_val.ull = strtoull (wbuf, &tmp_wbuf_ptr, base);
1030 }
1031 else
1032 {
1033 if (flags & IS_SIGNED_NUM)
1034 cv_val.l = strtol (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/);
1035 else
1036 cv_val.ul = strtoul (wbuf, &tmp_wbuf_ptr, base);
1037 }
1038 if (wbuf == tmp_wbuf_ptr)
1039 return cleanup_return (rval, &gcollect, pstr, &wbuf);
1040
1041 if ((flags & IS_SUPPRESSED) == 0)
1042 {
1043 if ((flags & IS_SIGNED_NUM) != 0)
1044 {
1045 if ((flags & IS_LL) != 0)
1046 *(npos != 0 ? (long long *) get_va_nth (argp, npos) : va_arg (arg, long long *)) = cv_val.ll;
1047 else if ((flags & IS_L) != 0)
1048 *(npos != 0 ? (long *) get_va_nth (argp, npos) : va_arg (arg, long *)) = cv_val.l;
1049 else if ((flags & IS_S) != 0)
1050 *(npos != 0 ? (short *) get_va_nth (argp, npos) : va_arg (arg, short *)) = (short) cv_val.l;
1051 else if ((flags & IS_C) != 0)
1052 *(npos != 0 ? (signed char *) get_va_nth (argp, npos) : va_arg (arg, signed char *)) = (signed char) cv_val.ul;
1053 else
1054 *(npos != 0 ? (int *) get_va_nth (argp, npos) : va_arg (arg, int *)) = (int) cv_val.l;
1055 }
1056 else
1057 {
1058 if ((flags & IS_LL) != 0)
1059 *(npos != 0 ? (unsigned long long *) get_va_nth (argp, npos) : va_arg (arg, unsigned long long *)) = cv_val.ull;
1060 else if ((flags & IS_L) != 0)
1061 *(npos != 0 ? (unsigned long *) get_va_nth (argp, npos) : va_arg (arg, unsigned long *)) = cv_val.ul;
1062 else if ((flags & IS_S) != 0)
1063 *(npos != 0 ? (unsigned short *) get_va_nth (argp, npos) : va_arg (arg, unsigned short *))
1064 = (unsigned short) cv_val.ul;
1065 else if ((flags & IS_C) != 0)
1066 *(npos != 0 ? (unsigned char *) get_va_nth (argp, npos) : va_arg (arg, unsigned char *)) = (unsigned char) cv_val.ul;
1067 else
1068 *(npos != 0 ? (unsigned int *) get_va_nth (argp, npos) : va_arg (arg, unsigned int *)) = (unsigned int) cv_val.ul;
1069 }
1070 ++rval;
1071 }
1072 break;
1073
1074 case 'e': case 'E':
1075 case 'f': case 'F':
1076 case 'g': case 'G':
1077 case 'a': case 'A':
1078 if (width > 0)
1079 --width;
1080 if ((c = in_ch (s, &read_in)) == EOF)
1081 return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf);
1082
1083 seen_dot = seen_exp = 0;
1084 is_neg = (c == '-' ? 1 : 0);
1085
1086 if (c == '-' || c == '+')
1087 {
1088 if (width == 0 || (c = in_ch (s, &read_in)) == EOF)
1089 return cleanup_return (rval, &gcollect, pstr, &wbuf);
1090 if (width > 0)
1091 --width;
1092 }
1093
1094 if (tolower (c) == 'n')
1095 {
1096 const char *match_txt = "nan";
1097
1098 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
1099 wbuf[wbuf_cur_sz++] = c;
1100
1101 ++match_txt;
1102 do
1103 {
1104 if (width == 0 || (c = in_ch (s, &read_in)) == EOF || tolower (c) != match_txt[0])
1105 return cleanup_return (rval, &gcollect, pstr, &wbuf);
1106
1107 if (width > 0)
1108 --width;
1109
1110 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
1111 wbuf[wbuf_cur_sz++] = c;
1112 ++match_txt;
1113 }
1114 while (*match_txt != 0);
1115 }
1116 else if (tolower (c) == 'i')
1117 {
1118 const char *match_txt = "inf";
1119
1120 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
1121 wbuf[wbuf_cur_sz++] = c;
1122
1123 ++match_txt;
1124 do
1125 {
1126 if (width == 0 || (c = in_ch (s, &read_in)) == EOF || tolower (c) != match_txt[0])
1127 return cleanup_return (rval, &gcollect, pstr, &wbuf);
1128 if (width > 0)
1129 --width;
1130
1131 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
1132 wbuf[wbuf_cur_sz++] = c;
1133 ++match_txt;
1134 }
1135 while (*match_txt != 0);
1136
1137 if (width != 0 && (c = in_ch (s, &read_in)) != EOF && tolower (c) == 'i')
1138 {
1139 match_txt = "inity";
1140
1141 if (width > 0)
1142 --width;
1143
1144 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
1145 wbuf[wbuf_cur_sz++] = c;
1146 ++match_txt;
1147
1148 do
1149 {
1150 if (width == 0 || (c = in_ch (s, &read_in)) == EOF || tolower (c) != match_txt[0])
1151 return cleanup_return (rval, &gcollect, pstr, &wbuf);
1152 if (width > 0)
1153 --width;
1154
1155 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
1156 wbuf[wbuf_cur_sz++] = c;
1157 ++match_txt;
1158 }
1159 while (*match_txt != 0);
1160 }
1161 else if (width != 0 && c != EOF)
1162 back_ch (c, s, &read_in, 0);
1163 }
1164 else
1165 {
1166 not_in = 'e';
1167 if (width != 0 && c == '0')
1168 {
1169 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
1170 wbuf[wbuf_cur_sz++] = c;
1171
1172 c = in_ch (s, &read_in);
1173 if (width > 0)
1174 --width;
1175 if (width != 0 && tolower (c) == 'x')
1176 {
1177 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
1178 wbuf[wbuf_cur_sz++] = c;
1179
1180 flags |= IS_HEX_FLOAT;
1181 not_in = 'p';
1182
1183 flags &= ~USE_GROUP;
1184 c = in_ch (s, &read_in);
1185 if (width > 0)
1186 --width;
1187 }
1188 }
1189
1190 while (1)
1191 {
1192 if (isdigit (c) || (!seen_exp && (flags & IS_HEX_FLOAT) != 0 && isxdigit (c))
1193 || (seen_exp && wbuf[wbuf_cur_sz - 1] == not_in && (c == '-' || c == '+')))
1194 {
1195 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
1196 wbuf[wbuf_cur_sz++] = c;
1197 }
1198 else if (wbuf_cur_sz > 0 && !seen_exp && (char) tolower (c) == not_in)
1199 {
1200 wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf);
1201 wbuf[wbuf_cur_sz++] = not_in;
1202 seen_exp = seen_dot = 1;
1203 }
1204 else
1205 {
1206 const char *p = lc_decimal_point;
1207 int remain = width > 0 ? width : INT_MAX;
1208
1209 if (! seen_dot)
1210 {
1211 while ((unsigned char) *p == c && remain >= 0)
1212 {
1213 ++p;
1214 if (*p == 0 || !remain || (c = in_ch (s, &read_in)) == EOF)
1215 break;