Removal of old libg++.
This commit is contained in:
parent
03548c36c3
commit
84a13b4cb6
@ -1,177 +0,0 @@
|
||||
// This may look like C code, but it is really -*- C++ -*-
|
||||
/*
|
||||
Copyright (C) 1988 Free Software Foundation
|
||||
written by Doug Lea (dl@rocky.oswego.edu)
|
||||
|
||||
This file is part of the GNU C++ Library. This library is free
|
||||
software; you can redistribute it and/or modify it under the terms of
|
||||
the GNU Library General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version. This library is distributed in the hope
|
||||
that it will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU Library General Public License for more details.
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: values.h,v 1.4 1995/12/16 01:03:33 thorpej Exp $
|
||||
*/
|
||||
|
||||
#ifndef _values_h
|
||||
#define _values_h 1
|
||||
|
||||
#define BITSPERBYTE 8
|
||||
#define BITS(type) (BITSPERBYTE * (int)sizeof(type))
|
||||
|
||||
#define CHARBITS BITS(char)
|
||||
#define SHORTBITS BITS(short)
|
||||
#define INTBITS BITS(int)
|
||||
#define LONGBITS BITS(long)
|
||||
#define PTRBITS BITS(char*)
|
||||
#define DOUBLEBITS BITS(double)
|
||||
#define FLOATBITS BITS(float)
|
||||
|
||||
#define MINSHORT ((short)(1 << (SHORTBITS - 1)))
|
||||
#define MININT (1 << (INTBITS - 1))
|
||||
#define MINLONG (1L << (LONGBITS - 1))
|
||||
|
||||
#define MAXSHORT ((short)~MINSHORT)
|
||||
#define MAXINT (~MININT)
|
||||
#define MAXLONG (~MINLONG)
|
||||
|
||||
#define HIBITS MINSHORT
|
||||
#define HIBITL MINLONG
|
||||
|
||||
#if defined(sun) || defined(hp300) || defined(hpux) || defined(masscomp) || defined(sgi)
|
||||
#ifdef masscomp
|
||||
#define MAXDOUBLE \
|
||||
({ \
|
||||
double maxdouble_val; \
|
||||
\
|
||||
__asm ("fmove%.d #0x7fefffffffffffff,%0" /* Max double */ \
|
||||
: "=f" (maxdouble_val) \
|
||||
: /* no inputs */); \
|
||||
maxdouble_val; \
|
||||
})
|
||||
#define MAXFLOAT ((float) 3.40e+38)
|
||||
#else
|
||||
#define MAXDOUBLE 1.79769313486231470e+308
|
||||
#define MAXFLOAT ((float)3.40282346638528860e+38)
|
||||
#endif
|
||||
#define MINDOUBLE 4.94065645841246544e-324
|
||||
#define MINFLOAT ((float)1.40129846432481707e-45)
|
||||
#define _IEEE 1
|
||||
#define _DEXPLEN 11
|
||||
#define _FEXPLEN 8
|
||||
#define _HIDDENBIT 1
|
||||
#define DMINEXP (-(DMAXEXP + DSIGNIF - _HIDDENBIT - 3))
|
||||
#define FMINEXP (-(FMAXEXP + FSIGNIF - _HIDDENBIT - 3))
|
||||
#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE)
|
||||
#define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE)
|
||||
|
||||
#elif defined(sony)
|
||||
#define MAXDOUBLE 1.79769313486231470e+308
|
||||
#define MAXFLOAT ((float)3.40282346638528860e+38)
|
||||
#define MINDOUBLE 2.2250738585072010e-308
|
||||
#define MINFLOAT ((float)1.17549435e-38)
|
||||
#define _IEEE 1
|
||||
#define _DEXPLEN 11
|
||||
#define _FEXPLEN 8
|
||||
#define _HIDDENBIT 1
|
||||
#define DMINEXP (-(DMAXEXP + DSIGNIF - _HIDDENBIT - 3))
|
||||
#define FMINEXP (-(FMAXEXP + FSIGNIF - _HIDDENBIT - 3))
|
||||
#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE)
|
||||
#define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE)
|
||||
|
||||
#elif defined(sequent)
|
||||
extern double _maxdouble, _mindouble;
|
||||
extern float _maxfloat, _minfloat;
|
||||
#define MAXDOUBLE _maxdouble
|
||||
#define MAXFLOAT _maxfloat
|
||||
#define MINDOUBLE _mindouble
|
||||
#define MINFLOAT _minfloat
|
||||
#define _IEEE 1
|
||||
#define _DEXPLEN 11
|
||||
#define _FEXPLEN 8
|
||||
#define _HIDDENBIT 1
|
||||
#define DMINEXP (-(DMAXEXP - 3))
|
||||
#define FMINEXP (-(FMAXEXP - 3))
|
||||
#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE)
|
||||
#define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE)
|
||||
|
||||
#elif defined(i386)
|
||||
#define MAXDOUBLE 1.79769313486231570e+308
|
||||
#define MAXFLOAT ((float)3.40282346638528860e+38)
|
||||
#define MINDOUBLE 2.22507385850720140e-308
|
||||
#define MINFLOAT ((float)1.17549435082228750e-38)
|
||||
#define _IEEE 0
|
||||
#define _DEXPLEN 11
|
||||
#define _FEXPLEN 8
|
||||
#define _HIDDENBIT 1
|
||||
#define DMINEXP (-DMAXEXP)
|
||||
#define FMINEXP (-FMAXEXP)
|
||||
#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE)
|
||||
#define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE)
|
||||
|
||||
/* from Andrew Klossner <andrew%frip.wv.tek.com@relay.cs.net> */
|
||||
#elif defined(m88k)
|
||||
/* These are "good" guesses ...
|
||||
I'll figure out the true mins and maxes later, at the time I find
|
||||
out the mins and maxes that the compiler can tokenize. */
|
||||
#define MAXDOUBLE 1.79769313486231e+308
|
||||
#define MAXFLOAT ((float)3.40282346638528e+38)
|
||||
#define MINDOUBLE 2.22507385850720e-308
|
||||
#define MINFLOAT ((float)1.17549435082228e-38)
|
||||
#define _IEEE 1
|
||||
#define _DEXPLEN 11
|
||||
#define _FEXPLEN 8
|
||||
#define _HIDDENBIT 1
|
||||
#define DMINEXP (1-DMAXEXP)
|
||||
#define FMINEXP (1-FMAXEXP)
|
||||
#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE)
|
||||
#define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE)
|
||||
|
||||
#elif defined(convex)
|
||||
#define MAXDOUBLE 8.9884656743115785e+306
|
||||
#define MAXFLOAT ((float) 1.70141173e+38)
|
||||
#define MINDOUBLE 5.5626846462680035e-308
|
||||
#define MINFLOAT ((float) 2.93873588e-39)
|
||||
#define _IEEE 0
|
||||
#define _DEXPLEN 11
|
||||
#define _FEXPLEN 8
|
||||
#define _HIDDENBIT 1
|
||||
#define DMINEXP (-DMAXEXP)
|
||||
#define FMINEXP (-FMAXEXP)
|
||||
#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE)
|
||||
#define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE)
|
||||
|
||||
// #elif defined(vax)
|
||||
// use vax versions by default -- they seem to be the most conservative
|
||||
#else
|
||||
|
||||
#define MAXDOUBLE 1.701411834604692293e+38
|
||||
#define MINDOUBLE (2.938735877055718770e-39)
|
||||
|
||||
#ifndef __NetBSD__ /* XXX */
|
||||
#define MAXFLOAT 1.7014117331926443e+38
|
||||
#endif /* ! __NetBSD__ */
|
||||
#define MINFLOAT 2.9387358770557188e-39
|
||||
|
||||
#define _IEEE 0
|
||||
#define _DEXPLEN 8
|
||||
#define _FEXPLEN 8
|
||||
#define _HIDDENBIT 1
|
||||
#define DMINEXP (-DMAXEXP)
|
||||
#define FMINEXP (-FMAXEXP)
|
||||
#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE)
|
||||
#define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE)
|
||||
#endif
|
||||
|
||||
#define DSIGNIF (DOUBLEBITS - _DEXPLEN + _HIDDENBIT - 1)
|
||||
#define FSIGNIF (FLOATBITS - _FEXPLEN + _HIDDENBIT - 1)
|
||||
#define DMAXPOWTWO ((double)(1L << LONGBITS -2)*(1L << DSIGNIF - LONGBITS +1))
|
||||
#define FMAXPOWTWO ((float)(1L << FSIGNIF - 1))
|
||||
|
||||
#endif
|
||||
|
@ -1,13 +0,0 @@
|
||||
# Makefile for g++ library genclass
|
||||
|
||||
PROG= genclass
|
||||
SRCS= genclass.sh
|
||||
NOMAN=
|
||||
STRIP=
|
||||
|
||||
genclass: genclass.sh
|
||||
sed -e 's|^PROTODIR=.*|PROTODIR=${DESTDIR}/usr/include/g++/gen|' \
|
||||
-e 's|<VERSION>|2.4|' ${.ALLSRC} > ${.TARGET}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
.include "../../../usr.bin/Makefile.inc"
|
@ -1,452 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 1989 Free Software Foundation, Inc.
|
||||
#
|
||||
# genclass program enhanced by Wendell C. Baker
|
||||
# (original by Doug Lea (dl@rocky.oswego.edu))
|
||||
|
||||
#This file is part of GNU libg++.
|
||||
|
||||
#GNU libg++ is free software; you can redistribute it and/or modify
|
||||
#it under the terms of the GNU General Public License as published by
|
||||
#the Free Software Foundation; either version 1, or (at your option)
|
||||
#any later version.
|
||||
|
||||
#GNU libg++ is distributed in the hope that it will be useful,
|
||||
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
#GNU General Public License for more details.
|
||||
|
||||
#You should have received a copy of the GNU General Public License
|
||||
#along with GNU libg++; see the file COPYING. If not, write to
|
||||
#the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
|
||||
#
|
||||
# genclass -list [proto ...]
|
||||
# genclass -catalog [proto ...]
|
||||
# genclass type1 {ref|val} proto [out_prefix]
|
||||
# genclass -2 type1 {ref|val} type2 {ref, val} proto [out_prefix]
|
||||
#
|
||||
# Generate classes from prototypes
|
||||
#
|
||||
name=genclass ;
|
||||
usage="
|
||||
$name -list [proto ...]
|
||||
$name -catalog [proto ...]
|
||||
$name type1 {ref|val} proto [out_prefix]
|
||||
$name -2 type1 {ref|val} type2 {ref|val} proto [out_prefix]" ;
|
||||
|
||||
case "$1" in
|
||||
-usage)
|
||||
#
|
||||
# -usage
|
||||
#
|
||||
echo "usage: $usage" 1>&2 ;
|
||||
exit 0;
|
||||
;;
|
||||
-version)
|
||||
#
|
||||
# -version
|
||||
#
|
||||
# <VERSION> is substituted by the build process.
|
||||
# We currently use the libg++ version number (extracted from ../Makefile).
|
||||
echo "$name: version <VERSION>" ;
|
||||
exit 0;
|
||||
;;
|
||||
-requires)
|
||||
#
|
||||
# -requires
|
||||
#
|
||||
# The following line should contain any nonstandard programs
|
||||
# which must be in the users's path (i.e. not referenced by a
|
||||
# fullpath);it allows one to check a script for dependencies
|
||||
# without exhaustively testing its usages.
|
||||
# ... in this case genclass depends on nothing else.
|
||||
echo ;
|
||||
exit 0;
|
||||
;;
|
||||
esac ;
|
||||
|
||||
# pull it in from the environment
|
||||
[ "$TRACE" = "" ] || set -xv
|
||||
|
||||
# Search in standard g++ prototype directory and in the current directory
|
||||
# NOTE: this variable is edited by the install process
|
||||
PROTODIR=/projects/gnu-cygnus/gnu-cygnus-2/mips/lib/g++-include/gen
|
||||
|
||||
pwd=`pwd`
|
||||
|
||||
case "$1" in
|
||||
-catalog*|-list*)
|
||||
#
|
||||
# genclass -catalog [proto ...]
|
||||
# genclass -list [proto ...]
|
||||
#
|
||||
option="$1" ;
|
||||
shift ;
|
||||
|
||||
case $# in
|
||||
0)
|
||||
#
|
||||
# -catalog
|
||||
# -list
|
||||
#
|
||||
select=all ;
|
||||
select_pattern=p ;
|
||||
;;
|
||||
*)
|
||||
#
|
||||
# -catalog proto ...
|
||||
# -list proto ...
|
||||
#
|
||||
select="$@" ;
|
||||
select_pattern= ;
|
||||
for i in $@ ; do
|
||||
select_pattern="\
|
||||
$select_pattern
|
||||
/.*$i\$/ p
|
||||
" ;
|
||||
done ;
|
||||
|
||||
;;
|
||||
esac ;
|
||||
|
||||
#
|
||||
# select_pattern is now a (possibly-vacuous) newline-
|
||||
# separated list of patterns of the form:
|
||||
#
|
||||
# /.*Proto1$/ p
|
||||
# /.*Proto2$/ p
|
||||
# /.*Proto3$/ p
|
||||
#
|
||||
# or select_pattern is simply ``p'' to select everything
|
||||
|
||||
# Hmmm... not all systems have a fmt program; should we
|
||||
# just go ahead and use ``nroff -Tcrt | cat -s'' here?
|
||||
fmt='nroff -Tcrt | cat -s'
|
||||
#fmt=fmt ;
|
||||
|
||||
case "$option" in
|
||||
-catalog*)
|
||||
#
|
||||
# -catalog [proto ...]
|
||||
#
|
||||
echo "\
|
||||
Catalog of ${name} class templates
|
||||
directories searched:
|
||||
$PROTODIR
|
||||
$pwd
|
||||
selecting: $select
|
||||
classes available:" ;
|
||||
;;
|
||||
-list*)
|
||||
#
|
||||
# -list [proto ...]
|
||||
#
|
||||
# no need to do anything (the list is coming out next)
|
||||
;;
|
||||
esac ;
|
||||
|
||||
# The sed script does the following:
|
||||
# - If it does not end in a .ccP or .hP then
|
||||
# it's not a template and we are not intereseted.
|
||||
# - Get rid of pathname components [s;.*/;;]
|
||||
# - Just take the template names
|
||||
# - change quoting conventions and select off what we want to see
|
||||
# -if it did not pass the patterns, kill it
|
||||
|
||||
ls $pwd $PROTODIR | sed -e '
|
||||
/\.ccP$/ !{
|
||||
/\.hP$/ !{
|
||||
d
|
||||
}
|
||||
}
|
||||
s;.*/;;
|
||||
s/\.ccP$//
|
||||
s/\.hP$//
|
||||
' -e "$select_pattern
|
||||
d
|
||||
" | sort -u | case "$option" in
|
||||
-catalog*)
|
||||
# The library catalog information preceded the list
|
||||
# format the list, and tab in in a bit to make it readable.
|
||||
# Re-evaluate $fmt because it might contain a shell command
|
||||
eval $fmt | sed -e 's/.*/ &/' ;
|
||||
;;
|
||||
-list*)
|
||||
# nothing special, just let the sorted list dribble out
|
||||
# we must use cat to receive (and reproduce) the incoming list
|
||||
cat ;
|
||||
;;
|
||||
esac ;
|
||||
exit 0;
|
||||
;;
|
||||
-2)
|
||||
#
|
||||
# genclass -2 type1 {ref|val} type2 {ref|val} proto [out_prefix]
|
||||
#
|
||||
N=2 ;
|
||||
|
||||
case $# in
|
||||
6) # genclass -2 type1 {ref|val} type2 {ref|val} proto
|
||||
;;
|
||||
7) # genclass -2 type1 {ref|val} type2 {ref|val} proto out_prefix
|
||||
;;
|
||||
*)
|
||||
echo "usage: $usage" 1>&2 ;
|
||||
exit 1;
|
||||
esac ;
|
||||
shift ;
|
||||
;;
|
||||
*)
|
||||
#
|
||||
# genclass type1 {ref|val} proto [out_prefix]
|
||||
#
|
||||
N=1 ;
|
||||
|
||||
case $# in
|
||||
3) # genclass type1 {ref|val} proto
|
||||
;;
|
||||
4) # genclass type1 {ref|val} proto out_prefix
|
||||
;;
|
||||
*)
|
||||
echo "usage: $usage" 1>&2 ;
|
||||
exit 1;
|
||||
esac ;
|
||||
;;
|
||||
esac
|
||||
|
||||
#
|
||||
# Args are now (the point being the leading ``-2'' is gone)
|
||||
#
|
||||
# type1 {ref|val} proto [out_prefix]
|
||||
# type1 {ref|val} type2 {ref|val} proto [out_prefix]
|
||||
#
|
||||
|
||||
#
|
||||
# Quote all of the $1 $2 etc references to guard against
|
||||
# dynamic syntax errors due to vacuous arguments (i.e. '')
|
||||
# as sometimes occurs when genclass is used from a Makefile
|
||||
#
|
||||
|
||||
T1="$1";
|
||||
T1NAME="$T1." ;
|
||||
T1SEDNAME="$T1" ;
|
||||
|
||||
case "$2" in
|
||||
ref)
|
||||
T1ACC="\&" ;
|
||||
;;
|
||||
val)
|
||||
T1ACC=" " ;
|
||||
;;
|
||||
*)
|
||||
echo "${name}: Must specify type1 access as ref or val" 1>&2 ;
|
||||
echo "usage: $usage" 1>&2 ;
|
||||
exit 1;
|
||||
;;
|
||||
esac
|
||||
|
||||
# N is either 1 or 2
|
||||
|
||||
case $N in
|
||||
1)
|
||||
#
|
||||
# type1 {ref|val} proto [out_prefix]
|
||||
#
|
||||
class="$3" ;
|
||||
|
||||
T2="" ;
|
||||
T2ACC="" ;
|
||||
;;
|
||||
2)
|
||||
#
|
||||
# type1 {ref|val} type2 {ref|val} proto [out_prefix]
|
||||
#
|
||||
class="$5" ;
|
||||
|
||||
T2="$3";
|
||||
T2NAME="$T2." ;
|
||||
T2SEDNAME="$T2" ;
|
||||
|
||||
case "$4" in
|
||||
ref)
|
||||
T2ACC="\&" ;
|
||||
;;
|
||||
val)
|
||||
T2ACC=" " ;
|
||||
;;
|
||||
*)
|
||||
echo "${name}: Must specify type2 access: ref or val" 1>&2 ;
|
||||
echo "usage: $usage" 1>&2 ;
|
||||
exit 1;;
|
||||
esac;
|
||||
;;
|
||||
esac
|
||||
|
||||
defaultprefix="$T1NAME$T2NAME" ;
|
||||
|
||||
case $# in
|
||||
3) # type1 {ref|val} proto
|
||||
replaceprefix="N" ;
|
||||
prefix="$defaultprefix" ;
|
||||
;;
|
||||
5) # type1 {ref|val} type2 {ref|val} proto
|
||||
replaceprefix="N" ;
|
||||
prefix="$defaultprefix" ;
|
||||
;;
|
||||
4) # type1 {ref|val} proto out_prefix
|
||||
prefix="$4" ;
|
||||
replaceprefix="Y" ;
|
||||
;;
|
||||
6) # type1 {ref|val} type2 {ref|val} proto out_prefix
|
||||
prefix="$6" ;
|
||||
replaceprefix="Y" ;
|
||||
;;
|
||||
*)
|
||||
echo "${name}: too many arguments" 1>&2 ;
|
||||
echo "usage: $usage" 1>&2 ;
|
||||
exit 1;
|
||||
;;
|
||||
esac ;
|
||||
|
||||
src_h=$class.hP
|
||||
src_cc=$class.ccP
|
||||
out_h=$prefix$class.h;
|
||||
out_cc=$prefix$class.cc ;
|
||||
|
||||
#
|
||||
# Note #1: The .h and .cc parts are done separately
|
||||
# in case only a .h exists for the prototype
|
||||
#
|
||||
# Note #2: Bind the .h and .cc parts to the fullpath
|
||||
# directories at the same time to ensure consistency.
|
||||
#
|
||||
|
||||
if [ -f $pwd/$src_h ] ; then
|
||||
fullsrc_h=$pwd/$src_h ;
|
||||
fullsrc_cc=$pwd/$src_cc ;
|
||||
elif [ -f $PROTODIR/$src_h ] ; then
|
||||
fullsrc_h=$PROTODIR/$src_h ;
|
||||
fullsrc_cc=$PROTODIR/$src_cc ;
|
||||
else
|
||||
echo "${name}: there is no prototype for class $class - file $src_h" 1>&2 ;
|
||||
$0 -list ;
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
CASES="$N$replaceprefix" ;
|
||||
# CASES is one of { 2Y 2N 1Y 1N }
|
||||
|
||||
#
|
||||
# WATCHOUT - we have no way of checking whether or not
|
||||
# the proper case type is being used with the prototype.
|
||||
#
|
||||
# For example, we have no way of ensuring that any of
|
||||
# Map variants are specified with the -2 argument set
|
||||
# Further, we have no way of ensuring that -2 is not
|
||||
# used with the prototypes which require only one.
|
||||
#
|
||||
# The second problem is not serious because it still
|
||||
# results in correctly-generated C++ code; the first
|
||||
# problem is serious because it results in C++ code that
|
||||
# still has ``<C>'' and ``<C&>'' syntax inside it. Such
|
||||
# code of course will not compile.
|
||||
#
|
||||
# SO THE BEST WE CAN DO - is check for the presence of
|
||||
# <C> and <C&> AFTER the thing has been generated.
|
||||
#
|
||||
|
||||
case $CASES in
|
||||
2Y) # Two output substitutions, change the prefix
|
||||
sed < $fullsrc_h > $out_h -e "
|
||||
s/<T>/$T1/g
|
||||
s/<T&>/$T1$T1ACC/g
|
||||
s/<C>/$T2/g
|
||||
s/<C&>/$T2$T2ACC/g
|
||||
s/$T1SEDNAME\.$T2SEDNAME\./$prefix/g
|
||||
s/$T1SEDNAME\./$prefix/g
|
||||
s/$T2SEDNAME\./$prefix/g
|
||||
" ;
|
||||
;;
|
||||
2N) # Two output substitutions, use the default prefix
|
||||
sed < $fullsrc_h > $out_h -e "
|
||||
s/<T>/$T1/g
|
||||
s/<T&>/$T1$T1ACC/g
|
||||
s/<C>/$T2/g
|
||||
s/<C&>/$T2$T2ACC/g
|
||||
" ;
|
||||
;;
|
||||
1Y) # One output substitution, change the prefix
|
||||
sed < $fullsrc_h > $out_h -e "
|
||||
s/<T>/$T1/g
|
||||
s/<T&>/$T1$T1ACC/g
|
||||
s/$T1SEDNAME\./$prefix/g
|
||||
" ;
|
||||
;;
|
||||
1N) # One output substitution, use the default prefix
|
||||
sed < $fullsrc_h > $out_h -e "
|
||||
s/<T>/$T1/g
|
||||
s/<T&>/$T1$T1ACC/g
|
||||
" ;
|
||||
;;
|
||||
esac
|
||||
|
||||
if egrep '<C&?>' $out_h > /dev/null ; then
|
||||
echo "${name}: the $class class requires the -2 syntax for the 2nd type" 1>&2 ;
|
||||
echo "usage: $usage" 1>&2 ;
|
||||
# the user does not get to see the mistakes (he might try to compile it)
|
||||
rm $out_h ;
|
||||
exit 1;
|
||||
fi ;
|
||||
|
||||
if [ ! -f $fullsrc_cc ] ; then
|
||||
echo "${name}: warning, class has a .h but no .cc file" 1>&2 ;
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
case $CASES in
|
||||
2Y) # Two output substitutions, change the prefix
|
||||
sed < $fullsrc_cc > $out_cc -e "
|
||||
s/<T>/$T1/g
|
||||
s/<T&>/$T1$T1ACC/g
|
||||
s/<C>/$T2/g
|
||||
s/<C&>/$T2$T2ACC/g
|
||||
s/$T1SEDNAME\.$T2SEDNAME\./$prefix/g
|
||||
s/$T1SEDNAME\./$prefix/g
|
||||
s/$T2SEDNAME\./$prefix/g
|
||||
"
|
||||
;;
|
||||
2N) # Two output substitutions, use the default prefix
|
||||
sed < $fullsrc_cc > $out_cc -e "
|
||||
s/<T>/$T1/g
|
||||
s/<T&>/$T1$T1ACC/g
|
||||
s/<C>/$T2/g
|
||||
s/<C&>/$T2$T2ACC/g
|
||||
"
|
||||
;;
|
||||
1Y) # One output substitution, change the prefix
|
||||
sed < $fullsrc_cc > $out_cc -e "
|
||||
s/<T>/$T1/g
|
||||
s/<T&>/$T1$T1ACC/g
|
||||
s/$T1SEDNAME\./$prefix/g
|
||||
"
|
||||
;;
|
||||
1N) # One output substitution, use the default prefix
|
||||
sed < $fullsrc_cc > $out_cc -e "
|
||||
s/<T>/$T1/g
|
||||
s/<T&>/$T1$T1ACC/g
|
||||
"
|
||||
;;
|
||||
esac
|
||||
|
||||
if egrep '<C&?>' $out_h $out_cc > /dev/null ; then
|
||||
echo "${name}: the $class class requires the -2 syntax for the 2nd type" 1>&2 ;
|
||||
echo "usage: $usage" 1>&2 ;
|
||||
# the user does not get to see the mistakes (he might try to compile it)
|
||||
rm $out_h $out_cc ;
|
||||
exit 1;
|
||||
fi ;
|
||||
|
||||
exit 0;
|
@ -1,130 +0,0 @@
|
||||
// This may look like C code, but it is really -*- C++ -*-
|
||||
/*
|
||||
Copyright (C) 1988, 1992 Free Software Foundation
|
||||
written by Doug Lea (dl@rocky.oswego.edu)
|
||||
converted to use iostream library by Per Bothner (bothner@cygnus.com)
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY. No author or distributor
|
||||
accepts responsibility to anyone for the consequences of using it
|
||||
or for whether it serves any particular purpose or works at all,
|
||||
unless he says so in writing. Refer to the GNU CC General Public
|
||||
License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute
|
||||
GNU CC, but only under the conditions described in the
|
||||
GNU CC General Public License. A copy of this license is
|
||||
supposed to have been given to you along with GNU CC so you
|
||||
can know your rights and responsibilities. It should be in a
|
||||
file named COPYING. Among other things, the copyright notice
|
||||
and this notice must be preserved on all copies.
|
||||
*/
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#endif
|
||||
#include <PlotFile.h>
|
||||
|
||||
/*
|
||||
PlotFile implementation module
|
||||
*/
|
||||
|
||||
|
||||
PlotFile& PlotFile:: cmd(char c)
|
||||
{
|
||||
ofstream::put(c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PlotFile& PlotFile:: operator<<(const int x)
|
||||
{
|
||||
#if defined(convex)
|
||||
ofstream::put((char)(x>>8));
|
||||
ofstream::put((char)(x&0377));
|
||||
#else
|
||||
ofstream::put((char)(x&0377));
|
||||
ofstream::put((char)(x>>8));
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
PlotFile& PlotFile:: operator<<(const char *s)
|
||||
{
|
||||
*(ofstream*)this << s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PlotFile& PlotFile:: arc(const int xi, const int yi,
|
||||
const int x0, const int y0,
|
||||
const int x1, const int y1)
|
||||
{
|
||||
return cmd('a') << xi << yi << x0 << y0 << x1 << y1;
|
||||
}
|
||||
|
||||
|
||||
PlotFile& PlotFile:: box(const int x0, const int y0,
|
||||
const int x1, const int y1)
|
||||
{
|
||||
line(x0, y0, x0, y1);
|
||||
line(x0, y1, x1, y1);
|
||||
line(x1, y1, x1, y0);
|
||||
return line(x1, y0, x0, y0);
|
||||
}
|
||||
|
||||
PlotFile& PlotFile:: circle(const int x, const int y, const int r)
|
||||
{
|
||||
return cmd('c') << x << y << r;
|
||||
}
|
||||
|
||||
PlotFile& PlotFile:: cont(const int xi, const int yi)
|
||||
{
|
||||
return cmd('n') << xi << yi;
|
||||
}
|
||||
|
||||
PlotFile& PlotFile:: dot(const int xi, const int yi, const int dx,
|
||||
int n, const int* pat)
|
||||
{
|
||||
cmd('d') << xi << yi << dx << n;
|
||||
while (n-- > 0) *this << *pat++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PlotFile& PlotFile:: erase()
|
||||
{
|
||||
return cmd('e');
|
||||
}
|
||||
|
||||
PlotFile& PlotFile:: label(const char* s)
|
||||
{
|
||||
return cmd('t') << s << "\n";
|
||||
}
|
||||
|
||||
PlotFile& PlotFile:: line(const int x0, const int y0,
|
||||
const int x1, const int y1)
|
||||
{
|
||||
return cmd('l') << x0 << y0 << x1 << y1;
|
||||
}
|
||||
|
||||
PlotFile& PlotFile:: linemod(const char* s)
|
||||
{
|
||||
return cmd('f') << s << "\n";
|
||||
}
|
||||
|
||||
PlotFile& PlotFile:: move(const int xi, const int yi)
|
||||
{
|
||||
return cmd('m') << xi << yi;
|
||||
}
|
||||
|
||||
PlotFile& PlotFile:: point(const int xi, const int yi)
|
||||
{
|
||||
return cmd('p') << xi << yi;
|
||||
}
|
||||
|
||||
PlotFile& PlotFile:: space(const int x0, const int y0,
|
||||
const int x1, const int y1)
|
||||
{
|
||||
return cmd('s') << x0 << y0 << x1 << y1;
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
// This may look like C code, but it is really -*- C++ -*-
|
||||
/*
|
||||
Copyright (C) 1988, 1992 Free Software Foundation
|
||||
written by Doug Lea (dl@rocky.oswego.edu)
|
||||
converted to use iostream library by Per Bothner (bothner@cygnus.com)
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY. No author or distributor
|
||||
accepts responsibility to anyone for the consequences of using it
|
||||
or for whether it serves any particular purpose or works at all,
|
||||
unless he says so in writing. Refer to the GNU CC General Public
|
||||
License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute
|
||||
GNU CC, but only under the conditions described in the
|
||||
GNU CC General Public License. A copy of this license is
|
||||
supposed to have been given to you along with GNU CC so you
|
||||
can know your rights and responsibilities. It should be in a
|
||||
file named COPYING. Among other things, the copyright notice
|
||||
and this notice must be preserved on all copies.
|
||||
|
||||
$Id: PlotFile.h,v 1.2 1993/08/02 17:22:28 mycroft Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
a very simple implementation of a class to output unix "plot"
|
||||
format plotter files. See corresponding unix man pages for
|
||||
more details.
|
||||
*/
|
||||
|
||||
#ifndef _PlotFile_h
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
#define _PlotFile_h
|
||||
|
||||
#include <fstream.h>
|
||||
|
||||
/*
|
||||
Some plot libraries have the `box' command to draw boxes. Some don't.
|
||||
`box' is included here via moves & lines to allow both possiblilties.
|
||||
*/
|
||||
|
||||
|
||||
class PlotFile : public ofstream
|
||||
{
|
||||
protected:
|
||||
PlotFile& cmd(char c);
|
||||
PlotFile& operator << (const int x);
|
||||
PlotFile& operator << (const char *s);
|
||||
|
||||
public:
|
||||
|
||||
PlotFile() : ofstream() { }
|
||||
PlotFile(int fd) : ofstream(fd) { }
|
||||
PlotFile(const char *name, int mode=ios::out, int prot=0664)
|
||||
: ofstream(name, mode, prot) { }
|
||||
|
||||
// PlotFile& remove() { ofstream::remove(); return *this; }
|
||||
|
||||
// int filedesc() { return ofstream::filedesc(); }
|
||||
// const char* name() { return File::name(); }
|
||||
// void setname(const char* newname) { File::setname(newname); }
|
||||
// int iocount() { return File::iocount(); }
|
||||
|
||||
PlotFile& arc(const int xi, const int yi,
|
||||
const int x0, const int y0,
|
||||
const int x1, const int y1);
|
||||
PlotFile& box(const int x0, const int y0,
|
||||
const int x1, const int y1);
|
||||
PlotFile& circle(const int x, const int y, const int r);
|
||||
PlotFile& cont(const int xi, const int yi);
|
||||
PlotFile& dot(const int xi, const int yi, const int dx,
|
||||
int n, const int* pat);
|
||||
PlotFile& erase();
|
||||
PlotFile& label(const char* s);
|
||||
PlotFile& line(const int x0, const int y0,
|
||||
const int x1, const int y1);
|
||||
PlotFile& linemod(const char* s);
|
||||
PlotFile& move(const int xi, const int yi);
|
||||
PlotFile& point(const int xi, const int yi);
|
||||
PlotFile& space(const int x0, const int y0,
|
||||
const int x1, const int y1);
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 1988 Free Software Foundation
|
||||
written by Doug Lea (dl@rocky.oswego.edu)
|
||||
|
||||
This file is part of the GNU C++ Library. This library is free
|
||||
software; you can redistribute it and/or modify it under the terms of
|
||||
the GNU Library General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version. This library is distributed in the hope
|
||||
that it will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU Library General Public License for more details.
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#endif
|
||||
#include <SFile.h>
|
||||
|
||||
SFile::SFile(const char *filename, int size, int mode, int prot)
|
||||
: fstream(filename, mode, prot)
|
||||
{
|
||||
sz = size;
|
||||
}
|
||||
|
||||
SFile::SFile(int fd, int size)
|
||||
: fstream(fd)
|
||||
{
|
||||
sz = size;
|
||||
}
|
||||
|
||||
void SFile::open(const char *name, int size, int mode, int prot)
|
||||
{
|
||||
fstream::open(name, mode, prot);
|
||||
sz = size;
|
||||
}
|
||||
|
||||
SFile& SFile::get(void* x)
|
||||
{
|
||||
read(x, sz);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SFile& SFile::put(void* x)
|
||||
{
|
||||
write(x, sz);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SFile& SFile::operator[](long i)
|
||||
{
|
||||
if (rdbuf()->seekoff(i * sz, ios::beg) == EOF)
|
||||
set(ios::badbit);
|
||||
return *this;
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
// This may look like C code, but it is really -*- C++ -*-
|
||||
/*
|
||||
Copyright (C) 1988, 1992 Free Software Foundation
|
||||
written by Doug Lea (dl@rocky.oswego.edu)
|
||||
|
||||
This file is part of the GNU C++ Library. This library is free
|
||||
software; you can redistribute it and/or modify it under the terms of
|
||||
the GNU Library General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version. This library is distributed in the hope
|
||||
that it will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU Library General Public License for more details.
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: SFile.h,v 1.2 1993/08/02 17:22:29 mycroft Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SFile_h
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
#define _SFile_h 1
|
||||
|
||||
#include <fstream.h>
|
||||
|
||||
class SFile: public fstream
|
||||
{
|
||||
protected:
|
||||
int sz; // unit size for structured binary IO
|
||||
|
||||
public:
|
||||
SFile() : fstream() { }
|
||||
SFile(int fd, int size);
|
||||
SFile(const char *name, int size, int mode, int prot=0664);
|
||||
void open(const char *name, int size, int mode, int prot=0664);
|
||||
|
||||
int size() { return sz; }
|
||||
int setsize(int s) { int old = sz; sz = s; return old; }
|
||||
|
||||
SFile& get(void* x);
|
||||
SFile& put(void* x);
|
||||
SFile& operator[](long i);
|
||||
};
|
||||
|
||||
#endif
|
@ -1,707 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1991 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#endif
|
||||
#include "ioprivate.h"
|
||||
#include "editbuf.h"
|
||||
#include <stddef.h>
|
||||
|
||||
/* NOTE: Some of the code here is taken from GNU emacs */
|
||||
/* Hence this file falls under the GNU License! */
|
||||
|
||||
// Invariants for edit_streambuf:
|
||||
// An edit_streambuf is associated with a specific edit_string,
|
||||
// which again is a sub-string of a specific edit_buffer.
|
||||
// An edit_streambuf is always in either get mode or put mode, never both.
|
||||
// In get mode, gptr() is the current position,
|
||||
// and pbase(), pptr(), and epptr() are all NULL.
|
||||
// In put mode, pptr() is the current position,
|
||||
// and eback(), gptr(), and egptr() are all NULL.
|
||||
// Any edit_streambuf that is actively doing insertion (as opposed to
|
||||
// replacing) // must have its pptr() pointing to the start of the gap.
|
||||
// Only one edit_streambuf can be actively inserting into a specific
|
||||
// edit_buffer; the edit_buffer's _writer field points to that edit_streambuf.
|
||||
// That edit_streambuf "owns" the gap, and the actual start of the
|
||||
// gap is the pptr() of the edit_streambuf; the edit_buffer::_gap_start pointer
|
||||
// will only be updated on an edit_streambuf::overflow().
|
||||
|
||||
int edit_streambuf::truncate()
|
||||
{
|
||||
str->buffer->delete_range(str->buffer->tell((buf_char*)pptr()),
|
||||
str->buffer->tell(str->end));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef OLD_STDIO
|
||||
inline void disconnect_gap_from_file(edit_buffer* buffer, FILE* fp)
|
||||
{
|
||||
if (buffer->gap_start_ptr != &fp->__bufp)
|
||||
return;
|
||||
buffer->gap_start_normal = fp->__bufp;
|
||||
buffer->gap_start_ptr = &buffer->gap_start_normal;
|
||||
}
|
||||
#endif
|
||||
|
||||
void edit_streambuf::flush_to_buffer(edit_buffer* buffer)
|
||||
{
|
||||
if (pptr() > buffer->_gap_start && pptr() < buffer->gap_end())
|
||||
buffer->_gap_start = pptr();
|
||||
}
|
||||
|
||||
void edit_streambuf::disconnect_gap_from_file(edit_buffer* buffer)
|
||||
{
|
||||
if (buffer->_writer != this) return;
|
||||
flush_to_buffer(buffer);
|
||||
setp(pptr(),pptr());
|
||||
buffer->_writer = NULL;
|
||||
}
|
||||
|
||||
buf_index edit_buffer::tell(buf_char *ptr)
|
||||
{
|
||||
if (ptr <= gap_start())
|
||||
return ptr - data;
|
||||
else
|
||||
return ptr - gap_end() + size1();
|
||||
}
|
||||
|
||||
#if 0
|
||||
buf_index buf_cookie::tell()
|
||||
{
|
||||
return str->buffer->tell(file->__bufp);
|
||||
}
|
||||
#endif
|
||||
|
||||
buf_index edit_buffer::tell(edit_mark*mark)
|
||||
{
|
||||
return tell(data + mark->index_in_buffer(this));
|
||||
}
|
||||
|
||||
// adjust the position of the gap
|
||||
|
||||
void edit_buffer::move_gap(buf_offset pos)
|
||||
{
|
||||
if (pos < size1())
|
||||
gap_left (pos);
|
||||
else if (pos > size1())
|
||||
gap_right (pos);
|
||||
}
|
||||
|
||||
void edit_buffer::gap_left (int pos)
|
||||
{
|
||||
register buf_char *to, *from;
|
||||
register int i;
|
||||
int new_s1;
|
||||
|
||||
i = size1();
|
||||
from = gap_start();
|
||||
to = from + gap_size();
|
||||
new_s1 = size1();
|
||||
|
||||
/* Now copy the characters. To move the gap down,
|
||||
copy characters up. */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* I gets number of characters left to copy. */
|
||||
i = new_s1 - pos;
|
||||
if (i == 0)
|
||||
break;
|
||||
#if 0
|
||||
/* If a quit is requested, stop copying now.
|
||||
Change POS to be where we have actually moved the gap to. */
|
||||
if (QUITP)
|
||||
{
|
||||
pos = new_s1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* Move at most 32000 chars before checking again for a quit. */
|
||||
if (i > 32000)
|
||||
i = 32000;
|
||||
new_s1 -= i;
|
||||
while (--i >= 0)
|
||||
*--to = *--from;
|
||||
}
|
||||
|
||||
/* Adjust markers, and buffer data structure, to put the gap at POS.
|
||||
POS is where the loop above stopped, which may be what was specified
|
||||
or may be where a quit was detected. */
|
||||
adjust_markers (pos << 1, size1() << 1, gap_size(), data);
|
||||
#ifndef OLD_STDIO
|
||||
_gap_start = data + pos;
|
||||
#else
|
||||
if (gap_start_ptr == &gap_start_normal)
|
||||
gap_start_normal = data + pos;
|
||||
#endif
|
||||
__gap_end_pos = to - data;
|
||||
/* QUIT;*/
|
||||
}
|
||||
|
||||
void edit_buffer::gap_right (int pos)
|
||||
{
|
||||
register buf_char *to, *from;
|
||||
register int i;
|
||||
int new_s1;
|
||||
|
||||
i = size1();
|
||||
to = gap_start();
|
||||
from = i + gap_end();
|
||||
new_s1 = i;
|
||||
|
||||
/* Now copy the characters. To move the gap up,
|
||||
copy characters down. */
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* I gets number of characters left to copy. */
|
||||
i = pos - new_s1;
|
||||
if (i == 0)
|
||||
break;
|
||||
#if 0
|
||||
/* If a quit is requested, stop copying now.
|
||||
Change POS to be where we have actually moved the gap to. */
|
||||
if (QUITP)
|
||||
{
|
||||
pos = new_s1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* Move at most 32000 chars before checking again for a quit. */
|
||||
if (i > 32000)
|
||||
i = 32000;
|
||||
new_s1 += i;
|
||||
while (--i >= 0)
|
||||
*to++ = *from++;
|
||||
}
|
||||
|
||||
adjust_markers ((size1() + gap_size()) << 1, (pos + gap_size()) << 1,
|
||||
- gap_size(), data);
|
||||
#ifndef OLD_STDIO
|
||||
_gap_start = data+pos;
|
||||
#else
|
||||
if (gap_start_ptr == &gap_start_normal)
|
||||
gap_start_normal = data + pos;
|
||||
#endif
|
||||
__gap_end_pos = from - data;
|
||||
/* QUIT;*/
|
||||
}
|
||||
|
||||
/* make sure that the gap in the current buffer is at least k
|
||||
characters wide */
|
||||
|
||||
void edit_buffer::make_gap(buf_offset k)
|
||||
{
|
||||
register buf_char *p1, *p2, *lim;
|
||||
buf_char *old_data = data;
|
||||
int s1 = size1();
|
||||
|
||||
if (gap_size() >= k)
|
||||
return;
|
||||
|
||||
/* Get more than just enough */
|
||||
if (buf_size > 1000) k += 2000;
|
||||
else k += /*200;*/ 20; // for testing!
|
||||
|
||||
p1 = (buf_char *) realloc (data, s1 + size2() + k);
|
||||
if (p1 == 0)
|
||||
abort(); /*memory_full ();*/
|
||||
|
||||
k -= gap_size(); /* Amount of increase. */
|
||||
|
||||
/* Record new location of text */
|
||||
data = p1;
|
||||
|
||||
/* Transfer the new free space from the end to the gap
|
||||
by shifting the second segment upward */
|
||||
p2 = data + buf_size;
|
||||
p1 = p2 + k;
|
||||
lim = p2 - size2();
|
||||
while (lim < p2)
|
||||
*--p1 = *--p2;
|
||||
|
||||
/* Finish updating text location data */
|
||||
__gap_end_pos += k;
|
||||
|
||||
#ifndef OLD_STDIO
|
||||
_gap_start = data + s1;
|
||||
#else
|
||||
if (gap_start_ptr == &gap_start_normal)
|
||||
gap_start_normal = data + s1;
|
||||
#endif
|
||||
|
||||
/* adjust markers */
|
||||
adjust_markers (s1 << 1, (buf_size << 1) + 1, k, old_data);
|
||||
buf_size += k;
|
||||
}
|
||||
|
||||
/* Add `amount' to the position of every marker in the current buffer
|
||||
whose current position is between `from' (exclusive) and `to' (inclusive).
|
||||
Also, any markers past the outside of that interval, in the direction
|
||||
of adjustment, are first moved back to the near end of the interval
|
||||
and then adjusted by `amount'. */
|
||||
|
||||
void edit_buffer::adjust_markers(register mark_pointer low,
|
||||
register mark_pointer high,
|
||||
int amount, buf_char *old_data)
|
||||
{
|
||||
register struct edit_mark *m;
|
||||
register mark_pointer mpos;
|
||||
/* convert to mark_pointer */
|
||||
amount <<= 1;
|
||||
|
||||
if (_writer)
|
||||
_writer->disconnect_gap_from_file(this);
|
||||
|
||||
for (m = mark_list(); m != NULL; m = m->chain)
|
||||
{
|
||||
mpos = m->_pos;
|
||||
if (amount > 0)
|
||||
{
|
||||
if (mpos > high && mpos < high + amount)
|
||||
mpos = high + amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mpos > low + amount && mpos <= low)
|
||||
mpos = low + amount;
|
||||
}
|
||||
if (mpos > low && mpos <= high)
|
||||
mpos += amount;
|
||||
m->_pos = mpos;
|
||||
}
|
||||
|
||||
// Now adjust files
|
||||
edit_streambuf *file;
|
||||
|
||||
for (file = files; file != NULL; file = file->next) {
|
||||
mpos = file->current() - old_data;
|
||||
if (amount > 0)
|
||||
{
|
||||
if (mpos > high && mpos < high + amount)
|
||||
mpos = high + amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mpos > low + amount && mpos <= low)
|
||||
mpos = low + amount;
|
||||
}
|
||||
if (mpos > low && mpos <= high)
|
||||
mpos += amount;
|
||||
char* new_pos = data + mpos;
|
||||
file->set_current(new_pos, file->is_reading());
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
stdio_
|
||||
__off == index at start of buffer (need only be valid after seek ? )
|
||||
__buf ==
|
||||
|
||||
if read/read_delete/overwrite mode:
|
||||
__endp <= min(*gap_start_ptr, edit_string->end->ptr(buffer))
|
||||
|
||||
if inserting:
|
||||
must have *gap_start_ptr == __bufp && *gap_start_ptr+gap == __endp
|
||||
file->edit_string->end->ptr(buffer) == *gap_start_ptr+end
|
||||
if write_mode:
|
||||
if before gap
|
||||
#endif
|
||||
|
||||
int edit_streambuf::underflow()
|
||||
{
|
||||
if (!(_mode & ios::in))
|
||||
return EOF;
|
||||
struct edit_buffer *buffer = str->buffer;
|
||||
if (!is_reading()) { // Must switch from put to get mode.
|
||||
disconnect_gap_from_file(buffer);
|
||||
set_current(pptr(), 1);
|
||||
}
|
||||
buf_char *str_end = str->end->ptr(buffer);
|
||||
retry:
|
||||
if (gptr() < egptr()) {
|
||||
return *gptr();
|
||||
}
|
||||
if ((buf_char*)gptr() == str_end)
|
||||
return EOF;
|
||||
if (str_end <= buffer->gap_start()) {
|
||||
setg(eback(), gptr(), str_end);
|
||||
goto retry;
|
||||
}
|
||||
if (gptr() < buffer->gap_start()) {
|
||||
setg(eback(), gptr(), buffer->gap_start());
|
||||
goto retry;
|
||||
}
|
||||
if (gptr() == buffer->gap_start()) {
|
||||
disconnect_gap_from_file(buffer);
|
||||
// fp->__offset += fp->__bufp - fp->__buffer;
|
||||
setg(buffer->gap_end(), buffer->gap_end(), str_end);
|
||||
}
|
||||
else
|
||||
setg(eback(), gptr(), str_end);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
int edit_streambuf::overflow(int ch)
|
||||
{
|
||||
if (_mode == ios::in)
|
||||
return EOF;
|
||||
struct edit_buffer *buffer = str->buffer;
|
||||
flush_to_buffer(buffer);
|
||||
if (ch == EOF)
|
||||
return 0;
|
||||
if (is_reading()) { // Must switch from get to put mode.
|
||||
set_current(gptr(), 0);
|
||||
}
|
||||
buf_char *str_end = str->end->ptr(buffer);
|
||||
retry:
|
||||
if (pptr() < epptr()) {
|
||||
*pptr() = ch;
|
||||
pbump(1);
|
||||
return (unsigned char)ch;
|
||||
}
|
||||
if ((buf_char*)pptr() == str_end || inserting()) {
|
||||
/* insert instead */
|
||||
if (buffer->_writer)
|
||||
buffer->_writer->flush_to_buffer(); // Redundant?
|
||||
buffer->_writer = NULL;
|
||||
if (pptr() >= buffer->gap_end())
|
||||
buffer->move_gap(pptr() - buffer->gap_size());
|
||||
else
|
||||
buffer->move_gap(pptr());
|
||||
buffer->make_gap(1);
|
||||
setp(buffer->gap_start(), buffer->gap_end());
|
||||
buffer->_writer = this;
|
||||
*pptr() = ch;
|
||||
pbump(1);
|
||||
return (unsigned char)ch;
|
||||
}
|
||||
if (str_end <= buffer->gap_start()) {
|
||||
// Entire string is left of gap.
|
||||
setp(pptr(), str_end);
|
||||
}
|
||||
else if (pptr() < buffer->gap_start()) {
|
||||
// Current pos is left of gap.
|
||||
setp(pptr(), buffer->gap_start());
|
||||
goto retry;
|
||||
}
|
||||
else if (pptr() == buffer->gap_start()) {
|
||||
// Current pos is at start of gap; move to end of gap.
|
||||
// disconnect_gap_from_file(buffer);
|
||||
setp(buffer->gap_end(), str_end);
|
||||
// __offset += __bufp - __buffer;
|
||||
}
|
||||
else {
|
||||
// Otherwise, current pos is right of gap.
|
||||
setp(pptr(), str_end);
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
|
||||
void edit_streambuf::set_current(char *new_pos, int reading)
|
||||
{
|
||||
if (reading) {
|
||||
setg(new_pos, new_pos, new_pos);
|
||||
setp(NULL, NULL);
|
||||
}
|
||||
else {
|
||||
setg(NULL, NULL, NULL);
|
||||
setp(new_pos, new_pos);
|
||||
}
|
||||
}
|
||||
|
||||
// Called by fseek(fp, pos, whence) if fp is bound to a edit_buffer.
|
||||
|
||||
streampos edit_streambuf::seekoff(streamoff offset, _seek_dir dir,
|
||||
int mode /* =ios::in|ios::out*/)
|
||||
{
|
||||
struct edit_buffer *buffer = str->buffer;
|
||||
disconnect_gap_from_file(buffer);
|
||||
buf_index cur_pos = buffer->tell((buf_char*)current());;
|
||||
buf_index start_pos = buffer->tell(str->start);
|
||||
buf_index end_pos = buffer->tell(str->end);
|
||||
switch (dir) {
|
||||
case ios::beg:
|
||||
offset += start_pos;
|
||||
break;
|
||||
case ios::cur:
|
||||
offset += cur_pos;
|
||||
break;
|
||||
case ios::end:
|
||||
offset += end_pos;
|
||||
break;
|
||||
}
|
||||
if (offset < start_pos || offset > end_pos)
|
||||
return EOF;
|
||||
buf_char *new_pos = buffer->data + offset;
|
||||
buf_char* gap_start = buffer->gap_start();
|
||||
if (new_pos > gap_start) {
|
||||
buf_char* gap_end = buffer->gap_end();
|
||||
new_pos += gap_end - gap_start;
|
||||
if (new_pos >= buffer->data + buffer->buf_size) abort(); // Paranoia.
|
||||
}
|
||||
set_current(new_pos, is_reading());
|
||||
return EOF;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int buf_seek(void *arg_cookie, fpos_t * pos, int whence)
|
||||
{
|
||||
struct buf_cookie *cookie = arg_cookie;
|
||||
FILE *file = cookie->file;
|
||||
struct edit_buffer *buffer = cookie->str->buffer;
|
||||
buf_char *str_start = cookie->str->start->ptr(buffer);
|
||||
disconnect_gap_from_file(buffer, cookie->file);
|
||||
fpos_t cur_pos, new_pos;
|
||||
if (file->__bufp <= *buffer->gap_start_ptr
|
||||
|| str_start >= buffer->__gap_end)
|
||||
cur_pos = str_start - file->__bufp;
|
||||
else
|
||||
cur_pos =
|
||||
(*buffer->gap_start_ptr - str_start) + (file->__bufp - __gap_end);
|
||||
end_pos = ...;
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
new_pos = *pos;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
new_pos = cur_pos + *pos;
|
||||
break;
|
||||
case SEEK_END:
|
||||
new_pos = end_pos + *pos;
|
||||
break;
|
||||
}
|
||||
if (new_pos > end_pos) {
|
||||
seek to end_pos;
|
||||
insert_nulls(new_pos - end_pos);
|
||||
return;
|
||||
}
|
||||
if (str_start + new_pos <= *gap_start_ptr &* *gap_start_ptr < end) {
|
||||
__buffer = str_start;
|
||||
__off = 0;
|
||||
__bufp = str_start + new_pos;
|
||||
file->__get_limit =
|
||||
*buffer->gap_start_ptr; /* what if gap_start_ptr == &bufp ??? */
|
||||
} else if () {
|
||||
|
||||
}
|
||||
*pos = new_pos;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Delete characters from `from' up to (but not incl) `to' */
|
||||
|
||||
void edit_buffer::delete_range (buf_index from, buf_index to)
|
||||
{
|
||||
register int numdel;
|
||||
|
||||
if ((numdel = to - from) <= 0)
|
||||
return;
|
||||
|
||||
/* Make sure the gap is somewhere in or next to what we are deleting */
|
||||
if (from > size1())
|
||||
gap_right (from);
|
||||
if (to < size1())
|
||||
gap_left (to);
|
||||
|
||||
/* Relocate all markers pointing into the new, larger gap
|
||||
to point at the end of the text before the gap. */
|
||||
adjust_markers ((to + gap_size()) << 1, (to + gap_size()) << 1,
|
||||
- numdel - gap_size(), data);
|
||||
|
||||
__gap_end_pos = to + gap_size();
|
||||
_gap_start = data + from;
|
||||
}
|
||||
|
||||
void edit_buffer::delete_range(struct edit_mark *start, struct edit_mark *end)
|
||||
{
|
||||
delete_range(tell(start), tell(end));
|
||||
}
|
||||
|
||||
void buf_delete_chars(struct edit_buffer *buf, struct edit_mark *mark, size_t count)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
edit_streambuf::edit_streambuf(edit_string* bstr, int mode)
|
||||
{
|
||||
_mode = mode;
|
||||
str = bstr;
|
||||
edit_buffer* buffer = bstr->buffer;
|
||||
next = buffer->files;
|
||||
buffer->files = this;
|
||||
char* buf_ptr = bstr->start->ptr(buffer);
|
||||
_inserting = 0;
|
||||
// setb(buf_ptr, buf_ptr, 0);
|
||||
set_current(buf_ptr, !(mode & ios::out+ios::trunc+ios::app));
|
||||
if (_mode & ios::trunc)
|
||||
truncate();
|
||||
if (_mode & ios::ate)
|
||||
seekoff(0, ios::end);
|
||||
}
|
||||
|
||||
// Called by fclose(fp) if fp is bound to a edit_buffer.
|
||||
|
||||
#if 0
|
||||
static int buf_close(void *arg)
|
||||
{
|
||||
register struct buf_cookie *cookie = arg;
|
||||
struct edit_buffer *buffer = cookie->str->buffer;
|
||||
struct buf_cookie **ptr;
|
||||
for (ptr = &buffer->files; *ptr != cookie; ptr = &(*ptr)->next) ;
|
||||
*ptr = cookie->next;
|
||||
disconnect_gap_from_file(buffer, cookie->file);
|
||||
free (cookie);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
edit_streambuf::~edit_streambuf()
|
||||
{
|
||||
if (_mode == ios::out)
|
||||
truncate();
|
||||
// Unlink this from list of files associated with bstr->buffer.
|
||||
edit_streambuf **ptr = &str->buffer->files;
|
||||
for (; *ptr != this; ptr = &(*ptr)->next) { }
|
||||
*ptr = next;
|
||||
|
||||
disconnect_gap_from_file(str->buffer);
|
||||
}
|
||||
|
||||
edit_buffer::edit_buffer()
|
||||
{
|
||||
buf_size = /*200;*/ 15; /* for testing! */
|
||||
data = (buf_char*)malloc(buf_size);
|
||||
files = NULL;
|
||||
#ifndef OLD_STDIO
|
||||
_gap_start = data;
|
||||
_writer = NULL;
|
||||
#else
|
||||
gap_start_normal = data;
|
||||
gap_start_ptr = &gap_start_normal;
|
||||
#endif
|
||||
__gap_end_pos = buf_size;
|
||||
start_mark.chain = &end_mark;
|
||||
start_mark._pos = 0;
|
||||
end_mark.chain = NULL;
|
||||
end_mark._pos = 2 * buf_size + 1;
|
||||
}
|
||||
|
||||
// Allocate a new mark, which is adjusted by 'delta' bytes from 'this'.
|
||||
// Restrict new mark to lie within 'str'.
|
||||
|
||||
edit_mark::edit_mark(struct edit_string *str, long delta)
|
||||
{
|
||||
struct edit_buffer *buf = str->buffer;
|
||||
chain = buf->start_mark.chain;
|
||||
buf->start_mark.chain = this;
|
||||
mark_pointer size1 = buf->size1() << 1;
|
||||
int gap_size = buf->gap_size() << 1;
|
||||
delta <<= 1;
|
||||
|
||||
// check if new and old marks are opposite sides of gap
|
||||
if (_pos <= size1 && _pos + delta > size1)
|
||||
delta += gap_size;
|
||||
else if (_pos >= size1 + gap_size && _pos + delta < size1 + gap_size)
|
||||
delta -= gap_size;
|
||||
|
||||
_pos = _pos + delta;
|
||||
if (_pos < str->start->_pos & ~1)
|
||||
_pos = (str->start->_pos & ~ 1) + (_pos & 1);
|
||||
else if (_pos >= str->end->_pos)
|
||||
_pos = (str->end->_pos & ~ 1) + (_pos & 1);
|
||||
}
|
||||
|
||||
// A (slow) way to find the buffer a mark belongs to.
|
||||
|
||||
edit_buffer * edit_mark::buffer()
|
||||
{
|
||||
struct edit_mark *mark;
|
||||
for (mark = this; mark->chain != NULL; mark = mark->chain) ;
|
||||
// Assume that the last mark on the chain is the end_mark.
|
||||
return (edit_buffer *)((char*)mark - offsetof(edit_buffer, end_mark));
|
||||
}
|
||||
|
||||
edit_mark::~edit_mark()
|
||||
{
|
||||
// Must unlink mark from chain of owning buffer
|
||||
struct edit_buffer *buf = buffer();
|
||||
if (this == &buf->start_mark || this == &buf->end_mark) abort();
|
||||
edit_mark **ptr;
|
||||
for (ptr = &buf->start_mark.chain; *ptr != this; ptr = &(*ptr)->chain) ;
|
||||
*ptr = this->chain;
|
||||
}
|
||||
|
||||
int edit_string::length() const
|
||||
{
|
||||
ptrdiff_t delta = end->ptr(buffer) - start->ptr(buffer);
|
||||
if (end->ptr(buffer) <= buffer->gap_start() ||
|
||||
start->ptr(buffer) >= buffer->gap_end())
|
||||
return delta;
|
||||
return delta - buffer->gap_size();
|
||||
}
|
||||
|
||||
buf_char * edit_string::copy_bytes(int *lenp) const
|
||||
{
|
||||
char *new_str;
|
||||
int len1, len2;
|
||||
buf_char *start1, *start2;
|
||||
start1 = start->ptr(buffer);
|
||||
if (end->ptr(buffer) <= buffer->gap_start()
|
||||
|| start->ptr(buffer) >= buffer->gap_end()) {
|
||||
len1 = end->ptr(buffer) - start1;
|
||||
len2 = 0;
|
||||
start2 = NULL; // To avoid a warning from g++.
|
||||
}
|
||||
else {
|
||||
len1 = buffer->gap_start() - start1;
|
||||
start2 = buffer->gap_end();
|
||||
len2 = end->ptr(buffer) - start2;
|
||||
}
|
||||
new_str = (char*)malloc(len1 + len2 + 1);
|
||||
memcpy(new_str, start1, len1);
|
||||
if (len2 > 0) memcpy(new_str + len1, start2, len2);
|
||||
new_str[len1+len2] = '\0';
|
||||
*lenp = len1+len2;
|
||||
return new_str;
|
||||
}
|
||||
|
||||
// Replace the buf_chars in 'this' with ones from 'src'.
|
||||
// Equivalent to deleting this, then inserting src, except tries
|
||||
// to leave marks in place: Marks whose offset from the start
|
||||
// of 'this' is less than 'src->length()' will still have the
|
||||
// same offset in 'this' when done.
|
||||
|
||||
void edit_string::assign(struct edit_string *src)
|
||||
{
|
||||
edit_streambuf dst_file(this, ios::out);
|
||||
if (buffer == src->buffer /*&& ???*/) { /* overly conservative */
|
||||
int src_len;
|
||||
buf_char *new_str;
|
||||
new_str = src->copy_bytes(&src_len);
|
||||
dst_file.sputn(new_str, src_len);
|
||||
free (new_str);
|
||||
} else {
|
||||
edit_streambuf src_file(src, ios::in);
|
||||
for ( ; ; ) {
|
||||
int ch = src_file.sbumpc();
|
||||
if (ch == EOF) break;
|
||||
dst_file.sputc(ch);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,175 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1991 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: editbuf.h,v 1.2 1993/08/02 17:22:30 mycroft Exp $
|
||||
|
||||
#ifndef _EDITBUF_H
|
||||
#define _EDITBUF_H
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <fstream.h>
|
||||
|
||||
typedef unsigned long mark_pointer;
|
||||
// At some point, it might be nice to parameterize this code
|
||||
// in terms of buf_char.
|
||||
typedef /*unsigned*/ char buf_char;
|
||||
|
||||
// Logical pos from start of buffer (does not count gap).
|
||||
typedef long buf_index;
|
||||
|
||||
// Pos from start of buffer, possibly including gap_size.
|
||||
typedef long buf_offset;
|
||||
|
||||
#if 0
|
||||
struct buf_cookie {
|
||||
FILE *file;
|
||||
struct edit_string *str;
|
||||
struct buf_cookie *next;
|
||||
buf_index tell();
|
||||
};
|
||||
#endif
|
||||
|
||||
struct edit_buffer;
|
||||
struct edit_mark;
|
||||
|
||||
// A edit_string is defined as the region between the 'start' and 'end' marks.
|
||||
// Normally (always?) 'start->insert_before()' should be false,
|
||||
// and 'end->insert_before()' should be true.
|
||||
|
||||
struct edit_string {
|
||||
struct edit_buffer *buffer; // buffer that 'start' and 'end' belong to
|
||||
struct edit_mark *start, *end;
|
||||
int length() const; // count of buf_chars currently in string
|
||||
edit_string(struct edit_buffer *b,
|
||||
struct edit_mark *ms, struct edit_mark *me)
|
||||
{ buffer = b; start = ms; end = me; }
|
||||
/* Make a fresh, contiguous copy of the data in STR.
|
||||
Assign length of STR to *LENP.
|
||||
(Output has extra NUL at out[*LENP].) */
|
||||
buf_char *copy_bytes(int *lenp) const;
|
||||
// FILE *open_file(char *mode);
|
||||
void assign(struct edit_string *src); // copy bytes from src to this
|
||||
};
|
||||
|
||||
struct edit_streambuf : public streambuf {
|
||||
friend edit_buffer;
|
||||
edit_string *str;
|
||||
edit_streambuf* next; // Chain of edit_streambuf's for a edit_buffer.
|
||||
short _mode;
|
||||
edit_streambuf(edit_string* bstr, int mode);
|
||||
~edit_streambuf();
|
||||
virtual int underflow();
|
||||
virtual int overflow(int c = EOF);
|
||||
virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
|
||||
void flush_to_buffer();
|
||||
void flush_to_buffer(edit_buffer* buffer);
|
||||
int _inserting;
|
||||
int inserting() { return _inserting; }
|
||||
void inserting(int i) { _inserting = i; }
|
||||
// int delete_chars(int count, char* cut_buf); Not implemented.
|
||||
int truncate();
|
||||
int is_reading() { return gptr() != NULL; }
|
||||
buf_char* current() { return is_reading() ? gptr() : pptr(); }
|
||||
void set_current(char *p, int is_reading);
|
||||
protected:
|
||||
void disconnect_gap_from_file(edit_buffer* buffer);
|
||||
};
|
||||
|
||||
// A 'edit_mark' indicates a position in a buffer.
|
||||
// It is "attached" the text (rather than the offset).
|
||||
// There are two kinds of mark, which have different behavior
|
||||
// when text is inserted at the mark:
|
||||
// If 'insert_before()' is true the mark will be adjusted to be
|
||||
// *after* the new text.
|
||||
|
||||
struct edit_mark {
|
||||
struct edit_mark *chain;
|
||||
mark_pointer _pos;
|
||||
inline int insert_before() { return _pos & 1; }
|
||||
inline unsigned long index_in_buffer(struct edit_buffer *buffer)
|
||||
{ return _pos >> 1; }
|
||||
inline buf_char *ptr(struct edit_buffer *buf);
|
||||
buf_index tell();
|
||||
edit_mark() { }
|
||||
edit_mark(struct edit_string *str, long delta);
|
||||
edit_buffer *buffer();
|
||||
~edit_mark();
|
||||
};
|
||||
|
||||
// A 'edit_buffer' consists of a sequence of buf_chars (the data),
|
||||
// a list of edit_marks pointing into the data, and a list of FILEs
|
||||
// also pointing into the data.
|
||||
// A 'edit_buffer' coerced to a edit_string is the string of
|
||||
// all the buf_chars in the buffer.
|
||||
|
||||
// This implementation uses a conventional buffer gap (as in Emacs).
|
||||
// The gap start is defined by de-referencing a (buf_char**).
|
||||
// This is because sometimes a FILE is inserting into the buffer,
|
||||
// so rather than having each putc adjust the gap, we use indirection
|
||||
// to have the gap be defined as the write pointer of the FILE.
|
||||
// (This assumes that putc adjusts a pointer (as in GNU's libc), not an index.)
|
||||
|
||||
struct edit_buffer {
|
||||
buf_char *data; /* == emacs buffer_text.p1+1 */
|
||||
buf_char *_gap_start;
|
||||
edit_streambuf* _writer; // If non-NULL, currently writing stream
|
||||
inline buf_char *gap_start()
|
||||
{ return _writer ? _writer->pptr() : _gap_start; }
|
||||
buf_offset __gap_end_pos; // size of part 1 + size of gap
|
||||
/* int gap; implicit: buf_size - size1 - size2 */
|
||||
int buf_size;
|
||||
struct edit_streambuf *files;
|
||||
struct edit_mark start_mark;
|
||||
struct edit_mark end_mark;
|
||||
edit_buffer();
|
||||
inline buf_offset gap_end_pos() { return __gap_end_pos; }
|
||||
inline struct edit_mark *start_marker() { return &start_mark; }
|
||||
inline struct edit_mark *end_marker() { return &end_mark; }
|
||||
/* these should be protected, ultimately */
|
||||
buf_index tell(edit_mark*);
|
||||
buf_index tell(buf_char*);
|
||||
inline buf_char *gap_end() { return data + gap_end_pos(); }
|
||||
inline int gap_size() { return gap_end() - gap_start(); }
|
||||
inline int size1() { return gap_start() - data; }
|
||||
inline int size2() { return buf_size - gap_end_pos(); }
|
||||
inline struct edit_mark * mark_list() { return &start_mark; }
|
||||
void make_gap (buf_offset);
|
||||
void move_gap (buf_offset pos);
|
||||
void move_gap (buf_char *pos) { move_gap(pos - data); }
|
||||
void gap_left (int pos);
|
||||
void gap_right (int pos);
|
||||
void adjust_markers(mark_pointer low, mark_pointer high,
|
||||
int amount, buf_char *old_data);
|
||||
void delete_range(buf_index from, buf_index to);
|
||||
void delete_range(struct edit_mark *start, struct edit_mark *end);
|
||||
};
|
||||
|
||||
extern buf_char * bstr_copy(struct edit_string *str, int *lenp);
|
||||
|
||||
// Convert a edit_mark to a (buf_char*)
|
||||
|
||||
inline buf_char *edit_mark::ptr(struct edit_buffer *buf)
|
||||
{ return buf->data + index_in_buffer(buf); }
|
||||
|
||||
inline void edit_streambuf::flush_to_buffer()
|
||||
{
|
||||
edit_buffer* buffer = str->buffer;
|
||||
if (buffer->_writer == this) flush_to_buffer(buffer);
|
||||
}
|
||||
#endif /* !_EDITBUF_H*/
|
||||
|
@ -1,580 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1991, 1992 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#include "ioprivate.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
// An fstream can be in at most one of put mode, get mode, or putback mode.
|
||||
// Putback mode is a variant of get mode.
|
||||
|
||||
// In a filebuf, there is only one current position, instead of two
|
||||
// separate get and put pointers. In get mode, the current posistion
|
||||
// is that of gptr(); in put mode that of pptr().
|
||||
|
||||
// The position in the buffer that corresponds to the position
|
||||
// in external file system is file_ptr().
|
||||
// This is normally egptr(), except in putback mode, when it is _save_egptr.
|
||||
// If the field _fb._offset is >= 0, it gives the offset in
|
||||
// the file as a whole corresponding to eGptr(). (???)
|
||||
|
||||
// PUT MODE:
|
||||
// If a filebuf is in put mode, pbase() is non-NULL and equal to base().
|
||||
// Also, epptr() == ebuf().
|
||||
// Also, eback() == gptr() && gptr() == egptr().
|
||||
// The un-flushed character are those between pbase() and pptr().
|
||||
// GET MODE:
|
||||
// If a filebuf is in get or putback mode, eback() != egptr().
|
||||
// In get mode, the unread characters are between gptr() and egptr().
|
||||
// The OS file position corresponds to that of egptr().
|
||||
// PUTBACK MODE:
|
||||
// Putback mode is used to remember "excess" characters that have
|
||||
// been sputbackc'd in a separate putback buffer.
|
||||
// In putback mode, the get buffer points to the special putback buffer.
|
||||
// The unread characters are the characters between gptr() and egptr()
|
||||
// in the putback buffer, as well as the area between save_gptr()
|
||||
// and save_egptr(), which point into the original reserve buffer.
|
||||
// (The pointers save_gptr() and save_egptr() are the values
|
||||
// of gptr() and egptr() at the time putback mode was entered.)
|
||||
// The OS position corresponds to that of save_egptr().
|
||||
//
|
||||
// LINE BUFFERED OUTPUT:
|
||||
// During line buffered output, pbase()==base() && epptr()==base().
|
||||
// However, ptr() may be anywhere between base() and ebuf().
|
||||
// This forces a call to filebuf::overflow(int C) on every put.
|
||||
// If there is more space in the buffer, and C is not a '\n',
|
||||
// then C is inserted, and pptr() incremented.
|
||||
//
|
||||
// UNBUFFERED STREAMS:
|
||||
// If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
|
||||
|
||||
#define CLOSED_FILEBUF_FLAGS \
|
||||
(_S_IS_FILEBUF+_S_NO_READS+_S_NO_WRITES+_S_TIED_PUT_GET)
|
||||
|
||||
void filebuf::init()
|
||||
{
|
||||
_fb._offset = 0;
|
||||
|
||||
_link_in();
|
||||
_fb._fileno = -1;
|
||||
}
|
||||
|
||||
filebuf::filebuf() : backupbuf(CLOSED_FILEBUF_FLAGS)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
filebuf::filebuf(int fd) : backupbuf(CLOSED_FILEBUF_FLAGS)
|
||||
{
|
||||
init();
|
||||
attach(fd);
|
||||
}
|
||||
|
||||
filebuf::filebuf(int fd, char* p, int len) : backupbuf(CLOSED_FILEBUF_FLAGS)
|
||||
{
|
||||
init();
|
||||
attach(fd);
|
||||
setbuf(p, len);
|
||||
}
|
||||
|
||||
filebuf::~filebuf()
|
||||
{
|
||||
if (!(xflags() & _S_DELETE_DONT_CLOSE))
|
||||
close();
|
||||
|
||||
_un_link();
|
||||
}
|
||||
|
||||
filebuf* filebuf::open(const char *filename, ios::openmode mode, int prot)
|
||||
{
|
||||
if (is_open())
|
||||
return NULL;
|
||||
int posix_mode;
|
||||
int read_write;
|
||||
if (mode & ios::app)
|
||||
mode |= ios::out;
|
||||
if ((mode & (ios::in|ios::out)) == (ios::in|ios::out)) {
|
||||
posix_mode = O_RDWR;
|
||||
read_write = 0;
|
||||
}
|
||||
else if (mode & ios::out)
|
||||
posix_mode = O_WRONLY, read_write = _S_NO_READS;
|
||||
else if (mode & (int)ios::in)
|
||||
posix_mode = O_RDONLY, read_write = _S_NO_WRITES;
|
||||
else
|
||||
posix_mode = 0, read_write = _S_NO_READS+_S_NO_WRITES;
|
||||
if ((mode & (int)ios::trunc) || mode == (int)ios::out)
|
||||
posix_mode |= O_TRUNC;
|
||||
if (mode & ios::app)
|
||||
posix_mode |= O_APPEND, read_write |= _S_IS_APPENDING;
|
||||
if (!(mode & (int)ios::nocreate) && mode != ios::in)
|
||||
posix_mode |= O_CREAT;
|
||||
if (mode & (int)ios::noreplace)
|
||||
posix_mode |= O_EXCL;
|
||||
int fd = ::open(filename, posix_mode, prot);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
_fb._fileno = fd;
|
||||
xsetflags(read_write, _S_NO_READS+_S_NO_WRITES+_S_IS_APPENDING);
|
||||
if (mode & (ios::ate|ios::app)) {
|
||||
if (seekoff(0, ios::end) == EOF)
|
||||
return NULL;
|
||||
}
|
||||
_link_in();
|
||||
return this;
|
||||
}
|
||||
|
||||
filebuf* filebuf::open(const char *filename, const char *mode)
|
||||
{
|
||||
if (is_open())
|
||||
return NULL;
|
||||
int oflags = 0, omode;
|
||||
int read_write;
|
||||
int oprot = 0666;
|
||||
switch (*mode++) {
|
||||
case 'r':
|
||||
omode = O_RDONLY;
|
||||
read_write = _S_NO_WRITES;
|
||||
break;
|
||||
case 'w':
|
||||
omode = O_WRONLY;
|
||||
oflags = O_CREAT|O_TRUNC;
|
||||
read_write = _S_NO_READS;
|
||||
break;
|
||||
case 'a':
|
||||
omode = O_WRONLY;
|
||||
oflags = O_CREAT|O_APPEND;
|
||||
read_write = _S_NO_READS|_S_IS_APPENDING;
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+')) {
|
||||
omode = O_RDWR;
|
||||
read_write &= _S_IS_APPENDING;
|
||||
}
|
||||
int fdesc = ::open(filename, omode|oflags, oprot);
|
||||
if (fdesc < 0)
|
||||
return NULL;
|
||||
_fb._fileno = fdesc;
|
||||
xsetflags(read_write, _S_NO_READS+_S_NO_WRITES+_S_IS_APPENDING);
|
||||
if (read_write & _S_IS_APPENDING)
|
||||
if (seekoff(0, ios::end) == EOF)
|
||||
return NULL;
|
||||
_link_in();
|
||||
return this;
|
||||
}
|
||||
|
||||
filebuf* filebuf::attach(int fd)
|
||||
{
|
||||
if (is_open())
|
||||
return NULL;
|
||||
_fb._fileno = fd;
|
||||
xsetflags(0, _S_NO_READS+_S_NO_WRITES);
|
||||
return this;
|
||||
}
|
||||
|
||||
streambuf* filebuf::setbuf(char* p, int len)
|
||||
{
|
||||
if (streambuf::setbuf(p, len) == NULL)
|
||||
return NULL;
|
||||
setp(_base, _base);
|
||||
setg(_base, _base, _base);
|
||||
return this;
|
||||
}
|
||||
|
||||
int filebuf::overflow(int c)
|
||||
{
|
||||
if (xflags() & _S_NO_WRITES) // SET ERROR
|
||||
return EOF;
|
||||
// Allocate a buffer if needed.
|
||||
if (base() == NULL) {
|
||||
doallocbuf();
|
||||
if (xflags() & _S_LINE_BUF+_S_UNBUFFERED) setp(_base, _base);
|
||||
else setp(_base, _ebuf);
|
||||
setg(_base, _base, _base);
|
||||
_flags |= _S_CURRENTLY_PUTTING;
|
||||
}
|
||||
// If currently reading, switch to writing.
|
||||
else if ((_flags & _S_CURRENTLY_PUTTING) == 0) {
|
||||
if (xflags() & _S_LINE_BUF+_S_UNBUFFERED) setp(gptr(), gptr());
|
||||
else setp(gptr(), ebuf());
|
||||
setg(egptr(), egptr(), egptr());
|
||||
_flags |= _S_CURRENTLY_PUTTING;
|
||||
}
|
||||
if (c == EOF)
|
||||
return do_flush();
|
||||
if (pptr() == ebuf() ) // Buffer is really full
|
||||
if (do_flush() == EOF)
|
||||
return EOF;
|
||||
xput_char(c);
|
||||
if (unbuffered() || (linebuffered() && c == '\n'))
|
||||
if (do_flush() == EOF)
|
||||
return EOF;
|
||||
return (unsigned char)c;
|
||||
}
|
||||
|
||||
int filebuf::underflow()
|
||||
{
|
||||
#if 0
|
||||
/* SysV does not make this test; take it out for compatibility */
|
||||
if (fp->_flags & __SEOF)
|
||||
return (EOF);
|
||||
#endif
|
||||
|
||||
if (xflags() & _S_NO_READS)
|
||||
return EOF;
|
||||
if (gptr() < egptr())
|
||||
return *(unsigned char*)gptr();
|
||||
allocbuf();
|
||||
|
||||
// FIXME This can/should be moved to __streambuf ??
|
||||
if ((xflags() & _S_LINE_BUF) || unbuffered()) {
|
||||
// Flush all line buffered files before reading.
|
||||
streambuf::flush_all_linebuffered();
|
||||
}
|
||||
|
||||
switch_to_get_mode();
|
||||
|
||||
_G_ssize_t count = sys_read(base(), ebuf() - base());
|
||||
if (count <= 0) {
|
||||
if (count == 0)
|
||||
xsetflags(_S_EOF_SEEN);
|
||||
else
|
||||
xsetflags(_S_ERR_SEEN), count = 0;
|
||||
}
|
||||
setg(base(), base(), base() + count);
|
||||
setp(base(), base());
|
||||
if (count == 0)
|
||||
return EOF;
|
||||
if (_fb._offset >= 0)
|
||||
_fb._offset += count;
|
||||
return *(unsigned char*)gptr();
|
||||
}
|
||||
|
||||
int filebuf::do_write(const char *data, int to_do)
|
||||
{
|
||||
if (to_do == 0)
|
||||
return 0;
|
||||
if (xflags() & _S_IS_APPENDING) {
|
||||
// On a system without a proper O_APPEND implementation,
|
||||
// you would need to sys_seek(0, ios::end) here, but is
|
||||
// is not needed nor desirable for Unix- or Posix-like systems.
|
||||
// Instead, just indicate that offset (before and after) is
|
||||
// unpredictable.
|
||||
_fb._offset = -1;
|
||||
}
|
||||
else if (egptr() != pbase()) {
|
||||
long new_pos = sys_seek(pbase()-egptr(), ios::cur);
|
||||
if (new_pos == -1)
|
||||
return EOF;
|
||||
_fb._offset = new_pos;
|
||||
}
|
||||
_G_ssize_t count = sys_write(data, to_do);
|
||||
if (_cur_column)
|
||||
_cur_column = __adjust_column(_cur_column - 1, data, to_do) + 1;
|
||||
setg(base(), base(), base());
|
||||
if (xflags() & _S_LINE_BUF+_S_UNBUFFERED) setp(base(), base());
|
||||
else setp(base(), ebuf());
|
||||
return count != to_do ? EOF : 0;
|
||||
}
|
||||
|
||||
int filebuf::sync()
|
||||
{
|
||||
// char* ptr = cur_ptr();
|
||||
if (pptr() > pbase())
|
||||
if (do_flush()) return EOF;
|
||||
if (gptr() != egptr()) {
|
||||
streampos delta = gptr() - egptr();
|
||||
if (in_backup())
|
||||
delta -= eGptr() - Gbase();
|
||||
_G_fpos_t new_pos = sys_seek(delta, ios::cur);
|
||||
if (new_pos == EOF)
|
||||
return EOF;
|
||||
_fb._offset = new_pos;
|
||||
setg(eback(), gptr(), gptr());
|
||||
}
|
||||
// FIXME: Cleanup - can this be shared?
|
||||
// setg(base(), ptr, ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
streampos filebuf::seekoff(streamoff offset, _seek_dir dir, int mode)
|
||||
{
|
||||
streampos result, new_offset, delta;
|
||||
_G_ssize_t count;
|
||||
|
||||
if (mode == 0) // Don't move any pointers.
|
||||
dir = ios::cur, offset = 0;
|
||||
|
||||
// Flush unwritten characters.
|
||||
// (This may do an unneeded write if we seek within the buffer.
|
||||
// But to be able to switch to reading, we would need to set
|
||||
// egptr to ptr. That can't be done in the current design,
|
||||
// which assumes file_ptr() is eGptr. Anyway, since we probably
|
||||
// end up flushing when we close(), it doesn't make much difference.)
|
||||
if (pptr() > pbase() || put_mode())
|
||||
if (switch_to_get_mode()) return EOF;
|
||||
|
||||
if (base() == NULL) {
|
||||
doallocbuf();
|
||||
setp(base(), base());
|
||||
setg(base(), base(), base());
|
||||
}
|
||||
switch (dir) {
|
||||
case ios::cur:
|
||||
if (_fb._offset < 0) {
|
||||
_fb._offset = sys_seek(0, ios::cur);
|
||||
if (_fb._offset < 0)
|
||||
return EOF;
|
||||
}
|
||||
// Make offset absolute, assuming current pointer is file_ptr().
|
||||
offset += _fb._offset;
|
||||
|
||||
offset -= _egptr - _gptr;
|
||||
if (in_backup())
|
||||
offset -= _other_egptr - _other_gbase;
|
||||
dir = ios::beg;
|
||||
break;
|
||||
case ios::beg:
|
||||
break;
|
||||
case ios::end:
|
||||
struct stat st;
|
||||
if (sys_stat(&st) == 0 && S_ISREG(st.st_mode)) {
|
||||
offset += st.st_size;
|
||||
dir = ios::beg;
|
||||
}
|
||||
else
|
||||
goto dumb;
|
||||
}
|
||||
// At this point, dir==ios::beg.
|
||||
|
||||
// If destination is within current buffer, optimize:
|
||||
if (_fb._offset >= 0 && _eback != NULL) {
|
||||
// Offset relative to start of main get area.
|
||||
_G_fpos_t rel_offset = offset - _fb._offset
|
||||
+ (eGptr()-Gbase());
|
||||
if (rel_offset >= 0) {
|
||||
if (in_backup())
|
||||
switch_to_main_get_area();
|
||||
if (rel_offset <= _egptr - _eback) {
|
||||
setg(base(), base() + rel_offset, egptr());
|
||||
setp(base(), base());
|
||||
return offset;
|
||||
}
|
||||
// If we have streammarkers, seek forward by reading ahead.
|
||||
if (have_markers()) {
|
||||
int to_skip = rel_offset - (_gptr - _eback);
|
||||
if (ignore(to_skip) != to_skip)
|
||||
goto dumb;
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
if (rel_offset < 0 && rel_offset >= Bbase() - Bptr()) {
|
||||
if (!in_backup())
|
||||
switch_to_backup_area();
|
||||
gbump(_egptr + rel_offset - gptr());
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
|
||||
unsave_markers();
|
||||
|
||||
// Try to seek to a block boundary, to improve kernel page management.
|
||||
new_offset = offset & ~(ebuf() - base() - 1);
|
||||
delta = offset - new_offset;
|
||||
if (delta > ebuf() - base()) {
|
||||
new_offset = offset;
|
||||
delta = 0;
|
||||
}
|
||||
result = sys_seek(new_offset, ios::beg);
|
||||
if (result < 0)
|
||||
return EOF;
|
||||
if (delta == 0)
|
||||
count = 0;
|
||||
else {
|
||||
count = sys_read(base(), ebuf()-base());
|
||||
if (count < delta) {
|
||||
// We weren't allowed to read, but try to seek the remainder.
|
||||
offset = count == EOF ? delta : delta-count;
|
||||
dir = ios::cur;
|
||||
goto dumb;
|
||||
}
|
||||
}
|
||||
setg(base(), base()+delta, base()+count);
|
||||
setp(base(), base());
|
||||
_fb._offset = result + count;
|
||||
xflags(xflags() & ~ _S_EOF_SEEN);
|
||||
return offset;
|
||||
dumb:
|
||||
unsave_markers();
|
||||
result = sys_seek(offset, dir);
|
||||
if (result != EOF) {
|
||||
xflags(xflags() & ~_S_EOF_SEEN);
|
||||
}
|
||||
_fb._offset = result;
|
||||
setg(base(), base(), base());
|
||||
setp(base(), base());
|
||||
return result;
|
||||
}
|
||||
|
||||
filebuf* filebuf::close()
|
||||
{
|
||||
if (!is_open())
|
||||
return NULL;
|
||||
|
||||
// This flushes as well as switching mode.
|
||||
if (pptr() > pbase() || put_mode())
|
||||
if (switch_to_get_mode()) return NULL;
|
||||
|
||||
unsave_markers();
|
||||
|
||||
int status = sys_close();
|
||||
|
||||
// Free buffer.
|
||||
setb(NULL, NULL, 0);
|
||||
setg(NULL, NULL, NULL);
|
||||
setp(NULL, NULL);
|
||||
|
||||
_un_link();
|
||||
_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
|
||||
_fb._fileno = EOF;
|
||||
_fb._offset = 0;
|
||||
|
||||
return status < 0 ? NULL : this;
|
||||
}
|
||||
|
||||
_G_ssize_t filebuf::sys_read(char* buf, size_t size)
|
||||
{
|
||||
for (;;) {
|
||||
_G_ssize_t count = ::read(_fb._fileno, buf, size);
|
||||
if (count != -1 || errno != EINTR)
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
_G_fpos_t filebuf::sys_seek(_G_fpos_t offset, _seek_dir dir)
|
||||
{
|
||||
return ::lseek(fd(), offset, (int)dir);
|
||||
}
|
||||
|
||||
_G_ssize_t filebuf::sys_write(const void *buf, long n)
|
||||
{
|
||||
long to_do = n;
|
||||
while (to_do > 0) {
|
||||
_G_ssize_t count = ::write(fd(), buf, to_do);
|
||||
if (count == EOF) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else {
|
||||
_flags |= _S_ERR_SEEN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
to_do -= count;
|
||||
buf = (void*)((char*)buf + count);
|
||||
}
|
||||
n -= to_do;
|
||||
if (_fb._offset >= 0)
|
||||
_fb._offset += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
int filebuf::sys_stat(void* st)
|
||||
{
|
||||
return ::_fstat(fd(), (struct stat*)st);
|
||||
}
|
||||
|
||||
int filebuf::sys_close()
|
||||
{
|
||||
return ::close(fd());
|
||||
}
|
||||
|
||||
int filebuf::xsputn(const char *s, int n)
|
||||
{
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
// This is an optimized implementation.
|
||||
// If the amount to be written straddles a block boundary
|
||||
// (or the filebuf is unbuffered), use sys_write directly.
|
||||
|
||||
int to_do = n;
|
||||
int must_flush = 0;
|
||||
// First figure out how much space is available in the buffer.
|
||||
int count = _epptr - _pptr; // Space available.
|
||||
if (linebuffered() && (_flags & _S_CURRENTLY_PUTTING)) {
|
||||
count =_ebuf - _pptr;
|
||||
if (count >= n) {
|
||||
for (register const char *p = s + n; p > s; ) {
|
||||
if (*--p == '\n') {
|
||||
count = p - s + 1;
|
||||
must_flush = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Then fill the buffer.
|
||||
if (count > 0) {
|
||||
if (count > to_do)
|
||||
count = to_do;
|
||||
if (count > 20) {
|
||||
memcpy(pptr(), s, count);
|
||||
s += count;
|
||||
}
|
||||
else {
|
||||
register char *p = pptr();;
|
||||
for (register int i = count; --i >= 0; ) *p++ = *s++;
|
||||
}
|
||||
pbump(count);
|
||||
to_do -= count;
|
||||
}
|
||||
if (to_do + must_flush > 0) {
|
||||
// Next flush the (full) buffer.
|
||||
if (__overflow(this, EOF) == EOF)
|
||||
return n - to_do;
|
||||
|
||||
// Try to maintain alignment: write a whole number of blocks.
|
||||
// dont_write is what gets left over.
|
||||
int block_size = _ebuf - _base;
|
||||
int dont_write = block_size >= 128 ? to_do % block_size : 0;
|
||||
|
||||
_G_ssize_t count = to_do - dont_write;
|
||||
if (do_write(s, count) == EOF)
|
||||
return n - to_do;
|
||||
to_do = dont_write;
|
||||
|
||||
// Now write out the remainder. Normally, this will fit in the
|
||||
// buffer, but it's somewhat messier for line-buffered files,
|
||||
// so we let streambuf::sputn handle the general case.
|
||||
if (dont_write)
|
||||
to_do -= streambuf::sputn(s+count, dont_write);
|
||||
}
|
||||
return n - to_do;
|
||||
}
|
||||
|
||||
int filebuf::xsgetn(char *s, int n)
|
||||
{
|
||||
// FIXME: OPTIMIZE THIS (specifically, when unbuffered()).
|
||||
return streambuf::xsgetn(s, n);
|
||||
}
|
||||
|
||||
// Non-ANSI AT&T-ism: Default open protection.
|
||||
const int filebuf::openprot = 0644;
|
File diff suppressed because it is too large
Load Diff
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id: floatio.h,v 1.2 1993/08/02 17:22:31 mycroft Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Floating point scanf/printf (input/output) definitions.
|
||||
*/
|
||||
|
||||
/* 11-bit exponent (VAX G floating point) is 308 decimal digits */
|
||||
#define MAXEXP 308
|
||||
/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
|
||||
#define MAXFRACT 39
|
@ -1,65 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1991 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#endif
|
||||
#define _STREAM_COMPAT
|
||||
#include "ioprivate.h"
|
||||
#include <fstream.h>
|
||||
|
||||
fstreambase::fstreambase()
|
||||
{
|
||||
init(new filebuf());
|
||||
}
|
||||
|
||||
fstreambase::fstreambase(int fd)
|
||||
{
|
||||
init(new filebuf(fd));
|
||||
}
|
||||
|
||||
fstreambase::fstreambase(const char *name, int mode, int prot)
|
||||
{
|
||||
init(new filebuf());
|
||||
if (!rdbuf()->open(name, mode, prot))
|
||||
set(ios::badbit);
|
||||
}
|
||||
|
||||
void fstreambase::open(const char *name, int mode, int prot)
|
||||
{
|
||||
clear();
|
||||
if (!rdbuf()->open(name, mode, prot))
|
||||
set(ios::badbit);
|
||||
}
|
||||
|
||||
void fstreambase::close()
|
||||
{
|
||||
if (!rdbuf()->close())
|
||||
set(ios::failbit);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int mode_to_sys(enum open_mode mode)
|
||||
{
|
||||
return O_WRONLY;
|
||||
}
|
||||
|
||||
static char* fopen_cmd_arg(io_mode i)
|
||||
{
|
||||
return "w";
|
||||
}
|
||||
#endif
|
@ -1,72 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1991 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: fstream.h,v 1.2 1993/08/02 17:22:32 mycroft Exp $
|
||||
|
||||
#ifndef _FSTREAM_H
|
||||
#define _FSTREAM_H
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
#include <iostream.h>
|
||||
|
||||
class fstreambase : virtual public ios {
|
||||
public:
|
||||
fstreambase();
|
||||
fstreambase(int fd);
|
||||
fstreambase(const char *name, int mode, int prot=0664);
|
||||
void close();
|
||||
filebuf* rdbuf() const { return (filebuf*)_strbuf; }
|
||||
void open(const char *name, int mode, int prot=0664);
|
||||
int is_open() const { return rdbuf()->is_open(); }
|
||||
void setbuf(char *ptr, int len) { rdbuf()->setbuf(ptr, len); }
|
||||
#ifdef _STREAM_COMPAT
|
||||
int filedesc() { return rdbuf()->fd(); }
|
||||
fstreambase& raw() { rdbuf()->setbuf(NULL, 0); return *this; }
|
||||
#endif
|
||||
};
|
||||
|
||||
class ifstream : public fstreambase, public istream {
|
||||
public:
|
||||
ifstream() : fstreambase() { }
|
||||
ifstream(int fd) : fstreambase(fd) { }
|
||||
ifstream(const char *name, int mode=ios::in, int prot=0664)
|
||||
: fstreambase(name, mode, prot) { }
|
||||
void open(const char *name, int mode=ios::in, int prot=0664)
|
||||
{ fstreambase::open(name, mode, prot); }
|
||||
};
|
||||
|
||||
class ofstream : public fstreambase, public ostream {
|
||||
public:
|
||||
ofstream() : fstreambase() { }
|
||||
ofstream(int fd) : fstreambase(fd) { }
|
||||
ofstream(const char *name, int mode=ios::out, int prot=0664)
|
||||
: fstreambase(name, mode, prot) { }
|
||||
void open(const char *name, int mode=ios::out, int prot=0664)
|
||||
{ fstreambase::open(name, mode, prot); }
|
||||
};
|
||||
|
||||
class fstream : public fstreambase, public iostream {
|
||||
public:
|
||||
fstream() : fstreambase() { }
|
||||
fstream(int fd) : fstreambase(fd) { }
|
||||
fstream(const char *name, int mode, int prot=0664)
|
||||
: fstreambase(name, mode, prot) { }
|
||||
void open(const char *name, int mode, int prot=0664)
|
||||
{ fstreambase::open(name, mode, prot); }
|
||||
};
|
||||
#endif /*!_FSTREAM_H*/
|
@ -1,135 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1992 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#include "iostream.h"
|
||||
#include <string.h>
|
||||
|
||||
istream& istream::getline(char* buf, int len, char delim)
|
||||
{
|
||||
_gcount = 0;
|
||||
if (ipfx1()) {
|
||||
streambuf *sb = rdbuf();
|
||||
long count = sb->sgetline(buf, len, delim, -1);
|
||||
if (count == len-1)
|
||||
set(ios::failbit);
|
||||
else {
|
||||
int ch = sb->sbumpc();
|
||||
if (ch == EOF)
|
||||
set(ios::failbit|ios::eofbit);
|
||||
else if (ch == (unsigned char)delim)
|
||||
count++;
|
||||
else
|
||||
sb->sungetc(); // Leave delimiter unread.
|
||||
}
|
||||
_gcount = count;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream& istream::get(char* buf, int len, char delim)
|
||||
{
|
||||
_gcount = 0;
|
||||
if (ipfx1()) {
|
||||
streambuf *sbuf = rdbuf();
|
||||
long count = sbuf->sgetline(buf, len, delim, -1);
|
||||
if (count < 0 || (count == 0 && sbuf->sgetc() == EOF))
|
||||
set(ios::failbit|ios::eofbit);
|
||||
else
|
||||
_gcount = count;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1992 Free Software Foundation.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
// from Doug Schmidt
|
||||
|
||||
#define CHUNK_SIZE 512
|
||||
|
||||
/* Reads an arbitrarily long input line terminated by a user-specified
|
||||
TERMINATOR. Super-nifty trick using recursion avoids unnecessary calls
|
||||
to NEW! */
|
||||
|
||||
char *_sb_readline (streambuf *sb, long& total, char terminator)
|
||||
{
|
||||
char buf[CHUNK_SIZE+1];
|
||||
char *ptr;
|
||||
int ch;
|
||||
|
||||
long count = sb->sgetline(buf, CHUNK_SIZE+1, terminator, -1);
|
||||
if (count == EOF)
|
||||
return NULL;
|
||||
ch = sb->sbumpc();
|
||||
long old_total = total;
|
||||
total += count;
|
||||
if (ch != EOF && ch != terminator) {
|
||||
total++; // Include ch in total.
|
||||
ptr = _sb_readline(sb, total, terminator);
|
||||
if (ptr) {
|
||||
memcpy(ptr + old_total, buf, count);
|
||||
ptr[old_total+count] = ch;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
if (ptr = new char[total+1]) {
|
||||
ptr[total] = '\0';
|
||||
memcpy(ptr + total - count, buf, count);
|
||||
return ptr;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Reads an arbitrarily long input line terminated by TERMINATOR.
|
||||
This routine allocates its own memory, so the user should
|
||||
only supply the address of a (char *). */
|
||||
|
||||
istream& istream::gets(char **s, char delim /* = '\n' */)
|
||||
{
|
||||
if (ipfx1()) {
|
||||
long size = 0;
|
||||
streambuf *sb = rdbuf();
|
||||
*s = _sb_readline (sb, size, delim);
|
||||
_gcount = *s ? size : 0;
|
||||
if (sb->_flags & _S_EOF_SEEN) {
|
||||
set(ios::eofbit);
|
||||
if (_gcount == 0)
|
||||
set(ios::failbit);
|
||||
}
|
||||
}
|
||||
else {
|
||||
_gcount = 0;
|
||||
*s = NULL;
|
||||
}
|
||||
return *this;
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1992 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#include "ioprivate.h"
|
||||
#include "iostream.h"
|
||||
|
||||
istream& istream::get(streambuf& sb, char delim /* = '\n' */)
|
||||
{
|
||||
_gcount = 0;
|
||||
if (ipfx1()) {
|
||||
register streambuf* isb = rdbuf();
|
||||
for (;;) {
|
||||
int len = isb->egptr() - isb->gptr();
|
||||
if (len <= 0)
|
||||
if (isb->underflow() == EOF)
|
||||
break;
|
||||
else
|
||||
len = isb->egptr() - isb->gptr();
|
||||
char *delimp = (char*)memchr((void*)isb->gptr(), delim, len);
|
||||
if (delimp != NULL)
|
||||
len = delimp - isb->gptr();
|
||||
int written = sb.sputn(isb->gptr(), len);
|
||||
isb->gbump(written);
|
||||
_gcount += written;
|
||||
if (written != len) {
|
||||
set(ios::failbit);
|
||||
break;
|
||||
}
|
||||
if (delimp != NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
// This is part of the iostream library, providing -*- C++ -*- input/output.
|
||||
// Copyright (C) 1992 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#endif
|
||||
|
||||
#include <indstream.h>
|
||||
|
||||
indirectbuf::indirectbuf(streambuf *get, streambuf *put, int delete_mode)
|
||||
: streambuf()
|
||||
{
|
||||
_get_stream = get;
|
||||
_put_stream = put == NULL ? get : put;
|
||||
_delete_flags = delete_mode;
|
||||
}
|
||||
|
||||
indirectbuf::~indirectbuf()
|
||||
{
|
||||
if (_delete_flags & ios::in) delete get_stream();
|
||||
if (_delete_flags & ios::out) delete put_stream();
|
||||
}
|
||||
|
||||
int indirectbuf::xsputn(const char* s, int n)
|
||||
{
|
||||
return put_stream()->sputn(s, n);
|
||||
}
|
||||
|
||||
int indirectbuf::xsgetn(char* s, int n)
|
||||
{
|
||||
return get_stream()->sgetn(s, n);
|
||||
}
|
||||
|
||||
int indirectbuf::overflow(int c /* = EOF */)
|
||||
{
|
||||
if (c == EOF)
|
||||
return put_stream()->overflow(c);
|
||||
else
|
||||
return put_stream()->sputc(c);
|
||||
}
|
||||
|
||||
int indirectbuf::underflow()
|
||||
{
|
||||
return get_stream()->sbumpc();
|
||||
}
|
||||
|
||||
streampos indirectbuf::seekoff(streamoff off, _seek_dir dir, int mode)
|
||||
{
|
||||
int ret_val = 0;
|
||||
int select = mode == 0 ? (ios::in|ios::out) : mode;
|
||||
streambuf *gbuf = (select & ios::in) ? get_stream() : 0;
|
||||
streambuf *pbuf = (select & ios::out) ? put_stream() : 0;
|
||||
if (gbuf == pbuf)
|
||||
ret_val = gbuf->seekoff(off, dir, mode);
|
||||
else {
|
||||
if (gbuf)
|
||||
ret_val = gbuf->seekoff(off, dir, ios::in);
|
||||
if (pbuf && ret_val != EOF)
|
||||
ret_val = pbuf->seekoff(off, dir, ios::out);
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
streampos indirectbuf::seekpos(streampos pos, int mode)
|
||||
{
|
||||
int ret_val = EOF;
|
||||
int select = mode == 0 ? (ios::in|ios::out) : mode;
|
||||
streambuf *gbuf = (select & ios::in) ? get_stream() : 0;
|
||||
streambuf *pbuf = (select & ios::out) ? put_stream() : 0;
|
||||
if (gbuf == pbuf)
|
||||
ret_val = gbuf->seekpos(pos, mode);
|
||||
else {
|
||||
if (gbuf)
|
||||
ret_val = gbuf->seekpos(pos, ios::in);
|
||||
if (pbuf && ret_val != EOF)
|
||||
ret_val = pbuf->seekpos(pos, ios::out);
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int indirectbuf::sync()
|
||||
{
|
||||
streambuf *gbuf = get_stream();
|
||||
int ret_val = gbuf->sync();
|
||||
if (ret_val == EOF) return ret_val;
|
||||
streambuf *pbuf = put_stream();
|
||||
if (pbuf != gbuf) return pbuf->sync();
|
||||
else return ret_val;
|
||||
}
|
||||
|
||||
int indirectbuf::pbackfail(int c)
|
||||
{
|
||||
return get_stream()->sputbackc(c);
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
// This is part of the iostream library, providing -*- C++ -*- input/output.
|
||||
// Copyright (C) 1992 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: indstream.h,v 1.2 1993/08/02 17:22:33 mycroft Exp $
|
||||
|
||||
#ifndef _INDSTREAM_H
|
||||
#define _INDSTREAM_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
|
||||
#include <iostream.h>
|
||||
|
||||
// An indirectbuf is one that forwards all of its I/O requests
|
||||
// to another streambuf.
|
||||
// All get-related requests are sent to get_stream().
|
||||
// All put-related requests are sent to put_stream().
|
||||
|
||||
// An indirectbuf can be used to implement Common Lisp
|
||||
// synonym-streams and two-way-streams.
|
||||
//
|
||||
// class synonymbuf : public indirectbuf {
|
||||
// Symbol *sym;
|
||||
// synonymbuf(Symbol *s) { sym = s; }
|
||||
// virtual streambuf *lookup_stream(int mode) {
|
||||
// return coerce_to_streambuf(lookup_value(sym)); }
|
||||
// };
|
||||
|
||||
class indirectbuf : public streambuf {
|
||||
protected:
|
||||
streambuf *_get_stream; // Optional cache for get_stream().
|
||||
streambuf *_put_stream; // Optional cache for put_stream().
|
||||
int _delete_flags;
|
||||
public:
|
||||
streambuf *get_stream()
|
||||
{ return _get_stream ? _get_stream : lookup_stream(ios::in); }
|
||||
streambuf *put_stream()
|
||||
{ return _put_stream ? _put_stream : lookup_stream(ios::out); }
|
||||
virtual streambuf *lookup_stream(int/*mode*/) { return NULL; } // ERROR!
|
||||
indirectbuf(streambuf *get=NULL, streambuf *put=NULL, int delete_mode=0);
|
||||
virtual ~indirectbuf();
|
||||
virtual int xsputn(const char* s, int n);
|
||||
virtual int xsgetn(char* s, int n);
|
||||
virtual int underflow();
|
||||
virtual int overflow(int c = EOF);
|
||||
virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
|
||||
virtual streampos seekpos(streampos pos, int mode = ios::in|ios::out);
|
||||
virtual int sync();
|
||||
virtual int pbackfail(int c);
|
||||
};
|
||||
|
||||
#endif /* !_INDSTREAM_H */
|
@ -1,77 +0,0 @@
|
||||
// -*- C++ -*-
|
||||
// This is part of the iostream library, providing parametrized manipulators
|
||||
// Written by Heinz G. Seidl, Copyright (C) 1992 Cygnus Support
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#ifdef __GNUG__
|
||||
//#pragma implementation
|
||||
#endif
|
||||
|
||||
#include "iomanip.h"
|
||||
|
||||
|
||||
// Those functions are called through a pointer,
|
||||
// thus it does not make sense, to inline them.
|
||||
|
||||
ios & __iomanip_setbase (ios& i, int n)
|
||||
{
|
||||
ios::fmtflags b;
|
||||
switch (n)
|
||||
{
|
||||
case 8:
|
||||
b = ios::oct; break;
|
||||
case 10:
|
||||
b = ios::dec; break;
|
||||
case 16:
|
||||
b = ios::hex; break;
|
||||
default:
|
||||
b = 0;
|
||||
}
|
||||
i.setf(b, ios::basefield);
|
||||
return i;
|
||||
}
|
||||
|
||||
ios & __iomanip_setfill (ios& i, int n)
|
||||
{
|
||||
//FIXME if ( i.flags() & ios::widechar )
|
||||
i.fill( (char) n);
|
||||
//FIXME else
|
||||
//FIXME i.fill( (wchar) n);
|
||||
return i;
|
||||
}
|
||||
|
||||
ios & __iomanip_setprecision (ios& i, int n)
|
||||
{
|
||||
i.precision(n);
|
||||
return i;
|
||||
}
|
||||
ios & __iomanip_setw (ios& i, int n)
|
||||
{
|
||||
i.width(n);
|
||||
return i;
|
||||
}
|
||||
|
||||
ios & __iomanip_setiosflags (ios& i, ios::fmtflags n)
|
||||
{
|
||||
i.setf(n,n);
|
||||
return i;
|
||||
}
|
||||
|
||||
ios & __iomanip_resetiosflags (ios& i, ios::fmtflags n)
|
||||
{
|
||||
i.setf(0,n);
|
||||
return i;
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
// -*- C++ -*-
|
||||
// This is part of the iostream library, providing parametrized manipulators
|
||||
// Written by Heinz G. Seidl, Copyright (C) 1992 Cygnus Support
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: iomanip.h,v 1.2 1993/08/02 17:22:34 mycroft Exp $
|
||||
|
||||
#ifndef _IOMANIP_H
|
||||
//
|
||||
// Not specifying `pragma interface' causes the compiler to emit the
|
||||
// template definitions in the files, where they are used.
|
||||
//
|
||||
//#ifdef __GNUG__
|
||||
//#pragma interface
|
||||
//#endif
|
||||
#define _IOMANIP_H
|
||||
|
||||
#include <_G_config.h>
|
||||
|
||||
#ifndef _G_NO_TEMPLATES
|
||||
|
||||
#include <iostream.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Parametrized Manipulators as specified by ANSI draft
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Stream Manipulators
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
template<class TP> class smanip; // TP = Type Param
|
||||
|
||||
template<class TP> class sapp {
|
||||
ios& (*_f)(ios&, TP);
|
||||
public:
|
||||
sapp(ios& (*f)(ios&, TP)) : _f(f) {}
|
||||
//
|
||||
smanip<TP> operator()(TP a)
|
||||
{ return smanip<TP>(_f, a); }
|
||||
};
|
||||
|
||||
template <class TP> class smanip {
|
||||
ios& (*_f)(ios&, TP);
|
||||
TP _a;
|
||||
public:
|
||||
smanip(ios& (*f)(ios&, TP), TP a) : _f(f), _a(a) {}
|
||||
//
|
||||
friend
|
||||
istream& operator>>(istream& i, const smanip<TP>& m);
|
||||
friend
|
||||
ostream& operator<<(ostream& o, const smanip<TP>& m);
|
||||
};
|
||||
|
||||
template<class TP>
|
||||
inline istream& operator>>(istream& i, const smanip<TP>& m)
|
||||
{ (*m._f)(i, m._a); return i; }
|
||||
|
||||
template<class TP>
|
||||
inline ostream& operator<<(ostream& o, const smanip<TP>& m)
|
||||
{ (*m._f)(o, m._a); return o;}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Input-Stream Manipulators
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
template<class TP> class imanip;
|
||||
|
||||
template<class TP> class iapp {
|
||||
istream& (*_f)(istream&, TP);
|
||||
public:
|
||||
iapp(ostream& (*f)(istream&,TP)) : _f(f) {}
|
||||
//
|
||||
imanip<TP> operator()(TP a)
|
||||
{ return imanip<TP>(_f, a); }
|
||||
};
|
||||
|
||||
template <class TP> class imanip {
|
||||
istream& (*_f)(istream&, TP);
|
||||
TP _a;
|
||||
public:
|
||||
imanip(istream& (*f)(istream&, TP), TP a) : _f(f), _a(a) {}
|
||||
//
|
||||
friend
|
||||
istream& operator>>(istream& i, const imanip<TP>& m)
|
||||
{ return (*m._f)( i, m._a); }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Output-Stream Manipulators
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
template<class TP> class omanip;
|
||||
|
||||
template<class TP> class oapp {
|
||||
ostream& (*_f)(ostream&, TP);
|
||||
public:
|
||||
oapp(ostream& (*f)(ostream&,TP)) : _f(f) {}
|
||||
//
|
||||
omanip<TP> operator()(TP a)
|
||||
{ return omanip<TP>(_f, a); }
|
||||
};
|
||||
|
||||
template <class TP> class omanip {
|
||||
ostream& (*_f)(ostream&, TP);
|
||||
TP _a;
|
||||
public:
|
||||
omanip(ostream& (*f)(ostream&, TP), TP a) : _f(f), _a(a) {}
|
||||
//
|
||||
friend
|
||||
ostream& operator<<(ostream& o, omanip<TP>& m)
|
||||
{ return (*m._f)(o, m._a); }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Available Manipulators
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// Macro to define an iomanip function, with one argument
|
||||
// The underlying function is `__iomanip_<name>'
|
||||
//
|
||||
#define __DEFINE_IOMANIP_FN1(type,param,function) \
|
||||
extern ios& __iomanip_##function (ios&, param); \
|
||||
inline type<param> function (param n) \
|
||||
{ return type<param> (__iomanip_##function, n); }
|
||||
|
||||
__DEFINE_IOMANIP_FN1( smanip, int, setbase)
|
||||
__DEFINE_IOMANIP_FN1( smanip, int, setfill)
|
||||
__DEFINE_IOMANIP_FN1( smanip, int, setprecision)
|
||||
__DEFINE_IOMANIP_FN1( smanip, int, setw)
|
||||
|
||||
__DEFINE_IOMANIP_FN1( smanip, ios::fmtflags, resetiosflags)
|
||||
__DEFINE_IOMANIP_FN1( smanip, ios::fmtflags, setiosflags)
|
||||
|
||||
#endif /*!_G_NO_TEMPLATES*/
|
||||
#endif /*!_IOMANIP_H*/
|
@ -1,66 +0,0 @@
|
||||
// This is part of the iostream library, providing -*- C++ -*- input/output.
|
||||
// Copyright (C) 1991 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: ioprivate.h,v 1.2 1993/08/02 17:22:35 mycroft Exp $
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "streambuf.h"
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define _fstat(x, y) fstat(x,y)
|
||||
#define _isatty(fd) isatty(fd)
|
||||
|
||||
extern int __cvt_double(double number, register int prec, int flags,
|
||||
int *signp, int fmtch, char *startp, char *endp);
|
||||
|
||||
/*#define USE_MALLOC_BUF*/
|
||||
|
||||
#ifndef USE_MALLOC_BUF
|
||||
#define ALLOC_BUF(size) new char[size]
|
||||
#define FREE_BUF(ptr) delete [] (ptr)
|
||||
#else
|
||||
#define ALLOC_BUF(size) (char*)malloc(size)
|
||||
#define FREE_BUF(ptr) free(ptr)
|
||||
#endif
|
||||
|
||||
#define USE_DTOA
|
||||
|
||||
// Advantages:
|
||||
// - Input gets closest value
|
||||
// - Output emits string that when read yields identical value.
|
||||
// - Handles Infinity and NaNs (but not re-readable).
|
||||
// Disadvantages of dtoa:
|
||||
// - May not work for all double formats.
|
||||
// - Big chunck of code.
|
||||
// - Not reentrant - uses atatic variables freelist,
|
||||
// result, result_k in dtoa
|
||||
// (plus initializes p5s, HOWORD, and LOWORD).
|
||||
|
||||
#ifdef USE_DTOA
|
||||
extern "C" double _Xstrtod(const char *s00, char **se);
|
||||
#define strtod(s, e) _Xstrtod(s, e)
|
||||
extern "C" char *dtoa(double d, int mode, int ndigits,
|
||||
int *decpt, int *sign, char **rve);
|
||||
extern int __outfloat(double value, streambuf *sb, char mode,
|
||||
int width, int precision, __fmtflags flags,
|
||||
char sign_mode, char fill);
|
||||
#endif
|
||||
|
@ -1,783 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1991, 1992 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#endif
|
||||
#define _STREAM_COMPAT
|
||||
#include "ioprivate.h"
|
||||
#include <iostream.h>
|
||||
#include <stdio.h> /* Needed for sprintf */
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include "floatio.h"
|
||||
|
||||
#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
|
||||
|
||||
//#define isspace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n')
|
||||
|
||||
istream::istream(streambuf *sb, ostream* tied) : ios(sb, tied)
|
||||
{
|
||||
_flags |= ios::dont_close;
|
||||
_gcount = 0;
|
||||
}
|
||||
|
||||
int skip_ws(streambuf* sb)
|
||||
{
|
||||
int ch;
|
||||
for (;;) {
|
||||
ch = sb->sbumpc();
|
||||
if (ch == EOF || !isspace(ch))
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
|
||||
istream& istream::get(char& c)
|
||||
{
|
||||
if (ipfx1()) {
|
||||
int ch = _strbuf->sbumpc();
|
||||
if (ch == EOF) {
|
||||
set(ios::eofbit|ios::failbit);
|
||||
_gcount = 0;
|
||||
}
|
||||
else {
|
||||
c = (char)ch;
|
||||
_gcount = 1;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
int istream::peek()
|
||||
{
|
||||
if (!good())
|
||||
return EOF;
|
||||
if (_tie && rdbuf()->in_avail() == 0)
|
||||
_tie->flush();
|
||||
int ch = _strbuf->sgetc();
|
||||
if (ch == EOF)
|
||||
set(ios::eofbit);
|
||||
return ch;
|
||||
}
|
||||
|
||||
istream& istream::ignore(int n /* = 1 */, int delim /* = EOF */)
|
||||
{
|
||||
if (ipfx1()) {
|
||||
register streambuf* sb = _strbuf;
|
||||
if (delim == EOF) {
|
||||
_gcount = sb->ignore(n);
|
||||
return *this;
|
||||
}
|
||||
_gcount = 0;
|
||||
for (;;) {
|
||||
#if 0
|
||||
if (n != MAXINT) // FIXME
|
||||
#endif
|
||||
if (--n < 0)
|
||||
break;
|
||||
int ch = sb->sbumpc();
|
||||
if (ch == EOF) {
|
||||
set(ios::eofbit|ios::failbit);
|
||||
break;
|
||||
}
|
||||
_gcount++;
|
||||
if (ch == delim)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream& istream::read(char *s, int n)
|
||||
{
|
||||
if (ipfx1()) {
|
||||
_gcount = _strbuf->sgetn(s, n);
|
||||
if (_gcount != n)
|
||||
set(ios::failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream& istream::seekg(streampos pos)
|
||||
{
|
||||
pos = _strbuf->seekpos(pos, ios::in);
|
||||
if (pos == streampos(EOF))
|
||||
set(ios::badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream& istream::seekg(streamoff off, _seek_dir dir)
|
||||
{
|
||||
streampos pos = _strbuf->seekoff(off, dir, ios::in);
|
||||
if (pos == streampos(EOF))
|
||||
set(ios::badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
streampos istream::tellg()
|
||||
{
|
||||
streampos pos = _strbuf->seekoff(0, ios::cur, ios::in);
|
||||
if (pos == streampos(EOF))
|
||||
set(ios::badbit);
|
||||
return pos;
|
||||
}
|
||||
|
||||
istream& istream::scan(const char *format ...)
|
||||
{
|
||||
if (ipfx0()) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
_strbuf->vscan(format, ap, this);
|
||||
va_end(ap);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream& istream::vscan(const char *format, _G_va_list args)
|
||||
{
|
||||
if (ipfx0())
|
||||
_strbuf->vscan(format, args, this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream& istream::operator>>(char& c)
|
||||
{
|
||||
if (ipfx0()) {
|
||||
int ch = _strbuf->sbumpc();
|
||||
if (ch == EOF)
|
||||
set(ios::eofbit|ios::failbit);
|
||||
else
|
||||
c = (char)ch;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream& istream::operator>>(char* ptr)
|
||||
{
|
||||
register char *p = ptr;
|
||||
int w = width(0);
|
||||
if (ipfx0()) {
|
||||
register streambuf* sb = _strbuf;
|
||||
for (;;)
|
||||
{
|
||||
int ch = sb->sbumpc();
|
||||
if (ch == EOF)
|
||||
{
|
||||
set(p == ptr ? (ios::eofbit|ios::failbit) : (ios::eofbit));
|
||||
break;
|
||||
}
|
||||
else if (isspace(ch))
|
||||
{
|
||||
sb->sputbackc(ch);
|
||||
break;
|
||||
}
|
||||
else if (w == 1)
|
||||
{
|
||||
set(ios::failbit);
|
||||
sb->sputbackc(ch);
|
||||
break;
|
||||
}
|
||||
else *p++ = ch;
|
||||
w--;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define LONGEST long long
|
||||
#else
|
||||
#define LONGEST long
|
||||
#endif
|
||||
|
||||
static int read_int(istream& stream, unsigned LONGEST& val, int& neg)
|
||||
{
|
||||
if (!stream.ipfx0())
|
||||
return 0;
|
||||
register streambuf* sb = stream.rdbuf();
|
||||
int base = 10;
|
||||
int ndigits = 0;
|
||||
register int ch = skip_ws(sb);
|
||||
if (ch == EOF)
|
||||
goto eof_fail;
|
||||
neg = 0;
|
||||
if (ch == '+') {
|
||||
ch = skip_ws(sb);
|
||||
}
|
||||
else if (ch == '-') {
|
||||
neg = 1;
|
||||
ch = skip_ws(sb);
|
||||
}
|
||||
if (ch == EOF) goto eof_fail;
|
||||
if (!(stream.flags() & ios::basefield)) {
|
||||
if (ch == '0') {
|
||||
ch = sb->sbumpc();
|
||||
if (ch == EOF) {
|
||||
val = 0;
|
||||
return 1;
|
||||
}
|
||||
if (ch == 'x' || ch == 'X') {
|
||||
base = 16;
|
||||
ch = sb->sbumpc();
|
||||
if (ch == EOF) goto eof_fail;
|
||||
}
|
||||
else {
|
||||
sb->sputbackc(ch);
|
||||
base = 8;
|
||||
ch = '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((stream.flags() & ios::basefield) == ios::hex)
|
||||
base = 16;
|
||||
else if ((stream.flags() & ios::basefield) == ios::oct)
|
||||
base = 8;
|
||||
val = 0;
|
||||
for (;;) {
|
||||
if (ch == EOF)
|
||||
break;
|
||||
int digit;
|
||||
if (ch >= '0' && ch <= '9')
|
||||
digit = ch - '0';
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
digit = ch - 'A' + 10;
|
||||
else if (ch >= 'a' && ch <= 'f')
|
||||
digit = ch - 'a' + 10;
|
||||
else
|
||||
digit = 999;
|
||||
if (digit >= base) {
|
||||
sb->sputbackc(ch);
|
||||
if (ndigits == 0)
|
||||
goto fail;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
ndigits++;
|
||||
val = base * val + digit;
|
||||
ch = sb->sbumpc();
|
||||
}
|
||||
return 1;
|
||||
fail:
|
||||
stream.set(ios::failbit);
|
||||
return 0;
|
||||
eof_fail:
|
||||
stream.set(ios::failbit|ios::eofbit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define READ_INT(TYPE) \
|
||||
istream& istream::operator>>(TYPE& i)\
|
||||
{\
|
||||
unsigned LONGEST val; int neg;\
|
||||
if (read_int(*this, val, neg)) {\
|
||||
if (neg) val = -val;\
|
||||
i = (TYPE)val;\
|
||||
}\
|
||||
return *this;\
|
||||
}
|
||||
|
||||
READ_INT(short)
|
||||
READ_INT(unsigned short)
|
||||
READ_INT(int)
|
||||
READ_INT(unsigned int)
|
||||
READ_INT(long)
|
||||
READ_INT(unsigned long)
|
||||
#ifdef __GNUG__
|
||||
READ_INT(long long)
|
||||
READ_INT(unsigned long long)
|
||||
#endif
|
||||
|
||||
istream& istream::operator>>(double& x)
|
||||
{
|
||||
if (ipfx0())
|
||||
scan("%lg", &x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream& istream::operator>>(float& x)
|
||||
{
|
||||
if (ipfx0())
|
||||
scan("%g", &x);
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream& istream::operator>>(register streambuf* sbuf)
|
||||
{
|
||||
if (ipfx0()) {
|
||||
register streambuf* inbuf = rdbuf();
|
||||
// FIXME: Should optimize!
|
||||
for (;;) {
|
||||
register int ch = inbuf->sbumpc();
|
||||
if (ch == EOF) {
|
||||
set(ios::eofbit);
|
||||
break;
|
||||
}
|
||||
if (sbuf->sputc(ch) == EOF) {
|
||||
set(ios::failbit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(char c)
|
||||
{
|
||||
if (opfx()) {
|
||||
#if 1
|
||||
// This is what the cfront implementation does.
|
||||
_strbuf->sputc(c);
|
||||
#else
|
||||
// This is what cfront documentation and current ANSI drafts say.
|
||||
int w = width(0);
|
||||
char fill_char = fill();
|
||||
register int padding = w > 0 ? w - 1 : 0;
|
||||
register streambuf *sb = _strbuf;
|
||||
if (!(flags() & ios::left)) // Default adjustment.
|
||||
while (--padding >= 0) sb->sputc(fill_char);
|
||||
sb->sputc(c);
|
||||
if (flags() & ios::left) // Left adjustment.
|
||||
while (--padding >= 0) sb->sputc(fill_char);
|
||||
#endif
|
||||
osfx();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Write VAL on STREAM.
|
||||
If SIGN<0, val is the absolute value of a negative number.
|
||||
If SIGN>0, val is a signed non-negative number.
|
||||
If SIGN==0, val is unsigned. */
|
||||
|
||||
static void write_int(ostream& stream, unsigned LONGEST val, int sign)
|
||||
{
|
||||
#define WRITE_BUF_SIZE (10 + sizeof(unsigned LONGEST) * 3)
|
||||
char buf[WRITE_BUF_SIZE];
|
||||
register char *buf_ptr = buf+WRITE_BUF_SIZE; // End of buf.
|
||||
char *show_base = "";
|
||||
int show_base_len = 0;
|
||||
int show_pos = 0; // If 1, print a '+'.
|
||||
|
||||
// Now do the actual conversion, placing the result at the *end* of buf.
|
||||
// Note that we use separate code for decimal, octal, and hex,
|
||||
// so we can divide by optimizable constants.
|
||||
if ((stream.flags() & ios::basefield) == ios::oct) { // Octal
|
||||
do {
|
||||
*--buf_ptr = (val & 7) + '0';
|
||||
val = val >> 3;
|
||||
} while (val != 0);
|
||||
if ((stream.flags() & ios::showbase) && (val != 0))
|
||||
*--buf_ptr = '0';
|
||||
}
|
||||
else if ((stream.flags() & ios::basefield) == ios::hex) { // Hex
|
||||
char *xdigs = (stream.flags() & ios::uppercase) ? "0123456789ABCDEF0X"
|
||||
: "0123456789abcdef0x";
|
||||
do {
|
||||
*--buf_ptr = xdigs[val & 15];
|
||||
val = val >> 4;
|
||||
} while (val != 0);
|
||||
if ((stream.flags() & ios::showbase) && (val != 0)) {
|
||||
show_base = xdigs + 16; // Either "0X" or "0x".
|
||||
show_base_len = 2;
|
||||
}
|
||||
}
|
||||
else { // Decimal
|
||||
#ifdef __GNUC__
|
||||
// Optimization: Only use long long when we need to.
|
||||
while (val > UINT_MAX) {
|
||||
*--buf_ptr = (val % 10) + '0';
|
||||
val /= 10;
|
||||
}
|
||||
// Use more efficient (int) arithmetic for the rest.
|
||||
register unsigned int ival = (unsigned int)val;
|
||||
#else
|
||||
register unsigned LONGEST ival = val;
|
||||
#endif
|
||||
do {
|
||||
*--buf_ptr = (ival % 10) + '0';
|
||||
ival /= 10;
|
||||
} while (ival != 0);
|
||||
if (sign > 0 && (stream.flags() & ios::showpos))
|
||||
show_pos=1;
|
||||
}
|
||||
|
||||
int buf_len = buf+WRITE_BUF_SIZE - buf_ptr;
|
||||
int w = stream.width(0);
|
||||
|
||||
// Calculate padding.
|
||||
int len = buf_len+show_pos;
|
||||
if (sign < 0) len++;
|
||||
len += show_base_len;
|
||||
int padding = len > w ? 0 : w - len;
|
||||
|
||||
// Do actual output.
|
||||
register streambuf* sbuf = stream.rdbuf();
|
||||
ios::fmtflags pad_kind =
|
||||
stream.flags() & (ios::left|ios::right|ios::internal);
|
||||
char fill_char = stream.fill();
|
||||
if (padding > 0
|
||||
&& pad_kind != (ios::fmtflags)ios::left
|
||||
&& pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust.
|
||||
sbuf->padn(fill_char, padding);
|
||||
if (sign < 0) sbuf->sputc('-');
|
||||
else if (show_pos) sbuf->sputc('+');
|
||||
if (show_base_len)
|
||||
sbuf->sputn(show_base, show_base_len);
|
||||
if (pad_kind == (ios::fmtflags)ios::internal && padding > 0)
|
||||
sbuf->padn(fill_char, padding);
|
||||
sbuf->sputn(buf_ptr, buf_len);
|
||||
if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment
|
||||
sbuf->padn(fill_char, padding);
|
||||
stream.osfx();
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(int n)
|
||||
{
|
||||
if (opfx()) {
|
||||
int sign = 1;
|
||||
if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
|
||||
n = -n, sign = -1;
|
||||
write_int(*this, n, sign);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(unsigned int n)
|
||||
{
|
||||
if (opfx())
|
||||
write_int(*this, n, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
ostream& ostream::operator<<(long n)
|
||||
{
|
||||
if (opfx()) {
|
||||
int sign = 1;
|
||||
if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
|
||||
n = -n, sign = -1;
|
||||
write_int(*this, n, sign);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(unsigned long n)
|
||||
{
|
||||
if (opfx())
|
||||
write_int(*this, n, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef __GNUG__
|
||||
ostream& ostream::operator<<(long long n)
|
||||
{
|
||||
if (opfx()) {
|
||||
int sign = 1;
|
||||
if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
|
||||
n = -n, sign = -1;
|
||||
write_int(*this, n, sign);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
ostream& ostream::operator<<(unsigned long long n)
|
||||
{
|
||||
if (opfx())
|
||||
write_int(*this, n, 0);
|
||||
return *this;
|
||||
}
|
||||
#endif /*__GNUG__*/
|
||||
|
||||
ostream& ostream::operator<<(double n)
|
||||
{
|
||||
if (opfx()) {
|
||||
// Uses __cvt_double (renamed from static cvt), in Chris Torek's
|
||||
// stdio implementation. The setup code uses the same logic
|
||||
// as in __vsbprintf.C (also based on Torek's code).
|
||||
int format_char;
|
||||
#if 0
|
||||
if (flags() ios::showpos) sign = '+';
|
||||
#endif
|
||||
if ((flags() & ios::floatfield) == ios::fixed)
|
||||
format_char = 'f';
|
||||
else if ((flags() & ios::floatfield) == ios::scientific)
|
||||
format_char = flags() & ios::uppercase ? 'E' : 'e';
|
||||
else
|
||||
format_char = flags() & ios::uppercase ? 'G' : 'g';
|
||||
|
||||
int fpprec = 0; // 'Extra' (suppressed) floating precision.
|
||||
int prec = precision();
|
||||
if (prec > MAXFRACT) {
|
||||
if (flags() & (ios::fixed|ios::scientific) & ios::showpos)
|
||||
fpprec = prec - MAXFRACT;
|
||||
prec = MAXFRACT;
|
||||
}
|
||||
else if (prec <= 0 && !(flags() & ios::fixed))
|
||||
prec = 6; /* default */
|
||||
|
||||
// Do actual conversion.
|
||||
#ifdef USE_DTOA
|
||||
if (__outfloat(n, rdbuf(), format_char, width(0),
|
||||
prec, flags(), 0, fill()) < 0)
|
||||
set(ios::badbit|ios::failbit); // ??
|
||||
#else
|
||||
int negative;
|
||||
char buf[BUF];
|
||||
int sign = '\0';
|
||||
char *cp = buf;
|
||||
*cp = 0;
|
||||
int size = __cvt_double(n, prec,
|
||||
flags() & ios::showpoint ? 0x80 : 0,
|
||||
&negative,
|
||||
format_char, cp, buf + sizeof(buf));
|
||||
if (negative) sign = '-';
|
||||
if (*cp == 0)
|
||||
cp++;
|
||||
|
||||
// Calculate padding.
|
||||
int fieldsize = size + fpprec;
|
||||
if (sign) fieldsize++;
|
||||
int padding = 0;
|
||||
int w = width(0);
|
||||
if (fieldsize < w)
|
||||
padding = w - fieldsize;
|
||||
|
||||
// Do actual output.
|
||||
register streambuf* sbuf = rdbuf();
|
||||
register i;
|
||||
char fill_char = fill();
|
||||
ios::fmtflags pad_kind =
|
||||
flags() & (ios::left|ios::right|ios::internal);
|
||||
if (pad_kind != (ios::fmtflags)ios::left // Default (right) adjust.
|
||||
&& pad_kind != (ios::fmtflags)ios::internal)
|
||||
for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
|
||||
if (sign)
|
||||
sbuf->sputc(sign);
|
||||
if (pad_kind == (ios::fmtflags)ios::internal)
|
||||
for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
|
||||
|
||||
// Emit the actual concented field, followed by extra zeros.
|
||||
sbuf->sputn(cp, size);
|
||||
for (i = fpprec; --i >= 0; ) sbuf->sputc('0');
|
||||
|
||||
if (pad_kind == (ios::fmtflags)ios::left) // Left adjustment
|
||||
for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
|
||||
#endif
|
||||
osfx();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(const char *s)
|
||||
{
|
||||
if (opfx()) {
|
||||
if (s == NULL)
|
||||
s = "(null)";
|
||||
int len = strlen(s);
|
||||
int w = width(0);
|
||||
char fill_char = fill();
|
||||
register streambuf *sbuf = rdbuf();
|
||||
register int padding = w > len ? w - len : 0;
|
||||
if (!(flags() & ios::left)) // Default adjustment.
|
||||
while (--padding >= 0) sbuf->sputc(fill_char);
|
||||
sbuf->sputn(s, len);
|
||||
if (flags() & ios::left) // Left adjustment.
|
||||
while (--padding >= 0) sbuf->sputc(fill_char);
|
||||
osfx();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(const void *p)
|
||||
{
|
||||
if (opfx()) {
|
||||
form("%p", p);
|
||||
osfx();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::operator<<(register streambuf* sbuf)
|
||||
{
|
||||
if (opfx()) {
|
||||
register streambuf* outbuf = rdbuf();
|
||||
// FIXME: Should optimize!
|
||||
for (;;) {
|
||||
register int ch = sbuf->sbumpc();
|
||||
if (ch == EOF) break;
|
||||
if (outbuf->sputc(ch) == EOF) {
|
||||
set(ios::badbit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
osfx();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream::ostream(streambuf* sb, ostream* tied) : ios(sb, tied)
|
||||
{
|
||||
_flags |= ios::dont_close;
|
||||
}
|
||||
|
||||
ostream& ostream::seekp(streampos pos)
|
||||
{
|
||||
pos = _strbuf->seekpos(pos, ios::out);
|
||||
if (pos == streampos(EOF))
|
||||
set(ios::badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::seekp(streamoff off, _seek_dir dir)
|
||||
{
|
||||
streampos pos = _strbuf->seekoff(off, dir, ios::out);
|
||||
if (pos == streampos(EOF))
|
||||
set(ios::badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
streampos ostream::tellp()
|
||||
{
|
||||
streampos pos = _strbuf->seekoff(0, ios::cur, ios::out);
|
||||
if (pos == streampos(EOF))
|
||||
set(ios::badbit);
|
||||
return pos;
|
||||
}
|
||||
|
||||
ostream& ostream::form(const char *format ...)
|
||||
{
|
||||
if (opfx()) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
_strbuf->vform(format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::vform(const char *format, _G_va_list args)
|
||||
{
|
||||
if (opfx())
|
||||
_strbuf->vform(format, args);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& ostream::flush()
|
||||
{
|
||||
if (_strbuf->sync())
|
||||
set(ios::badbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ostream& flush(ostream& outs)
|
||||
{
|
||||
return outs.flush();
|
||||
}
|
||||
|
||||
istream& ws(istream& ins)
|
||||
{
|
||||
if (ins.ipfx1()) {
|
||||
int ch = skip_ws(ins._strbuf);
|
||||
if (ch == EOF)
|
||||
ins.set(ios::eofbit);
|
||||
else
|
||||
ins._strbuf->sputbackc(ch);
|
||||
}
|
||||
return ins;
|
||||
}
|
||||
|
||||
// Skip white-space. Return 0 on failure (EOF), or 1 on success.
|
||||
// Differs from ws() manipulator in that failbit is set on EOF.
|
||||
// Called by ipfx() and ipfx0() if needed.
|
||||
|
||||
int istream::_skip_ws()
|
||||
{
|
||||
int ch = skip_ws(_strbuf);
|
||||
if (ch == EOF) {
|
||||
set(ios::eofbit|ios::failbit);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
_strbuf->sputbackc(ch);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
ostream& ends(ostream& outs)
|
||||
{
|
||||
outs.put('\0');
|
||||
return outs;
|
||||
}
|
||||
|
||||
ostream& endl(ostream& outs)
|
||||
{
|
||||
return flush(outs.put('\n'));
|
||||
}
|
||||
|
||||
ostream& ostream::write(const char *s, int n)
|
||||
{
|
||||
if (opfx()) {
|
||||
if (_strbuf->sputn(s, n) != n)
|
||||
set(ios::failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ostream::do_osfx()
|
||||
{
|
||||
if (flags() & ios::unitbuf)
|
||||
flush();
|
||||
if (flags() & ios::stdio) {
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
iostream::iostream(streambuf* sb, ostream* tied) : ios(sb, tied)
|
||||
{
|
||||
_flags |= ios::dont_close;
|
||||
_gcount = 0;
|
||||
}
|
||||
|
||||
// NOTE: extension for compatibility with old libg++.
|
||||
// Not really compatible with fistream::close().
|
||||
#ifdef _STREAM_COMPAT
|
||||
void ios::close()
|
||||
{
|
||||
if (!(_flags & (unsigned int)ios::dont_close))
|
||||
delete _strbuf;
|
||||
else if (_strbuf->_flags & _S_IS_FILEBUF)
|
||||
((struct filebuf*)_strbuf)->close();
|
||||
else if (_strbuf != NULL)
|
||||
_strbuf->sync();
|
||||
_flags |= ios::dont_close;
|
||||
_strbuf = NULL;
|
||||
_state = badbit;
|
||||
}
|
||||
|
||||
int istream::skip(int i)
|
||||
{
|
||||
int old = (_flags & ios::skipws) != 0;
|
||||
if (i)
|
||||
_flags |= ios::skipws;
|
||||
else
|
||||
_flags &= ~ios::skipws;
|
||||
return old;
|
||||
}
|
||||
#endif
|
@ -1,228 +0,0 @@
|
||||
// This is part of the iostream library, providing -*- C++ -*- input/output.
|
||||
// Copyright (C) 1991 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: iostream.h,v 1.2 1993/08/02 17:22:36 mycroft Exp $
|
||||
|
||||
#ifndef _IOSTREAM_H
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
#define _IOSTREAM_H
|
||||
|
||||
#include <streambuf.h>
|
||||
|
||||
class istream; class ostream;
|
||||
typedef ios& (*__manip)(ios&);
|
||||
typedef istream& (*__imanip)(istream&);
|
||||
typedef ostream& (*__omanip)(ostream&);
|
||||
|
||||
extern istream& ws(istream& ins);
|
||||
extern ostream& flush(ostream& outs);
|
||||
extern ostream& endl(ostream& outs);
|
||||
extern ostream& ends(ostream& outs);
|
||||
|
||||
class ostream : virtual public ios
|
||||
{
|
||||
// NOTE: If fields are changed, you must fix _fake_ostream in stdstreams.C!
|
||||
void do_osfx();
|
||||
public:
|
||||
ostream() { }
|
||||
ostream(streambuf* sb, ostream* tied=NULL);
|
||||
int opfx() {
|
||||
if (!good()) return 0; else { if (_tie) _tie->flush(); return 1;} }
|
||||
void osfx() { if (flags() & (ios::unitbuf|ios::stdio))
|
||||
do_osfx(); }
|
||||
streambuf* ostreambuf() const { return _strbuf; }
|
||||
ostream& flush();
|
||||
ostream& put(char c) { _strbuf->sputc(c); return *this; }
|
||||
ostream& put(unsigned char c) { return put((char)c); }
|
||||
|
||||
ostream& write(const char *s, int n);
|
||||
ostream& write(const unsigned char *s, int n) { return write((const char*)s, n);}
|
||||
#ifndef _G_BROKEN_SIGNED_CHAR
|
||||
ostream& put(signed char c) { return put((char)c); }
|
||||
ostream& write(const signed char *s, int n) { return write((const char*)s, n);}
|
||||
#endif
|
||||
ostream& write(const void *s, int n) { return write((const char*)s, n);}
|
||||
ostream& seekp(streampos);
|
||||
ostream& seekp(streamoff, _seek_dir);
|
||||
streampos tellp();
|
||||
ostream& form(const char *format ...);
|
||||
ostream& vform(const char *format, _G_va_list args);
|
||||
|
||||
ostream& operator<<(char c);
|
||||
ostream& operator<<(unsigned char c) { return (*this) << (char)c; }
|
||||
#ifndef _G_BROKEN_SIGNED_CHAR
|
||||
ostream& operator<<(signed char c) { return (*this) << (char)c; }
|
||||
#endif
|
||||
ostream& operator<<(const char *s);
|
||||
ostream& operator<<(const unsigned char *s)
|
||||
{ return (*this) << (const char*)s; }
|
||||
#ifndef _G_BROKEN_SIGNED_CHAR
|
||||
ostream& operator<<(const signed char *s)
|
||||
{ return (*this) << (const char*)s; }
|
||||
#endif
|
||||
ostream& operator<<(const void *p);
|
||||
ostream& operator<<(int n);
|
||||
ostream& operator<<(unsigned int n);
|
||||
ostream& operator<<(long n);
|
||||
ostream& operator<<(unsigned long n);
|
||||
#ifdef __GNUG__
|
||||
ostream& operator<<(long long n);
|
||||
ostream& operator<<(unsigned long long n);
|
||||
#endif
|
||||
ostream& operator<<(short n) {return operator<<((int)n);}
|
||||
ostream& operator<<(unsigned short n) {return operator<<((unsigned int)n);}
|
||||
ostream& operator<<(double n);
|
||||
ostream& operator<<(float n) { return operator<<((double)n); }
|
||||
ostream& operator<<(__omanip func) { return (*func)(*this); }
|
||||
ostream& operator<<(__manip func) {(*func)(*this); return *this;}
|
||||
ostream& operator<<(streambuf*);
|
||||
};
|
||||
|
||||
class istream : virtual public ios
|
||||
{
|
||||
// NOTE: If fields are changed, you must fix _fake_istream in stdstreams.C!
|
||||
_G_ssize_t _gcount;
|
||||
|
||||
int _skip_ws();
|
||||
public:
|
||||
istream() { _gcount = 0; }
|
||||
istream(streambuf* sb, ostream*tied=NULL);
|
||||
streambuf* istreambuf() const { return _strbuf; }
|
||||
istream& get(char* ptr, int len, char delim = '\n');
|
||||
istream& get(unsigned char* ptr, int len, char delim = '\n')
|
||||
{ return get((char*)ptr, len, delim); }
|
||||
istream& get(char& c);
|
||||
istream& get(unsigned char& c) { return get((char&)c); }
|
||||
istream& getline(char* ptr, int len, char delim = '\n');
|
||||
istream& getline(unsigned char* ptr, int len, char delim = '\n')
|
||||
{ return getline((char*)ptr, len, delim); }
|
||||
#ifndef _G_BROKEN_SIGNED_CHAR
|
||||
istream& get(signed char& c) { return get((char&)c); }
|
||||
istream& get(signed char* ptr, int len, char delim = '\n')
|
||||
{ return get((char*)ptr, len, delim); }
|
||||
istream& getline(signed char* ptr, int len, char delim = '\n')
|
||||
{ return getline((char*)ptr, len, delim); }
|
||||
#endif
|
||||
istream& read(char *ptr, int n);
|
||||
istream& read(unsigned char *ptr, int n) { return read((char*)ptr, n); }
|
||||
#ifndef _G_BROKEN_SIGNED_CHAR
|
||||
istream& read(signed char *ptr, int n) { return read((char*)ptr, n); }
|
||||
#endif
|
||||
istream& read(void *ptr, int n) { return read((char*)ptr, n); }
|
||||
istream& get(streambuf& sb, char delim = '\n');
|
||||
istream& gets(char **s, char delim = '\n');
|
||||
int ipfx(int need) {
|
||||
if (!good()) { set(ios::failbit); return 0; }
|
||||
else {
|
||||
if (_tie && (need == 0 || rdbuf()->in_avail() < need)) _tie->flush();
|
||||
if (!need && (flags() & ios::skipws)) return _skip_ws();
|
||||
else return 1;
|
||||
}
|
||||
}
|
||||
int ipfx0() { // Optimized version of ipfx(0).
|
||||
if (!good()) { set(ios::failbit); return 0; }
|
||||
else {
|
||||
if (_tie) _tie->flush();
|
||||
if (flags() & ios::skipws) return _skip_ws();
|
||||
else return 1;
|
||||
}
|
||||
}
|
||||
int ipfx1() { // Optimized version of ipfx(1).
|
||||
if (!good()) { set(ios::failbit); return 0; }
|
||||
else {
|
||||
if (_tie && rdbuf()->in_avail() == 0) _tie->flush();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
void isfx() { }
|
||||
int get() { if (!ipfx1()) return EOF;
|
||||
else { int ch = _strbuf->sbumpc();
|
||||
if (ch == EOF) set(ios::eofbit);
|
||||
return ch;
|
||||
} }
|
||||
int peek();
|
||||
_G_ssize_t gcount() { return _gcount; }
|
||||
istream& ignore(int n=1, int delim = EOF);
|
||||
istream& seekg(streampos);
|
||||
istream& seekg(streamoff, _seek_dir);
|
||||
streampos tellg();
|
||||
istream& putback(char ch) {
|
||||
if (good() && _strbuf->sputbackc(ch) == EOF) clear(ios::badbit);
|
||||
return *this;}
|
||||
istream& unget() {
|
||||
if (good() && _strbuf->sungetc() == EOF) clear(ios::badbit);
|
||||
return *this;}
|
||||
istream& scan(const char *format ...);
|
||||
istream& vscan(const char *format, _G_va_list args);
|
||||
#ifdef _STREAM_COMPAT
|
||||
istream& unget(char ch) { return putback(ch); }
|
||||
int skip(int i);
|
||||
#endif
|
||||
|
||||
istream& operator>>(char*);
|
||||
istream& operator>>(unsigned char* p) { return operator>>((char*)p); }
|
||||
#ifndef _G_BROKEN_SIGNED_CHAR
|
||||
istream& operator>>(signed char*p) { return operator>>((char*)p); }
|
||||
#endif
|
||||
istream& operator>>(char& c);
|
||||
istream& operator>>(unsigned char& c) {return operator>>((char&)c);}
|
||||
#ifndef _G_BROKEN_SIGNED_CHAR
|
||||
istream& operator>>(signed char& c) {return operator>>((char&)c);}
|
||||
#endif
|
||||
istream& operator>>(int&);
|
||||
istream& operator>>(long&);
|
||||
#ifdef __GNUG__
|
||||
istream& operator>>(long long&);
|
||||
#endif
|
||||
istream& operator>>(short&);
|
||||
istream& operator>>(unsigned int&);
|
||||
istream& operator>>(unsigned long&);
|
||||
#ifdef __GNUG__
|
||||
istream& operator>>(unsigned long long&);
|
||||
#endif
|
||||
istream& operator>>(unsigned short&);
|
||||
istream& operator>>(float&);
|
||||
istream& operator>>(double&);
|
||||
istream& operator>>( __manip func) {(*func)(*this); return *this;}
|
||||
istream& operator>>(__imanip func) { return (*func)(*this); }
|
||||
istream& operator>>(streambuf*);
|
||||
};
|
||||
|
||||
|
||||
class iostream : public istream, public ostream
|
||||
{
|
||||
_G_ssize_t _gcount;
|
||||
public:
|
||||
iostream() { _gcount = 0; }
|
||||
iostream(streambuf* sb, ostream*tied=NULL);
|
||||
};
|
||||
|
||||
extern istream cin;
|
||||
extern ostream cout, cerr, clog; // clog->rdbuf() == cerr->rdbuf()
|
||||
|
||||
struct Iostream_init { } ; // Compatibility hack for AT&T library.
|
||||
|
||||
inline ios& dec(ios& i)
|
||||
{ i.setf(ios::dec, ios::dec|ios::hex|ios::oct); return i; }
|
||||
inline ios& hex(ios& i)
|
||||
{ i.setf(ios::hex, ios::dec|ios::hex|ios::oct); return i; }
|
||||
inline ios& oct(ios& i)
|
||||
{ i.setf(ios::oct, ios::dec|ios::hex|ios::oct); return i; }
|
||||
|
||||
#endif /*!_IOSTREAM_H*/
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
// Modified for GNU iostream by Per Bothner 1991.
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "%W% (Berkeley) %G%";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include "ioprivate.h"
|
||||
#include "fstream.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/*
|
||||
* Allocate a file buffer, or switch to unbuffered I/O.
|
||||
* Per the ANSI C standard, ALL tty devices default to line buffered.
|
||||
*
|
||||
* As a side effect, we set __SOPT or __SNPT (en/dis-able fseek
|
||||
* optimisation) right after the _fstat() that finds the buffer size.
|
||||
*/
|
||||
int filebuf::doallocate()
|
||||
{
|
||||
register size_t size, couldbetty;
|
||||
register char *p;
|
||||
struct stat st;
|
||||
|
||||
if (fd() < 0 || _fstat(fd(), &st) < 0) {
|
||||
couldbetty = 0;
|
||||
size = _G_BUFSIZ;
|
||||
#if 0
|
||||
/* do not try to optimise fseek() */
|
||||
fp->_flags |= __SNPT;
|
||||
#endif
|
||||
} else {
|
||||
couldbetty = S_ISCHR(st.st_mode);
|
||||
#if _G_HAVE_ST_BLKSIZE
|
||||
size = st.st_blksize <= 0 ? _G_BUFSIZ : st.st_blksize;
|
||||
#else
|
||||
size = _G_BUFSIZ;
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_MALLOC_BUF
|
||||
if ((p = malloc(size)) == NULL) {
|
||||
unbuffered(1);
|
||||
// fp->_bf._base = fp->_p = fp->_nbuf;
|
||||
// fp->_bf._size = 1;
|
||||
return EOF;
|
||||
}
|
||||
#else
|
||||
p = ALLOC_BUF(size);
|
||||
#endif
|
||||
setb(p, p+size, 1);
|
||||
if (couldbetty && _isatty(fd()))
|
||||
_flags |= _S_LINE_BUF;
|
||||
return 1;
|
||||
}
|
@ -1,183 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1992 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#include "ioprivate.h"
|
||||
|
||||
// Format floating-point number and print them.
|
||||
// Return number of chars printed, or EOF on error.
|
||||
|
||||
// sign_mode == '+' : print "-" or "+"
|
||||
// sign_mode == ' ' : print "-" or " "
|
||||
// sign_mode == '\0' : print "-' or ""
|
||||
|
||||
int __outfloat(double value, streambuf *sb, char type,
|
||||
int width, int precision, ios::fmtflags flags,
|
||||
char sign_mode, char fill)
|
||||
{
|
||||
int count = 0;
|
||||
#define PUT(x) do {if (sb->sputc(x) < 0) goto error; count++;} while (0)
|
||||
#define PUTN(p, n) \
|
||||
do {int _n=n; count+=_n; if (sb->sputn(p,_n) != _n) goto error;} while(0)
|
||||
#define PADN(fill, n) \
|
||||
do {int _n = n; count+=_n; if (sb->padn(fill, _n) < 0) goto error;} while (0)
|
||||
ios::fmtflags pad_kind = flags & (ios::left|ios::right|ios::internal);
|
||||
int skip_zeroes = 0;
|
||||
int show_dot = (flags & ios::showpoint) != 0;
|
||||
int decpt;
|
||||
int sign;
|
||||
int mode;
|
||||
#define EBUF_SIZE 12
|
||||
#define EBUF_END &ebuf[EBUF_SIZE]
|
||||
char ebuf[EBUF_SIZE];
|
||||
char *end;
|
||||
int exp = 0;
|
||||
switch (type) {
|
||||
case 'f':
|
||||
mode = 3;
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
exp = type;
|
||||
mode = 2;
|
||||
if (precision != 999)
|
||||
precision++; // Add one to include digit before decimal point.
|
||||
break;
|
||||
case 'g':
|
||||
case 'G':
|
||||
exp = type == 'g' ? 'e' : 'E';
|
||||
if (precision == 0) precision = 1;
|
||||
if (!(flags & ios::showpoint))
|
||||
skip_zeroes = 1;
|
||||
type = 'g';
|
||||
mode = 2;
|
||||
break;
|
||||
}
|
||||
/* Do the actual convension */
|
||||
if (precision == 999 && mode != 3)
|
||||
mode = 0;
|
||||
char *p = dtoa(value, mode, precision, &decpt, &sign, &end);
|
||||
register int i;
|
||||
int useful_digits = end-p;
|
||||
char *exponent_start = EBUF_END;
|
||||
if (mode == 0)
|
||||
precision = useful_digits;
|
||||
// Check if we need to emit an exponent.
|
||||
if (mode != 3 && decpt != 9999) {
|
||||
i = decpt - 1;
|
||||
if ((type != 'g' && type != 'F') || i < -4 || i >= precision) {
|
||||
// Print the exponent into ebuf.
|
||||
// We write ebuf in reverse order (right-to-left).
|
||||
char sign;
|
||||
if (i >= 0)
|
||||
sign = '+';
|
||||
else
|
||||
sign = '-', i = -i;
|
||||
/* Note: ANSI requires at least 2 exponent digits. */
|
||||
do {
|
||||
*--exponent_start = (i % 10) + '0';
|
||||
i /= 10;
|
||||
} while (i >= 10);
|
||||
*--exponent_start = i + '0';
|
||||
*--exponent_start = sign;
|
||||
*--exponent_start = exp;
|
||||
}
|
||||
}
|
||||
int exponent_size = EBUF_END - exponent_start;
|
||||
if (mode == 1)
|
||||
precision = 1;
|
||||
/* If we print an exponent, always show just one digit before point. */
|
||||
if (exponent_size)
|
||||
decpt = 1;
|
||||
if (decpt == 9999) { // Infinity or NaN
|
||||
decpt = useful_digits;
|
||||
precision = 0;
|
||||
show_dot = 0;
|
||||
}
|
||||
|
||||
// dtoa truncates trailing zeroes. Set the variable trailing_zeroes to
|
||||
// the number of 0's we have to add (after the decimal point).
|
||||
int trailing_zeroes = 0;
|
||||
if (skip_zeroes)
|
||||
trailing_zeroes = 0;
|
||||
else if (type == 'f')
|
||||
trailing_zeroes = useful_digits <= decpt ? precision
|
||||
: precision-(useful_digits-decpt);
|
||||
else if (exponent_size) // 'e' 'E' or 'g' format using exponential notation.
|
||||
trailing_zeroes = precision - useful_digits;
|
||||
else // 'g' format not using exponential notation.
|
||||
trailing_zeroes = useful_digits <= decpt ? precision - decpt
|
||||
: precision-useful_digits;
|
||||
if (trailing_zeroes < 0) trailing_zeroes = 0;
|
||||
|
||||
if (trailing_zeroes != 0 || useful_digits > decpt)
|
||||
show_dot = 1;
|
||||
int print_sign;
|
||||
if (sign_mode == 0)
|
||||
print_sign = sign ? '-' : 0;
|
||||
else if (sign_mode == '+')
|
||||
print_sign = sign ? '-' : '+';
|
||||
else /* if (sign_mode == ' ') */
|
||||
print_sign = sign ? '-' : ' ';
|
||||
|
||||
// Calculate the width (before padding).
|
||||
int unpadded_width =
|
||||
(print_sign != 0) + trailing_zeroes + exponent_size + show_dot
|
||||
+ useful_digits
|
||||
+ (decpt > useful_digits ? decpt - useful_digits
|
||||
: decpt > 0 ? 0 : 1 - decpt);
|
||||
|
||||
int padding = width > unpadded_width ? width - unpadded_width : 0;
|
||||
if (padding > 0
|
||||
&& pad_kind != (ios::fmtflags)ios::left
|
||||
&& pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust.
|
||||
PADN(fill, padding);
|
||||
if (print_sign)
|
||||
PUT(print_sign);
|
||||
if (pad_kind == (ios::fmtflags)ios::internal && padding > 0)
|
||||
PADN(fill, padding);
|
||||
if (decpt > 0) {
|
||||
if (useful_digits >= decpt)
|
||||
PUTN(p, decpt);
|
||||
else {
|
||||
PUTN(p, useful_digits);
|
||||
PADN('0', decpt-useful_digits);
|
||||
}
|
||||
if (show_dot) {
|
||||
PUT('.');
|
||||
// Print digits after the decimal point.
|
||||
if (useful_digits > decpt)
|
||||
PUTN(p + decpt, useful_digits-decpt);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PUT('0');
|
||||
if (show_dot) {
|
||||
PUT('.');
|
||||
PADN('0', -decpt);
|
||||
// Print digits after the decimal point.
|
||||
PUTN(p, useful_digits);
|
||||
}
|
||||
}
|
||||
PADN('0', trailing_zeroes);
|
||||
if (exponent_size)
|
||||
PUTN(exponent_start, exponent_size);
|
||||
if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment
|
||||
PADN(fill, padding);
|
||||
return count;
|
||||
error:
|
||||
return EOF;
|
||||
}
|
@ -1,307 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1991 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#endif
|
||||
#include "ioprivate.h"
|
||||
#include "parsestream.h"
|
||||
|
||||
streambuf* parsebuf::setbuf(char*, int)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int parsebuf::tell_in_line()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parsebuf::pbackfail(int c)
|
||||
{
|
||||
if (c == EOF)
|
||||
return 0;
|
||||
if (seekoff(-1, ios::cur) == EOF)
|
||||
return EOF;
|
||||
return (unsigned char)c;
|
||||
}
|
||||
|
||||
char* parsebuf::current_line() { return NULL; }
|
||||
|
||||
streampos parsebuf::seekoff(streamoff offset, _seek_dir dir, int)
|
||||
{
|
||||
// Make offset relative to line start.
|
||||
switch (dir) {
|
||||
case ios::beg:
|
||||
offset -= pos_at_line_start;
|
||||
break;
|
||||
case ios::cur:
|
||||
offset += tell_in_line();
|
||||
break;
|
||||
default:
|
||||
return EOF;
|
||||
}
|
||||
if (offset < -1)
|
||||
return EOF;
|
||||
if (offset > _line_length + 1)
|
||||
return EOF;
|
||||
return seek_in_line(offset) + pos_at_line_start;
|
||||
}
|
||||
|
||||
// string_parsebuf invariants:
|
||||
// The reserve ares (base() .. ebuf()) is always the entire string.
|
||||
// The get area (eback() .. egptr()) is the extended current line
|
||||
// (i.e. with the '\n' at either end, if these exist).
|
||||
|
||||
string_parsebuf::string_parsebuf(char *buf, int len,
|
||||
int delete_at_close /* = 0*/)
|
||||
: parsebuf()
|
||||
{
|
||||
setb(buf, buf+len, delete_at_close);
|
||||
register char *ptr = buf;
|
||||
while (ptr < ebuf() && *ptr != '\n') ptr++;
|
||||
_line_length = ptr - buf;
|
||||
setg(buf, buf, ptr);
|
||||
}
|
||||
|
||||
int string_parsebuf::underflow()
|
||||
{
|
||||
register char* ptr = egptr(); // Point to end of current_line
|
||||
do {
|
||||
int i = right() - ptr;
|
||||
if (i <= 0)
|
||||
return EOF;
|
||||
ptr++; i--; // Skip '\n'.
|
||||
char *line_start = ptr;
|
||||
while (ptr < right() && *ptr == '\n') ptr++;
|
||||
setg(line_start-1, line_start, ptr + (ptr < right()));
|
||||
pos_at_line_start = line_start - left();
|
||||
_line_length = ptr - line_start;
|
||||
__line_number++;
|
||||
} while (gptr() == ptr);
|
||||
return *gptr();
|
||||
}
|
||||
|
||||
char* string_parsebuf::current_line()
|
||||
{
|
||||
char *ptr = eback();
|
||||
if (__line_number > 0)
|
||||
ptr++; // Skip '\n' at end of previous line.
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int string_parsebuf::tell_in_line()
|
||||
{
|
||||
int offset = gptr() - eback();
|
||||
if (__line_number > 0)
|
||||
offset--;
|
||||
return offset;
|
||||
}
|
||||
|
||||
int string_parsebuf::seek_in_line(int i)
|
||||
{
|
||||
int delta = i - tell_in_line();
|
||||
gbump(delta); // FIXME: Needs error (bounds) checking!
|
||||
return i;
|
||||
}
|
||||
|
||||
static const char NewLine[1] = { '\n' };
|
||||
|
||||
general_parsebuf::general_parsebuf(streambuf *buf, int delete_arg_buf)
|
||||
: parsebuf()
|
||||
{
|
||||
delete_buf = delete_arg_buf;
|
||||
sbuf = buf;
|
||||
int buf_size = 128;
|
||||
char* buffer = ALLOC_BUF(buf_size);
|
||||
setb(buffer, buffer+buf_size, 1);
|
||||
// setg(buffer, buffer, buffer);
|
||||
}
|
||||
|
||||
general_parsebuf::~general_parsebuf()
|
||||
{
|
||||
if (delete_buf)
|
||||
delete sbuf;
|
||||
}
|
||||
|
||||
int general_parsebuf::underflow()
|
||||
{
|
||||
register char *ptr = base();
|
||||
int has_newline = eback() < gptr() && gptr()[-1] == '\n';
|
||||
if (has_newline)
|
||||
*ptr++ = '\n';
|
||||
register streambuf *sb = sbuf;
|
||||
register int ch;
|
||||
for (;;) {
|
||||
ch = sb->sbumpc();
|
||||
if (ch == EOF)
|
||||
break;
|
||||
if (ptr == ebuf()) {
|
||||
int old_size = ebuf() - base();
|
||||
char *new_buffer = new char[old_size * 2];
|
||||
memcpy(new_buffer, base(), old_size);
|
||||
setb(new_buffer, new_buffer + 2 * old_size, 1);
|
||||
ptr = new_buffer + old_size;
|
||||
}
|
||||
*ptr++ = ch;
|
||||
if (ch == '\n')
|
||||
break;
|
||||
}
|
||||
char *cur_pos = base() + has_newline;
|
||||
pos_at_line_start += _line_length + 1;
|
||||
_line_length = ptr - cur_pos;
|
||||
if (ch != EOF || _line_length > 0)
|
||||
__line_number++;
|
||||
setg(base(), cur_pos, ptr);
|
||||
return ptr == cur_pos ? EOF : cur_pos[0];
|
||||
}
|
||||
|
||||
char* general_parsebuf::current_line()
|
||||
{
|
||||
char* ret = base();
|
||||
if (__line_number > 1)
|
||||
ret++; // Move past '\n' from end of previous line.
|
||||
return ret;
|
||||
}
|
||||
|
||||
int general_parsebuf::tell_in_line()
|
||||
{
|
||||
int off = gptr() - base();
|
||||
if (__line_number > 1)
|
||||
off--; // Subtract 1 for '\n' from end of previous line.
|
||||
return off;
|
||||
}
|
||||
|
||||
int general_parsebuf::seek_in_line(int i)
|
||||
{
|
||||
if (__line_number == 0)
|
||||
(void)general_parsebuf::underflow();
|
||||
if (__line_number > 1)
|
||||
i++; // Add 1 for '\n' from end of previous line.
|
||||
if (i < 0) i = 0;
|
||||
int len = egptr() - eback();
|
||||
if (i > len) i = len;
|
||||
setg(base(), base() + i, egptr());
|
||||
return i;
|
||||
}
|
||||
|
||||
func_parsebuf::func_parsebuf(CharReader func, void *argm) : parsebuf()
|
||||
{
|
||||
read_func = func;
|
||||
arg = argm;
|
||||
buf_start = NULL;
|
||||
buf_end = NULL;
|
||||
setb((char*)NewLine, (char*)NewLine+1, 0);
|
||||
setg((char*)NewLine, (char*)NewLine+1, (char*)NewLine+1);
|
||||
backed_up_to_newline = 0;
|
||||
}
|
||||
|
||||
int func_parsebuf::tell_in_line()
|
||||
{
|
||||
if (buf_start == NULL)
|
||||
return 0;
|
||||
if (egptr() != (char*)NewLine+1)
|
||||
// Get buffer was line buffer.
|
||||
return gptr() - buf_start;
|
||||
if (backed_up_to_newline)
|
||||
return -1; // Get buffer is '\n' preceding current line.
|
||||
// Get buffer is '\n' following current line.
|
||||
return (buf_end - buf_start) + (gptr() - (char*)NewLine);
|
||||
}
|
||||
|
||||
char* func_parsebuf::current_line()
|
||||
{
|
||||
return buf_start;
|
||||
}
|
||||
|
||||
int func_parsebuf::seek_in_line(int i)
|
||||
{
|
||||
if (i < 0) {
|
||||
// Back up to preceding '\n'.
|
||||
if (i < -1) i = -1;
|
||||
backed_up_to_newline = 1;
|
||||
setg((char*)NewLine, (char*)NewLine+(i+1), (char*)NewLine+1);
|
||||
return i;
|
||||
}
|
||||
backed_up_to_newline = 0;
|
||||
int line_length = buf_end-buf_start;
|
||||
if (i <= line_length) {
|
||||
setg(buf_start, buf_start+i, buf_end);
|
||||
return i;
|
||||
}
|
||||
i -= line_length;
|
||||
if (i > 0) i = 1;
|
||||
setg((char*)NewLine, (char*)NewLine+i, (char*)NewLine+1);
|
||||
return line_length + i;
|
||||
}
|
||||
|
||||
int func_parsebuf::underflow()
|
||||
{
|
||||
retry:
|
||||
if (gptr() < egptr())
|
||||
return *gptr();
|
||||
if (gptr() != (char*)NewLine+1) {
|
||||
// Get buffer was line buffer. Move to following '\n'.
|
||||
setg((char*)NewLine, (char*)NewLine, (char*)NewLine+1);
|
||||
return *gptr();
|
||||
}
|
||||
if (backed_up_to_newline)
|
||||
// Get buffer was '\n' preceding current line. Move to current line.
|
||||
backed_up_to_newline = 0;
|
||||
else {
|
||||
// Get buffer was '\n' following current line. Read new line.
|
||||
if (buf_start) free(buf_start);
|
||||
char *str = (*read_func)(arg);
|
||||
buf_start = str;
|
||||
if (str == NULL)
|
||||
return EOF;
|
||||
// Initially, _line_length == -1, so pos_at_line_start becomes 0.
|
||||
pos_at_line_start += _line_length + 1;
|
||||
_line_length = strlen(str);
|
||||
buf_end = str + _line_length;
|
||||
__line_number++;
|
||||
}
|
||||
setg(buf_start, buf_start, buf_end);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
#if 0
|
||||
size_t parsebuf::line_length()
|
||||
{
|
||||
if (current_line_length == (size_t)(-1)) // Initial value;
|
||||
(void)sgetc();
|
||||
return current_line_length;
|
||||
}
|
||||
#endif
|
||||
|
||||
int parsebuf::seek_in_line(int i)
|
||||
{
|
||||
#if 1
|
||||
abort();
|
||||
return 0; // Suppress warning.
|
||||
#else
|
||||
if (i > 0) {
|
||||
size_t len = line_length();
|
||||
if ((unsigned)i > len) i = len;
|
||||
}
|
||||
else if (i < -1) i = -1;
|
||||
int new_pos = seekoff(pos_at_line_start + i, ios::beg);
|
||||
if (new_pos == EOF)
|
||||
return tell_in_line();
|
||||
else return new_pos - pos_at_line_start;
|
||||
#endif
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
// This is part of the iostream library, providing -*- C++ -*- input/output.
|
||||
// Copyright (C) 1991 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: parsestream.h,v 1.2 1993/08/02 17:22:37 mycroft Exp $
|
||||
|
||||
#ifndef PARSESTREAM_H
|
||||
#define PARSESTREAM_H
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
#include "streambuf.h"
|
||||
|
||||
// A parsebuf is a streambuf optimized for scanning text files.
|
||||
// It keeps track of line and column numbers.
|
||||
// It is guaranteed to remember the entire current line,
|
||||
// as well the '\n'-s on either side of it (if they exist).
|
||||
// You can arbitrarily seek (or unget) within this extended line.
|
||||
// Other backward seeks are not supported.
|
||||
// Normal read semantics are supported (and hence istream operators like >>).
|
||||
|
||||
class parsebuf : public backupbuf {
|
||||
protected:
|
||||
_G_fpos_t pos_at_line_start;
|
||||
long _line_length;
|
||||
unsigned long __line_number;
|
||||
char *buf_start;
|
||||
char *buf_end;
|
||||
|
||||
public:
|
||||
parsebuf *chain;
|
||||
|
||||
// Return column number (raw - don't handle tabs etc).
|
||||
// Retult can be -1, meaning: at '\n' before current line.
|
||||
virtual int tell_in_line();
|
||||
|
||||
// seek to (raw) column I in current line.
|
||||
// Result is new (raw) column position - differs from I if unable to seek.
|
||||
// Seek to -1 tries to seek to before previous LF.
|
||||
virtual int seek_in_line(int i);
|
||||
|
||||
// Note: there is no "current line" initially, until something is read.
|
||||
|
||||
// Current line number, starting with 0.
|
||||
// If tell_in_line()==-1, then line number of next line.
|
||||
int line_number() { return __line_number; }
|
||||
|
||||
// Length of current line, not counting either '\n'.
|
||||
int line_length() { return _line_length; }
|
||||
// Current line - not a copy, so file ops may trash it.
|
||||
virtual char* current_line();
|
||||
virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
|
||||
virtual streambuf* setbuf(char* p, int len);
|
||||
protected:
|
||||
parsebuf() : backupbuf() { chain= NULL;
|
||||
__line_number = 0; pos_at_line_start = 0; _line_length = -1; }
|
||||
virtual int pbackfail(int c);
|
||||
};
|
||||
|
||||
// A string_parsebuf is a parsebuf whose source is a fixed string.
|
||||
|
||||
class string_parsebuf : public parsebuf {
|
||||
public:
|
||||
int do_delete;
|
||||
string_parsebuf(char *str, int len, int delete_at_close=0);
|
||||
virtual int underflow();
|
||||
virtual char* current_line();
|
||||
virtual int seek_in_line(int i);
|
||||
virtual int tell_in_line();
|
||||
char *left() const { return base(); }
|
||||
char *right() const { return ebuf(); }
|
||||
// streampos seekoff(streamoff, _seek_dir, int);
|
||||
};
|
||||
|
||||
// A func_parsebuf calls a given function to get new input.
|
||||
// Each call returns an entire NUL-terminated line (without the '\n').
|
||||
// That line has been allocated with malloc(), not new.
|
||||
// The interface is tailored to the GNU readline library.
|
||||
// Example:
|
||||
// char* DoReadLine(void* arg)
|
||||
// {
|
||||
// char *line = readline((char*)arg); /* 'arg' is used as prompt. */
|
||||
// if line == NULL) { putc('\n', stderr); return NULL; }
|
||||
// if (line[0] != '\0') add_history(line);
|
||||
// return line;
|
||||
// }
|
||||
// char PromptBuffer[100] = "> ";
|
||||
// func_parsebuf my_stream(DoReadLine, PromptBuffer);
|
||||
|
||||
typedef char *(*CharReader)(void *arg);
|
||||
class istream;
|
||||
|
||||
class func_parsebuf : public parsebuf {
|
||||
public:
|
||||
void *arg;
|
||||
CharReader read_func;
|
||||
int backed_up_to_newline;
|
||||
func_parsebuf(CharReader func, void *argm = NULL);
|
||||
int underflow();
|
||||
virtual int tell_in_line();
|
||||
virtual int seek_in_line(int i);
|
||||
virtual char* current_line();
|
||||
};
|
||||
|
||||
// A general_parsebuf is a parsebuf which gets its input from some
|
||||
// other streambuf. It explicitly buffers up an entire line.
|
||||
|
||||
class general_parsebuf : public parsebuf {
|
||||
public:
|
||||
streambuf *sbuf;
|
||||
int delete_buf; // Delete sbuf when destroying this.
|
||||
general_parsebuf(streambuf *buf, int delete_arg_buf = 0);
|
||||
int underflow();
|
||||
virtual int tell_in_line();
|
||||
virtual int seek_in_line(int i);
|
||||
~general_parsebuf();
|
||||
virtual char* current_line();
|
||||
};
|
||||
|
||||
#if 0
|
||||
class parsestream : public istream {
|
||||
streammarker marks[2];
|
||||
short _first; // of the two marks; either 0 or 1
|
||||
int _lineno;
|
||||
int first() { return _first; }
|
||||
int second() { return 1-_first; }
|
||||
int line_length() { marks[second].delta(marks[first]); }
|
||||
int line_length() { marks[second].delta(marks[first]); }
|
||||
int seek_in_line(int i);
|
||||
int tell_in_line();
|
||||
int line_number();
|
||||
};
|
||||
#endif
|
||||
#endif /*!defined(PARSESTREAM_H)*/
|
@ -1,126 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1992 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#define _POSIX_SOURCE
|
||||
#include "ioprivate.h"
|
||||
#include "procbuf.h"
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
||||
#ifndef FORK
|
||||
#define FORK vfork
|
||||
#ifndef __NetBSD__
|
||||
extern "C" _G_pid_t vfork(void);
|
||||
#else
|
||||
extern "C" int vfork(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
procbuf::procbuf(const char *command, int mode) : filebuf()
|
||||
{
|
||||
open(command, mode);
|
||||
}
|
||||
|
||||
procbuf *procbuf::open(const char *command, int mode)
|
||||
{
|
||||
int read_or_write;
|
||||
if (is_open())
|
||||
return NULL;
|
||||
int pipe_fds[2];
|
||||
int parent_end, child_end;
|
||||
if (::pipe(pipe_fds) < 0)
|
||||
return NULL;
|
||||
if (mode == ios::in) {
|
||||
parent_end = pipe_fds[0];
|
||||
child_end = pipe_fds[1];
|
||||
read_or_write = _S_NO_WRITES;
|
||||
}
|
||||
else {
|
||||
parent_end = pipe_fds[1];
|
||||
child_end = pipe_fds[0];
|
||||
read_or_write = _S_NO_READS;
|
||||
}
|
||||
_pid = FORK();
|
||||
if (_pid == 0) {
|
||||
::close(parent_end);
|
||||
int child_std_end = mode == ios::in ? 1 : 0;
|
||||
if (child_end != child_std_end) {
|
||||
::dup2(child_end, child_std_end);
|
||||
::close(child_end);
|
||||
}
|
||||
::execl("/bin/sh", "sh", "-c", command, NULL);
|
||||
::_exit(127);
|
||||
}
|
||||
::close(child_end);
|
||||
if (_pid < 0) {
|
||||
::close(parent_end);
|
||||
return NULL;
|
||||
}
|
||||
_fb._fileno = parent_end;
|
||||
xsetflags(read_or_write, _S_NO_READS|_S_NO_WRITES);
|
||||
return this;
|
||||
}
|
||||
|
||||
/* #define USE_SIGMASK */
|
||||
|
||||
int procbuf::sys_close()
|
||||
{
|
||||
_G_pid_t wait_pid;
|
||||
int status = filebuf::sys_close();
|
||||
if (status < 0)
|
||||
return status;
|
||||
int wstatus;
|
||||
#if defined(SIG_BLOCK) && defined(SIG_SETMASK)
|
||||
sigset_t set, oset;
|
||||
sigemptyset (&set);
|
||||
sigaddset (&set, SIGINT);
|
||||
sigaddset (&set, SIGQUIT);
|
||||
sigaddset (&set, SIGHUP);
|
||||
sigprocmask (SIG_BLOCK, &set, &oset);
|
||||
#else
|
||||
#ifdef USE_SIGMASK
|
||||
int mask = sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGHUP));
|
||||
#else
|
||||
typedef void (*void_func)(int);
|
||||
void_func intsave = (void_func)signal(SIGINT, SIG_IGN);
|
||||
void_func quitsave = (void_func)signal(SIGQUIT, SIG_IGN);
|
||||
void_func hupsave = (void_func)signal(SIGHUP, SIG_IGN);
|
||||
#endif
|
||||
#endif
|
||||
while ((wait_pid = wait(&wstatus)) != _pid && wait_pid != -1) { }
|
||||
#if defined(SIG_BLOCK) && defined(SIG_SETMASK)
|
||||
sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
|
||||
#else
|
||||
#ifdef USE_SIGMASK
|
||||
(void) sigsetmask(mask);
|
||||
#else
|
||||
signal(SIGINT, intsave);
|
||||
signal(SIGQUIT, quitsave);
|
||||
signal(SIGHUP, hupsave);
|
||||
#endif
|
||||
#endif
|
||||
if (wait_pid == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
procbuf::~procbuf()
|
||||
{
|
||||
close();
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1992 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: procbuf.h,v 1.2 1993/08/02 17:22:38 mycroft Exp $
|
||||
|
||||
#include <streambuf.h>
|
||||
|
||||
class procbuf : public filebuf {
|
||||
_G_pid_t _pid;
|
||||
public:
|
||||
procbuf() : filebuf() { }
|
||||
procbuf(const char *command, int mode);
|
||||
procbuf* open(const char *command, int mode);
|
||||
procbuf *close() { return (procbuf*)filebuf::close(); }
|
||||
virtual int sys_close();
|
||||
~procbuf();
|
||||
};
|
@ -1,856 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1990 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "%W% (Berkeley) %G%";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/*
|
||||
* Actual printf innards.
|
||||
*
|
||||
* This code is large and complicated...
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "ioprivate.h"
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/*
|
||||
* Define FLOATING_POINT to get floating point.
|
||||
*/
|
||||
#ifndef NO_FLOATING_POINT
|
||||
#define FLOATING_POINT
|
||||
#endif
|
||||
|
||||
/* end of configuration stuff */
|
||||
|
||||
|
||||
/*
|
||||
* Helper class and function for `fprintf to unbuffered': creates a
|
||||
* temporary buffer. We only work on write-only files; this avoids
|
||||
* worries about ungetc buffers and so forth.
|
||||
*/
|
||||
|
||||
class help_streambuf : public backupbuf {
|
||||
public:
|
||||
char *buffer;
|
||||
int buf_size;
|
||||
streambuf *sb;
|
||||
help_streambuf(streambuf *sbuf, char *buf, int n) {
|
||||
sb = sbuf; buffer = buf; buf_size = n;
|
||||
setp(buffer, buffer+buf_size); }
|
||||
~help_streambuf();
|
||||
virtual int overflow(int c = EOF);
|
||||
};
|
||||
|
||||
int help_streambuf::overflow(int c)
|
||||
{
|
||||
int used = pptr() - pbase();
|
||||
if (used) {
|
||||
sb->sputn(pbase(), used);
|
||||
pbump(-used);
|
||||
}
|
||||
if (c == EOF || buf_size == 0)
|
||||
return sb->overflow(c);
|
||||
return sputc(c);
|
||||
}
|
||||
help_streambuf::~help_streambuf()
|
||||
{
|
||||
int used = pptr() - pbase();
|
||||
if (used) {
|
||||
sb->sputn(pbase(), used);
|
||||
pbump(-used);
|
||||
}
|
||||
}
|
||||
|
||||
int help_vform(streambuf *sb, char const *fmt0, va_list ap)
|
||||
{
|
||||
char buf[_G_BUFSIZ];
|
||||
help_streambuf helper(sb, buf, _G_BUFSIZ);
|
||||
return helper.vform(fmt0, ap);
|
||||
}
|
||||
|
||||
#ifdef FLOATING_POINT
|
||||
|
||||
#include "floatio.h"
|
||||
#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
|
||||
#define DEFPREC 6
|
||||
extern "C" double modf(double, double*);
|
||||
|
||||
#else /* no FLOATING_POINT */
|
||||
|
||||
#define BUF 40
|
||||
|
||||
#endif /* FLOATING_POINT */
|
||||
|
||||
|
||||
/*
|
||||
* Macros for converting digits to letters and vice versa
|
||||
*/
|
||||
#define to_digit(c) ((c) - '0')
|
||||
#define is_digit(c) ((unsigned)to_digit(c) <= 9)
|
||||
#define to_char(n) ((n) + '0')
|
||||
|
||||
/*
|
||||
* Flags used during conversion.
|
||||
*/
|
||||
#define LONGINT 0x01 /* long integer */
|
||||
#define LONGDBL 0x02 /* long double; unimplemented */
|
||||
#define SHORTINT 0x04 /* short integer */
|
||||
#define ALT 0x08 /* alternate form */
|
||||
#define LADJUST 0x10 /* left adjustment */
|
||||
#define ZEROPAD 0x20 /* zero (as opposed to blank) pad */
|
||||
#define HEXPREFIX 0x40 /* add 0x or 0X prefix */
|
||||
|
||||
int streambuf::vform(char const *fmt0, _G_va_list ap)
|
||||
{
|
||||
register const char *fmt; /* format string */
|
||||
register int ch; /* character from fmt */
|
||||
register int n; /* handy integer (short term usage) */
|
||||
register char *cp; /* handy char pointer (short term usage) */
|
||||
const char *fmark; /* for remembering a place in fmt */
|
||||
register int flags; /* flags as above */
|
||||
int ret; /* return value accumulator */
|
||||
int width; /* width from format (%8d), or 0 */
|
||||
int prec; /* precision from format (%.3d), or -1 */
|
||||
char sign; /* sign prefix (' ', '+', '-', or \0) */
|
||||
#ifdef FLOATING_POINT
|
||||
int softsign; /* temporary negative sign for floats */
|
||||
double _double; /* double precision arguments %[eEfgG] */
|
||||
#ifndef USE_DTOA
|
||||
int fpprec; /* `extra' floating precision in [eEfgG] */
|
||||
#endif
|
||||
#endif
|
||||
unsigned long _ulong; /* integer arguments %[diouxX] */
|
||||
enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
|
||||
int dprec; /* a copy of prec if [diouxX], 0 otherwise */
|
||||
int dpad; /* extra 0 padding needed for integers */
|
||||
int fieldsz; /* field size expanded by sign, dpad etc */
|
||||
// The initialization of 'size' is to suppress a warning that
|
||||
// 'size' might be used unitialized. It seems gcc can't
|
||||
// quite grok this spaghetti code ...
|
||||
int size = 0; /* size of converted field or string */
|
||||
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
|
||||
char ox[2]; /* space for 0x hex-prefix */
|
||||
|
||||
/*
|
||||
* Choose PADSIZE to trade efficiency vs size. If larger
|
||||
* printf fields occur frequently, increase PADSIZE (and make
|
||||
* the initialisers below longer).
|
||||
*/
|
||||
#define PADSIZE 16 /* pad chunk size */
|
||||
static char const blanks[PADSIZE] =
|
||||
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
|
||||
static char const zeroes[PADSIZE] =
|
||||
{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
|
||||
|
||||
/*
|
||||
* BEWARE, these `goto error' on error, and PAD uses `n'.
|
||||
*/
|
||||
#define PRINT(ptr, len) \
|
||||
do { if (sputn(ptr, len) != len) goto error; } while (0)
|
||||
#if 1
|
||||
#define PAD_SP(howmany) if (padn(' ', howmany) < 0) goto error;
|
||||
#define PAD_0(howmany) if (padn('0', howmany) < 0) goto error;
|
||||
#else
|
||||
#define PAD(howmany, with) { \
|
||||
if ((n = (howmany)) > 0) { \
|
||||
while (n > PADSIZE) { \
|
||||
PRINT(with, PADSIZE); \
|
||||
n -= PADSIZE; \
|
||||
} \
|
||||
PRINT(with, n); \
|
||||
} \
|
||||
}
|
||||
#define PAD_SP(howmany) PAD(howmany, blanks)
|
||||
#define PAD_0(howmany) PAD(howmany, zeroes)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* To extend shorts properly, we need both signed and unsigned
|
||||
* argument extraction methods.
|
||||
*/
|
||||
#define SARG() \
|
||||
(flags&LONGINT ? va_arg(ap, long) : \
|
||||
flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
|
||||
(long)va_arg(ap, int))
|
||||
#define UARG() \
|
||||
(flags&LONGINT ? va_arg(ap, unsigned long) : \
|
||||
flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \
|
||||
(unsigned long)va_arg(ap, unsigned int))
|
||||
|
||||
/* optimise cerr (and other unbuffered Unix files) */
|
||||
if (unbuffered())
|
||||
return help_vform(this, fmt0, ap);
|
||||
|
||||
fmt = fmt0;
|
||||
ret = 0;
|
||||
|
||||
/*
|
||||
* Scan the format for conversions (`%' character).
|
||||
*/
|
||||
for (;;) {
|
||||
for (fmark = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
|
||||
/* void */;
|
||||
if ((n = fmt - fmark) != 0) {
|
||||
PRINT(fmark, n);
|
||||
ret += n;
|
||||
}
|
||||
if (ch == '\0')
|
||||
goto done;
|
||||
fmt++; /* skip over '%' */
|
||||
|
||||
flags = 0;
|
||||
dprec = 0;
|
||||
#if defined(FLOATING_POINT) && !defined (USE_DTOA)
|
||||
fpprec = 0;
|
||||
#endif
|
||||
width = 0;
|
||||
prec = -1;
|
||||
sign = '\0';
|
||||
|
||||
rflag: ch = *fmt++;
|
||||
reswitch: switch (ch) {
|
||||
case ' ':
|
||||
/*
|
||||
* ``If the space and + flags both appear, the space
|
||||
* flag will be ignored.''
|
||||
* -- ANSI X3J11
|
||||
*/
|
||||
if (!sign)
|
||||
sign = ' ';
|
||||
goto rflag;
|
||||
case '#':
|
||||
flags |= ALT;
|
||||
goto rflag;
|
||||
case '*':
|
||||
/*
|
||||
* ``A negative field width argument is taken as a
|
||||
* - flag followed by a positive field width.''
|
||||
* -- ANSI X3J11
|
||||
* They don't exclude field widths read from args.
|
||||
*/
|
||||
if ((width = va_arg(ap, int)) >= 0)
|
||||
goto rflag;
|
||||
width = -width;
|
||||
/* FALLTHROUGH */
|
||||
case '-':
|
||||
flags |= LADJUST;
|
||||
flags &= ~ZEROPAD; /* '-' disables '0' */
|
||||
goto rflag;
|
||||
case '+':
|
||||
sign = '+';
|
||||
goto rflag;
|
||||
case '.':
|
||||
if ((ch = *fmt++) == '*') {
|
||||
n = va_arg(ap, int);
|
||||
prec = n < 0 ? -1 : n;
|
||||
goto rflag;
|
||||
}
|
||||
n = 0;
|
||||
while (is_digit(ch)) {
|
||||
n = 10 * n + to_digit(ch);
|
||||
ch = *fmt++;
|
||||
}
|
||||
prec = n < 0 ? -1 : n;
|
||||
goto reswitch;
|
||||
case '0':
|
||||
/*
|
||||
* ``Note that 0 is taken as a flag, not as the
|
||||
* beginning of a field width.''
|
||||
* -- ANSI X3J11
|
||||
*/
|
||||
if (!(flags & LADJUST))
|
||||
flags |= ZEROPAD; /* '-' disables '0' */
|
||||
goto rflag;
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
n = 0;
|
||||
do {
|
||||
n = 10 * n + to_digit(ch);
|
||||
ch = *fmt++;
|
||||
} while (is_digit(ch));
|
||||
width = n;
|
||||
goto reswitch;
|
||||
#ifdef FLOATING_POINT
|
||||
case 'L':
|
||||
flags |= LONGDBL;
|
||||
goto rflag;
|
||||
#endif
|
||||
case 'h':
|
||||
flags |= SHORTINT;
|
||||
goto rflag;
|
||||
case 'l':
|
||||
flags |= LONGINT;
|
||||
goto rflag;
|
||||
case 'c':
|
||||
*(cp = buf) = va_arg(ap, int);
|
||||
size = 1;
|
||||
sign = '\0';
|
||||
break;
|
||||
case 'D':
|
||||
flags |= LONGINT;
|
||||
/*FALLTHROUGH*/
|
||||
case 'd':
|
||||
case 'i':
|
||||
_ulong = SARG();
|
||||
if ((long)_ulong < 0) {
|
||||
_ulong = -_ulong;
|
||||
sign = '-';
|
||||
}
|
||||
base = DEC;
|
||||
goto number;
|
||||
#ifdef FLOATING_POINT
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'g':
|
||||
case 'G':
|
||||
_double = va_arg(ap, double);
|
||||
#ifdef USE_DTOA
|
||||
{
|
||||
ios::fmtflags fmt_flags = 0;
|
||||
int fill = ' ';
|
||||
if (flags & ALT)
|
||||
fmt_flags |= ios::showpoint;
|
||||
if (flags & LADJUST)
|
||||
fmt_flags |= ios::left;
|
||||
else if (flags & ZEROPAD)
|
||||
fmt_flags |= ios::internal, fill = '0';
|
||||
n = __outfloat(_double, this, ch, width,
|
||||
prec < 0 ? DEFPREC : prec,
|
||||
fmt_flags, sign, fill);
|
||||
if (n < 0)
|
||||
goto error;
|
||||
ret += n;
|
||||
}
|
||||
// CHECK ERROR!
|
||||
continue;
|
||||
#else
|
||||
/*
|
||||
* don't do unrealistic precision; just pad it with
|
||||
* zeroes later, so buffer size stays rational.
|
||||
*/
|
||||
if (prec > MAXFRACT) {
|
||||
if ((ch != 'g' && ch != 'G') || (flags&ALT))
|
||||
fpprec = prec - MAXFRACT;
|
||||
prec = MAXFRACT;
|
||||
} else if (prec == -1)
|
||||
prec = DEFPREC;
|
||||
// __cvt_double may have to round up before the
|
||||
// "start" of its buffer, i.e.
|
||||
// ``intf("%.2f", (double)9.999);'';
|
||||
// if the first character is still NUL, it did.
|
||||
// softsign avoids negative 0 if _double < 0 but
|
||||
// no significant digits will be shown.
|
||||
cp = buf;
|
||||
*cp = '\0';
|
||||
size = __cvt_double(_double, prec, flags, &softsign,
|
||||
ch, cp, buf + sizeof(buf));
|
||||
if (softsign)
|
||||
sign = '-';
|
||||
if (*cp == '\0')
|
||||
cp++;
|
||||
break;
|
||||
#endif
|
||||
#endif /* FLOATING_POINT */
|
||||
case 'n':
|
||||
if (flags & LONGINT)
|
||||
*va_arg(ap, long *) = ret;
|
||||
else if (flags & SHORTINT)
|
||||
*va_arg(ap, short *) = ret;
|
||||
else
|
||||
*va_arg(ap, int *) = ret;
|
||||
continue; /* no output */
|
||||
case 'O':
|
||||
flags |= LONGINT;
|
||||
/*FALLTHROUGH*/
|
||||
case 'o':
|
||||
_ulong = UARG();
|
||||
base = OCT;
|
||||
goto nosign;
|
||||
case 'p':
|
||||
/*
|
||||
* ``The argument shall be a pointer to void. The
|
||||
* value of the pointer is converted to a sequence
|
||||
* of printable characters, in an implementation-
|
||||
* defined manner.''
|
||||
* -- ANSI X3J11
|
||||
*/
|
||||
/* NOSTRICT */
|
||||
_ulong = (unsigned long)va_arg(ap, void *);
|
||||
base = HEX;
|
||||
flags |= HEXPREFIX;
|
||||
ch = 'x';
|
||||
goto nosign;
|
||||
case 's':
|
||||
if ((cp = va_arg(ap, char *)) == NULL)
|
||||
cp = "(null)";
|
||||
if (prec >= 0) {
|
||||
/*
|
||||
* can't use strlen; can only look for the
|
||||
* NUL in the first `prec' characters, and
|
||||
* strlen() will go further.
|
||||
*/
|
||||
char *p = (char*)memchr(cp, 0, prec);
|
||||
|
||||
if (p != NULL) {
|
||||
size = p - cp;
|
||||
if (size > prec)
|
||||
size = prec;
|
||||
} else
|
||||
size = prec;
|
||||
} else
|
||||
size = strlen(cp);
|
||||
sign = '\0';
|
||||
break;
|
||||
case 'U':
|
||||
flags |= LONGINT;
|
||||
/*FALLTHROUGH*/
|
||||
case 'u':
|
||||
_ulong = UARG();
|
||||
base = DEC;
|
||||
goto nosign;
|
||||
case 'X':
|
||||
case 'x':
|
||||
_ulong = UARG();
|
||||
base = HEX;
|
||||
/* leading 0x/X only if non-zero */
|
||||
if (flags & ALT && _ulong != 0)
|
||||
flags |= HEXPREFIX;
|
||||
|
||||
/* unsigned conversions */
|
||||
nosign: sign = '\0';
|
||||
/*
|
||||
* ``... diouXx conversions ... if a precision is
|
||||
* specified, the 0 flag will be ignored.''
|
||||
* -- ANSI X3J11
|
||||
*/
|
||||
number: if ((dprec = prec) >= 0)
|
||||
flags &= ~ZEROPAD;
|
||||
|
||||
/*
|
||||
* ``The result of converting a zero value with an
|
||||
* explicit precision of zero is no characters.''
|
||||
* -- ANSI X3J11
|
||||
*/
|
||||
cp = buf + BUF;
|
||||
if (_ulong != 0 || prec != 0) {
|
||||
char *xdigs; /* digits for [xX] conversion */
|
||||
/*
|
||||
* unsigned mod is hard, and unsigned mod
|
||||
* by a constant is easier than that by
|
||||
* a variable; hence this switch.
|
||||
*/
|
||||
switch (base) {
|
||||
case OCT:
|
||||
do {
|
||||
*--cp = to_char(_ulong & 7);
|
||||
_ulong >>= 3;
|
||||
} while (_ulong);
|
||||
/* handle octal leading 0 */
|
||||
if (flags & ALT && *cp != '0')
|
||||
*--cp = '0';
|
||||
break;
|
||||
|
||||
case DEC:
|
||||
/* many numbers are 1 digit */
|
||||
while (_ulong >= 10) {
|
||||
*--cp = to_char(_ulong % 10);
|
||||
_ulong /= 10;
|
||||
}
|
||||
*--cp = to_char(_ulong);
|
||||
break;
|
||||
|
||||
case HEX:
|
||||
if (ch == 'X')
|
||||
xdigs = "0123456789ABCDEF";
|
||||
else /* ch == 'x' || ch == 'p' */
|
||||
xdigs = "0123456789abcdef";
|
||||
do {
|
||||
*--cp = xdigs[_ulong & 15];
|
||||
_ulong >>= 4;
|
||||
} while (_ulong);
|
||||
break;
|
||||
|
||||
default:
|
||||
cp = "bug in vform: bad base";
|
||||
goto skipsize;
|
||||
}
|
||||
}
|
||||
size = buf + BUF - cp;
|
||||
skipsize:
|
||||
break;
|
||||
default: /* "%?" prints ?, unless ? is NUL */
|
||||
if (ch == '\0')
|
||||
goto done;
|
||||
/* pretend it was %c with argument ch */
|
||||
cp = buf;
|
||||
*cp = ch;
|
||||
size = 1;
|
||||
sign = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* All reasonable formats wind up here. At this point,
|
||||
* `cp' points to a string which (if not flags&LADJUST)
|
||||
* should be padded out to `width' places. If
|
||||
* flags&ZEROPAD, it should first be prefixed by any
|
||||
* sign or other prefix; otherwise, it should be blank
|
||||
* padded before the prefix is emitted. After any
|
||||
* left-hand padding and prefixing, emit zeroes
|
||||
* required by a decimal [diouxX] precision, then print
|
||||
* the string proper, then emit zeroes required by any
|
||||
* leftover floating precision; finally, if LADJUST,
|
||||
* pad with blanks.
|
||||
*/
|
||||
|
||||
/*
|
||||
* compute actual size, so we know how much to pad.
|
||||
*/
|
||||
#if defined(FLOATING_POINT) && !defined (USE_DTOA)
|
||||
fieldsz = size + fpprec;
|
||||
#else
|
||||
fieldsz = size;
|
||||
#endif
|
||||
dpad = dprec - size;
|
||||
if (dpad < 0)
|
||||
dpad = 0;
|
||||
|
||||
if (sign)
|
||||
fieldsz++;
|
||||
else if (flags & HEXPREFIX)
|
||||
fieldsz += 2;
|
||||
fieldsz += dpad;
|
||||
|
||||
/* right-adjusting blank padding */
|
||||
if ((flags & (LADJUST|ZEROPAD)) == 0)
|
||||
PAD_SP(width - fieldsz);
|
||||
|
||||
/* prefix */
|
||||
if (sign) {
|
||||
PRINT(&sign, 1);
|
||||
} else if (flags & HEXPREFIX) {
|
||||
ox[0] = '0';
|
||||
ox[1] = ch;
|
||||
PRINT(ox, 2);
|
||||
}
|
||||
|
||||
/* right-adjusting zero padding */
|
||||
if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
|
||||
PAD_0(width - fieldsz);
|
||||
|
||||
/* leading zeroes from decimal precision */
|
||||
PAD_0(dpad);
|
||||
|
||||
/* the string or number proper */
|
||||
PRINT(cp, size);
|
||||
|
||||
#if defined(FLOATING_POINT) && !defined (USE_DTOA)
|
||||
/* trailing f.p. zeroes */
|
||||
PAD_0(fpprec);
|
||||
#endif
|
||||
|
||||
/* left-adjusting padding (always blank) */
|
||||
if (flags & LADJUST)
|
||||
PAD_SP(width - fieldsz);
|
||||
|
||||
/* finally, adjust ret */
|
||||
ret += width > fieldsz ? width : fieldsz;
|
||||
|
||||
}
|
||||
done:
|
||||
return ret;
|
||||
error:
|
||||
return EOF;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#if defined(FLOATING_POINT) && !defined(USE_DTOA)
|
||||
|
||||
static char *exponent(register char *p, register int exp, int fmtch)
|
||||
{
|
||||
register char *t;
|
||||
char expbuf[MAXEXP];
|
||||
|
||||
*p++ = fmtch;
|
||||
if (exp < 0) {
|
||||
exp = -exp;
|
||||
*p++ = '-';
|
||||
}
|
||||
else
|
||||
*p++ = '+';
|
||||
t = expbuf + MAXEXP;
|
||||
if (exp > 9) {
|
||||
do {
|
||||
*--t = to_char(exp % 10);
|
||||
} while ((exp /= 10) > 9);
|
||||
*--t = to_char(exp);
|
||||
for (; t < expbuf + MAXEXP; *p++ = *t++);
|
||||
}
|
||||
else {
|
||||
*p++ = '0';
|
||||
*p++ = to_char(exp);
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
static char * round(double fract, int *exp,
|
||||
register char *start, register char *end,
|
||||
char ch, int *signp)
|
||||
{
|
||||
double tmp;
|
||||
|
||||
if (fract)
|
||||
(void)modf(fract * 10, &tmp);
|
||||
else
|
||||
tmp = to_digit(ch);
|
||||
if (tmp > 4)
|
||||
for (;; --end) {
|
||||
if (*end == '.')
|
||||
--end;
|
||||
if (++*end <= '9')
|
||||
break;
|
||||
*end = '0';
|
||||
if (end == start) {
|
||||
if (exp) { /* e/E; increment exponent */
|
||||
*end = '1';
|
||||
++*exp;
|
||||
}
|
||||
else { /* f; add extra digit */
|
||||
*--end = '1';
|
||||
--start;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
|
||||
else if (*signp == '-')
|
||||
for (;; --end) {
|
||||
if (*end == '.')
|
||||
--end;
|
||||
if (*end != '0')
|
||||
break;
|
||||
if (end == start)
|
||||
*signp = 0;
|
||||
}
|
||||
return (start);
|
||||
}
|
||||
|
||||
int __cvt_double(double number, register int prec, int flags, int *signp,
|
||||
int fmtch, char *startp, char *endp)
|
||||
{
|
||||
register char *p, *t;
|
||||
register double fract;
|
||||
int dotrim = 0, expcnt, gformat = 0;
|
||||
double integer, tmp;
|
||||
|
||||
expcnt = 0;
|
||||
if (number < 0) {
|
||||
number = -number;
|
||||
*signp = '-';
|
||||
} else
|
||||
*signp = 0;
|
||||
|
||||
fract = modf(number, &integer);
|
||||
|
||||
/* get an extra slot for rounding. */
|
||||
t = ++startp;
|
||||
|
||||
/*
|
||||
* get integer portion of number; put into the end of the buffer; the
|
||||
* .01 is added for modf(356.0 / 10, &integer) returning .59999999...
|
||||
*/
|
||||
for (p = endp - 1; integer; ++expcnt) {
|
||||
tmp = modf(integer / 10, &integer);
|
||||
*p-- = to_char((int)((tmp + .01) * 10));
|
||||
}
|
||||
switch (fmtch) {
|
||||
case 'f':
|
||||
case 'F':
|
||||
/* reverse integer into beginning of buffer */
|
||||
if (expcnt)
|
||||
for (; ++p < endp; *t++ = *p);
|
||||
else
|
||||
*t++ = '0';
|
||||
/*
|
||||
* if precision required or alternate flag set, add in a
|
||||
* decimal point.
|
||||
*/
|
||||
if (prec || flags&ALT)
|
||||
*t++ = '.';
|
||||
/* if requires more precision and some fraction left */
|
||||
if (fract) {
|
||||
if (prec)
|
||||
do {
|
||||
fract = modf(fract * 10, &tmp);
|
||||
*t++ = to_char((int)tmp);
|
||||
} while (--prec && fract);
|
||||
if (fract)
|
||||
startp = round(fract, (int *)NULL, startp,
|
||||
t - 1, (char)0, signp);
|
||||
}
|
||||
for (; prec--; *t++ = '0');
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
eformat: if (expcnt) {
|
||||
*t++ = *++p;
|
||||
if (prec || flags&ALT)
|
||||
*t++ = '.';
|
||||
/* if requires more precision and some integer left */
|
||||
for (; prec && ++p < endp; --prec)
|
||||
*t++ = *p;
|
||||
/*
|
||||
* if done precision and more of the integer component,
|
||||
* round using it; adjust fract so we don't re-round
|
||||
* later.
|
||||
*/
|
||||
if (!prec && ++p < endp) {
|
||||
fract = 0;
|
||||
startp = round((double)0, &expcnt, startp,
|
||||
t - 1, *p, signp);
|
||||
}
|
||||
/* adjust expcnt for digit in front of decimal */
|
||||
--expcnt;
|
||||
}
|
||||
/* until first fractional digit, decrement exponent */
|
||||
else if (fract) {
|
||||
/* adjust expcnt for digit in front of decimal */
|
||||
for (expcnt = -1;; --expcnt) {
|
||||
fract = modf(fract * 10, &tmp);
|
||||
if (tmp)
|
||||
break;
|
||||
}
|
||||
*t++ = to_char((int)tmp);
|
||||
if (prec || flags&ALT)
|
||||
*t++ = '.';
|
||||
}
|
||||
else {
|
||||
*t++ = '0';
|
||||
if (prec || flags&ALT)
|
||||
*t++ = '.';
|
||||
}
|
||||
/* if requires more precision and some fraction left */
|
||||
if (fract) {
|
||||
if (prec)
|
||||
do {
|
||||
fract = modf(fract * 10, &tmp);
|
||||
*t++ = to_char((int)tmp);
|
||||
} while (--prec && fract);
|
||||
if (fract)
|
||||
startp = round(fract, &expcnt, startp,
|
||||
t - 1, (char)0, signp);
|
||||
}
|
||||
/* if requires more precision */
|
||||
for (; prec--; *t++ = '0');
|
||||
|
||||
/* unless alternate flag, trim any g/G format trailing 0's */
|
||||
if (gformat && !(flags&ALT)) {
|
||||
while (t > startp && *--t == '0');
|
||||
if (*t == '.')
|
||||
--t;
|
||||
++t;
|
||||
}
|
||||
t = exponent(t, expcnt, fmtch);
|
||||
break;
|
||||
case 'g':
|
||||
case 'G':
|
||||
/* a precision of 0 is treated as a precision of 1. */
|
||||
if (!prec)
|
||||
++prec;
|
||||
/*
|
||||
* ``The style used depends on the value converted; style e
|
||||
* will be used only if the exponent resulting from the
|
||||
* conversion is less than -4 or greater than the precision.''
|
||||
* -- ANSI X3J11
|
||||
*/
|
||||
if (expcnt > prec || (!expcnt && fract && fract < .0001)) {
|
||||
/*
|
||||
* g/G format counts "significant digits, not digits of
|
||||
* precision; for the e/E format, this just causes an
|
||||
* off-by-one problem, i.e. g/G considers the digit
|
||||
* before the decimal point significant and e/E doesn't
|
||||
* count it as precision.
|
||||
*/
|
||||
--prec;
|
||||
fmtch -= 2; /* G->E, g->e */
|
||||
gformat = 1;
|
||||
goto eformat;
|
||||
}
|
||||
/*
|
||||
* reverse integer into beginning of buffer,
|
||||
* note, decrement precision
|
||||
*/
|
||||
if (expcnt)
|
||||
for (; ++p < endp; *t++ = *p, --prec);
|
||||
else
|
||||
*t++ = '0';
|
||||
/*
|
||||
* if precision required or alternate flag set, add in a
|
||||
* decimal point. If no digits yet, add in leading 0.
|
||||
*/
|
||||
if (prec || flags&ALT) {
|
||||
dotrim = 1;
|
||||
*t++ = '.';
|
||||
}
|
||||
else
|
||||
dotrim = 0;
|
||||
/* if requires more precision and some fraction left */
|
||||
if (fract) {
|
||||
if (prec) {
|
||||
/* If no integer part, don't count initial
|
||||
* zeros as significant digits. */
|
||||
do {
|
||||
fract = modf(fract * 10, &tmp);
|
||||
*t++ = to_char((int)tmp);
|
||||
} while(!tmp && !expcnt);
|
||||
while (--prec && fract) {
|
||||
fract = modf(fract * 10, &tmp);
|
||||
*t++ = to_char((int)tmp);
|
||||
}
|
||||
}
|
||||
if (fract)
|
||||
startp = round(fract, (int *)NULL, startp,
|
||||
t - 1, (char)0, signp);
|
||||
}
|
||||
/* alternate format, adds 0's for precision, else trim 0's */
|
||||
if (flags&ALT)
|
||||
for (; prec--; *t++ = '0');
|
||||
else if (dotrim) {
|
||||
while (t > startp && *--t == '0');
|
||||
if (*t != '.')
|
||||
++t;
|
||||
}
|
||||
}
|
||||
return (t - startp);
|
||||
}
|
||||
|
||||
#endif /* defined(FLOATING_POINT) && !defined(USE_DTOA) */
|
||||
|
||||
int streambuf::form(char const *format ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int count = vform(format, ap);
|
||||
va_end(ap);
|
||||
return count;
|
||||
}
|
@ -1,746 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
// Extensively hacked for GNU iostream by Per Bothner 1991, 1992.
|
||||
// Changes copyright Per Bothner 1992.
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "%W% (Berkeley) %G%";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <ioprivate.h>
|
||||
#include <ctype.h>
|
||||
#ifndef NO_STDARG
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#ifndef NO_FLOATING_POINT
|
||||
#define FLOATING_POINT
|
||||
#endif
|
||||
|
||||
#ifdef FLOATING_POINT
|
||||
#include "floatio.h"
|
||||
#define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */
|
||||
#else
|
||||
#define BUF 40
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Flags used during conversion.
|
||||
*/
|
||||
#define LONG 0x01 /* l: long or double */
|
||||
#define LONGDBL 0x02 /* L: long double; unimplemented */
|
||||
#define SHORT 0x04 /* h: short */
|
||||
#define SUPPRESS 0x08 /* suppress assignment */
|
||||
#define POINTER 0x10 /* weird %p pointer (`fake hex') */
|
||||
#define NOSKIP 0x20 /* do not skip blanks */
|
||||
|
||||
/*
|
||||
* The following are used in numeric conversions only:
|
||||
* SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
|
||||
* SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
|
||||
*/
|
||||
#define SIGNOK 0x40 /* +/- is (still) legal */
|
||||
#define NDIGITS 0x80 /* no digits detected */
|
||||
|
||||
#define DPTOK 0x100 /* (float) decimal point is still legal */
|
||||
#define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */
|
||||
|
||||
#define PFXOK 0x100 /* 0x prefix is (still) legal */
|
||||
#define NZDIGITS 0x200 /* no zero digits detected */
|
||||
|
||||
/*
|
||||
* Conversion types.
|
||||
*/
|
||||
#define CT_CHAR 0 /* %c conversion */
|
||||
#define CT_CCL 1 /* %[...] conversion */
|
||||
#define CT_STRING 2 /* %s conversion */
|
||||
#define CT_INT 3 /* integer, i.e., strtol or strtoul */
|
||||
#define CT_FLOAT 4 /* floating, i.e., strtod */
|
||||
|
||||
#define u_char unsigned char
|
||||
#define u_long unsigned long
|
||||
|
||||
extern "C" u_long strtoul(const char*, char**, int);
|
||||
static const u_char *__sccl(register char *tab, register const u_char *fmt);
|
||||
|
||||
// If state is non-NULL, set failbit and/or eofbit as appropriate.
|
||||
|
||||
int streambuf::vscan(char const *fmt0,
|
||||
_G_va_list ap,
|
||||
ios *stream /* = NULL */)
|
||||
{
|
||||
register const u_char *fmt = (const u_char *)fmt0;
|
||||
register int c; /* character from format, or conversion */
|
||||
register size_t width; /* field width, or 0 */
|
||||
register char *p; /* points into all kinds of strings */
|
||||
register int n; /* handy integer */
|
||||
register int flags; /* flags as defined above */
|
||||
register char *p0; /* saves original value of p when necessary */
|
||||
int nassigned; /* number of fields assigned */
|
||||
int nread; /* number of characters consumed from fp */
|
||||
// Assignments to base and ccfn are just to suppress warnings from gcc.
|
||||
int base = 0; /* base argument to strtol/strtoul */
|
||||
typedef u_long (*strtoulfn)(const char*, char**, int);
|
||||
strtoulfn ccfn = 0;
|
||||
// conversion function (strtol/strtoul)
|
||||
char ccltab[256]; /* character class table for %[...] */
|
||||
char buf[BUF]; /* buffer for numeric conversions */
|
||||
int seen_eof = 0;
|
||||
|
||||
/* `basefix' is used to avoid `if' tests in the integer scanner */
|
||||
static short basefix[17] =
|
||||
{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
|
||||
|
||||
nassigned = 0;
|
||||
nread = 0;
|
||||
for (;;) {
|
||||
c = *fmt++;
|
||||
if (c == 0)
|
||||
goto done;
|
||||
if (isspace(c)) {
|
||||
for (;;) {
|
||||
c = sbumpc();
|
||||
if (c == EOF)
|
||||
goto eof_failure;
|
||||
if (!isspace(c)) {
|
||||
sputbackc(c);
|
||||
break;
|
||||
}
|
||||
nread++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (c != '%')
|
||||
goto literal;
|
||||
width = 0;
|
||||
flags = 0;
|
||||
/*
|
||||
* switch on the format. continue if done;
|
||||
* break once format type is derived.
|
||||
*/
|
||||
again: c = *fmt++;
|
||||
switch (c) {
|
||||
case '%':
|
||||
literal:
|
||||
n = sbumpc();
|
||||
if (n == EOF)
|
||||
goto eof_failure;
|
||||
if (n != c) {
|
||||
sputbackc(n);
|
||||
goto match_failure;
|
||||
}
|
||||
nread++;
|
||||
continue;
|
||||
|
||||
case '*':
|
||||
flags |= SUPPRESS;
|
||||
goto again;
|
||||
case 'l':
|
||||
flags |= LONG;
|
||||
goto again;
|
||||
case 'L':
|
||||
flags |= LONGDBL;
|
||||
goto again;
|
||||
case 'h':
|
||||
flags |= SHORT;
|
||||
goto again;
|
||||
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
width = width * 10 + c - '0';
|
||||
goto again;
|
||||
|
||||
/*
|
||||
* Conversions.
|
||||
* Those marked `compat' are for 4.[123]BSD compatibility.
|
||||
*
|
||||
* (According to ANSI, E and X formats are supposed
|
||||
* to the same as e and x. Sorry about that.)
|
||||
*/
|
||||
case 'D': /* compat */
|
||||
flags |= LONG;
|
||||
/* FALLTHROUGH */
|
||||
case 'd':
|
||||
c = CT_INT;
|
||||
ccfn = (strtoulfn)strtol;
|
||||
base = 10;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
c = CT_INT;
|
||||
ccfn = (strtoulfn)strtol;
|
||||
base = 0;
|
||||
break;
|
||||
|
||||
case 'O': /* compat */
|
||||
flags |= LONG;
|
||||
/* FALLTHROUGH */
|
||||
case 'o':
|
||||
c = CT_INT;
|
||||
ccfn = strtoul;
|
||||
base = 8;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
c = CT_INT;
|
||||
ccfn = strtoul;
|
||||
base = 10;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
case 'x':
|
||||
flags |= PFXOK; /* enable 0x prefixing */
|
||||
c = CT_INT;
|
||||
ccfn = strtoul;
|
||||
base = 16;
|
||||
break;
|
||||
|
||||
#ifdef FLOATING_POINT
|
||||
case 'E': case 'F':
|
||||
case 'e': case 'f': case 'g':
|
||||
c = CT_FLOAT;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 's':
|
||||
c = CT_STRING;
|
||||
break;
|
||||
|
||||
case '[':
|
||||
fmt = __sccl(ccltab, fmt);
|
||||
flags |= NOSKIP;
|
||||
c = CT_CCL;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
flags |= NOSKIP;
|
||||
c = CT_CHAR;
|
||||
break;
|
||||
|
||||
case 'p': /* pointer format is like hex */
|
||||
flags |= POINTER | PFXOK;
|
||||
c = CT_INT;
|
||||
ccfn = strtoul;
|
||||
base = 16;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (flags & SUPPRESS) /* ??? */
|
||||
continue;
|
||||
if (flags & SHORT)
|
||||
*va_arg(ap, short *) = nread;
|
||||
else if (flags & LONG)
|
||||
*va_arg(ap, long *) = nread;
|
||||
else
|
||||
*va_arg(ap, int *) = nread;
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Disgusting backwards compatibility hacks. XXX
|
||||
*/
|
||||
case '\0': /* compat */
|
||||
nassigned = EOF;
|
||||
goto done;
|
||||
|
||||
default: /* compat */
|
||||
if (isupper(c))
|
||||
flags |= LONG;
|
||||
c = CT_INT;
|
||||
ccfn = (strtoulfn)strtol;
|
||||
base = 10;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have a conversion that requires input.
|
||||
*/
|
||||
if (sgetc() == EOF)
|
||||
goto eof_failure;
|
||||
|
||||
/*
|
||||
* Consume leading white space, except for formats
|
||||
* that suppress this.
|
||||
*/
|
||||
if ((flags & NOSKIP) == 0) {
|
||||
n = (unsigned char)*_gptr;
|
||||
while (isspace(n)) {
|
||||
_gptr++;
|
||||
nread++;
|
||||
n = sgetc();
|
||||
if (n == EOF)
|
||||
goto eof_failure;
|
||||
}
|
||||
// Note that there is at least one character in
|
||||
// the buffer, so conversions that do not set NOSKIP
|
||||
// can no longer result in an input failure.
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the conversion.
|
||||
*/
|
||||
switch (c) {
|
||||
|
||||
case CT_CHAR:
|
||||
/* scan arbitrary characters (sets NOSKIP) */
|
||||
if (width == 0) // FIXME!
|
||||
width = 1;
|
||||
if (flags & SUPPRESS) {
|
||||
size_t sum = 0;
|
||||
for (;;) {
|
||||
if ((n = _egptr - _gptr) < (int)width) {
|
||||
sum += n;
|
||||
width -= n;
|
||||
_gptr += n;
|
||||
if (underflow() == EOF)
|
||||
if (sum == 0)
|
||||
goto eof_failure;
|
||||
else {
|
||||
seen_eof++;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sum += width;
|
||||
_gptr += width;
|
||||
break;
|
||||
}
|
||||
}
|
||||
nread += sum;
|
||||
} else {
|
||||
size_t r = sgetn((char*)va_arg(ap, char*),
|
||||
width);
|
||||
if (r != width)
|
||||
goto eof_failure;
|
||||
nread += r;
|
||||
nassigned++;
|
||||
}
|
||||
break;
|
||||
|
||||
case CT_CCL:
|
||||
/* scan a (nonempty) character class (sets NOSKIP) */
|
||||
if (width == 0)
|
||||
width = ~0; /* `infinity' */
|
||||
/* take only those things in the class */
|
||||
if (flags & SUPPRESS) {
|
||||
n = 0;
|
||||
while (ccltab[(unsigned char)*_gptr]) {
|
||||
n++, _gptr++;
|
||||
if (--width == 0)
|
||||
break;
|
||||
if (sgetc() == EOF) {
|
||||
if (n == 0)
|
||||
goto eof_failure;
|
||||
seen_eof++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n == 0)
|
||||
goto match_failure;
|
||||
} else {
|
||||
p0 = p = va_arg(ap, char *);
|
||||
while (ccltab[(unsigned char)*_gptr]) {
|
||||
*p++ = *_gptr++;
|
||||
if (--width == 0)
|
||||
break;
|
||||
if (sgetc() == EOF) {
|
||||
if (p == p0)
|
||||
goto eof_failure;
|
||||
seen_eof++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
n = p - p0;
|
||||
if (n == 0)
|
||||
goto match_failure;
|
||||
*p = 0;
|
||||
nassigned++;
|
||||
}
|
||||
nread += n;
|
||||
break;
|
||||
|
||||
case CT_STRING:
|
||||
/* like CCL, but zero-length string OK, & no NOSKIP */
|
||||
if (width == 0)
|
||||
width = ~0;
|
||||
if (flags & SUPPRESS) {
|
||||
n = 0;
|
||||
while (!isspace((unsigned char)*_gptr)) {
|
||||
n++, _gptr++;
|
||||
if (--width == 0)
|
||||
break;
|
||||
if (sgetc() == EOF) {
|
||||
seen_eof++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
nread += n;
|
||||
} else {
|
||||
p0 = p = va_arg(ap, char *);
|
||||
while (!isspace((unsigned char)*_gptr)) {
|
||||
*p++ = *_gptr++;
|
||||
if (--width == 0)
|
||||
break;
|
||||
if (sgetc() == EOF) {
|
||||
seen_eof++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*p = 0;
|
||||
nread += p - p0;
|
||||
nassigned++;
|
||||
}
|
||||
continue;
|
||||
|
||||
case CT_INT:
|
||||
/* scan an integer as if by strtol/strtoul */
|
||||
if (width == 0 || width > sizeof(buf) - 1)
|
||||
width = sizeof(buf) - 1;
|
||||
flags |= SIGNOK | NDIGITS | NZDIGITS;
|
||||
for (p = buf; width; width--) {
|
||||
c = (unsigned char)*_gptr;
|
||||
/*
|
||||
* Switch on the character; `goto ok'
|
||||
* if we accept it as a part of number.
|
||||
*/
|
||||
switch (c) {
|
||||
|
||||
/*
|
||||
* The digit 0 is always legal, but is
|
||||
* special. For %i conversions, if no
|
||||
* digits (zero or nonzero) have been
|
||||
* scanned (only signs), we will have
|
||||
* base==0. In that case, we should set
|
||||
* it to 8 and enable 0x prefixing.
|
||||
* Also, if we have not scanned zero digits
|
||||
* before this, do not turn off prefixing
|
||||
* (someone else will turn it off if we
|
||||
* have scanned any nonzero digits).
|
||||
*/
|
||||
case '0':
|
||||
if (base == 0) {
|
||||
base = 8;
|
||||
flags |= PFXOK;
|
||||
}
|
||||
if (flags & NZDIGITS)
|
||||
flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
|
||||
else
|
||||
flags &= ~(SIGNOK|PFXOK|NDIGITS);
|
||||
goto ok;
|
||||
|
||||
/* 1 through 7 always legal */
|
||||
case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
base = basefix[base];
|
||||
flags &= ~(SIGNOK | PFXOK | NDIGITS);
|
||||
goto ok;
|
||||
|
||||
/* digits 8 and 9 ok iff decimal or hex */
|
||||
case '8': case '9':
|
||||
base = basefix[base];
|
||||
if (base <= 8)
|
||||
break; /* not legal here */
|
||||
flags &= ~(SIGNOK | PFXOK | NDIGITS);
|
||||
goto ok;
|
||||
|
||||
/* letters ok iff hex */
|
||||
case 'A': case 'B': case 'C':
|
||||
case 'D': case 'E': case 'F':
|
||||
case 'a': case 'b': case 'c':
|
||||
case 'd': case 'e': case 'f':
|
||||
/* no need to fix base here */
|
||||
if (base <= 10)
|
||||
break; /* not legal here */
|
||||
flags &= ~(SIGNOK | PFXOK | NDIGITS);
|
||||
goto ok;
|
||||
|
||||
/* sign ok only as first character */
|
||||
case '+': case '-':
|
||||
if (flags & SIGNOK) {
|
||||
flags &= ~SIGNOK;
|
||||
goto ok;
|
||||
}
|
||||
break;
|
||||
|
||||
/* x ok iff flag still set & 2nd char */
|
||||
case 'x': case 'X':
|
||||
if (flags & PFXOK && p == buf + 1) {
|
||||
base = 16; /* if %i */
|
||||
flags &= ~PFXOK;
|
||||
goto ok;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we got here, c is not a legal character
|
||||
* for a number. Stop accumulating digits.
|
||||
*/
|
||||
break;
|
||||
ok:
|
||||
/*
|
||||
* c is legal: store it and look at the next.
|
||||
*/
|
||||
*p++ = c;
|
||||
_gptr++;
|
||||
if (sgetc() == EOF) {
|
||||
seen_eof++;
|
||||
break; /* EOF */
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If we had only a sign, it is no good; push
|
||||
* back the sign. If the number ends in `x',
|
||||
* it was [sign] '0' 'x', so push back the x
|
||||
* and treat it as [sign] '0'.
|
||||
*/
|
||||
if (flags & NDIGITS) {
|
||||
if (p > buf)
|
||||
(void) sputbackc(*(u_char *)--p);
|
||||
goto match_failure;
|
||||
}
|
||||
c = ((u_char *)p)[-1];
|
||||
if (c == 'x' || c == 'X') {
|
||||
--p;
|
||||
(void) sputbackc(c);
|
||||
}
|
||||
if ((flags & SUPPRESS) == 0) {
|
||||
u_long res;
|
||||
|
||||
*p = 0;
|
||||
res = (*ccfn)(buf, (char **)NULL, base);
|
||||
if (flags & POINTER)
|
||||
*va_arg(ap, void **) = (void *)res;
|
||||
else if (flags & SHORT)
|
||||
*va_arg(ap, short *) = res;
|
||||
else if (flags & LONG)
|
||||
*va_arg(ap, long *) = res;
|
||||
else
|
||||
*va_arg(ap, int *) = res;
|
||||
nassigned++;
|
||||
}
|
||||
nread += p - buf;
|
||||
break;
|
||||
|
||||
#ifdef FLOATING_POINT
|
||||
case CT_FLOAT:
|
||||
/* scan a floating point number as if by strtod */
|
||||
if (width == 0 || width > sizeof(buf) - 1)
|
||||
width = sizeof(buf) - 1;
|
||||
flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
|
||||
for (p = buf; width; width--) {
|
||||
c = (unsigned char)*_gptr;
|
||||
/*
|
||||
* This code mimicks the integer conversion
|
||||
* code, but is much simpler.
|
||||
*/
|
||||
switch (c) {
|
||||
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
case '8': case '9':
|
||||
flags &= ~(SIGNOK | NDIGITS);
|
||||
goto fok;
|
||||
|
||||
case '+': case '-':
|
||||
if (flags & SIGNOK) {
|
||||
flags &= ~SIGNOK;
|
||||
goto fok;
|
||||
}
|
||||
break;
|
||||
case '.':
|
||||
if (flags & DPTOK) {
|
||||
flags &= ~(SIGNOK | DPTOK);
|
||||
goto fok;
|
||||
}
|
||||
break;
|
||||
case 'e': case 'E':
|
||||
/* no exponent without some digits */
|
||||
if ((flags&(NDIGITS|EXPOK)) == EXPOK) {
|
||||
flags =
|
||||
(flags & ~(EXPOK|DPTOK)) |
|
||||
SIGNOK | NDIGITS;
|
||||
goto fok;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
fok:
|
||||
*p++ = c;
|
||||
_gptr++;
|
||||
if (sgetc() == EOF) {
|
||||
seen_eof++;
|
||||
break; /* EOF */
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If no digits, might be missing exponent digits
|
||||
* (just give back the exponent) or might be missing
|
||||
* regular digits, but had sign and/or decimal point.
|
||||
*/
|
||||
if (flags & NDIGITS) {
|
||||
if (flags & EXPOK) {
|
||||
/* no digits at all */
|
||||
while (p > buf)
|
||||
sputbackc(*(u_char *)--p);
|
||||
goto match_failure;
|
||||
}
|
||||
/* just a bad exponent (e and maybe sign) */
|
||||
c = *(u_char *)--p;
|
||||
if (c != 'e' && c != 'E') {
|
||||
(void)sputbackc(c);/* sign */
|
||||
c = *(u_char *)--p;
|
||||
}
|
||||
(void) sputbackc(c);
|
||||
}
|
||||
if ((flags & SUPPRESS) == 0) {
|
||||
double res;
|
||||
*p = 0;
|
||||
#ifdef USE_DTOA
|
||||
res = strtod(buf, NULL);
|
||||
#else
|
||||
res = atof(buf);
|
||||
#endif
|
||||
if (flags & LONG)
|
||||
*va_arg(ap, double *) = res;
|
||||
else
|
||||
*va_arg(ap, float *) = res;
|
||||
nassigned++;
|
||||
}
|
||||
nread += p - buf;
|
||||
break;
|
||||
#endif /* FLOATING_POINT */
|
||||
}
|
||||
}
|
||||
eof_failure:
|
||||
seen_eof++;
|
||||
input_failure:
|
||||
if (nassigned == 0)
|
||||
nassigned = -1;
|
||||
match_failure:
|
||||
if (stream)
|
||||
stream->set(ios::failbit);
|
||||
done:
|
||||
if (stream && seen_eof)
|
||||
stream->set(ios::eofbit);
|
||||
return (nassigned);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the given table from the scanset at the given format
|
||||
* (just after `['). Return a pointer to the character past the
|
||||
* closing `]'. The table has a 1 wherever characters should be
|
||||
* considered part of the scanset.
|
||||
*/
|
||||
static const u_char *__sccl(register char *tab, register const u_char *fmt)
|
||||
{
|
||||
register int c, n, v;
|
||||
|
||||
/* first `clear' the whole table */
|
||||
c = *fmt++; /* first char hat => negated scanset */
|
||||
if (c == '^') {
|
||||
v = 1; /* default => accept */
|
||||
c = *fmt++; /* get new first char */
|
||||
} else
|
||||
v = 0; /* default => reject */
|
||||
/* should probably use memset here */
|
||||
for (n = 0; n < 256; n++)
|
||||
tab[n] = v;
|
||||
if (c == 0)
|
||||
return (fmt - 1);/* format ended before closing ] */
|
||||
|
||||
/*
|
||||
* Now set the entries corresponding to the actual scanset
|
||||
* to the opposite of the above.
|
||||
*
|
||||
* The first character may be ']' (or '-') without being special;
|
||||
* the last character may be '-'.
|
||||
*/
|
||||
v = 1 - v;
|
||||
for (;;) {
|
||||
tab[c] = v; /* take character c */
|
||||
doswitch:
|
||||
n = *fmt++; /* and examine the next */
|
||||
switch (n) {
|
||||
|
||||
case 0: /* format ended too soon */
|
||||
return (fmt - 1);
|
||||
|
||||
case '-':
|
||||
/*
|
||||
* A scanset of the form
|
||||
* [01+-]
|
||||
* is defined as `the digit 0, the digit 1,
|
||||
* the character +, the character -', but
|
||||
* the effect of a scanset such as
|
||||
* [a-zA-Z0-9]
|
||||
* is implementation defined. The V7 Unix
|
||||
* scanf treats `a-z' as `the letters a through
|
||||
* z', but treats `a-a' as `the letter a, the
|
||||
* character -, and the letter a'.
|
||||
*
|
||||
* For compatibility, the `-' is not considerd
|
||||
* to define a range if the character following
|
||||
* it is either a close bracket (required by ANSI)
|
||||
* or is not numerically greater than the character
|
||||
* we just stored in the table (c).
|
||||
*/
|
||||
n = *fmt;
|
||||
if (n == ']' || n < c) {
|
||||
c = '-';
|
||||
break; /* resume the for(;;) */
|
||||
}
|
||||
fmt++;
|
||||
do { /* fill in the range */
|
||||
tab[++c] = v;
|
||||
} while (c < n);
|
||||
#if 1 /* XXX another disgusting compatibility hack */
|
||||
/*
|
||||
* Alas, the V7 Unix scanf also treats formats
|
||||
* such as [a-c-e] as `the letters a through e'.
|
||||
* This too is permitted by the standard....
|
||||
*/
|
||||
goto doswitch;
|
||||
#else
|
||||
c = *fmt++;
|
||||
if (c == 0)
|
||||
return (fmt - 1);
|
||||
if (c == ']')
|
||||
return (fmt);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ']': /* end of scanset */
|
||||
return (fmt);
|
||||
|
||||
default: /* just another character */
|
||||
c = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
int streambuf::scan(char const *format ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int count = vscan(format, ap);
|
||||
va_end(ap);
|
||||
return count;
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1991 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#include "ioprivate.h"
|
||||
|
||||
// Algorithm based on that used by Berkeley pre-4.4 fgets implementation.
|
||||
|
||||
// Read chars into buf (of size n), until delim is seen.
|
||||
// Return number of chars read (at most n-1).
|
||||
// If extract_delim < 0, leave delimiter unread.
|
||||
// If extract_delim > 0, insert delim in output.
|
||||
|
||||
long streambuf::sgetline(char* buf, size_t n, char delim, int extract_delim)
|
||||
{
|
||||
register char *ptr = buf;
|
||||
if (n <= 0)
|
||||
return EOF;
|
||||
n--; // Leave space for final '\0'.
|
||||
do {
|
||||
int len = egptr() - gptr();
|
||||
if (len <= 0)
|
||||
if (underflow() == EOF)
|
||||
break;
|
||||
else
|
||||
len = egptr() - gptr();
|
||||
if (len >= (int)n)
|
||||
len = n;
|
||||
char *t = (char*)memchr((void*)_gptr, delim, len);
|
||||
if (t != NULL) {
|
||||
size_t old_len = ptr-buf;
|
||||
len = t - _gptr;
|
||||
if (extract_delim >= 0) {
|
||||
t++;
|
||||
old_len++;
|
||||
if (extract_delim > 0)
|
||||
len++;
|
||||
}
|
||||
memcpy((void*)ptr, (void*)_gptr, len);
|
||||
ptr[len] = 0;
|
||||
_gptr = t;
|
||||
return old_len + len;
|
||||
}
|
||||
memcpy((void*)ptr, (void*)_gptr, len);
|
||||
_gptr += len;
|
||||
ptr += len;
|
||||
n -= len;
|
||||
} while (n != 0);
|
||||
*ptr = 0;
|
||||
return ptr - buf;
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
// This is part of the iostream library, providing -*- C++ -*- input/output.
|
||||
// Copyright (C) 1992 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#endif
|
||||
|
||||
#include <stdiostream.h>
|
||||
|
||||
// A stdiobuf is "tied" to a FILE object (as used by the stdio package).
|
||||
// Thus a stdiobuf is always synchronized with the corresponding FILE,
|
||||
// though at the cost of some overhead. (If you use the implementation
|
||||
// of stdio supplied with this library, you don't need stdiobufs.)
|
||||
// This implementation inherits from filebuf, but implement the virtual
|
||||
// functions sys_read/..., using the stdio functions fread/... instead
|
||||
// of the low-level read/... system calls. This has the advantage that
|
||||
// we get all of the nice filebuf semantics automatically, though
|
||||
// with some overhead.
|
||||
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0
|
||||
#endif
|
||||
#ifndef SEEK_CUR
|
||||
#define SEEK_CUR 1
|
||||
#endif
|
||||
#ifndef SEEK_END
|
||||
#define SEEK_END 2
|
||||
#endif
|
||||
|
||||
stdiobuf::stdiobuf(FILE *f) : filebuf(fileno(f))
|
||||
{
|
||||
_file = f;
|
||||
// Turn off buffer in stdiobuf. Instead, rely on buffering in (FILE).
|
||||
// Thus the stdiobuf will be synchronized with the FILE.
|
||||
setbuf(NULL, 0);
|
||||
}
|
||||
|
||||
_G_ssize_t stdiobuf::sys_read(char* buf, size_t size)
|
||||
{
|
||||
return fread(buf, 1, size, _file);
|
||||
}
|
||||
|
||||
_G_ssize_t stdiobuf::sys_write(const void *buf, long n)
|
||||
{
|
||||
_G_ssize_t count = fwrite(buf, 1, n, _file);
|
||||
if (_fb._offset >= 0)
|
||||
_fb._offset += n;
|
||||
return count;
|
||||
}
|
||||
|
||||
_G_fpos_t stdiobuf::sys_seek(_G_fpos_t offset, _seek_dir dir)
|
||||
{
|
||||
// Normally, equivalent to: fdir=dir
|
||||
int fdir =
|
||||
(dir == ios::beg) ? SEEK_SET :
|
||||
(dir == ios::cur) ? SEEK_CUR :
|
||||
(dir == ios::end) ? SEEK_END :
|
||||
dir;
|
||||
return fseek(_file, offset, fdir);
|
||||
}
|
||||
|
||||
int stdiobuf::sys_close()
|
||||
{
|
||||
int status = fclose(_file);
|
||||
_file = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
int stdiobuf::sync()
|
||||
{
|
||||
if (filebuf::sync() == EOF)
|
||||
return EOF;
|
||||
if (!(xflags() & _S_NO_WRITES))
|
||||
if (fflush(_file))
|
||||
return EOF;
|
||||
#if 0
|
||||
// This loses when writing to a pipe.
|
||||
if (fseek(_file, 0, SEEK_CUR) == EOF)
|
||||
return EOF;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stdiobuf::overflow(int c /* = EOF*/)
|
||||
{
|
||||
if (filebuf::overflow(c) == EOF)
|
||||
return EOF;
|
||||
if (c != EOF)
|
||||
return c;
|
||||
return fflush(_file);
|
||||
}
|
||||
|
||||
int stdiobuf::xsputn(const char* s, int n)
|
||||
{
|
||||
// The filebuf implementation of sputn loses.
|
||||
return streambuf::xsputn(s, n);
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
// This is part of the iostream library, providing -*- C++ -*- input/output.
|
||||
// Copyright (C) 1992 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: stdiostream.h,v 1.2 1993/08/02 17:22:39 mycroft Exp $
|
||||
|
||||
#ifndef _STDIOSTREAM_H
|
||||
#define _STDIOSTREAM_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
|
||||
#include <streambuf.h>
|
||||
#include <stdio.h>
|
||||
|
||||
class stdiobuf : public filebuf {
|
||||
protected:
|
||||
FILE *_file;
|
||||
public:
|
||||
FILE* stdiofile() const { return _file; }
|
||||
stdiobuf(FILE *f);
|
||||
virtual _G_ssize_t sys_read(char* buf, _G_size_t size);
|
||||
virtual _G_fpos_t sys_seek(_G_fpos_t, _seek_dir);
|
||||
virtual _G_ssize_t sys_write(const void*, long);
|
||||
virtual int sys_close();
|
||||
virtual int sync();
|
||||
virtual int overflow(int c = EOF);
|
||||
virtual int xsputn(const char* s, int n);
|
||||
};
|
||||
|
||||
#endif /* !_STDIOSTREAM_H */
|
@ -1,129 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1992 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#include "ioprivate.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// This file defines the standard streambufs, corresponding to cin, cout, cerr.
|
||||
// We define two sets:
|
||||
//
|
||||
// __std_filebuf_0, __std_filebuf_1, __std_filebuf_2 are filebufs using
|
||||
// file descriptor 0/1/2.
|
||||
//
|
||||
// __stdin_stdiobuf, __stdout_stdiobuf, __stderr_stdiobuf are stdiostreams
|
||||
// pointing to stdin, stdout, stderr.
|
||||
|
||||
|
||||
// To avoid problems depending on constructor order (and for
|
||||
// efficiency) the standard streambufs (and streams) are
|
||||
// constructed statically using C-style '{ ... }' initializers.
|
||||
// Since you're not allowed to do this for structs that
|
||||
// have virtuals, we define fake streambuf and stream classes
|
||||
// that don't have any C++-isms, and initialize those.
|
||||
// To initialize the vtable field of the standard filebufs,
|
||||
// we use the expression 'vt_filebuf' which must evaluate to
|
||||
// (the address of) the virtual function table for the
|
||||
// filebuf class.
|
||||
|
||||
#if _G_NAMES_HAVE_UNDERSCORE
|
||||
#define UNDERSCORE "_"
|
||||
#else
|
||||
#define UNDERSCORE ""
|
||||
#endif
|
||||
|
||||
// First define the filebuf-based objects.
|
||||
|
||||
#if !defined(vt_filebuf)
|
||||
#ifndef __GNUG__
|
||||
// This works for cfront.
|
||||
#define vt_filebuf __vtbl__7filebuf
|
||||
extern char vt_filebuf[1];
|
||||
#elif _G_DOLLAR_IN_LABEL
|
||||
#if __GNUC_MAJOR__ > 2 || __GNUC_MINOR__ >= 5
|
||||
extern char vt_filebuf[1] asm(UNDERSCORE "_vt$7filebuf");
|
||||
#else
|
||||
extern char vt_filebuf[1] asm(UNDERSCORE "_vt$filebuf");
|
||||
#endif
|
||||
#else
|
||||
#if __GNUC_MAJOR__ > 2 || __GNUC_MINOR__ >= 5
|
||||
extern char vt_filebuf[1] asm(UNDERSCORE "_vt.7filebuf");
|
||||
#else
|
||||
extern char vt_filebuf[1] asm(UNDERSCORE "_vt.filebuf");
|
||||
#endif
|
||||
#endif
|
||||
#endif /* !defined(vt_filebuf) */
|
||||
|
||||
struct _fake_filebuf {
|
||||
struct __streambuf s;
|
||||
char* vtable;
|
||||
struct __file_fields f;
|
||||
};
|
||||
|
||||
#define FILEBUF_LITERAL(CHAIN, FLAGS) \
|
||||
{ _IO_MAGIC+_S_LINKED+_S_IS_FILEBUF+_S_IS_BACKUPBUF+FLAGS, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, CHAIN, 0, 0, 0, 0, 0}
|
||||
|
||||
#define DEF_FILEBUF(NAME, FD, CHAIN, FLAGS) \
|
||||
_fake_filebuf NAME = {FILEBUF_LITERAL(CHAIN, FLAGS), vt_filebuf, {FD}};
|
||||
|
||||
DEF_FILEBUF(__std_filebuf_0, 0, 0, _S_NO_WRITES);
|
||||
DEF_FILEBUF(__std_filebuf_1, 1, (streambuf*)&__std_filebuf_0, _S_NO_READS);
|
||||
DEF_FILEBUF(__std_filebuf_2, 2, (streambuf*)&__std_filebuf_1,
|
||||
_S_NO_READS+_S_UNBUFFERED);
|
||||
|
||||
// Nest define the stdiobuf-bases objects.
|
||||
|
||||
#if !defined(vt_stdiobuf)
|
||||
#ifndef __GNUG__
|
||||
// This works for cfront.
|
||||
#define vt_stdiobuf __vtbl__8stdiobuf
|
||||
extern char vt_stdiobuf[1];
|
||||
#elif _G_DOLLAR_IN_LABEL
|
||||
#if __GNUC_MAJOR__ > 2 || __GNUC_MINOR__ >= 5
|
||||
extern char vt_stdiobuf[1] asm(UNDERSCORE "_vt$8stdiobuf");
|
||||
#else
|
||||
extern char vt_stdiobuf[1] asm(UNDERSCORE "_vt$stdiobuf");
|
||||
#endif
|
||||
#else
|
||||
#if __GNUC_MAJOR__ > 2 || __GNUC_MINOR__ >= 5
|
||||
extern char vt_stdiobuf[1] asm(UNDERSCORE "_vt.8stdiobuf");
|
||||
#else
|
||||
extern char vt_stdiobuf[1] asm(UNDERSCORE "_vt.stdiobuf");
|
||||
#endif
|
||||
#endif
|
||||
#endif /* !defined(vt_stdiobuf) */
|
||||
|
||||
struct _fake_stdiobuf {
|
||||
struct __streambuf s;
|
||||
char* vtable;
|
||||
struct __file_fields f;
|
||||
FILE *_f;
|
||||
};
|
||||
|
||||
#define DEF_STDIOBUF(NAME, FILE, FD, CHAIN, FLAGS) \
|
||||
_fake_stdiobuf NAME[1] = {{ \
|
||||
FILEBUF_LITERAL(CHAIN, (FLAGS)|_S_UNBUFFERED),\
|
||||
vt_stdiobuf, {FD}, FILE}};
|
||||
|
||||
DEF_STDIOBUF(__stdin_stdiobuf, stdin, 0, (streambuf*)&__std_filebuf_2,
|
||||
_S_NO_WRITES);
|
||||
DEF_STDIOBUF(__stdout_stdiobuf, stdout, 1, (streambuf*)__stdin_stdiobuf,
|
||||
_S_NO_READS);
|
||||
DEF_STDIOBUF(__stderr_stdiobuf, stderr, 2, (streambuf*)__stdout_stdiobuf,
|
||||
_S_NO_READS);
|
||||
|
||||
streambuf* streambuf::_list_all = (streambuf*)__stderr_stdiobuf;
|
@ -1,145 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1992 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#include "ioprivate.h"
|
||||
|
||||
// The ANSI draft requires that operations on cin/cout/cerr can be
|
||||
// mixed with operations on stdin/stdout/stderr on a character by
|
||||
// character basis. This normally requires that the streambuf's
|
||||
// used by cin/cout/cerr be stdiostreams. However, if the stdio
|
||||
// implementation is the one that is built using this library,
|
||||
// then we don't need to, since in that case stdin/stdout/stderr
|
||||
// are identical to &__std_filebuf_0/&__std_filebuf_1/&__std_filebuf_2.
|
||||
|
||||
#ifdef _STDIO_USES_IOSTREAM
|
||||
#define USE_FILEBUF
|
||||
#endif
|
||||
|
||||
#ifdef NAMES_HAVE_UNDERSCORE
|
||||
#define UNDERSCORE "_"
|
||||
#else
|
||||
#define UNDERSCORE ""
|
||||
#endif
|
||||
|
||||
#ifdef USE_FILEBUF
|
||||
#define CIN_SBUF __std_filebuf_0
|
||||
#define COUT_SBUF __std_filebuf_1
|
||||
#define CERR_SBUF __std_filebuf_2
|
||||
static int use_stdiobuf = 0;
|
||||
#else
|
||||
#define CIN_SBUF __stdin_stdiobuf
|
||||
#define COUT_SBUF __stdout_stdiobuf
|
||||
#define CERR_SBUF __stderr_stdiobuf
|
||||
static int use_stdiobuf = 1;
|
||||
#endif
|
||||
|
||||
struct _fake_filebuf;
|
||||
extern _fake_filebuf __std_filebuf_0, __std_filebuf_1, __std_filebuf_2;
|
||||
struct _fake_stdiobuf;
|
||||
extern _fake_stdiobuf __stdin_stdiobuf, __stdout_stdiobuf, __stderr_stdiobuf;
|
||||
|
||||
#define cin CIN
|
||||
#define cout COUT
|
||||
#define cerr CERR
|
||||
#define clog CLOG
|
||||
#include "iostream.h"
|
||||
#undef cin
|
||||
#undef cout
|
||||
#undef cerr
|
||||
#undef clog
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define PAD 0 /* g++ allows 0-length arrays. */
|
||||
#else
|
||||
#define PAD 1
|
||||
#endif
|
||||
struct _fake_istream {
|
||||
struct myfields {
|
||||
#ifdef __GNUC__
|
||||
_ios_fields *vb; /* pointer to virtual base class ios */
|
||||
_G_ssize_t _gcount;
|
||||
#else
|
||||
/* This is supposedly correct for cfront. */
|
||||
_G_ssize_t _gcount;
|
||||
void *vptr;
|
||||
_ios_fields *vb; /* pointer to virtual base class ios */
|
||||
#endif
|
||||
} mine;
|
||||
_ios_fields base;
|
||||
char filler[sizeof(struct istream)-sizeof(struct _ios_fields)+PAD];
|
||||
};
|
||||
struct _fake_ostream {
|
||||
struct myfields {
|
||||
#ifndef __GNUC__
|
||||
void *vptr;
|
||||
#endif
|
||||
_ios_fields *vb; /* pointer to virtual base class ios */
|
||||
} mine;
|
||||
_ios_fields base;
|
||||
char filler[sizeof(struct ostream)-sizeof(struct _ios_fields)+PAD];
|
||||
};
|
||||
|
||||
#define STD_STR(SBUF, TIE, EXTRA_FLAGS) \
|
||||
(streambuf*)&SBUF, TIE, 0, ios::dont_close|ios::skipws|EXTRA_FLAGS, ' ',0,0,6
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define OSTREAM_DEF(TYPE, NAME, SBUF, TIE, EXTRA_FLAGS) \
|
||||
TYPE NAME = { {&NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }};
|
||||
#define ISTREAM_DEF(TYPE, NAME, SBUF, TIE, EXTRA_FLAGS) \
|
||||
TYPE NAME = { {&NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }};
|
||||
#else
|
||||
#define OSTREAM_DEF(TYPE, NAME, SBUF, TIE, EXTRA_FLAGS) \
|
||||
TYPE NAME = { {0, &NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }};
|
||||
#define ISTREAM_DEF(TYPE, NAME, SBUF, TIE, EXTRA_FLAGS) \
|
||||
TYPE NAME = { {0, 0, &NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }};
|
||||
#endif
|
||||
|
||||
OSTREAM_DEF(_fake_ostream, cout, COUT_SBUF, NULL, 0)
|
||||
OSTREAM_DEF(_fake_ostream, cerr, CERR_SBUF, (ostream*)&cout, ios::unitbuf)
|
||||
ISTREAM_DEF(_fake_istream, cin, CIN_SBUF, (ostream*)&cout, 0)
|
||||
|
||||
/* Only for (partial) compatibility with AT&T's library. */
|
||||
OSTREAM_DEF(_fake_ostream, clog, CERR_SBUF, (ostream*)&cout, 0)
|
||||
|
||||
// Switches between using __std_filebuf_{0,1,2} and
|
||||
// __std{in,out,err}_stdiobuf for standard streams. This is
|
||||
// normally not needed, but is provided for AT&T compatibility.
|
||||
|
||||
int ios::sync_with_stdio(int new_state)
|
||||
{
|
||||
#ifdef _STDIO_USES_IOSTREAM
|
||||
// It is always synced.
|
||||
return 0;
|
||||
#else
|
||||
if (new_state == use_stdiobuf) // The usual case now.
|
||||
return use_stdiobuf;
|
||||
if (new_state) {
|
||||
cout.base._strbuf = (streambuf*)&__stdout_stdiobuf;
|
||||
cin.base._strbuf = (streambuf*)&__stdin_stdiobuf;
|
||||
cerr.base._strbuf = (streambuf*)&__stderr_stdiobuf;
|
||||
clog.base._strbuf = (streambuf*)&__stderr_stdiobuf;
|
||||
} else {
|
||||
cout.base._strbuf = (streambuf*)&__std_filebuf_1;
|
||||
cin.base._strbuf = (streambuf*)&__std_filebuf_0;
|
||||
cerr.base._strbuf = (streambuf*)&__std_filebuf_2;
|
||||
clog.base._strbuf = (streambuf*)&__std_filebuf_2;
|
||||
}
|
||||
int old_state = use_stdiobuf;
|
||||
use_stdiobuf = new_state;
|
||||
return old_state;
|
||||
#endif
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
#include <stdarg.h>
|
||||
#include "ioprivate.h"
|
||||
#include "stream.h"
|
||||
#include "strstream.h"
|
||||
|
||||
static char Buffer[_G_BUFSIZ];
|
||||
#define EndBuffer (Buffer+_G_BUFSIZ)
|
||||
static char* next_chunk = Buffer; // Start of available part of Buffer.
|
||||
|
||||
char* form(const char* format, ...)
|
||||
{
|
||||
int space_left = EndBuffer - next_chunk;
|
||||
// If less that 25% of the space is available start over.
|
||||
if (space_left < (_G_BUFSIZ>>2))
|
||||
next_chunk = Buffer;
|
||||
char* buf = next_chunk;
|
||||
|
||||
strstreambuf stream(buf, EndBuffer-buf-1, buf);
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int count = stream.vform(format, ap);
|
||||
va_end(ap);
|
||||
stream.sputc(0);
|
||||
next_chunk = buf + stream.pcount();
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define u_long unsigned long
|
||||
|
||||
static char* itoa(unsigned long i, int size, int neg, int base)
|
||||
{
|
||||
// Conservative estimate: If base==2, might need 8 characters
|
||||
// for each input byte, but normally 3 is plenty.
|
||||
int needed = size ? size
|
||||
: (base >= 8 ? 3 : 8) * sizeof(unsigned long) + 2;
|
||||
int space_left = EndBuffer - next_chunk;
|
||||
if (space_left <= needed)
|
||||
next_chunk = Buffer; // start over.
|
||||
|
||||
char* buf = next_chunk;
|
||||
|
||||
register char* ptr = buf+needed+1;
|
||||
next_chunk = ptr;
|
||||
|
||||
if (needed < (2+neg) || ptr > EndBuffer)
|
||||
return NULL;
|
||||
*--ptr = 0;
|
||||
|
||||
if (i == 0)
|
||||
*--ptr = '0';
|
||||
while (i != 0 && ptr > buf) {
|
||||
int ch = i % base;
|
||||
i = i / base;
|
||||
if (ch >= 10)
|
||||
ch += 'a' - 10;
|
||||
else
|
||||
ch += '0';
|
||||
*--ptr = ch;
|
||||
}
|
||||
if (neg)
|
||||
*--ptr = '-';
|
||||
if (size == 0)
|
||||
return ptr;
|
||||
while (ptr > buf)
|
||||
*--ptr = ' ';
|
||||
return buf;
|
||||
}
|
||||
|
||||
char* dec(long i, int len /* = 0 */)
|
||||
{
|
||||
if (i >= 0) return itoa((unsigned long)i, len, 0, 10);
|
||||
else return itoa((unsigned long)(-i), len, 1, 10);
|
||||
}
|
||||
char* dec(int i, int len /* = 0 */)
|
||||
{
|
||||
if (i >= 0) return itoa((unsigned long)i, len, 0, 10);
|
||||
else return itoa((unsigned long)(-i), len, 1, 10);
|
||||
}
|
||||
char* dec(unsigned long i, int len /* = 0 */)
|
||||
{
|
||||
return itoa(i, len, 0, 10);
|
||||
}
|
||||
char* dec(unsigned int i, int len /* = 0 */)
|
||||
{
|
||||
return itoa(i, len, 0, 10);
|
||||
}
|
||||
|
||||
char* hex(long i, int len /* = 0 */)
|
||||
{
|
||||
return itoa((unsigned long)i, len, 0, 16);
|
||||
}
|
||||
char* hex(int i, int len /* = 0 */)
|
||||
{
|
||||
return itoa((unsigned long)i, len, 0, 16);
|
||||
}
|
||||
char* hex(unsigned long i, int len /* = 0 */)
|
||||
{
|
||||
return itoa(i, len, 0, 16);
|
||||
}
|
||||
char* hex(unsigned int i, int len /* = 0 */)
|
||||
{
|
||||
return itoa(i, len, 0, 16);
|
||||
}
|
||||
|
||||
char* oct(long i, int len /* = 0 */)
|
||||
{
|
||||
return itoa((unsigned long)i, len, 0, 8);
|
||||
}
|
||||
char* oct(int i, int len /* = 0 */)
|
||||
{
|
||||
return itoa((unsigned long)i, len, 0, 8);
|
||||
}
|
||||
char* oct(unsigned long i, int len /* = 0 */)
|
||||
{
|
||||
return itoa(i, len, 0, 8);
|
||||
}
|
||||
char* oct(unsigned int i, int len /* = 0 */)
|
||||
{
|
||||
return itoa(i, len, 0, 8);
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
// $Id: stream.h,v 1.2 1993/08/02 17:22:40 mycroft Exp $
|
||||
|
||||
#ifndef _COMPAT_STREAM_H
|
||||
#define _COMPAT_STREAM_H
|
||||
|
||||
// Compatibility with old library.
|
||||
|
||||
#define _STREAM_COMPAT
|
||||
#include <iostream.h>
|
||||
|
||||
extern char* form(const char*, ...);
|
||||
|
||||
extern char* dec(long, int=0);
|
||||
extern char* dec(int, int=0);
|
||||
extern char* dec(unsigned long, int=0);
|
||||
extern char* dec(unsigned int, int=0);
|
||||
|
||||
extern char* hex(long, int=0);
|
||||
extern char* hex(int, int=0);
|
||||
extern char* hex(unsigned long, int=0);
|
||||
extern char* hex(unsigned int, int=0);
|
||||
|
||||
extern char* oct(long, int=0);
|
||||
extern char* oct(int, int=0);
|
||||
extern char* oct(unsigned long, int=0);
|
||||
extern char* oct(unsigned int, int=0);
|
||||
|
||||
char* chr(char ch, int width = 0);
|
||||
char* str(const char* s, int width = 0);
|
||||
|
||||
inline istream& WS(istream& str) { return ws(str); }
|
||||
|
||||
#endif /* !_COMPAT_STREAM_H */
|
@ -1,666 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1991, 1992 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#define _STREAM_COMPAT
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#endif
|
||||
#include "ioprivate.h"
|
||||
#include <string.h>
|
||||
|
||||
void streambuf::_un_link()
|
||||
{
|
||||
if (_flags & _S_LINKED) {
|
||||
streambuf **f;
|
||||
for (f = &_list_all; *f != NULL; f = &(*f)->xchain()) {
|
||||
if (*f == this) {
|
||||
*f = xchain();
|
||||
break;
|
||||
}
|
||||
}
|
||||
_flags &= ~_S_LINKED;
|
||||
}
|
||||
}
|
||||
|
||||
void streambuf::_link_in()
|
||||
{
|
||||
if ((_flags & _S_LINKED) == 0) {
|
||||
_flags |= _S_LINKED;
|
||||
xchain() = _list_all;
|
||||
_list_all = this;
|
||||
}
|
||||
}
|
||||
|
||||
// Return minimum _pos markers
|
||||
// Assumes the current get area is the main get area.
|
||||
int streambuf::_least_marker()
|
||||
{
|
||||
int least_so_far = _egptr - _eback;
|
||||
for (register streammarker *mark = _markers;
|
||||
mark != NULL; mark = mark->_next)
|
||||
if (mark->_pos < least_so_far)
|
||||
least_so_far = mark->_pos;
|
||||
return least_so_far;
|
||||
}
|
||||
|
||||
// Switch current get area from backup buffer to (start of) main get area.
|
||||
|
||||
void streambuf::switch_to_main_get_area()
|
||||
{
|
||||
char *tmp;
|
||||
_flags &= ~_S_IN_BACKUP;
|
||||
// Swap _egptr and _other_egptr.
|
||||
tmp= _egptr; _egptr= _other_egptr; _other_egptr= tmp;
|
||||
// Swap _eback and _other_gbase.
|
||||
tmp= _eback; _eback = _other_gbase; _other_gbase = tmp;
|
||||
_gptr = _eback;
|
||||
}
|
||||
|
||||
// Switch current get area from main get area to (end of) backup area.
|
||||
|
||||
void streambuf::switch_to_backup_area()
|
||||
{
|
||||
char *tmp;
|
||||
_flags |= _S_IN_BACKUP;
|
||||
// Swap _egptr and _other_egptr.
|
||||
tmp = _egptr; _egptr = _other_egptr; _other_egptr = tmp;
|
||||
// Swap _gbase and _other_gbase.
|
||||
tmp = _eback; _eback = _other_gbase; _other_gbase = tmp;
|
||||
_gptr = _egptr;
|
||||
}
|
||||
|
||||
int streambuf::switch_to_get_mode()
|
||||
{
|
||||
if (_pptr > _pbase)
|
||||
if (overflow(EOF) == EOF)
|
||||
return EOF;
|
||||
if (in_backup()) {
|
||||
_eback = _aux_limit;
|
||||
}
|
||||
else {
|
||||
_eback = _base;
|
||||
if (_pptr > _egptr)
|
||||
_egptr = _pptr;
|
||||
}
|
||||
_gptr = _pptr;
|
||||
|
||||
setp(_gptr, _gptr);
|
||||
|
||||
_flags &= ~_S_CURRENTLY_PUTTING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void streambuf::free_backup_area()
|
||||
{
|
||||
if (in_backup())
|
||||
switch_to_main_get_area(); // Just in case.
|
||||
delete [] _other_gbase;
|
||||
_other_gbase = NULL;
|
||||
_other_egptr = NULL;
|
||||
_aux_limit = NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int streambuf::switch_to_put_mode()
|
||||
{
|
||||
_pbase = _gptr;
|
||||
_pptr = _gptr;
|
||||
_epptr = in_backup() ? _egptr : _ebuf; // wrong if line- or un-buffered?
|
||||
|
||||
_gptr = _egptr;
|
||||
_eback = _egptr;
|
||||
|
||||
_flags |= _S_CURRENTLY_PUTTING;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _G_FRIEND_BUG
|
||||
int __underflow(register streambuf *sb) { return __UNDERFLOW(sb); }
|
||||
int __UNDERFLOW(register streambuf *sb)
|
||||
#else
|
||||
int __underflow(register streambuf *sb)
|
||||
#endif
|
||||
{
|
||||
if (sb->put_mode())
|
||||
if (sb->switch_to_get_mode() == EOF) return EOF;
|
||||
if (sb->_gptr < sb->_egptr)
|
||||
return *(unsigned char*)sb->_gptr;
|
||||
if (sb->in_backup()) {
|
||||
sb->switch_to_main_get_area();
|
||||
if (sb->_gptr < sb->_egptr)
|
||||
return *sb->_gptr;
|
||||
}
|
||||
if (sb->have_markers()) {
|
||||
// Append [_gbase.._egptr] to backup area.
|
||||
int least_mark = sb->_least_marker();
|
||||
// needed_size is how much space we need in the backup area.
|
||||
int needed_size = (sb->_egptr - sb->_eback) - least_mark;
|
||||
int current_Bsize = sb->_other_egptr - sb->_other_gbase;
|
||||
int avail; // Extra space available for future expansion.
|
||||
if (needed_size > current_Bsize) {
|
||||
avail = 0; // 100 ?? FIXME
|
||||
char *new_buffer = new char[avail+needed_size];
|
||||
if (least_mark < 0) {
|
||||
memcpy(new_buffer + avail,
|
||||
sb->_other_egptr + least_mark,
|
||||
-least_mark);
|
||||
memcpy(new_buffer +avail - least_mark,
|
||||
sb->_eback,
|
||||
sb->_egptr - sb->_eback);
|
||||
}
|
||||
else
|
||||
memcpy(new_buffer + avail,
|
||||
sb->_eback + least_mark,
|
||||
needed_size);
|
||||
delete [] sb->_other_gbase;
|
||||
sb->_other_gbase = new_buffer;
|
||||
sb->_other_egptr = new_buffer + avail + needed_size;
|
||||
}
|
||||
else {
|
||||
avail = current_Bsize - needed_size;
|
||||
if (least_mark < 0) {
|
||||
memmove(sb->_other_gbase + avail,
|
||||
sb->_other_egptr + least_mark,
|
||||
-least_mark);
|
||||
memcpy(sb->_other_gbase + avail - least_mark,
|
||||
sb->_eback,
|
||||
sb->_egptr - sb->_eback);
|
||||
}
|
||||
else if (needed_size > 0)
|
||||
memcpy(sb->_other_gbase + avail,
|
||||
sb->_eback + least_mark,
|
||||
needed_size);
|
||||
}
|
||||
// FIXME: Dubious arithmetic if pointers are NULL
|
||||
sb->_aux_limit = sb->_other_gbase + avail;
|
||||
// Adjust all the streammarkers.
|
||||
int delta = sb->_egptr - sb->_eback;
|
||||
for (register streammarker *mark = sb->_markers;
|
||||
mark != NULL; mark = mark->_next)
|
||||
mark->_pos -= delta;
|
||||
}
|
||||
else if (sb->have_backup())
|
||||
sb->free_backup_area();
|
||||
return sb->underflow();
|
||||
}
|
||||
|
||||
#ifdef _G_FRIEND_BUG
|
||||
int __overflow(register streambuf *sb, int c) { return __OVERFLOW(sb, c); }
|
||||
int __OVERFLOW(register streambuf *sb, int c)
|
||||
#else
|
||||
int __overflow(streambuf* sb, int c)
|
||||
#endif
|
||||
{
|
||||
return sb->overflow(c);
|
||||
}
|
||||
|
||||
int streambuf::xsputn(register const char* s, int n)
|
||||
{
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
register int more = n;
|
||||
for (;;) {
|
||||
int count = _epptr - _pptr; // Space available.
|
||||
if (count > 0) {
|
||||
if (count > more)
|
||||
count = more;
|
||||
if (count > 20) {
|
||||
memcpy(_pptr, s, count);
|
||||
s += count;
|
||||
_pptr += count;
|
||||
}
|
||||
else if (count <= 0)
|
||||
count = 0;
|
||||
else {
|
||||
register char *p = _pptr;
|
||||
for (register int i = count; --i >= 0; ) *p++ = *s++;
|
||||
_pptr = p;
|
||||
}
|
||||
more -= count;
|
||||
}
|
||||
if (more == 0 || __overflow(this, (unsigned char)*s++) == EOF)
|
||||
break;
|
||||
more--;
|
||||
}
|
||||
return n - more;
|
||||
}
|
||||
|
||||
int streambuf::padn(char pad, int count)
|
||||
{
|
||||
#define PADSIZE 16
|
||||
static char const blanks[PADSIZE] =
|
||||
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
|
||||
static char const zeroes[PADSIZE] =
|
||||
{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
|
||||
char padbuf[PADSIZE];
|
||||
const char *padptr;
|
||||
register int i;
|
||||
|
||||
if (pad == ' ')
|
||||
padptr = blanks;
|
||||
else if (pad == '0')
|
||||
padptr = zeroes;
|
||||
else {
|
||||
for (i = PADSIZE; --i >= 0; ) padbuf[i] = pad;
|
||||
padptr = padbuf;
|
||||
}
|
||||
for (i = count; i >= PADSIZE; i -= PADSIZE)
|
||||
if (sputn(padptr, PADSIZE) != PADSIZE)
|
||||
return EOF;
|
||||
if (i > 0 && sputn(padptr, i) != i)
|
||||
return EOF;
|
||||
return pad;
|
||||
}
|
||||
|
||||
int streambuf::xsgetn(char* s, int n)
|
||||
{
|
||||
register int more = n;
|
||||
for (;;) {
|
||||
int count = _egptr - _gptr; // Data available.
|
||||
if (count > 0) {
|
||||
if (count > more)
|
||||
count = more;
|
||||
if (count > 20) {
|
||||
memcpy(s, _gptr, count);
|
||||
s += count;
|
||||
_gptr += count;
|
||||
}
|
||||
else if (count <= 0)
|
||||
count = 0;
|
||||
else {
|
||||
register char *p = _gptr;
|
||||
for (register int i = count; --i >= 0; ) *s++ = *p++;
|
||||
_gptr = p;
|
||||
}
|
||||
more -= count;
|
||||
}
|
||||
if (more == 0 || __underflow(this) == EOF)
|
||||
break;
|
||||
}
|
||||
return n - more;
|
||||
}
|
||||
|
||||
int streambuf::ignore(int n)
|
||||
{
|
||||
register int more = n;
|
||||
for (;;) {
|
||||
int count = _egptr - _gptr; // Data available.
|
||||
if (count > 0) {
|
||||
if (count > more)
|
||||
count = more;
|
||||
_gptr += count;
|
||||
more -= count;
|
||||
}
|
||||
if (more == 0 || __underflow(this) == EOF)
|
||||
break;
|
||||
}
|
||||
return n - more;
|
||||
}
|
||||
|
||||
int streambuf::sync()
|
||||
{
|
||||
if (gptr() == egptr() && pptr() == pbase())
|
||||
return 0;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
int streambuf::pbackfail(int c)
|
||||
{
|
||||
if (_gptr > _eback)
|
||||
_gptr--;
|
||||
else if (seekoff(-1, ios::cur, ios::in) == EOF)
|
||||
return EOF;
|
||||
if (c != EOF && *_gptr != c)
|
||||
*_gptr = c;
|
||||
return (unsigned char)c;
|
||||
}
|
||||
|
||||
streambuf* streambuf::setbuf(char* p, int len)
|
||||
{
|
||||
if (sync() == EOF)
|
||||
return NULL;
|
||||
if (p == NULL || len == 0) {
|
||||
unbuffered(1);
|
||||
setb(_shortbuf, _shortbuf+1, 0);
|
||||
}
|
||||
else {
|
||||
unbuffered(0);
|
||||
setb(p, p+len, 0);
|
||||
}
|
||||
setp(0, 0);
|
||||
setg(0, 0, 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
streampos streambuf::seekpos(streampos pos, int mode)
|
||||
{
|
||||
return seekoff(pos, ios::beg, mode);
|
||||
}
|
||||
|
||||
void streambuf::setb(char* b, char* eb, int a)
|
||||
{
|
||||
if (_base && !(_flags & _S_USER_BUF))
|
||||
FREE_BUF(_base);
|
||||
_base = b;
|
||||
_ebuf = eb;
|
||||
if (a)
|
||||
_flags &= ~_S_USER_BUF;
|
||||
else
|
||||
_flags |= _S_USER_BUF;
|
||||
}
|
||||
|
||||
int streambuf::doallocate()
|
||||
{
|
||||
char *buf = ALLOC_BUF(_G_BUFSIZ);
|
||||
if (buf == NULL)
|
||||
return EOF;
|
||||
setb(buf, buf+_G_BUFSIZ, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void streambuf::doallocbuf()
|
||||
{
|
||||
if (base() || (!unbuffered() && doallocate() != EOF)) return;
|
||||
setb(_shortbuf, _shortbuf+1, 0);
|
||||
}
|
||||
|
||||
streambuf::streambuf(int flags)
|
||||
{
|
||||
_flags = _IO_MAGIC|flags;
|
||||
_base = NULL;
|
||||
_ebuf = NULL;
|
||||
_eback = NULL;
|
||||
_gptr = NULL;
|
||||
_egptr = NULL;
|
||||
_pbase = NULL;
|
||||
_pptr = NULL;
|
||||
_epptr = NULL;
|
||||
_chain = NULL; // Not necessary.
|
||||
|
||||
_other_gbase = NULL;
|
||||
_aux_limit = NULL;
|
||||
_other_egptr = NULL;
|
||||
_markers = NULL;
|
||||
_cur_column = 0;
|
||||
}
|
||||
|
||||
streambuf::~streambuf()
|
||||
{
|
||||
if (_base && !(_flags & _S_USER_BUF))
|
||||
FREE_BUF(_base);
|
||||
|
||||
for (register streammarker *mark = _markers;
|
||||
mark != NULL; mark = mark->_next)
|
||||
mark->_sbuf = NULL;
|
||||
|
||||
}
|
||||
|
||||
streampos
|
||||
streambuf::seekoff(streamoff, _seek_dir, int mode /*=ios::in|ios::out*/)
|
||||
{
|
||||
return EOF;
|
||||
}
|
||||
|
||||
int streambuf::sputbackc(char c)
|
||||
{
|
||||
if (_gptr > _eback && (unsigned char)_gptr[-1] == (unsigned char)c) {
|
||||
_gptr--;
|
||||
return (unsigned char)c;
|
||||
}
|
||||
return pbackfail(c);
|
||||
}
|
||||
|
||||
int streambuf::sungetc()
|
||||
{
|
||||
if (_gptr > _eback) {
|
||||
_gptr--;
|
||||
return (unsigned char)*_gptr;
|
||||
}
|
||||
else
|
||||
return pbackfail(EOF);
|
||||
}
|
||||
|
||||
#if 0 /* Work in progress */
|
||||
void streambuf::collumn(int c)
|
||||
{
|
||||
if (c == -1)
|
||||
_collumn = -1;
|
||||
else
|
||||
_collumn = c - (_pptr - _pbase);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int streambuf::get_column()
|
||||
{
|
||||
if (_cur_column)
|
||||
return __adjust_column(_cur_column - 1, pbase(), pptr() - pbase());
|
||||
return -1;
|
||||
}
|
||||
|
||||
int streambuf::set_column(int i)
|
||||
{
|
||||
_cur_column = i+1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int streambuf::flush_all()
|
||||
{
|
||||
int result = 0;
|
||||
for (streambuf *sb = _list_all; sb != NULL; sb = sb->xchain())
|
||||
if (sb->overflow(EOF) == EOF)
|
||||
result = EOF;
|
||||
return result;
|
||||
}
|
||||
|
||||
void streambuf::flush_all_linebuffered()
|
||||
{
|
||||
for (streambuf *sb = _list_all; sb != NULL; sb = sb->xchain())
|
||||
if (sb->linebuffered())
|
||||
sb->overflow(EOF);
|
||||
}
|
||||
|
||||
int backupbuf::underflow()
|
||||
{
|
||||
return EOF;
|
||||
}
|
||||
|
||||
int backupbuf::overflow(int c)
|
||||
{
|
||||
return EOF;
|
||||
}
|
||||
|
||||
streammarker::streammarker(streambuf *sb)
|
||||
{
|
||||
_sbuf = sb;
|
||||
if (!(sb->xflags() & _S_IS_BACKUPBUF)) {
|
||||
set_streampos(sb->seekoff(0, ios::cur, ios::in));
|
||||
_next = 0;
|
||||
}
|
||||
else {
|
||||
if (sb->put_mode())
|
||||
sb->switch_to_get_mode();
|
||||
if (((backupbuf*)sb)->in_backup())
|
||||
set_offset(sb->_gptr - sb->_egptr);
|
||||
else
|
||||
set_offset(sb->_gptr - sb->_eback);
|
||||
|
||||
// Should perhaps sort the chain?
|
||||
_next = ((backupbuf*)sb)->_markers;
|
||||
((backupbuf*)sb)->_markers = this;
|
||||
}
|
||||
}
|
||||
|
||||
streammarker::~streammarker()
|
||||
{
|
||||
if (saving()) {
|
||||
// Unlink from sb's chain.
|
||||
register streammarker **ptr = &((backupbuf*)_sbuf)->_markers;
|
||||
for (; ; ptr = &(*ptr)->_next)
|
||||
if (*ptr == NULL)
|
||||
break;
|
||||
else if (*ptr == this) {
|
||||
*ptr = _next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
if _sbuf has a backup area that is no longer needed, should we delete
|
||||
it now, or wait until underflow()?
|
||||
#endif
|
||||
}
|
||||
|
||||
#define BAD_DELTA EOF
|
||||
|
||||
int streammarker::delta(streammarker& other_mark)
|
||||
{
|
||||
if (_sbuf != other_mark._sbuf)
|
||||
return BAD_DELTA;
|
||||
if (saving() && other_mark.saving())
|
||||
return _pos - other_mark._pos;
|
||||
else if (!saving() && !other_mark.saving())
|
||||
return _spos - other_mark._spos;
|
||||
else
|
||||
return BAD_DELTA;
|
||||
}
|
||||
|
||||
int streammarker::delta()
|
||||
{
|
||||
if (_sbuf == NULL)
|
||||
return BAD_DELTA;
|
||||
if (saving()) {
|
||||
int cur_pos;
|
||||
if (_sbuf->in_backup())
|
||||
cur_pos = _sbuf->_gptr - _sbuf->_egptr;
|
||||
else
|
||||
cur_pos = _sbuf->_gptr - _sbuf->_eback;
|
||||
return _pos - cur_pos;
|
||||
}
|
||||
else {
|
||||
if (_spos == EOF)
|
||||
return BAD_DELTA;
|
||||
int cur_pos = _sbuf->seekoff(0, ios::cur);
|
||||
if (cur_pos == EOF)
|
||||
return BAD_DELTA;
|
||||
return _pos - cur_pos;
|
||||
}
|
||||
}
|
||||
|
||||
int streambuf::seekmark(streammarker& mark, int delta /* = 0 */)
|
||||
{
|
||||
if (mark._sbuf != this)
|
||||
return EOF;
|
||||
if (!mark.saving()) {
|
||||
return seekpos(mark._spos, ios::in);
|
||||
}
|
||||
else if (mark._pos >= 0) {
|
||||
if (in_backup())
|
||||
switch_to_main_get_area();
|
||||
_gptr = _eback + mark._pos;
|
||||
}
|
||||
else {
|
||||
if (!in_backup())
|
||||
switch_to_backup_area();
|
||||
_gptr = _egptr + mark._pos;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void streambuf::unsave_markers()
|
||||
{
|
||||
register streammarker *mark =_markers;
|
||||
if (_markers) {
|
||||
streampos offset = seekoff(0, ios::cur, ios::in);
|
||||
if (offset != EOF) {
|
||||
offset += eGptr() - Gbase();
|
||||
for ( ; mark != NULL; mark = mark->_next)
|
||||
mark->set_streampos(mark->_pos + offset);
|
||||
}
|
||||
else {
|
||||
for ( ; mark != NULL; mark = mark->_next)
|
||||
mark->set_streampos(EOF);
|
||||
}
|
||||
_markers = 0;
|
||||
}
|
||||
|
||||
free_backup_area();
|
||||
}
|
||||
|
||||
int backupbuf::pbackfail(int c)
|
||||
{
|
||||
if (_gptr <= _eback) {
|
||||
// Need to handle a filebuf in write mode (switch to read mode). FIXME!
|
||||
|
||||
if (have_backup() && !in_backup()) {
|
||||
switch_to_backup_area();
|
||||
}
|
||||
if (!have_backup()) {
|
||||
// No backup buffer: allocate one.
|
||||
// Use short buffer, if unused? (probably not) FIXME
|
||||
int backup_size = 128;
|
||||
_other_gbase = new char [backup_size];
|
||||
_other_egptr = _other_gbase + backup_size;
|
||||
_aux_limit = _other_egptr;
|
||||
switch_to_backup_area();
|
||||
}
|
||||
else if (gptr() <= eback()) {
|
||||
// Increase size of existing backup buffer.
|
||||
size_t new_size;
|
||||
size_t old_size = egptr() - eback();
|
||||
new_size = 2 * old_size;
|
||||
char* new_buf = new char [new_size];
|
||||
memcpy(new_buf+(new_size-old_size), eback(), old_size);
|
||||
delete [] eback();
|
||||
setg(new_buf, new_buf+(new_size-old_size), new_buf+new_size);
|
||||
_aux_limit = _gptr;
|
||||
}
|
||||
}
|
||||
_gptr--;
|
||||
if (c != EOF && *_gptr != c)
|
||||
*_gptr = c;
|
||||
return (unsigned char)*_gptr;
|
||||
}
|
||||
|
||||
unsigned __adjust_column(unsigned start, const char *line, int count)
|
||||
{
|
||||
register const char *ptr = line + count;
|
||||
while (ptr > line)
|
||||
if (*--ptr == '\n')
|
||||
return line + count - ptr - 1;
|
||||
return start + count;
|
||||
}
|
||||
|
||||
int ios::readable() { return !(rdbuf()->_flags & _S_NO_READS); }
|
||||
int ios::writable() { return !(rdbuf()->_flags & _S_NO_WRITES); }
|
||||
int ios::is_open() { return rdbuf()
|
||||
&& (rdbuf()->_flags & _S_NO_READS+_S_NO_WRITES)
|
||||
!= _S_NO_READS+_S_NO_WRITES; }
|
||||
|
||||
#if defined(linux)
|
||||
#define IO_CLEANUP ;
|
||||
#endif
|
||||
|
||||
#ifdef IO_CLEANUP
|
||||
IO_CLEANUP
|
||||
#else
|
||||
struct __io_defs {
|
||||
__io_defs() { }
|
||||
~__io_defs() { streambuf::flush_all(); }
|
||||
};
|
||||
__io_defs io_defs__;
|
||||
#endif
|
@ -1,497 +0,0 @@
|
||||
// This is part of the iostream library, providing -*- C++ -*- input/output.
|
||||
// Copyright (C) 1991 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: streambuf.h,v 1.2 1993/08/02 17:22:41 mycroft Exp $
|
||||
|
||||
#ifndef _STREAMBUF_H
|
||||
#define _STREAMBUF_H
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
|
||||
/* #define _G_IO_THROW */ /* Not implemented: ios::failure */
|
||||
|
||||
#include <_G_config.h>
|
||||
#ifdef _G_NEED_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#ifndef EOF
|
||||
#define EOF (-1)
|
||||
#endif
|
||||
#ifndef NULL
|
||||
#ifdef __GNUC__
|
||||
#define NULL ((void*)0)
|
||||
#else
|
||||
#define NULL (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class ostream; class streambuf; class backupbuf;
|
||||
|
||||
// In case some header files defines these as macros.
|
||||
#undef open
|
||||
#undef close
|
||||
|
||||
#ifdef _G_FRIEND_BUG
|
||||
extern int __UNDERFLOW(streambuf*);
|
||||
extern int __OVERFLOW(streambuf*, int);
|
||||
#endif
|
||||
extern "C" int __underflow(streambuf*);
|
||||
extern "C" int __overflow(streambuf*, int);
|
||||
|
||||
typedef _G_off_t streamoff;
|
||||
typedef _G_off_t streampos; // Should perhaps be _G_fpos_t ?
|
||||
|
||||
typedef unsigned long __fmtflags;
|
||||
typedef unsigned char __iostate;
|
||||
|
||||
struct _ios_fields { // The data members of an ios.
|
||||
streambuf *_strbuf;
|
||||
ostream* _tie;
|
||||
int _width;
|
||||
__fmtflags _flags;
|
||||
_G_wchar_t _fill;
|
||||
__iostate _state;
|
||||
__iostate _exceptions;
|
||||
int _precision;
|
||||
};
|
||||
|
||||
#define _IOS_GOOD 0
|
||||
#define _IOS_EOF 1
|
||||
#define _IOS_FAIL 2
|
||||
#define _IOS_BAD 4
|
||||
|
||||
#define _IOS_INPUT 1
|
||||
#define _IOS_OUTPUT 2
|
||||
#define _IOS_ATEND 4
|
||||
#define _IOS_APPEND 8
|
||||
#define _IOS_TRUNC 16
|
||||
#define _IOS_NOCREATE 32
|
||||
#define _IOS_NOREPLACE 64
|
||||
#define _IOS_BIN 128
|
||||
|
||||
#ifdef _STREAM_COMPAT
|
||||
enum state_value {
|
||||
_good = _IOS_GOOD,
|
||||
_eof = _IOS_EOF,
|
||||
_fail = _IOS_FAIL,
|
||||
_bad = _IOS_BAD };
|
||||
enum open_mode {
|
||||
input = _IOS_INPUT,
|
||||
output = _IOS_OUTPUT,
|
||||
atend = _IOS_ATEND,
|
||||
append = _IOS_APPEND };
|
||||
#endif
|
||||
|
||||
class ios : public _ios_fields {
|
||||
public:
|
||||
typedef __fmtflags fmtflags;
|
||||
typedef int iostate;
|
||||
typedef int openmode;
|
||||
typedef int streamsize;
|
||||
enum io_state {
|
||||
goodbit = _IOS_GOOD,
|
||||
eofbit = _IOS_EOF,
|
||||
failbit = _IOS_FAIL,
|
||||
badbit = _IOS_BAD };
|
||||
enum open_mode {
|
||||
in = _IOS_INPUT,
|
||||
out = _IOS_OUTPUT,
|
||||
ate = _IOS_ATEND,
|
||||
app = _IOS_APPEND,
|
||||
trunc = _IOS_TRUNC,
|
||||
nocreate = _IOS_NOCREATE,
|
||||
noreplace = _IOS_NOREPLACE,
|
||||
bin = _IOS_BIN };
|
||||
enum seek_dir { beg, cur, end};
|
||||
// ANSI: typedef enum seek_dir seekdir; etc
|
||||
enum { skipws=01, left=02, right=04, internal=010,
|
||||
dec=020, oct=040, hex=0100,
|
||||
showbase=0200, showpoint=0400, uppercase=01000, showpos=02000,
|
||||
scientific=04000, fixed=010000, unitbuf=020000, stdio=040000,
|
||||
dont_close=0100000 //Don't delete streambuf on stream destruction
|
||||
};
|
||||
enum { // Masks.
|
||||
basefield=dec+oct+hex,
|
||||
floatfield = scientific+fixed,
|
||||
adjustfield = left+right+internal
|
||||
};
|
||||
|
||||
#ifdef _G_IO_THROW
|
||||
class failure : public xmsg {
|
||||
ios* _stream;
|
||||
public:
|
||||
failure(ios* stream) { _stream = stream; }
|
||||
failure(string cause, ios* stream) { _stream = stream; }
|
||||
ios* rdios() const { return _stream; }
|
||||
};
|
||||
#endif
|
||||
|
||||
ostream* tie() const { return _tie; }
|
||||
ostream* tie(ostream* val) { ostream* save=_tie; _tie=val; return save; }
|
||||
|
||||
// Methods to change the format state.
|
||||
_G_wchar_t fill() const { return (_G_wchar_t)_fill; }
|
||||
_G_wchar_t fill(_G_wchar_t newf)
|
||||
{_G_wchar_t oldf = (_G_wchar_t)_fill; _fill = (char)newf; return oldf;}
|
||||
fmtflags flags() const { return _flags; }
|
||||
fmtflags flags(fmtflags new_val) {
|
||||
fmtflags old_val = _flags; _flags = new_val; return old_val; }
|
||||
int precision() const { return _precision; }
|
||||
int precision(int newp) {
|
||||
unsigned short oldp = _precision; _precision = (unsigned short)newp;
|
||||
return oldp; }
|
||||
fmtflags setf(fmtflags val) {
|
||||
fmtflags oldbits = _flags;
|
||||
_flags |= val; return oldbits; }
|
||||
fmtflags setf(fmtflags val, fmtflags mask) {
|
||||
fmtflags oldbits = _flags;
|
||||
_flags = (_flags & ~mask) | (val & mask); return oldbits; }
|
||||
fmtflags unsetf(fmtflags mask) {
|
||||
fmtflags oldbits = _flags & mask;
|
||||
_flags &= ~mask; return oldbits; }
|
||||
int width() const { return _width; }
|
||||
int width(int val) { int save = _width; _width = val; return save; }
|
||||
|
||||
#ifdef _G_IO_THROW
|
||||
void _throw_failure() { throw new ios::failure(this); }
|
||||
#else
|
||||
void _throw_failure() { }
|
||||
#endif
|
||||
|
||||
streambuf* rdbuf() const { return _strbuf; }
|
||||
void clear(iostate state = 0) {
|
||||
_state = _strbuf ? state : state|badbit;
|
||||
if (_state & _exceptions) _throw_failure(); }
|
||||
void set(iostate flag) { _state |= flag;
|
||||
if (_state & _exceptions) _throw_failure(); }
|
||||
void setstate(iostate flag) { _state |= flag; // ANSI
|
||||
if (_state & _exceptions) _throw_failure(); }
|
||||
int good() const { return _state == 0; }
|
||||
int eof() const { return _state & ios::eofbit; }
|
||||
int fail() const { return _state & (ios::badbit|ios::failbit); }
|
||||
int bad() const { return _state & ios::badbit; }
|
||||
iostate rdstate() const { return _state; }
|
||||
operator void*() const { return fail() ? (void*)0 : (void*)(-1); }
|
||||
int operator!() const { return fail(); }
|
||||
iostate exceptions() const { return _exceptions; }
|
||||
void exceptions(iostate enable) {
|
||||
_exceptions = enable;
|
||||
if (_state & _exceptions) _throw_failure(); }
|
||||
|
||||
static int sync_with_stdio(int on);
|
||||
static void sync_with_stdio() { sync_with_stdio(1); }
|
||||
|
||||
#ifdef _STREAM_COMPAT
|
||||
void unset(state_value flag) { _state &= ~flag; }
|
||||
void close();
|
||||
int is_open();
|
||||
int readable();
|
||||
int writable();
|
||||
#endif
|
||||
|
||||
// Used to initialize standard streams. Not needed in this implementation.
|
||||
class Init {
|
||||
public:
|
||||
Init () { }
|
||||
};
|
||||
|
||||
protected:
|
||||
ios(streambuf* sb = 0, ostream* tie = 0);
|
||||
virtual ~ios();
|
||||
void init(streambuf* sb) { _state=0; _strbuf=sb; }
|
||||
};
|
||||
|
||||
#if __GNUG__==1
|
||||
typedef int _seek_dir;
|
||||
#else
|
||||
typedef ios::seek_dir _seek_dir;
|
||||
#endif
|
||||
|
||||
// Magic numbers and bits for the _flags field.
|
||||
// The magic numbers use the high-order bits of _flags;
|
||||
// the remaining bits are abailable for variable flags.
|
||||
// Note: The magic numbers must all be negative if stdio
|
||||
// emulation is desired.
|
||||
|
||||
#define _IO_MAGIC 0xFBAD0000 /* Magic number */
|
||||
#define _OLD_STDIO_MAGIC 0xFABC0000 /* Emulate old stdio. */
|
||||
#define _IO_MAGIC_MASK 0xFFFF0000
|
||||
#define _S_USER_BUF 1 /* User owns buffer; don't delete it on close. */
|
||||
#define _S_UNBUFFERED 2
|
||||
#define _S_NO_READS 4 /* Reading not allowed */
|
||||
#define _S_NO_WRITES 8 /* Writing not allowd */
|
||||
#define _S_EOF_SEEN 0x10
|
||||
#define _S_ERR_SEEN 0x20
|
||||
#define _S_DELETE_DONT_CLOSE 0x40
|
||||
#define _S_LINKED 0x80 // Set if linked (using _chain) to streambuf::_list_all.
|
||||
#define _S_IN_BACKUP 0x100
|
||||
#define _S_LINE_BUF 0x200
|
||||
#define _S_TIED_PUT_GET 0x400 // Set if put and get pointer logicly tied.
|
||||
#define _S_CURRENTLY_PUTTING 0x800
|
||||
#define _S_IS_APPENDING 0x1000
|
||||
#define _S_IS_BACKUPBUF 0x4000
|
||||
#define _S_IS_FILEBUF 0x8000
|
||||
|
||||
// A streammarker remembers a position in a buffer.
|
||||
// You are guaranteed to be able to seek back to it if it is saving().
|
||||
class streammarker {
|
||||
friend class streambuf;
|
||||
#ifdef _G_FRIEND_BUG
|
||||
friend int __UNDERFLOW(streambuf*);
|
||||
#else
|
||||
friend int __underflow(streambuf*);
|
||||
#endif
|
||||
struct streammarker *_next; // Only if saving()
|
||||
streambuf *_sbuf; // Only valid if saving().
|
||||
streampos _spos; // -2: means that _pos is valid.
|
||||
void set_streampos(streampos sp) { _spos = sp; }
|
||||
void set_offset(int offset) { _pos = offset; _spos = (streampos)(-2); }
|
||||
// If _pos >= 0, it points to _buf->Gbase()+_pos.
|
||||
// if _pos < 0, it points to _buf->eBptr()+_pos.
|
||||
int _pos;
|
||||
public:
|
||||
streammarker(streambuf *sb);
|
||||
~streammarker();
|
||||
int saving() { return _spos == -2; }
|
||||
int delta(streammarker&);
|
||||
int delta();
|
||||
};
|
||||
|
||||
struct __streambuf {
|
||||
// NOTE: If this is changed, also change __FILE in stdio/stdio.h!
|
||||
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
|
||||
char* _gptr; /* Current get pointer */
|
||||
char* _egptr; /* End of get area. */
|
||||
char* _eback; /* Start of putback+get area. */
|
||||
char* _pbase; /* Start of put area. */
|
||||
char* _pptr; /* Current put pointer. */
|
||||
char* _epptr; /* End of put area. */
|
||||
char* _base; /* Start of reserve area. */
|
||||
char* _ebuf; /* End of reserve area. */
|
||||
struct streambuf *_chain;
|
||||
|
||||
// The following fields are used to support backing up and undo.
|
||||
friend class streammarker;
|
||||
char *_other_gbase; // Pointer to start of non-current get area.
|
||||
char *_aux_limit; // Pointer to first valid character of backup area,
|
||||
char *_other_egptr; // Pointer to end of non-current get area.
|
||||
streammarker *_markers;
|
||||
|
||||
#define __HAVE_COLUMN /* temporary */
|
||||
// 1+column number of pbase(); 0 is unknown.
|
||||
unsigned short _cur_column;
|
||||
char _unused;
|
||||
char _shortbuf[1];
|
||||
};
|
||||
|
||||
extern unsigned __adjust_column(unsigned start, const char *line, int count);
|
||||
|
||||
struct streambuf : public __streambuf {
|
||||
friend class ios;
|
||||
friend class istream;
|
||||
friend class ostream;
|
||||
friend class streammarker;
|
||||
#ifdef _G_FRIEND_BUG
|
||||
friend int __UNDERFLOW(streambuf*);
|
||||
#else
|
||||
friend int __underflow(streambuf*);
|
||||
#endif
|
||||
protected:
|
||||
static streambuf* _list_all; /* List of open streambufs. */
|
||||
streambuf*& xchain() { return _chain; }
|
||||
void _un_link();
|
||||
void _link_in();
|
||||
char* gptr() const { return _gptr; }
|
||||
char* pptr() const { return _pptr; }
|
||||
char* egptr() const { return _egptr; }
|
||||
char* epptr() const { return _epptr; }
|
||||
char* pbase() const { return _pbase; }
|
||||
char* eback() const { return _eback; }
|
||||
char* base() const { return _base; }
|
||||
char* ebuf() const { return _ebuf; }
|
||||
int blen() const { return _ebuf - _base; }
|
||||
void xput_char(char c) { *_pptr++ = c; }
|
||||
int xflags() { return _flags; }
|
||||
int xflags(int f) { int fl = _flags; _flags = f; return fl; }
|
||||
void xsetflags(int f) { _flags |= f; }
|
||||
void xsetflags(int f, int mask) { _flags = (_flags & ~mask) | (f & mask); }
|
||||
void gbump(int n) { _gptr += n; }
|
||||
void pbump(int n) { _pptr += n; }
|
||||
void setb(char* b, char* eb, int a=0);
|
||||
void setp(char* p, char* ep) { _pbase=_pptr=p; _epptr=ep; }
|
||||
void setg(char* eb, char* g, char *eg) { _eback=eb; _gptr=g; _egptr=eg; }
|
||||
char *shortbuf() { return _shortbuf; }
|
||||
|
||||
int in_backup() { return _flags & _S_IN_BACKUP; }
|
||||
// The start of the main get area: FIXME: wrong for write-mode filebuf?
|
||||
char *Gbase() { return in_backup() ? _other_gbase : _eback; }
|
||||
// The end of the main get area:
|
||||
char *eGptr() { return in_backup() ? _other_egptr : _egptr; }
|
||||
// The start of the backup area:
|
||||
char *Bbase() { return in_backup() ? _eback : _other_gbase; }
|
||||
char *Bptr() { return _aux_limit; }
|
||||
// The end of the backup area:
|
||||
char *eBptr() { return in_backup() ? _egptr : _other_egptr; }
|
||||
char *Nbase() { return _other_gbase; }
|
||||
char *eNptr() { return _other_egptr; }
|
||||
int have_backup() { return _other_gbase != NULL; }
|
||||
int have_markers() { return _markers != NULL; }
|
||||
int _least_marker();
|
||||
void switch_to_main_get_area();
|
||||
void switch_to_backup_area();
|
||||
void free_backup_area();
|
||||
void unsave_markers(); // Make all streammarkers !saving().
|
||||
int put_mode() { return _flags & _S_CURRENTLY_PUTTING; }
|
||||
int switch_to_get_mode();
|
||||
|
||||
streambuf(int flags=0);
|
||||
public:
|
||||
static int flush_all();
|
||||
static void flush_all_linebuffered(); // Flush all line buffered files.
|
||||
virtual int underflow() = 0; // Leave public for now
|
||||
virtual int overflow(int c = EOF) = 0; // Leave public for now
|
||||
virtual int doallocate();
|
||||
virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
|
||||
virtual streampos seekpos(streampos pos, int mode = ios::in|ios::out);
|
||||
int seekmark(streammarker& mark, int delta = 0);
|
||||
int sputbackc(char c);
|
||||
int sungetc();
|
||||
virtual ~streambuf();
|
||||
int unbuffered() { return _flags & _S_UNBUFFERED ? 1 : 0; }
|
||||
int linebuffered() { return _flags & _S_LINE_BUF ? 1 : 0; }
|
||||
void unbuffered(int i)
|
||||
{ if (i) _flags |= _S_UNBUFFERED; else _flags &= ~_S_UNBUFFERED; }
|
||||
void linebuffered(int i)
|
||||
{ if (i) _flags |= _S_LINE_BUF; else _flags &= ~_S_LINE_BUF; }
|
||||
int allocate() { // For AT&T compatibility
|
||||
if (base() || unbuffered()) return 0;
|
||||
else return doallocate(); }
|
||||
// Allocate a buffer if needed; use _shortbuf if appropriate.
|
||||
void allocbuf() { if (base() == NULL) doallocbuf(); }
|
||||
void doallocbuf();
|
||||
virtual int sync();
|
||||
virtual int pbackfail(int c);
|
||||
virtual streambuf* setbuf(char* p, int len);
|
||||
int in_avail() { return _egptr - _gptr; }
|
||||
int out_waiting() { return _pptr - _pbase; }
|
||||
virtual int xsputn(const char* s, int n);
|
||||
int sputn(const char* s, int n) { return xsputn(s, n); }
|
||||
int padn(char pad, int n); // Emit 'n' copies of 'pad'.
|
||||
virtual int xsgetn(char* s, int n);
|
||||
int sgetn(char* s, int n) { return xsgetn(s, n); }
|
||||
int ignore(int);
|
||||
virtual int get_column();
|
||||
virtual int set_column(int);
|
||||
long sgetline(char* buf, _G_size_t n, char delim, int putback_delim);
|
||||
int sbumpc() {
|
||||
if (_gptr >= _egptr && __underflow(this) == EOF) return EOF;
|
||||
else return *(unsigned char*)_gptr++; }
|
||||
int sgetc() {
|
||||
if (_gptr >= _egptr && __underflow(this) == EOF) return EOF;
|
||||
else return *(unsigned char*)_gptr; }
|
||||
int snextc() {
|
||||
if (_gptr >= _egptr && __underflow(this) == EOF) return EOF;
|
||||
else return _gptr++, sgetc(); }
|
||||
int sputc(int c) {
|
||||
if (_pptr >= _epptr) return __overflow(this, (unsigned char)c);
|
||||
else return *_pptr++ = c, (unsigned char)c; }
|
||||
void stossc() { if (_gptr < _egptr) _gptr++; }
|
||||
int vscan(char const *fmt0, _G_va_list ap, ios* stream = NULL);
|
||||
int scan(char const *fmt0 ...);
|
||||
int vform(char const *fmt0, _G_va_list ap);
|
||||
int form(char const *fmt0 ...);
|
||||
#if 0 /* Work in progress */
|
||||
int collumn(); // Current collumn number (of put pointer). -1 is unknown.
|
||||
void collumn(int c); // Set collumn number of put pointer to c.
|
||||
#endif
|
||||
};
|
||||
|
||||
// A backupbuf is a streambuf with full backup and savepoints on reading.
|
||||
// All standard streambufs in the GNU iostream library are backupbufs.
|
||||
|
||||
// A backupbuf may have two get area:
|
||||
// - The main get area, and (sometimes) the putback area.
|
||||
// Whichever one of these contains the gptr is the current get area;
|
||||
// the other one is the non-current get area.
|
||||
|
||||
class backupbuf : public streambuf {
|
||||
friend class streammarker;
|
||||
protected:
|
||||
backupbuf(int flags=0) : streambuf(flags|_S_IS_BACKUPBUF) { }
|
||||
public:
|
||||
virtual int pbackfail(int c);
|
||||
virtual int underflow();
|
||||
virtual int overflow(int c = EOF);
|
||||
};
|
||||
|
||||
struct __file_fields {
|
||||
short _fileno;
|
||||
int _blksize;
|
||||
_G_off_t _offset;
|
||||
// char* _save_gptr; char* _save_egptr;
|
||||
};
|
||||
|
||||
class filebuf : public backupbuf {
|
||||
protected:
|
||||
struct __file_fields _fb;
|
||||
void init();
|
||||
public:
|
||||
static const int openprot; // Non-ANSI AT&T-ism: Default open protection.
|
||||
filebuf();
|
||||
filebuf(int fd);
|
||||
filebuf(int fd, char* p, int len);
|
||||
~filebuf();
|
||||
filebuf* attach(int fd);
|
||||
filebuf* open(const char *filename, const char *mode);
|
||||
filebuf* open(const char *filename, ios::openmode mode, int prot = 0664);
|
||||
virtual int underflow();
|
||||
virtual int overflow(int c = EOF);
|
||||
int is_open() const { return _fb._fileno >= 0; }
|
||||
int fd() const { return is_open() ? _fb._fileno : EOF; }
|
||||
filebuf* close();
|
||||
virtual int doallocate();
|
||||
virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
|
||||
virtual streambuf* setbuf(char* p, int len);
|
||||
int xsputn(const char* s, int n);
|
||||
int xsgetn(char* s, int n);
|
||||
virtual int sync();
|
||||
protected: // See documentation in filebuf.C.
|
||||
// virtual int pbackfail(int c);
|
||||
int is_reading() { return eback() != egptr(); }
|
||||
char* cur_ptr() { return is_reading() ? gptr() : pptr(); }
|
||||
/* System's idea of pointer */
|
||||
char* file_ptr() { return eGptr(); }
|
||||
int do_write(const char *data, int to_do);
|
||||
int do_flush() { return do_write(_pbase, _pptr-_pbase); }
|
||||
// Low-level operations (Usually invoke system calls.)
|
||||
virtual _G_ssize_t sys_read(char* buf, _G_size_t size);
|
||||
virtual _G_fpos_t sys_seek(_G_fpos_t, _seek_dir);
|
||||
virtual _G_ssize_t sys_write(const void*, long);
|
||||
virtual int sys_stat(void*); // Actually, a (struct stat*)
|
||||
virtual int sys_close();
|
||||
};
|
||||
|
||||
inline ios::ios(streambuf* sb /* = 0 */, ostream* tie_to /* = 0 */) {
|
||||
_state = sb ? ios::goodbit : ios::badbit; _exceptions=0;
|
||||
_strbuf=sb; _tie = tie_to; _width=0; _fill=' ';
|
||||
_flags=ios::skipws|ios::dec; _precision=6; }
|
||||
inline ios::~ios() {
|
||||
if (!(_flags & (unsigned int)ios::dont_close)) delete _strbuf; }
|
||||
|
||||
#endif /* _STREAMBUF_H */
|
@ -1,238 +0,0 @@
|
||||
// This is part of the iostream library, providing input/output for C++.
|
||||
// Copyright (C) 1991 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#endif
|
||||
#include "ioprivate.h"
|
||||
#include <strstream.h>
|
||||
|
||||
static void* default_alloc(_G_size_t size)
|
||||
{
|
||||
return (void*)new char[size];
|
||||
}
|
||||
|
||||
static void default_free(void* ptr)
|
||||
{
|
||||
delete [] (char*)ptr;
|
||||
}
|
||||
|
||||
istrstream::istrstream(const char *cp, int n)
|
||||
{
|
||||
init(new strstreambuf(cp, n));
|
||||
}
|
||||
|
||||
ostrstream::ostrstream()
|
||||
{
|
||||
init(new strstreambuf());
|
||||
}
|
||||
|
||||
strstreambase::strstreambase(char *cp, int n, int mode)
|
||||
{
|
||||
char *pstart;
|
||||
if (mode == ios::app || mode == ios::ate)
|
||||
pstart = cp + strlen(cp);
|
||||
else
|
||||
pstart = cp;
|
||||
init(new strstreambuf(cp, n, pstart));
|
||||
}
|
||||
|
||||
char *strstreambuf::str()
|
||||
{
|
||||
freeze(1);
|
||||
return base();
|
||||
}
|
||||
|
||||
_G_size_t strstreambuf::pcount()
|
||||
{
|
||||
_G_size_t put_len = pptr() - pbase();
|
||||
if (put_len < _len) put_len = _len;
|
||||
return put_len;
|
||||
}
|
||||
|
||||
int strstreambuf::overflow(int c /* = EOF */)
|
||||
{
|
||||
const int flush_only = c == EOF;
|
||||
if (_flags & _S_NO_WRITES)
|
||||
return flush_only ? 0 : EOF;
|
||||
size_t pos = pptr() - pbase();
|
||||
size_t get_pos = gptr() - pbase();
|
||||
if (pos > _len) _len = pos;
|
||||
if (pos >= blen() + flush_only) {
|
||||
char *new_buf;
|
||||
size_t new_size = 2 * blen();
|
||||
if (frozen()) /* not allowed to enlarge */
|
||||
return EOF;
|
||||
new_buf = (char*)(*_allocate_buffer)(new_size);
|
||||
memcpy(new_buf, base(), blen());
|
||||
if (new_buf == NULL) {
|
||||
// __ferror(fp) = 1;
|
||||
return EOF;
|
||||
}
|
||||
#if 0
|
||||
if (lenp == &_len) /* use '\0'-filling */
|
||||
memset(new_buf + pos, 0, blen() - pos);
|
||||
#endif
|
||||
if (_base) {
|
||||
(*_free_buffer)(_base);
|
||||
_base = NULL; // So setb() won't try to delete _base.
|
||||
}
|
||||
setb(new_buf, new_buf + new_size, 1);
|
||||
}
|
||||
|
||||
setp(base(), ebuf());
|
||||
pbump(pos);
|
||||
setg(base(), base() + get_pos, base() + _len);
|
||||
if (!flush_only) {
|
||||
*pptr() = (unsigned char) c;
|
||||
pbump(1);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
int strstreambuf::underflow()
|
||||
{
|
||||
size_t ppos = pptr() - pbase();
|
||||
if (ppos > _len) _len = ppos;
|
||||
setg(base(), gptr(), base() + _len);
|
||||
if (gptr() < egptr())
|
||||
return *gptr();
|
||||
else
|
||||
return EOF;
|
||||
}
|
||||
|
||||
|
||||
void strstreambuf::init_dynamic(_alloc_type alloc, _free_type free,
|
||||
int initial_size)
|
||||
|
||||
{
|
||||
_len = 0;
|
||||
if (initial_size < 16)
|
||||
initial_size = 16;
|
||||
_allocate_buffer = alloc ? alloc : default_alloc;
|
||||
_free_buffer = free ? free : default_free;
|
||||
char * buf = (char*)(*_allocate_buffer)(initial_size);
|
||||
setb(buf, buf + initial_size, 1);
|
||||
setp(buf, buf + initial_size);
|
||||
setg(buf, buf, buf);
|
||||
}
|
||||
|
||||
void strstreambuf::init_static(char *ptr, int size, char *pstart)
|
||||
{
|
||||
if (size == 0)
|
||||
size = strlen(ptr);
|
||||
else if (size < 0) {
|
||||
// If size is negative 'the characters are assumed to
|
||||
// continue indefinitely.' This is kind of messy ...
|
||||
#if 1
|
||||
size = 512;
|
||||
// Try increasing powers of 2, as long as we don't wrap around.
|
||||
// This can lose in pathological cases (ptr near the end
|
||||
// of the address space). A better solution might be to
|
||||
// adjust the size on underflow/overflow. FIXME.
|
||||
int s;
|
||||
for (; s = 2*size, s > 0 && ptr + s > ptr && s < 0x4000000L; )
|
||||
size = s;
|
||||
size = s;
|
||||
#else
|
||||
// The following semi-portable kludge assumes that
|
||||
// sizeof(unsigned long) == sizeof(char*). Hence,
|
||||
// (unsigned long)(-1) should be the largest possible address.
|
||||
unsigned long highest = (unsigned long)(-1);
|
||||
// Pointers are signed on some brain-damaged systems, in
|
||||
// which case we divide by two to get the maximum signed address.
|
||||
if ((char*)highest < ptr)
|
||||
highest >>= 1;
|
||||
size = (char*)highest - ptr;
|
||||
#endif
|
||||
}
|
||||
setb(ptr, ptr+size);
|
||||
if (pstart) {
|
||||
setp(ptr, ebuf());
|
||||
pbump(pstart-ptr);
|
||||
setg(ptr, ptr, pstart);
|
||||
}
|
||||
else {
|
||||
setp(ptr, ptr);
|
||||
setg(ptr, ptr, ebuf());
|
||||
}
|
||||
_len = egptr() - ptr;
|
||||
}
|
||||
|
||||
void strstreambuf::init_static (const char *ptr, int size)
|
||||
{
|
||||
init_static((char*)ptr, size, NULL);
|
||||
xsetflags(_S_NO_WRITES);
|
||||
}
|
||||
|
||||
strstreambuf::~strstreambuf()
|
||||
{
|
||||
if (_base && !(_flags & _S_USER_BUF))
|
||||
(_free_buffer)(_base);
|
||||
_base = NULL;
|
||||
}
|
||||
|
||||
streampos strstreambuf::seekoff(streamoff off, _seek_dir dir,
|
||||
int mode /*=ios::in|ios::out*/)
|
||||
{
|
||||
size_t cur_size = pcount();
|
||||
streampos new_pos = EOF;
|
||||
|
||||
// Move the get pointer, if requested.
|
||||
if (mode & ios::in) {
|
||||
switch (dir) {
|
||||
case ios::end:
|
||||
off += cur_size;
|
||||
break;
|
||||
case ios::cur:
|
||||
off += gptr() - pbase();
|
||||
break;
|
||||
default: /*case ios::beg: */
|
||||
break;
|
||||
}
|
||||
if (off < 0 || (size_t)off > cur_size)
|
||||
return EOF;
|
||||
setg(base(), base() + off, base() + cur_size);
|
||||
new_pos = off;
|
||||
}
|
||||
|
||||
// Move the put pointer, if requested.
|
||||
if (mode & ios::out) {
|
||||
switch (dir) {
|
||||
case ios::end:
|
||||
off += cur_size;
|
||||
break;
|
||||
case ios::cur:
|
||||
off += pptr() - pbase();
|
||||
break;
|
||||
default: /*case ios::beg: */
|
||||
break;
|
||||
}
|
||||
if (off < 0 || (size_t)off > cur_size)
|
||||
return EOF;
|
||||
pbump(base() + off - pptr());
|
||||
new_pos = off;
|
||||
}
|
||||
return new_pos;
|
||||
}
|
||||
|
||||
int strstreambuf::pbackfail(int c)
|
||||
{
|
||||
if ((_flags & _S_NO_WRITES) && c != EOF)
|
||||
return EOF;
|
||||
return backupbuf::pbackfail(c);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
// This is part of the iostream library, providing -*- C++ -*- input/output.
|
||||
// Copyright (C) 1991 Per Bothner.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free
|
||||
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
// $Id: strstream.h,v 1.3 1993/08/02 17:22:42 mycroft Exp $
|
||||
|
||||
#ifndef __STRSTREAM_H
|
||||
#define __STRSTREAM_H
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
#include <iostream.h>
|
||||
|
||||
class strstreambuf : public backupbuf {
|
||||
_G_size_t _len; // The current length is max(_len, _pptr-_pbase).
|
||||
typedef void *(*_alloc_type)(_G_size_t);
|
||||
typedef void (*_free_type)(void*);
|
||||
_alloc_type _allocate_buffer;
|
||||
_free_type _free_buffer;
|
||||
void init_dynamic(_alloc_type alloc, _free_type free,
|
||||
int initial_size = 128);
|
||||
void init_static(char *ptr, int size, char *pstart);
|
||||
void init_static(const char *ptr, int size);
|
||||
protected:
|
||||
int is_static() const { return _allocate_buffer == (_alloc_type)0; }
|
||||
virtual int overflow(int = EOF);
|
||||
virtual int underflow();
|
||||
virtual int pbackfail(int c);
|
||||
public:
|
||||
virtual ~strstreambuf();
|
||||
strstreambuf() { init_dynamic(0, 0); }
|
||||
strstreambuf(int initial_size) { init_dynamic(0, 0, initial_size); }
|
||||
strstreambuf(void *(*alloc)(_G_size_t), void (*free)(void*))
|
||||
{ init_dynamic(alloc, free); }
|
||||
strstreambuf(char *ptr, int size, char *pstart = NULL)
|
||||
{ init_static(ptr, size, pstart); }
|
||||
strstreambuf(unsigned char *ptr, int size, unsigned char *pstart = NULL)
|
||||
{ init_static((char*)ptr, size, (char*)pstart); }
|
||||
strstreambuf(const char *ptr, int size)
|
||||
{ init_static(ptr, size); }
|
||||
strstreambuf(const unsigned char *ptr, int size)
|
||||
{ init_static((const char*)ptr, size); }
|
||||
#ifndef _G_BROKEN_SIGNED_CHAR
|
||||
strstreambuf(signed char *ptr, int size, signed char *pstart = NULL)
|
||||
{ init_static((char*)ptr, size, (char*)pstart); }
|
||||
strstreambuf(const signed char *ptr, int size)
|
||||
{ init_static((const char*)ptr, size); }
|
||||
#endif
|
||||
// Note: frozen() is always true if is_static().
|
||||
int frozen() { return _flags & _S_USER_BUF ? 1 : 0; }
|
||||
void freeze(int n=1)
|
||||
{ if (!is_static())
|
||||
{ if (n) _flags |= _S_USER_BUF; else _flags &= ~_S_USER_BUF; } }
|
||||
_G_size_t pcount();
|
||||
char *str();
|
||||
virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
|
||||
};
|
||||
|
||||
class strstreambase : virtual public ios {
|
||||
public:
|
||||
strstreambuf* rdbuf() { return (strstreambuf*)_strbuf; }
|
||||
protected:
|
||||
strstreambase() { }
|
||||
strstreambase(char *cp, int n, int mode=ios::out);
|
||||
};
|
||||
|
||||
class istrstream : public strstreambase, public istream {
|
||||
public:
|
||||
istrstream(const char*, int=0);
|
||||
};
|
||||
|
||||
class ostrstream : public strstreambase, public ostream {
|
||||
public:
|
||||
ostrstream();
|
||||
ostrstream(char *cp, int n, int mode=ios::out) :strstreambase(cp,n,mode){}
|
||||
_G_size_t pcount() { return ((strstreambuf*)_strbuf)->pcount(); }
|
||||
char *str() { return ((strstreambuf*)_strbuf)->str(); }
|
||||
void freeze(int n = 1) { ((strstreambuf*)_strbuf)->freeze(n); }
|
||||
int frozen() { return ((strstreambuf*)_strbuf)->frozen(); }
|
||||
};
|
||||
|
||||
class strstream : public strstreambase, public iostream {
|
||||
public:
|
||||
strstream() : strstreambase() { init(new strstreambuf()); }
|
||||
strstream(char *cp, int n, int mode=ios::out) :strstreambase(cp,n,mode){}
|
||||
_G_size_t pcount() { return ((strstreambuf*)_strbuf)->pcount(); }
|
||||
char *str() { return ((strstreambuf*)_strbuf)->str(); }
|
||||
void freeze(int n = 1) { ((strstreambuf*)_strbuf)->freeze(n); }
|
||||
int frozen() { return ((strstreambuf*)_strbuf)->frozen(); }
|
||||
};
|
||||
|
||||
#endif /*!__STRSTREAM_H*/
|
Loading…
Reference in New Issue
Block a user