From c8e1897c969ce43b551c29d65bc605f175c01263 Mon Sep 17 00:00:00 2001 From: Matthias Andree Date: Thu, 2 Jul 2009 19:48:34 +0000 Subject: Update trio to CVS checkout of 2009-07-02. svn path=/branches/BRANCH_6-3/; revision=5370 --- trio/CHANGES | 147 +- trio/Makefile.in | 9 +- trio/configure | 1213 -------------- trio/configure.in | 5 +- trio/doc/doc.h | 13 +- trio/doc/doc_nan.h | 58 + trio/doc/doc_printf.h | 8 +- trio/doc/doc_register.h | 45 +- trio/doc/footer.html | 2 +- trio/example.c | 187 +-- trio/regression.c | 567 ++++++- trio/trio.c | 4239 ++++++++++++++++++++++++++++------------------- trio/trio.h | 13 +- trio/triodef.h | 232 ++- trio/trionan.c | 1114 ++++++++----- trio/trionan.h | 132 +- trio/triop.h | 350 +++- trio/triostr.c | 949 +++++++---- trio/triostr.h | 706 +++++++- 19 files changed, 5927 insertions(+), 4062 deletions(-) delete mode 100755 trio/configure create mode 100644 trio/doc/doc_nan.h (limited to 'trio') 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 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 <&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 <&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 <&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 <&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 </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 < 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 <> $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 <> $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 +@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("%\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("$\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("\n", my_data); + trio_printf("%\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("\n", my_handle, my_data); + trio_printf("%\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("\n", anon_handle, my_data); + trio_printf("%\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, "%\n", recursive_writer, trio_get_argument()); + trio_print_ref(ref, "%\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 @@
- + 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 #include #include +/* #include */ #include -#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 #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); @@ -437,12 +470,110 @@ VerifyFormatting(TRIO_NOARGS) "%.2e", 0.9999); 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", + "%", &integer); + + /* New style */ + nerrors += Verify(__FILE__, __LINE__, "123", + "$", &integer); + nerrors += Verify(__FILE__, __LINE__, "123", + "$", number_handle, &integer); + nerrors += Verify(__FILE__, __LINE__, "$", + "$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,12 +1095,31 @@ VerifyScanningIntegers(TRIO_NOARGS) return nerrors; } +#endif /************************************************************************* * */ +#if TRIO_FEATURE_SCANF int VerifyScanningOneFloat +TRIO_ARGS5((file, line, expected, format, original), + TRIO_CONST char *file, + int line, + TRIO_CONST char *expected, + 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, @@ -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 #include -#include +#if TRIO_FEATURE_FLOAT +# include +# include +#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 #include -#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 @@ -92,7 +195,11 @@ # include #endif #include -#include +#if defined(TRIO_PLATFORM_WINCE) +extern int errno; +#else +# include +#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 # include # include -# define USE_LOCALE +# if !defined(TRIO_FEATURE_LOCALE) +# define USE_LOCALE +# endif #endif /* TRIO_PLATFORM_UNIX */ #if defined(TRIO_PLATFORM_VMS) # include #endif #if defined(TRIO_PLATFORM_WIN32) -# include -# 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 +# 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 # include 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 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 +#else +# if defined(PREDEF_STANDARD_UNIX98) +# include typedef intmax_t trio_intmax_t; typedef uintmax_t trio_uintmax_t; typedef int8_t trio_int8_t; typedef int16_t trio_int16_t; typedef int32_t trio_int32_t; typedef int64_t trio_int64_t; -#elif defined(TRIO_COMPILER_SUPPORTS_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 */ @@ -671,6 +838,10 @@ typedef struct _trio_class_t { * The function to read characters from a stream. */ 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. */ @@ -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,748 +1378,824 @@ TRIO_ARGS1((base), default : return TrioLogarithm((double)base, 2); } } +#endif /* TRIO_FEATURE_FLOAT */ /************************************************************************* - * TrioParse + * TrioParseQualifiers * * Description: - * Parse the format string + * Parse the qualifiers of a potential conversion specifier */ TRIO_PRIVATE int -TrioParse -TRIO_ARGS5((type, format, parameters, arglist, argarray), +TrioParseQualifiers +TRIO_ARGS4((type, format, offset, parameter), int type, TRIO_CONST char *format, - trio_parameter_t *parameters, - va_list *arglist, - trio_pointer_t *argarray) + int offset, + trio_parameter_t *parameter) { - /* Count the number of times a parameter is referenced */ - unsigned short usedEntries[MAX_PARAMETERS]; - /* Parameter counters */ - int parameterPosition; - int currentParam; - int maxParam = -1; - /* Utility variables */ - trio_flags_t flags; - int width; - int precision; - int varsize; - int base; - int index; /* Index into formatting string */ - int dots; /* Count number of dots in modifier part */ - BOOLEAN_T positional; /* Does the specifier have a positional? */ - BOOLEAN_T gotSticky = FALSE; /* Are there any sticky modifiers at all? */ - /* - * indices specifies the order in which the parameters must be - * read from the va_args (this is necessary to handle positionals) - */ - int indices[MAX_PARAMETERS]; - int pos = 0; - /* Various variables */ char ch; -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - int charlen; -#endif - int save_errno; - int i = -1; - int num; + int dots = 0; /* Count number of dots in modifier part */ char *tmpformat; - /* One and only one of arglist and argarray must be used */ - assert((arglist != NULL) ^ (argarray != NULL)); - - /* - * The 'parameters' array is not initialized, but we need to - * know which entries we have used. - */ - memset(usedEntries, 0, sizeof(usedEntries)); - - save_errno = errno; - index = 0; - parameterPosition = 0; -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - (void)mblen(NULL, 0); -#endif - - while (format[index]) - { -#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) - if (! isascii(format[index])) - { - /* - * Multibyte characters cannot be legal specifiers or - * modifiers, so we skip over them. - */ - charlen = mblen(&format[index], MB_LEN_MAX); - index += (charlen > 0) ? charlen : 1; - continue; /* while */ - } -#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */ - if (CHAR_IDENTIFIER == format[index++]) - { - if (CHAR_IDENTIFIER == format[index]) - { - index++; - continue; /* while */ - } + parameter->beginOffset = offset - 1; + parameter->flags = FLAGS_NEW; + parameter->position = TrioGetPosition(format, &offset); - 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); - } + /* Default values */ + parameter->width = NO_WIDTH; + parameter->precision = NO_PRECISION; + parameter->base = NO_BASE; + parameter->varsize = NO_SIZE; - if (currentParam > maxParam) - maxParam = currentParam; + while (TrioIsQualifier(format[offset])) + { + ch = format[offset++]; - /* Default values */ - width = NO_WIDTH; - precision = NO_PRECISION; - base = NO_BASE; - varsize = NO_SIZE; + switch (ch) + { + case QUALIFIER_SPACE: + parameter->flags |= FLAGS_SPACE; + break; - while (TrioIsQualifier(format[index])) - { - ch = format[index++]; + case QUALIFIER_PLUS: + parameter->flags |= FLAGS_SHOWSIGN; + break; - switch (ch) - { - case QUALIFIER_SPACE: - flags |= FLAGS_SPACE; - break; + case QUALIFIER_MINUS: + parameter->flags |= FLAGS_LEFTADJUST; + parameter->flags &= ~FLAGS_NILPADDING; + break; - case QUALIFIER_PLUS: - flags |= FLAGS_SHOWSIGN; - break; + case QUALIFIER_ALTERNATIVE: + parameter->flags |= FLAGS_ALTERNATIVE; + break; - case QUALIFIER_MINUS: - flags |= FLAGS_LEFTADJUST; - flags &= ~FLAGS_NILPADDING; - break; + case QUALIFIER_DOT: + if (dots == 0) /* Precision */ + { + dots++; - case QUALIFIER_ALTERNATIVE: - flags |= FLAGS_ALTERNATIVE; - break; + /* Skip if no precision */ + if (QUALIFIER_DOT == format[offset]) + 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]) + /* After the first dot we have the precision */ + parameter->flags |= FLAGS_PRECISION; + if ((QUALIFIER_STAR == format[offset]) #if defined(QUALIFIER_PARAM) - || (QUALIFIER_PARAM == format[index]) + || (QUALIFIER_PARAM == format[offset]) #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]) + ) + { + 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[index]) + || (QUALIFIER_PARAM == format[offset]) #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 */ + ) + { + 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: - type = TYPE_PRINT; - /* FALLTHROUGH */ + 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 */ - 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_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 (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_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 (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: + 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; - case QUALIFIER_LONG_UPPER: - flags |= FLAGS_LONGDOUBLE; - break; +#if TRIO_FEATURE_LONGDOUBLE + case QUALIFIER_LONG_UPPER: + parameter->flags |= FLAGS_LONGDOUBLE; + break; +#endif -#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; +#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 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; +#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 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; +#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 defined(QUALIFIER_QUAD) - case QUALIFIER_QUAD: - flags |= FLAGS_QUAD; - break; +#if TRIO_FEATURE_QUAD + case QUALIFIER_QUAD: + parameter->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 TRIO_FEATURE_FIXED_SIZE + case QUALIFIER_FIXED_SIZE: + if (parameter->flags & FLAGS_FIXED_SIZE) + return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - if (flags & (FLAGS_ALL_SIZES | FLAGS_LONGDOUBLE | - FLAGS_WIDECHAR | FLAGS_VARSIZE_PARAMETER)) - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); + if (parameter->flags & (FLAGS_ALL_SIZES | + FLAGS_LONGDOUBLE | + FLAGS_WIDECHAR | + FLAGS_VARSIZE_PARAMETER)) + return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); - 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 ((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: - flags |= FLAGS_WIDECHAR; - break; + case QUALIFIER_WIDECHAR: + parameter->flags |= FLAGS_WIDECHAR; + break; #endif -#if defined(QUALIFIER_SIZE_T_UPPER) - case QUALIFIER_SIZE_T_UPPER: - break; +#if TRIO_FEATURE_SIZE_T_UPPER + case QUALIFIER_SIZE_T_UPPER: + break; #endif -#if defined(QUALIFIER_QUOTE) - case QUALIFIER_QUOTE: - flags |= FLAGS_QUOTE; - break; +#if TRIO_FEATURE_QUOTE + case QUALIFIER_QUOTE: + parameter->flags |= FLAGS_QUOTE; + break; #endif -#if defined(QUALIFIER_STICKY) - case QUALIFIER_STICKY: - flags |= FLAGS_STICKY; - gotSticky = TRUE; - break; +#if TRIO_FEATURE_STICKY + case QUALIFIER_STICKY: + parameter->flags |= FLAGS_STICKY; + 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; + +#if TRIO_FEATURE_VARSIZE + case QUALIFIER_VARSIZE: + parameter->flags |= FLAGS_VARSIZE_PARAMETER; + break; #endif -#if defined(QUALIFIER_ROUNDING_UPPER) - case QUALIFIER_ROUNDING_UPPER: - flags |= FLAGS_ROUNDING; - break; +#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, index); - } - } /* while qualifier */ + default: + /* Bail out completely to make the error more obvious */ + return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); + } + } /* while qualifier */ - /* - * Parameters only need the type and value. The value is - * read later. - */ - if (flags & FLAGS_WIDTH_PARAMETER) - { - usedEntries[width] += 1; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[width] = pos; - width = pos++; - } - if (flags & FLAGS_PRECISION_PARAMETER) - { - usedEntries[precision] += 1; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[precision] = pos; - precision = pos++; - } - if (flags & FLAGS_BASE_PARAMETER) - { - usedEntries[base] += 1; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[base] = pos; - base = pos++; - } - if (flags & FLAGS_VARSIZE_PARAMETER) - { - usedEntries[varsize] += 1; - parameters[pos].type = FORMAT_PARAMETER; - parameters[pos].flags = 0; - indices[varsize] = pos; - varsize = pos++; - } - - indices[currentParam] = pos; - - switch (format[index++]) - { + 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: - flags |= FLAGS_WIDECHAR; - /* FALLTHROUGH */ + case SPECIFIER_CHAR_UPPER: + parameter->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; + 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: - flags |= FLAGS_WIDECHAR; - /* FALLTHROUGH */ + case SPECIFIER_STRING_UPPER: + parameter->flags |= FLAGS_WIDECHAR; + /* FALLTHROUGH */ #endif - case SPECIFIER_STRING: - if (flags & FLAGS_LONG) - flags |= FLAGS_WIDECHAR; - else if (flags & FLAGS_SHORT) - flags &= ~FLAGS_WIDECHAR; - parameters[pos].type = FORMAT_STRING; - break; + case SPECIFIER_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; - case SPECIFIER_GROUP: - if (TYPE_SCAN == type) +#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) { - 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++; - } + depth++; } - break; - - case SPECIFIER_INTEGER: - parameters[pos].type = FORMAT_INT; - break; - - case SPECIFIER_UNSIGNED: - flags |= FLAGS_UNSIGNED; - parameters[pos].type = FORMAT_INT; - break; + else if (format[offset] == SPECIFIER_UNGROUP) + { + if (--depth <= 0) + { + offset++; + break; + } + } + offset++; + } + } + break; +#endif /* defined(SPECIFIER_GROUP) */ - case SPECIFIER_DECIMAL: - /* Disable base modifier */ - flags &= ~FLAGS_BASE_PARAMETER; - base = BASE_DECIMAL; - parameters[pos].type = FORMAT_INT; - break; + case SPECIFIER_INTEGER: + parameter->type = FORMAT_INT; + break; - case SPECIFIER_OCTAL: - flags |= FLAGS_UNSIGNED; - flags &= ~FLAGS_BASE_PARAMETER; - base = BASE_OCTAL; - parameters[pos].type = FORMAT_INT; - break; + case SPECIFIER_UNSIGNED: + parameter->flags |= FLAGS_UNSIGNED; + parameter->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; + 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: - 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_HEX_UPPER: + parameter->flags |= FLAGS_UPPER; + /* FALLTHROUGH */ + case SPECIFIER_HEX: + parameter->flags |= FLAGS_UNSIGNED; + parameter->baseSpecifier = BASE_HEX; + parameter->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; +#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 - case SPECIFIER_FLOAT_G_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_FLOAT_G: - flags |= FLAGS_FLOAT_G; - parameters[pos].type = FORMAT_DOUBLE; - break; +#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 - case SPECIFIER_FLOAT_F_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ - case SPECIFIER_FLOAT_F: - parameters[pos].type = FORMAT_DOUBLE; - break; +#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 - 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 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: - parameters[pos].type = FORMAT_COUNT; - break; + case SPECIFIER_COUNT: + parameter->type = FORMAT_COUNT; + break; -#if defined(SPECIFIER_HEXFLOAT) -# if defined(SPECIFIER_HEXFLOAT_UPPER) - case SPECIFIER_HEXFLOAT_UPPER: - flags |= FLAGS_UPPER; - /* FALLTHROUGH */ -# endif - case SPECIFIER_HEXFLOAT: - base = BASE_HEX; - parameters[pos].type = FORMAT_DOUBLE; - break; +#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 defined(FORMAT_ERRNO) - case SPECIFIER_ERRNO: - parameters[pos].type = FORMAT_ERRNO; - break; +#if TRIO_FEATURE_ERRNO + case SPECIFIER_ERRNO: + parameter->type = FORMAT_ERRNO; + break; #endif -#if defined(SPECIFIER_USER_DEFINED_BEGIN) - case SPECIFIER_USER_DEFINED_BEGIN: +#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)) { - 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); + 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 */ } - break; -#endif /* defined(SPECIFIER_USER_DEFINED_BEGIN) */ - - default: - /* Bail out completely to make the error more obvious */ - return TRIO_ERROR_RETURN(TRIO_EINVAL, index); + + 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 + * + * Description: + * Parse the format string + */ +TRIO_PRIVATE int +TrioParse +TRIO_ARGS5((type, format, parameters, arglist, argarray), + int type, + TRIO_CONST char *format, + trio_parameter_t *parameters, + 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 maxParam = -1; + /* Utility variables */ + 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) + */ + int indices[MAX_PARAMETERS]; + int pos = 0; + /* Various variables */ +#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) + int charlen; +#endif + int save_errno; + int i = -1; + int num; + trio_parameter_t workParameter; + int status; + + /* + * The 'parameters' array is not initialized, but we need to + * know which entries we have used. + */ + memset(usedEntries, 0, sizeof(usedEntries)); + + save_errno = errno; + offset = 0; + parameterPosition = 0; +#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) + (void)mblen(NULL, 0); +#endif + + while (format[offset]) + { + TrioInitializeParameter(&workParameter); + +#if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) + if (! isascii(format[offset])) + { + /* + * Multibyte characters cannot be legal specifiers or + * modifiers, so we skip over them. + */ + charlen = mblen(&format[offset], MB_LEN_MAX); + offset += (charlen > 0) ? charlen : 1; + continue; /* while */ + } +#endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */ + + switch(format[offset++]) { + + case CHAR_IDENTIFIER: + { + if (CHAR_IDENTIFIER == format[offset]) + { + /* skip double "%" */ + offset++; + continue; /* while */ } - /* Count the number of times this entry has been used */ - usedEntries[currentParam] += 1; - - /* Find last sticky parameters */ - if (gotSticky && !(flags & FLAGS_STICKY)) + status = TrioParseQualifiers(type, format, offset, &workParameter); + if (status < 0) + return status; /* Return qualifier syntax error */ + + status = TrioParseSpecifier(type, format, workParameter.endOffset, &workParameter); + if (status < 0) + return status; /* Return specifier syntax error */ + } + break; + +#if TRIO_EXTENSION + case CHAR_ALT_IDENTIFIER: + { + status = TrioParseQualifiers(type, format, offset, &workParameter); + if (status < 0) + continue; /* False alert, not a user defined specifier */ + + 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 + + default: + continue; /* while */ + } + + /* now handle the parsed conversion specification */ + positional = (NO_POSITION != workParameter.position); + + /* + * Parameters only need the type and value. The value is + * read later. + */ + if (workParameter.flags & FLAGS_WIDTH_PARAMETER) + { + if (workParameter.width == NO_WIDTH) + { + workParameter.width = parameterPosition++; + } + else + { + if (! positional) + workParameter.position = workParameter.width + 1; + } + + 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) + { + workParameter.precision = parameterPosition++; + } + else + { + if (! positional) + workParameter.position = workParameter.precision + 1; + } + + 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) + { + workParameter.base = parameterPosition++; + } + else + { + if (! positional) + workParameter.position = workParameter.base + 1; + } + + 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 +#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 + + if (NO_POSITION == workParameter.position) + { + workParameter.position = parameterPosition++; + } + + if (workParameter.position > maxParam) + maxParam = workParameter.position; + + if (workParameter.position >= MAX_PARAMETERS) + { + /* Bail out completely to make the error more obvious */ + return TRIO_ERROR_RETURN(TRIO_ETOOMANY, offset); + } + + indices[workParameter.position] = pos; + + /* Count the number of times this entry has been used */ + usedEntries[workParameter.position] += 1; + + /* 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(¶meters[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 */ - - case FORMAT_POINTER: - { - trio_reference_t reference; - - reference.data = data; - reference.parameter = ¶meters[i]; - trio_print_pointer(&reference, parameters[i].data.pointer); - } - break; /* FORMAT_POINTER */ + { + TrioWriteString(data, + parameters[i].data.string, + flags, + width, + precision); + } + break; /* FORMAT_STRING */ - 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 + case FORMAT_POINTER: + { + trio_reference_t reference; + + reference.data = data; + reference.parameter = ¶meters[i]; + trio_print_pointer(&reference, parameters[i].data.pointer); + } + break; /* FORMAT_POINTER */ + + case FORMAT_COUNT: + pointer = parameters[i].data.pointer; + if (NULL != pointer) + { + /* + * C99 paragraph 7.19.6.1.8 says "the number of + * characters written to the output stream so far by + * this call", which is data->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 = ¶meters[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 = ¶meters[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[offset++] = (char)ch; + self->InStream(self, &ch); + } + } + if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E')) + { + /* Exponent */ + doubleString[offset++] = (char)ch; + self->InStream(self, &ch); + if ((ch == '+') || (ch == '-')) { - doubleString[index++] = (char)ch; + doubleString[offset++] = (char)ch; self->InStream(self, &ch); } - if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E')) + while (isdigit(ch) && (offset - start < width)) { - /* Exponent */ - doubleString[index++] = (char)ch; + 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])) - { - 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)) + /* Skip the parameter entries */ + while (parameters[i].type == FORMAT_PARAMETER) { - 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; + base = (int)parameters[base].data.number.as_signed; + } + else + { + /* Use base from format string */ base = parameters[i].base; - if (flags & FLAGS_BASE_PARAMETER) - { - /* Get base from parameter list */ - base = (int)parameters[base].data.number.as_signed; - } - - switch (parameters[i].type) - { - case FORMAT_INT: - { - trio_uintmax_t number; + } - if (0 == base) - base = BASE_DECIMAL; + switch (parameters[i].type) + { + case FORMAT_INT: + { + trio_uintmax_t number; - if (!TrioReadNumber(data, - &number, - flags, - width, - base)) - return assignment; + if (0 == base) + base = BASE_DECIMAL; - if (!(flags & FLAGS_IGNORE)) - { - assignment++; + if (!TrioReadNumber(data, + &number, + flags, + width, + base)) + { + status = assignment; + goto end; + } - 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 + if (!(flags & FLAGS_IGNORE)) + { + assignment++; + + 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; + } + 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)) + { + status = assignment; + goto end; + } + if (!(flags & FLAGS_IGNORE)) + { + assignment++; } - case FORMAT_GROUP: + break; /* FORMAT_DOUBLE */ + } +#endif + + case FORMAT_GROUP: + { + int characterclass[MAX_CHARACTER_CLASS + 1]; + + /* Skip over modifiers */ + while (format[offset] != SPECIFIER_GROUP) { - int characterclass[MAX_CHARACTER_CLASS + 1]; - int rc; + offset++; + } + /* Skip over group specifier */ + offset++; - /* Skip over modifiers */ - while (format[index] != SPECIFIER_GROUP) - { - index++; - } - /* Skip over group specifier */ - index++; - - memset(characterclass, 0, sizeof(characterclass)); - rc = TrioGetCharacterClass(format, - &index, + 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 #endif -#include "triodef.h" +#include "triop.h" #include -#include -#if defined(TRIO_COMPILER_ANCIENT) -# include -#else -# include -#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 * @@ -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 +#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 * @@ -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 #include #include -#include +#if !defined(TRIO_PLATFORM_SYMBIAN) +# include +#endif #if defined(TRIO_PLATFORM_UNIX) # include #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. +#endif /* TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT */ - @return Floating-point representation of NaN. -*/ -TRIO_PUBLIC double -trio_nan(TRIO_NOARGS) +#if defined(TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT) + +TRIO_PRIVATE_NAN TRIO_INLINE int +xlc_fpclassify_and_signbit +TRIO_ARGS2((number, is_negative), + double number, + int *is_negative) { - /* Cache the result */ - static double result = 0.0; + /* + * 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 - if (result == 0.0) { - -#if defined(TRIO_COMPILER_SUPPORTS_C99) - result = nan(""); + 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; + } +} -#elif defined(NAN) && defined(__STDC_IEC_559__) - result = (double)NAN; - -#elif defined(USE_IEEE_754) - result = trio_make_double(ieee_754_qnan_array); +#endif /* 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); -# endif - -#endif - } - return result; -} +#if defined(TRIO_FUNC_INTERNAL_ISNAN) -/** - Check for NaN. - - @param number An arbitrary floating-point number. - @return Boolean value indicating whether or not the number is a NaN. -*/ -TRIO_PUBLIC int -trio_isnan +TRIO_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); + +# endif -#elif defined(USE_IEEE_754) +# 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); + +#endif - return (! trio_is_special_quantity(number, &dummy)); +#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 * @@ -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 +#endif #include #include #include #include -#include #include "triodef.h" #include "triostr.h" +#if defined(TRIO_FUNC_TO_LONG_DOUBLE) +# define USE_MATH +#endif +#if defined(USE_MATH) +# include +#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 #include #include @@ -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 */ -- cgit v1.2.3