aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Andree <matthias.andree@gmx.de>2009-07-02 19:48:34 +0000
committerMatthias Andree <matthias.andree@gmx.de>2009-07-02 19:48:34 +0000
commitc8e1897c969ce43b551c29d65bc605f175c01263 (patch)
treed976ad001b090dbebd5ee58a4929108de7ce426d
parent33c48f99e8b28504cc68a9bd672e487422602038 (diff)
downloadfetchmail-c8e1897c969ce43b551c29d65bc605f175c01263.tar.gz
fetchmail-c8e1897c969ce43b551c29d65bc605f175c01263.tar.bz2
fetchmail-c8e1897c969ce43b551c29d65bc605f175c01263.zip
Update trio to CVS checkout of 2009-07-02.
svn path=/branches/BRANCH_6-3/; revision=5370
-rw-r--r--trio/CHANGES147
-rw-r--r--trio/Makefile.in9
-rwxr-xr-xtrio/configure1213
-rw-r--r--trio/configure.in5
-rw-r--r--trio/doc/doc.h13
-rw-r--r--trio/doc/doc_nan.h58
-rw-r--r--trio/doc/doc_printf.h8
-rw-r--r--trio/doc/doc_register.h45
-rw-r--r--trio/doc/footer.html2
-rw-r--r--trio/example.c187
-rw-r--r--trio/regression.c567
-rw-r--r--trio/trio.c4225
-rw-r--r--trio/trio.h13
-rw-r--r--trio/triodef.h232
-rw-r--r--trio/trionan.c1112
-rw-r--r--trio/trionan.h132
-rw-r--r--trio/triop.h350
-rw-r--r--trio/triostr.c949
-rw-r--r--trio/triostr.h706
19 files changed, 5919 insertions, 4054 deletions
diff --git a/trio/CHANGES b/trio/CHANGES
index 4fe3aa80..da7b76ca 100644
--- a/trio/CHANGES
+++ b/trio/CHANGES
@@ -4,10 +4,152 @@ CHANGES -- trio
The changes listed without a name attributed to them were most likely done by
Bjorn Reese and/or Daniel Stenberg.
+Version 1.14 - 2009/05/31
+-------------------------
+* Adam McLaurin
+ Improved parsing performance by avoiding memset() and memcpy() on character
+ arrays.
+
+* Gideon Smeding
+ Fixed %u scanning of signed numbers.
+
+* Gideon Smeding
+ Fixed group scanning for non-matching input.
+
+* Fixed missing undo of look-ahead reading for scanf functions. This does only
+ work for the scanf* and fscanf* functions, not dscanf* and cscanf* functions
+ (reported by Gideon Smeding).
+
+* If the format string is empty, scanf does not attempt to read any input.
+
+* Ralf Junker
+ Fixed Borland compilation for user-defined specifiers.
+
+
+Version 1.13 - 2008/11/09
+-------------------------
+* Ives Aerts
+ Added the $<format|skip> format for user-defined specifiers, which is
+ compatible with compiler warnings about mismatches between specifiers and
+ arguments.
+
+* Added TRIO_DEPRECATED flag (reported by David Boyce)
+
+* Fixed rounding adjustment for long double (reported as bug item #2136686).
+
+* Added Makefile dependency for test target (reported as bug item #2136636).
+
+* David Boyce
+ Fixed long long support for MSVC.
+
+* Fixed potential problem with read after buffer end for non-zero terminated
+ strings (reported as bug item #1828465).
+
+* Andreas Stricker
+ Added WinCE support.
+
+* Fixed number of significant digits for %g.
+
+
+Version 1.12 - 2006/10/22
+-------------------------
+* Fixed scanning of floats (reported by Bernd Ahlers).
+
+* Fixed configure.in for GCC on Tru64 and MIPSpro on IRIX (reported by Andreas
+ Maus).
+
+* Olli Savia
+ Added support for LynxOS.
+
+
+Version 1.11 - 2006/04/08
+-------------------------
+* Mark Pickelmann
+ Fixed trio_unregister. If the first element was removed, the remaining
+ list would be removed as well.
+
+* Fixed unintended formatting of %e that would result in non-zero numbers
+ starting with zero (reported by Mark Pickelmann and Gisli Ottarsson).
+
+* Fixed compilation with Sun Workshop 6 (reported by Matthias Andree).
+
+* Fixed accuracy for denormalized numbers (bug item #758327).
+
+* Glen Davidson
+ Fixed scanning of floating-point numbers without a decimal-point (bug item
+ #1370427).
+
+* David Byron
+ Fixed more compiler warnings.
+
+* Fixed compilation of trio_to_long_double and TRIO_FEATURE_FLOAT (reported by
+ David Byron).
+
+* Fixed precision of large floating-point numbers (bug item #1314524).
+
+* Karl Bochert
+ Fixed trio_fpclassify_and_signbit to only restore the floating-point
+ precision.
+
+* Fixed detection of need for ieee option on FreeBSD/Alpha.
+
+* Added TRIO_SNPRINTF_ONLY compilation.
+
+* Fixed trio_to_double by not using strtod() on Tru64/DECC because it does not
+ support hex-floats.
+
+* Fixed crash on 64 bits machines related to a previous workaround in version
+ 1.9 for uninitialized va_list (reported by Nicolai Tufar, suggestion by
+ Douglas Gwyn).
+
+* Patrick Jessee
+ Fixed width calculation for %g.
+
+* Added macros for internal features.
+
+* Jon Foster
+ Added macros for conditional compilation of many features. Documented all
+ the features.
+
+* Karl Bochert
+ Fixed problem with Borland C++, which changes the floating-point precision
+ for certain math functions (log10() and _fpclass()).
+
+* Karl Bochert
+ Fixed compilation warnings on Borland C++.
+
+* Removed any occurrence of #elif because Borland C++ reports wrong line
+ numbers when they are present (reported by Karl Bochert).
+
+* David Byron
+ Added trio_asprintfv.
+
+* Brian Chapman
+ Fixed Mac OS X compilation.
+
+* David Byron
+ Fixed several compiler warnings.
+
+* Fixed printing of out-of-range arguments for %hhd and %hd. These arguments
+ can be out of range because of default integer promotion.
+
+* Bob Friesenhahn
+ Fixed installation of header files.
+
+* Joe Orton
+ Added SHELL to Makefile.in to avoid problems with CShells.
+
+* Shaun Tancheff
+ Fixed regresion tests for MSVC.
+
+* Craig Berry
+ Fixed the VMS C99 workaround.
+
+
Version 1.10 - 2003/03/06
-------------------------
* Rearranged some include files to accommodate large file support (reported by
- Albert Chin-A-Young)
+ Albert Chin-A-Young).
* Added support for SunOS 4.1.x lack of strerror, tolower, and toupper
(reported by Peter McCluskey).
@@ -371,9 +513,6 @@ Version 0.21 - 2000/07/19
async-safe. However, reading from stdin (STDIN_FILENO) or writing to stdout
(STDOUT_FILENO) reintroduces the buffering.
-* Added trio_dprintf and trio_vdprintf. These can be used to write directly
- to pipes and sockets.
-
* Paul Janzen
Added trio_asprintf and trio_vasprintf, which are compatible with the GNU
and BSD interfaces.
diff --git a/trio/Makefile.in b/trio/Makefile.in
index 7be4bcb1..f57f16ba 100644
--- a/trio/Makefile.in
+++ b/trio/Makefile.in
@@ -1,5 +1,6 @@
+SHELL = @SHELL@
CC = @CC@
-CFLAGS = @CFLAGS@ -DDEBUG
+CFLAGS = @CFLAGS@ -I. -DDEBUG
OBJS = triostr.o trio.o trionan.o
TARGETLIB = libtrio.a
TARGETINCS = trio.h triop.h triodef.h trionan.h triostr.h
@@ -23,14 +24,14 @@ libdir = @libdir@
all: $(TARGETLIB) $(TARGET) regression
-test:
+test: all
./regression
install: $(TARGETLIB)
$(MKDIR) $(libdir)
$(MKDIR) $(includedir)
$(INSTALL_DATA) $(TARGETLIB) $(libdir)/$(TARGETLIB)
- for i in $(TARGET_INCS);do \
+ for i in $(TARGETINCS);do \
(set -x;$(INSTALL_DATA) $$i $(includedir)); \
done
@@ -57,4 +58,4 @@ doc::
$(GENDOC) doc/trio.cfg
clean:
- $(ERASE) *~ core regression example $(TOBJS) $(OBJS) $(TARGET) $(TARGETLIB) example.o regression.o
+ $(ERASE) *~ core core.* regression example $(TOBJS) $(OBJS) $(TARGET) $(TARGETLIB) example.o regression.o
diff --git a/trio/configure b/trio/configure
deleted file mode 100755
index 35ab3503..00000000
--- a/trio/configure
+++ /dev/null
@@ -1,1213 +0,0 @@
-#! /bin/sh
-
-# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.13
-# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
-#
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-
-# Defaults:
-ac_help=
-ac_default_prefix=/usr/local
-# Any additions from configure.in:
-
-# Initialize some variables set by options.
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-build=NONE
-cache_file=./config.cache
-exec_prefix=NONE
-host=NONE
-no_create=
-nonopt=NONE
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-target=NONE
-verbose=
-x_includes=NONE
-x_libraries=NONE
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datadir='${prefix}/share'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-libdir='${exec_prefix}/lib'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-infodir='${prefix}/info'
-mandir='${prefix}/man'
-
-# Initialize some other variables.
-subdirs=
-MFLAGS= MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-# Maximum number of lines to put in a shell here document.
-ac_max_here_lines=12
-
-ac_prev=
-for ac_option
-do
-
- # If the previous option needs an argument, assign it.
- if test -n "$ac_prev"; then
- eval "$ac_prev=\$ac_option"
- ac_prev=
- continue
- fi
-
- case "$ac_option" in
- -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
- *) ac_optarg= ;;
- esac
-
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
- case "$ac_option" in
-
- -bindir | --bindir | --bindi | --bind | --bin | --bi)
- ac_prev=bindir ;;
- -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir="$ac_optarg" ;;
-
- -build | --build | --buil | --bui | --bu)
- ac_prev=build ;;
- -build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build="$ac_optarg" ;;
-
- -cache-file | --cache-file | --cache-fil | --cache-fi \
- | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
- ac_prev=cache_file ;;
- -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
- | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file="$ac_optarg" ;;
-
- -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
- ac_prev=datadir ;;
- -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
- | --da=*)
- datadir="$ac_optarg" ;;
-
- -disable-* | --disable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- eval "enable_${ac_feature}=no" ;;
-
- -enable-* | --enable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
- *) ac_optarg=yes ;;
- esac
- eval "enable_${ac_feature}='$ac_optarg'" ;;
-
- -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
- | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
- | --exec | --exe | --ex)
- ac_prev=exec_prefix ;;
- -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
- | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
- | --exec=* | --exe=* | --ex=*)
- exec_prefix="$ac_optarg" ;;
-
- -gas | --gas | --ga | --g)
- # Obsolete; use --with-gas.
- with_gas=yes ;;
-
- -help | --help | --hel | --he)
- # Omit some internal or obsolete options to make the list less imposing.
- # This message is too long to be a string in the A/UX 3.1 sh.
- cat << EOF
-Usage: configure [options] [host]
-Options: [defaults in brackets after descriptions]
-Configuration:
- --cache-file=FILE cache test results in FILE
- --help print this message
- --no-create do not create output files
- --quiet, --silent do not print \`checking...' messages
- --version print the version of autoconf that created configure
-Directory and file names:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [same as prefix]
- --bindir=DIR user executables in DIR [EPREFIX/bin]
- --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
- --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
- --datadir=DIR read-only architecture-independent data in DIR
- [PREFIX/share]
- --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data in DIR
- [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
- --libdir=DIR object code libraries in DIR [EPREFIX/lib]
- --includedir=DIR C header files in DIR [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
- --infodir=DIR info documentation in DIR [PREFIX/info]
- --mandir=DIR man documentation in DIR [PREFIX/man]
- --srcdir=DIR find the sources in DIR [configure dir or ..]
- --program-prefix=PREFIX prepend PREFIX to installed program names
- --program-suffix=SUFFIX append SUFFIX to installed program names
- --program-transform-name=PROGRAM
- run sed PROGRAM on installed program names
-EOF
- cat << EOF
-Host type:
- --build=BUILD configure for building on BUILD [BUILD=HOST]
- --host=HOST configure for HOST [guessed]
- --target=TARGET configure for TARGET [TARGET=HOST]
-Features and packages:
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --x-includes=DIR X include files are in DIR
- --x-libraries=DIR X library files are in DIR
-EOF
- if test -n "$ac_help"; then
- echo "--enable and --with options recognized:$ac_help"
- fi
- exit 0 ;;
-
- -host | --host | --hos | --ho)
- ac_prev=host ;;
- -host=* | --host=* | --hos=* | --ho=*)
- host="$ac_optarg" ;;
-
- -includedir | --includedir | --includedi | --included | --include \
- | --includ | --inclu | --incl | --inc)
- ac_prev=includedir ;;
- -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
- | --includ=* | --inclu=* | --incl=* | --inc=*)
- includedir="$ac_optarg" ;;
-
- -infodir | --infodir | --infodi | --infod | --info | --inf)
- ac_prev=infodir ;;
- -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir="$ac_optarg" ;;
-
- -libdir | --libdir | --libdi | --libd)
- ac_prev=libdir ;;
- -libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir="$ac_optarg" ;;
-
- -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
- | --libexe | --libex | --libe)
- ac_prev=libexecdir ;;
- -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
- | --libexe=* | --libex=* | --libe=*)
- libexecdir="$ac_optarg" ;;
-
- -localstatedir | --localstatedir | --localstatedi | --localstated \
- | --localstate | --localstat | --localsta | --localst \
- | --locals | --local | --loca | --loc | --lo)
- ac_prev=localstatedir ;;
- -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
- | --localstate=* | --localstat=* | --localsta=* | --localst=* \
- | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
- localstatedir="$ac_optarg" ;;
-
- -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
- ac_prev=mandir ;;
- -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir="$ac_optarg" ;;
-
- -nfp | --nfp | --nf)
- # Obsolete; use --without-fp.
- with_fp=no ;;
-
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c)
- no_create=yes ;;
-
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
- no_recursion=yes ;;
-
- -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
- | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
- | --oldin | --oldi | --old | --ol | --o)
- ac_prev=oldincludedir ;;
- -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
- | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
- | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir="$ac_optarg" ;;
-
- -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
- ac_prev=prefix ;;
- -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix="$ac_optarg" ;;
-
- -program-prefix | --program-prefix | --program-prefi | --program-pref \
- | --program-pre | --program-pr | --program-p)
- ac_prev=program_prefix ;;
- -program-prefix=* | --program-prefix=* | --program-prefi=* \
- | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
- program_prefix="$ac_optarg" ;;
-
- -program-suffix | --program-suffix | --program-suffi | --program-suff \
- | --program-suf | --program-su | --program-s)
- ac_prev=program_suffix ;;
- -program-suffix=* | --program-suffix=* | --program-suffi=* \
- | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
- program_suffix="$ac_optarg" ;;
-
- -program-transform-name | --program-transform-name \
- | --program-transform-nam | --program-transform-na \
- | --program-transform-n | --program-transform- \
- | --program-transform | --program-transfor \
- | --program-transfo | --program-transf \
- | --program-trans | --program-tran \
- | --progr-tra | --program-tr | --program-t)
- ac_prev=program_transform_name ;;
- -program-transform-name=* | --program-transform-name=* \
- | --program-transform-nam=* | --program-transform-na=* \
- | --program-transform-n=* | --program-transform-=* \
- | --program-transform=* | --program-transfor=* \
- | --program-transfo=* | --program-transf=* \
- | --program-trans=* | --program-tran=* \
- | --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name="$ac_optarg" ;;
-
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- silent=yes ;;
-
- -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
- ac_prev=sbindir ;;
- -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
- | --sbi=* | --sb=*)
- sbindir="$ac_optarg" ;;
-
- -sharedstatedir | --sharedstatedir | --sharedstatedi \
- | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
- | --sharedst | --shareds | --shared | --share | --shar \
- | --sha | --sh)
- ac_prev=sharedstatedir ;;
- -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
- | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
- | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
- | --sha=* | --sh=*)
- sharedstatedir="$ac_optarg" ;;
-
- -site | --site | --sit)
- ac_prev=site ;;
- -site=* | --site=* | --sit=*)
- site="$ac_optarg" ;;
-
- -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
- ac_prev=srcdir ;;
- -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir="$ac_optarg" ;;
-
- -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
- | --syscon | --sysco | --sysc | --sys | --sy)
- ac_prev=sysconfdir ;;
- -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
- | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
- sysconfdir="$ac_optarg" ;;
-
- -target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target ;;
- -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target="$ac_optarg" ;;
-
- -v | -verbose | --verbose | --verbos | --verbo | --verb)
- verbose=yes ;;
-
- -version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.13"
- exit 0 ;;
-
- -with-* | --with-*)
- ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
- *) ac_optarg=yes ;;
- esac
- eval "with_${ac_package}='$ac_optarg'" ;;
-
- -without-* | --without-*)
- ac_package=`echo $ac_option|sed -e 's/-*without-//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- eval "with_${ac_package}=no" ;;
-
- --x)
- # Obsolete; use --with-x.
- with_x=yes ;;
-
- -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
- | --x-incl | --x-inc | --x-in | --x-i)
- ac_prev=x_includes ;;
- -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
- | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
- x_includes="$ac_optarg" ;;
-
- -x-libraries | --x-libraries | --x-librarie | --x-librari \
- | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
- ac_prev=x_libraries ;;
- -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
- | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
- x_libraries="$ac_optarg" ;;
-
- -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
- ;;
-
- *)
- if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
- echo "configure: warning: $ac_option: invalid host type" 1>&2
- fi
- if test "x$nonopt" != xNONE; then
- { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
- fi
- nonopt="$ac_option"
- ;;
-
- esac
-done
-
-if test -n "$ac_prev"; then
- { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
-fi
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 6 checking for... messages and results
-# 5 compiler messages saved in config.log
-if test "$silent" = yes; then
- exec 6>/dev/null
-else
- exec 6>&1
-fi
-exec 5>./config.log
-
-echo "\
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-" 1>&5
-
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Also quote any args containing shell metacharacters.
-ac_configure_args=
-for ac_arg
-do
- case "$ac_arg" in
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c) ;;
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
- ac_configure_args="$ac_configure_args '$ac_arg'" ;;
- *) ac_configure_args="$ac_configure_args $ac_arg" ;;
- esac
-done
-
-# NLS nuisances.
-# Only set these to C if already set. These must not be set unconditionally
-# because not all systems understand e.g. LANG=C (notably SCO).
-# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
-# Non-C LC_CTYPE values break the ctype check.
-if test "${LANG+set}" = set; then LANG=C; export LANG; fi
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
-if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
-if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo > confdefs.h
-
-# A filename unique to this package, relative to the directory that
-# configure is in, which we can look for to find out if srcdir is correct.
-ac_unique_file=triodef.h
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
- ac_srcdir_defaulted=yes
- # Try the directory containing this script, then its parent.
- ac_prog=$0
- ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
- test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
- srcdir=$ac_confdir
- if test ! -r $srcdir/$ac_unique_file; then
- srcdir=..
- fi
-else
- ac_srcdir_defaulted=no
-fi
-if test ! -r $srcdir/$ac_unique_file; then
- if test "$ac_srcdir_defaulted" = yes; then
- { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
- else
- { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
- fi
-fi
-srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
-
-# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
- if test "x$prefix" != xNONE; then
- CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
- else
- CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
- fi
-fi
-for ac_site_file in $CONFIG_SITE; do
- if test -r "$ac_site_file"; then
- echo "loading site script $ac_site_file"
- . "$ac_site_file"
- fi
-done
-
-if test -r "$cache_file"; then
- echo "loading cache $cache_file"
- . $cache_file
-else
- echo "creating cache $cache_file"
- > $cache_file
-fi
-
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-ac_exeext=
-ac_objext=o
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
- # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
- if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
- ac_n= ac_c='
-' ac_t=' '
- else
- ac_n=-n ac_c= ac_t=
- fi
-else
- ac_n= ac_c='\c' ac_t=
-fi
-
-
-
-# Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:529: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="gcc"
- break
- fi
- done
- IFS="$ac_save_ifs"
-fi
-fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-if test -z "$CC"; then
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:559: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_prog_rejected=no
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- break
- fi
- done
- IFS="$ac_save_ifs"
-if test $ac_prog_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $ac_cv_prog_CC
- shift
- if test $# -gt 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same basename, so the bogon will be chosen
- # first if we set CC to just the basename; use the full file name.
- shift
- set dummy "$ac_dir/$ac_word" "$@"
- shift
- ac_cv_prog_CC="$@"
- fi
-fi
-fi
-fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
- if test -z "$CC"; then
- case "`uname -s`" in
- *win32* | *WIN32*)
- # Extract the first word of "cl", so it can be a program name with args.
-set dummy cl; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:610: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="cl"
- break
- fi
- done
- IFS="$ac_save_ifs"
-fi
-fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
- ;;
- esac
- fi
- test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
-fi
-
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:642: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
-
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-cat > conftest.$ac_ext << EOF
-
-#line 653 "configure"
-#include "confdefs.h"
-
-main(){return(0);}
-EOF
-if { (eval echo configure:658: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- ac_cv_prog_cc_works=yes
- # If we can't run a trivial program, we are probably using a cross compiler.
- if (./conftest; exit) 2>/dev/null; then
- ac_cv_prog_cc_cross=no
- else
- ac_cv_prog_cc_cross=yes
- fi
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- ac_cv_prog_cc_works=no
-fi
-rm -fr conftest*
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
-if test $ac_cv_prog_cc_works = no; then
- { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
-fi
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:684: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
-echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:689: checking whether we are using GNU C" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.c <<EOF
-#ifdef __GNUC__
- yes;
-#endif
-EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:698: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
- ac_cv_prog_gcc=yes
-else
- ac_cv_prog_gcc=no
-fi
-fi
-
-echo "$ac_t""$ac_cv_prog_gcc" 1>&6
-
-if test $ac_cv_prog_gcc = yes; then
- GCC=yes
-else
- GCC=
-fi
-
-ac_test_CFLAGS="${CFLAGS+set}"
-ac_save_CFLAGS="$CFLAGS"
-CFLAGS=
-echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:717: checking whether ${CC-cc} accepts -g" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- echo 'void f(){}' > conftest.c
-if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
- ac_cv_prog_cc_g=yes
-else
- ac_cv_prog_cc_g=no
-fi
-rm -f conftest*
-
-fi
-
-echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
-if test "$ac_test_CFLAGS" = set; then
- CFLAGS="$ac_save_CFLAGS"
-elif test $ac_cv_prog_cc_g = yes; then
- if test "$GCC" = yes; then
- CFLAGS="-g -O2"
- else
- CFLAGS="-g"
- fi
-else
- if test "$GCC" = yes; then
- CFLAGS="-O2"
- else
- CFLAGS=
- fi
-fi
-
-
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-
-ac_aux_dir=
-for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
- if test -f $ac_dir/install-sh; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f $ac_dir/install.sh; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
-fi
-ac_config_guess=$ac_aux_dir/config.guess
-ac_config_sub=$ac_aux_dir/config.sub
-ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
-
-# Find a good install program. We prefer a C program (faster),
-# so one script is as good as another. But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# ./install, which can be erroneously created by make from ./install.sh.
-echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:788: checking for a BSD compatible install" >&5
-if test -z "$INSTALL"; then
-if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
- for ac_dir in $PATH; do
- # Account for people who put trailing slashes in PATH elements.
- case "$ac_dir/" in
- /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- # Don't use installbsd from OSF since it installs stuff as root
- # by default.
- for ac_prog in ginstall scoinst install; do
- if test -f $ac_dir/$ac_prog; then
- if test $ac_prog = install &&
- grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- :
- else
- ac_cv_path_install="$ac_dir/$ac_prog -c"
- break 2
- fi
- fi
- done
- ;;
- esac
- done
- IFS="$ac_save_IFS"
-
-fi
- if test "${ac_cv_path_install+set}" = set; then
- INSTALL="$ac_cv_path_install"
- else
- # As a last resort, use the slow shell script. We don't cache a
- # path for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the path is relative.
- INSTALL="$ac_install_sh"
- fi
-fi
-echo "$ac_t""$INSTALL" 1>&6
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
-# Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:843: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$RANLIB"; then
- ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_RANLIB="ranlib"
- break
- fi
- done
- IFS="$ac_save_ifs"
- test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
-fi
-fi
-RANLIB="$ac_cv_prog_RANLIB"
-if test -n "$RANLIB"; then
- echo "$ac_t""$RANLIB" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-
-
-echo $ac_n "checking for IEEE compilation options""... $ac_c" 1>&6
-echo "configure:873: checking for IEEE compilation options" >&5
-if eval "test \"`echo '$''{'ac_cv_ieee_option'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
-
-cat > conftest.$ac_ext <<EOF
-#line 879 "configure"
-#include "confdefs.h"
-
-int main() {
-
-#if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__))) && (defined(VMS) || defined(__VMS)))
-# error "Option needed"
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:890: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_ieee_option="/IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- cat > conftest.$ac_ext <<EOF
-#line 898 "configure"
-#include "confdefs.h"
-
-int main() {
-
-#if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__))) && !(defined(VMS) || defined(__VMS)) && !defined(_CFE))
-# error "Option needed"
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:909: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_ieee_option="-ieee"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- cat > conftest.$ac_ext <<EOF
-#line 917 "configure"
-#include "confdefs.h"
-
-int main() {
-
-#if !(defined(__alpha) && (defined(__GNUC__) && (defined(__osf__) || defined(__linux__))))
-# error "Option needed"
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:928: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_ieee_option="-mieee"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_ieee_option="none"
-
-fi
-rm -f conftest*
-
-fi
-rm -f conftest*
-
-fi
-rm -f conftest*
-
-fi
-
-echo "$ac_t""$ac_cv_ieee_option" 1>&6
-if test $ac_cv_ieee_option != none; then
- CFLAGS="${CFLAGS} ${ac_cv_ieee_option}"
-fi
-
-trap '' 1 2 15
-cat > confcache <<\EOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs. It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
-#
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already. You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
-#
-EOF
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
- case `(ac_space=' '; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote substitution
- # turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- -e "s/'/'\\\\''/g" \
- -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
- ;;
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
- ;;
- esac >> confcache
-if cmp -s $cache_file confcache; then
- :
-else
- if test -w $cache_file; then
- echo "updating cache $cache_file"
- cat confcache > $cache_file
- else
- echo "not updating unwritable cache $cache_file"
- fi
-fi
-rm -f confcache
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-# Any assignment to VPATH causes Sun make to only execute
-# the first set of double-colon rules, so remove it if not needed.
-# If there is a colon in the path, we need to keep it.
-if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
-fi
-
-trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
-
-# Transform confdefs.h into DEFS.
-# Protect against shell expansion while executing Makefile rules.
-# Protect against Makefile macro expansion.
-cat > conftest.defs <<\EOF
-s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
-s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
-s%\[%\\&%g
-s%\]%\\&%g
-s%\$%$$%g
-EOF
-DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
-rm -f conftest.defs
-
-
-# Without the "./", some shells look in PATH for config.status.
-: ${CONFIG_STATUS=./config.status}
-
-echo creating $CONFIG_STATUS
-rm -f $CONFIG_STATUS
-cat > $CONFIG_STATUS <<EOF
-#! /bin/sh
-# Generated automatically by configure.
-# Run this file to recreate the current configuration.
-# This directory was configured as follows,
-# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-#
-# $0 $ac_configure_args
-#
-# Compiler output produced by configure, useful for debugging
-# configure, is in ./config.log if it exists.
-
-ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
-for ac_option
-do
- case "\$ac_option" in
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
- exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
- -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
- echo "$CONFIG_STATUS generated by autoconf version 2.13"
- exit 0 ;;
- -help | --help | --hel | --he | --h)
- echo "\$ac_cs_usage"; exit 0 ;;
- *) echo "\$ac_cs_usage"; exit 1 ;;
- esac
-done
-
-ac_given_srcdir=$srcdir
-ac_given_INSTALL="$INSTALL"
-
-trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
-EOF
-cat >> $CONFIG_STATUS <<EOF
-
-# Protect against being on the right side of a sed subst in config.status.
-sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
- s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
-$ac_vpsub
-$extrasub
-s%@SHELL@%$SHELL%g
-s%@CFLAGS@%$CFLAGS%g
-s%@CPPFLAGS@%$CPPFLAGS%g
-s%@CXXFLAGS@%$CXXFLAGS%g
-s%@FFLAGS@%$FFLAGS%g
-s%@DEFS@%$DEFS%g
-s%@LDFLAGS@%$LDFLAGS%g
-s%@LIBS@%$LIBS%g
-s%@exec_prefix@%$exec_prefix%g
-s%@prefix@%$prefix%g
-s%@program_transform_name@%$program_transform_name%g
-s%@bindir@%$bindir%g
-s%@sbindir@%$sbindir%g
-s%@libexecdir@%$libexecdir%g
-s%@datadir@%$datadir%g
-s%@sysconfdir@%$sysconfdir%g
-s%@sharedstatedir@%$sharedstatedir%g
-s%@localstatedir@%$localstatedir%g
-s%@libdir@%$libdir%g
-s%@includedir@%$includedir%g
-s%@oldincludedir@%$oldincludedir%g
-s%@infodir@%$infodir%g
-s%@mandir@%$mandir%g
-s%@CC@%$CC%g
-s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
-s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
-s%@INSTALL_DATA@%$INSTALL_DATA%g
-s%@RANLIB@%$RANLIB%g
-
-CEOF
-EOF
-
-cat >> $CONFIG_STATUS <<\EOF
-
-# Split the substitutions into bite-sized pieces for seds with
-# small command number limits, like on Digital OSF/1 and HP-UX.
-ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
-ac_file=1 # Number of current file.
-ac_beg=1 # First line for current file.
-ac_end=$ac_max_sed_cmds # Line after last line for current file.
-ac_more_lines=:
-ac_sed_cmds=""
-while $ac_more_lines; do
- if test $ac_beg -gt 1; then
- sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
- else
- sed "${ac_end}q" conftest.subs > conftest.s$ac_file
- fi
- if test ! -s conftest.s$ac_file; then
- ac_more_lines=false
- rm -f conftest.s$ac_file
- else
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds="sed -f conftest.s$ac_file"
- else
- ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
- fi
- ac_file=`expr $ac_file + 1`
- ac_beg=$ac_end
- ac_end=`expr $ac_end + $ac_max_sed_cmds`
- fi
-done
-if test -z "$ac_sed_cmds"; then
- ac_sed_cmds=cat
-fi
-EOF
-
-cat >> $CONFIG_STATUS <<EOF
-
-CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
- # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case "$ac_file" in
- *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
- ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
- *) ac_file_in="${ac_file}.in" ;;
- esac
-
- # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
-
- # Remove last slash and all that follows it. Not all systems have dirname.
- ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
- if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
- # The file is in a subdirectory.
- test ! -d "$ac_dir" && mkdir "$ac_dir"
- ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
- # A "../" for each directory in $ac_dir_suffix.
- ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
- else
- ac_dir_suffix= ac_dots=
- fi
-
- case "$ac_given_srcdir" in
- .) srcdir=.
- if test -z "$ac_dots"; then top_srcdir=.
- else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
- /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
- *) # Relative path.
- srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
- top_srcdir="$ac_dots$ac_given_srcdir" ;;
- esac
-
- case "$ac_given_INSTALL" in
- [/$]*) INSTALL="$ac_given_INSTALL" ;;
- *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
- esac
-
- echo creating "$ac_file"
- rm -f "$ac_file"
- configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
- case "$ac_file" in
- *Makefile*) ac_comsub="1i\\
-# $configure_input" ;;
- *) ac_comsub= ;;
- esac
-
- ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
- sed -e "$ac_comsub
-s%@configure_input@%$configure_input%g
-s%@srcdir@%$srcdir%g
-s%@top_srcdir@%$top_srcdir%g
-s%@INSTALL@%$INSTALL%g
-" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
-fi; done
-rm -f conftest.s*
-
-EOF
-cat >> $CONFIG_STATUS <<EOF
-
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-
-exit 0
-EOF
-chmod +x $CONFIG_STATUS
-rm -fr confdefs* $ac_clean_files
-test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
-
diff --git a/trio/configure.in b/trio/configure.in
index 6783959b..212684d5 100644
--- a/trio/configure.in
+++ b/trio/configure.in
@@ -20,16 +20,19 @@ AC_CACHE_VAL(ac_cv_ieee_option, [
AC_TRY_COMPILE(,[
#if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__))) && (defined(VMS) || defined(__VMS)))
# error "Option needed"
+typedef int option_needed[-1];
#endif
],ac_cv_ieee_option="/IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE",
AC_TRY_COMPILE(,[
-#if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__))) && !(defined(VMS) || defined(__VMS)) && !defined(_CFE))
+#if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__) && !defined(__GNUC__))) && !(defined(VMS) || defined(__VMS)) && !defined(_CFE))
# error "Option needed"
+typedef int option_needed[-1];
#endif
],ac_cv_ieee_option="-ieee",
AC_TRY_COMPILE(,[
#if !(defined(__alpha) && (defined(__GNUC__) && (defined(__osf__) || defined(__linux__))))
# error "Option needed"
+typedef int option_needed[-1];
#endif
],ac_cv_ieee_option="-mieee",
ac_cv_ieee_option="none"
diff --git a/trio/doc/doc.h b/trio/doc/doc.h
index 4b368f46..49de1466 100644
--- a/trio/doc/doc.h
+++ b/trio/doc/doc.h
@@ -1,6 +1,6 @@
/*************************************************************************
*
- * $Id: doc.h,v 1.12 2002/12/08 10:42:49 breese Exp $
+ * $Id: doc.h,v 1.20 2006/08/18 11:32:08 breese Exp $
*
* Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
*
@@ -135,24 +135,35 @@ We have received contributions from the following persons (in alphabetic
order sorted by surname)
@li Craig Berry
+@li Karl Bochert
@li Stan Boehm
+@li David Byron
+@li Brian Chapman
@li Robert Collins
@li Danny Dulai
+@li Bob Friesenhahn
+@li Jon Foster
@li John Fotheringham
@li Markus Henke
@li Ken Gibson
@li Paul Janzen
+@li Patrick Jessee
@li Richard Jinks
@li Tero Jänkä
@li Howard Kapustein
@li Rune Enggaard Lausen
@li Mehdi Lavasani
@li Alexander Lukyanov
+@li Andreas Maus
+@li Mikey Menezes
@li Emmanuel Mogenet
@li Jacob Navia
@li Jose Ortiz
@li Joe Orton
@li Gisli Ottarsson
+@li Mark Pickelmann
+@li Olli Savia
+@li Shaun Tancheff
@li Marc Werwerft
@li Igor Zlatkovic
diff --git a/trio/doc/doc_nan.h b/trio/doc/doc_nan.h
new file mode 100644
index 00000000..bfb3ffc9
--- /dev/null
+++ b/trio/doc/doc_nan.h
@@ -0,0 +1,58 @@
+/*************************************************************************
+ *
+ * $Id: doc_nan.h,v 1.1 2001/12/30 12:47:41 breese Exp $
+ *
+ * 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
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
+ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
+ *
+ ************************************************************************/
+
+/** @addtogroup SpecialQuantities Special Quantifies.
+Functions to detect and fabricate special quantities in floating-point
+numbers.
+
+@b SYNOPSIS
+
+@verbatim
+cc ... -ltrio -lm
+
+#include <trionan.h>
+@endverbatim
+
+@b DESCRIPTION
+
+Certain arithmetical operations does not result in normal numbers. Instead
+they result in special quantities that must be handled differently by the
+floating-point hardware. These includes Infinity and Not-A-Number (NaN).
+
+For example, 0/0 (zero divided by zero) yields NaN. Any operation which
+involves a NaN will result in NaN. Any comparison involving NaN will be
+unsuccessful, even if NaN is compared to NaN.
+
+These special quantities are represented with special bit patterns by the
+floating-point hardware, and this bit patterns depend on the hardware.
+There may even be hardware that does not support special quantities, so
+the functions in this module are not guaranteed to work on all platforms.
+
+The approach used in this module is to (in decreasing order of importance)
+@li Use C99 functionality when available.
+@li Use IEEE 754-1985 bit patterns if possible.
+@li Use platform-specific techniques.
+
+@b NOTES
+
+This module does not depend on the rest of trio, and can thus be reused
+separately. The following files are necessary:
+@li @c triodef.h
+@li @c trionan.h
+@li @c trionan.c
+
+*/
diff --git a/trio/doc/doc_printf.h b/trio/doc/doc_printf.h
index 4321cd5c..32439e26 100644
--- a/trio/doc/doc_printf.h
+++ b/trio/doc/doc_printf.h
@@ -1,6 +1,6 @@
/*************************************************************************
*
- * $Id: doc_printf.h,v 1.3 2002/05/07 16:26:00 breese Exp $
+ * $Id: doc_printf.h,v 1.5 2008/10/12 12:09:51 breese Exp $
*
* Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
*
@@ -57,8 +57,8 @@ sufficient space, is returned.
@ref trio_snprintfcat appends the formatted text at the end of @p buffer.
-@ref trio_asprintf and @ref trio_vasprintf allocates and returns an
-allocated string in @p buffer containing the formatted text.
+@ref trio_asprintf, @ref trio_vasprintf, and @ref trio_asprintfv allocates
+and returns an allocated string in @p buffer containing the formatted text.
@b FORMATTING
@@ -249,7 +249,7 @@ Corresponds to the size_t modifier ( @c z ).
Prepend radix indicator for hexadecimal, octal, and binary integer numbers
and for pointers.
-Always add a decimal-pointer for floating-point numbers.
+Always add a decimal-point for floating-point numbers.
Escape non-printable characters for strings.
@em Spacing ( )
diff --git a/trio/doc/doc_register.h b/trio/doc/doc_register.h
index 03610bfa..3ce86c57 100644
--- a/trio/doc/doc_register.h
+++ b/trio/doc/doc_register.h
@@ -1,6 +1,6 @@
/*************************************************************************
*
- * $Id: doc_register.h,v 1.2 2002/04/20 13:28:09 breese Exp $
+ * $Id: doc_register.h,v 1.3 2008/10/12 12:09:51 breese Exp $
*
* Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
*
@@ -35,24 +35,51 @@ This documentation is incomplete.
The user-defined specifier consists of a start character (\074 = '<'), an
optional namespace string followed by a namespace separator (\072 = ':'),
-a format string, and an end character (\076 = '>').
+a format string, an optional skipping separator (\174 = '|'), and an end
+character (\076 = '>').
The namespace string can consist of alphanumeric characters, and is used to
define a named reference (see below). The namespace is case-sensitive. If no
namespace is specified, then we use an unnamed reference (see below).
The format can consist of any character except the end character ('>'), the
-namespace separator (':'), and the nil character (\000).
+namespace separator (':'), the skipping separator ('|'), and the nil character
+(\000).
Any modifier can be used together with the user-defined specifier.
+There are two formats for invoking a user-defined specifier. The first format
+is an extension of the normal printf/scanf formatting. It uses the percent
+character (\045 = '%') followed by optional qualifiers and a specifier. For
+example:
+
+@verbatim
+ trio_printf("%<format>\n", my_handle, my_data);
+@endverbatim
+
+Some C compilers can issue a warning if there is a mismatch between specifiers
+and arguments. Unfortunately, these warnings does not work with the first
+format for user-defined specifiers. Therefore the second format has been
+introduced. The second format can only be applied to user-defined specifiers.
+
+The second format starts with a dollar character (\044 = '$') instead of the
+percent character, and is followed by optional qualifiers and the user-defined
+specifier. If the specifier contains a pipe character (\174 = '|'), then
+everything between the pipe character and the end character ('>') is ignored.
+The ignored part can be used to list the normal specifiers that the C compiler
+uses to determine mismatches. For example:
+
+@verbatim
+ trio_printf("$<format|%p%p>\n", my_handle, my_data);
+@endverbatim
+
@b Registering
A user-defined specifier must be registered before it can be used.
Unregistered user-defined specifiers are ignored. The @ref trio_register
function is used to register a user-defined specifier. It takes two argument,
a callback function and a namespace, and it returns a handle. The handle must
-be used to unregister the specifier later.
+be used to unregister the specifier later.
The following example registers a user-define specifier with the "my_namespace"
namespace:
@@ -79,7 +106,7 @@ If the namespace is used, then a user-defined pointer must be passed as an
argument:
@verbatim
- trio_printf("<my_namespace:format>\n", my_data);
+ trio_printf("%<my_namespace:format>\n", my_data);
@endverbatim
If the handle is used, then the user-defined specifier must not contain a
@@ -87,7 +114,7 @@ namespace. Instead the handle must be passed as an argument, followed by a
user-defined pointer:
@verbatim
- trio_printf("<format>\n", my_handle, my_data);
+ trio_printf("%<format>\n", my_handle, my_data);
@endverbatim
The two examples above are equivalent.
@@ -107,7 +134,7 @@ No namespace can be specified.
@verbatim
anon_handle = trio_register(callback, NULL);
- trio_printf("<format>\n", anon_handle, my_data);
+ trio_printf("%<format>\n", anon_handle, my_data);
@endverbatim
@b Restrictions
@@ -166,7 +193,7 @@ equivalents.
@verbatim
trio_print_ref(ref, "There are %d towels\n", 42);
- trio_print_ref(ref, "%<recursive>\n", recursive_writer, trio_get_argument());
+ trio_print_ref(ref, "%<recursive>\n", recursive_writer, trio_get_argument(ref));
@endverbatim
@b GETTER @b AND @b SETTER @b FUNCTIONS
@@ -218,7 +245,7 @@ Print the time in the format "HOUR:MINUTE:SECOND" if "time" is specified inside
the user-defined specifier.
@verbatim
- static int time_writer(void *ref)
+ static int time_print(void *ref)
{
const char *format;
time_t *data;
diff --git a/trio/doc/footer.html b/trio/doc/footer.html
index 0e97ca00..f149fa2a 100644
--- a/trio/doc/footer.html
+++ b/trio/doc/footer.html
@@ -1,4 +1,4 @@
<HR>
-<center class="copyright">Copyright (C) 2001 Bj&oslash;rn Reese and Daniel Stenberg.</center>
+<center class="copyright">Copyright (C) 2001 - 2006 Bj&oslash;rn Reese and Daniel Stenberg.</center>
</body>
</html>
diff --git a/trio/example.c b/trio/example.c
index 50a1bd2f..279ff14e 100644
--- a/trio/example.c
+++ b/trio/example.c
@@ -6,9 +6,8 @@
#include <limits.h>
#include <math.h>
#include <unistd.h>
+/* #include <nan.h> */
#include <wchar.h>
-#include "triodef.h"
-#include "trionan.h"
#include "strio.h"
#include "trio.h"
#undef printf
@@ -33,15 +32,12 @@
# define LONGEST LONGLONG
#endif
-static TRIO_CONST char rcsid[] = "@(#)$Id: example.c,v 1.9 2001/11/25 13:47:38 breese Exp $";
+static const char rcsid[] = "@(#)$Id: example.c,v 1.9 2001/11/25 13:47:38 breese Exp $";
/*************************************************************************
*
*/
-void Dump
-TRIO_ARGS2((buffer, rc),
- char *buffer,
- int rc)
+void Dump(char *buffer, int rc)
{
if (rc < 0)
{
@@ -57,7 +53,7 @@ TRIO_ARGS2((buffer, rc),
/*************************************************************************
*
*/
-int main(TRIO_NOARGS)
+int main(void)
{
char buffer[512];
int rc;
@@ -66,9 +62,7 @@ int main(TRIO_NOARGS)
int num;
int num2;
int count;
- double dnum, dnum2;
- float fnum, fnum2;
- trio_long_double_t ldnum;
+ double dnum;
char *end;
char text[256];
char ch;
@@ -342,25 +336,25 @@ int main(TRIO_NOARGS)
/* printf("number = %f small_number = \"%f\"\n", number, small_number); */
/* } */
-/* rc = trio_sprintf(buffer, "abcba"); */
-/* Dump(buffer, rc); */
-/* trio_sscanf(buffer, "%[ab]", text); */
-/* printf("text = \"%s\"\n", text); */
-/* trio_sscanf(buffer, "%*[ab]c%[^\n]", text); */
-/* printf("text = \"%s\"\n", text); */
+ rc = trio_sprintf(buffer, "abcba");
+ Dump(buffer, rc);
+ trio_sscanf(buffer, "%[ab]", text);
+ printf("text = \"%s\"\n", text);
+ trio_sscanf(buffer, "%*[ab]c%[^\n]", text);
+ printf("text = \"%s\"\n", text);
-/* trio_sprintf(buffer, "aabcdba aaa"); */
-/* rc = trio_sscanf(buffer, "%s", text); */
-/* Dump(buffer, rc); */
-/* printf("text = \"%s\"\n", text); */
-/* rc = trio_sscanf(buffer, "%*1[aA]%[a-c]", text); */
-/* Dump(buffer, rc); */
-/* printf("text = \"%s\"\n", text); */
+ trio_sprintf(buffer, "aabcdba aaa");
+ rc = trio_sscanf(buffer, "%s", text);
+ Dump(buffer, rc);
+ printf("text = \"%s\"\n", text);
+ rc = trio_sscanf(buffer, "%*1[aA]%[a-c]", text);
+ Dump(buffer, rc);
+ printf("text = \"%s\"\n", text);
-/* rc = trio_sprintf(buffer, "10021"); */
-/* rc = trio_sscanf(buffer, "%b%n%d", &num, &count, &num2); */
-/* Dump(buffer, rc); */
-/* printf("num = %d %d %d\n", num, num2, count); */
+ rc = trio_sprintf(buffer, "10021");
+ rc = trio_sscanf(buffer, "%b%n%d", &num, &count, &num2);
+ Dump(buffer, rc);
+ printf("num = %d %d %d\n", num, num2, count);
/* rc = trio_sprintf(buffer, "%'d", 10000); */
/* rc = trio_sscanf(buffer, "%'d", &num); */
@@ -453,142 +447,5 @@ int main(TRIO_NOARGS)
/* rc = trio_sscanf("123,456.78", "%'f", &dnum); */
/* printf("%d %f\n", rc, dnum); */
-/* trio_printf("%.24f\n%.24f\n%.24f\n", 39413.80, 1.4, (2.0/3.0)); */
-/* printf("%.24f\n%.24f\n%.24f\n", 39413.80, 1.4, (2.0/3.0)); */
-
-/* trio_printf("%f\n%f\n", (7.0/5.0), (2.0/3.0)); */
-/* printf("%f\n%f\n", (7.0/5.0), (2.0/3.0)); */
-
-/* trio_printf("%a\n", 42.0); */
-/* trio_printf("%.2e\n", 0.9999); */
-/* trio_printf("%e\n", 3.14e+123); */
-/* trio_printf("%010.3e\n", 3141.5); */
-/* trio_printf("%.32Rf\n", 1.4); */
-/* trio_printf("%Rf\n", 1.234567890123456789e20); */
-/* printf("%.2g\n", 0.9999); */
-/* trio_printf("%.2g\n", 0.9999); */
-/* printf("%.2g\n", 99.9999); */
-/* trio_printf("%.2g\n", 99.9999); */
-/* printf("%g\n", 0.0); */
-/* trio_printf("%g\n", 0.0); */
-/* printf("%f\n", 3141.0); */
-/* trio_printf("%f\n", 3141.0); */
-/* printf("%.0f\n", 3141.0); */
-/* trio_printf("%.0f\n", 3141.0); */
-/* trio_printf("%f\n", 2.0/3.0); */
-/* trio_printf("%f\n", 16.25); */
-
-/* trio_printf("A: %f\nB: %.20f\nC: %Rf\n", 0.1, 0.1, 0.1); */
-/* trio_printf("A: %f\nB: %.20f\nC: %Rf\n", 2.0/3.0, 2.0/3.0, 2.0/3.0); */
-
-/* trio_printf("R %.*Rhf\n", FLT_DIG + 4, (double)((float)1.4)); */
-/* trio_printf("T %.*hf\n", FLT_DIG + 4, (double)((float)(2.0/3.0))); */
-/* trio_printf("R %.*Rhf\n", FLT_DIG + 4, (double)((float)(2.0/3.0))); */
-
-/* trio_printf("T %.*f\n", DBL_DIG + 4, (2.0/3.0)); */
-/* trio_printf("R %.*Rf\n", DBL_DIG + 4, (2.0/3.0)); */
-/* printf("C %.*f\n", DBL_DIG + 4, (2.0/3.0)); */
-
-/* trio_printf("T %.*f\n", DBL_DIG + 4, 1.4); */
-/* trio_printf("R %.*Rf\n", DBL_DIG + 4, 1.4); */
-/* printf("C %.*f\n", DBL_DIG + 4, 1.4); */
-
-/* trio_printf("T %.*f\n", DBL_DIG + 6, 0.1); */
-/* trio_printf("R %.*Rf\n", DBL_DIG + 6, 0.1); */
-/* printf("C %.*f\n", DBL_DIG + 6, 0.1); */
-
-/* ldnum = 2.0L / 3.0L; */
-/* trio_printf("R %.*Lf\n", LDBL_DIG + 4, ldnum); */
-/* trio_printf("R %RLf\n", ldnum); */
-
-/* trio_printf("T %.*.2f\n", DBL_MANT_DIG, 1.4); */
-/* trio_printf("R %.*.2Rf\n", DBL_MANT_DIG, 1.4); */
-
-/* trio_printf("R %Rf\n", 1.234567890123456789e20); */
-/* trio_printf("T %10.3e\n", 3141.5); */
-/* trio_printf("T %f\n", 1.0/3.0); */
-
- /* 2^-1 + 2^-15 */
-/* trio_printf("T %.*g\n", DBL_DIG + 200, 0.500030517578125); */
-/* printf("C %.*g\n", DBL_DIG + 200, 0.500030517578125); */
-/* trio_printf("T %.*g\n", DBL_DIG + 200, 2.0/3.0); */
-/* printf("C %.*g\n", DBL_DIG + 200, 2.0/3.0); */
-
-/* trio_printf("T %.*f\n", DBL_DIG + 2, 1.4); */
-/* trio_printf("TR %.*Rf\n", DBL_DIG + 2, 1.4); */
-
-/* rc = trio_sscanf("0.141882295971771490", "%Lf", &ldnum); */
-/* rc = trio_sprintf(buffer, "%.30Lf", ldnum); */
-/* Dump(buffer, rc); */
-
-/* ldnum = 1.0L; */
-/* ldnum /= 3.0L; */
-/* rc = trio_sprintf(buffer, "%.30Lf", ldnum); */
-/* Dump(buffer, rc); */
-
-/* { */
-/* float a = 5.9, b = 10.0, c = a * b; */
-/* double d = a * b; */
-/* trio_printf("%.15a %.15a\n", c, d); */
-/* trio_printf("%.15g %.15g\n", c, (float)(a * b)); */
-/* trio_printf("%.15a %.15a\n", c, (float)(a * b)); */
-/* trio_printf("%.30.2f %.30.2f\n", c, (float)(a * b)); */
-/* } */
-
-/* trio_locale_set_decimal_point(","); */
-/* trio_locale_set_thousand_separator("'"); */
-/* trio_locale_set_grouping("\1\3\2\177"); */
-/* trio_printf("%'d\n", 123456789); */
-/* trio_printf("%'f\n", 123456789.0); */
-/* trio_locale_set_grouping("\3\2\0"); */
-/* trio_printf("%'d\n", 123456789); */
-/* trio_printf("%'f\n", 123456789.0); */
-
-/* trio_printf("%.30Rf\n", 39413.80); */
-
-/* printf("% 10.5f\n", 5163723399.00000); */
-/* trio_printf("% 10.5f\n", 5163723399.00000); */
-
-/* printf("% 020.5f\n", 5163723399.00000); */
-/* trio_printf("% 020.5f\n", 5163723399.00000); */
-
-/* rc = trio_vsnprintf(buffer, 8, "printing\n", NULL); */
-/* Dump(buffer, rc); */
-
-/* rc = trio_sprintf(buffer, "%.o %#.o", 0, 0); */
-/* Dump(buffer, rc); */
-/* rc = trio_sprintf(buffer, "%8.o %08.4o", 0, 0); */
-/* Dump(buffer, rc); */
-/* rc = trio_sprintf(buffer, "%8o %08o", 0, 0); */
-/* Dump(buffer, rc); */
-
-/* rc = trio_sprintf(buffer, "%a %a", 0.0, 1.0); */
-/* Dump(buffer, rc); */
-
-/* printf("%*s%*s%*s\n", */
-/* -1, "one", */
-/* -20, "two", */
-/* -30,"three"); */
-/* trio_printf("%*s%*s%*s\n", */
-/* -1, "one", */
-/* -20, "two", */
-/* -30,"three"); */
-
-/* dnum = pow (2.0, -1024.1); */
-/* dnum = pow (2.0, -1024); */
-/* dnum = pow(2.0, 16.0); */
-/* rc = trio_snprintf(buffer, sizeof(buffer), "%.200g %a %.200.2g", */
-/* dnum, dnum, dnum); */
-/* Dump(buffer, rc); */
-
-/* dnum = 3.141e-44; */
-/* rc = trio_snprintf(buffer, sizeof(buffer), "%.200g %a %.200.2g", */
-/* dnum, dnum, dnum); */
-/* Dump(buffer, rc); */
-
- rc = trio_sscanf("0x2.ap+4", "%a", &dnum);
- trio_snprintf(buffer, sizeof(buffer), "%f %a", dnum, dnum);
- Dump(buffer, rc);
-
return 0;
}
diff --git a/trio/regression.c b/trio/regression.c
index ccbd78b5..0716cc63 100644
--- a/trio/regression.c
+++ b/trio/regression.c
@@ -15,16 +15,26 @@
#include "trio.h"
#include "triop.h"
+#if defined(TRIO_EMBED_NAN)
+# define TRIO_PUBLIC_NAN static
+# define TRIO_FUNC_NINF
+# define TRIO_FUNC_PINF
+# define TRIO_FUNC_NAN
+# define TRIO_FUNC_ISINF
+# define TRIO_FUNC_ISNAN
+# if TRIO_FEATURE_FLOAT
+# define TRIO_FUNC_NZERO
+# endif
+#endif
#include "trionan.h"
-#if defined(TRIO_MINIMAL)
-# define TRIO_STRING_PUBLIC static
-# include "triostr.c"
-#else
-# include "triostr.h"
+#if defined(TRIO_EMBED_STRING)
+# define TRIO_PUBLIC_STRING static
+# define TRIO_FUNC_EQUAL_CASE
#endif
+#include "triostr.h"
#undef printf
-#if TRIO_WIDECHAR
+#if TRIO_FEATURE_WIDECHAR
# include <wchar.h>
#endif
@@ -33,8 +43,14 @@
#define DOUBLE_EQUAL(x,y) (((x)>(y)-DBL_EPSILON) && ((x)<(y)+DBL_EPSILON))
#define FLOAT_EQUAL(x,y) (((x)>(y)-FLT_EPSILON) && ((x)<(y)+FLT_EPSILON))
-static TRIO_CONST char rcsid[] = "@(#)$Id: regression.c,v 1.44 2002/12/29 15:08:56 breese Exp $";
+static TRIO_CONST char rcsid[] = "@(#)$Id: regression.c,v 1.65 2009/06/07 15:14:31 breese Exp $";
+#if defined(TRIO_EMBED_NAN)
+# include "trionan.c"
+#endif
+#if defined(TRIO_EMBED_STRING)
+# include "triostr.c"
+#endif
/*************************************************************************
*
@@ -187,6 +203,7 @@ int
VerifyAllocate(TRIO_NOARGS)
{
int nerrors = 0;
+#if TRIO_FEATURE_DYNAMICSTRING
int rc;
char *string;
int count;
@@ -213,7 +230,8 @@ VerifyAllocate(TRIO_NOARGS)
}
if (string)
free(string);
-
+#endif
+
return nerrors;
}
@@ -222,10 +240,9 @@ VerifyAllocate(TRIO_NOARGS)
*
*/
int
-VerifyFormatting(TRIO_NOARGS)
+VerifyFormattingStrings(TRIO_NOARGS)
{
int nerrors = 0;
- char buffer[256];
/* Normal text */
nerrors += Verify(__FILE__, __LINE__, "Hello world",
@@ -233,20 +250,19 @@ VerifyFormatting(TRIO_NOARGS)
/* String */
nerrors += Verify(__FILE__, __LINE__, "Hello world",
"%s", "Hello world");
- /* Pointer */
- if (sizeof(void *) == 4)
- {
- nerrors += Verify(__FILE__, __LINE__, "Pointer 0x01234567",
- "Pointer %p", 0x1234567);
- }
- else if (sizeof(void *) == 8)
- {
- nerrors += Verify(__FILE__, __LINE__, "Pointer 0x0123456789012345",
- "Pointer %p", 0x123456789012345);
- }
- /* Nil pointer */
- nerrors += Verify(__FILE__, __LINE__, "Pointer (nil)",
- "Pointer %p", NULL);
+
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyFormattingIntegers(TRIO_NOARGS)
+{
+ int nerrors = 0;
+ char buffer[256];
+
/* Integer */
nerrors += Verify(__FILE__, __LINE__, "Number 42",
"Number %d", 42);
@@ -341,6 +357,19 @@ VerifyFormatting(TRIO_NOARGS)
sprintf(buffer, "%x", UINT_MAX);
nerrors += Verify(__FILE__, __LINE__, buffer,
"%x", -1);
+
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyFormattingFloats(TRIO_NOARGS)
+{
+ int nerrors = 0;
+
+#if TRIO_FEATURE_FLOAT
/* Double */
nerrors += Verify(__FILE__, __LINE__, "3141.000000",
"%f", 3141.0);
@@ -377,7 +406,7 @@ VerifyFormatting(TRIO_NOARGS)
/* Beyond accuracy */
nerrors += Verify(__FILE__, __LINE__, "0.000000",
"%f", 1.234567890123456789e-20);
-#if defined(TRIO_BREESE)
+# if defined(TRIO_BREESE)
nerrors += Verify(__FILE__, __LINE__, "1.3999999999999999111821580299875",
"%.32g", 1.4);
nerrors += Verify(__FILE__, __LINE__, "1.39999999999999991118215802998748",
@@ -392,7 +421,7 @@ VerifyFormatting(TRIO_NOARGS)
"%.14f", 1.4);
nerrors += Verify(__FILE__, __LINE__, "39413.800000000002910383045673370361",
"%.30f", 39413.80);
-#endif
+# endif
/* 2^-1 + 2^-15 */
nerrors += Verify(__FILE__, __LINE__, "0.500030517578125",
"%.*g", DBL_DIG + 10, 0.500030517578125);
@@ -413,6 +442,8 @@ VerifyFormatting(TRIO_NOARGS)
"%#.4f", 0.0);
nerrors += Verify(__FILE__, __LINE__, "0.000",
"%#.4g", 0.0);
+ nerrors += Verify(__FILE__, __LINE__, "0.001000",
+ "%#.4g", 1e-3);
nerrors += Verify(__FILE__, __LINE__, "3141.0000",
"%#.4f", 3141.0);
nerrors += Verify(__FILE__, __LINE__, "3141.",
@@ -427,9 +458,11 @@ VerifyFormatting(TRIO_NOARGS)
"%.e", 3141.0);
nerrors += Verify(__FILE__, __LINE__, "3.e+03",
"%#.e", 3141.0);
- nerrors += Verify(__FILE__, __LINE__, "100",
+ nerrors += Verify(__FILE__, __LINE__, "1.23457e+06",
+ "%g", 1234567.0);
+ nerrors += Verify(__FILE__, __LINE__, "1e+02",
"%.2g", 99.9999);
- nerrors += Verify(__FILE__, __LINE__, "100.",
+ nerrors += Verify(__FILE__, __LINE__, "1.0e+02",
"%#.2g", 99.9999);
nerrors += Verify(__FILE__, __LINE__, "0.123",
"%0g", 0.123);
@@ -438,11 +471,109 @@ VerifyFormatting(TRIO_NOARGS)
nerrors += Verify(__FILE__, __LINE__, "1",
"%.2g", 0.9999);
nerrors += Verify(__FILE__, __LINE__, "2",
+ "%.0g", 1.5);
+ nerrors += Verify(__FILE__, __LINE__, "2",
"%.g", 1.5);
nerrors += Verify(__FILE__, __LINE__, "0.01",
"%.2g", 0.01);
nerrors += Verify(__FILE__, __LINE__, "0.010",
"%#.2g", 0.01);
+ nerrors += Verify(__FILE__, __LINE__, "1e-04",
+ "%5.g", 0.999999e-4);
+ /* Double width and precision */
+ nerrors += Verify(__FILE__, __LINE__, " 1e-05",
+ "%11.5g", 1e-5);
+ nerrors += Verify(__FILE__, __LINE__, " 0.0001",
+ "%11.5g", 1e-4);
+ nerrors += Verify(__FILE__, __LINE__, " 0.001",
+ "%11.5g", 1e-3);
+ nerrors += Verify(__FILE__, __LINE__, " 0.01",
+ "%11.5g", 1e-2);
+ nerrors += Verify(__FILE__, __LINE__, " 0.1",
+ "%11.5g", 1e-1);
+ nerrors += Verify(__FILE__, __LINE__, " 1",
+ "%11.5g", 1e0);
+ nerrors += Verify(__FILE__, __LINE__, " 10",
+ "%11.5g", 1e1);
+ nerrors += Verify(__FILE__, __LINE__, " 100",
+ "%11.5g", 1e2);
+ nerrors += Verify(__FILE__, __LINE__, " 1000",
+ "%11.5g", 1e3);
+ nerrors += Verify(__FILE__, __LINE__, " 10000",
+ "%11.5g", 1e4);
+ nerrors += Verify(__FILE__, __LINE__, " 1e+05",
+ "%11.5g", 1e5);
+ nerrors += Verify(__FILE__, __LINE__, " 9.9e-05",
+ "%11.2g", 0.99e-4);
+ nerrors += Verify(__FILE__, __LINE__, " 0.00099",
+ "%11.2g", 0.99e-3);
+ nerrors += Verify(__FILE__, __LINE__, " 0.0099",
+ "%11.2g", 0.99e-2);
+ nerrors += Verify(__FILE__, __LINE__, " 0.099",
+ "%11.2g", 0.99e-1);
+ nerrors += Verify(__FILE__, __LINE__, " 0.99",
+ "%11.2g", 0.99e0);
+ nerrors += Verify(__FILE__, __LINE__, " 9.9",
+ "%11.2g", 0.99e1);
+ nerrors += Verify(__FILE__, __LINE__, " 99",
+ "%11.2g", 0.99e2);
+ nerrors += Verify(__FILE__, __LINE__, " 9.9e+02",
+ "%11.2g", 0.99e3);
+ nerrors += Verify(__FILE__, __LINE__, " 9.9e+03",
+ "%11.2g", 0.99e4);
+ nerrors += Verify(__FILE__, __LINE__, " 9.9e+04",
+ "%11.2g", 0.99e5);
+ /* Double width, precision, and alternative */
+ nerrors += Verify(__FILE__, __LINE__, " 1.0000e-05",
+ "%#11.5g", 1e-5);
+ nerrors += Verify(__FILE__, __LINE__, " 0.00010000",
+ "%#11.5g", 1e-4);
+ nerrors += Verify(__FILE__, __LINE__, " 0.0010000",
+ "%#11.5g", 1e-3);
+ nerrors += Verify(__FILE__, __LINE__, " 0.0010000",
+ "%#11.5g", 0.999999e-3);
+ nerrors += Verify(__FILE__, __LINE__, " 0.010000",
+ "%#11.5g", 1e-2);
+ nerrors += Verify(__FILE__, __LINE__, " 0.010000",
+ "%#11.5g", 0.999999e-2);
+ nerrors += Verify(__FILE__, __LINE__, " 0.10000",
+ "%#11.5g", 1e-1);
+ nerrors += Verify(__FILE__, __LINE__, " 0.10000",
+ "%#11.5g", 0.999999e-1);
+ nerrors += Verify(__FILE__, __LINE__, " 1.0000",
+ "%#11.5g", 1e0);
+ nerrors += Verify(__FILE__, __LINE__, " 1.0000",
+ "%#11.5g", 0.999999e0);
+ nerrors += Verify(__FILE__, __LINE__, " 10.000",
+ "%#11.5g", 1e1);
+ nerrors += Verify(__FILE__, __LINE__, " 100.00",
+ "%#11.5g", 1e2);
+ nerrors += Verify(__FILE__, __LINE__, " 1000.0",
+ "%#11.5g", 1e3);
+ nerrors += Verify(__FILE__, __LINE__, " 10000.",
+ "%#11.5g", 1e4);
+ nerrors += Verify(__FILE__, __LINE__, " 1.0000e+05",
+ "%#11.5g", 1e5);
+ nerrors += Verify(__FILE__, __LINE__, " 9.9e-05",
+ "%#11.2g", 0.99e-4);
+ nerrors += Verify(__FILE__, __LINE__, " 0.00099",
+ "%#11.2g", 0.99e-3);
+ nerrors += Verify(__FILE__, __LINE__, " 0.0099",
+ "%#11.2g", 0.99e-2);
+ nerrors += Verify(__FILE__, __LINE__, " 0.099",
+ "%#11.2g", 0.99e-1);
+ nerrors += Verify(__FILE__, __LINE__, " 0.99",
+ "%#11.2g", 0.99e0);
+ nerrors += Verify(__FILE__, __LINE__, " 9.9",
+ "%#11.2g", 0.99e1);
+ nerrors += Verify(__FILE__, __LINE__, " 99.",
+ "%#11.2g", 0.99e2);
+ nerrors += Verify(__FILE__, __LINE__, " 9.9e+02",
+ "%#11.2g", 0.99e3);
+ nerrors += Verify(__FILE__, __LINE__, " 9.9e+03",
+ "%#11.2g", 0.99e4);
+ nerrors += Verify(__FILE__, __LINE__, " 9.9e+04",
+ "%#11.2g", 0.99e5);
/* Double width, precision, and zero padding */
nerrors += Verify(__FILE__, __LINE__, "00003.141500e+03",
"%016e", 3141.5);
@@ -477,6 +608,134 @@ VerifyFormatting(TRIO_NOARGS)
nerrors += Verify(__FILE__, __LINE__, "NAN",
"%F", trio_nan());
+# if TRIO_FEATURE_HEXFLOAT
+ nerrors += Verify(__FILE__, __LINE__, "0x2.ap+4",
+ "%a", 42.0);
+ nerrors += Verify(__FILE__, __LINE__, "-0x2.ap+4",
+ "%a", -42.0);
+ nerrors += Verify(__FILE__, __LINE__, "0x1.8p+0",
+ "%a", 1.5);
+ nerrors += Verify(__FILE__, __LINE__, "0x1.6666666666666p+0",
+ "%a", 1.4);
+ nerrors += Verify(__FILE__, __LINE__, "0xc.45p+8",
+ "%a", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "0XC.45P+8",
+ "%A", 3141.0);
+ nerrors += Verify(__FILE__, __LINE__, "0xb.351c434a98fa8p-148",
+ "%a", 3.141e-44);
+# endif
+
+#endif /* TRIO_FEATURE_FLOAT */
+
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+#if TRIO_EXTENSION
+int number_writer(void *ref)
+{
+ const char *format;
+ int *data;
+
+ format = trio_get_format(ref);
+ if ((format) && trio_equal(format, "integer"))
+ {
+ data = trio_get_argument(ref);
+ if (data)
+ {
+ trio_print_int(ref, *data);
+ }
+ }
+ return 0;
+}
+
+#endif
+
+int
+VerifyFormattingUserDefined(TRIO_NOARGS)
+{
+ int nerrors = 0;
+#if TRIO_EXTENSION
+ void *number_handle;
+ int integer = 123;
+
+ number_handle = trio_register(number_writer, "number");
+
+ /* Old style */
+ nerrors += Verify(__FILE__, __LINE__, "123",
+ "%<number:integer>", &integer);
+
+ /* New style */
+ nerrors += Verify(__FILE__, __LINE__, "123",
+ "$<number:integer|%p>", &integer);
+ nerrors += Verify(__FILE__, __LINE__, "123",
+ "$<integer|%p%p>", number_handle, &integer);
+ nerrors += Verify(__FILE__, __LINE__, "$<integer|123",
+ "$<integer|%d", 123);
+ nerrors += Verify(__FILE__, __LINE__, "$integer|123>",
+ "$integer|%d>", 123);
+
+ trio_unregister(number_handle);
+#endif
+
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyFormattingRegression(TRIO_NOARGS)
+{
+ int nerrors = 0;
+
+#if TRIO_FEATURE_FLOAT
+ /* 0.6 was formatted as 0.600000e+00 */
+ nerrors += Verify(__FILE__, __LINE__, "5.000000e-01",
+ "%e", 0.5);
+ nerrors += Verify(__FILE__, __LINE__, "6.000000e-01",
+ "%e", 0.6);
+#endif
+
+ return nerrors;
+}
+
+/*************************************************************************
+ *
+ */
+int
+VerifyFormatting(TRIO_NOARGS)
+{
+ int nerrors = 0;
+#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
+ char buffer[256];
+#endif
+
+ nerrors += VerifyFormattingStrings();
+ nerrors += VerifyFormattingIntegers();
+ nerrors += VerifyFormattingFloats();
+ nerrors += VerifyFormattingRegression();
+ nerrors += VerifyFormattingUserDefined();
+
+ /* Pointer */
+ if (sizeof(void *) == 4)
+ {
+ nerrors += Verify(__FILE__, __LINE__, "Pointer 0x01234567",
+ "Pointer %p", 0x1234567);
+ }
+#if defined(TRIO_COMPILER_SUPPORTS_LL)
+ else if (sizeof(void *) == 8)
+ {
+ nerrors += Verify(__FILE__, __LINE__, "Pointer 0x0123456789012345",
+ "Pointer %p", 0x123456789012345LL);
+ }
+#endif
+ /* Nil pointer */
+ nerrors += Verify(__FILE__, __LINE__, "Pointer (nil)",
+ "Pointer %p", NULL);
+
/* Char width alignment */
nerrors += Verify(__FILE__, __LINE__, "Char X .",
"Char %-4c.", 'X');
@@ -495,7 +754,7 @@ VerifyFormatting(TRIO_NOARGS)
"%.*s", 4, "testing");
nerrors += Verify(__FILE__, __LINE__, "testing",
"%.*s", -4, "testing");
-#if TRIO_UNIX98
+#if TRIO_FEATURE_POSITIONAL
/* Positional */
nerrors += Verify(__FILE__, __LINE__, "222 111",
"%2$s %1$s", "111", "222");
@@ -504,41 +763,44 @@ VerifyFormatting(TRIO_NOARGS)
123, 1234, 12345, 123456, 5, 6, 7, 8);
#endif
-#if TRIO_GNU
+#if TRIO_FEATURE_SIZE_T_UPPER
nerrors += Verify(__FILE__, __LINE__, "256",
"%Zd", sizeof(buffer));
+#endif
+
+#if TRIO_FEATURE_ERRNO
errno = EINTR;
+# if defined(TRIO_PLATFORM_LYNX)
+# if defined(PREDEF_STANDARD_POSIX_1996)
+ nerrors += Verify(__FILE__, __LINE__, "Interrupted system call ",
+ "%m");
+# else
+ nerrors += Verify(__FILE__, __LINE__, "System call interrupted",
+ "%m");
+# endif
+# else
nerrors += Verify(__FILE__, __LINE__, "Interrupted system call",
"%m");
+# endif
#endif
-#if TRIO_BSD || TRIO_GNU
+#if TRIO_FEATURE_QUAD
# if defined(TRIO_COMPILER_SUPPORTS_LL)
/* This may fail if the preprocessor does not recognize LL */
nerrors += Verify(__FILE__, __LINE__, "42",
"%qd", 42LL);
# endif
#endif
-
-#if TRIO_C99
- nerrors += Verify(__FILE__, __LINE__, "0x2.ap+4",
- "%a", 42.0);
- nerrors += Verify(__FILE__, __LINE__, "-0x2.ap+4",
- "%a", -42.0);
- nerrors += Verify(__FILE__, __LINE__, "0x1.8p+0",
- "%a", 1.5);
- nerrors += Verify(__FILE__, __LINE__, "0x1.6666666666666p+0",
- "%a", 1.4);
- nerrors += Verify(__FILE__, __LINE__, "0xc.45p+8",
- "%a", 3141.0);
- nerrors += Verify(__FILE__, __LINE__, "0XC.45P+8",
- "%A", 3141.0);
- nerrors += Verify(__FILE__, __LINE__, "0xb.351c434a98fa8p-148",
- "%a", 3.141e-44);
+
+#if TRIO_FEATURE_SIZE_T
nerrors += Verify(__FILE__, __LINE__, "256",
"%zd", sizeof(buffer));
+#endif
+#if TRIO_FEATURE_PTRDIFF_T
nerrors += Verify(__FILE__, __LINE__, "42",
"%td", 42);
+#endif
+#if TRIO_FEATURE_INTMAX_T
# if defined(TRIO_COMPILER_SUPPORTS_LL)
/* Some compilers may not handle the LL suffix correctly */
nerrors += Verify(__FILE__, __LINE__, "42",
@@ -546,7 +808,7 @@ VerifyFormatting(TRIO_NOARGS)
# endif
#endif
-#if TRIO_WIDECHAR
+#if TRIO_FEATURE_WIDECHAR
nerrors += Verify(__FILE__, __LINE__, "Hello World",
"%ls", L"Hello World");
nerrors += Verify(__FILE__, __LINE__, "\\aHello World",
@@ -557,7 +819,7 @@ VerifyFormatting(TRIO_NOARGS)
"%#lc", L'\a');
#endif
-#if TRIO_MICROSOFT
+#if TRIO_FEATURE_FIXED_SIZE
nerrors += Verify(__FILE__, __LINE__, "42",
"%I8d", 42);
nerrors += Verify(__FILE__, __LINE__, "ffffffff",
@@ -594,6 +856,7 @@ VerifyFormatting(TRIO_NOARGS)
"Number %'d", 100);
nerrors += Verify(__FILE__, __LINE__, "Number 1,000,000",
"Number %'d", 1000000);
+# if TRIO_FEATURE_FLOAT
/* Float thousand separator */
nerrors += Verify(__FILE__, __LINE__, "31,415.200000",
"%'f", 31415.2);
@@ -606,12 +869,13 @@ VerifyFormatting(TRIO_NOARGS)
"%.17Rf", 1.4);
nerrors += Verify(__FILE__, __LINE__, "39413.8",
"%.30Rf", 39413.80);
-# if !defined(TRIO_COMPILER_ANCIENT)
+# if !defined(TRIO_COMPILER_ANCIENT)
/* Long double */
nerrors += Verify(__FILE__, __LINE__, "1.4",
"%RLf", 1.4L);
nerrors += Verify(__FILE__, __LINE__, "1.4",
"%.30RLf", 1.4L);
+# endif
# endif
#endif
@@ -656,70 +920,124 @@ VerifyErrors(TRIO_NOARGS)
/* Error: Invalid argument 1 */
rc = trio_snprintf(buffer, sizeof(buffer), "%d %r", 42, "text");
-#if TRIO_ERRORS
+#if TRIO_FEATURE_ERRORCODE
+# if TRIO_FEATURE_STRERR
trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
TRIO_ERROR_CODE(rc),
TRIO_ERROR_NAME(rc),
TRIO_ERROR_POSITION(rc));
nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 5",
"%s", buffer);
+# else
+ trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
+ TRIO_ERROR_CODE(rc),
+ TRIO_ERROR_POSITION(rc));
+ nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 5",
+ "%s", buffer);
+# endif
#else
nerrors += (rc != -1);
#endif
+
/* Error: Invalid argument 2 */
rc = trio_snprintf(buffer, sizeof(buffer), "%#");
-#if TRIO_ERRORS
+#if TRIO_FEATURE_ERRORCODE
+# if TRIO_FEATURE_STRERR
trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
TRIO_ERROR_CODE(rc),
TRIO_ERROR_NAME(rc),
TRIO_ERROR_POSITION(rc));
nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 3",
"%s", buffer);
+# else
+ trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
+ TRIO_ERROR_CODE(rc),
+ TRIO_ERROR_POSITION(rc));
+ nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 3",
+ "%s", buffer);
+# endif
#else
nerrors += (rc != -1);
#endif
+
/* Error: Invalid argument 3 */
rc = trio_snprintf(buffer, sizeof(buffer), "%hhhd", 42);
-#if TRIO_ERRORS
+#if TRIO_FEATURE_ERRORCODE
+# if TRIO_FEATURE_STRERR
trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
TRIO_ERROR_CODE(rc),
TRIO_ERROR_NAME(rc),
TRIO_ERROR_POSITION(rc));
nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 4",
"%s", buffer);
+# else
+ trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
+ TRIO_ERROR_CODE(rc),
+ TRIO_ERROR_POSITION(rc));
+ nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 4",
+ "%s", buffer);
+# endif
#else
nerrors += (rc != -1);
#endif
+
/* Error: Double reference */
rc = trio_snprintf(buffer, sizeof(buffer), "hello %1$d %1$d", 31, 32);
-#if TRIO_ERRORS
+#if TRIO_FEATURE_ERRORCODE
+# if TRIO_FEATURE_STRERR
trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
TRIO_ERROR_CODE(rc),
TRIO_ERROR_NAME(rc),
TRIO_ERROR_POSITION(rc));
-# if TRIO_UNIX98
+# if TRIO_UNIX98
nerrors += Verify(__FILE__, __LINE__, "Err = 4 (Double reference), Pos = 0",
"%s", buffer);
-# else
+# else
nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 9",
"%s", buffer);
+# endif
+# else
+ trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
+ TRIO_ERROR_CODE(rc),
+ TRIO_ERROR_POSITION(rc));
+# if TRIO_UNIX98
+ nerrors += Verify(__FILE__, __LINE__, "Err = 4, Pos = 0",
+ "%s", buffer);
+# else
+ nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 9",
+ "%s", buffer);
+# endif
# endif
#else
nerrors += (rc != -1);
#endif
+
/* Error: Reference gap */
rc = trio_snprintf(buffer, sizeof(buffer), "%3$d %1$d", 31, 32, 33);
-#if TRIO_ERRORS
+#if TRIO_FEATURE_ERRORCODE
+# if TRIO_FEATURE_STRERR
trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d",
TRIO_ERROR_CODE(rc),
TRIO_ERROR_NAME(rc),
TRIO_ERROR_POSITION(rc));
-# if TRIO_UNIX98
+# if TRIO_UNIX98
nerrors += Verify(__FILE__, __LINE__, "Err = 5 (Reference gap), Pos = 1",
"%s", buffer);
-# else
+# else
nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 3",
"%s", buffer);
+# endif
+# else
+ trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d",
+ TRIO_ERROR_CODE(rc),
+ TRIO_ERROR_POSITION(rc));
+# if TRIO_UNIX98
+ nerrors += Verify(__FILE__, __LINE__, "Err = 5, Pos = 1",
+ "%s", buffer);
+# else
+ nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 3",
+ "%s", buffer);
+# endif
# endif
#else
nerrors += (rc != -1);
@@ -731,6 +1049,7 @@ VerifyErrors(TRIO_NOARGS)
/*************************************************************************
*
*/
+#if TRIO_FEATURE_SCANF
int
VerifyScanningOneInteger
TRIO_ARGS5((file, line, expected, format, original),
@@ -776,10 +1095,12 @@ VerifyScanningIntegers(TRIO_NOARGS)
return nerrors;
}
+#endif
/*************************************************************************
*
*/
+#if TRIO_FEATURE_SCANF
int
VerifyScanningOneFloat
TRIO_ARGS5((file, line, expected, format, original),
@@ -789,6 +1110,23 @@ TRIO_ARGS5((file, line, expected, format, original),
TRIO_CONST char *format,
double original)
{
+ float number;
+ char data[512];
+
+ trio_snprintf(data, sizeof(data), format, original);
+ trio_sscanf(data, format, &number);
+ return Verify(file, line, expected, format, number);
+}
+
+int
+VerifyScanningOneDouble
+TRIO_ARGS5((file, line, expected, format, original),
+ TRIO_CONST char *file,
+ int line,
+ TRIO_CONST char *expected,
+ TRIO_CONST char *format,
+ double original)
+{
double number;
char data[512];
@@ -802,6 +1140,7 @@ VerifyScanningFloats(TRIO_NOARGS)
{
int nerrors = 0;
+#if TRIO_FEATURE_FLOAT
nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "42.000000",
"%f", 42.0);
nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "-42.000000",
@@ -830,29 +1169,32 @@ VerifyScanningFloats(TRIO_NOARGS)
"%.6g", 1234567.0);
nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1234567",
"%.10g", 1234567.0);
-#if TRIO_C99
+# if TRIO_FEATURE_HEXFLOAT
nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0x2.ap+4",
"%a", 42.0);
nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0x1.2d687p+20",
"%a", 1234567.0);
nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0X1.2D687P+20",
"%A", 1234567.0);
-#endif
- nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.79769e+308",
- "%g", 1.79769e+308);
+# endif
+ nerrors += VerifyScanningOneDouble(__FILE__, __LINE__, "1.79769e+308",
+ "%lg", 1.79769e+308);
nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "nan",
"%f", trio_nan());
nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "NAN",
"%F", trio_nan());
nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "-inf",
"%f", trio_ninf());
+#endif
return nerrors;
}
+#endif
/*************************************************************************
*
*/
+#if TRIO_FEATURE_SCANF
int
VerifyScanningOneString
TRIO_ARGS5((file, line, expected, format, original),
@@ -875,6 +1217,10 @@ VerifyScanningStrings(TRIO_NOARGS)
{
int nerrors = 0;
+ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "",
+ "hello", "hello");
+ nerrors += VerifyScanningOneString(__FILE__, __LINE__, "",
+ "", "");
nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello",
"%s", "hello");
nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello",
@@ -902,25 +1248,35 @@ VerifyScanningStrings(TRIO_NOARGS)
return nerrors;
}
+#endif
/*************************************************************************
*
*/
+#if TRIO_FEATURE_SCANF
int
VerifyScanningRegression(TRIO_NOARGS)
{
int nerrors = 0;
int rc;
- int index;
+#if TRIO_FEATURE_FLOAT
+ int offset;
double dnumber;
+# if defined(TRIO_BREESE)
trio_long_double_t ldnumber;
+# endif
+#endif
long lnumber;
int number;
char ch;
+ char buffer[4096];
+ FILE *stream;
- rc = trio_sscanf("1.5", "%lf%n", &dnumber, &index);
+#if TRIO_FEATURE_FLOAT
+ rc = trio_sscanf("1.5", "%lf%n", &dnumber, &offset);
nerrors += Verify(__FILE__, __LINE__, "1 3 1.500000",
- "%d %d %f", rc, index, dnumber);
+ "%d %d %f", rc, offset, dnumber);
+#endif
rc = trio_sscanf("q 123", "%c%ld", &ch, &lnumber);
nerrors += Verify(__FILE__, __LINE__, "q 123",
"%c %ld", ch, lnumber);
@@ -930,20 +1286,87 @@ VerifyScanningRegression(TRIO_NOARGS)
rc = trio_sscanf("abc def", "%*s%n", &number);
nerrors += Verify(__FILE__, __LINE__, "0 3",
"%d %d", rc, number);
+#if TRIO_FEATURE_FLOAT
rc = trio_sscanf("0.141882295971771490", "%lf", &dnumber);
+ /* FIXME: Verify */
+#endif
number = 33;
rc = trio_sscanf("total 1", "total %d", &number);
nerrors += Verify(__FILE__, __LINE__, "1 1",
"%d %d", rc, number);
#if defined(TRIO_BREESE)
+# if TRIO_FEATURE_FLOAT
nerrors += Verify(__FILE__, __LINE__, "1 0.141882295971771488",
"%d %.18f", rc, dnumber);
rc = trio_sscanf("0.141882295971771490", "%Lf", &ldnumber);
nerrors += Verify(__FILE__, __LINE__, "1 0.141882295971771490",
"%d %.18Lf", rc, ldnumber);
+# endif
#endif
+#if TRIO_FEATURE_FLOAT
+ rc = trio_sscanf("1.e-6", "%lg", &dnumber);
+ nerrors += Verify(__FILE__, __LINE__, "1e-06",
+ "%g", dnumber);
+ rc = trio_sscanf("1e-6", "%lg", &dnumber);
+ nerrors += Verify(__FILE__, __LINE__, "1e-06",
+ "%g", dnumber);
+#endif
+
+ /* Do not overwrite result on matching error */
+ ch = 'a';
+ rc = trio_sscanf("0123456789", "%1[c]", &ch);
+ nerrors += Verify(__FILE__, __LINE__, "a",
+ "%c", ch);
+
+ /* Scan plus prefix for unsigned integer */
+ rc = trio_sscanf("+42", "%u", &number);
+ nerrors += Verify(__FILE__, __LINE__, "1 42",
+ "%d %u", rc, number);
+
+ /* Scan minus prefix even for unsigned integer */
+ rc = trio_sscanf("-42", "%u", &number);
+ sprintf(buffer, "1 %u", -42U);
+ nerrors += Verify(__FILE__, __LINE__, buffer,
+ "%d %u", rc, number);
+
+ /* A scangroup match failure should not bind its argument,
+ * i.e., it shouldn't match the empty string. */
+ sprintf(buffer, "SPQR");
+ rc = trio_sscanf("asdf", "%[c]", buffer);
+ nerrors += Verify(__FILE__, __LINE__, "0 SPQR",
+ "%d %s", rc, buffer);
+
+ /* Even whitespace scanning shouldn't try to read past EOF */
+ stream = tmpfile();
+ trio_fprintf(stream, "");
+ rewind(stream);
+ rc = trio_fscanf(stream, " ");
+ nerrors += Verify(__FILE__, __LINE__, "0",
+ "%d", rc);
+ fclose(stream);
+
+ /* Idem, after a succesfull read */
+ stream = tmpfile();
+ trio_fprintf(stream, "123");
+ rewind(stream);
+ rc = trio_fscanf(stream, "%i ", &number);
+ nerrors += Verify(__FILE__, __LINE__, "1 123",
+ "%d %i", rc, number);
+ fclose(stream);
+
+ /* The scanner should unget its read-ahead char */
+ stream = tmpfile();
+ trio_fprintf(stream, "123");
+ rewind(stream);
+ trio_fscanf(stream, "%*c");
+ trio_fscanf(stream, "%c", &ch);
+ nerrors += Verify(__FILE__, __LINE__, "2",
+ "%c", ch);
+ fclose(stream);
+
return nerrors;
}
+#endif
/*************************************************************************
*
@@ -952,12 +1375,12 @@ int
VerifyScanning(TRIO_NOARGS)
{
int nerrors = 0;
-
+#if TRIO_FEATURE_SCANF
nerrors += VerifyScanningIntegers();
nerrors += VerifyScanningFloats();
nerrors += VerifyScanningStrings();
nerrors += VerifyScanningRegression();
-
+#endif
return nerrors;
}
@@ -970,8 +1393,10 @@ VerifyStrings(TRIO_NOARGS)
int nerrors = 0;
#if !defined(TRIO_MINIMAL)
char buffer[512];
+#if TRIO_FEATURE_FLOAT
double dnumber;
float fnumber;
+#endif
char *end;
/* Comparison */
@@ -1065,6 +1490,7 @@ VerifyStrings(TRIO_NOARGS)
Report0(__FILE__, __LINE__);
}
+#if TRIO_FEATURE_FLOAT
/* Double conversion */
trio_copy(buffer, "3.1415");
dnumber = trio_to_double(buffer, NULL);
@@ -1077,6 +1503,7 @@ VerifyStrings(TRIO_NOARGS)
nerrors++;
Report0(__FILE__, __LINE__);
}
+#endif
/* Long conversion */
trio_copy(buffer, "3.1415");
@@ -1170,10 +1597,12 @@ main(TRIO_NOARGS)
printf("%s\n", rcsid);
+#if TRIO_EXTENSION
/* Override system locale settings */
trio_locale_set_decimal_point(".");
trio_locale_set_thousand_separator(",");
trio_locale_set_grouping("\3");
+#endif
printf("Verifying strings\n");
nerrors += VerifyStrings();
@@ -1198,7 +1627,7 @@ main(TRIO_NOARGS)
nerrors += VerifyAllocate();
if (nerrors == 0)
- printf("Regression test suceeded\n");
+ printf("Regression test succeeded\n");
else
printf("Regression test failed in %d instance(s)\n", nerrors);
diff --git a/trio/trio.c b/trio/trio.c
index 8494e556..8c9d36e2 100644
--- a/trio/trio.c
+++ b/trio/trio.c
@@ -1,8 +1,8 @@
/*************************************************************************
*
- * $Id: trio.c,v 1.75 2003/03/01 15:34:01 breese Exp $
+ * $Id: trio.c,v 1.125 2009/06/23 15:46:21 breese Exp $
*
- * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg.
+ * Copyright (C) 1998, 2009 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
@@ -47,10 +47,71 @@
#include "triodef.h"
#include "trio.h"
#include "triop.h"
+
+#if defined(TRIO_EMBED_NAN)
+# define TRIO_PUBLIC_NAN static
+# if TRIO_FEATURE_FLOAT
+# define TRIO_FUNC_NAN
+# define TRIO_FUNC_NINF
+# define TRIO_FUNC_PINF
+# define TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT
+# define TRIO_FUNC_ISINF
+# endif
+#endif
#include "trionan.h"
-#if !defined(TRIO_MINIMAL)
-# include "triostr.h"
+
+#if defined(TRIO_EMBED_STRING)
+# define TRIO_PUBLIC_STRING static
+# define TRIO_FUNC_LENGTH
+# define TRIO_FUNC_LENGTH_MAX
+# define TRIO_FUNC_TO_LONG
+# if TRIO_FEATURE_LOCALE
+# define TRIO_FUNC_COPY_MAX
+# endif
+# if TRIO_FEATURE_DYNAMICSTRING
+# define TRIO_FUNC_XSTRING_DUPLICATE
+# endif
+# if TRIO_EXTENSION && TRIO_FEATURE_SCANF
+# define TRIO_FUNC_EQUAL_LOCALE
+# endif
+# if TRIO_FEATURE_ERRNO
+# define TRIO_FUNC_ERROR
+# endif
+# if TRIO_FEATURE_FLOAT && TRIO_FEATURE_SCANF
+# define TRIO_FUNC_TO_DOUBLE
+# endif
+# if TRIO_FEATURE_DYNAMICSTRING
+# define TRIO_FUNC_STRING_EXTRACT
+# endif
+# if TRIO_FEATURE_DYNAMICSTRING
+# define TRIO_FUNC_STRING_TERMINATE
+# endif
+# if TRIO_FEATURE_USER_DEFINED
+# define TRIO_FUNC_DUPLICATE
+# endif
+# if TRIO_FEATURE_DYNAMICSTRING
+# define TRIO_FUNC_STRING_DESTROY
+# endif
+# if TRIO_FEATURE_USER_DEFINED
+# define TRIO_FUNC_DESTROY
+# endif
+# if TRIO_FEATURE_USER_DEFINED || (TRIO_FEATURE_FLOAT && TRIO_FEATURE_SCANF)
+# define TRIO_FUNC_EQUAL
+# endif
+# if TRIO_FEATURE_USER_DEFINED || TRIO_FEATURE_SCANF
+# define TRIO_FUNC_EQUAL_CASE
+# endif
+# if (TRIO_EXTENSION && TRIO_FEATURE_SCANF)
+# define TRIO_FUNC_EQUAL_MAX
+# endif
+# if TRIO_FEATURE_SCANF
+# define TRIO_FUNC_TO_UPPER
+# endif
+# if TRIO_FEATURE_DYNAMICSTRING
+# define TRIO_FUNC_XSTRING_APPEND_CHAR
+# endif
#endif
+#include "triostr.h"
/**************************************************************************
*
@@ -58,19 +119,61 @@
*
*************************************************************************/
-#include <math.h>
#include <limits.h>
-#include <float.h>
+#if TRIO_FEATURE_FLOAT
+# include <math.h>
+# include <float.h>
+#endif
-#if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) || defined(USE_MULTIBYTE) || TRIO_WIDECHAR
-# define TRIO_COMPILER_SUPPORTS_MULTIBYTE
-# if !defined(MB_LEN_MAX)
-# define MB_LEN_MAX 6
+#if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) || defined(USE_MULTIBYTE) || TRIO_FEATURE_WIDECHAR
+# if !defined(TRIO_PLATFORM_WINCE)
+# define TRIO_COMPILER_SUPPORTS_MULTIBYTE
+# if !defined(MB_LEN_MAX)
+# define MB_LEN_MAX 6
+# endif
# endif
#endif
-#if (defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1100)) || defined(TRIO_COMPILER_BCB)
-# define TRIO_COMPILER_SUPPORTS_MSVC_INT
+#if (TRIO_COMPILER_VISUALC - 0 >= 1100) || defined(TRIO_COMPILER_BORLAND)
+# define TRIO_COMPILER_SUPPORTS_VISUALC_INT
+#endif
+
+#if TRIO_FEATURE_FLOAT
+# if defined(PREDEF_STANDARD_C99) \
+ || defined(PREDEF_STANDARD_UNIX03)
+# if !defined(HAVE_FLOORL)
+# define HAVE_FLOORL
+# endif
+# if !defined(HAVE_CEILL)
+# define HAVE_CEILL
+# endif
+# if !defined(HAVE_POWL)
+# define HAVE_POWL
+# endif
+# if !defined(HAVE_FMODL)
+# define HAVE_FMODL
+# endif
+# if !defined(HAVE_LOG10L)
+# define HAVE_LOG10L
+# endif
+# endif
+# if defined(TRIO_COMPILER_VISUALC)
+# if defined(floorl)
+# define HAVE_FLOORL
+# endif
+# if defined(ceill)
+# define HAVE_CEILL
+# endif
+# if defined(powl)
+# define HAVE_POWL
+# endif
+# if defined(fmodl)
+# define HAVE_FMODL
+# endif
+# if defined(log10l)
+# define HAVE_LOG10L
+# endif
+# endif
#endif
/*************************************************************************
@@ -83,8 +186,8 @@
#include <assert.h>
#include <ctype.h>
-#if !defined(TRIO_COMPILER_SUPPORTS_C99)
-# define isblank(x) (((x)==32) || ((x)==9))
+#if defined(PREDEF_STANDARD_C99) && !defined(isascii)
+# define isascii(x) ((x) & 0x7F)
#endif
#if defined(TRIO_COMPILER_ANCIENT)
# include <varargs.h>
@@ -92,7 +195,11 @@
# include <stdarg.h>
#endif
#include <stddef.h>
-#include <errno.h>
+#if defined(TRIO_PLATFORM_WINCE)
+extern int errno;
+#else
+# include <errno.h>
+#endif
#ifndef NULL
# define NULL 0
@@ -107,7 +214,7 @@
/* mincore() can be used for debugging purposes */
#define VALID(x) (NULL != (x))
-#if TRIO_ERRORS
+#if TRIO_FEATURE_ERRORCODE
/*
* Encode the error code and the position. This is decoded
* with TRIO_ERROR_CODE and TRIO_ERROR_POSITION.
@@ -127,19 +234,26 @@ typedef unsigned long trio_flags_t;
# include <unistd.h>
# include <signal.h>
# include <locale.h>
-# define USE_LOCALE
+# if !defined(TRIO_FEATURE_LOCALE)
+# define USE_LOCALE
+# endif
#endif /* TRIO_PLATFORM_UNIX */
#if defined(TRIO_PLATFORM_VMS)
# include <unistd.h>
#endif
#if defined(TRIO_PLATFORM_WIN32)
-# include <io.h>
-# define read _read
-# define write _write
+# if defined(TRIO_PLATFORM_WINCE)
+int read(int handle, char *buffer, unsigned int length);
+int write(int handle, const char *buffer, unsigned int length);
+# else
+# include <io.h>
+# define read _read
+# define write _write
+# endif
#endif /* TRIO_PLATFORM_WIN32 */
-#if TRIO_WIDECHAR
-# if defined(TRIO_COMPILER_SUPPORTS_ISO94)
+#if TRIO_FEATURE_WIDECHAR
+# if defined(PREDEF_STANDARD_C94)
# include <wchar.h>
# include <wctype.h>
typedef wchar_t trio_wchar_t;
@@ -151,7 +265,6 @@ typedef int trio_wint_t;
# 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)
@@ -174,10 +287,18 @@ typedef int trio_wint_t;
# 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
+# else
+# if defined(TRIO_COMPILER_SUNPRO)
+# define USE_LONGLONG
+# else
+# if defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1400)
+# define USE_LONGLONG
+# else
+# if defined(_LONG_LONG) || defined(_LONGLONG)
+# define USE_LONGLONG
+# endif
+# endif
+# endif
# endif
# endif
#endif
@@ -186,16 +307,18 @@ typedef int trio_wint_t;
#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)
+#else
+# if defined(TRIO_COMPILER_SUPPORTS_VISUALC_INT)
typedef signed __int64 trio_longlong_t;
typedef unsigned __int64 trio_ulonglong_t;
-#else
+# else
typedef TRIO_SIGNED long int trio_longlong_t;
typedef unsigned long int trio_ulonglong_t;
+# endif
#endif
/* Maximal and fixed integer types */
-#if defined(TRIO_COMPILER_SUPPORTS_C99)
+#if defined(PREDEF_STANDARD_C99)
# include <stdint.h>
typedef intmax_t trio_intmax_t;
typedef uintmax_t trio_uintmax_t;
@@ -203,100 +326,137 @@ 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)
-# include <inttypes.h>
+#else
+# if defined(PREDEF_STANDARD_UNIX98)
+# include <inttypes.h>
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)
+# else
+# if defined(TRIO_COMPILER_SUPPORTS_VISUALC_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
+# else
typedef trio_longlong_t trio_intmax_t;
typedef trio_ulonglong_t trio_uintmax_t;
-# if defined(TRIO_INT8_T)
+# if defined(TRIO_INT8_T)
typedef TRIO_INT8_T trio_int8_t;
-# else
+# else
typedef TRIO_SIGNED char trio_int8_t;
-# endif
-# if defined(TRIO_INT16_T)
+# endif
+# if defined(TRIO_INT16_T)
typedef TRIO_INT16_T trio_int16_t;
-# else
+# else
typedef TRIO_SIGNED short trio_int16_t;
-# endif
-# if defined(TRIO_INT32_T)
+# endif
+# if defined(TRIO_INT32_T)
typedef TRIO_INT32_T trio_int32_t;
-# else
+# else
typedef TRIO_SIGNED int trio_int32_t;
-# endif
-# if defined(TRIO_INT64_T)
+# endif
+# if defined(TRIO_INT64_T)
typedef TRIO_INT64_T trio_int64_t;
-# else
+# else
typedef trio_longlong_t trio_int64_t;
+# endif
+# endif
# endif
#endif
-#if !(defined(TRIO_COMPILER_SUPPORTS_C99) \
- || defined(TRIO_COMPILER_SUPPORTS_UNIX01))
-# define floorl(x) floor((double)(x))
-# define fmodl(x,y) fmod((double)(x),(double)(y))
-# define powl(x,y) pow((double)(x),(double)(y))
+#if defined(HAVE_FLOORL)
+# define trio_floor(x) floorl((x))
+#else
+# define trio_floor(x) floor((double)(x))
#endif
-#define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x))
+#if defined(HAVE_CEILL)
+# define trio_ceil(x) ceill((x))
+#else
+# define trio_ceil(x) ceil((double)(x))
+#endif
-/*************************************************************************
- * Internal Definitions
- */
+#if defined(HAVE_FMODL)
+# define trio_fmod(x,y) fmodl((x),(y))
+#else
+# define trio_fmod(x,y) fmod((double)(x),(double)(y))
+#endif
-#ifndef DECIMAL_DIG
-# define DECIMAL_DIG DBL_DIG
+#if defined(HAVE_POWL)
+# define trio_pow(x,y) powl((x),(y))
+#else
+# define trio_pow(x,y) pow((double)(x),(double)(y))
#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
+#if defined(HAVE_LOG10L)
+# define trio_log10(x) log10l((x))
#else
-# define MAX_MANTISSA_DIGITS DECIMAL_DIG
-# define MAX_EXPONENT_DIGITS 3
-# define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP
+# define trio_log10(x) log10((double)(x))
#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
+#if TRIO_FEATURE_FLOAT
+# define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x))
#endif
+/*************************************************************************
+ * Internal Definitions
+ */
+
+#if TRIO_FEATURE_FLOAT
+
+# if !defined(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
+
+#endif /* TRIO_FEATURE_FLOAT */
+
/* 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)
+#if TRIO_FEATURE_FLOAT
/* 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"
+# 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"
+#endif
/* Various constants */
enum {
TYPE_PRINT = 1,
+#if TRIO_FEATURE_SCANF
TYPE_SCAN = 2,
+#endif
/* Flags. FLAGS_LAST must be less than ULONG_MAX */
FLAGS_NEW = 0,
@@ -326,8 +486,7 @@ enum {
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 = 2 * FLAGS_WIDECHAR,
FLAGS_IGNORE_PARAMETER = 2 * FLAGS_IGNORE,
FLAGS_VARSIZE_PARAMETER = 2 * FLAGS_IGNORE_PARAMETER,
FLAGS_FIXED_SIZE = 2 * FLAGS_VARSIZE_PARAMETER,
@@ -335,6 +494,7 @@ enum {
/* Reused flags */
FLAGS_EXCLUDE = FLAGS_SHORT,
FLAGS_USER_DEFINED = FLAGS_IGNORE,
+ FLAGS_USER_DEFINED_PARAMETER = FLAGS_IGNORE_PARAMETER,
FLAGS_ROUNDING = FLAGS_INTMAX_T,
/* Compounded flags */
FLAGS_ALL_VARSIZES = FLAGS_LONG | FLAGS_QUAD | FLAGS_INTMAX_T | FLAGS_PTRDIFF_T | FLAGS_SIZE_T,
@@ -359,22 +519,22 @@ enum {
/* Maximal number of characters in class */
MAX_CHARACTER_CLASS = UCHAR_MAX + 1,
+#if TRIO_FEATURE_USER_DEFINED
/* Maximal string lengths for user-defined specifiers */
MAX_USER_NAME = 64,
MAX_USER_DATA = 256,
+#endif
/* 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
+ MAX_LOCALE_GROUPS = 64
};
#define NO_GROUPING ((int)CHAR_MAX)
/* Fundamental formatting parameter types */
+#define FORMAT_SENTINEL -1 /* marks end of parameters array */
#define FORMAT_UNKNOWN 0
#define FORMAT_INT 1
#define FORMAT_DOUBLE 2
@@ -384,32 +544,31 @@ enum {
#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
+#define FORMAT_ERRNO 9
+#define FORMAT_USER_DEFINED 10
/* Character constants */
#define CHAR_IDENTIFIER '%'
+#define CHAR_ALT_IDENTIFIER '$'
#define CHAR_BACKSLASH '\\'
#define CHAR_QUOTE '\"'
#define CHAR_ADJUST ' '
+#if TRIO_EXTENSION
/* 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:]"
+# 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:]"
+#endif
/*
* SPECIFIERS:
@@ -451,33 +610,36 @@ enum {
#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'
+#if TRIO_FEATURE_FLOAT
+# 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'
+#endif
#define SPECIFIER_POINTER 'p'
-#define SPECIFIER_GROUP '['
-#define SPECIFIER_UNGROUP ']'
+#if TRIO_FEATURE_SCANF
+# define SPECIFIER_GROUP '['
+# define SPECIFIER_UNGROUP ']'
+#endif
#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_HEXFLOAT 'a'
+#define SPECIFIER_HEXFLOAT_UPPER 'A'
+#define SPECIFIER_ERRNO 'm'
+#if TRIO_FEATURE_BINARY
# define SPECIFIER_BINARY 'b'
# define SPECIFIER_BINARY_UPPER 'B'
+#endif
+#if TRIO_FEATURE_USER_DEFINED
# define SPECIFIER_USER_DEFINED_BEGIN '<'
# define SPECIFIER_USER_DEFINED_END '>'
# define SPECIFIER_USER_DEFINED_SEPARATOR ':'
+# define SPECIFIER_USER_DEFINED_EXTRA '|'
#endif
/*
@@ -580,31 +742,23 @@ enum {
#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
+#define QUALIFIER_SIZE_T 'z'
+#define QUALIFIER_PTRDIFF_T 't'
+#define QUALIFIER_INTMAX_T 'j'
+#define QUALIFIER_QUAD 'q'
+#define QUALIFIER_SIZE_T_UPPER 'Z'
#if TRIO_MISC
# define QUALIFIER_WIDECHAR 'w'
#endif
-#if TRIO_MICROSOFT
-# define QUALIFIER_FIXED_SIZE 'I'
-#endif
+#define QUALIFIER_FIXED_SIZE 'I'
+#define QUALIFIER_QUOTE '\''
+#define QUALIFIER_STICKY '!'
+#define QUALIFIER_VARSIZE '&' /* This should remain undocumented */
+#define QUALIFIER_ROUNDING_UPPER 'R'
#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
@@ -626,14 +780,20 @@ typedef struct {
int precision;
/* The base qualifier */
int base;
+ /* Base from specifier */
+ int baseSpecifier;
/* The size for the variable size qualifier */
int varsize;
- /* The marker of the end of the specifier */
- int indexAfterSpecifier;
+ /* Offset of the first character of the specifier */
+ int beginOffset;
+ /* Offset of the first character after the specifier */
+ int endOffset;
+ /* Position in the argument list that this parameter refers to */
+ int position;
/* The data from the argument list */
union {
char *string;
-#if TRIO_WIDECHAR
+#if TRIO_FEATURE_WIDECHAR
trio_wchar_t *wstring;
#endif
trio_pointer_t pointer;
@@ -641,15 +801,22 @@ typedef struct {
trio_intmax_t as_signed;
trio_uintmax_t as_unsigned;
} number;
+#if TRIO_FEATURE_FLOAT
double doubleNumber;
double *doublePointer;
trio_long_double_t longdoubleNumber;
trio_long_double_t *longdoublePointer;
+#endif
int errorNumber;
} data;
+#if TRIO_FEATURE_USER_DEFINED
/* For the user-defined specifier */
- char user_name[MAX_USER_NAME];
+ union {
+ char namespace[MAX_USER_NAME];
+ int handler; /* if flags & FLAGS_USER_DEFINED_PARAMETER */
+ } user_defined;
char user_data[MAX_USER_DATA];
+#endif
} trio_parameter_t;
/* Container for customized functions */
@@ -672,6 +839,10 @@ typedef struct _trio_class_t {
*/
void (*InStream) TRIO_PROTO((struct _trio_class_t *, int *));
/*
+ * The function to undo read characters from a stream.
+ */
+ void (*UndoStream) TRIO_PROTO((struct _trio_class_t *));
+ /*
* The current location in the stream.
*/
trio_pointer_t location;
@@ -684,12 +855,17 @@ typedef struct _trio_class_t {
* 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;
+ union {
+ /*
+ * The number of characters that are actually written. Processed and
+ * committed will only differ for the *nprintf functions.
+ */
+ int committed;
+ /*
+ * The number of look-ahead characters read.
+ */
+ int cached;
+ } actually;
/*
* The upper limit of characters that may be written/read.
*/
@@ -706,12 +882,14 @@ typedef struct _trio_reference_t {
trio_parameter_t *parameter;
} trio_reference_t;
+#if TRIO_FEATURE_USER_DEFINED
/* 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;
+#endif
/*************************************************************************
*
@@ -719,15 +897,17 @@ typedef struct _trio_userdef_t {
*
*************************************************************************/
-static TRIO_CONST char rcsid[] = "@(#)$Id: trio.c,v 1.75 2003/03/01 15:34:01 breese Exp $";
+static TRIO_CONST char rcsid[] = "@(#)$Id: trio.c,v 1.125 2009/06/23 15:46:21 breese Exp $";
+#if TRIO_FEATURE_FLOAT
/*
* 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)
+# if defined(TRIO_PLATFORM_MPEIX)
static TRIO_CONST trio_long_double_t ___dummy_long_double = 0;
+# endif
#endif
static TRIO_CONST char internalNullString[] = "(nil)";
@@ -740,23 +920,29 @@ static struct lconv *internalLocaleValues = NULL;
* UNIX98 says "in a locale where the radix character is not defined,
* the radix character defaults to a period (.)"
*/
+#if TRIO_FEATURE_FLOAT || TRIO_FEATURE_LOCALE || defined(USE_LOCALE)
static int internalDecimalPointLength = 1;
-static int internalThousandSeparatorLength = 1;
static char internalDecimalPoint = '.';
static char internalDecimalPointString[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ".";
+#endif
+#if TRIO_FEATURE_QUOTE || TRIO_FEATURE_LOCALE || TRIO_EXTENSION
+static int internalThousandSeparatorLength = 1;
static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ",";
static char internalGrouping[MAX_LOCALE_GROUPS] = { (char)NO_GROUPING };
+#endif
static TRIO_CONST char internalDigitsLower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static TRIO_CONST char internalDigitsUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+#if TRIO_FEATURE_SCANF
static BOOLEAN_T internalDigitsUnconverted = TRUE;
static int internalDigitArray[128];
-#if TRIO_EXTENSION
+# if TRIO_EXTENSION
static BOOLEAN_T internalCollationUnconverted = TRUE;
static char internalCollationArray[MAX_CHARACTER_CLASS][MAX_CHARACTER_CLASS];
+# endif
#endif
-#if TRIO_EXTENSION
+#if TRIO_FEATURE_USER_DEFINED
static TRIO_VOLATILE trio_callback_t internalEnterCriticalRegion = NULL;
static TRIO_VOLATILE trio_callback_t internalLeaveCriticalRegion = NULL;
static trio_userdef_t *internalUserDef = NULL;
@@ -769,10 +955,80 @@ static trio_userdef_t *internalUserDef = NULL;
*
************************************************************************/
-#if defined(TRIO_MINIMAL)
-# define TRIO_STRING_PUBLIC static
+#if defined(TRIO_EMBED_NAN)
+# include "trionan.c"
+#endif
+
+#if defined(TRIO_EMBED_STRING)
# include "triostr.c"
-#endif /* defined(TRIO_MINIMAL) */
+#endif
+
+/*************************************************************************
+ * TrioInitializeParameter
+ *
+ * Description:
+ * Initialize a trio_parameter_t struct.
+ */
+TRIO_PRIVATE void
+TrioInitializeParameter
+TRIO_ARGS1((parameter),
+ trio_parameter_t *parameter)
+{
+ parameter->type = FORMAT_UNKNOWN;
+ parameter->flags = 0;
+ parameter->width = 0;
+ parameter->precision = 0;
+ parameter->base = 0;
+ parameter->baseSpecifier = 0;
+ parameter->varsize = 0;
+ parameter->beginOffset = 0;
+ parameter->endOffset = 0;
+ parameter->position = 0;
+ parameter->data.pointer = 0;
+#if TRIO_FEATURE_USER_DEFINED
+ parameter->user_defined.handler = 0;
+ parameter->user_data[0] = 0;
+#endif
+}
+
+/*************************************************************************
+ * TrioCopyParameter
+ *
+ * Description:
+ * Copies one trio_parameter_t struct to another.
+ */
+TRIO_PRIVATE void
+TrioCopyParameter
+TRIO_ARGS2((target, source),
+ trio_parameter_t *target,
+ TRIO_CONST trio_parameter_t *source)
+{
+#if TRIO_FEATURE_USER_DEFINED
+ size_t i;
+#endif
+
+ target->type = source->type;
+ target->flags = source->flags;
+ target->width = source->width;
+ target->precision = source->precision;
+ target->base = source->base;
+ target->baseSpecifier = source->baseSpecifier;
+ target->varsize = source->varsize;
+ target->beginOffset = source->beginOffset;
+ target->endOffset = source->endOffset;
+ target->position = source->position;
+ target->data = source->data;
+
+#if TRIO_FEATURE_USER_DEFINED
+ target->user_defined = source->user_defined;
+
+ for (i = 0U; i < sizeof(target->user_data); ++i)
+ {
+ if ((target->user_data[i] = source->user_data[i]) == NIL)
+ break;
+ }
+#endif
+}
/*************************************************************************
* TrioIsQualifier
@@ -799,44 +1055,24 @@ TRIO_ARGS1((character),
case QUALIFIER_ALTERNATIVE:
case QUALIFIER_SHORT:
case QUALIFIER_LONG:
- case QUALIFIER_LONG_UPPER:
case QUALIFIER_CIRCUMFLEX:
-#if defined(QUALIFIER_SIZE_T)
+ case QUALIFIER_LONG_UPPER:
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;
@@ -869,6 +1105,7 @@ TrioSetLocale(TRIO_NOARGS)
internalLocaleValues->decimal_point);
}
}
+# if TRIO_EXTENSION
if ((internalLocaleValues->thousands_sep) &&
(internalLocaleValues->thousands_sep[0] != NIL))
{
@@ -877,6 +1114,8 @@ TrioSetLocale(TRIO_NOARGS)
internalLocaleValues->thousands_sep);
internalThousandSeparatorLength = trio_length(internalThousandSeparator);
}
+# endif
+# if TRIO_EXTENSION
if ((internalLocaleValues->grouping) &&
(internalLocaleValues->grouping[0] != NIL))
{
@@ -884,16 +1123,17 @@ TrioSetLocale(TRIO_NOARGS)
sizeof(internalGrouping),
internalLocaleValues->grouping);
}
+# endif
}
}
#endif /* defined(USE_LOCALE) */
+#if TRIO_FEATURE_FLOAT && TRIO_FEATURE_QUOTE
TRIO_PRIVATE int
TrioCalcThousandSeparatorLength
TRIO_ARGS1((digits),
int digits)
{
-#if TRIO_EXTENSION
int count = 0;
int step = NO_GROUPING;
char *groupingPointer = internalGrouping;
@@ -923,17 +1163,15 @@ TRIO_ARGS1((digits),
digits -= step;
}
return count;
-#else
- return 0;
-#endif
}
+#endif /* TRIO_FEATURE_FLOAT && TRIO_FEATURE_QUOTE */
+#if TRIO_FEATURE_QUOTE
TRIO_PRIVATE BOOLEAN_T
TrioFollowedBySeparator
TRIO_ARGS1((position),
int position)
{
-#if TRIO_EXTENSION
int step = 0;
char *groupingPointer = internalGrouping;
@@ -956,10 +1194,8 @@ TRIO_ARGS1((position),
position -= step;
}
return (position == 0);
-#else
- return FALSE;
-#endif
}
+#endif /* TRIO_FEATURE_QUOTE */
/*************************************************************************
* TrioGetPosition
@@ -968,20 +1204,20 @@ TRIO_ARGS1((position),
*/
TRIO_PRIVATE int
TrioGetPosition
-TRIO_ARGS2((format, indexPointer),
+TRIO_ARGS2((format, offsetPointer),
TRIO_CONST char *format,
- int *indexPointer)
+ int *offsetPointer)
{
-#if TRIO_UNIX98
+#if TRIO_FEATURE_POSITIONAL
char *tmpformat;
int number = 0;
- int index = *indexPointer;
+ int offset = *offsetPointer;
- number = (int)trio_to_long(&format[index], &tmpformat, BASE_DECIMAL);
- index = (int)(tmpformat - format);
- if ((number != 0) && (QUALIFIER_POSITION == format[index++]))
+ number = (int)trio_to_long(&format[offset], &tmpformat, BASE_DECIMAL);
+ offset = (int)(tmpformat - format);
+ if ((number != 0) && (QUALIFIER_POSITION == format[offset++]))
{
- *indexPointer = index;
+ *offsetPointer = offset;
/*
* number is decreased by 1, because n$ starts from 1, whereas
* the array it is indexing starts from 0.
@@ -992,13 +1228,13 @@ TRIO_ARGS2((format, indexPointer),
return NO_POSITION;
}
-#if TRIO_EXTENSION
/*************************************************************************
* TrioFindNamespace
*
* Find registered user-defined specifier.
* The prev argument is used for optimization only.
*/
+#if TRIO_FEATURE_USER_DEFINED
TRIO_PRIVATE trio_userdef_t *
TrioFindNamespace
TRIO_ARGS2((name, prev),
@@ -1033,6 +1269,7 @@ TRIO_ARGS2((name, prev),
* Description:
* Calculate pow(base, exponent), where number and exponent are integers.
*/
+#if TRIO_FEATURE_FLOAT
TRIO_PRIVATE trio_long_double_t
TrioPower
TRIO_ARGS2((number, exponent),
@@ -1077,28 +1314,31 @@ TRIO_ARGS2((number, exponent),
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);
+ result = trio_pow((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 trio_pow((trio_long_double_t)number,
+ (trio_long_double_t)exponent);
}
return result;
}
+#endif /* TRIO_FEATURE_FLOAT */
/*************************************************************************
* TrioLogarithm
*/
-TRIO_PRIVATE double
+#if TRIO_FEATURE_FLOAT
+TRIO_PRIVATE trio_long_double_t
TrioLogarithm
TRIO_ARGS2((number, base),
- double number,
+ trio_long_double_t number,
int base)
{
- double result;
+ trio_long_double_t result;
if (number <= 0.0)
{
@@ -1109,19 +1349,21 @@ TRIO_ARGS2((number, base),
{
if (base == 10)
{
- result = log10(number);
+ result = trio_log10(number);
}
else
{
- result = log10(number) / log10((double)base);
+ result = trio_log10(number) / trio_log10((double)base);
}
}
return result;
}
+#endif /* TRIO_FEATURE_FLOAT */
/*************************************************************************
* TrioLogarithmBase
*/
+#if TRIO_FEATURE_FLOAT
TRIO_PRIVATE double
TrioLogarithmBase
TRIO_ARGS1((base),
@@ -1136,6 +1378,557 @@ TRIO_ARGS1((base),
default : return TrioLogarithm((double)base, 2);
}
}
+#endif /* TRIO_FEATURE_FLOAT */
+
+/*************************************************************************
+ * TrioParseQualifiers
+ *
+ * Description:
+ * Parse the qualifiers of a potential conversion specifier
+ */
+TRIO_PRIVATE int
+TrioParseQualifiers
+TRIO_ARGS4((type, format, offset, parameter),
+ int type,
+ TRIO_CONST char *format,
+ int offset,
+ trio_parameter_t *parameter)
+{
+ char ch;
+ int dots = 0; /* Count number of dots in modifier part */
+ char *tmpformat;
+
+ parameter->beginOffset = offset - 1;
+ parameter->flags = FLAGS_NEW;
+ parameter->position = TrioGetPosition(format, &offset);
+
+ /* Default values */
+ parameter->width = NO_WIDTH;
+ parameter->precision = NO_PRECISION;
+ parameter->base = NO_BASE;
+ parameter->varsize = NO_SIZE;
+
+ while (TrioIsQualifier(format[offset]))
+ {
+ ch = format[offset++];
+
+ switch (ch)
+ {
+ case QUALIFIER_SPACE:
+ parameter->flags |= FLAGS_SPACE;
+ break;
+
+ case QUALIFIER_PLUS:
+ parameter->flags |= FLAGS_SHOWSIGN;
+ break;
+
+ case QUALIFIER_MINUS:
+ parameter->flags |= FLAGS_LEFTADJUST;
+ parameter->flags &= ~FLAGS_NILPADDING;
+ break;
+
+ case QUALIFIER_ALTERNATIVE:
+ parameter->flags |= FLAGS_ALTERNATIVE;
+ break;
+
+ case QUALIFIER_DOT:
+ if (dots == 0) /* Precision */
+ {
+ dots++;
+
+ /* Skip if no precision */
+ if (QUALIFIER_DOT == format[offset])
+ break;
+
+ /* After the first dot we have the precision */
+ parameter->flags |= FLAGS_PRECISION;
+ if ((QUALIFIER_STAR == format[offset])
+#if defined(QUALIFIER_PARAM)
+ || (QUALIFIER_PARAM == format[offset])
+#endif
+ )
+ {
+ offset++;
+ parameter->flags |= FLAGS_PRECISION_PARAMETER;
+ parameter->precision = TrioGetPosition(format, &offset);
+ }
+ else
+ {
+ parameter->precision = trio_to_long(&format[offset],
+ &tmpformat,
+ BASE_DECIMAL);
+ offset = (int)(tmpformat - format);
+ }
+ }
+ else if (dots == 1) /* Base */
+ {
+ dots++;
+
+ /* After the second dot we have the base */
+ parameter->flags |= FLAGS_BASE;
+ if ((QUALIFIER_STAR == format[offset])
+#if defined(QUALIFIER_PARAM)
+ || (QUALIFIER_PARAM == format[offset])
+#endif
+ )
+ {
+ offset++;
+ parameter->flags |= FLAGS_BASE_PARAMETER;
+ parameter->base = TrioGetPosition(format, &offset);
+ }
+ else
+ {
+ parameter->base = trio_to_long(&format[offset],
+ &tmpformat,
+ BASE_DECIMAL);
+ if (parameter->base > MAX_BASE)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ offset = (int)(tmpformat - format);
+ }
+ }
+ else
+ {
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ }
+ break; /* QUALIFIER_DOT */
+
+#if defined(QUALIFIER_PARAM)
+ case QUALIFIER_PARAM:
+ parameter->type = TYPE_PRINT;
+ /* FALLTHROUGH */
+#endif
+ case QUALIFIER_STAR:
+ /* This has different meanings for print and scan */
+ if (TYPE_PRINT == type)
+ {
+ /* Read with from parameter */
+ int width = TrioGetPosition(format, &offset);
+ parameter->flags |= (FLAGS_WIDTH | FLAGS_WIDTH_PARAMETER);
+ if (NO_POSITION != width)
+ parameter->width = width;
+ /* else keep parameter->width = NO_WIDTH which != NO_POSITION */
+ }
+#if TRIO_FEATURE_SCANF
+ else
+ {
+ /* Scan, but do not store result */
+ parameter->flags |= FLAGS_IGNORE;
+ }
+#endif
+ break; /* QUALIFIER_STAR */
+
+ case '0':
+ if (! (parameter->flags & FLAGS_LEFTADJUST))
+ parameter->flags |= FLAGS_NILPADDING;
+ /* FALLTHROUGH */
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ parameter->flags |= FLAGS_WIDTH;
+ /*
+ * &format[offset - 1] is used to "rewind" the read
+ * character from format
+ */
+ parameter->width = trio_to_long(&format[offset - 1],
+ &tmpformat,
+ BASE_DECIMAL);
+ offset = (int)(tmpformat - format);
+ break;
+
+ case QUALIFIER_SHORT:
+ if (parameter->flags & FLAGS_SHORTSHORT)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ else if (parameter->flags & FLAGS_SHORT)
+ parameter->flags |= FLAGS_SHORTSHORT;
+ else
+ parameter->flags |= FLAGS_SHORT;
+ break;
+
+ case QUALIFIER_LONG:
+ if (parameter->flags & FLAGS_QUAD)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ else if (parameter->flags & FLAGS_LONG)
+ parameter->flags |= FLAGS_QUAD;
+ else
+ parameter->flags |= FLAGS_LONG;
+ break;
+
+#if TRIO_FEATURE_LONGDOUBLE
+ case QUALIFIER_LONG_UPPER:
+ parameter->flags |= FLAGS_LONGDOUBLE;
+ break;
+#endif
+
+#if TRIO_FEATURE_SIZE_T
+ case QUALIFIER_SIZE_T:
+ parameter->flags |= FLAGS_SIZE_T;
+ /* Modify flags for later truncation of number */
+ if (sizeof(size_t) == sizeof(trio_ulonglong_t))
+ parameter->flags |= FLAGS_QUAD;
+ else if (sizeof(size_t) == sizeof(long))
+ parameter->flags |= FLAGS_LONG;
+ break;
+#endif
+
+#if TRIO_FEATURE_PTRDIFF_T
+ case QUALIFIER_PTRDIFF_T:
+ parameter->flags |= FLAGS_PTRDIFF_T;
+ if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t))
+ parameter->flags |= FLAGS_QUAD;
+ else if (sizeof(ptrdiff_t) == sizeof(long))
+ parameter->flags |= FLAGS_LONG;
+ break;
+#endif
+
+#if TRIO_FEATURE_INTMAX_T
+ case QUALIFIER_INTMAX_T:
+ parameter->flags |= FLAGS_INTMAX_T;
+ if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t))
+ parameter->flags |= FLAGS_QUAD;
+ else if (sizeof(trio_intmax_t) == sizeof(long))
+ parameter->flags |= FLAGS_LONG;
+ break;
+#endif
+
+#if TRIO_FEATURE_QUAD
+ case QUALIFIER_QUAD:
+ parameter->flags |= FLAGS_QUAD;
+ break;
+#endif
+
+#if TRIO_FEATURE_FIXED_SIZE
+ case QUALIFIER_FIXED_SIZE:
+ if (parameter->flags & FLAGS_FIXED_SIZE)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+
+ if (parameter->flags & (FLAGS_ALL_SIZES |
+ FLAGS_LONGDOUBLE |
+ FLAGS_WIDECHAR |
+ FLAGS_VARSIZE_PARAMETER))
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+
+ if ((format[offset] == '6') &&
+ (format[offset + 1] == '4'))
+ {
+ parameter->varsize = sizeof(trio_int64_t);
+ offset += 2;
+ }
+ else if ((format[offset] == '3') &&
+ (format[offset + 1] == '2'))
+ {
+ parameter->varsize = sizeof(trio_int32_t);
+ offset += 2;
+ }
+ else if ((format[offset] == '1') &&
+ (format[offset + 1] == '6'))
+ {
+ parameter->varsize = sizeof(trio_int16_t);
+ offset += 2;
+ }
+ else if (format[offset] == '8')
+ {
+ parameter->varsize = sizeof(trio_int8_t);
+ offset++;
+ }
+ else
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+
+ parameter->flags |= FLAGS_FIXED_SIZE;
+ break;
+#endif /* TRIO_FEATURE_FIXED_SIZE */
+
+#if defined(QUALIFIER_WIDECHAR)
+ case QUALIFIER_WIDECHAR:
+ parameter->flags |= FLAGS_WIDECHAR;
+ break;
+#endif
+
+#if TRIO_FEATURE_SIZE_T_UPPER
+ case QUALIFIER_SIZE_T_UPPER:
+ break;
+#endif
+
+#if TRIO_FEATURE_QUOTE
+ case QUALIFIER_QUOTE:
+ parameter->flags |= FLAGS_QUOTE;
+ break;
+#endif
+
+#if TRIO_FEATURE_STICKY
+ case QUALIFIER_STICKY:
+ parameter->flags |= FLAGS_STICKY;
+ break;
+#endif
+
+#if TRIO_FEATURE_VARSIZE
+ case QUALIFIER_VARSIZE:
+ parameter->flags |= FLAGS_VARSIZE_PARAMETER;
+ break;
+#endif
+
+#if TRIO_FEATURE_ROUNDING
+ case QUALIFIER_ROUNDING_UPPER:
+ parameter->flags |= FLAGS_ROUNDING;
+ break;
+#endif
+
+ default:
+ /* Bail out completely to make the error more obvious */
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ }
+ } /* while qualifier */
+
+ parameter->endOffset = offset;
+
+ return 0;
+}
+
+/*************************************************************************
+ * TrioParseSpecifier
+ *
+ * Description:
+ * Parse the specifier part of a potential conversion specifier
+ */
+TRIO_PRIVATE int
+TrioParseSpecifier
+TRIO_ARGS4((type, format, offset, parameter),
+ int type,
+ TRIO_CONST char *format,
+ int offset,
+ trio_parameter_t *parameter)
+{
+ parameter->baseSpecifier = NO_BASE;
+
+ switch (format[offset++])
+ {
+#if defined(SPECIFIER_CHAR_UPPER)
+ case SPECIFIER_CHAR_UPPER:
+ parameter->flags |= FLAGS_WIDECHAR;
+ /* FALLTHROUGH */
+#endif
+ case SPECIFIER_CHAR:
+ if (parameter->flags & FLAGS_LONG)
+ parameter->flags |= FLAGS_WIDECHAR;
+ else if (parameter->flags & FLAGS_SHORT)
+ parameter->flags &= ~FLAGS_WIDECHAR;
+ parameter->type = FORMAT_CHAR;
+ break;
+
+#if defined(SPECIFIER_STRING_UPPER)
+ case SPECIFIER_STRING_UPPER:
+ parameter->flags |= FLAGS_WIDECHAR;
+ /* FALLTHROUGH */
+#endif
+ case SPECIFIER_STRING:
+ if (parameter->flags & FLAGS_LONG)
+ parameter->flags |= FLAGS_WIDECHAR;
+ else if (parameter->flags & FLAGS_SHORT)
+ parameter->flags &= ~FLAGS_WIDECHAR;
+ parameter->type = FORMAT_STRING;
+ break;
+
+#if defined(SPECIFIER_GROUP)
+ case SPECIFIER_GROUP:
+ if (TYPE_SCAN == type)
+ {
+ int depth = 1;
+ parameter->type = FORMAT_GROUP;
+ if (format[offset] == QUALIFIER_CIRCUMFLEX)
+ offset++;
+ if (format[offset] == SPECIFIER_UNGROUP)
+ offset++;
+ if (format[offset] == QUALIFIER_MINUS)
+ offset++;
+ /* Skip nested brackets */
+ while (format[offset] != NIL)
+ {
+ if (format[offset] == SPECIFIER_GROUP)
+ {
+ depth++;
+ }
+ else if (format[offset] == SPECIFIER_UNGROUP)
+ {
+ if (--depth <= 0)
+ {
+ offset++;
+ break;
+ }
+ }
+ offset++;
+ }
+ }
+ break;
+#endif /* defined(SPECIFIER_GROUP) */
+
+ case SPECIFIER_INTEGER:
+ parameter->type = FORMAT_INT;
+ break;
+
+ case SPECIFIER_UNSIGNED:
+ parameter->flags |= FLAGS_UNSIGNED;
+ parameter->type = FORMAT_INT;
+ break;
+
+ case SPECIFIER_DECIMAL:
+ parameter->baseSpecifier = BASE_DECIMAL;
+ parameter->type = FORMAT_INT;
+ break;
+
+ case SPECIFIER_OCTAL:
+ parameter->flags |= FLAGS_UNSIGNED;
+ parameter->baseSpecifier = BASE_OCTAL;
+ parameter->type = FORMAT_INT;
+ break;
+
+#if TRIO_FEATURE_BINARY
+ case SPECIFIER_BINARY_UPPER:
+ parameter->flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+ case SPECIFIER_BINARY:
+ parameter->flags |= FLAGS_NILPADDING;
+ parameter->baseSpecifier = BASE_BINARY;
+ parameter->type = FORMAT_INT;
+ break;
+#endif
+
+ case SPECIFIER_HEX_UPPER:
+ parameter->flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+ case SPECIFIER_HEX:
+ parameter->flags |= FLAGS_UNSIGNED;
+ parameter->baseSpecifier = BASE_HEX;
+ parameter->type = FORMAT_INT;
+ break;
+
+#if defined(SPECIFIER_FLOAT_E)
+# if defined(SPECIFIER_FLOAT_E_UPPER)
+ case SPECIFIER_FLOAT_E_UPPER:
+ parameter->flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+# endif
+ case SPECIFIER_FLOAT_E:
+ parameter->flags |= FLAGS_FLOAT_E;
+ parameter->type = FORMAT_DOUBLE;
+ break;
+#endif
+
+#if defined(SPECIFIER_FLOAT_G)
+# if defined(SPECIFIER_FLOAT_G_UPPER)
+ case SPECIFIER_FLOAT_G_UPPER:
+ parameter->flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+# endif
+ case SPECIFIER_FLOAT_G:
+ parameter->flags |= FLAGS_FLOAT_G;
+ parameter->type = FORMAT_DOUBLE;
+ break;
+#endif
+
+#if defined(SPECIFIER_FLOAT_F)
+# if defined(SPECIFIER_FLOAT_F_UPPER)
+ case SPECIFIER_FLOAT_F_UPPER:
+ parameter->flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+# endif
+ case SPECIFIER_FLOAT_F:
+ parameter->type = FORMAT_DOUBLE;
+ break;
+#endif
+
+#if defined(TRIO_COMPILER_VISUALC)
+# pragma warning( push )
+# pragma warning( disable : 4127 ) /* Conditional expression is constant */
+#endif
+ case SPECIFIER_POINTER:
+ if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t))
+ parameter->flags |= FLAGS_QUAD;
+ else if (sizeof(trio_pointer_t) == sizeof(long))
+ parameter->flags |= FLAGS_LONG;
+ parameter->type = FORMAT_POINTER;
+ break;
+#if defined(TRIO_COMPILER_VISUALC)
+# pragma warning( pop )
+#endif
+
+ case SPECIFIER_COUNT:
+ parameter->type = FORMAT_COUNT;
+ break;
+
+#if TRIO_FEATURE_HEXFLOAT
+ case SPECIFIER_HEXFLOAT_UPPER:
+ parameter->flags |= FLAGS_UPPER;
+ /* FALLTHROUGH */
+ case SPECIFIER_HEXFLOAT:
+ parameter->baseSpecifier = BASE_HEX;
+ parameter->type = FORMAT_DOUBLE;
+ break;
+#endif
+
+#if TRIO_FEATURE_ERRNO
+ case SPECIFIER_ERRNO:
+ parameter->type = FORMAT_ERRNO;
+ break;
+#endif
+
+#if TRIO_FEATURE_USER_DEFINED
+ case SPECIFIER_USER_DEFINED_BEGIN:
+ {
+ unsigned int max;
+ int without_namespace = TRUE;
+ char* tmpformat = (char *)&format[offset];
+ int ch;
+
+ parameter->type = FORMAT_USER_DEFINED;
+ parameter->user_defined.namespace[0] = NIL;
+
+ while ((ch = format[offset]) != NIL)
+ {
+ offset++;
+ if ((ch == SPECIFIER_USER_DEFINED_END) || (ch == SPECIFIER_USER_DEFINED_EXTRA))
+ {
+ if (without_namespace)
+ /* No namespace, handler will be passed as an argument */
+ parameter->flags |= FLAGS_USER_DEFINED_PARAMETER;
+
+ /* Copy the user data */
+ max = (unsigned int)(&format[offset] - tmpformat);
+ if (max > MAX_USER_DATA)
+ max = MAX_USER_DATA;
+ trio_copy_max(parameter->user_data, max, tmpformat);
+
+ /* Skip extra data (which is only there to keep the compiler happy) */
+ while ((ch != NIL) && (ch != SPECIFIER_USER_DEFINED_END))
+ ch = format[offset++];
+
+ break; /* while */
+ }
+
+ if (ch == SPECIFIER_USER_DEFINED_SEPARATOR)
+ {
+ without_namespace = FALSE;
+ /* Copy the namespace for later looking-up */
+ max = (int)(&format[offset] - tmpformat);
+ if (max > MAX_USER_NAME)
+ max = MAX_USER_NAME;
+ trio_copy_max(parameter->user_defined.namespace, max, tmpformat);
+ tmpformat = (char *)&format[offset];
+ }
+ }
+
+ if (ch != SPECIFIER_USER_DEFINED_END)
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ }
+ break;
+#endif /* TRIO_FEATURE_USER_DEFINED */
+
+ default:
+ /* Bail out completely to make the error more obvious */
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ }
+
+ parameter->endOffset = offset;
+
+ return 0;
+}
/*************************************************************************
* TrioParse
@@ -1149,25 +1942,20 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
int type,
TRIO_CONST char *format,
trio_parameter_t *parameters,
- va_list *arglist,
+ va_list 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 */
+ int offset; /* Offset into formatting string */
BOOLEAN_T positional; /* Does the specifier have a positional? */
+#if TRIO_FEATURE_STICKY
BOOLEAN_T gotSticky = FALSE; /* Are there any sticky modifiers at all? */
+#endif
/*
* indices specifies the order in which the parameters must be
* read from the va_args (this is necessary to handle positionals)
@@ -1175,18 +1963,15 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
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;
+ trio_parameter_t workParameter;
+ int status;
- /* 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.
@@ -1194,690 +1979,223 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
memset(usedEntries, 0, sizeof(usedEntries));
save_errno = errno;
- index = 0;
+ offset = 0;
parameterPosition = 0;
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
(void)mblen(NULL, 0);
#endif
- while (format[index])
+ while (format[offset])
{
+ TrioInitializeParameter(&workParameter);
+
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
- if (! isascii(format[index]))
+ if (! isascii(format[offset]))
{
/*
* 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;
+ charlen = mblen(&format[offset], MB_LEN_MAX);
+ offset += (charlen > 0) ? charlen : 1;
continue; /* while */
}
#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
- if (CHAR_IDENTIFIER == format[index++])
+
+ switch(format[offset++]) {
+
+ case CHAR_IDENTIFIER:
{
- if (CHAR_IDENTIFIER == format[index])
+ if (CHAR_IDENTIFIER == format[offset])
{
- index++;
+ /* skip double "%" */
+ offset++;
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;
+ status = TrioParseQualifiers(type, format, offset, &workParameter);
+ if (status < 0)
+ return status; /* Return qualifier syntax error */
- /* 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
+ status = TrioParseSpecifier(type, format, workParameter.endOffset, &workParameter);
+ if (status < 0)
+ return status; /* Return specifier syntax error */
+ }
+ break;
-#if defined(QUALIFIER_QUOTE)
- case QUALIFIER_QUOTE:
- flags |= FLAGS_QUOTE;
- break;
-#endif
+#if TRIO_EXTENSION
+ case CHAR_ALT_IDENTIFIER:
+ {
+ status = TrioParseQualifiers(type, format, offset, &workParameter);
+ if (status < 0)
+ continue; /* False alert, not a user defined specifier */
-#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;
+ status = TrioParseSpecifier(type, format, workParameter.endOffset, &workParameter);
+ if ((status < 0) || (FORMAT_USER_DEFINED != workParameter.type))
+ continue; /* False alert, not a user defined specifier */
+ }
+ break;
#endif
-#if defined(QUALIFIER_ROUNDING_UPPER)
- case QUALIFIER_ROUNDING_UPPER:
- flags |= FLAGS_ROUNDING;
- break;
-#endif
+ default:
+ continue; /* while */
+ }
- default:
- /* Bail out completely to make the error more obvious */
- return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
- }
- } /* while qualifier */
+ /* now handle the parsed conversion specification */
+ positional = (NO_POSITION != workParameter.position);
- /*
- * Parameters only need the type and value. The value is
- * read later.
- */
- if (flags & FLAGS_WIDTH_PARAMETER)
+ /*
+ * Parameters only need the type and value. The value is
+ * read later.
+ */
+ if (workParameter.flags & FLAGS_WIDTH_PARAMETER)
+ {
+ if (workParameter.width == NO_WIDTH)
{
- usedEntries[width] += 1;
- parameters[pos].type = FORMAT_PARAMETER;
- parameters[pos].flags = 0;
- indices[width] = pos;
- width = pos++;
+ workParameter.width = parameterPosition++;
}
- if (flags & FLAGS_PRECISION_PARAMETER)
+ else
{
- usedEntries[precision] += 1;
- parameters[pos].type = FORMAT_PARAMETER;
- parameters[pos].flags = 0;
- indices[precision] = pos;
- precision = pos++;
+ if (! positional)
+ workParameter.position = workParameter.width + 1;
}
- if (flags & FLAGS_BASE_PARAMETER)
+
+ usedEntries[workParameter.width] += 1;
+ if (workParameter.width > maxParam)
+ maxParam = workParameter.width;
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].flags = 0;
+ indices[workParameter.width] = pos;
+ workParameter.width = pos++;
+ }
+ if (workParameter.flags & FLAGS_PRECISION_PARAMETER)
+ {
+ if (workParameter.precision == NO_PRECISION)
{
- usedEntries[base] += 1;
- parameters[pos].type = FORMAT_PARAMETER;
- parameters[pos].flags = 0;
- indices[base] = pos;
- base = pos++;
+ workParameter.precision = parameterPosition++;
}
- if (flags & FLAGS_VARSIZE_PARAMETER)
+ else
{
- usedEntries[varsize] += 1;
- parameters[pos].type = FORMAT_PARAMETER;
- parameters[pos].flags = 0;
- indices[varsize] = pos;
- varsize = pos++;
+ if (! positional)
+ workParameter.position = workParameter.precision + 1;
}
-
- indices[currentParam] = pos;
-
- switch (format[index++])
+
+ usedEntries[workParameter.precision] += 1;
+ if (workParameter.precision > maxParam)
+ maxParam = workParameter.precision;
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].flags = 0;
+ indices[workParameter.precision] = pos;
+ workParameter.precision = pos++;
+ }
+ if (workParameter.flags & FLAGS_BASE_PARAMETER)
+ {
+ if (workParameter.base == NO_BASE)
{
-#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;
+ workParameter.base = parameterPosition++;
+ }
+ else
+ {
+ if (! positional)
+ workParameter.position = workParameter.base + 1;
+ }
-#if defined(SPECIFIER_STRING_UPPER)
- case SPECIFIER_STRING_UPPER:
- flags |= FLAGS_WIDECHAR;
- /* FALLTHROUGH */
+ usedEntries[workParameter.base] += 1;
+ if (workParameter.base > maxParam)
+ maxParam = workParameter.base;
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].flags = 0;
+ indices[workParameter.base] = pos;
+ workParameter.base = pos++;
+ }
+#if TRIO_FEATURE_VARSIZE
+ if (workParameter.flags & FLAGS_VARSIZE_PARAMETER)
+ {
+ workParameter.varsize = parameterPosition++;
+
+ usedEntries[workParameter.varsize] += 1;
+ if (workParameter.varsize > maxParam)
+ maxParam = workParameter.varsize;
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].flags = 0;
+ indices[workParameter.varsize] = pos;
+ workParameter.varsize = pos++;
+ }
#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;
+#if TRIO_FEATURE_USER_DEFINED
+ if (workParameter.flags & FLAGS_USER_DEFINED_PARAMETER)
+ {
+ workParameter.user_defined.handler = parameterPosition++;
+
+ usedEntries[workParameter.user_defined.handler] += 1;
+ if (workParameter.user_defined.handler > maxParam)
+ maxParam = workParameter.user_defined.handler;
+ parameters[pos].type = FORMAT_PARAMETER;
+ parameters[pos].flags = FLAGS_USER_DEFINED;
+ indices[workParameter.user_defined.handler] = pos;
+ workParameter.user_defined.handler = pos++;
+ }
#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;
+ if (NO_POSITION == workParameter.position)
+ {
+ workParameter.position = parameterPosition++;
+ }
- case SPECIFIER_FLOAT_F_UPPER:
- flags |= FLAGS_UPPER;
- /* FALLTHROUGH */
- case SPECIFIER_FLOAT_F:
- parameters[pos].type = FORMAT_DOUBLE;
- break;
+ if (workParameter.position > maxParam)
+ maxParam = workParameter.position;
- 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;
+ if (workParameter.position >= MAX_PARAMETERS)
+ {
+ /* Bail out completely to make the error more obvious */
+ return TRIO_ERROR_RETURN(TRIO_ETOOMANY, offset);
+ }
- case SPECIFIER_COUNT:
- parameters[pos].type = FORMAT_COUNT;
- break;
+ indices[workParameter.position] = pos;
-#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
+ /* Count the number of times this entry has been used */
+ usedEntries[workParameter.position] += 1;
-#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))
+ /* Find last sticky parameters */
+#if TRIO_FEATURE_STICKY
+ if (workParameter.flags & FLAGS_STICKY)
+ {
+ gotSticky = TRUE;
+ }
+ else if (gotSticky)
+ {
+ for (i = pos - 1; i >= 0; i--)
{
- for (i = pos - 1; i >= 0; i--)
+ if (parameters[i].type == FORMAT_PARAMETER)
+ continue;
+ if ((parameters[i].flags & FLAGS_STICKY) &&
+ (parameters[i].type == workParameter.type))
{
- 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;
- }
+ /* Do not overwrite current qualifiers */
+ workParameter.flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY);
+ if (workParameter.width == NO_WIDTH)
+ workParameter.width = parameters[i].width;
+ if (workParameter.precision == NO_PRECISION)
+ workParameter.precision = parameters[i].precision;
+ if (workParameter.base == NO_BASE)
+ workParameter.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 */
-
+ }
+#endif
+
+ if (workParameter.base == NO_BASE)
+ workParameter.base = BASE_DECIMAL;
+
+ offset = workParameter.endOffset;
+
+ TrioCopyParameter(&parameters[pos++], &workParameter);
} /* while format characters left */
+ parameters[pos].type = FORMAT_SENTINEL; /* end parameter array with sentinel */
+ parameters[pos].beginOffset = offset;
+
for (num = 0; num <= maxParam; num++)
{
if (usedEntries[num] != 1)
@@ -1923,40 +2241,41 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
{
case FORMAT_GROUP:
case FORMAT_STRING:
-#if TRIO_WIDECHAR
- if (flags & FLAGS_WIDECHAR)
+#if TRIO_FEATURE_WIDECHAR
+ if (parameters[i].flags & FLAGS_WIDECHAR)
{
parameters[i].data.wstring = (argarray == NULL)
- ? va_arg(*arglist, trio_wchar_t *)
+ ? va_arg(arglist, trio_wchar_t *)
: (trio_wchar_t *)(argarray[num]);
}
else
#endif
{
parameters[i].data.string = (argarray == NULL)
- ? va_arg(*arglist, char *)
+ ? va_arg(arglist, char *)
: (char *)(argarray[num]);
}
break;
-#if defined(FORMAT_USER_DEFINED)
+#if TRIO_FEATURE_USER_DEFINED
case FORMAT_USER_DEFINED:
#endif
case FORMAT_POINTER:
case FORMAT_COUNT:
case FORMAT_UNKNOWN:
parameters[i].data.pointer = (argarray == NULL)
- ? va_arg(*arglist, trio_pointer_t )
+ ? va_arg(arglist, trio_pointer_t )
: argarray[num];
break;
case FORMAT_CHAR:
case FORMAT_INT:
+#if TRIO_FEATURE_SCANF
if (TYPE_SCAN == type)
{
if (argarray == NULL)
parameters[i].data.pointer =
- (trio_pointer_t)va_arg(*arglist, trio_pointer_t);
+ (trio_pointer_t)va_arg(arglist, trio_pointer_t);
else
{
if (parameters[i].type == FORMAT_CHAR)
@@ -1971,11 +2290,13 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
}
}
else
+#endif /* TRIO_FEATURE_SCANF */
{
-#if defined(QUALIFIER_VARSIZE) || defined(QUALIFIER_FIXED_SIZE)
+#if TRIO_FEATURE_VARSIZE || TRIO_FEATURE_FIXED_SIZE
if (parameters[i].flags
& (FLAGS_VARSIZE_PARAMETER | FLAGS_FIXED_SIZE))
{
+ int varsize;
if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER)
{
/*
@@ -2000,7 +2321,7 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
;
else if (varsize <= (int)sizeof(long))
parameters[i].flags |= FLAGS_LONG;
-#if defined(QUALIFIER_INTMAX_T)
+#if TRIO_FEATURE_INTMAX_T
else if (varsize <= (int)sizeof(trio_longlong_t))
parameters[i].flags |= FLAGS_QUAD;
else
@@ -2010,40 +2331,40 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
parameters[i].flags |= FLAGS_QUAD;
#endif
}
-#endif /* defined(QUALIFIER_VARSIZE) */
-#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
+#endif /* TRIO_FEATURE_VARSIZE */
+#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
if (parameters[i].flags & FLAGS_SIZE_T)
parameters[i].data.number.as_unsigned = (argarray == NULL)
- ? (trio_uintmax_t)va_arg(*arglist, size_t)
+ ? (trio_uintmax_t)va_arg(arglist, size_t)
: (trio_uintmax_t)(*((size_t *)argarray[num]));
else
#endif
-#if defined(QUALIFIER_PTRDIFF_T)
+#if TRIO_FEATURE_PTRDIFF_T
if (parameters[i].flags & FLAGS_PTRDIFF_T)
parameters[i].data.number.as_unsigned = (argarray == NULL)
- ? (trio_uintmax_t)va_arg(*arglist, ptrdiff_t)
+ ? (trio_uintmax_t)va_arg(arglist, ptrdiff_t)
: (trio_uintmax_t)(*((ptrdiff_t *)argarray[num]));
else
#endif
-#if defined(QUALIFIER_INTMAX_T)
+#if TRIO_FEATURE_INTMAX_T
if (parameters[i].flags & FLAGS_INTMAX_T)
parameters[i].data.number.as_unsigned = (argarray == NULL)
- ? (trio_uintmax_t)va_arg(*arglist, trio_intmax_t)
+ ? (trio_uintmax_t)va_arg(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(*arglist, trio_ulonglong_t)
+ ? (trio_uintmax_t)va_arg(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(*arglist, long)
+ ? (trio_uintmax_t)va_arg(arglist, long)
: (trio_uintmax_t)(*((long *)argarray[num]));
else
{
if (argarray == NULL)
- parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(*arglist, int);
+ parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(arglist, int);
else
{
if (parameters[i].type == FORMAT_CHAR)
@@ -2064,44 +2385,47 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
*/
if (parameters[i].flags & FLAGS_USER_DEFINED)
parameters[i].data.pointer = (argarray == NULL)
- ? va_arg(*arglist, trio_pointer_t )
+ ? va_arg(arglist, trio_pointer_t )
: argarray[num];
else
parameters[i].data.number.as_unsigned = (argarray == NULL)
- ? (trio_uintmax_t)va_arg(*arglist, int)
+ ? (trio_uintmax_t)va_arg(arglist, int)
: (trio_uintmax_t)(*((int *)argarray[num]));
break;
+#if TRIO_FEATURE_FLOAT
case FORMAT_DOUBLE:
+# if TRIO_FEATURE_SCANF
if (TYPE_SCAN == type)
{
if (parameters[i].flags & FLAGS_LONGDOUBLE)
parameters[i].data.longdoublePointer = (argarray == NULL)
- ? va_arg(*arglist, trio_long_double_t *)
+ ? va_arg(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(*arglist, double *)
+ ? va_arg(arglist, double *)
: (double *)argarray[num];
else
parameters[i].data.doublePointer = (argarray == NULL)
- ? (double *)va_arg(*arglist, float *)
+ ? (double *)va_arg(arglist, float *)
: (double *)((float *)argarray[num]);
}
}
else
+# endif /* TRIO_FEATURE_SCANF */
{
if (parameters[i].flags & FLAGS_LONGDOUBLE)
parameters[i].data.longdoubleNumber = (argarray == NULL)
- ? va_arg(*arglist, trio_long_double_t)
+ ? va_arg(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(*arglist, double);
+ (trio_long_double_t)va_arg(arglist, double);
else
{
if (parameters[i].flags & FLAGS_SHORT)
@@ -2114,8 +2438,9 @@ TRIO_ARGS5((type, format, parameters, arglist, argarray),
}
}
break;
+#endif /* TRIO_FEATURE_FLOAT */
-#if defined(FORMAT_ERRNO)
+#if TRIO_FEATURE_ERRNO
case FORMAT_ERRNO:
parameters[i].data.errorNumber = save_errno;
break;
@@ -2163,9 +2488,12 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
char *pointer;
TRIO_CONST char *digits;
int i;
+#if TRIO_FEATURE_QUOTE
int length;
char *p;
+#endif
int count;
+ int digitOffset;
assert(VALID(self));
assert(VALID(self->OutStream));
@@ -2205,11 +2533,13 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
*pointer-- = NIL;
for (i = 1; i < (int)sizeof(buffer); i++)
{
- *pointer-- = digits[number % base];
+ digitOffset = number % base;
+ *pointer-- = digits[digitOffset];
number /= base;
if (number == 0)
break;
+#if TRIO_FEATURE_QUOTE
if ((flags & FLAGS_QUOTE) && TrioFollowedBySeparator(i + 1))
{
/*
@@ -2225,6 +2555,7 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
*pointer-- = *p--;
}
}
+#endif
}
if (! ignoreNumber)
@@ -2418,13 +2749,22 @@ TRIO_ARGS5((self, string, flags, width, precision),
{
string = internalNullString;
length = sizeof(internalNullString) - 1;
+#if TRIO_FEATURE_QUOTE
/* Disable quoting for the null pointer */
flags &= (~FLAGS_QUOTE);
+#endif
width = 0;
}
else
{
- length = trio_length(string);
+ if (precision == 0)
+ {
+ length = trio_length(string);
+ }
+ else
+ {
+ length = trio_length_max(string, precision);
+ }
}
if ((NO_PRECISION != precision) &&
(precision < length))
@@ -2433,8 +2773,10 @@ TRIO_ARGS5((self, string, flags, width, precision),
}
width -= length;
+#if TRIO_FEATURE_QUOTE
if (flags & FLAGS_QUOTE)
self->OutStream(self, CHAR_QUOTE);
+#endif
if (! (flags & FLAGS_LEFTADJUST))
{
@@ -2454,8 +2796,10 @@ TRIO_ARGS5((self, string, flags, width, precision),
while (width-- > 0)
self->OutStream(self, CHAR_ADJUST);
}
+#if TRIO_FEATURE_QUOTE
if (flags & FLAGS_QUOTE)
self->OutStream(self, CHAR_QUOTE);
+#endif
}
/*************************************************************************
@@ -2464,7 +2808,7 @@ TRIO_ARGS5((self, string, flags, width, precision),
* Description:
* Output a wide string as a multi-byte sequence
*/
-#if TRIO_WIDECHAR
+#if TRIO_FEATURE_WIDECHAR
TRIO_PRIVATE int
TrioWriteWideStringCharacter
TRIO_ARGS4((self, wch, flags, width),
@@ -2496,7 +2840,7 @@ TRIO_ARGS4((self, wch, flags, width),
}
return size;
}
-#endif /* TRIO_WIDECHAR */
+#endif /* TRIO_FEATURE_WIDECHAR */
/*************************************************************************
* TrioWriteWideString
@@ -2504,7 +2848,7 @@ TRIO_ARGS4((self, wch, flags, width),
* Description:
* Output a wide character string as a multi-byte string
*/
-#if TRIO_WIDECHAR
+#if TRIO_FEATURE_WIDECHAR
TRIO_PRIVATE void
TrioWriteWideString
TRIO_ARGS5((self, wstring, flags, width, precision),
@@ -2521,6 +2865,7 @@ TRIO_ARGS5((self, wstring, flags, width, precision),
assert(VALID(self->OutStream));
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ /* Required by TrioWriteWideStringCharacter */
(void)mblen(NULL, 0);
#endif
@@ -2540,8 +2885,10 @@ TRIO_ARGS5((self, wstring, flags, width, precision),
width -= length;
}
+#if TRIO_FEATURE_QUOTE
if (flags & FLAGS_QUOTE)
self->OutStream(self, CHAR_QUOTE);
+#endif
if (! (flags & FLAGS_LEFTADJUST))
{
@@ -2562,10 +2909,12 @@ TRIO_ARGS5((self, wstring, flags, width, precision),
while (width-- > 0)
self->OutStream(self, CHAR_ADJUST);
}
+#if TRIO_FEATURE_QUOTE
if (flags & FLAGS_QUOTE)
self->OutStream(self, CHAR_QUOTE);
+#endif
}
-#endif /* TRIO_WIDECHAR */
+#endif /* TRIO_FEATURE_WIDECHAR */
/*************************************************************************
* TrioWriteDouble
@@ -2582,6 +2931,7 @@ TRIO_ARGS5((self, wstring, flags, width, precision),
/* FIXME: handle all instances of constant long-double number (L)
* and *l() math functions.
*/
+#if TRIO_FEATURE_FLOAT
TRIO_PRIVATE void
TrioWriteDouble
TRIO_ARGS6((self, number, flags, width, precision, base),
@@ -2598,6 +2948,7 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
int integerDigits;
int fractionDigits;
int exponentDigits;
+ int workDigits;
int baseDigits;
int integerThreshold;
int fractionThreshold;
@@ -2606,24 +2957,29 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
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;
+ trio_long_double_t workFractionNumber;
+ trio_long_double_t workFractionAdjust;
+ int fractionDigitsInspect;
BOOLEAN_T isNegative;
BOOLEAN_T isExponentNegative = FALSE;
BOOLEAN_T requireTwoDigitExponent;
BOOLEAN_T isHex;
TRIO_CONST char *digits;
+# if TRIO_FEATURE_QUOTE
char *groupingPointer;
+# endif
int i;
- int index;
+ int offset;
BOOLEAN_T hasOnlyZeroes;
- int zeroes = 0;
+ int leadingFractionZeroes = -1;
register int trailingZeroes;
BOOLEAN_T keepTrailingZeroes;
BOOLEAN_T keepDecimalPoint;
trio_long_double_t epsilon;
+ BOOLEAN_T adjustNumber = FALSE;
assert(VALID(self));
assert(VALID(self->OutStream));
@@ -2672,21 +3028,21 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
{
baseDigits = (base == 10)
? LDBL_DIG
- : (int)floor(LDBL_MANT_DIG / TrioLogarithmBase(base));
+ : (int)trio_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));
+ : (int)trio_floor(FLT_MANT_DIG / TrioLogarithmBase(base));
epsilon = FLT_EPSILON;
}
else
{
baseDigits = (base == BASE_DECIMAL)
? DBL_DIG
- : (int)floor(DBL_MANT_DIG / TrioLogarithmBase(base));
+ : (int)trio_floor(DBL_MANT_DIG / TrioLogarithmBase(base));
epsilon = DBL_EPSILON;
}
@@ -2699,8 +3055,12 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
( (flags & FLAGS_FLOAT_G) &&
!(flags & FLAGS_ALTERNATIVE) ) );
+# if TRIO_FEATURE_ROUNDING
if (flags & FLAGS_ROUNDING)
- precision = baseDigits;
+ {
+ precision = baseDigits;
+ }
+# endif
if (precision == NO_PRECISION)
{
@@ -2716,18 +3076,24 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
}
if (isNegative)
- number = -number;
+ {
+ number = -number;
+ }
if (isHex)
- flags |= FLAGS_FLOAT_E;
+ {
+ flags |= FLAGS_FLOAT_E;
+ }
+
+ reprocess:
if (flags & FLAGS_FLOAT_G)
{
if (precision == 0)
precision = 1;
- if ((number < 1.0E-4) || (number > powl(base,
- (trio_long_double_t)precision)))
+ if ( (number < 1.0E-4) ||
+ (number >= trio_pow(base, (trio_long_double_t)precision)) )
{
/* Use scientific notation */
flags |= FLAGS_FLOAT_E;
@@ -2741,9 +3107,9 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
*/
workNumber = TrioLogarithm(number, base);
workNumber = TRIO_FABS(workNumber);
- if (workNumber - floorl(workNumber) < 0.001)
+ if (workNumber - trio_floor(workNumber) < epsilon)
workNumber--;
- zeroes = (int)floorl(workNumber);
+ leadingFractionZeroes = (int)trio_floor(workNumber);
}
}
@@ -2760,63 +3126,165 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
}
else
{
- exponent = (int)floorl(workNumber);
- number /= powl(dblBase, (trio_long_double_t)exponent);
+ exponent = (int)trio_floor(workNumber);
+ /*
+ * The expression A * 10^-B is equivalent to A / 10^B but the former
+ * usually gives better accuracy.
+ */
+ workNumber = number * trio_pow(dblBase, (trio_long_double_t)-exponent);
+ if (trio_isinf(workNumber))
+ {
+ workNumber = number / trio_pow(dblBase, (trio_long_double_t)exponent);
+ }
+ number = workNumber;
isExponentNegative = (exponent < 0);
uExponent = (isExponentNegative) ? -exponent : exponent;
if (isHex)
uExponent *= 4; /* log16(2) */
+#if TRIO_FEATURE_QUOTE
/* No thousand separators */
flags &= ~FLAGS_QUOTE;
+#endif
}
}
- integerNumber = floorl(number);
+ integerNumber = trio_floor(number);
fractionNumber = number - integerNumber;
/*
* Truncated number.
*
- * Precision is number of significant digits for FLOAT_G
- * and number of fractional digits for others.
+ * 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;
+ integerDigits = 1;
+ if (integerNumber > epsilon)
+ {
+ integerDigits += (int)TrioLogarithm(integerNumber, base);
+ }
+
+ fractionDigits = precision;
+ if (flags & FLAGS_FLOAT_G)
+ {
+ if (leadingFractionZeroes > 0)
+ {
+ fractionDigits += leadingFractionZeroes;
+ }
+ if ((integerNumber > epsilon) || (number <= epsilon))
+ {
+ fractionDigits -= integerDigits;
+ }
+ }
dblFractionBase = TrioPower(base, fractionDigits);
-
- workNumber = number + 0.5 / dblFractionBase;
- if (floorl(number) != floorl(workNumber))
+
+ if (integerNumber < 1.0)
+ {
+ workNumber = number * dblFractionBase + 0.5;
+ if (trio_floor(number * dblFractionBase) != trio_floor(workNumber))
+ {
+ adjustNumber = TRUE;
+ /* Remove a leading fraction zero if fraction is rounded up */
+ if ((int)TrioLogarithm(number * dblFractionBase, base) != (int)TrioLogarithm(workNumber, base))
+ {
+ --leadingFractionZeroes;
+ }
+ }
+ workNumber /= dblFractionBase;
+ }
+ else
{
+ workNumber = number + 0.5 / dblFractionBase;
+ adjustNumber = (trio_floor(number) != trio_floor(workNumber));
+ }
+ if (adjustNumber)
+ {
+ if ((flags & FLAGS_FLOAT_G) && !(flags & FLAGS_FLOAT_E))
+ {
+ /* The adjustment may require a change to scientific notation */
+ if ( (workNumber < 1.0E-4) ||
+ (workNumber >= trio_pow(base, (trio_long_double_t)precision)) )
+ {
+ /* Use scientific notation */
+ flags |= FLAGS_FLOAT_E;
+ goto reprocess;
+ }
+ }
+
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;
+ workDigits = 1 + TrioLogarithm(trio_floor(workNumber), base);
+ if (integerDigits == workDigits)
+ {
+ /* Adjust if the same number of digits are used */
+ number += 0.5 / dblFractionBase;
+ integerNumber = trio_floor(number);
+ fractionNumber = number - integerNumber;
+ }
+ else
+ {
+ /* 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 = trio_floor(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;
+ if (workNumber > 1.0)
+ {
+ /* Adjust if number was rounded up one digit (ie. 99 to 100) */
+ integerNumber = trio_floor(workNumber);
+ fractionNumber = 0.0;
+ integerDigits = (integerNumber > epsilon)
+ ? 1 + (int)TrioLogarithm(integerNumber, base)
+ : 1;
+ if (flags & FLAGS_FLOAT_G)
+ {
+ if (flags & FLAGS_ALTERNATIVE)
+ {
+ if ((integerNumber > epsilon) || (number <= epsilon))
+ {
+ fractionDigits -= integerDigits;
+ }
+ }
+ else
+ {
+ fractionDigits = 0;
+ }
+ }
+ }
+ else
+ {
+ integerNumber = trio_floor(workNumber);
+ fractionNumber = workNumber - integerNumber;
+ if (flags & FLAGS_FLOAT_G)
+ {
+ if (flags & FLAGS_ALTERNATIVE)
+ {
+ fractionDigits = precision;
+ if (leadingFractionZeroes > 0)
+ {
+ fractionDigits += leadingFractionZeroes;
+ }
+ if ((integerNumber > epsilon) || (number <= epsilon))
+ {
+ fractionDigits -= integerDigits;
+ }
+ }
+ }
+ }
}
}
/* Estimate accuracy */
integerAdjust = fractionAdjust = 0.5;
+# if TRIO_FEATURE_ROUNDING
if (flags & FLAGS_ROUNDING)
{
if (integerDigits > baseDigits)
@@ -2837,6 +3305,7 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
}
}
else
+# endif
{
integerThreshold = INT_MAX;
fractionThreshold = INT_MAX;
@@ -2848,35 +3317,88 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
* + fraction + exponent
*/
fractionAdjust /= dblFractionBase;
- hasOnlyZeroes = (floorl((fractionNumber + fractionAdjust) * dblFractionBase) < epsilon);
+ hasOnlyZeroes = (trio_floor((fractionNumber + fractionAdjust) *
+ dblFractionBase) < epsilon);
keepDecimalPoint = ( (flags & FLAGS_ALTERNATIVE) ||
!((precision == 0) ||
(!keepTrailingZeroes && hasOnlyZeroes)) );
+
+ expectedWidth = integerDigits + fractionDigits;
+
+ if (!keepTrailingZeroes)
+ {
+ trailingZeroes = 0;
+ workFractionNumber = fractionNumber;
+ workFractionAdjust = fractionAdjust;
+ fractionDigitsInspect = fractionDigits;
+
+ if (integerDigits > integerThreshold)
+ {
+ fractionDigitsInspect = 0;
+ }
+ else if (fractionThreshold <= fractionDigits)
+ {
+ fractionDigitsInspect = fractionThreshold + 1;
+ }
+
+ trailingZeroes = fractionDigits - fractionDigitsInspect;
+ for (i = 0; i < fractionDigitsInspect; i++)
+ {
+ workFractionNumber *= dblBase;
+ workFractionAdjust *= dblBase;
+ workNumber = trio_floor(workFractionNumber + workFractionAdjust);
+ workFractionNumber -= workNumber;
+ offset = (int)trio_fmod(workNumber, dblBase);
+ if (offset == 0)
+ {
+ trailingZeroes++;
+ }
+ else
+ {
+ trailingZeroes = 0;
+ }
+ }
+ expectedWidth -= trailingZeroes;
+ }
+
+ if (keepDecimalPoint)
+ {
+ expectedWidth += internalDecimalPointLength;
+ }
+
+#if TRIO_FEATURE_QUOTE
+ if (flags & FLAGS_QUOTE)
+ {
+ expectedWidth += TrioCalcThousandSeparatorLength(integerDigits);
+ }
+#endif
+
+ if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
+ {
+ expectedWidth += sizeof("-") - 1;
+ }
+
+ exponentDigits = 0;
if (flags & FLAGS_FLOAT_E)
{
exponentDigits = (uExponent == 0)
? 1
- : (int)ceil(TrioLogarithm((double)(uExponent + 1),
- (isHex) ? 10.0 : base));
+ : (int)trio_ceil(TrioLogarithm((double)(uExponent + 1),
+ (isHex) ? 10 : 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);
+ {
+ expectedWidth += exponentDigits;
+ expectedWidth += (requireTwoDigitExponent
+ ? sizeof("E+0") - 1
+ : sizeof("E+") - 1);
+ }
+
if (isHex)
- expectedWidth += sizeof("0X") - 1;
+ {
+ expectedWidth += sizeof("0X") - 1;
+ }
/* Output prefixing */
if (flags & FLAGS_NILPADDING)
@@ -2925,10 +3447,10 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
}
/* 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));
+ workNumber = trio_floor(((integerNumber + integerAdjust)
+ / TrioPower(base, integerDigits - i - 1)));
if (i > integerThreshold)
{
/* Beyond accuracy */
@@ -2936,10 +3458,10 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
}
else
{
- self->OutStream(self, digits[(int)fmodl(workNumber, dblBase)]);
+ self->OutStream(self, digits[(int)trio_fmod(workNumber, dblBase)]);
}
- dblIntegerBase *= dblBase;
-
+
+#if TRIO_FEATURE_QUOTE
if (((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE)
&& TrioFollowedBySeparator(integerDigits - i))
{
@@ -2950,6 +3472,7 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
self->OutStream(self, *groupingPointer);
}
}
+#endif
}
/* Insert decimal point and build the fraction part */
@@ -2981,10 +3504,19 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
{
fractionNumber *= dblBase;
fractionAdjust *= dblBase;
- workNumber = floorl(fractionNumber + fractionAdjust);
- fractionNumber -= workNumber;
- index = (int)fmodl(workNumber, dblBase);
- if (index == 0)
+ workNumber = trio_floor(fractionNumber + fractionAdjust);
+ if (workNumber > fractionNumber)
+ {
+ /* fractionNumber should never become negative */
+ fractionNumber = 0.0;
+ fractionAdjust = 0.0;
+ }
+ else
+ {
+ fractionNumber -= workNumber;
+ }
+ offset = (int)trio_fmod(workNumber, dblBase);
+ if (offset == 0)
{
trailingZeroes++;
}
@@ -2996,7 +3528,7 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
self->OutStream(self, digits[0]);
trailingZeroes--;
}
- self->OutStream(self, digits[index]);
+ self->OutStream(self, digits[offset]);
}
}
}
@@ -3024,7 +3556,7 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
self->OutStream(self, '0');
if (isHex)
- base = 10.0;
+ base = 10;
exponentBase = (int)TrioPower(base, exponentDigits - 1);
for (i = 0; i < exponentDigits; i++)
{
@@ -3041,6 +3573,7 @@ TRIO_ARGS6((self, number, flags, width, precision, base),
}
}
}
+#endif /* TRIO_FEATURE_FLOAT */
/*************************************************************************
* TrioFormatProcess
@@ -3055,318 +3588,318 @@ TRIO_ARGS3((data, format, parameters),
TRIO_CONST char *format,
trio_parameter_t *parameters)
{
-#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
- int charlen;
-#endif
int i;
+#if TRIO_FEATURE_ERRNO
TRIO_CONST char *string;
+#endif
trio_pointer_t pointer;
trio_flags_t flags;
int width;
int precision;
int base;
- int index;
+ int offset;
- index = 0;
+ offset = 0;
i = 0;
-#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
- (void)mblen(NULL, 0);
-#endif
-
- while (format[index])
+
+ for (;;)
{
-#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)
+ /* Skip the parameter entries */
+ while (parameters[i].type == FORMAT_PARAMETER)
+ i++;
+
+ /* Copy non conversion-specifier part of format string */
+ while (offset < parameters[i].beginOffset)
+ {
+ if (CHAR_IDENTIFIER == format[offset] && CHAR_IDENTIFIER == format[offset + 1])
{
- while (charlen-- > 0)
- {
- data->OutStream(data, format[index++]);
- }
- continue; /* while characters left in formatting string */
+ data->OutStream(data, CHAR_IDENTIFIER);
+ offset += 2;
+ }
+ else
+ {
+ data->OutStream(data, format[offset++]);
}
}
-#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */
- if (CHAR_IDENTIFIER == format[index])
+
+ /* Abort if we reached end of format string */
+ if (parameters[i].type == FORMAT_SENTINEL)
+ break;
+
+ /* Ouput parameter */
+ flags = parameters[i].flags;
+
+ /* Find width */
+ width = parameters[i].width;
+ if (flags & FLAGS_WIDTH_PARAMETER)
{
- if (CHAR_IDENTIFIER == format[index + 1])
+ /* Get width from parameter list */
+ width = (int)parameters[width].data.number.as_signed;
+ if (width < 0)
{
- data->OutStream(data, CHAR_IDENTIFIER);
- index += 2;
+ /*
+ * A negative width is the same as the - flag and
+ * a positive width.
+ */
+ flags |= FLAGS_LEFTADJUST;
+ flags &= ~FLAGS_NILPADDING;
+ width = -width;
}
- 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
+ /* 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
+ /* Find base */
+ if (NO_BASE != parameters[i].baseSpecifier)
+ {
+ /* Base from specifier has priority */
+ base = parameters[i].baseSpecifier;
+ }
+ else if (flags & FLAGS_BASE_PARAMETER)
+ {
+ /* Get base from parameter list */
+ base = parameters[i].base;
+ base = (int)parameters[base].data.number.as_signed;
+ }
+ else
+ {
+ /* Use base from format string */
+ base = parameters[i].base;
+ }
+
+ switch (parameters[i].type)
+ {
+ case FORMAT_CHAR:
+#if TRIO_FEATURE_QUOTE
+ if (flags & FLAGS_QUOTE)
+ data->OutStream(data, CHAR_QUOTE);
#endif
- {
- TrioWriteStringCharacter(data,
- (int)parameters[i].data.number.as_signed,
- flags);
- }
+ if (! (flags & FLAGS_LEFTADJUST))
+ {
+ while (--width > 0)
+ data->OutStream(data, CHAR_ADJUST);
+ }
+#if TRIO_FEATURE_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);
+ if (flags & FLAGS_LEFTADJUST)
+ {
+ while(--width > 0)
+ data->OutStream(data, CHAR_ADJUST);
+ }
+#if TRIO_FEATURE_QUOTE
+ if (flags & FLAGS_QUOTE)
+ data->OutStream(data, CHAR_QUOTE);
+#endif
- break; /* FORMAT_CHAR */
+ break; /* FORMAT_CHAR */
- case FORMAT_INT:
- TrioWriteNumber(data,
- parameters[i].data.number.as_unsigned,
- flags,
- width,
- precision,
- base);
+ case FORMAT_INT:
+ TrioWriteNumber(data,
+ parameters[i].data.number.as_unsigned,
+ flags,
+ width,
+ precision,
+ base);
+
+ break; /* FORMAT_INT */
- break; /* FORMAT_INT */
+#if TRIO_FEATURE_FLOAT
+ case FORMAT_DOUBLE:
+ TrioWriteDouble(data,
+ parameters[i].data.longdoubleNumber,
+ flags,
+ width,
+ precision,
+ base);
+ break; /* FORMAT_DOUBLE */
+#endif
- case FORMAT_DOUBLE:
- TrioWriteDouble(data,
- parameters[i].data.longdoubleNumber,
+ case FORMAT_STRING:
+#if TRIO_FEATURE_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ TrioWriteWideString(data,
+ parameters[i].data.wstring,
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
+ precision);
+ }
+ else
#endif
- {
- TrioWriteString(data,
- parameters[i].data.string,
- flags,
- width,
- precision);
- }
- break; /* FORMAT_STRING */
+ {
+ TrioWriteString(data,
+ parameters[i].data.string,
+ flags,
+ width,
+ precision);
+ }
+ break; /* FORMAT_STRING */
- case FORMAT_POINTER:
- {
- trio_reference_t reference;
-
- reference.data = data;
- reference.parameter = &parameters[i];
- trio_print_pointer(&reference, parameters[i].data.pointer);
- }
- break; /* FORMAT_POINTER */
+ case FORMAT_POINTER:
+ {
+ trio_reference_t reference;
- 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
+ reference.data = data;
+ reference.parameter = &parameters[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->actually.committed
+ */
+#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER
+ if (flags & FLAGS_SIZE_T)
+ *(size_t *)pointer = (size_t)data->actually.committed;
+ else
#endif
-#if defined(QUALIFIER_PTRDIFF_T)
- if (flags & FLAGS_PTRDIFF_T)
- *(ptrdiff_t *)pointer = (ptrdiff_t)data->committed;
- else
+#if TRIO_FEATURE_PTRDIFF_T
+ if (flags & FLAGS_PTRDIFF_T)
+ *(ptrdiff_t *)pointer = (ptrdiff_t)data->actually.committed;
+ else
#endif
-#if defined(QUALIFIER_INTMAX_T)
- if (flags & FLAGS_INTMAX_T)
- *(trio_intmax_t *)pointer = (trio_intmax_t)data->committed;
- else
+#if TRIO_FEATURE_INTMAX_T
+ if (flags & FLAGS_INTMAX_T)
+ *(trio_intmax_t *)pointer = (trio_intmax_t)data->actually.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 */
+ if (flags & FLAGS_QUAD)
+ {
+ *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->actually.committed;
+ }
+ else if (flags & FLAGS_LONG)
+ {
+ *(long int *)pointer = (long int)data->actually.committed;
+ }
+ else if (flags & FLAGS_SHORT)
+ {
+ *(short int *)pointer = (short int)data->actually.committed;
+ }
+ else
+ {
+ *(int *)pointer = (int)data->actually.committed;
+ }
+ }
+ break; /* FORMAT_COUNT */
- case FORMAT_PARAMETER:
- break; /* FORMAT_PARAMETER */
+ 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 TRIO_FEATURE_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 /* TRIO_FEATURE_ERRNO */
+
+#if TRIO_FEATURE_USER_DEFINED
+ case FORMAT_USER_DEFINED:
+ {
+ trio_reference_t reference;
+ trio_userdef_t *def = NULL;
-#if defined(FORMAT_USER_DEFINED)
- case FORMAT_USER_DEFINED:
- {
- trio_reference_t reference;
- trio_userdef_t *def = NULL;
+ if (parameters[i].flags & FLAGS_USER_DEFINED_PARAMETER)
+ {
+ /* 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_defined.namespace, NULL);
+ }
+ if (def)
+ {
+ reference.data = data;
+ reference.parameter = &parameters[i];
+ def->callback(&reference);
+ }
+ }
+ break;
+#endif /* TRIO_FEATURE_USER_DEFINED */
- 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 = &parameters[i];
- def->callback(&reference);
- }
- }
- break;
-#endif /* defined(FORMAT_USER_DEFINED) */
-
- default:
- break;
- } /* switch parameter type */
+ default:
+ break;
+ } /* switch parameter type */
- /* Prepare for next */
- index = parameters[i].indexAfterSpecifier;
- i++;
- }
- }
- else /* not identifier */
- {
- data->OutStream(data, format[index++]);
- }
+ /* Prepare for next */
+ offset = parameters[i].endOffset;
+ i++;
}
+
return data->processed;
}
/*************************************************************************
* TrioFormatRef
*/
+#if TRIO_EXTENSION
TRIO_PRIVATE int
TrioFormatRef
TRIO_ARGS4((reference, format, arglist, argarray),
trio_reference_t *reference,
TRIO_CONST char *format,
- va_list *arglist,
+ va_list arglist,
trio_pointer_t *argarray)
{
int status;
@@ -3383,6 +3916,7 @@ TRIO_ARGS4((reference, format, arglist, argarray),
}
return status;
}
+#endif /* TRIO_EXTENSION */
/*************************************************************************
* TrioFormat
@@ -3394,7 +3928,7 @@ TRIO_ARGS6((destination, destinationSize, OutStream, format, arglist, argarray),
size_t destinationSize,
void (*OutStream) TRIO_PROTO((trio_class_t *, int)),
TRIO_CONST char *format,
- va_list *arglist,
+ va_list arglist,
trio_pointer_t *argarray)
{
int status;
@@ -3432,6 +3966,7 @@ TRIO_ARGS6((destination, destinationSize, OutStream, format, arglist, argarray),
/*************************************************************************
* TrioOutStreamFile
*/
+#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO
TRIO_PRIVATE void
TrioOutStreamFile
TRIO_ARGS2((self, output),
@@ -3451,13 +3986,15 @@ TRIO_ARGS2((self, output),
}
else
{
- self->committed++;
+ self->actually.committed++;
}
}
+#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */
/*************************************************************************
* TrioOutStreamFileDescriptor
*/
+#if TRIO_FEATURE_FD
TRIO_PRIVATE void
TrioOutStreamFileDescriptor
TRIO_ARGS2((self, output),
@@ -3478,13 +4015,15 @@ TRIO_ARGS2((self, output),
}
else
{
- self->committed++;
+ self->actually.committed++;
}
}
+#endif /* TRIO_FEATURE_FD */
/*************************************************************************
* TrioOutStreamCustom
*/
+#if TRIO_FEATURE_CLOSURE
TRIO_PRIVATE void
TrioOutStreamCustom
TRIO_ARGS2((self, output),
@@ -3503,7 +4042,7 @@ TRIO_ARGS2((self, output),
status = (data->stream.out)(data->closure, output);
if (status >= 0)
{
- self->committed++;
+ self->actually.committed++;
}
else
{
@@ -3515,6 +4054,7 @@ TRIO_ARGS2((self, output),
}
self->processed++;
}
+#endif /* TRIO_FEATURE_CLOSURE */
/*************************************************************************
* TrioOutStreamString
@@ -3534,7 +4074,7 @@ TRIO_ARGS2((self, output),
**buffer = (char)output;
(*buffer)++;
self->processed++;
- self->committed++;
+ self->actually.committed++;
}
/*************************************************************************
@@ -3557,7 +4097,7 @@ TRIO_ARGS2((self, output),
{
**buffer = (char)output;
(*buffer)++;
- self->committed++;
+ self->actually.committed++;
}
self->processed++;
}
@@ -3565,6 +4105,7 @@ TRIO_ARGS2((self, output),
/*************************************************************************
* TrioOutStreamStringDynamic
*/
+#if TRIO_FEATURE_DYNAMICSTRING
TRIO_PRIVATE void
TrioOutStreamStringDynamic
TRIO_ARGS2((self, output),
@@ -3578,11 +4119,12 @@ TRIO_ARGS2((self, output),
{
trio_xstring_append_char((trio_string_t *)self->location,
(char)output);
- self->committed++;
+ self->actually.committed++;
}
/* The processed variable must always be increased */
self->processed++;
}
+#endif /* TRIO_FEATURE_DYNAMICSTRING */
/*************************************************************************
*
@@ -3608,6 +4150,7 @@ TRIO_ARGS2((self, output),
@param ... Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_STDIO
TRIO_PUBLIC int
trio_printf
TRIO_VARGS2((format, va_alist),
@@ -3620,10 +4163,11 @@ TRIO_VARGS2((format, va_alist),
assert(VALID(format));
TRIO_VA_START(args, format);
- status = TrioFormat(stdout, 0, TrioOutStreamFile, format, &args, NULL);
+ status = TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_STDIO */
/**
Print to standard output stream.
@@ -3632,6 +4176,7 @@ TRIO_VARGS2((format, va_alist),
@param args Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_STDIO
TRIO_PUBLIC int
trio_vprintf
TRIO_ARGS2((format, args),
@@ -3640,8 +4185,9 @@ TRIO_ARGS2((format, args),
{
assert(VALID(format));
- return TrioFormat(stdout, 0, TrioOutStreamFile, format, &args, NULL);
+ return TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL);
}
+#endif /* TRIO_FEATURE_STDIO */
/**
Print to standard output stream.
@@ -3650,16 +4196,20 @@ TRIO_ARGS2((format, args),
@param args Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_STDIO
TRIO_PUBLIC int
trio_printfv
TRIO_ARGS2((format, args),
TRIO_CONST char *format,
trio_pointer_t * args)
{
+ static va_list unused;
+
assert(VALID(format));
- return TrioFormat(stdout, 0, TrioOutStreamFile, format, NULL, args);
+ return TrioFormat(stdout, 0, TrioOutStreamFile, format, unused, args);
}
+#endif /* TRIO_FEATURE_STDIO */
/*************************************************************************
* fprintf
@@ -3673,6 +4223,7 @@ TRIO_ARGS2((format, args),
@param ... Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_FILE
TRIO_PUBLIC int
trio_fprintf
TRIO_VARGS3((file, format, va_alist),
@@ -3687,10 +4238,11 @@ TRIO_VARGS3((file, format, va_alist),
assert(VALID(format));
TRIO_VA_START(args, format);
- status = TrioFormat(file, 0, TrioOutStreamFile, format, &args, NULL);
+ status = TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_FILE */
/**
Print to file.
@@ -3700,6 +4252,7 @@ TRIO_VARGS3((file, format, va_alist),
@param args Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_FILE
TRIO_PUBLIC int
trio_vfprintf
TRIO_ARGS3((file, format, args),
@@ -3710,8 +4263,9 @@ TRIO_ARGS3((file, format, args),
assert(VALID(file));
assert(VALID(format));
- return TrioFormat(file, 0, TrioOutStreamFile, format, &args, NULL);
+ return TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL);
}
+#endif /* TRIO_FEATURE_FILE */
/**
Print to file.
@@ -3721,6 +4275,7 @@ TRIO_ARGS3((file, format, args),
@param args Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_FILE
TRIO_PUBLIC int
trio_fprintfv
TRIO_ARGS3((file, format, args),
@@ -3728,11 +4283,14 @@ TRIO_ARGS3((file, format, args),
TRIO_CONST char *format,
trio_pointer_t * args)
{
+ static va_list unused;
+
assert(VALID(file));
assert(VALID(format));
- return TrioFormat(file, 0, TrioOutStreamFile, format, NULL, args);
+ return TrioFormat(file, 0, TrioOutStreamFile, format, unused, args);
}
+#endif /* TRIO_FEATURE_FILE */
/*************************************************************************
* dprintf
@@ -3746,6 +4304,7 @@ TRIO_ARGS3((file, format, args),
@param ... Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_FD
TRIO_PUBLIC int
trio_dprintf
TRIO_VARGS3((fd, format, va_alist),
@@ -3759,10 +4318,11 @@ TRIO_VARGS3((fd, format, va_alist),
assert(VALID(format));
TRIO_VA_START(args, format);
- status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, &args, NULL);
+ status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_FD */
/**
Print to file descriptor.
@@ -3772,6 +4332,7 @@ TRIO_VARGS3((fd, format, va_alist),
@param args Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_FD
TRIO_PUBLIC int
trio_vdprintf
TRIO_ARGS3((fd, format, args),
@@ -3781,8 +4342,9 @@ TRIO_ARGS3((fd, format, args),
{
assert(VALID(format));
- return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, &args, NULL);
+ return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL);
}
+#endif /* TRIO_FEATURE_FD */
/**
Print to file descriptor.
@@ -3792,6 +4354,7 @@ TRIO_ARGS3((fd, format, args),
@param args Arguments.
@return Number of printed characters.
*/
+#if TRIO_FEATURE_FD
TRIO_PUBLIC int
trio_dprintfv
TRIO_ARGS3((fd, format, args),
@@ -3799,14 +4362,18 @@ TRIO_ARGS3((fd, format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
+
assert(VALID(format));
- return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, NULL, args);
+ return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, unused, args);
}
+#endif /* TRIO_FEATURE_FD */
/*************************************************************************
* cprintf
*/
+#if TRIO_FEATURE_CLOSURE
TRIO_PUBLIC int
trio_cprintf
TRIO_VARGS4((stream, closure, format, va_alist),
@@ -3825,11 +4392,13 @@ TRIO_VARGS4((stream, closure, format, va_alist),
TRIO_VA_START(args, format);
data.stream.out = stream;
data.closure = closure;
- status = TrioFormat(&data, 0, TrioOutStreamCustom, format, &args, NULL);
+ status = TrioFormat(&data, 0, TrioOutStreamCustom, format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_CLOSURE */
+#if TRIO_FEATURE_CLOSURE
TRIO_PUBLIC int
trio_vcprintf
TRIO_ARGS4((stream, closure, format, args),
@@ -3845,9 +4414,11 @@ TRIO_ARGS4((stream, closure, format, args),
data.stream.out = stream;
data.closure = closure;
- return TrioFormat(&data, 0, TrioOutStreamCustom, format, &args, NULL);
+ return TrioFormat(&data, 0, TrioOutStreamCustom, format, args, NULL);
}
+#endif /* TRIO_FEATURE_CLOSURE */
+#if TRIO_FEATURE_CLOSURE
TRIO_PUBLIC int
trio_cprintfv
TRIO_ARGS4((stream, closure, format, args),
@@ -3856,6 +4427,7 @@ TRIO_ARGS4((stream, closure, format, args),
TRIO_CONST char *format,
void **args)
{
+ static va_list unused;
trio_custom_t data;
assert(VALID(stream));
@@ -3863,8 +4435,9 @@ TRIO_ARGS4((stream, closure, format, args),
data.stream.out = stream;
data.closure = closure;
- return TrioFormat(&data, 0, TrioOutStreamCustom, format, NULL, args);
+ return TrioFormat(&data, 0, TrioOutStreamCustom, format, unused, args);
}
+#endif /* TRIO_FEATURE_CLOSURE */
/*************************************************************************
* sprintf
@@ -3892,7 +4465,7 @@ TRIO_VARGS3((buffer, format, va_alist),
assert(VALID(format));
TRIO_VA_START(args, format);
- status = TrioFormat(&buffer, 0, TrioOutStreamString, format, &args, NULL);
+ status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL);
*buffer = NIL; /* Terminate with NIL character */
TRIO_VA_END(args);
return status;
@@ -3918,7 +4491,7 @@ TRIO_ARGS3((buffer, format, args),
assert(VALID(buffer));
assert(VALID(format));
- status = TrioFormat(&buffer, 0, TrioOutStreamString, format, &args, NULL);
+ status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL);
*buffer = NIL;
return status;
}
@@ -3938,12 +4511,13 @@ TRIO_ARGS3((buffer, format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
int status;
-
+
assert(VALID(buffer));
assert(VALID(format));
- status = TrioFormat(&buffer, 0, TrioOutStreamString, format, NULL, args);
+ status = TrioFormat(&buffer, 0, TrioOutStreamString, format, unused, args);
*buffer = NIL;
return status;
}
@@ -3972,12 +4546,12 @@ TRIO_VARGS4((buffer, max, format, va_alist),
int status;
va_list args;
- assert(VALID(buffer));
+ assert(VALID(buffer) || (max == 0));
assert(VALID(format));
TRIO_VA_START(args, format);
status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
- TrioOutStreamStringMax, format, &args, NULL);
+ TrioOutStreamStringMax, format, args, NULL);
if (max > 0)
*buffer = NIL;
TRIO_VA_END(args);
@@ -4003,11 +4577,11 @@ TRIO_ARGS4((buffer, max, format, args),
{
int status;
- assert(VALID(buffer));
+ assert(VALID(buffer) || (max == 0));
assert(VALID(format));
status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
- TrioOutStreamStringMax, format, &args, NULL);
+ TrioOutStreamStringMax, format, args, NULL);
if (max > 0)
*buffer = NIL;
return status;
@@ -4030,13 +4604,14 @@ TRIO_ARGS4((buffer, max, format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
int status;
- assert(VALID(buffer));
+ assert(VALID(buffer) || (max == 0));
assert(VALID(format));
status = TrioFormat(&buffer, max > 0 ? max - 1 : 0,
- TrioOutStreamStringMax, format, NULL, args);
+ TrioOutStreamStringMax, format, unused, args);
if (max > 0)
*buffer = NIL;
return status;
@@ -4047,6 +4622,7 @@ TRIO_ARGS4((buffer, max, format, args),
* Appends the new string to the buffer string overwriting the '\0'
* character at the end of buffer.
*/
+#if TRIO_EXTENSION
TRIO_PUBLIC int
trio_snprintfcat
TRIO_VARGS4((buffer, max, format, va_alist),
@@ -4068,12 +4644,14 @@ TRIO_VARGS4((buffer, max, format, va_alist),
buffer = &buffer[buf_len];
status = TrioFormat(&buffer, max - 1 - buf_len,
- TrioOutStreamStringMax, format, &args, NULL);
+ TrioOutStreamStringMax, format, args, NULL);
TRIO_VA_END(args);
*buffer = NIL;
return status;
}
+#endif
+#if TRIO_EXTENSION
TRIO_PUBLIC int
trio_vsnprintfcat
TRIO_ARGS4((buffer, max, format, args),
@@ -4091,16 +4669,17 @@ TRIO_ARGS4((buffer, max, format, args),
buf_len = trio_length(buffer);
buffer = &buffer[buf_len];
status = TrioFormat(&buffer, max - 1 - buf_len,
- TrioOutStreamStringMax, format, &args, NULL);
+ TrioOutStreamStringMax, format, args, NULL);
*buffer = NIL;
return status;
}
+#endif
/*************************************************************************
* trio_aprintf
*/
-/* Deprecated */
+#if TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING
TRIO_PUBLIC char *
trio_aprintf
TRIO_VARGS2((format, va_alist),
@@ -4118,7 +4697,7 @@ TRIO_VARGS2((format, va_alist),
{
TRIO_VA_START(args, format);
(void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
- format, &args, NULL);
+ format, args, NULL);
TRIO_VA_END(args);
trio_string_terminate(info);
@@ -4127,8 +4706,9 @@ TRIO_VARGS2((format, va_alist),
}
return result;
}
+#endif /* TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING */
-/* Deprecated */
+#if TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING
TRIO_PUBLIC char *
trio_vaprintf
TRIO_ARGS2((format, args),
@@ -4144,14 +4724,26 @@ TRIO_ARGS2((format, args),
if (info)
{
(void)TrioFormat(info, 0, TrioOutStreamStringDynamic,
- format, &args, NULL);
+ format, args, NULL);
trio_string_terminate(info);
result = trio_string_extract(info);
trio_string_destroy(info);
}
return result;
}
+#endif /* TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING */
+
+/**
+ Allocate and print to string.
+ The memory allocated and returned by @p result must be freed by the
+ calling application.
+ @param result Output string.
+ @param format Formatting string.
+ @param ... Arguments.
+ @return Number of printed characters.
+ */
+#if TRIO_FEATURE_DYNAMICSTRING
TRIO_PUBLIC int
trio_asprintf
TRIO_VARGS3((result, format, va_alist),
@@ -4176,7 +4768,7 @@ TRIO_VARGS3((result, format, va_alist),
{
TRIO_VA_START(args, format);
status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
- format, &args, NULL);
+ format, args, NULL);
TRIO_VA_END(args);
if (status >= 0)
{
@@ -4187,7 +4779,19 @@ TRIO_VARGS3((result, format, va_alist),
}
return status;
}
+#endif /* TRIO_FEATURE_DYNAMICSTRING */
+/**
+ Allocate and print to string.
+ The memory allocated and returned by @p result must be freed by the
+ calling application.
+
+ @param result Output string.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of printed characters.
+ */
+#if TRIO_FEATURE_DYNAMICSTRING
TRIO_PUBLIC int
trio_vasprintf
TRIO_ARGS3((result, format, args),
@@ -4210,7 +4814,7 @@ TRIO_ARGS3((result, format, args),
else
{
status = TrioFormat(info, 0, TrioOutStreamStringDynamic,
- format, &args, NULL);
+ format, args, NULL);
if (status >= 0)
{
trio_string_terminate(info);
@@ -4220,6 +4824,53 @@ TRIO_ARGS3((result, format, args),
}
return status;
}
+#endif /* TRIO_FEATURE_DYNAMICSTRING */
+
+/**
+ Allocate and print to string.
+ The memory allocated and returned by @p result must be freed by the
+ calling application.
+
+ @param result Output string.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of printed characters.
+ */
+#if TRIO_FEATURE_DYNAMICSTRING
+TRIO_PUBLIC int
+trio_asprintfv
+TRIO_ARGS3((result, format, args),
+ char **result,
+ TRIO_CONST char *format,
+ trio_pointer_t * args)
+{
+ static va_list unused;
+ 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, unused, args);
+ if (status >= 0)
+ {
+ trio_string_terminate(info);
+ *result = trio_string_extract(info);
+ }
+ trio_string_destroy(info);
+ }
+ return status;
+}
+#endif /* TRIO_FEATURE_DYNAMICSTRING */
/** @} End of Printf documentation module */
@@ -4237,7 +4888,7 @@ TRIO_ARGS3((result, format, args),
@{
*/
-#if TRIO_EXTENSION
+#if TRIO_FEATURE_USER_DEFINED
/*************************************************************************
* trio_register
@@ -4340,7 +4991,7 @@ TRIO_ARGS1((handle),
(void)internalEnterCriticalRegion(NULL);
if (prev == NULL)
- internalUserDef = NULL;
+ internalUserDef = internalUserDef->next;
else
prev->next = def->next;
@@ -4360,7 +5011,7 @@ trio_get_format
TRIO_ARGS1((ref),
trio_pointer_t ref)
{
-#if defined(FORMAT_USER_DEFINED)
+#if TRIO_FEATURE_USER_DEFINED
assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
#endif
@@ -4375,7 +5026,7 @@ trio_get_argument
TRIO_ARGS1((ref),
trio_pointer_t ref)
{
-#if defined(FORMAT_USER_DEFINED)
+#if TRIO_FEATURE_USER_DEFINED
assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED);
#endif
@@ -4495,6 +5146,7 @@ TRIO_ARGS2((ref, is_longlong),
/*************************************************************************
* trio_get_longdouble / trio_set_longdouble [public]
*/
+# if TRIO_FEATURE_FLOAT
int
trio_get_longdouble
TRIO_ARGS1((ref),
@@ -4516,6 +5168,7 @@ TRIO_ARGS2((ref, is_longdouble),
else
((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONGDOUBLE;
}
+# endif /* TRIO_FEATURE_FLOAT */
/*************************************************************************
* trio_get_short / trio_set_short [public]
@@ -4695,6 +5348,7 @@ TRIO_ARGS2((ref, is_padding),
/*************************************************************************
* trio_get_quote / trio_set_quote [public]
*/
+# if TRIO_FEATURE_QUOTE
int
trio_get_quote
TRIO_ARGS1((ref),
@@ -4716,6 +5370,7 @@ TRIO_ARGS2((ref, is_quote),
else
((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUOTE;
}
+#endif /* TRIO_FEATURE_QUOTE */
/*************************************************************************
* trio_get_upper / trio_set_upper [public]
@@ -4745,7 +5400,7 @@ TRIO_ARGS2((ref, is_upper),
/*************************************************************************
* trio_get_largest / trio_set_largest [public]
*/
-#if TRIO_C99
+#if TRIO_FEATURE_INTMAX_T
int
trio_get_largest
TRIO_ARGS1((ref),
@@ -4767,11 +5422,12 @@ TRIO_ARGS2((ref, is_largest),
else
((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_INTMAX_T;
}
-#endif
+#endif /* TRIO_FEATURE_INTMAX_T */
/*************************************************************************
* trio_get_ptrdiff / trio_set_ptrdiff [public]
*/
+#if TRIO_FEATURE_PTRDIFF_T
int
trio_get_ptrdiff
TRIO_ARGS1((ref),
@@ -4793,11 +5449,12 @@ TRIO_ARGS2((ref, is_ptrdiff),
else
((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_PTRDIFF_T;
}
+#endif /* TRIO_FEATURE_PTRDIFF_T */
/*************************************************************************
* trio_get_size / trio_set_size [public]
*/
-#if TRIO_C99
+#if TRIO_FEATURE_SIZE_T
int
trio_get_size
TRIO_ARGS1((ref),
@@ -4819,7 +5476,7 @@ TRIO_ARGS2((ref, is_size),
else
((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SIZE_T;
}
-#endif
+#endif /* TRIO_FEATURE_SIZE_T */
/*************************************************************************
* trio_print_int [public]
@@ -4862,6 +5519,7 @@ TRIO_ARGS2((ref, number),
/*************************************************************************
* trio_print_double [public]
*/
+#if TRIO_FEATURE_FLOAT
void
trio_print_double
TRIO_ARGS2((ref, number),
@@ -4877,6 +5535,7 @@ TRIO_ARGS2((ref, number),
self->parameter->precision,
self->parameter->base);
}
+#endif /* TRIO_FEATURE_FLOAT */
/*************************************************************************
* trio_print_string [public]
@@ -4885,7 +5544,7 @@ void
trio_print_string
TRIO_ARGS2((ref, string),
trio_pointer_t ref,
- char *string)
+ TRIO_CONST char *string)
{
trio_reference_t *self = (trio_reference_t *)ref;
@@ -4912,7 +5571,7 @@ TRIO_VARGS3((ref, format, va_alist),
assert(VALID(format));
TRIO_VA_START(arglist, format);
- status = TrioFormatRef((trio_reference_t *)ref, format, &arglist, NULL);
+ status = TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL);
TRIO_VA_END(arglist);
return status;
}
@@ -4929,7 +5588,7 @@ TRIO_ARGS3((ref, format, arglist),
{
assert(VALID(format));
- return TrioFormatRef((trio_reference_t *)ref, format, &arglist, NULL);
+ return TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL);
}
/*************************************************************************
@@ -4942,12 +5601,14 @@ TRIO_ARGS3((ref, format, argarray),
TRIO_CONST char *format,
trio_pointer_t *argarray)
{
+ static va_list unused;
+
assert(VALID(format));
- return TrioFormatRef((trio_reference_t *)ref, format, NULL, argarray);
+ return TrioFormatRef((trio_reference_t *)ref, format, unused, argarray);
}
-#endif /* TRIO_EXTENSION */
+#endif
/*************************************************************************
* trio_print_pointer [public]
@@ -5007,6 +5668,7 @@ TRIO_ARGS2((ref, pointer),
* string to enable multibyte characters. At most MB_LEN_MAX characters
* will be used.
*/
+#if TRIO_FEATURE_LOCALE
TRIO_PUBLIC void
trio_locale_set_decimal_point
TRIO_ARGS1((decimalPoint),
@@ -5031,28 +5693,31 @@ TRIO_ARGS1((decimalPoint),
decimalPoint);
}
}
+#endif
/*************************************************************************
* trio_locale_set_thousand_separator
*
* See trio_locale_set_decimal_point
*/
+#if TRIO_FEATURE_LOCALE || TRIO_EXTENSION
TRIO_PUBLIC void
trio_locale_set_thousand_separator
TRIO_ARGS1((thousandSeparator),
char *thousandSeparator)
{
-#if defined(USE_LOCALE)
+# if defined(USE_LOCALE)
if (NULL == internalLocaleValues)
{
TrioSetLocale();
}
-#endif
+# endif
trio_copy_max(internalThousandSeparator,
sizeof(internalThousandSeparator),
thousandSeparator);
internalThousandSeparatorLength = trio_length(internalThousandSeparator);
}
+#endif
/*************************************************************************
* trio_locale_set_grouping
@@ -5066,21 +5731,23 @@ TRIO_ARGS1((thousandSeparator),
*
* Same order as the grouping attribute in LC_NUMERIC.
*/
+#if TRIO_FEATURE_LOCALE || TRIO_EXTENSION
TRIO_PUBLIC void
trio_locale_set_grouping
TRIO_ARGS1((grouping),
char *grouping)
{
-#if defined(USE_LOCALE)
+# if defined(USE_LOCALE)
if (NULL == internalLocaleValues)
{
TrioSetLocale();
}
-#endif
+# endif
trio_copy_max(internalGrouping,
sizeof(internalGrouping),
grouping);
}
+#endif
/*************************************************************************
@@ -5089,6 +5756,8 @@ TRIO_ARGS1((grouping),
*
************************************************************************/
+#if TRIO_FEATURE_SCANF
+
/*************************************************************************
* TrioSkipWhitespaces
*/
@@ -5146,13 +5815,13 @@ TrioGetCollation(TRIO_NOARGS)
*/
TRIO_PRIVATE int
TrioGetCharacterClass
-TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
+TRIO_ARGS4((format, offsetPointer, flagsPointer, characterclass),
TRIO_CONST char *format,
- int *indexPointer,
+ int *offsetPointer,
trio_flags_t *flagsPointer,
int *characterclass)
{
- int index = *indexPointer;
+ int offset = *offsetPointer;
int i;
char ch;
char range_begin;
@@ -5160,34 +5829,34 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
*flagsPointer &= ~FLAGS_EXCLUDE;
- if (format[index] == QUALIFIER_CIRCUMFLEX)
+ if (format[offset] == QUALIFIER_CIRCUMFLEX)
{
*flagsPointer |= FLAGS_EXCLUDE;
- index++;
+ offset++;
}
/*
* 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)
+ if (format[offset] == SPECIFIER_UNGROUP)
{
characterclass[(int)SPECIFIER_UNGROUP]++;
- index++;
+ offset++;
}
/*
* 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)
+ if (format[offset] == QUALIFIER_MINUS)
{
characterclass[(int)QUALIFIER_MINUS]++;
- index++;
+ offset++;
}
/* Collect characters */
- for (ch = format[index];
+ for (ch = format[offset];
(ch != SPECIFIER_UNGROUP) && (ch != NIL);
- ch = format[++index])
+ ch = format[++offset])
{
switch (ch)
{
@@ -5206,8 +5875,8 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
* - duplicates (although we can easily convert these
* into errors)
*/
- range_begin = format[index - 1];
- range_end = format[++index];
+ range_begin = format[offset - 1];
+ range_end = format[++offset];
if (range_end == SPECIFIER_UNGROUP)
{
/* Trailing minus is included */
@@ -5216,9 +5885,9 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
break; /* for */
}
if (range_end == NIL)
- return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
if (range_begin > range_end)
- return TRIO_ERROR_RETURN(TRIO_ERANGE, index);
+ return TRIO_ERROR_RETURN(TRIO_ERANGE, offset);
for (i = (int)range_begin; i <= (int)range_end; i++)
characterclass[i]++;
@@ -5230,7 +5899,7 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
case SPECIFIER_GROUP:
- switch (format[index + 1])
+ switch (format[offset + 1])
{
case QUALIFIER_DOT: /* Collating symbol */
/*
@@ -5238,7 +5907,7 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
* characters have been implemented. Until now, we ignore
* this feature.
*/
- for (i = index + 2; ; i++)
+ for (i = offset + 2; ; i++)
{
if (format[i] == NIL)
/* Error in syntax */
@@ -5249,7 +5918,7 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
if (format[++i] != SPECIFIER_UNGROUP)
return -1;
- index = i;
+ offset = i;
break;
case QUALIFIER_EQUAL: /* Equivalence class expressions */
@@ -5263,7 +5932,7 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
TrioGetCollation();
internalCollationUnconverted = FALSE;
}
- for (i = index + 2; ; i++)
+ for (i = offset + 2; ; i++)
{
if (format[i] == NIL)
/* Error in syntax */
@@ -5281,99 +5950,99 @@ TRIO_ARGS4((format, indexPointer, flagsPointer, characterclass),
if (format[++i] != SPECIFIER_UNGROUP)
return -1;
- index = i;
+ offset = i;
}
break;
case QUALIFIER_COLON: /* Character class expressions */
if (trio_equal_max(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isalnum(i))
characterclass[i]++;
- index += sizeof(CLASS_ALNUM) - 1;
+ offset += sizeof(CLASS_ALNUM) - 1;
}
else if (trio_equal_max(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isalpha(i))
characterclass[i]++;
- index += sizeof(CLASS_ALPHA) - 1;
+ offset += sizeof(CLASS_ALPHA) - 1;
}
else if (trio_equal_max(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (iscntrl(i))
characterclass[i]++;
- index += sizeof(CLASS_CNTRL) - 1;
+ offset += sizeof(CLASS_CNTRL) - 1;
}
else if (trio_equal_max(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isdigit(i))
characterclass[i]++;
- index += sizeof(CLASS_DIGIT) - 1;
+ offset += sizeof(CLASS_DIGIT) - 1;
}
else if (trio_equal_max(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isgraph(i))
characterclass[i]++;
- index += sizeof(CLASS_GRAPH) - 1;
+ offset += sizeof(CLASS_GRAPH) - 1;
}
else if (trio_equal_max(CLASS_LOWER, sizeof(CLASS_LOWER) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (islower(i))
characterclass[i]++;
- index += sizeof(CLASS_LOWER) - 1;
+ offset += sizeof(CLASS_LOWER) - 1;
}
else if (trio_equal_max(CLASS_PRINT, sizeof(CLASS_PRINT) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isprint(i))
characterclass[i]++;
- index += sizeof(CLASS_PRINT) - 1;
+ offset += sizeof(CLASS_PRINT) - 1;
}
else if (trio_equal_max(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (ispunct(i))
characterclass[i]++;
- index += sizeof(CLASS_PUNCT) - 1;
+ offset += sizeof(CLASS_PUNCT) - 1;
}
else if (trio_equal_max(CLASS_SPACE, sizeof(CLASS_SPACE) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isspace(i))
characterclass[i]++;
- index += sizeof(CLASS_SPACE) - 1;
+ offset += sizeof(CLASS_SPACE) - 1;
}
else if (trio_equal_max(CLASS_UPPER, sizeof(CLASS_UPPER) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isupper(i))
characterclass[i]++;
- index += sizeof(CLASS_UPPER) - 1;
+ offset += sizeof(CLASS_UPPER) - 1;
}
else if (trio_equal_max(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1,
- &format[index]))
+ &format[offset]))
{
for (i = 0; i < MAX_CHARACTER_CLASS; i++)
if (isxdigit(i))
characterclass[i]++;
- index += sizeof(CLASS_XDIGIT) - 1;
+ offset += sizeof(CLASS_XDIGIT) - 1;
}
else
{
@@ -5437,18 +6106,15 @@ TRIO_ARGS5((self, target, flags, width, base),
TrioSkipWhitespaces(self);
- if (!(flags & FLAGS_UNSIGNED))
+ /* Leading sign */
+ if (self->current == '+')
{
- /* Leading sign */
- if (self->current == '+')
- {
- self->InStream(self, NULL);
- }
- else if (self->current == '-')
- {
- self->InStream(self, NULL);
- isNegative = TRUE;
- }
+ self->InStream(self, NULL);
+ }
+ else if (self->current == '-')
+ {
+ self->InStream(self, NULL);
+ isNegative = TRUE;
}
count = self->processed;
@@ -5496,6 +6162,7 @@ TRIO_ARGS5((self, target, flags, width, base),
if ((digit == -1) || (digit >= base))
break;
}
+#if TRIO_FEATURE_QUOTE
else if (flags & FLAGS_QUOTE)
{
/* Compare with thousands separator */
@@ -5511,6 +6178,7 @@ TRIO_ARGS5((self, target, flags, width, base),
else
continue; /* Match */
}
+#endif
else
break;
@@ -5526,7 +6194,7 @@ TRIO_ARGS5((self, target, flags, width, base),
return FALSE;
if (target)
- *target = (isNegative) ? -((trio_intmax_t)number) : number;
+ *target = (isNegative) ? (trio_uintmax_t)(-((trio_intmax_t)number)) : number;
return TRUE;
}
@@ -5634,7 +6302,7 @@ TRIO_ARGS4((self, target, flags, width),
/*************************************************************************
* TrioReadWideChar
*/
-#if TRIO_WIDECHAR
+#if TRIO_FEATURE_WIDECHAR
TRIO_PRIVATE int
TrioReadWideChar
TRIO_ARGS4((self, target, flags, width),
@@ -5690,12 +6358,12 @@ TRIO_ARGS4((self, target, flags, width),
}
return amount;
}
-#endif /* TRIO_WIDECHAR */
+#endif /* TRIO_FEATURE_WIDECHAR */
/*************************************************************************
* TrioReadWideString
*/
-#if TRIO_WIDECHAR
+#if TRIO_FEATURE_WIDECHAR
TRIO_PRIVATE BOOLEAN_T
TrioReadWideString
TRIO_ARGS4((self, target, flags, width),
@@ -5713,6 +6381,7 @@ TRIO_ARGS4((self, target, flags, width),
TrioSkipWhitespaces(self);
#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
+ /* Required by TrioReadWideChar */
(void)mblen(NULL, 0);
#endif
@@ -5735,11 +6404,13 @@ TRIO_ARGS4((self, target, flags, width),
target[i] = WCONST('\0');
return TRUE;
}
-#endif /* TRIO_WIDECHAR */
+#endif /* TRIO_FEATURE_WIDECHAR */
/*************************************************************************
* TrioReadGroup
*
+ * Reads non-empty character groups.
+ *
* FIXME: characterclass does not work with multibyte characters
*/
TRIO_PRIVATE BOOLEAN_T
@@ -5768,7 +6439,11 @@ TRIO_ARGS5((self, target, characterclass, flags, width),
target[i] = (char)ch;
self->InStream(self, &ch);
}
-
+
+ if (i == 0)
+ return FALSE;
+
+ /* Terminate the string if input saved */
if (target)
target[i] = NIL;
return TRUE;
@@ -5781,6 +6456,7 @@ TRIO_ARGS5((self, target, characterclass, flags, width),
* add long double
* handle base
*/
+#if TRIO_FEATURE_FLOAT
TRIO_PRIVATE BOOLEAN_T
TrioReadDouble
TRIO_ARGS4((self, target, flags, width),
@@ -5791,10 +6467,13 @@ TRIO_ARGS4((self, target, flags, width),
{
int ch;
char doubleString[512];
- int index = 0;
+ int offset = 0;
int start;
+# if TRIO_FEATURE_QUOTE
int j;
+# endif
BOOLEAN_T isHex = FALSE;
+ trio_long_double_t infinity;
doubleString[0] = 0;
@@ -5811,55 +6490,48 @@ TRIO_ARGS4((self, target, flags, width),
ch = self->current;
if ((ch == '+') || (ch == '-'))
{
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
width--;
}
- start = index;
+ start = offset;
switch (ch)
{
case 'n':
case 'N':
/* Not-a-number */
- if (index != 0)
+ if (offset != 0)
break;
/* FALLTHROUGH */
case 'i':
case 'I':
/* Infinity */
- while (isalpha(ch) && (index - start < width))
+ while (isalpha(ch) && (offset - start < width))
{
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
}
- doubleString[index] = NIL;
+ doubleString[offset] = NIL;
/* Case insensitive string comparison */
if (trio_equal(&doubleString[start], INFINITE_UPPER) ||
trio_equal(&doubleString[start], LONG_INFINITE_UPPER))
{
+ infinity = ((start == 1) && (doubleString[0] == '-'))
+ ? trio_ninf()
+ : trio_pinf();
if (flags & FLAGS_LONGDOUBLE)
{
- if ((start == 1) && (doubleString[0] == '-'))
- {
- *((trio_long_double_t *)target) = trio_ninf();
- }
- else
- {
- *((trio_long_double_t *)target) = trio_pinf();
- }
+ *((trio_long_double_t *)target) = infinity;
+ }
+ else if (flags & FLAGS_LONG)
+ {
+ *((double *)target) = infinity;
}
else
{
- if ((start == 1) && (doubleString[0] == '-'))
- {
- *((double *)target) = trio_ninf();
- }
- else
- {
- *((double *)target) = trio_pinf();
- }
+ *((float *)target) = infinity;
}
return TRUE;
}
@@ -5870,21 +6542,25 @@ TRIO_ARGS4((self, target, flags, width),
{
*((trio_long_double_t *)target) = trio_nan();
}
- else
+ else if (flags & FLAGS_LONG)
{
*((double *)target) = trio_nan();
}
+ else
+ {
+ *((float *)target) = trio_nan();
+ }
return TRUE;
}
return FALSE;
case '0':
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
if (trio_to_upper(ch) == 'X')
{
isHex = TRUE;
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
}
break;
@@ -5893,14 +6569,15 @@ TRIO_ARGS4((self, target, flags, width),
break;
}
- while ((ch != EOF) && (index - start < width))
+ while ((ch != EOF) && (offset - start < width))
{
/* Integer part */
if (isHex ? isxdigit(ch) : isdigit(ch))
{
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
}
+# if TRIO_FEATURE_QUOTE
else if (flags & FLAGS_QUOTE)
{
/* Compare with thousands separator */
@@ -5916,53 +6593,59 @@ TRIO_ARGS4((self, target, flags, width),
else
continue; /* Match */
}
+# endif
else
break; /* while */
}
if (ch == '.')
{
/* Decimal part */
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
while ((isHex ? isxdigit(ch) : isdigit(ch)) &&
- (index - start < width))
+ (offset - start < width))
{
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
self->InStream(self, &ch);
}
- if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E'))
+ }
+ if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E'))
+ {
+ /* Exponent */
+ doubleString[offset++] = (char)ch;
+ self->InStream(self, &ch);
+ if ((ch == '+') || (ch == '-'))
{
- /* Exponent */
- doubleString[index++] = (char)ch;
+ doubleString[offset++] = (char)ch;
+ self->InStream(self, &ch);
+ }
+ while (isdigit(ch) && (offset - start < width))
+ {
+ doubleString[offset++] = (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))
+ if ((offset == start) || (*doubleString == NIL))
return FALSE;
- doubleString[index] = 0;
+ doubleString[offset] = 0;
if (flags & FLAGS_LONGDOUBLE)
{
*((trio_long_double_t *)target) = trio_to_long_double(doubleString, NULL);
}
- else
+ else if (flags & FLAGS_LONG)
{
*((double *)target) = trio_to_double(doubleString, NULL);
}
+ else
+ {
+ *((float *)target) = trio_to_float(doubleString, NULL);
+ }
return TRUE;
}
+#endif /* TRIO_FEATURE_FLOAT */
/*************************************************************************
* TrioReadPointer
@@ -5985,12 +6668,18 @@ TRIO_ARGS3((self, target, flags),
POINTER_WIDTH,
BASE_HEX))
{
- /*
- * The strange assignment of number is a workaround for a compiler
- * warning
- */
if (target)
- *target = (char *)0 + number;
+ {
+#if defined(TRIO_COMPILER_GCC) || defined(TRIO_COMPILER_MIPSPRO)
+ /*
+ * The strange assignment of number is a workaround for a compiler
+ * warning
+ */
+ *target = &((char *)0)[number];
+#else
+ *target = (trio_pointer_t)number;
+#endif
+ }
return TRUE;
}
else if (TrioReadString(self,
@@ -5999,7 +6688,7 @@ TRIO_ARGS3((self, target, flags),
: buffer,
0,
sizeof(internalNullString) - 1))
- {
+ {
if (trio_equal_case(buffer, internalNullString))
{
if (target)
@@ -6020,330 +6709,364 @@ TRIO_ARGS3((data, format, parameters),
TRIO_CONST char *format,
trio_parameter_t *parameters)
{
-#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
- int charlen;
- int cnt;
-#endif
+ int status;
int assignment;
int ch;
- int index; /* Index of format string */
- int i; /* Index of current parameter */
+ int offset; /* Offset of format string */
+ int i; /* Offset of current parameter */
trio_flags_t flags;
int width;
int base;
trio_pointer_t pointer;
+ /* Return on empty format string */
+ if (format[0] == NIL)
+ return 0;
+
+ status = 0;
assignment = 0;
i = 0;
- index = 0;
+ offset = 0;
data->InStream(data, &ch);
-#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
- (void)mblen(NULL, 0);
-#endif
-
- while (format[index])
+ for (;;)
{
-#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE)
- if (! isascii(format[index]))
+ /* Skip the parameter entries */
+ while (parameters[i].type == FORMAT_PARAMETER)
{
- 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;
+ assert(i <= MAX_PARAMETERS);
+ i++;
}
-
- if (CHAR_IDENTIFIER == format[index])
+
+ /* Compare non conversion-specifier part of format string */
+ while (offset < parameters[i].beginOffset)
{
- if (CHAR_IDENTIFIER == format[index + 1])
+ if ((CHAR_IDENTIFIER == format[offset]) &&
+ (CHAR_IDENTIFIER == format[offset + 1]))
{
/* Two % in format matches one % in input stream */
if (CHAR_IDENTIFIER == ch)
{
data->InStream(data, &ch);
- index += 2;
+ offset += 2;
continue; /* while format chars left */
}
else
- return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
+ {
+ status = TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ goto end;
+ }
}
-
- /* 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)
+ else /* Not an % identifier */
{
- /* Get width from parameter list */
- width = (int)parameters[width].data.number.as_signed;
+ if (isspace((int)format[offset]))
+ {
+ /* Whitespaces may match any amount of whitespaces */
+ ch = TrioSkipWhitespaces(data);
+ }
+ else if (ch == format[offset])
+ {
+ data->InStream(data, &ch);
+ }
+ else
+ {
+ status = assignment;
+ goto end;
+ }
+
+ offset++;
}
- /* Find base */
+ }
+
+ if (parameters[i].type == FORMAT_SENTINEL)
+ break;
+
+ if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT))
+ {
+ status = (assignment > 0) ? assignment : EOF;
+ goto end;
+ }
+
+ 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 */
+ if (NO_BASE != parameters[i].baseSpecifier)
+ {
+ /* Base from specifier has priority */
+ base = parameters[i].baseSpecifier;
+ }
+ else if (flags & FLAGS_BASE_PARAMETER)
+ {
+ /* Get base from parameter list */
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;
+ base = (int)parameters[base].data.number.as_signed;
+ }
+ else
+ {
+ /* Use base from format string */
+ base = parameters[i].base;
+ }
+
+ switch (parameters[i].type)
+ {
+ case FORMAT_INT:
+ {
+ trio_uintmax_t number;
- if (0 == base)
- base = BASE_DECIMAL;
+ if (0 == base)
+ base = BASE_DECIMAL;
- if (!TrioReadNumber(data,
- &number,
- flags,
- width,
- base))
- return assignment;
+ if (!TrioReadNumber(data,
+ &number,
+ flags,
+ width,
+ base))
+ {
+ status = assignment;
+ goto end;
+ }
- if (!(flags & FLAGS_IGNORE))
- {
- 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
+ pointer = parameters[i].data.pointer;
+#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_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
+#if TRIO_FEATURE_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
+#if TRIO_FEATURE_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;
- }
+ 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,
+ }
+ break; /* FORMAT_INT */
+
+ case FORMAT_STRING:
+#if TRIO_FEATURE_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ if (!TrioReadWideString(data,
(flags & FLAGS_IGNORE)
? NULL
- : parameters[i].data.string,
+ : parameters[i].data.wstring,
flags,
width))
- return assignment;
+ {
+ status = assignment;
+ goto end;
}
- if (!(flags & FLAGS_IGNORE))
- assignment++;
- break; /* FORMAT_STRING */
+ }
+ else
+#endif
+ {
+ if (!TrioReadString(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.string,
+ flags,
+ width))
+ {
+ status = assignment;
+ goto end;
+ }
+ }
+ if (!(flags & FLAGS_IGNORE))
+ assignment++;
+ break; /* FORMAT_STRING */
- case FORMAT_DOUBLE:
+#if TRIO_FEATURE_FLOAT
+ case FORMAT_DOUBLE:
+ {
+ if (flags & FLAGS_IGNORE)
{
- 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 */
+ pointer = NULL;
}
- case FORMAT_GROUP:
+ else
{
- int characterclass[MAX_CHARACTER_CLASS + 1];
- int rc;
+ pointer = (flags & FLAGS_LONGDOUBLE)
+ ? (trio_pointer_t)parameters[i].data.longdoublePointer
+ : (trio_pointer_t)parameters[i].data.doublePointer;
+ }
+ if (!TrioReadDouble(data, pointer, flags, width))
+ {
+ status = assignment;
+ goto end;
+ }
+ if (!(flags & FLAGS_IGNORE))
+ {
+ assignment++;
+ }
+ break; /* FORMAT_DOUBLE */
+ }
+#endif
- /* Skip over modifiers */
- while (format[index] != SPECIFIER_GROUP)
- {
- index++;
- }
- /* Skip over group specifier */
- index++;
-
- memset(characterclass, 0, sizeof(characterclass));
- rc = TrioGetCharacterClass(format,
- &index,
+ case FORMAT_GROUP:
+ {
+ int characterclass[MAX_CHARACTER_CLASS + 1];
+
+ /* Skip over modifiers */
+ while (format[offset] != SPECIFIER_GROUP)
+ {
+ offset++;
+ }
+ /* Skip over group specifier */
+ offset++;
+
+ memset(characterclass, 0, sizeof(characterclass));
+ status = TrioGetCharacterClass(format,
+ &offset,
&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++;
+ if (status < 0)
+ goto end;
+
+ if (!TrioReadGroup(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.string,
+ characterclass,
+ flags,
+ parameters[i].width))
+ {
+ status = assignment;
+ goto end;
}
- break; /* FORMAT_GROUP */
+ 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
+ case FORMAT_COUNT:
+ pointer = parameters[i].data.pointer;
+ if (NULL != pointer)
+ {
+ int count = data->processed;
+ if (ch != EOF)
+ count--; /* a character is read, but is not consumed yet */
+#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_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
+#if TRIO_FEATURE_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
+#if TRIO_FEATURE_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;
- }
+ if (flags & FLAGS_QUAD)
+ {
+ *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count;
}
- break; /* FORMAT_COUNT */
-
- case FORMAT_CHAR:
-#if TRIO_WIDECHAR
- if (flags & FLAGS_WIDECHAR)
+ else if (flags & FLAGS_LONG)
+ {
+ *(long int *)pointer = (long int)count;
+ }
+ else if (flags & FLAGS_SHORT)
{
- if (TrioReadWideChar(data,
- (flags & FLAGS_IGNORE)
- ? NULL
- : parameters[i].data.wstring,
- flags,
- (width == NO_WIDTH) ? 1 : width) == 0)
- return assignment;
+ *(short int *)pointer = (short int)count;
}
else
-#endif
{
- if (TrioReadChar(data,
+ *(int *)pointer = (int)count;
+ }
+ }
+ break; /* FORMAT_COUNT */
+
+ case FORMAT_CHAR:
+#if TRIO_FEATURE_WIDECHAR
+ if (flags & FLAGS_WIDECHAR)
+ {
+ if (TrioReadWideChar(data,
(flags & FLAGS_IGNORE)
? NULL
- : parameters[i].data.string,
+ : parameters[i].data.wstring,
flags,
(width == NO_WIDTH) ? 1 : width) == 0)
- return assignment;
+ {
+ status = assignment;
+ goto end;
}
- 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]))
+ else
+#endif
{
- /* Whitespaces may match any amount of whitespaces */
- ch = TrioSkipWhitespaces(data);
+ if (TrioReadChar(data,
+ (flags & FLAGS_IGNORE)
+ ? NULL
+ : parameters[i].data.string,
+ flags,
+ (width == NO_WIDTH) ? 1 : width) == 0)
+ {
+ status = assignment;
+ goto end;
+ }
}
- else if (ch == format[index])
+ 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))
{
- data->InStream(data, &ch);
+ status = assignment;
+ goto end;
}
- else
- return assignment;
-
- index++;
+ if (!(flags & FLAGS_IGNORE))
+ assignment++;
+ break; /* FORMAT_POINTER */
+
+ case FORMAT_PARAMETER:
+ break; /* FORMAT_PARAMETER */
+
+ default:
+ status = TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
+ goto end;
}
+
+ ch = data->current;
+ offset = parameters[i].endOffset;
+ i++;
}
- return assignment;
+
+ status = assignment;
+ end:
+ if (data->UndoStream)
+ data->UndoStream(data);
+ return status;
}
/*************************************************************************
@@ -6351,12 +7074,13 @@ TRIO_ARGS3((data, format, parameters),
*/
TRIO_PRIVATE int
TrioScan
-TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray),
+TRIO_ARGS7((source, sourceSize, InStream, UndoStream, format, arglist, argarray),
trio_pointer_t source,
size_t sourceSize,
void (*InStream) TRIO_PROTO((trio_class_t *, int *)),
+ void (*UndoStream) TRIO_PROTO((trio_class_t *)),
TRIO_CONST char *format,
- va_list *arglist,
+ va_list arglist,
trio_pointer_t *argarray)
{
int status;
@@ -6368,6 +7092,7 @@ TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray),
memset(&data, 0, sizeof(data));
data.InStream = InStream;
+ data.UndoStream = UndoStream;
data.location = (trio_pointer_t)source;
data.max = sourceSize;
data.error = 0;
@@ -6378,7 +7103,7 @@ TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray),
TrioSetLocale();
}
#endif
-
+
status = TrioParse(TYPE_SCAN, format, parameters, arglist, argarray);
if (status < 0)
return status;
@@ -6394,6 +7119,7 @@ TRIO_ARGS6((source, sourceSize, InStream, format, arglist, argarray),
/*************************************************************************
* TrioInStreamFile
*/
+#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO
TRIO_PRIVATE void
TrioInStreamFile
TRIO_ARGS2((self, intPointer),
@@ -6405,7 +7131,9 @@ TRIO_ARGS2((self, intPointer),
assert(VALID(self));
assert(VALID(file));
- self->current = fgetc(file);
+ self->actually.cached = 0;
+
+ /* The initial value of self->current is zero */
if (self->current == EOF)
{
self->error = (ferror(file))
@@ -6415,18 +7143,46 @@ TRIO_ARGS2((self, intPointer),
else
{
self->processed++;
- self->committed++;
+ self->actually.cached++;
}
-
+
+ self->current = fgetc(file);
+
if (VALID(intPointer))
{
*intPointer = self->current;
}
}
+#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */
+
+/*************************************************************************
+ * TrioUndoStreamFile
+ */
+#if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO
+TRIO_PRIVATE void
+TrioUndoStreamFile
+TRIO_ARGS1((self),
+ trio_class_t *self)
+{
+ FILE *file = (FILE *)self->location;
+
+ assert(VALID(self));
+ assert(VALID(file));
+
+ if (self->actually.cached > 0)
+ {
+ assert(self->actually.cached == 1);
+
+ self->current = ungetc(self->current, file);
+ self->actually.cached = 0;
+ }
+}
+#endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */
/*************************************************************************
* TrioInStreamFileDescriptor
*/
+#if TRIO_FEATURE_FD
TRIO_PRIVATE void
TrioInStreamFileDescriptor
TRIO_ARGS2((self, intPointer),
@@ -6439,6 +7195,8 @@ TRIO_ARGS2((self, intPointer),
assert(VALID(self));
+ self->actually.cached = 0;
+
size = read(fd, &input, sizeof(char));
if (size == -1)
{
@@ -6451,19 +7209,21 @@ TRIO_ARGS2((self, intPointer),
}
if (self->current != EOF)
{
- self->committed++;
+ self->actually.cached++;
self->processed++;
}
-
+
if (VALID(intPointer))
{
*intPointer = self->current;
}
}
+#endif /* TRIO_FEATURE_FD */
/*************************************************************************
* TrioInStreamCustom
*/
+#if TRIO_FEATURE_CLOSURE
TRIO_PRIVATE void
TrioInStreamCustom
TRIO_ARGS2((self, intPointer),
@@ -6471,16 +7231,18 @@ TRIO_ARGS2((self, intPointer),
int *intPointer)
{
trio_custom_t *data;
-
+
assert(VALID(self));
assert(VALID(self->location));
+ self->actually.cached = 0;
+
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;
@@ -6488,14 +7250,15 @@ TRIO_ARGS2((self, intPointer),
else
{
self->processed++;
- self->committed++;
+ self->actually.cached++;
}
-
+
if (VALID(intPointer))
{
*intPointer = self->current;
}
}
+#endif /* TRIO_FEATURE_CLOSURE */
/*************************************************************************
* TrioInStreamString
@@ -6511,6 +7274,8 @@ TRIO_ARGS2((self, intPointer),
assert(VALID(self));
assert(VALID(self->location));
+ self->actually.cached = 0;
+
buffer = (unsigned char **)self->location;
self->current = (*buffer)[0];
if (self->current == NIL)
@@ -6521,9 +7286,9 @@ TRIO_ARGS2((self, intPointer),
{
(*buffer)++;
self->processed++;
- self->committed++;
+ self->actually.cached++;
}
-
+
if (VALID(intPointer))
{
*intPointer = self->current;
@@ -6554,6 +7319,7 @@ TRIO_ARGS2((self, intPointer),
@param ... Arguments.
@return Number of scanned characters.
*/
+#if TRIO_FEATURE_STDIO
TRIO_PUBLIC int
trio_scanf
TRIO_VARGS2((format, va_alist),
@@ -6568,11 +7334,21 @@ TRIO_VARGS2((format, va_alist),
TRIO_VA_START(args, format);
status = TrioScan((trio_pointer_t)stdin, 0,
TrioInStreamFile,
- format, &args, NULL);
+ TrioUndoStreamFile,
+ format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_STDIO */
+
+/**
+ Scan characters from standard input stream.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_STDIO
TRIO_PUBLIC int
trio_vscanf
TRIO_ARGS2((format, args),
@@ -6583,25 +7359,49 @@ TRIO_ARGS2((format, args),
return TrioScan((trio_pointer_t)stdin, 0,
TrioInStreamFile,
- format, &args, NULL);
+ TrioUndoStreamFile,
+ format, args, NULL);
}
+#endif /* TRIO_FEATURE_STDIO */
+
+/**
+ Scan characters from standard input stream.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_STDIO
TRIO_PUBLIC int
trio_scanfv
TRIO_ARGS2((format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
+
assert(VALID(format));
return TrioScan((trio_pointer_t)stdin, 0,
TrioInStreamFile,
- format, NULL, args);
+ TrioUndoStreamFile,
+ format, unused, args);
}
+#endif /* TRIO_FEATURE_STDIO */
/*************************************************************************
* fscanf
*/
+
+/**
+ Scan characters from file.
+
+ @param file File pointer.
+ @param format Formatting string.
+ @param ... Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_FILE
TRIO_PUBLIC int
trio_fscanf
TRIO_VARGS3((file, format, va_alist),
@@ -6618,11 +7418,22 @@ TRIO_VARGS3((file, format, va_alist),
TRIO_VA_START(args, format);
status = TrioScan((trio_pointer_t)file, 0,
TrioInStreamFile,
- format, &args, NULL);
+ TrioUndoStreamFile,
+ format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_FILE */
+/**
+ Scan characters from file.
+
+ @param file File pointer.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_FILE
TRIO_PUBLIC int
trio_vfscanf
TRIO_ARGS3((file, format, args),
@@ -6635,9 +7446,20 @@ TRIO_ARGS3((file, format, args),
return TrioScan((trio_pointer_t)file, 0,
TrioInStreamFile,
- format, &args, NULL);
+ TrioUndoStreamFile,
+ format, args, NULL);
}
+#endif /* TRIO_FEATURE_FILE */
+/**
+ Scan characters from file.
+
+ @param file File pointer.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_FILE
TRIO_PUBLIC int
trio_fscanfv
TRIO_ARGS3((file, format, args),
@@ -6645,17 +7467,31 @@ TRIO_ARGS3((file, format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
+
assert(VALID(file));
assert(VALID(format));
return TrioScan((trio_pointer_t)file, 0,
TrioInStreamFile,
- format, NULL, args);
+ TrioUndoStreamFile,
+ format, unused, args);
}
+#endif /* TRIO_FEATURE_FILE */
/*************************************************************************
* dscanf
*/
+
+/**
+ Scan characters from file descriptor.
+
+ @param fd File descriptor.
+ @param format Formatting string.
+ @param ... Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_FD
TRIO_PUBLIC int
trio_dscanf
TRIO_VARGS3((fd, format, va_alist),
@@ -6671,11 +7507,22 @@ TRIO_VARGS3((fd, format, va_alist),
TRIO_VA_START(args, format);
status = TrioScan((trio_pointer_t)&fd, 0,
TrioInStreamFileDescriptor,
- format, &args, NULL);
+ NULL,
+ format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_FD */
+/**
+ Scan characters from file descriptor.
+
+ @param fd File descriptor.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_FD
TRIO_PUBLIC int
trio_vdscanf
TRIO_ARGS3((fd, format, args),
@@ -6687,9 +7534,20 @@ TRIO_ARGS3((fd, format, args),
return TrioScan((trio_pointer_t)&fd, 0,
TrioInStreamFileDescriptor,
- format, &args, NULL);
+ NULL,
+ format, args, NULL);
}
+#endif /* TRIO_FEATURE_FD */
+
+/**
+ Scan characters from file descriptor.
+ @param fd File descriptor.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
+#if TRIO_FEATURE_FD
TRIO_PUBLIC int
trio_dscanfv
TRIO_ARGS3((fd, format, args),
@@ -6697,16 +7555,21 @@ TRIO_ARGS3((fd, format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
+
assert(VALID(format));
return TrioScan((trio_pointer_t)&fd, 0,
TrioInStreamFileDescriptor,
- format, NULL, args);
+ NULL,
+ format, unused, args);
}
+#endif /* TRIO_FEATURE_FD */
/*************************************************************************
* cscanf
*/
+#if TRIO_FEATURE_CLOSURE
TRIO_PUBLIC int
trio_cscanf
TRIO_VARGS4((stream, closure, format, va_alist),
@@ -6725,11 +7588,13 @@ TRIO_VARGS4((stream, closure, format, va_alist),
TRIO_VA_START(args, format);
data.stream.in = stream;
data.closure = closure;
- status = TrioScan(&data, 0, TrioInStreamCustom, format, &args, NULL);
+ status = TrioScan(&data, 0, TrioInStreamCustom, NULL, format, args, NULL);
TRIO_VA_END(args);
return status;
}
+#endif /* TRIO_FEATURE_CLOSURE */
+#if TRIO_FEATURE_CLOSURE
TRIO_PUBLIC int
trio_vcscanf
TRIO_ARGS4((stream, closure, format, args),
@@ -6745,9 +7610,11 @@ TRIO_ARGS4((stream, closure, format, args),
data.stream.in = stream;
data.closure = closure;
- return TrioScan(&data, 0, TrioInStreamCustom, format, &args, NULL);
+ return TrioScan(&data, 0, TrioInStreamCustom, NULL, format, args, NULL);
}
+#endif /* TRIO_FEATURE_CLOSURE */
+#if TRIO_FEATURE_CLOSURE
TRIO_PUBLIC int
trio_cscanfv
TRIO_ARGS4((stream, closure, format, args),
@@ -6756,6 +7623,7 @@ TRIO_ARGS4((stream, closure, format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
trio_custom_t data;
assert(VALID(stream));
@@ -6763,12 +7631,22 @@ TRIO_ARGS4((stream, closure, format, args),
data.stream.in = stream;
data.closure = closure;
- return TrioScan(&data, 0, TrioInStreamCustom, format, NULL, args);
+ return TrioScan(&data, 0, TrioInStreamCustom, NULL, format, unused, args);
}
+#endif /* TRIO_FEATURE_CLOSURE */
/*************************************************************************
* sscanf
*/
+
+/**
+ Scan characters from string.
+
+ @param buffer Input string.
+ @param format Formatting string.
+ @param ... Arguments.
+ @return Number of scanned characters.
+ */
TRIO_PUBLIC int
trio_sscanf
TRIO_VARGS3((buffer, format, va_alist),
@@ -6785,11 +7663,20 @@ TRIO_VARGS3((buffer, format, va_alist),
TRIO_VA_START(args, format);
status = TrioScan((trio_pointer_t)&buffer, 0,
TrioInStreamString,
- format, &args, NULL);
+ NULL,
+ format, args, NULL);
TRIO_VA_END(args);
return status;
}
+/**
+ Scan characters from string.
+
+ @param buffer Input string.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
TRIO_PUBLIC int
trio_vsscanf
TRIO_ARGS3((buffer, format, args),
@@ -6802,9 +7689,18 @@ TRIO_ARGS3((buffer, format, args),
return TrioScan((trio_pointer_t)&buffer, 0,
TrioInStreamString,
- format, &args, NULL);
+ NULL,
+ format, args, NULL);
}
+/**
+ Scan characters from string.
+
+ @param buffer Input string.
+ @param format Formatting string.
+ @param args Arguments.
+ @return Number of scanned characters.
+ */
TRIO_PUBLIC int
trio_sscanfv
TRIO_ARGS3((buffer, format, args),
@@ -6812,14 +7708,19 @@ TRIO_ARGS3((buffer, format, args),
TRIO_CONST char *format,
trio_pointer_t *args)
{
+ static va_list unused;
+
assert(VALID(buffer));
assert(VALID(format));
return TrioScan((trio_pointer_t)&buffer, 0,
TrioInStreamString,
- format, NULL, args);
+ NULL,
+ format, unused, args);
}
+#endif /* TRIO_FEATURE_SCANF */
+
/** @} End of Scanf documentation module */
/*************************************************************************
@@ -6830,6 +7731,7 @@ trio_strerror
TRIO_ARGS1((errorcode),
int errorcode)
{
+#if TRIO_FEATURE_STRERR
/* Textual versions of the error codes */
switch (TRIO_ERROR_CODE(errorcode))
{
@@ -6852,4 +7754,7 @@ TRIO_ARGS1((errorcode),
default:
return "Unknown";
}
+#else
+ return "Unknown";
+#endif
}
diff --git a/trio/trio.h b/trio/trio.h
index 82e65fcc..ad29222d 100644
--- a/trio/trio.h
+++ b/trio/trio.h
@@ -1,6 +1,6 @@
/*************************************************************************
*
- * $Id: trio.h,v 1.16 2003/03/06 20:29:48 breese Exp $
+ * $Id: trio.h,v 1.18 2008/11/09 10:52:26 breese Exp $
*
* Copyright (C) 1998 Bjorn Reese and Daniel Stenberg.
*
@@ -32,15 +32,9 @@
# include <config.h>
#endif
-#include "triodef.h"
+#include "triop.h"
#include <stdio.h>
-#include <stdlib.h>
-#if defined(TRIO_COMPILER_ANCIENT)
-# include <varargs.h>
-#else
-# include <stdarg.h>
-#endif
#ifdef __cplusplus
extern "C" {
@@ -110,11 +104,14 @@ int trio_snprintfcat TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *form
int trio_vsnprintfcat TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format,
va_list args));
+#if defined(TRIO_DEPRECATED)
char *trio_aprintf TRIO_PROTO((TRIO_CONST char *format, ...));
char *trio_vaprintf TRIO_PROTO((TRIO_CONST char *format, va_list args));
+#endif
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));
+int trio_asprintfv TRIO_PROTO((char **result, TRIO_CONST char *format, trio_pointer_t * args));
/*************************************************************************
* Scan Functions
diff --git a/trio/triodef.h b/trio/triodef.h
index 400dfcfc..2ce12b8b 100644
--- a/trio/triodef.h
+++ b/trio/triodef.h
@@ -1,6 +1,6 @@
/*************************************************************************
*
- * $Id: triodef.h,v 1.18 2003/03/01 15:34:01 breese Exp $
+ * $Id: triodef.h,v 1.33 2009/05/24 11:39:24 breese Exp $
*
* Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
*
@@ -19,61 +19,122 @@
#define TRIO_TRIODEF_H
/*************************************************************************
- * Platform and compiler support detection
+ * 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__)
+#endif
+
+#if defined(__SUNPRO_CC)
+# define TRIO_COMPILER_SUNPRO __SUNPRO_CC
+#else
+# if defined(__SUNPRO_C)
+# define TRIO_COMPILER_SUNPRO __SUNPRO_C
+# endif
+#endif
+
+#if 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)
+#else
+# if defined(_AIX) && !defined(__GNUC__)
+# define TRIO_COMPILER_XLC /* Workaround for old xlc */
+# endif
+#endif
+
+#if 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)
+#else
+# if defined(__osf__) && defined(__LANGUAGE_C__) && !defined(__GNUC__)
+# define TRIO_COMPILER_DECC /* Workaround for old DEC C compilers */
+# endif
+#endif
+
+#if defined(__HP_aCC) || defined(__HP_cc)
+# define TRIO_COMPILER_HP
+#endif
+
+#if defined(sgi) || defined(__sgi)
+# define TRIO_COMPILER_MIPSPRO
+#endif
+
+#if defined(_MSC_VER)
# define TRIO_COMPILER_MSVC
-#elif defined(__BORLANDC__)
+#endif
+
+#if 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.
+/*************************************************************************
+ * Platform support detection
*/
+
+#if defined(VMS) || defined(__VMS)
# define TRIO_PLATFORM_VMS
-#elif defined(unix) || defined(__unix) || defined(__unix__)
+#endif
+
+#if defined(unix) || defined(__unix) || defined(__unix__)
# define TRIO_PLATFORM_UNIX
-#elif defined(TRIO_COMPILER_XLC) || defined(_AIX)
+#endif
+
+#if defined(TRIO_COMPILER_XLC) || defined(_AIX)
# define TRIO_PLATFORM_UNIX
-#elif defined(TRIO_COMPILER_DECC) || defined(__osf___)
+#endif
+
+#if defined(TRIO_COMPILER_DECC) || defined(__osf___)
+# if !defined(TRIO_PLATFORM_VMS)
+# define TRIO_PLATFORM_UNIX
+# endif
+#endif
+
+#if defined(__NetBSD__)
+# define TRIO_PLATFORM_UNIX
+#endif
+
+#if defined(__Lynx__)
# define TRIO_PLATFORM_UNIX
-#elif defined(__NetBSD__)
+# define TRIO_PLATFORM_LYNX
+#endif
+
+#if defined(__APPLE__) && defined(__MACH__)
# define TRIO_PLATFORM_UNIX
-#elif defined(__QNX__)
+#endif
+
+#if defined(__QNX__)
# define TRIO_PLATFORM_UNIX
# define TRIO_PLATFORM_QNX
-#elif defined(__CYGWIN__)
+#endif
+
+#if defined(__CYGWIN__)
# define TRIO_PLATFORM_UNIX
-#elif defined(AMIGA) && defined(TRIO_COMPILER_GCC)
+#endif
+
+#if defined(AMIGA) && defined(TRIO_COMPILER_GCC)
# define TRIO_PLATFORM_UNIX
-#elif defined(TRIO_COMPILER_MSVC) || defined(WIN32) || defined(_WIN32)
+#endif
+
+#if defined(TRIO_COMPILER_MSVC) || defined(WIN32) || defined(_WIN32)
# define TRIO_PLATFORM_WIN32
-#elif defined(mpeix) || defined(__mpexl)
+#endif
+
+#if defined(_WIN32_WCE)
+# define TRIO_PLATFORM_WINCE
+#endif
+
+#if defined(mpeix) || defined(__mpexl)
# define TRIO_PLATFORM_MPEIX
#endif
#if defined(_AIX)
# define TRIO_PLATFORM_AIX
-#elif defined(__hpux)
+#endif
+
+#if defined(__hpux)
# define TRIO_PLATFORM_HPUX
-#elif defined(sun) || defined(__sun__)
+#endif
+
+#if defined(sun) || defined(__sun__)
# if defined(__SVR4) || defined(__svr4__)
# define TRIO_PLATFORM_SOLARIS
# else
@@ -81,35 +142,65 @@
# 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
+/*************************************************************************
+ * Standards support detection
+ */
+
+#if defined(__STDC__) \
+ || defined(_MSC_EXTENSIONS) \
+ || defined(TRIO_COMPILER_BORLAND)
+# define PREDEF_STANDARD_C89
+#endif
+#if defined(__STDC_VERSION__)
+# define PREDEF_STANDARD_C90
+#endif
+#if (__STDC_VERSION__ - 0 >= 199409L)
+# define PREDEF_STANDARD_C94
+#endif
+#if (__STDC_VERSION__ - 0 >= 199901L)
+# define PREDEF_STANDARD_C99
+#endif
+#if defined(TRIO_COMPILER_SUNPRO) && (TRIO_COMPILER_SUNPRO >= 0x420)
+# if !defined(PREDEF_STANDARD_C94)
+# define PREDEF_STANDARD_C94
# endif
#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
+#if defined(__cplusplus)
+# define PREDEF_STANDARD_CXX
+#endif
+#if __cplusplus - 0 >= 199711L
+# define PREDEF_STANDARD_CXX89
+#endif
+
+#if defined(TRIO_PLATFORM_UNIX)
+# include <unistd.h>
+#endif
+
+#if defined(_POSIX_VERSION)
+# define PREDEF_STANDARD_POSIX _POSIX_VERSION
+# if (_POSIX_VERSION >= 199506L)
+# define PREDEF_STANDARD_POSIX_1996
# endif
#endif
+#if (_XOPEN_VERSION - 0 >= 3) || defined(_XOPEN_XPG3)
+# define PREDEF_STANDARD_XPG3
+#endif
+#if (_XOPEN_VERSION - 0 >= 4) || defined(_XOPEN_XPG4)
+# define PREDEF_STANDARD_XPG4
+#endif
+#if (_XOPEN_VERSION - 0 > 4) \
+ || (defined(_XOPEN_UNIX) && (_XOPEN_VERSION - 0 == 4))
+# define PREDEF_STANDARD_UNIX95
+#endif
+#if (_XOPEN_VERSION - 0 >= 500)
+# define PREDEF_STANDARD_UNIX98
+#endif
+#if (_XOPEN_VERSION - 0 >= 600)
+# define PREDEF_STANDARD_UNIX03
+#endif
+
/*************************************************************************
* Generic defines
*/
@@ -121,7 +212,7 @@
# define TRIO_PRIVATE static
#endif
-#if !(defined(TRIO_COMPILER_SUPPORTS_C89) || defined(__cplusplus))
+#if !(defined(PREDEF_STANDARD_C89) || defined(PREDEF_STANDARD_CXX))
# define TRIO_COMPILER_ANCIENT
#endif
@@ -140,6 +231,7 @@ typedef char * trio_pointer_t;
# 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_ARGS7(list,a1,a2,a3,a4,a5,a6,a7) list a1; a2; a3; a4; a5; a6; a7;
# 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
@@ -162,6 +254,7 @@ typedef void * trio_pointer_t;
# 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_ARGS7(list,a1,a2,a3,a4,a5,a6,a7) (a1,a2,a3,a4,a5,a6,a7)
# define TRIO_VARGS2 TRIO_ARGS2
# define TRIO_VARGS3 TRIO_ARGS3
# define TRIO_VARGS4 TRIO_ARGS4
@@ -171,15 +264,20 @@ typedef void * trio_pointer_t;
# define TRIO_VA_END(x) va_end(x)
#endif
-#if defined(TRIO_COMPILER_SUPPORTS_C99) || defined(__cplusplus)
+#if defined(PREDEF_STANDARD_C99) || defined(PREDEF_STANDARD_CXX)
# 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
+# if defined(TRIO_COMPILER_GCC)
+# define TRIO_INLINE __inline__
+# endif
+# if defined(TRIO_COMPILER_MSVC)
+# define TRIO_INLINE _inline
+# endif
+# if defined(TRIO_COMPILER_BCB)
+# define TRIO_INLINE __inline
+# endif
+#endif
+#if !defined(TRIO_INLINE)
# define TRIO_INLINE
#endif
@@ -194,17 +292,13 @@ typedef void * trio_pointer_t;
*/
# pragma message disable (UNDERFLOW, FLOATOVERFL)
-# if (__CRTL_VER > 80000000)
+# if (__CRTL_VER < 80210001)
/*
* 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
+# if defined(PREDEF_STANDARD_C99)
+# undef PREDEF_STANDARD_C99
# endif
# endif
#endif
@@ -212,7 +306,7 @@ typedef void * trio_pointer_t;
/*
* Not all preprocessors supports the LL token.
*/
-#if defined(TRIO_COMPILER_BCB)
+#if defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
#else
# define TRIO_COMPILER_SUPPORTS_LL
#endif
diff --git a/trio/trionan.c b/trio/trionan.c
index 4391477e..30163225 100644
--- a/trio/trionan.c
+++ b/trio/trionan.c
@@ -1,6 +1,6 @@
/*************************************************************************
*
- * $Id: trionan.c,v 1.26 2002/12/08 12:08:21 breese Exp $
+ * $Id: trionan.c,v 1.33 2005/05/29 11:57:25 breese Exp $
*
* Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
*
@@ -31,12 +31,6 @@
*
************************************************************************/
-/*
- * TODO:
- * o Put all the magic into trio_fpclassify_and_signbit(), and use this from
- * trio_isnan() etc.
- */
-
/*************************************************************************
* Include files
*/
@@ -46,7 +40,9 @@
#include <math.h>
#include <string.h>
#include <limits.h>
-#include <float.h>
+#if !defined(TRIO_PLATFORM_SYMBIAN)
+# include <float.h>
+#endif
#if defined(TRIO_PLATFORM_UNIX)
# include <signal.h>
#endif
@@ -66,6 +62,13 @@
* Definitions
*/
+#if !defined(TRIO_PUBLIC_NAN)
+# define TRIO_PUBLIC_NAN TRIO_PUBLIC
+#endif
+#if !defined(TRIO_PRIVATE_NAN)
+# define TRIO_PRIVATE_NAN TRIO_PRIVATE
+#endif
+
#define TRIO_TRUE (1 == 1)
#define TRIO_FALSE (0 == 1)
@@ -81,8 +84,10 @@
# 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"
+# else
+# if defined(TRIO_COMPILER_GCC)
+# error "Must be compiled with option -mieee"
+# endif
# endif
#endif /* __alpha && ! _IEEE_FP */
@@ -99,19 +104,135 @@
* 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
+#if defined(__STDC_IEC_559__)
+# define TRIO_IEEE_754
+#else
+# if (FLT_RADIX - 0 == 2) && (DBL_MAX_EXP - 0 == 1024) && (DBL_MANT_DIG - 0 == 53)
+# define TRIO_IEEE_754
+# endif
+#endif
+
+/*
+ * Determine which fpclassify_and_sign() function to use.
+ */
+#if defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT)
+# if defined(PREDEF_STANDARD_C99) && defined(fpclassify)
+# define TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT
+# else
+# if defined(TRIO_COMPILER_DECC)
+# define TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT
+# else
+# if defined(TRIO_COMPILER_VISUALC) || defined(TRIO_COMPILER_BORLAND)
+# define TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT
+# else
+# if defined(TRIO_COMPILER_HP) && defined(FP_PLUS_NORM)
+# define TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT
+# else
+# if defined(TRIO_COMPILER_XLC) && defined(FP_PLUS_NORM)
+# define TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT
+# else
+# define TRIO_FUNC_INTERNAL_FPCLASSIFY_AND_SIGNBIT
+# endif
+# endif
+# endif
+# endif
+# endif
+#endif
+
+/*
+ * Determine how to generate negative zero.
+ */
+#if defined(TRIO_FUNC_NZERO)
+# if defined(TRIO_IEEE_754)
+# define TRIO_NZERO_IEEE_754
+# else
+# define TRIO_NZERO_FALLBACK
+# endif
+#endif
+
+/*
+ * Determine how to generate positive infinity.
+ */
+#if defined(TRIO_FUNC_PINF)
+# if defined(INFINITY) && defined(__STDC_IEC_559__)
+# define TRIO_PINF_C99_MACRO
+# else
+# if defined(TRIO_IEEE_754)
+# define TRIO_PINF_IEEE_754
+# else
+# define TRIO_PINF_FALLBACK
+# endif
+# endif
+#endif
+
+/*
+ * Determine how to generate NaN.
+ */
+#if defined(TRIO_FUNC_NAN)
+# if defined(PREDEF_STANDARD_C99) && !defined(TRIO_COMPILER_DECC)
+# define TRIO_NAN_C99_FUNCTION
+# else
+# if defined(NAN) && defined(__STDC_IEC_559__)
+# define TRIO_NAN_C99_MACRO
+# else
+# if defined(TRIO_IEEE_754)
+# define TRIO_NAN_IEEE_754
+# else
+# define TRIO_NAN_FALLBACK
+# endif
+# endif
+# endif
+#endif
+
+/*
+ * Resolve internal dependencies.
+ */
+#if defined(TRIO_FUNC_INTERNAL_FPCLASSIFY_AND_SIGNBIT)
+# define TRIO_FUNC_INTERNAL_ISNAN
+# define TRIO_FUNC_INTERNAL_ISINF
+# if defined(TRIO_IEEE_754)
+# define TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY
+# define TRIO_FUNC_INTERNAL_IS_NEGATIVE
+# endif
+#endif
+
+#if defined(TRIO_NZERO_IEEE_754) \
+ || defined(TRIO_PINF_IEEE_754) \
+ || defined(TRIO_NAN_IEEE_754)
+# define TRIO_FUNC_INTERNAL_MAKE_DOUBLE
#endif
+#if defined(TRIO_FUNC_INTERNAL_ISNAN)
+# if defined(PREDEF_STANDARD_XPG3)
+# define TRIO_INTERNAL_ISNAN_XPG3
+# else
+# if defined(TRIO_IEEE_754)
+# define TRIO_INTERNAL_ISNAN_IEEE_754
+# else
+# define TRIO_INTERNAL_ISNAN_FALLBACK
+# endif
+# endif
+#endif
+
+#if defined(TRIO_FUNC_INTERNAL_ISINF)
+# if defined(TRIO_IEEE_754)
+# define TRIO_INTERNAL_ISINF_IEEE_754
+# else
+# define TRIO_INTERNAL_ISINF_FALLBACK
+# endif
+#endif
/*************************************************************************
* Constants
*/
-static TRIO_CONST char rcsid[] = "@(#)$Id: trionan.c,v 1.26 2002/12/08 12:08:21 breese Exp $";
-
-#if defined(USE_IEEE_754)
+#if !defined(TRIO_EMBED_NAN)
+static TRIO_CONST char rcsid[] = "@(#)$Id: trionan.c,v 1.33 2005/05/29 11:57:25 breese Exp $";
+#endif
+#if defined(TRIO_FUNC_INTERNAL_MAKE_DOUBLE) \
+ || defined(TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY) \
+ || defined(TRIO_FUNC_INTERNAL_IS_NEGATIVE)
/*
* Endian-agnostic indexing macro.
*
@@ -124,9 +245,10 @@ static TRIO_CONST char rcsid[] = "@(#)$Id: trionan.c,v 1.26 2002/12/08 12:08:21
* for the IEEE 754 bit-patterns and masks.
*/
#define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)])
-
static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275;
+#endif
+#if defined(TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY)
/* Mask for the exponent */
static TRIO_CONST unsigned char ieee_754_exponent_mask[] = {
0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
@@ -136,37 +258,48 @@ static TRIO_CONST unsigned char ieee_754_exponent_mask[] = {
static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = {
0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
+#endif
+#if defined(TRIO_FUNC_INTERNAL_IS_NEGATIVE)
/* Mask for the sign bit */
static TRIO_CONST unsigned char ieee_754_sign_mask[] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+#endif
+#if defined(TRIO_NZERO_IEEE_754)
/* Bit-pattern for negative zero */
static TRIO_CONST unsigned char ieee_754_negzero_array[] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+#endif
+#if defined(TRIO_PINF_IEEE_754)
/* Bit-pattern for infinity */
static TRIO_CONST unsigned char ieee_754_infinity_array[] = {
0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+#endif
+#if defined(TRIO_NAN_IEEE_754)
/* Bit-pattern for quiet NaN */
static TRIO_CONST unsigned char ieee_754_qnan_array[] = {
0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+#endif
/*************************************************************************
- * Functions
+ * Internal functions
*/
/*
- * trio_make_double
+ * internal_make_double
*/
-TRIO_PRIVATE double
-trio_make_double
+#if defined(TRIO_FUNC_INTERNAL_MAKE_DOUBLE)
+
+TRIO_PRIVATE_NAN double
+internal_make_double
TRIO_ARGS1((values),
TRIO_CONST unsigned char *values)
{
@@ -179,11 +312,15 @@ TRIO_ARGS1((values),
return result;
}
+#endif
+
/*
- * trio_is_special_quantity
+ * internal_is_special_quantity
*/
-TRIO_PRIVATE int
-trio_is_special_quantity
+#if defined(TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY)
+
+TRIO_PRIVATE_NAN int
+internal_is_special_quantity
TRIO_ARGS2((number, has_mantissa),
double number,
int *has_mantissa)
@@ -203,11 +340,15 @@ TRIO_ARGS2((number, has_mantissa),
return is_special_quantity;
}
+#endif
+
/*
- * trio_is_negative
+ * internal_is_negative
*/
-TRIO_PRIVATE int
-trio_is_negative
+#if defined(TRIO_FUNC_INTERNAL_IS_NEGATIVE)
+
+TRIO_PRIVATE_NAN int
+internal_is_negative
TRIO_ARGS1((number),
double number)
{
@@ -221,167 +362,271 @@ TRIO_ARGS1((number),
return is_negative;
}
-#endif /* USE_IEEE_754 */
-
+#endif
-/**
- Generate negative zero.
+#if defined(TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT)
- @return Floating-point representation of negative zero.
-*/
-TRIO_PUBLIC double
-trio_nzero(TRIO_NOARGS)
+TRIO_PRIVATE_NAN TRIO_INLINE int
+c99_fpclassify_and_signbit
+TRIO_ARGS2((number, is_negative),
+ double number,
+ int *is_negative)
{
-#if defined(USE_IEEE_754)
- return trio_make_double(ieee_754_negzero_array);
-#else
- TRIO_VOLATILE double zero = 0.0;
-
- return -zero;
-#endif
+ *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;
+ }
}
-/**
- Generate positive infinity.
+#endif /* TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT */
- @return Floating-point representation of positive infinity.
-*/
-TRIO_PUBLIC double
-trio_pinf(TRIO_NOARGS)
-{
- /* Cache the result */
- static double result = 0.0;
+#if defined(TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT)
- if (result == 0.0) {
-
-#if defined(INFINITY) && defined(__STDC_IEC_559__)
- result = (double)INFINITY;
+TRIO_PRIVATE_NAN TRIO_INLINE int
+decc_fpclassify_and_signbit
+TRIO_ARGS2((number, is_negative),
+ double number,
+ int *is_negative)
+{
+ switch (fp_class(number)) {
+ case FP_QNAN:
+ case FP_SNAN:
+ *is_negative = TRIO_FALSE; /* NaN has no sign */
+ return TRIO_FP_NAN;
+ case FP_POS_INF:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_INFINITE;
+ case FP_NEG_INF:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_INFINITE;
+ case FP_POS_DENORM:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_SUBNORMAL;
+ case FP_NEG_DENORM:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_SUBNORMAL;
+ case FP_POS_ZERO:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_ZERO;
+ case FP_NEG_ZERO:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_ZERO;
+ case FP_POS_NORM:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_NORMAL;
+ case FP_NEG_NORM:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_NORMAL;
+ default:
+ *is_negative = (number < 0.0);
+ return TRIO_FP_NORMAL;
+ }
+}
-#elif defined(USE_IEEE_754)
- result = trio_make_double(ieee_754_infinity_array);
+#endif /* TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT */
-#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
+#if defined(TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT)
- result = HUGE_VAL;
- if (HUGE_VAL == DBL_MAX) {
- /* Force overflow */
- result += HUGE_VAL;
- }
-
-# if defined(TRIO_PLATFORM_UNIX)
- signal(SIGFPE, signal_handler);
+TRIO_PRIVATE_NAN int
+ms_fpclassify_and_signbit
+TRIO_ARGS2((number, is_negative),
+ double number,
+ int *is_negative)
+{
+ int result;
+# if defined(TRIO_COMPILER_BORLAND)
+ /*
+ * The floating-point precision may be changed by the Borland _fpclass()
+ * function, so we have to save and restore the floating-point control mask.
+ */
+ unsigned int mask;
+ /* Remember the old mask */
+ mask = _control87(0, 0);
# endif
-
-#endif
+
+ switch (_fpclass(number)) {
+ case _FPCLASS_QNAN:
+ case _FPCLASS_SNAN:
+ *is_negative = TRIO_FALSE; /* NaN has no sign */
+ result = TRIO_FP_NAN;
+ break;
+ case _FPCLASS_PINF:
+ *is_negative = TRIO_FALSE;
+ result = TRIO_FP_INFINITE;
+ break;
+ case _FPCLASS_NINF:
+ *is_negative = TRIO_TRUE;
+ result = TRIO_FP_INFINITE;
+ break;
+ case _FPCLASS_PD:
+ *is_negative = TRIO_FALSE;
+ result = TRIO_FP_SUBNORMAL;
+ break;
+ case _FPCLASS_ND:
+ *is_negative = TRIO_TRUE;
+ result = TRIO_FP_SUBNORMAL;
+ break;
+ case _FPCLASS_PZ:
+ *is_negative = TRIO_FALSE;
+ result = TRIO_FP_ZERO;
+ break;
+ case _FPCLASS_NZ:
+ *is_negative = TRIO_TRUE;
+ result = TRIO_FP_ZERO;
+ break;
+ case _FPCLASS_PN:
+ *is_negative = TRIO_FALSE;
+ result = TRIO_FP_NORMAL;
+ break;
+ case _FPCLASS_NN:
+ *is_negative = TRIO_TRUE;
+ result = TRIO_FP_NORMAL;
+ break;
+ default:
+ *is_negative = (number < 0.0);
+ result = TRIO_FP_NORMAL;
+ break;
}
+
+# if defined(TRIO_COMPILER_BORLAND)
+ /* Restore the old precision */
+ (void)_control87(mask, MCW_PC);
+# endif
+
return result;
}
-/**
- Generate negative infinity.
+#endif /* TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT */
- @return Floating-point value of negative infinity.
-*/
-TRIO_PUBLIC double
-trio_ninf(TRIO_NOARGS)
-{
- static double result = 0.0;
+#if defined(TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT)
- 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();
+TRIO_PRIVATE_NAN TRIO_INLINE int
+hp_fpclassify_and_signbit
+TRIO_ARGS2((number, is_negative),
+ double number,
+ int *is_negative)
+{
+ /*
+ * 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.
+ */
+ switch (fpclassify(number)) {
+ case FP_QNAN:
+ case FP_SNAN:
+ *is_negative = TRIO_FALSE; /* NaN has no sign */
+ return TRIO_FP_NAN;
+ case FP_PLUS_INF:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_INFINITE;
+ case FP_MINUS_INF:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_INFINITE;
+ case FP_PLUS_DENORM:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_SUBNORMAL;
+ case FP_MINUS_DENORM:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_SUBNORMAL;
+ case FP_PLUS_ZERO:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_ZERO;
+ case FP_MINUS_ZERO:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_ZERO;
+ case FP_PLUS_NORM:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_NORMAL;
+ case FP_MINUS_NORM:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_NORMAL;
+ default:
+ *is_negative = (number < 0.0);
+ return TRIO_FP_NORMAL;
}
- 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;
+#endif /* TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT */
- 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);
+#if defined(TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT)
-#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);
+TRIO_PRIVATE_NAN TRIO_INLINE int
+xlc_fpclassify_and_signbit
+TRIO_ARGS2((number, is_negative),
+ double number,
+ int *is_negative)
+{
+ /*
+ * AIX has class() for C, and _class() for C++
+ */
+# if defined(__cplusplus)
+# define AIX_CLASS(n) _class(n)
+# else
+# define AIX_CLASS(n) class(n)
# endif
-
-#endif
+
+ switch (AIX_CLASS(number)) {
+ case FP_QNAN:
+ case FP_SNAN:
+ *is_negative = TRIO_FALSE; /* NaN has no sign */
+ return TRIO_FP_NAN;
+ case FP_PLUS_INF:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_INFINITE;
+ case FP_MINUS_INF:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_INFINITE;
+ case FP_PLUS_DENORM:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_SUBNORMAL;
+ case FP_MINUS_DENORM:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_SUBNORMAL;
+ case FP_PLUS_ZERO:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_ZERO;
+ case FP_MINUS_ZERO:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_ZERO;
+ case FP_PLUS_NORM:
+ *is_negative = TRIO_FALSE;
+ return TRIO_FP_NORMAL;
+ case FP_MINUS_NORM:
+ *is_negative = TRIO_TRUE;
+ return TRIO_FP_NORMAL;
+ default:
+ *is_negative = (number < 0.0);
+ return TRIO_FP_NORMAL;
}
- return result;
}
-/**
- Check for NaN.
+#endif /* TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT */
- @param number An arbitrary floating-point number.
- @return Boolean value indicating whether or not the number is a NaN.
-*/
-TRIO_PUBLIC int
-trio_isnan
+#if defined(TRIO_FUNC_INTERNAL_ISNAN)
+
+TRIO_PRIVATE_NAN TRIO_INLINE int
+internal_isnan
TRIO_ARGS1((number),
double number)
{
-#if (defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isnan)) \
- || defined(TRIO_COMPILER_SUPPORTS_UNIX95)
+# if defined(TRIO_INTERNAL_ISNAN_XPG3) || defined(TRIO_PLATFORM_SYMBIAN)
/*
- * 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.
+ * XPG3 defines isnan() as a function.
*/
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)
+# endif
+
+# if defined(TRIO_INTERNAL_ISNAN_IEEE_754)
+
/*
* Examine IEEE 754 bit-pattern. A NaN must have a special exponent
* pattern, and a non-empty mantissa.
@@ -389,20 +634,23 @@ TRIO_ARGS1((number),
int has_mantissa;
int is_special_quantity;
- is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
+ is_special_quantity = internal_is_special_quantity(number, &has_mantissa);
return (is_special_quantity && has_mantissa);
-#else
+# endif
+
+# if defined(TRIO_INTERNAL_ISNAN_FALLBACK)
+
/*
* Fallback solution
*/
int status;
double integral, fraction;
-# if defined(TRIO_PLATFORM_UNIX)
+# if defined(TRIO_PLATFORM_UNIX)
void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
-# endif
+# endif
status = (/*
* NaN is the only number which does not compare to itself
@@ -415,53 +663,31 @@ TRIO_ARGS1((number),
(fraction = modf(number, &integral),
integral == fraction)));
-# if defined(TRIO_PLATFORM_UNIX)
+# if defined(TRIO_PLATFORM_UNIX)
signal(SIGFPE, signal_handler);
-# endif
+# endif
return status;
-#endif
+# endif
}
-/**
- Check for infinity.
+#endif /* TRIO_FUNC_INTERNAL_ISNAN */
- @param number An arbitrary floating-point number.
- @return 1 if positive infinity, -1 if negative infinity, 0 otherwise.
-*/
-TRIO_PUBLIC int
-trio_isinf
+#if defined(TRIO_FUNC_INTERNAL_ISINF)
+
+TRIO_PRIVATE_NAN TRIO_INLINE int
+internal_isinf
TRIO_ARGS1((number),
double number)
{
-#if defined(TRIO_COMPILER_DECC)
- /*
- * 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));
+# if defined(TRIO_PLATFORM_SYMBIAN)
-#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));
+ return isinf(number);
-#elif defined(USE_IEEE_754)
+# endif
+
+# if defined(TRIO_INTERNAL_ISINF_IEEE_754)
/*
* Examine IEEE 754 bit-pattern. Infinity must have a special exponent
* pattern, and an empty mantissa.
@@ -469,21 +695,24 @@ TRIO_ARGS1((number),
int has_mantissa;
int is_special_quantity;
- is_special_quantity = trio_is_special_quantity(number, &has_mantissa);
+ is_special_quantity = internal_is_special_quantity(number, &has_mantissa);
return (is_special_quantity && !has_mantissa)
? ((number < 0.0) ? -1 : 1)
: 0;
-#else
+# endif
+
+# if defined(TRIO_INTERNAL_ISINF_FALLBACK)
+
/*
* Fallback solution.
*/
int status;
-# if defined(TRIO_PLATFORM_UNIX)
+# if defined(TRIO_PLATFORM_UNIX)
void (*signal_handler)(int) = signal(SIGFPE, SIG_IGN);
-# endif
+# endif
double infinity = trio_pinf();
@@ -491,185 +720,63 @@ TRIO_ARGS1((number),
? 1
: ((number == -infinity) ? -1 : 0));
-# if defined(TRIO_PLATFORM_UNIX)
+# if defined(TRIO_PLATFORM_UNIX)
signal(SIGFPE, signal_handler);
-# endif
+# endif
return status;
-
-#endif
+
+# endif
}
+#endif /* TRIO_FUNC_INTERNAL_ISINF */
-/**
- Check for finity.
+/*************************************************************************
+ * Public functions
+ */
- @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_FUNC_FPCLASSIFY_AND_SIGNBIT)
+
+TRIO_PUBLIC_NAN int
+trio_fpclassify_and_signbit
+TRIO_ARGS2((number, is_negative),
+ double number,
+ int *is_negative)
{
-#if defined(TRIO_COMPILER_SUPPORTS_C99) && defined(isfinite)
- /*
- * C99 defines isfinite() as a macro.
- */
- return isfinite(number);
+ /* The TRIO_FUNC_xxx_FPCLASSIFY_AND_SIGNBIT macros are mutually exclusive */
-#elif defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB)
- /*
- * Microsoft Visual C++ and Borland C++ Builder use _finite().
- */
- return _finite(number);
+#if defined(TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT)
-#elif defined(USE_IEEE_754)
- /*
- * Examine IEEE 754 bit-pattern. For finity we do not care about the
- * mantissa.
- */
- int dummy;
+ return c99_fpclassify_and_signbit(number, is_negative);
- return (! trio_is_special_quantity(number, &dummy));
+#endif
+
+#if defined(TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT)
+
+ return decc_fpclassify_and_signbit(number, is_negative);
-#else
- /*
- * Fallback solution.
- */
- return ((trio_isinf(number) == 0) && (trio_isnan(number) == 0));
-
#endif
-}
+#if defined(TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT)
-/*
- * 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;
- }
+ return ms_fpclassify_and_signbit(number, is_negative);
-#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
+#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;
- }
+#if defined(TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT)
+
+ return hp_fpclassify_and_signbit(number, is_negative);
+
+#endif
+
+#if defined(TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT)
+
+ return xlc_fpclassify_and_signbit(number, is_negative);
+
+#endif
+
+#if defined(TRIO_FUNC_INTERNAL_FPCLASSIFY_AND_SIGNBIT)
-# else
/*
* Fallback solution.
*/
@@ -681,18 +788,19 @@ TRIO_ARGS2((number, is_negative),
* 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
+# if defined(TRIO_IEEE_754)
+ *is_negative = internal_is_negative(number);
+# else
*is_negative = TRIO_FALSE; /* FIXME */
-# endif
+# endif
return TRIO_FP_ZERO;
}
- if (trio_isnan(number)) {
+ if (internal_isnan(number)) {
*is_negative = TRIO_FALSE;
return TRIO_FP_NAN;
}
- if ((rc = trio_isinf(number))) {
+ rc = internal_isinf(number);
+ if (rc != 0) {
*is_negative = (rc == -1);
return TRIO_FP_INFINITE;
}
@@ -706,11 +814,86 @@ TRIO_ARGS2((number, is_negative),
}
*is_negative = (number < 0.0);
return TRIO_FP_NORMAL;
+
+#endif
+}
+
+#endif
+
+/**
+ Check for NaN.
+
+ @param number An arbitrary floating-point number.
+ @return Boolean value indicating whether or not the number is a NaN.
+*/
+#if defined(TRIO_FUNC_ISNAN)
+
+TRIO_PUBLIC_NAN int
+trio_isnan
+TRIO_ARGS1((number),
+ double number)
+{
+ int dummy;
-# endif
+ return (trio_fpclassify_and_signbit(number, &dummy) == TRIO_FP_NAN);
+}
+
+#endif
+
+/**
+ Check for infinity.
+
+ @param number An arbitrary floating-point number.
+ @return 1 if positive infinity, -1 if negative infinity, 0 otherwise.
+*/
+#if defined(TRIO_FUNC_ISINF)
+
+TRIO_PUBLIC_NAN int
+trio_isinf
+TRIO_ARGS1((number),
+ double number)
+{
+ int is_negative;
+
+ if (trio_fpclassify_and_signbit(number, &is_negative) == TRIO_FP_INFINITE)
+ {
+ return (is_negative) ? -1 : 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
#endif
+
+/**
+ Check for finity.
+
+ @param number An arbitrary floating-point number.
+ @return Boolean value indicating whether or not the number is a finite.
+*/
+#if defined(TRIO_FUNC_ISFINITE)
+
+TRIO_PUBLIC_NAN int
+trio_isfinite
+TRIO_ARGS1((number),
+ double number)
+{
+ int dummy;
+
+ switch (trio_fpclassify_and_signbit(number, &dummy))
+ {
+ case TRIO_FP_INFINITE:
+ case TRIO_FP_NAN:
+ return 0;
+ default:
+ return 1;
+ }
}
+#endif
+
/**
Examine the sign of a number.
@@ -718,7 +901,9 @@ TRIO_ARGS2((number, is_negative),
@return Boolean value indicating whether or not the number has the
sign bit set (i.e. is negative).
*/
-TRIO_PUBLIC int
+#if defined(TRIO_FUNC_SIGNBIT)
+
+TRIO_PUBLIC_NAN int
trio_signbit
TRIO_ARGS1((number),
double number)
@@ -729,13 +914,17 @@ TRIO_ARGS1((number),
return is_negative;
}
+#endif
+
/**
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
+#if defined(TRIO_FUNC_FPCLASSIFY)
+
+TRIO_PUBLIC_NAN int
trio_fpclassify
TRIO_ARGS1((number),
double number)
@@ -745,6 +934,173 @@ TRIO_ARGS1((number),
return trio_fpclassify_and_signbit(number, &dummy);
}
+#endif
+
+/**
+ Generate negative zero.
+
+ @return Floating-point representation of negative zero.
+*/
+#if defined(TRIO_FUNC_NZERO)
+
+TRIO_PUBLIC_NAN double
+trio_nzero(TRIO_NOARGS)
+{
+# if defined(TRIO_NZERO_IEEE_754)
+
+ return internal_make_double(ieee_754_negzero_array);
+
+# endif
+
+# if defined(TRIO_NZERO_FALLBACK)
+
+ TRIO_VOLATILE double zero = 0.0;
+
+ return -zero;
+
+# endif
+}
+
+#endif
+
+/**
+ Generate positive infinity.
+
+ @return Floating-point representation of positive infinity.
+*/
+#if defined(TRIO_FUNC_PINF)
+
+TRIO_PUBLIC_NAN double
+trio_pinf(TRIO_NOARGS)
+{
+ /* Cache the result */
+ static double pinf_value = 0.0;
+
+ if (pinf_value == 0.0) {
+
+# if defined(TRIO_PINF_C99_MACRO)
+
+ pinf_value = (double)INFINITY;
+
+# endif
+
+# if defined(TRIO_PINF_IEEE_754)
+
+ pinf_value = internal_make_double(ieee_754_infinity_array);
+
+# endif
+
+# if defined(TRIO_PINF_FALLBACK)
+ /*
+ * 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
+
+ pinf_value = HUGE_VAL;
+ if (HUGE_VAL == DBL_MAX) {
+ /* Force overflow */
+ pinf_value += HUGE_VAL;
+ }
+
+# if defined(TRIO_PLATFORM_UNIX)
+ signal(SIGFPE, signal_handler);
+# endif
+
+# endif
+ }
+ return pinf_value;
+}
+
+#endif
+
+/**
+ Generate negative infinity.
+
+ @return Floating-point value of negative infinity.
+*/
+#if defined(TRIO_FUNC_NINF)
+
+TRIO_PUBLIC_NAN double
+trio_ninf(TRIO_NOARGS)
+{
+ static double ninf_value = 0.0;
+
+ if (ninf_value == 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).
+ */
+ ninf_value = -trio_pinf();
+ }
+ return ninf_value;
+}
+
+#endif
+
+/**
+ Generate NaN.
+
+ @return Floating-point representation of NaN.
+*/
+#if defined(TRIO_FUNC_NAN)
+
+TRIO_PUBLIC_NAN double
+trio_nan(TRIO_NOARGS)
+{
+ /* Cache the result */
+ static double nan_value = 0.0;
+
+ if (nan_value == 0.0) {
+
+# if defined(TRIO_NAN_C99_FUNCTION) || defined(TRIO_PLATFORM_SYMBIAN)
+
+ nan_value = nan("");
+
+# endif
+
+# if defined(TRIO_NAN_C99_MACRO)
+
+ nan_value = (double)NAN;
+
+# endif
+
+# if defined(TRIO_NAN_IEEE_754)
+
+ nan_value = internal_make_double(ieee_754_qnan_array);
+
+# endif
+
+# if defined(TRIO_NAN_FALLBACK)
+ /*
+ * 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
+
+ nan_value = trio_pinf() / trio_pinf();
+
+# if defined(TRIO_PLATFORM_UNIX)
+ signal(SIGFPE, signal_handler);
+# endif
+
+# endif
+ }
+ return nan_value;
+}
+
+#endif
/** @} SpecialQuantities */
@@ -816,7 +1172,7 @@ int main(TRIO_NOARGS)
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",
+ printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n",
my_nan,
((unsigned char *)&my_nan)[0],
((unsigned char *)&my_nan)[1],
@@ -826,8 +1182,8 @@ int main(TRIO_NOARGS)
((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",
+ trio_isnan(my_nan), trio_isinf(my_nan), trio_isfinite(my_nan));
+ printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n",
my_pinf,
((unsigned char *)&my_pinf)[0],
((unsigned char *)&my_pinf)[1],
@@ -837,8 +1193,8 @@ int main(TRIO_NOARGS)
((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",
+ trio_isnan(my_pinf), trio_isinf(my_pinf), trio_isfinite(my_pinf));
+ printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n",
my_ninf,
((unsigned char *)&my_ninf)[0],
((unsigned char *)&my_ninf)[1],
@@ -848,7 +1204,7 @@ int main(TRIO_NOARGS)
((unsigned char *)&my_ninf)[5],
((unsigned char *)&my_ninf)[6],
((unsigned char *)&my_ninf)[7],
- trio_isnan(my_ninf), trio_isinf(my_ninf));
+ trio_isnan(my_ninf), trio_isinf(my_ninf), trio_isfinite(my_ninf));
# if defined(TRIO_PLATFORM_UNIX)
signal_handler = signal(SIGFPE, SIG_IGN);
@@ -862,7 +1218,7 @@ int main(TRIO_NOARGS)
signal(SIGFPE, signal_handler);
# endif
- printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d)\n",
+ printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n",
my_nan,
((unsigned char *)&my_nan)[0],
((unsigned char *)&my_nan)[1],
@@ -872,8 +1228,8 @@ int main(TRIO_NOARGS)
((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",
+ trio_isnan(my_nan), trio_isinf(my_nan), trio_isfinite(my_nan));
+ printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n",
my_pinf,
((unsigned char *)&my_pinf)[0],
((unsigned char *)&my_pinf)[1],
@@ -883,8 +1239,8 @@ int main(TRIO_NOARGS)
((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",
+ trio_isnan(my_pinf), trio_isinf(my_pinf), trio_isfinite(my_pinf));
+ printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n",
my_ninf,
((unsigned char *)&my_ninf)[0],
((unsigned char *)&my_ninf)[1],
@@ -894,7 +1250,7 @@ int main(TRIO_NOARGS)
((unsigned char *)&my_ninf)[5],
((unsigned char *)&my_ninf)[6],
((unsigned char *)&my_ninf)[7],
- trio_isnan(my_ninf), trio_isinf(my_ninf));
+ trio_isnan(my_ninf), trio_isinf(my_ninf), trio_isfinite(my_ninf));
return 0;
}
diff --git a/trio/trionan.h b/trio/trionan.h
index 3fbed375..a38b1cc2 100644
--- a/trio/trionan.h
+++ b/trio/trionan.h
@@ -1,6 +1,6 @@
/*************************************************************************
*
- * $Id: trionan.h,v 1.7 2002/05/04 14:26:44 breese Exp $
+ * $Id: trionan.h,v 1.9 2005/03/27 18:52:45 breese Exp $
*
* Copyright (C) 2001 Bjorn Reese <breese@users.sourceforge.net>
*
@@ -15,8 +15,8 @@
*
************************************************************************/
-#ifndef TRIO_NAN_H
-#define TRIO_NAN_H
+#ifndef TRIO_TRIONAN_H
+#define TRIO_TRIONAN_H
#include "triodef.h"
@@ -24,6 +24,13 @@
extern "C" {
#endif
+#if !defined(TRIO_PUBLIC_NAN)
+# if !defined(TRIO_PUBLIC)
+# define TRIO_PUBLIC
+# endif
+# define TRIO_PUBLIC_NAN TRIO_PUBLIC
+#endif
+
enum {
TRIO_FP_INFINITE,
TRIO_FP_NAN,
@@ -32,50 +39,145 @@ enum {
TRIO_FP_ZERO
};
+/*************************************************************************
+ * Dependencies
+ */
+
+#if defined(TRIO_EMBED_NAN)
+
+/*
+ * The application that trionan is embedded in must define which functions
+ * it uses.
+ *
+ * The following resolves internal dependencies.
+ */
+
+# if defined(TRIO_FUNC_ISNAN) \
+ || defined(TRIO_FUNC_ISINF)
+# if !defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT)
+# define TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT
+# endif
+# endif
+
+# if defined(TRIO_FUNC_NAN)
+# if !defined(TRIO_FUNC_PINF)
+# define TRIO_FUNC_PINF
+# endif
+# endif
+
+# if defined(TRIO_FUNC_NINF)
+# if !defined(TRIO_FUNC_PINF)
+# define TRIO_FUNC_PINF
+# endif
+# endif
+
+#else
+
+/*
+ * When trionan is not embedded all all functions are defined.
+ */
+
+# define TRIO_FUNC_NAN
+# define TRIO_FUNC_PINF
+# define TRIO_FUNC_NINF
+# define TRIO_FUNC_NZERO
+# define TRIO_FUNC_ISNAN
+# define TRIO_FUNC_ISINF
+# define TRIO_FUNC_ISFINITE
+# define TRIO_FUNC_SIGNBIT
+# define TRIO_FUNC_FPCLASSIFY
+# define TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT
+
+#endif
+
+/*************************************************************************
+ * Functions
+ */
+
/*
* Return NaN (Not-a-Number).
*/
-TRIO_PUBLIC double trio_nan TRIO_PROTO((void));
+#if defined(TRIO_FUNC_NAN)
+TRIO_PUBLIC_NAN double
+trio_nan
+TRIO_PROTO((void));
+#endif
/*
* Return positive infinity.
*/
-TRIO_PUBLIC double trio_pinf TRIO_PROTO((void));
+#if defined(TRIO_FUNC_PINF)
+TRIO_PUBLIC_NAN double
+trio_pinf
+TRIO_PROTO((void));
+#endif
/*
* Return negative infinity.
*/
-TRIO_PUBLIC double trio_ninf TRIO_PROTO((void));
-
+#if defined(TRIO_FUNC_NINF)
+TRIO_PUBLIC_NAN double
+trio_ninf
+TRIO_PROTO((void));
+#endif
+
/*
* Return negative zero.
*/
-TRIO_PUBLIC double trio_nzero TRIO_PROTO((TRIO_NOARGS));
+#if defined(TRIO_FUNC_NZERO)
+TRIO_PUBLIC_NAN double
+trio_nzero
+TRIO_PROTO((TRIO_NOARGS));
+#endif
/*
* If number is a NaN return non-zero, otherwise return zero.
*/
-TRIO_PUBLIC int trio_isnan TRIO_PROTO((double number));
+#if defined(TRIO_FUNC_ISNAN)
+TRIO_PUBLIC_NAN int
+trio_isnan
+TRIO_PROTO((double number));
+#endif
/*
* 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 defined(TRIO_FUNC_ISINF)
+TRIO_PUBLIC_NAN int
+trio_isinf
+TRIO_PROTO((double number));
+#endif
/*
* If number is finite return non-zero, otherwise return zero.
*/
-TRIO_PUBLIC int trio_isfinite TRIO_PROTO((double number));
+#if defined(TRIO_FUNC_ISFINITE)
+TRIO_PUBLIC_NAN int
+trio_isfinite
+TRIO_PROTO((double number));
+#endif
-TRIO_PUBLIC int trio_signbit TRIO_PROTO((double number));
+#if defined(TRIO_FUNC_SIGNBIT)
+TRIO_PUBLIC_NAN int
+trio_signbit
+TRIO_PROTO((double number));
+#endif
-TRIO_PUBLIC int trio_fpclassify TRIO_PROTO((double number));
+#if defined(TRIO_FUNC_FPCLASSIFY)
+TRIO_PUBLIC_NAN int
+trio_fpclassify
+TRIO_PROTO((double number));
+#endif
-TRIO_PUBLIC int trio_fpclassify_and_signbit TRIO_PROTO((double number, int *is_negative));
+#if defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT)
+TRIO_PUBLIC_NAN int
+trio_fpclassify_and_signbit
+TRIO_PROTO((double number, int *is_negative));
+#endif
#ifdef __cplusplus
}
#endif
-#endif /* TRIO_NAN_H */
+#endif /* TRIO_TRIONAN_H */
diff --git a/trio/triop.h b/trio/triop.h
index a0132528..bc8c5808 100644
--- a/trio/triop.h
+++ b/trio/triop.h
@@ -1,6 +1,6 @@
/*************************************************************************
*
- * $Id: triop.h,v 1.12 2002/06/23 11:58:06 breese Exp $
+ * $Id: triop.h,v 1.17 2009/05/21 12:52:14 breese Exp $
*
* Copyright (C) 2000 Bjorn Reese and Daniel Stenberg.
*
@@ -39,34 +39,350 @@
extern "C" {
#endif
-#ifndef TRIO_C99
+/*************************************************************************
+ * Supported standards
+ */
+
+/*
+ * TRIO_C99 (=0 or =1)
+ *
+ * Define this to 0 to disable C99 format specifier extensions, or
+ * define to 1 to enable them. The format specifiers that are
+ * disabled by this switch are labelled with [C99] in the format
+ * specifier documentation.
+ */
+#if !defined(TRIO_C99)
# define TRIO_C99 1
#endif
-#ifndef TRIO_BSD
+
+/*
+ * TRIO_BSD (=0 or =1)
+ *
+ * Define this to 0 to disable BSD format specifier extensions, or
+ * define to 1 to enable them. The format specifiers that are
+ * disabled by this switch are labelled with [BSD] in the format
+ * specifier documentation.
+ */
+#if !defined(TRIO_BSD)
# define TRIO_BSD 1
#endif
-#ifndef TRIO_GNU
+
+/*
+ * TRIO_GNU (=0 or =1)
+ *
+ * Define this to 0 to disable GNU format specifier extensions, or
+ * define to 1 to enable them. The format specifiers that are
+ * disabled by this switch are labelled with [GNU] in the format
+ * specifier documentation.
+ */
+#if !defined(TRIO_GNU)
# define TRIO_GNU 1
#endif
-#ifndef TRIO_MISC
+
+/*
+ * TRIO_MISC (=0 or =1)
+ *
+ * Define this to 0 to disable miscellaneous format specifier
+ * extensions, or define to 1 to enable them. The format specifiers
+ * that are disabled by this switch are labelled with [MISC] in the
+ * format specifier documentation.
+ */
+#if !defined(TRIO_MISC)
# define TRIO_MISC 1
#endif
-#ifndef TRIO_UNIX98
+
+/*
+ * TRIO_UNIX98 (=0 or =1)
+ *
+ * Define this to 0 to disable UNIX98 format specifier extensions,
+ * or define to 1 to enable them. The format specifiers that are
+ * disabled by this switch are labelled with [UNIX98] in the format
+ * specifier documentation.
+ */
+#if !defined(TRIO_UNIX98)
# define TRIO_UNIX98 1
#endif
-#ifndef TRIO_MICROSOFT
+
+/*
+ * TRIO_MICROSOFT (=0 or =1)
+ *
+ * Define this to 0 to disable Microsoft Visual C format specifier
+ * extensions, or define to 1 to enable them. The format specifiers
+ * that are disabled by this switch are labelled with [MSVC] in the
+ * format specifier documentation.
+ */
+#if !defined(TRIO_MICROSOFT)
# define TRIO_MICROSOFT 1
#endif
-#ifndef TRIO_EXTENSION
+
+/*
+ * TRIO_EXTENSION (=0 or =1)
+ *
+ * Define this to 0 to disable Trio-specific extensions, or define
+ * to 1 to enable them. This has two effects: it controls whether
+ * or not the Trio user-defined formating mechanism
+ * (trio_register() etc) is supported, and it enables or disables
+ * Trio's own format specifier extensions. The format specifiers
+ * that are disabled by this switch are labelled with [TRIO] in
+ * the format specifier documentation.
+ */
+#if !defined(TRIO_EXTENSION)
# define TRIO_EXTENSION 1
#endif
-#ifndef TRIO_WIDECHAR /* Does not work yet. Do not enable */
-# define TRIO_WIDECHAR 0
+
+/*
+ * TRIO_DEPRECATED (=0 or =1)
+ *
+ * Define this to 0 to disable deprecated functionality, or define
+ * to 1 to enable them.
+ */
+#if !defined(TRIO_DEPRECATED)
+# define TRIO_DEPRECATED 1
+#endif
+
+/*************************************************************************
+ * Features
+ */
+
+#if defined(TRIO_SNPRINTF_ONLY)
+# define TRIO_FEATURE_SCANF 0
+# define TRIO_FEATURE_FILE 0
+# define TRIO_FEATURE_STDIO 0
+# define TRIO_FEATURE_FD 0
+# define TRIO_FEATURE_DYNAMICSTRING 0
+# define TRIO_FEATURE_CLOSURE 0
+# define TRIO_FEATURE_STRERR 0
+# define TRIO_FEATURE_LOCALE 0
+# define TRIO_EMBED_NAN 1
+# define TRIO_EMBED_STRING 1
+#endif
+
+/*
+ * TRIO_FEATURE_SCANF (=0 or =1)
+ *
+ * Define this to 0 to disable all the scanf() variants, or define to 1
+ * to enable them.
+ */
+#if !defined(TRIO_FEATURE_SCANF)
+# define TRIO_FEATURE_SCANF 1
+#endif
+
+/*
+ * TRIO_FEATURE_FILE (=0 or =1)
+ *
+ * Define this to 0 to disable compilation of the trio_fprintf() and
+ * trio_fscanf() family of functions, or define to 1 to enable them.
+ *
+ * This may be useful on an embedded platform with no filesystem.
+ * Note that trio_printf() uses fwrite to write to stdout, so if you
+ * do not have an implementation of fwrite() at all then you must also
+ * define TRIO_FEATURE_STDIO to 0.
+ */
+#if !defined(TRIO_FEATURE_FILE)
+# define TRIO_FEATURE_FILE 1
+#endif
+
+/*
+ * TRIO_FEATURE_STDIO (=0 or =1)
+ *
+ * Define this to 0 to disable compilation of the trio_printf() and
+ * trio_scanf() family of functions, or define to 1 to enable them.
+ *
+ * This may be useful on an embedded platform with no standard I/O.
+ */
+#if !defined(TRIO_FEATURE_STDIO)
+# define TRIO_FEATURE_STDIO 1
+#endif
+
+/*
+ * TRIO_FEATURE_FD (=0 or =1)
+ *
+ * Define this to 0 to disable compilation of the trio_dprintf() and
+ * trio_dscanf() family of functions, or define to 1 to enable them.
+ *
+ * This may be useful on an embedded platform with no filesystem, or on
+ * a platform that supports file I/O using FILE* but not using raw file
+ * descriptors.
+ */
+#if !defined(TRIO_FEATURE_FD)
+# define TRIO_FEATURE_FD 1
+#endif
+
+/*
+ * TRIO_FEATURE_DYNAMICSTRING (=0 or =1)
+ *
+ * Define this to 0 to disable compilation of the trio_aprintf()
+ * family of functions, or define to 1 to enable them.
+ *
+ * If you define both this and TRIO_MINIMAL to 0, then Trio will never
+ * call malloc or free.
+ */
+#if !defined(TRIO_FEATURE_DYNAMICSTRING)
+# define TRIO_FEATURE_DYNAMICSTRING 1
#endif
-#ifndef TRIO_ERRORS
-# define TRIO_ERRORS 1
+
+/*
+ * TRIO_FEATURE_CLOSURE (=0 or =1)
+ *
+ * Define this to 0 to disable compilation of the trio_cprintf() and
+ * trio_cscanf() family of functions, or define to 1 to enable them.
+ *
+ * These functions are rarely needed. This saves a (small) amount of code.
+ */
+#if !defined(TRIO_FEATURE_CLOSURE)
+# define TRIO_FEATURE_CLOSURE 1
#endif
+/*
+ * TRIO_FEATURE_ERRORCODE (=0 or =1)
+ *
+ * Define this to 0 to return -1 from the print and scan function on
+ * error, or define to 1 to return a negative number with debugging
+ * information as part of the return code.
+ *
+ * If enabled, the return code will be a negative number, which encodes
+ * an error code and an error location. These can be decoded with the
+ * TRIO_ERROR_CODE and TRIO_ERROR_POSITION macros.
+ */
+#if defined(TRIO_ERRORS)
+# define TRIO_FEATURE_ERRORCODE TRIO_ERRORS
+#endif
+#if !defined(TRIO_FEATURE_ERRORCODE)
+# define TRIO_FEATURE_ERRORCODE 1
+#endif
+
+/*
+ * TRIO_FEATURE_STRERR (=0 or =1)
+ *
+ * Define this to 0 if you do not use trio_strerror(), or define to 1 if
+ * you do use it.
+ *
+ * This saves a (small) amount of code.
+ */
+#if !defined(TRIO_FEATURE_STRERR)
+# define TRIO_FEATURE_STRERR 1
+#endif
+
+/*
+ * TRIO_FEATURE_FLOAT (=0 or =1)
+ *
+ * Define this to 0 to disable all floating-point support, or define
+ * to 1 to enable it.
+ *
+ * This is useful in restricted embedded platforms that do not support
+ * floating-point. Obviously you cannot use floating-point format
+ * specifiers if you define this.
+ *
+ * Do not compile trionan.c if you disable this.
+ */
+#if !defined(TRIO_FEATURE_FLOAT)
+# define TRIO_FEATURE_FLOAT 1
+#endif
+
+/*
+ * TRIO_FEATURE_LOCALE (=0 or =1)
+ *
+ * Define this to 0 to disable customized locale support, or define
+ * to 1 to enable it.
+ *
+ * This saves a (small) amount of code.
+ */
+#if !defined(TRIO_FEATURE_LOCALE)
+# define TRIO_FEATURE_LOCALE 1
+#endif
+
+/*
+ * TRIO_MINIMAL
+ *
+ * Define this to disable building the public trionan.h and triostr.h.
+ * If you define this, then you must not compile trionan.c and triostr.c
+ * separately.
+ */
+#if defined(TRIO_MINIMAL)
+# if !defined(TRIO_EMBED_NAN)
+# define TRIO_EMBED_NAN
+# endif
+# if !defined(TRIO_EMBED_STRING)
+# define TRIO_EMBED_STRING
+# endif
+#endif
+
+/* Does not work yet. Do not enable */
+#ifndef TRIO_FEATURE_WIDECHAR
+# define TRIO_FEATURE_WIDECHAR 0
+#endif
+
+/*************************************************************************
+ * Mapping standards to internal features
+ */
+
+#if !defined(TRIO_FEATURE_HEXFLOAT)
+# define TRIO_FEATURE_HEXFLOAT (TRIO_C99 && TRIO_FEATURE_FLOAT)
+#endif
+
+#if !defined(TRIO_FEATURE_LONGDOUBLE)
+# define TRIO_FEATURE_LONGDOUBLE TRIO_FEATURE_FLOAT
+#endif
+
+#if !defined(TRIO_FEATURE_ERRNO)
+# define TRIO_FEATURE_ERRNO TRIO_GNU
+#endif
+
+#if !defined(TRIO_FEATURE_QUAD)
+# define TRIO_FEATURE_QUAD (TRIO_BSD || TRIO_GNU)
+#endif
+
+#if !defined(TRIO_FEATURE_SIZE_T)
+# define TRIO_FEATURE_SIZE_T TRIO_C99
+#endif
+
+#if !defined(TRIO_FEATURE_SIZE_T_UPPER)
+# define TRIO_FEATURE_SIZE_T_UPPER TRIO_GNU
+#endif
+
+#if !defined(TRIO_FEATURE_PTRDIFF_T)
+# define TRIO_FEATURE_PTRDIFF_T TRIO_C99
+#endif
+
+#if !defined(TRIO_FEATURE_INTMAX_T)
+# define TRIO_FEATURE_INTMAX_T TRIO_C99
+#endif
+
+#if !defined(TRIO_FEATURE_FIXED_SIZE)
+# define TRIO_FEATURE_FIXED_SIZE TRIO_MICROSOFT
+#endif
+
+#if !defined(TRIO_FEATURE_POSITIONAL)
+# define TRIO_FEATURE_POSITIONAL TRIO_UNIX98
+#endif
+
+#if !defined(TRIO_FEATURE_USER_DEFINED)
+# define TRIO_FEATURE_USER_DEFINED TRIO_EXTENSION
+#endif
+
+#if !defined(TRIO_FEATURE_BINARY)
+# define TRIO_FEATURE_BINARY TRIO_EXTENSION
+#endif
+
+#if !defined(TRIO_FEATURE_QUOTE)
+# define TRIO_FEATURE_QUOTE TRIO_EXTENSION
+#endif
+
+#if !defined(TRIO_FEATURE_STICKY)
+# define TRIO_FEATURE_STICKY TRIO_EXTENSION
+#endif
+
+#if !defined(TRIO_FEATURE_VARSIZE)
+# define TRIO_FEATURE_VARSIZE TRIO_EXTENSION
+#endif
+
+#if !defined(TRIO_FEATURE_ROUNDING)
+# define TRIO_FEATURE_ROUNDING TRIO_EXTENSION
+#endif
+
+/*************************************************************************
+ * Memory handling
+ */
#ifndef TRIO_MALLOC
# define TRIO_MALLOC(n) malloc(n)
#endif
@@ -117,15 +433,21 @@ 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));
+#if TRIO_FEATURE_QUOTE
int trio_get_quote TRIO_PROTO((trio_pointer_t ref)); /* ' */
void trio_set_quote TRIO_PROTO((trio_pointer_t ref, int is_quote));
+#endif
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
+#if TRIO_FEATURE_INTMAX_T
int trio_get_largest TRIO_PROTO((trio_pointer_t ref)); /* j */
void trio_set_largest TRIO_PROTO((trio_pointer_t ref, int is_largest));
+#endif
+#if TRIO_FEATURE_PTRDIFF_T
int trio_get_ptrdiff TRIO_PROTO((trio_pointer_t ref)); /* t */
void trio_set_ptrdiff TRIO_PROTO((trio_pointer_t ref, int is_ptrdiff));
+#endif
+#if TRIO_FEATURE_SIZE_T
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
@@ -140,7 +462,7 @@ 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_string TRIO_PROTO((trio_pointer_t ref, TRIO_CONST char *string));
void trio_print_pointer TRIO_PROTO((trio_pointer_t ref, trio_pointer_t pointer));
#ifdef __cplusplus
diff --git a/trio/triostr.c b/trio/triostr.c
index 199429e4..069e9225 100644
--- a/trio/triostr.c
+++ b/trio/triostr.c
@@ -1,6 +1,6 @@
/*************************************************************************
*
- * $Id: triostr.c,v 1.19 2003/03/01 15:34:02 breese Exp $
+ * $Id: triostr.c,v 1.34 2008/11/09 12:17:39 breese Exp $
*
* Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
*
@@ -19,23 +19,31 @@
* Include files
*/
+#if defined(HAVE_CONFIG_H)
+# include <config.h>
+#endif
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#include <math.h>
#include "triodef.h"
#include "triostr.h"
+#if defined(TRIO_FUNC_TO_LONG_DOUBLE)
+# define USE_MATH
+#endif
+#if defined(USE_MATH)
+# include <math.h>
+#endif
/*************************************************************************
* Definitions
*/
-#if !defined(TRIO_STRING_PUBLIC)
-# define TRIO_STRING_PUBLIC TRIO_PUBLIC
+#if !defined(TRIO_PUBLIC_STRING)
+# define TRIO_PUBLIC_STRING TRIO_PUBLIC
#endif
-#if !defined(TRIO_STRING_PRIVATE)
-# define TRIO_STRING_PRIVATE TRIO_PRIVATE
+#if !defined(TRIO_PRIVATE_STRING)
+# define TRIO_PRIVATE_STRING TRIO_PRIVATE
#endif
#if !defined(NULL)
@@ -52,16 +60,33 @@
# define BOOLEAN_T int
#endif
-#if defined(TRIO_COMPILER_SUPPORTS_C99)
-# define USE_STRTOD
-# define USE_STRTOF
-#elif defined(TRIO_COMPILER_MSVC)
-# define USE_STRTOD
+#if defined(USE_MATH)
+# if defined(PREDEF_STANDARD_C99)
+# if defined(TRIO_COMPILER_DECC)
+# if (TRIO_COMPILER_DECC - 0 > 80000000)
+/*
+ * The OSF/1 runtime that comes with the DECC compiler does not support
+ * hexfloats conversion.
+ */
+# define USE_STRTOD
+# define USE_STRTOF
+# endif
+# else
+# define USE_STRTOD
+# define USE_STRTOF
+# endif
+# else
+# if defined(TRIO_COMPILER_VISUALC)
+# define USE_STRTOD
+# endif
+#endif
#endif
#if defined(TRIO_PLATFORM_UNIX)
-# define USE_STRCASECMP
-# define USE_STRNCASECMP
+# if defined(PREDEF_STANDARD_UNIX95)
+# define USE_STRCASECMP
+# define USE_STRNCASECMP
+# endif
# if defined(TRIO_PLATFORM_SUNOS)
# define USE_SYS_ERRLIST
# else
@@ -71,14 +96,52 @@
# define strcasecmp(x,y) stricmp(x,y)
# define strncasecmp(x,y,n) strnicmp(x,y,n)
# endif
-#elif defined(TRIO_PLATFORM_WIN32)
+#endif
+
+#if defined(TRIO_PLATFORM_WIN32)
# define USE_STRCASECMP
-# define strcasecmp(x,y) strcmpi(x,y)
+# if defined(TRIO_PLATFORM_WINCE)
+# define strcasecmp(x,y) _stricmp(x,y)
+# else
+# define strcasecmp(x,y) strcmpi(x,y)
+# endif
#endif
-#if !(defined(TRIO_PLATFORM_SUNOS))
-# define USE_TOLOWER
-# define USE_TOUPPER
+#if !defined(HAVE_CONFIG_H)
+# if !(defined(TRIO_PLATFORM_SUNOS))
+# define HAVE_TOLOWER
+# define HAVE_TOUPPER
+# endif
+#endif
+
+#if defined(USE_MATH)
+# if !defined(HAVE_POWL)
+# if defined(PREDEF_STANDARD_C99) \
+ || defined(PREDEF_STANDARD_UNIX03)
+# define HAVE_POWL
+# else
+# if defined(TRIO_COMPILER_VISUALC)
+# if defined(powl)
+# define HAVE_POWL
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#if defined(HAVE_POWL)
+# define trio_powl(x,y) powl((x),(y))
+#else
+# define trio_powl(x,y) pow((double)(x),(double)(y))
+#endif
+
+#if defined(TRIO_FUNC_TO_UPPER) \
+ || (defined(TRIO_FUNC_EQUAL) && !defined(USE_STRCASECMP)) \
+ || (defined(TRIO_FUNC_EQUAL_MAX) && !defined(USE_STRNCASECMP)) \
+ || defined(TRIO_FUNC_MATCH) \
+ || defined(TRIO_FUNC_TO_LONG_DOUBLE) \
+ || defined(TRIO_FUNC_UPPER)
+# define TRIO_FUNC_INTERNAL_TO_UPPER
#endif
/*************************************************************************
@@ -96,8 +159,8 @@ struct _trio_string_t
* Constants
*/
-#if !defined(TRIO_MINIMAL)
-static TRIO_CONST char rcsid[] = "@(#)$Id: triostr.c,v 1.19 2003/03/01 15:34:02 breese Exp $";
+#if !defined(TRIO_EMBED_STRING)
+static TRIO_CONST char rcsid[] = "@(#)$Id: triostr.c,v 1.34 2008/11/09 12:17:39 breese Exp $";
#endif
/*************************************************************************
@@ -111,13 +174,154 @@ static TRIO_CONST char rcsid[] = "@(#)$Id: triostr.c,v 1.19 2003/03/01 15:34:02
@{
*/
+/*
+ * internal_duplicate_max
+ */
+#if defined(TRIO_FUNC_DUPLICATE) \
+ || defined(TRIO_FUNC_DUPLICATE_MAX) \
+ || defined(TRIO_FUNC_STRING_DUPLICATE) \
+ || defined(TRIO_FUNC_XSTRING_DUPLICATE)
+
+TRIO_PRIVATE_STRING char *
+internal_duplicate_max
+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;
+}
+
+#endif
+
+/*
+ * internal_string_alloc
+ */
+#if defined(TRIO_FUNC_STRING_CREATE) \
+ || defined(TRIO_FUNC_STRING_DUPLICATE) \
+ || defined(TRIO_FUNC_XSTRING_DUPLICATE)
+
+TRIO_PRIVATE_STRING trio_string_t *
+internal_string_alloc(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;
+}
+
+#endif
+
+/*
+ * internal_string_grow
+ *
+ * The size of the string will be increased by 'delta' characters. If
+ * 'delta' is zero, the size will be doubled.
+ */
+#if defined(TRIO_FUNC_STRING_CREATE) \
+ || defined(TRIO_FUNC_STRING_APPEND) \
+ || defined(TRIO_FUNC_XSTRING_APPEND) \
+ || defined(TRIO_FUNC_XSTRING_APPEND_CHAR)
+
+TRIO_PRIVATE_STRING BOOLEAN_T
+internal_string_grow
+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;
+}
+
+#endif
+
+/*
+ * internal_string_grow_to
+ *
+ * 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).
+ */
+#if defined(TRIO_FUNC_STRING_APPEND) \
+ || defined(TRIO_FUNC_XSTRING_APPEND)
+
+TRIO_PRIVATE_STRING BOOLEAN_T
+internal_string_grow_to
+TRIO_ARGS2((self, length),
+ trio_string_t *self,
+ size_t length)
+{
+ length++; /* Room for terminating zero */
+ return (self->allocated < length)
+ ? internal_string_grow(self, length - self->allocated)
+ : TRUE;
+}
+
+#endif
+
+#if defined(TRIO_FUNC_INTERNAL_TO_UPPER)
+
+TRIO_PRIVATE_STRING TRIO_INLINE int
+internal_to_upper
+TRIO_ARGS1((source),
+ int source)
+{
+# if defined(HAVE_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
+}
+
+#endif
+
+
/**
Create new string.
@param size Size of new string.
@return Pointer to string, or NULL if allocation failed.
*/
-TRIO_STRING_PUBLIC char *
+#if defined(TRIO_FUNC_CREATE)
+
+TRIO_PUBLIC_STRING char *
trio_create
TRIO_ARGS1((size),
size_t size)
@@ -125,13 +329,16 @@ TRIO_ARGS1((size),
return (char *)TRIO_MALLOC(size);
}
+#endif
/**
Destroy string.
@param string String to be freed.
*/
-TRIO_STRING_PUBLIC void
+#if defined(TRIO_FUNC_DESTROY)
+
+TRIO_PUBLIC_STRING void
trio_destroy
TRIO_ARGS1((string),
char *string)
@@ -142,14 +349,17 @@ TRIO_ARGS1((string),
}
}
+#endif
/**
Count the number of characters in a string.
@param string String to measure.
- @return Number of characters in @string.
+ @return Number of characters in @p string.
*/
-TRIO_STRING_PUBLIC size_t
+#if defined(TRIO_FUNC_LENGTH)
+
+TRIO_PUBLIC_STRING size_t
trio_length
TRIO_ARGS1((string),
TRIO_CONST char *string)
@@ -157,8 +367,35 @@ TRIO_ARGS1((string),
return strlen(string);
}
+#endif
+
+/**
+ Count at most @p max characters in a string.
+
+ @param string String to measure.
+ @param max Maximum number of characters to count.
+ @return The maximum value of @p max and number of characters in @p string.
+*/
+#if defined(TRIO_FUNC_LENGTH)
+
+TRIO_PUBLIC_STRING size_t
+trio_length_max
+TRIO_ARGS2((string, max),
+ TRIO_CONST char *string,
+ size_t max)
+{
+ size_t i;
+
+ for (i = 0; i < max; ++i)
+ {
+ if (string[i] == 0)
+ break;
+ }
+ return i;
+}
+
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Append @p source at the end of @p target.
@@ -172,7 +409,9 @@ TRIO_ARGS1((string),
result in a buffer overrun.
@post @p target will be zero terminated.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_APPEND)
+
+TRIO_PUBLIC_STRING int
trio_append
TRIO_ARGS2((target, source),
char *target,
@@ -183,9 +422,9 @@ TRIO_ARGS2((target, source),
return (strcat(target, source) != NULL);
}
-#endif /* !defined(TRIO_MINIMAL) */
-#if !defined(TRIO_MINIMAL)
+#endif
+
/**
Append at most @p max characters from @p source to @p target.
@@ -201,7 +440,9 @@ TRIO_ARGS2((target, source),
result in a buffer overrun.
@post @p target will be zero terminated.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_APPEND_MAX)
+
+TRIO_PUBLIC_STRING int
trio_append_max
TRIO_ARGS3((target, max, source),
char *target,
@@ -221,10 +462,9 @@ TRIO_ARGS3((target, max, source),
}
return TRUE;
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Determine if a string contains a substring.
@@ -232,7 +472,9 @@ TRIO_ARGS3((target, max, source),
@param substring String to be found.
@return Boolean value indicating success or failure.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_CONTAINS)
+
+TRIO_PUBLIC_STRING int
trio_contains
TRIO_ARGS2((string, substring),
TRIO_CONST char *string,
@@ -243,10 +485,9 @@ TRIO_ARGS2((string, substring),
return (0 != strstr(string, substring));
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Copy @p source to @p target.
@@ -260,7 +501,9 @@ TRIO_ARGS2((string, substring),
result in a buffer overrun.
@post @p target will be zero terminated.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_COPY)
+
+TRIO_PUBLIC_STRING int
trio_copy
TRIO_ARGS2((target, source),
char *target,
@@ -272,8 +515,8 @@ TRIO_ARGS2((target, source),
(void)strcpy(target, source);
return TRUE;
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
/**
Copy at most @p max characters from @p source to @p target.
@@ -289,7 +532,9 @@ TRIO_ARGS2((target, source),
result in a buffer overrun.
@post @p target will be zero terminated.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_COPY_MAX)
+
+TRIO_PUBLIC_STRING int
trio_copy_max
TRIO_ARGS3((target, max, source),
char *target,
@@ -305,30 +550,7 @@ TRIO_ARGS3((target, max, source),
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;
-}
-
+#endif
/**
Duplicate @p source.
@@ -338,16 +560,18 @@ TRIO_ARGS2((source, size),
@post @p target will be zero terminated.
*/
-TRIO_STRING_PUBLIC char *
+#if defined(TRIO_FUNC_DUPLICATE)
+
+TRIO_PUBLIC_STRING char *
trio_duplicate
TRIO_ARGS1((source),
TRIO_CONST char *source)
{
- return TrioDuplicateMax(source, trio_length(source));
+ return internal_duplicate_max(source, trio_length(source));
}
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Duplicate at most @p max characters of @p source.
@@ -357,10 +581,13 @@ TRIO_ARGS1((source),
@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)
+#if defined(TRIO_FUNC_DUPLICATE_MAX)
+
+TRIO_PUBLIC_STRING char *
+trio_duplicate_max
+TRIO_ARGS2((source, max),
+ TRIO_CONST char *source,
+ size_t max)
{
size_t length;
@@ -372,10 +599,10 @@ trio_duplicate_max TRIO_ARGS2((source, max),
{
length = max;
}
- return TrioDuplicateMax(source, length);
+ return internal_duplicate_max(source, length);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
/**
Compare if two strings are equal.
@@ -386,7 +613,9 @@ trio_duplicate_max TRIO_ARGS2((source, max),
Case-insensitive comparison.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_EQUAL)
+
+TRIO_PUBLIC_STRING int
trio_equal
TRIO_ARGS2((first, second),
TRIO_CONST char *first,
@@ -397,12 +626,12 @@ TRIO_ARGS2((first, second),
if ((first != NULL) && (second != NULL))
{
-#if defined(USE_STRCASECMP)
+# if defined(USE_STRCASECMP)
return (0 == strcasecmp(first, second));
-#else
+# else
while ((*first != NIL) && (*second != NIL))
{
- if (trio_to_upper(*first) != trio_to_upper(*second))
+ if (internal_to_upper(*first) != internal_to_upper(*second))
{
break;
}
@@ -410,11 +639,12 @@ TRIO_ARGS2((first, second),
second++;
}
return ((*first == NIL) && (*second == NIL));
-#endif
+# endif
}
return FALSE;
}
+#endif
/**
Compare if two strings are equal.
@@ -425,7 +655,9 @@ TRIO_ARGS2((first, second),
Case-sensitive comparison.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_EQUAL_CASE)
+
+TRIO_PUBLIC_STRING int
trio_equal_case
TRIO_ARGS2((first, second),
TRIO_CONST char *first,
@@ -441,8 +673,8 @@ TRIO_ARGS2((first, second),
return FALSE;
}
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Compare if two strings up until the first @p max characters are equal.
@@ -453,7 +685,9 @@ TRIO_ARGS2((first, second),
Case-sensitive comparison.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_EQUAL_CASE_MAX)
+
+TRIO_PUBLIC_STRING int
trio_equal_case_max
TRIO_ARGS3((first, max, second),
TRIO_CONST char *first,
@@ -469,8 +703,8 @@ TRIO_ARGS3((first, max, second),
}
return FALSE;
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
/**
Compare if two strings are equal.
@@ -481,7 +715,9 @@ TRIO_ARGS3((first, max, second),
Collating characters are considered equal.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_EQUAL_LOCALE)
+
+TRIO_PUBLIC_STRING int
trio_equal_locale
TRIO_ARGS2((first, second),
TRIO_CONST char *first,
@@ -490,13 +726,14 @@ TRIO_ARGS2((first, second),
assert(first);
assert(second);
-#if defined(LC_COLLATE)
+# if defined(LC_COLLATE)
return (strcoll(first, second) == 0);
-#else
+# else
return trio_equal(first, second);
-#endif
+# endif
}
+#endif
/**
Compare if two strings up until the first @p max characters are equal.
@@ -508,7 +745,9 @@ TRIO_ARGS2((first, second),
Case-insensitive comparison.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_EQUAL_MAX)
+
+TRIO_PUBLIC_STRING int
trio_equal_max
TRIO_ARGS3((first, max, second),
TRIO_CONST char *first,
@@ -520,14 +759,14 @@ TRIO_ARGS3((first, max, second),
if ((first != NULL) && (second != NULL))
{
-#if defined(USE_STRNCASECMP)
+# if defined(USE_STRNCASECMP)
return (0 == strncasecmp(first, second, max));
-#else
+# 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))
+ if (internal_to_upper(*first) != internal_to_upper(*second))
{
break;
}
@@ -536,11 +775,12 @@ TRIO_ARGS3((first, max, second),
cnt++;
}
return ((cnt == max) || ((*first == NIL) && (*second == NIL)));
-#endif
+# endif
}
return FALSE;
}
+#endif
/**
Provide a textual description of an error code (errno).
@@ -548,16 +788,19 @@ TRIO_ARGS3((first, max, second),
@param error_number Error number.
@return Textual description of @p error_number.
*/
-TRIO_STRING_PUBLIC TRIO_CONST char *
+#if defined(TRIO_FUNC_ERROR)
+
+TRIO_PUBLIC_STRING TRIO_CONST char *
trio_error
TRIO_ARGS1((error_number),
int error_number)
{
-#if defined(USE_STRERROR)
+# if defined(USE_STRERROR)
return strerror(error_number);
-#elif defined(USE_SYS_ERRLIST)
+# else
+# if defined(USE_SYS_ERRLIST)
extern char *sys_errlist[];
extern int sys_nerr;
@@ -566,15 +809,16 @@ TRIO_ARGS1((error_number),
? "unknown"
: sys_errlist[error_number];
-#else
+# else
return "unknown";
-
-#endif
+
+# endif
+# endif
}
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Format the date/time according to @p format.
@@ -587,7 +831,9 @@ TRIO_ARGS1((error_number),
The formatting string accepts the same specifiers as the standard C
function strftime.
*/
-TRIO_STRING_PUBLIC size_t
+#if defined(TRIO_FUNC_FORMAT_DATE_MAX)
+
+TRIO_PUBLIC_STRING size_t
trio_format_date_max
TRIO_ARGS4((target, max, format, datetime),
char *target,
@@ -599,13 +845,12 @@ TRIO_ARGS4((target, max, format, datetime),
assert(format);
assert(datetime);
assert(max > 0);
-
+
return strftime(target, max, format, datetime);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Calculate a hash value for a string.
@@ -616,7 +861,9 @@ TRIO_ARGS4((target, max, format, datetime),
@p type can be one of the following
@li @c TRIO_HASH_PLAIN Plain hash function.
*/
-TRIO_STRING_PUBLIC unsigned long
+#if defined(TRIO_FUNC_HASH)
+
+TRIO_PUBLIC_STRING unsigned long
trio_hash
TRIO_ARGS2((string, type),
TRIO_CONST char *string,
@@ -642,18 +889,19 @@ TRIO_ARGS2((string, type),
}
return value;
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#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.
+ @return A pointer to the found character, or NULL if character was not found.
*/
-TRIO_STRING_PUBLIC char *
+#if defined(TRIO_FUNC_INDEX)
+
+TRIO_PUBLIC_STRING char *
trio_index
TRIO_ARGS2((string, character),
TRIO_CONST char *string,
@@ -663,18 +911,19 @@ TRIO_ARGS2((string, character),
return strchr(string, character);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#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.
+ @return A pointer to the found character, or NULL if character was not found.
*/
-TRIO_STRING_PUBLIC char *
+#if defined(TRIO_FUNC_INDEX_LAST)
+
+TRIO_PUBLIC_STRING char *
trio_index_last
TRIO_ARGS2((string, character),
TRIO_CONST char *string,
@@ -684,17 +933,18 @@ TRIO_ARGS2((string, character),
return strchr(string, character);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#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
+#if defined(TRIO_FUNC_LOWER)
+
+TRIO_PUBLIC_STRING int
trio_lower
TRIO_ARGS1((target),
char *target)
@@ -703,10 +953,9 @@ TRIO_ARGS1((target),
return trio_span_function(target, target, trio_to_lower);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Compare two strings using wildcards.
@@ -720,7 +969,9 @@ TRIO_ARGS1((target),
@li @c * Match any number of characters.
@li @c ? Match a single character.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_MATCH)
+
+TRIO_PUBLIC_STRING int
trio_match
TRIO_ARGS2((string, pattern),
TRIO_CONST char *string,
@@ -735,7 +986,7 @@ TRIO_ARGS2((string, pattern),
{
return (NIL == *pattern);
}
- if ((trio_to_upper((int)*string) != trio_to_upper((int)*pattern))
+ if ((internal_to_upper((int)*string) != internal_to_upper((int)*pattern))
&& ('?' != *pattern))
{
return FALSE;
@@ -756,10 +1007,9 @@ TRIO_ARGS2((string, pattern),
return FALSE;
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Compare two strings using wildcards.
@@ -773,7 +1023,9 @@ TRIO_ARGS2((string, pattern),
@li @c * Match any number of characters.
@li @c ? Match a single character.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_MATCH_CASE)
+
+TRIO_PUBLIC_STRING int
trio_match_case
TRIO_ARGS2((string, pattern),
TRIO_CONST char *string,
@@ -809,10 +1061,9 @@ TRIO_ARGS2((string, pattern),
return FALSE;
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Execute a function on each character in string.
@@ -821,7 +1072,9 @@ TRIO_ARGS2((string, pattern),
@param Function Function to be executed.
@return Number of processed characters.
*/
-TRIO_STRING_PUBLIC size_t
+#if defined(TRIO_FUNC_SPAN_FUNCTION)
+
+TRIO_PUBLIC_STRING size_t
trio_span_function
TRIO_ARGS3((target, source, Function),
char *target,
@@ -841,10 +1094,9 @@ TRIO_ARGS3((target, source, Function),
}
return count;
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Search for a substring in a string.
@@ -853,7 +1105,9 @@ TRIO_ARGS3((target, source, Function),
@return Pointer to first occurrence of @p substring in @p string, or NULL
if no match was found.
*/
-TRIO_STRING_PUBLIC char *
+#if defined(TRIO_FUNC_SUBSTRING)
+
+TRIO_PUBLIC_STRING char *
trio_substring
TRIO_ARGS2((string, substring),
TRIO_CONST char *string,
@@ -864,10 +1118,9 @@ TRIO_ARGS2((string, substring),
return strstr(string, substring);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Search for a substring in the first @p max characters of a string.
@@ -877,7 +1130,9 @@ TRIO_ARGS2((string, substring),
@return Pointer to first occurrence of @p substring in @p string, or NULL
if no match was found.
*/
-TRIO_STRING_PUBLIC char *
+#if defined(TRIO_FUNC_SUBSTRING_MAX)
+
+TRIO_PUBLIC_STRING char *
trio_substring_max
TRIO_ARGS3((string, max, substring),
TRIO_CONST char *string,
@@ -905,20 +1160,21 @@ TRIO_ARGS3((string, max, substring),
}
return result;
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Tokenize string.
@param string String to be tokenized.
- @param tokens String containing list of delimiting characters.
+ @param delimiters String containing list of delimiting characters.
@return Start of new token.
@warning @p string will be destroyed.
*/
-TRIO_STRING_PUBLIC char *
+#if defined(TRIO_FUNC_TOKENIZE)
+
+TRIO_PUBLIC_STRING char *
trio_tokenize
TRIO_ARGS2((string, delimiters),
char *string,
@@ -928,8 +1184,8 @@ TRIO_ARGS2((string, delimiters),
return strtok(string, delimiters);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
/**
Convert string to floating-point number.
@@ -952,16 +1208,18 @@ TRIO_ARGS2((string, delimiters),
decimal_point ::= '.'
@endverbatim
*/
+#if defined(TRIO_FUNC_TO_LONG_DOUBLE)
+
/* FIXME: Add EBNF for hex-floats */
-TRIO_STRING_PUBLIC trio_long_double_t
+TRIO_PUBLIC_STRING trio_long_double_t
trio_to_long_double
TRIO_ARGS2((source, endp),
TRIO_CONST char *source,
char **endp)
{
-#if defined(USE_STRTOLD)
+# if defined(USE_STRTOLD)
return strtold(source, endp);
-#else
+# else
int isNegative = FALSE;
int isExponentNegative = FALSE;
trio_long_double_t integer = 0.0;
@@ -981,7 +1239,7 @@ TRIO_ARGS2((source, endp),
integer *= base;
integer += (isdigit((int)*source)
? (*source - '0')
- : 10 + (trio_to_upper((int)*source) - 'A'));
+ : 10 + (internal_to_upper((int)*source) - 'A'));
source++;
}
if (*source == '.')
@@ -992,7 +1250,7 @@ TRIO_ARGS2((source, endp),
fracdiv /= base;
fraction += fracdiv * (isdigit((int)*source)
? (*source - '0')
- : 10 + (trio_to_upper((int)*source) - 'A'));
+ : 10 + (internal_to_upper((int)*source) - 'A'));
source++;
}
if ((*source == 'p') || (*source == 'P'))
@@ -1042,10 +1300,10 @@ TRIO_ARGS2((source, endp),
}
if ((*source == 'e')
|| (*source == 'E')
-#if TRIO_MICROSOFT
+# if TRIO_MICROSOFT
|| (*source == 'd')
|| (*source == 'D')
-#endif
+# endif
)
{
source++; /* Skip exponential indicator */
@@ -1065,9 +1323,9 @@ TRIO_ARGS2((source, endp),
if (exponent != 0)
{
if (isExponentNegative)
- value /= pow(base, (double)exponent);
+ value /= trio_powl(base, (trio_long_double_t)exponent);
else
- value *= pow(base, (double)exponent);
+ value *= trio_powl(base, (trio_long_double_t)exponent);
}
if (isNegative)
value = -value;
@@ -1075,9 +1333,10 @@ TRIO_ARGS2((source, endp),
if (endp)
*endp = (char *)source;
return value;
-#endif
+# endif
}
+#endif
/**
Convert string to floating-point number.
@@ -1088,7 +1347,9 @@ TRIO_ARGS2((source, endp),
See @ref trio_to_long_double.
*/
-TRIO_STRING_PUBLIC double
+#if defined(TRIO_FUNC_TO_DOUBLE)
+
+TRIO_PUBLIC_STRING double
trio_to_double
TRIO_ARGS2((source, endp),
TRIO_CONST char *source,
@@ -1101,7 +1362,8 @@ TRIO_ARGS2((source, endp),
#endif
}
-#if !defined(TRIO_MINIMAL)
+#endif
+
/**
Convert string to floating-point number.
@@ -1111,20 +1373,22 @@ TRIO_ARGS2((source, endp),
See @ref trio_to_long_double.
*/
-TRIO_STRING_PUBLIC float
+#if defined(TRIO_FUNC_TO_FLOAT)
+
+TRIO_PUBLIC_STRING float
trio_to_float
TRIO_ARGS2((source, endp),
TRIO_CONST char *source,
char **endp)
{
-#if defined(USE_STRTOF)
+# if defined(USE_STRTOF)
return strtof(source, endp);
-#else
+# else
return (float)trio_to_long_double(source, endp);
-#endif
+# endif
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
/**
Convert string to signed integer.
@@ -1133,7 +1397,9 @@ TRIO_ARGS2((source, endp),
@param endp Pointer to end of converted string.
@param base Radix number of number.
*/
-TRIO_STRING_PUBLIC long
+#if defined(TRIO_FUNC_TO_LONG)
+
+TRIO_PUBLIC_STRING long
trio_to_long
TRIO_ARGS3((string, endp, base),
TRIO_CONST char *string,
@@ -1146,35 +1412,37 @@ TRIO_ARGS3((string, endp, base),
return strtol(string, endp, base);
}
+#endif
-#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
+#if defined(TRIO_FUNC_TO_LOWER)
+
+TRIO_PUBLIC_STRING int
trio_to_lower
TRIO_ARGS1((source),
int source)
{
-#if defined(USE_TOLOWER)
+# if defined(HAVE_TOLOWER)
return tolower(source);
-#else
+# else
/* Does not handle locales or non-contiguous alphabetic characters */
return ((source >= (int)'A') && (source <= (int)'Z'))
? source - 'A' + 'a'
: source;
-#endif
+# endif
}
-#endif /* !defined(TRIO_MINIMAL) */
-#if !defined(TRIO_MINIMAL)
+#endif
+
/**
Convert string to unsigned integer.
@@ -1182,7 +1450,9 @@ TRIO_ARGS1((source),
@param endp Pointer to end of converted string.
@param base Radix number of number.
*/
-TRIO_STRING_PUBLIC unsigned long
+#if defined(TRIO_FUNC_TO_UNSIGNED_LONG)
+
+TRIO_PUBLIC_STRING unsigned long
trio_to_unsigned_long
TRIO_ARGS3((string, endp, base),
TRIO_CONST char *string,
@@ -1194,8 +1464,8 @@ TRIO_ARGS3((string, endp, base),
return strtoul(string, endp, base);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
/**
Convert one alphabetic letter to upper-case.
@@ -1203,43 +1473,37 @@ TRIO_ARGS3((string, endp, base),
@param source The letter to be converted.
@return The converted letter.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_TO_UPPER)
+
+TRIO_PUBLIC_STRING int
trio_to_upper
TRIO_ARGS1((source),
int source)
{
-#if defined(USE_TOUPPER)
-
- return toupper(source);
-
-#else
+ return internal_to_upper(source);
+}
- /* 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
+#if defined(TRIO_FUNC_UPPER)
+
+TRIO_PUBLIC_STRING int
trio_upper
TRIO_ARGS1((target),
char *target)
{
assert(target);
- return trio_span_function(target, target, trio_to_upper);
+ return trio_span_function(target, target, internal_to_upper);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
/** @} End of StaticStrings */
@@ -1255,96 +1519,25 @@ TRIO_ARGS1((target),
@{
*/
-/*
- * 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 *
+#if defined(TRIO_FUNC_STRING_CREATE)
+
+TRIO_PUBLIC_STRING trio_string_t *
trio_string_create
TRIO_ARGS1((initial_size),
int initial_size)
{
trio_string_t *self;
- self = TrioStringAlloc();
+ self = internal_string_alloc();
if (self)
{
- if (TrioStringGrow(self,
+ if (internal_string_grow(self,
(size_t)((initial_size > 0) ? initial_size : 1)))
{
self->content[0] = (char)0;
@@ -1358,15 +1551,17 @@ TRIO_ARGS1((initial_size),
}
return self;
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
/**
Deallocate the dynamic string and its contents.
@param self Dynamic string
*/
-TRIO_STRING_PUBLIC void
+#if defined(TRIO_FUNC_STRING_DESTROY)
+
+TRIO_PUBLIC_STRING void
trio_string_destroy
TRIO_ARGS1((self),
trio_string_t *self)
@@ -1380,8 +1575,8 @@ TRIO_ARGS1((self),
}
}
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Get a pointer to the content.
@@ -1396,7 +1591,9 @@ TRIO_ARGS1((self),
number of characters from the ending of the string, starting at the
terminating zero, is returned.
*/
-TRIO_STRING_PUBLIC char *
+#if defined(TRIO_FUNCT_STRING_GET)
+
+TRIO_PUBLIC_STRING char *
trio_string_get
TRIO_ARGS2((self, offset),
trio_string_t *self,
@@ -1431,8 +1628,8 @@ TRIO_ARGS2((self, offset),
}
return result;
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
/**
Extract the content.
@@ -1443,7 +1640,9 @@ TRIO_ARGS2((self, offset),
The content is removed from the dynamic string. This enables destruction
of the dynamic string without deallocation of the content.
*/
-TRIO_STRING_PUBLIC char *
+#if defined(TRIO_FUNC_STRING_EXTRACT)
+
+TRIO_PUBLIC_STRING char *
trio_string_extract
TRIO_ARGS1((self),
trio_string_t *self)
@@ -1459,8 +1658,8 @@ TRIO_ARGS1((self),
return result;
}
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Set the content of the dynamic string.
@@ -1474,7 +1673,9 @@ TRIO_ARGS1((self),
This function will make a copy of @p buffer.
You are responsible for deallocating @p buffer yourself.
*/
-TRIO_STRING_PUBLIC void
+#if defined(TRIO_FUNC_XSTRING_SET)
+
+TRIO_PUBLIC_STRING void
trio_xstring_set
TRIO_ARGS2((self, buffer),
trio_string_t *self,
@@ -1485,13 +1686,15 @@ TRIO_ARGS2((self, buffer),
trio_destroy(self->content);
self->content = trio_duplicate(buffer);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
/*
* trio_string_size
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_STRING_SIZE)
+
+TRIO_PUBLIC_STRING int
trio_string_size
TRIO_ARGS1((self),
trio_string_t *self)
@@ -1501,11 +1704,14 @@ TRIO_ARGS1((self),
return self->allocated;
}
+#endif
/*
* trio_string_terminate
*/
-TRIO_STRING_PUBLIC void
+#if defined(TRIO_FUNC_STRING_TERMINATE)
+
+TRIO_PUBLIC_STRING void
trio_string_terminate
TRIO_ARGS1((self),
trio_string_t *self)
@@ -1513,8 +1719,8 @@ TRIO_ARGS1((self),
trio_xstring_append_char(self, 0);
}
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Append the second string to the first.
@@ -1522,7 +1728,9 @@ TRIO_ARGS1((self),
@param other Dynamic string to copy from.
@return Boolean value indicating success or failure.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_STRING_APPEND)
+
+TRIO_PUBLIC_STRING int
trio_string_append
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -1534,7 +1742,7 @@ TRIO_ARGS2((self, other),
assert(other);
length = self->length + other->length;
- if (!TrioStringGrowTo(self, length))
+ if (!internal_string_grow_to(self, length))
goto error;
trio_copy(&self->content[self->length], other->content);
self->length = length;
@@ -1543,14 +1751,16 @@ TRIO_ARGS2((self, other),
error:
return FALSE;
}
-#endif /* !defined(TRIO_MINIMAL) */
+
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_xstring_append
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_XSTRING_APPEND)
+
+TRIO_PUBLIC_STRING int
trio_xstring_append
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -1562,7 +1772,7 @@ TRIO_ARGS2((self, other),
assert(other);
length = self->length + trio_length(other);
- if (!TrioStringGrowTo(self, length))
+ if (!internal_string_grow_to(self, length))
goto error;
trio_copy(&self->content[self->length], other);
self->length = length;
@@ -1571,13 +1781,15 @@ TRIO_ARGS2((self, other),
error:
return FALSE;
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
/*
* trio_xstring_append_char
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_XSTRING_APPEND_CHAR)
+
+TRIO_PUBLIC_STRING int
trio_xstring_append_char
TRIO_ARGS2((self, character),
trio_string_t *self,
@@ -1587,7 +1799,7 @@ TRIO_ARGS2((self, character),
if ((int)self->length >= trio_string_size(self))
{
- if (!TrioStringGrow(self, 0))
+ if (!internal_string_grow(self, 0))
goto error;
}
self->content[self->length] = character;
@@ -1598,8 +1810,8 @@ TRIO_ARGS2((self, character),
return FALSE;
}
+#endif
-#if !defined(TRIO_MINIMAL)
/**
Search for the first occurrence of second parameter in the first.
@@ -1607,7 +1819,9 @@ TRIO_ARGS2((self, character),
@param other Dynamic string to copy from.
@return Boolean value indicating success or failure.
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_STRING_CONTAINS)
+
+TRIO_PUBLIC_STRING int
trio_string_contains
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -1618,14 +1832,15 @@ TRIO_ARGS2((self, other),
return trio_contains(self->content, other->content);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_xstring_contains
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_XSTRING_CONTAINS)
+
+TRIO_PUBLIC_STRING int
trio_xstring_contains
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -1636,14 +1851,15 @@ TRIO_ARGS2((self, other),
return trio_contains(self->content, other);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_copy
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_STRING_COPY)
+
+TRIO_PUBLIC_STRING int
trio_string_copy
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -1655,14 +1871,16 @@ TRIO_ARGS2((self, other),
self->length = 0;
return trio_string_append(self, other);
}
-#endif /* !defined(TRIO_MINIMAL) */
+
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_xstring_copy
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_XSTRING_COPY)
+
+TRIO_PUBLIC_STRING int
trio_xstring_copy
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -1674,14 +1892,15 @@ TRIO_ARGS2((self, other),
self->length = 0;
return trio_xstring_append(self, other);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_duplicate
*/
-TRIO_STRING_PUBLIC trio_string_t *
+#if defined(TRIO_FUNC_STRING_DUPLICATE)
+
+TRIO_PUBLIC_STRING trio_string_t *
trio_string_duplicate
TRIO_ARGS1((other),
trio_string_t *other)
@@ -1690,10 +1909,10 @@ TRIO_ARGS1((other),
assert(other);
- self = TrioStringAlloc();
+ self = internal_string_alloc();
if (self)
{
- self->content = TrioDuplicateMax(other->content, other->length);
+ self->content = internal_duplicate_max(other->content, other->length);
if (self->content)
{
self->length = other->length;
@@ -1706,13 +1925,15 @@ TRIO_ARGS1((other),
}
return self;
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
/*
* trio_xstring_duplicate
*/
-TRIO_STRING_PUBLIC trio_string_t *
+#if defined(TRIO_FUNC_XSTRING_DUPLICATE)
+
+TRIO_PUBLIC_STRING trio_string_t *
trio_xstring_duplicate
TRIO_ARGS1((other),
TRIO_CONST char *other)
@@ -1721,10 +1942,10 @@ TRIO_ARGS1((other),
assert(other);
- self = TrioStringAlloc();
+ self = internal_string_alloc();
if (self)
{
- self->content = TrioDuplicateMax(other, trio_length(other));
+ self->content = internal_duplicate_max(other, trio_length(other));
if (self->content)
{
self->length = trio_length(self->content);
@@ -1738,12 +1959,14 @@ TRIO_ARGS1((other),
return self;
}
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_equal
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_STRING_EQUAL)
+
+TRIO_PUBLIC_STRING int
trio_string_equal
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -1754,14 +1977,16 @@ TRIO_ARGS2((self, other),
return trio_equal(self->content, other->content);
}
-#endif /* !defined(TRIO_MINIMAL) */
+
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_xstring_equal
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_XSTRING_EQUAL)
+
+TRIO_PUBLIC_STRING int
trio_xstring_equal
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -1772,14 +1997,15 @@ TRIO_ARGS2((self, other),
return trio_equal(self->content, other);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_equal_max
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_STRING_EQUAL_MAX)
+
+TRIO_PUBLIC_STRING int
trio_string_equal_max
TRIO_ARGS3((self, max, other),
trio_string_t *self,
@@ -1791,14 +2017,14 @@ TRIO_ARGS3((self, max, other),
return trio_equal_max(self->content, max, other->content);
}
-#endif /* !defined(TRIO_MINIMAL) */
-
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_xstring_equal_max
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_XSTRING_EQUAL_MAX)
+
+TRIO_PUBLIC_STRING int
trio_xstring_equal_max
TRIO_ARGS3((self, max, other),
trio_string_t *self,
@@ -1810,14 +2036,15 @@ TRIO_ARGS3((self, max, other),
return trio_equal_max(self->content, max, other);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_equal_case
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_STRING_EQUAL_CASE)
+
+TRIO_PUBLIC_STRING int
trio_string_equal_case
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -1828,14 +2055,15 @@ TRIO_ARGS2((self, other),
return trio_equal_case(self->content, other->content);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_xstring_equal_case
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_XSTRING_EQUAL_CASE)
+
+TRIO_PUBLIC_STRING int
trio_xstring_equal_case
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -1846,14 +2074,15 @@ TRIO_ARGS2((self, other),
return trio_equal_case(self->content, other);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_equal_case_max
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_STRING_EQUAL_CASE_MAX)
+
+TRIO_PUBLIC_STRING int
trio_string_equal_case_max
TRIO_ARGS3((self, max, other),
trio_string_t *self,
@@ -1865,14 +2094,15 @@ TRIO_ARGS3((self, max, other),
return trio_equal_case_max(self->content, max, other->content);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_xstring_equal_case_max
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_XSTRING_EQUAL_CASE_MAX)
+
+TRIO_PUBLIC_STRING int
trio_xstring_equal_case_max
TRIO_ARGS3((self, max, other),
trio_string_t *self,
@@ -1884,14 +2114,15 @@ TRIO_ARGS3((self, max, other),
return trio_equal_case_max(self->content, max, other);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_format_data_max
*/
-TRIO_STRING_PUBLIC size_t
+#if defined(TRIO_FUNC_STRING_FORMAT_DATE_MAX)
+
+TRIO_PUBLIC_STRING size_t
trio_string_format_date_max
TRIO_ARGS4((self, max, format, datetime),
trio_string_t *self,
@@ -1903,14 +2134,15 @@ TRIO_ARGS4((self, max, format, datetime),
return trio_format_date_max(self->content, max, format, datetime);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_index
*/
-TRIO_STRING_PUBLIC char *
+#if defined(TRIO_FUNC_STRING_INDEX)
+
+TRIO_PUBLIC_STRING char *
trio_string_index
TRIO_ARGS2((self, character),
trio_string_t *self,
@@ -1920,14 +2152,15 @@ TRIO_ARGS2((self, character),
return trio_index(self->content, character);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_index_last
*/
-TRIO_STRING_PUBLIC char *
+#if defined(TRIO_FUNC_STRING_INDEX_LAST)
+
+TRIO_PUBLIC_STRING char *
trio_string_index_last
TRIO_ARGS2((self, character),
trio_string_t *self,
@@ -1937,14 +2170,15 @@ TRIO_ARGS2((self, character),
return trio_index_last(self->content, character);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_length
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_STRING_LENGTH)
+
+TRIO_PUBLIC_STRING int
trio_string_length
TRIO_ARGS1((self),
trio_string_t *self)
@@ -1957,14 +2191,15 @@ TRIO_ARGS1((self),
}
return self->length;
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_lower
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_STRING_LOWER)
+
+TRIO_PUBLIC_STRING int
trio_string_lower
TRIO_ARGS1((self),
trio_string_t *self)
@@ -1973,14 +2208,15 @@ TRIO_ARGS1((self),
return trio_lower(self->content);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_match
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_STRING_MATCH)
+
+TRIO_PUBLIC_STRING int
trio_string_match
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -1991,14 +2227,15 @@ TRIO_ARGS2((self, other),
return trio_match(self->content, other->content);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_xstring_match
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_XSTRING_MATCH)
+
+TRIO_PUBLIC_STRING int
trio_xstring_match
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -2009,14 +2246,15 @@ TRIO_ARGS2((self, other),
return trio_match(self->content, other);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_match_case
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_STRING_MATCH_CASE)
+
+TRIO_PUBLIC_STRING int
trio_string_match_case
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -2027,14 +2265,15 @@ TRIO_ARGS2((self, other),
return trio_match_case(self->content, other->content);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_xstring_match_case
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_XSTRING_MATCH_CASE)
+
+TRIO_PUBLIC_STRING int
trio_xstring_match_case
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -2045,14 +2284,15 @@ TRIO_ARGS2((self, other),
return trio_match_case(self->content, other);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_substring
*/
-TRIO_STRING_PUBLIC char *
+#if defined(TRIO_FUNC_STRING_SUBSTRING)
+
+TRIO_PUBLIC_STRING char *
trio_string_substring
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -2063,14 +2303,15 @@ TRIO_ARGS2((self, other),
return trio_substring(self->content, other->content);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_xstring_substring
*/
-TRIO_STRING_PUBLIC char *
+#if defined(TRIO_FUNC_XSTRING_SUBSTRING)
+
+TRIO_PUBLIC_STRING char *
trio_xstring_substring
TRIO_ARGS2((self, other),
trio_string_t *self,
@@ -2081,14 +2322,15 @@ TRIO_ARGS2((self, other),
return trio_substring(self->content, other);
}
-#endif /* !defined(TRIO_MINIMAL) */
+#endif
-#if !defined(TRIO_MINIMAL)
/*
* trio_string_upper
*/
-TRIO_STRING_PUBLIC int
+#if defined(TRIO_FUNC_STRING_UPPER)
+
+TRIO_PUBLIC_STRING int
trio_string_upper
TRIO_ARGS1((self),
trio_string_t *self)
@@ -2097,6 +2339,7 @@ TRIO_ARGS1((self),
return trio_upper(self->content);
}
-#endif /* !defined(TRIO_MINIMAL) */
+
+#endif
/** @} End of DynamicStrings */
diff --git a/trio/triostr.h b/trio/triostr.h
index edec4264..357d192b 100644
--- a/trio/triostr.h
+++ b/trio/triostr.h
@@ -1,6 +1,6 @@
/*************************************************************************
*
- * $Id: triostr.h,v 1.10 2003/03/01 15:34:01 breese Exp $
+ * $Id: triostr.h,v 1.17 2007/11/11 13:21:49 breese Exp $
*
* Copyright (C) 2001 Bjorn Reese and Daniel Stenberg.
*
@@ -18,6 +18,10 @@
#ifndef TRIO_TRIOSTR_H
#define TRIO_TRIOSTR_H
+/*
+ * Documentation is located in triostr.c
+ */
+
#include <assert.h>
#include <stdlib.h>
#include <string.h>
@@ -25,63 +29,417 @@
#include "triodef.h"
#include "triop.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
enum {
TRIO_HASH_NONE = 0,
TRIO_HASH_PLAIN,
TRIO_HASH_TWOSIGNED
};
-#if !defined(TRIO_STRING_PUBLIC)
+#if !defined(TRIO_PUBLIC_STRING)
# if !defined(TRIO_PUBLIC)
# define TRIO_PUBLIC
# endif
-# define TRIO_STRING_PUBLIC TRIO_PUBLIC
+# define TRIO_PUBLIC_STRING TRIO_PUBLIC
#endif
/*************************************************************************
+ * Dependencies
+ */
+
+#if defined(TRIO_EMBED_STRING)
+
+/*
+ * The application that triostr is embedded in must define which functions
+ * it uses.
+ *
+ * The following resolves internal dependencies.
+ */
+
+# if defined(TRIO_FUNC_XSTRING_SET)
+# if !defined(TRIO_FUNC_DUPLICATE)
+# define TRIO_FUNC_DUPLICATE
+# endif
+# endif
+
+# if defined(TRIO_FUNC_DUPLICATE) \
+ || defined(TRIO_FUNC_DUPLICATE_MAX) \
+ || defined(TRIO_FUNC_STRING_DUPLICATE) \
+ || defined(TRIO_FUNC_XSTRING_DUPLICATE)
+# if !defined(TRIO_FUNC_CREATE)
+# define TRIO_FUNC_CREATE
+# endif
+# if !defined(TRIO_FUNC_COPY_MAX)
+# define TRIO_FUNC_COPY_MAX
+# endif
+# endif
+
+# if defined(TRIO_FUNC_STRING_CREATE)
+# if !defined(TRIO_FUNC_STRING_DESTROY)
+# define TRIO_FUNC_STRING_DESTROY
+# endif
+# endif
+
+# if defined(TRIO_FUNC_STRING_DESTROY) \
+ || defined(TRIO_FUNC_XSTRING_SET)
+# if !defined(TRIO_FUNC_DESTROY)
+# define TRIO_FUNC_DESTROY
+# endif
+# endif
+
+# if defined(TRIO_FUNC_EQUAL_LOCALE) \
+ || defined(TRIO_FUNC_STRING_EQUAL) \
+ || defined(TRIO_FUNC_XSTRING_EQUAL)
+# if !defined(TRIO_FUNC_EQUAL)
+# define TRIO_FUNC_EQUAL
+# endif
+# endif
+
+# if defined(TRIO_FUNC_EQUAL_CASE) \
+ || defined(TRIO_FUNC_STRING_EQUAL_CASE) \
+ || defined(TRIO_FUNC_XSTRING_EQUAL_CASE)
+# if !defined(TRIO_FUNC_EQUAL_CASE)
+# define TRIO_FUNC_EQUAL_CASE
+# endif
+# endif
+
+# if defined(TRIO_FUNC_SUBSTRING_MAX) \
+ || defined(TRIO_FUNC_STRING_EQUAL_MAX) \
+ || defined(TRIO_FUNC_XSTRING_EQUAL_MAX)
+# if !defined(TRIO_FUNC_EQUAL_MAX)
+# define TRIO_FUNC_EQUAL_MAX
+# endif
+# endif
+
+# if defined(TRIO_FUNC_TO_DOUBLE) \
+ || defined(TRIO_FUNC_TO_FLOAT)
+# if !defined(TRIO_FUNC_TO_LONG_DOUBLE)
+# define TRIO_FUNC_TO_LONG_DOUBLE
+# endif
+# endif
+
+# if defined(TRIO_FUNC_STRING_TERMINATE)
+# if !defined(TRIO_FUNC_XSTRING_APPEND_CHAR)
+# define TRIO_FUNC_XSTRING_APPEND_CHAR
+# endif
+# endif
+
+# if defined(TRIO_FUNC_XSTRING_APPEND_CHAR)
+# if !defined(TRIO_FUNC_STRING_SIZE)
+# define TRIO_FUNC_STRING_SIZE
+# endif
+# endif
+
+#else
+
+/*
+ * When triostr is not embedded all functions are defined.
+ */
+
+# define TRIO_FUNC_APPEND
+# define TRIO_FUNC_APPEND_MAX
+# define TRIO_FUNC_CONTAINS
+# define TRIO_FUNC_COPY
+# define TRIO_FUNC_COPY_MAX
+# define TRIO_FUNC_CREATE
+# define TRIO_FUNC_DESTROY
+# define TRIO_FUNC_DUPLICATE
+# define TRIO_FUNC_DUPLICATE_MAX
+# define TRIO_FUNC_EQUAL
+# define TRIO_FUNC_EQUAL_CASE
+# define TRIO_FUNC_EQUAL_CASE_MAX
+# define TRIO_FUNC_EQUAL_LOCALE
+# define TRIO_FUNC_EQUAL_MAX
+# define TRIO_FUNC_ERROR
+# if !defined(TRIO_PLATFORM_WINCE)
+# define TRIO_FUNC_FORMAT_DATE_MAX
+# endif
+# define TRIO_FUNC_HASH
+# define TRIO_FUNC_INDEX
+# define TRIO_FUNC_INDEX_LAST
+# define TRIO_FUNC_LENGTH
+# define TRIO_FUNC_LENGTH_MAX
+# define TRIO_FUNC_LOWER
+# define TRIO_FUNC_MATCH
+# define TRIO_FUNC_MATCH_CASE
+# define TRIO_FUNC_SPAN_FUNCTION
+# define TRIO_FUNC_SUBSTRING
+# define TRIO_FUNC_SUBSTRING_MAX
+# define TRIO_FUNC_TO_DOUBLE
+# define TRIO_FUNC_TO_FLOAT
+# define TRIO_FUNC_TO_LONG
+# define TRIO_FUNC_TO_LONG_DOUBLE
+# define TRIO_FUNC_TO_LOWER
+# define TRIO_FUNC_TO_UNSIGNED_LONG
+# define TRIO_FUNC_TO_UPPER
+# define TRIO_FUNC_TOKENIZE
+# define TRIO_FUNC_UPPER
+
+# define TRIO_FUNC_STRING_APPEND
+# define TRIO_FUNC_STRING_CONTAINS
+# define TRIO_FUNC_STRING_COPY
+# define TRIO_FUNC_STRING_CREATE
+# define TRIO_FUNC_STRING_DESTROY
+# define TRIO_FUNC_STRING_DUPLICATE
+# define TRIO_FUNC_STRING_EQUAL
+# define TRIO_FUNC_STRING_EQUAL_CASE
+# define TRIO_FUNC_STRING_EQUAL_CASE_MAX
+# define TRIO_FUNC_STRING_EQUAL_MAX
+# define TRIO_FUNC_STRING_EXTRACT
+# if !defined(TRIO_PLATFORM_WINCE)
+# define TRIO_FUNC_STRING_FORMAT_DATE_MAX
+# endif
+# define TRIO_FUNC_STRING_GET
+# define TRIO_FUNC_STRING_INDEX
+# define TRIO_FUNC_STRING_INDEX_LAST
+# define TRIO_FUNC_STRING_LENGTH
+# define TRIO_FUNC_STRING_LOWER
+# define TRIO_FUNC_STRING_MATCH
+# define TRIO_FUNC_STRING_MATCH_CASE
+# define TRIO_FUNC_STRING_SIZE
+# define TRIO_FUNC_STRING_SUBSTRING
+# define TRIO_FUNC_STRING_TERMINATE
+# define TRIO_FUNC_STRING_UPPER
+
+# define TRIO_FUNC_XSTRING_APPEND
+# define TRIO_FUNC_XSTRING_APPEND_CHAR
+# define TRIO_FUNC_XSTRING_CONTAINS
+# define TRIO_FUNC_XSTRING_COPY
+# define TRIO_FUNC_XSTRING_DUPLICATE
+# define TRIO_FUNC_XSTRING_EQUAL
+# define TRIO_FUNC_XSTRING_EQUAL_CASE
+# define TRIO_FUNC_XSTRING_EQUAL_CASE_MAX
+# define TRIO_FUNC_XSTRING_EQUAL_MAX
+# define TRIO_FUNC_XSTRING_MATCH
+# define TRIO_FUNC_XSTRING_MATCH_CASE
+# define TRIO_FUNC_XSTRING_SET
+# define TRIO_FUNC_XSTRING_SUBSTRING
+
+#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));
-TRIO_STRING_PUBLIC size_t trio_format_date_max TRIO_PROTO((char *target, size_t max, const char *format, const struct tm *datetime));
-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) */
+#if defined(TRIO_FUNC_APPEND)
+TRIO_PUBLIC_STRING int
+trio_append
+TRIO_PROTO((char *target, TRIO_CONST char *source));
+#endif
+
+#if defined(TRIO_FUNC_APPEND_MAX)
+TRIO_PUBLIC_STRING int
+trio_append_max
+TRIO_PROTO((char *target, size_t max, TRIO_CONST char *source));
+#endif
+
+#if defined(TRIO_FUNC_CONTAINS)
+TRIO_PUBLIC_STRING int
+trio_contains
+TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *substring));
+#endif
+
+#if defined(TRIO_FUNC_COPY)
+TRIO_PUBLIC_STRING int
+trio_copy
+TRIO_PROTO((char *target, TRIO_CONST char *source));
+#endif
+
+#if defined(TRIO_FUNC_COPY_MAX)
+TRIO_PUBLIC_STRING int
+trio_copy_max
+TRIO_PROTO((char *target, size_t max, TRIO_CONST char *source));
+#endif
+
+#if defined(TRIO_FUNC_CREATE)
+TRIO_PUBLIC_STRING char *
+trio_create
+TRIO_PROTO((size_t size));
+#endif
+
+#if defined(TRIO_FUNC_DESTROY)
+TRIO_PUBLIC_STRING void
+trio_destroy
+TRIO_PROTO((char *string));
+#endif
+
+#if defined(TRIO_FUNC_DUPLICATE)
+TRIO_PUBLIC_STRING char *
+trio_duplicate
+TRIO_PROTO((TRIO_CONST char *source));
+#endif
+
+#if defined(TRIO_FUNC_DUPLICATE_MAX)
+TRIO_PUBLIC_STRING char *
+trio_duplicate_max
+TRIO_PROTO((TRIO_CONST char *source, size_t max));
+#endif
+
+#if defined(TRIO_FUNC_EQUAL)
+TRIO_PUBLIC_STRING int
+trio_equal
+TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second));
+#endif
+
+#if defined(TRIO_FUNC_EQUAL_CASE)
+TRIO_PUBLIC_STRING int
+trio_equal_case
+TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second));
+#endif
+
+#if defined(TRIO_FUNC_EQUAL_CASE_MAX)
+TRIO_PUBLIC_STRING int
+trio_equal_case_max
+TRIO_PROTO((TRIO_CONST char *first, size_t max, TRIO_CONST char *second));
+#endif
+
+#if defined(TRIO_FUNC_EQUAL_LOCALE)
+TRIO_PUBLIC_STRING int
+trio_equal_locale
+TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second));
+#endif
+
+#if defined(TRIO_FUNC_EQUAL_MAX)
+TRIO_PUBLIC_STRING int
+trio_equal_max
+TRIO_PROTO((TRIO_CONST char *first, size_t max, TRIO_CONST char *second));
+#endif
+
+#if defined(TRIO_FUNC_ERROR)
+TRIO_PUBLIC_STRING TRIO_CONST char *
+trio_error
+TRIO_PROTO((int));
+#endif
+
+#if defined(TRIO_FUNC_FORMAT_DATE_MAX)
+TRIO_PUBLIC_STRING size_t
+trio_format_date_max
+TRIO_PROTO((char *target, size_t max, TRIO_CONST char *format, TRIO_CONST struct tm *datetime));
+#endif
+
+#if defined(TRIO_FUNC_HASH)
+TRIO_PUBLIC_STRING unsigned long
+trio_hash
+TRIO_PROTO((TRIO_CONST char *string, int type));
+#endif
+
+#if defined(TRIO_FUNC_INDEX)
+TRIO_PUBLIC_STRING char *
+trio_index
+TRIO_PROTO((TRIO_CONST char *string, int character));
+#endif
+
+#if defined(TRIO_FUNC_INDEX_LAST)
+TRIO_PUBLIC_STRING char *
+trio_index_last
+TRIO_PROTO((TRIO_CONST char *string, int character));
+#endif
+
+#if defined(TRIO_FUNC_LENGTH)
+TRIO_PUBLIC_STRING size_t
+trio_length
+TRIO_PROTO((TRIO_CONST char *string));
+#endif
+
+#if defined(TRIO_FUNC_LENGTH_MAX)
+TRIO_PUBLIC_STRING size_t
+trio_length_max
+TRIO_PROTO((TRIO_CONST char *string, size_t max));
+#endif
+
+#if defined(TRIO_FUNC_LOWER)
+TRIO_PUBLIC_STRING int
+trio_lower
+TRIO_PROTO((char *target));
+#endif
+
+#if defined(TRIO_FUNC_MATCH)
+TRIO_PUBLIC_STRING int
+trio_match
+TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *pattern));
+#endif
+
+#if defined(TRIO_FUNC_MATCH_CASE)
+TRIO_PUBLIC_STRING int
+trio_match_case
+TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *pattern));
+#endif
+
+#if defined(TRIO_FUNC_SPAN_FUNCTION)
+TRIO_PUBLIC_STRING size_t
+trio_span_function
+TRIO_PROTO((char *target, TRIO_CONST char *source, int (*Function) TRIO_PROTO((int))));
+#endif
+
+#if defined(TRIO_FUNC_SUBSTRING)
+TRIO_PUBLIC_STRING char *
+trio_substring
+TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *substring));
+#endif
+
+#if defined(TRIO_FUNC_SUBSTRING_MAX)
+TRIO_PUBLIC_STRING char *
+trio_substring_max
+TRIO_PROTO((TRIO_CONST char *string, size_t max, TRIO_CONST char *substring));
+#endif
+
+#if defined(TRIO_FUNC_TO_DOUBLE)
+TRIO_PUBLIC_STRING double
+trio_to_double
+TRIO_PROTO((TRIO_CONST char *source, char **endp));
+#endif
+
+#if defined(TRIO_FUNC_TO_FLOAT)
+TRIO_PUBLIC_STRING float
+trio_to_float
+TRIO_PROTO((TRIO_CONST char *source, char **endp));
+#endif
+
+#if defined(TRIO_FUNC_TO_LONG)
+TRIO_PUBLIC_STRING long
+trio_to_long
+TRIO_PROTO((TRIO_CONST char *source, char **endp, int base));
+#endif
+
+#if defined(TRIO_FUNC_TO_LOWER)
+TRIO_PUBLIC_STRING int
+trio_to_lower
+TRIO_PROTO((int source));
+#endif
+
+#if defined(TRIO_FUNC_TO_LONG_DOUBLE)
+TRIO_PUBLIC_STRING trio_long_double_t
+trio_to_long_double
+TRIO_PROTO((TRIO_CONST char *source, char **endp));
+#endif
+
+#if defined(TRIO_FUNC_TO_UNSIGNED_LONG)
+TRIO_PUBLIC_STRING unsigned long
+trio_to_unsigned_long
+TRIO_PROTO((TRIO_CONST char *source, char **endp, int base));
+#endif
+
+#if defined(TRIO_FUNC_TO_UPPER)
+TRIO_PUBLIC_STRING int
+trio_to_upper
+TRIO_PROTO((int source));
+#endif
+
+#if defined(TRIO_FUNC_TOKENIZE)
+TRIO_PUBLIC_STRING char *
+trio_tokenize
+TRIO_PROTO((char *string, TRIO_CONST char *delimiters));
+#endif
+
+#if defined(TRIO_FUNC_UPPER)
+TRIO_PUBLIC_STRING int
+trio_upper
+TRIO_PROTO((char *target));
+#endif
/*************************************************************************
* Dynamic string functions
@@ -93,48 +451,224 @@ TRIO_STRING_PUBLIC int trio_upper TRIO_PROTO((char *target));
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));
-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));
-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) */
+#if defined(TRIO_FUNC_STRING_APPEND)
+TRIO_PUBLIC_STRING int
+trio_string_append
+TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+#endif
+
+#if defined(TRIO_FUNC_STRING_CONTAINS)
+TRIO_PUBLIC_STRING int
+trio_string_contains
+TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+#endif
+
+#if defined(TRIO_FUNC_STRING_COPY)
+TRIO_PUBLIC_STRING int
+trio_string_copy
+TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+#endif
+
+#if defined(TRIO_FUNC_STRING_CREATE)
+TRIO_PUBLIC_STRING trio_string_t *
+trio_string_create
+TRIO_PROTO((int initial_size));
+#endif
+
+#if defined(TRIO_FUNC_STRING_DESTROY)
+TRIO_PUBLIC_STRING void
+trio_string_destroy
+TRIO_PROTO((trio_string_t *self));
+#endif
+
+#if defined(TRIO_FUNC_STRING_DUPLICATE)
+TRIO_PUBLIC_STRING trio_string_t *
+trio_string_duplicate
+TRIO_PROTO((trio_string_t *other));
+#endif
+
+#if defined(TRIO_FUNC_STRING_EQUAL)
+TRIO_PUBLIC_STRING int
+trio_string_equal
+TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+#endif
+
+#if defined(TRIO_FUNC_STRING_EQUAL_MAX)
+TRIO_PUBLIC_STRING int
+trio_string_equal_max
+TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *second));
+#endif
+
+#if defined(TRIO_FUNC_STRING_EQUAL_CASE)
+TRIO_PUBLIC_STRING int
+trio_string_equal_case
+TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+#endif
+
+#if defined(TRIO_FUNC_STRING_EQUAL_CASE_MAX)
+TRIO_PUBLIC_STRING int
+trio_string_equal_case_max
+TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *other));
+#endif
+
+#if defined(TRIO_FUNC_STRING_EXTRACT)
+TRIO_PUBLIC_STRING char *
+trio_string_extract
+TRIO_PROTO((trio_string_t *self));
+#endif
+
+#if defined(TRIO_FUNC_STRING_FORMAT_DATE_MAX)
+TRIO_PUBLIC_STRING size_t
+trio_string_format_date_max
+TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *format, TRIO_CONST struct tm *datetime));
+#endif
+
+#if defined(TRIO_FUNC_STRING_GET)
+TRIO_PUBLIC_STRING char *
+trio_string_get
+TRIO_PROTO((trio_string_t *self, int offset));
+#endif
+
+#if defined(TRIO_FUNC_STRING_INDEX)
+TRIO_PUBLIC_STRING char *
+trio_string_index
+TRIO_PROTO((trio_string_t *self, int character));
+#endif
+
+#if defined(TRIO_FUNC_STRING_INDEX_LAST)
+TRIO_PUBLIC_STRING char *
+trio_string_index_last
+TRIO_PROTO((trio_string_t *self, int character));
+#endif
+
+#if defined(TRIO_FUNC_STRING_LENGTH)
+TRIO_PUBLIC_STRING int
+trio_string_length
+TRIO_PROTO((trio_string_t *self));
+#endif
+
+#if defined(TRIO_FUNC_STRING_LOWER)
+TRIO_PUBLIC_STRING int
+trio_string_lower
+TRIO_PROTO((trio_string_t *self));
+#endif
+
+#if defined(TRIO_FUNC_STRING_MATCH)
+TRIO_PUBLIC_STRING int
+trio_string_match
+TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+#endif
+
+#if defined(TRIO_FUNC_STRING_MATCH_CASE)
+TRIO_PUBLIC_STRING int
+trio_string_match_case
+TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+#endif
+
+#if defined(TRIO_FUNC_STRING_SIZE)
+TRIO_PUBLIC_STRING int
+trio_string_size
+TRIO_PROTO((trio_string_t *self));
+#endif
+
+#if defined(TRIO_FUNC_STRING_SUBSTRING)
+TRIO_PUBLIC_STRING char *
+trio_string_substring
+TRIO_PROTO((trio_string_t *self, trio_string_t *other));
+#endif
+
+#if defined(TRIO_FUNC_STRING_TERMINATE)
+TRIO_PUBLIC_STRING void
+trio_string_terminate
+TRIO_PROTO((trio_string_t *self));
+#endif
+
+#if defined(TRIO_FUNC_STRING_UPPER)
+TRIO_PUBLIC_STRING int
+trio_string_upper
+TRIO_PROTO((trio_string_t *self));
+#endif
+
+#if defined(TRIO_FUNC_XSTRING_APPEND)
+TRIO_PUBLIC_STRING int
+trio_xstring_append
+TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
+#endif
+
+#if defined(TRIO_FUNC_XSTRING_APPEND_CHAR)
+TRIO_PUBLIC_STRING int
+trio_xstring_append_char
+TRIO_PROTO((trio_string_t *self, char character));
+#endif
+
+#if defined(TRIO_FUNC_XSTRING_CONTAINS)
+TRIO_PUBLIC_STRING int
+trio_xstring_contains
+TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
+#endif
+
+#if defined(TRIO_FUNC_XSTRING_COPY)
+TRIO_PUBLIC_STRING int
+trio_xstring_copy
+TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
+#endif
+
+#if defined(TRIO_FUNC_XSTRING_DUPLICATE)
+TRIO_PUBLIC_STRING trio_string_t *
+trio_xstring_duplicate
+TRIO_PROTO((TRIO_CONST char *other));
+#endif
+
+#if defined(TRIO_FUNC_XSTRING_EQUAL)
+TRIO_PUBLIC_STRING int
+trio_xstring_equal
+TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
+#endif
+
+#if defined(TRIO_FUNC_XSTRING_EQUAL_MAX)
+TRIO_PUBLIC_STRING int
+trio_xstring_equal_max
+TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *other));
+#endif
+
+#if defined(TRIO_FUNC_XSTRING_EQUAL_CASE)
+TRIO_PUBLIC_STRING int
+trio_xstring_equal_case
+TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
+#endif
+
+#if defined(TRIO_FUNC_XSTRING_EQUAL_CASE_MAX)
+TRIO_PUBLIC_STRING int
+trio_xstring_equal_case_max
+TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *other));
+#endif
+
+#if defined(TRIO_FUNC_XSTRING_MATCH)
+TRIO_PUBLIC_STRING int
+trio_xstring_match
+TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
+#endif
+
+#if defined(TRIO_FUNC_XSTRING_MATCH_CASE)
+TRIO_PUBLIC_STRING int
+trio_xstring_match_case
+TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
+#endif
+
+#if defined(TRIO_FUNC_XSTRING_SET)
+TRIO_PUBLIC_STRING void
+trio_xstring_set
+TRIO_PROTO((trio_string_t *self, char *buffer));
+#endif
+
+#if defined(TRIO_FUNC_XSTRING_SUBSTRING)
+TRIO_PUBLIC_STRING char *
+trio_xstring_substring
+TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other));
+#endif
+
+#ifdef __cplusplus
+}
+#endif
#endif /* TRIO_TRIOSTR_H */