From 7d6969d95509a94347d6f96167ac5420abafa291 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Thu, 23 Nov 2023 15:48:52 +0100 Subject: [PATCH] Remove Trio Trio is a rather old cross-platform printf library which was bundled with libxml2. It was needed for ancient pre-C99 systems without snprintf and should be safe to remove these days. --- CMakeLists.txt | 7 +- Copyright | 6 +- Makefile.am | 6 +- configure.ac | 15 - doc/apibuild.py | 4 - include/libxml/xmlversion.h.in | 25 - libxml.h | 5 - python/libxml.c | 5 - trio.c | 6892 -------------------------------- trio.h | 230 -- triodef.h | 228 -- trionan.c | 914 ----- trionan.h | 84 - triop.h | 150 - triostr.c | 2112 ---------- triostr.h | 144 - win32/configure.js | 10 +- 17 files changed, 6 insertions(+), 10831 deletions(-) delete mode 100644 trio.c delete mode 100644 trio.h delete mode 100644 triodef.h delete mode 100644 trionan.c delete mode 100644 trionan.h delete mode 100644 triop.h delete mode 100644 triostr.c delete mode 100644 triostr.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6553255c..c7c9eeb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,6 @@ option(LIBXML2_WITH_TESTS "Build tests" ON) option(LIBXML2_WITH_THREADS "Add multithread support" ON) option(LIBXML2_WITH_THREAD_ALLOC "Add per-thread memory" OFF) option(LIBXML2_WITH_TREE "Add the DOM like tree manipulation APIs" ON) -set(LIBXML2_WITH_TRIO OFF) set(LIBXML2_WITH_UNICODE ON) option(LIBXML2_WITH_VALID "Add the DTD validation support" ON) option(LIBXML2_WITH_WRITER "Add the xmlWriter saving interface" ON) @@ -73,7 +72,7 @@ if(LIBXML2_WITH_PYTHON) CACHE PATH "Python bindings install directory") endif() -foreach(VARIABLE IN ITEMS WITH_AUTOMATA WITH_C14N WITH_CATALOG WITH_DEBUG WITH_EXPR WITH_FTP WITH_HTML WITH_HTTP WITH_ICONV WITH_ICU WITH_ISO8859X WITH_LEGACY WITH_LZMA WITH_MEM_DEBUG WITH_MODULES WITH_OUTPUT WITH_PATTERN WITH_PUSH WITH_READER WITH_REGEXPS WITH_SAX1 WITH_SCHEMAS WITH_SCHEMATRON WITH_THREADS WITH_THREAD_ALLOC WITH_TREE WITH_TRIO WITH_UNICODE WITH_VALID WITH_WRITER WITH_XINCLUDE WITH_XPATH WITH_XPTR WITH_XPTR_LOCS WITH_ZLIB) +foreach(VARIABLE IN ITEMS WITH_AUTOMATA WITH_C14N WITH_CATALOG WITH_DEBUG WITH_EXPR WITH_FTP WITH_HTML WITH_HTTP WITH_ICONV WITH_ICU WITH_ISO8859X WITH_LEGACY WITH_LZMA WITH_MEM_DEBUG WITH_MODULES WITH_OUTPUT WITH_PATTERN WITH_PUSH WITH_READER WITH_REGEXPS WITH_SAX1 WITH_SCHEMAS WITH_SCHEMATRON WITH_THREADS WITH_THREAD_ALLOC WITH_TREE WITH_UNICODE WITH_VALID WITH_WRITER WITH_XINCLUDE WITH_XPATH WITH_XPTR WITH_XPTR_LOCS WITH_ZLIB) if(LIBXML2_${VARIABLE}) set(${VARIABLE} 1) else() @@ -330,10 +329,6 @@ if(WIN32) ) endif() -if(LIBXML2_WITH_TRIO) - list(APPEND LIBXML2_SRCS trio.c triostr.c) -endif() - add_library(LibXml2 ${LIBXML2_HDRS} ${LIBXML2_SRCS}) add_library(LibXml2::LibXml2 ALIAS LibXml2) diff --git a/Copyright b/Copyright index c058f022..f76a86df 100644 --- a/Copyright +++ b/Copyright @@ -1,6 +1,6 @@ -Except where otherwise noted in the source code (e.g. the files dict.c, -list.c and the trio files, which are covered by a similar licence but -with different Copyright notices) all the files are: +Except where otherwise noted in the source code (e.g. the files dict.c and +list.c, which are covered by a similar licence but with different Copyright +notices) all the files are: Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved. diff --git a/Makefile.am b/Makefile.am index 0a49d375..826ee8f0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -97,9 +97,6 @@ endif if WITH_SCHEMATRON_SOURCES libxml2_la_SOURCES += schematron.c endif -if WITH_TRIO_SOURCES -libxml2_la_SOURCES += triostr.c trio.c -endif if WITH_WRITER_SOURCES libxml2_la_SOURCES += xmlwriter.c endif @@ -389,8 +386,7 @@ EXTRA_DIST = Copyright check-xml-test-suite.py gentest.py \ check-xsddata-test-suite.py check-xinclude-test-suite.py \ example/Makefile.am example/gjobread.c example/gjobs.xml \ libxml2-config.cmake.in autogen.sh \ - trionan.c trionan.h triostr.c triostr.h trio.c trio.h \ - triop.h triodef.h libxml.h \ + libxml.h \ genUnicode.py \ dbgen.pl dbgenattr.pl \ libxml2.syms timsort.h \ diff --git a/configure.ac b/configure.ac index 0dd50720..63078475 100644 --- a/configure.ac +++ b/configure.ac @@ -530,9 +530,6 @@ case ${host} in *-*-solaris*) XML_LIBDIR="${XML_LIBDIR} -R${libdir}" ;; - hppa*-hp-mpeix) - NEED_TRIO=1 - ;; *-*-cygwin* | *-*-mingw* | *-*-msys* ) # If the host is Windows, and shared libraries are disabled, we # need to add -DLIBXML_STATIC to AM_CFLAGS in order for linking to @@ -839,18 +836,6 @@ AC_SUBST(MODULE_PLATFORM_LIBS) AC_SUBST(MODULE_EXTENSION) AM_CONDITIONAL(WITH_MODULES_SOURCES, test "$WITH_MODULES" = "1") -dnl -dnl Check for trio string functions -dnl -if test "${NEED_TRIO}" = "1" ; then - echo Adding trio library for string functions - WITH_TRIO=1 -else - WITH_TRIO=0 -fi -AM_CONDITIONAL(WITH_TRIO_SOURCES, test "${NEED_TRIO}" = "1") -AC_SUBST(WITH_TRIO) - dnl dnl Thread-related stuff dnl diff --git a/doc/apibuild.py b/doc/apibuild.py index f7e66df0..2e388260 100755 --- a/doc/apibuild.py +++ b/doc/apibuild.py @@ -19,10 +19,6 @@ debugsym=None # C parser analysis code # ignored_files = { - "trio": "too many non standard macros", - "trio.c": "too many non standard macros", - "trionan.c": "too many non standard macros", - "triostr.c": "too many non standard macros", "config.h": "generated portability layer", "libxml.h": "internal only", "testOOM.c": "out of memory tester", diff --git a/include/libxml/xmlversion.h.in b/include/libxml/xmlversion.h.in index bdc27087..abcf9c54 100644 --- a/include/libxml/xmlversion.h.in +++ b/include/libxml/xmlversion.h.in @@ -60,31 +60,6 @@ XMLPUBFUN void xmlCheckVersion(int version); */ #define LIBXML_TEST_VERSION xmlCheckVersion(@LIBXML_VERSION_NUMBER@); -#ifndef VMS -#if @WITH_TRIO@ -/** - * WITH_TRIO: - * - * defined if the trio support need to be configured in - */ -#define WITH_TRIO -#else -/** - * WITHOUT_TRIO: - * - * defined if the trio support should not be configured in - */ -#define WITHOUT_TRIO -#endif -#else /* VMS */ -/** - * WITH_TRIO: - * - * defined if the trio support need to be configured in - */ -#define WITH_TRIO 1 -#endif /* VMS */ - /** * LIBXML_THREAD_ENABLED: * diff --git a/libxml.h b/libxml.h index 8d6b43a3..00404d2f 100644 --- a/libxml.h +++ b/libxml.h @@ -38,11 +38,6 @@ #define SYSCONFDIR "/etc" #endif -#ifdef WITH_TRIO - #define TRIO_REPLACE_STDIO - #include "trio.h" -#endif - #if !defined(_WIN32) && \ !defined(__CYGWIN__) && \ (defined(__clang__) || \ diff --git a/python/libxml.c b/python/libxml.c index bf048006..08e18940 100644 --- a/python/libxml.c +++ b/python/libxml.c @@ -29,11 +29,6 @@ #include "libxml_wrap.h" #include "libxml2-py.h" -#if defined(WITH_TRIO) -#include "trio.h" -#define vsnprintf trio_vsnprintf -#endif - #if PY_MAJOR_VERSION >= 3 PyObject *PyInit_libxml2mod(void); diff --git a/trio.c b/trio.c deleted file mode 100644 index 31b3b371..00000000 --- a/trio.c +++ /dev/null @@ -1,6892 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************* - * - * A note to trio contributors: - * - * Avoid heap allocation at all costs to ensure that the trio functions - * are async-safe. The exceptions are the printf/fprintf functions, which - * uses fputc, and the asprintf functions and the modifier, which - * by design are required to allocate form the heap. - * - ************************************************************************/ - -/* - * TODO: - * - Scan is probably too permissive about its modifiers. - * - C escapes in %#[] ? - * - Multibyte characters (done for format parsing, except scan groups) - * - Complex numbers? (C99 _Complex) - * - Boolean values? (C99 _Bool) - * - C99 NaN(n-char-sequence) missing. The n-char-sequence can be used - * to print the mantissa, e.g. NaN(0xc000000000000000) - * - Should we support the GNU %a alloc modifier? GNU has an ugly hack - * for %a, because C99 used %a for other purposes. If specified as - * %as or %a[ it is interpreted as the alloc modifier, otherwise as - * the C99 hex-float. This means that you cannot scan %as as a hex-float - * immediately followed by an 's'. - * - Scanning of collating symbols. - */ - -/************************************************************************* - * Trio include files - */ -#include "triodef.h" -#include "trio.h" -#include "triop.h" -#include "trionan.h" -#if !defined(TRIO_MINIMAL) -# include "triostr.h" -#endif - -/************************************************************************** - * - * Definitions - * - *************************************************************************/ - -#include -#include -#include - -#if (defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) \ - || defined(USE_MULTIBYTE) || TRIO_WIDECHAR) \ - && !defined(_WIN32_WCE) -# define TRIO_COMPILER_SUPPORTS_MULTIBYTE -# if !defined(MB_LEN_MAX) -# define MB_LEN_MAX 6 -# endif -#endif - -#if (defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1100)) || defined(TRIO_COMPILER_BCB) -# define TRIO_COMPILER_SUPPORTS_MSVC_INT -#endif - -#if defined(_WIN32_WCE) -#include -#endif - -/************************************************************************* - * Generic definitions - */ - -#if !(defined(DEBUG) || defined(NDEBUG)) -# define NDEBUG -#endif - -#include -#include -#if !defined(TRIO_COMPILER_SUPPORTS_C99) -# define isblank(x) (((x)==32) || ((x)==9)) -#endif -#if defined(TRIO_COMPILER_ANCIENT) -# include -#else -# include -#endif -#include -#include - -#ifndef NULL -# define NULL 0 -#endif -#define NIL ((char)0) -#ifndef FALSE -# define FALSE (1 == 0) -# define TRUE (! FALSE) -#endif -#define BOOLEAN_T int - -/* mincore() can be used for debugging purposes */ -#define VALID(x) (NULL != (x)) - -#if TRIO_ERRORS - /* - * Encode the error code and the position. This is decoded - * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION. - */ -# define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8))) -#else -# define TRIO_ERROR_RETURN(x,y) (-1) -#endif - -#ifndef VA_LIST_IS_ARRAY -#define TRIO_VA_LIST_PTR va_list * -#define TRIO_VA_LIST_ADDR(l) (&(l)) -#define TRIO_VA_LIST_DEREF(l) (*(l)) -#else -#define TRIO_VA_LIST_PTR va_list -#define TRIO_VA_LIST_ADDR(l) (l) -#define TRIO_VA_LIST_DEREF(l) (l) -#endif - -typedef unsigned long trio_flags_t; - - -/************************************************************************* - * Platform specific definitions - */ -#if defined(TRIO_PLATFORM_UNIX) || defined(TRIO_PLATFORM_OS400) -# include -# include -# include -# define USE_LOCALE -#endif /* TRIO_PLATFORM_UNIX */ -#if defined(TRIO_PLATFORM_VMS) -# include -#endif -#if defined(TRIO_PLATFORM_WIN32) -# if defined(_WIN32_WCE) -# include -# else -# include -# define read _read -# define write _write -# endif -#endif /* TRIO_PLATFORM_WIN32 */ - -#if TRIO_WIDECHAR -# if defined(TRIO_COMPILER_SUPPORTS_ISO94) -# include -# include -typedef wchar_t trio_wchar_t; -typedef wint_t trio_wint_t; -# else -typedef char trio_wchar_t; -typedef int trio_wint_t; -# define WCONST(x) L ## x -# define WEOF EOF -# define iswalnum(x) isalnum(x) -# define iswalpha(x) isalpha(x) -# define iswblank(x) isblank(x) -# define iswcntrl(x) iscntrl(x) -# define iswdigit(x) isdigit(x) -# define iswgraph(x) isgraph(x) -# define iswlower(x) islower(x) -# define iswprint(x) isprint(x) -# define iswpunct(x) ispunct(x) -# define iswspace(x) isspace(x) -# define iswupper(x) isupper(x) -# define iswxdigit(x) isxdigit(x) -# endif -#endif - - -/************************************************************************* - * Compiler dependent definitions - */ - -/* Support for long long */ -#ifndef __cplusplus -# if !defined(USE_LONGLONG) -# if defined(TRIO_COMPILER_GCC) && !defined(__STRICT_ANSI__) -# define USE_LONGLONG -# elif defined(TRIO_COMPILER_SUNPRO) -# define USE_LONGLONG -# elif defined(_LONG_LONG) || defined(_LONGLONG) -# define USE_LONGLONG -# endif -# endif -#endif - -/* The extra long numbers */ -#if defined(USE_LONGLONG) -typedef signed long long int trio_longlong_t; -typedef unsigned long long int trio_ulonglong_t; -#elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT) -typedef signed __int64 trio_longlong_t; -typedef unsigned __int64 trio_ulonglong_t; -#else -typedef TRIO_SIGNED long int trio_longlong_t; -typedef unsigned long int trio_ulonglong_t; -#endif - -/* Maximal and fixed integer types */ -#if defined(TRIO_COMPILER_SUPPORTS_C99) && !defined( __VMS ) -# include -typedef intmax_t trio_intmax_t; -typedef uintmax_t trio_uintmax_t; -typedef int8_t trio_int8_t; -typedef int16_t trio_int16_t; -typedef int32_t trio_int32_t; -typedef int64_t trio_int64_t; -#elif defined(TRIO_COMPILER_SUPPORTS_UNIX98) || defined( __VMS ) -# include -#ifdef __VMS -typedef long long int intmax_t; -typedef unsigned long long int uintmax_t; -#endif -typedef intmax_t trio_intmax_t; -typedef uintmax_t trio_uintmax_t; -typedef int8_t trio_int8_t; -typedef int16_t trio_int16_t; -typedef int32_t trio_int32_t; -typedef int64_t trio_int64_t; -#elif defined(TRIO_COMPILER_SUPPORTS_MSVC_INT) -typedef trio_longlong_t trio_intmax_t; -typedef trio_ulonglong_t trio_uintmax_t; -typedef __int8 trio_int8_t; -typedef __int16 trio_int16_t; -typedef __int32 trio_int32_t; -typedef __int64 trio_int64_t; -#else -typedef trio_longlong_t trio_intmax_t; -typedef trio_ulonglong_t trio_uintmax_t; -# if defined(TRIO_INT8_T) -typedef TRIO_INT8_T trio_int8_t; -# else -typedef TRIO_SIGNED char trio_int8_t; -# endif -# if defined(TRIO_INT16_T) -typedef TRIO_INT16_T trio_int16_t; -# else -typedef TRIO_SIGNED short trio_int16_t; -# endif -# if defined(TRIO_INT32_T) -typedef TRIO_INT32_T trio_int32_t; -# else -typedef TRIO_SIGNED int trio_int32_t; -# endif -# if defined(TRIO_INT64_T) -typedef TRIO_INT64_T trio_int64_t; -# else -typedef trio_longlong_t trio_int64_t; -# endif -#endif - -#if (!(defined(TRIO_COMPILER_SUPPORTS_C99) \ - || defined(TRIO_COMPILER_SUPPORTS_UNIX01))) \ - && !defined(_WIN32_WCE) -# define floorl(x) floor((double)(x)) -# define fmodl(x,y) fmod((double)(x),(double)(y)) -# define powl(x,y) pow((double)(x),(double)(y)) -#endif - -#define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x)) - -/************************************************************************* - * Internal Definitions - */ - -#ifndef DECIMAL_DIG -# define DECIMAL_DIG DBL_DIG -#endif - -/* Long double sizes */ -#ifdef LDBL_DIG -# define MAX_MANTISSA_DIGITS LDBL_DIG -# define MAX_EXPONENT_DIGITS 4 -# define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP -#else -# define MAX_MANTISSA_DIGITS DECIMAL_DIG -# define MAX_EXPONENT_DIGITS 3 -# define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP -#endif - -#if defined(TRIO_COMPILER_ANCIENT) || !defined(LDBL_DIG) -# undef LDBL_DIG -# undef LDBL_MANT_DIG -# undef LDBL_EPSILON -# define LDBL_DIG DBL_DIG -# define LDBL_MANT_DIG DBL_MANT_DIG -# define LDBL_EPSILON DBL_EPSILON -#endif - -/* The maximal number of digits is for base 2 */ -#define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT) -/* The width of a pointer. The number of bits in a hex digit is 4 */ -#define POINTER_WIDTH ((sizeof("0x") - 1) + sizeof(trio_pointer_t) * CHAR_BIT / 4) - -/* Infinite and Not-A-Number for floating-point */ -#define INFINITE_LOWER "inf" -#define INFINITE_UPPER "INF" -#define LONG_INFINITE_LOWER "infinite" -#define LONG_INFINITE_UPPER "INFINITE" -#define NAN_LOWER "nan" -#define NAN_UPPER "NAN" - -#if !defined(HAVE_ISASCII) && !defined(isascii) -#ifndef __VMS -# define isascii(x) ((unsigned int)(x) < 128) -#endif -#endif - -/* Various constants */ -enum { - TYPE_PRINT = 1, - TYPE_SCAN = 2, - - /* Flags. FLAGS_LAST must be less than ULONG_MAX */ - FLAGS_NEW = 0, - FLAGS_STICKY = 1, - FLAGS_SPACE = 2 * FLAGS_STICKY, - FLAGS_SHOWSIGN = 2 * FLAGS_SPACE, - FLAGS_LEFTADJUST = 2 * FLAGS_SHOWSIGN, - FLAGS_ALTERNATIVE = 2 * FLAGS_LEFTADJUST, - FLAGS_SHORT = 2 * FLAGS_ALTERNATIVE, - FLAGS_SHORTSHORT = 2 * FLAGS_SHORT, - FLAGS_LONG = 2 * FLAGS_SHORTSHORT, - FLAGS_QUAD = 2 * FLAGS_LONG, - FLAGS_LONGDOUBLE = 2 * FLAGS_QUAD, - FLAGS_SIZE_T = 2 * FLAGS_LONGDOUBLE, - FLAGS_PTRDIFF_T = 2 * FLAGS_SIZE_T, - FLAGS_INTMAX_T = 2 * FLAGS_PTRDIFF_T, - FLAGS_NILPADDING = 2 * FLAGS_INTMAX_T, - FLAGS_UNSIGNED = 2 * FLAGS_NILPADDING, - FLAGS_UPPER = 2 * FLAGS_UNSIGNED, - FLAGS_WIDTH = 2 * FLAGS_UPPER, - FLAGS_WIDTH_PARAMETER = 2 * FLAGS_WIDTH, - FLAGS_PRECISION = 2 * FLAGS_WIDTH_PARAMETER, - FLAGS_PRECISION_PARAMETER = 2 * FLAGS_PRECISION, - FLAGS_BASE = 2 * FLAGS_PRECISION_PARAMETER, - FLAGS_BASE_PARAMETER = 2 * FLAGS_BASE, - FLAGS_FLOAT_E = 2 * FLAGS_BASE_PARAMETER, - FLAGS_FLOAT_G = 2 * FLAGS_FLOAT_E, - FLAGS_QUOTE = 2 * FLAGS_FLOAT_G, - FLAGS_WIDECHAR = 2 * FLAGS_QUOTE, - FLAGS_ALLOC = 2 * FLAGS_WIDECHAR, - FLAGS_IGNORE = 2 * FLAGS_ALLOC, - FLAGS_IGNORE_PARAMETER = 2 * FLAGS_IGNORE, - FLAGS_VARSIZE_PARAMETER = 2 * FLAGS_IGNORE_PARAMETER, - FLAGS_FIXED_SIZE = 2 * FLAGS_VARSIZE_PARAMETER, - FLAGS_LAST = FLAGS_FIXED_SIZE, - /* Reused flags */ - FLAGS_EXCLUDE = FLAGS_SHORT, - FLAGS_USER_DEFINED = FLAGS_IGNORE, - FLAGS_ROUNDING = FLAGS_INTMAX_T, - /* Compounded flags */ - FLAGS_ALL_VARSIZES = FLAGS_LONG | FLAGS_QUAD | FLAGS_INTMAX_T | FLAGS_PTRDIFF_T | FLAGS_SIZE_T, - FLAGS_ALL_SIZES = FLAGS_ALL_VARSIZES | FLAGS_SHORTSHORT | FLAGS_SHORT, - - NO_POSITION = -1, - NO_WIDTH = 0, - NO_PRECISION = -1, - NO_SIZE = -1, - - /* Do not change these */ - NO_BASE = -1, - MIN_BASE = 2, - MAX_BASE = 36, - BASE_BINARY = 2, - BASE_OCTAL = 8, - BASE_DECIMAL = 10, - BASE_HEX = 16, - - /* Maximal number of allowed parameters */ - MAX_PARAMETERS = 64, - /* Maximal number of characters in class */ - MAX_CHARACTER_CLASS = UCHAR_MAX + 1, - - /* Maximal string lengths for user-defined specifiers */ - MAX_USER_NAME = 64, - MAX_USER_DATA = 256, - - /* Maximal length of locale separator strings */ - MAX_LOCALE_SEPARATOR_LENGTH = MB_LEN_MAX, - /* Maximal number of integers in grouping */ - MAX_LOCALE_GROUPS = 64, - - /* Initial size of asprintf buffer */ - DYNAMIC_START_SIZE = 32 -}; - -#define NO_GROUPING ((int)CHAR_MAX) - -/* Fundamental formatting parameter types */ -#define FORMAT_UNKNOWN 0 -#define FORMAT_INT 1 -#define FORMAT_DOUBLE 2 -#define FORMAT_CHAR 3 -#define FORMAT_STRING 4 -#define FORMAT_POINTER 5 -#define FORMAT_COUNT 6 -#define FORMAT_PARAMETER 7 -#define FORMAT_GROUP 8 -#if TRIO_GNU -# define FORMAT_ERRNO 9 -#endif -#if TRIO_EXTENSION -# define FORMAT_USER_DEFINED 10 -#endif - -/* Character constants */ -#define CHAR_IDENTIFIER '%' -#define CHAR_BACKSLASH '\\' -#define CHAR_QUOTE '\"' -#define CHAR_ADJUST ' ' - -/* Character class expressions */ -#define CLASS_ALNUM "[:alnum:]" -#define CLASS_ALPHA "[:alpha:]" -#define CLASS_BLANK "[:blank:]" -#define CLASS_CNTRL "[:cntrl:]" -#define CLASS_DIGIT "[:digit:]" -#define CLASS_GRAPH "[:graph:]" -#define CLASS_LOWER "[:lower:]" -#define CLASS_PRINT "[:print:]" -#define CLASS_PUNCT "[:punct:]" -#define CLASS_SPACE "[:space:]" -#define CLASS_UPPER "[:upper:]" -#define CLASS_XDIGIT "[:xdigit:]" - -/* - * SPECIFIERS: - * - * - * a Hex-float - * A Hex-float - * c Character - * C Widechar character (wint_t) - * d Decimal - * e Float - * E Float - * F Float - * F Float - * g Float - * G Float - * i Integer - * m Error message - * n Count - * o Octal - * p Pointer - * s String - * S Widechar string (wchar_t *) - * u Unsigned - * x Hex - * X Hex - * [] Group - * <> User-defined - * - * Reserved: - * - * D Binary Coded Decimal %D(length,precision) (OS/390) - */ -#define SPECIFIER_CHAR 'c' -#define SPECIFIER_STRING 's' -#define SPECIFIER_DECIMAL 'd' -#define SPECIFIER_INTEGER 'i' -#define SPECIFIER_UNSIGNED 'u' -#define SPECIFIER_OCTAL 'o' -#define SPECIFIER_HEX 'x' -#define SPECIFIER_HEX_UPPER 'X' -#define SPECIFIER_FLOAT_E 'e' -#define SPECIFIER_FLOAT_E_UPPER 'E' -#define SPECIFIER_FLOAT_F 'f' -#define SPECIFIER_FLOAT_F_UPPER 'F' -#define SPECIFIER_FLOAT_G 'g' -#define SPECIFIER_FLOAT_G_UPPER 'G' -#define SPECIFIER_POINTER 'p' -#define SPECIFIER_GROUP '[' -#define SPECIFIER_UNGROUP ']' -#define SPECIFIER_COUNT 'n' -#if TRIO_UNIX98 -# define SPECIFIER_CHAR_UPPER 'C' -# define SPECIFIER_STRING_UPPER 'S' -#endif -#if TRIO_C99 -# define SPECIFIER_HEXFLOAT 'a' -# define SPECIFIER_HEXFLOAT_UPPER 'A' -#endif -#if TRIO_GNU -# define SPECIFIER_ERRNO 'm' -#endif -#if TRIO_EXTENSION -# define SPECIFIER_BINARY 'b' -# define SPECIFIER_BINARY_UPPER 'B' -# define SPECIFIER_USER_DEFINED_BEGIN '<' -# define SPECIFIER_USER_DEFINED_END '>' -# define SPECIFIER_USER_DEFINED_SEPARATOR ':' -#endif - -/* - * QUALIFIERS: - * - * - * Numbers = d,i,o,u,x,X - * Float = a,A,e,E,f,F,g,G - * String = s - * Char = c - * - * - * 9$ Position - * Use the 9th parameter. 9 can be any number between 1 and - * the maximal argument - * - * 9 Width - * Set width to 9. 9 can be any number, but must not be postfixed - * by '$' - * - * h Short - * Numbers: - * (unsigned) short int - * - * hh Short short - * Numbers: - * (unsigned) char - * - * l Long - * Numbers: - * (unsigned) long int - * String: - * as the S specifier - * Char: - * as the C specifier - * - * ll Long Long - * Numbers: - * (unsigned) long long int - * - * L Long Double - * Float - * long double - * - * # Alternative - * Float: - * Decimal-point is always present - * String: - * non-printable characters are handled as \number - * - * Spacing - * - * + Sign - * - * - Alignment - * - * . Precision - * - * * Parameter - * print: use parameter - * scan: no parameter (ignore) - * - * q Quad - * - * Z size_t - * - * w Widechar - * - * ' Thousands/quote - * Numbers: - * Integer part grouped in thousands - * Binary numbers: - * Number grouped in nibbles (4 bits) - * String: - * Quoted string - * - * j intmax_t - * t prtdiff_t - * z size_t - * - * ! Sticky - * @ Parameter (for both print and scan) - * - * I n-bit Integer - * Numbers: - * The following options exists - * I8 = 8-bit integer - * I16 = 16-bit integer - * I32 = 32-bit integer - * I64 = 64-bit integer - */ -#define QUALIFIER_POSITION '$' -#define QUALIFIER_SHORT 'h' -#define QUALIFIER_LONG 'l' -#define QUALIFIER_LONG_UPPER 'L' -#define QUALIFIER_ALTERNATIVE '#' -#define QUALIFIER_SPACE ' ' -#define QUALIFIER_PLUS '+' -#define QUALIFIER_MINUS '-' -#define QUALIFIER_DOT '.' -#define QUALIFIER_STAR '*' -#define QUALIFIER_CIRCUMFLEX '^' /* For scanlists */ -#if TRIO_C99 -# define QUALIFIER_SIZE_T 'z' -# define QUALIFIER_PTRDIFF_T 't' -# define QUALIFIER_INTMAX_T 'j' -#endif -#if TRIO_BSD || TRIO_GNU -# define QUALIFIER_QUAD 'q' -#endif -#if TRIO_GNU -# define QUALIFIER_SIZE_T_UPPER 'Z' -#endif -#if TRIO_MISC -# define QUALIFIER_WIDECHAR 'w' -#endif -#if TRIO_MICROSOFT -# define QUALIFIER_FIXED_SIZE 'I' -#endif -#if TRIO_EXTENSION -# define QUALIFIER_QUOTE '\'' -# define QUALIFIER_STICKY '!' -# define QUALIFIER_VARSIZE '&' /* This should remain undocumented */ -# define QUALIFIER_PARAM '@' /* Experimental */ -# define QUALIFIER_COLON ':' /* For scanlists */ -# define QUALIFIER_EQUAL '=' /* For scanlists */ -# define QUALIFIER_ROUNDING_UPPER 'R' -#endif - - -/************************************************************************* - * - * Internal Structures - * - *************************************************************************/ - -/* Parameters */ -typedef struct { - /* An indication of which entry in the data union is used */ - int type; - /* The flags */ - trio_flags_t flags; - /* The width qualifier */ - int width; - /* The precision qualifier */ - int precision; - /* The base qualifier */ - int base; - /* The size for the variable size qualifier */ - int varsize; - /* The marker of the end of the specifier */ - int indexAfterSpecifier; - /* The data from the argument list */ - union { - char *string; -#if TRIO_WIDECHAR - trio_wchar_t *wstring; -#endif - trio_pointer_t pointer; - union { - trio_intmax_t as_signed; - trio_uintmax_t as_unsigned; - } number; - double doubleNumber; - double *doublePointer; - trio_long_double_t longdoubleNumber; - trio_long_double_t *longdoublePointer; - int errorNumber; - } data; - /* For the user-defined specifier */ - char user_name[MAX_USER_NAME]; - char user_data[MAX_USER_DATA]; -} trio_parameter_t; - -/* Container for customized functions */ -typedef struct { - union { - trio_outstream_t out; - trio_instream_t in; - } stream; - trio_pointer_t closure; -} trio_custom_t; - -/* General trio "class" */ -typedef struct _trio_class_t { - /* - * The function to write characters to a stream. - */ - void (*OutStream) TRIO_PROTO((struct _trio_class_t *, int)); - /* - * The function to read characters from a stream. - */ - void (*InStream) TRIO_PROTO((struct _trio_class_t *, int *)); - /* - * The current location in the stream. - */ - trio_pointer_t location; - /* - * The character currently being processed. - */ - int current; - /* - * The number of characters that would have been written/read - * if there had been sufficient space. - */ - int processed; - /* - * The number of characters that are actually written/read. - * Processed and committed will only differ for the *nprintf - * and *nscanf functions. - */ - int committed; - /* - * The upper limit of characters that may be written/read. - */ - int max; - /* - * The last output error that was detected. - */ - int error; -} trio_class_t; - -/* References (for user-defined callbacks) */ -typedef struct _trio_reference_t { - trio_class_t *data; - trio_parameter_t *parameter; -} trio_reference_t; - -/* Registered entries (for user-defined callbacks) */ -typedef struct _trio_userdef_t { - struct _trio_userdef_t *next; - trio_callback_t callback; - char *name; -} trio_userdef_t; - -/************************************************************************* - * - * Internal Variables - * - *************************************************************************/ - -static TRIO_CONST char rcsid[] = "@(#)$Id$"; - -/* - * Need this to workaround a parser bug in HP C/iX compiler that fails - * to resolves macro definitions that includes type 'long double', - * e.g: va_arg(arg_ptr, long double) - */ -#if defined(TRIO_PLATFORM_MPEIX) -static TRIO_CONST trio_long_double_t ___dummy_long_double = 0; -#endif - -static TRIO_CONST char internalNullString[] = "(nil)"; - -#if defined(USE_LOCALE) -static struct lconv *internalLocaleValues = NULL; -#endif - -/* - * UNIX98 says "in a locale where the radix character is not defined, - * the radix character defaults to a period (.)" - */ -static int internalDecimalPointLength = 1; -static int internalThousandSeparatorLength = 1; -static char internalDecimalPoint = '.'; -static char internalDecimalPointString[MAX_LOCALE_SEPARATOR_LENGTH + 1] = "."; -static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ","; -static char internalGrouping[MAX_LOCALE_GROUPS] = { (char)NO_GROUPING }; - -static TRIO_CONST char internalDigitsLower[] = "0123456789abcdefghijklmnopqrstuvwxyz"; -static TRIO_CONST char internalDigitsUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -static BOOLEAN_T internalDigitsUnconverted = TRUE; -static int internalDigitArray[128]; -#if TRIO_EXTENSION -static BOOLEAN_T internalCollationUnconverted = TRUE; -static char internalCollationArray[MAX_CHARACTER_CLASS][MAX_CHARACTER_CLASS]; -#endif - -#if TRIO_EXTENSION -static TRIO_VOLATILE trio_callback_t internalEnterCriticalRegion = NULL; -static TRIO_VOLATILE trio_callback_t internalLeaveCriticalRegion = NULL; -static trio_userdef_t *internalUserDef = NULL; -#endif - - -/************************************************************************* - * - * Internal Functions - * - ************************************************************************/ - -#if defined(TRIO_MINIMAL) -# define TRIO_STRING_PUBLIC static -# include "triostr.c" -#endif /* defined(TRIO_MINIMAL) */ - -/************************************************************************* - * TrioIsQualifier - * - * Description: - * Remember to add all new qualifiers to this function. - * QUALIFIER_POSITION must not be added. - */ -TRIO_PRIVATE BOOLEAN_T -TrioIsQualifier -TRIO_ARGS1((character), - TRIO_CONST char character) -{ - /* QUALIFIER_POSITION is not included */ - switch (character) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - case QUALIFIER_PLUS: - case QUALIFIER_MINUS: - case QUALIFIER_SPACE: - case QUALIFIER_DOT: - case QUALIFIER_STAR: - case QUALIFIER_ALTERNATIVE: - case QUALIFIER_SHORT: - case QUALIFIER_LONG: - case QUALIFIER_LONG_UPPER: - case QUALIFIER_CIRCUMFLEX: -#if defined(QUALIFIER_SIZE_T) - case QUALIFIER_SIZE_T: -#endif -#if defined(QUALIFIER_PTRDIFF_T) - case QUALIFIER_PTRDIFF_T: -#endif -#if defined(QUALIFIER_INTMAX_T) - case QUALIFIER_INTMAX_T: -#endif -#if defined(QUALIFIER_QUAD) - case QUALIFIER_QUAD: -#endif -#if defined(QUALIFIER_SIZE_T_UPPER) - case QUALIFIER_SIZE_T_UPPER: -#endif -#if defined(QUALIFIER_WIDECHAR) - case QUALIFIER_WIDECHAR: -#endif -#if defined(QUALIFIER_QUOTE) - case QUALIFIER_QUOTE: -#endif -#if defined(QUALIFIER_STICKY) - case QUALIFIER_STICKY: -#endif -#if defined(QUALIFIER_VARSIZE) - case QUALIFIER_VARSIZE: -#endif -#if defined(QUALIFIER_PARAM) - case QUALIFIER_PARAM: -#endif -#if defined(QUALIFIER_FIXED_SIZE) - case QUALIFIER_FIXED_SIZE: -#endif -#if defined(QUALIFIER_ROUNDING_UPPER) - case QUALIFIER_ROUNDING_UPPER: -#endif - return TRUE; - default: - return FALSE; - } -} - -/************************************************************************* - * TrioSetLocale - */ -#if defined(USE_LOCALE) -TRIO_PRIVATE void -TrioSetLocale(TRIO_NOARGS) -{ - internalLocaleValues = (struct lconv *)localeconv(); - if (internalLocaleValues) - { - if ((internalLocaleValues->decimal_point) && - (internalLocaleValues->decimal_point[0] != NIL)) - { - internalDecimalPointLength = trio_length(internalLocaleValues->decimal_point); - if (internalDecimalPointLength == 1) - { - internalDecimalPoint = internalLocaleValues->decimal_point[0]; - } - else - { - internalDecimalPoint = NIL; - trio_copy_max(internalDecimalPointString, - sizeof(internalDecimalPointString), - internalLocaleValues->decimal_point); - } - } - if ((internalLocaleValues->thousands_sep) && - (internalLocaleValues->thousands_sep[0] != NIL)) - { - trio_copy_max(internalThousandSeparator, - sizeof(internalThousandSeparator), - internalLocaleValues->thousands_sep); - internalThousandSeparatorLength = trio_length(internalThousandSeparator); - } - if ((internalLocaleValues->grouping) && - (internalLocaleValues->grouping[0] != NIL)) - { - trio_copy_max(internalGrouping, - sizeof(internalGrouping), - internalLocaleValues->grouping); - } - } -} -#endif /* defined(USE_LOCALE) */ - -TRIO_PRIVATE int -TrioCalcThousandSeparatorLength -TRIO_ARGS1((digits), - int digits) -{ -#if TRIO_EXTENSION - int count = 0; - int step = NO_GROUPING; - char *groupingPointer = internalGrouping; - - while (digits > 0) - { - if (*groupingPointer == CHAR_MAX) - { - /* Disable grouping */ - break; /* while */ - } - else if (*groupingPointer == 0) - { - /* Repeat last group */ - if (step == NO_GROUPING) - { - /* Error in locale */ - break; /* while */ - } - } - else - { - step = *groupingPointer++; - } - if (digits > step) - count += internalThousandSeparatorLength; - digits -= step; - } - return count; -#else - return 0; -#endif -} - -TRIO_PRIVATE BOOLEAN_T -TrioFollowedBySeparator -TRIO_ARGS1((position), - int position) -{ -#if TRIO_EXTENSION - int step = 0; - char *groupingPointer = internalGrouping; - - position--; - if (position == 0) - return FALSE; - while (position > 0) - { - if (*groupingPointer == CHAR_MAX) - { - /* Disable grouping */ - break; /* while */ - } - else if (*groupingPointer != 0) - { - step = *groupingPointer++; - } - if (step == 0) - break; - position -= step; - } - return (position == 0); -#else - return FALSE; -#endif -} - -/************************************************************************* - * TrioGetPosition - * - * Get the %n$ position. - */ -TRIO_PRIVATE int -TrioGetPosition -TRIO_ARGS2((format, indexPointer), - TRIO_CONST char *format, - int *indexPointer) -{ -#if TRIO_UNIX98 - char *tmpformat; - int number = 0; - int index = *indexPointer; - - number = (int)trio_to_long(&format[index], &tmpformat, BASE_DECIMAL); - index = (int)(tmpformat - format); - if ((number != 0) && (QUALIFIER_POSITION == format[index++])) - { - *indexPointer = index; - /* - * number is decreased by 1, because n$ starts from 1, whereas - * the array it is indexing starts from 0. - */ - return number - 1; - } -#endif - return NO_POSITION; -} - -#if TRIO_EXTENSION -/************************************************************************* - * TrioFindNamespace - * - * Find registered user-defined specifier. - * The prev argument is used for optimization only. - */ -TRIO_PRIVATE trio_userdef_t * -TrioFindNamespace -TRIO_ARGS2((name, prev), - TRIO_CONST char *name, - trio_userdef_t **prev) -{ - trio_userdef_t *def; - - if (internalEnterCriticalRegion) - (void)internalEnterCriticalRegion(NULL); - - for (def = internalUserDef; def; def = def->next) - { - /* Case-sensitive string comparison */ - if (trio_equal_case(def->name, name)) - break; - - if (prev) - *prev = def; - } - - if (internalLeaveCriticalRegion) - (void)internalLeaveCriticalRegion(NULL); - - return def; -} -#endif - -/************************************************************************* - * TrioPower - * - * Description: - * Calculate pow(base, exponent), where number and exponent are integers. - */ -TRIO_PRIVATE trio_long_double_t -TrioPower -TRIO_ARGS2((number, exponent), - int number, - int exponent) -{ - trio_long_double_t result; - - if (number == 10) - { - switch (exponent) - { - /* Speed up calculation of common cases */ - case 0: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E-1); - break; - case 1: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+0); - break; - case 2: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+1); - break; - case 3: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+2); - break; - case 4: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+3); - break; - case 5: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+4); - break; - case 6: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+5); - break; - case 7: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+6); - break; - case 8: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+7); - break; - case 9: - result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+8); - break; - default: - result = powl((trio_long_double_t)number, - (trio_long_double_t)exponent); - break; - } - } - else - { - return powl((trio_long_double_t)number, (trio_long_double_t)exponent); - } - return result; -} - -/************************************************************************* - * TrioLogarithm - */ -TRIO_PRIVATE double -TrioLogarithm -TRIO_ARGS2((number, base), - double number, - int base) -{ - double result; - - if (number <= 0.0) - { - /* xlC crashes on log(0) */ - result = (number == 0.0) ? trio_ninf() : trio_nan(); - } - else - { - if (base == 10) - { - result = log10(number); - } - else - { - result = log10(number) / log10((double)base); - } - } - return result; -} - -/************************************************************************* - * TrioLogarithmBase - */ -TRIO_PRIVATE double -TrioLogarithmBase -TRIO_ARGS1((base), - int base) -{ - switch (base) - { - case BASE_BINARY : return 1.0; - case BASE_OCTAL : return 3.0; - case BASE_DECIMAL: return 3.321928094887362345; - case BASE_HEX : return 4.0; - default : return TrioLogarithm((double)base, 2); - } -} - -/************************************************************************* - * TrioParse - * - * Description: - * Parse the format string - */ -TRIO_PRIVATE int -TrioParse -TRIO_ARGS5((type, format, parameters, arglist, argarray), - int type, - TRIO_CONST char *format, - trio_parameter_t *parameters, - TRIO_VA_LIST_PTR arglist, - trio_pointer_t *argarray) -{ - /* Count the number of times a parameter is referenced */ - unsigned short usedEntries[MAX_PARAMETERS]; - /* Parameter counters */ - int parameterPosition; - int currentParam; - int maxParam = -1; - /* Utility variables */ - trio_flags_t flags; - int width; - int precision; - int varsize; - int base; - int index; /* Index into formatting string */ - int dots; /* Count number of dots in modifier part */ - BOOLEAN_T positional; /* Does the specifier have a positional? */ - BOOLEAN_T gotSticky = FALSE; /* Are there any sticky modifiers at all? */ - /* - * indices specifies the order in which the parameters must be - * read from the va_args (this is necessary to handle positionals) - */ - int indices[MAX_PARAMETERS]; - int pos = 0; - /* Various variables */ - char ch; -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - int charlen; -#endif - int save_errno; - int i = -1; - int num; - char *tmpformat; - - /* One and only one of arglist and argarray must be used */ - assert((arglist != NULL) ^ (argarray != NULL)); - - /* - * The 'parameters' array is not initialized, but we need to - * know which entries we have used. - */ - memset(usedEntries, 0, sizeof(usedEntries)); - - save_errno = errno; - index = 0; - parameterPosition = 0; -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - (void)mblen(NULL, 0); -#endif - - while (format[index]) - { -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - if (! isascii(format[index])) - { - /* - * Multibyte characters cannot be legal specifiers or - * modifiers, so we skip over them. - */ - charlen = mblen(&format[index], MB_LEN_MAX); - index += (charlen > 0) ? charlen : 1; - continue; /* while */ - } -#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */ - if (CHAR_IDENTIFIER == format[index++]) - { - if (CHAR_IDENTIFIER == format[index]) - { - index++; - continue; /* while */ - } - - flags = FLAGS_NEW; - dots = 0; - currentParam = TrioGetPosition(format, &index); - positional = (NO_POSITION != currentParam); - if (!positional) - { - /* We have no positional, get the next counter */ - currentParam = parameterPosition; - } - if(currentParam >= MAX_PARAMETERS) - { - /* Bail out completely to make the error more obvious */ - return TRIO_ERROR_RETURN(TRIO_ETOOMANY, index); - } - - if (currentParam > maxParam) - maxParam = currentParam; - - /* Default values */ - width = NO_WIDTH; - precision = NO_PRECISION; - base = NO_BASE; - varsize = NO_SIZE; - - while (TrioIsQualifier(format[index])) - { - ch = format[index++]; - - switch (ch) - { - case QUALIFIER_SPACE: - flags |= FLAGS_SPACE; - break; - - case QUALIFIER_PLUS: - flags |= FLAGS_SHOWSIGN; - break; - - case QUALIFIER_MINUS: - flags |= FLAGS_LEFTADJUST; - flags &= ~FLAGS_NILPADDING; - break; - - case QUALIFIER_ALTERNATIVE: - flags |= FLAGS_ALTERNATIVE; - break; - - case QUALIFIER_DOT: - if (dots == 0) /* Precision */ - { - dots++; - - /* Skip if no precision */ - if (QUALIFIER_DOT == format[index]) - break; - - /* After the first dot we have the precision */ - flags |= FLAGS_PRECISION; - if ((QUALIFIER_STAR == format[index]) -#if defined(QUALIFIER_PARAM) - || (QUALIFIER_PARAM == format[index]) -#endif - ) - { - index++; - flags |= FLAGS_PRECISION_PARAMETER; - - precision = TrioGetPosition(format, &index); - if (precision == NO_POSITION) - { - parameterPosition++; - if (positional) - precision = parameterPosition; - else - { - precision = currentParam; - currentParam = precision + 1; - } - } - else - { - if (! positional) - currentParam = precision + 1; - if (width > maxParam) - maxParam = precision; - } - if (currentParam > maxParam) - maxParam = currentParam; - } - else - { - precision = trio_to_long(&format[index], - &tmpformat, - BASE_DECIMAL); - index = (int)(tmpformat - format); - } - } - else if (dots == 1) /* Base */ - { - dots++; - - /* After the second dot we have the base */ - flags |= FLAGS_BASE; - if ((QUALIFIER_STAR == format[index]) -#if defined(QUALIFIER_PARAM) - || (QUALIFIER_PARAM == format[index]) -#endif - ) - { - index++; - flags |= FLAGS_BASE_PARAMETER; - base = TrioGetPosition(format, &index); - if (base == NO_POSITION) - { - parameterPosition++; - if (positional) - base = parameterPosition; - else - { - base = currentParam; - currentParam = base + 1; - } - } - else - { - if (! positional) - currentParam = base + 1; - if (base > maxParam) - maxParam = base; - } - if (currentParam > maxParam) - maxParam = currentParam; - } - else - { - base = trio_to_long(&format[index], - &tmpformat, - BASE_DECIMAL); - if (base > MAX_BASE) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - index = (int)(tmpformat - format); - } - } - else - { - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - } - break; /* QUALIFIER_DOT */ - -#if defined(QUALIFIER_PARAM) - case QUALIFIER_PARAM: - type = TYPE_PRINT; - /* FALLTHROUGH */ -#endif - case QUALIFIER_STAR: - /* This has different meanings for print and scan */ - if (TYPE_PRINT == type) - { - /* Read with from parameter */ - flags |= (FLAGS_WIDTH | FLAGS_WIDTH_PARAMETER); - width = TrioGetPosition(format, &index); - if (width == NO_POSITION) - { - parameterPosition++; - if (positional) - width = parameterPosition; - else - { - width = currentParam; - currentParam = width + 1; - } - } - else - { - if (! positional) - currentParam = width + 1; - if (width > maxParam) - maxParam = width; - } - if (currentParam > maxParam) - maxParam = currentParam; - } - else - { - /* Scan, but do not store result */ - flags |= FLAGS_IGNORE; - } - - break; /* QUALIFIER_STAR */ - - case '0': - if (! (flags & FLAGS_LEFTADJUST)) - flags |= FLAGS_NILPADDING; - /* FALLTHROUGH */ - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - flags |= FLAGS_WIDTH; - /* &format[index - 1] is used to "rewind" the read - * character from format - */ - width = trio_to_long(&format[index - 1], - &tmpformat, - BASE_DECIMAL); - index = (int)(tmpformat - format); - break; - - case QUALIFIER_SHORT: - if (flags & FLAGS_SHORTSHORT) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - else if (flags & FLAGS_SHORT) - flags |= FLAGS_SHORTSHORT; - else - flags |= FLAGS_SHORT; - break; - - case QUALIFIER_LONG: - if (flags & FLAGS_QUAD) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - else if (flags & FLAGS_LONG) - flags |= FLAGS_QUAD; - else - flags |= FLAGS_LONG; - break; - - case QUALIFIER_LONG_UPPER: - flags |= FLAGS_LONGDOUBLE; - break; - -#if defined(QUALIFIER_SIZE_T) - case QUALIFIER_SIZE_T: - flags |= FLAGS_SIZE_T; - /* Modify flags for later truncation of number */ - if (sizeof(size_t) == sizeof(trio_ulonglong_t)) - flags |= FLAGS_QUAD; - else if (sizeof(size_t) == sizeof(long)) - flags |= FLAGS_LONG; - break; -#endif - -#if defined(QUALIFIER_PTRDIFF_T) - case QUALIFIER_PTRDIFF_T: - flags |= FLAGS_PTRDIFF_T; - if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t)) - flags |= FLAGS_QUAD; - else if (sizeof(ptrdiff_t) == sizeof(long)) - flags |= FLAGS_LONG; - break; -#endif - -#if defined(QUALIFIER_INTMAX_T) - case QUALIFIER_INTMAX_T: - flags |= FLAGS_INTMAX_T; - if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t)) - flags |= FLAGS_QUAD; - else if (sizeof(trio_intmax_t) == sizeof(long)) - flags |= FLAGS_LONG; - break; -#endif - -#if defined(QUALIFIER_QUAD) - case QUALIFIER_QUAD: - flags |= FLAGS_QUAD; - break; -#endif - -#if defined(QUALIFIER_FIXED_SIZE) - case QUALIFIER_FIXED_SIZE: - if (flags & FLAGS_FIXED_SIZE) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - - if (flags & (FLAGS_ALL_SIZES | FLAGS_LONGDOUBLE | - FLAGS_WIDECHAR | FLAGS_VARSIZE_PARAMETER)) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - - if ((format[index] == '6') && - (format[index + 1] == '4')) - { - varsize = sizeof(trio_int64_t); - index += 2; - } - else if ((format[index] == '3') && - (format[index + 1] == '2')) - { - varsize = sizeof(trio_int32_t); - index += 2; - } - else if ((format[index] == '1') && - (format[index + 1] == '6')) - { - varsize = sizeof(trio_int16_t); - index += 2; - } - else if (format[index] == '8') - { - varsize = sizeof(trio_int8_t); - index++; - } - else - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - - flags |= FLAGS_FIXED_SIZE; - break; -#endif - -#if defined(QUALIFIER_WIDECHAR) - case QUALIFIER_WIDECHAR: - flags |= FLAGS_WIDECHAR; - break; -#endif - -#if defined(QUALIFIER_SIZE_T_UPPER) - case QUALIFIER_SIZE_T_UPPER: - break; -#endif - -#if defined(QUALIFIER_QUOTE) - case QUALIFIER_QUOTE: - flags |= FLAGS_QUOTE; - break; -#endif - -#if defined(QUALIFIER_STICKY) - case QUALIFIER_STICKY: - flags |= FLAGS_STICKY; - gotSticky = TRUE; - break; -#endif - -#if defined(QUALIFIER_VARSIZE) - case QUALIFIER_VARSIZE: - flags |= FLAGS_VARSIZE_PARAMETER; - parameterPosition++; - if (positional) - varsize = parameterPosition; - else - { - varsize = currentParam; - currentParam = varsize + 1; - } - if (currentParam > maxParam) - maxParam = currentParam; - break; -#endif - -#if defined(QUALIFIER_ROUNDING_UPPER) - case QUALIFIER_ROUNDING_UPPER: - flags |= FLAGS_ROUNDING; - break; -#endif - - default: - /* Bail out completely to make the error more obvious */ - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - } - } /* while qualifier */ - - /* - * Parameters only need the type and value. The value is - * read later. - */ - if (flags & FLAGS_WIDTH_PARAMETER) - { - usedEntries[width] += 1; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[width] = pos; - width = pos++; - } - if (flags & FLAGS_PRECISION_PARAMETER) - { - usedEntries[precision] += 1; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[precision] = pos; - precision = pos++; - } - if (flags & FLAGS_BASE_PARAMETER) - { - usedEntries[base] += 1; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[base] = pos; - base = pos++; - } - if (flags & FLAGS_VARSIZE_PARAMETER) - { - usedEntries[varsize] += 1; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[varsize] = pos; - varsize = pos++; - } - - indices[currentParam] = pos; - - switch (format[index++]) - { -#if defined(SPECIFIER_CHAR_UPPER) - case SPECIFIER_CHAR_UPPER: - flags |= FLAGS_WIDECHAR; - /* FALLTHROUGH */ -#endif - case SPECIFIER_CHAR: - if (flags & FLAGS_LONG) - flags |= FLAGS_WIDECHAR; - else if (flags & FLAGS_SHORT) - flags &= ~FLAGS_WIDECHAR; - parameters[pos].type = FORMAT_CHAR; - break; - -#if defined(SPECIFIER_STRING_UPPER) - case SPECIFIER_STRING_UPPER: - flags |= FLAGS_WIDECHAR; - /* FALLTHROUGH */ -#endif - case SPECIFIER_STRING: - if (flags & FLAGS_LONG) - flags |= FLAGS_WIDECHAR; - else if (flags & FLAGS_SHORT) - flags &= ~FLAGS_WIDECHAR; - parameters[pos].type = FORMAT_STRING; - break; - - case SPECIFIER_GROUP: - if (TYPE_SCAN == type) - { - int depth = 1; - parameters[pos].type = FORMAT_GROUP; - if (format[index] == QUALIFIER_CIRCUMFLEX) - index++; - if (format[index] == SPECIFIER_UNGROUP) - index++; - if (format[index] == QUALIFIER_MINUS) - index++; - /* Skip nested brackets */ - while (format[index] != NIL) - { - if (format[index] == SPECIFIER_GROUP) - { - depth++; - } - else if (format[index] == SPECIFIER_UNGROUP) - { - if (--depth <= 0) - { - index++; - break; - } - } - index++; - } - } - break; - - case SPECIFIER_INTEGER: - parameters[pos].type = FORMAT_INT; - break; - - case SPECIFIER_UNSIGNED: - flags |= FLAGS_UNSIGNED; - parameters[pos].type = FORMAT_INT; - break; - - case SPECIFIER_DECIMAL: - /* Disable base modifier */ - flags &= ~FLAGS_BASE_PARAMETER; - base = BASE_DECIMAL; - parameters[pos].type = FORMAT_INT; - break; - - case SPECIFIER_OCTAL: - flags |= FLAGS_UNSIGNED; - flags &= ~FLAGS_BASE_PARAMETER; - base = BASE_OCTAL; - parameters[pos].type = FORMAT_INT; - break; - -#if defined(SPECIFIER_BINARY) - case SPECIFIER_BINARY_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_BINARY: - flags |= FLAGS_NILPADDING; - flags &= ~FLAGS_BASE_PARAMETER; - base = BASE_BINARY; - parameters[pos].type = FORMAT_INT; - break; -#endif - - case SPECIFIER_HEX_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_HEX: - flags |= FLAGS_UNSIGNED; - flags &= ~FLAGS_BASE_PARAMETER; - base = BASE_HEX; - parameters[pos].type = FORMAT_INT; - break; - - case SPECIFIER_FLOAT_E_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_FLOAT_E: - flags |= FLAGS_FLOAT_E; - parameters[pos].type = FORMAT_DOUBLE; - break; - - case SPECIFIER_FLOAT_G_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_FLOAT_G: - flags |= FLAGS_FLOAT_G; - parameters[pos].type = FORMAT_DOUBLE; - break; - - case SPECIFIER_FLOAT_F_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_FLOAT_F: - parameters[pos].type = FORMAT_DOUBLE; - break; - - case SPECIFIER_POINTER: - if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t)) - flags |= FLAGS_QUAD; - else if (sizeof(trio_pointer_t) == sizeof(long)) - flags |= FLAGS_LONG; - parameters[pos].type = FORMAT_POINTER; - break; - - case SPECIFIER_COUNT: - parameters[pos].type = FORMAT_COUNT; - break; - -#if defined(SPECIFIER_HEXFLOAT) -# if defined(SPECIFIER_HEXFLOAT_UPPER) - case SPECIFIER_HEXFLOAT_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ -# endif - case SPECIFIER_HEXFLOAT: - base = BASE_HEX; - parameters[pos].type = FORMAT_DOUBLE; - break; -#endif - -#if defined(FORMAT_ERRNO) - case SPECIFIER_ERRNO: - parameters[pos].type = FORMAT_ERRNO; - break; -#endif - -#if defined(SPECIFIER_USER_DEFINED_BEGIN) - case SPECIFIER_USER_DEFINED_BEGIN: - { - unsigned int max; - int without_namespace = TRUE; - - parameters[pos].type = FORMAT_USER_DEFINED; - parameters[pos].user_name[0] = NIL; - tmpformat = (char *)&format[index]; - - while ((ch = format[index])) - { - index++; - if (ch == SPECIFIER_USER_DEFINED_END) - { - if (without_namespace) - { - /* We must get the handle first */ - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].indexAfterSpecifier = index; - parameters[pos].flags = FLAGS_USER_DEFINED; - /* Adjust parameters for insertion of new one */ - pos++; - usedEntries[currentParam] += 1; - parameters[pos].type = FORMAT_USER_DEFINED; - currentParam++; - indices[currentParam] = pos; - if (currentParam > maxParam) - maxParam = currentParam; - } - /* Copy the user data */ - max = (unsigned int)(&format[index] - tmpformat); - if (max > MAX_USER_DATA) - max = MAX_USER_DATA; - trio_copy_max(parameters[pos].user_data, - max, - tmpformat); - break; /* while */ - } - if (ch == SPECIFIER_USER_DEFINED_SEPARATOR) - { - without_namespace = FALSE; - /* Copy the namespace for later looking-up */ - max = (int)(&format[index] - tmpformat); - if (max > MAX_USER_NAME) - max = MAX_USER_NAME; - trio_copy_max(parameters[pos].user_name, - max, - tmpformat); - tmpformat = (char *)&format[index]; - } - } - if (ch != SPECIFIER_USER_DEFINED_END) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - } - break; -#endif /* defined(SPECIFIER_USER_DEFINED_BEGIN) */ - - default: - /* Bail out completely to make the error more obvious */ - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - } - - /* Count the number of times this entry has been used */ - usedEntries[currentParam] += 1; - - /* Find last sticky parameters */ - if (gotSticky && !(flags & FLAGS_STICKY)) - { - for (i = pos - 1; i >= 0; i--) - { - if (parameters[i].type == FORMAT_PARAMETER) - continue; - if ((parameters[i].flags & FLAGS_STICKY) && - (parameters[i].type == parameters[pos].type)) - { - /* Do not overwrite current qualifiers */ - flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY); - if (width == NO_WIDTH) - width = parameters[i].width; - if (precision == NO_PRECISION) - precision = parameters[i].precision; - if (base == NO_BASE) - base = parameters[i].base; - break; - } - } - } - - parameters[pos].indexAfterSpecifier = index; - parameters[pos].flags = flags; - parameters[pos].width = width; - parameters[pos].precision = precision; - parameters[pos].base = (base == NO_BASE) ? BASE_DECIMAL : base; - parameters[pos].varsize = varsize; - pos++; - - if (! positional) - parameterPosition++; - - } /* if identifier */ - - } /* while format characters left */ - - for (num = 0; num <= maxParam; num++) - { - if (usedEntries[num] != 1) - { - if (usedEntries[num] == 0) /* gap detected */ - return TRIO_ERROR_RETURN(TRIO_EGAP, num); - else /* double references detected */ - return TRIO_ERROR_RETURN(TRIO_EDBLREF, num); - } - - i = indices[num]; - - /* - * FORMAT_PARAMETERS are only present if they must be read, - * so it makes no sense to check the ignore flag (besides, - * the flags variable is not set for that particular type) - */ - if ((parameters[i].type != FORMAT_PARAMETER) && - (parameters[i].flags & FLAGS_IGNORE)) - continue; /* for all arguments */ - - /* - * The stack arguments are read according to ANSI C89 - * default argument promotions: - * - * char = int - * short = int - * unsigned char = unsigned int - * unsigned short = unsigned int - * float = double - * - * In addition to the ANSI C89 these types are read (the - * default argument promotions of C99 has not been - * considered yet) - * - * long long - * long double - * size_t - * ptrdiff_t - * intmax_t - */ - switch (parameters[i].type) - { - case FORMAT_GROUP: - case FORMAT_STRING: -#if TRIO_WIDECHAR - if (flags & FLAGS_WIDECHAR) - { - parameters[i].data.wstring = (argarray == NULL) - ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_wchar_t *) - : (trio_wchar_t *)(argarray[num]); - } - else -#endif - { - parameters[i].data.string = (argarray == NULL) - ? va_arg(TRIO_VA_LIST_DEREF(arglist), char *) - : (char *)(argarray[num]); - } - break; - -#if defined(FORMAT_USER_DEFINED) - case FORMAT_USER_DEFINED: -#endif - case FORMAT_POINTER: - case FORMAT_COUNT: - case FORMAT_UNKNOWN: - parameters[i].data.pointer = (argarray == NULL) - ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_pointer_t ) - : argarray[num]; - break; - - case FORMAT_CHAR: - case FORMAT_INT: - if (TYPE_SCAN == type) - { - if (argarray == NULL) - parameters[i].data.pointer = - (trio_pointer_t)va_arg(TRIO_VA_LIST_DEREF(arglist), trio_pointer_t); - else - { - if (parameters[i].type == FORMAT_CHAR) - parameters[i].data.pointer = - (trio_pointer_t)((char *)argarray[num]); - else if (parameters[i].flags & FLAGS_SHORT) - parameters[i].data.pointer = - (trio_pointer_t)((short *)argarray[num]); - else - parameters[i].data.pointer = - (trio_pointer_t)((int *)argarray[num]); - } - } - else - { -#if defined(QUALIFIER_VARSIZE) || defined(QUALIFIER_FIXED_SIZE) - if (parameters[i].flags - & (FLAGS_VARSIZE_PARAMETER | FLAGS_FIXED_SIZE)) - { - if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER) - { - /* - * Variable sizes are mapped onto the fixed sizes, in - * accordance with integer promotion. - * - * Please note that this may not be portable, as we - * only guess the size, not the layout of the numbers. - * For example, if int is little-endian, and long is - * big-endian, then this will fail. - */ - varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned; - } - else - { - /* Used for the I modifiers */ - varsize = parameters[i].varsize; - } - parameters[i].flags &= ~FLAGS_ALL_VARSIZES; - - if (varsize <= (int)sizeof(int)) - ; - else if (varsize <= (int)sizeof(long)) - parameters[i].flags |= FLAGS_LONG; -#if defined(QUALIFIER_INTMAX_T) - else if (varsize <= (int)sizeof(trio_longlong_t)) - parameters[i].flags |= FLAGS_QUAD; - else - parameters[i].flags |= FLAGS_INTMAX_T; -#else - else - parameters[i].flags |= FLAGS_QUAD; -#endif - } -#endif /* defined(QUALIFIER_VARSIZE) */ -#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER) - if (parameters[i].flags & FLAGS_SIZE_T) - parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), size_t) - : (trio_uintmax_t)(*((size_t *)argarray[num])); - else -#endif -#if defined(QUALIFIER_PTRDIFF_T) - if (parameters[i].flags & FLAGS_PTRDIFF_T) - parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), ptrdiff_t) - : (trio_uintmax_t)(*((ptrdiff_t *)argarray[num])); - else -#endif -#if defined(QUALIFIER_INTMAX_T) - if (parameters[i].flags & FLAGS_INTMAX_T) - parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), trio_intmax_t) - : (trio_uintmax_t)(*((trio_intmax_t *)argarray[num])); - else -#endif - if (parameters[i].flags & FLAGS_QUAD) - parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), trio_ulonglong_t) - : (trio_uintmax_t)(*((trio_ulonglong_t *)argarray[num])); - else if (parameters[i].flags & FLAGS_LONG) - parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), long) - : (trio_uintmax_t)(*((long *)argarray[num])); - else - { - if (argarray == NULL) - parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), int); - else - { - if (parameters[i].type == FORMAT_CHAR) - parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((char *)argarray[num])); - else if (parameters[i].flags & FLAGS_SHORT) - parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((short *)argarray[num])); - else - parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((int *)argarray[num])); - } - } - } - break; - - case FORMAT_PARAMETER: - /* - * The parameter for the user-defined specifier is a pointer, - * whereas the rest (width, precision, base) uses an integer. - */ - if (parameters[i].flags & FLAGS_USER_DEFINED) - parameters[i].data.pointer = (argarray == NULL) - ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_pointer_t ) - : argarray[num]; - else - parameters[i].data.number.as_unsigned = (argarray == NULL) - ? (trio_uintmax_t)va_arg(TRIO_VA_LIST_DEREF(arglist), int) - : (trio_uintmax_t)(*((int *)argarray[num])); - break; - - case FORMAT_DOUBLE: - if (TYPE_SCAN == type) - { - if (parameters[i].flags & FLAGS_LONGDOUBLE) - parameters[i].data.longdoublePointer = (argarray == NULL) - ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_long_double_t *) - : (trio_long_double_t *)argarray[num]; - else - { - if (parameters[i].flags & FLAGS_LONG) - parameters[i].data.doublePointer = (argarray == NULL) - ? va_arg(TRIO_VA_LIST_DEREF(arglist), double *) - : (double *)argarray[num]; - else - parameters[i].data.doublePointer = (argarray == NULL) - ? (double *)va_arg(TRIO_VA_LIST_DEREF(arglist), float *) - : (double *)((float *)argarray[num]); - } - } - else - { - if (parameters[i].flags & FLAGS_LONGDOUBLE) - parameters[i].data.longdoubleNumber = (argarray == NULL) - ? va_arg(TRIO_VA_LIST_DEREF(arglist), trio_long_double_t) - : (trio_long_double_t)(*((trio_long_double_t *)argarray[num])); - else - { - if (argarray == NULL) - parameters[i].data.longdoubleNumber = - (trio_long_double_t)va_arg(TRIO_VA_LIST_DEREF(arglist), double); - else - { - if (parameters[i].flags & FLAGS_SHORT) - parameters[i].data.longdoubleNumber = - (trio_long_double_t)(*((float *)argarray[num])); - else - parameters[i].data.longdoubleNumber = - (trio_long_double_t)(*((double *)argarray[num])); - } - } - } - break; - -#if defined(FORMAT_ERRNO) - case FORMAT_ERRNO: - parameters[i].data.errorNumber = save_errno; - break; -#endif - - default: - break; - } - } /* for all specifiers */ - return num; -} - - -/************************************************************************* - * - * FORMATTING - * - ************************************************************************/ - - -/************************************************************************* - * TrioWriteNumber - * - * Description: - * Output a number. - * The complexity of this function is a result of the complexity - * of the dependencies of the flags. - */ -TRIO_PRIVATE void -TrioWriteNumber -TRIO_ARGS6((self, number, flags, width, precision, base), - trio_class_t *self, - trio_uintmax_t number, - trio_flags_t flags, - int width, - int precision, - int base) -{ - BOOLEAN_T isNegative; - BOOLEAN_T isNumberZero; - BOOLEAN_T isPrecisionZero; - BOOLEAN_T ignoreNumber; - char buffer[MAX_CHARS_IN(trio_uintmax_t) * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1]; - char *bufferend; - char *pointer; - TRIO_CONST char *digits; - int i; - int length; - char *p; - int count; - - assert(VALID(self)); - assert(VALID(self->OutStream)); - assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE)); - - digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower; - if (base == NO_BASE) - base = BASE_DECIMAL; - - isNumberZero = (number == 0); - isPrecisionZero = (precision == 0); - ignoreNumber = (isNumberZero - && isPrecisionZero - && !((flags & FLAGS_ALTERNATIVE) && (base == BASE_OCTAL))); - - if (flags & FLAGS_UNSIGNED) - { - isNegative = FALSE; - flags &= ~FLAGS_SHOWSIGN; - } - else - { - isNegative = ((trio_intmax_t)number < 0); - if (isNegative) - number = -((trio_intmax_t)number); - } - - if (flags & FLAGS_QUAD) - number &= (trio_ulonglong_t)-1; - else if (flags & FLAGS_LONG) - number &= (unsigned long)-1; - else - number &= (unsigned int)-1; - - /* Build number */ - pointer = bufferend = &buffer[sizeof(buffer) - 1]; - *pointer-- = NIL; - for (i = 1; i < (int)sizeof(buffer); i++) - { - *pointer-- = digits[number % base]; - number /= base; - if (number == 0) - break; - - if ((flags & FLAGS_QUOTE) && TrioFollowedBySeparator(i + 1)) - { - /* - * We are building the number from the least significant - * to the most significant digit, so we have to copy the - * thousand separator backwards - */ - length = internalThousandSeparatorLength; - if (((int)(pointer - buffer) - length) > 0) - { - p = &internalThousandSeparator[length - 1]; - while (length-- > 0) - *pointer-- = *p--; - } - } - } - - if (! ignoreNumber) - { - /* Adjust width */ - width -= (bufferend - pointer) - 1; - } - - /* Adjust precision */ - if (NO_PRECISION != precision) - { - precision -= (bufferend - pointer) - 1; - if (precision < 0) - precision = 0; - flags |= FLAGS_NILPADDING; - } - - /* Calculate padding */ - count = (! ((flags & FLAGS_LEFTADJUST) || (precision == NO_PRECISION))) - ? precision - : 0; - - /* Adjust width further */ - if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE)) - width--; - if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero) - { - switch (base) - { - case BASE_BINARY: - case BASE_HEX: - width -= 2; - break; - case BASE_OCTAL: - if (!(flags & FLAGS_NILPADDING) || (count == 0)) - width--; - break; - default: - break; - } - } - - /* Output prefixes spaces if needed */ - if (! ((flags & FLAGS_LEFTADJUST) || - ((flags & FLAGS_NILPADDING) && (precision == NO_PRECISION)))) - { - while (width-- > count) - self->OutStream(self, CHAR_ADJUST); - } - - /* width has been adjusted for signs and alternatives */ - if (isNegative) - self->OutStream(self, '-'); - else if (flags & FLAGS_SHOWSIGN) - self->OutStream(self, '+'); - else if (flags & FLAGS_SPACE) - self->OutStream(self, ' '); - - /* Prefix is not written when the value is zero */ - if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero) - { - switch (base) - { - case BASE_BINARY: - self->OutStream(self, '0'); - self->OutStream(self, (flags & FLAGS_UPPER) ? 'B' : 'b'); - break; - - case BASE_OCTAL: - if (!(flags & FLAGS_NILPADDING) || (count == 0)) - self->OutStream(self, '0'); - break; - - case BASE_HEX: - self->OutStream(self, '0'); - self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x'); - break; - - default: - break; - } /* switch base */ - } - - /* Output prefixed zero padding if needed */ - if (flags & FLAGS_NILPADDING) - { - if (precision == NO_PRECISION) - precision = width; - while (precision-- > 0) - { - self->OutStream(self, '0'); - width--; - } - } - - if (! ignoreNumber) - { - /* Output the number itself */ - while (*(++pointer)) - { - self->OutStream(self, *pointer); - } - } - - /* Output trailing spaces if needed */ - if (flags & FLAGS_LEFTADJUST) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } -} - -/************************************************************************* - * TrioWriteStringCharacter - * - * Description: - * Output a single character of a string - */ -TRIO_PRIVATE void -TrioWriteStringCharacter -TRIO_ARGS3((self, ch, flags), - trio_class_t *self, - int ch, - trio_flags_t flags) -{ - if (flags & FLAGS_ALTERNATIVE) - { - if (! isprint(ch)) - { - /* - * Non-printable characters are converted to C escapes or - * \number, if no C escape exists. - */ - self->OutStream(self, CHAR_BACKSLASH); - switch (ch) - { - case '\007': self->OutStream(self, 'a'); break; - case '\b': self->OutStream(self, 'b'); break; - case '\f': self->OutStream(self, 'f'); break; - case '\n': self->OutStream(self, 'n'); break; - case '\r': self->OutStream(self, 'r'); break; - case '\t': self->OutStream(self, 't'); break; - case '\v': self->OutStream(self, 'v'); break; - case '\\': self->OutStream(self, '\\'); break; - default: - self->OutStream(self, 'x'); - TrioWriteNumber(self, (trio_uintmax_t)ch, - FLAGS_UNSIGNED | FLAGS_NILPADDING, - 2, 2, BASE_HEX); - break; - } - } - else if (ch == CHAR_BACKSLASH) - { - self->OutStream(self, CHAR_BACKSLASH); - self->OutStream(self, CHAR_BACKSLASH); - } - else - { - self->OutStream(self, ch); - } - } - else - { - self->OutStream(self, ch); - } -} - -/************************************************************************* - * TrioWriteString - * - * Description: - * Output a string - */ -TRIO_PRIVATE void -TrioWriteString -TRIO_ARGS5((self, string, flags, width, precision), - trio_class_t *self, - TRIO_CONST char *string, - trio_flags_t flags, - int width, - int precision) -{ - int length; - int ch; - - assert(VALID(self)); - assert(VALID(self->OutStream)); - - if (string == NULL) - { - string = internalNullString; - length = sizeof(internalNullString) - 1; - /* Disable quoting for the null pointer */ - flags &= (~FLAGS_QUOTE); - width = 0; - } - else - { - length = trio_length(string); - } - if ((NO_PRECISION != precision) && - (precision < length)) - { - length = precision; - } - width -= length; - - if (flags & FLAGS_QUOTE) - self->OutStream(self, CHAR_QUOTE); - - if (! (flags & FLAGS_LEFTADJUST)) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } - - while (length-- > 0) - { - /* The ctype parameters must be an unsigned char (or EOF) */ - ch = (int)((unsigned char)(*string++)); - TrioWriteStringCharacter(self, ch, flags); - } - - if (flags & FLAGS_LEFTADJUST) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } - if (flags & FLAGS_QUOTE) - self->OutStream(self, CHAR_QUOTE); -} - -/************************************************************************* - * TrioWriteWideStringCharacter - * - * Description: - * Output a wide string as a multi-byte sequence - */ -#if TRIO_WIDECHAR -TRIO_PRIVATE int -TrioWriteWideStringCharacter -TRIO_ARGS4((self, wch, flags, width), - trio_class_t *self, - trio_wchar_t wch, - trio_flags_t flags, - int width) -{ - int size; - int i; - int ch; - char *string; - char buffer[MB_LEN_MAX + 1]; - - if (width == NO_WIDTH) - width = sizeof(buffer); - - size = wctomb(buffer, wch); - if ((size <= 0) || (size > width) || (buffer[0] == NIL)) - return 0; - - string = buffer; - i = size; - while ((width >= i) && (width-- > 0) && (i-- > 0)) - { - /* The ctype parameters must be an unsigned char (or EOF) */ - ch = (int)((unsigned char)(*string++)); - TrioWriteStringCharacter(self, ch, flags); - } - return size; -} -#endif /* TRIO_WIDECHAR */ - -/************************************************************************* - * TrioWriteWideString - * - * Description: - * Output a wide character string as a multi-byte string - */ -#if TRIO_WIDECHAR -TRIO_PRIVATE void -TrioWriteWideString -TRIO_ARGS5((self, wstring, flags, width, precision), - trio_class_t *self, - TRIO_CONST trio_wchar_t *wstring, - trio_flags_t flags, - int width, - int precision) -{ - int length; - int size; - - assert(VALID(self)); - assert(VALID(self->OutStream)); - -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - (void)mblen(NULL, 0); -#endif - - if (wstring == NULL) - { - TrioWriteString(self, NULL, flags, width, precision); - return; - } - - if (NO_PRECISION == precision) - { - length = INT_MAX; - } - else - { - length = precision; - width -= length; - } - - if (flags & FLAGS_QUOTE) - self->OutStream(self, CHAR_QUOTE); - - if (! (flags & FLAGS_LEFTADJUST)) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } - - while (length > 0) - { - size = TrioWriteWideStringCharacter(self, *wstring++, flags, length); - if (size == 0) - break; /* while */ - length -= size; - } - - if (flags & FLAGS_LEFTADJUST) - { - while (width-- > 0) - self->OutStream(self, CHAR_ADJUST); - } - if (flags & FLAGS_QUOTE) - self->OutStream(self, CHAR_QUOTE); -} -#endif /* TRIO_WIDECHAR */ - -/************************************************************************* - * TrioWriteDouble - * - * http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_211.htm - * - * "5.2.4.2.2 paragraph #4 - * - * The accuracy [...] is implementation defined, as is the accuracy - * of the conversion between floating-point internal representations - * and string representations performed by the library routine in - * " - */ -/* FIXME: handle all instances of constant long-double number (L) - * and *l() math functions. - */ -TRIO_PRIVATE void -TrioWriteDouble -TRIO_ARGS6((self, number, flags, width, precision, base), - trio_class_t *self, - trio_long_double_t number, - trio_flags_t flags, - int width, - int precision, - int base) -{ - trio_long_double_t integerNumber; - trio_long_double_t fractionNumber; - trio_long_double_t workNumber; - int integerDigits; - int fractionDigits; - int exponentDigits; - int baseDigits; - int integerThreshold; - int fractionThreshold; - int expectedWidth; - int exponent = 0; - unsigned int uExponent = 0; - int exponentBase; - trio_long_double_t dblBase; - trio_long_double_t dblIntegerBase; - trio_long_double_t dblFractionBase; - trio_long_double_t integerAdjust; - trio_long_double_t fractionAdjust; - BOOLEAN_T isNegative; - BOOLEAN_T isExponentNegative = FALSE; - BOOLEAN_T requireTwoDigitExponent; - BOOLEAN_T isHex; - TRIO_CONST char *digits; - char *groupingPointer; - int i; - int index; - BOOLEAN_T hasOnlyZeroes; - int zeroes = 0; - register int trailingZeroes; - BOOLEAN_T keepTrailingZeroes; - BOOLEAN_T keepDecimalPoint; - trio_long_double_t epsilon; - - assert(VALID(self)); - assert(VALID(self->OutStream)); - assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE)); - - /* Determine sign and look for special quantities */ - switch (trio_fpclassify_and_signbit(number, &isNegative)) - { - case TRIO_FP_NAN: - TrioWriteString(self, - (flags & FLAGS_UPPER) - ? NAN_UPPER - : NAN_LOWER, - flags, width, precision); - return; - - case TRIO_FP_INFINITE: - if (isNegative) - { - /* Negative infinity */ - TrioWriteString(self, - (flags & FLAGS_UPPER) - ? "-" INFINITE_UPPER - : "-" INFINITE_LOWER, - flags, width, precision); - return; - } - else - { - /* Positive infinity */ - TrioWriteString(self, - (flags & FLAGS_UPPER) - ? INFINITE_UPPER - : INFINITE_LOWER, - flags, width, precision); - return; - } - - default: - /* Finitude */ - break; - } - - /* Normal numbers */ - if (flags & FLAGS_LONGDOUBLE) - { - baseDigits = (base == 10) - ? LDBL_DIG - : (int)floor(LDBL_MANT_DIG / TrioLogarithmBase(base)); - epsilon = LDBL_EPSILON; - } - else if (flags & FLAGS_SHORT) - { - baseDigits = (base == BASE_DECIMAL) - ? FLT_DIG - : (int)floor(FLT_MANT_DIG / TrioLogarithmBase(base)); - epsilon = FLT_EPSILON; - } - else - { - baseDigits = (base == BASE_DECIMAL) - ? DBL_DIG - : (int)floor(DBL_MANT_DIG / TrioLogarithmBase(base)); - epsilon = DBL_EPSILON; - } - - digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower; - isHex = (base == BASE_HEX); - if (base == NO_BASE) - base = BASE_DECIMAL; - dblBase = (trio_long_double_t)base; - keepTrailingZeroes = !( (flags & FLAGS_ROUNDING) || - ( (flags & FLAGS_FLOAT_G) && - !(flags & FLAGS_ALTERNATIVE) ) ); - - if (flags & FLAGS_ROUNDING) - precision = baseDigits; - - if (precision == NO_PRECISION) - { - if (isHex) - { - keepTrailingZeroes = FALSE; - precision = FLT_MANT_DIG; - } - else - { - precision = FLT_DIG; - } - } - - if (isNegative) - number = -number; - - if (isHex) - flags |= FLAGS_FLOAT_E; - - if (flags & FLAGS_FLOAT_G) - { - if (precision == 0) - precision = 1; - - if ((number < 1.0E-4) || (number > powl(base, - (trio_long_double_t)precision))) - { - /* Use scientific notation */ - flags |= FLAGS_FLOAT_E; - } - else if (number < 1.0) - { - /* - * Use normal notation. If the integer part of the number is - * zero, then adjust the precision to include leading fractional - * zeros. - */ - workNumber = TrioLogarithm(number, base); - workNumber = TRIO_FABS(workNumber); - if (workNumber - floorl(workNumber) < 0.001) - workNumber--; - zeroes = (int)floorl(workNumber); - } - } - - if (flags & FLAGS_FLOAT_E) - { - /* Scale the number */ - workNumber = TrioLogarithm(number, base); - if (trio_isinf(workNumber) == -1) - { - exponent = 0; - /* Undo setting */ - if (flags & FLAGS_FLOAT_G) - flags &= ~FLAGS_FLOAT_E; - } - else - { - exponent = (int)floorl(workNumber); - number /= powl(dblBase, (trio_long_double_t)exponent); - isExponentNegative = (exponent < 0); - uExponent = (isExponentNegative) ? -exponent : exponent; - if (isHex) - uExponent *= 4; /* log16(2) */ - /* No thousand separators */ - flags &= ~FLAGS_QUOTE; - } - } - - integerNumber = floorl(number); - fractionNumber = number - integerNumber; - - /* - * Truncated number. - * - * Precision is number of significant digits for FLOAT_G - * and number of fractional digits for others. - */ - integerDigits = (integerNumber > epsilon) - ? 1 + (int)TrioLogarithm(integerNumber, base) - : 1; - fractionDigits = ((flags & FLAGS_FLOAT_G) && (zeroes == 0)) - ? precision - integerDigits - : zeroes + precision; - - dblFractionBase = TrioPower(base, fractionDigits); - - workNumber = number + 0.5 / dblFractionBase; - if (floorl(number) != floorl(workNumber)) - { - if (flags & FLAGS_FLOAT_E) - { - /* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */ - exponent++; - isExponentNegative = (exponent < 0); - uExponent = (isExponentNegative) ? -exponent : exponent; - if (isHex) - uExponent *= 4; /* log16(2) */ - workNumber = (number + 0.5 / dblFractionBase) / dblBase; - integerNumber = floorl(workNumber); - fractionNumber = workNumber - integerNumber; - } - else - { - /* Adjust if number was rounded up one digit (ie. 99 to 100) */ - integerNumber = floorl(number + 0.5); - fractionNumber = 0.0; - integerDigits = (integerNumber > epsilon) - ? 1 + (int)TrioLogarithm(integerNumber, base) - : 1; - } - } - - /* Estimate accuracy */ - integerAdjust = fractionAdjust = 0.5; - if (flags & FLAGS_ROUNDING) - { - if (integerDigits > baseDigits) - { - integerThreshold = baseDigits; - fractionDigits = 0; - dblFractionBase = 1.0; - fractionThreshold = 0; - precision = 0; /* Disable decimal-point */ - integerAdjust = TrioPower(base, integerDigits - integerThreshold - 1); - fractionAdjust = 0.0; - } - else - { - integerThreshold = integerDigits; - fractionThreshold = fractionDigits - integerThreshold; - fractionAdjust = 1.0; - } - } - else - { - integerThreshold = INT_MAX; - fractionThreshold = INT_MAX; - } - - /* - * Calculate expected width. - * sign + integer part + thousands separators + decimal point - * + fraction + exponent - */ - fractionAdjust /= dblFractionBase; - hasOnlyZeroes = (floorl((fractionNumber + fractionAdjust) * dblFractionBase) < epsilon); - keepDecimalPoint = ( (flags & FLAGS_ALTERNATIVE) || - !((precision == 0) || - (!keepTrailingZeroes && hasOnlyZeroes)) ); - if (flags & FLAGS_FLOAT_E) - { - exponentDigits = (uExponent == 0) - ? 1 - : (int)ceil(TrioLogarithm((double)(uExponent + 1), - (isHex) ? 10.0 : base)); - } - else - exponentDigits = 0; - requireTwoDigitExponent = ((base == BASE_DECIMAL) && (exponentDigits == 1)); - - expectedWidth = integerDigits + fractionDigits - + (keepDecimalPoint - ? internalDecimalPointLength - : 0) - + ((flags & FLAGS_QUOTE) - ? TrioCalcThousandSeparatorLength(integerDigits) - : 0); - if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE)) - expectedWidth += sizeof("-") - 1; - if (exponentDigits > 0) - expectedWidth += exponentDigits + - ((requireTwoDigitExponent ? sizeof("E+0") : sizeof("E+")) - 1); - if (isHex) - expectedWidth += sizeof("0X") - 1; - - /* Output prefixing */ - if (flags & FLAGS_NILPADDING) - { - /* Leading zeros must be after sign */ - if (isNegative) - self->OutStream(self, '-'); - else if (flags & FLAGS_SHOWSIGN) - self->OutStream(self, '+'); - else if (flags & FLAGS_SPACE) - self->OutStream(self, ' '); - if (isHex) - { - self->OutStream(self, '0'); - self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x'); - } - if (!(flags & FLAGS_LEFTADJUST)) - { - for (i = expectedWidth; i < width; i++) - { - self->OutStream(self, '0'); - } - } - } - else - { - /* Leading spaces must be before sign */ - if (!(flags & FLAGS_LEFTADJUST)) - { - for (i = expectedWidth; i < width; i++) - { - self->OutStream(self, CHAR_ADJUST); - } - } - if (isNegative) - self->OutStream(self, '-'); - else if (flags & FLAGS_SHOWSIGN) - self->OutStream(self, '+'); - else if (flags & FLAGS_SPACE) - self->OutStream(self, ' '); - if (isHex) - { - self->OutStream(self, '0'); - self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x'); - } - } - - /* Output the integer part and thousand separators */ - dblIntegerBase = 1.0 / TrioPower(base, integerDigits - 1); - for (i = 0; i < integerDigits; i++) - { - workNumber = floorl(((integerNumber + integerAdjust) * dblIntegerBase)); - if (i > integerThreshold) - { - /* Beyond accuracy */ - self->OutStream(self, digits[0]); - } - else - { - self->OutStream(self, digits[(int)fmodl(workNumber, dblBase)]); - } - dblIntegerBase *= dblBase; - - if (((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE) - && TrioFollowedBySeparator(integerDigits - i)) - { - for (groupingPointer = internalThousandSeparator; - *groupingPointer != NIL; - groupingPointer++) - { - self->OutStream(self, *groupingPointer); - } - } - } - - /* Insert decimal point and build the fraction part */ - trailingZeroes = 0; - - if (keepDecimalPoint) - { - if (internalDecimalPoint) - { - self->OutStream(self, internalDecimalPoint); - } - else - { - for (i = 0; i < internalDecimalPointLength; i++) - { - self->OutStream(self, internalDecimalPointString[i]); - } - } - } - - for (i = 0; i < fractionDigits; i++) - { - if ((integerDigits > integerThreshold) || (i > fractionThreshold)) - { - /* Beyond accuracy */ - trailingZeroes++; - } - else - { - fractionNumber *= dblBase; - fractionAdjust *= dblBase; - workNumber = floorl(fractionNumber + fractionAdjust); - fractionNumber -= workNumber; - index = (int)fmodl(workNumber, dblBase); - if (index == 0) - { - trailingZeroes++; - } - else - { - while (trailingZeroes > 0) - { - /* Not trailing zeroes after all */ - self->OutStream(self, digits[0]); - trailingZeroes--; - } - self->OutStream(self, digits[index]); - } - } - } - - if (keepTrailingZeroes) - { - while (trailingZeroes > 0) - { - self->OutStream(self, digits[0]); - trailingZeroes--; - } - } - - /* Output exponent */ - if (exponentDigits > 0) - { - self->OutStream(self, - isHex - ? ((flags & FLAGS_UPPER) ? 'P' : 'p') - : ((flags & FLAGS_UPPER) ? 'E' : 'e')); - self->OutStream(self, (isExponentNegative) ? '-' : '+'); - - /* The exponent must contain at least two digits */ - if (requireTwoDigitExponent) - self->OutStream(self, '0'); - - if (isHex) - base = 10.0; - exponentBase = (int)TrioPower(base, exponentDigits - 1); - for (i = 0; i < exponentDigits; i++) - { - self->OutStream(self, digits[(uExponent / exponentBase) % base]); - exponentBase /= base; - } - } - /* Output trailing spaces */ - if (flags & FLAGS_LEFTADJUST) - { - for (i = expectedWidth; i < width; i++) - { - self->OutStream(self, CHAR_ADJUST); - } - } -} - -/************************************************************************* - * TrioFormatProcess - * - * Description: - * This is the main engine for formatting output - */ -TRIO_PRIVATE int -TrioFormatProcess -TRIO_ARGS3((data, format, parameters), - trio_class_t *data, - TRIO_CONST char *format, - trio_parameter_t *parameters) -{ -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - int charlen; -#endif - int i; - TRIO_CONST char *string; - trio_pointer_t pointer; - trio_flags_t flags; - int width; - int precision; - int base; - int index; - - index = 0; - i = 0; -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - (void)mblen(NULL, 0); -#endif - - while (format[index]) - { -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - if (! isascii(format[index])) - { - charlen = mblen(&format[index], MB_LEN_MAX); - /* - * Only valid multibyte characters are handled here. Invalid - * multibyte characters (charlen == -1) are handled as normal - * characters. - */ - if (charlen != -1) - { - while (charlen-- > 0) - { - data->OutStream(data, format[index++]); - } - continue; /* while characters left in formatting string */ - } - } -#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */ - if (CHAR_IDENTIFIER == format[index]) - { - if (CHAR_IDENTIFIER == format[index + 1]) - { - data->OutStream(data, CHAR_IDENTIFIER); - index += 2; - } - else - { - /* Skip the parameter entries */ - while (parameters[i].type == FORMAT_PARAMETER) - i++; - - flags = parameters[i].flags; - - /* Find width */ - width = parameters[i].width; - if (flags & FLAGS_WIDTH_PARAMETER) - { - /* Get width from parameter list */ - width = (int)parameters[width].data.number.as_signed; - if (width < 0) - { - /* - * A negative width is the same as the - flag and - * a positive width. - */ - flags |= FLAGS_LEFTADJUST; - flags &= ~FLAGS_NILPADDING; - width = -width; - } - } - - /* Find precision */ - if (flags & FLAGS_PRECISION) - { - precision = parameters[i].precision; - if (flags & FLAGS_PRECISION_PARAMETER) - { - /* Get precision from parameter list */ - precision = (int)parameters[precision].data.number.as_signed; - if (precision < 0) - { - /* - * A negative precision is the same as no - * precision - */ - precision = NO_PRECISION; - } - } - } - else - { - precision = NO_PRECISION; - } - - /* Find base */ - base = parameters[i].base; - if (flags & FLAGS_BASE_PARAMETER) - { - /* Get base from parameter list */ - base = (int)parameters[base].data.number.as_signed; - } - - switch (parameters[i].type) - { - case FORMAT_CHAR: - if (flags & FLAGS_QUOTE) - data->OutStream(data, CHAR_QUOTE); - if (! (flags & FLAGS_LEFTADJUST)) - { - while (--width > 0) - data->OutStream(data, CHAR_ADJUST); - } -#if TRIO_WIDECHAR - if (flags & FLAGS_WIDECHAR) - { - TrioWriteWideStringCharacter(data, - (trio_wchar_t)parameters[i].data.number.as_signed, - flags, - NO_WIDTH); - } - else -#endif - { - TrioWriteStringCharacter(data, - (int)parameters[i].data.number.as_signed, - flags); - } - - if (flags & FLAGS_LEFTADJUST) - { - while(--width > 0) - data->OutStream(data, CHAR_ADJUST); - } - if (flags & FLAGS_QUOTE) - data->OutStream(data, CHAR_QUOTE); - - break; /* FORMAT_CHAR */ - - case FORMAT_INT: - TrioWriteNumber(data, - parameters[i].data.number.as_unsigned, - flags, - width, - precision, - base); - - break; /* FORMAT_INT */ - - case FORMAT_DOUBLE: - TrioWriteDouble(data, - parameters[i].data.longdoubleNumber, - flags, - width, - precision, - base); - break; /* FORMAT_DOUBLE */ - - case FORMAT_STRING: -#if TRIO_WIDECHAR - if (flags & FLAGS_WIDECHAR) - { - TrioWriteWideString(data, - parameters[i].data.wstring, - flags, - width, - precision); - } - else -#endif - { - TrioWriteString(data, - parameters[i].data.string, - flags, - width, - precision); - } - break; /* FORMAT_STRING */ - - case FORMAT_POINTER: - { - trio_reference_t reference; - - reference.data = data; - reference.parameter = ¶meters[i]; - trio_print_pointer(&reference, parameters[i].data.pointer); - } - break; /* FORMAT_POINTER */ - - case FORMAT_COUNT: - pointer = parameters[i].data.pointer; - if (NULL != pointer) - { - /* - * C99 paragraph 7.19.6.1.8 says "the number of - * characters written to the output stream so far by - * this call", which is data->committed - */ -#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER) - if (flags & FLAGS_SIZE_T) - *(size_t *)pointer = (size_t)data->committed; - else -#endif -#if defined(QUALIFIER_PTRDIFF_T) - if (flags & FLAGS_PTRDIFF_T) - *(ptrdiff_t *)pointer = (ptrdiff_t)data->committed; - else -#endif -#if defined(QUALIFIER_INTMAX_T) - if (flags & FLAGS_INTMAX_T) - *(trio_intmax_t *)pointer = (trio_intmax_t)data->committed; - else -#endif - if (flags & FLAGS_QUAD) - { - *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->committed; - } - else if (flags & FLAGS_LONG) - { - *(long int *)pointer = (long int)data->committed; - } - else if (flags & FLAGS_SHORT) - { - *(short int *)pointer = (short int)data->committed; - } - else - { - *(int *)pointer = (int)data->committed; - } - } - break; /* FORMAT_COUNT */ - - case FORMAT_PARAMETER: - break; /* FORMAT_PARAMETER */ - -#if defined(FORMAT_ERRNO) - case FORMAT_ERRNO: - string = trio_error(parameters[i].data.errorNumber); - if (string) - { - TrioWriteString(data, - string, - flags, - width, - precision); - } - else - { - data->OutStream(data, '#'); - TrioWriteNumber(data, - (trio_uintmax_t)parameters[i].data.errorNumber, - flags, - width, - precision, - BASE_DECIMAL); - } - break; /* FORMAT_ERRNO */ -#endif /* defined(FORMAT_ERRNO) */ - -#if defined(FORMAT_USER_DEFINED) - case FORMAT_USER_DEFINED: - { - trio_reference_t reference; - trio_userdef_t *def = NULL; - - if (parameters[i].user_name[0] == NIL) - { - /* Use handle */ - if ((i > 0) || - (parameters[i - 1].type == FORMAT_PARAMETER)) - def = (trio_userdef_t *)parameters[i - 1].data.pointer; - } - else - { - /* Look up namespace */ - def = TrioFindNamespace(parameters[i].user_name, NULL); - } - if (def) { - reference.data = data; - reference.parameter = ¶meters[i]; - def->callback(&reference); - } - } - break; -#endif /* defined(FORMAT_USER_DEFINED) */ - - default: - break; - } /* switch parameter type */ - - /* Prepare for next */ - index = parameters[i].indexAfterSpecifier; - i++; - } - } - else /* not identifier */ - { - data->OutStream(data, format[index++]); - } - } - return data->processed; -} - -/************************************************************************* - * TrioFormatRef - */ -TRIO_PRIVATE int -TrioFormatRef -TRIO_ARGS4((reference, format, arglist, argarray), - trio_reference_t *reference, - TRIO_CONST char *format, - TRIO_VA_LIST_PTR arglist, - trio_pointer_t *argarray) -{ - int status; - trio_parameter_t parameters[MAX_PARAMETERS]; - - status = TrioParse(TYPE_PRINT, format, parameters, arglist, argarray); - if (status < 0) - return status; - - status = TrioFormatProcess(reference->data, format, parameters); - if (reference->data->error != 0) - { - status = reference->data->error; - } - return status; -} - -/************************************************************************* - * TrioFormat - */ -TRIO_PRIVATE int -TrioFormat -TRIO_ARGS6((destination, destinationSize, OutStream, format, arglist, argarray), - trio_pointer_t destination, - size_t destinationSize, - void (*OutStream) TRIO_PROTO((trio_class_t *, int)), - TRIO_CONST char *format, - TRIO_VA_LIST_PTR arglist, - trio_pointer_t *argarray) -{ - int status; - trio_class_t data; - trio_parameter_t parameters[MAX_PARAMETERS]; - - assert(VALID(OutStream)); - assert(VALID(format)); - - memset(&data, 0, sizeof(data)); - data.OutStream = OutStream; - data.location = destination; - data.max = destinationSize; - data.error = 0; - -#if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -#endif - - status = TrioParse(TYPE_PRINT, format, parameters, arglist, argarray); - if (status < 0) - return status; - - status = TrioFormatProcess(&data, format, parameters); - if (data.error != 0) - { - status = data.error; - } - return status; -} - -/************************************************************************* - * TrioOutStreamFile - */ -TRIO_PRIVATE void -TrioOutStreamFile -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - FILE *file; - - assert(VALID(self)); - assert(VALID(self->location)); - - file = (FILE *)self->location; - self->processed++; - if (fputc(output, file) == EOF) - { - self->error = TRIO_ERROR_RETURN(TRIO_EOF, 0); - } - else - { - self->committed++; - } -} - -/************************************************************************* - * TrioOutStreamFileDescriptor - */ -TRIO_PRIVATE void -TrioOutStreamFileDescriptor -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - int fd; - char ch; - - assert(VALID(self)); - - fd = *((int *)self->location); - ch = (char)output; - self->processed++; - if (write(fd, &ch, sizeof(char)) == -1) - { - self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0); - } - else - { - self->committed++; - } -} - -/************************************************************************* - * TrioOutStreamCustom - */ -TRIO_PRIVATE void -TrioOutStreamCustom -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - int status; - trio_custom_t *data; - - assert(VALID(self)); - assert(VALID(self->location)); - - data = (trio_custom_t *)self->location; - if (data->stream.out) - { - status = (data->stream.out)(data->closure, output); - if (status >= 0) - { - self->committed++; - } - else - { - if (self->error == 0) - { - self->error = TRIO_ERROR_RETURN(TRIO_ECUSTOM, -status); - } - } - } - self->processed++; -} - -/************************************************************************* - * TrioOutStreamString - */ -TRIO_PRIVATE void -TrioOutStreamString -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - char **buffer; - - assert(VALID(self)); - assert(VALID(self->location)); - - buffer = (char **)self->location; - **buffer = (char)output; - (*buffer)++; - self->processed++; - self->committed++; -} - -/************************************************************************* - * TrioOutStreamStringMax - */ -TRIO_PRIVATE void -TrioOutStreamStringMax -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - char **buffer; - - assert(VALID(self)); - assert(VALID(self->location)); - - buffer = (char **)self->location; - - if (self->processed < self->max) - { - **buffer = (char)output; - (*buffer)++; - self->committed++; - } - self->processed++; -} - -/************************************************************************* - * TrioOutStreamStringDynamic - */ -TRIO_PRIVATE void -TrioOutStreamStringDynamic -TRIO_ARGS2((self, output), - trio_class_t *self, - int output) -{ - assert(VALID(self)); - assert(VALID(self->location)); - - if (self->error == 0) - { - trio_xstring_append_char((trio_string_t *)self->location, - (char)output); - self->committed++; - } - /* The processed variable must always be increased */ - self->processed++; -} - -/************************************************************************* - * - * Formatted printing functions - * - ************************************************************************/ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_printf.h" -#endif -/** @addtogroup Printf - @{ -*/ - -/************************************************************************* - * printf - */ - -/** - Print to standard output stream. - - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_printf -TRIO_VARGS2((format, va_alist), - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(stdout, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -/** - Print to standard output stream. - - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_vprintf -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(format)); - - return TrioFormat(stdout, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL); -} - -/** - Print to standard output stream. - - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_printfv -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - trio_pointer_t * args) -{ - assert(VALID(format)); - - return TrioFormat(stdout, 0, TrioOutStreamFile, format, NULL, args); -} - -/************************************************************************* - * fprintf - */ - -/** - Print to file. - - @param file File pointer. - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_fprintf -TRIO_VARGS3((file, format, va_alist), - FILE *file, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(file)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(file, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -/** - Print to file. - - @param file File pointer. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_vfprintf -TRIO_ARGS3((file, format, args), - FILE *file, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(file)); - assert(VALID(format)); - - return TrioFormat(file, 0, TrioOutStreamFile, format, TRIO_VA_LIST_ADDR(args), NULL); -} - -/** - Print to file. - - @param file File pointer. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_fprintfv -TRIO_ARGS3((file, format, args), - FILE *file, - TRIO_CONST char *format, - trio_pointer_t * args) -{ - assert(VALID(file)); - assert(VALID(format)); - - return TrioFormat(file, 0, TrioOutStreamFile, format, NULL, args); -} - -/************************************************************************* - * dprintf - */ - -/** - Print to file descriptor. - - @param fd File descriptor. - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_dprintf -TRIO_VARGS3((fd, format, va_alist), - int fd, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -/** - Print to file descriptor. - - @param fd File descriptor. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_vdprintf -TRIO_ARGS3((fd, format, args), - int fd, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(format)); - - return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, TRIO_VA_LIST_ADDR(args), NULL); -} - -/** - Print to file descriptor. - - @param fd File descriptor. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_dprintfv -TRIO_ARGS3((fd, format, args), - int fd, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - assert(VALID(format)); - - return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, NULL, args); -} - -/************************************************************************* - * cprintf - */ -TRIO_PUBLIC int -trio_cprintf -TRIO_VARGS4((stream, closure, format, va_alist), - trio_outstream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - data.stream.out = stream; - data.closure = closure; - status = TrioFormat(&data, 0, TrioOutStreamCustom, format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -TRIO_PUBLIC int -trio_vcprintf -TRIO_ARGS4((stream, closure, format, args), - trio_outstream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - va_list args) -{ - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - data.stream.out = stream; - data.closure = closure; - return TrioFormat(&data, 0, TrioOutStreamCustom, format, TRIO_VA_LIST_ADDR(args), NULL); -} - -TRIO_PUBLIC int -trio_cprintfv -TRIO_ARGS4((stream, closure, format, args), - trio_outstream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - void **args) -{ - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - data.stream.out = stream; - data.closure = closure; - return TrioFormat(&data, 0, TrioOutStreamCustom, format, NULL, args); -} - -/************************************************************************* - * sprintf - */ - -/** - Print to string. - - @param buffer Output string. - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_sprintf -TRIO_VARGS3((buffer, format, va_alist), - char *buffer, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(buffer)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(&buffer, 0, TrioOutStreamString, format, TRIO_VA_LIST_ADDR(args), NULL); - *buffer = NIL; /* Terminate with NIL character */ - TRIO_VA_END(args); - return status; -} - -/** - Print to string. - - @param buffer Output string. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_vsprintf -TRIO_ARGS3((buffer, format, args), - char *buffer, - TRIO_CONST char *format, - va_list args) -{ - int status; - - assert(VALID(buffer)); - assert(VALID(format)); - - status = TrioFormat(&buffer, 0, TrioOutStreamString, format, TRIO_VA_LIST_ADDR(args), NULL); - *buffer = NIL; - return status; -} - -/** - Print to string. - - @param buffer Output string. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_sprintfv -TRIO_ARGS3((buffer, format, args), - char *buffer, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - int status; - - assert(VALID(buffer)); - assert(VALID(format)); - - status = TrioFormat(&buffer, 0, TrioOutStreamString, format, NULL, args); - *buffer = NIL; - return status; -} - -/************************************************************************* - * snprintf - */ - -/** - Print at most @p max characters to string. - - @param buffer Output string. - @param max Maximum number of characters to print. - @param format Formatting string. - @param ... Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_snprintf -TRIO_VARGS4((buffer, max, format, va_alist), - char *buffer, - size_t max, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(buffer)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, - TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL); - if (max > 0) - *buffer = NIL; - TRIO_VA_END(args); - return status; -} - -/** - Print at most @p max characters to string. - - @param buffer Output string. - @param max Maximum number of characters to print. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_vsnprintf -TRIO_ARGS4((buffer, max, format, args), - char *buffer, - size_t max, - TRIO_CONST char *format, - va_list args) -{ - int status; - - assert(VALID(buffer)); - assert(VALID(format)); - - status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, - TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL); - if (max > 0) - *buffer = NIL; - return status; -} - -/** - Print at most @p max characters to string. - - @param buffer Output string. - @param max Maximum number of characters to print. - @param format Formatting string. - @param args Arguments. - @return Number of printed characters. - */ -TRIO_PUBLIC int -trio_snprintfv -TRIO_ARGS4((buffer, max, format, args), - char *buffer, - size_t max, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - int status; - - assert(VALID(buffer)); - assert(VALID(format)); - - status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, - TrioOutStreamStringMax, format, NULL, args); - if (max > 0) - *buffer = NIL; - return status; -} - -/************************************************************************* - * snprintfcat - * Appends the new string to the buffer string overwriting the '\0' - * character at the end of buffer. - */ -TRIO_PUBLIC int -trio_snprintfcat -TRIO_VARGS4((buffer, max, format, va_alist), - char *buffer, - size_t max, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - size_t buf_len; - - TRIO_VA_START(args, format); - - assert(VALID(buffer)); - assert(VALID(format)); - - buf_len = trio_length(buffer); - buffer = &buffer[buf_len]; - - status = TrioFormat(&buffer, max - 1 - buf_len, - TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - *buffer = NIL; - return status; -} - -TRIO_PUBLIC int -trio_vsnprintfcat -TRIO_ARGS4((buffer, max, format, args), - char *buffer, - size_t max, - TRIO_CONST char *format, - va_list args) -{ - int status; - size_t buf_len; - - assert(VALID(buffer)); - assert(VALID(format)); - - buf_len = trio_length(buffer); - buffer = &buffer[buf_len]; - status = TrioFormat(&buffer, max - 1 - buf_len, - TrioOutStreamStringMax, format, TRIO_VA_LIST_ADDR(args), NULL); - *buffer = NIL; - return status; -} - -/************************************************************************* - * trio_aprintf - */ - -/* Deprecated */ -TRIO_PUBLIC char * -trio_aprintf -TRIO_VARGS2((format, va_alist), - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - va_list args; - trio_string_t *info; - char *result = NULL; - - assert(VALID(format)); - - info = trio_xstring_duplicate(""); - if (info) - { - TRIO_VA_START(args, format); - (void)TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - - trio_string_terminate(info); - result = trio_string_extract(info); - trio_string_destroy(info); - } - return result; -} - -/* Deprecated */ -TRIO_PUBLIC char * -trio_vaprintf -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - va_list args) -{ - trio_string_t *info; - char *result = NULL; - - assert(VALID(format)); - - info = trio_xstring_duplicate(""); - if (info) - { - (void)TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, TRIO_VA_LIST_ADDR(args), NULL); - trio_string_terminate(info); - result = trio_string_extract(info); - trio_string_destroy(info); - } - return result; -} - -TRIO_PUBLIC int -trio_asprintf -TRIO_VARGS3((result, format, va_alist), - char **result, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - va_list args; - int status; - trio_string_t *info; - - assert(VALID(format)); - - *result = NULL; - - info = trio_xstring_duplicate(""); - if (info == NULL) - { - status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0); - } - else - { - TRIO_VA_START(args, format); - status = TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - if (status >= 0) - { - trio_string_terminate(info); - *result = trio_string_extract(info); - } - trio_string_destroy(info); - } - return status; -} - -TRIO_PUBLIC int -trio_vasprintf -TRIO_ARGS3((result, format, args), - char **result, - TRIO_CONST char *format, - va_list args) -{ - int status; - trio_string_t *info; - - assert(VALID(format)); - - *result = NULL; - - info = trio_xstring_duplicate(""); - if (info == NULL) - { - status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0); - } - else - { - status = TrioFormat(info, 0, TrioOutStreamStringDynamic, - format, TRIO_VA_LIST_ADDR(args), NULL); - if (status >= 0) - { - trio_string_terminate(info); - *result = trio_string_extract(info); - } - trio_string_destroy(info); - } - return status; -} - -/** @} End of Printf documentation module */ - -/************************************************************************* - * - * CALLBACK - * - ************************************************************************/ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_register.h" -#endif -/** - @addtogroup UserDefined - @{ -*/ - -#if TRIO_EXTENSION - -/************************************************************************* - * trio_register - */ - -/** - Register new user-defined specifier. - - @param callback - @param name - @return Handle. - */ -TRIO_PUBLIC trio_pointer_t -trio_register -TRIO_ARGS2((callback, name), - trio_callback_t callback, - TRIO_CONST char *name) -{ - trio_userdef_t *def; - trio_userdef_t *prev = NULL; - - if (callback == NULL) - return NULL; - - if (name) - { - /* Handle built-in namespaces */ - if (name[0] == ':') - { - if (trio_equal(name, ":enter")) - { - internalEnterCriticalRegion = callback; - } - else if (trio_equal(name, ":leave")) - { - internalLeaveCriticalRegion = callback; - } - return NULL; - } - - /* Bail out if namespace is too long */ - if (trio_length(name) >= MAX_USER_NAME) - return NULL; - - /* Bail out if namespace already is registered */ - def = TrioFindNamespace(name, &prev); - if (def) - return NULL; - } - - def = (trio_userdef_t *)TRIO_MALLOC(sizeof(trio_userdef_t)); - if (def) - { - if (internalEnterCriticalRegion) - (void)internalEnterCriticalRegion(NULL); - - if (name) - { - /* Link into internal list */ - if (prev == NULL) - internalUserDef = def; - else - prev->next = def; - } - /* Initialize */ - def->callback = callback; - def->name = (name == NULL) - ? NULL - : trio_duplicate(name); - def->next = NULL; - - if (internalLeaveCriticalRegion) - (void)internalLeaveCriticalRegion(NULL); - } - return (trio_pointer_t)def; -} - -/** - Unregister an existing user-defined specifier. - - @param handle - */ -void -trio_unregister -TRIO_ARGS1((handle), - trio_pointer_t handle) -{ - trio_userdef_t *self = (trio_userdef_t *)handle; - trio_userdef_t *def; - trio_userdef_t *prev = NULL; - - assert(VALID(self)); - - if (self->name) - { - def = TrioFindNamespace(self->name, &prev); - if (def) - { - if (internalEnterCriticalRegion) - (void)internalEnterCriticalRegion(NULL); - - if (prev == NULL) - internalUserDef = NULL; - else - prev->next = def->next; - - if (internalLeaveCriticalRegion) - (void)internalLeaveCriticalRegion(NULL); - } - trio_destroy(self->name); - } - TRIO_FREE(self); -} - -/************************************************************************* - * trio_get_format [public] - */ -TRIO_CONST char * -trio_get_format -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ -#if defined(FORMAT_USER_DEFINED) - assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED); -#endif - - return (((trio_reference_t *)ref)->parameter->user_data); -} - -/************************************************************************* - * trio_get_argument [public] - */ -trio_pointer_t -trio_get_argument -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ -#if defined(FORMAT_USER_DEFINED) - assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED); -#endif - - return ((trio_reference_t *)ref)->parameter->data.pointer; -} - -/************************************************************************* - * trio_get_width / trio_set_width [public] - */ -int -trio_get_width -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return ((trio_reference_t *)ref)->parameter->width; -} - -void -trio_set_width -TRIO_ARGS2((ref, width), - trio_pointer_t ref, - int width) -{ - ((trio_reference_t *)ref)->parameter->width = width; -} - -/************************************************************************* - * trio_get_precision / trio_set_precision [public] - */ -int -trio_get_precision -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->precision); -} - -void -trio_set_precision -TRIO_ARGS2((ref, precision), - trio_pointer_t ref, - int precision) -{ - ((trio_reference_t *)ref)->parameter->precision = precision; -} - -/************************************************************************* - * trio_get_base / trio_set_base [public] - */ -int -trio_get_base -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->base); -} - -void -trio_set_base -TRIO_ARGS2((ref, base), - trio_pointer_t ref, - int base) -{ - ((trio_reference_t *)ref)->parameter->base = base; -} - -/************************************************************************* - * trio_get_long / trio_set_long [public] - */ -int -trio_get_long -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONG) - ? TRUE - : FALSE; -} - -void -trio_set_long -TRIO_ARGS2((ref, is_long), - trio_pointer_t ref, - int is_long) -{ - if (is_long) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONG; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONG; -} - -/************************************************************************* - * trio_get_longlong / trio_set_longlong [public] - */ -int -trio_get_longlong -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUAD) - ? TRUE - : FALSE; -} - -void -trio_set_longlong -TRIO_ARGS2((ref, is_longlong), - trio_pointer_t ref, - int is_longlong) -{ - if (is_longlong) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUAD; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUAD; -} - -/************************************************************************* - * trio_get_longdouble / trio_set_longdouble [public] - */ -int -trio_get_longdouble -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONGDOUBLE) - ? TRUE - : FALSE; -} - -void -trio_set_longdouble -TRIO_ARGS2((ref, is_longdouble), - trio_pointer_t ref, - int is_longdouble) -{ - if (is_longdouble) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONGDOUBLE; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONGDOUBLE; -} - -/************************************************************************* - * trio_get_short / trio_set_short [public] - */ -int -trio_get_short -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORT) - ? TRUE - : FALSE; -} - -void -trio_set_short -TRIO_ARGS2((ref, is_short), - trio_pointer_t ref, - int is_short) -{ - if (is_short) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORT; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORT; -} - -/************************************************************************* - * trio_get_shortshort / trio_set_shortshort [public] - */ -int -trio_get_shortshort -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORTSHORT) - ? TRUE - : FALSE; -} - -void -trio_set_shortshort -TRIO_ARGS2((ref, is_shortshort), - trio_pointer_t ref, - int is_shortshort) -{ - if (is_shortshort) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORTSHORT; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORTSHORT; -} - -/************************************************************************* - * trio_get_alternative / trio_set_alternative [public] - */ -int -trio_get_alternative -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_ALTERNATIVE) - ? TRUE - : FALSE; -} - -void -trio_set_alternative -TRIO_ARGS2((ref, is_alternative), - trio_pointer_t ref, - int is_alternative) -{ - if (is_alternative) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_ALTERNATIVE; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_ALTERNATIVE; -} - -/************************************************************************* - * trio_get_alignment / trio_set_alignment [public] - */ -int -trio_get_alignment -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LEFTADJUST) - ? TRUE - : FALSE; -} - -void -trio_set_alignment -TRIO_ARGS2((ref, is_leftaligned), - trio_pointer_t ref, - int is_leftaligned) -{ - if (is_leftaligned) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LEFTADJUST; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LEFTADJUST; -} - -/************************************************************************* - * trio_get_spacing /trio_set_spacing [public] - */ -int -trio_get_spacing -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SPACE) - ? TRUE - : FALSE; -} - -void -trio_set_spacing -TRIO_ARGS2((ref, is_space), - trio_pointer_t ref, - int is_space) -{ - if (is_space) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SPACE; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SPACE; -} - -/************************************************************************* - * trio_get_sign / trio_set_sign [public] - */ -int -trio_get_sign -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHOWSIGN) - ? TRUE - : FALSE; -} - -void -trio_set_sign -TRIO_ARGS2((ref, is_sign), - trio_pointer_t ref, - int is_sign) -{ - if (is_sign) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHOWSIGN; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHOWSIGN; -} - -/************************************************************************* - * trio_get_padding / trio_set_padding [public] - */ -int -trio_get_padding -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_NILPADDING) - ? TRUE - : FALSE; -} - -void -trio_set_padding -TRIO_ARGS2((ref, is_padding), - trio_pointer_t ref, - int is_padding) -{ - if (is_padding) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_NILPADDING; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_NILPADDING; -} - -/************************************************************************* - * trio_get_quote / trio_set_quote [public] - */ -int -trio_get_quote -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUOTE) - ? TRUE - : FALSE; -} - -void -trio_set_quote -TRIO_ARGS2((ref, is_quote), - trio_pointer_t ref, - int is_quote) -{ - if (is_quote) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUOTE; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUOTE; -} - -/************************************************************************* - * trio_get_upper / trio_set_upper [public] - */ -int -trio_get_upper -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_UPPER) - ? TRUE - : FALSE; -} - -void -trio_set_upper -TRIO_ARGS2((ref, is_upper), - trio_pointer_t ref, - int is_upper) -{ - if (is_upper) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_UPPER; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_UPPER; -} - -/************************************************************************* - * trio_get_largest / trio_set_largest [public] - */ -#if TRIO_C99 -int -trio_get_largest -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_INTMAX_T) - ? TRUE - : FALSE; -} - -void -trio_set_largest -TRIO_ARGS2((ref, is_largest), - trio_pointer_t ref, - int is_largest) -{ - if (is_largest) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_INTMAX_T; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_INTMAX_T; -} -#endif - -/************************************************************************* - * trio_get_ptrdiff / trio_set_ptrdiff [public] - */ -int -trio_get_ptrdiff -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_PTRDIFF_T) - ? TRUE - : FALSE; -} - -void -trio_set_ptrdiff -TRIO_ARGS2((ref, is_ptrdiff), - trio_pointer_t ref, - int is_ptrdiff) -{ - if (is_ptrdiff) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_PTRDIFF_T; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_PTRDIFF_T; -} - -/************************************************************************* - * trio_get_size / trio_set_size [public] - */ -#if TRIO_C99 -int -trio_get_size -TRIO_ARGS1((ref), - trio_pointer_t ref) -{ - return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SIZE_T) - ? TRUE - : FALSE; -} - -void -trio_set_size -TRIO_ARGS2((ref, is_size), - trio_pointer_t ref, - int is_size) -{ - if (is_size) - ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SIZE_T; - else - ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SIZE_T; -} -#endif - -/************************************************************************* - * trio_print_int [public] - */ -void -trio_print_int -TRIO_ARGS2((ref, number), - trio_pointer_t ref, - int number) -{ - trio_reference_t *self = (trio_reference_t *)ref; - - TrioWriteNumber(self->data, - (trio_uintmax_t)number, - self->parameter->flags, - self->parameter->width, - self->parameter->precision, - self->parameter->base); -} - -/************************************************************************* - * trio_print_uint [public] - */ -void -trio_print_uint -TRIO_ARGS2((ref, number), - trio_pointer_t ref, - unsigned int number) -{ - trio_reference_t *self = (trio_reference_t *)ref; - - TrioWriteNumber(self->data, - (trio_uintmax_t)number, - self->parameter->flags | FLAGS_UNSIGNED, - self->parameter->width, - self->parameter->precision, - self->parameter->base); -} - -/************************************************************************* - * trio_print_double [public] - */ -void -trio_print_double -TRIO_ARGS2((ref, number), - trio_pointer_t ref, - double number) -{ - trio_reference_t *self = (trio_reference_t *)ref; - - TrioWriteDouble(self->data, - number, - self->parameter->flags, - self->parameter->width, - self->parameter->precision, - self->parameter->base); -} - -/************************************************************************* - * trio_print_string [public] - */ -void -trio_print_string -TRIO_ARGS2((ref, string), - trio_pointer_t ref, - char *string) -{ - trio_reference_t *self = (trio_reference_t *)ref; - - TrioWriteString(self->data, - string, - self->parameter->flags, - self->parameter->width, - self->parameter->precision); -} - -/************************************************************************* - * trio_print_ref [public] - */ -int -trio_print_ref -TRIO_VARGS3((ref, format, va_alist), - trio_pointer_t ref, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list arglist; - - assert(VALID(format)); - - TRIO_VA_START(arglist, format); - status = TrioFormatRef((trio_reference_t *)ref, format, TRIO_VA_LIST_ADDR(arglist), NULL); - TRIO_VA_END(arglist); - return status; -} - -/************************************************************************* - * trio_vprint_ref [public] - */ -int -trio_vprint_ref -TRIO_ARGS3((ref, format, arglist), - trio_pointer_t ref, - TRIO_CONST char *format, - va_list arglist) -{ - assert(VALID(format)); - - return TrioFormatRef((trio_reference_t *)ref, format, TRIO_VA_LIST_ADDR(arglist), NULL); -} - -/************************************************************************* - * trio_printv_ref [public] - */ -int -trio_printv_ref -TRIO_ARGS3((ref, format, argarray), - trio_pointer_t ref, - TRIO_CONST char *format, - trio_pointer_t *argarray) -{ - assert(VALID(format)); - - return TrioFormatRef((trio_reference_t *)ref, format, NULL, argarray); -} - -#endif /* TRIO_EXTENSION */ - -/************************************************************************* - * trio_print_pointer [public] - */ -void -trio_print_pointer -TRIO_ARGS2((ref, pointer), - trio_pointer_t ref, - trio_pointer_t pointer) -{ - trio_reference_t *self = (trio_reference_t *)ref; - trio_flags_t flags; - trio_uintmax_t number; - - if (NULL == pointer) - { - TRIO_CONST char *string = internalNullString; - while (*string) - self->data->OutStream(self->data, *string++); - } - else - { - /* - * The subtraction of the null pointer is a workaround - * to avoid a compiler warning. The performance overhead - * is negligible (and likely to be removed by an - * optimizing compiler). The (char *) casting is done - * to please ANSI C++. - */ - number = (trio_uintmax_t)((char *)pointer - (char *)0); - /* Shrink to size of pointer */ - number &= (trio_uintmax_t)-1; - flags = self->parameter->flags; - flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | - FLAGS_NILPADDING); - TrioWriteNumber(self->data, - number, - flags, - POINTER_WIDTH, - NO_PRECISION, - BASE_HEX); - } -} - -/** @} End of UserDefined documentation module */ - -/************************************************************************* - * - * LOCALES - * - ************************************************************************/ - -/************************************************************************* - * trio_locale_set_decimal_point - * - * Decimal point can only be one character. The input argument is a - * string to enable multibyte characters. At most MB_LEN_MAX characters - * will be used. - */ -TRIO_PUBLIC void -trio_locale_set_decimal_point -TRIO_ARGS1((decimalPoint), - char *decimalPoint) -{ -#if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -#endif - internalDecimalPointLength = trio_length(decimalPoint); - if (internalDecimalPointLength == 1) - { - internalDecimalPoint = *decimalPoint; - } - else - { - internalDecimalPoint = NIL; - trio_copy_max(internalDecimalPointString, - sizeof(internalDecimalPointString), - decimalPoint); - } -} - -/************************************************************************* - * trio_locale_set_thousand_separator - * - * See trio_locale_set_decimal_point - */ -TRIO_PUBLIC void -trio_locale_set_thousand_separator -TRIO_ARGS1((thousandSeparator), - char *thousandSeparator) -{ -#if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -#endif - trio_copy_max(internalThousandSeparator, - sizeof(internalThousandSeparator), - thousandSeparator); - internalThousandSeparatorLength = trio_length(internalThousandSeparator); -} - -/************************************************************************* - * trio_locale_set_grouping - * - * Array of bytes. Reversed order. - * - * CHAR_MAX : No further grouping - * 0 : Repeat last group for the remaining digits (not necessary - * as C strings are zero-terminated) - * n : Set current group to n - * - * Same order as the grouping attribute in LC_NUMERIC. - */ -TRIO_PUBLIC void -trio_locale_set_grouping -TRIO_ARGS1((grouping), - char *grouping) -{ -#if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -#endif - trio_copy_max(internalGrouping, - sizeof(internalGrouping), - grouping); -} - - -/************************************************************************* - * - * SCANNING - * - ************************************************************************/ - -/************************************************************************* - * TrioSkipWhitespaces - */ -TRIO_PRIVATE int -TrioSkipWhitespaces -TRIO_ARGS1((self), - trio_class_t *self) -{ - int ch; - - ch = self->current; - while (isspace(ch)) - { - self->InStream(self, &ch); - } - return ch; -} - -/************************************************************************* - * TrioGetCollation - */ -#if TRIO_EXTENSION -TRIO_PRIVATE void -TrioGetCollation(TRIO_NOARGS) -{ - int i; - int j; - int k; - char first[2]; - char second[2]; - - /* This is computationally expensive */ - first[1] = NIL; - second[1] = NIL; - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - { - k = 0; - first[0] = (char)i; - for (j = 0; j < MAX_CHARACTER_CLASS; j++) - { - second[0] = (char)j; - if (trio_equal_locale(first, second)) - internalCollationArray[i][k++] = (char)j; - } - internalCollationArray[i][k] = NIL; - } -} -#endif - -/************************************************************************* - * TrioGetCharacterClass - * - * FIXME: - * multibyte - */ -TRIO_PRIVATE int -TrioGetCharacterClass -TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass), - TRIO_CONST char *format, - int *indexPointer, - trio_flags_t *flagsPointer, - int *characterclass) -{ - int index = *indexPointer; - int i; - char ch; - char range_begin; - char range_end; - - *flagsPointer &= ~FLAGS_EXCLUDE; - - if (format[index] == QUALIFIER_CIRCUMFLEX) - { - *flagsPointer |= FLAGS_EXCLUDE; - index++; - } - /* - * If the ungroup character is at the beginning of the scanlist, - * it will be part of the class, and a second ungroup character - * must follow to end the group. - */ - if (format[index] == SPECIFIER_UNGROUP) - { - characterclass[(int)SPECIFIER_UNGROUP]++; - index++; - } - /* - * Minus is used to specify ranges. To include minus in the class, - * it must be at the beginning of the list - */ - if (format[index] == QUALIFIER_MINUS) - { - characterclass[(int)QUALIFIER_MINUS]++; - index++; - } - /* Collect characters */ - for (ch = format[index]; - (ch != SPECIFIER_UNGROUP) && (ch != NIL); - ch = format[++index]) - { - switch (ch) - { - case QUALIFIER_MINUS: /* Scanlist ranges */ - - /* - * Both C99 and UNIX98 describes ranges as implementation- - * defined. - * - * We support the following behaviour (although this may - * change as we become wiser) - * - only increasing ranges, ie. [a-b] but not [b-a] - * - transitive ranges, ie. [a-b-c] == [a-c] - * - trailing minus, ie. [a-] is interpreted as an 'a' - * and a '-' - * - duplicates (although we can easily convert these - * into errors) - */ - range_begin = format[index - 1]; - range_end = format[++index]; - if (range_end == SPECIFIER_UNGROUP) - { - /* Trailing minus is included */ - characterclass[(int)ch]++; - ch = range_end; - break; /* for */ - } - if (range_end == NIL) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - if (range_begin > range_end) - return TRIO_ERROR_RETURN(TRIO_ERANGE, index); - - for (i = (int)range_begin; i <= (int)range_end; i++) - characterclass[i]++; - - ch = range_end; - break; - -#if TRIO_EXTENSION - - case SPECIFIER_GROUP: - - switch (format[index + 1]) - { - case QUALIFIER_DOT: /* Collating symbol */ - /* - * FIXME: This will be easier to implement when multibyte - * characters have been implemented. Until now, we ignore - * this feature. - */ - for (i = index + 2; ; i++) - { - if (format[i] == NIL) - /* Error in syntax */ - return -1; - else if (format[i] == QUALIFIER_DOT) - break; /* for */ - } - if (format[++i] != SPECIFIER_UNGROUP) - return -1; - - index = i; - break; - - case QUALIFIER_EQUAL: /* Equivalence class expressions */ - { - unsigned int j; - unsigned int k; - - if (internalCollationUnconverted) - { - /* Lazy evaluation of collation array */ - TrioGetCollation(); - internalCollationUnconverted = FALSE; - } - for (i = index + 2; ; i++) - { - if (format[i] == NIL) - /* Error in syntax */ - return -1; - else if (format[i] == QUALIFIER_EQUAL) - break; /* for */ - else - { - /* Mark any equivalent character */ - k = (unsigned int)format[i]; - for (j = 0; internalCollationArray[k][j] != NIL; j++) - characterclass[(int)internalCollationArray[k][j]]++; - } - } - if (format[++i] != SPECIFIER_UNGROUP) - return -1; - - index = i; - } - break; - - case QUALIFIER_COLON: /* Character class expressions */ - - if (trio_equal_max(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isalnum(i)) - characterclass[i]++; - index += sizeof(CLASS_ALNUM) - 1; - } - else if (trio_equal_max(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isalpha(i)) - characterclass[i]++; - index += sizeof(CLASS_ALPHA) - 1; - } - else if (trio_equal_max(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (iscntrl(i)) - characterclass[i]++; - index += sizeof(CLASS_CNTRL) - 1; - } - else if (trio_equal_max(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isdigit(i)) - characterclass[i]++; - index += sizeof(CLASS_DIGIT) - 1; - } - else if (trio_equal_max(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isgraph(i)) - characterclass[i]++; - index += sizeof(CLASS_GRAPH) - 1; - } - else if (trio_equal_max(CLASS_LOWER, sizeof(CLASS_LOWER) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (islower(i)) - characterclass[i]++; - index += sizeof(CLASS_LOWER) - 1; - } - else if (trio_equal_max(CLASS_PRINT, sizeof(CLASS_PRINT) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isprint(i)) - characterclass[i]++; - index += sizeof(CLASS_PRINT) - 1; - } - else if (trio_equal_max(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (ispunct(i)) - characterclass[i]++; - index += sizeof(CLASS_PUNCT) - 1; - } - else if (trio_equal_max(CLASS_SPACE, sizeof(CLASS_SPACE) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isspace(i)) - characterclass[i]++; - index += sizeof(CLASS_SPACE) - 1; - } - else if (trio_equal_max(CLASS_UPPER, sizeof(CLASS_UPPER) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isupper(i)) - characterclass[i]++; - index += sizeof(CLASS_UPPER) - 1; - } - else if (trio_equal_max(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1, - &format[index])) - { - for (i = 0; i < MAX_CHARACTER_CLASS; i++) - if (isxdigit(i)) - characterclass[i]++; - index += sizeof(CLASS_XDIGIT) - 1; - } - else - { - characterclass[(int)ch]++; - } - break; - - default: - characterclass[(int)ch]++; - break; - } - break; - -#endif /* TRIO_EXTENSION */ - - default: - characterclass[(int)ch]++; - break; - } - } - return 0; -} - -/************************************************************************* - * TrioReadNumber - * - * We implement our own number conversion in preference of strtol and - * strtoul, because we must handle 'long long' and thousand separators. - */ -TRIO_PRIVATE BOOLEAN_T -TrioReadNumber -TRIO_ARGS5((self, target, flags, width, base), - trio_class_t *self, - trio_uintmax_t *target, - trio_flags_t flags, - int width, - int base) -{ - trio_uintmax_t number = 0; - int digit; - int count; - BOOLEAN_T isNegative = FALSE; - BOOLEAN_T gotNumber = FALSE; - int j; - - assert(VALID(self)); - assert(VALID(self->InStream)); - assert((base >= MIN_BASE && base <= MAX_BASE) || (base == NO_BASE)); - - if (internalDigitsUnconverted) - { - /* Lazy evaluation of digits array */ - memset(internalDigitArray, -1, sizeof(internalDigitArray)); - for (j = 0; j < (int)sizeof(internalDigitsLower) - 1; j++) - { - internalDigitArray[(int)internalDigitsLower[j]] = j; - internalDigitArray[(int)internalDigitsUpper[j]] = j; - } - internalDigitsUnconverted = FALSE; - } - - TrioSkipWhitespaces(self); - - if (!(flags & FLAGS_UNSIGNED)) - { - /* Leading sign */ - if (self->current == '+') - { - self->InStream(self, NULL); - } - else if (self->current == '-') - { - self->InStream(self, NULL); - isNegative = TRUE; - } - } - - count = self->processed; - - if (flags & FLAGS_ALTERNATIVE) - { - switch (base) - { - case NO_BASE: - case BASE_OCTAL: - case BASE_HEX: - case BASE_BINARY: - if (self->current == '0') - { - self->InStream(self, NULL); - if (self->current) - { - if ((base == BASE_HEX) && - (trio_to_upper(self->current) == 'X')) - { - self->InStream(self, NULL); - } - else if ((base == BASE_BINARY) && - (trio_to_upper(self->current) == 'B')) - { - self->InStream(self, NULL); - } - } - } - else - return FALSE; - break; - default: - break; - } - } - - while (((width == NO_WIDTH) || (self->processed - count < width)) && - (! ((self->current == EOF) || isspace(self->current)))) - { - if (isascii(self->current)) - { - digit = internalDigitArray[self->current]; - /* Abort if digit is not allowed in the specified base */ - if ((digit == -1) || (digit >= base)) - break; - } - else if (flags & FLAGS_QUOTE) - { - /* Compare with thousands separator */ - for (j = 0; internalThousandSeparator[j] && self->current; j++) - { - if (internalThousandSeparator[j] != self->current) - break; - - self->InStream(self, NULL); - } - if (internalThousandSeparator[j]) - break; /* Mismatch */ - else - continue; /* Match */ - } - else - break; - - number *= base; - number += digit; - gotNumber = TRUE; /* we need at least one digit */ - - self->InStream(self, NULL); - } - - /* Was anything read at all? */ - if (!gotNumber) - return FALSE; - - if (target) - *target = (isNegative) ? -((trio_intmax_t)number) : number; - return TRUE; -} - -/************************************************************************* - * TrioReadChar - */ -TRIO_PRIVATE int -TrioReadChar -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - char *target, - trio_flags_t flags, - int width) -{ - int i; - char ch; - trio_uintmax_t number; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - for (i = 0; - (self->current != EOF) && (i < width); - i++) - { - ch = (char)self->current; - self->InStream(self, NULL); - if ((flags & FLAGS_ALTERNATIVE) && (ch == CHAR_BACKSLASH)) - { - switch (self->current) - { - case '\\': ch = '\\'; break; - case 'a': ch = '\007'; break; - case 'b': ch = '\b'; break; - case 'f': ch = '\f'; break; - case 'n': ch = '\n'; break; - case 'r': ch = '\r'; break; - case 't': ch = '\t'; break; - case 'v': ch = '\v'; break; - default: - if (isdigit(self->current)) - { - /* Read octal number */ - if (!TrioReadNumber(self, &number, 0, 3, BASE_OCTAL)) - return 0; - ch = (char)number; - } - else if (trio_to_upper(self->current) == 'X') - { - /* Read hexadecimal number */ - self->InStream(self, NULL); - if (!TrioReadNumber(self, &number, 0, 2, BASE_HEX)) - return 0; - ch = (char)number; - } - else - { - ch = (char)self->current; - } - break; - } - } - - if (target) - target[i] = ch; - } - return i + 1; -} - -/************************************************************************* - * TrioReadString - */ -TRIO_PRIVATE BOOLEAN_T -TrioReadString -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - char *target, - trio_flags_t flags, - int width) -{ - int i; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - TrioSkipWhitespaces(self); - - /* - * Continue until end of string is reached, a whitespace is encountered, - * or width is exceeded - */ - for (i = 0; - ((width == NO_WIDTH) || (i < width)) && - (! ((self->current == EOF) || isspace(self->current))); - i++) - { - if (TrioReadChar(self, (target ? &target[i] : 0), flags, 1) == 0) - break; /* for */ - } - if (target) - target[i] = NIL; - return TRUE; -} - -/************************************************************************* - * TrioReadWideChar - */ -#if TRIO_WIDECHAR -TRIO_PRIVATE int -TrioReadWideChar -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - trio_wchar_t *target, - trio_flags_t flags, - int width) -{ - int i; - int j; - int size; - int amount = 0; - trio_wchar_t wch; - char buffer[MB_LEN_MAX + 1]; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - for (i = 0; - (self->current != EOF) && (i < width); - i++) - { - if (isascii(self->current)) - { - if (TrioReadChar(self, buffer, flags, 1) == 0) - return 0; - buffer[1] = NIL; - } - else - { - /* - * Collect a multibyte character, by enlarging buffer until - * it contains a fully legal multibyte character, or the - * buffer is full. - */ - j = 0; - do - { - buffer[j++] = (char)self->current; - buffer[j] = NIL; - self->InStream(self, NULL); - } - while ((j < (int)sizeof(buffer)) && (mblen(buffer, (size_t)j) != j)); - } - if (target) - { - size = mbtowc(&wch, buffer, sizeof(buffer)); - if (size > 0) - target[i] = wch; - } - amount += size; - self->InStream(self, NULL); - } - return amount; -} -#endif /* TRIO_WIDECHAR */ - -/************************************************************************* - * TrioReadWideString - */ -#if TRIO_WIDECHAR -TRIO_PRIVATE BOOLEAN_T -TrioReadWideString -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - trio_wchar_t *target, - trio_flags_t flags, - int width) -{ - int i; - int size; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - TrioSkipWhitespaces(self); - -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - (void)mblen(NULL, 0); -#endif - - /* - * Continue until end of string is reached, a whitespace is encountered, - * or width is exceeded - */ - for (i = 0; - ((width == NO_WIDTH) || (i < width)) && - (! ((self->current == EOF) || isspace(self->current))); - ) - { - size = TrioReadWideChar(self, &target[i], flags, 1); - if (size == 0) - break; /* for */ - - i += size; - } - if (target) - target[i] = WCONST('\0'); - return TRUE; -} -#endif /* TRIO_WIDECHAR */ - -/************************************************************************* - * TrioReadGroup - * - * FIXME: characterclass does not work with multibyte characters - */ -TRIO_PRIVATE BOOLEAN_T -TrioReadGroup -TRIO_ARGS5((self, target, characterclass, flags, width), - trio_class_t *self, - char *target, - int *characterclass, - trio_flags_t flags, - int width) -{ - int ch; - int i; - - assert(VALID(self)); - assert(VALID(self->InStream)); - - ch = self->current; - for (i = 0; - ((width == NO_WIDTH) || (i < width)) && - (! ((ch == EOF) || - (((flags & FLAGS_EXCLUDE) != 0) ^ (characterclass[ch] == 0)))); - i++) - { - if (target) - target[i] = (char)ch; - self->InStream(self, &ch); - } - - if (target) - target[i] = NIL; - return TRUE; -} - -/************************************************************************* - * TrioReadDouble - * - * FIXME: - * add long double - * handle base - */ -TRIO_PRIVATE BOOLEAN_T -TrioReadDouble -TRIO_ARGS4((self, target, flags, width), - trio_class_t *self, - trio_pointer_t target, - trio_flags_t flags, - int width) -{ - int ch; - char doubleString[512]; - int index = 0; - int start; - int j; - BOOLEAN_T isHex = FALSE; - - doubleString[0] = 0; - - if ((width == NO_WIDTH) || (width > (int)sizeof(doubleString) - 1)) - width = sizeof(doubleString) - 1; - - TrioSkipWhitespaces(self); - - /* - * Read entire double number from stream. trio_to_double requires - * a string as input, but InStream can be anything, so we have to - * collect all characters. - */ - ch = self->current; - if ((ch == '+') || (ch == '-')) - { - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - width--; - } - - start = index; - switch (ch) - { - case 'n': - case 'N': - /* Not-a-number */ - if (index != 0) - break; - /* FALLTHROUGH */ - case 'i': - case 'I': - /* Infinity */ - while (isalpha(ch) && (index - start < width)) - { - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - } - doubleString[index] = NIL; - - /* Case insensitive string comparison */ - if (trio_equal(&doubleString[start], INFINITE_UPPER) || - trio_equal(&doubleString[start], LONG_INFINITE_UPPER)) - { - if (flags & FLAGS_LONGDOUBLE) - { - if ((start == 1) && (doubleString[0] == '-')) - { - *((trio_long_double_t *)target) = trio_ninf(); - } - else - { - *((trio_long_double_t *)target) = trio_pinf(); - } - } - else - { - if ((start == 1) && (doubleString[0] == '-')) - { - *((double *)target) = trio_ninf(); - } - else - { - *((double *)target) = trio_pinf(); - } - } - return TRUE; - } - if (trio_equal(doubleString, NAN_UPPER)) - { - /* NaN must not have a preceding + nor - */ - if (flags & FLAGS_LONGDOUBLE) - { - *((trio_long_double_t *)target) = trio_nan(); - } - else - { - *((double *)target) = trio_nan(); - } - return TRUE; - } - return FALSE; - - case '0': - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - if (trio_to_upper(ch) == 'X') - { - isHex = TRUE; - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - } - break; - - default: - break; - } - - while ((ch != EOF) && (index - start < width)) - { - /* Integer part */ - if (isHex ? isxdigit(ch) : isdigit(ch)) - { - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - } - else if (flags & FLAGS_QUOTE) - { - /* Compare with thousands separator */ - for (j = 0; internalThousandSeparator[j] && self->current; j++) - { - if (internalThousandSeparator[j] != self->current) - break; - - self->InStream(self, &ch); - } - if (internalThousandSeparator[j]) - break; /* Mismatch */ - else - continue; /* Match */ - } - else - break; /* while */ - } - if (ch == '.') - { - /* Decimal part */ - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - while ((isHex ? isxdigit(ch) : isdigit(ch)) && - (index - start < width)) - { - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - } - if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E')) - { - /* Exponent */ - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - if ((ch == '+') || (ch == '-')) - { - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - } - while (isdigit(ch) && (index - start < width)) - { - doubleString[index++] = (char)ch; - self->InStream(self, &ch); - } - } - } - - if ((index == start) || (*doubleString == NIL)) - return FALSE; - - doubleString[index] = 0; - - if (flags & FLAGS_LONGDOUBLE) - { - *((trio_long_double_t *)target) = trio_to_long_double(doubleString, NULL); - } - else - { - *((double *)target) = trio_to_double(doubleString, NULL); - } - return TRUE; -} - -/************************************************************************* - * TrioReadPointer - */ -TRIO_PRIVATE BOOLEAN_T -TrioReadPointer -TRIO_ARGS3((self, target, flags), - trio_class_t *self, - trio_pointer_t *target, - trio_flags_t flags) -{ - trio_uintmax_t number; - char buffer[sizeof(internalNullString)]; - - flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | FLAGS_NILPADDING); - - if (TrioReadNumber(self, - &number, - flags, - POINTER_WIDTH, - BASE_HEX)) - { - /* - * The strange assignment of number is a workaround for a compiler - * warning - */ - if (target) - *target = (char *)0 + number; - return TRUE; - } - else if (TrioReadString(self, - (flags & FLAGS_IGNORE) - ? NULL - : buffer, - 0, - sizeof(internalNullString) - 1)) - { - if (trio_equal_case(buffer, internalNullString)) - { - if (target) - *target = NULL; - return TRUE; - } - } - return FALSE; -} - -/************************************************************************* - * TrioScanProcess - */ -TRIO_PRIVATE int -TrioScanProcess -TRIO_ARGS3((data, format, parameters), - trio_class_t *data, - TRIO_CONST char *format, - trio_parameter_t *parameters) -{ -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - int charlen; - int cnt; -#endif - int assignment; - int ch; - int index; /* Index of format string */ - int i; /* Index of current parameter */ - trio_flags_t flags; - int width; - int base; - trio_pointer_t pointer; - - assignment = 0; - i = 0; - index = 0; - data->InStream(data, &ch); - -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - (void)mblen(NULL, 0); -#endif - - while (format[index]) - { -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - if (! isascii(format[index])) - { - charlen = mblen(&format[index], MB_LEN_MAX); - if (charlen != -1) - { - /* Compare multibyte characters in format string */ - for (cnt = 0; cnt < charlen - 1; cnt++) - { - if (ch != format[index + cnt]) - { - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - } - data->InStream(data, &ch); - } - continue; /* while characters left in formatting string */ - } - } -#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */ - - if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT)) - { - return (assignment > 0) ? assignment : EOF; - } - - if (CHAR_IDENTIFIER == format[index]) - { - if (CHAR_IDENTIFIER == format[index + 1]) - { - /* Two % in format matches one % in input stream */ - if (CHAR_IDENTIFIER == ch) - { - data->InStream(data, &ch); - index += 2; - continue; /* while format chars left */ - } - else - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - } - - /* Skip the parameter entries */ - while (parameters[i].type == FORMAT_PARAMETER) - i++; - - flags = parameters[i].flags; - /* Find width */ - width = parameters[i].width; - if (flags & FLAGS_WIDTH_PARAMETER) - { - /* Get width from parameter list */ - width = (int)parameters[width].data.number.as_signed; - } - /* Find base */ - base = parameters[i].base; - if (flags & FLAGS_BASE_PARAMETER) - { - /* Get base from parameter list */ - base = (int)parameters[base].data.number.as_signed; - } - - switch (parameters[i].type) - { - case FORMAT_INT: - { - trio_uintmax_t number; - - if (0 == base) - base = BASE_DECIMAL; - - if (!TrioReadNumber(data, - &number, - flags, - width, - base)) - return assignment; - - if (!(flags & FLAGS_IGNORE)) - { - assignment++; - - pointer = parameters[i].data.pointer; -#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER) - if (flags & FLAGS_SIZE_T) - *(size_t *)pointer = (size_t)number; - else -#endif -#if defined(QUALIFIER_PTRDIFF_T) - if (flags & FLAGS_PTRDIFF_T) - *(ptrdiff_t *)pointer = (ptrdiff_t)number; - else -#endif -#if defined(QUALIFIER_INTMAX_T) - if (flags & FLAGS_INTMAX_T) - *(trio_intmax_t *)pointer = (trio_intmax_t)number; - else -#endif - if (flags & FLAGS_QUAD) - *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)number; - else if (flags & FLAGS_LONG) - *(long int *)pointer = (long int)number; - else if (flags & FLAGS_SHORT) - *(short int *)pointer = (short int)number; - else - *(int *)pointer = (int)number; - } - } - break; /* FORMAT_INT */ - - case FORMAT_STRING: -#if TRIO_WIDECHAR - if (flags & FLAGS_WIDECHAR) - { - if (!TrioReadWideString(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.wstring, - flags, - width)) - return assignment; - } - else -#endif - { - if (!TrioReadString(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.string, - flags, - width)) - return assignment; - } - if (!(flags & FLAGS_IGNORE)) - assignment++; - break; /* FORMAT_STRING */ - - case FORMAT_DOUBLE: - { - trio_pointer_t pointer; - - if (flags & FLAGS_IGNORE) - { - pointer = NULL; - } - else - { - pointer = (flags & FLAGS_LONGDOUBLE) - ? (trio_pointer_t)parameters[i].data.longdoublePointer - : (trio_pointer_t)parameters[i].data.doublePointer; - } - if (!TrioReadDouble(data, pointer, flags, width)) - { - return assignment; - } - if (!(flags & FLAGS_IGNORE)) - { - assignment++; - } - break; /* FORMAT_DOUBLE */ - } - case FORMAT_GROUP: - { - int characterclass[MAX_CHARACTER_CLASS + 1]; - int rc; - - /* Skip over modifiers */ - while (format[index] != SPECIFIER_GROUP) - { - index++; - } - /* Skip over group specifier */ - index++; - - memset(characterclass, 0, sizeof(characterclass)); - rc = TrioGetCharacterClass(format, - &index, - &flags, - characterclass); - if (rc < 0) - return rc; - - if (!TrioReadGroup(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.string, - characterclass, - flags, - parameters[i].width)) - return assignment; - if (!(flags & FLAGS_IGNORE)) - assignment++; - } - break; /* FORMAT_GROUP */ - - case FORMAT_COUNT: - pointer = parameters[i].data.pointer; - if (NULL != pointer) - { - int count = data->committed; - if (ch != EOF) - count--; /* a character is read, but is not consumed yet */ -#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER) - if (flags & FLAGS_SIZE_T) - *(size_t *)pointer = (size_t)count; - else -#endif -#if defined(QUALIFIER_PTRDIFF_T) - if (flags & FLAGS_PTRDIFF_T) - *(ptrdiff_t *)pointer = (ptrdiff_t)count; - else -#endif -#if defined(QUALIFIER_INTMAX_T) - if (flags & FLAGS_INTMAX_T) - *(trio_intmax_t *)pointer = (trio_intmax_t)count; - else -#endif - if (flags & FLAGS_QUAD) - { - *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count; - } - else if (flags & FLAGS_LONG) - { - *(long int *)pointer = (long int)count; - } - else if (flags & FLAGS_SHORT) - { - *(short int *)pointer = (short int)count; - } - else - { - *(int *)pointer = (int)count; - } - } - break; /* FORMAT_COUNT */ - - case FORMAT_CHAR: -#if TRIO_WIDECHAR - if (flags & FLAGS_WIDECHAR) - { - if (TrioReadWideChar(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.wstring, - flags, - (width == NO_WIDTH) ? 1 : width) == 0) - return assignment; - } - else -#endif - { - if (TrioReadChar(data, - (flags & FLAGS_IGNORE) - ? NULL - : parameters[i].data.string, - flags, - (width == NO_WIDTH) ? 1 : width) == 0) - return assignment; - } - if (!(flags & FLAGS_IGNORE)) - assignment++; - break; /* FORMAT_CHAR */ - - case FORMAT_POINTER: - if (!TrioReadPointer(data, - (flags & FLAGS_IGNORE) - ? NULL - : (trio_pointer_t *)parameters[i].data.pointer, - flags)) - return assignment; - if (!(flags & FLAGS_IGNORE)) - assignment++; - break; /* FORMAT_POINTER */ - - case FORMAT_PARAMETER: - break; /* FORMAT_PARAMETER */ - - default: - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); - } - ch = data->current; - index = parameters[i].indexAfterSpecifier; - i++; - } - else /* Not an % identifier */ - { - if (isspace((int)format[index])) - { - /* Whitespaces may match any amount of whitespaces */ - ch = TrioSkipWhitespaces(data); - } - else if (ch == format[index]) - { - data->InStream(data, &ch); - } - else - return assignment; - - index++; - } - } - return assignment; -} - -/************************************************************************* - * TrioScan - */ -TRIO_PRIVATE int -TrioScan -TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray), - trio_pointer_t source, - size_t sourceSize, - void (*InStream) TRIO_PROTO((trio_class_t *, int *)), - TRIO_CONST char *format, - TRIO_VA_LIST_PTR arglist, - trio_pointer_t *argarray) -{ - int status; - trio_parameter_t parameters[MAX_PARAMETERS]; - trio_class_t data; - - assert(VALID(InStream)); - assert(VALID(format)); - - memset(&data, 0, sizeof(data)); - data.InStream = InStream; - data.location = (trio_pointer_t)source; - data.max = sourceSize; - data.error = 0; - -#if defined(USE_LOCALE) - if (NULL == internalLocaleValues) - { - TrioSetLocale(); - } -#endif - - status = TrioParse(TYPE_SCAN, format, parameters, arglist, argarray); - if (status < 0) - return status; - - status = TrioScanProcess(&data, format, parameters); - if (data.error != 0) - { - status = data.error; - } - return status; -} - -/************************************************************************* - * TrioInStreamFile - */ -TRIO_PRIVATE void -TrioInStreamFile -TRIO_ARGS2((self, intPointer), - trio_class_t *self, - int *intPointer) -{ - FILE *file; - - assert(VALID(self)); - assert(VALID(self->location)); - assert(VALID(file)); - - file = (FILE *)self->location; - - self->current = fgetc(file); - if (self->current == EOF) - { - self->error = (ferror(file)) - ? TRIO_ERROR_RETURN(TRIO_ERRNO, 0) - : TRIO_ERROR_RETURN(TRIO_EOF, 0); - } - else - { - self->processed++; - self->committed++; - } - - if (VALID(intPointer)) - { - *intPointer = self->current; - } -} - -/************************************************************************* - * TrioInStreamFileDescriptor - */ -TRIO_PRIVATE void -TrioInStreamFileDescriptor -TRIO_ARGS2((self, intPointer), - trio_class_t *self, - int *intPointer) -{ - int fd; - int size; - unsigned char input; - - assert(VALID(self)); - assert(VALID(self->location)); - - fd = *((int *)self->location); - - size = read(fd, &input, sizeof(char)); - if (size == -1) - { - self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0); - self->current = EOF; - } - else - { - self->current = (size == 0) ? EOF : input; - } - if (self->current != EOF) - { - self->committed++; - self->processed++; - } - - if (VALID(intPointer)) - { - *intPointer = self->current; - } -} - -/************************************************************************* - * TrioInStreamCustom - */ -TRIO_PRIVATE void -TrioInStreamCustom -TRIO_ARGS2((self, intPointer), - trio_class_t *self, - int *intPointer) -{ - trio_custom_t *data; - - assert(VALID(self)); - assert(VALID(self->location)); - - data = (trio_custom_t *)self->location; - - self->current = (data->stream.in == NULL) - ? NIL - : (data->stream.in)(data->closure); - - if (self->current == NIL) - { - self->current = EOF; - } - else - { - self->processed++; - self->committed++; - } - - if (VALID(intPointer)) - { - *intPointer = self->current; - } -} - -/************************************************************************* - * TrioInStreamString - */ -TRIO_PRIVATE void -TrioInStreamString -TRIO_ARGS2((self, intPointer), - trio_class_t *self, - int *intPointer) -{ - unsigned char **buffer; - - assert(VALID(self)); - assert(VALID(self->location)); - - buffer = (unsigned char **)self->location; - self->current = (*buffer)[0]; - if (self->current == NIL) - { - self->current = EOF; - } - else - { - (*buffer)++; - self->processed++; - self->committed++; - } - - if (VALID(intPointer)) - { - *intPointer = self->current; - } -} - -/************************************************************************* - * - * Formatted scanning functions - * - ************************************************************************/ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_scanf.h" -#endif -/** @addtogroup Scanf - @{ -*/ - -/************************************************************************* - * scanf - */ - -/** - Scan characters from standard input stream. - - @param format Formatting string. - @param ... Arguments. - @return Number of scanned characters. - */ -TRIO_PUBLIC int -trio_scanf -TRIO_VARGS2((format, va_alist), - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioScan((trio_pointer_t)stdin, 0, - TrioInStreamFile, - format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -TRIO_PUBLIC int -trio_vscanf -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(format)); - - return TrioScan((trio_pointer_t)stdin, 0, - TrioInStreamFile, - format, TRIO_VA_LIST_ADDR(args), NULL); -} - -TRIO_PUBLIC int -trio_scanfv -TRIO_ARGS2((format, args), - TRIO_CONST char *format, - trio_pointer_t *args) -{ - assert(VALID(format)); - - return TrioScan((trio_pointer_t)stdin, 0, - TrioInStreamFile, - format, NULL, args); -} - -/************************************************************************* - * fscanf - */ -TRIO_PUBLIC int -trio_fscanf -TRIO_VARGS3((file, format, va_alist), - FILE *file, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(file)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioScan((trio_pointer_t)file, 0, - TrioInStreamFile, - format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -TRIO_PUBLIC int -trio_vfscanf -TRIO_ARGS3((file, format, args), - FILE *file, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(file)); - assert(VALID(format)); - - return TrioScan((trio_pointer_t)file, 0, - TrioInStreamFile, - format, TRIO_VA_LIST_ADDR(args), NULL); -} - -TRIO_PUBLIC int -trio_fscanfv -TRIO_ARGS3((file, format, args), - FILE *file, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - assert(VALID(file)); - assert(VALID(format)); - - return TrioScan((trio_pointer_t)file, 0, - TrioInStreamFile, - format, NULL, args); -} - -/************************************************************************* - * dscanf - */ -TRIO_PUBLIC int -trio_dscanf -TRIO_VARGS3((fd, format, va_alist), - int fd, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioScan((trio_pointer_t)&fd, 0, - TrioInStreamFileDescriptor, - format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -TRIO_PUBLIC int -trio_vdscanf -TRIO_ARGS3((fd, format, args), - int fd, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(format)); - - return TrioScan((trio_pointer_t)&fd, 0, - TrioInStreamFileDescriptor, - format, TRIO_VA_LIST_ADDR(args), NULL); -} - -TRIO_PUBLIC int -trio_dscanfv -TRIO_ARGS3((fd, format, args), - int fd, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - assert(VALID(format)); - - return TrioScan((trio_pointer_t)&fd, 0, - TrioInStreamFileDescriptor, - format, NULL, args); -} - -/************************************************************************* - * cscanf - */ -TRIO_PUBLIC int -trio_cscanf -TRIO_VARGS4((stream, closure, format, va_alist), - trio_instream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - data.stream.in = stream; - data.closure = closure; - status = TrioScan(&data, 0, TrioInStreamCustom, format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -TRIO_PUBLIC int -trio_vcscanf -TRIO_ARGS4((stream, closure, format, args), - trio_instream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - va_list args) -{ - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - data.stream.in = stream; - data.closure = closure; - return TrioScan(&data, 0, TrioInStreamCustom, format, TRIO_VA_LIST_ADDR(args), NULL); -} - -TRIO_PUBLIC int -trio_cscanfv -TRIO_ARGS4((stream, closure, format, args), - trio_instream_t stream, - trio_pointer_t closure, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - trio_custom_t data; - - assert(VALID(stream)); - assert(VALID(format)); - - data.stream.in = stream; - data.closure = closure; - return TrioScan(&data, 0, TrioInStreamCustom, format, NULL, args); -} - -/************************************************************************* - * sscanf - */ -TRIO_PUBLIC int -trio_sscanf -TRIO_VARGS3((buffer, format, va_alist), - TRIO_CONST char *buffer, - TRIO_CONST char *format, - TRIO_VA_DECL) -{ - int status; - va_list args; - - assert(VALID(buffer)); - assert(VALID(format)); - - TRIO_VA_START(args, format); - status = TrioScan((trio_pointer_t)&buffer, 0, - TrioInStreamString, - format, TRIO_VA_LIST_ADDR(args), NULL); - TRIO_VA_END(args); - return status; -} - -TRIO_PUBLIC int -trio_vsscanf -TRIO_ARGS3((buffer, format, args), - TRIO_CONST char *buffer, - TRIO_CONST char *format, - va_list args) -{ - assert(VALID(buffer)); - assert(VALID(format)); - - return TrioScan((trio_pointer_t)&buffer, 0, - TrioInStreamString, - format, TRIO_VA_LIST_ADDR(args), NULL); -} - -TRIO_PUBLIC int -trio_sscanfv -TRIO_ARGS3((buffer, format, args), - TRIO_CONST char *buffer, - TRIO_CONST char *format, - trio_pointer_t *args) -{ - assert(VALID(buffer)); - assert(VALID(format)); - - return TrioScan((trio_pointer_t)&buffer, 0, - TrioInStreamString, - format, NULL, args); -} - -/** @} End of Scanf documentation module */ - -/************************************************************************* - * trio_strerror - */ -TRIO_PUBLIC TRIO_CONST char * -trio_strerror -TRIO_ARGS1((errorcode), - int errorcode) -{ - /* Textual versions of the error codes */ - switch (TRIO_ERROR_CODE(errorcode)) - { - case TRIO_EOF: - return "End of file"; - case TRIO_EINVAL: - return "Invalid argument"; - case TRIO_ETOOMANY: - return "Too many arguments"; - case TRIO_EDBLREF: - return "Double reference"; - case TRIO_EGAP: - return "Reference gap"; - case TRIO_ENOMEM: - return "Out of memory"; - case TRIO_ERANGE: - return "Invalid range"; - case TRIO_ECUSTOM: - return "Custom error"; - default: - return "Unknown"; - } -} diff --git a/trio.h b/trio.h deleted file mode 100644 index dcf96b63..00000000 --- a/trio.h +++ /dev/null @@ -1,230 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************* - * - * http://ctrio.sourceforge.net/ - * - ************************************************************************/ - -#ifndef TRIO_TRIO_H -#define TRIO_TRIO_H - -#if !defined(WITHOUT_TRIO) - -/* - * Use autoconf defines if present. Packages using trio must define - * HAVE_CONFIG_H as a compiler option themselves. - */ -#if defined(TRIO_HAVE_CONFIG_H) -# include "config.h" -#endif - -#include "triodef.h" - -#include -#include -#if defined(TRIO_COMPILER_ANCIENT) -# include -#else -# include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Error codes. - * - * Remember to add a textual description to trio_strerror. - */ -enum { - TRIO_EOF = 1, - TRIO_EINVAL = 2, - TRIO_ETOOMANY = 3, - TRIO_EDBLREF = 4, - TRIO_EGAP = 5, - TRIO_ENOMEM = 6, - TRIO_ERANGE = 7, - TRIO_ERRNO = 8, - TRIO_ECUSTOM = 9 -}; - -/* Error macros */ -#define TRIO_ERROR_CODE(x) ((-(x)) & 0x00FF) -#define TRIO_ERROR_POSITION(x) ((-(x)) >> 8) -#define TRIO_ERROR_NAME(x) trio_strerror(x) - -typedef int (*trio_outstream_t) TRIO_PROTO((trio_pointer_t, int)); -typedef int (*trio_instream_t) TRIO_PROTO((trio_pointer_t)); - -TRIO_CONST char *trio_strerror TRIO_PROTO((int)); - -/************************************************************************* - * Print Functions - */ - -int trio_printf TRIO_PROTO((TRIO_CONST char *format, ...)); -int trio_vprintf TRIO_PROTO((TRIO_CONST char *format, va_list args)); -int trio_printfv TRIO_PROTO((TRIO_CONST char *format, void **args)); - -int trio_fprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, ...)); -int trio_vfprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args)); -int trio_fprintfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args)); - -int trio_dprintf TRIO_PROTO((int fd, TRIO_CONST char *format, ...)); -int trio_vdprintf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args)); -int trio_dprintfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args)); - -int trio_cprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, - TRIO_CONST char *format, ...)); -int trio_vcprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, - TRIO_CONST char *format, va_list args)); -int trio_cprintfv TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, - TRIO_CONST char *format, void **args)); - -int trio_sprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, ...)); -int trio_vsprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, va_list args)); -int trio_sprintfv TRIO_PROTO((char *buffer, TRIO_CONST char *format, void **args)); - -int trio_snprintf TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *format, ...)); -int trio_vsnprintf TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, - va_list args)); -int trio_snprintfv TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, - void **args)); - -int trio_snprintfcat TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *format, ...)); -int trio_vsnprintfcat TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, - va_list args)); - -char *trio_aprintf TRIO_PROTO((TRIO_CONST char *format, ...)); -char *trio_vaprintf TRIO_PROTO((TRIO_CONST char *format, va_list args)); - -int trio_asprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, ...)); -int trio_vasprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, va_list args)); - -/************************************************************************* - * Scan Functions - */ -int trio_scanf TRIO_PROTO((TRIO_CONST char *format, ...)); -int trio_vscanf TRIO_PROTO((TRIO_CONST char *format, va_list args)); -int trio_scanfv TRIO_PROTO((TRIO_CONST char *format, void **args)); - -int trio_fscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, ...)); -int trio_vfscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args)); -int trio_fscanfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args)); - -int trio_dscanf TRIO_PROTO((int fd, TRIO_CONST char *format, ...)); -int trio_vdscanf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args)); -int trio_dscanfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args)); - -int trio_cscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, - TRIO_CONST char *format, ...)); -int trio_vcscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, - TRIO_CONST char *format, va_list args)); -int trio_cscanfv TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, - TRIO_CONST char *format, void **args)); - -int trio_sscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, ...)); -int trio_vsscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, va_list args)); -int trio_sscanfv TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, void **args)); - -/************************************************************************* - * Locale Functions - */ -void trio_locale_set_decimal_point TRIO_PROTO((char *decimalPoint)); -void trio_locale_set_thousand_separator TRIO_PROTO((char *thousandSeparator)); -void trio_locale_set_grouping TRIO_PROTO((char *grouping)); - -/************************************************************************* - * Renaming - */ -#ifdef TRIO_REPLACE_STDIO -/* Replace the functions */ -#ifndef HAVE_PRINTF -# undef printf -# define printf trio_printf -#endif -#ifndef HAVE_VPRINTF -# undef vprintf -# define vprintf trio_vprintf -#endif -#ifndef HAVE_FPRINTF -# undef fprintf -# define fprintf trio_fprintf -#endif -#ifndef HAVE_VFPRINTF -# undef vfprintf -# define vfprintf trio_vfprintf -#endif -#ifndef HAVE_SPRINTF -# undef sprintf -# define sprintf trio_sprintf -#endif -#ifndef HAVE_VSPRINTF -# undef vsprintf -# define vsprintf trio_vsprintf -#endif -#ifndef HAVE_SNPRINTF -# undef snprintf -# define snprintf trio_snprintf -#endif -#ifndef HAVE_VSNPRINTF -# undef vsnprintf -# define vsnprintf trio_vsnprintf -#endif -#ifndef HAVE_SCANF -# undef scanf -# define scanf trio_scanf -#endif -#ifndef HAVE_VSCANF -# undef vscanf -# define vscanf trio_vscanf -#endif -#ifndef HAVE_FSCANF -# undef fscanf -# define fscanf trio_fscanf -#endif -#ifndef HAVE_VFSCANF -# undef vfscanf -# define vfscanf trio_vfscanf -#endif -#ifndef HAVE_SSCANF -# undef sscanf -# define sscanf trio_sscanf -#endif -#ifndef HAVE_VSSCANF -# undef vsscanf -# define vsscanf trio_vsscanf -#endif -/* These aren't stdio functions, but we make them look similar */ -#define dprintf trio_dprintf -#define vdprintf trio_vdprintf -#define aprintf trio_aprintf -#define vaprintf trio_vaprintf -#define asprintf trio_asprintf -#define vasprintf trio_vasprintf -#define dscanf trio_dscanf -#define vdscanf trio_vdscanf -#endif - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* WITHOUT_TRIO */ - -#endif /* TRIO_TRIO_H */ diff --git a/triodef.h b/triodef.h deleted file mode 100644 index e101f6df..00000000 --- a/triodef.h +++ /dev/null @@ -1,228 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2001 Bjorn Reese - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************/ - -#ifndef TRIO_TRIODEF_H -#define TRIO_TRIODEF_H - -/************************************************************************* - * Platform and compiler support detection - */ -#if defined(__GNUC__) -# define TRIO_COMPILER_GCC -#elif defined(__SUNPRO_C) -# define TRIO_COMPILER_SUNPRO -#elif defined(__SUNPRO_CC) -# define TRIO_COMPILER_SUNPRO -# define __SUNPRO_C __SUNPRO_CC -#elif defined(__xlC__) || defined(__IBMC__) || defined(__IBMCPP__) -# define TRIO_COMPILER_XLC -#elif defined(_AIX) && !defined(__GNUC__) -# define TRIO_COMPILER_XLC /* Workaround for old xlc */ -#elif defined(__DECC) || defined(__DECCXX) -# define TRIO_COMPILER_DECC -#elif defined(__osf__) && defined(__LANGUAGE_C__) -# define TRIO_COMPILER_DECC /* Workaround for old DEC C compilers */ -#elif defined(_MSC_VER) -# define TRIO_COMPILER_MSVC -#elif defined(__BORLANDC__) -# define TRIO_COMPILER_BCB -#endif - -#if defined(VMS) || defined(__VMS) -/* - * VMS is placed first to avoid identifying the platform as Unix - * based on the DECC compiler later on. - */ -# define TRIO_PLATFORM_VMS -#elif defined(__OS400__) -# define TRIO_PLATFORM_OS400 -#elif defined(unix) || defined(__unix) || defined(__unix__) -# define TRIO_PLATFORM_UNIX -#elif defined(TRIO_COMPILER_XLC) || defined(_AIX) -# define TRIO_PLATFORM_UNIX -#elif defined(TRIO_COMPILER_DECC) || defined(__osf___) -# define TRIO_PLATFORM_UNIX -#elif defined(__NetBSD__) -# define TRIO_PLATFORM_UNIX -#elif defined(__Lynx__) -# define TRIO_PLATFORM_UNIX -#elif defined(__QNX__) -# define TRIO_PLATFORM_UNIX -# define TRIO_PLATFORM_QNX -#elif defined(__CYGWIN__) -# define TRIO_PLATFORM_UNIX -#elif defined(AMIGA) && defined(TRIO_COMPILER_GCC) -# define TRIO_PLATFORM_UNIX -#elif defined(TRIO_COMPILER_MSVC) || defined(WIN32) || defined(_WIN32) -# define TRIO_PLATFORM_WIN32 -#elif defined(mpeix) || defined(__mpexl) -# define TRIO_PLATFORM_MPEIX -#endif - -#if defined(_AIX) -# define TRIO_PLATFORM_AIX -#elif defined(__hpux) -# define TRIO_PLATFORM_HPUX -#elif defined(sun) || defined(__sun__) -# if defined(__SVR4) || defined(__svr4__) -# define TRIO_PLATFORM_SOLARIS -# else -# define TRIO_PLATFORM_SUNOS -# endif -#endif - -#if defined(__STDC__) || defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) -# define TRIO_COMPILER_SUPPORTS_C89 -# if defined(__STDC_VERSION__) -# define TRIO_COMPILER_SUPPORTS_C90 -# if (__STDC_VERSION__ >= 199409L) -# define TRIO_COMPILER_SUPPORTS_C94 -# endif -# if (__STDC_VERSION__ >= 199901L) -# define TRIO_COMPILER_SUPPORTS_C99 -# endif -# elif defined(TRIO_COMPILER_SUNPRO) -# if (__SUNPRO_C >= 0x420) -# define TRIO_COMPILER_SUPPORTS_C94 -# endif -# endif -#elif defined(TRIO_COMPILER_XLC) && defined(__EXTENDED__) -# define TRIO_COMPILER_SUPPORTS_C89 -# define TRIO_COMPILER_SUPPORTS_C90 -# define TRIO_COMPILER_SUPPORTS_C94 -#endif - -#if defined(_XOPEN_SOURCE) -# if defined(_XOPEN_SOURCE_EXTENDED) -# define TRIO_COMPILER_SUPPORTS_UNIX95 -# endif -# if (_XOPEN_VERSION >= 500) -# define TRIO_COMPILER_SUPPORTS_UNIX98 -# endif -# if (_XOPEN_VERSION >= 600) -# define TRIO_COMPILER_SUPPORTS_UNIX01 -# endif -#endif - -/************************************************************************* - * Generic defines - */ - -#if !defined(TRIO_PUBLIC) -# define TRIO_PUBLIC -#endif -#if !defined(TRIO_PRIVATE) -# define TRIO_PRIVATE static -#endif - -#if !(defined(TRIO_COMPILER_SUPPORTS_C89) || defined(__cplusplus)) -# define TRIO_COMPILER_ANCIENT -#endif - -#if defined(TRIO_COMPILER_ANCIENT) -# define TRIO_CONST -# define TRIO_VOLATILE -# define TRIO_SIGNED -typedef double trio_long_double_t; -typedef char * trio_pointer_t; -# define TRIO_SUFFIX_LONG(x) x -# define TRIO_PROTO(x) () -# define TRIO_NOARGS -# define TRIO_ARGS1(list,a1) list a1; -# define TRIO_ARGS2(list,a1,a2) list a1; a2; -# define TRIO_ARGS3(list,a1,a2,a3) list a1; a2; a3; -# define TRIO_ARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4; -# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5; -# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) list a1; a2; a3; a4; a5; a6; -# define TRIO_VARGS2(list,a1,a2) list a1; a2 -# define TRIO_VARGS3(list,a1,a2,a3) list a1; a2; a3 -# define TRIO_VARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4 -# define TRIO_VARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5 -# define TRIO_VA_DECL va_dcl -# define TRIO_VA_START(x,y) va_start(x) -# define TRIO_VA_END(x) va_end(x) -#else /* ANSI C */ -# define TRIO_CONST const -# define TRIO_VOLATILE volatile -# define TRIO_SIGNED signed -typedef long double trio_long_double_t; -typedef void * trio_pointer_t; -# define TRIO_SUFFIX_LONG(x) x ## L -# define TRIO_PROTO(x) x -# define TRIO_NOARGS void -# define TRIO_ARGS1(list,a1) (a1) -# define TRIO_ARGS2(list,a1,a2) (a1,a2) -# define TRIO_ARGS3(list,a1,a2,a3) (a1,a2,a3) -# define TRIO_ARGS4(list,a1,a2,a3,a4) (a1,a2,a3,a4) -# define TRIO_ARGS5(list,a1,a2,a3,a4,a5) (a1,a2,a3,a4,a5) -# define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) (a1,a2,a3,a4,a5,a6) -# define TRIO_VARGS2 TRIO_ARGS2 -# define TRIO_VARGS3 TRIO_ARGS3 -# define TRIO_VARGS4 TRIO_ARGS4 -# define TRIO_VARGS5 TRIO_ARGS5 -# define TRIO_VA_DECL ... -# define TRIO_VA_START(x,y) va_start(x,y) -# define TRIO_VA_END(x) va_end(x) -#endif - -#if defined(TRIO_COMPILER_SUPPORTS_C99) || defined(__cplusplus) -# define TRIO_INLINE inline -#elif defined(TRIO_COMPILER_GCC) -# define TRIO_INLINE __inline__ -#elif defined(TRIO_COMPILER_MSVC) -# define TRIO_INLINE _inline -#elif defined(TRIO_COMPILER_BCB) -# define TRIO_INLINE __inline -#else -# define TRIO_INLINE -#endif - -/************************************************************************* - * Workarounds - */ - -#if defined(TRIO_PLATFORM_VMS) -/* - * Computations done with constants at compile time can trigger these - * even when compiling with IEEE enabled. - */ -# pragma message disable (UNDERFLOW, FLOATOVERFL) - -# if (__CRTL_VER < 80000000) -/* - * Although the compiler supports C99 language constructs, the C - * run-time library does not contain all C99 functions. - * - * This was the case for 70300022. Update the 80000000 value when - * it has been accurately determined what version of the library - * supports C99. - */ -# if defined(TRIO_COMPILER_SUPPORTS_C99) -# undef TRIO_COMPILER_SUPPORTS_C99 -# endif -# endif -#endif - -/* - * Not all preprocessors supports the LL token. - */ -#if defined(TRIO_COMPILER_BCB) -#else -# define TRIO_COMPILER_SUPPORTS_LL -#endif - -#endif /* TRIO_TRIODEF_H */ diff --git a/trionan.c b/trionan.c deleted file mode 100644 index 8767a9fe..00000000 --- a/trionan.c +++ /dev/null @@ -1,914 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2001 Bjorn Reese - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************ - * - * Functions to handle special quantities in floating-point numbers - * (that is, NaNs and infinity). They provide the capability to detect - * and fabricate special quantities. - * - * Although written to be as portable as possible, it can never be - * guaranteed to work on all platforms, as not all hardware supports - * special quantities. - * - * The approach used here (approximately) is to: - * - * 1. Use C99 functionality when available. - * 2. Use IEEE 754 bit-patterns if possible. - * 3. Use platform-specific techniques. - * - ************************************************************************/ - -/* - * TODO: - * o Put all the magic into trio_fpclassify_and_signbit(), and use this from - * trio_isnan() etc. - */ - -/************************************************************************* - * Include files - */ -#include "triodef.h" -#include "trionan.h" - -#include -#include -#include -#include -#if defined(TRIO_PLATFORM_UNIX) -# include -#endif -#if defined(TRIO_COMPILER_DECC) -# if defined(__linux__) -# include -# else -# include -# endif -#endif -#include - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_nan.h" -#endif -/** @addtogroup SpecialQuantities - @{ -*/ - -/************************************************************************* - * Definitions - */ - -#define TRIO_TRUE (1 == 1) -#define TRIO_FALSE (0 == 1) - -/* - * We must enable IEEE floating-point on Alpha - */ -#if defined(__alpha) && !defined(_IEEE_FP) -# if defined(TRIO_COMPILER_DECC) -# if defined(TRIO_PLATFORM_VMS) -# error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE" -# else -# if !defined(_CFE) -# error "Must be compiled with option -ieee" -# endif -# endif -# elif defined(TRIO_COMPILER_GCC) && (defined(__osf__) || defined(__linux__)) -# error "Must be compiled with option -mieee" -# endif -#endif /* __alpha && ! _IEEE_FP */ - -/* - * In ANSI/IEEE 754-1985 64-bits double format numbers have the - * following properties (amongst others) - * - * o FLT_RADIX == 2: binary encoding - * o DBL_MAX_EXP == 1024: 11 bits exponent, where one bit is used - * to indicate special numbers (e.g. NaN and Infinity), so the - * maximum exponent is 10 bits wide (2^10 == 1024). - * o DBL_MANT_DIG == 53: The mantissa is 52 bits wide, but because - * numbers are normalized the initial binary 1 is represented - * implicitly (the so-called "hidden bit"), which leaves us with - * the ability to represent 53 bits wide mantissa. - */ -#if (FLT_RADIX == 2) && (DBL_MAX_EXP == 1024) && (DBL_MANT_DIG == 53) -# define USE_IEEE_754 -#endif - - -/************************************************************************* - * Constants - */ - -static TRIO_CONST char rcsid[] = "@(#)$Id$"; - -#if defined(USE_IEEE_754) - -/* - * Endian-agnostic indexing macro. - * - * The value of internalEndianMagic, when converted into a 64-bit - * integer, becomes 0x0706050403020100 (we could have used a 64-bit - * integer value instead of a double, but not all platforms supports - * that type). The value is automatically encoded with the correct - * endianness by the compiler, which means that we can support any - * kind of endianness. The individual bytes are then used as an index - * for the IEEE 754 bit-patterns and masks. - */ -#define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)]) - -#if (defined(__BORLANDC__) && __BORLANDC__ >= 0x0590) -static TRIO_CONST double internalEndianMagic = 7.949928895127362e-275; -#else -static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275; -#endif - -/* Mask for the exponent */ -static TRIO_CONST unsigned char ieee_754_exponent_mask[] = { - 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* Mask for the mantissa */ -static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = { - 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/* Mask for the sign bit */ -static TRIO_CONST unsigned char ieee_754_sign_mask[] = { - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* Bit-pattern for negative zero */ -static TRIO_CONST unsigned char ieee_754_negzero_array[] = { - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* Bit-pattern for infinity */ -static TRIO_CONST unsigned char ieee_754_infinity_array[] = { - 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* Bit-pattern for quiet NaN */ -static TRIO_CONST unsigned char ieee_754_qnan_array[] = { - 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - - -/************************************************************************* - * Functions - */ - -/* - * trio_make_double - */ -TRIO_PRIVATE double -trio_make_double -TRIO_ARGS1((values), - TRIO_CONST unsigned char *values) -{ - TRIO_VOLATILE double result; - int i; - - for (i = 0; i < (int)sizeof(double); i++) { - ((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i]; - } - return result; -} - -/* - * trio_is_special_quantity - */ -TRIO_PRIVATE int -trio_is_special_quantity -TRIO_ARGS2((number, has_mantissa), - double number, - int *has_mantissa) -{ - unsigned int i; - unsigned char current; - int is_special_quantity = TRIO_TRUE; - - *has_mantissa = 0; - - for (i = 0; i < (unsigned int)sizeof(double); i++) { - current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)]; - is_special_quantity - &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]); - *has_mantissa |= (current & ieee_754_mantissa_mask[i]); - } - return is_special_quantity; -} - -/* - * trio_is_negative - */ -TRIO_PRIVATE int -trio_is_negative -TRIO_ARGS1((number), - double number) -{ - unsigned int i; - int is_negative = TRIO_FALSE; - - for (i = 0; i < (unsigned int)sizeof(double); i++) { - is_negative |= (((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)] - & ieee_754_sign_mask[i]); - } - return is_negative; -} - -#endif /* USE_IEEE_754 */ - - -/** - Generate negative zero. - - @return Floating-point representation of negative zero. -*/ -TRIO_PUBLIC double -trio_nzero(TRIO_NOARGS) -{ -#if defined(USE_IEEE_754) - return trio_make_double(ieee_754_negzero_array); -#else - TRIO_VOLATILE double zero = 0.0; - - return -zero; -#endif -} - -/** - Generate positive infinity. - - @return Floating-point representation of positive infinity. -*/ -TRIO_PUBLIC double -trio_pinf(TRIO_NOARGS) -{ - /* Cache the result */ - static double result = 0.0; - - if (result == 0.0) { - -#if defined(INFINITY) && defined(__STDC_IEC_559__) - result = (double)INFINITY; - -#elif defined(USE_IEEE_754) - result = trio_make_double(ieee_754_infinity_array); - -#else - /* - * If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used - * as infinity. Otherwise we have to resort to an overflow - * operation to generate infinity. - */ -# if defined(TRIO_PLATFORM_UNIX) - void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); -# endif - - result = HUGE_VAL; - if (HUGE_VAL == DBL_MAX) { - /* Force overflow */ - result += HUGE_VAL; - } - -# if defined(TRIO_PLATFORM_UNIX) - signal(SIGFPE, signal_handler); -# endif - -#endif - } - return result; -} - -/** - Generate negative infinity. - - @return Floating-point value of negative infinity. -*/ -TRIO_PUBLIC double -trio_ninf(TRIO_NOARGS) -{ - static double result = 0.0; - - if (result == 0.0) { - /* - * Negative infinity is calculated by negating positive infinity, - * which can be done because it is legal to do calculations on - * infinity (for example, 1 / infinity == 0). - */ - result = -trio_pinf(); - } - return result; -} - -/** - Generate NaN. - - @return Floating-point representation of NaN. -*/ -TRIO_PUBLIC double -trio_nan(TRIO_NOARGS) -{ - /* Cache the result */ - static double result = 0.0; - - if (result == 0.0) { - -#if defined(TRIO_COMPILER_SUPPORTS_C99) - result = nan(""); - -#elif defined(NAN) && defined(__STDC_IEC_559__) - result = (double)NAN; - -#elif defined(USE_IEEE_754) - result = trio_make_double(ieee_754_qnan_array); - -#else - /* - * There are several ways to generate NaN. The one used here is - * to divide infinity by infinity. I would have preferred to add - * negative infinity to positive infinity, but that yields wrong - * result (infinity) on FreeBSD. - * - * This may fail if the hardware does not support NaN, or if - * the Invalid Operation floating-point exception is unmasked. - */ -# if defined(TRIO_PLATFORM_UNIX) - void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); -# endif - - result = trio_pinf() / trio_pinf(); - -# if defined(TRIO_PLATFORM_UNIX) - signal(SIGFPE, signal_handler); -# endif - -#endif - } - return result; -} - -/** - Check for NaN. - - @param number An arbitrary floating-point number. - @return Boolean value indicating whether or not the number is a NaN. -*/ -TRIO_PUBLIC int -trio_isnan -TRIO_ARGS1((number), - double number) -{ -#if (defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isnan)) \ - || defined(TRIO_COMPILER_SUPPORTS_UNIX95) - /* - * C99 defines isnan() as a macro. UNIX95 defines isnan() as a - * function. This function was already present in XPG4, but this - * is a bit tricky to detect with compiler defines, so we choose - * the conservative approach and only use it for UNIX95. - */ - return isnan(number); - -#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) - /* - * Microsoft Visual C++ and Borland C++ Builder have an _isnan() - * function. - */ - return _isnan(number) ? TRIO_TRUE : TRIO_FALSE; - -#elif defined(USE_IEEE_754) - /* - * Examine IEEE 754 bit-pattern. A NaN must have a special exponent - * pattern, and a non-empty mantissa. - */ - int has_mantissa; - int is_special_quantity; - - is_special_quantity = trio_is_special_quantity(number, &has_mantissa); - - return (is_special_quantity && has_mantissa); - -#else - /* - * Fallback solution - */ - int status; - double integral, fraction; - -# if defined(TRIO_PLATFORM_UNIX) - void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); -# endif - - status = (/* - * NaN is the only number which does not compare to itself - */ - ((TRIO_VOLATILE double)number != (TRIO_VOLATILE double)number) || - /* - * Fallback solution if NaN compares to NaN - */ - ((number != 0.0) && - (fraction = modf(number, &integral), - integral == fraction))); - -# if defined(TRIO_PLATFORM_UNIX) - signal(SIGFPE, signal_handler); -# endif - - return status; - -#endif -} - -/** - Check for infinity. - - @param number An arbitrary floating-point number. - @return 1 if positive infinity, -1 if negative infinity, 0 otherwise. -*/ -TRIO_PUBLIC int -trio_isinf -TRIO_ARGS1((number), - double number) -{ -#if defined(TRIO_COMPILER_DECC) && !defined(__linux__) - /* - * DECC has an isinf() macro, but it works differently than that - * of C99, so we use the fp_class() function instead. - */ - return ((fp_class(number) == FP_POS_INF) - ? 1 - : ((fp_class(number) == FP_NEG_INF) ? -1 : 0)); - -#elif defined(isinf) - /* - * C99 defines isinf() as a macro. - */ - return isinf(number) - ? ((number > 0.0) ? 1 : -1) - : 0; - -#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) - /* - * Microsoft Visual C++ and Borland C++ Builder have an _fpclass() - * function that can be used to detect infinity. - */ - return ((_fpclass(number) == _FPCLASS_PINF) - ? 1 - : ((_fpclass(number) == _FPCLASS_NINF) ? -1 : 0)); - -#elif defined(USE_IEEE_754) - /* - * Examine IEEE 754 bit-pattern. Infinity must have a special exponent - * pattern, and an empty mantissa. - */ - int has_mantissa; - int is_special_quantity; - - is_special_quantity = trio_is_special_quantity(number, &has_mantissa); - - return (is_special_quantity && !has_mantissa) - ? ((number < 0.0) ? -1 : 1) - : 0; - -#else - /* - * Fallback solution. - */ - int status; - -# if defined(TRIO_PLATFORM_UNIX) - void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN); -# endif - - double infinity = trio_pinf(); - - status = ((number == infinity) - ? 1 - : ((number == -infinity) ? -1 : 0)); - -# if defined(TRIO_PLATFORM_UNIX) - signal(SIGFPE, signal_handler); -# endif - - return status; - -#endif -} - -#if 0 - /* Temporary fix - this routine is not used anywhere */ -/** - Check for finity. - - @param number An arbitrary floating-point number. - @return Boolean value indicating whether or not the number is a finite. -*/ -TRIO_PUBLIC int -trio_isfinite -TRIO_ARGS1((number), - double number) -{ -#if defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isfinite) - /* - * C99 defines isfinite() as a macro. - */ - return isfinite(number); - -#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) - /* - * Microsoft Visual C++ and Borland C++ Builder use _finite(). - */ - return _finite(number); - -#elif defined(USE_IEEE_754) - /* - * Examine IEEE 754 bit-pattern. For finity we do not care about the - * mantissa. - */ - int dummy; - - return (! trio_is_special_quantity(number, &dummy)); - -#else - /* - * Fallback solution. - */ - return ((trio_isinf(number) == 0) && (trio_isnan(number) == 0)); - -#endif -} - -#endif - -/* - * The sign of NaN is always false - */ -TRIO_PUBLIC int -trio_fpclassify_and_signbit -TRIO_ARGS2((number, is_negative), - double number, - int *is_negative) -{ -#if defined(fpclassify) && defined(signbit) - /* - * C99 defines fpclassify() and signbit() as a macros - */ - *is_negative = signbit(number); - switch (fpclassify(number)) { - case FP_NAN: - return TRIO_FP_NAN; - case FP_INFINITE: - return TRIO_FP_INFINITE; - case FP_SUBNORMAL: - return TRIO_FP_SUBNORMAL; - case FP_ZERO: - return TRIO_FP_ZERO; - default: - return TRIO_FP_NORMAL; - } - -#else -# if defined(TRIO_COMPILER_DECC) - /* - * DECC has an fp_class() function. - */ -# define TRIO_FPCLASSIFY(n) fp_class(n) -# define TRIO_QUIET_NAN FP_QNAN -# define TRIO_SIGNALLING_NAN FP_SNAN -# define TRIO_POSITIVE_INFINITY FP_POS_INF -# define TRIO_NEGATIVE_INFINITY FP_NEG_INF -# define TRIO_POSITIVE_SUBNORMAL FP_POS_DENORM -# define TRIO_NEGATIVE_SUBNORMAL FP_NEG_DENORM -# define TRIO_POSITIVE_ZERO FP_POS_ZERO -# define TRIO_NEGATIVE_ZERO FP_NEG_ZERO -# define TRIO_POSITIVE_NORMAL FP_POS_NORM -# define TRIO_NEGATIVE_NORMAL FP_NEG_NORM - -# elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) - /* - * Microsoft Visual C++ and Borland C++ Builder have an _fpclass() - * function. - */ -# define TRIO_FPCLASSIFY(n) _fpclass(n) -# define TRIO_QUIET_NAN _FPCLASS_QNAN -# define TRIO_SIGNALLING_NAN _FPCLASS_SNAN -# define TRIO_POSITIVE_INFINITY _FPCLASS_PINF -# define TRIO_NEGATIVE_INFINITY _FPCLASS_NINF -# define TRIO_POSITIVE_SUBNORMAL _FPCLASS_PD -# define TRIO_NEGATIVE_SUBNORMAL _FPCLASS_ND -# define TRIO_POSITIVE_ZERO _FPCLASS_PZ -# define TRIO_NEGATIVE_ZERO _FPCLASS_NZ -# define TRIO_POSITIVE_NORMAL _FPCLASS_PN -# define TRIO_NEGATIVE_NORMAL _FPCLASS_NN - -# elif defined(FP_PLUS_NORM) - /* - * HP-UX 9.x and 10.x have an fpclassify() function, that is different - * from the C99 fpclassify() macro supported on HP-UX 11.x. - * - * AIX has class() for C, and _class() for C++, which returns the - * same values as the HP-UX fpclassify() function. - */ -# if defined(TRIO_PLATFORM_AIX) -# if defined(__cplusplus) -# define TRIO_FPCLASSIFY(n) _class(n) -# else -# define TRIO_FPCLASSIFY(n) class(n) -# endif -# else -# define TRIO_FPCLASSIFY(n) fpclassify(n) -# endif -# define TRIO_QUIET_NAN FP_QNAN -# define TRIO_SIGNALLING_NAN FP_SNAN -# define TRIO_POSITIVE_INFINITY FP_PLUS_INF -# define TRIO_NEGATIVE_INFINITY FP_MINUS_INF -# define TRIO_POSITIVE_SUBNORMAL FP_PLUS_DENORM -# define TRIO_NEGATIVE_SUBNORMAL FP_MINUS_DENORM -# define TRIO_POSITIVE_ZERO FP_PLUS_ZERO -# define TRIO_NEGATIVE_ZERO FP_MINUS_ZERO -# define TRIO_POSITIVE_NORMAL FP_PLUS_NORM -# define TRIO_NEGATIVE_NORMAL FP_MINUS_NORM -# endif - -# if defined(TRIO_FPCLASSIFY) - switch (TRIO_FPCLASSIFY(number)) { - case TRIO_QUIET_NAN: - case TRIO_SIGNALLING_NAN: - *is_negative = TRIO_FALSE; /* NaN has no sign */ - return TRIO_FP_NAN; - case TRIO_POSITIVE_INFINITY: - *is_negative = TRIO_FALSE; - return TRIO_FP_INFINITE; - case TRIO_NEGATIVE_INFINITY: - *is_negative = TRIO_TRUE; - return TRIO_FP_INFINITE; - case TRIO_POSITIVE_SUBNORMAL: - *is_negative = TRIO_FALSE; - return TRIO_FP_SUBNORMAL; - case TRIO_NEGATIVE_SUBNORMAL: - *is_negative = TRIO_TRUE; - return TRIO_FP_SUBNORMAL; - case TRIO_POSITIVE_ZERO: - *is_negative = TRIO_FALSE; - return TRIO_FP_ZERO; - case TRIO_NEGATIVE_ZERO: - *is_negative = TRIO_TRUE; - return TRIO_FP_ZERO; - case TRIO_POSITIVE_NORMAL: - *is_negative = TRIO_FALSE; - return TRIO_FP_NORMAL; - case TRIO_NEGATIVE_NORMAL: - *is_negative = TRIO_TRUE; - return TRIO_FP_NORMAL; - default: - /* Just in case... */ - *is_negative = (number < 0.0); - return TRIO_FP_NORMAL; - } - -# else - /* - * Fallback solution. - */ - int rc; - - if (number == 0.0) { - /* - * In IEEE 754 the sign of zero is ignored in comparisons, so we - * have to handle this as a special case by examining the sign bit - * directly. - */ -# if defined(USE_IEEE_754) - *is_negative = trio_is_negative(number); -# else - *is_negative = TRIO_FALSE; /* FIXME */ -# endif - return TRIO_FP_ZERO; - } - if (trio_isnan(number)) { - *is_negative = TRIO_FALSE; - return TRIO_FP_NAN; - } - if ((rc = trio_isinf(number))) { - *is_negative = (rc == -1); - return TRIO_FP_INFINITE; - } - if ((number > 0.0) && (number < DBL_MIN)) { - *is_negative = TRIO_FALSE; - return TRIO_FP_SUBNORMAL; - } - if ((number < 0.0) && (number > -DBL_MIN)) { - *is_negative = TRIO_TRUE; - return TRIO_FP_SUBNORMAL; - } - *is_negative = (number < 0.0); - return TRIO_FP_NORMAL; - -# endif -#endif -} - -/** - Examine the sign of a number. - - @param number An arbitrary floating-point number. - @return Boolean value indicating whether or not the number has the - sign bit set (i.e. is negative). -*/ -TRIO_PUBLIC int -trio_signbit -TRIO_ARGS1((number), - double number) -{ - int is_negative; - - (void)trio_fpclassify_and_signbit(number, &is_negative); - return is_negative; -} - -#if 0 - /* Temporary fix - this routine is not used in libxml */ -/** - Examine the class of a number. - - @param number An arbitrary floating-point number. - @return Enumerable value indicating the class of @p number -*/ -TRIO_PUBLIC int -trio_fpclassify -TRIO_ARGS1((number), - double number) -{ - int dummy; - - return trio_fpclassify_and_signbit(number, &dummy); -} - -#endif - -/** @} SpecialQuantities */ - -/************************************************************************* - * For test purposes. - * - * Add the following compiler option to include this test code. - * - * Unix : -DSTANDALONE - * VMS : /DEFINE=(STANDALONE) - */ -#if defined(STANDALONE) -# include - -static TRIO_CONST char * -getClassification -TRIO_ARGS1((type), - int type) -{ - switch (type) { - case TRIO_FP_INFINITE: - return "FP_INFINITE"; - case TRIO_FP_NAN: - return "FP_NAN"; - case TRIO_FP_NORMAL: - return "FP_NORMAL"; - case TRIO_FP_SUBNORMAL: - return "FP_SUBNORMAL"; - case TRIO_FP_ZERO: - return "FP_ZERO"; - default: - return "FP_UNKNOWN"; - } -} - -static void -print_class -TRIO_ARGS2((prefix, number), - TRIO_CONST char *prefix, - double number) -{ - printf("%-6s: %s %-15s %g\n", - prefix, - trio_signbit(number) ? "-" : "+", - getClassification(TRIO_FPCLASSIFY(number)), - number); -} - -int main(TRIO_NOARGS) -{ - double my_nan; - double my_pinf; - double my_ninf; -# if defined(TRIO_PLATFORM_UNIX) - void (*signal_handler) TRIO_PROTO((int)); -# endif - - my_nan = trio_nan(); - my_pinf = trio_pinf(); - my_ninf = trio_ninf(); - - print_class("Nan", my_nan); - print_class("PInf", my_pinf); - print_class("NInf", my_ninf); - print_class("PZero", 0.0); - print_class("NZero", -0.0); - print_class("PNorm", 1.0); - print_class("NNorm", -1.0); - print_class("PSub", 1.01e-307 - 1.00e-307); - print_class("NSub", 1.00e-307 - 1.01e-307); - - printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", - my_nan, - ((unsigned char *)&my_nan)[0], - ((unsigned char *)&my_nan)[1], - ((unsigned char *)&my_nan)[2], - ((unsigned char *)&my_nan)[3], - ((unsigned char *)&my_nan)[4], - ((unsigned char *)&my_nan)[5], - ((unsigned char *)&my_nan)[6], - ((unsigned char *)&my_nan)[7], - trio_isnan(my_nan), trio_isinf(my_nan)); - printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", - my_pinf, - ((unsigned char *)&my_pinf)[0], - ((unsigned char *)&my_pinf)[1], - ((unsigned char *)&my_pinf)[2], - ((unsigned char *)&my_pinf)[3], - ((unsigned char *)&my_pinf)[4], - ((unsigned char *)&my_pinf)[5], - ((unsigned char *)&my_pinf)[6], - ((unsigned char *)&my_pinf)[7], - trio_isnan(my_pinf), trio_isinf(my_pinf)); - printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", - my_ninf, - ((unsigned char *)&my_ninf)[0], - ((unsigned char *)&my_ninf)[1], - ((unsigned char *)&my_ninf)[2], - ((unsigned char *)&my_ninf)[3], - ((unsigned char *)&my_ninf)[4], - ((unsigned char *)&my_ninf)[5], - ((unsigned char *)&my_ninf)[6], - ((unsigned char *)&my_ninf)[7], - trio_isnan(my_ninf), trio_isinf(my_ninf)); - -# if defined(TRIO_PLATFORM_UNIX) - signal_handler = signal(SIGFPE, SIG_IGN); -# endif - - my_pinf = DBL_MAX + DBL_MAX; - my_ninf = -my_pinf; - my_nan = my_pinf / my_pinf; - -# if defined(TRIO_PLATFORM_UNIX) - signal(SIGFPE, signal_handler); -# endif - - printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", - my_nan, - ((unsigned char *)&my_nan)[0], - ((unsigned char *)&my_nan)[1], - ((unsigned char *)&my_nan)[2], - ((unsigned char *)&my_nan)[3], - ((unsigned char *)&my_nan)[4], - ((unsigned char *)&my_nan)[5], - ((unsigned char *)&my_nan)[6], - ((unsigned char *)&my_nan)[7], - trio_isnan(my_nan), trio_isinf(my_nan)); - printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", - my_pinf, - ((unsigned char *)&my_pinf)[0], - ((unsigned char *)&my_pinf)[1], - ((unsigned char *)&my_pinf)[2], - ((unsigned char *)&my_pinf)[3], - ((unsigned char *)&my_pinf)[4], - ((unsigned char *)&my_pinf)[5], - ((unsigned char *)&my_pinf)[6], - ((unsigned char *)&my_pinf)[7], - trio_isnan(my_pinf), trio_isinf(my_pinf)); - printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n", - my_ninf, - ((unsigned char *)&my_ninf)[0], - ((unsigned char *)&my_ninf)[1], - ((unsigned char *)&my_ninf)[2], - ((unsigned char *)&my_ninf)[3], - ((unsigned char *)&my_ninf)[4], - ((unsigned char *)&my_ninf)[5], - ((unsigned char *)&my_ninf)[6], - ((unsigned char *)&my_ninf)[7], - trio_isnan(my_ninf), trio_isinf(my_ninf)); - - return 0; -} -#endif diff --git a/trionan.h b/trionan.h deleted file mode 100644 index eac0e6f1..00000000 --- a/trionan.h +++ /dev/null @@ -1,84 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2001 Bjorn Reese - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************/ - -#ifndef TRIO_NAN_H -#define TRIO_NAN_H - -#include "triodef.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - TRIO_FP_INFINITE, - TRIO_FP_NAN, - TRIO_FP_NORMAL, - TRIO_FP_SUBNORMAL, - TRIO_FP_ZERO -}; - -/* - * Return NaN (Not-a-Number). - */ -TRIO_PUBLIC double trio_nan TRIO_PROTO((void)); - -/* - * Return positive infinity. - */ -TRIO_PUBLIC double trio_pinf TRIO_PROTO((void)); - -/* - * Return negative infinity. - */ -TRIO_PUBLIC double trio_ninf TRIO_PROTO((void)); - -/* - * Return negative zero. - */ -TRIO_PUBLIC double trio_nzero TRIO_PROTO((TRIO_NOARGS)); - -/* - * If number is a NaN return non-zero, otherwise return zero. - */ -TRIO_PUBLIC int trio_isnan TRIO_PROTO((double number)); - -/* - * If number is positive infinity return 1, if number is negative - * infinity return -1, otherwise return 0. - */ -TRIO_PUBLIC int trio_isinf TRIO_PROTO((double number)); - -/* - * If number is finite return non-zero, otherwise return zero. - */ -#if 0 - /* Temporary fix - these 2 routines not used in libxml */ -TRIO_PUBLIC int trio_isfinite TRIO_PROTO((double number)); - -TRIO_PUBLIC int trio_fpclassify TRIO_PROTO((double number)); -#endif - -TRIO_PUBLIC int trio_signbit TRIO_PROTO((double number)); - -TRIO_PUBLIC int trio_fpclassify_and_signbit TRIO_PROTO((double number, int *is_negative)); - -#ifdef __cplusplus -} -#endif - -#endif /* TRIO_NAN_H */ diff --git a/triop.h b/triop.h deleted file mode 100644 index 6d486f86..00000000 --- a/triop.h +++ /dev/null @@ -1,150 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2000 Bjorn Reese and Daniel Stenberg. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************ - * - * Private functions, types, etc. used for callback functions. - * - * The ref pointer is an opaque type and should remain as such. - * Private data must only be accessible through the getter and - * setter functions. - * - ************************************************************************/ - -#ifndef TRIO_TRIOP_H -#define TRIO_TRIOP_H - -#include "triodef.h" - -#include -#if defined(TRIO_COMPILER_ANCIENT) -# include -#else -# include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef TRIO_C99 -# define TRIO_C99 1 -#endif -#ifndef TRIO_BSD -# define TRIO_BSD 1 -#endif -#ifndef TRIO_GNU -# define TRIO_GNU 1 -#endif -#ifndef TRIO_MISC -# define TRIO_MISC 1 -#endif -#ifndef TRIO_UNIX98 -# define TRIO_UNIX98 1 -#endif -#ifndef TRIO_MICROSOFT -# define TRIO_MICROSOFT 1 -#endif -#ifndef TRIO_EXTENSION -# define TRIO_EXTENSION 1 -#endif -#ifndef TRIO_WIDECHAR /* Does not work yet. Do not enable */ -# define TRIO_WIDECHAR 0 -#endif -#ifndef TRIO_ERRORS -# define TRIO_ERRORS 1 -#endif - -#ifndef TRIO_MALLOC -# define TRIO_MALLOC(n) malloc(n) -#endif -#ifndef TRIO_REALLOC -# define TRIO_REALLOC(x,n) realloc((x),(n)) -#endif -#ifndef TRIO_FREE -# define TRIO_FREE(x) free(x) -#endif - - -/************************************************************************* - * User-defined specifiers - */ - -typedef int (*trio_callback_t) TRIO_PROTO((trio_pointer_t)); - -trio_pointer_t trio_register TRIO_PROTO((trio_callback_t callback, const char *name)); -void trio_unregister TRIO_PROTO((trio_pointer_t handle)); - -TRIO_CONST char *trio_get_format TRIO_PROTO((trio_pointer_t ref)); -trio_pointer_t trio_get_argument TRIO_PROTO((trio_pointer_t ref)); - -/* Modifiers */ -int trio_get_width TRIO_PROTO((trio_pointer_t ref)); -void trio_set_width TRIO_PROTO((trio_pointer_t ref, int width)); -int trio_get_precision TRIO_PROTO((trio_pointer_t ref)); -void trio_set_precision TRIO_PROTO((trio_pointer_t ref, int precision)); -int trio_get_base TRIO_PROTO((trio_pointer_t ref)); -void trio_set_base TRIO_PROTO((trio_pointer_t ref, int base)); -int trio_get_padding TRIO_PROTO((trio_pointer_t ref)); -void trio_set_padding TRIO_PROTO((trio_pointer_t ref, int is_padding)); -int trio_get_short TRIO_PROTO((trio_pointer_t ref)); /* h */ -void trio_set_shortshort TRIO_PROTO((trio_pointer_t ref, int is_shortshort)); -int trio_get_shortshort TRIO_PROTO((trio_pointer_t ref)); /* hh */ -void trio_set_short TRIO_PROTO((trio_pointer_t ref, int is_short)); -int trio_get_long TRIO_PROTO((trio_pointer_t ref)); /* l */ -void trio_set_long TRIO_PROTO((trio_pointer_t ref, int is_long)); -int trio_get_longlong TRIO_PROTO((trio_pointer_t ref)); /* ll */ -void trio_set_longlong TRIO_PROTO((trio_pointer_t ref, int is_longlong)); -int trio_get_longdouble TRIO_PROTO((trio_pointer_t ref)); /* L */ -void trio_set_longdouble TRIO_PROTO((trio_pointer_t ref, int is_longdouble)); -int trio_get_alternative TRIO_PROTO((trio_pointer_t ref)); /* # */ -void trio_set_alternative TRIO_PROTO((trio_pointer_t ref, int is_alternative)); -int trio_get_alignment TRIO_PROTO((trio_pointer_t ref)); /* - */ -void trio_set_alignment TRIO_PROTO((trio_pointer_t ref, int is_leftaligned)); -int trio_get_spacing TRIO_PROTO((trio_pointer_t ref)); /* TRIO_PROTO((space) */ -void trio_set_spacing TRIO_PROTO((trio_pointer_t ref, int is_space)); -int trio_get_sign TRIO_PROTO((trio_pointer_t ref)); /* + */ -void trio_set_sign TRIO_PROTO((trio_pointer_t ref, int is_showsign)); -int trio_get_quote TRIO_PROTO((trio_pointer_t ref)); /* ' */ -void trio_set_quote TRIO_PROTO((trio_pointer_t ref, int is_quote)); -int trio_get_upper TRIO_PROTO((trio_pointer_t ref)); -void trio_set_upper TRIO_PROTO((trio_pointer_t ref, int is_upper)); -#if TRIO_C99 -int trio_get_largest TRIO_PROTO((trio_pointer_t ref)); /* j */ -void trio_set_largest TRIO_PROTO((trio_pointer_t ref, int is_largest)); -int trio_get_ptrdiff TRIO_PROTO((trio_pointer_t ref)); /* t */ -void trio_set_ptrdiff TRIO_PROTO((trio_pointer_t ref, int is_ptrdiff)); -int trio_get_size TRIO_PROTO((trio_pointer_t ref)); /* z / Z */ -void trio_set_size TRIO_PROTO((trio_pointer_t ref, int is_size)); -#endif - -/* Printing */ -int trio_print_ref TRIO_PROTO((trio_pointer_t ref, const char *format, ...)); -int trio_vprint_ref TRIO_PROTO((trio_pointer_t ref, const char *format, va_list args)); -int trio_printv_ref TRIO_PROTO((trio_pointer_t ref, const char *format, trio_pointer_t *args)); - -void trio_print_int TRIO_PROTO((trio_pointer_t ref, int number)); -void trio_print_uint TRIO_PROTO((trio_pointer_t ref, unsigned int number)); -/* void trio_print_long TRIO_PROTO((trio_pointer_t ref, long number)); */ -/* void trio_print_ulong TRIO_PROTO((trio_pointer_t ref, unsigned long number)); */ -void trio_print_double TRIO_PROTO((trio_pointer_t ref, double number)); -void trio_print_string TRIO_PROTO((trio_pointer_t ref, char *string)); -void trio_print_pointer TRIO_PROTO((trio_pointer_t ref, trio_pointer_t pointer)); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* TRIO_TRIOP_H */ diff --git a/triostr.c b/triostr.c deleted file mode 100644 index 5937a44c..00000000 --- a/triostr.c +++ /dev/null @@ -1,2112 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************/ - -/************************************************************************* - * Include files - */ - -#include -#include -#include -#include -#include -#include "triodef.h" -#include "triostr.h" - -/************************************************************************* - * Definitions - */ - -#if !defined(TRIO_STRING_PUBLIC) -# define TRIO_STRING_PUBLIC TRIO_PUBLIC -#endif -#if !defined(TRIO_STRING_PRIVATE) -# define TRIO_STRING_PRIVATE TRIO_PRIVATE -#endif - -#if !defined(NULL) -# define NULL 0 -#endif -#if !defined(NIL) -# define NIL ((char)0) -#endif -#if !defined(FALSE) -# define FALSE (1 == 0) -# define TRUE (! FALSE) -#endif -#if !defined(BOOLEAN_T) -# define BOOLEAN_T int -#endif - -#ifdef __VMS -# define USE_STRTOD -#elif defined(TRIO_COMPILER_SUPPORTS_C99) -# define USE_STRTOD -# define USE_STRTOF -#elif defined(TRIO_COMPILER_MSVC) -# define USE_STRTOD -#endif - -#if defined(TRIO_PLATFORM_UNIX) -# define USE_STRCASECMP -# define USE_STRNCASECMP -# if defined(TRIO_PLATFORM_SUNOS) -# define USE_SYS_ERRLIST -# else -# define USE_STRERROR -# endif -# if defined(TRIO_PLATFORM_QNX) -# define strcasecmp(x,y) stricmp(x,y) -# define strncasecmp(x,y,n) strnicmp(x,y,n) -# endif -#elif defined(TRIO_PLATFORM_WIN32) -# define USE_STRCASECMP -# if defined(_WIN32_WCE) -# define strcasecmp(x,y) _stricmp(x,y) -# else -# define strcasecmp(x,y) strcmpi(x,y) -# endif -#elif defined(TRIO_PLATFORM_OS400) -# define USE_STRCASECMP -# define USE_STRNCASECMP -# include -#endif - -#if !(defined(TRIO_PLATFORM_SUNOS)) -# define USE_TOLOWER -# define USE_TOUPPER -#endif - -/************************************************************************* - * Structures - */ - -struct _trio_string_t -{ - char *content; - size_t length; - size_t allocated; -}; - -/************************************************************************* - * Constants - */ - -#if !defined(TRIO_MINIMAL) -static TRIO_CONST char rcsid[] = "@(#)$Id$"; -#endif - -/************************************************************************* - * Static String Functions - */ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_static.h" -#endif -/** @addtogroup StaticStrings - @{ -*/ - -/** - Create new string. - - @param size Size of new string. - @return Pointer to string, or NULL if allocation failed. -*/ -TRIO_STRING_PUBLIC char * -trio_create -TRIO_ARGS1((size), - size_t size) -{ - return (char *)TRIO_MALLOC(size); -} - - -/** - Destroy string. - - @param string String to be freed. -*/ -TRIO_STRING_PUBLIC void -trio_destroy -TRIO_ARGS1((string), - char *string) -{ - if (string) - { - TRIO_FREE(string); - } -} - - -/** - Count the number of characters in a string. - - @param string String to measure. - @return Number of characters in @string. -*/ -TRIO_STRING_PUBLIC size_t -trio_length -TRIO_ARGS1((string), - TRIO_CONST char *string) -{ - return strlen(string); -} - - -#if !defined(TRIO_MINIMAL) -/** - Append @p source at the end of @p target. - - @param target Target string. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chunk with sufficient room to - contain the @p target string and @p source string. - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -TRIO_STRING_PUBLIC int -trio_append -TRIO_ARGS2((target, source), - char *target, - TRIO_CONST char *source) -{ - assert(target); - assert(source); - - return (strcat(target, source) != NULL); -} -#endif /* !defined(TRIO_MINIMAL) */ - -#if !defined(TRIO_MINIMAL) -/** - Append at most @p max characters from @p source to @p target. - - @param target Target string. - @param max Maximum number of characters to append. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chuck with sufficient room to - contain the @p target string and the @p source string (at most @p max - characters). - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -TRIO_STRING_PUBLIC int -trio_append_max -TRIO_ARGS3((target, max, source), - char *target, - size_t max, - TRIO_CONST char *source) -{ - size_t length; - - assert(target); - assert(source); - - length = trio_length(target); - - if (max > length) - { - strncat(target, source, max - length - 1); - } - return TRUE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Determine if a string contains a substring. - - @param string String to be searched. - @param substring String to be found. - @return Boolean value indicating success or failure. -*/ -TRIO_STRING_PUBLIC int -trio_contains -TRIO_ARGS2((string, substring), - TRIO_CONST char *string, - TRIO_CONST char *substring) -{ - assert(string); - assert(substring); - - return (0 != strstr(string, substring)); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Copy @p source to @p target. - - @param target Target string. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chunk with sufficient room to - contain the @p source string. - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -TRIO_STRING_PUBLIC int -trio_copy -TRIO_ARGS2((target, source), - char *target, - TRIO_CONST char *source) -{ - assert(target); - assert(source); - - (void)strcpy(target, source); - return TRUE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Copy at most @p max characters from @p source to @p target. - - @param target Target string. - @param max Maximum number of characters to append. - @param source Source string. - @return Boolean value indicating success or failure. - - @pre @p target must point to a memory chunk with sufficient room to - contain the @p source string (at most @p max characters). - @pre No boundary checking is performed, so insufficient memory will - result in a buffer overrun. - @post @p target will be zero terminated. -*/ -TRIO_STRING_PUBLIC int -trio_copy_max -TRIO_ARGS3((target, max, source), - char *target, - size_t max, - TRIO_CONST char *source) -{ - assert(target); - assert(source); - assert(max > 0); /* Includes != 0 */ - - (void)strncpy(target, source, max - 1); - target[max - 1] = (char)0; - return TRUE; -} - - -/* - * TrioDuplicateMax - */ -TRIO_STRING_PRIVATE char * -TrioDuplicateMax -TRIO_ARGS2((source, size), - TRIO_CONST char *source, - size_t size) -{ - char *target; - - assert(source); - - /* Make room for string plus a terminating zero */ - size++; - target = trio_create(size); - if (target) - { - trio_copy_max(target, size, source); - } - return target; -} - - -/** - Duplicate @p source. - - @param source Source string. - @return A copy of the @p source string. - - @post @p target will be zero terminated. -*/ -TRIO_STRING_PUBLIC char * -trio_duplicate -TRIO_ARGS1((source), - TRIO_CONST char *source) -{ - return TrioDuplicateMax(source, trio_length(source)); -} - - -#if !defined(TRIO_MINIMAL) -/** - Duplicate at most @p max characters of @p source. - - @param source Source string. - @param max Maximum number of characters to duplicate. - @return A copy of the @p source string. - - @post @p target will be zero terminated. -*/ -TRIO_STRING_PUBLIC char * -trio_duplicate_max TRIO_ARGS2((source, max), - TRIO_CONST char *source, - size_t max) -{ - size_t length; - - assert(source); - assert(max > 0); - - length = trio_length(source); - if (length > max) - { - length = max; - } - return TrioDuplicateMax(source, length); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Compare if two strings are equal. - - @param first First string. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Case-insensitive comparison. -*/ -TRIO_STRING_PUBLIC int -trio_equal -TRIO_ARGS2((first, second), - TRIO_CONST char *first, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - - if ((first != NULL) && (second != NULL)) - { -#if defined(USE_STRCASECMP) - return (0 == strcasecmp(first, second)); -#else - while ((*first != NIL) && (*second != NIL)) - { - if (trio_to_upper(*first) != trio_to_upper(*second)) - { - break; - } - first++; - second++; - } - return ((*first == NIL) && (*second == NIL)); -#endif - } - return FALSE; -} - - -/** - Compare if two strings are equal. - - @param first First string. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Case-sensitive comparison. -*/ -TRIO_STRING_PUBLIC int -trio_equal_case -TRIO_ARGS2((first, second), - TRIO_CONST char *first, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - - if ((first != NULL) && (second != NULL)) - { - return (0 == strcmp(first, second)); - } - return FALSE; -} - - -#if !defined(TRIO_MINIMAL) -/** - Compare if two strings up until the first @p max characters are equal. - - @param first First string. - @param max Maximum number of characters to compare. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Case-sensitive comparison. -*/ -TRIO_STRING_PUBLIC int -trio_equal_case_max -TRIO_ARGS3((first, max, second), - TRIO_CONST char *first, - size_t max, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - - if ((first != NULL) && (second != NULL)) - { - return (0 == strncmp(first, second, max)); - } - return FALSE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Compare if two strings are equal. - - @param first First string. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Collating characters are considered equal. -*/ -TRIO_STRING_PUBLIC int -trio_equal_locale -TRIO_ARGS2((first, second), - TRIO_CONST char *first, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - -#if defined(LC_COLLATE) - return (strcoll(first, second) == 0); -#else - return trio_equal(first, second); -#endif -} - - -/** - Compare if two strings up until the first @p max characters are equal. - - @param first First string. - @param max Maximum number of characters to compare. - @param second Second string. - @return Boolean indicating whether the two strings are equal or not. - - Case-insensitive comparison. -*/ -TRIO_STRING_PUBLIC int -trio_equal_max -TRIO_ARGS3((first, max, second), - TRIO_CONST char *first, - size_t max, - TRIO_CONST char *second) -{ - assert(first); - assert(second); - - if ((first != NULL) && (second != NULL)) - { -#if defined(USE_STRNCASECMP) - return (0 == strncasecmp(first, second, max)); -#else - /* Not adequately tested yet */ - size_t cnt = 0; - while ((*first != NIL) && (*second != NIL) && (cnt <= max)) - { - if (trio_to_upper(*first) != trio_to_upper(*second)) - { - break; - } - first++; - second++; - cnt++; - } - return ((cnt == max) || ((*first == NIL) && (*second == NIL))); -#endif - } - return FALSE; -} - - -/** - Provide a textual description of an error code (errno). - - @param error_number Error number. - @return Textual description of @p error_number. -*/ -TRIO_STRING_PUBLIC TRIO_CONST char * -trio_error -TRIO_ARGS1((error_number), - int error_number) -{ -#if defined(USE_STRERROR) - - return strerror(error_number); - -#elif defined(USE_SYS_ERRLIST) - - extern char *sys_errlist[]; - extern int sys_nerr; - - return ((error_number < 0) || (error_number >= sys_nerr)) - ? "unknown" - : sys_errlist[error_number]; - -#else - - return "unknown"; - -#endif -} - - -#if !defined(TRIO_MINIMAL) && !defined(_WIN32_WCE) -/** - Format the date/time according to @p format. - - @param target Target string. - @param max Maximum number of characters to format. - @param format Formatting string. - @param datetime Date/time structure. - @return Number of formatted characters. - - The formatting string accepts the same specifiers as the standard C - function strftime. -*/ -TRIO_STRING_PUBLIC size_t -trio_format_date_max -TRIO_ARGS4((target, max, format, datetime), - char *target, - size_t max, - TRIO_CONST char *format, - TRIO_CONST struct tm *datetime) -{ - assert(target); - assert(format); - assert(datetime); - assert(max > 0); - - return strftime(target, max, format, datetime); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Calculate a hash value for a string. - - @param string String to be calculated on. - @param type Hash function. - @return Calculated hash value. - - @p type can be one of the following - @li @c TRIO_HASH_PLAIN Plain hash function. -*/ -TRIO_STRING_PUBLIC unsigned long -trio_hash -TRIO_ARGS2((string, type), - TRIO_CONST char *string, - int type) -{ - unsigned long value = 0L; - char ch; - - assert(string); - - switch (type) - { - case TRIO_HASH_PLAIN: - while ( (ch = *string++) != NIL ) - { - value *= 31; - value += (unsigned long)ch; - } - break; - default: - assert(FALSE); - break; - } - return value; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Find first occurrence of a character in a string. - - @param string String to be searched. - @param character Character to be found. - @param A pointer to the found character, or NULL if character was not found. - */ -TRIO_STRING_PUBLIC char * -trio_index -TRIO_ARGS2((string, character), - TRIO_CONST char *string, - int character) -{ - assert(string); - - return strchr(string, character); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Find last occurrence of a character in a string. - - @param string String to be searched. - @param character Character to be found. - @param A pointer to the found character, or NULL if character was not found. - */ -TRIO_STRING_PUBLIC char * -trio_index_last -TRIO_ARGS2((string, character), - TRIO_CONST char *string, - int character) -{ - assert(string); - - return strchr(string, character); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Convert the alphabetic letters in the string to lower-case. - - @param target String to be converted. - @return Number of processed characters (converted or not). -*/ -TRIO_STRING_PUBLIC int -trio_lower -TRIO_ARGS1((target), - char *target) -{ - assert(target); - - return trio_span_function(target, target, trio_to_lower); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Compare two strings using wildcards. - - @param string String to be searched. - @param pattern Pattern, including wildcards, to search for. - @return Boolean value indicating success or failure. - - Case-insensitive comparison. - - The following wildcards can be used - @li @c * Match any number of characters. - @li @c ? Match a single character. -*/ -TRIO_STRING_PUBLIC int -trio_match -TRIO_ARGS2((string, pattern), - TRIO_CONST char *string, - TRIO_CONST char *pattern) -{ - assert(string); - assert(pattern); - - for (; ('*' != *pattern); ++pattern, ++string) - { - if (NIL == *string) - { - return (NIL == *pattern); - } - if ((trio_to_upper((int)*string) != trio_to_upper((int)*pattern)) - && ('?' != *pattern)) - { - return FALSE; - } - } - /* two-line patch to prevent *too* much recursiveness: */ - while ('*' == pattern[1]) - pattern++; - - do - { - if ( trio_match(string, &pattern[1]) ) - { - return TRUE; - } - } - while (*string++); - - return FALSE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Compare two strings using wildcards. - - @param string String to be searched. - @param pattern Pattern, including wildcards, to search for. - @return Boolean value indicating success or failure. - - Case-sensitive comparison. - - The following wildcards can be used - @li @c * Match any number of characters. - @li @c ? Match a single character. -*/ -TRIO_STRING_PUBLIC int -trio_match_case -TRIO_ARGS2((string, pattern), - TRIO_CONST char *string, - TRIO_CONST char *pattern) -{ - assert(string); - assert(pattern); - - for (; ('*' != *pattern); ++pattern, ++string) - { - if (NIL == *string) - { - return (NIL == *pattern); - } - if ((*string != *pattern) - && ('?' != *pattern)) - { - return FALSE; - } - } - /* two-line patch to prevent *too* much recursiveness: */ - while ('*' == pattern[1]) - pattern++; - - do - { - if ( trio_match_case(string, &pattern[1]) ) - { - return TRUE; - } - } - while (*string++); - - return FALSE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Execute a function on each character in string. - - @param target Target string. - @param source Source string. - @param Function Function to be executed. - @return Number of processed characters. -*/ -TRIO_STRING_PUBLIC size_t -trio_span_function -TRIO_ARGS3((target, source, Function), - char *target, - TRIO_CONST char *source, - int (*Function) TRIO_PROTO((int))) -{ - size_t count = 0; - - assert(target); - assert(source); - assert(Function); - - while (*source != NIL) - { - *target++ = Function(*source++); - count++; - } - return count; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Search for a substring in a string. - - @param string String to be searched. - @param substring String to be found. - @return Pointer to first occurrence of @p substring in @p string, or NULL - if no match was found. -*/ -TRIO_STRING_PUBLIC char * -trio_substring -TRIO_ARGS2((string, substring), - TRIO_CONST char *string, - TRIO_CONST char *substring) -{ - assert(string); - assert(substring); - - return strstr(string, substring); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Search for a substring in the first @p max characters of a string. - - @param string String to be searched. - @param max Maximum characters to be searched. - @param substring String to be found. - @return Pointer to first occurrence of @p substring in @p string, or NULL - if no match was found. -*/ -TRIO_STRING_PUBLIC char * -trio_substring_max -TRIO_ARGS3((string, max, substring), - TRIO_CONST char *string, - size_t max, - TRIO_CONST char *substring) -{ - size_t count; - size_t size; - char *result = NULL; - - assert(string); - assert(substring); - - size = trio_length(substring); - if (size <= max) - { - for (count = 0; count <= max - size; count++) - { - if (trio_equal_max(substring, size, &string[count])) - { - result = (char *)&string[count]; - break; - } - } - } - return result; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Tokenize string. - - @param string String to be tokenized. - @param tokens String containing list of delimiting characters. - @return Start of new token. - - @warning @p string will be destroyed. -*/ -TRIO_STRING_PUBLIC char * -trio_tokenize -TRIO_ARGS2((string, delimiters), - char *string, - TRIO_CONST char *delimiters) -{ - assert(delimiters); - - return strtok(string, delimiters); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Convert string to floating-point number. - - @param source String to be converted. - @param endp Pointer to end of the converted string. - @return A floating-point number. - - The following Extended Backus-Naur form is used - @verbatim - double ::= [ ] - ( | - | - ) - [ [ ] ] - number ::= 1*( ) - digit ::= ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ) - exponential ::= ( 'e' | 'E' ) - sign ::= ( '-' | '+' ) - decimal_point ::= '.' - @endverbatim -*/ -/* FIXME: Add EBNF for hex-floats */ -TRIO_STRING_PUBLIC trio_long_double_t -trio_to_long_double -TRIO_ARGS2((source, endp), - TRIO_CONST char *source, - char **endp) -{ -#if defined(USE_STRTOLD) - return strtold(source, endp); -#else - int isNegative = FALSE; - int isExponentNegative = FALSE; - trio_long_double_t integer = 0.0; - trio_long_double_t fraction = 0.0; - unsigned long exponent = 0; - trio_long_double_t base; - trio_long_double_t fracdiv = 1.0; - trio_long_double_t value = 0.0; - - /* First try hex-floats */ - if ((source[0] == '0') && ((source[1] == 'x') || (source[1] == 'X'))) - { - base = 16.0; - source += 2; - while (isxdigit((int)*source)) - { - integer *= base; - integer += (isdigit((int)*source) - ? (*source - '0') - : 10 + (trio_to_upper((int)*source) - 'A')); - source++; - } - if (*source == '.') - { - source++; - while (isxdigit((int)*source)) - { - fracdiv /= base; - fraction += fracdiv * (isdigit((int)*source) - ? (*source - '0') - : 10 + (trio_to_upper((int)*source) - 'A')); - source++; - } - if ((*source == 'p') || (*source == 'P')) - { - source++; - if ((*source == '+') || (*source == '-')) - { - isExponentNegative = (*source == '-'); - source++; - } - while (isdigit((int)*source)) - { - exponent *= 10; - exponent += (*source - '0'); - source++; - } - } - } - /* For later use with exponent */ - base = 2.0; - } - else /* Then try normal decimal floats */ - { - base = 10.0; - isNegative = (*source == '-'); - /* Skip sign */ - if ((*source == '+') || (*source == '-')) - source++; - - /* Integer part */ - while (isdigit((int)*source)) - { - integer *= base; - integer += (*source - '0'); - source++; - } - - if (*source == '.') - { - source++; /* skip decimal point */ - while (isdigit((int)*source)) - { - fracdiv /= base; - fraction += (*source - '0') * fracdiv; - source++; - } - } - if ((*source == 'e') - || (*source == 'E') -#if TRIO_MICROSOFT - || (*source == 'd') - || (*source == 'D') -#endif - ) - { - source++; /* Skip exponential indicator */ - isExponentNegative = (*source == '-'); - if ((*source == '+') || (*source == '-')) - source++; - while (isdigit((int)*source)) - { - exponent *= (int)base; - exponent += (*source - '0'); - source++; - } - } - } - - value = integer + fraction; - if (exponent != 0) - { - if (isExponentNegative) - value /= pow(base, (double)exponent); - else - value *= pow(base, (double)exponent); - } - if (isNegative) - value = -value; - - if (endp) - *endp = (char *)source; - return value; -#endif -} - - -/** - Convert string to floating-point number. - - @param source String to be converted. - @param endp Pointer to end of the converted string. - @return A floating-point number. - - See @ref trio_to_long_double. -*/ -TRIO_STRING_PUBLIC double -trio_to_double -TRIO_ARGS2((source, endp), - TRIO_CONST char *source, - char **endp) -{ -#if defined(USE_STRTOD) - return strtod(source, endp); -#else - return (double)trio_to_long_double(source, endp); -#endif -} - -#if !defined(TRIO_MINIMAL) -/** - Convert string to floating-point number. - - @param source String to be converted. - @param endp Pointer to end of the converted string. - @return A floating-point number. - - See @ref trio_to_long_double. -*/ -TRIO_STRING_PUBLIC float -trio_to_float -TRIO_ARGS2((source, endp), - TRIO_CONST char *source, - char **endp) -{ -#if defined(USE_STRTOF) - return strtof(source, endp); -#else - return (float)trio_to_long_double(source, endp); -#endif -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Convert string to signed integer. - - @param string String to be converted. - @param endp Pointer to end of converted string. - @param base Radix number of number. -*/ -TRIO_STRING_PUBLIC long -trio_to_long -TRIO_ARGS3((string, endp, base), - TRIO_CONST char *string, - char **endp, - int base) -{ - assert(string); - assert((base >= 2) && (base <= 36)); - - return strtol(string, endp, base); -} - - -#if !defined(TRIO_MINIMAL) -/** - Convert one alphabetic letter to lower-case. - - @param source The letter to be converted. - @return The converted letter. -*/ -TRIO_STRING_PUBLIC int -trio_to_lower -TRIO_ARGS1((source), - int source) -{ -#if defined(USE_TOLOWER) - - return tolower(source); - -#else - - /* Does not handle locales or non-contiguous alphabetic characters */ - return ((source >= (int)'A') && (source <= (int)'Z')) - ? source - 'A' + 'a' - : source; - -#endif -} -#endif /* !defined(TRIO_MINIMAL) */ - -#if !defined(TRIO_MINIMAL) -/** - Convert string to unsigned integer. - - @param string String to be converted. - @param endp Pointer to end of converted string. - @param base Radix number of number. -*/ -TRIO_STRING_PUBLIC unsigned long -trio_to_unsigned_long -TRIO_ARGS3((string, endp, base), - TRIO_CONST char *string, - char **endp, - int base) -{ - assert(string); - assert((base >= 2) && (base <= 36)); - - return strtoul(string, endp, base); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Convert one alphabetic letter to upper-case. - - @param source The letter to be converted. - @return The converted letter. -*/ -TRIO_STRING_PUBLIC int -trio_to_upper -TRIO_ARGS1((source), - int source) -{ -#if defined(USE_TOUPPER) - - return toupper(source); - -#else - - /* Does not handle locales or non-contiguous alphabetic characters */ - return ((source >= (int)'a') && (source <= (int)'z')) - ? source - 'a' + 'A' - : source; - -#endif -} - -#if !defined(TRIO_MINIMAL) -/** - Convert the alphabetic letters in the string to upper-case. - - @param target The string to be converted. - @return The number of processed characters (converted or not). -*/ -TRIO_STRING_PUBLIC int -trio_upper -TRIO_ARGS1((target), - char *target) -{ - assert(target); - - return trio_span_function(target, target, trio_to_upper); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** @} End of StaticStrings */ - - -/************************************************************************* - * Dynamic String Functions - */ - -#if defined(TRIO_DOCUMENTATION) -# include "doc/doc_dynamic.h" -#endif -/** @addtogroup DynamicStrings - @{ -*/ - -/* - * TrioStringAlloc - */ -TRIO_STRING_PRIVATE trio_string_t * -TrioStringAlloc(TRIO_NOARGS) -{ - trio_string_t *self; - - self = (trio_string_t *)TRIO_MALLOC(sizeof(trio_string_t)); - if (self) - { - self->content = NULL; - self->length = 0; - self->allocated = 0; - } - return self; -} - - -/* - * TrioStringGrow - * - * The size of the string will be increased by 'delta' characters. If - * 'delta' is zero, the size will be doubled. - */ -TRIO_STRING_PRIVATE BOOLEAN_T -TrioStringGrow -TRIO_ARGS2((self, delta), - trio_string_t *self, - size_t delta) -{ - BOOLEAN_T status = FALSE; - char *new_content; - size_t new_size; - - new_size = (delta == 0) - ? ( (self->allocated == 0) ? 1 : self->allocated * 2 ) - : self->allocated + delta; - - new_content = (char *)TRIO_REALLOC(self->content, new_size); - if (new_content) - { - self->content = new_content; - self->allocated = new_size; - status = TRUE; - } - return status; -} - - -#if !defined(TRIO_MINIMAL) -/* - * TrioStringGrowTo - * - * The size of the string will be increased to 'length' plus one characters. - * If 'length' is less than the original size, the original size will be - * used (that is, the size of the string is never decreased). - */ -TRIO_STRING_PRIVATE BOOLEAN_T -TrioStringGrowTo -TRIO_ARGS2((self, length), - trio_string_t *self, - size_t length) -{ - length++; /* Room for terminating zero */ - return (self->allocated < length) - ? TrioStringGrow(self, length - self->allocated) - : TRUE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/** - Create a new dynamic string. - - @param initial_size Initial size of the buffer. - @return Newly allocated dynamic string, or NULL if memory allocation failed. -*/ -TRIO_STRING_PUBLIC trio_string_t * -trio_string_create -TRIO_ARGS1((initial_size), - int initial_size) -{ - trio_string_t *self; - - self = TrioStringAlloc(); - if (self) - { - if (TrioStringGrow(self, - (size_t)((initial_size > 0) ? initial_size : 1))) - { - self->content[0] = (char)0; - self->allocated = initial_size; - } - else - { - trio_string_destroy(self); - self = NULL; - } - } - return self; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Deallocate the dynamic string and its contents. - - @param self Dynamic string -*/ -TRIO_STRING_PUBLIC void -trio_string_destroy -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - if (self) - { - trio_destroy(self->content); - TRIO_FREE(self); - } -} - - -#if !defined(TRIO_MINIMAL) -/** - Get a pointer to the content. - - @param self Dynamic string. - @param offset Offset into content. - @return Pointer to the content. - - @p Offset can be zero, positive, or negative. If @p offset is zero, - then the start of the content will be returned. If @p offset is positive, - then a pointer to @p offset number of characters from the beginning of the - content is returned. If @p offset is negative, then a pointer to @p offset - number of characters from the ending of the string, starting at the - terminating zero, is returned. -*/ -TRIO_STRING_PUBLIC char * -trio_string_get -TRIO_ARGS2((self, offset), - trio_string_t *self, - int offset) -{ - char *result = NULL; - - assert(self); - - if (self->content != NULL) - { - if (self->length == 0) - { - (void)trio_string_length(self); - } - if (offset >= 0) - { - if (offset > (int)self->length) - { - offset = self->length; - } - } - else - { - offset += self->length + 1; - if (offset < 0) - { - offset = 0; - } - } - result = &(self->content[offset]); - } - return result; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/** - Extract the content. - - @param self Dynamic String - @return Content of dynamic string. - - The content is removed from the dynamic string. This enables destruction - of the dynamic string without deallocation of the content. -*/ -TRIO_STRING_PUBLIC char * -trio_string_extract -TRIO_ARGS1((self), - trio_string_t *self) -{ - char *result; - - assert(self); - - result = self->content; - /* FIXME: Allocate new empty buffer? */ - self->content = NULL; - self->length = self->allocated = 0; - return result; -} - - -#if !defined(TRIO_MINIMAL) -/** - Set the content of the dynamic string. - - @param self Dynamic String - @param buffer The new content. - - Sets the content of the dynamic string to a copy @p buffer. - An existing content will be deallocated first, if necessary. - - @remark - This function will make a copy of @p buffer. - You are responsible for deallocating @p buffer yourself. -*/ -TRIO_STRING_PUBLIC void -trio_xstring_set -TRIO_ARGS2((self, buffer), - trio_string_t *self, - char *buffer) -{ - assert(self); - - trio_destroy(self->content); - self->content = trio_duplicate(buffer); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/* - * trio_string_size - */ -TRIO_STRING_PUBLIC int -trio_string_size -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - return self->allocated; -} - - -/* - * trio_string_terminate - */ -TRIO_STRING_PUBLIC void -trio_string_terminate -TRIO_ARGS1((self), - trio_string_t *self) -{ - trio_xstring_append_char(self, 0); -} - - -#if !defined(TRIO_MINIMAL) -/** - Append the second string to the first. - - @param self Dynamic string to be modified. - @param other Dynamic string to copy from. - @return Boolean value indicating success or failure. -*/ -TRIO_STRING_PUBLIC int -trio_string_append -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - size_t length; - - assert(self); - assert(other); - - length = self->length + other->length; - if (!TrioStringGrowTo(self, length)) - goto error; - trio_copy(&self->content[self->length], other->content); - self->length = length; - return TRUE; - - error: - return FALSE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_append - */ -TRIO_STRING_PUBLIC int -trio_xstring_append -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - size_t length; - - assert(self); - assert(other); - - length = self->length + trio_length(other); - if (!TrioStringGrowTo(self, length)) - goto error; - trio_copy(&self->content[self->length], other); - self->length = length; - return TRUE; - - error: - return FALSE; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/* - * trio_xstring_append_char - */ -TRIO_STRING_PUBLIC int -trio_xstring_append_char -TRIO_ARGS2((self, character), - trio_string_t *self, - char character) -{ - assert(self); - - if ((int)self->length >= trio_string_size(self)) - { - if (!TrioStringGrow(self, 0)) - goto error; - } - self->content[self->length] = character; - self->length++; - return TRUE; - - error: - return FALSE; -} - - -#if !defined(TRIO_MINIMAL) -/** - Search for the first occurrence of second parameter in the first. - - @param self Dynamic string to be modified. - @param other Dynamic string to copy from. - @return Boolean value indicating success or failure. -*/ -TRIO_STRING_PUBLIC int -trio_string_contains -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_contains(self->content, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_contains - */ -TRIO_STRING_PUBLIC int -trio_xstring_contains -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_contains(self->content, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_copy - */ -TRIO_STRING_PUBLIC int -trio_string_copy -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - self->length = 0; - return trio_string_append(self, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_copy - */ -TRIO_STRING_PUBLIC int -trio_xstring_copy -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - self->length = 0; - return trio_xstring_append(self, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_duplicate - */ -TRIO_STRING_PUBLIC trio_string_t * -trio_string_duplicate -TRIO_ARGS1((other), - trio_string_t *other) -{ - trio_string_t *self; - - assert(other); - - self = TrioStringAlloc(); - if (self) - { - self->content = TrioDuplicateMax(other->content, other->length); - if (self->content) - { - self->length = other->length; - self->allocated = self->length + 1; - } - else - { - self->length = self->allocated = 0; - } - } - return self; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -/* - * trio_xstring_duplicate - */ -TRIO_STRING_PUBLIC trio_string_t * -trio_xstring_duplicate -TRIO_ARGS1((other), - TRIO_CONST char *other) -{ - trio_string_t *self; - - assert(other); - - self = TrioStringAlloc(); - if (self) - { - self->content = TrioDuplicateMax(other, trio_length(other)); - if (self->content) - { - self->length = trio_length(self->content); - self->allocated = self->length + 1; - } - else - { - self->length = self->allocated = 0; - } - } - return self; -} - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_equal - */ -TRIO_STRING_PUBLIC int -trio_string_equal -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_equal(self->content, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_equal - */ -TRIO_STRING_PUBLIC int -trio_xstring_equal -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_equal(self->content, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_equal_max - */ -TRIO_STRING_PUBLIC int -trio_string_equal_max -TRIO_ARGS3((self, max, other), - trio_string_t *self, - size_t max, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_equal_max(self->content, max, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_equal_max - */ -TRIO_STRING_PUBLIC int -trio_xstring_equal_max -TRIO_ARGS3((self, max, other), - trio_string_t *self, - size_t max, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_equal_max(self->content, max, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_equal_case - */ -TRIO_STRING_PUBLIC int -trio_string_equal_case -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_equal_case(self->content, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_equal_case - */ -TRIO_STRING_PUBLIC int -trio_xstring_equal_case -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_equal_case(self->content, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_equal_case_max - */ -TRIO_STRING_PUBLIC int -trio_string_equal_case_max -TRIO_ARGS3((self, max, other), - trio_string_t *self, - size_t max, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_equal_case_max(self->content, max, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_equal_case_max - */ -TRIO_STRING_PUBLIC int -trio_xstring_equal_case_max -TRIO_ARGS3((self, max, other), - trio_string_t *self, - size_t max, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_equal_case_max(self->content, max, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) && !defined(_WIN32_WCE) -/* - * trio_string_format_data_max - */ -TRIO_STRING_PUBLIC size_t -trio_string_format_date_max -TRIO_ARGS4((self, max, format, datetime), - trio_string_t *self, - size_t max, - TRIO_CONST char *format, - TRIO_CONST struct tm *datetime) -{ - assert(self); - - return trio_format_date_max(self->content, max, format, datetime); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_index - */ -TRIO_STRING_PUBLIC char * -trio_string_index -TRIO_ARGS2((self, character), - trio_string_t *self, - int character) -{ - assert(self); - - return trio_index(self->content, character); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_index_last - */ -TRIO_STRING_PUBLIC char * -trio_string_index_last -TRIO_ARGS2((self, character), - trio_string_t *self, - int character) -{ - assert(self); - - return trio_index_last(self->content, character); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_length - */ -TRIO_STRING_PUBLIC int -trio_string_length -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - if (self->length == 0) - { - self->length = trio_length(self->content); - } - return self->length; -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_lower - */ -TRIO_STRING_PUBLIC int -trio_string_lower -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - return trio_lower(self->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_match - */ -TRIO_STRING_PUBLIC int -trio_string_match -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_match(self->content, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_match - */ -TRIO_STRING_PUBLIC int -trio_xstring_match -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_match(self->content, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_match_case - */ -TRIO_STRING_PUBLIC int -trio_string_match_case -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_match_case(self->content, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_match_case - */ -TRIO_STRING_PUBLIC int -trio_xstring_match_case -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_match_case(self->content, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_substring - */ -TRIO_STRING_PUBLIC char * -trio_string_substring -TRIO_ARGS2((self, other), - trio_string_t *self, - trio_string_t *other) -{ - assert(self); - assert(other); - - return trio_substring(self->content, other->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_xstring_substring - */ -TRIO_STRING_PUBLIC char * -trio_xstring_substring -TRIO_ARGS2((self, other), - trio_string_t *self, - TRIO_CONST char *other) -{ - assert(self); - assert(other); - - return trio_substring(self->content, other); -} -#endif /* !defined(TRIO_MINIMAL) */ - - -#if !defined(TRIO_MINIMAL) -/* - * trio_string_upper - */ -TRIO_STRING_PUBLIC int -trio_string_upper -TRIO_ARGS1((self), - trio_string_t *self) -{ - assert(self); - - return trio_upper(self->content); -} -#endif /* !defined(TRIO_MINIMAL) */ - -/** @} End of DynamicStrings */ diff --git a/triostr.h b/triostr.h deleted file mode 100644 index 0a0e71ad..00000000 --- a/triostr.h +++ /dev/null @@ -1,144 +0,0 @@ -/************************************************************************* - * - * $Id$ - * - * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND - * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. - * - ************************************************************************/ - -#ifndef TRIO_TRIOSTR_H -#define TRIO_TRIOSTR_H - -#include -#include -#include -#include -#include "triodef.h" -#include "triop.h" - -enum { - TRIO_HASH_NONE = 0, - TRIO_HASH_PLAIN, - TRIO_HASH_TWOSIGNED -}; - -#if !defined(TRIO_STRING_PUBLIC) -# if !defined(TRIO_PUBLIC) -# define TRIO_PUBLIC -# endif -# define TRIO_STRING_PUBLIC TRIO_PUBLIC -#endif - -/************************************************************************* - * String functions - */ - -TRIO_STRING_PUBLIC int trio_copy_max TRIO_PROTO((char *target, size_t max, const char *source)); -TRIO_STRING_PUBLIC char *trio_create TRIO_PROTO((size_t size)); -TRIO_STRING_PUBLIC void trio_destroy TRIO_PROTO((char *string)); -TRIO_STRING_PUBLIC char *trio_duplicate TRIO_PROTO((const char *source)); -TRIO_STRING_PUBLIC int trio_equal TRIO_PROTO((const char *first, const char *second)); -TRIO_STRING_PUBLIC int trio_equal_case TRIO_PROTO((const char *first, const char *second)); -TRIO_STRING_PUBLIC int trio_equal_locale TRIO_PROTO((const char *first, const char *second)); -TRIO_STRING_PUBLIC int trio_equal_max TRIO_PROTO((const char *first, size_t max, const char *second)); -TRIO_STRING_PUBLIC TRIO_CONST char *trio_error TRIO_PROTO((int)); -TRIO_STRING_PUBLIC size_t trio_length TRIO_PROTO((const char *string)); -TRIO_STRING_PUBLIC double trio_to_double TRIO_PROTO((const char *source, char **endp)); -TRIO_STRING_PUBLIC long trio_to_long TRIO_PROTO((const char *source, char **endp, int base)); -TRIO_STRING_PUBLIC trio_long_double_t trio_to_long_double TRIO_PROTO((const char *source, char **endp)); -TRIO_STRING_PUBLIC int trio_to_upper TRIO_PROTO((int source)); - -#if !defined(TRIO_MINIMAL) - -TRIO_STRING_PUBLIC int trio_append TRIO_PROTO((char *target, const char *source)); -TRIO_STRING_PUBLIC int trio_append_max TRIO_PROTO((char *target, size_t max, const char *source)); -TRIO_STRING_PUBLIC int trio_contains TRIO_PROTO((const char *string, const char *substring)); -TRIO_STRING_PUBLIC int trio_copy TRIO_PROTO((char *target, const char *source)); -TRIO_STRING_PUBLIC char *trio_duplicate_max TRIO_PROTO((const char *source, size_t max)); -TRIO_STRING_PUBLIC int trio_equal_case_max TRIO_PROTO((const char *first, size_t max, const char *second)); -#if !defined(_WIN32_WCE) -TRIO_STRING_PUBLIC size_t trio_format_date_max TRIO_PROTO((char *target, size_t max, const char *format, const struct tm *datetime)); -#endif -TRIO_STRING_PUBLIC unsigned long trio_hash TRIO_PROTO((const char *string, int type)); -TRIO_STRING_PUBLIC char *trio_index TRIO_PROTO((const char *string, int character)); -TRIO_STRING_PUBLIC char *trio_index_last TRIO_PROTO((const char *string, int character)); -TRIO_STRING_PUBLIC int trio_lower TRIO_PROTO((char *target)); -TRIO_STRING_PUBLIC int trio_match TRIO_PROTO((const char *string, const char *pattern)); -TRIO_STRING_PUBLIC int trio_match_case TRIO_PROTO((const char *string, const char *pattern)); -TRIO_STRING_PUBLIC size_t trio_span_function TRIO_PROTO((char *target, const char *source, int (*Function) TRIO_PROTO((int)))); -TRIO_STRING_PUBLIC char *trio_substring TRIO_PROTO((const char *string, const char *substring)); -TRIO_STRING_PUBLIC char *trio_substring_max TRIO_PROTO((const char *string, size_t max, const char *substring)); -TRIO_STRING_PUBLIC float trio_to_float TRIO_PROTO((const char *source, char **endp)); -TRIO_STRING_PUBLIC int trio_to_lower TRIO_PROTO((int source)); -TRIO_STRING_PUBLIC unsigned long trio_to_unsigned_long TRIO_PROTO((const char *source, char **endp, int base)); -TRIO_STRING_PUBLIC char *trio_tokenize TRIO_PROTO((char *string, const char *delimiters)); -TRIO_STRING_PUBLIC int trio_upper TRIO_PROTO((char *target)); - -#endif /* !defined(TRIO_MINIMAL) */ - -/************************************************************************* - * Dynamic string functions - */ - -/* - * Opaque type for dynamic strings - */ - -typedef struct _trio_string_t trio_string_t; - -TRIO_STRING_PUBLIC void trio_string_destroy TRIO_PROTO((trio_string_t *self)); -TRIO_STRING_PUBLIC char *trio_string_extract TRIO_PROTO((trio_string_t *self)); -TRIO_STRING_PUBLIC int trio_string_size TRIO_PROTO((trio_string_t *self)); -TRIO_STRING_PUBLIC void trio_string_terminate TRIO_PROTO((trio_string_t *self)); -TRIO_STRING_PUBLIC int trio_xstring_append_char TRIO_PROTO((trio_string_t *self, char character)); -TRIO_STRING_PUBLIC trio_string_t *trio_xstring_duplicate TRIO_PROTO((const char *other)); - -#if !defined(TRIO_MINIMAL) - -TRIO_STRING_PUBLIC trio_string_t *trio_string_create TRIO_PROTO((int initial_size)); -TRIO_STRING_PUBLIC char *trio_string_get TRIO_PROTO((trio_string_t *self, int offset)); -TRIO_STRING_PUBLIC void trio_xstring_set TRIO_PROTO((trio_string_t *self, char *buffer)); - -TRIO_STRING_PUBLIC int trio_string_append TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC int trio_string_contains TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC int trio_string_copy TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC trio_string_t *trio_string_duplicate TRIO_PROTO((trio_string_t *other)); -TRIO_STRING_PUBLIC int trio_string_equal TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC int trio_string_equal_max TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *second)); -TRIO_STRING_PUBLIC int trio_string_equal_case TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC int trio_string_equal_case_max TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *other)); -#if !defined(_WIN32_WCE) -TRIO_STRING_PUBLIC size_t trio_string_format_date_max TRIO_PROTO((trio_string_t *self, size_t max, const char *format, const struct tm *datetime)); -#endif -TRIO_STRING_PUBLIC char *trio_string_index TRIO_PROTO((trio_string_t *self, int character)); -TRIO_STRING_PUBLIC char *trio_string_index_last TRIO_PROTO((trio_string_t *self, int character)); -TRIO_STRING_PUBLIC int trio_string_length TRIO_PROTO((trio_string_t *self)); -TRIO_STRING_PUBLIC int trio_string_lower TRIO_PROTO((trio_string_t *self)); -TRIO_STRING_PUBLIC int trio_string_match TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC int trio_string_match_case TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC char *trio_string_substring TRIO_PROTO((trio_string_t *self, trio_string_t *other)); -TRIO_STRING_PUBLIC int trio_string_upper TRIO_PROTO((trio_string_t *self)); - -TRIO_STRING_PUBLIC int trio_xstring_append TRIO_PROTO((trio_string_t *self, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_contains TRIO_PROTO((trio_string_t *self, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_copy TRIO_PROTO((trio_string_t *self, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_equal TRIO_PROTO((trio_string_t *self, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_equal_max TRIO_PROTO((trio_string_t *self, size_t max, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_equal_case TRIO_PROTO((trio_string_t *self, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_equal_case_max TRIO_PROTO((trio_string_t *self, size_t max, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_match TRIO_PROTO((trio_string_t *self, const char *other)); -TRIO_STRING_PUBLIC int trio_xstring_match_case TRIO_PROTO((trio_string_t *self, const char *other)); -TRIO_STRING_PUBLIC char *trio_xstring_substring TRIO_PROTO((trio_string_t *self, const char *other)); - -#endif /* !defined(TRIO_MINIMAL) */ - -#endif /* TRIO_TRIOSTR_H */ diff --git a/win32/configure.js b/win32/configure.js index 3e496355..d40f32b6 100644 --- a/win32/configure.js +++ b/win32/configure.js @@ -28,7 +28,6 @@ var verMicroSuffix; var verCvs; var useCvsVer = true; /* Libxml features. */ -var withTrio = false; var withThreads = "native"; var withFtp = true; var withHttp = true; @@ -113,7 +112,6 @@ function usage() txt += "Options can be specified in the form