cedric pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=d1722eb394216ff304ee8aa83146641057d99e72
commit d1722eb394216ff304ee8aa83146641057d99e72 Author: Vincent Torri <vincent.to...@gmail.com> Date: Sun Apr 19 08:28:56 2015 +0200 evil: remove unused files (evil_p*) and uneeded evil_uuid.c file (managed by mingw-w64) Just keeping up with latest mingw-w64. --- src/Makefile_Evil.am | 11 +- src/lib/evil/evil_pformat.h | 61 -- src/lib/evil/evil_pformata.c | 2493 ------------------------------------------ src/lib/evil/evil_pformatw.c | 9 - src/lib/evil/evil_print.h | 37 - src/lib/evil/evil_printa.c | 1768 ------------------------------ src/lib/evil/evil_printw.c | 4 - src/lib/evil/evil_uuid.c | 9 - 8 files changed, 5 insertions(+), 4387 deletions(-) diff --git a/src/Makefile_Evil.am b/src/Makefile_Evil.am index c2e7ee4..3c6fd0e 100644 --- a/src/Makefile_Evil.am +++ b/src/Makefile_Evil.am @@ -13,16 +13,16 @@ lib/evil/evil_langinfo.h \ lib/evil/evil_macro.h \ lib/evil/evil_macro_pop.h \ lib/evil/evil_main.h \ -lib/evil/evil_stdlib.h \ lib/evil/evil_stdio.h \ +lib/evil/evil_stdlib.h \ lib/evil/evil_string.h \ lib/evil/evil_time.h \ lib/evil/evil_unistd.h \ lib/evil/evil_util.h \ -lib/evil/pwd.h \ -lib/evil/fnmatch.h \ lib/evil/dirent.h \ -lib/evil/dlfcn.h +lib/evil/dlfcn.h \ +lib/evil/fnmatch.h \ +lib/evil/pwd.h evilmmanheadersdir = $(includedir)/evil-@VMAJ@/sys dist_evilmmanheaders_DATA = \ @@ -39,13 +39,12 @@ lib/evil/evil_link_xp.cpp \ lib/evil/evil_main.c \ lib/evil/evil_mman.c \ lib/evil/evil_pwd.c \ -lib/evil/evil_stdlib.c \ lib/evil/evil_stdio.c \ +lib/evil/evil_stdlib.c \ lib/evil/evil_string.c \ lib/evil/evil_time.c \ lib/evil/evil_unistd.c \ lib/evil/evil_util.c \ -lib/evil/evil_uuid.c \ lib/evil/evil_private.h \ lib/evil/evil_fnmatch_private.h diff --git a/src/lib/evil/evil_pformat.h b/src/lib/evil/evil_pformat.h deleted file mode 100644 index ad9b61e..0000000 --- a/src/lib/evil/evil_pformat.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef __EVIL_PRIVATE_H__ -#define __EVIL_PRIVATE_H__ - - -#include "evil_macro.h" - - -#ifdef __BUILD_WIDEAPI -#define APICHAR wchar_t -#else -#define APICHAR char -#endif - -/* The following are the declarations specific to the `pformat' API... - */ -#define PFORMAT_TO_FILE 0x1000 -#define PFORMAT_NOLIMIT 0x2000 - - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifdef __BUILD_WIDEAPI -# define __fputc(X,STR) fputwc((wchar_t) (X), (STR)) -# define _evil_pformat _evil_pformatw - -# define _evil_fprintf _evil_fprintfw -# define _evil_printf _evil_printfw -# define _evil_snprintf _evil_snprintfw -# define _evil_sprintf _evil_sprintfw - -# define _evil_vfprintf _evil_vfprintfw -# define _evil_vprintf _evil_vprintfw -# define _evil_vsnprintf _evil_vsnprintfw -# define _evil_vsprintf _evil_vsprintfw -#else -# define __fputc(X,STR) fputc((X), (STR)) -# define _evil_pformat _evil_pformata - -# define _evil_fprintf _evil_fprintfa -# define _evil_printf _evil_printfa -# define _evil_snprintf _evil_snprintfa -# define _evil_sprintf _evil_sprintfa - -# define _evil_vfprintf _evil_vfprintfa -# define _evil_vprintf _evil_vprintfa -# define _evil_vsnprintf _evil_vsnprintfa -# define _evil_vsprintf _evil_vsprintfa -#endif - -int __cdecl _evil_pformat(int, void *, int, const APICHAR *, va_list) __EVIL_NOTHROW; - - -#ifdef __cplusplus -} -#endif - - -#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 ee1d68e..0000000 --- a/src/lib/evil/evil_pformata.c +++ /dev/null @@ -1,2493 +0,0 @@ -/* pformat.c - * - * $Id: pformat.c,v 1.9 2011/01/07 22:57:00 keithmarshall Exp $ - * - * Provides a core implementation of the formatting capabilities - * common to the entire `printf()' family of functions; it conforms - * generally to C99 and SUSv3/POSIX specifications, with extensions - * to support Microsoft's non-standard format specifications. - * - * Written by Keith Marshall <keithmarsh...@users.sourceforge.net> - * - * This is free software. You may redistribute and/or modify it as you - * see fit, without restriction of copyright. - * - * This software is provided "as is", in the hope that it may be useful, - * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of - * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no - * time will the author accept any form of liability for any damages, - * however caused, resulting from the use of this software. - * - * The elements of this implementation which deal with the formatting - * of floating point numbers, (i.e. the `%e', `%E', `%f', `%F', `%g' - * and `%G' format specifiers, but excluding the hexadecimal floating - * point `%a' and `%A' specifiers), make use of the `__gdtoa' function - * written by David M. Gay, and are modelled on his sample code, which - * has been deployed under its accompanying terms of use:-- - * - ****************************************************************** - * Copyright (C) 1997, 1999, 2001 Lucent Technologies - * All Rights Reserved - * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby - * granted, provided that the above copyright notice appear in all - * copies and that both that the copyright notice and this - * permission notice and warranty disclaimer appear in supporting - * documentation, and that the name of Lucent or any of its entities - * not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. - * - * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. - * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER - * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - * THIS SOFTWARE. - ****************************************************************** - * - */ -#include <stdio.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <limits.h> -#include <locale.h> -#include <wchar.h> -#include <math.h> - -/* FIXME: The following belongs in values.h, but current MinGW - * has nothing useful there! OTOH, values.h is not a standard - * header, and it's use may be considered obsolete; perhaps it - * is better to just keep these definitions here. - */ -#ifndef _VALUES_H -/* - * values.h - * - */ -#define _VALUES_H - -#include <limits.h> - -#define _TYPEBITS(type) (sizeof(type) * CHAR_BIT) - -#define LLONGBITS _TYPEBITS(long long) - -#endif /* !defined _VALUES_H -- end of file */ - -#include "evil_pformat.h" -#include "gdtoa/gdtoa.h" - -/* Bit-map constants, defining the internal format control - * states, which propagate through the flags. - */ -#define PFORMAT_GROUPED 0x1000 -#define PFORMAT_HASHED 0x0800 -#define PFORMAT_LJUSTIFY 0x0400 -#define PFORMAT_ZEROFILL 0x0200 - -#define PFORMAT_JUSTIFY (PFORMAT_LJUSTIFY | PFORMAT_ZEROFILL) -#define PFORMAT_IGNORE -1 - -#define PFORMAT_SIGNED 0x01C0 -#define PFORMAT_POSITIVE 0x0100 -#define PFORMAT_NEGATIVE 0x0080 -#define PFORMAT_ADDSPACE 0x0040 - -#define PFORMAT_XCASE 0x0020 - -#define PFORMAT_LDOUBLE 0x0004 - -/* `%o' format digit extraction mask, and shift count... - * (These are constant, and do not propagate through the flags). - */ -#define PFORMAT_OMASK 0x0007 -#define PFORMAT_OSHIFT 0x0003 - -/* `%x' and `%X' format digit extraction mask, and shift count... - * (These are constant, and do not propagate through the flags). - */ -#define PFORMAT_XMASK 0x000F -#define PFORMAT_XSHIFT 0x0004 - -/* The radix point character, used in floating point formats, is - * localised on the basis of the active LC_NUMERIC locale category. - * It is stored locally, as a `wchar_t' entity, which is converted - * to a (possibly multibyte) character on output. Initialisation - * of the stored `wchar_t' entity, together with a record of its - * effective multibyte character length, is required each time - * `__pformat()' is entered, (static storage would not be thread - * safe), but this initialisation is deferred until it is actually - * needed; on entry, the effective character length is first set to - * the following value, (and the `wchar_t' entity is zeroed), to - * indicate that a call of `localeconv()' is needed, to complete - * the initialisation. - */ -#define PFORMAT_RPINIT -3 - -/* The floating point format handlers return the following value - * for the radix point position index, when the argument value is - * infinite, or not a number. - */ -#define PFORMAT_INFNAN -32768 - -#ifdef _WIN32 -/* - * The Microsoft standard for printing `%e' format exponents is - * with a minimum of three digits, unless explicitly set otherwise, - * by a prior invocation of the `_set_output_format()' function. - * - * The following macro allows us to replicate this behaviour. - */ -# define PFORMAT_MINEXP __pformat_exponent_digits() - /* - * However, this feature is unsupported for versions of the - * MSVC runtime library prior to msvcr80.dll, and by default, - * MinGW uses an earlier version, (equivalent to msvcr60.dll), - * for which `_TWO_DIGIT_EXPONENT' will be undefined. - */ -# ifndef _TWO_DIGIT_EXPONENT - /* - * This hack works around the lack of the `_set_output_format()' - * feature, when supporting versions of the MSVC runtime library - * prior to msvcr80.dll; it simply enforces Microsoft's original - * convention, for all cases where the feature is unsupported. - */ -# define _get_output_format() 0 -# define _TWO_DIGIT_EXPONENT 1 -# endif -/* - * Irrespective of the MSVCRT version supported, *we* will add - * an additional capability, through the following inline function, - * which will allow the user to choose his own preferred default - * for `PRINTF_EXPONENT_DIGITS', through the simple expedient - * of defining it as an environment variable. - */ -static -int __pformat_exponent_digits( void ) -{ - char *exponent_digits = getenv( "PRINTF_EXPONENT_DIGITS" ); - return ((exponent_digits != NULL) && ((unsigned)(*exponent_digits - '0') < 3)) - || (_get_output_format() & _TWO_DIGIT_EXPONENT) - ? 2 - : 3 - ; -} -#else -/* - * When we don't care to mimic Microsoft's standard behaviour, - * we adopt the C99/POSIX standard of two digit exponents. - */ -# define PFORMAT_MINEXP 2 -#endif - -typedef union -{ - /* A data type agnostic representation, - * for printf arguments of any integral data type... - */ - signed long __pformat_long_t; - signed long long __pformat_llong_t; - unsigned long __pformat_ulong_t; - unsigned long long __pformat_ullong_t; - unsigned short __pformat_ushort_t; - unsigned char __pformat_uchar_t; - signed short __pformat_short_t; - signed char __pformat_char_t; - void * __pformat_ptr_t; -} __pformat_intarg_t; - -typedef enum -{ - /* Format interpreter state indices... - * (used to identify the active phase of format string parsing). - */ - PFORMAT_INIT = 0, - PFORMAT_SET_WIDTH, - PFORMAT_GET_PRECISION, - PFORMAT_SET_PRECISION, - PFORMAT_END -} __pformat_state_t; - -typedef enum -{ - /* Argument length classification indices... - * (used for arguments representing integer data types). - */ - PFORMAT_LENGTH_INT = 0, - PFORMAT_LENGTH_SHORT, - PFORMAT_LENGTH_LONG, - PFORMAT_LENGTH_LLONG, - PFORMAT_LENGTH_CHAR -} __pformat_length_t; -/* - * And a macro to map any arbitrary data type to an appropriate - * matching index, selected from those above; the compiler should - * collapse this to a simple assignment. - */ -#define __pformat_arg_length( type ) \ - sizeof( type ) == sizeof( long long ) ? PFORMAT_LENGTH_LLONG : \ - sizeof( type ) == sizeof( long ) ? PFORMAT_LENGTH_LONG : \ - sizeof( type ) == sizeof( short ) ? PFORMAT_LENGTH_SHORT : \ - sizeof( type ) == sizeof( char ) ? PFORMAT_LENGTH_CHAR : \ - /* should never need this default */ PFORMAT_LENGTH_INT - -typedef struct -{ - /* Formatting and output control data... - * An instance of this control block is created, (on the stack), - * for each call to `__pformat()', and is passed by reference to - * each of the output handlers, as required. - */ - void * dest; - int flags; - int width; - int precision; - int rplen; - wchar_t rpchr; - int thousands_chr_len; - wchar_t thousands_chr; - int count; - int quota; - int expmin; -} __pformat_t; - -static -void __pformat_putc( int c, __pformat_t *stream ) -{ - /* Place a single character into the `__pformat()' output queue, - * provided any specified output quota has not been exceeded. - */ - if( (stream->flags & PFORMAT_NOLIMIT) || (stream->quota > stream->count) ) - { - /* Either there was no quota specified, - * or the active quota has not yet been reached. - */ - if( stream->flags & PFORMAT_TO_FILE ) - /* - * This is single character output to a FILE stream... - */ - __fputc(c, (FILE *)(stream->dest)); - - else - /* Whereas, this is to an internal memory buffer... - */ - ((APICHAR *)(stream->dest))[stream->count] = c; - } - ++stream->count; -} - -static -void __pformat_putchars( const char *s, int count, __pformat_t *stream ) -{ - /* Handler for `%c' and (indirectly) `%s' conversion specifications. - * - * Transfer characters from the string buffer at `s', character by - * character, up to the number of characters specified by `count', or - * if `precision' has been explicitly set to a value less than `count', - * stopping after the number of characters specified for `precision', - * to the `__pformat()' output stream. - * - * Characters to be emitted are passed through `__pformat_putc()', to - * ensure that any specified output quota is honoured. - */ - if( (stream->precision >= 0) && (count > stream->precision) ) - /* - * Ensure that the maximum number of characters transferred doesn't - * exceed any explicitly set `precision' specification. - */ - count = stream->precision; - - /* Establish the width of any field padding required... - */ - if( stream->width > count ) - /* - * as the number of spaces equivalent to the number of characters - * by which those to be emitted is fewer than the field width... - */ - stream->width -= count; - - else - /* ignoring any width specification which is insufficient. - */ - stream->width = PFORMAT_IGNORE; - - if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) ) - /* - * When not doing flush left justification, (i.e. the `-' flag - * is not set), any residual unreserved field width must appear - * as blank padding, to the left of the output string. - */ - while( stream->width-- ) - __pformat_putc( '\x20', stream ); - - /* Emit the data... - */ -#ifdef __BUILD_WIDEAPI - { - /* mbrtowc */ - size_t l; - wchar_t w[12], *p; - while( count > 0 ) - { - mbstate_t ps; - memset(&ps, 0, sizeof(ps) ); - --count; - p = &w[0]; - l = mbrtowc (p, s, strlen (s), &ps); - if (!l) - break; - if ((ssize_t)l < 0) - { - l = 1; - w[0] = (wchar_t) *s; - } - s += l; - __pformat_putc((int)w[0], stream); - } - } -#else - while( count-- ) - /* - * copying the requisite number of characters from the input. - */ - __pformat_putc( *s++, stream ); -#endif - - /* If we still haven't consumed the entire specified field width, - * we must be doing flush left justification; any residual width - * must be filled with blanks, to the right of the output value. - */ - while( stream->width-- > 0 ) - __pformat_putc( '\x20', stream ); -} - -static -void __pformat_puts( const char *s, __pformat_t *stream ) -{ - /* Handler for `%s' conversion specifications. - * - * Transfer a NUL terminated character string, character by character, - * stopping when the end of the string is encountered, or if `precision' - * has been explicitly set, when the specified number of characters has - * been emitted, if that is less than the length of the input string, - * to the `__pformat()' output stream. - * - * This is implemented as a trivial call to `__pformat_putchars()', - * passing the length of the input string as the character count, - * (after first verifying that the input pointer is not NULL). - */ - if( s == NULL ) s = "(null)"; - __pformat_putchars( s, strlen( s ), stream ); -} - -static -void __pformat_wputchars( const wchar_t *s, int count, __pformat_t *stream ) -{ - /* Handler for `%C'(`%lc') and `%S'(`%ls') conversion specifications; - * (this is a wide character variant of `__pformat_putchars()'). - * - * Each multibyte character sequence to be emitted is passed, byte - * by byte, through `__pformat_putc()', to ensure that any specified - * output quota is honoured. - */ - char buf[16]; - mbstate_t state; - int len = wcrtomb(buf, L'\0', &state); - - if( (stream->precision >= 0) && (count > stream->precision) ) - /* - * Ensure that the maximum number of characters transferred doesn't - * exceed any explicitly set `precision' specification. - */ - count = stream->precision; - - /* Establish the width of any field padding required... - */ - if( stream->width > count ) - /* - * as the number of spaces equivalent to the number of characters - * by which those to be emitted is fewer than the field width... - */ - stream->width -= count; - - else - /* ignoring any width specification which is insufficient. - */ - stream->width = PFORMAT_IGNORE; - - if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) ) - /* - * When not doing flush left justification, (i.e. the `-' flag - * is not set), any residual unreserved field width must appear - * as blank padding, to the left of the output string. - */ - while( stream->width-- ) - __pformat_putc( '\x20', stream ); - - /* Emit the data, converting each character from the wide - * to the multibyte domain as we go... - */ -#ifdef __BUILD_WIDEAPI - len = count; - while(len-- > 0 && *s != 0) - { - __pformat_putc(*s++, stream); - } - count = len; -#else - while( (count-- > 0) && ((len = wcrtomb( buf, *s++, &state )) > 0) ) - { - char *p = buf; - while( len-- > 0 ) - __pformat_putc( *p++, stream ); - } -#endif - /* If we still haven't consumed the entire specified field width, - * we must be doing flush left justification; any residual width - * must be filled with blanks, to the right of the output value. - */ - while( stream->width-- > 0 ) - __pformat_putc( '\x20', stream ); -} - -static -void __pformat_wcputs( const wchar_t *s, __pformat_t *stream ) -{ - /* Handler for `%S' (`%ls') conversion specifications. - * - * Transfer a NUL terminated wide character string, character by - * character, converting to its equivalent multibyte representation - * on output, and stopping when the end of the string is encountered, - * or if `precision' has been explicitly set, when the specified number - * of characters has been emitted, if that is less than the length of - * the input string, to the `__pformat()' output stream. - * - * This is implemented as a trivial call to `__pformat_wputchars()', - * passing the length of the input string as the character count, - * (after first verifying that the input pointer is not NULL). - */ - if( s == NULL ) s = L"(null)"; - __pformat_wputchars( s, wcslen( s ), stream ); -} - -static -int __pformat_int_bufsiz( int bias, int size, __pformat_t *stream ) -{ - /* Helper to establish the size of the internal buffer, which - * is required to queue the ASCII decomposition of an integral - * data value, prior to transfer to the output stream. - */ - size = ((size - 1 + LLONGBITS) / size) + bias; - size += (stream->precision > 0) ? stream->precision : 0; - if ((stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0) - size += (size / 3); - return (size > stream->width) ? size : stream->width; -} - -static -void __pformat_int( __pformat_intarg_t value, __pformat_t *stream ) -{ - /* Handler for `%d', `%i' and `%u' conversion specifications. - * - * Transfer the ASCII representation of an integer value parameter, - * formatted as a decimal number, to the `__pformat()' output queue; - * output will be truncated, if any specified quota is exceeded. - */ - char buf[__pformat_int_bufsiz(1, PFORMAT_OSHIFT, stream)]; - char *p = buf; int precision; - - if( stream->flags & PFORMAT_NEGATIVE ) - { - /* The input value might be negative, (i.e. it is a signed value)... - */ - if( value.__pformat_llong_t < 0LL ) - /* - * It IS negative, but we want to encode it as unsigned, - * displayed with a leading minus sign, so convert it... - */ - value.__pformat_llong_t = -value.__pformat_llong_t; - - else - /* It is unequivocally a POSITIVE value, so turn off the - * request to prefix it with a minus sign... - */ - stream->flags &= ~PFORMAT_NEGATIVE; - } - - /* Encode the input value for display... - */ - while( value.__pformat_ullong_t ) - { - /* decomposing it into its constituent decimal digits, - * in order from least significant to most significant, using - * the local buffer as a LIFO queue in which to store them. - */ - if (p != buf && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0 - && ((p - buf) % 4) == 3) - { - *p++ = ','; - } - *p++ = '0' + (unsigned char)(value.__pformat_ullong_t % 10LL); - value.__pformat_ullong_t /= 10LL; - } - - if( (stream->precision > 0) - && ((precision = stream->precision - (p - buf)) > 0) ) - /* - * We have not yet queued sufficient digits to fill the field width - * specified for minimum `precision'; pad with zeros to achieve this. - */ - while( precision-- > 0 ) - *p++ = '0'; - - if( (p == buf) && (stream->precision != 0) ) - /* - * Input value was zero; make sure we print at least one digit, - * unless the precision is also explicitly zero. - */ - *p++ = '0'; - - if( (stream->width > 0) && ((stream->width -= p - buf) > 0) ) - { - /* We have now queued sufficient characters to display the input value, - * at the desired precision, but this will not fill the output field... - */ - if( stream->flags & PFORMAT_SIGNED ) - /* - * We will fill one additional space with a sign... - */ - stream->width--; - - if( (stream->precision < 0) - && ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) ) - /* - * and the `0' flag is in effect, so we pad the remaining spaces, - * to the left of the displayed value, with zeros. - */ - while( stream->width-- > 0 ) - *p++ = '0'; - - else if( (stream->flags & PFORMAT_LJUSTIFY) == 0 ) - /* - * the `0' flag is not in effect, and neither is the `-' flag, - * so we pad to the left of the displayed value with spaces, so that - * the value appears right justified within the output field. - */ - while( stream->width-- > 0 ) - __pformat_putc( '\x20', stream ); - } - - if( stream->flags & PFORMAT_NEGATIVE ) - /* - * A negative value needs a sign... - */ - *p++ = '-'; - - else if( stream->flags & PFORMAT_POSITIVE ) - /* - * A positive value may have an optionally displayed sign... - */ - *p++ = '+'; - - else if( stream->flags & PFORMAT_ADDSPACE ) - /* - * Space was reserved for displaying a sign, but none was emitted... - */ - *p++ = '\x20'; - - while( p > buf ) - /* - * Emit the accumulated constituent digits, - * in order from most significant to least significant... - */ - __pformat_putc( *--p, stream ); - - while( stream->width-- > 0 ) - /* - * The specified output field has not yet been completely filled; - * the `-' flag must be in effect, resulting in a displayed value which - * appears left justified within the output field; we must pad the field - * to the right of the displayed value, by emitting additional spaces, - * until we reach the rightmost field boundary. - */ - __pformat_putc( '\x20', stream ); -} - -static -void __pformat_xint( int fmt, __pformat_intarg_t value, __pformat_t *stream ) -{ - /* Handler for `%o', `%p', `%x' and `%X' conversions. - * - * These can be implemented using a simple `mask and shift' strategy; - * set up the mask and shift values appropriate to the conversion format, - * and allocate a suitably sized local buffer, in which to queue encoded - * digits of the formatted value, in preparation for output. - */ - int width; - int mask = (fmt == 'o') ? PFORMAT_OMASK : PFORMAT_XMASK; - int shift = (fmt == 'o') ? PFORMAT_OSHIFT : PFORMAT_XSHIFT; - char buf[__pformat_int_bufsiz(2, shift, stream)]; - char *p = buf; - - while( value.__pformat_ullong_t ) - { - /* Encode the specified non-zero input value as a sequence of digits, - * in the appropriate `base' encoding and in reverse digit order, each - * encoded in its printable ASCII form, with no leading zeros, using - * the local buffer as a LIFO queue in which to store them. - */ - char *q; - if( (*(q = p++) = '0' + (value.__pformat_ullong_t & mask)) > '9' ) - *q = (*q + 'A' - '9' - 1) | (fmt & PFORMAT_XCASE); - value.__pformat_ullong_t >>= shift; - } - - if( p == buf ) - /* - * Nothing was queued; input value must be zero, which should never be - * emitted in the `alternative' PFORMAT_HASHED style. - */ - stream->flags &= ~PFORMAT_HASHED; - - if( ((width = stream->precision) > 0) && ((width -= p - buf) > 0) ) - /* - * We have not yet queued sufficient digits to fill the field width - * specified for minimum `precision'; pad with zeros to achieve this. - */ - while( width-- > 0 ) - *p++ = '0'; - - else if( (fmt == 'o') && (stream->flags & PFORMAT_HASHED) ) - /* - * The field width specified for minimum `precision' has already - * been filled, but the `alternative' PFORMAT_HASHED style for octal - * output requires at least one initial zero; that will not have - * been queued, so add it now. - */ - *p++ = '0'; - - if( (p == buf) && (stream->precision != 0) ) - /* - * Still nothing queued for output, but the `precision' has not been - * explicitly specified as zero, (which is necessary if no output for - * an input value of zero is desired); queue exactly one zero digit. - */ - *p++ = '0'; - - if( stream->width > (width = p - buf) ) - /* - * Specified field width exceeds the minimum required... - * Adjust so that we retain only the additional padding width. - */ - stream->width -= width; - - else - /* Ignore any width specification which is insufficient. - */ - stream->width = PFORMAT_IGNORE; - - if( ((width = stream->width) > 0) - && (fmt != 'o') && (stream->flags & PFORMAT_HASHED) ) - /* - * For `%#x' or `%#X' formats, (which have the `#' flag set), - * further reduce the padding width to accommodate the radix - * indicating prefix. - */ - width -= 2; - - if( (width > 0) && (stream->precision < 0) - && ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) ) - /* - * When the `0' flag is set, and not overridden by the `-' flag, - * or by a specified precision, add sufficient leading zeros to - * consume the remaining field width. - */ - while( width-- > 0 ) - *p++ = '0'; - - if( (fmt != 'o') && (stream->flags & PFORMAT_HASHED) ) - { - /* For formats other than octal, the PFORMAT_HASHED output style - * requires the addition of a two character radix indicator, as a - * prefix to the actual encoded numeric value. - */ - *p++ = fmt; - *p++ = '0'; - } - - if( (width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) ) - /* - * When not doing flush left justification, (i.e. the `-' flag - * is not set), any residual unreserved field width must appear - * as blank padding, to the left of the output value. - */ - while( width-- > 0 ) - __pformat_putc( '\x20', stream ); - - while( p > buf ) - /* - * Move the queued output from the local buffer to the ultimate - * destination, in LIFO order. - */ - __pformat_putc( *--p, stream ); - - /* If we still haven't consumed the entire specified field width, - * we must be doing flush left justification; any residual width - * must be filled with blanks, to the right of the output value. - */ - while( width-- > 0 ) - __pformat_putc( '\x20', stream ); -} - -typedef union -{ - /* A multifaceted representation of an IEEE extended precision, - * (80-bit), floating point number, facilitating access to its - * component parts. - */ - double __pformat_fpreg_double_t; - long double __pformat_fpreg_ldouble_t; - struct - { unsigned long long __pformat_fpreg_mantissa; - signed short __pformat_fpreg_exponent; - }; - unsigned short __pformat_fpreg_bitmap[5]; - unsigned long __pformat_fpreg_bits; -} __pformat_fpreg_t; - - -static -char *__pformat_cvt( int mode, __pformat_fpreg_t x, int nd, int *dp, int *sign ) -{ - /* Helper function, derived from David M. Gay's `g_xfmt()', calling - * his `__gdtoa()' function in a manner to provide extended precision - * replacements for `ecvt()' and `fcvt()'. - */ - int k; unsigned int e = 0; char *ep; - static FPI fpi = { 64, 1-16383-64+1, 32766-16383-64+1, FPI_Round_near, 0, 14 /* Int_max */ }; - - /* Classify the argument into an appropriate `__gdtoa()' category... - */ - if( (k = __fpclassifyl( x.__pformat_fpreg_ldouble_t )) & FP_NAN ) - /* - * identifying infinities or not-a-number... - */ - k = (k & FP_NORMAL) ? STRTOG_Infinite : STRTOG_NaN; - - else if( k & FP_NORMAL ) - { - /* normal and near-zero `denormals'... - */ - if( k & FP_ZERO ) - { - /* with appropriate exponent adjustment for a `denormal'... - */ - k = STRTOG_Denormal; - e = 1 - 0x3FFF - 63; - } - else - { - /* or with `normal' exponent adjustment... - */ - k = STRTOG_Normal; - e = (x.__pformat_fpreg_exponent & 0x7FFF) - 0x3FFF - 63; - } - } - - else - /* or, if none of the above, it's a zero, (positive or negative). - */ - k = STRTOG_Zero; - - /* Check for negative values, always treating NaN as unsigned... - * (return value is zero for positive/unsigned; non-zero for negative). - */ - *sign = (k == STRTOG_NaN) ? 0 : x.__pformat_fpreg_exponent & 0x8000; - - /* Finally, get the raw digit string, and radix point position index. - */ - return __gdtoa( &fpi, e, &x.__pformat_fpreg_bits, &k, mode, nd, dp, &ep ); -} - -static -char *__pformat_ecvt( long double x, int precision, int *dp, int *sign ) -{ - /* A convenience wrapper for the above... - * it emulates `ecvt()', but takes a `long double' argument. - */ - __pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x; - return __pformat_cvt( 2, z, precision, dp, sign ); -} - -static -char *__pformat_fcvt( long double x, int precision, int *dp, int *sign ) -{ - /* A convenience wrapper for the above... - * it emulates `fcvt()', but takes a `long double' argument. - */ - __pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x; - return __pformat_cvt( 3, z, precision, dp, sign ); -} - -/* The following are required, to clean up the `__gdtoa()' memory pool, - * after processing the data returned by the above. - */ -#define __pformat_ecvt_release( value ) __freedtoa( value ) -#define __pformat_fcvt_release( value ) __freedtoa( value ) - -static -void __pformat_emit_radix_point( __pformat_t *stream ) -{ - /* Helper to place a localised representation of the radix point - * character at the ultimate destination, when formatting fixed or - * floating point numbers. - */ - if( stream->rplen == PFORMAT_RPINIT ) - { - /* Radix point initialisation not yet completed; - * establish a multibyte to `wchar_t' converter... - */ - int len; wchar_t rpchr; mbstate_t state; - - /* Initialise the conversion state... - */ - memset( &state, 0, sizeof( state ) ); - - /* Fetch and convert the localised radix point representation... - */ - if( (len = mbrtowc( &rpchr, localeconv()->decimal_point, 16, &state )) > 0 ) - /* - * and store it, if valid. - */ - stream->rpchr = rpchr; - - /* In any case, store the reported effective multibyte length, - * (or the error flag), marking initialisation as `done'. - */ - stream->rplen = len; - } - - if( stream->rpchr != (wchar_t)(0) ) - { - /* We have a localised radix point mark; - * establish a converter to make it a multibyte character... - */ -#ifdef __BUILD_WIDEAPI - __pformat_putc (stream->rpchr, stream); -#else - int len; char buf[len = stream->rplen]; mbstate_t state; - - /* Initialise the conversion state... - */ - memset( &state, 0, sizeof( state ) ); - - /* Convert the `wchar_t' representation to multibyte... - */ - if( (len = wcrtomb( buf, stream->rpchr, &state )) > 0 ) - { - /* and copy to the output destination, when valid... - */ - char *p = buf; - while( len-- > 0 ) - __pformat_putc( *p++, stream ); - } - - else - /* otherwise fall back to plain ASCII '.'... - */ - __pformat_putc( '.', stream ); -#endif - } - else - /* No localisation: just use ASCII '.'... - */ - __pformat_putc( '.', stream ); -} - -static -void __pformat_emit_numeric_value( int c, __pformat_t *stream ) -{ - /* Convenience helper to transfer numeric data from an internal - * formatting buffer to the ultimate destination... - */ - if( c == '.' ) - /* - * converting this internal representation of the the radix - * point to the appropriately localised representation... - */ - __pformat_emit_radix_point( stream ); - else if (c == ',') - { - wchar_t wcs; - if ((wcs = stream->thousands_chr) != 0) - __pformat_wputchars (&wcs, 1, stream); - } - else - /* and passing all other characters through, unmodified. - */ - __pformat_putc( c, stream ); -} - -static -void __pformat_emit_inf_or_nan( int sign, char *value, __pformat_t *stream ) -{ - /* Helper to emit INF or NAN where a floating point value - * resolves to one of these special states. - */ - int i; - char buf[4]; - char *p = buf; - - /* We use the string formatting helper to display INF/NAN, - * but we don't want truncation if the precision set for the - * original floating point output request was insufficient; - * ignore it! - */ - stream->precision = PFORMAT_IGNORE; - - if( sign ) - /* - * Negative infinity: emit the sign... - */ - *p++ = '-'; - - else if( stream->flags & PFORMAT_POSITIVE ) - /* - * Not negative infinity, but '+' flag is in effect; - * thus, we emit a positive sign... - */ - *p++ = '+'; - - else if( stream->flags & PFORMAT_ADDSPACE ) - /* - * No sign required, but space was reserved for it... - */ - *p++ = '\x20'; - - /* Copy the appropriate status indicator, up to a maximum of - * three characters, transforming to the case corresponding to - * the format specification... - */ - for( i = 3; i > 0; --i ) - *p++ = (*value++ & ~PFORMAT_XCASE) | (stream->flags & PFORMAT_XCASE); - - /* and emit the result. - */ - __pformat_putchars( buf, p - buf, stream ); -} - -static -void __pformat_emit_float( int sign, char *value, int len, __pformat_t *stream ) -{ - /* Helper to emit a fixed point representation of numeric data, - * as encoded by a prior call to `ecvt()' or `fcvt()'; (this does - * NOT include the exponent, for floating point format). - */ - if( len > 0 ) - { - /* The magnitude of `x' is greater than or equal to 1.0... - * reserve space in the output field, for the required number of - * decimal digits to be placed before the decimal point... - */ - if( stream->width > len ) - /* - * adjusting as appropriate, when width is sufficient... - */ - stream->width -= len; - - else - /* or simply ignoring the width specification, if not. - */ - stream->width = PFORMAT_IGNORE; - } - - else if( stream->width > 0 ) - /* - * The magnitude of `x' is less than 1.0... - * reserve space for exactly one zero before the decimal point. - */ - stream->width--; - - /* Reserve additional space for the digits which will follow the - * decimal point... - */ - if( (stream->width >= 0) && (stream->width > stream->precision) ) - /* - * adjusting appropriately, when sufficient width remains... - * (note that we must check both of these conditions, because - * precision may be more negative than width, as a result of - * adjustment to provide extra padding when trailing zeros - * are to be discarded from "%g" format conversion with a - * specified field width, but if width itself is negative, - * then there is explicitly to be no padding anyway). - */ - stream->width -= stream->precision; - - else - /* or again, ignoring the width specification, if not. - */ - stream->width = PFORMAT_IGNORE; - - /* Reserve space in the output field, for display of the decimal point, - * unless the precision is explicity zero, with the `#' flag not set. - */ - if ((stream->width > 0) - && ((stream->precision > 0) || (stream->flags & PFORMAT_HASHED))) - stream->width--; - - if (len > 0 && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0) - { - int cths = ((len + 2) / 3) - 1; - while (cths > 0 && stream->width > 0) - { - --cths; stream->width--; - } - } - - /* Reserve space in the output field, for display of the sign of the - * formatted value, if required; (i.e. if the value is negative, or if - * either the `space' or `+' formatting flags are set). - */ - if( (stream->width > 0) && (sign || (stream->flags & PFORMAT_SIGNED)) ) - stream->width--; - - /* Emit any padding space, as required to correctly right justify - * the output within the alloted field width. - */ - if( (stream->width > 0) && ((stream->flags & PFORMAT_JUSTIFY) == 0) ) - while( stream->width-- > 0 ) - __pformat_putc( '\x20', stream ); - - /* Emit the sign indicator, as appropriate... - */ - if( sign ) - /* - * mandatory, for negative values... - */ - __pformat_putc( '-', stream ); - - else if( stream->flags & PFORMAT_POSITIVE ) - /* - * optional, for positive values... - */ - __pformat_putc( '+', stream ); - - else if( stream->flags & PFORMAT_ADDSPACE ) - /* - * or just fill reserved space, when the space flag is in effect. - */ - __pformat_putc( '\x20', stream ); - - /* If the `0' flag is in effect, and not overridden by the `-' flag, - * then zero padding, to fill out the field, goes here... - */ - if( (stream->width > 0) - && ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) ) - while( stream->width-- > 0 ) - __pformat_putc( '0', stream ); - - /* Emit the digits of the encoded numeric value... - */ - if( len > 0 ) - { - /* - * ...beginning with those which precede the radix point, - * and appending any necessary significant trailing zeros. - */ - do { - __pformat_putc( *value ? *value++ : '0', stream); - --len; - if (len != 0 && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0 - && (len % 3) == 0) - __pformat_wputchars (&stream->thousands_chr, 1, stream); - } - while (len > 0); - } - else - /* The magnitude of the encoded value is less than 1.0, so no - * digits precede the radix point; we emit a mandatory initial - * zero, followed immediately by the radix point. - */ - __pformat_putc( '0', stream ); - - /* Unless the encoded value is integral, AND the radix point - * is not expressly demanded by the `#' flag, we must insert - * the appropriately localised radix point mark here... - */ - if( (stream->precision > 0) || (stream->flags & PFORMAT_HASHED) ) - __pformat_emit_radix_point( stream ); - - /* When the radix point offset, `len', is negative, this implies - * that additional zeros must appear, following the radix point, - * and preceding the first significant digit... - */ - if( len < 0 ) - { - /* To accommodate these, we adjust the precision, (reducing it - * by adding a negative value), and then we emit as many zeros - * as are required. - */ - stream->precision += len; - do __pformat_putc( '0', stream ); - while( ++len < 0 ); - } - - /* Now we emit any remaining significant digits, or trailing zeros, - * until the required precision has been achieved. - */ - while( stream->precision-- > 0 ) - __pformat_putc( *value ? *value++ : '0', stream ); -} - -static -void __pformat_emit_efloat( int sign, char *value, int e, __pformat_t *stream ) -{ - /* Helper to emit a floating point representation of numeric data, - * as encoded by a prior call to `ecvt()' or `fcvt()'; (this DOES - * include the following exponent). - */ - int exp_width = 1; - __pformat_intarg_t exponent; exponent.__pformat_llong_t = e -= 1; - - /* Determine how many digit positions are required for the exponent. - */ - while( (e /= 10) != 0 ) - exp_width++; - - /* Ensure that this is at least as many as the standard requirement. - */ - if( exp_width < stream->expmin ) - exp_width = stream->expmin; - - /* Adjust the residual field width allocation, to allow for the - * number of exponent digits to be emitted, together with a sign - * and exponent separator... - */ - if( stream->width > (exp_width += 2) ) - stream->width -= exp_width; - - else - /* ignoring the field width specification, if insufficient. - */ - stream->width = PFORMAT_IGNORE; - - /* Emit the significand, as a fixed point value with one digit - * preceding the radix point. - */ - __pformat_emit_float( sign, value, 1, stream ); - - /* Reset precision, to ensure the mandatory minimum number of - * exponent digits will be emitted, and set the flags to ensure - * the sign is displayed. - */ - stream->precision = stream->expmin; - stream->flags |= PFORMAT_SIGNED; - - /* Emit the exponent separator. - */ - __pformat_putc( ('E' | (stream->flags & PFORMAT_XCASE)), stream ); - - /* Readjust the field width setting, such that it again allows - * for the digits of the exponent, (which had been discounted when - * computing any left side padding requirement), so that they are - * correctly included in the computation of any right side padding - * requirement, (but here we exclude the exponent separator, which - * has been emitted, and so counted already). - */ - stream->width += exp_width - 1; - - /* And finally, emit the exponent itself, as a signed integer, - * with any padding required to achieve flush left justification, - * (which will be added automatically, by `__pformat_int()'). - */ - __pformat_int( exponent, stream ); -} - -static -void __pformat_float( long double x, __pformat_t *stream ) -{ - /* Handler for `%f' and `%F' format specifiers. - * - * This wraps calls to `__pformat_cvt()', `__pformat_emit_float()' - * and `__pformat_emit_inf_or_nan()', as appropriate, to achieve - * output in fixed point format. - */ - int sign, intlen; char *value; - - /* Establish the precision for the displayed value, defaulting to six - * digits following the decimal point, if not explicitly specified. - */ - if( stream->precision < 0 ) - stream->precision = 6; - - /* Encode the input value as ASCII, for display... - */ - value = __pformat_fcvt( x, stream->precision, &intlen, &sign ); - - if( intlen == PFORMAT_INFNAN ) - /* - * handle cases of `infinity' or `not-a-number'... - */ - __pformat_emit_inf_or_nan( sign, value, stream ); - - else - { /* or otherwise, emit the formatted result. - */ - __pformat_emit_float( sign, value, intlen, stream ); - - /* and, if there is any residual field width as yet unfilled, - * then we must be doing flush left justification, so pad out to - * the right hand field boundary. - */ - while( stream->width-- > 0 ) - __pformat_putc( '\x20', stream ); - } - - /* Clean up `__pformat_fcvt()' memory allocation for `value'... - */ - __pformat_fcvt_release( value ); -} - -static -void __pformat_efloat( long double x, __pformat_t *stream ) -{ - /* Handler for `%e' and `%E' format specifiers. - * - * This wraps calls to `__pformat_cvt()', `__pformat_emit_efloat()' - * and `__pformat_emit_inf_or_nan()', as appropriate, to achieve - * output in floating point format. - */ - int sign, intlen; char *value; - - /* Establish the precision for the displayed value, defaulting to six - * digits following the decimal point, if not explicitly specified. - */ - if( stream->precision < 0 ) - stream->precision = 6; - - /* Encode the input value as ASCII, for display... - */ - value = __pformat_ecvt( x, stream->precision + 1, &intlen, &sign ); - - if( intlen == PFORMAT_INFNAN ) - /* - * handle cases of `infinity' or `not-a-number'... - */ - __pformat_emit_inf_or_nan( sign, value, stream ); - - else - /* or otherwise, emit the formatted result. - */ - __pformat_emit_efloat( sign, value, intlen, stream ); - - /* Clean up `__pformat_ecvt()' memory allocation for `value'... - */ - __pformat_ecvt_release( value ); -} - -static -void __pformat_gfloat( long double x, __pformat_t *stream ) -{ - /* Handler for `%g' and `%G' format specifiers. - * - * This wraps calls to `__pformat_cvt()', `__pformat_emit_float()', - * `__pformat_emit_efloat()' and `__pformat_emit_inf_or_nan()', as - * appropriate, to achieve output in the more suitable of either - * fixed or floating point format. - */ - int sign, intlen; char *value; - - /* Establish the precision for the displayed value, defaulting to - * six significant digits, if not explicitly specified... - */ - if( stream->precision < 0 ) - stream->precision = 6; - - /* or to a minimum of one digit, otherwise... - */ - else if( stream->precision == 0 ) - stream->precision = 1; - - /* Encode the input value as ASCII, for display. - */ - value = __pformat_ecvt( x, stream->precision, &intlen, &sign ); - - if( intlen == PFORMAT_INFNAN ) - /* - * Handle cases of `infinity' or `not-a-number'. - */ - __pformat_emit_inf_or_nan( sign, value, stream ); - - else if( (-4 < intlen) && (intlen <= stream->precision) ) - { - /* Value lies in the acceptable range for fixed point output, - * (i.e. the exponent is no less than minus four, and the number - * of significant digits which precede the radix point is fewer - * than the least number which would overflow the field width, - * specified or implied by the established precision). - */ - if( (stream->flags & PFORMAT_HASHED) == PFORMAT_HASHED ) - /* - * The `#' flag is in effect... - * Adjust precision to retain the specified number of significant - * digits, with the proper number preceding the radix point, and - * the balance following it... - */ - stream->precision -= intlen; - - else - /* The `#' flag is not in effect... - * Here we adjust the precision to accommodate all digits which - * precede the radix point, but we truncate any balance following - * it, to suppress output of non-significant trailing zeros... - */ - if( ((stream->precision = strlen( value ) - intlen) < 0) - /* - * This may require a compensating adjustment to the field - * width, to accommodate significant trailing zeros, which - * precede the radix point... - */ - && (stream->width > 0) ) - stream->width += stream->precision; - - /* Now, we format the result as any other fixed point value. - */ - __pformat_emit_float( sign, value, intlen, stream ); - - /* If there is any residual field width as yet unfilled, then - * we must be doing flush left justification, so pad out to the - * right hand field boundary. - */ - while( stream->width-- > 0 ) - __pformat_putc( '\x20', stream ); - } - - else - { /* Value lies outside the acceptable range for fixed point; - * one significant digit will precede the radix point, so we - * decrement the precision to retain only the appropriate number - * of additional digits following it, when we emit the result - * in floating point format. - */ - if( (stream->flags & PFORMAT_HASHED) == PFORMAT_HASHED ) - /* - * The `#' flag is in effect... - * Adjust precision to emit the specified number of significant - * digits, with one preceding the radix point, and the balance - * following it, retaining any non-significant trailing zeros - * which are required to exactly match the requested precision... - */ - stream->precision--; - - else - /* The `#' flag is not in effect... - * Adjust precision to emit only significant digits, with one - * preceding the radix point, and any others following it, but - * suppressing non-significant trailing zeros... - */ - stream->precision = strlen( value ) - 1; - - /* Now, we format the result as any other floating point value. - */ - __pformat_emit_efloat( sign, value, intlen, stream ); - } - - /* Clean up `__pformat_ecvt()' memory allocation for `value'. - */ - __pformat_ecvt_release( value ); -} - -static -void __pformat_emit_xfloat( __pformat_fpreg_t value, __pformat_t *stream ) -{ - /* Helper for emitting floating point data, originating as - * either `double' or `long double' type, as a hexadecimal - * representation of the argument value. - */ - char buf[18 + 6], *p = buf; - __pformat_intarg_t exponent; short exp_width = 2; - - /* The mantissa field of the argument value representation can - * accommodate at most 16 hexadecimal digits, of which one will - * be placed before the radix point, leaving at most 15 digits - * to satisfy any requested precision; thus... - */ - if( (stream->precision >= 0) && (stream->precision < 15) ) - { - /* When the user specifies a precision within this range, - * we want to adjust the mantissa, to retain just the number - * of digits required, rounding up when the high bit of the - * leftmost discarded digit is set; (mask of 0x08 accounts - * for exactly one digit discarded, shifting 4 bits per - * digit, with up to 14 additional digits, to consume the - * full availability of 15 precision digits). - * - * However, before we perform the rounding operation, we - * normalise the mantissa, shifting it to the left by as many - * bit positions may be necessary, until its highest order bit - * is set, thus preserving the maximum number of bits in the - * rounded result as possible. - */ - while( value.__pformat_fpreg_mantissa < (LLONG_MAX + 1ULL) ) - value.__pformat_fpreg_mantissa <<= 1; - - /* We then shift the mantissa one bit position back to the - * right, to guard against possible overflow when the rounding - * adjustment is added. - */ - value.__pformat_fpreg_mantissa >>= 1; - - /* We now add the rounding adjustment, noting that to keep the - * 0x08 mask aligned with the shifted mantissa, we also need to - * shift it right by one bit initially, changing its starting - * value to 0x04... - */ - value.__pformat_fpreg_mantissa += 0x04LL << (4 * (14 - stream->precision)); - if( (value.__pformat_fpreg_mantissa & (LLONG_MAX + 1ULL)) == 0ULL ) - /* - * When the rounding adjustment would not have overflowed, - * then we shift back to the left again, to fill the vacated - * bit we reserved to accommodate the carry. - */ - value.__pformat_fpreg_mantissa <<= 1; - - else - /* Otherwise the rounding adjustment would have overflowed, - * so the carry has already filled the vacated bit; the effect - * of this is equivalent to an increment of the exponent. - */ - value.__pformat_fpreg_exponent++; - - /* We now complete the rounding to the required precision, by - * shifting the unwanted digits out, from the right hand end of - * the mantissa. - */ - value.__pformat_fpreg_mantissa >>= 4 * (15 - stream->precision); - } - - /* Encode the significant digits of the mantissa in hexadecimal - * ASCII notation, ready for transfer to the output stream... - */ - while( value.__pformat_fpreg_mantissa ) - { - /* taking the rightmost digit in each pass... - */ - int c = value.__pformat_fpreg_mantissa & 0xF; - if( c == (int) value.__pformat_fpreg_mantissa) - { - /* inserting the radix point, when we reach the last, - * (i.e. the most significant digit), unless we found no - * less significant digits, with no mandatory radix point - * inclusion, and no additional required precision... - */ - if( (p > buf) - || (stream->flags & PFORMAT_HASHED) || (stream->precision > 0) ) - { - /* - * Internally, we represent the radix point as an ASCII '.'; - * we will replace it with any locale specific alternative, - * at the time of transfer to the ultimate destination. - */ - *p++ = '.'; - } - - /* If the most significant hexadecimal digit of the encoded - * output value is greater than one, then the indicated value - * will appear too large, by an additional binary exponent - * corresponding to the number of higher order bit positions - * which it occupies... - */ - while( value.__pformat_fpreg_mantissa > 1 ) - { - /* so reduce the exponent value to compensate... - */ - value.__pformat_fpreg_exponent--; - value.__pformat_fpreg_mantissa >>= 1; - } - } - - else if( stream->precision > 0 ) - /* - * we have not yet fulfilled the desired precision, - * and we have not yet found the most significant digit, - * so account for the current digit, within the field - * width required to meet the specified precision. - */ - stream->precision--; - - if( (c > 0) || (p > buf) || (stream->precision >= 0) ) - { - /* - * Ignoring insignificant trailing zeros, (unless required to - * satisfy specified precision), store the current encoded digit - * into the pending output buffer, in LIFO order, and using the - * appropriate case for digits in the `A'..`F' range. - */ - *p++ = c > 9 ? (c - 10 + 'A') | (stream->flags & PFORMAT_XCASE) : c + '0'; - } - /* Shift out the current digit, (4-bit logical shift right), - * to align the next more significant digit to be extracted, - * and encoded in the next pass. - */ - value.__pformat_fpreg_mantissa >>= 4; - } - - if( p == buf ) - { - /* Nothing has been queued for output... - * We need at least one zero, and possibly a radix point. - */ - if( (stream->precision > 0) || (stream->flags & PFORMAT_HASHED) ) - *p++ = '.'; - - *p++ = '0'; - } - - if( stream->width > 0 ) - { - /* Adjust the user specified field width, to account for the - * number of digits minimally required, to display the encoded - * value, at the requested precision. - * - * FIXME: this uses the minimum number of digits possible for - * representation of the binary exponent, in strict conformance - * with C99 and POSIX specifications. Although there appears to - * be no Microsoft precedent for doing otherwise, we may wish to - * relate this to the `_get_output_format()' result, to maintain - * consistency with `%e', `%f' and `%g' styles. - */ - int min_width = p - buf; - int exponent2 = value.__pformat_fpreg_exponent; - - /* If we have not yet queued sufficient digits to fulfil the - * requested precision, then we must adjust the minimum width - * specification, to accommodate the additional digits which - * are required to do so. - */ - if( stream->precision > 0 ) - min_width += stream->precision; - - /* Adjust the minimum width requirement, to accomodate the - * sign, radix indicator and at least one exponent digit... - */ - min_width += stream->flags & PFORMAT_SIGNED ? 6 : 5; - while( (exponent2 = exponent2 / 10) != 0 ) - { - /* and increase as required, if additional exponent digits - * are needed, also saving the exponent field width adjustment, - * for later use when that is emitted. - */ - min_width++; - exp_width++; - } - - if( stream->width > min_width ) - { - /* When specified field width exceeds the minimum required, - * adjust to retain only the excess... - */ - stream->width -= min_width; - - /* and then emit any required left side padding spaces. - */ - if( (stream->flags & PFORMAT_JUSTIFY) == 0 ) - while( stream->width-- > 0 ) - __pformat_putc( '\x20', stream ); - } - - else - /* Specified field width is insufficient; just ignore it! - */ - stream->width = PFORMAT_IGNORE; - } - - /* Emit the sign of the encoded value, as required... - */ - if( stream->flags & PFORMAT_NEGATIVE ) - /* - * this is mandatory, to indicate a negative value... - */ - __pformat_putc( '-', stream ); - - else if( stream->flags & PFORMAT_POSITIVE ) - /* - * but this is optional, for a positive value... - */ - __pformat_putc( '+', stream ); - - else if( stream->flags & PFORMAT_ADDSPACE ) - /* - * with this optional alternative. - */ - __pformat_putc( '\x20', stream ); - - /* Prefix a `0x' or `0X' radix indicator to the encoded value, - * with case appropriate to the format specification. - */ - __pformat_putc( '0', stream ); - __pformat_putc( 'X' | (stream->flags & PFORMAT_XCASE), stream ); - - /* If the `0' flag is in effect... - * Zero padding, to fill out the field, goes here... - */ - if( (stream->width > 0) && (stream->flags & PFORMAT_ZEROFILL) ) - while( stream->width-- > 0 ) - __pformat_putc( '0', stream ); - - /* Next, we emit the encoded value, without its exponent... - */ - while( p > buf ) - __pformat_emit_numeric_value( *--p, stream ); - - /* followed by any additional zeros needed to satisfy the - * precision specification... - */ - while( stream->precision-- > 0 ) - __pformat_putc( '0', stream ); - - /* then the exponent prefix, (C99 and POSIX specify `p'), - * in the case appropriate to the format specification... - */ - __pformat_putc( 'P' | (stream->flags & PFORMAT_XCASE), stream ); - - /* and finally, the decimal representation of the binary exponent, - * as a signed value with mandatory sign displayed, in a field width - * adjusted to accommodate it, LEFT justified, with any additional - * right side padding remaining from the original field width. - */ - stream->width += exp_width; - stream->flags |= PFORMAT_SIGNED; - exponent.__pformat_llong_t = value.__pformat_fpreg_exponent; - __pformat_int( exponent, stream ); -} - -static -void __pformat_xldouble( long double x, __pformat_t *stream ) -{ - /* Handler for `%La' and `%LA' format specifiers, (with argument - * value specified as `long double' type). - */ - unsigned sign_bit = 0; - __pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x; - - /* First check for NaN; it is emitted unsigned... - */ - if( isnan( x ) ) - __pformat_emit_inf_or_nan( sign_bit, "NaN", stream ); - - else - { /* Capture the sign bit up-front, so we can show it correctly - * even when the argument value is zero or infinite. - */ - if( (sign_bit = (z.__pformat_fpreg_exponent & 0x8000)) != 0 ) - stream->flags |= PFORMAT_NEGATIVE; - - /* Check for infinity, (positive or negative)... - */ - if( isinf( x ) ) - /* - * displaying the appropriately signed indicator, - * when appropriate. - */ - __pformat_emit_inf_or_nan( sign_bit, "Inf", stream ); - - else - { /* The argument value is a representable number... - * extract the effective value of the biased exponent... - */ - z.__pformat_fpreg_exponent &= 0x7FFF; - if( z.__pformat_fpreg_exponent == 0 ) - { - /* A biased exponent value of zero means either a - * true zero value, if the mantissa field also has - * a zero value, otherwise... - */ - if( z.__pformat_fpreg_mantissa != 0 ) - { - /* ...this mantissa represents a subnormal value; - * adjust the exponent, while shifting the mantissa - * to the left, until its leading bit is 1. - */ - z.__pformat_fpreg_exponent = 1-0x3FFF; - while( (z.__pformat_fpreg_mantissa & (LLONG_MAX + 1ULL)) == 0 ) - { - z.__pformat_fpreg_mantissa <<= 1; - --z.__pformat_fpreg_exponent; - } - } - } - else - /* This argument represents a non-zero normal number; - * eliminate the bias from the exponent... - */ - z.__pformat_fpreg_exponent -= 0x3FFF; - - /* Finally, hand the adjusted representation off to the - * generalised hexadecimal floating point format handler... - */ - __pformat_emit_xfloat( z, stream ); - } - } -} - -int __cdecl -_evil_pformat (int flags, void *dest, int max, const APICHAR *fmt, va_list argv) -{ - int c; - int saved_errno = errno; - - __pformat_t stream = - { - /* Create and initialise a format control block - * for this output request. - */ - dest, /* output goes to here */ - flags &= PFORMAT_TO_FILE | PFORMAT_NOLIMIT, /* only these valid initially */ - PFORMAT_IGNORE, /* no field width yet */ - PFORMAT_IGNORE, /* nor any precision spec */ - PFORMAT_RPINIT, /* radix point uninitialised */ - (wchar_t)(0), /* leave it unspecified */ - 0, - (wchar_t)(0), /* leave it unspecified */ - 0, /* zero output char count */ - max, /* establish output limit */ - PFORMAT_MINEXP /* exponent chars preferred */ - }; - - format_scan: while( (c = *fmt++) != 0 ) - { - /* Format string parsing loop... - * The entry point is labelled, so that we can return to the start state - * from within the inner `conversion specification' interpretation loop, - * as soon as a conversion specification has been resolved. - */ - if( c == '%' ) - { - /* Initiate parsing of a `conversion specification'... - */ - __pformat_intarg_t argval; - __pformat_state_t state = PFORMAT_INIT; - __pformat_length_t length = PFORMAT_LENGTH_INT; - - /* Save the current format scan position, so that we can backtrack - * in the event of encountering an invalid format specification... - */ - const APICHAR *backtrack = fmt; - - /* Restart capture for dynamic field width and precision specs... - */ - int *width_spec = &stream.width; - - /* Reset initial state for flags, width and precision specs... - */ - stream.flags = flags; - stream.width = stream.precision = PFORMAT_IGNORE; - - while( *fmt ) - { - switch( c = *fmt++ ) - { - /* Data type specifiers... - * All are terminal, so exit the conversion spec parsing loop - * with a `goto format_scan', thus resuming at the outer level - * in the regular format string parser. - */ - case '%': - /* - * Not strictly a data type specifier... - * it simply converts as a literal `%' character. - * - * FIXME: should we require this to IMMEDIATELY follow the - * initial `%' of the "conversion spec"? (glibc `printf()' - * on GNU/Linux does NOT appear to require this, but POSIX - * and SUSv3 do seem to demand it). - */ - __pformat_putc( c, &stream ); - goto format_scan; - - case 'C': - /* - * Equivalent to `%lc'; set `length' accordingly, - * and simply fall through. - */ - length = PFORMAT_LENGTH_LONG; - - case 'c': - /* - * Single, (or single multibyte), character output... - * - * We handle these by copying the argument into our local - * `argval' buffer, and then we pass the address of that to - * either `__pformat_putchars()' or `__pformat_wputchars()', - * as appropriate, effectively formatting it as a string of - * the appropriate type, with a length of one. - * - * A side effect of this method of handling character data - * is that, if the user sets a precision of zero, then no - * character is actually emitted; we don't want that, so we - * forcibly override any user specified precision. - */ - stream.precision = PFORMAT_IGNORE; - - /* Now we invoke the appropriate format handler... - */ - if( (length == PFORMAT_LENGTH_LONG) - || (length == PFORMAT_LENGTH_LLONG) ) - { - /* considering any `long' type modifier as a reference to - * `wchar_t' data, (which is promoted to an `int' argument)... - */ - wchar_t iargval = (wchar_t)(va_arg( argv, int )); - __pformat_wputchars( &iargval, 1, &stream ); - } - else - { /* while anything else is simply taken as `char', (which - * is also promoted to an `int' argument)... - */ - argval.__pformat_uchar_t = (unsigned char)(va_arg( argv, int )); - __pformat_putchars( (char *)(&argval), 1, &stream ); - } - goto format_scan; - - case 'S': - /* - * Equivalent to `%ls'; set `length' accordingly, - * and simply fall through. - */ - length = PFORMAT_LENGTH_LONG; - - case 's': - if( (length == PFORMAT_LENGTH_LONG) - || (length == PFORMAT_LENGTH_LLONG)) - { - /* considering any `long' type modifier as a reference to - * a `wchar_t' string... - */ - __pformat_wcputs( va_arg( argv, wchar_t * ), &stream ); - } - else - /* This is normal string output; - * we simply invoke the appropriate handler... - */ - __pformat_puts( va_arg( argv, char * ), &stream ); - goto format_scan; - case 'm': /* strerror (errno) */ - __pformat_puts (strerror (saved_errno), &stream); - goto format_scan; - - case 'o': - case 'u': - case 'x': - case 'X': - /* - * Unsigned integer values; octal, decimal or hexadecimal format... - */ - if( length == PFORMAT_LENGTH_LLONG ) - /* - * with an `unsigned long long' argument, which we - * process `as is'... - */ - argval.__pformat_ullong_t = va_arg( argv, unsigned long long ); - - else if( length == PFORMAT_LENGTH_LONG ) - /* - * or with an `unsigned long', which we promote to - * `unsigned long long'... - */ - argval.__pformat_ullong_t = va_arg( argv, unsigned long ); - - else - { /* or for any other size, which will have been promoted - * to `unsigned int', we select only the appropriately sized - * least significant segment, and again promote to the same - * size as `unsigned long long'... - */ - argval.__pformat_ullong_t = va_arg( argv, unsigned int ); - if( length == PFORMAT_LENGTH_SHORT ) - /* - * from `unsigned short'... - */ - argval.__pformat_ullong_t = argval.__pformat_ushort_t; - - else if( length == PFORMAT_LENGTH_CHAR ) - /* - * or even from `unsigned char'... - */ - argval.__pformat_ullong_t = argval.__pformat_uchar_t; - } - - /* so we can pass any size of argument to either of two - * common format handlers... - */ - if( c == 'u' ) - /* - * depending on whether output is to be encoded in - * decimal format... - */ - __pformat_int( argval, &stream ); - - else - /* or in octal or hexadecimal format... - */ - __pformat_xint( c, argval, &stream ); - - goto format_scan; - - case 'd': - case 'i': - /* - * Signed integer values; decimal format... - * This is similar to `u', but must process `argval' as signed, - * and be prepared to handle negative numbers. - */ - stream.flags |= PFORMAT_NEGATIVE; - - if( length == PFORMAT_LENGTH_LLONG ) - /* - * The argument is a `long long' type... - */ - argval.__pformat_llong_t = va_arg( argv, long long ); - - else if( length == PFORMAT_LENGTH_LONG ) - /* - * or here, a `long' type... - */ - argval.__pformat_llong_t = va_arg( argv, long ); - - else - { /* otherwise, it's an `int' type... - */ - argval.__pformat_llong_t = va_arg( argv, int ); - if( length == PFORMAT_LENGTH_SHORT ) - /* - * but it was promoted from a `short' type... - */ - argval.__pformat_llong_t = argval.__pformat_short_t; - else if( length == PFORMAT_LENGTH_CHAR ) - /* - * or even from a `char' type... - */ - argval.__pformat_llong_t = argval.__pformat_char_t; - } - - /* In any case, all share a common handler... - */ - __pformat_int( argval, &stream ); - goto format_scan; - - case 'p': - /* - * Pointer argument; format as hexadecimal, subject to... - */ - if( (state == PFORMAT_INIT) && (stream.flags == flags) ) - { - /* Here, the user didn't specify any particular - * formatting attributes. We must choose a default - * which will be compatible with Microsoft's (broken) - * scanf() implementation, (i.e. matching the default - * used by MSVCRT's printf(), which appears to resemble - * "%0.8X" for 32-bit pointers); in particular, we MUST - * NOT adopt a GNU-like format resembling "%#x", because - * Microsoft's scanf() will choke on the "0x" prefix. - */ - stream.flags |= PFORMAT_ZEROFILL; - stream.precision = 2 * sizeof( uintptr_t ); - } - argval.__pformat_ullong_t = va_arg( argv, uintptr_t ); - __pformat_xint( 'x', argval, &stream ); - goto format_scan; - - case 'e': - /* - * Floating point format, with lower case exponent indicator - * and lower case `inf' or `nan' representation when required; - * select lower case mode, and simply fall through... - */ - stream.flags |= PFORMAT_XCASE; - - case 'E': - /* - * Floating point format, with upper case exponent indicator - * and upper case `INF' or `NAN' representation when required, - * (or lower case for all of these, on fall through from above); - * select lower case mode, and simply fall through... - */ - if( stream.flags & PFORMAT_LDOUBLE ) - /* - * for a `long double' argument... - */ - __pformat_efloat( va_arg( argv, long double ), &stream ); - - else - /* or just a `double', which we promote to `long double', - * so the two may share a common format handler. - */ - __pformat_efloat( (long double)(va_arg( argv, double )), &stream ); - - goto format_scan; - - case 'f': - /* - * Fixed point format, using lower case for `inf' and - * `nan', when appropriate; select lower case mode, and - * simply fall through... - */ - stream.flags |= PFORMAT_XCASE; - - case 'F': - /* - * Fixed case format using upper case, or lower case on - * fall through from above, for `INF' and `NAN'... - */ - if( stream.flags & PFORMAT_LDOUBLE ) - /* - * for a `long double' argument... - */ - __pformat_float( va_arg( argv, long double ), &stream ); - - else - /* or just a `double', which we promote to `long double', - * so the two may share a common format handler. - */ - __pformat_float( (long double)(va_arg( argv, double )), &stream ); - - goto format_scan; - - case 'g': - /* - * Generalised floating point format, with lower case - * exponent indicator when required; select lower case - * mode, and simply fall through... - */ - stream.flags |= PFORMAT_XCASE; - - case 'G': - /* - * Generalised floating point format, with upper case, - * or on fall through from above, with lower case exponent - * indicator when required... - */ - if( stream.flags & PFORMAT_LDOUBLE ) - /* - * for a `long double' argument... - */ - __pformat_gfloat( va_arg( argv, long double ), &stream ); - - else - /* or just a `double', which we promote to `long double', - * so the two may share a common format handler. - */ - __pformat_gfloat( (long double)(va_arg( argv, double )), &stream ); - - goto format_scan; - - case 'a': - /* - * Hexadecimal floating point format, with lower case radix - * and exponent indicators; select the lower case mode, and - * fall through... - */ - stream.flags |= PFORMAT_XCASE; - - case 'A': - /* - * Hexadecimal floating point format; handles radix and - * exponent indicators in either upper or lower case... - */ - if( stream.flags & PFORMAT_LDOUBLE ) - /* - * with a `long double' argument... - */ - __pformat_xldouble( va_arg( argv, long double ), &stream ); - - else - /* or just a `double'. - */ - __pformat_xldouble( (long double)(va_arg( argv, double )), &stream ); - - goto format_scan; - - case 'n': - /* - * Save current output character count... - */ - if( length == PFORMAT_LENGTH_CHAR ) - /* - * to a signed `char' destination... - */ - *va_arg( argv, char * ) = stream.count; - - else if( length == PFORMAT_LENGTH_SHORT ) - /* - * or to a signed `short'... - */ - *va_arg( argv, short * ) = stream.count; - - else if( length == PFORMAT_LENGTH_LONG ) - /* - * or to a signed `long'... - */ - *va_arg( argv, long * ) = stream.count; - - else if( length == PFORMAT_LENGTH_LLONG ) - /* - * or to a signed `long long'... - */ - *va_arg( argv, long long * ) = stream.count; - - else - /* - * or, by default, to a signed `int'. - */ - *va_arg( argv, int * ) = stream.count; - - goto format_scan; - - /* Argument length modifiers... - * These are non-terminal; each sets the format parser - * into the PFORMAT_END state, and ends with a `break'. - */ - case 'h': - /* - * Interpret the argument as explicitly of a `short' - * or `char' data type, truncated from the standard - * length defined for integer promotion. - */ - if( *fmt == 'h' ) - { - /* Modifier is `hh'; data type is `char' sized... - * Skip the second `h', and set length accordingly. - */ - ++fmt; - length = PFORMAT_LENGTH_CHAR; - } - - else - /* Modifier is `h'; data type is `short' sized... - */ - length = PFORMAT_LENGTH_SHORT; - - state = PFORMAT_END; - break; - - case 'j': - /* - * Interpret the argument as being of the same size as - * a `intmax_t' entity... - */ - length = __pformat_arg_length( intmax_t ); - state = PFORMAT_END; - break; - -# ifdef _WIN32 - - case 'I': - /* - * The MSVCRT implementation of the printf() family of - * functions explicitly uses... - */ - if( (fmt[0] == '6') && (fmt[1] == '4') ) - { - /* I64' instead of `ll', - * when referring to `long long' integer types... - */ - length = PFORMAT_LENGTH_LLONG; - fmt += 2; - } - - else if( (fmt[0] == '3') && (fmt[1] == '2') ) - { - /* and `I32' instead of `l', - * when referring to `long' integer types... - */ - length = PFORMAT_LENGTH_LONG; - fmt += 2; - } - - else - /* or unqualified `I' instead of `t' or `z', - * when referring to `ptrdiff_t' or `size_t' entities; - * (we will choose to map it to `ptrdiff_t'). - */ - length = __pformat_arg_length( ptrdiff_t ); - - state = PFORMAT_END; - break; - -# endif - - case 'l': - /* - * Interpret the argument as explicitly of a - * `long' or `long long' data type. - */ - if( *fmt == 'l' ) - { - /* Modifier is `ll'; data type is `long long' sized... - * Skip the second `l', and set length accordingly. - */ - ++fmt; - length = PFORMAT_LENGTH_LLONG; - } - - else - /* Modifier is `l'; data type is `long' sized... - */ - length = PFORMAT_LENGTH_LONG; - - state = PFORMAT_END; - break; - - case 'L': - /* - * Identify the appropriate argument as a `long double', - * when associated with `%a', `%A', `%e', `%E', `%f', `%F', - * `%g' or `%G' format specifications. - */ - stream.flags |= PFORMAT_LDOUBLE; - state = PFORMAT_END; - break; - - case 't': - /* - * Interpret the argument as being of the same size as - * a `ptrdiff_t' entity... - */ - length = __pformat_arg_length( ptrdiff_t ); - state = PFORMAT_END; - break; - - case 'z': - /* - * Interpret the argument as being of the same size as - * a `size_t' entity... - */ - length = __pformat_arg_length( size_t ); - state = PFORMAT_END; - break; - - /* Precision indicator... - * May appear once only; it must precede any modifier - * for argument length, or any data type specifier. - */ - case '.': - if( state < PFORMAT_GET_PRECISION ) - { - /* We haven't seen a precision specification yet, - * so initialise it to zero, (in case no digits follow), - * and accept any following digits as the precision. - */ - stream.precision = 0; - width_spec = &stream.precision; - state = PFORMAT_GET_PRECISION; - } - - else - /* We've already seen a precision specification, - * so this is just junk; proceed to end game. - */ - state = PFORMAT_END; - - /* Either way, we must not fall through here. - */ - break; - - /* Variable field width, or precision specification, - * derived from the argument list... - */ - case '*': - /* - * When this appears... - */ - if( width_spec - && ((state == PFORMAT_INIT) || (state == PFORMAT_GET_PRECISION)) ) - { - /* in proper context; assign to field width - * or precision, as appropriate. - */ - if( (*width_spec = va_arg( argv, int )) < 0 ) - { - /* Assigned value was negative... - */ - if( state == PFORMAT_INIT ) - { - /* For field width, this is equivalent to - * a positive value with the `-' flag... - */ - stream.flags |= PFORMAT_LJUSTIFY; - stream.width = -stream.width; - } - - else - /* while as a precision specification, - * it should simply be ignored. - */ - stream.precision = PFORMAT_IGNORE; - } - } - - else - /* out of context; give up on width and precision - * specifications for this conversion. - */ - state = PFORMAT_END; - - /* Mark as processed... - * we must not see `*' again, in this context. - */ - width_spec = NULL; - break; - - /* Formatting flags... - * Must appear while in the PFORMAT_INIT state, - * and are non-terminal, so again, end with `break'. - */ - case '#': - /* - * Select alternate PFORMAT_HASHED output style. - */ - if( state == PFORMAT_INIT ) - stream.flags |= PFORMAT_HASHED; - break; - - case '+': - /* - * Print a leading sign with numeric output, - * for both positive and negative values. - */ - if( state == PFORMAT_INIT ) - stream.flags |= PFORMAT_POSITIVE; - break; - - case '-': - /* - * Select left justification of displayed output - * data, within the output field width, instead of - * the default flush right justification. - */ - if( state == PFORMAT_INIT ) - stream.flags |= PFORMAT_LJUSTIFY; - break; - - case '\'': - /* - * This is an XSI extension to the POSIX standard, - * which we do not support, at present. - */ - if (state == PFORMAT_INIT) - { - int len; wchar_t rpchr; mbstate_t cstate; - stream.flags |= PFORMAT_GROUPED; /* $$$$ */ - memset (&cstate, 0, sizeof(state)); - if ((len = mbrtowc( &rpchr, localeconv()->thousands_sep, 16, &cstate)) > 0) - stream.thousands_chr = rpchr; - stream.thousands_chr_len = len; - } - break; - - case '\x20': - /* - * Reserve a single space, within the output field, - * for display of the sign of signed data; this will - * be occupied by the minus sign, if the data value - * is negative, or by a plus sign if the data value - * is positive AND the `+' flag is also present, or - * by a space otherwise. (Technically, this flag - * is redundant, if the `+' flag is present). - */ - if( state == PFORMAT_INIT ) - stream.flags |= PFORMAT_ADDSPACE; - break; - - case '0': - /* - * May represent a flag, to activate the `pad with zeros' - * option, or it may simply be a digit in a width or in a - * precision specification... - */ - if( state == PFORMAT_INIT ) - { - /* This is the flag usage... - */ - stream.flags |= PFORMAT_ZEROFILL; - break; - } - - default: - /* - * If we didn't match anything above, then we will check - * for digits, which we may accumulate to generate field - * width or precision specifications... - */ - if( (state < PFORMAT_END) && ('9' >= c) && (c >= '0') ) - { - if( state == PFORMAT_INIT ) - /* - * Initial digits explicitly relate to field width... - */ - state = PFORMAT_SET_WIDTH; - - else if( state == PFORMAT_GET_PRECISION ) - /* - * while those following a precision indicator - * explicitly relate to precision. - */ - state = PFORMAT_SET_PRECISION; - - if( width_spec ) - { - /* We are accepting a width or precision specification... - */ - if( *width_spec < 0 ) - /* - * and accumulation hasn't started yet; we simply - * initialise the accumulator with the current digit - * value, converting from ASCII to decimal. - */ - *width_spec = c - '0'; - - else - /* Accumulation has already started; we perform a - * `leftwise decimal digit shift' on the accumulator, - * (i.e. multiply it by ten), then add the decimal - * equivalent value of the current digit. - */ - *width_spec = *width_spec * 10 + c - '0'; - } - } - - else - { - /* We found a digit out of context, or some other character - * with no designated meaning; reject this format specification, - * backtrack, and emit it as literal text... - */ - fmt = backtrack; - __pformat_putc( '%', &stream ); - goto format_scan; - } - } - } - } - - else - /* We just parsed a character which is not included within any format - * specification; we simply emit it as a literal. - */ - __pformat_putc( c, &stream ); - } - - /* When we have fully dispatched the format string, the return value is the - * total number of bytes we transferred to the output destination. - */ - return stream.count; -} - -/* $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 592b568..0000000 --- a/src/lib/evil/evil_pformatw.c +++ /dev/null @@ -1,9 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the w64 mingw-runtime package. - * No warranty is given; refer to the file DISCLAIMER.PD within this package. - */ -#define __BUILD_WIDEAPI 1 - -#include "evil_pformata.c" - diff --git a/src/lib/evil/evil_print.h b/src/lib/evil/evil_print.h deleted file mode 100644 index 511247b..0000000 --- a/src/lib/evil/evil_print.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __EVIL_PRINT_H__ -#define __EVIL_PRINT_H__ - - -#include "evil_macro.h" - - -EAPI int __cdecl _evil_fprintfa(FILE *, const char *, ...) __EVIL_NOTHROW; -EAPI int __cdecl _evil_printfa(const char *, ...) __EVIL_PRINTF(1, 2) __EVIL_NOTHROW; -EAPI int __cdecl _evil_sprintfa(char *, const char *, ...) __EVIL_NOTHROW; -EAPI int __cdecl _evil_snprintfa(char *, size_t, const char *, ...) __EVIL_PRINTF(3, 4) __EVIL_NOTHROW; -EAPI int __cdecl _evil_vfprintfa(FILE *, const char *, va_list) __EVIL_NOTHROW; -EAPI int __cdecl _evil_vprintfa(const char *, va_list) __EVIL_NOTHROW; -EAPI int __cdecl _evil_vsprintfa(char *, const char *, va_list) __EVIL_NOTHROW; -EAPI int __cdecl _evil_vsnprintfa(char *, size_t, const char *, va_list) __EVIL_NOTHROW; - -EAPI int __cdecl _evil_fscanf (FILE *, const char *, ...) __EVIL_NOTHROW; -EAPI int __cdecl _evil_scanf (const char *, ...) __EVIL_NOTHROW; -EAPI int __cdecl _evil_sscanf (const char *, const char *, ...) __EVIL_NOTHROW; -EAPI int __cdecl _evil_vfscanf(FILE *, const char *, va_list) __EVIL_NOTHROW; -EAPI int __cdecl _evil_vscanf (const char *, va_list) __EVIL_NOTHROW; -EAPI int __cdecl _evil_vsscanf(const char *, const char *, va_list) __EVIL_NOTHROW; - -EAPI int __cdecl _evil_asprintf(char ** __restrict__, const char * __restrict__, ...) __EVIL_NOTHROW; -EAPI int __cdecl _evil_vasprintf(char ** __restrict__, const char * __restrict__, va_list) __EVIL_NOTHROW; - -EAPI int __cdecl _evil_fprintfw(FILE *, const wchar_t *, ...) __EVIL_NOTHROW; -EAPI int __cdecl _evil_printfw(const wchar_t *, ...) __EVIL_NOTHROW; -EAPI int __cdecl _evil_sprintfw(wchar_t *, const wchar_t *, ...) __EVIL_NOTHROW; -EAPI int __cdecl _evil_snprintfw(wchar_t *, size_t, const wchar_t *, ...) __EVIL_NOTHROW; -EAPI int __cdecl _evil_vfprintfw(FILE *, const wchar_t *, va_list) __EVIL_NOTHROW; -EAPI int __cdecl _evil_vprintfw(const wchar_t *, va_list) __EVIL_NOTHROW; -EAPI int __cdecl _evil_vsprintfw(wchar_t *, const wchar_t *, va_list) __EVIL_NOTHROW; -EAPI int __cdecl _evil_vsnprintfw(wchar_t *, size_t, const wchar_t *, va_list) __EVIL_NOTHROW; - - -#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 a0f8593..0000000 --- a/src/lib/evil/evil_printa.c +++ /dev/null @@ -1,1768 +0,0 @@ -#define __CRT__NO_INLINE - -#include <errno.h> -#include <limits.h> -#include <stddef.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <wchar.h> -#include <ctype.h> -#include <wctype.h> -#include <locale.h> - -#include "evil_pformat.h" -#include "evil_print.h" -#include "gdtoa/gdtoa.h" - - -/*============================================================================* - * Local * - *============================================================================*/ - - -/* Helper flags for conversion. */ -#define IS_C 0x0001 -#define IS_S 0x0002 -#define IS_L 0x0004 -#define IS_LL 0x0008 -#define IS_SIGNED_NUM 0x0010 -#define IS_POINTER 0x0020 -#define IS_HEX_FLOAT 0x0040 -#define IS_SUPPRESSED 0x0080 -#define USE_GROUP 0x0100 -#define USE_GNU_ALLOC 0x0200 -#define USE_POSIX_ALLOC 0x0400 - -#define IS_ALLOC_USED (USE_GNU_ALLOC | USE_POSIX_ALLOC) - -#ifndef __BUILD_WIDEAPI - -/* internal stream structure with back-buffer. */ -typedef struct _IFP -{ - __extension__ union { - void *fp; - const char *str; - }; - int bch[1024]; - int is_string : 1; - int back_top; - int seen_eof : 1; -} _IFP; - -static void * -get_va_nth (va_list argp, unsigned int n) -{ - va_list ap; - if (!n) abort (); - va_copy (ap, argp); - while (--n > 0) - (void) va_arg(ap, void *); - return va_arg (ap, void *); -} - -static void -optimize_alloc (char **p, char *end, size_t alloc_sz) -{ - size_t need_sz; - char *h; - - if (!p || !*p) - return; - - need_sz = end - *p; - if (need_sz == alloc_sz) - return; - - if ((h = (char *) realloc (*p, need_sz)) != NULL) - *p = h; -} - -static void -back_ch (int c, _IFP *s, size_t *rin, int not_eof) -{ - if (!not_eof && c == EOF) - return; - if (s->is_string == 0) - { - FILE *fp = s->fp; - ungetc (c, fp); - rin[0] -= 1; - return; - } - rin[0] -= 1; - s->bch[s->back_top] = c; - s->back_top += 1; -} - -static int -in_ch (_IFP *s, size_t *rin) -{ - int r; - if (s->back_top) - { - s->back_top -= 1; - r = s->bch[s->back_top]; - rin[0] += 1; - } - else if (s->seen_eof) - { - return EOF; - } - else if (s->is_string) - { - const char *ps = s->str; - r = ((int) *ps) & 0xff; - ps++; - if (r != 0) - { - rin[0] += 1; - s->str = ps; - return r; - } - s->seen_eof = 1; - return EOF; - } - else - { - FILE *fp = (FILE *) s->fp; - r = getc (fp); - if (r != EOF) - rin[0] += 1; - else s->seen_eof = 1; - } - return r; -} - -static int -match_string (_IFP *s, size_t *rin, int *c, const char *str) -{ - int ch = *c; - - if (*str == 0) - return 1; - - if (*str != (char) tolower (ch)) - return 0; - ++str; - while (*str != 0) - { - if ((ch = in_ch (s, rin)) == EOF) - { - c[0] = ch; - return 0; - } - - if (*str != (char) tolower (ch)) - { - c[0] = ch; - return 0; - } - ++str; - } - c[0] = ch; - return 1; -} - -struct gcollect -{ - size_t count; - struct gcollect *next; - char **ptrs[32]; -}; - -static void -release_ptrs (struct gcollect **pt, char **wbuf) -{ - struct gcollect *pf; - size_t cnt; - - if (!pt || (pf = *pt) == NULL) - return; - while (pf != NULL) - { - struct gcollect *pf_sv = pf; - for (cnt = 0; cnt < pf->count; ++cnt) - { - free (*pf->ptrs[cnt]); - *pf->ptrs[cnt] = NULL; - } - pf = pf->next; - free (pf_sv); - } - *pt = NULL; - if (wbuf) - { - free (*wbuf); - *wbuf = NULL; - } -} - -static int -cleanup_return (int rval, struct gcollect **pfree, char **strp, char **wbuf) -{ - if (rval == EOF) - release_ptrs (pfree, wbuf); - else - { - if (pfree) - { - struct gcollect *pf = *pfree, *pf_sv; - while (pf != NULL) - { - pf_sv = pf; - pf = pf->next; - free (pf_sv); - } - *pfree = NULL; - } - if (strp != NULL) - { - free (*strp); - *strp = NULL; - } - if (wbuf) - { - free (*wbuf); - *wbuf = NULL; - } - } - return rval; -} - -static struct gcollect * -resize_gcollect (struct gcollect *pf) -{ - struct gcollect *np; - if (pf && pf->count < 32) - return pf; - np = malloc (sizeof (struct gcollect)); - np->count = 0; - np->next = pf; - return np; -} - -static char * -resize_wbuf (size_t wpsz, size_t *wbuf_max_sz, char *old) -{ - char *wbuf; - size_t nsz; - if (*wbuf_max_sz != wpsz) - return old; - nsz = (256 > (2 * wbuf_max_sz[0]) ? 256 : (2 * wbuf_max_sz[0])); - if (!old) - wbuf = (char *) malloc (nsz); - else - wbuf = (char *) realloc (old, nsz); - if (!wbuf) - { - if (old) - free (old); - } - else - *wbuf_max_sz = nsz; - return wbuf; -} - -static int -_evil_sformat (_IFP *s, const char *format, va_list argp) -{ - const char *f = format; - struct gcollect *gcollect = NULL; - size_t read_in = 0, wbuf_max_sz = 0, cnt; - ssize_t str_sz = 0; - char *str = NULL, **pstr = NULL, *wbuf = NULL; - wchar_t *wstr = NULL; - int rval = 0, c = 0, ignore_ws = 0; - va_list arg; - unsigned char fc; - unsigned int npos; - int width, flags, base = 0, errno_sv; - size_t wbuf_cur_sz, read_in_sv, new_sz, n; - char seen_dot, seen_exp, is_neg, not_in; - char *tmp_wbuf_ptr, buf[MB_LEN_MAX]; - const char *lc_decimal_point, *lc_thousands_sep; - mbstate_t state, cstate; - union { - unsigned long long ull; - unsigned long ul; - long long ll; - long l; - } cv_val; - - arg = argp; - - if (!s || s->fp == NULL || !format) - { - errno = EINVAL; - return EOF; - } - - memset (&state, 0, sizeof (state)); - - lc_decimal_point = localeconv()->decimal_point; - lc_thousands_sep = localeconv()->thousands_sep; - if (lc_thousands_sep != NULL && *lc_thousands_sep == 0) - lc_thousands_sep = NULL; - - while (*f != 0) - { - if (!isascii ((unsigned char) *f)) - { - int len; - - if ((len = mbrlen (f, strlen (f), &state)) > 0) - { - do - { - if ((c = in_ch (s, &read_in)) == EOF || c != (unsigned char) *f++) - { - back_ch (c, s, &read_in, 1); - return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); - } - } - while (--len > 0); - - continue; - } - } - - fc = *f++; - if (fc != '%') - { - if (isspace (fc)) - ignore_ws = 1; - else - { - if ((c = in_ch (s, &read_in)) == EOF) - return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); - - if (ignore_ws) - { - ignore_ws = 0; - if (isspace (c)) - { - do - { - if ((c = in_ch (s, &read_in)) == EOF) - return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); - } - while (isspace (c)); - } - } - - if (c != fc) - { - back_ch (c, s, &read_in, 0); - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - } - - continue; - } - - width = flags = 0; - npos = 0; - wbuf_cur_sz = 0; - - if (isdigit ((unsigned char) *f)) - { - const char *svf = f; - npos = (unsigned char) *f++ - '0'; - while (isdigit ((unsigned char) *f)) - npos = npos * 10 + ((unsigned char) *f++ - '0'); - if (*f != '$') - { - npos = 0; - f = svf; - } - else - f++; - } - - do - { - if (*f == '*') - flags |= IS_SUPPRESSED; - else if (*f == '\'') - { - if (lc_thousands_sep) - flags |= USE_GROUP; - } - else if (*f == 'I') - /* we don't support locale's digits (i18N), but ignore it for now silently. */ - ; - else - break; - ++f; - } - while (1); - - while (isdigit ((unsigned char) *f)) - width = width * 10 + ((unsigned char) *f++ - '0'); - - if (!width) - width = -1; - - switch (*f) - { - case 'h': - ++f; - flags |= (*f == 'h' ? IS_C : IS_S); - if (*f == 'h') - ++f; - break; - case 'l': - ++f; - flags |= (*f == 'l' ? IS_LL : 0) | IS_L; - if (*f == 'l') - ++f; - break; - case 'q': case 'L': - ++f; - flags |= IS_LL | IS_L; - break; - case 'a': - if (f[1] != 's' && f[1] != 'S' && f[1] != '[') - break; - ++f; - flags |= USE_GNU_ALLOC; - break; - case 'm': - flags |= USE_POSIX_ALLOC; - ++f; - if (*f == 'l') - { - flags |= IS_L; - f++; - } - break; - case 'z': -#ifdef _WIN64 - flags |= IS_LL; -#else - flags |= IS_L; -#endif - ++f; - break; - case 'j': - if (sizeof (uintmax_t) > sizeof (unsigned long)) - flags |= IS_LL; - else if (sizeof (uintmax_t) > sizeof (unsigned int)) - flags |= IS_L; - ++f; - break; - case 't': -#ifdef _WIN64 - flags |= IS_LL; -#else - flags |= IS_L; -#endif - ++f; - break; - case 0: - return cleanup_return (rval, &gcollect, pstr, &wbuf); - default: - break; - } - - if (*f == 0) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - - fc = *f++; - if (ignore_ws || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n')) - { - errno_sv = errno; - errno = 0; - do - { - if ((c == EOF || (c = in_ch (s, &read_in)) == EOF) - && errno == EINTR) - return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); - } - while (isspace (c)); - - ignore_ws = 0; - errno = errno_sv; - back_ch (c, s, &read_in, 0); - } - - switch (fc) - { - case 'c': - if ((flags & IS_L) != 0) - fc = 'C'; - break; - case 's': - if ((flags & IS_L) != 0) - fc = 'S'; - break; - } - - switch (fc) - { - case '%': - if ((c = in_ch (s, &read_in)) == EOF) - return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); - if (c != fc) - { - back_ch (c, s, &read_in, 1); - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - break; - - case 'n': - if ((flags & IS_SUPPRESSED) == 0) - { - if ((flags & IS_LL) != 0) - *(npos != 0 ? (long long *) get_va_nth (argp, npos) : va_arg (arg, long long *)) = read_in; - else if ((flags & IS_L) != 0) - *(npos != 0 ? (long *) get_va_nth (argp, npos) : va_arg (arg, long *)) = read_in; - else if ((flags & IS_S) != 0) - *(npos != 0 ? (short *) get_va_nth (argp, npos) : va_arg (arg, short *)) = read_in; - else if ((flags & IS_C) != 0) - *(npos != 0 ? (char *) get_va_nth (argp, npos) : va_arg (arg, char *)) = read_in; - else - *(npos != 0 ? (int *) get_va_nth (argp, npos) : va_arg (arg, int *)) = read_in; - } - break; - - case 'c': - if (width == -1) - width = 1; - - if ((flags & IS_SUPPRESSED) == 0) - { - if ((flags & IS_ALLOC_USED) != 0) - { - if (npos != 0) - pstr = (char **) get_va_nth (argp, npos); - else - pstr = va_arg (arg, char **); - - if (!pstr) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - - str_sz = (width > 1024 ? 1024 : width); - if ((str = *pstr = (char *) malloc (str_sz)) == NULL) - return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); - - gcollect = resize_gcollect (gcollect); - gcollect->ptrs[gcollect->count++] = pstr; - } - else - { - if (npos != 0) - str = (char *) get_va_nth (argp, npos); - else - str = va_arg (arg, char *); - if (!str) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - } - - if ((c = in_ch (s, &read_in)) == EOF) - return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); - - if ((flags & IS_SUPPRESSED) == 0) - { - do - { - if ((flags & IS_ALLOC_USED) != 0 && str == (*pstr + str_sz)) - { - new_sz = str_sz + (str_sz >= width ? width - 1 : str_sz); - while ((str = (char *) realloc (*pstr, new_sz)) == NULL - && new_sz > (size_t) (str_sz + 1)) - new_sz = str_sz + 1; - if (!str) - { - release_ptrs (&gcollect, &wbuf); - return EOF; - } - *pstr = str; - str += str_sz; - str_sz = new_sz; - } - *str++ = c; - } - while (--width > 0 && (c = in_ch (s, &read_in)) != EOF); - } - else - while (--width > 0 && (c = in_ch (s, &read_in)) != EOF); - - if ((flags & IS_SUPPRESSED) == 0) - { - optimize_alloc (pstr, str, str_sz); - pstr = NULL; - ++rval; - } - - break; - - case 'C': - if (width == -1) - width = 1; - - if ((flags & IS_SUPPRESSED) == 0) - { - if ((flags & IS_ALLOC_USED) != 0) - { - if (npos != 0) - pstr = (char **) get_va_nth (argp, npos); - else - pstr = va_arg (arg, char **); - - if (!pstr) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - str_sz = (width > 1024 ? 1024 : width); - *pstr = (char *) malloc (str_sz * sizeof (wchar_t)); - if ((wstr = (wchar_t *) *pstr) == NULL) - return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); - gcollect = resize_gcollect (gcollect); - gcollect->ptrs[gcollect->count++] = pstr; - } - else - { - if (npos != 0) - wstr = (wchar_t *) get_va_nth (argp, npos); - else - wstr = va_arg (arg, wchar_t *); - if (!wstr) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - } - - if ((c = in_ch (s, &read_in)) == EOF) - return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); - - memset (&cstate, 0, sizeof (cstate)); - - do - { - buf[0] = c; - - if ((flags & IS_SUPPRESSED) == 0 && (flags & IS_ALLOC_USED) != 0 - && wstr == ((wchar_t *) *pstr + str_sz)) - { - new_sz = str_sz + (str_sz > width ? width - 1 : str_sz); - - while ((wstr = (wchar_t *) realloc (*pstr, new_sz * sizeof (wchar_t))) == NULL - && new_sz > (size_t) (str_sz + 1)) - new_sz = str_sz + 1; - if (!wstr) - { - release_ptrs (&gcollect, &wbuf); - return EOF; - } - *pstr = (char *) wstr; - wstr += str_sz; - str_sz = new_sz; - } - - while (1) - { - n = mbrtowc ((flags & IS_SUPPRESSED) == 0 ? wstr : NULL, buf, 1, &cstate); - - if (n == (size_t) -2) - { - if ((c = in_ch (s, &read_in)) == EOF) - { - errno = EILSEQ; - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - - buf[0] = c; - continue; - } - - if (n != 1) - { - errno = EILSEQ; - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - break; - } - - ++wstr; - } - while (--width > 0 && (c = in_ch (s, &read_in)) != EOF); - - if ((flags & IS_SUPPRESSED) == 0) - { - optimize_alloc (pstr, (char *) wstr, str_sz * sizeof (wchar_t)); - pstr = NULL; - ++rval; - } - break; - - case 's': - if ((flags & IS_SUPPRESSED) == 0) - { - if ((flags & IS_ALLOC_USED) != 0) - { - if (npos != 0) - pstr = (char **) get_va_nth (argp, npos); - else - pstr = va_arg (arg, char **); - - if (!pstr) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - - str_sz = 100; - if ((str = *pstr = (char *) malloc (100)) == NULL) - return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); - gcollect = resize_gcollect (gcollect); - gcollect->ptrs[gcollect->count++] = pstr; - } - else - { - if (npos != 0) - str = (char *) get_va_nth (argp, npos); - else - str = va_arg (arg, char *); - if (!str) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - } - - if ((c = in_ch (s, &read_in)) == EOF) - return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); - - do - { - if (isspace (c)) - { - back_ch (c, s, &read_in, 1); - break; - } - - if ((flags & IS_SUPPRESSED) == 0) - { - *str++ = c; - if ((flags & IS_ALLOC_USED) != 0 && str == (*pstr + str_sz)) - { - new_sz = str_sz * 2; - - while ((str = (char *) realloc (*pstr, new_sz)) == NULL - && new_sz > (size_t) (str_sz + 1)) - new_sz = str_sz + 1; - if (!str) - { - if ((flags & USE_POSIX_ALLOC) == 0) - { - (*pstr)[str_sz - 1] = 0; - pstr = NULL; - ++rval; - } - return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); - } - *pstr = str; - str += str_sz; - str_sz = new_sz; - } - } - } - while ((width <= 0 || --width > 0) && (c = in_ch (s, &read_in)) != EOF); - - if ((flags & IS_SUPPRESSED) == 0) - { - *str++ = 0; - optimize_alloc (pstr, str, str_sz); - pstr = NULL; - ++rval; - } - break; - - case 'S': - if ((flags & IS_SUPPRESSED) == 0) - { - if ((flags & IS_ALLOC_USED) != 0) - { - if (npos != 0) - pstr = (char **) get_va_nth (argp, npos); - else - pstr = va_arg (arg, char **); - - if (!pstr) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - - str_sz = 100; - *pstr = (char *) malloc (100 * sizeof (wchar_t)); - if ((wstr = (wchar_t *) *pstr) == NULL) - return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); - gcollect = resize_gcollect (gcollect); - gcollect->ptrs[gcollect->count++] = pstr; - } - else - { - if (npos != 0) - wstr = (wchar_t *) get_va_nth (argp, npos); - else - wstr = va_arg (arg, wchar_t *); - if (!wstr) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - } - - if ((c = in_ch (s, &read_in)) == EOF) - return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); - - memset (&cstate, 0, sizeof (cstate)); - - do - { - if (isspace (c)) - { - back_ch (c, s, &read_in, 1); - break; - } - - buf[0] = c; - - while (1) - { - n = mbrtowc ((flags & IS_SUPPRESSED) == 0 ? wstr : NULL, buf, 1, &cstate); - - if (n == (size_t) -2) - { - if ((c = in_ch (s, &read_in)) == EOF) - { - errno = EILSEQ; - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - - buf[0] = c; - continue; - } - - if (n != 1) - { - errno = EILSEQ; - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - - ++wstr; - break; - } - - if ((flags & IS_SUPPRESSED) == 0 && (flags & IS_ALLOC_USED) != 0 - && wstr == ((wchar_t *) *pstr + str_sz)) - { - new_sz = str_sz * 2; - while ((wstr = (wchar_t *) realloc (*pstr, new_sz * sizeof (wchar_t))) == NULL - && new_sz > (size_t) (str_sz + 1)) - new_sz = str_sz + 1; - if (!wstr) - { - if ((flags & USE_POSIX_ALLOC) == 0) - { - ((wchar_t *) (*pstr))[str_sz - 1] = 0; - pstr = NULL; - ++rval; - } - return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); - } - *pstr = (char *) wstr; - wstr += str_sz; - str_sz = new_sz; - } - } - while ((width <= 0 || --width > 0) && (c = in_ch (s, &read_in)) != EOF); - - if ((flags & IS_SUPPRESSED) == 0) - { - *wstr++ = 0; - optimize_alloc (pstr, (char *) wstr, str_sz * sizeof (wchar_t)); - pstr = NULL; - ++rval; - } - break; - - case 'd': case 'i': - case 'o': case 'p': - case 'u': - case 'x': case 'X': - switch (fc) - { - case 'd': - flags |= IS_SIGNED_NUM; - base = 10; - break; - case 'i': - flags |= IS_SIGNED_NUM; - base = 0; - break; - case 'o': - base = 8; - break; - case 'p': - base = 16; - flags &= ~(IS_S | IS_LL | IS_L); - #ifdef _WIN64 - flags |= IS_LL; - #endif - flags |= IS_L | IS_POINTER; - break; - case 'u': - base = 10; - break; - case 'x': case 'X': - base = 16; - break; - } - - if ((c = in_ch (s, &read_in)) == EOF) - return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); - if (c == '+' || c == '-') - { - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = c; - if (width > 0) - --width; - c = in_ch (s, &read_in); - } - if (width != 0 && c == '0') - { - if (width > 0) - --width; - - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = c; - c = in_ch (s, &read_in); - - if (width != 0 && tolower (c) == 'x') - { - if (!base) - base = 16; - if (base == 16) - { - if (width > 0) - --width; - c = in_ch (s, &read_in); - } - } - else if (!base) - base = 8; - } - - if (!base) - base = 10; - - while (c != EOF && width != 0) - { - if (base == 16) - { - if (!isxdigit (c)) - break; - } - else if (!isdigit (c) || (int) (c - '0') >= base) - { - const char *p = lc_thousands_sep; - int remain; - - if (base != 10 || (flags & USE_GROUP) == 0) - break; - remain = width > 0 ? width : INT_MAX; - while ((unsigned char) *p == c && remain >= 0) - { - /* As our conversion routines aren't supporting thousands - separators, we are filtering them here. */ - - ++p; - if (*p == 0 || !remain || (c = in_ch (s, &read_in)) == EOF) - break; - --remain; - } - - if (*p != 0) - { - if (p > lc_thousands_sep) - { - back_ch (c, s, &read_in, 0); - while (--p > lc_thousands_sep) - back_ch ((unsigned char) *p, s, &read_in, 1); - c = (unsigned char) *p; - } - break; - } - - if (width > 0) - width = remain; - --wbuf_cur_sz; - } - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = c; - if (width > 0) - --width; - - c = in_ch (s, &read_in); - } - - if (!wbuf_cur_sz || (wbuf_cur_sz == 1 && (wbuf[0] == '+' || wbuf[0] == '-'))) - { - if (!wbuf_cur_sz && (flags & IS_POINTER) != 0 - && match_string (s, &read_in, &c, "(nil)")) - { - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = '0'; - } - else - { - back_ch (c, s, &read_in, 0); - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - } - else - back_ch (c, s, &read_in, 0); - - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = 0; - - if ((flags & IS_LL)) - { - if (flags & IS_SIGNED_NUM) - cv_val.ll = strtoll (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/); - else - cv_val.ull = strtoull (wbuf, &tmp_wbuf_ptr, base); - } - else - { - if (flags & IS_SIGNED_NUM) - cv_val.l = strtol (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/); - else - cv_val.ul = strtoul (wbuf, &tmp_wbuf_ptr, base); - } - if (wbuf == tmp_wbuf_ptr) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - - if ((flags & IS_SUPPRESSED) == 0) - { - if ((flags & IS_SIGNED_NUM) != 0) - { - if ((flags & IS_LL) != 0) - *(npos != 0 ? (long long *) get_va_nth (argp, npos) : va_arg (arg, long long *)) = cv_val.ll; - else if ((flags & IS_L) != 0) - *(npos != 0 ? (long *) get_va_nth (argp, npos) : va_arg (arg, long *)) = cv_val.l; - else if ((flags & IS_S) != 0) - *(npos != 0 ? (short *) get_va_nth (argp, npos) : va_arg (arg, short *)) = (short) cv_val.l; - else if ((flags & IS_C) != 0) - *(npos != 0 ? (signed char *) get_va_nth (argp, npos) : va_arg (arg, signed char *)) = (signed char) cv_val.ul; - else - *(npos != 0 ? (int *) get_va_nth (argp, npos) : va_arg (arg, int *)) = (int) cv_val.l; - } - else - { - if ((flags & IS_LL) != 0) - *(npos != 0 ? (unsigned long long *) get_va_nth (argp, npos) : va_arg (arg, unsigned long long *)) = cv_val.ull; - else if ((flags & IS_L) != 0) - *(npos != 0 ? (unsigned long *) get_va_nth (argp, npos) : va_arg (arg, unsigned long *)) = cv_val.ul; - else if ((flags & IS_S) != 0) - *(npos != 0 ? (unsigned short *) get_va_nth (argp, npos) : va_arg (arg, unsigned short *)) - = (unsigned short) cv_val.ul; - else if ((flags & IS_C) != 0) - *(npos != 0 ? (unsigned char *) get_va_nth (argp, npos) : va_arg (arg, unsigned char *)) = (unsigned char) cv_val.ul; - else - *(npos != 0 ? (unsigned int *) get_va_nth (argp, npos) : va_arg (arg, unsigned int *)) = (unsigned int) cv_val.ul; - } - ++rval; - } - break; - - case 'e': case 'E': - case 'f': case 'F': - case 'g': case 'G': - case 'a': case 'A': - if (width > 0) - --width; - if ((c = in_ch (s, &read_in)) == EOF) - return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); - - seen_dot = seen_exp = 0; - is_neg = (c == '-' ? 1 : 0); - - if (c == '-' || c == '+') - { - if (width == 0 || (c = in_ch (s, &read_in)) == EOF) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - if (width > 0) - --width; - } - - if (tolower (c) == 'n') - { - const char *match_txt = "nan"; - - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = c; - - ++match_txt; - do - { - if (width == 0 || (c = in_ch (s, &read_in)) == EOF || tolower (c) != match_txt[0]) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - - if (width > 0) - --width; - - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = c; - ++match_txt; - } - while (*match_txt != 0); - } - else if (tolower (c) == 'i') - { - const char *match_txt = "inf"; - - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = c; - - ++match_txt; - do - { - if (width == 0 || (c = in_ch (s, &read_in)) == EOF || tolower (c) != match_txt[0]) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - if (width > 0) - --width; - - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = c; - ++match_txt; - } - while (*match_txt != 0); - - if (width != 0 && (c = in_ch (s, &read_in)) != EOF && tolower (c) == 'i') - { - match_txt = "inity"; - - if (width > 0) - --width; - - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = c; - ++match_txt; - - do - { - if (width == 0 || (c = in_ch (s, &read_in)) == EOF || tolower (c) != match_txt[0]) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - if (width > 0) - --width; - - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = c; - ++match_txt; - } - while (*match_txt != 0); - } - else if (width != 0 && c != EOF) - back_ch (c, s, &read_in, 0); - } - else - { - not_in = 'e'; - if (width != 0 && c == '0') - { - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = c; - - c = in_ch (s, &read_in); - if (width > 0) - --width; - if (width != 0 && tolower (c) == 'x') - { - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = c; - - flags |= IS_HEX_FLOAT; - not_in = 'p'; - - flags &= ~USE_GROUP; - c = in_ch (s, &read_in); - if (width > 0) - --width; - } - } - - while (1) - { - if (isdigit (c) || (!seen_exp && (flags & IS_HEX_FLOAT) != 0 && isxdigit (c)) - || (seen_exp && wbuf[wbuf_cur_sz - 1] == not_in && (c == '-' || c == '+'))) - { - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = c; - } - else if (wbuf_cur_sz > 0 && !seen_exp && (char) tolower (c) == not_in) - { - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = not_in; - seen_exp = seen_dot = 1; - } - else - { - const char *p = lc_decimal_point; - int remain = width > 0 ? width : INT_MAX; - - if (! seen_dot) - { - while ((unsigned char) *p == c && remain >= 0) - { - ++p; - if (*p == 0 || !remain || (c = in_ch (s, &read_in)) == EOF) - break; - --remain; - } - } - - if (*p == 0) - { - for (p = lc_decimal_point; *p != 0; ++p) - { - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = (unsigned char) *p; - } - if (width > 0) - width = remain; - seen_dot = 1; - } - else - { - const char *pp = lc_thousands_sep; - - if (!seen_dot && (flags & USE_GROUP) != 0) - { - while ((pp - lc_thousands_sep) < (p - lc_decimal_point) - && *pp == lc_decimal_point[(pp - lc_thousands_sep)]) - ++pp; - if ((pp - lc_thousands_sep) == (p - lc_decimal_point)) - { - while ((unsigned char) *pp == c && remain >= 0) - { - ++pp; - if (*pp == 0 || !remain || (c = in_ch (s, &read_in)) == EOF) - break; - --remain; - } - } - } - - if (pp != NULL && *pp == 0) - { - /* As our conversion routines aren't supporting thousands - separators, we are filtering them here. */ - if (width > 0) - width = remain; - } - else - { - back_ch (c, s, &read_in, 0); - break; - } - } - } - - if (width == 0 || (c = in_ch (s, &read_in)) == EOF) - break; - - if (width > 0) - --width; - } - - if (!wbuf_cur_sz || ((flags & IS_HEX_FLOAT) != 0 && wbuf_cur_sz == 2)) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - - wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); - wbuf[wbuf_cur_sz++] = 0; - - if ((flags & IS_LL) != 0) - { - long double ld; - ld = __evil_strtold (wbuf, &tmp_wbuf_ptr/*, flags & USE_GROUP*/); - if ((flags & IS_SUPPRESSED) == 0 && tmp_wbuf_ptr != wbuf) - *(npos != 0 ? (long double *) get_va_nth (argp, npos) : va_arg (arg, long double *)) = is_neg ? -ld : ld; - } - else if ((flags & IS_L) != 0) - { - double d; - d = (double) __evil_strtold (wbuf, &tmp_wbuf_ptr/*, flags & USE_GROUP*/); - if ((flags & IS_SUPPRESSED) == 0 && tmp_wbuf_ptr != wbuf) - *(npos != 0 ? (double *) get_va_nth (argp, npos) : va_arg (arg, double *)) = is_neg ? -d : d; - } - else - { - float d = __evil_strtof (wbuf, &tmp_wbuf_ptr/*, flags & USE_GROUP*/); - if ((flags & IS_SUPPRESSED) == 0 && tmp_wbuf_ptr != wbuf) - *(npos != 0 ? (float *) get_va_nth (argp, npos) : va_arg (arg, float *)) = is_neg ? -d : d; - } - - if (wbuf == tmp_wbuf_ptr) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - - if ((flags & IS_SUPPRESSED) == 0) - ++rval; - break; - - case '[': - if ((flags & IS_L) != 0) - { - if ((flags & IS_SUPPRESSED) == 0) - { - if ((flags & IS_ALLOC_USED) != 0) - { - if (npos != 0) - pstr = (char **) get_va_nth (argp, npos); - else - pstr = va_arg (arg, char **); - - if (!pstr) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - - str_sz = 100; - *pstr = (char *) malloc (100 * sizeof (wchar_t)); - - if ((wstr = (wchar_t *) *pstr) == NULL) - return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); - gcollect = resize_gcollect (gcollect); - gcollect->ptrs[gcollect->count++] = pstr; - } - else - { - if (npos != 0) - wstr = (wchar_t *) get_va_nth (argp, npos); - else - wstr = va_arg (arg, wchar_t *); - if (!wstr) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - } - } - else if ((flags & IS_SUPPRESSED) == 0) - { - if ((flags & IS_ALLOC_USED) != 0) - { - if (npos != 0) - pstr = (char **) get_va_nth (argp, npos); - else - pstr = va_arg (arg, char **); - - if (!pstr) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - - str_sz = 100; - if ((str = *pstr = (char *) malloc (100)) == NULL) - return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); - - gcollect = resize_gcollect (gcollect); - gcollect->ptrs[gcollect->count++] = pstr; - } - else - { - if (npos != 0) - str = (char *) get_va_nth (argp, npos); - else - str = va_arg (arg, char *); - if (!str) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - } - - not_in = (*f == '^' ? 1 : 0); - if (*f == '^') - f++; - - if (width < 0) - width = INT_MAX; - - if (wbuf_max_sz < 256) - { - wbuf_max_sz = 256; - if (wbuf) - free (wbuf); - wbuf = (char *) malloc (wbuf_max_sz); - } - memset (wbuf, 0, 256); - - fc = *f; - if (fc == ']' || fc == '-') - { - wbuf[fc] = 1; - ++f; - } - - while ((fc = *f++) != 0 && fc != ']') - { - if (fc == '-' && *f != 0 && *f != ']' && (unsigned char) f[-2] <= (unsigned char) *f) - { - for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc) - wbuf[fc] = 1; - } - else - wbuf[fc] = 1; - } - - if (!fc) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - - if ((flags & IS_L) != 0) - { - read_in_sv = read_in; - cnt = 0; - - if ((c = in_ch (s, &read_in)) == EOF) - return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); - - memset (&cstate, 0, sizeof (cstate)); - - do - { - if (wbuf[c] == not_in) - { - back_ch (c, s, &read_in, 1); - break; - } - - if ((flags & IS_SUPPRESSED) == 0) - { - buf[0] = c; - n = mbrtowc (wstr, buf, 1, &cstate); - - if (n == (size_t) -2) - { - ++cnt; - continue; - } - cnt = 0; - - ++wstr; - if ((flags & IS_ALLOC_USED) != 0 && wstr == ((wchar_t *) *pstr + str_sz)) - { - new_sz = str_sz * 2; - while ((wstr = (wchar_t *) realloc (*pstr, new_sz * sizeof (wchar_t))) == NULL - && new_sz > (size_t) (str_sz + 1)) - new_sz = str_sz + 1; - if (!wstr) - { - if ((flags & USE_POSIX_ALLOC) == 0) - { - ((wchar_t *) (*pstr))[str_sz - 1] = 0; - pstr = NULL; - ++rval; - } - else - rval = EOF; - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - *pstr = (char *) wstr; - wstr += str_sz; - str_sz = new_sz; - } - } - - if (--width <= 0) - break; - } - while ((c = in_ch (s, &read_in)) != EOF); - - if (cnt != 0) - { - errno = EILSEQ; - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - - if (read_in_sv == read_in) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - - - if ((flags & IS_SUPPRESSED) == 0) - { - *wstr++ = 0; - optimize_alloc (pstr, (char *) wstr, str_sz * sizeof (wchar_t)); - pstr = NULL; - ++rval; - } - } - else - { - read_in_sv = read_in; - - if ((c = in_ch (s, &read_in)) == EOF) - return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); - - do - { - if (wbuf[c] == not_in) - { - back_ch (c, s, &read_in, 1); - break; - } - - if ((flags & IS_SUPPRESSED) == 0) - { - *str++ = c; - if ((flags & IS_ALLOC_USED) != 0 && str == (*pstr + str_sz)) - { - new_sz = str_sz * 2; - - while ((str = (char *) realloc (*pstr, new_sz)) == NULL - && new_sz > (size_t) (str_sz + 1)) - new_sz = str_sz + 1; - if (!str) - { - if ((flags & USE_POSIX_ALLOC) == 0) - { - (*pstr)[str_sz - 1] = 0; - pstr = NULL; - ++rval; - } - else - rval = EOF; - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - *pstr = str; - str += str_sz; - str_sz = new_sz; - } - } - } - while (--width > 0 && (c = in_ch (s, &read_in)) != EOF); - - if (read_in_sv == read_in) - return cleanup_return (rval, &gcollect, pstr, &wbuf); - - if ((flags & IS_SUPPRESSED) == 0) - { - *str++ = 0; - optimize_alloc (pstr, str, str_sz); - pstr = NULL; - ++rval; - } - } - break; - - default: - return cleanup_return (rval, &gcollect, pstr, &wbuf); - } - } - - if (ignore_ws) - { - while (isspace ((c = in_ch (s, &read_in)))); - back_ch (c, s, &read_in, 0); - } - - return cleanup_return (rval, &gcollect, pstr, &wbuf); -} - -#endif - -/*============================================================================* - * API * - *============================================================================*/ - -/**** printf family ****/ - -int __cdecl _evil_fprintf(FILE *stream, const APICHAR *fmt, ...) -{ - register int retval; - va_list argv; - - va_start( argv, fmt ); - retval = _evil_pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stream, 0, fmt, argv ); - va_end( argv ); - - return retval; -} - -int __cdecl _evil_printf(const APICHAR *fmt, ...) -{ - register int retval; - va_list argv; - - va_start( argv, fmt ); - retval = _evil_pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stdout, 0, fmt, argv ); - va_end( argv ); - - return retval; -} - -int __cdecl _evil_sprintf(APICHAR *buf, const APICHAR *fmt, ...) -{ - register int retval; - va_list argv; - - va_start( argv, fmt ); - buf[retval = _evil_pformat( PFORMAT_NOLIMIT, buf, 0, fmt, argv )] = '\0'; - va_end( argv ); - - return retval; -} - -int __cdecl _evil_snprintf(APICHAR *buf, size_t length, const APICHAR *fmt, ...) -{ - register int retval; - va_list argv; - - va_start( argv, fmt ); - retval = _evil_vsnprintf( buf, length, fmt, argv ); - va_end( argv ); - - return retval; -} - -int __cdecl _evil_vfprintf(FILE *stream, const APICHAR *fmt, va_list argv) -{ - return _evil_pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stream, 0, fmt, argv ); -} - -int __cdecl _evil_vprintf(const APICHAR *fmt, va_list argv) -{ - return _evil_pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stdout, 0, fmt, argv ); -} - -int __cdecl _evil_vsprintf(APICHAR *buf, const APICHAR *fmt, va_list argv) -{ - register int retval; - buf[retval = _evil_pformat( PFORMAT_NOLIMIT, buf, 0, fmt, argv )] = '\0'; - return retval; -} - -int __cdecl _evil_vsnprintf(APICHAR *buf, size_t length, const APICHAR *fmt, va_list argv ) -{ - register int retval; - - if( length == (size_t)(0) ) - /* - * No buffer; simply compute and return the size required, - * without actually emitting any data. - */ - return _evil_pformat( 0, buf, 0, fmt, argv); - - /* If we get to here, then we have a buffer... - * Emit data up to the limit of buffer length less one, - * then add the requisite NUL terminator. - */ - retval = _evil_pformat( 0, buf, --length, fmt, argv ); - buf[retval < (int) length ? retval : (int)length] = '\0'; - - return retval; -} - - -/**** scanf family ****/ - -#ifndef __BUILD_WIDEAPI - -int __cdecl _evil_fscanf (FILE *stream, const APICHAR *format, ...) -{ - va_list argp; - int r; - - va_start (argp, format); - r = _evil_vfscanf (stream, format, argp); - va_end (argp); - - return r; -} - -int __cdecl _evil_scanf (const APICHAR *format, ...) -{ - va_list argp; - int r; - - va_start (argp, format); - r = _evil_vfscanf (stdin, format, argp); - va_end (argp); - - return r; -} - -int __cdecl _evil_sscanf (const APICHAR *buf, const APICHAR *format, ...) -{ - va_list argp; - int r; - - va_start (argp, format); - r = _evil_vsscanf (buf, format, argp); - va_end (argp); - - return r; -} - -int __cdecl _evil_vfscanf (FILE *s, const APICHAR *format, va_list argp) -{ - _IFP ifp; - - memset (&ifp, 0, sizeof (_IFP)); - ifp.fp = s; - - return _evil_sformat (&ifp, format, argp); -} - -int __cdecl _evil_vscanf (const APICHAR *format, va_list argp) -{ - return _evil_vfscanf (stdin, format, argp); -} - -int __cdecl _evil_vsscanf (const APICHAR *s, const APICHAR *format, va_list argp) -{ - _IFP ifp; - - memset (&ifp, 0, sizeof (_IFP)); - ifp.str = s; - ifp.is_string = 1; - - return _evil_sformat (&ifp, format, argp); -} - -#endif - -/**** asprintf family ****/ - -#ifndef __BUILD_WIDEAPI - -int _evil_asprintf(char ** __restrict__ ret, const char * __restrict__ format, ...) -{ - va_list ap; - int len; - va_start(ap,format); - /* Get Length */ - len = _evil_vsnprintf(NULL,0,format,ap); - if (len < 0) goto _end; - /* +1 for \0 terminator. */ - *ret = malloc(len + 1); - /* Check malloc fail*/ - if (!*ret) { - len = -1; - goto _end; - } - /* Write String */ - _evil_vsnprintf(*ret,len+1,format,ap); - /* Terminate explicitly */ - (*ret)[len] = '\0'; - _end: - va_end(ap); - return len; -} - -int __cdecl _evil_vasprintf(char ** __restrict__ ret, const char * __restrict__ format, va_list ap) -{ - int len; - /* Get Length */ - len = _evil_vsnprintf(NULL,0,format,ap); - if (len < 0) return -1; - /* +1 for \0 terminator. */ - *ret = malloc(len + 1); - /* Check malloc fail*/ - if (!*ret) return -1; - /* Write String */ - _evil_vsnprintf(*ret,len+1,format,ap); - /* Terminate explicitly */ - (*ret)[len] = '\0'; - return len; -} - -#endif diff --git a/src/lib/evil/evil_printw.c b/src/lib/evil/evil_printw.c deleted file mode 100644 index 8e8fa18..0000000 --- a/src/lib/evil/evil_printw.c +++ /dev/null @@ -1,4 +0,0 @@ - -#define __BUILD_WIDEAPI 1 - -#include "evil_printa.c" diff --git a/src/lib/evil/evil_uuid.c b/src/lib/evil/evil_uuid.c deleted file mode 100644 index 9620f0c..0000000 --- a/src/lib/evil/evil_uuid.c +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Defines the windows UUID IID_IPersistFile used for links in - * evil. This is here since uuid.lib is a static only library and - * libtool does not allow you to link a DLL against a static library. - */ - -# define INITGUID -# include <basetyps.h> -DEFINE_OLEGUID(IID_IPersistFile, 0x0000010BL, 0, 0); --