diff options
author | phk <phk@FreeBSD.org> | 1994-08-08 05:52:55 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 1994-08-08 05:52:55 +0000 |
commit | c8beafaf61a7e1bf16aaef28f9112c7705f4f1f1 (patch) | |
tree | 45b379846d17cbe73053d37a6dc47dae07cdc33d /gnu | |
parent | 4c5e434fdaef40513ed9bc2059aa202f7e1b9929 (diff) | |
download | FreeBSD-src-c8beafaf61a7e1bf16aaef28f9112c7705f4f1f1.zip FreeBSD-src-c8beafaf61a7e1bf16aaef28f9112c7705f4f1f1.tar.gz |
I belive this should be makeable under 2.0. There may be outstanding
issues in these areas:
.h's installed
.hP's installed
-lcurses interaction
files needed in ~/legal for copyleft reasons.
Diffstat (limited to 'gnu')
185 files changed, 40372 insertions, 0 deletions
diff --git a/gnu/lib/libg++/Makefile b/gnu/lib/libg++/Makefile new file mode 100644 index 0000000..519c317 --- /dev/null +++ b/gnu/lib/libg++/Makefile @@ -0,0 +1,18 @@ +# +# $FreeBSD$ +# + +SRCS= vasprintf.c strerror.c strsignal.c +SRCS+= filedoalloc.c floatconv.c genops.c fileops.c iovfprintf.c iovfscanf.c ioignore.c iopadn.c iofgetpos.c iofread.c iofscanf.c iofsetpos.c iogetline.c ioprintf.c ioseekoff.c ioseekpos.c outfloat.c strops.c iofclose.c iopopen.c ioungetc.c builtinbuf.cc filebuf.cc fstream.cc indstream.cc isgetline.cc isgetsb.cc isscan.cc ioextend.cc iomanip.cc iostream.cc osform.cc procbuf.cc sbform.cc sbgetline.cc sbscan.cc stdiostream.cc stdstrbufs.cc stdstreams.cc stream.cc streambuf.cc strstream.cc PlotFile.cc SFile.cc parsestream.cc pfstream.cc editbuf.cc ioprims.c iostrerror.c cleanup.c +SRCS+= AllocRing.cc Obstack.cc builtin.cc regex.cc Regex.cc String.cc Intdouble.cc Integer.cc Rational.cc Complex.cc Random.cc BitSet.cc BitString.cc LogNorm.cc SmplHist.cc SmplStat.cc Normal.cc NegExp.cc Weibull.cc Erlang.cc DiscUnif.cc Uniform.cc Poisson.cc HypGeom.cc Geom.cc Binomial.cc RNG.cc ACG.cc MLCG.cc RndInt.cc Fix.cc Fix16.cc Fix24.cc CursesW.cc GetOpt.cc new.cc chr.cc error.cc gcd.cc hash.cc lg.cc fmtq.cc ioob.cc pow.cc sqrt.cc str.cc timer.c math.cc compare.cc bitand.c bitany.c bitblt.c bitclear.c bitcopy.c bitcount.c bitinvert.c bitlcomp.c bitset1.c bitxor.c SLList.cc DLList.cc +LIB= libg++ +NOMAN= noman +CFLAGS+= -nostdinc -I${.CURDIR}/include -I/usr/include +CXXFLAGS+= -fexternal-templates +.PATH: ${.CURDIR}/libiberty ${.CURDIR}/libio ${.CURDIR}/libg++ + +beforeinstall: + @-if [ ! -d ${DESTDIR}/usr/include/g++ ]; then mkdir ${DESTDIR}/usr/include/g++; chown ${BINOWN}.${BINGRP} ${DESTDIR}/usr/include/g++; chmod 755 ${DESTDIR}/usr/include/g++; fi + @(cd include ; for j in *.h; do cmp -s $$j ${DESTDIR}/usr/include/g++/$$j || install -c -o ${BINOWN} -g ${BINGRP} -m 444 $$j ${DESTDIR}/usr/include/$$j; done) + +.include <bsd.lib.mk> diff --git a/gnu/lib/libg++/include/ACG.h b/gnu/lib/libg++/include/ACG.h new file mode 100644 index 0000000..d7101c7 --- /dev/null +++ b/gnu/lib/libg++/include/ACG.h @@ -0,0 +1,68 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _ACG_h +#define _ACG_h 1 + +#include <RNG.h> +#include <math.h> +#ifdef __GNUG__ +#pragma interface +#endif + +// +// Additive number generator. This method is presented in Volume II +// of The Art of Computer Programming by Knuth. I've coded the algorithm +// and have added the extensions by Andres Nowatzyk of CMU to randomize +// the result of algorithm M a bit by using an LCG & a spatial +// permutation table. +// +// The version presented uses the same constants for the LCG that Andres +// uses (chosen by trial & error). The spatial permutation table is +// the same size (it's based on word size). This is for 32-bit words. +// +// The ``auxillary table'' used by the LCG table varies in size, and +// is chosen to be the the smallest power of two which is larger than +// twice the size of the state table. +// + +class ACG : public RNG { + + unsigned long initialSeed; // used to reset generator + int initialTableEntry; + + unsigned long *state; + unsigned long *auxState; + short stateSize; + short auxSize; + unsigned long lcgRecurr; + short j; + short k; + +protected: + +public: + ACG(unsigned long seed = 0, int size = 55); + virtual ~ACG(); + // + // Return a long-words word of random bits + // + virtual unsigned long asLong(); + virtual void reset(); +}; + +#endif diff --git a/gnu/lib/libg++/include/AllocRing.h b/gnu/lib/libg++/include/AllocRing.h new file mode 100644 index 0000000..15dd161 --- /dev/null +++ b/gnu/lib/libg++/include/AllocRing.h @@ -0,0 +1,62 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1989 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. +*/ + + +#ifndef _AllocRing_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _AllocRing_h 1 + + +/* + An AllocRing holds the last n malloc'ed strings, reallocating/reusing + one only when the queue wraps around. It thus guarantees that the + last n allocations are intact. It is useful for things like I/O + formatting where reasonable restrictions may be made about the + number of allowable live allocations before auto-deletion. +*/ + +class AllocRing +{ + + struct AllocQNode + { + void* ptr; + int sz; + }; + + AllocQNode* nodes; + int n; + int current; + + int find(void* p); + +public: + + AllocRing(int max); + ~AllocRing(); + + void* alloc(int size); + int contains(void* ptr); + void clear(); + void free(void* p); +}; + + +#endif diff --git a/gnu/lib/libg++/include/Binomial.h b/gnu/lib/libg++/include/Binomial.h new file mode 100644 index 0000000..f88dfc3 --- /dev/null +++ b/gnu/lib/libg++/include/Binomial.h @@ -0,0 +1,55 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _Binomial_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Binomial_h 1 + +#include <Random.h> + +class Binomial: public Random { +protected: + int pN; + double pU; +public: + Binomial(int n, double u, RNG *gen); + + int n(); + int n(int xn); + + double u(); + double u(int xu); + + virtual double operator()(); + +}; + + +inline Binomial::Binomial(int n, double u, RNG *gen) +: Random(gen){ + pN = n; pU = u; +} + +inline int Binomial::n() { return pN; } +inline int Binomial::n(int xn) { int tmp = pN; pN = xn; return tmp; } + +inline double Binomial::u() { return pU; } +inline double Binomial::u(int xu) { double tmp = pU; pU = xu; return tmp; } + +#endif diff --git a/gnu/lib/libg++/include/BitSet.h b/gnu/lib/libg++/include/BitSet.h new file mode 100644 index 0000000..ca1d96f --- /dev/null +++ b/gnu/lib/libg++/include/BitSet.h @@ -0,0 +1,374 @@ +// 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. +*/ + +#ifndef _BitSet_h +#ifdef __GNUG__ +#pragma interface +#endif + +#define _BitSet_h 1 + +#include <iostream.h> +#include <limits.h> + +#define BITSETBITS (sizeof(short) * CHAR_BIT) + +struct BitSetRep +{ + unsigned short len; // number of shorts in s + unsigned short sz; // allocated slots + unsigned short virt; // virtual 0 or 1 + unsigned short s[1]; // bits start here +}; + +extern BitSetRep* BitSetalloc(BitSetRep*, const unsigned short*, + int, int, int); +extern BitSetRep* BitSetcopy(BitSetRep*, const BitSetRep*); +extern BitSetRep* BitSetresize(BitSetRep*, int); +extern BitSetRep* BitSetop(const BitSetRep*, const BitSetRep*, + BitSetRep*, char); +extern BitSetRep* BitSetcmpl(const BitSetRep*, BitSetRep*); + + +extern BitSetRep _nilBitSetRep; + +class BitSet; + +class BitSetBit +{ +protected: + BitSet* src; + unsigned long pos; + + public: + BitSetBit(BitSet* v, int p); + BitSetBit(const BitSetBit& b); + ~BitSetBit(); + operator int() const; + int operator = (int b); + int operator = (const BitSetBit& b); +}; + +class BitSet +{ +protected: + BitSetRep* rep; + + +public: + +// constructors + BitSet(); + BitSet(const BitSet&); + + ~BitSet(); + + BitSet& operator = (const BitSet& y); + +// equality & subset tests + + friend int operator == (const BitSet& x, const BitSet& y); + friend int operator != (const BitSet& x, const BitSet& y); + friend int operator < (const BitSet& x, const BitSet& y); + friend int operator <= (const BitSet& x, const BitSet& y); + friend int operator > (const BitSet& x, const BitSet& y); + friend int operator >= (const BitSet& x, const BitSet& y); + + +// operations on self + + BitSet& operator |= (const BitSet& y); + BitSet& operator &= (const BitSet& y); + BitSet& operator -= (const BitSet& y); + BitSet& operator ^= (const BitSet& y); + + void complement(); + +// individual bit manipulation + + void set(int pos); + void set(int from, int to); + void set(); // set all + + void clear(int pos); + void clear(int from, int to); + void clear(); // clear all + + void invert(int pos); + void invert(int from, int to); + + int test(int pos) const; + int test(int from, int to) const; + + BitSetBit operator [] (int i); + +// iterators + + int first(int b = 1) const; + int last(int b = 1) const; + + int next(int pos, int b = 1) const; + int prev(int pos, int b = 1) const; + int previous(int pos, int b = 1) const /* Obsolete synonym */ + { return prev(pos, b); } + +// status + + int empty() const; + int virtual_bit() const; + int count(int b = 1) const; + +// convertors & IO + + friend BitSet atoBitSet(const char* s, + char f='0', char t='1', char star='*'); + // BitSettoa is deprecated; do not use in new programs. + friend const char* BitSettoa(const BitSet& x, + char f='0', char t='1', char star='*'); + + friend BitSet shorttoBitSet(unsigned short w); + friend BitSet longtoBitSet(unsigned long w); + + friend ostream& operator << (ostream& s, const BitSet& x); + void printon(ostream& s, + char f='0', char t='1', char star='*') const; + +// procedural versions of operators + + friend void and(const BitSet& x, const BitSet& y, BitSet& r); + friend void or(const BitSet& x, const BitSet& y, BitSet& r); + friend void xor(const BitSet& x, const BitSet& y, BitSet& r); + friend void diff(const BitSet& x, const BitSet& y, BitSet& r); + friend void complement(const BitSet& x, BitSet& r); + +// misc + + void error(const char* msg) const; + int OK() const; +}; + + +typedef BitSet BitSetTmp; + + + BitSet operator | (const BitSet& x, const BitSet& y); + BitSet operator & (const BitSet& x, const BitSet& y); + BitSet operator - (const BitSet& x, const BitSet& y); + BitSet operator ^ (const BitSet& x, const BitSet& y); + + BitSet operator ~ (const BitSet& x); + +// These are inlined regardless of optimization + +inline int BitSet_index(int l) +{ + return (unsigned)(l) / BITSETBITS; +} + +inline int BitSet_pos(int l) +{ + return l & (BITSETBITS - 1); +} + + +inline BitSet::BitSet() : rep(&_nilBitSetRep) {} + +inline BitSet::BitSet(const BitSet& x) :rep(BitSetcopy(0, x.rep)) {} + +inline BitSet::~BitSet() { if (rep != &_nilBitSetRep) delete rep; } + +inline BitSet& BitSet::operator = (const BitSet& y) +{ + rep = BitSetcopy(rep, y.rep); + return *this; +} + +inline int operator != (const BitSet& x, const BitSet& y) { return !(x == y); } + +inline int operator > (const BitSet& x, const BitSet& y) { return y < x; } + +inline int operator >= (const BitSet& x, const BitSet& y) { return y <= x; } + +inline void and(const BitSet& x, const BitSet& y, BitSet& r) +{ + r.rep = BitSetop(x.rep, y.rep, r.rep, '&'); +} + +inline void or(const BitSet& x, const BitSet& y, BitSet& r) +{ + r.rep = BitSetop(x.rep, y.rep, r.rep, '|'); +} + +inline void xor(const BitSet& x, const BitSet& y, BitSet& r) +{ + r.rep = BitSetop(x.rep, y.rep, r.rep, '^'); +} + +inline void diff(const BitSet& x, const BitSet& y, BitSet& r) +{ + r.rep = BitSetop(x.rep, y.rep, r.rep, '-'); +} + +inline void complement(const BitSet& x, BitSet& r) +{ + r.rep = BitSetcmpl(x.rep, r.rep); +} + +#if defined(__GNUG__) && !defined(_G_NO_NRV) + +inline BitSet operator & (const BitSet& x, const BitSet& y) return r +{ + and(x, y, r); +} + +inline BitSet operator | (const BitSet& x, const BitSet& y) return r +{ + or(x, y, r); +} + +inline BitSet operator ^ (const BitSet& x, const BitSet& y) return r +{ + xor(x, y, r); +} + +inline BitSet operator - (const BitSet& x, const BitSet& y) return r +{ + diff(x, y, r); +} + +inline BitSet operator ~ (const BitSet& x) return r +{ + ::complement(x, r); +} + +#else /* NO_NRV */ + +inline BitSet operator & (const BitSet& x, const BitSet& y) +{ + BitSet r; and(x, y, r); return r; +} + +inline BitSet operator | (const BitSet& x, const BitSet& y) +{ + BitSet r; or(x, y, r); return r; +} + +inline BitSet operator ^ (const BitSet& x, const BitSet& y) +{ + BitSet r; xor(x, y, r); return r; +} + +inline BitSet operator - (const BitSet& x, const BitSet& y) +{ + BitSet r; diff(x, y, r); return r; +} + +inline BitSet operator ~ (const BitSet& x) +{ + BitSet r; ::complement(x, r); return r; +} + +#endif + +inline BitSet& BitSet::operator &= (const BitSet& y) +{ + and(*this, y, *this); + return *this; +} + +inline BitSet& BitSet::operator |= (const BitSet& y) +{ + or(*this, y, *this); + return *this; +} + +inline BitSet& BitSet::operator ^= (const BitSet& y) +{ + xor(*this, y, *this); + return *this; +} + +inline BitSet& BitSet::operator -= (const BitSet& y) +{ + diff(*this, y, *this); + return *this; +} + + +inline void BitSet::complement() +{ + ::complement(*this, *this); +} + +inline int BitSet::virtual_bit() const +{ + return rep->virt; +} + +inline int BitSet::first(int b) const +{ + return next(-1, b); +} + +inline int BitSet::test(int p) const +{ + if (p < 0) error("Illegal bit index"); + int index = BitSet_index(p); + return (index >= rep->len)? rep->virt : + ((rep->s[index] & (1 << BitSet_pos(p))) != 0); +} + + +inline void BitSet::set() +{ + rep = BitSetalloc(rep, 0, 0, 1, 0); +} + +inline BitSetBit::BitSetBit(const BitSetBit& b) :src(b.src), pos(b.pos) {} + +inline BitSetBit::BitSetBit(BitSet* v, int p) +{ + src = v; pos = p; +} + +inline BitSetBit::~BitSetBit() {} + +inline BitSetBit::operator int() const +{ + return src->test(pos); +} + +inline int BitSetBit::operator = (int b) +{ + if (b) src->set(pos); else src->clear(pos); return b; +} + +inline int BitSetBit::operator = (const BitSetBit& b) +{ + int i = (int)b; + *this = i; + return i; +} + +inline BitSetBit BitSet::operator [] (int i) +{ + if (i < 0) error("illegal bit index"); + return BitSetBit(this, i); +} + +#endif diff --git a/gnu/lib/libg++/include/BitString.h b/gnu/lib/libg++/include/BitString.h new file mode 100644 index 0000000..b2b92b1 --- /dev/null +++ b/gnu/lib/libg++/include/BitString.h @@ -0,0 +1,761 @@ +// 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. +*/ + +#ifndef _BitString_h +#ifdef __GNUG__ +#pragma interface +#endif + +#define _BitString_h 1 + +#include <stream.h> +#include <limits.h> + +#include <bitprims.h> +#define BITSTRBITS _BS_BITS_PER_WORD + +struct BitStrRep +{ + unsigned int len; // length in bits + unsigned short sz; // allocated slots + _BS_word s[1]; // bits start here +}; + +extern BitStrRep* BStr_alloc(BitStrRep*, const _BS_word*, int, int,int); +extern BitStrRep* BStr_resize(BitStrRep*, int); +extern BitStrRep* BStr_copy(BitStrRep*, const BitStrRep*); +extern BitStrRep* cmpl(const BitStrRep*, BitStrRep*); +extern BitStrRep* and(const BitStrRep*, const BitStrRep*, BitStrRep*); +extern BitStrRep* or(const BitStrRep*, const BitStrRep*, BitStrRep*); +extern BitStrRep* xor(const BitStrRep*, const BitStrRep*, BitStrRep*); +extern BitStrRep* diff(const BitStrRep*, const BitStrRep*, BitStrRep*); +extern BitStrRep* cat(const BitStrRep*, const BitStrRep*, BitStrRep*); +extern BitStrRep* cat(const BitStrRep*, unsigned int, BitStrRep*); +extern BitStrRep* lshift(const BitStrRep*, int, BitStrRep*); + + +class BitString; +class BitPattern; + +class BitStrBit +{ +protected: + BitString& src; + unsigned int pos; + + public: + BitStrBit(BitString& v, int p); + BitStrBit(const BitStrBit& b); + ~BitStrBit(); + operator unsigned int() const; + int operator = (unsigned int b); +}; + +class BitSubString +{ + friend class BitString; + friend class BitPattern; + +protected: + + BitString& S; + unsigned int pos; + unsigned int len; + + BitSubString(BitString& x, int p, int l); + BitSubString(const BitSubString& x); +public: + ~BitSubString(); + + BitSubString& operator = (const BitString&); + BitSubString& operator = (const BitSubString&); + + int length() const; + int empty() const; + + int OK() const; +}; + +class BitString +{ + friend class BitSubString; + friend class BitPattern; +protected: + BitStrRep* rep; + + int search(int, int, const _BS_word*, int, int) const; + int match(int, int, int, const _BS_word*,int,int) const; + BitSubString _substr(int first, int l); + +public: + +// constructors + BitString(); + BitString(const BitString&); + BitString(const BitSubString& y); + + ~BitString(); + + BitString& operator = (unsigned int bit); + BitString& operator = (const BitString& y); + BitString& operator = (const BitSubString& y); + +// equality & subset tests + + friend int operator == (const BitString&, const BitString&); + friend int operator != (const BitString&, const BitString&); + friend int operator < (const BitString&, const BitString&); + friend int operator <= (const BitString&, const BitString&); + friend int operator > (const BitString&, const BitString&); + friend int operator >= (const BitString&, const BitString&); + +// procedural versions of operators + + + friend void and(const BitString&, const BitString&, BitString&); + friend void or(const BitString&, const BitString&, BitString&); + friend void xor(const BitString&, const BitString&, BitString&); + friend void diff(const BitString&, const BitString&, BitString&); + friend void cat(const BitString&, const BitString&, BitString&); + friend void cat(const BitString&, unsigned int, BitString&); + friend void lshift(const BitString&, int, BitString&); + friend void rshift(const BitString&, int, BitString&); + + friend void complement(const BitString&, BitString&); + + friend int lcompare(const BitString&, const BitString&); + +// assignment-based operators +// (constuctive versions decalred inline below + + BitString& operator |= (const BitString&); + BitString& operator &= (const BitString&); + BitString& operator -= (const BitString&); + BitString& operator ^= (const BitString&); + BitString& operator += (const BitString&); + BitString& operator += (unsigned int b); + BitString& operator <<=(int s); + BitString& operator >>=(int s); + + void complement(); + +// individual bit manipulation + + void set(int pos); + void set(int from, int to); + void set(); + + void clear(int pos); + void clear(int from, int to); + void clear(); + + void invert(int pos); + void invert(int from, int to); + + int test(int pos) const; + int test(int from, int to) const; + + void assign(int p, unsigned int bit); + +// indexing + + BitStrBit operator [] (int pos); + +// iterators + + int first(unsigned int bit = 1) const; + int last(unsigned int b = 1) const; + + int next(int pos, unsigned int b = 1) const; + int prev(int pos, unsigned int b = 1) const; + int previous(int pos, unsigned int b = 1) const + { return prev(pos, b); } /* Obsolete synonym */ + +// searching & matching + + int index(unsigned int bit, int startpos = 0) const ; + int index(const BitString&, int startpos = 0) const; + int index(const BitSubString&, int startpos = 0) const; + int index(const BitPattern&, int startpos = 0) const; + + int contains(const BitString&) const; + int contains(const BitSubString&) const; + int contains(const BitPattern&) const; + + int contains(const BitString&, int pos) const; + int contains(const BitSubString&, int pos) const; + int contains(const BitPattern&, int pos) const; + + int matches(const BitString&, int pos = 0) const; + int matches(const BitSubString&, int pos = 0) const; + int matches(const BitPattern&, int pos = 0) const; + +// BitSubString extraction + + BitSubString at(int pos, int len); + BitSubString at(const BitString&, int startpos = 0); + BitSubString at(const BitSubString&, int startpos = 0); + BitSubString at(const BitPattern&, int startpos = 0); + + BitSubString before(int pos); + BitSubString before(const BitString&, int startpos = 0); + BitSubString before(const BitSubString&, int startpos = 0); + BitSubString before(const BitPattern&, int startpos = 0); + + BitSubString after(int pos); + BitSubString after(const BitString&, int startpos = 0); + BitSubString after(const BitSubString&, int startpos = 0); + BitSubString after(const BitPattern&, int startpos = 0); + +// other friends & utilities + + friend BitString common_prefix(const BitString&, const BitString&, + int pos = 0); + friend BitString common_suffix(const BitString&, const BitString&, + int pos = -1); + friend BitString reverse(const BitString&); + + void right_trim(unsigned int bit); + void left_trim(unsigned int bit); + +// status + + int empty() const ; + int count(unsigned int bit = 1) const; + int length() const; + +// convertors & IO + + friend BitString atoBitString(const char* s, char f='0', char t='1'); + // BitStringtoa is deprecated; do not use in new programs! + friend const char* BitStringtoa(const BitString&, char f='0', char t='1'); + void printon(ostream&, char f='0', char t='1') const; + + friend BitString shorttoBitString(unsigned short); + friend BitString longtoBitString(unsigned long); + + friend ostream& operator << (ostream& s, const BitString&); + +// misc + + void error(const char* msg) const; + +// indirect friends + + friend BitPattern atoBitPattern(const char* s, + char f='0',char t='1',char x='X'); + friend const char* BitPatterntoa(const BitPattern& p, + char f='0',char t='1',char x='X'); + int OK() const; +}; + + +class BitPattern +{ +public: + BitString pattern; + BitString mask; + + BitPattern(); + BitPattern(const BitPattern&); + BitPattern(const BitString& p, const BitString& m); + + ~BitPattern(); + + friend const char* BitPatterntoa(const BitPattern& p, + char f/*='0'*/,char t/*='1'*/,char x/*='X'*/); + void printon(ostream&, char f='0',char t='1',char x='X') const; + friend BitPattern atoBitPattern(const char* s, char f,char t, char x); + friend ostream& operator << (ostream& s, const BitPattern&); + + int search(const _BS_word*, int, int) const; + int match(const _BS_word* xs, int, int, int) const; + + int OK() const; +}; + +BitString operator & (const BitString& x, const BitString& y); +BitString operator | (const BitString& x, const BitString& y); +BitString operator ^ (const BitString& x, const BitString& y); +BitString operator << (const BitString& x, int y); +BitString operator >> (const BitString& x, int y); +BitString operator - (const BitString& x, const BitString& y); +BitString operator + (const BitString& x, const BitString& y); +BitString operator + (const BitString& x, unsigned int y); +BitString operator ~ (const BitString& x); +int operator != (const BitString& x, const BitString& y); +int operator>(const BitString& x, const BitString& y); +int operator>=(const BitString& x, const BitString& y); + +extern BitStrRep _nilBitStrRep; +extern BitString _nil_BitString; + +// primitive bit extraction + +// These must be inlined regardless of optimization. + +inline int BitStr_index(int l) { return (unsigned)(l) / BITSTRBITS; } + +inline int BitStr_pos(int l) { return l & (BITSTRBITS - 1); } + + +// constructors & assignment + +inline BitString::BitString() :rep(&_nilBitStrRep) {} + +inline BitString::BitString(const BitString& x) :rep(BStr_copy(0, x.rep)) {} + +inline BitString::BitString(const BitSubString& y) + :rep (BStr_alloc(0, y.S.rep->s, y.pos, y.pos+y.len, y.len)) {} + +inline BitString::~BitString() +{ + if (rep != &_nilBitStrRep) delete rep; +} + +inline BitString shorttoBitString(unsigned short w) +{ + BitString r; + _BS_word ww = w; +#if _BS_BIGENDIAN + abort(); +#endif + r.rep = BStr_alloc(0, &ww, 0, 8 * sizeof(short), 8 * sizeof(short)); + return r; +} + +inline BitString longtoBitString(unsigned long w) +{ + BitString r; +#if 1 + _BS_word u = w; + r.rep = BStr_alloc(0, &u, 0, BITSTRBITS, BITSTRBITS); +#else + unsigned short u[2]; + u[0] = w & ((unsigned short)(~(0))); + u[1] = w >> BITSTRBITS; + r.rep = BStr_alloc(0, &u[0], 0, 2*BITSTRBITS, 2*BITSTRBITS); +#endif + return r; +} + +inline BitString& BitString::operator = (const BitString& y) +{ + rep = BStr_copy(rep, y.rep); + return *this; +} + +inline BitString& BitString::operator = (unsigned int b) +{ + _BS_word bit = b; + rep = BStr_alloc(rep, &bit, 0, 1, 1); + return *this; +} + +inline BitString& BitString::operator=(const BitSubString& y) +{ + rep = BStr_alloc(rep, y.S.rep->s, y.pos, y.pos+y.len, y.len); + return *this; +} + +inline BitSubString::BitSubString(const BitSubString& x) + :S(x.S), pos(x.pos), len(x.len) {} + +inline BitSubString::BitSubString(BitString& x, int p, int l) + : S(x), pos(p), len(l) {} + +inline BitSubString::~BitSubString() {} + +inline BitPattern::BitPattern(const BitString& p, const BitString& m) + :pattern(p), mask(m) {} + +inline BitPattern::BitPattern(const BitPattern& b) + :pattern(b.pattern), mask(b.mask) {} + +inline BitPattern::BitPattern() {} +inline BitPattern::~BitPattern() {} + + +// procedural versions of operators + +inline void and(const BitString& x, const BitString& y, BitString& r) +{ + r.rep = and(x.rep, y.rep, r.rep); +} + +inline void or(const BitString& x, const BitString& y, BitString& r) +{ + r.rep = or(x.rep, y.rep, r.rep); +} + +inline void xor(const BitString& x, const BitString& y, BitString& r) +{ + r.rep = xor(x.rep, y.rep, r.rep); +} + +inline void diff(const BitString& x, const BitString& y, BitString& r) +{ + r.rep = diff(x.rep, y.rep, r.rep); +} + +inline void cat(const BitString& x, const BitString& y, BitString& r) +{ + r.rep = cat(x.rep, y.rep, r.rep); +} + +inline void cat(const BitString& x, unsigned int y, BitString& r) +{ + r.rep = cat(x.rep, y, r.rep); +} + +inline void rshift(const BitString& x, int y, BitString& r) +{ + r.rep = lshift(x.rep, -y, r.rep); +} + +inline void lshift(const BitString& x, int y, BitString& r) +{ + r.rep = lshift(x.rep, y, r.rep); +} + +inline void complement(const BitString& x, BitString& r) +{ + r.rep = cmpl(x.rep, r.rep); +} + +// operators + + +inline BitString& BitString::operator &= (const BitString& y) +{ + and(*this, y, *this); + return *this; +} + + +inline BitString& BitString::operator |= (const BitString& y) +{ + or(*this, y, *this); + return *this; +} + +inline BitString& BitString::operator ^= (const BitString& y) +{ + xor(*this, y, *this); + return *this; +} + +inline BitString& BitString::operator <<= (int y) +{ + lshift(*this, y, *this); + return *this; +} + +inline BitString& BitString::operator >>= (int y) +{ + rshift(*this, y, *this); + return *this; +} + +inline BitString& BitString::operator -= (const BitString& y) +{ + diff(*this, y, *this); + return *this; +} + +inline BitString& BitString::operator += (const BitString& y) +{ + cat(*this, y, *this); + return *this; +} + +inline BitString& BitString::operator += (unsigned int y) +{ + cat(*this, y, *this); + return *this; +} + +inline void BitString::complement() +{ + ::complement(*this, *this); +} + +#if defined(__GNUG__) && !defined(_G_NO_NRV) + +inline BitString operator & (const BitString& x, const BitString& y) return r +{ + and(x, y, r); +} + +inline BitString operator | (const BitString& x, const BitString& y) return r +{ + or(x, y, r); +} + +inline BitString operator ^ (const BitString& x, const BitString& y) return r +{ + xor(x, y, r); +} + +inline BitString operator << (const BitString& x, int y) return r +{ + lshift(x, y, r); +} + +inline BitString operator >> (const BitString& x, int y) return r +{ + rshift(x, y, r); +} + +inline BitString operator - (const BitString& x, const BitString& y) return r +{ + diff(x, y, r); +} + +inline BitString operator + (const BitString& x, const BitString& y) return r +{ + cat(x, y, r); +} + +inline BitString operator + (const BitString& x, unsigned int y) return r +{ + cat(x, y, r); +} + +inline BitString operator ~ (const BitString& x) return r +{ + complement(x, r); +} + +#else /* NO_NRV */ + +inline BitString operator & (const BitString& x, const BitString& y) +{ + BitString r; and(x, y, r); return r; +} + +inline BitString operator | (const BitString& x, const BitString& y) +{ + BitString r; or(x, y, r); return r; +} + +inline BitString operator ^ (const BitString& x, const BitString& y) +{ + BitString r; xor(x, y, r); return r; +} + +inline BitString operator << (const BitString& x, int y) +{ + BitString r; lshift(x, y, r); return r; +} + +inline BitString operator >> (const BitString& x, int y) +{ + BitString r; rshift(x, y, r); return r; +} + +inline BitString operator - (const BitString& x, const BitString& y) +{ + BitString r; diff(x, y, r); return r; +} + +inline BitString operator + (const BitString& x, const BitString& y) +{ + BitString r; cat(x, y, r); return r; +} + +inline BitString operator + (const BitString& x, unsigned int y) +{ + BitString r; cat(x, y, r); return r; +} + +inline BitString operator ~ (const BitString& x) +{ + BitString r; complement(x, r); return r; +} + +#endif + +// status, matching + +inline int BitString::length() const +{ + return rep->len; +} + +inline int BitString::empty() const +{ + return rep->len == 0; +} + +inline int BitString::index(const BitString& y, int startpos) const +{ + return search(startpos, rep->len, y.rep->s, 0, y.rep->len); +} + +inline int BitString::index(const BitSubString& y, int startpos) const +{ + return search(startpos, rep->len, y.S.rep->s, y.pos, y.pos+y.len); +} + +inline int BitString::contains(const BitString& y) const +{ + return search(0, rep->len, y.rep->s, 0, y.rep->len) >= 0; +} + +inline int BitString::contains(const BitSubString& y) const +{ + return search(0, rep->len, y.S.rep->s, y.pos, y.pos+y.len) >= 0; +} + +inline int BitString::contains(const BitString& y, int p) const +{ + return match(p, rep->len, 0, y.rep->s, 0, y.rep->len); +} + +inline int BitString::matches(const BitString& y, int p) const +{ + return match(p, rep->len, 1, y.rep->s, 0, y.rep->len); +} + +inline int BitString::contains(const BitSubString& y, int p) const +{ + return match(p, rep->len, 0, y.S.rep->s, y.pos, y.pos+y.len); +} + +inline int BitString::matches(const BitSubString& y, int p) const +{ + return match(p, rep->len, 1, y.S.rep->s, y.pos, y.pos+y.len); +} + +inline int BitString::contains(const BitPattern& r) const +{ + return r.search(rep->s, 0, rep->len) >= 0; +} + +inline int BitString::contains(const BitPattern& r, int p) const +{ + return r.match(rep->s, p, rep->len, 0); +} + +inline int BitString::matches(const BitPattern& r, int p) const +{ + return r.match(rep->s, p, rep->len, 1); +} + +inline int BitString::index(const BitPattern& r, int startpos) const +{ + return r.search(rep->s, startpos, rep->len); +} + +inline int BitSubString::length() const +{ + return len; +} + +inline int BitSubString::empty() const +{ + return len == 0; +} + +inline int operator != (const BitString& x, const BitString& y) +{ + return !(x == y); +} + +inline int operator>(const BitString& x, const BitString& y) +{ + return y < x; +} + +inline int operator>=(const BitString& x, const BitString& y) +{ + return y <= x; +} + +inline int BitString::first(unsigned int b) const +{ + return next(-1, b); +} + +inline int BitString::last(unsigned int b) const +{ + return prev(rep->len, b); +} + +inline int BitString::index(unsigned int bit, int startpos) const +{ + if (startpos >= 0) + return next(startpos - 1, bit); + else + return prev(rep->len + startpos + 1, bit); +} + +inline void BitString::right_trim(unsigned int b) +{ + int nb = (b == 0)? 1 : 0; + rep = BStr_resize(rep, prev(rep->len, nb) + 1); +} + +inline void BitString::left_trim(unsigned int b) +{ + int nb = (b == 0)? 1 : 0; + int p = next(-1, nb); + rep = BStr_alloc(rep, rep->s, p, rep->len, rep->len - p); +} + +inline int BitString::test(int i) const +{ + return ((unsigned)(i) >= rep->len)? 0 : + ((rep->s[BitStr_index(i)] & (1 << (BitStr_pos(i)))) != 0); +} + + +// subscripting + +inline BitStrBit::BitStrBit(const BitStrBit& b) :src(b.src), pos(b.pos) {} + +inline BitStrBit::BitStrBit(BitString& v, int p) :src(v), pos(p) {} + +inline BitStrBit::~BitStrBit() {} + +inline BitStrBit::operator unsigned int() const +{ + return src.test(pos); +} + +inline int BitStrBit::operator = (unsigned int b) +{ + src.assign(pos, b); return b; +} + +inline BitStrBit BitString::operator [] (int i) +{ + if ((unsigned)(i) >= rep->len) error("illegal bit index"); + return BitStrBit(*this, i); +} + +inline BitSubString BitString::_substr(int first, int l) +{ + if (first < 0 || l <= 0 || (unsigned)(first + l) > rep->len) + return BitSubString(_nil_BitString, 0, 0) ; + else + return BitSubString(*this, first, l); +} + +#endif diff --git a/gnu/lib/libg++/include/Complex.h b/gnu/lib/libg++/include/Complex.h new file mode 100644 index 0000000..385ea606d7 --- /dev/null +++ b/gnu/lib/libg++/include/Complex.h @@ -0,0 +1,276 @@ +// 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. +*/ + +#ifndef _Complex_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Complex_h 1 + + +#include <iostream.h> +#include <math.h> + +class Complex +{ +#ifdef __ATT_complex__ +public: +#else +protected: +#endif + + double re; + double im; + +public: + + double real() const; + double imag() const; + + Complex(); + Complex(const Complex& y); + Complex(double r, double i=0); + + ~Complex(); + + Complex& operator = (const Complex& y); + + Complex& operator += (const Complex& y); + Complex& operator += (double y); + Complex& operator -= (const Complex& y); + Complex& operator -= (double y); + Complex& operator *= (const Complex& y); + Complex& operator *= (double y); + + Complex& operator /= (const Complex& y); + Complex& operator /= (double y); + + void error(const char* msg) const; +}; + + +// non-inline functions + +Complex operator / (const Complex& x, const Complex& y); +Complex operator / (const Complex& x, double y); +Complex operator / (double x, const Complex& y); + +Complex cos(const Complex& x); +Complex sin(const Complex& x); + +Complex cosh(const Complex& x); +Complex sinh(const Complex& x); + +Complex exp(const Complex& x); +Complex log(const Complex& x); + +Complex pow(const Complex& x, int p); +Complex pow(const Complex& x, const Complex& p); +Complex pow(const Complex& x, double y); +Complex sqrt(const Complex& x); + +istream& operator >> (istream& s, Complex& x); +ostream& operator << (ostream& s, const Complex& x); + +// other functions defined as inlines + +int operator == (const Complex& x, const Complex& y); +int operator == (const Complex& x, double y); +int operator != (const Complex& x, const Complex& y); +int operator != (const Complex& x, double y); + +Complex operator - (const Complex& x); +Complex conj(const Complex& x); +Complex operator + (const Complex& x, const Complex& y); +Complex operator + (const Complex& x, double y); +Complex operator + (double x, const Complex& y); +Complex operator - (const Complex& x, const Complex& y); +Complex operator - (const Complex& x, double y); +Complex operator - (double x, const Complex& y); +Complex operator * (const Complex& x, const Complex& y); +Complex operator * (const Complex& x, double y); +Complex operator * (double x, const Complex& y); + +double real(const Complex& x); +double imag(const Complex& x); +double abs(const Complex& x); +double norm(const Complex& x); +double arg(const Complex& x); + +Complex polar(double r, double t = 0.0); + + +// inline members + +inline double Complex::real() const { return re; } +inline double Complex::imag() const { return im; } + +inline Complex::Complex() {} +inline Complex::Complex(const Complex& y) :re(y.real()), im(y.imag()) {} +inline Complex::Complex(double r, double i) :re(r), im(i) {} + +inline Complex::~Complex() {} + +inline Complex& Complex::operator = (const Complex& y) +{ + re = y.real(); im = y.imag(); return *this; +} + +inline Complex& Complex::operator += (const Complex& y) +{ + re += y.real(); im += y.imag(); return *this; +} + +inline Complex& Complex::operator += (double y) +{ + re += y; return *this; +} + +inline Complex& Complex::operator -= (const Complex& y) +{ + re -= y.real(); im -= y.imag(); return *this; +} + +inline Complex& Complex::operator -= (double y) +{ + re -= y; return *this; +} + +inline Complex& Complex::operator *= (const Complex& y) +{ + double r = re * y.real() - im * y.imag(); + im = re * y.imag() + im * y.real(); + re = r; + return *this; +} + +inline Complex& Complex::operator *= (double y) +{ + re *= y; im *= y; return *this; +} + + +// functions + +inline int operator == (const Complex& x, const Complex& y) +{ + return x.real() == y.real() && x.imag() == y.imag(); +} + +inline int operator == (const Complex& x, double y) +{ + return x.imag() == 0.0 && x.real() == y; +} + +inline int operator != (const Complex& x, const Complex& y) +{ + return x.real() != y.real() || x.imag() != y.imag(); +} + +inline int operator != (const Complex& x, double y) +{ + return x.imag() != 0.0 || x.real() != y; +} + +inline Complex operator - (const Complex& x) +{ + return Complex(-x.real(), -x.imag()); +} + +inline Complex conj(const Complex& x) +{ + return Complex(x.real(), -x.imag()); +} + +inline Complex operator + (const Complex& x, const Complex& y) +{ + return Complex(x.real() + y.real(), x.imag() + y.imag()); +} + +inline Complex operator + (const Complex& x, double y) +{ + return Complex(x.real() + y, x.imag()); +} + +inline Complex operator + (double x, const Complex& y) +{ + return Complex(x + y.real(), y.imag()); +} + +inline Complex operator - (const Complex& x, const Complex& y) +{ + return Complex(x.real() - y.real(), x.imag() - y.imag()); +} + +inline Complex operator - (const Complex& x, double y) +{ + return Complex(x.real() - y, x.imag()); +} + +inline Complex operator - (double x, const Complex& y) +{ + return Complex(x - y.real(), -y.imag()); +} + +inline Complex operator * (const Complex& x, const Complex& y) +{ + return Complex(x.real() * y.real() - x.imag() * y.imag(), + x.real() * y.imag() + x.imag() * y.real()); +} + +inline Complex operator * (const Complex& x, double y) +{ + return Complex(x.real() * y, x.imag() * y); +} + +inline Complex operator * (double x, const Complex& y) +{ + return Complex(x * y.real(), x * y.imag()); +} + +inline double real(const Complex& x) +{ + return x.real(); +} + +inline double imag(const Complex& x) +{ + return x.imag(); +} + +inline double abs(const Complex& x) +{ + return hypot(x.real(), x.imag()); +} + +inline double norm(const Complex& x) +{ + return (x.real() * x.real() + x.imag() * x.imag()); +} + +inline double arg(const Complex& x) +{ + return atan2(x.imag(), x.real()); +} + +inline Complex polar(double r, double t) +{ + return Complex(r * cos(t), r * sin(t)); +} + +#endif diff --git a/gnu/lib/libg++/include/CursesW.h b/gnu/lib/libg++/include/CursesW.h new file mode 100644 index 0000000..4f367fd --- /dev/null +++ b/gnu/lib/libg++/include/CursesW.h @@ -0,0 +1,590 @@ +// This may look like C code, but it is really -*- C++ -*- + +/* +Copyright (C) 1989 Free Software Foundation + written by Eric Newton (newton@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. +*/ + +#ifndef _CursesWindow_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _CursesWindow_h + +#include <_G_config.h> +#if _G_HAVE_CURSES +#include <curses.h> + +/* SCO 3.2v4 curses.h includes term.h, which defines lines as a macro. + Undefine it here, because CursesWindow uses lines as a method. */ +#undef lines + +// "Convert" macros to inlines, if needed. +#ifdef addch +inline int (addch)(char ch) { return addch(ch); } +#undef addch +#endif +#ifdef addstr +/* The (char*) cast is to hack around missing const's */ +inline int (addstr)(const char * str) { return addstr((char*)str); } +#undef addstr +#endif +#ifdef clear +inline int (clear)() { return clear(); } +#undef clear +#endif +#ifdef clearok +inline int (clearok)(WINDOW* win, int bf) { return clearok(win, bf); } +#undef clearok +#else +extern "C" int clearok(WINDOW*, int); +#endif +#ifdef clrtobot +inline int (clrtobot)() { return clrtobot(); } +#undef clrtobot +#endif +#ifdef clrtoeol +inline int (clrtoeol)() { return clrtoeol(); } +#undef clrtoeol +#endif +#ifdef delch +inline int (delch)() { return delch(); } +#undef delch +#endif +#ifdef deleteln +inline int (deleteln)() { return deleteln(); } +#undef deleteln +#endif +#ifdef erase +inline int (erase)() { return erase(); } +#undef erase +#endif +#ifdef flushok +inline int (flushok)(WINDOW* _win, int _bf) { return flushok(_win, _bf); } +#undef flushok +#else +#define _no_flushok +#endif +#ifdef getch +inline int (getch)() { return getch(); } +#undef getch +#endif +#ifdef getstr +inline int (getstr)(char *_str) { return getstr(_str); } +#undef getstr +#endif +#ifdef getyx +inline void (getyx)(WINDOW* win, int& y, int& x) { getyx(win, y, x); } +#undef getyx +#endif +#ifdef inch +inline int (inch)() { return inch(); } +#undef inch +#endif +#ifdef insch +inline int (insch)(char c) { return insch(c); } +#undef insch +#endif +#ifdef insertln +inline int (insertln)() { return insertln(); } +#undef insertln +#endif +#ifdef leaveok +inline int (leaveok)(WINDOW* win, int bf) { return leaveok(win, bf); } +#undef leaveok +#else +extern "C" int leaveok(WINDOW* win, int bf); +#endif +#ifdef move +inline int (move)(int x, int y) { return move(x, y); } +#undef move +#endif +#ifdef refresh +inline int (rfresh)() { return refresh(); } +#undef refresh +#endif +#ifdef scrollok +inline int (scrollok)(WINDOW* win, int bf) { return scrollok(win, bf); } +#undef scrollok +#else +#ifndef hpux +extern "C" int scrollok(WINDOW*, int); +#else +extern "C" int scrollok(WINDOW*, char); +#endif +#endif +#ifdef standend +inline int (standend)() { return standend(); } +#undef standend +#endif +#ifdef standout +inline int (standout)() { return standout(); } +#undef standout +#endif +#ifdef wstandend +inline int (wstandend)(WINDOW *win) { return wstandend(win); } +#undef wstandend +#endif +#ifdef wstandout +inline int (wstandout)(WINDOW *win) { return wstandout(win); } +#undef wstandout +#endif +#ifdef winch +inline int (winch)(WINDOW* win) { return winch(win); } +#undef winch +#endif + +/* deal with conflicting macros in ncurses.h which is SYSV based*/ +#ifdef box +inline (box)(WINDOW* win, chtype v, chtype h) {return box(win, v, h); } +#undef box +#endif +#ifdef scroll +inline (scroll)(WINDOW* win) { return scroll(win); } +#undef scroll +#endif +#ifdef touchwin +inline (touchwin)(WINDOW* win) { return touchwin(win); } +#undef touchwin +#endif + +#ifdef mvwaddch +inline int (mvwaddch)(WINDOW *win, int y, int x, char ch) +{ return mvwaddch(win, y, x, ch); } +#undef mvwaddch +#endif +#ifdef mvwaddstr +inline int (mvwaddstr)(WINDOW *win, int y, int x, const char * str) +{ return mvwaddstr(win, y, x, (char*)str); } +#undef mvwaddstr +#endif +#ifdef mvwdelch +inline int (mvwdelch)(WINDOW *win, int y, int x) { return mvwdelch(win, y, x);} +#undef mvwdelch +#endif +#ifdef mvwgetch +inline int (mvwgetch)(WINDOW *win, int y, int x) { return mvwgetch(win, y, x);} +#undef mvwgetch +#endif +#ifdef mvwgetstr +inline int (mvwgetstr)(WINDOW *win, int y, int x, char *str) +{return mvwgetstr(win,y,x, str);} +#undef mvwgetstr +#endif +#ifdef mvwinch +inline int (mvwinch)(WINDOW *win, int y, int x) { return mvwinch(win, y, x);} +#undef mvwinch +#endif +#ifdef mvwinsch +inline int (mvwinsch)(WINDOW *win, int y, int x, char c) +{ return mvwinsch(win, y, x, c); } +#undef mvwinsch +#endif + +#ifdef mvaddch +inline int (mvaddch)(int y, int x, char ch) +{ return mvaddch(y, x, ch); } +#undef mvaddch +#endif +#ifdef mvaddstr +inline int (mvaddstr)(int y, int x, const char * str) +{ return mvaddstr(y, x, (char*)str); } +#undef mvaddstr +#endif +#ifdef mvdelch +inline int (mvdelch)(int y, int x) { return mvdelch(y, x);} +#undef mvdelch +#endif +#ifdef mvgetch +inline int (mvgetch)(int y, int x) { return mvgetch(y, x);} +#undef mvgetch +#endif +#ifdef mvgetstr +inline int (mvgetstr)(int y, int x, char *str) {return mvgetstr(y, x, str);} +#undef mvgetstr +#endif +#ifdef mvinch +inline int (mvinch)(int y, int x) { return mvinch(y, x);} +#undef mvinch +#endif +#ifdef mvinsch +inline int (mvinsch)(int y, int x, char c) +{ return mvinsch(y, x, c); } +#undef mvinsch +#endif + +/* + * + * C++ class for windows. + * + * + */ + +class CursesWindow +{ +protected: + static int count; // count of all active windows: + // We rely on the c++ promise that + // all otherwise uninitialized + // static class vars are set to 0 + + WINDOW * w; // the curses WINDOW + + int alloced; // true if we own the WINDOW + + CursesWindow* par; // parent, if subwindow + CursesWindow* subwins; // head of subwindows list + CursesWindow* sib; // next subwindow of parent + + void kill_subwindows(); // disable all subwindows + +public: + CursesWindow(WINDOW* &window); // useful only for stdscr + + CursesWindow(int lines, // number of lines + int cols, // number of columns + int begin_y, // line origin + int begin_x); // col origin + + CursesWindow(CursesWindow& par, // parent window + int lines, // number of lines + int cols, // number of columns + int by, // absolute or relative + int bx, // origins: + char absrel = 'a'); // if `a', by & bx are + // absolute screen pos, + // else if `r', they are + // relative to par origin + ~CursesWindow(); + +// terminal status + int lines(); // number of lines on terminal, *not* window + int cols(); // number of cols on terminal, *not* window + +// window status + int height(); // number of lines in this window + int width(); // number of cols in this window + int begx(); // smallest x coord in window + int begy(); // smallest y coord in window + int maxx(); // largest x coord in window + int maxy(); // largest x coord in window + +// window positioning + int move(int y, int x); + +// coordinate positioning + void getyx(int& y, int& x); + int mvcur(int sy, int ey, int sx, int ex); + +// input + int getch(); + int getstr(char * str); + int scanw(const char *, ...); + +// input + positioning + int mvgetch(int y, int x); + int mvgetstr(int y, int x, char * str); + int mvscanw(int, int, const char*, ...); + +// output + int addch(const char ch); + int addstr(const char * str); + int printw(const char * fmt, ...); + int inch(); + int insch(char c); + int insertln(); + +// output + positioning + int mvaddch(int y, int x, char ch); + int mvaddstr(int y, int x, const char * str); + int mvprintw(int y, int x, const char * fmt, ...); + int mvinch(int y, int x); + int mvinsch(int y, int x, char ch); + +// borders + int box(char vert, char hor); + +// erasure + int erase(); + int clear(); + int clearok(int bf); + int clrtobot(); + int clrtoeol(); + int delch(); + int mvdelch(int y, int x); + int deleteln(); + +// screen control + int scroll(); + int scrollok(int bf); + int touchwin(); + int refresh(); + int leaveok(int bf); +#ifndef _no_flushok + int flushok(int bf); +#endif + int standout(); + int standend(); + +// multiple window control + int overlay(CursesWindow &win); + int overwrite(CursesWindow &win); + + +// traversal support + CursesWindow* child(); + CursesWindow* sibling(); + CursesWindow* parent(); +}; + + +inline int CursesWindow::begx() +{ + return w->_begx; +} + +inline int CursesWindow::begy() +{ + return w->_begy; +} + +inline int CursesWindow::maxx() +{ + return w->_maxx; +} + +inline int CursesWindow::maxy() +{ + return w->_maxy; +} + +inline int CursesWindow::height() +{ + return maxy() - begy() + 1; +} + +inline int CursesWindow::width() +{ + return maxx() - begx() + 1; +} + +inline int CursesWindow::box(char vert, char hor) +{ + return ::box(w, vert, hor); +} + +inline int CursesWindow::overlay(CursesWindow &win) +{ + return ::overlay(w, win.w); +} + +inline int CursesWindow::overwrite(CursesWindow &win) +{ + return ::overwrite(w, win.w); +} + +inline int CursesWindow::scroll() +{ + return ::scroll(w); +} + + +inline int CursesWindow::touchwin() +{ + return ::touchwin(w); +} + +inline int CursesWindow::addch(const char ch) +{ + return ::waddch(w, ch); +} + +inline int CursesWindow::addstr(const char * str) +{ + // The (char*) cast is to hack around prototypes in curses.h that + // have const missing in the parameter lists. [E.g. SVR4] + return ::waddstr(w, (char*)str); +} + +inline int CursesWindow::clear() +{ + return ::wclear(w); +} + +inline int CursesWindow::clrtobot() +{ + return ::wclrtobot(w); +} + +inline int CursesWindow::clrtoeol() +{ + return ::wclrtoeol(w); +} + +inline int CursesWindow::delch() +{ + return ::wdelch(w); +} + +inline int CursesWindow::deleteln() +{ + return ::wdeleteln(w); +} + +inline int CursesWindow::erase() +{ + return ::werase(w); +} + +inline int CursesWindow::getch() +{ + return ::wgetch(w); +} + +inline int CursesWindow::getstr(char * str) +{ + return ::wgetstr(w, str); +} + +inline int CursesWindow::inch() +{ + return winch(w); +} + +inline int CursesWindow::insch(char c) +{ + return ::winsch(w, c); +} + +inline int CursesWindow::insertln() +{ + return ::winsertln(w); +} + +inline int CursesWindow::move(int y, int x) +{ + return ::wmove(w, y, x); +} + + +inline int CursesWindow::mvcur(int sy, int ey, int sx, int ex) +{ + return ::mvcur(sy, ey, sx,ex); +} + +inline int CursesWindow::mvaddch(int y, int x, char ch) +{ + return (::wmove(w, y, x)==ERR) ? ERR : ::waddch(w, ch); +} + +inline int CursesWindow::mvgetch(int y, int x) +{ + return (::wmove(w, y, x)==ERR) ? ERR : ::wgetch(w); +} + +inline int CursesWindow::mvaddstr(int y, int x, const char * str) +{ + return (::wmove(w, y, x)==ERR) ? ERR : ::waddstr(w, (char*)str); +} + +inline int CursesWindow::mvgetstr(int y, int x, char * str) +{ + return (::wmove(w, y, x)==ERR) ? ERR : ::wgetstr(w, str); +} + +inline int CursesWindow::mvinch(int y, int x) +{ + return (::wmove(w, y, x)==ERR) ? ERR : ::winch(w); +} + +inline int CursesWindow::mvdelch(int y, int x) +{ + return (::wmove(w, y, x)==ERR) ? ERR : ::wdelch(w); +} + +inline int CursesWindow::mvinsch(int y, int x, char ch) +{ + return (::wmove(w, y, x)==ERR) ? ERR : ::winsch(w, ch); +} + +inline int CursesWindow::refresh() +{ + return ::wrefresh(w); +} + +inline int CursesWindow::clearok(int bf) +{ + return ::clearok(w,bf); +} + +inline int CursesWindow::leaveok(int bf) +{ + return ::leaveok(w,bf); +} + +inline int CursesWindow::scrollok(int bf) +{ + return ::scrollok(w,bf); +} + +#ifndef _no_flushok +inline int CursesWindow::flushok(int bf) +{ + return ::flushok(w, bf); +} +#endif + +inline void CursesWindow::getyx(int& y, int& x) +{ + ::getyx(w, y, x); +} + +inline int CursesWindow::standout() +{ + return ::wstandout(w); +} + +inline int CursesWindow::standend() +{ + return ::wstandend(w); +} + +inline int CursesWindow::lines() +{ + return LINES; +} + +inline int CursesWindow::cols() +{ + return COLS; +} + +inline CursesWindow* CursesWindow::child() +{ + return subwins; +} + +inline CursesWindow* CursesWindow::parent() +{ + return par; +} + +inline CursesWindow* CursesWindow::sibling() +{ + return sib; +} + +#endif /* _G_HAVE_CURSES */ +#endif diff --git a/gnu/lib/libg++/include/DLList.h b/gnu/lib/libg++/include/DLList.h new file mode 100644 index 0000000..0c3adc2 --- /dev/null +++ b/gnu/lib/libg++/include/DLList.h @@ -0,0 +1,126 @@ +// 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. +*/ + + +#ifndef _DLList_h +#ifdef __GNUG__ +//#pragma interface +#endif +#define _DLList_h 1 + +#include <Pix.h> + +struct BaseDLNode { + BaseDLNode *bk; + BaseDLNode *fd; + void *item() {return (void*)(this+1);} //Return ((DLNode<T>*)this)->hd +}; + +template<class T> +class DLNode : public BaseDLNode +{ + public: + T hd; + DLNode() { } + DLNode(const T& h, DLNode* p = 0, DLNode* n = 0) + : hd(h) { bk = p; fd = n; } + ~DLNode() { } +}; + +class BaseDLList { + protected: + BaseDLNode *h; + + BaseDLList() { h = 0; } + void copy(const BaseDLList&); + BaseDLList& operator= (const BaseDLList& a); + virtual void delete_node(BaseDLNode*node) = 0; + virtual BaseDLNode* copy_node(const void* datum) = 0; + virtual void copy_item(void *dst, void *src) = 0; + virtual ~BaseDLList() { } + + Pix prepend(const void*); + Pix append(const void*); + Pix ins_after(Pix p, const void *datum); + Pix ins_before(Pix p, const void *datum); + void remove_front(void *dst); + void remove_rear(void *dst); + void join(BaseDLList&); + + public: + int empty() const { return h == 0; } + int length() const; + void clear(); + void error(const char* msg); + int owns(Pix p); + int OK(); + void del(Pix& p, int dir = 1); + void del_after(Pix& p); + void del_front(); + void del_rear(); +}; + +template <class T> +class DLList : public BaseDLList { + //friend class <T>DLListTrav; + + virtual void delete_node(BaseDLNode *node) { delete (DLNode<T>*)node; } + virtual BaseDLNode* copy_node(const void *datum) + { return new DLNode<T>(*(const T*)datum); } + virtual void copy_item(void *dst, void *src) { *(T*)dst = *(T*)src; } + + public: + DLList() : BaseDLList() { } + DLList(const DLList<T>& a) : BaseDLList() { copy(a); } + + DLList<T>& operator = (const DLList<T>& a) + { BaseDLList::operator=((const BaseDLList&) a); return *this; } + virtual ~DLList() { clear(); } + + Pix prepend(const T& item) {return BaseDLList::prepend(&item);} + Pix append(const T& item) {return BaseDLList::append(&item);} + + void join(DLList<T>& a) { BaseDLList::join(a); } + + T& front() { + if (h == 0) error("front: empty list"); + return ((DLNode<T>*)h)->hd; } + T& rear() { + if (h == 0) error("rear: empty list"); + return ((DLNode<T>*)h->bk)->hd; + } + T remove_front() { T dst; BaseDLList::remove_front(&dst); return dst; } + T remove_rear() { T dst; BaseDLList::remove_rear(&dst); return dst; } + + T& operator () (Pix p) { + if (p == 0) error("null Pix"); + return ((DLNode<T>*)p)->hd; + } + Pix first() { return Pix(h); } + Pix last() { return (h == 0)? 0 : Pix(h->bk); } + void next(Pix& p) + { p = (p == 0 || p == h->bk)? 0 : Pix(((DLNode<T>*)p)->fd); } + void prev(Pix& p) + { p = (p == 0 || p == h)? 0 : Pix(((DLNode<T>*)p)->bk); } + Pix ins_after(Pix p, const T& item) + {return BaseDLList::ins_after(p, &item); } + Pix ins_before(Pix p, const T& item) + {return BaseDLList::ins_before(p, &item);} +}; + +#endif diff --git a/gnu/lib/libg++/include/DiscUnif.h b/gnu/lib/libg++/include/DiscUnif.h new file mode 100644 index 0000000..5f26f90 --- /dev/null +++ b/gnu/lib/libg++/include/DiscUnif.h @@ -0,0 +1,72 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _DiscreteUniform_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _DiscreteUniform_h 1 + +#include <Random.h> + +// +// The interval [lo..hi) +// + +class DiscreteUniform: public Random { + long pLow; + long pHigh; + double delta; +public: + DiscreteUniform(long low, long high, RNG *gen); + + long low(); + long low(long x); + long high(); + long high(long x); + + virtual double operator()(); +}; + + +inline DiscreteUniform::DiscreteUniform(long low, long high, RNG *gen) +: Random(gen) +{ + pLow = (low < high) ? low : high; + pHigh = (low < high) ? high : low; + delta = (pHigh - pLow) + 1; +} + +inline long DiscreteUniform::low() { return pLow; } + +inline long DiscreteUniform::low(long x) { + long tmp = pLow; + pLow = x; + delta = (pHigh - pLow) + 1; + return tmp; +} + +inline long DiscreteUniform::high() { return pHigh; } + +inline long DiscreteUniform::high(long x) { + long tmp = pHigh; + pHigh = x; + delta = (pHigh - pLow) + 1; + return tmp; +} + +#endif diff --git a/gnu/lib/libg++/include/Erlang.h b/gnu/lib/libg++/include/Erlang.h new file mode 100644 index 0000000..9809388 --- /dev/null +++ b/gnu/lib/libg++/include/Erlang.h @@ -0,0 +1,68 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _Erlang_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Erlang_h 1 + +#include <Random.h> + +class Erlang: public Random { +protected: + double pMean; + double pVariance; + int k; + double a; + void setState(); +public: + Erlang(double mean, double variance, RNG *gen); + + double mean(); + double mean(double x); + double variance(); + double variance(double x); + + virtual double operator()(); + +}; + + +inline void Erlang::setState() { + k = int( (pMean * pMean ) / pVariance + 0.5 ); + k = (k > 0) ? k : 1; + a = k / pMean; +} + +inline Erlang::Erlang(double mean, double variance, RNG *gen) : Random(gen) +{ + pMean = mean; pVariance = variance; + setState(); +} + +inline double Erlang::mean() { return pMean; } +inline double Erlang::mean(double x) { + double tmp = pMean; pMean = x; setState(); return tmp; +}; + +inline double Erlang::variance() { return pVariance; } +inline double Erlang::variance(double x) { + double tmp = pVariance; pVariance = x; setState(); return tmp; +} + +#endif diff --git a/gnu/lib/libg++/include/Fix.h b/gnu/lib/libg++/include/Fix.h new file mode 100644 index 0000000..df76c94 --- /dev/null +++ b/gnu/lib/libg++/include/Fix.h @@ -0,0 +1,513 @@ +// -*- C++ -*- +// Fix.h : variable length fixed point data type +// + +#ifndef _Fix_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Fix_h 1 + +#include <stream.h> +#include <std.h> +#include <stddef.h> +#include <Integer.h> +#include <builtin.h> + +class Fix +{ + struct Rep // internal Fix representation + { + _G_uint16_t len; // length in bits + _G_uint16_t siz; // allocated storage + _G_int16_t ref; // reference count + _G_uint16_t s[1]; // start of ushort array represention + }; + +public: + + typedef void (*PEH)(Rep*); + +private: + + Rep* rep; + + Fix(Rep*); + Fix(int, const Rep*); + + void unique(); + + static const _G_uint16_t min_length = 1; + static const _G_uint16_t max_length = 65535; + static const double min_value = -1.0; + static const double max_value = 1.0; + + static _G_uint16_t default_length; + static int default_print_width; + static Rep Rep_0; + static Rep Rep_m1; + static Rep Rep_quotient_bump; + + // internal class functions + static void mask(Rep*); + static int compare(const Rep*, const Rep* = &Rep_0); + + static Rep* new_Fix(_G_uint16_t); + static Rep* new_Fix(_G_uint16_t, const Rep*); + static Rep* new_Fix(_G_uint16_t, double); + + static Rep* copy(const Rep*, Rep*); + static Rep* negate(const Rep*, Rep* = NULL); + static Rep* add(const Rep*, const Rep*, Rep* = NULL); + static Rep* subtract(const Rep*, const Rep*, Rep* = NULL); + static Rep* multiply(const Rep*, const Rep*, Rep* = NULL); + static Rep* multiply(const Rep*, int, Rep* = NULL); + static Rep* divide(const Rep*, const Rep*, Rep* = NULL, + Rep* = NULL); + static Rep* shift(const Rep*, int, Rep* = NULL); + + static one_arg_error_handler_t error_handler; + static one_arg_error_handler_t range_error_handler; + + static PEH overflow_handler; + +public: + Fix(); + Fix(const Fix&); + Fix(double); + Fix(int); + Fix(int, const Fix&); + Fix(int, double); + + ~Fix(); + + Fix operator = (const Fix&); + Fix operator = (double); + + friend int operator == (const Fix&, const Fix&); + friend int operator != (const Fix&, const Fix&); + + friend int operator < (const Fix&, const Fix&); + friend int operator <= (const Fix&, const Fix&); + friend int operator > (const Fix&, const Fix&); + friend int operator >= (const Fix&, const Fix&); + + Fix& operator + (); + Fix operator - (); + + friend Fix operator + (const Fix&, const Fix&); + friend Fix operator - (const Fix&, const Fix&); + friend Fix operator * (const Fix&, const Fix&); + friend Fix operator / (const Fix&, const Fix&); + + friend Fix operator * (const Fix&, int); + friend Fix operator * (int, const Fix&); + friend Fix operator % (const Fix&, int); + friend Fix operator << (const Fix&, int); + friend Fix operator >> (const Fix&, int); + +#if defined (__GNUG__) && ! defined (__STRICT_ANSI__) + friend Fix operator <? (const Fix&, const Fix&); // min + friend Fix operator >? (const Fix&, const Fix&); // max +#endif + + Fix operator += (const Fix&); + Fix operator -= (const Fix&); + Fix operator *= (const Fix&); + Fix operator /= (const Fix&); + + Fix operator *= (int); + Fix operator %= (int); + Fix operator <<=(int); + Fix operator >>=(int); + + friend char* Ftoa(const Fix&, int width = default_print_width); + void printon(ostream&, int width = default_print_width) const; + friend Fix atoF(const char*, int len = default_length); + + friend istream& operator >> (istream&, Fix&); + friend ostream& operator << (ostream&, const Fix&); + + // built-in functions + friend Fix abs(Fix); // absolute value + friend int sgn(const Fix&); // -1, 0, +1 + friend Integer mantissa(const Fix&); // integer representation + friend double value(const Fix&); // double value + friend int length(const Fix&); // field length + friend void show(const Fix&); // show contents + + // error handlers + static void error(const char* msg); // error handler + static void range_error(const char* msg); // range error handler + + static one_arg_error_handler_t set_error_handler(one_arg_error_handler_t f); + static one_arg_error_handler_t + set_range_error_handler(one_arg_error_handler_t f); + + static void default_error_handler (const char *); + static void default_range_error_handler (const char *); + + // non-operator versions for user + friend void negate(const Fix& x, Fix& r); + friend void add(const Fix& x, const Fix& y, Fix& r); + friend void subtract(const Fix& x, const Fix& y, Fix& r); + friend void multiply(const Fix& x, const Fix& y, Fix& r); + friend void divide(const Fix& x, const Fix& y, Fix& q, Fix& r); + friend void shift(const Fix& x, int y, Fix& r); + + // overflow handlers + static void overflow_saturate(Fix::Rep*); + static void overflow_wrap(Fix::Rep*); + static void overflow_warning_saturate(Fix::Rep*); + static void overflow_warning(Fix::Rep*); + static void overflow_error(Fix::Rep*); + + static PEH set_overflow_handler(PEH); + + static int set_default_length(int); +}; + +// function definitions + +inline void +Fix::unique() +{ + if ( rep->ref > 1 ) + { + rep->ref--; + rep = new_Fix(rep->len,rep); + } +} + +inline void +Fix::mask (Fix::Rep* x) +{ + int n = x->len & 0x0f; + if ( n ) + x->s[x->siz - 1] &= 0xffff0000 >> n; +} + +inline Fix::Rep* +Fix::copy(const Fix::Rep* from, Fix::Rep* to) +{ + _G_uint16_t *ts = to->s; + const _G_uint16_t *fs = from->s; + int ilim = to->siz < from->siz ? to->siz : from->siz; + for ( int i=0; i < ilim; i++ ) + *ts++ = *fs++; + for ( ; i < to->siz; i++ ) + *ts++ = 0; + mask(to); + return to; +} + +inline +Fix::Fix(Rep* f) +{ + rep = f; +} + +inline +Fix::Fix() +{ + rep = new_Fix(default_length); +} + +inline +Fix::Fix(int len) +{ + if ( len < min_length || len > max_length ) + error("illegal length in declaration"); + rep = new_Fix((_G_uint16_t) len); +} + +inline +Fix::Fix(double d) +{ + rep = new_Fix(default_length,d); +} + +inline +Fix::Fix(const Fix& y) +{ + rep = y.rep; rep->ref++; +} + +inline +Fix::Fix(int len, const Fix& y) +{ + if ( len < Fix::min_length || len > Fix::max_length ) + error("illegal length in declaration"); + rep = new_Fix((_G_uint16_t) len,y.rep); +} + +inline +Fix::Fix(int len, const Rep* fr) +{ + if ( len < Fix::min_length || len > Fix::max_length ) + error("illegal length in declaration"); + rep = new_Fix((_G_uint16_t) len,fr); +} + +inline +Fix::Fix(int len, double d) +{ + if ( len < Fix::min_length || len > Fix::max_length ) + error("illegal length in declaration"); + rep = new_Fix((_G_uint16_t) len,d); +} + +inline +Fix::~Fix() +{ + if ( --rep->ref <= 0 ) delete rep; +} + +inline Fix +Fix::operator = (const Fix& y) +{ + if ( rep->len == y.rep->len ) { + ++y.rep->ref; + if ( --rep->ref <= 0 ) delete rep; + rep = y.rep; + } + else { + unique(); + copy(y.rep,rep); + } + return *this; +} + +inline Fix +Fix::operator = (double d) +{ + int oldlen = rep->len; + if ( --rep->ref <= 0 ) delete rep; + rep = new_Fix(oldlen,d); + return *this; +} + +inline int +operator == (const Fix& x, const Fix& y) +{ + return Fix::compare(x.rep, y.rep) == 0; +} + +inline int +operator != (const Fix& x, const Fix& y) +{ + return Fix::compare(x.rep, y.rep) != 0; +} + +inline int +operator < (const Fix& x, const Fix& y) +{ + return Fix::compare(x.rep, y.rep) < 0; +} + +inline int +operator <= (const Fix& x, const Fix& y) +{ + return Fix::compare(x.rep, y.rep) <= 0; +} + +inline int +operator > (const Fix& x, const Fix& y) +{ + return Fix::compare(x.rep, y.rep) > 0; +} + +inline int +operator >= (const Fix& x, const Fix& y) +{ + return Fix::compare(x.rep, y.rep) >= 0; +} + +inline Fix& +Fix::operator + () +{ + return *this; +} + +inline Fix +Fix::operator - () +{ + Rep* r = negate(rep); return r; +} + +inline Fix +operator + (const Fix& x, const Fix& y) +{ + Fix::Rep* r = Fix::add(x.rep, y.rep); return r; +} + +inline Fix +operator - (const Fix& x, const Fix& y) +{ + Fix::Rep* r = Fix::subtract(x.rep, y.rep); return r; +} + +inline Fix +operator * (const Fix& x, const Fix& y) +{ + Fix::Rep* r = Fix::multiply(x.rep, y.rep); return r; +} + +inline Fix +operator * (const Fix& x, int y) +{ + Fix::Rep* r = Fix::multiply(x.rep, y); return r; +} + +inline Fix +operator * (int y, const Fix& x) +{ + Fix::Rep* r = Fix::multiply(x.rep, y); return r; +} + +inline Fix +operator / (const Fix& x, const Fix& y) +{ + Fix::Rep* r = Fix::divide(x.rep, y.rep); return r; +} + +inline Fix +Fix::operator += (const Fix& y) +{ + unique(); Fix::add(rep, y.rep, rep); return *this; +} + +inline Fix +Fix::operator -= (const Fix& y) +{ + unique(); Fix::subtract(rep, y.rep, rep); return *this; +} + +inline Fix +Fix::operator *= (const Fix& y) +{ + unique(); Fix::multiply(rep, y.rep, rep); return *this; +} + +inline Fix +Fix::operator *= (int y) +{ + unique(); Fix::multiply(rep, y, rep); return *this; +} + +inline Fix +Fix::operator /= (const Fix& y) +{ + unique(); Fix::divide(rep, y.rep, rep); return *this; +} + +inline Fix +operator % (const Fix& x, int y) +{ + Fix r((int) x.rep->len + y, x); return r; +} + +inline Fix +operator << (const Fix& x, int y) +{ + Fix::Rep* rep = Fix::shift(x.rep, y); return rep; +} + +inline Fix +operator >> (const Fix& x, int y) +{ + Fix::Rep* rep = Fix::shift(x.rep, -y); return rep; +} + +inline Fix +Fix::operator <<= (int y) +{ + unique(); Fix::shift(rep, y, rep); return *this; +} + +inline Fix +Fix::operator >>= (int y) +{ + unique(); Fix::shift(rep, -y, rep); return *this; +} + +#if defined (__GNUG__) && ! defined (__STRICT_ANSI__) +inline Fix +operator <? (const Fix& x, const Fix& y) +{ + if ( Fix::compare(x.rep, y.rep) <= 0 ) return x; else return y; +} + +inline Fix +operator >? (const Fix& x, const Fix& y) +{ + if ( Fix::compare(x.rep, y.rep) >= 0 ) return x; else return y; +} +#endif + +inline Fix +abs(Fix x) +{ + Fix::Rep* r = (Fix::compare(x.rep) >= 0 ? Fix::new_Fix(x.rep->len,x.rep) : + Fix::negate(x.rep)); + return r; +} + +inline int +sgn(const Fix& x) +{ + int a = Fix::compare(x.rep); + return a == 0 ? 0 : (a > 0 ? 1 : -1); +} + +inline int +length(const Fix& x) +{ + return x.rep->len; +} + +inline ostream& +operator << (ostream& s, const Fix& y) +{ + if (s.opfx()) + y.printon(s); + return s; +} + +inline void +negate (const Fix& x, Fix& r) +{ + Fix::negate(x.rep, r.rep); +} + +inline void +add (const Fix& x, const Fix& y, Fix& r) +{ + Fix::add(x.rep, y.rep, r.rep); +} + +inline void +subtract (const Fix& x, const Fix& y, Fix& r) +{ + Fix::subtract(x.rep, y.rep, r.rep); +} + +inline void +multiply (const Fix& x, const Fix& y, Fix& r) +{ + Fix::multiply(x.rep, y.rep, r.rep); +} + +inline void +divide (const Fix& x, const Fix& y, Fix& q, Fix& r) +{ + Fix::divide(x.rep, y.rep, q.rep, r.rep); +} + +inline void +shift (const Fix& x, int y, Fix& r) +{ + Fix::shift(x.rep, y, r.rep); +} + +#endif diff --git a/gnu/lib/libg++/include/Fix16.h b/gnu/lib/libg++/include/Fix16.h new file mode 100644 index 0000000..36728b4 --- /dev/null +++ b/gnu/lib/libg++/include/Fix16.h @@ -0,0 +1,648 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Kurt Baudendistel (gt-eedsp!baud@gatech.edu) + adapted for libg++ 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. +*/ + +#ifndef _Fix16_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Fix16_h 1 + +#include <stream.h> +#include <std.h> + +// constant definitions + +#define Fix16_fs ((double)((unsigned)(1 << 15))) + +#define Fix16_msb (1 << 15) +#define Fix16_m_max ((1 << 15) - 1) +#define Fix16_m_min ((short)(1 << 15)) + +#define Fix16_mult Fix16_fs +#define Fix16_div (1./Fix16_fs) +#define Fix16_max (1. - .5/Fix16_fs) +#define Fix16_min (-1.) + + +#define Fix32_fs ((double)((unsigned long)(1 << 31))) + +#define Fix32_msb ((unsigned long)(1 << 31)) +#define Fix32_m_max ((long)((1 << 31) - 1)) +#define Fix32_m_min ((long)(1 << 31)) + +#define Fix32_mult Fix32_fs +#define Fix32_div (1./Fix32_fs) +#define Fix32_max (1. - .5/Fix32_fs) +#define Fix32_min (-1.) + + +// +// Fix16 class: 16-bit Fixed point data type +// +// consists of a 16-bit mantissa (sign bit & 15 data bits). +// + +class Fix16 +{ + friend class Fix32; + + short m; + + short round(double d); + short assign(double d); + Fix16(short i); + Fix16(int i); + + operator double() const; + + +public: + Fix16(); + Fix16(const Fix16& f); + Fix16(double d); + Fix16(const Fix32& f); + + ~Fix16(); + + Fix16& operator=(const Fix16& f); + Fix16& operator=(double d); + Fix16& operator=(const Fix32& f); + + friend short& mantissa(Fix16& f); + friend const short& mantissa(const Fix16& f); + friend double value(const Fix16& f); + + Fix16 operator + () const; + Fix16 operator - () const; + + friend Fix16 operator + (const Fix16& f, const Fix16& g); + friend Fix16 operator - (const Fix16& f, const Fix16& g); + friend Fix32 operator * (const Fix16& f, const Fix16& g); + friend Fix16 operator / (const Fix16& f, const Fix16& g); + friend Fix16 operator << (const Fix16& f, int b); + friend Fix16 operator >> (const Fix16& f, int b); + + Fix16& operator += (const Fix16& f); + Fix16& operator -= (const Fix16& f); + Fix16& operator *= (const Fix16& ); + Fix16& operator /= (const Fix16& f); + + Fix16& operator <<=(int b); + Fix16& operator >>=(int b); + + friend int operator == (const Fix16& f, const Fix16& g); + friend int operator != (const Fix16& f, const Fix16& g); + friend int operator >= (const Fix16& f, const Fix16& g); + friend int operator <= (const Fix16& f, const Fix16& g); + friend int operator > (const Fix16& f, const Fix16& g); + friend int operator < (const Fix16& f, const Fix16& g); + + friend istream& operator >> (istream& s, Fix16& f); + friend ostream& operator << (ostream& s, const Fix16& f); + + void overflow(short&) const; + void range_error(short&) const; + + friend Fix16 operator * (const Fix16& f, int g); + friend Fix16 operator * (int g, const Fix16& f); + Fix16& operator *= (int g); +}; + + +// +// Fix32 class: 32-bit Fixed point data type +// +// consists of a 32-bit mantissa (sign bit & 31 data bits). +// + +class Fix32 +{ + friend class Fix16; + + long m; + + long round(double d); + long assign(double d); + + Fix32(long i); + operator double() const; + + +public: + Fix32(); + Fix32(const Fix32& f); + Fix32(const Fix16& f); + Fix32(double d); + ~Fix32(); + + Fix32& operator = (const Fix32& f); + Fix32& operator = (const Fix16& f); + Fix32& operator = (double d); + + friend long& mantissa(Fix32& f); + friend const long& mantissa(const Fix32& f); + friend double value(const Fix32& f); + + Fix32 operator + () const; + Fix32 operator - () const; + + friend Fix32 operator + (const Fix32& f, const Fix32& g); + friend Fix32 operator - (const Fix32& f, const Fix32& g); + friend Fix32 operator * (const Fix32& f, const Fix32& g); + friend Fix32 operator / (const Fix32& f, const Fix32& g); + friend Fix32 operator << (const Fix32& f, int b); + friend Fix32 operator >> (const Fix32& f, int b); + + friend Fix32 operator * (const Fix16& f, const Fix16& g); + + Fix32& operator += (const Fix32& f); + Fix32& operator -= (const Fix32& f); + Fix32& operator *= (const Fix32& f); + Fix32& operator /= (const Fix32& f); + Fix32& operator <<=(int b); + Fix32& operator >>=(int b); + + friend int operator == (const Fix32& f, const Fix32& g); + friend int operator != (const Fix32& f, const Fix32& g); + friend int operator >= (const Fix32& f, const Fix32& g); + friend int operator <= (const Fix32& f, const Fix32& g); + friend int operator > (const Fix32& f, const Fix32& g); + friend int operator < (const Fix32& f, const Fix32& g); + + friend istream& operator >> (istream& s, Fix32& f); + friend ostream& operator << (ostream& s, const Fix32& f); + + void overflow(long& i) const; + void range_error(long& i) const; + + friend Fix32 operator * (const Fix32& f, int g); + friend Fix32 operator * (int g, const Fix32& f); + Fix32& operator *= (int g); +}; + +// active error handler declarations + +typedef void (*Fix16_peh)(short&); +typedef void (*Fix32_peh)(long&); + +extern Fix16_peh Fix16_overflow_handler; +extern Fix32_peh Fix32_overflow_handler; + +extern Fix16_peh Fix16_range_error_handler; +extern Fix32_peh Fix32_range_error_handler; + +#if defined(SHORT_NAMES) || defined(VMS) +#define set_overflow_handler sohndl +#define set_range_error_handler srnghdl +#endif + + +// error handler declarations + +extern Fix16_peh set_Fix16_overflow_handler(Fix16_peh); +extern Fix32_peh set_Fix32_overflow_handler(Fix32_peh); +extern void set_overflow_handler(Fix16_peh, Fix32_peh); + +extern Fix16_peh set_Fix16_range_error_handler(Fix16_peh); +extern Fix32_peh set_Fix32_range_error_handler(Fix32_peh); +extern void set_range_error_handler(Fix16_peh, Fix32_peh); + +extern void + Fix16_ignore(short&), + Fix16_overflow_saturate(short&), + Fix16_overflow_warning_saturate(short&), + Fix16_warning(short&), + Fix16_abort(short&); + +extern void + Fix32_ignore(long&), + Fix32_overflow_saturate(long&), + Fix32_overflow_warning_saturate(long&), + Fix32_warning(long&), + Fix32_abort(long&); + + +inline Fix16::~Fix16() {} + +inline short Fix16::round(double d) +{ + return short( (d >= 0)? d + 0.5 : d - 0.5); +} + +inline Fix16::Fix16(short i) +{ + m = i; +} + +inline Fix16::Fix16(int i) +{ + m = i; +} + +inline Fix16::operator double() const +{ + return Fix16_div * m; +} + +inline Fix16::Fix16() +{ + m = 0; +} + +inline Fix16::Fix16(const Fix16& f) +{ + m = f.m; +} + +inline Fix16::Fix16(double d) +{ + m = assign(d); +} + + +inline Fix16& Fix16::operator=(const Fix16& f) +{ + m = f.m; + return *this; +} + +inline Fix16& Fix16::operator=(double d) +{ + m = assign(d); + return *this; +} + + +inline Fix32::Fix32() +{ + m = 0; +} + +inline Fix32::Fix32(long i) +{ + m = i; +} + +inline Fix32:: operator double() const +{ + return Fix32_div * m; +} + + +inline Fix32::Fix32(const Fix32& f) +{ + m = f.m; +} + +inline Fix32::Fix32(const Fix16& f) +{ + m = long(f.m) << 16; +} + +inline Fix32::Fix32(double d) +{ + m = assign(d); +} + +inline Fix16::Fix16(const Fix32& f) +{ + m = f.m >> 16; +} + + +inline Fix16& Fix16::operator=(const Fix32& f) +{ + m = f.m >> 16; + return *this; +} + +inline Fix32& Fix32::operator=(const Fix32& f) +{ + m = f.m; + return *this; +} + +inline Fix32& Fix32::operator=(const Fix16& f) +{ + m = long(f.m) << 16; + return *this; +} + +inline Fix32& Fix32::operator=(double d) +{ + m = assign(d); + return *this; +} + +inline short& mantissa(Fix16& f) +{ + return f.m; +} + +inline const short& mantissa(const Fix16& f) +{ + return f.m; +} + +inline double value(const Fix16& f) +{ + return double(f); +} + +inline Fix16 Fix16::operator+() const +{ + return m; +} + +inline Fix16 Fix16::operator-() const +{ + return -m; +} + +inline Fix16 operator+(const Fix16& f, const Fix16& g) +{ + short sum = f.m + g.m; + if ( (f.m ^ sum) & (g.m ^ sum) & Fix16_msb ) + f.overflow(sum); + return sum; +} + +inline Fix16 operator-(const Fix16& f, const Fix16& g) +{ + short sum = f.m - g.m; + if ( (f.m ^ sum) & (-g.m ^ sum) & Fix16_msb ) + f.overflow(sum); + return sum; +} + +inline Fix32 operator*(const Fix16& f, const Fix16& g) +{ + return Fix32( long( long(f.m) * long(g.m) << 1)); +} + +inline Fix16 operator<<(const Fix16& a, int b) +{ + return a.m << b; +} + +inline Fix16 operator>>(const Fix16& a, int b) +{ + return a.m >> b; +} + +inline Fix16& Fix16:: operator+=(const Fix16& f) +{ + return *this = *this + f; +} + +inline Fix16& Fix16:: operator-=(const Fix16& f) +{ + return *this = *this - f; +} + +inline Fix16& Fix16::operator*=(const Fix16& f) +{ + return *this = *this * f; +} + +inline Fix16& Fix16:: operator/=(const Fix16& f) +{ + return *this = *this / f; +} + +inline Fix16& Fix16:: operator<<=(int b) +{ + return *this = *this << b; +} + +inline Fix16& Fix16:: operator>>=(int b) +{ + return *this = *this >> b; +} + +inline int operator==(const Fix16& f, const Fix16& g) +{ + return f.m == g.m; +} + +inline int operator!=(const Fix16& f, const Fix16& g) +{ + return f.m != g.m; +} + +inline int operator>=(const Fix16& f, const Fix16& g) +{ + return f.m >= g.m; +} + +inline int operator<=(const Fix16& f, const Fix16& g) +{ + return f.m <= g.m; +} + +inline int operator>(const Fix16& f, const Fix16& g) +{ + return f.m > g.m; +} + +inline int operator<(const Fix16& f, const Fix16& g) +{ + return f.m < g.m; +} + +inline istream& operator>>(istream& s, Fix16& f) +{ + double d; + s >> d; + f = d; + return s; +} + +inline ostream& operator<<(ostream& s, const Fix16& f) +{ + return s << double(f); +} + + +inline Fix16 operator*(const Fix16& f, int g) +{ + return Fix16(short(f.m * g)); +} + +inline Fix16 operator*(int g, const Fix16& f) +{ + return f * g; +} + + +inline Fix16& Fix16::operator*=(int g) +{ + return *this = *this * g; +} + +inline Fix32::~Fix32() {} + +inline long Fix32::round(double d) +{ + return long( (d >= 0)? d + 0.5 : d - 0.5); +} + +inline long& mantissa(Fix32& f) +{ + return f.m; +} + +inline const long& mantissa(const Fix32& f) +{ + return f.m; +} + +inline double value(const Fix32& f) +{ + return double(f); +} + +inline Fix32 Fix32::operator+() const +{ + return m; +} + +inline Fix32 Fix32::operator-() const +{ + return -m; +} + +inline Fix32 operator+(const Fix32& f, const Fix32& g) +{ + long sum = f.m + g.m; + if ( (f.m ^ sum) & (g.m ^ sum) & Fix32_msb ) + f.overflow(sum); + return sum; +} + +inline Fix32 operator-(const Fix32& f, const Fix32& g) +{ + long sum = f.m - g.m; + if ( (f.m ^ sum) & (-g.m ^ sum) & Fix32_msb ) + f.overflow(sum); + return sum; +} + +inline Fix32 operator<<(const Fix32& a, int b) +{ + return a.m << b; +} + +inline Fix32 operator>>(const Fix32& a, int b) +{ + return a.m >> b; +} + +inline Fix32& Fix32::operator+=(const Fix32& f) +{ + return *this = *this + f; +} + +inline Fix32& Fix32::operator-=(const Fix32& f) +{ + return *this = *this - f; +} + +inline Fix32& Fix32::operator*=(const Fix32& f) +{ + return *this = *this * f; +} + +inline Fix32& Fix32::operator/=(const Fix32& f) +{ + return *this = *this / f; +} + + +inline Fix32& Fix32::operator<<=(int b) +{ + return *this = *this << b; +} + +inline Fix32& Fix32::operator>>=(int b) +{ + return *this = *this >> b; +} + +inline int operator==(const Fix32& f, const Fix32& g) +{ + return f.m == g.m; +} + +inline int operator!=(const Fix32& f, const Fix32& g) +{ + return f.m != g.m; +} + +inline int operator>=(const Fix32& f, const Fix32& g) +{ + return f.m >= g.m; +} + +inline int operator<=(const Fix32& f, const Fix32& g) +{ + return f.m <= g.m; +} + +inline int operator>(const Fix32& f, const Fix32& g) +{ + return f.m > g.m; +} + +inline int operator<(const Fix32& f, const Fix32& g) +{ + return f.m < g.m; +} + +inline istream& operator>>(istream& s, Fix32& f) +{ + double d; + s >> d; + f = d; + return s; +} + +inline ostream& operator<<(ostream& s, const Fix32& f) +{ + return s << double(f); +} + +inline Fix32 operator*(const Fix32& f, int g) +{ + return Fix32(long(f.m * g)); +} + +inline Fix32 operator*(int g, const Fix32& f) +{ + return f * g; +} + + + +inline Fix32& Fix32::operator*=(int g) +{ + return *this = *this * g; +} + +#endif diff --git a/gnu/lib/libg++/include/Fix24.h b/gnu/lib/libg++/include/Fix24.h new file mode 100644 index 0000000..56d1191 --- /dev/null +++ b/gnu/lib/libg++/include/Fix24.h @@ -0,0 +1,597 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Kurt Baudendistel (gt-eedsp!baud@gatech.edu) + adapted for libg++ 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. +*/ + +#ifndef _Fix24_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Fix24_h 1 + +#include <stream.h> +#include <std.h> + +// extra type definitions + +typedef struct { + long u; + unsigned long l; +} twolongs; + +// constant definitions + +static const int + Fix24_shift = 31; + +static const double + Fix24_fs = 2147483648., // 2^Fix24_shift + Fix24_mult = Fix24_fs, + Fix24_div = 1./Fix24_fs, + Fix24_max = 1. - .5/Fix24_fs, + Fix24_min = -1.; + +static const unsigned long + Fix24_msb = 0x80000000L, + Fix24_lsb = 0x00000100L, + Fix24_m_max = 0x7fffff00L, + Fix24_m_min = 0x80000000L; + +static const double + Fix48_fs = 36028797018963968., // 2^(24+Fix24_shift) + Fix48_max = 1. - .5/Fix48_fs, + Fix48_min = -1., + Fix48_div_u = 1./Fix24_fs, + Fix48_div_l = 1./Fix48_fs; + +static const twolongs + Fix48_msb = { 0x80000000L, 0L }, + Fix48_lsb = { 0L, 0x00000100L }, + Fix48_m_max = { 0x7fffff00L, 0xffffff00L }, + Fix48_m_min = { 0x80000000L, 0L }; + +// +// Fix24 class: 24-bit Fixed point data type +// +// consists of a 24-bit mantissa (sign bit & 23 data bits). +// + +class Fix24 +{ + friend class Fix48; + + long m; + + long assign(double d); + operator double() const; + Fix24(long i); + Fix24(int i); + + +public: + Fix24(); + Fix24(const Fix24& f); + Fix24(double d); + Fix24(const Fix48& f); + + ~Fix24(); + + Fix24& operator=(const Fix24& f); + Fix24& operator=(double d); + Fix24& operator=(const Fix48& f); + + friend long& mantissa(Fix24& f); + friend const long& mantissa(const Fix24& f); + friend double value(const Fix24& f); + + Fix24 operator + () const; + Fix24 operator - () const; + + friend Fix24 operator + (const Fix24& f, const Fix24& g); + friend Fix24 operator - (const Fix24& f, const Fix24& g); + friend Fix48 operator * (const Fix24& f, const Fix24& g); + friend Fix24 operator * (const Fix24& f, int g); + friend Fix24 operator * (int g, const Fix24& f); + friend Fix24 operator / (const Fix24& f, const Fix24& g); + friend Fix24 operator << (const Fix24& f, int b); + friend Fix24 operator >> (const Fix24& f, int b); + + Fix24& operator += (const Fix24& f); + Fix24& operator -= (const Fix24& f); + Fix24& operator *= (const Fix24& f); + Fix24& operator *= (int b); + Fix24& operator /= (const Fix24& f); + + Fix24& operator <<=(int b); + Fix24& operator >>=(int b); + + friend int operator == (const Fix24& f, const Fix24& g); + friend int operator != (const Fix24& f, const Fix24& g); + friend int operator >= (const Fix24& f, const Fix24& g); + friend int operator <= (const Fix24& f, const Fix24& g); + friend int operator > (const Fix24& f, const Fix24& g); + friend int operator < (const Fix24& f, const Fix24& g); + + friend istream& operator >> (istream& s, Fix24& f); + friend ostream& operator << (ostream& s, const Fix24& f); + + void overflow(long&) const; + void range_error(long&) const; +}; + + +// +// Fix48 class: 48-bit Fixed point data type +// +// consists of a 48-bit mantissa (sign bit & 47 data bits). +// + +class Fix48 +{ + friend class Fix24; + + twolongs m; + + twolongs assign(double d); + operator double() const; + Fix48(twolongs i); + +public: + Fix48(); + Fix48(const Fix48& f); + Fix48(const Fix24& f); + Fix48(double d); + ~Fix48(); + + Fix48& operator = (const Fix48& f); + Fix48& operator = (const Fix24& f); + Fix48& operator = (double d); + + friend twolongs& mantissa(Fix48& f); + friend const twolongs& mantissa(const Fix48& f); + friend double value(const Fix48& f); + + Fix48 operator + () const; + Fix48 operator - () const; + + friend Fix48 operator + (const Fix48& f, const Fix48& g); + friend Fix48 operator - (const Fix48& f, const Fix48& g); + friend Fix48 operator * (const Fix48& f, int g); + friend Fix48 operator * (int g, const Fix48& f); + friend Fix48 operator << (const Fix48& f, int b); + friend Fix48 operator >> (const Fix48& f, int b); + + friend Fix48 operator * (const Fix24& f, const Fix24& g); + + Fix48& operator += (const Fix48& f); + Fix48& operator -= (const Fix48& f); + Fix48& operator *= (int b); + Fix48& operator <<=(int b); + Fix48& operator >>=(int b); + + friend int operator == (const Fix48& f, const Fix48& g); + friend int operator != (const Fix48& f, const Fix48& g); + friend int operator >= (const Fix48& f, const Fix48& g); + friend int operator <= (const Fix48& f, const Fix48& g); + friend int operator > (const Fix48& f, const Fix48& g); + friend int operator < (const Fix48& f, const Fix48& g); + + friend istream& operator >> (istream& s, Fix48& f); + friend ostream& operator << (ostream& s, const Fix48& f); + + void overflow(twolongs& i) const; + void range_error(twolongs& i) const; +}; + + +// active error handler declarations + +typedef void (*Fix24_peh)(long&); +typedef void (*Fix48_peh)(twolongs&); + +extern Fix24_peh Fix24_overflow_handler; +extern Fix48_peh Fix48_overflow_handler; + +extern Fix24_peh Fix24_range_error_handler; +extern Fix48_peh Fix48_range_error_handler; + + +// error handler declarations + +#if defined(SHORT_NAMES) || defined(VMS) +#define set_overflow_handler sohndl +#define set_range_error_handler srnghdl +#endif + +extern Fix24_peh set_Fix24_overflow_handler(Fix24_peh); +extern Fix48_peh set_Fix48_overflow_handler(Fix48_peh); +extern void set_overflow_handler(Fix24_peh, Fix48_peh); + +extern Fix24_peh set_Fix24_range_error_handler(Fix24_peh); +extern Fix48_peh set_Fix48_range_error_handler(Fix48_peh); +extern void set_range_error_handler(Fix24_peh, Fix48_peh); + +extern void + Fix24_ignore(long&), + Fix24_overflow_saturate(long&), + Fix24_overflow_warning_saturate(long&), + Fix24_warning(long&), + Fix24_abort(long&); + +extern void + Fix48_ignore(twolongs&), + Fix48_overflow_saturate(twolongs&), + Fix48_overflow_warning_saturate(twolongs&), + Fix48_warning(twolongs&), + Fix48_abort(twolongs&); + + +inline Fix24::~Fix24() {} + +inline Fix24::Fix24(long i) +{ + m = i; +} + +inline Fix24::Fix24(int i) +{ + m = i; +} + +inline Fix24::operator double() const +{ + return Fix24_div * m; +} + +inline Fix24::Fix24() +{ + m = 0; +} + +inline Fix24::Fix24(const Fix24& f) +{ + m = f.m; +} + +inline Fix24::Fix24(double d) +{ + m = assign(d); +} + +inline Fix24::Fix24(const Fix48& f) +{ + m = f.m.u; +} + +inline Fix24& Fix24::operator=(const Fix24& f) +{ + m = f.m; + return *this; +} + +inline Fix24& Fix24::operator=(double d) +{ + m = assign(d); + return *this; +} + +inline Fix24& Fix24::operator=(const Fix48& f) +{ + m = f.m.u; + return *this; +} + +inline long& mantissa(Fix24& f) +{ + return f.m; +} + +inline const long& mantissa(const Fix24& f) +{ + return f.m; +} + +inline double value(const Fix24& f) +{ + return double(f); +} + +inline Fix24 Fix24::operator+() const +{ + return m; +} + +inline Fix24 Fix24::operator-() const +{ + return -m; +} + +inline Fix24 operator+(const Fix24& f, const Fix24& g) +{ + long sum = f.m + g.m; + if ( (f.m ^ sum) & (g.m ^ sum) & Fix24_msb ) + f.overflow(sum); + return sum; +} + +inline Fix24 operator-(const Fix24& f, const Fix24& g) +{ + long sum = f.m - g.m; + if ( (f.m ^ sum) & (-g.m ^ sum) & Fix24_msb ) + f.overflow(sum); + return sum; +} + +inline Fix24 operator*(const Fix24& a, int b) +{ + return a.m * b; +} + +inline Fix24 operator*(int b, const Fix24& a) +{ + return a * b; +} + +inline Fix24 operator<<(const Fix24& a, int b) +{ + return a.m << b; +} + +inline Fix24 operator>>(const Fix24& a, int b) +{ + return (a.m >> b) & (long)0xffffff00; +} + +inline Fix24& Fix24:: operator+=(const Fix24& f) +{ + return *this = *this + f; +} + +inline Fix24& Fix24:: operator-=(const Fix24& f) +{ + return *this = *this - f; +} + +inline Fix24& Fix24::operator*=(const Fix24& f) +{ + return *this = *this * f; +} + +inline Fix24& Fix24:: operator/=(const Fix24& f) +{ + return *this = *this / f; +} + +inline Fix24& Fix24:: operator<<=(int b) +{ + return *this = *this << b; +} + +inline Fix24& Fix24:: operator>>=(int b) +{ + return *this = *this >> b; +} + +inline Fix24& Fix24::operator*=(int b) +{ + return *this = *this * b; +} + +inline int operator==(const Fix24& f, const Fix24& g) +{ + return f.m == g.m; +} + +inline int operator!=(const Fix24& f, const Fix24& g) +{ + return f.m != g.m; +} + +inline int operator>=(const Fix24& f, const Fix24& g) +{ + return f.m >= g.m; +} + +inline int operator<=(const Fix24& f, const Fix24& g) +{ + return f.m <= g.m; +} + +inline int operator>(const Fix24& f, const Fix24& g) +{ + return f.m > g.m; +} + +inline int operator<(const Fix24& f, const Fix24& g) +{ + return f.m < g.m; +} + +inline istream& operator>>(istream& s, Fix24& f) +{ + double d; + s >> d; + f = d; + return s; +} + +inline ostream& operator<<(ostream& s, const Fix24& f) +{ + return s << double(f); +} + +inline Fix48::~Fix48() {} + +inline Fix48::Fix48(twolongs i) +{ + m = i; +} + +inline Fix48:: operator double() const +{ +/* + * Note: can't simply do Fix48_div_u * m.u + Fix48_div_l * m.l, because + * m.u is signed and m.l is unsigned. + */ + return (m.u >= 0)? Fix48_div_u * m.u + Fix48_div_l * m.l : + (Fix48_div_u * ((unsigned long)(m.u & 0xffffff00)) + + Fix48_div_l * m.l) - 2; +} + +inline Fix48::Fix48() +{ + m.u = 0; + m.l = 0; +} + +inline Fix48::Fix48(const Fix48& f) +{ + m = f.m; +} + +inline Fix48::Fix48(const Fix24& f) +{ + m.u = f.m; + m.l = 0; +} + +inline Fix48::Fix48(double d) +{ + m = assign(d); +} + +inline Fix48& Fix48::operator=(const Fix48& f) +{ + m = f.m; + return *this; +} + +inline Fix48& Fix48::operator=(const Fix24& f) +{ + m.u = f.m; + m.l = 0; + return *this; +} + +inline Fix48& Fix48::operator=(double d) +{ + m = assign(d); + return *this; +} + +inline twolongs& mantissa(Fix48& f) +{ + return f.m; +} + +inline const twolongs& mantissa(const Fix48& f) +{ + return f.m; +} + +inline double value(const Fix48& f) +{ + return double(f); +} + +inline Fix48 Fix48::operator+() const +{ + return m; +} + +inline Fix48 Fix48::operator-() const +{ + twolongs n; + n.l = -m.l; + n.u = ~m.u + ((n.l ^ m.l) & Fix24_msb ? 0 : Fix24_lsb); + return Fix48(n); +} + +inline Fix48 operator*(int b, const Fix48& a) +{ + return a * b; +} + +inline Fix48& Fix48::operator+=(const Fix48& f) +{ + return *this = *this + f; +} + +inline Fix48& Fix48::operator-=(const Fix48& f) +{ + return *this = *this - f; +} + +inline Fix48& Fix48::operator*=(int b) +{ + return *this = *this * b; +} + +inline Fix48& Fix48::operator<<=(int b) +{ + return *this = *this << b; +} + +inline Fix48& Fix48::operator>>=(int b) +{ + return *this = *this >> b; +} + +inline int operator==(const Fix48& f, const Fix48& g) +{ + return f.m.u == g.m.u && f.m.l == g.m.l; +} + +inline int operator!=(const Fix48& f, const Fix48& g) +{ + return f.m.u != g.m.u || f.m.l != g.m.l; +} + +inline int operator>=(const Fix48& f, const Fix48& g) +{ + return f.m.u >= g.m.u || (f.m.u == g.m.u && f.m.l >= g.m.l); +} + +inline int operator<=(const Fix48& f, const Fix48& g) +{ + return f.m.u <= g.m.u || (f.m.u == g.m.u && f.m.l <= g.m.l); +} + +inline int operator>(const Fix48& f, const Fix48& g) +{ + return f.m.u > g.m.u || (f.m.u == g.m.u && f.m.l > g.m.l); +} + +inline int operator<(const Fix48& f, const Fix48& g) +{ + return f.m.u < g.m.u || (f.m.u == g.m.u && f.m.l < g.m.l); +} + +inline istream& operator>>(istream& s, Fix48& f) +{ + double d; + s >> d; + f = d; + return s; +} + +inline ostream& operator<<(ostream& s, const Fix48& f) +{ + return s << double(f); +} + +#endif diff --git a/gnu/lib/libg++/include/Geom.h b/gnu/lib/libg++/include/Geom.h new file mode 100644 index 0000000..5cfa39a --- /dev/null +++ b/gnu/lib/libg++/include/Geom.h @@ -0,0 +1,52 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _Geometric_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Geometric_h + +#include <Random.h> + +class Geometric: public Random { +protected: + double pMean; +public: + Geometric(double mean, RNG *gen); + + double mean(); + double mean(double x); + + virtual double operator()(); + +}; + + +inline Geometric::Geometric(double mean, RNG *gen) : Random(gen) +{ + pMean = mean; +} + + +inline double Geometric::mean() { return pMean; } +inline double Geometric::mean(double x) { + double tmp = pMean; pMean = x; return tmp; +} + + +#endif diff --git a/gnu/lib/libg++/include/GetOpt.h b/gnu/lib/libg++/include/GetOpt.h new file mode 100644 index 0000000..66ecf5c --- /dev/null +++ b/gnu/lib/libg++/include/GetOpt.h @@ -0,0 +1,129 @@ +/* Getopt for GNU. + Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. + (Modified by Douglas C. Schmidt for use with GNU G++.) + +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. +*/ + + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of `argv' so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable _POSIX_OPTION_ORDER disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#ifndef GetOpt_h +#ifdef __GNUG__ +#pragma interface +#endif +#define GetOpt_h 1 + +#include <std.h> +#include <stdio.h> + +class GetOpt +{ +private: + /* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + + static char *nextchar; + + + /* Describe how to deal with options that follow non-option ARGV-elements. + + UNSPECIFIED means the caller did not specify anything; + the default is then REQUIRE_ORDER if the environment variable + _OPTIONS_FIRST is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options. + Stop option processing when the first non-option is seen. + This is what Unix does. + + PERMUTE is the default. We permute the contents of `argv' as we scan, + so that eventually all the options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code zero. + Using `-' as the first character of the list of option characters + requests this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return EOF with `optind' != ARGC. */ + + enum OrderingEnum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER }; + OrderingEnum ordering; + + /* Handle permutation of arguments. */ + + /* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + + static int first_nonopt; + static int last_nonopt; + + void exchange (char **argv); +public: + /* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + + char *optarg; + + /* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + + int optind; + + /* Callers store zero here to inhibit the error message + for unrecognized options. */ + + int opterr; + + int nargc; + char **nargv; + const char *noptstring; + + GetOpt (int argc, char **argv, const char *optstring); + int operator () (void); +}; + +#endif diff --git a/gnu/lib/libg++/include/HypGeom.h b/gnu/lib/libg++/include/HypGeom.h new file mode 100644 index 0000000..e16e655 --- /dev/null +++ b/gnu/lib/libg++/include/HypGeom.h @@ -0,0 +1,70 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _HyperGeometric_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _HyperGeometric_h + +#include <Random.h> + +class HyperGeometric: public Random { +protected: + double pMean; + double pVariance; + double pP; + void setState(); + +public: + HyperGeometric(double mean, double variance, RNG *gen); + + double mean(); + double mean(double x); + double variance(); + double variance(double x); + + virtual double operator()(); +}; + + +inline void HyperGeometric::setState() { + double z = pVariance / (pMean * pMean); + pP = 0.5 * (1.0 - sqrt((z - 1.0) / ( z + 1.0 ))); +} + +inline HyperGeometric::HyperGeometric(double mean, double variance, RNG *gen) +: Random(gen) { + pMean = mean; pVariance = variance; + setState(); +} + +inline double HyperGeometric::mean() { return pMean; }; + +inline double HyperGeometric::mean(double x) { + double t = pMean; pMean = x; + setState(); return t; +} + +inline double HyperGeometric::variance() { return pVariance; } + +inline double HyperGeometric::variance(double x) { + double t = pVariance; pVariance = x; + setState(); return t; +} + +#endif diff --git a/gnu/lib/libg++/include/Integer.h b/gnu/lib/libg++/include/Integer.h new file mode 100644 index 0000000..7e67ae5 --- /dev/null +++ b/gnu/lib/libg++/include/Integer.h @@ -0,0 +1,1119 @@ +// 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. +*/ + +#ifndef _Integer_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Integer_h 1 + +#include <iostream.h> + +struct IntRep // internal Integer representations +{ + unsigned short len; // current length + unsigned short sz; // allocated space (0 means static). + short sgn; // 1 means >= 0; 0 means < 0 + unsigned short s[1]; // represented as ushort array starting here +}; + +// True if REP is staticly (or manually) allocated, +// and should not be deleted by an Integer destructor. +#define STATIC_IntRep(rep) ((rep)->sz==0) + +extern IntRep* Ialloc(IntRep*, const unsigned short *, int, int, int); +extern IntRep* Icalloc(IntRep*, int); +extern IntRep* Icopy_ulong(IntRep*, unsigned long); +extern IntRep* Icopy_long(IntRep*, long); +extern IntRep* Icopy(IntRep*, const IntRep*); +extern IntRep* Iresize(IntRep*, int); +extern IntRep* add(const IntRep*, int, const IntRep*, int, IntRep*); +extern IntRep* add(const IntRep*, int, long, IntRep*); +extern IntRep* multiply(const IntRep*, const IntRep*, IntRep*); +extern IntRep* multiply(const IntRep*, long, IntRep*); +extern IntRep* lshift(const IntRep*, long, IntRep*); +extern IntRep* lshift(const IntRep*, const IntRep*, int, IntRep*); +extern IntRep* bitop(const IntRep*, const IntRep*, IntRep*, char); +extern IntRep* bitop(const IntRep*, long, IntRep*, char); +extern IntRep* power(const IntRep*, long, IntRep*); +extern IntRep* div(const IntRep*, const IntRep*, IntRep*); +extern IntRep* mod(const IntRep*, const IntRep*, IntRep*); +extern IntRep* div(const IntRep*, long, IntRep*); +extern IntRep* mod(const IntRep*, long, IntRep*); +extern IntRep* compl(const IntRep*, IntRep*); +extern IntRep* abs(const IntRep*, IntRep*); +extern IntRep* negate(const IntRep*, IntRep*); +extern IntRep* pow(const IntRep*, long); +extern IntRep* gcd(const IntRep*, const IntRep* y); +extern int compare(const IntRep*, const IntRep*); +extern int compare(const IntRep*, long); +extern int ucompare(const IntRep*, const IntRep*); +extern int ucompare(const IntRep*, long); +extern char* Itoa(const IntRep* x, int base = 10, int width = 0); +extern char* cvtItoa(const IntRep* x, char* fmt, int& fmtlen, int base, + int showbase, int width, int align_right, + char fillchar, char Xcase, int showpos); +extern IntRep* atoIntRep(const char* s, int base = 10); +extern long Itolong(const IntRep*); +extern int Iislong(const IntRep*); +extern long lg(const IntRep*); + +extern IntRep _ZeroRep, _OneRep, _MinusOneRep; + +class Integer +{ +protected: + IntRep* rep; +public: + Integer(); + Integer(int); + Integer(long); + Integer(unsigned long); + Integer(IntRep*); + Integer(const Integer&); + + ~Integer(); + Integer& operator = (const Integer&); + Integer& operator = (long); + +// unary operations to self + + Integer& operator ++ (); + Integer& operator -- (); + void negate(); // negate in-place + void abs(); // absolute-value in-place + void complement(); // bitwise complement in-place + +// assignment-based operations + + Integer& operator += (const Integer&); + Integer& operator -= (const Integer&); + Integer& operator *= (const Integer&); + Integer& operator /= (const Integer&); + Integer& operator %= (const Integer&); + Integer& operator <<=(const Integer&); + Integer& operator >>=(const Integer&); + Integer& operator &= (const Integer&); + Integer& operator |= (const Integer&); + Integer& operator ^= (const Integer&); + + Integer& operator += (long); + Integer& operator -= (long); + Integer& operator *= (long); + Integer& operator /= (long); + Integer& operator %= (long); + Integer& operator <<=(long); + Integer& operator >>=(long); + Integer& operator &= (long); + Integer& operator |= (long); + Integer& operator ^= (long); + +// (constructive binary operations are inlined below) + +#if defined (__GNUG__) && ! defined (__STRICT_ANSI__) + friend Integer operator <? (const Integer& x, const Integer& y); // min + friend Integer operator >? (const Integer& x, const Integer& y); // max +#endif + +// builtin Integer functions that must be friends + + friend long lg (const Integer&); // floor log base 2 of abs(x) + friend double ratio(const Integer& x, const Integer& y); + // return x/y as a double + + friend Integer gcd(const Integer&, const Integer&); + friend int even(const Integer&); // true if even + friend int odd(const Integer&); // true if odd + friend int sign(const Integer&); // returns -1, 0, +1 + + friend void (setbit)(Integer& x, long b); // set b'th bit of x + friend void clearbit(Integer& x, long b); // clear b'th bit + friend int testbit(const Integer& x, long b); // return b'th bit + +// procedural versions of operators + + friend void abs(const Integer& x, Integer& dest); + friend void negate(const Integer& x, Integer& dest); + friend void complement(const Integer& x, Integer& dest); + + friend int compare(const Integer&, const Integer&); + friend int ucompare(const Integer&, const Integer&); + friend void add(const Integer& x, const Integer& y, Integer& dest); + friend void sub(const Integer& x, const Integer& y, Integer& dest); + friend void mul(const Integer& x, const Integer& y, Integer& dest); + friend void div(const Integer& x, const Integer& y, Integer& dest); + friend void mod(const Integer& x, const Integer& y, Integer& dest); + friend void divide(const Integer& x, const Integer& y, + Integer& q, Integer& r); + friend void and(const Integer& x, const Integer& y, Integer& dest); + friend void or(const Integer& x, const Integer& y, Integer& dest); + friend void xor(const Integer& x, const Integer& y, Integer& dest); + friend void lshift(const Integer& x, const Integer& y, Integer& dest); + friend void rshift(const Integer& x, const Integer& y, Integer& dest); + friend void pow(const Integer& x, const Integer& y, Integer& dest); + + friend int compare(const Integer&, long); + friend int ucompare(const Integer&, long); + friend void add(const Integer& x, long y, Integer& dest); + friend void sub(const Integer& x, long y, Integer& dest); + friend void mul(const Integer& x, long y, Integer& dest); + friend void div(const Integer& x, long y, Integer& dest); + friend void mod(const Integer& x, long y, Integer& dest); + friend void divide(const Integer& x, long y, Integer& q, long& r); + friend void and(const Integer& x, long y, Integer& dest); + friend void or(const Integer& x, long y, Integer& dest); + friend void xor(const Integer& x, long y, Integer& dest); + friend void lshift(const Integer& x, long y, Integer& dest); + friend void rshift(const Integer& x, long y, Integer& dest); + friend void pow(const Integer& x, long y, Integer& dest); + + friend int compare(long, const Integer&); + friend int ucompare(long, const Integer&); + friend void add(long x, const Integer& y, Integer& dest); + friend void sub(long x, const Integer& y, Integer& dest); + friend void mul(long x, const Integer& y, Integer& dest); + friend void and(long x, const Integer& y, Integer& dest); + friend void or(long x, const Integer& y, Integer& dest); + friend void xor(long x, const Integer& y, Integer& dest); + +// coercion & conversion + + int fits_in_long() const { return Iislong(rep); } + int fits_in_double() const; + + long as_long() const { return Itolong(rep); } + double as_double() const; + + friend char* Itoa(const Integer& x, int base = 10, int width = 0); + friend Integer atoI(const char* s, int base = 10); + void printon(ostream& s, int base = 10, int width = 0) const; + + friend istream& operator >> (istream& s, Integer& y); + friend ostream& operator << (ostream& s, const Integer& y); + +// error detection + + int initialized() const; + void error(const char* msg) const; + int OK() const; +}; + + +// (These are declared inline) + + int operator == (const Integer&, const Integer&); + int operator == (const Integer&, long); + int operator != (const Integer&, const Integer&); + int operator != (const Integer&, long); + int operator < (const Integer&, const Integer&); + int operator < (const Integer&, long); + int operator <= (const Integer&, const Integer&); + int operator <= (const Integer&, long); + int operator > (const Integer&, const Integer&); + int operator > (const Integer&, long); + int operator >= (const Integer&, const Integer&); + int operator >= (const Integer&, long); + Integer operator - (const Integer&); + Integer operator ~ (const Integer&); + Integer operator + (const Integer&, const Integer&); + Integer operator + (const Integer&, long); + Integer operator + (long, const Integer&); + Integer operator - (const Integer&, const Integer&); + Integer operator - (const Integer&, long); + Integer operator - (long, const Integer&); + Integer operator * (const Integer&, const Integer&); + Integer operator * (const Integer&, long); + Integer operator * (long, const Integer&); + Integer operator / (const Integer&, const Integer&); + Integer operator / (const Integer&, long); + Integer operator % (const Integer&, const Integer&); + Integer operator % (const Integer&, long); + Integer operator << (const Integer&, const Integer&); + Integer operator << (const Integer&, long); + Integer operator >> (const Integer&, const Integer&); + Integer operator >> (const Integer&, long); + Integer operator & (const Integer&, const Integer&); + Integer operator & (const Integer&, long); + Integer operator & (long, const Integer&); + Integer operator | (const Integer&, const Integer&); + Integer operator | (const Integer&, long); + Integer operator | (long, const Integer&); + Integer operator ^ (const Integer&, const Integer&); + Integer operator ^ (const Integer&, long); + Integer operator ^ (long, const Integer&); + + Integer abs(const Integer&); // absolute value + Integer sqr(const Integer&); // square + + Integer pow(const Integer& x, const Integer& y); + Integer pow(const Integer& x, long y); + Integer Ipow(long x, long y); // x to the y as Integer + + +extern char* dec(const Integer& x, int width = 0); +extern char* oct(const Integer& x, int width = 0); +extern char* hex(const Integer& x, int width = 0); +extern Integer sqrt(const Integer&); // floor of square root +extern Integer lcm(const Integer& x, const Integer& y); // least common mult + + +typedef Integer IntTmp; // for backward compatibility + +inline Integer::Integer() :rep(&_ZeroRep) {} + +inline Integer::Integer(IntRep* r) :rep(r) {} + +inline Integer::Integer(int y) :rep(Icopy_long(0, (long)y)) {} + +inline Integer::Integer(long y) :rep(Icopy_long(0, y)) {} + +inline Integer::Integer(unsigned long y) :rep(Icopy_ulong(0, y)) {} + +inline Integer::Integer(const Integer& y) :rep(Icopy(0, y.rep)) {} + +inline Integer::~Integer() { if (rep && !STATIC_IntRep(rep)) delete rep; } + +inline Integer& Integer::operator = (const Integer& y) +{ + rep = Icopy(rep, y.rep); + return *this; +} + +inline Integer& Integer::operator = (long y) +{ + rep = Icopy_long(rep, y); + return *this; +} + +inline int Integer::initialized() const +{ + return rep != 0; +} + +// procedural versions + +inline int compare(const Integer& x, const Integer& y) +{ + return compare(x.rep, y.rep); +} + +inline int ucompare(const Integer& x, const Integer& y) +{ + return ucompare(x.rep, y.rep); +} + +inline int compare(const Integer& x, long y) +{ + return compare(x.rep, y); +} + +inline int ucompare(const Integer& x, long y) +{ + return ucompare(x.rep, y); +} + +inline int compare(long x, const Integer& y) +{ + return -compare(y.rep, x); +} + +inline int ucompare(long x, const Integer& y) +{ + return -ucompare(y.rep, x); +} + +inline void add(const Integer& x, const Integer& y, Integer& dest) +{ + dest.rep = add(x.rep, 0, y.rep, 0, dest.rep); +} + +inline void sub(const Integer& x, const Integer& y, Integer& dest) +{ + dest.rep = add(x.rep, 0, y.rep, 1, dest.rep); +} + +inline void mul(const Integer& x, const Integer& y, Integer& dest) +{ + dest.rep = multiply(x.rep, y.rep, dest.rep); +} + +inline void div(const Integer& x, const Integer& y, Integer& dest) +{ + dest.rep = div(x.rep, y.rep, dest.rep); +} + +inline void mod(const Integer& x, const Integer& y, Integer& dest) +{ + dest.rep = mod(x.rep, y.rep, dest.rep); +} + +inline void and(const Integer& x, const Integer& y, Integer& dest) +{ + dest.rep = bitop(x.rep, y.rep, dest.rep, '&'); +} + +inline void or(const Integer& x, const Integer& y, Integer& dest) +{ + dest.rep = bitop(x.rep, y.rep, dest.rep, '|'); +} + +inline void xor(const Integer& x, const Integer& y, Integer& dest) +{ + dest.rep = bitop(x.rep, y.rep, dest.rep, '^'); +} + +inline void lshift(const Integer& x, const Integer& y, Integer& dest) +{ + dest.rep = lshift(x.rep, y.rep, 0, dest.rep); +} + +inline void rshift(const Integer& x, const Integer& y, Integer& dest) +{ + dest.rep = lshift(x.rep, y.rep, 1, dest.rep); +} + +inline void pow(const Integer& x, const Integer& y, Integer& dest) +{ + dest.rep = power(x.rep, Itolong(y.rep), dest.rep); // not incorrect +} + +inline void add(const Integer& x, long y, Integer& dest) +{ + dest.rep = add(x.rep, 0, y, dest.rep); +} + +inline void sub(const Integer& x, long y, Integer& dest) +{ + dest.rep = add(x.rep, 0, -y, dest.rep); +} + +inline void mul(const Integer& x, long y, Integer& dest) +{ + dest.rep = multiply(x.rep, y, dest.rep); +} + +inline void div(const Integer& x, long y, Integer& dest) +{ + dest.rep = div(x.rep, y, dest.rep); +} + +inline void mod(const Integer& x, long y, Integer& dest) +{ + dest.rep = mod(x.rep, y, dest.rep); +} + +inline void and(const Integer& x, long y, Integer& dest) +{ + dest.rep = bitop(x.rep, y, dest.rep, '&'); +} + +inline void or(const Integer& x, long y, Integer& dest) +{ + dest.rep = bitop(x.rep, y, dest.rep, '|'); +} + +inline void xor(const Integer& x, long y, Integer& dest) +{ + dest.rep = bitop(x.rep, y, dest.rep, '^'); +} + +inline void lshift(const Integer& x, long y, Integer& dest) +{ + dest.rep = lshift(x.rep, y, dest.rep); +} + +inline void rshift(const Integer& x, long y, Integer& dest) +{ + dest.rep = lshift(x.rep, -y, dest.rep); +} + +inline void pow(const Integer& x, long y, Integer& dest) +{ + dest.rep = power(x.rep, y, dest.rep); +} + +inline void abs(const Integer& x, Integer& dest) +{ + dest.rep = abs(x.rep, dest.rep); +} + +inline void negate(const Integer& x, Integer& dest) +{ + dest.rep = negate(x.rep, dest.rep); +} + +inline void complement(const Integer& x, Integer& dest) +{ + dest.rep = compl(x.rep, dest.rep); +} + +inline void add(long x, const Integer& y, Integer& dest) +{ + dest.rep = add(y.rep, 0, x, dest.rep); +} + +inline void sub(long x, const Integer& y, Integer& dest) +{ + dest.rep = add(y.rep, 1, x, dest.rep); +} + +inline void mul(long x, const Integer& y, Integer& dest) +{ + dest.rep = multiply(y.rep, x, dest.rep); +} + +inline void and(long x, const Integer& y, Integer& dest) +{ + dest.rep = bitop(y.rep, x, dest.rep, '&'); +} + +inline void or(long x, const Integer& y, Integer& dest) +{ + dest.rep = bitop(y.rep, x, dest.rep, '|'); +} + +inline void xor(long x, const Integer& y, Integer& dest) +{ + dest.rep = bitop(y.rep, x, dest.rep, '^'); +} + + +// operator versions + +inline int operator == (const Integer& x, const Integer& y) +{ + return compare(x, y) == 0; +} + +inline int operator == (const Integer& x, long y) +{ + return compare(x, y) == 0; +} + +inline int operator != (const Integer& x, const Integer& y) +{ + return compare(x, y) != 0; +} + +inline int operator != (const Integer& x, long y) +{ + return compare(x, y) != 0; +} + +inline int operator < (const Integer& x, const Integer& y) +{ + return compare(x, y) < 0; +} + +inline int operator < (const Integer& x, long y) +{ + return compare(x, y) < 0; +} + +inline int operator <= (const Integer& x, const Integer& y) +{ + return compare(x, y) <= 0; +} + +inline int operator <= (const Integer& x, long y) +{ + return compare(x, y) <= 0; +} + +inline int operator > (const Integer& x, const Integer& y) +{ + return compare(x, y) > 0; +} + +inline int operator > (const Integer& x, long y) +{ + return compare(x, y) > 0; +} + +inline int operator >= (const Integer& x, const Integer& y) +{ + return compare(x, y) >= 0; +} + +inline int operator >= (const Integer& x, long y) +{ + return compare(x, y) >= 0; +} + + +inline Integer& Integer::operator += (const Integer& y) +{ + add(*this, y, *this); + return *this; +} + +inline Integer& Integer::operator += (long y) +{ + add(*this, y, *this); + return *this; +} + +inline Integer& Integer::operator ++ () +{ + add(*this, 1, *this); + return *this; +} + + +inline Integer& Integer::operator -= (const Integer& y) +{ + sub(*this, y, *this); + return *this; +} + +inline Integer& Integer::operator -= (long y) +{ + sub(*this, y, *this); + return *this; +} + +inline Integer& Integer::operator -- () +{ + add(*this, -1, *this); + return *this; +} + + + +inline Integer& Integer::operator *= (const Integer& y) +{ + mul(*this, y, *this); + return *this; +} + +inline Integer& Integer::operator *= (long y) +{ + mul(*this, y, *this); + return *this; +} + + +inline Integer& Integer::operator &= (const Integer& y) +{ + and(*this, y, *this); + return *this; +} + +inline Integer& Integer::operator &= (long y) +{ + and(*this, y, *this); + return *this; +} + +inline Integer& Integer::operator |= (const Integer& y) +{ + or(*this, y, *this); + return *this; +} + +inline Integer& Integer::operator |= (long y) +{ + or(*this, y, *this); + return *this; +} + + +inline Integer& Integer::operator ^= (const Integer& y) +{ + xor(*this, y, *this); + return *this; +} + +inline Integer& Integer::operator ^= (long y) +{ + xor(*this, y, *this); + return *this; +} + + + +inline Integer& Integer::operator /= (const Integer& y) +{ + div(*this, y, *this); + return *this; +} + +inline Integer& Integer::operator /= (long y) +{ + div(*this, y, *this); + return *this; +} + + +inline Integer& Integer::operator <<= (const Integer& y) +{ + lshift(*this, y, *this); + return *this; +} + +inline Integer& Integer::operator <<= (long y) +{ + lshift(*this, y, *this); + return *this; +} + + +inline Integer& Integer::operator >>= (const Integer& y) +{ + rshift(*this, y, *this); + return *this; +} + +inline Integer& Integer::operator >>= (long y) +{ + rshift(*this, y, *this); + return *this; +} + +#if defined (__GNUG__) && ! defined (__STRICT_ANSI__) +inline Integer operator <? (const Integer& x, const Integer& y) +{ + return (compare(x.rep, y.rep) <= 0) ? x : y; +} + +inline Integer operator >? (const Integer& x, const Integer& y) +{ + return (compare(x.rep, y.rep) >= 0)? x : y; +} +#endif + + +inline void Integer::abs() +{ + ::abs(*this, *this); +} + +inline void Integer::negate() +{ + ::negate(*this, *this); +} + + +inline void Integer::complement() +{ + ::complement(*this, *this); +} + + +inline int sign(const Integer& x) +{ + return (x.rep->len == 0) ? 0 : ( (x.rep->sgn == 1) ? 1 : -1 ); +} + +inline int even(const Integer& y) +{ + return y.rep->len == 0 || !(y.rep->s[0] & 1); +} + +inline int odd(const Integer& y) +{ + return y.rep->len > 0 && (y.rep->s[0] & 1); +} + +inline char* Itoa(const Integer& y, int base, int width) +{ + return Itoa(y.rep, base, width); +} + + + +inline long lg(const Integer& x) +{ + return lg(x.rep); +} + +// constructive operations + +#if defined(__GNUG__) && !defined(_G_NO_NRV) + +inline Integer operator + (const Integer& x, const Integer& y) return r +{ + add(x, y, r); +} + +inline Integer operator + (const Integer& x, long y) return r +{ + add(x, y, r); +} + +inline Integer operator + (long x, const Integer& y) return r +{ + add(x, y, r); +} + +inline Integer operator - (const Integer& x, const Integer& y) return r +{ + sub(x, y, r); +} + +inline Integer operator - (const Integer& x, long y) return r +{ + sub(x, y, r); +} + +inline Integer operator - (long x, const Integer& y) return r +{ + sub(x, y, r); +} + +inline Integer operator * (const Integer& x, const Integer& y) return r +{ + mul(x, y, r); +} + +inline Integer operator * (const Integer& x, long y) return r +{ + mul(x, y, r); +} + +inline Integer operator * (long x, const Integer& y) return r +{ + mul(x, y, r); +} + +inline Integer sqr(const Integer& x) return r +{ + mul(x, x, r); +} + +inline Integer operator & (const Integer& x, const Integer& y) return r +{ + and(x, y, r); +} + +inline Integer operator & (const Integer& x, long y) return r +{ + and(x, y, r); +} + +inline Integer operator & (long x, const Integer& y) return r +{ + and(x, y, r); +} + +inline Integer operator | (const Integer& x, const Integer& y) return r +{ + or(x, y, r); +} + +inline Integer operator | (const Integer& x, long y) return r +{ + or(x, y, r); +} + +inline Integer operator | (long x, const Integer& y) return r +{ + or(x, y, r); +} + +inline Integer operator ^ (const Integer& x, const Integer& y) return r +{ + xor(x, y, r); +} + +inline Integer operator ^ (const Integer& x, long y) return r +{ + xor(x, y, r); +} + +inline Integer operator ^ (long x, const Integer& y) return r +{ + xor(x, y, r); +} + +inline Integer operator / (const Integer& x, const Integer& y) return r +{ + div(x, y, r); +} + +inline Integer operator / (const Integer& x, long y) return r +{ + div(x, y, r); +} + +inline Integer operator % (const Integer& x, const Integer& y) return r +{ + mod(x, y, r); +} + +inline Integer operator % (const Integer& x, long y) return r +{ + mod(x, y, r); +} + +inline Integer operator << (const Integer& x, const Integer& y) return r +{ + lshift(x, y, r); +} + +inline Integer operator << (const Integer& x, long y) return r +{ + lshift(x, y, r); +} + +inline Integer operator >> (const Integer& x, const Integer& y) return r; +{ + rshift(x, y, r); +} + +inline Integer operator >> (const Integer& x, long y) return r +{ + rshift(x, y, r); +} + +inline Integer pow(const Integer& x, long y) return r +{ + pow(x, y, r); +} + +inline Integer Ipow(long x, long y) return r(x) +{ + pow(r, y, r); +} + +inline Integer pow(const Integer& x, const Integer& y) return r +{ + pow(x, y, r); +} + + + +inline Integer abs(const Integer& x) return r +{ + abs(x, r); +} + +inline Integer operator - (const Integer& x) return r +{ + negate(x, r); +} + +inline Integer operator ~ (const Integer& x) return r +{ + complement(x, r); +} + +inline Integer atoI(const char* s, int base) return r +{ + r.rep = atoIntRep(s, base); +} + +inline Integer gcd(const Integer& x, const Integer& y) return r +{ + r.rep = gcd(x.rep, y.rep); +} + +#else /* NO_NRV */ + +inline Integer operator + (const Integer& x, const Integer& y) +{ + Integer r; add(x, y, r); return r; +} + +inline Integer operator + (const Integer& x, long y) +{ + Integer r; add(x, y, r); return r; +} + +inline Integer operator + (long x, const Integer& y) +{ + Integer r; add(x, y, r); return r; +} + +inline Integer operator - (const Integer& x, const Integer& y) +{ + Integer r; sub(x, y, r); return r; +} + +inline Integer operator - (const Integer& x, long y) +{ + Integer r; sub(x, y, r); return r; +} + +inline Integer operator - (long x, const Integer& y) +{ + Integer r; sub(x, y, r); return r; +} + +inline Integer operator * (const Integer& x, const Integer& y) +{ + Integer r; mul(x, y, r); return r; +} + +inline Integer operator * (const Integer& x, long y) +{ + Integer r; mul(x, y, r); return r; +} + +inline Integer operator * (long x, const Integer& y) +{ + Integer r; mul(x, y, r); return r; +} + +inline Integer sqr(const Integer& x) +{ + Integer r; mul(x, x, r); return r; +} + +inline Integer operator & (const Integer& x, const Integer& y) +{ + Integer r; and(x, y, r); return r; +} + +inline Integer operator & (const Integer& x, long y) +{ + Integer r; and(x, y, r); return r; +} + +inline Integer operator & (long x, const Integer& y) +{ + Integer r; and(x, y, r); return r; +} + +inline Integer operator | (const Integer& x, const Integer& y) +{ + Integer r; or(x, y, r); return r; +} + +inline Integer operator | (const Integer& x, long y) +{ + Integer r; or(x, y, r); return r; +} + +inline Integer operator | (long x, const Integer& y) +{ + Integer r; or(x, y, r); return r; +} + +inline Integer operator ^ (const Integer& x, const Integer& y) +{ + Integer r; xor(x, y, r); return r; +} + +inline Integer operator ^ (const Integer& x, long y) +{ + Integer r; xor(x, y, r); return r; +} + +inline Integer operator ^ (long x, const Integer& y) +{ + Integer r; xor(x, y, r); return r; +} + +inline Integer operator / (const Integer& x, const Integer& y) +{ + Integer r; div(x, y, r); return r; +} + +inline Integer operator / (const Integer& x, long y) +{ + Integer r; div(x, y, r); return r; +} + +inline Integer operator % (const Integer& x, const Integer& y) +{ + Integer r; mod(x, y, r); return r; +} + +inline Integer operator % (const Integer& x, long y) +{ + Integer r; mod(x, y, r); return r; +} + +inline Integer operator << (const Integer& x, const Integer& y) +{ + Integer r; lshift(x, y, r); return r; +} + +inline Integer operator << (const Integer& x, long y) +{ + Integer r; lshift(x, y, r); return r; +} + +inline Integer operator >> (const Integer& x, const Integer& y) +{ + Integer r; rshift(x, y, r); return r; +} + +inline Integer operator >> (const Integer& x, long y) +{ + Integer r; rshift(x, y, r); return r; +} + +inline Integer pow(const Integer& x, long y) +{ + Integer r; pow(x, y, r); return r; +} + +inline Integer Ipow(long x, long y) +{ + Integer r(x); pow(r, y, r); return r; +} + +inline Integer pow(const Integer& x, const Integer& y) +{ + Integer r; pow(x, y, r); return r; +} + + + +inline Integer abs(const Integer& x) +{ + Integer r; abs(x, r); return r; +} + +inline Integer operator - (const Integer& x) +{ + Integer r; negate(x, r); return r; +} + +inline Integer operator ~ (const Integer& x) +{ + Integer r; complement(x, r); return r; +} + +inline Integer atoI(const char* s, int base) +{ + Integer r; r.rep = atoIntRep(s, base); return r; +} + +inline Integer gcd(const Integer& x, const Integer& y) +{ + Integer r; r.rep = gcd(x.rep, y.rep); return r; +} + +#endif /* NO_NRV */ + +inline Integer& Integer::operator %= (const Integer& y) +{ + *this = *this % y; // mod(*this, y, *this) doesn't work. + return *this; +} + +inline Integer& Integer::operator %= (long y) +{ + *this = *this % y; // mod(*this, y, *this) doesn't work. + return *this; +} +#endif /* !_Integer_h */ diff --git a/gnu/lib/libg++/include/Integer.hP b/gnu/lib/libg++/include/Integer.hP new file mode 100644 index 0000000..b8a8039 --- /dev/null +++ b/gnu/lib/libg++/include/Integer.hP @@ -0,0 +1,30 @@ +// Stuff used to implement the Integer class. +// WARNING: Its internals WILL change! + +/* + Sizes of shifts for multiple-precision arithmetic. + These should not be changed unless Integer representation + as unsigned shorts is changed in the implementation files. +*/ + +#define I_SHIFT (sizeof(short) * CHAR_BIT) +#define I_RADIX ((unsigned long)(1L << I_SHIFT)) +#define I_MAXNUM ((unsigned long)((I_RADIX - 1))) +#define I_MINNUM ((unsigned long)(I_RADIX >> 1)) +#define I_POSITIVE 1 +#define I_NEGATIVE 0 + +/* All routines assume SHORT_PER_LONG > 1 */ +#define SHORT_PER_LONG ((unsigned)(((sizeof(long) + sizeof(short) - 1) / sizeof(short)))) +#define CHAR_PER_LONG ((unsigned)sizeof(long)) + +/* + minimum and maximum sizes for an IntRep +*/ + +#define MINIntRep_SIZE 16 +#define MAXIntRep_SIZE I_MAXNUM + +#ifndef MALLOC_MIN_OVERHEAD +#define MALLOC_MIN_OVERHEAD 4 +#endif diff --git a/gnu/lib/libg++/include/LogNorm.h b/gnu/lib/libg++/include/LogNorm.h new file mode 100644 index 0000000..ac98141 --- /dev/null +++ b/gnu/lib/libg++/include/LogNorm.h @@ -0,0 +1,78 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _LogNormal_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _LogNormal_h + +#include <Normal.h> + +class LogNormal: public Normal { +protected: + double logMean; + double logVariance; + void setState(); +public: + LogNormal(double mean, double variance, RNG *gen); + double mean(); + double mean(double x); + double variance(); + double variance(double x); + virtual double operator()(); +}; + + +inline void LogNormal::setState() +{ + double m2 = logMean * logMean; + pMean = log(m2 / sqrt(logVariance + m2) ); +// from ch@heike.informatik.uni-dortmund.de: +// (was pVariance = log((sqrt(logVariance + m2)/m2 )); ) + pStdDev = sqrt(log((logVariance + m2)/m2 )); +} + +inline LogNormal::LogNormal(double mean, double variance, RNG *gen) + : Normal(mean, variance, gen) +{ + logMean = mean; + logVariance = variance; + setState(); +} + +inline double LogNormal::mean() { + return logMean; +} + +inline double LogNormal::mean(double x) +{ + double t=logMean; logMean = x; setState(); + return t; +} + +inline double LogNormal::variance() { + return logVariance; +} + +inline double LogNormal::variance(double x) +{ + double t=logVariance; logVariance = x; setState(); + return t; +} + +#endif diff --git a/gnu/lib/libg++/include/MLCG.h b/gnu/lib/libg++/include/MLCG.h new file mode 100644 index 0000000..8f104a1 --- /dev/null +++ b/gnu/lib/libg++/include/MLCG.h @@ -0,0 +1,87 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _MLCG_h +#define _MLCG_h 1 +#ifdef __GNUG__ +#pragma interface +#endif + +#include <RNG.h> +#include <math.h> + +// +// Multiplicative Linear Conguential Generator +// + +class MLCG : public RNG { + _G_int32_t initialSeedOne; + _G_int32_t initialSeedTwo; + _G_int32_t seedOne; + _G_int32_t seedTwo; + +protected: + +public: + MLCG(_G_int32_t seed1 = 0, _G_int32_t seed2 = 1); + // + // Return a long-words word of random bits + // + virtual unsigned long asLong(); + virtual void reset(); + _G_int32_t seed1(); + void seed1(_G_int32_t); + _G_int32_t seed2(); + void seed2(_G_int32_t); + void reseed(_G_int32_t, _G_int32_t); +}; + +inline _G_int32_t +MLCG::seed1() +{ + return(seedOne); +} + +inline void +MLCG::seed1(_G_int32_t s) +{ + initialSeedOne = s; + reset(); +} + +inline _G_int32_t +MLCG::seed2() +{ + return(seedTwo); +} + +inline void +MLCG::seed2(_G_int32_t s) +{ + initialSeedTwo = s; + reset(); +} + +inline void +MLCG::reseed(_G_int32_t s1, _G_int32_t s2) +{ + initialSeedOne = s1; + initialSeedTwo = s2; + reset(); +} + +#endif diff --git a/gnu/lib/libg++/include/NegExp.h b/gnu/lib/libg++/include/NegExp.h new file mode 100644 index 0000000..b96f913 --- /dev/null +++ b/gnu/lib/libg++/include/NegExp.h @@ -0,0 +1,55 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _NegativeExpntl_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _NegativeExpntl_h 1 + + +// +// Negative Exponential Random Numbers +// +// + +#include <Random.h> + +class NegativeExpntl: public Random { +protected: + double pMean; +public: + NegativeExpntl(double xmean, RNG *gen); + double mean(); + double mean(double x); + + virtual double operator()(); +}; + + +inline NegativeExpntl::NegativeExpntl(double xmean, RNG *gen) +: Random(gen) { + pMean = xmean; +} + +inline double NegativeExpntl::mean() { return pMean; } +inline double NegativeExpntl::mean(double x) { + double t = pMean; pMean = x; + return t; +} + +#endif diff --git a/gnu/lib/libg++/include/Normal.h b/gnu/lib/libg++/include/Normal.h new file mode 100644 index 0000000..8c8358e --- /dev/null +++ b/gnu/lib/libg++/include/Normal.h @@ -0,0 +1,66 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _Normal_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Normal_h + +#include <Random.h> + +class Normal: public Random { + char haveCachedNormal; + double cachedNormal; + +protected: + double pMean; + double pVariance; + double pStdDev; + +public: + Normal(double xmean, double xvariance, RNG *gen); + double mean(); + double mean(double x); + double variance(); + double variance(double x); + virtual double operator()(); +}; + + +inline Normal::Normal(double xmean, double xvariance, RNG *gen) +: Random(gen) { + pMean = xmean; + pVariance = xvariance; + pStdDev = sqrt(pVariance); + haveCachedNormal = 0; +} + +inline double Normal::mean() { return pMean; }; +inline double Normal::mean(double x) { + double t=pMean; pMean = x; + return t; +} + +inline double Normal::variance() { return pVariance; } +inline double Normal::variance(double x) { + double t=pVariance; pVariance = x; + pStdDev = sqrt(pVariance); + return t; +}; + +#endif diff --git a/gnu/lib/libg++/include/Obstack.h b/gnu/lib/libg++/include/Obstack.h new file mode 100644 index 0000000..384157f --- /dev/null +++ b/gnu/lib/libg++/include/Obstack.h @@ -0,0 +1,216 @@ +// 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. +*/ + + +#ifndef _Obstack_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Obstack_h 1 + +#include <std.h> + +class Obstack +{ + struct _obstack_chunk + { + char* limit; + _obstack_chunk* prev; + char contents[4]; + }; + +protected: + long chunksize; + _obstack_chunk* chunk; + char* objectbase; + char* nextfree; + char* chunklimit; + int alignmentmask; + + void _free(void* obj); + void newchunk(int size); + +public: + Obstack(int size = 4080, int alignment = 4); // 4080=4096-mallocslop + + ~Obstack(); + + void* base(); + void* next_free(); + int alignment_mask(); + int chunk_size(); + int size(); + int room(); + int contains(void* p); // does Obstack hold pointer p? + + void grow(const void* data, int size); + void grow(const void* data, int size, char terminator); + void grow(const char* s); + void grow(char c); + void grow_fast(char c); + void blank(int size); + void blank_fast(int size); + + void* finish(); + void* finish(char terminator); + + void* copy(const void* data, int size); + void* copy(const void* data, int size, char terminator); + void* copy(const char* s); + void* copy(char c); + void* alloc(int size); + + void free(void* obj); + void shrink(int size = 1); // suggested by ken@cs.rochester.edu + + int OK(); // rep invariant +}; + + +inline Obstack::~Obstack() +{ + _free(0); +} + +inline void* Obstack::base() +{ + return objectbase; +} + +inline void* Obstack::next_free() +{ + return nextfree; +} + +inline int Obstack::alignment_mask() +{ + return alignmentmask; +} + +inline int Obstack::chunk_size() +{ + return chunksize; +} + +inline int Obstack::size() +{ + return nextfree - objectbase; +} + +inline int Obstack::room() +{ + return chunklimit - nextfree; +} + +inline void Obstack:: grow(const void* data, int size) +{ + if (nextfree+size > chunklimit) + newchunk(size); + memcpy(nextfree, data, size); + nextfree += size; +} + +inline void Obstack:: grow(const void* data, int size, char terminator) +{ + if (nextfree+size+1 > chunklimit) + newchunk(size+1); + memcpy(nextfree, data, size); + nextfree += size; + *(nextfree)++ = terminator; +} + +inline void Obstack:: grow(const char* s) +{ + grow((const void*)s, strlen(s), 0); +} + +inline void Obstack:: grow(char c) +{ + if (nextfree+1 > chunklimit) + newchunk(1); + *(nextfree)++ = c; +} + +inline void Obstack:: blank(int size) +{ + if (nextfree+size > chunklimit) + newchunk(size); + nextfree += size; +} + +inline void* Obstack::finish(char terminator) +{ + grow(terminator); + return finish(); +} + +inline void* Obstack::copy(const void* data, int size) +{ + grow (data, size); + return finish(); +} + +inline void* Obstack::copy(const void* data, int size, char terminator) +{ + grow(data, size, terminator); + return finish(); +} + +inline void* Obstack::copy(const char* s) +{ + grow((const void*)s, strlen(s), 0); + return finish(); +} + +inline void* Obstack::copy(char c) +{ + grow(c); + return finish(); +} + +inline void* Obstack::alloc(int size) +{ + blank(size); + return finish(); +} + +inline void Obstack:: free(void* obj) +{ + if (obj >= (void*)chunk && obj<(void*)chunklimit) + nextfree = objectbase = (char *) obj; + else + _free(obj); +} + +inline void Obstack:: grow_fast(char c) +{ + *(nextfree)++ = c; +} + +inline void Obstack:: blank_fast(int size) +{ + nextfree += size; +} + +inline void Obstack:: shrink(int size) // from ken@cs.rochester.edu +{ + if (nextfree >= objectbase + size) + nextfree -= size; +} + +#endif diff --git a/gnu/lib/libg++/include/Pix.h b/gnu/lib/libg++/include/Pix.h new file mode 100644 index 0000000..be90525 --- /dev/null +++ b/gnu/lib/libg++/include/Pix.h @@ -0,0 +1,5 @@ + +#ifndef _Pix_h +#define _Pix_h 1 +typedef void* Pix; +#endif diff --git a/gnu/lib/libg++/include/PlotFile.h b/gnu/lib/libg++/include/PlotFile.h new file mode 100644 index 0000000..91ab6ae --- /dev/null +++ b/gnu/lib/libg++/include/PlotFile.h @@ -0,0 +1,121 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* + a very simple implementation of a class to output unix "plot" + format plotter files. See corresponding unix man pages for + more details. + + written by Doug Lea (dl@rocky.oswego.edu) + converted to use iostream library by Per Bothner (bothner@cygnus.com) +*/ + +#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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gnu/lib/libg++/include/Poisson.h b/gnu/lib/libg++/include/Poisson.h new file mode 100644 index 0000000..e585145 --- /dev/null +++ b/gnu/lib/libg++/include/Poisson.h @@ -0,0 +1,51 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _Poisson_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Poisson_h + +#include <Random.h> + +class Poisson: public Random { +protected: + double pMean; +public: + Poisson(double mean, RNG *gen); + + double mean(); + double mean(double x); + + virtual double operator()(); +}; + + +inline Poisson::Poisson(double mean, RNG *gen) +: Random(gen) { + pMean = mean; +} + +inline double Poisson::mean() { return pMean; } +inline double Poisson::mean(double x) { + double t = pMean; + pMean = x; + return t; +} + +#endif diff --git a/gnu/lib/libg++/include/RNG.h b/gnu/lib/libg++/include/RNG.h new file mode 100644 index 0000000..43d95b7 --- /dev/null +++ b/gnu/lib/libg++/include/RNG.h @@ -0,0 +1,58 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _RNG_h +#define _RNG_h 1 +#ifdef __GNUG__ +#pragma interface +#endif + +#include <assert.h> +#include <math.h> +#include <_G_config.h> + +union PrivateRNGSingleType { // used to access floats as unsigneds + float s; + _G_uint32_t u; +}; + +union PrivateRNGDoubleType { // used to access doubles as unsigneds + double d; + _G_uint32_t u[2]; +}; + +// +// Base class for Random Number Generators. See ACG and MLCG for instances. +// +class RNG { + static PrivateRNGSingleType singleMantissa; // mantissa bit vector + static PrivateRNGDoubleType doubleMantissa; // mantissa bit vector +public: + RNG(); + // + // Return a long-words word of random bits + // + virtual unsigned long asLong() = 0; + virtual void reset() = 0; + // + // Return random bits converted to either a float or a double + // + float asFloat(); + double asDouble(); +}; + +#endif diff --git a/gnu/lib/libg++/include/Random.h b/gnu/lib/libg++/include/Random.h new file mode 100644 index 0000000..925698f --- /dev/null +++ b/gnu/lib/libg++/include/Random.h @@ -0,0 +1,54 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _Random_h +#define _Random_h 1 +#ifdef __GNUG__ +#pragma interface +#endif + +#include <math.h> +#include <RNG.h> + +class Random { +protected: + RNG *pGenerator; +public: + Random(RNG *generator); + virtual double operator()() = 0; + + RNG *generator(); + void generator(RNG *p); +}; + + +inline Random::Random(RNG *gen) +{ + pGenerator = gen; +} + +inline RNG *Random::generator() +{ + return(pGenerator); +} + +inline void Random::generator(RNG *p) +{ + pGenerator = p; +} + +#endif diff --git a/gnu/lib/libg++/include/Rational.h b/gnu/lib/libg++/include/Rational.h new file mode 100644 index 0000000..131aabc --- /dev/null +++ b/gnu/lib/libg++/include/Rational.h @@ -0,0 +1,288 @@ +// 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. +*/ + +#ifndef _Rational_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Rational_h 1 + +#include <Integer.h> +#include <math.h> + +class Rational +{ +protected: + Integer num; + Integer den; + + void normalize(); + +public: + Rational(); + Rational(double); + Rational(int n); + Rational(long n); + Rational(int n, int d); + Rational(long n, long d); + Rational(long n, unsigned long d); + Rational(unsigned long n, long d); + Rational(unsigned long n, unsigned long d); + Rational(const Integer& n); + Rational(const Integer& n, const Integer& d); + Rational(const Rational&); + + ~Rational(); + + Rational& operator = (const Rational& y); + + friend int operator == (const Rational& x, const Rational& y); + friend int operator != (const Rational& x, const Rational& y); + friend int operator < (const Rational& x, const Rational& y); + friend int operator <= (const Rational& x, const Rational& y); + friend int operator > (const Rational& x, const Rational& y); + friend int operator >= (const Rational& x, const Rational& y); + + friend Rational operator + (const Rational& x, const Rational& y); + friend Rational operator - (const Rational& x, const Rational& y); + friend Rational operator * (const Rational& x, const Rational& y); + friend Rational operator / (const Rational& x, const Rational& y); + + Rational& operator += (const Rational& y); + Rational& operator -= (const Rational& y); + Rational& operator *= (const Rational& y); + Rational& operator /= (const Rational& y); + +#if defined (__GNUG__) && ! defined (__STRICT_ANSI__) + friend Rational operator <? (const Rational& x, const Rational& y); // min + friend Rational operator >? (const Rational& x, const Rational& y); // max +#endif + + friend Rational operator - (const Rational& x); + + +// builtin Rational functions + + + void negate(); // x = -x + void invert(); // x = 1/x + + friend int sign(const Rational& x); // -1, 0, or +1 + friend Rational abs(const Rational& x); // absolute value + friend Rational sqr(const Rational& x); // square + friend Rational pow(const Rational& x, long y); + friend Rational pow(const Rational& x, const Integer& y); + const Integer& numerator() const; + const Integer& denominator() const; + +// coercion & conversion + + operator double() const; + friend Integer floor(const Rational& x); + friend Integer ceil(const Rational& x); + friend Integer trunc(const Rational& x); + friend Integer round(const Rational& x); + + friend istream& operator >> (istream& s, Rational& y); + friend ostream& operator << (ostream& s, const Rational& y); + + int fits_in_float() const; + int fits_in_double() const; + +// procedural versions of operators + + friend int compare(const Rational& x, const Rational& y); + friend void add(const Rational& x, const Rational& y, Rational& dest); + friend void sub(const Rational& x, const Rational& y, Rational& dest); + friend void mul(const Rational& x, const Rational& y, Rational& dest); + friend void div(const Rational& x, const Rational& y, Rational& dest); + +// error detection + + void error(const char* msg) const; + int OK() const; + +}; + +typedef Rational RatTmp; // backwards compatibility + +inline Rational::Rational() : num(&_ZeroRep), den(&_OneRep) {} +inline Rational::~Rational() {} + +inline Rational::Rational(const Rational& y) :num(y.num), den(y.den) {} + +inline Rational::Rational(const Integer& n) :num(n), den(&_OneRep) {} + +inline Rational::Rational(const Integer& n, const Integer& d) :num(n),den(d) +{ + normalize(); +} + +inline Rational::Rational(long n) :num(n), den(&_OneRep) { } + +inline Rational::Rational(int n) :num(n), den(&_OneRep) { } + +inline Rational::Rational(long n, long d) :num(n), den(d) { normalize(); } +inline Rational::Rational(int n, int d) :num(n), den(d) { normalize(); } +inline Rational::Rational(long n, unsigned long d) :num(n), den(d) +{ + normalize(); +} +inline Rational::Rational(unsigned long n, long d) :num(n), den(d) +{ + normalize(); +} +inline Rational::Rational(unsigned long n, unsigned long d) :num(n), den(d) +{ + normalize(); +} + +inline Rational& Rational::operator = (const Rational& y) +{ + num = y.num; den = y.den; + return *this; +} + +inline int operator == (const Rational& x, const Rational& y) +{ + return compare(x.num, y.num) == 0 && compare(x.den, y.den) == 0; +} + +inline int operator != (const Rational& x, const Rational& y) +{ + return compare(x.num, y.num) != 0 || compare(x.den, y.den) != 0; +} + +inline int operator < (const Rational& x, const Rational& y) +{ + return compare(x, y) < 0; +} + +inline int operator <= (const Rational& x, const Rational& y) +{ + return compare(x, y) <= 0; +} + +inline int operator > (const Rational& x, const Rational& y) +{ + return compare(x, y) > 0; +} + +inline int operator >= (const Rational& x, const Rational& y) +{ + return compare(x, y) >= 0; +} + +inline int sign(const Rational& x) +{ + return sign(x.num); +} + +inline void Rational::negate() +{ + num.negate(); +} + + +inline Rational& Rational::operator += (const Rational& y) +{ + add(*this, y, *this); + return *this; +} + +inline Rational& Rational::operator -= (const Rational& y) +{ + sub(*this, y, *this); + return *this; +} + +inline Rational& Rational::operator *= (const Rational& y) +{ + mul(*this, y, *this); + return *this; +} + +inline Rational& Rational::operator /= (const Rational& y) +{ + div(*this, y, *this); + return *this; +} + +inline const Integer& Rational::numerator() const { return num; } +inline const Integer& Rational::denominator() const { return den; } +inline Rational::operator double() const { return ratio(num, den); } + +#if defined (__GNUG__) && ! defined (__STRICT_ANSI__) +inline Rational operator <? (const Rational& x, const Rational& y) +{ + if (compare(x, y) <= 0) return x; else return y; +} + +inline Rational operator >? (const Rational& x, const Rational& y) +{ + if (compare(x, y) >= 0) return x; else return y; +} +#endif + +#if defined(__GNUG__) && !defined(_G_NO_NRV) + +inline Rational operator + (const Rational& x, const Rational& y) return r +{ + add(x, y, r); +} + +inline Rational operator - (const Rational& x, const Rational& y) return r +{ + sub(x, y, r); +} + +inline Rational operator * (const Rational& x, const Rational& y) return r +{ + mul(x, y, r); +} + +inline Rational operator / (const Rational& x, const Rational& y) return r +{ + div(x, y, r); +} + +#else /* NO_NRV */ + +inline Rational operator + (const Rational& x, const Rational& y) +{ + Rational r; add(x, y, r); return r; +} + +inline Rational operator - (const Rational& x, const Rational& y) +{ + Rational r; sub(x, y, r); return r; +} + +inline Rational operator * (const Rational& x, const Rational& y) +{ + Rational r; mul(x, y, r); return r; +} + +inline Rational operator / (const Rational& x, const Rational& y) +{ + Rational r; div(x, y, r); return r; +} +#endif + +#endif diff --git a/gnu/lib/libg++/include/Regex.h b/gnu/lib/libg++/include/Regex.h new file mode 100644 index 0000000..c8cf731 --- /dev/null +++ b/gnu/lib/libg++/include/Regex.h @@ -0,0 +1,76 @@ +// 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. +*/ + + +#ifndef _Regex_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Regex_h 1 + +#if defined(SHORT_NAMES) || defined(VMS) +#define re_compile_pattern recmppat +#define re_pattern_buffer repatbuf +#define re_registers reregs +#endif + +struct re_pattern_buffer; // defined elsewhere +struct re_registers; + +class Regex +{ +private: + + Regex(const Regex&) {} // no X(X&) + void operator = (const Regex&) {} // no assignment + +protected: + re_pattern_buffer* buf; + re_registers* reg; + +public: + Regex(const char* t, + int fast = 0, + int bufsize = 40, + const char* transtable = 0); + + ~Regex(); + + int match(const char* s, int len, int pos = 0) const; + int search(const char* s, int len, + int& matchlen, int startpos = 0) const; + int match_info(int& start, int& length, int nth = 0) const; + + int OK() const; // representation invariant +}; + +// some built in regular expressions + +extern const Regex RXwhite; // = "[ \n\t\r\v\f]+" +extern const Regex RXint; // = "-?[0-9]+" +extern const Regex RXdouble; // = "-?\\(\\([0-9]+\\.[0-9]*\\)\\| + // \\([0-9]+\\)\\|\\(\\.[0-9]+\\)\\) + // \\([eE][---+]?[0-9]+\\)?" +extern const Regex RXalpha; // = "[A-Za-z]+" +extern const Regex RXlowercase; // = "[a-z]+" +extern const Regex RXuppercase; // = "[A-Z]+" +extern const Regex RXalphanum; // = "[0-9A-Za-z]+" +extern const Regex RXidentifier; // = "[A-Za-z_][A-Za-z0-9_]*" + + +#endif diff --git a/gnu/lib/libg++/include/RndInt.h b/gnu/lib/libg++/include/RndInt.h new file mode 100644 index 0000000..b16c7f8 --- /dev/null +++ b/gnu/lib/libg++/include/RndInt.h @@ -0,0 +1,175 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1990 Free Software Foundation + adapted from a submission from John Reidl <riedl@cs.purdue.edu> + + +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 +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. +*/ + +#ifndef _RandomInteger_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _RandomInteger_h 1 + +// RandomInteger uses a random number generator to generate an integer +// in a specified range. By default the range is 0..1. Since in my +// experience random numbers are often needed for a wide variety of +// ranges in the same program, this generator accepts a new low or high value +// as an argument to the asLong and operator() methods to temporarily +// override stored values + +#include <math.h> +#include <RNG.h> + +class RandomInteger +{ + protected: + RNG *pGenerator; + long pLow; + long pHigh; + + long _asLong(long, long); + + public: + + RandomInteger(long low, long high, RNG *gen); + RandomInteger(long high, RNG *gen); + RandomInteger(RNG *gen); + +// read params + + long low() const; + long high() const; + RNG* generator() const; + +// change params + + long low(long x); + long high(long x); + RNG* generator(RNG *gen); + +// get a random number + + long asLong(); + long operator()(); // synonym for asLong + int asInt(); // (possibly) truncate as int + +// override params for one shot + + long asLong(long high); + long asLong(long low, long high); + + long operator () (long high); // synonyms + long operator () (long low, long high); + +}; + + +inline RandomInteger::RandomInteger(long low, long high, RNG *gen) + : pLow((low < high) ? low : high), + pHigh((low < high) ? high : low), + pGenerator(gen) +{} + +inline RandomInteger::RandomInteger(long high, RNG *gen) + : pLow((0 < high) ? 0 : high), + pHigh((0 < high) ? high : 0), + pGenerator(gen) +{} + + +inline RandomInteger::RandomInteger(RNG *gen) + : pLow(0), + pHigh(1), + pGenerator(gen) +{} + +inline RNG* RandomInteger::generator() const { return pGenerator;} +inline long RandomInteger::low() const { return pLow; } +inline long RandomInteger::high() const { return pHigh; } + +inline RNG* RandomInteger::generator(RNG *gen) +{ + RNG *tmp = pGenerator; pGenerator = gen; return tmp; +} + +inline long RandomInteger::low(long x) +{ + long tmp = pLow; pLow = x; return tmp; +} + +inline long RandomInteger:: high(long x) +{ + long tmp = pHigh; pHigh = x; return tmp; +} + +inline long RandomInteger:: _asLong(long low, long high) +{ + return (pGenerator->asLong() % (high-low+1)) + low; +} + + +inline long RandomInteger:: asLong() +{ + return _asLong(pLow, pHigh); +} + +inline long RandomInteger:: asLong(long high) +{ + return _asLong(pLow, high); +} + +inline long RandomInteger:: asLong(long low, long high) +{ + return _asLong(low, high); +} + +inline long RandomInteger:: operator () () +{ + return _asLong(pLow, pHigh); +} + +inline long RandomInteger:: operator () (long high) +{ + return _asLong(pLow, high); +} + +inline long RandomInteger:: operator () (long low, long high) +{ + return _asLong(low, high); +} + + + + +inline int RandomInteger:: asInt() +{ + return int(asLong()); +} + +#endif diff --git a/gnu/lib/libg++/include/SFile.h b/gnu/lib/libg++/include/SFile.h new file mode 100644 index 0000000..3726844 --- /dev/null +++ b/gnu/lib/libg++/include/SFile.h @@ -0,0 +1,53 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1988, 1992, 1993 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#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 diff --git a/gnu/lib/libg++/include/SLList.h b/gnu/lib/libg++/include/SLList.h new file mode 100644 index 0000000..c613674 --- /dev/null +++ b/gnu/lib/libg++/include/SLList.h @@ -0,0 +1,115 @@ +// 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. +*/ + +#ifndef _SLList_h +#ifdef __GNUG__ +//#pragma interface +#endif +#define _SLList_h 1 + +#include <Pix.h> + +struct BaseSLNode +{ + BaseSLNode *tl; + void *item() {return (void*)(this+1);} // Return ((SLNode<T>*)this)->hd +}; + +template<class T> +class SLNode : public BaseSLNode +{ + public: + T hd; // Data part of node + SLNode() { } + SLNode(const T& h, SLNode* t = 0) + : hd(h) { tl = t; } + ~SLNode() { } +}; + +extern int __SLListLength(BaseSLNode *ptr); + +class BaseSLList { + protected: + BaseSLNode *last; + virtual void delete_node(BaseSLNode*node) = 0; + virtual BaseSLNode* copy_node(const void* datum) = 0; + virtual void copy_item(void *dst, void *src) = 0; + virtual ~BaseSLList() { } + BaseSLList() { last = 0; } + void copy(const BaseSLList&); + BaseSLList& operator = (const BaseSLList& a); + Pix ins_after(Pix p, const void *datum); + Pix prepend(const void *datum); + Pix append(const void *datum); + int remove_front(void *dst, int signal_error = 0); + void join(BaseSLList&); + public: + int length() const; + int empty() const { return last == 0; } + void clear(); + Pix prepend(BaseSLNode*); + Pix append(BaseSLNode*); + int OK(); + void error(const char* msg); + void del_after(Pix p); + int owns(Pix p); + void del_front(); +}; + +template <class T> +class SLList : public BaseSLList +{ + private: + virtual void delete_node(BaseSLNode *node) { delete (SLNode<T>*)node; } + virtual BaseSLNode* copy_node(const void *datum) + { return new SLNode<T>(*(const T*)datum); } + virtual void copy_item(void *dst, void *src) { *(T*)dst = *(T*)src; } + +public: + SLList() : BaseSLList() { } + SLList(const SLList<T>& a) : BaseSLList() { copy(a); } + SLList<T>& operator = (const SLList<T>& a) + { BaseSLList::operator=((const BaseSLList&) a); return *this; } + virtual ~SLList() { clear(); } + + Pix prepend(const T& item) {return BaseSLList::prepend(&item);} + Pix append(const T& item) {return BaseSLList::append(&item);} + Pix prepend(SLNode<T>* node) {return BaseSLList::prepend(node);} + Pix append(SLNode<T>* node) {return BaseSLList::append(node);} + + T& operator () (Pix p) { + if (p == 0) error("null Pix"); + return ((SLNode<T>*)(p))->hd; } + inline Pix first() { return (last == 0)? 0 : Pix(last->tl); } + void next(Pix& p) + { p = (p == 0 || p == last)? 0 : Pix(((SLNode<T>*)(p))->tl); } + Pix ins_after(Pix p, const T& item) + { return BaseSLList::ins_after(p, &item); } + void join(SLList<T>& a) { BaseSLList::join(a); } + + T& front() { + if (last == 0) error("front: empty list"); + return ((SLNode<T>*)last->tl)->hd; } + T& rear() { + if (last == 0) error("rear: empty list"); + return ((SLNode<T>*)last)->hd; } + int remove_front(T& x) { return BaseSLList::remove_front(&x); } + T remove_front() { T dst; BaseSLList::remove_front(&dst, 1); return dst; } +}; + +#endif diff --git a/gnu/lib/libg++/include/SmplHist.h b/gnu/lib/libg++/include/SmplHist.h new file mode 100644 index 0000000..a9a7550 --- /dev/null +++ b/gnu/lib/libg++/include/SmplHist.h @@ -0,0 +1,72 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ + +#ifndef SampleHistogram_h +#ifdef __GNUG__ +#pragma interface +#endif +#define SampleHistogram_h 1 + +#include <iostream.h> +#include <SmplStat.h> + +extern const int SampleHistogramMinimum; +extern const int SampleHistogramMaximum; + +class SampleHistogram : public SampleStatistic +{ +protected: + short howManyBuckets; + int *bucketCount; + double *bucketLimit; + +public: + + SampleHistogram(double low, double hi, double bucketWidth = -1.0); + + ~SampleHistogram(); + + virtual void reset(); + virtual void operator+=(double); + + int similarSamples(double); + + int buckets(); + + double bucketThreshold(int i); + int inBucket(int i); + void printBuckets(ostream&); + +}; + + +inline int SampleHistogram:: buckets() { return(howManyBuckets); }; + +inline double SampleHistogram:: bucketThreshold(int i) { + if (i < 0 || i >= howManyBuckets) + error("invalid bucket access"); + return(bucketLimit[i]); +} + +inline int SampleHistogram:: inBucket(int i) { + if (i < 0 || i >= howManyBuckets) + error("invalid bucket access"); + return(bucketCount[i]); +} + +#endif diff --git a/gnu/lib/libg++/include/SmplStat.h b/gnu/lib/libg++/include/SmplStat.h new file mode 100644 index 0000000..191ec67 --- /dev/null +++ b/gnu/lib/libg++/include/SmplStat.h @@ -0,0 +1,66 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef SampleStatistic_h +#ifdef __GNUG__ +#pragma interface +#endif +#define SampleStatistic_h 1 + +#include <builtin.h> + +class SampleStatistic { +protected: + int n; + double x; + double x2; + double minValue, maxValue; + + public : + + SampleStatistic(); + virtual ~SampleStatistic(); + virtual void reset(); + + virtual void operator+=(double); + int samples(); + double mean(); + double stdDev(); + double var(); + double min(); + double max(); + double confidence(int p_percentage); + double confidence(double p_value); + + void error(const char* msg); +}; + +// error handlers + +extern void default_SampleStatistic_error_handler(const char*); +extern one_arg_error_handler_t SampleStatistic_error_handler; + +extern one_arg_error_handler_t + set_SampleStatistic_error_handler(one_arg_error_handler_t f); + +inline SampleStatistic:: SampleStatistic(){ reset();} +inline int SampleStatistic:: samples() {return(n);} +inline double SampleStatistic:: min() {return(minValue);} +inline double SampleStatistic:: max() {return(maxValue);} +inline SampleStatistic::~SampleStatistic() {} + +#endif diff --git a/gnu/lib/libg++/include/String.h b/gnu/lib/libg++/include/String.h new file mode 100644 index 0000000..9537ba6 --- /dev/null +++ b/gnu/lib/libg++/include/String.h @@ -0,0 +1,1328 @@ +// 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. +*/ + + +#ifndef _String_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _String_h 1 + +#include <iostream.h> +#include <Regex.h> + +struct StrRep // internal String representations +{ + unsigned short len; // string length + unsigned short sz; // allocated space + char s[1]; // the string starts here + // (at least 1 char for trailing null) + // allocated & expanded via non-public fcts +}; + +// primitive ops on StrReps -- nearly all String fns go through these. + +StrRep* Salloc(StrRep*, const char*, int, int); +StrRep* Scopy(StrRep*, const StrRep*); +StrRep* Sresize(StrRep*, int); +StrRep* Scat(StrRep*, const char*, int, const char*, int); +StrRep* Scat(StrRep*, const char*, int,const char*,int, const char*,int); +StrRep* Sprepend(StrRep*, const char*, int); +StrRep* Sreverse(const StrRep*, StrRep*); +StrRep* Supcase(const StrRep*, StrRep*); +StrRep* Sdowncase(const StrRep*, StrRep*); +StrRep* Scapitalize(const StrRep*, StrRep*); + +// These classes need to be defined in the order given + +class String; +class SubString; + +class SubString +{ + friend class String; +protected: + + String& S; // The String I'm a substring of + unsigned short pos; // starting position in S's rep + unsigned short len; // length of substring + + void assign(const StrRep*, const char*, int = -1); + SubString(String& x, int p, int l); + SubString(const SubString& x); + +public: + +// Note there are no public constructors. SubStrings are always +// created via String operations + + ~SubString(); + + SubString& operator = (const String& y); + SubString& operator = (const SubString& y); + SubString& operator = (const char* t); + SubString& operator = (char c); + +// return 1 if target appears anywhere in SubString; else 0 + + int contains(char c) const; + int contains(const String& y) const; + int contains(const SubString& y) const; + int contains(const char* t) const; + int contains(const Regex& r) const; + +// return 1 if target matches entire SubString + + int matches(const Regex& r) const; + +// IO + + friend ostream& operator<<(ostream& s, const SubString& x); + +// status + + unsigned int length() const; + int empty() const; + const char* chars() const; + + int OK() const; + +}; + + +class String +{ + friend class SubString; + +protected: + StrRep* rep; // Strings are pointers to their representations + +// some helper functions + + int search(int, int, const char*, int = -1) const; + int search(int, int, char) const; + int match(int, int, int, const char*, int = -1) const; + int _gsub(const char*, int, const char* ,int); + int _gsub(const Regex&, const char*, int); + SubString _substr(int, int); + +public: + +// constructors & assignment + + String(); + String(const String& x); + String(const SubString& x); + String(const char* t); + String(const char* t, int len); + String(char c); + + ~String(); + + String& operator = (const String& y); + String& operator = (const char* y); + String& operator = (char c); + String& operator = (const SubString& y); + +// concatenation + + String& operator += (const String& y); + String& operator += (const SubString& y); + String& operator += (const char* t); + String& operator += (char c); + + void prepend(const String& y); + void prepend(const SubString& y); + void prepend(const char* t); + void prepend(char c); + + +// procedural versions: +// concatenate first 2 args, store result in last arg + + friend void cat(const String&, const String&, String&); + friend void cat(const String&, const SubString&, String&); + friend void cat(const String&, const char*, String&); + friend void cat(const String&, char, String&); + + friend void cat(const SubString&, const String&, String&); + friend void cat(const SubString&, const SubString&, String&); + friend void cat(const SubString&, const char*, String&); + friend void cat(const SubString&, char, String&); + + friend void cat(const char*, const String&, String&); + friend void cat(const char*, const SubString&, String&); + friend void cat(const char*, const char*, String&); + friend void cat(const char*, char, String&); + +// double concatenation, by request. (yes, there are too many versions, +// but if one is supported, then the others should be too...) +// Concatenate first 3 args, store in last arg + + friend void cat(const String&,const String&, const String&,String&); + friend void cat(const String&,const String&,const SubString&,String&); + friend void cat(const String&,const String&, const char*, String&); + friend void cat(const String&,const String&, char, String&); + friend void cat(const String&,const SubString&,const String&,String&); + friend void cat(const String&,const SubString&,const SubString&,String&); + friend void cat(const String&,const SubString&, const char*, String&); + friend void cat(const String&,const SubString&, char, String&); + friend void cat(const String&,const char*, const String&, String&); + friend void cat(const String&,const char*, const SubString&, String&); + friend void cat(const String&,const char*, const char*, String&); + friend void cat(const String&,const char*, char, String&); + + friend void cat(const char*, const String&, const String&,String&); + friend void cat(const char*,const String&,const SubString&,String&); + friend void cat(const char*,const String&, const char*, String&); + friend void cat(const char*,const String&, char, String&); + friend void cat(const char*,const SubString&,const String&,String&); + friend void cat(const char*,const SubString&,const SubString&,String&); + friend void cat(const char*,const SubString&, const char*, String&); + friend void cat(const char*,const SubString&, char, String&); + friend void cat(const char*,const char*, const String&, String&); + friend void cat(const char*,const char*, const SubString&, String&); + friend void cat(const char*,const char*, const char*, String&); + friend void cat(const char*,const char*, char, String&); + + +// searching & matching + +// return position of target in string or -1 for failure + + int index(char c, int startpos = 0) const; + int index(const String& y, int startpos = 0) const; + int index(const SubString& y, int startpos = 0) const; + int index(const char* t, int startpos = 0) const; + int index(const Regex& r, int startpos = 0) const; + +// return 1 if target appears anyhere in String; else 0 + + int contains(char c) const; + int contains(const String& y) const; + int contains(const SubString& y) const; + int contains(const char* t) const; + int contains(const Regex& r) const; + +// return 1 if target appears anywhere after position pos +// (or before, if pos is negative) in String; else 0 + + int contains(char c, int pos) const; + int contains(const String& y, int pos) const; + int contains(const SubString& y, int pos) const; + int contains(const char* t, int pos) const; + int contains(const Regex& r, int pos) const; + +// return 1 if target appears at position pos in String; else 0 + + int matches(char c, int pos = 0) const; + int matches(const String& y, int pos = 0) const; + int matches(const SubString& y, int pos = 0) const; + int matches(const char* t, int pos = 0) const; + int matches(const Regex& r, int pos = 0) const; + +// return number of occurences of target in String + + int freq(char c) const; + int freq(const String& y) const; + int freq(const SubString& y) const; + int freq(const char* t) const; + +// SubString extraction + +// Note that you can't take a substring of a const String, since +// this leaves open the possiblility of indirectly modifying the +// String through the SubString + + SubString at(int pos, int len); + SubString operator () (int pos, int len); // synonym for at + + SubString at(const String& x, int startpos = 0); + SubString at(const SubString& x, int startpos = 0); + SubString at(const char* t, int startpos = 0); + SubString at(char c, int startpos = 0); + SubString at(const Regex& r, int startpos = 0); + + SubString before(int pos); + SubString before(const String& x, int startpos = 0); + SubString before(const SubString& x, int startpos = 0); + SubString before(const char* t, int startpos = 0); + SubString before(char c, int startpos = 0); + SubString before(const Regex& r, int startpos = 0); + + SubString through(int pos); + SubString through(const String& x, int startpos = 0); + SubString through(const SubString& x, int startpos = 0); + SubString through(const char* t, int startpos = 0); + SubString through(char c, int startpos = 0); + SubString through(const Regex& r, int startpos = 0); + + SubString from(int pos); + SubString from(const String& x, int startpos = 0); + SubString from(const SubString& x, int startpos = 0); + SubString from(const char* t, int startpos = 0); + SubString from(char c, int startpos = 0); + SubString from(const Regex& r, int startpos = 0); + + SubString after(int pos); + SubString after(const String& x, int startpos = 0); + SubString after(const SubString& x, int startpos = 0); + SubString after(const char* t, int startpos = 0); + SubString after(char c, int startpos = 0); + SubString after(const Regex& r, int startpos = 0); + + +// deletion + +// delete len chars starting at pos + void del(int pos, int len); + +// delete the first occurrence of target after startpos + + void del(const String& y, int startpos = 0); + void del(const SubString& y, int startpos = 0); + void del(const char* t, int startpos = 0); + void del(char c, int startpos = 0); + void del(const Regex& r, int startpos = 0); + +// global substitution: substitute all occurrences of pat with repl + + int gsub(const String& pat, const String& repl); + int gsub(const SubString& pat, const String& repl); + int gsub(const char* pat, const String& repl); + int gsub(const char* pat, const char* repl); + int gsub(const Regex& pat, const String& repl); + +// friends & utilities + +// split string into array res at separators; return number of elements + + friend int split(const String& x, String res[], int maxn, + const String& sep); + friend int split(const String& x, String res[], int maxn, + const Regex& sep); + + friend String common_prefix(const String& x, const String& y, + int startpos = 0); + friend String common_suffix(const String& x, const String& y, + int startpos = -1); + friend String replicate(char c, int n); + friend String replicate(const String& y, int n); + friend String join(String src[], int n, const String& sep); + +// simple builtin transformations + + friend String reverse(const String& x); + friend String upcase(const String& x); + friend String downcase(const String& x); + friend String capitalize(const String& x); + +// in-place versions of above + + void reverse(); + void upcase(); + void downcase(); + void capitalize(); + +// element extraction + + char& operator [] (int i); + char elem(int i) const; + char firstchar() const; + char lastchar() const; + +// conversion + + operator const char*() const; + const char* chars() const; + + +// IO + + friend ostream& operator<<(ostream& s, const String& x); + friend ostream& operator<<(ostream& s, const SubString& x); + friend istream& operator>>(istream& s, String& x); + + friend int readline(istream& s, String& x, + char terminator = '\n', + int discard_terminator = 1); + +// status + + unsigned int length() const; + int empty() const; + +// preallocate some space for String + void alloc(int newsize); + +// report current allocation (not length!) + + int allocation() const; + + + void error(const char* msg) const; + + int OK() const; +}; + +typedef String StrTmp; // for backward compatibility + +// other externs + +int compare(const String& x, const String& y); +int compare(const String& x, const SubString& y); +int compare(const String& x, const char* y); +int compare(const SubString& x, const String& y); +int compare(const SubString& x, const SubString& y); +int compare(const SubString& x, const char* y); +int fcompare(const String& x, const String& y); // ignore case + +extern StrRep _nilStrRep; +extern String _nilString; + +// other inlines + +String operator + (const String& x, const String& y); +String operator + (const String& x, const SubString& y); +String operator + (const String& x, const char* y); +String operator + (const String& x, char y); +String operator + (const SubString& x, const String& y); +String operator + (const SubString& x, const SubString& y); +String operator + (const SubString& x, const char* y); +String operator + (const SubString& x, char y); +String operator + (const char* x, const String& y); +String operator + (const char* x, const SubString& y); + +int operator==(const String& x, const String& y); +int operator!=(const String& x, const String& y); +int operator> (const String& x, const String& y); +int operator>=(const String& x, const String& y); +int operator< (const String& x, const String& y); +int operator<=(const String& x, const String& y); +int operator==(const String& x, const SubString& y); +int operator!=(const String& x, const SubString& y); +int operator> (const String& x, const SubString& y); +int operator>=(const String& x, const SubString& y); +int operator< (const String& x, const SubString& y); +int operator<=(const String& x, const SubString& y); +int operator==(const String& x, const char* t); +int operator!=(const String& x, const char* t); +int operator> (const String& x, const char* t); +int operator>=(const String& x, const char* t); +int operator< (const String& x, const char* t); +int operator<=(const String& x, const char* t); +int operator==(const SubString& x, const String& y); +int operator!=(const SubString& x, const String& y); +int operator> (const SubString& x, const String& y); +int operator>=(const SubString& x, const String& y); +int operator< (const SubString& x, const String& y); +int operator<=(const SubString& x, const String& y); +int operator==(const SubString& x, const SubString& y); +int operator!=(const SubString& x, const SubString& y); +int operator> (const SubString& x, const SubString& y); +int operator>=(const SubString& x, const SubString& y); +int operator< (const SubString& x, const SubString& y); +int operator<=(const SubString& x, const SubString& y); +int operator==(const SubString& x, const char* t); +int operator!=(const SubString& x, const char* t); +int operator> (const SubString& x, const char* t); +int operator>=(const SubString& x, const char* t); +int operator< (const SubString& x, const char* t); +int operator<=(const SubString& x, const char* t); + + +// status reports, needed before defining other things + +inline unsigned int String::length() const { return rep->len; } +inline int String::empty() const { return rep->len == 0; } +inline const char* String::chars() const { return &(rep->s[0]); } +inline int String::allocation() const { return rep->sz; } +inline void String::alloc(int newsize) { rep = Sresize(rep, newsize); } + +inline unsigned int SubString::length() const { return len; } +inline int SubString::empty() const { return len == 0; } +inline const char* SubString::chars() const { return &(S.rep->s[pos]); } + + +// constructors + +inline String::String() + : rep(&_nilStrRep) {} +inline String::String(const String& x) + : rep(Scopy(0, x.rep)) {} +inline String::String(const char* t) + : rep(Salloc(0, t, -1, -1)) {} +inline String::String(const char* t, int tlen) + : rep(Salloc(0, t, tlen, tlen)) {} +inline String::String(const SubString& y) + : rep(Salloc(0, y.chars(), y.length(), y.length())) {} +inline String::String(char c) + : rep(Salloc(0, &c, 1, 1)) {} + +inline String::~String() { if (rep != &_nilStrRep) delete rep; } + +inline SubString::SubString(const SubString& x) + :S(x.S), pos(x.pos), len(x.len) {} +inline SubString::SubString(String& x, int first, int l) + :S(x), pos(first), len(l) {} + +inline SubString::~SubString() {} + +// assignment + +inline String& String::operator = (const String& y) +{ + rep = Scopy(rep, y.rep); + return *this; +} + +inline String& String::operator=(const char* t) +{ + rep = Salloc(rep, t, -1, -1); + return *this; +} + +inline String& String::operator=(const SubString& y) +{ + rep = Salloc(rep, y.chars(), y.length(), y.length()); + return *this; +} + +inline String& String::operator=(char c) +{ + rep = Salloc(rep, &c, 1, 1); + return *this; +} + + +inline SubString& SubString::operator = (const char* ys) +{ + assign(0, ys); + return *this; +} + +inline SubString& SubString::operator = (char ch) +{ + assign(0, &ch, 1); + return *this; +} + +inline SubString& SubString::operator = (const String& y) +{ + assign(y.rep, y.chars(), y.length()); + return *this; +} + +inline SubString& SubString::operator = (const SubString& y) +{ + assign(y.S.rep, y.chars(), y.length()); + return *this; +} + +// Zillions of cats... + +inline void cat(const String& x, const String& y, String& r) +{ + r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length()); +} + +inline void cat(const String& x, const SubString& y, String& r) +{ + r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length()); +} + +inline void cat(const String& x, const char* y, String& r) +{ + r.rep = Scat(r.rep, x.chars(), x.length(), y, -1); +} + +inline void cat(const String& x, char y, String& r) +{ + r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1); +} + +inline void cat(const SubString& x, const String& y, String& r) +{ + r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length()); +} + +inline void cat(const SubString& x, const SubString& y, String& r) +{ + r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length()); +} + +inline void cat(const SubString& x, const char* y, String& r) +{ + r.rep = Scat(r.rep, x.chars(), x.length(), y, -1); +} + +inline void cat(const SubString& x, char y, String& r) +{ + r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1); +} + +inline void cat(const char* x, const String& y, String& r) +{ + r.rep = Scat(r.rep, x, -1, y.chars(), y.length()); +} + +inline void cat(const char* x, const SubString& y, String& r) +{ + r.rep = Scat(r.rep, x, -1, y.chars(), y.length()); +} + +inline void cat(const char* x, const char* y, String& r) +{ + r.rep = Scat(r.rep, x, -1, y, -1); +} + +inline void cat(const char* x, char y, String& r) +{ + r.rep = Scat(r.rep, x, -1, &y, 1); +} + +inline void cat(const String& a, const String& x, const String& y, String& r) +{ + r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length()); +} + +inline void cat(const String& a, const String& x, const SubString& y, String& r) +{ + r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length()); +} + +inline void cat(const String& a, const String& x, const char* y, String& r) +{ + r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1); +} + +inline void cat(const String& a, const String& x, char y, String& r) +{ + r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1); +} + +inline void cat(const String& a, const SubString& x, const String& y, String& r) +{ + r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length()); +} + +inline void cat(const String& a, const SubString& x, const SubString& y, String& r) +{ + r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length()); +} + +inline void cat(const String& a, const SubString& x, const char* y, String& r) +{ + r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1); +} + +inline void cat(const String& a, const SubString& x, char y, String& r) +{ + r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1); +} + +inline void cat(const String& a, const char* x, const String& y, String& r) +{ + r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length()); +} + +inline void cat(const String& a, const char* x, const SubString& y, String& r) +{ + r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length()); +} + +inline void cat(const String& a, const char* x, const char* y, String& r) +{ + r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y, -1); +} + +inline void cat(const String& a, const char* x, char y, String& r) +{ + r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, &y, 1); +} + + +inline void cat(const char* a, const String& x, const String& y, String& r) +{ + r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length()); +} + +inline void cat(const char* a, const String& x, const SubString& y, String& r) +{ + r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length()); +} + +inline void cat(const char* a, const String& x, const char* y, String& r) +{ + r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1); +} + +inline void cat(const char* a, const String& x, char y, String& r) +{ + r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1); +} + +inline void cat(const char* a, const SubString& x, const String& y, String& r) +{ + r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length()); +} + +inline void cat(const char* a, const SubString& x, const SubString& y, String& r) +{ + r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length()); +} + +inline void cat(const char* a, const SubString& x, const char* y, String& r) +{ + r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1); +} + +inline void cat(const char* a, const SubString& x, char y, String& r) +{ + r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1); +} + +inline void cat(const char* a, const char* x, const String& y, String& r) +{ + r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length()); +} + +inline void cat(const char* a, const char* x, const SubString& y, String& r) +{ + r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length()); +} + +inline void cat(const char* a, const char* x, const char* y, String& r) +{ + r.rep = Scat(r.rep, a, -1, x, -1, y, -1); +} + +inline void cat(const char* a, const char* x, char y, String& r) +{ + r.rep = Scat(r.rep, a, -1, x, -1, &y, 1); +} + + +// operator versions + +inline String& String::operator +=(const String& y) +{ + cat(*this, y, *this); + return *this; +} + +inline String& String::operator +=(const SubString& y) +{ + cat(*this, y, *this); + return *this; +} + +inline String& String::operator += (const char* y) +{ + cat(*this, y, *this); + return *this; +} + +inline String& String:: operator +=(char y) +{ + cat(*this, y, *this); + return *this; +} + +// constructive concatenation + +#if defined(__GNUG__) && !defined(_G_NO_NRV) + +inline String operator + (const String& x, const String& y) return r; +{ + cat(x, y, r); +} + +inline String operator + (const String& x, const SubString& y) return r; +{ + cat(x, y, r); +} + +inline String operator + (const String& x, const char* y) return r; +{ + cat(x, y, r); +} + +inline String operator + (const String& x, char y) return r; +{ + cat(x, y, r); +} + +inline String operator + (const SubString& x, const String& y) return r; +{ + cat(x, y, r); +} + +inline String operator + (const SubString& x, const SubString& y) return r; +{ + cat(x, y, r); +} + +inline String operator + (const SubString& x, const char* y) return r; +{ + cat(x, y, r); +} + +inline String operator + (const SubString& x, char y) return r; +{ + cat(x, y, r); +} + +inline String operator + (const char* x, const String& y) return r; +{ + cat(x, y, r); +} + +inline String operator + (const char* x, const SubString& y) return r; +{ + cat(x, y, r); +} + +inline String reverse(const String& x) return r; +{ + r.rep = Sreverse(x.rep, r.rep); +} + +inline String upcase(const String& x) return r; +{ + r.rep = Supcase(x.rep, r.rep); +} + +inline String downcase(const String& x) return r; +{ + r.rep = Sdowncase(x.rep, r.rep); +} + +inline String capitalize(const String& x) return r; +{ + r.rep = Scapitalize(x.rep, r.rep); +} + +#else /* NO_NRV */ + +inline String operator + (const String& x, const String& y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const String& x, const SubString& y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const String& x, const char* y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const String& x, char y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const SubString& x, const String& y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const SubString& x, const SubString& y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const SubString& x, const char* y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const SubString& x, char y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const char* x, const String& y) +{ + String r; cat(x, y, r); return r; +} + +inline String operator + (const char* x, const SubString& y) +{ + String r; cat(x, y, r); return r; +} + +inline String reverse(const String& x) +{ + String r; r.rep = Sreverse(x.rep, r.rep); return r; +} + +inline String upcase(const String& x) +{ + String r; r.rep = Supcase(x.rep, r.rep); return r; +} + +inline String downcase(const String& x) +{ + String r; r.rep = Sdowncase(x.rep, r.rep); return r; +} + +inline String capitalize(const String& x) +{ + String r; r.rep = Scapitalize(x.rep, r.rep); return r; +} + +#endif + +// prepend + +inline void String::prepend(const String& y) +{ + rep = Sprepend(rep, y.chars(), y.length()); +} + +inline void String::prepend(const char* y) +{ + rep = Sprepend(rep, y, -1); +} + +inline void String::prepend(char y) +{ + rep = Sprepend(rep, &y, 1); +} + +inline void String::prepend(const SubString& y) +{ + rep = Sprepend(rep, y.chars(), y.length()); +} + +// misc transformations + + +inline void String::reverse() +{ + rep = Sreverse(rep, rep); +} + + +inline void String::upcase() +{ + rep = Supcase(rep, rep); +} + + +inline void String::downcase() +{ + rep = Sdowncase(rep, rep); +} + + +inline void String::capitalize() +{ + rep = Scapitalize(rep, rep); +} + +// element extraction + +inline char& String::operator [] (int i) +{ + if (((unsigned)i) >= length()) error("invalid index"); + return rep->s[i]; +} + +inline char String::elem (int i) const +{ + if (((unsigned)i) >= length()) error("invalid index"); + return rep->s[i]; +} + +inline char String::firstchar() const +{ + return elem(0); +} + +inline char String::lastchar() const +{ + return elem(length() - 1); +} + +// searching + +inline int String::index(char c, int startpos) const +{ + return search(startpos, length(), c); +} + +inline int String::index(const char* t, int startpos) const +{ + return search(startpos, length(), t); +} + +inline int String::index(const String& y, int startpos) const +{ + return search(startpos, length(), y.chars(), y.length()); +} + +inline int String::index(const SubString& y, int startpos) const +{ + return search(startpos, length(), y.chars(), y.length()); +} + +inline int String::index(const Regex& r, int startpos) const +{ + int unused; return r.search(chars(), length(), unused, startpos); +} + +inline int String::contains(char c) const +{ + return search(0, length(), c) >= 0; +} + +inline int String::contains(const char* t) const +{ + return search(0, length(), t) >= 0; +} + +inline int String::contains(const String& y) const +{ + return search(0, length(), y.chars(), y.length()) >= 0; +} + +inline int String::contains(const SubString& y) const +{ + return search(0, length(), y.chars(), y.length()) >= 0; +} + +inline int String::contains(char c, int p) const +{ + return match(p, length(), 0, &c, 1) >= 0; +} + +inline int String::contains(const char* t, int p) const +{ + return match(p, length(), 0, t) >= 0; +} + +inline int String::contains(const String& y, int p) const +{ + return match(p, length(), 0, y.chars(), y.length()) >= 0; +} + +inline int String::contains(const SubString& y, int p) const +{ + return match(p, length(), 0, y.chars(), y.length()) >= 0; +} + +inline int String::contains(const Regex& r) const +{ + int unused; return r.search(chars(), length(), unused, 0) >= 0; +} + +inline int String::contains(const Regex& r, int p) const +{ + return r.match(chars(), length(), p) >= 0; +} + + +inline int String::matches(const SubString& y, int p) const +{ + return match(p, length(), 1, y.chars(), y.length()) >= 0; +} + +inline int String::matches(const String& y, int p) const +{ + return match(p, length(), 1, y.chars(), y.length()) >= 0; +} + +inline int String::matches(const char* t, int p) const +{ + return match(p, length(), 1, t) >= 0; +} + +inline int String::matches(char c, int p) const +{ + return match(p, length(), 1, &c, 1) >= 0; +} + +inline int String::matches(const Regex& r, int p) const +{ + int l = (p < 0)? -p : length() - p; + return r.match(chars(), length(), p) == l; +} + + +inline int SubString::contains(const char* t) const +{ + return S.search(pos, pos+len, t) >= 0; +} + +inline int SubString::contains(const String& y) const +{ + return S.search(pos, pos+len, y.chars(), y.length()) >= 0; +} + +inline int SubString::contains(const SubString& y) const +{ + return S.search(pos, pos+len, y.chars(), y.length()) >= 0; +} + +inline int SubString::contains(char c) const +{ + return S.search(pos, pos+len, c) >= 0; +} + +inline int SubString::contains(const Regex& r) const +{ + int unused; return r.search(chars(), len, unused, 0) >= 0; +} + +inline int SubString::matches(const Regex& r) const +{ + return r.match(chars(), len, 0) == len; +} + + +inline int String::gsub(const String& pat, const String& r) +{ + return _gsub(pat.chars(), pat.length(), r.chars(), r.length()); +} + +inline int String::gsub(const SubString& pat, const String& r) +{ + return _gsub(pat.chars(), pat.length(), r.chars(), r.length()); +} + +inline int String::gsub(const Regex& pat, const String& r) +{ + return _gsub(pat, r.chars(), r.length()); +} + +inline int String::gsub(const char* pat, const String& r) +{ + return _gsub(pat, -1, r.chars(), r.length()); +} + +inline int String::gsub(const char* pat, const char* r) +{ + return _gsub(pat, -1, r, -1); +} + + + +inline ostream& operator<<(ostream& s, const String& x) +{ + s << x.chars(); return s; +} + +// a zillion comparison operators + +inline int operator==(const String& x, const String& y) +{ + return compare(x, y) == 0; +} + +inline int operator!=(const String& x, const String& y) +{ + return compare(x, y) != 0; +} + +inline int operator>(const String& x, const String& y) +{ + return compare(x, y) > 0; +} + +inline int operator>=(const String& x, const String& y) +{ + return compare(x, y) >= 0; +} + +inline int operator<(const String& x, const String& y) +{ + return compare(x, y) < 0; +} + +inline int operator<=(const String& x, const String& y) +{ + return compare(x, y) <= 0; +} + +inline int operator==(const String& x, const SubString& y) +{ + return compare(x, y) == 0; +} + +inline int operator!=(const String& x, const SubString& y) +{ + return compare(x, y) != 0; +} + +inline int operator>(const String& x, const SubString& y) +{ + return compare(x, y) > 0; +} + +inline int operator>=(const String& x, const SubString& y) +{ + return compare(x, y) >= 0; +} + +inline int operator<(const String& x, const SubString& y) +{ + return compare(x, y) < 0; +} + +inline int operator<=(const String& x, const SubString& y) +{ + return compare(x, y) <= 0; +} + +inline int operator==(const String& x, const char* t) +{ + return compare(x, t) == 0; +} + +inline int operator!=(const String& x, const char* t) +{ + return compare(x, t) != 0; +} + +inline int operator>(const String& x, const char* t) +{ + return compare(x, t) > 0; +} + +inline int operator>=(const String& x, const char* t) +{ + return compare(x, t) >= 0; +} + +inline int operator<(const String& x, const char* t) +{ + return compare(x, t) < 0; +} + +inline int operator<=(const String& x, const char* t) +{ + return compare(x, t) <= 0; +} + +inline int operator==(const SubString& x, const String& y) +{ + return compare(y, x) == 0; +} + +inline int operator!=(const SubString& x, const String& y) +{ + return compare(y, x) != 0; +} + +inline int operator>(const SubString& x, const String& y) +{ + return compare(y, x) < 0; +} + +inline int operator>=(const SubString& x, const String& y) +{ + return compare(y, x) <= 0; +} + +inline int operator<(const SubString& x, const String& y) +{ + return compare(y, x) > 0; +} + +inline int operator<=(const SubString& x, const String& y) +{ + return compare(y, x) >= 0; +} + +inline int operator==(const SubString& x, const SubString& y) +{ + return compare(x, y) == 0; +} + +inline int operator!=(const SubString& x, const SubString& y) +{ + return compare(x, y) != 0; +} + +inline int operator>(const SubString& x, const SubString& y) +{ + return compare(x, y) > 0; +} + +inline int operator>=(const SubString& x, const SubString& y) +{ + return compare(x, y) >= 0; +} + +inline int operator<(const SubString& x, const SubString& y) +{ + return compare(x, y) < 0; +} + +inline int operator<=(const SubString& x, const SubString& y) +{ + return compare(x, y) <= 0; +} + +inline int operator==(const SubString& x, const char* t) +{ + return compare(x, t) == 0; +} + +inline int operator!=(const SubString& x, const char* t) +{ + return compare(x, t) != 0; +} + +inline int operator>(const SubString& x, const char* t) +{ + return compare(x, t) > 0; +} + +inline int operator>=(const SubString& x, const char* t) +{ + return compare(x, t) >= 0; +} + +inline int operator<(const SubString& x, const char* t) +{ + return compare(x, t) < 0; +} + +inline int operator<=(const SubString& x, const char* t) +{ + return compare(x, t) <= 0; +} + + +// a helper needed by at, before, etc. + +inline SubString String::_substr(int first, int l) +{ + if (first < 0 || (unsigned)(first + l) > length() ) + return SubString(_nilString, 0, 0) ; + else + return SubString(*this, first, l); +} + +#endif diff --git a/gnu/lib/libg++/include/Uniform.h b/gnu/lib/libg++/include/Uniform.h new file mode 100644 index 0000000..5933f6b --- /dev/null +++ b/gnu/lib/libg++/include/Uniform.h @@ -0,0 +1,71 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _Uniform_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Uniform_h 1 + +#include <Random.h> + +// +// The interval [lo..hi] +// + +class Uniform: public Random { + double pLow; + double pHigh; + double delta; +public: + Uniform(double low, double high, RNG *gen); + + double low(); + double low(double x); + double high(); + double high(double x); + + virtual double operator()(); +}; + + +inline Uniform::Uniform(double low, double high, RNG *gen) : Random(gen) +{ + pLow = (low < high) ? low : high; + pHigh = (low < high) ? high : low; + delta = pHigh - pLow; +} + +inline double Uniform::low() { return pLow; } + +inline double Uniform::low(double x) { + double tmp = pLow; + pLow = x; + delta = pHigh - pLow; + return tmp; +} + +inline double Uniform::high() { return pHigh; } + +inline double Uniform::high(double x) { + double tmp = pHigh; + pHigh = x; + delta = pHigh - pLow; + return tmp; +} + +#endif diff --git a/gnu/lib/libg++/include/Weibull.h b/gnu/lib/libg++/include/Weibull.h new file mode 100644 index 0000000..d03567a --- /dev/null +++ b/gnu/lib/libg++/include/Weibull.h @@ -0,0 +1,74 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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. +*/ +#ifndef _Weibull_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _Weibull_h + +#include <Random.h> + +class Weibull: public Random { +protected: + double pAlpha; + double pInvAlpha; + double pBeta; + + void setState(); + +public: + Weibull(double alpha, double beta, RNG *gen); + + double alpha(); + double alpha(double x); + + double beta(); + double beta(double x); + + virtual double operator()(); +}; + + +inline void Weibull::setState() { + pInvAlpha = 1.0 / pAlpha; +} + +inline Weibull::Weibull(double alpha, double beta, RNG *gen) : Random(gen) +{ + pAlpha = alpha; + pBeta = beta; + setState(); +} + +inline double Weibull::alpha() { return pAlpha; } + +inline double Weibull::alpha(double x) { + double tmp = pAlpha; + pAlpha = x; + setState(); + return tmp; +} + +inline double Weibull::beta() { return pBeta; }; +inline double Weibull::beta(double x) { + double tmp = pBeta; + pBeta = x; + return tmp; +}; + +#endif diff --git a/gnu/lib/libg++/include/_G_config.h b/gnu/lib/libg++/include/_G_config.h new file mode 100644 index 0000000..2b73e90 --- /dev/null +++ b/gnu/lib/libg++/include/_G_config.h @@ -0,0 +1,70 @@ +/* AUTOMATICALLY GENERATED; DO NOT EDIT! */ +#ifndef _G_config_h +#define _G_config_h +#define _G_LIB_VERSION "0.65" +#define _G_NAMES_HAVE_UNDERSCORE 1 +#define _G_VTABLE_LABEL_HAS_LENGTH 0 +#define _G_VTABLE_LABEL_PREFIX "__vt$" +#define _G_HAVE_ST_BLKSIZE 1 +typedef unsigned long _G_clock_t; +typedef unsigned long _G_dev_t; +typedef quad_t _G_fpos_t; +typedef unsigned long _G_gid_t; +typedef unsigned long _G_ino_t; +typedef unsigned short _G_mode_t; +typedef unsigned short _G_nlink_t; +typedef long long _G_off_t; +typedef long _G_pid_t; +#ifndef __PTRDIFF_TYPE__ +#define __PTRDIFF_TYPE__ int +#endif +typedef __PTRDIFF_TYPE__ _G_ptrdiff_t; +typedef unsigned int _G_sigset_t; +#ifndef __SIZE_TYPE__ +#define __SIZE_TYPE__ unsigned int +#endif +typedef __SIZE_TYPE__ _G_size_t; +typedef long _G_time_t; +typedef unsigned long _G_uid_t; +#ifndef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ int +#endif +typedef __WCHAR_TYPE__ _G_wchar_t; +typedef int _G_ssize_t; +typedef int _G_wint_t; +typedef char* /* default */ _G_va_list; +#define _G_signal_return_type void +#define _G_sprintf_return_type int +#ifdef __STDC__ +typedef signed char _G_int8_t; +#endif +typedef unsigned char _G_uint8_t; +typedef short _G_int16_t; +typedef unsigned short _G_uint16_t; +typedef int _G_int32_t; +typedef unsigned long _G_uint32_t; +#define HAVE_INT64 +typedef long long _G_int64_t; +typedef unsigned _G_uint64_t; +#define _G_BUFSIZ 1024 +#define _G_FOPEN_MAX 20 +#define _G_FILENAME_MAX 1024 +#define _G_NULL 0 /* default */ +#if defined (__cplusplus) || defined (__STDC__) +#define _G_ARGS(ARGLIST) ARGLIST +#else +#define _G_ARGS(ARGLIST) () +#endif +#if defined (__GNUG__) && defined (__STRICT_ANSI__) +#define _G_NO_NRV +#endif +#define _G_HAVE_ATEXIT 1 +#define _G_HAVE_SYS_RESOURCE 0 +#define _G_HAVE_SYS_SOCKET 1 +#define _G_HAVE_SYS_WAIT 1 +#define _G_HAVE_UNISTD 1 +#define _G_HAVE_DIRENT 1 +#define _G_HAVE_CURSES 1 +#define _G_MATH_H_INLINES 0 +#define _G_HAVE_BOOL 0 +#endif /* !_G_config_h */ diff --git a/gnu/lib/libg++/include/ansidecl.h b/gnu/lib/libg++/include/ansidecl.h new file mode 100644 index 0000000..3c0dcb3 --- /dev/null +++ b/gnu/lib/libg++/include/ansidecl.h @@ -0,0 +1,141 @@ +/* ANSI and traditional C compatability macros + Copyright 1991, 1992 Free Software Foundation, Inc. + This file is part of the GNU C Library. + +This program 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 2 of the License, or +(at your option) any later version. + +This program 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 this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* ANSI and traditional C compatibility macros + + ANSI C is assumed if __STDC__ is #defined. + + Macro ANSI C definition Traditional C definition + ----- ---- - ---------- ----------- - ---------- + PTR `void *' `char *' + LONG_DOUBLE `long double' `double' + VOLATILE `volatile' `' + SIGNED `signed' `' + PTRCONST `void *const' `char *' + ANSI_PROTOTYPES 1 not defined + + CONST is also defined, but is obsolete. Just use const. + + DEFUN (name, arglist, args) + + Defines function NAME. + + ARGLIST lists the arguments, separated by commas and enclosed in + parentheses. ARGLIST becomes the argument list in traditional C. + + ARGS list the arguments with their types. It becomes a prototype in + ANSI C, and the type declarations in traditional C. Arguments should + be separated with `AND'. For functions with a variable number of + arguments, the last thing listed should be `DOTS'. + + DEFUN_VOID (name) + + Defines a function NAME, which takes no arguments. + + obsolete -- EXFUN (name, (prototype)) -- obsolete. + + Replaced by PARAMS. Do not use; will disappear someday soon. + Was used in external function declarations. + In ANSI C it is `NAME PROTOTYPE' (so PROTOTYPE should be enclosed in + parentheses). In traditional C it is `NAME()'. + For a function that takes no arguments, PROTOTYPE should be `(void)'. + + PARAMS ((args)) + + We could use the EXFUN macro to handle prototype declarations, but + the name is misleading and the result is ugly. So we just define a + simple macro to handle the parameter lists, as in: + + static int foo PARAMS ((int, char)); + + This produces: `static int foo();' or `static int foo (int, char);' + + EXFUN would have done it like this: + + static int EXFUN (foo, (int, char)); + + but the function is not external...and it's hard to visually parse + the function name out of the mess. EXFUN should be considered + obsolete; new code should be written to use PARAMS. + + For example: + extern int printf PARAMS ((CONST char *format DOTS)); + int DEFUN(fprintf, (stream, format), + FILE *stream AND CONST char *format DOTS) { ... } + void DEFUN_VOID(abort) { ... } +*/ + +#ifndef _ANSIDECL_H + +#define _ANSIDECL_H 1 + + +/* Every source file includes this file, + so they will all get the switch for lint. */ +/* LINTLIBRARY */ + + +#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) +/* All known AIX compilers implement these things (but don't always + define __STDC__). The RISC/OS MIPS compiler defines these things + in SVR4 mode, but does not define __STDC__. */ + +#define PTR void * +#define PTRCONST void *CONST +#define LONG_DOUBLE long double + +#define AND , +#define NOARGS void +#define CONST const +#define VOLATILE volatile +#define SIGNED signed +#define DOTS , ... + +#define EXFUN(name, proto) name proto +#define DEFUN(name, arglist, args) name(args) +#define DEFUN_VOID(name) name(void) + +#define PROTO(type, name, arglist) type name arglist +#define PARAMS(paramlist) paramlist +#define ANSI_PROTOTYPES 1 + +#else /* Not ANSI C. */ + +#define PTR char * +#define PTRCONST PTR +#define LONG_DOUBLE double + +#define AND ; +#define NOARGS +#define CONST +#ifndef const /* some systems define it in header files for non-ansi mode */ +#define const +#endif +#define VOLATILE +#define SIGNED +#define DOTS + +#define EXFUN(name, proto) name() +#define DEFUN(name, arglist, args) name arglist args; +#define DEFUN_VOID(name) name() +#define PROTO(type, name, arglist) type name () +#define PARAMS(paramlist) () + +#endif /* ANSI C. */ + +#endif /* ansidecl.h */ diff --git a/gnu/lib/libg++/include/bitdo1.h b/gnu/lib/libg++/include/bitdo1.h new file mode 100644 index 0000000..c234d41 --- /dev/null +++ b/gnu/lib/libg++/include/bitdo1.h @@ -0,0 +1,32 @@ +#ifndef ONES +#define ONES ((_BS_word)(~0L)) +#endif + register int nwords; + register _BS_word mask; + if (offset == 0) + ; + else if (offset + length >= _BS_BITS_PER_WORD) + { + mask = ONES _BS_RIGHT offset; + DOIT(*ptr++, mask); + length -= _BS_BITS_PER_WORD - offset; + } + else + { + mask = (ONES _BS_RIGHT (_BS_BITS_PER_WORD - length)) + _BS_LEFT (_BS_BITS_PER_WORD - length - offset); + DOIT(*ptr, mask); + goto done; + } + nwords = _BS_INDEX(length); + while (--nwords >= 0) + { + DOIT(*ptr++, ONES); + } + length = _BS_POS (length); + if (length) + { + mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - length); + DOIT(*ptr, mask); + } + done: ; diff --git a/gnu/lib/libg++/include/bitdo2.h b/gnu/lib/libg++/include/bitdo2.h new file mode 100644 index 0000000..6e99523 --- /dev/null +++ b/gnu/lib/libg++/include/bitdo2.h @@ -0,0 +1,184 @@ +#ifndef ONES +#define ONES ((_BS_word)(~0L)) +#endif + +#ifndef DOIT_SOLID +#ifdef DOIT +#define DOIT_SOLID(dst, src) DOIT(dst, src, (_BS_word)(~0)) +#else +#define DOIT_SOLID(dst, src) (dst) = (COMBINE(dst, src)) +#endif +#endif + +#ifndef DOIT +#define DOIT(dst, src, mask) \ + (dst) = ((COMBINE(dst, src)) & (mask)) | ((dst) & ~(mask)) +#endif + + _BS_word word0, mask; + int shift0, shift1; + + if (length == 0) + goto done; + + shift0 = srcbit - dstbit; + + /* First handle the case that only one destination word is touched. */ + if (length + dstbit <= _BS_BITS_PER_WORD) + { + _BS_word mask + = (ONES _BS_LEFT (_BS_BITS_PER_WORD - length)) _BS_RIGHT dstbit; + _BS_word word0 = *psrc++; + if (shift0 <= 0) /* dstbit >= srcbit */ + { + word0 = word0 _BS_RIGHT (-shift0); + } + else + { + word0 = word0 _BS_LEFT shift0; + if (length + srcbit > _BS_BITS_PER_WORD) + word0 = word0 | (*psrc _BS_RIGHT (_BS_BITS_PER_WORD - shift0)); + } + DOIT(*pdst, word0, mask); + goto done; + } + + /* Next optimize the case that the source and destination are aligned. */ + if (shift0 == 0) + { + _BS_word mask; + if (psrc > pdst) + { + if (srcbit) + { + mask = ONES _BS_RIGHT srcbit; + DOIT(*pdst, *psrc, mask); + pdst++; psrc++; + length -= _BS_BITS_PER_WORD - srcbit; + } + for (; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD) + { + DOIT_SOLID(*pdst, *psrc); + pdst++; psrc++; + } + if (length) + { + mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - length); + DOIT(*pdst, *psrc, mask); + } + } + else if (psrc < pdst) + { + _BS_size_t span = srcbit + length; + pdst += span / (_BS_size_t)_BS_BITS_PER_WORD; + psrc += span / (_BS_size_t)_BS_BITS_PER_WORD; + span %= (_BS_size_t)_BS_BITS_PER_WORD; + if (span) + { + mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - span); + DOIT(*pdst, *psrc, mask); + length -= span; + } + pdst--; psrc--; + for (; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD) + { + DOIT_SOLID(*pdst, *psrc); + pdst--; psrc--; + } + if (srcbit) + { + mask = ONES _BS_RIGHT srcbit; + DOIT(*pdst, *psrc, mask); + } + } + /* else if (psrc == pdst) --nothing to do--; */ + goto done; + } + + /* Now we assume shift!=0, and more than on destination word is changed. */ + if (psrc >= pdst) /* Do the updates in forward direction. */ + { + _BS_word word0 = *psrc++; + _BS_word mask = ONES _BS_RIGHT dstbit; + if (shift0 > 0) + { + _BS_word word1 = *psrc++; + shift1 = _BS_BITS_PER_WORD - shift0; + DOIT(*pdst, (word0 _BS_LEFT shift0) | (word1 _BS_RIGHT shift1), mask); + word0 = word1; + } + else /* dstbit > srcbit */ + { + shift1 = -shift0; + shift0 += _BS_BITS_PER_WORD; + DOIT(*pdst, word0 _BS_RIGHT shift1, mask); + } + pdst++; + length -= _BS_BITS_PER_WORD - dstbit; + + for ( ; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD) + { + register _BS_word word1 = *psrc++; + DOIT_SOLID(*pdst, + (word0 _BS_LEFT shift0) | (word1 _BS_RIGHT shift1)); + pdst++; + word0 = word1; + } + if (length > 0) + { + _BS_size_t mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - length); + word0 = word0 _BS_LEFT shift0; + if (length > shift1) + word0 = word0 | (*psrc _BS_RIGHT shift1) ; + DOIT (*pdst, word0, mask); + } + } + else /* Do the updates in backward direction. */ + { + _BS_word word0; + + /* Make (psrc, srcbit) and (pdst, dstbit) point to *last* bit. */ + psrc += (srcbit + length - 1) / _BS_BITS_PER_WORD; + srcbit = (srcbit + length - 1) % _BS_BITS_PER_WORD; + pdst += (dstbit + length - 1) / _BS_BITS_PER_WORD; + dstbit = (dstbit + length - 1) % _BS_BITS_PER_WORD; + + shift0 = srcbit - dstbit; + + word0 = *psrc--; + mask = ONES _BS_LEFT (_BS_BITS_PER_WORD - 1 - dstbit); + if (shift0 < 0) + { + _BS_word word1 = *psrc--; + shift1 = -shift0; + shift0 += _BS_BITS_PER_WORD; + DOIT (*pdst, (word0 _BS_RIGHT shift1) | (word1 _BS_LEFT shift0), + mask); + word0 = word1; + } + else + { + shift1 = _BS_BITS_PER_WORD - shift0; + DOIT(*pdst, word0 _BS_LEFT shift0, mask); + } + pdst--; + length -= dstbit + 1; + + for ( ; length >= _BS_BITS_PER_WORD; length -= _BS_BITS_PER_WORD) + { + register _BS_word word1 = *psrc--; + DOIT_SOLID(*pdst, + (word0 _BS_RIGHT shift1) | (word1 _BS_LEFT shift0)); + pdst--; + word0 = word1; + } + if (length > 0) + { + _BS_size_t mask = ONES _BS_RIGHT (_BS_BITS_PER_WORD - length); + word0 = word0 _BS_RIGHT shift1; + if (length > shift0) + word0 = word0 | (*psrc _BS_LEFT shift0) ; + DOIT (*pdst, word0, mask); + } + } + done: ; diff --git a/gnu/lib/libg++/include/bitprims.h b/gnu/lib/libg++/include/bitprims.h new file mode 100644 index 0000000..771acd9 --- /dev/null +++ b/gnu/lib/libg++/include/bitprims.h @@ -0,0 +1,125 @@ +#ifndef _BS_PRIMS +#define _BS_PRIMS + +/* For now, use unsigned short for compatibility with old libg++ code. + Later, change to unsigned long as the default. */ +typedef unsigned long _BS_word; + +#define _BS_CHAR_BIT 8 +#define _BS_BITS_PER_WORD (_BS_CHAR_BIT*sizeof(_BS_word)) +#define _BS_WORDS_NEEDED(NBITS) ((NBITS+_BS_BITS_PER_WORD-1)/_BS_BITS_PER_WORD) + +/* For now, we number the bits in a _BS_word in little-endian order. + Later, might use machine order. */ +#ifdef CHILL_LIB +#ifndef BITS_BIG_ENDIAN +#include "config.h" +#endif +#define _BS_BIGENDIAN BITS_BIG_ENDIAN +#else +#define _BS_BIGENDIAN 0 +#endif + +/* By "left" we mean where bit number 0 is. + Hence, so left shift is << if we're numbering the bits in big-endian oder, + and >> if we're numbering the bits in little-endian order. + Currently, we always use little-endian order. + Later, we might use machine-endian order. */ +#if _BS_BIGENDIAN +#define _BS_LEFT << +#define _BS_RIGHT >> +#else +#define _BS_LEFT >> +#define _BS_RIGHT << +#endif + +#if _BS_BIGENDIAN +#define _BS_BITMASK(BITNO) (1 << (_BS_BITS_PER_WORD - 1 - (BITNO))) +#else +#define _BS_BITMASK(BITNO) (1 << (BITNO)) +#endif + +/* Given a PTR which may not be aligned on a _BS_word boundary, + set NEW_PTR to point to (the beginning of) the corresponding _BS_word. + Adjust the bit-offset OFFSET to compensate for the difference. */ +#define _BS_ADJUST_ALIGNED(NEW_PTR, PTR, OFFSET) \ + ( (NEW_PTR) = (_BS_word*)(((char*)(PTR)-(char*)0) & ~(sizeof(_BS_word)-1)), \ + (OFFSET) += (char*)(PTR) - (char*)(NEW_PTR) ) + +/* Given a bit point (PTR, OFFSET) normalize it so that + OFFSET < _BS_BITS_PER_WORD. */ +#define _BS_NORMALIZE(PTR, OFFSET) \ +{ _BS_size_t __tmp_ind = _BS_INDEX (OFFSET); \ + (PTR) += __tmp_ind; \ + (OFFSET) -= __tmp_ind * _BS_BITS_PER_WORD; } + +#define _BS_INDEX(I) ((unsigned)(I) / _BS_BITS_PER_WORD) +#define _BS_POS(I) ((I) & (_BS_BITS_PER_WORD -1 )) + +#ifndef _BS_size_t +#ifdef __GNUC__ +#define _BS_size_t __SIZE_TYPE__ +#else +#define _BS_size_t unsigned long +#endif +#endif + +#ifndef __P +#ifdef __STDC__ +#define __P(paramlist) paramlist +#else +#define __P(paramlist) () +#endif +#endif /*!__P*/ +#if !defined(__STDC__) && !defined(const) +#define const +#endif +#if !defined(__STDC__) && !defined(void) +#define void int +#endif + +/* The 16 2-operand raster-ops: + These match the correspodning GX codes in X11. */ +enum _BS_alu { + _BS_alu_clear = 0 /* 0 */, + _BS_alu_and = 1 /* src & dst */, + _BS_alu_andReverse = 2 /* src & ~dst */, + _BS_alu_copy = 3 /* src */, + _BS_alu_andInverted = 4 /* ~src & dst */, + _BS_alu_noop = 5 /* dst */, + _BS_alu_xor = 6 /* src ^ dst */, + _BS_alu_or = 7 /* src | dst */, + _BS_alu_nor = 8 /* ~src & ~dst */, + _BS_alu_equiv = 9 /* ~(src ^ dst) */, + _BS_alu_invert = 10 /* ~dst */, + _BS_alu_orReverse = 11 /* src | ~dst */, + _BS_alu_copyInverted = 12 /* ~src */, + _BS_alu_orInverted = 13 /* ~src | dst */, + _BS_alu_nand = 14 /* ~src | d~st */, + _BS_alu_set = 15 /* ~src | dst */ +}; +#define _BS +#define _BS + +#ifdef __cplusplus +extern "C" { +#endif + +extern void _BS_and __P((_BS_word*,int, const _BS_word*, int, _BS_size_t)); +extern void _BS_blt __P((enum _BS_alu, + _BS_word*,int, const _BS_word*,int, _BS_size_t)); +extern void _BS_copy __P((_BS_word*,int, const _BS_word*,int, _BS_size_t)); +#define _BS_copy_0(DS, SS, LENGTH) _BS_copy(DS, 0, SS, 0, LENGTH) +extern int _BS_count __P((const _BS_word*, int, _BS_size_t)); +extern int _BS_any __P((const _BS_word*, int, _BS_size_t)); +extern void _BS_clear __P((_BS_word*, int, _BS_size_t)); +extern void _BS_set __P((_BS_word*, int, _BS_size_t)); +extern void _BS_invert __P((_BS_word*, int, _BS_size_t)); +int _BS_lcompare_0 __P((_BS_word*, _BS_size_t, _BS_word*, _BS_size_t)); +extern void _BS_xor __P((_BS_word*,int, const _BS_word*,int, _BS_size_t)); + +#ifdef __cplusplus +} +#endif + +#endif _BS_PRIMS diff --git a/gnu/lib/libg++/include/builtin.h b/gnu/lib/libg++/include/builtin.h new file mode 100644 index 0000000..7f8299c --- /dev/null +++ b/gnu/lib/libg++/include/builtin.h @@ -0,0 +1,159 @@ +// 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. +*/ + +/* + arithmetic, etc. functions on built in types +*/ + + +#ifndef _builtin_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _builtin_h 1 + +#include <stddef.h> +#include <std.h> +#include <math.h> + +#ifdef __GNUG__ +#define _VOLATILE_VOID volatile void +#else +#define _VOLATILE_VOID void +#endif + +typedef void (*one_arg_error_handler_t)(const char*); +typedef void (*two_arg_error_handler_t)(const char*, const char*); + +long gcd(long, long); +long lg(unsigned long); +double pow(double, long); +long pow(long, long); + +extern "C" double start_timer(); +extern "C" double return_elapsed_time(double last_time = 0.0); + +char* dtoa(double x, char cvt = 'g', int width = 0, int prec = 6); + +unsigned int hashpjw(const char*); +unsigned int multiplicativehash(int); +unsigned int foldhash(double); + +extern _VOLATILE_VOID default_one_arg_error_handler(const char*); +extern _VOLATILE_VOID default_two_arg_error_handler(const char*, const char*); + +extern two_arg_error_handler_t lib_error_handler; + +extern two_arg_error_handler_t + set_lib_error_handler(two_arg_error_handler_t f); + + +double abs(double arg); +float abs(float arg); +short abs(short arg); +long abs(long arg); +int sign(long arg); +int sign(double arg); +long sqr(long arg); +double sqr(double arg); +int even(long arg); +int odd(long arg); +long lcm(long x, long y); +void (setbit)(long& x, long b); +void clearbit(long& x, long b); +int testbit(long x, long b); + +#if !defined(IV) + +#if ! _G_MATH_H_INLINES /* hpux and SCO define this in math.h */ +inline double abs(double arg) +{ + return (arg < 0.0)? -arg : arg; +} +#endif + +inline float abs(float arg) +{ + return (arg < 0.0)? -arg : arg; +} + +inline short abs(short arg) +{ + return (arg < 0)? -arg : arg; +} + +inline long abs(long arg) +{ + return (arg < 0)? -arg : arg; +} + +inline int sign(long arg) +{ + return (arg == 0) ? 0 : ( (arg > 0) ? 1 : -1 ); +} + +inline int sign(double arg) +{ + return (arg == 0.0) ? 0 : ( (arg > 0.0) ? 1 : -1 ); +} + +inline long sqr(long arg) +{ + return arg * arg; +} + +#if ! _G_MATH_H_INLINES /* hpux and SCO define this in math.h */ +inline double sqr(double arg) +{ + return arg * arg; +} +#endif + +inline int even(long arg) +{ + return !(arg & 1); +} + +inline int odd(long arg) +{ + return (arg & 1); +} + +inline long lcm(long x, long y) +{ + return x / gcd(x, y) * y; +} + +inline void (setbit)(long& x, long b) +{ + x |= (1 << b); +} + +inline void clearbit(long& x, long b) +{ + x &= ~(1 << b); +} + +inline int testbit(long x, long b) +{ + return ((x & (1 << b)) != 0); +} + +#endif +#endif diff --git a/gnu/lib/libg++/include/builtinbuf.h b/gnu/lib/libg++/include/builtinbuf.h new file mode 100644 index 0000000..fb91e6a --- /dev/null +++ b/gnu/lib/libg++/include/builtinbuf.h @@ -0,0 +1,63 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#ifndef _BUILTINBUF_H +#define _BUILTINBUF_H + +#ifdef __GNUC__ +#pragma interface +#endif + +#include <streambuf.h> + +// A builtinbuf a a streambuf where all the virtual operations +// call the _IO_jump_t table. + +class builtinbuf : public streambuf { + friend ios; + virtual int overflow(int); + virtual int underflow(); + virtual streamsize xsgetn(char *, streamsize); + virtual streamsize xsputn(const char *, streamsize); + virtual streambuf* setbuf(char*, int); + virtual int doallocate(); + virtual ~builtinbuf(); + virtual int sync(); + + 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 pbackfail(int c); + virtual streamsize sys_read(char* buf, streamsize size); + virtual streampos sys_seek(streamoff, _seek_dir); + virtual streamsize sys_write(const char*, streamsize); + virtual int sys_stat(void*); // Actually, a (struct stat*) + virtual int sys_close(); +#if 0 + virtual int get_column(); + virtual int set_column(int); +#endif + private: + builtinbuf() { } +}; +#endif /* _BUILTINBUF_H */ diff --git a/gnu/lib/libg++/include/compare.h b/gnu/lib/libg++/include/compare.h new file mode 100644 index 0000000..bd13614 --- /dev/null +++ b/gnu/lib/libg++/include/compare.h @@ -0,0 +1,91 @@ +// 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. +*/ + +#ifndef _compare_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _compare_h 1 + +#include <builtin.h> + +int compare(int a, int b); +int compare(short a, short b); +int compare(unsigned long a, unsigned long b); +int compare(unsigned int a, unsigned int b); +int compare(unsigned short a, unsigned short b); +int compare(unsigned char a, unsigned char b); +int compare(signed char a, signed char b); +int compare(float a, float b); +int compare(double a, double b); +int compare(const char* a, const char* b); + + +inline int compare(int a, int b) +{ + return a - b; +} + +inline int compare(short a, short b) +{ + return a - b; +} + + +inline int compare(signed char a, signed char b) +{ + return a - b; +} + +inline int compare(unsigned long a, unsigned long b) +{ + return (a < b)? -1 : (a > b)? 1 : 0; +} + +inline int compare(unsigned int a, unsigned int b) +{ + return (a < b)? -1 : (a > b)? 1 : 0; +} + +inline int compare(unsigned short a, unsigned short b) +{ + return (a < b)? -1 : (a > b)? 1 : 0; +} + +inline int compare(unsigned char a, unsigned char b) +{ + return (a < b)? -1 : (a > b)? 1 : 0; +} + +inline int compare(float a, float b) +{ + return (a < b)? -1 : (a > b)? 1 : 0; +} + +inline int compare(double a, double b) +{ + return (a < b)? -1 : (a > b)? 1 : 0; +} + +inline int compare(const char* a, const char* b) +{ + return strcmp(a,b); +} + +#endif diff --git a/gnu/lib/libg++/include/config.h b/gnu/lib/libg++/include/config.h new file mode 100644 index 0000000..b37ee84 --- /dev/null +++ b/gnu/lib/libg++/include/config.h @@ -0,0 +1 @@ +/* !Automatically generated from ./functions.def - DO NOT EDIT! */ diff --git a/gnu/lib/libg++/include/defines.h b/gnu/lib/libg++/include/defines.h new file mode 100644 index 0000000..ddb76e9 --- /dev/null +++ b/gnu/lib/libg++/include/defines.h @@ -0,0 +1,33 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1994 Free Software Foundation + written by Jason Merrill (jason@cygnus.com) + +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. +*/ + +#ifndef _defines_h +#define _defines_h + +#include <_G_config.h> +#include <stddef.h> + +const size_t NPOS = (size_t)(-1); +typedef void fvoid_t(); + +#ifndef _WINT_T +#define _WINT_T +typedef _G_wint_t wint_t; +#endif + +#endif diff --git a/gnu/lib/libg++/include/editbuf.h b/gnu/lib/libg++/include/editbuf.h new file mode 100644 index 0000000..8535155 --- /dev/null +++ b/gnu/lib/libg++/include/editbuf.h @@ -0,0 +1,183 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. + +Written by Per Bothner (bothner@cygnus.com). */ + +#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*/ + diff --git a/gnu/lib/libg++/include/floatio.h b/gnu/lib/libg++/include/floatio.h new file mode 100644 index 0000000..edfe297 --- /dev/null +++ b/gnu/lib/libg++/include/floatio.h @@ -0,0 +1,51 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* + * 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. + * + * %W% (Berkeley) %G% + */ + +/* + * 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 diff --git a/gnu/lib/libg++/include/fstream.h b/gnu/lib/libg++/include/fstream.h new file mode 100644 index 0000000..20dfbf2 --- /dev/null +++ b/gnu/lib/libg++/include/fstream.h @@ -0,0 +1,81 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#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(int fd, char *p, int l); /* Deprecated */ + fstreambase(const char *name, int mode, int prot=0664); + void close(); + filebuf* rdbuf() const { return (filebuf*) ios::rdbuf(); } + 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(int fd, char *p, int l) : fstreambase(fd, p, l) { } /*Deprecated*/ + 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(int fd, char *p, int l) : fstreambase(fd, p, l) { } /*Deprecated*/ + 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) { } + fstream(int fd, char *p, int l) : fstreambase(fd, p, l) { } /*Deprecated*/ + void open(const char *name, int mode, int prot=0664) + { fstreambase::open(name, mode, prot); } +}; +#endif /*!_FSTREAM_H*/ diff --git a/gnu/lib/libg++/include/indstream.h b/gnu/lib/libg++/include/indstream.h new file mode 100644 index 0000000..8047b82 --- /dev/null +++ b/gnu/lib/libg++/include/indstream.h @@ -0,0 +1,74 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. + +Written by Per Bothner (bothner@cygnus.com). */ + +#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 */ diff --git a/gnu/lib/libg++/include/iolibio.h b/gnu/lib/libg++/include/iolibio.h new file mode 100644 index 0000000..2a7c145 --- /dev/null +++ b/gnu/lib/libg++/include/iolibio.h @@ -0,0 +1,46 @@ +#include "libio.h" + +/* These emulate stdio functionality, but with a different name + (_IO_ungetc instead of ungetc), and using _IO_FILE instead of FILE. */ + +extern int _IO_fclose __P((_IO_FILE*)); +extern _IO_FILE *_IO_fdopen __P((int, const char*)); +extern int _IO_fflush __P((_IO_FILE*)); +extern int _IO_fgetpos __P((_IO_FILE*, _IO_fpos_t*)); +extern char* _IO_fgets __P((char*, int, _IO_FILE*)); +extern _IO_FILE *_IO_fopen __P((const char*, const char*)); +extern int _IO_fprintf __P((_IO_FILE*, const char*, ...)); +extern int _IO_fputs __P((const char*, _IO_FILE*)); +extern int _IO_fsetpos __P((_IO_FILE*, const _IO_fpos_t *)); +extern long int _IO_ftell __P((_IO_FILE*)); +extern _IO_size_t _IO_fwrite __P((const void*, + _IO_size_t, _IO_size_t, _IO_FILE*)); +extern char* _IO_gets __P((char*)); +extern void _IO_perror __P((const char*)); +extern int _IO_puts __P((const char*)); +extern int _IO_scanf __P((const char*, ...)); +extern void _IO_setbuffer __P((_IO_FILE *, char*, _IO_size_t)); +extern int _IO_setvbuf __P((_IO_FILE*, char*, int, _IO_size_t)); +extern int _IO_sscanf __P((const char*, const char*, ...)); +extern int _IO_sprintf __P((char *, const char*, ...)); +extern int _IO_ungetc __P((int, _IO_FILE*)); +extern int _IO_vsscanf __P((const char *, const char *, _IO_va_list)); +extern int _IO_vsprintf __P((char*, const char*, _IO_va_list)); +#ifndef _IO_pos_BAD +#define _IO_pos_BAD ((_IO_fpos_t)(-1)) +#endif +#define _IO_clearerr(FP) ((FP)->_flags &= ~(_IO_ERR_SEEN|_IO_EOF_SEEN)) +#define _IO_feof(__fp) (((__fp)->_flags & _IO_EOF_SEEN) != 0) +#define _IO_ferror(__fp) (((__fp)->_flags & _IO_ERR_SEEN) != 0) +#define _IO_fseek(__fp, __offset, __whence) \ + (_IO_seekoff(__fp, __offset, (_IO_off_t)(__whence)) == _IO_pos_BAD ? EOF : 0) +#define _IO_rewind(FILE) (void)_IO_seekoff(FILE, 0, 0) +#define _IO_vprintf(FORMAT, ARGS) _IO_vfprintf(_IO_stdout, FORMAT, ARGS) +#define _IO_freopen(FILENAME, MODE, FP) \ + (_IO_file_close_it(FP), _IO_file_fopen(FP, FILENAME, MODE)) +#define _IO_fileno(FP) ((FP)->_fileno) +extern _IO_FILE* _IO_popen __P((const char*, const char*)); +#define _IO_pclose _IO_fclose +#define _IO_setbuf(_FP, _BUF) _IO_setbuffer(_FP, _BUF, _IO_BUFSIZ) +#define _IO_setlinebuf(_FP) _IO_setvbuf(_FP, NULL, 1, 0) + diff --git a/gnu/lib/libg++/include/iomanip.h b/gnu/lib/libg++/include/iomanip.h new file mode 100644 index 0000000..cab4b97 --- /dev/null +++ b/gnu/lib/libg++/include/iomanip.h @@ -0,0 +1,159 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#ifndef _IOMANIP_H +#ifdef __GNUG__ +#pragma interface +#endif +#define _IOMANIP_H + +#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); +}; + +#ifdef __GNUG__ +extern template class smanip<int>; +extern template class smanip<ios::fmtflags>; +#endif + +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;} + +#ifdef __GNUG__ +extern template istream& operator>>(istream&, const smanip<int>&); +extern template istream& operator>>(istream&, const smanip<ios::fmtflags>&); +extern template ostream& operator<<(ostream&, const smanip<int>&); +extern template ostream& operator<<(ostream&, const smanip<ios::fmtflags>&); +#endif + +//----------------------------------------------------------------------------- +// Input-Stream Manipulators +//----------------------------------------------------------------------------- +// +template<class TP> class imanip; + +template<class TP> class iapp { + istream& (*_f)(istream&, TP); +public: + iapp(istream& (*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 /*!_IOMANIP_H*/ diff --git a/gnu/lib/libg++/include/iostream.h b/gnu/lib/libg++/include/iostream.h new file mode 100644 index 0000000..7348ce2 --- /dev/null +++ b/gnu/lib/libg++/include/iostream.h @@ -0,0 +1,227 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#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(); } + ostream& flush(); + ostream& put(char c) { _strbuf->sputc(c); return *this; } +#ifdef _STREAM_COMPAT + /* Temporary binary compatibility. REMOVE IN NEXT RELEASE. */ + ostream& put(unsigned char c) { return put((char)c); } + ostream& put(signed char c) { return put((char)c); } +#endif + ostream& write(const char *s, int n); + ostream& write(const unsigned char *s, int n) { return write((const char*)s, n);} + ostream& write(const signed char *s, int n) { return write((const char*)s, n);} + 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, _IO_va_list args); + + ostream& operator<<(char c); + ostream& operator<<(unsigned char c) { return (*this) << (char)c; } + ostream& operator<<(signed char c) { return (*this) << (char)c; } + ostream& operator<<(const char *s); + ostream& operator<<(const unsigned char *s) + { return (*this) << (const char*)s; } + ostream& operator<<(const signed char *s) + { return (*this) << (const char*)s; } + ostream& operator<<(const void *p); + ostream& operator<<(int n); + ostream& operator<<(unsigned int n); + ostream& operator<<(long n); + ostream& operator<<(unsigned long n); +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) + 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);} +#if _G_HAVE_BOOL + ostream& operator<<(bool b) { return operator<<((int)b); } +#endif + 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*); +#ifdef _STREAM_COMPAT + streambuf* ostreambuf() const { return _strbuf; } +#endif +}; + +class istream : virtual public ios +{ + // NOTE: If fields are changed, you must fix _fake_istream in stdstreams.C! + _IO_size_t _gcount; + + int _skip_ws(); + public: + istream() { _gcount = 0; } + istream(streambuf* sb, ostream*tied=NULL); + 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); } + 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); } + istream& read(char *ptr, int n); + istream& read(unsigned char *ptr, int n) { return read((char*)ptr, n); } + istream& read(signed char *ptr, int n) { return read((char*)ptr, n); } + 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(); + _IO_size_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, _IO_va_list args); +#ifdef _STREAM_COMPAT + istream& unget(char ch) { return putback(ch); } + int skip(int i); + streambuf* istreambuf() const { return _strbuf; } +#endif + + istream& operator>>(char*); + istream& operator>>(unsigned char* p) { return operator>>((char*)p); } + istream& operator>>(signed char*p) { return operator>>((char*)p); } + istream& operator>>(char& c); + istream& operator>>(unsigned char& c) {return operator>>((char&)c);} + istream& operator>>(signed char& c) {return operator>>((char&)c);} + istream& operator>>(int&); + istream& operator>>(long&); +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) + istream& operator>>(long long&); + istream& operator>>(unsigned long long&); +#endif + istream& operator>>(short&); + istream& operator>>(unsigned int&); + istream& operator>>(unsigned long&); + istream& operator>>(unsigned short&); +#if _G_HAVE_BOOL + istream& operator>>(bool&); +#endif + 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 +{ + _IO_size_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*/ diff --git a/gnu/lib/libg++/include/iostreamP.h b/gnu/lib/libg++/include/iostreamP.h new file mode 100644 index 0000000..720deb3 --- /dev/null +++ b/gnu/lib/libg++/include/iostreamP.h @@ -0,0 +1,34 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "streambuf.h" +#include "libioP.h" + +inline _IO_seekflags +convert_to_seekflags(int dir, int mode) +{ + return (_IO_seekflags)((int)dir + | (mode & ios::in ? _IO_seek_set : _IO_seek_not_in) + | (mode & ios::out ? _IO_seek_set : _IO_seek_not_out)); +} diff --git a/gnu/lib/libg++/include/libiberty.h b/gnu/lib/libg++/include/libiberty.h new file mode 100644 index 0000000..9854b4c --- /dev/null +++ b/gnu/lib/libg++/include/libiberty.h @@ -0,0 +1,107 @@ +/* Function declarations for libiberty. + Written by Cygnus Support, 1994. + + The libiberty library provides a number of functions which are + missing on some operating systems. We do not declare those here, + to avoid conflicts with the system header files on operating + systems that do support those functions. In this file we only + declare those functions which are specific to libiberty. */ + +#ifndef LIBIBERTY_H +#define LIBIBERTY_H + +#include "ansidecl.h" + +/* Build an argument vector from a string. Allocates memory using + malloc. Use freeargv to free the vector. */ + +extern char **buildargv PARAMS ((char *)); + +/* Free a vector returned by buildargv. */ + +extern void freeargv PARAMS ((char **)); + +/* Return the last component of a path name. */ + +extern char *basename PARAMS ((char *)); + +/* Concatenate an arbitrary number of strings, up to (char *) NULL. + Allocates memory using xmalloc. */ + +extern char *concat PARAMS ((const char *, ...)); + +/* Check whether two file descriptors refer to the same file. */ + +extern int fdmatch PARAMS ((int fd1, int fd2)); + +/* Get the amount of time the process has run, in microseconds. */ + +extern long get_run_time PARAMS ((void)); + +/* Allocate memory filled with spaces. Allocates using malloc. */ + +extern const char *spaces PARAMS ((int count)); + +/* Return the maximum error number for which strerror will return a + string. */ + +extern int errno_max PARAMS ((void)); + +/* Return the name of an errno value (e.g., strerrno (EINVAL) returns + "EINVAL"). */ + +extern const char *strerrno PARAMS ((int)); + +/* Given the name of an errno value, return the value. */ + +extern int strtoerrno PARAMS ((const char *)); + +/* Return the maximum signal number for which strsignal will return a + string. */ + +extern int signo_max PARAMS ((void)); + +/* Return the name of a signal number (e.g., strsigno (SIGHUP) returns + "SIGHUP"). */ + +extern const char *strsigno PARAMS ((int)); + +/* Given the name of a signal, return its number. */ + +extern int strtosigno PARAMS ((const char *)); + +/* Register a function to be run by xexit. Returns 0 on success. */ + +extern int xatexit PARAMS ((void (*fn) (void))); + +/* Exit, calling all the functions registered with xatexit. */ + +#ifndef __GNUC__ +extern void xexit PARAMS ((int status)); +#else +typedef void libiberty_voidfn PARAMS ((int status)); +__volatile__ libiberty_voidfn xexit; +#endif + +/* Set the program name used by xmalloc. */ + +extern void xmalloc_set_program_name PARAMS ((const char *)); + +/* Allocate memory without fail. If malloc fails, this will print a + message to stderr (using the name set by xmalloc_set_program_name, + if any) and then call xexit. + + FIXME: We do not declare the parameter type (size_t) in order to + avoid conflicts with other declarations of xmalloc that exist in + programs which use libiberty. */ + +extern PTR xmalloc (); + +/* Reallocate memory without fail. This works like xmalloc. + + FIXME: We do not declare the parameter types for the same reason as + xmalloc. */ + +extern PTR xrealloc (); + +#endif /* ! defined (LIBIBERTY_H) */ diff --git a/gnu/lib/libg++/include/libio.h b/gnu/lib/libg++/include/libio.h new file mode 100644 index 0000000..a064197 --- /dev/null +++ b/gnu/lib/libg++/include/libio.h @@ -0,0 +1,254 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* This is part of the iostream library. + Copyright (C) 1991, 1992 Per Bothner. */ + +#ifndef _IO_STDIO_H +#define _IO_STDIO_H + +#if 1 +#include <_G_config.h> +#define _IO_pos_t _G_fpos_t /* obsolete */ +#define _IO_fpos_t _G_fpos_t +#define _IO_size_t _G_size_t +#define _IO_ssize_t _G_ssize_t +#define _IO_off_t _G_off_t +#define _IO_pid_t _G_pid_t +#define _IO_uid_t _G_uid_t +#define _IO_HAVE_SYS_WAIT _G_HAVE_SYS_WAIT +#define _IO_HAVE_ST_BLKSIZE _G_HAVE_ST_BLKSIZE +#define _IO_BUFSIZ _G_BUFSIZ +#define _IO_va_list _G_va_list + +#ifdef _G_NEED_STDARG_H +/* This define avoids name pollution if we're using GNU stdarg.h */ +#define __need___va_list +#include <stdarg.h> +#ifdef __GNUC_VA_LIST +#undef _IO_va_list +#define _IO_va_list __gnuc_va_list +#endif /* __GNUC_VA_LIST */ +#endif + +#else +#include <_IO_config.h> +typedef _IO_fpos_t _IO_pos_t; +#endif + +#ifndef __P +#ifdef __STDC__ +#define __P(paramlist) paramlist +#else +#define __P(paramlist) () +#endif +#endif /*!__P*/ + +/* For backward compatibility */ +#ifndef _PARAMS +#define _PARAMS(paramlist) __P(paramlist) +#endif /*!_PARAMS*/ + +#ifndef __STDC__ +#define const +#endif +#define USE_DTOA + +#if 0 +#ifdef _IO_NEED_STDARG_H +#include <stdarg.h> +#endif +#endif + +#ifndef EOF +#define EOF (-1) +#endif +#ifndef NULL +#if !defined(__cplusplus) || defined(__GNUC__) +#define NULL ((void*)0) +#else +#define NULL (0) +#endif +#endif + +#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 + +/* 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 _IO_USER_BUF 1 /* User owns buffer; don't delete it on close. */ +#define _IO_UNBUFFERED 2 +#define _IO_NO_READS 4 /* Reading not allowed */ +#define _IO_NO_WRITES 8 /* Writing not allowd */ +#define _IO_EOF_SEEN 0x10 +#define _IO_ERR_SEEN 0x20 +#define _IO_DELETE_DONT_CLOSE 0x40 +#define _IO_LINKED 0x80 /* Set if linked (using _chain) to streambuf::_list_all.*/ +#define _IO_IN_BACKUP 0x100 +#define _IO_LINE_BUF 0x200 +#define _IO_TIED_PUT_GET 0x400 /* Set if put and get pointer logicly tied. */ +#define _IO_CURRENTLY_PUTTING 0x800 +#define _IO_IS_APPENDING 0x1000 +#define _IO_IS_FILEBUF 0x2000 + +/* These are "formatting flags" matching the iostream fmtflags enum values. */ +#define _IO_SKIPWS 01 +#define _IO_LEFT 02 +#define _IO_RIGHT 04 +#define _IO_INTERNAL 010 +#define _IO_DEC 020 +#define _IO_OCT 040 +#define _IO_HEX 0100 +#define _IO_SHOWBASE 0200 +#define _IO_SHOWPOINT 0400 +#define _IO_UPPERCASE 01000 +#define _IO_SHOWPOS 02000 +#define _IO_SCIENTIFIC 04000 +#define _IO_FIXED 010000 +#define _IO_UNITBUF 020000 +#define _IO_STDIO 040000 +#define _IO_DONT_CLOSE 0100000 + +/* A streammarker remembers a position in a buffer. */ + +struct _IO_jump_t; struct _IO_FILE; + +struct _IO_marker { + struct _IO_marker *_next; + struct _IO_FILE *_sbuf; + /* If _pos >= 0 + it points to _buf->Gbase()+_pos. FIXME comment */ + /* if _pos < 0, it points to _buf->eBptr()+_pos. FIXME comment */ + int _pos; +#if 0 + void set_streampos(streampos sp) { _spos = sp; } + void set_offset(int offset) { _pos = offset; _spos = (streampos)(-2); } + public: + streammarker(streambuf *sb); + ~streammarker(); + int saving() { return _spos == -2; } + int delta(streammarker&); + int delta(); +#endif +}; + +struct _IO_FILE { + int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ +#define _IO_file_flags _flags + + /* The following pointers correspond to the C++ streambuf protocol. */ + char* _IO_read_ptr; /* Current read pointer */ + char* _IO_read_end; /* End of get area. */ + char* _IO_read_base; /* Start of putback+get area. */ + char* _IO_write_base; /* Start of put area. */ + char* _IO_write_ptr; /* Current put pointer. */ + char* _IO_write_end; /* End of put area. */ + char* _IO_buf_base; /* Start of reserve area. */ + char* _IO_buf_end; /* End of reserve area. */ + /* The following fields are used to support backing up and undo. */ + char *_IO_save_base; /* Pointer to start of non-current get area. */ + char *_IO_backup_base; /* Pointer to first valid character of backup area */ + char *_IO_save_end; /* Pointer to end of non-current get area. */ + + struct _IO_marker *_markers; + + struct _IO_FILE *_chain; + + struct _IO_jump_t *_jumps; /* Jump table */ + + int _fileno; + int _blksize; + _IO_off_t _offset; + +#define __HAVE_COLUMN /* temporary */ + /* 1+column number of pbase(); 0 is unknown. */ + unsigned short _cur_column; + char _unused; + char _shortbuf[1]; + + /* char* _save_gptr; char* _save_egptr; */ +}; + +#ifndef __cplusplus +typedef struct _IO_FILE _IO_FILE; +#endif + +struct _IO_FILE_plus; +extern struct _IO_FILE_plus _IO_stdin_, _IO_stdout_, _IO_stderr_; +#define _IO_stdin ((_IO_FILE*)(&_IO_stdin_)) +#define _IO_stdout ((_IO_FILE*)(&_IO_stdout_)) +#define _IO_stderr ((_IO_FILE*)(&_IO_stderr_)) + +#ifdef __cplusplus +extern "C" { +#endif + +extern int __underflow __P((_IO_FILE*)); +extern int __uflow __P((_IO_FILE*)); +extern int __overflow __P((_IO_FILE*, int)); + +extern unsigned __adjust_column __P((unsigned start, const char *line, int count)); + +#define _IO_getc(_fp) \ + ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end ? __uflow(_fp) \ + : *(unsigned char*)(_fp)->_IO_read_ptr++) +#define _IO_peekc(_fp) \ + ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end \ + && __underflow(_fp) == EOF ? EOF \ + : *(unsigned char*)(_fp)->_IO_read_ptr) + +#define _IO_putc(_ch, _fp) \ + (((_fp)->_IO_write_ptr >= (_fp)->_IO_write_end) \ + ? __overflow(_fp, (unsigned char)(_ch)) \ + : (unsigned char)(*(_fp)->_IO_write_ptr++ = (_ch))) + +/* This one is for Emacs. */ +#define _IO_PENDING_OUTPUT_COUNT(_fp) \ + ((_fp)->_IO_write_ptr - (_fp)->_IO_write_base) + +extern int _IO_vfscanf __P((_IO_FILE*, const char*, _IO_va_list, int*)); +extern int _IO_vfprintf __P((_IO_FILE*, const char*, _IO_va_list)); +extern _IO_ssize_t _IO_padn __P((_IO_FILE *, int, _IO_ssize_t)); +extern _IO_size_t _IO_sgetn __P((_IO_FILE *, void*, _IO_size_t)); + +extern void _IO_free_backup_area __P((_IO_FILE*)); + +#ifdef __cplusplus +} +#endif + +#endif /* _IO_STDIO_H */ diff --git a/gnu/lib/libg++/include/libioP.h b/gnu/lib/libg++/include/libioP.h new file mode 100644 index 0000000..11d90f5 --- /dev/null +++ b/gnu/lib/libg++/include/libioP.h @@ -0,0 +1,308 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include <errno.h> +#ifndef errno +extern int errno; +#endif + +#include "iolibio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum _IO_seekflags_ { + _IO_seek_set = 0, + _IO_seek_cur = 1, + _IO_seek_end = 2, + + /* These bits are ignored unless the _IO_FILE has independent + read and write positions. */ + _IO_seek_not_in = 4, /* Don't move read posistion. */ + _IO_seek_not_out = 8, /* Don't move write posistion. */ + _IO_seek_pos_ignored = 16 /* Result is ignored (except EOF) */ +} _IO_seekflags; + +typedef int (*_IO_overflow_t) __P((_IO_FILE*, int)); +typedef int (*_IO_underflow_t) __P((_IO_FILE*)); +typedef _IO_size_t (*_IO_xsputn_t) __P((_IO_FILE*,const void*,_IO_size_t)); +typedef _IO_size_t (*_IO_xsgetn_t) __P((_IO_FILE*, void*, _IO_size_t)); +typedef _IO_ssize_t (*_IO_read_t) __P((_IO_FILE*, void*, _IO_ssize_t)); +typedef _IO_ssize_t (*_IO_write_t) __P((_IO_FILE*,const void*,_IO_ssize_t)); +typedef int (*_IO_stat_t) __P((_IO_FILE*, void*)); +typedef _IO_fpos_t (*_IO_seek_t) __P((_IO_FILE*, _IO_off_t, int)); +typedef int (*_IO_doallocate_t) __P((_IO_FILE*)); +typedef int (*_IO_pbackfail_t) __P((_IO_FILE*, int)); +typedef int (*_IO_setbuf_t) __P((_IO_FILE*, char *, _IO_ssize_t)); +typedef int (*_IO_sync_t) __P((_IO_FILE*)); +typedef void (*_IO_finish_t) __P((_IO_FILE*)); /* finalize */ +typedef int (*_IO_close_t) __P((_IO_FILE*)); /* finalize */ +typedef _IO_fpos_t (*_IO_seekoff_t) __P((_IO_FILE*, _IO_off_t, _IO_seekflags)); + +/* The _IO_seek_cur and _IO_seek_end options are not allowed. */ +typedef _IO_fpos_t (*_IO_seekpos_t) __P((_IO_FILE*, _IO_fpos_t, _IO_seekflags)); + +struct _IO_jump_t { + _IO_overflow_t __overflow; + _IO_underflow_t __underflow; + _IO_xsputn_t __xsputn; + _IO_xsgetn_t __xsgetn; + _IO_read_t __read; + _IO_write_t __write; + _IO_doallocate_t __doallocate; + _IO_pbackfail_t __pbackfail; + _IO_setbuf_t __setbuf; + _IO_sync_t __sync; + _IO_finish_t __finish; + _IO_close_t __close; + _IO_stat_t __stat; + _IO_seek_t __seek; + _IO_seekoff_t __seekoff; + _IO_seekpos_t __seekpos; + _IO_underflow_t __uflow; +#if 0 + get_column; + set_column; +#endif +}; + +/* We always allocate an extra word following an _IO_FILE. + This is for compatibility with C++ streambuf; the word can + be used to smash to a pointer to a virtual function table. */ + +struct _IO_FILE_plus { + _IO_FILE file; + const void *vtable; +}; + +/* Generic functions */ + +extern _IO_fpos_t _IO_seekoff __P((_IO_FILE*, _IO_off_t, _IO_seekflags)); +extern _IO_fpos_t _IO_seekpos __P((_IO_FILE*, _IO_fpos_t, _IO_seekflags)); + +extern int _IO_switch_to_get_mode __P((_IO_FILE*)); +extern void _IO_init __P((_IO_FILE*, int)); +extern int _IO_sputbackc __P((_IO_FILE*, int)); +extern int _IO_sungetc __P((_IO_FILE*)); +extern void _IO_un_link __P((_IO_FILE*)); +extern void _IO_link_in __P((_IO_FILE *)); +extern void _IO_doallocbuf __P((_IO_FILE*)); +extern void _IO_unsave_markers __P((_IO_FILE*)); +extern void _IO_setb __P((_IO_FILE*, char*, char*, int)); +extern unsigned _IO_adjust_column __P((unsigned, const char *, int)); +#define _IO_sputn(__fp, __s, __n) (__fp->_jumps->__xsputn(__fp, __s, __n)) + +/* Marker-related function. */ + +extern void _IO_init_marker __P((struct _IO_marker *, _IO_FILE *)); +extern void _IO_remove_marker __P((struct _IO_marker*)); +extern int _IO_marker_difference __P((struct _IO_marker *, struct _IO_marker *)); +extern int _IO_marker_delta __P((struct _IO_marker *)); +extern int _IO_seekmark __P((_IO_FILE *, struct _IO_marker *, int)); + +/* Default jumptable functions. */ + +extern int _IO_default_underflow __P((_IO_FILE*)); +extern int _IO_default_uflow _PARAMS((_IO_FILE*)); +extern int _IO_default_doallocate __P((_IO_FILE*)); +extern void _IO_default_finish __P((_IO_FILE *)); +extern int _IO_default_pbackfail __P((_IO_FILE*, int)); +extern int _IO_default_setbuf __P((_IO_FILE *, char*, _IO_ssize_t)); +extern _IO_size_t _IO_default_xsputn __P((_IO_FILE *, const void*, _IO_size_t)); +extern _IO_size_t _IO_default_xsgetn __P((_IO_FILE *, void*, _IO_size_t)); +extern _IO_fpos_t _IO_default_seekoff __P((_IO_FILE*, _IO_off_t, _IO_seekflags)); +extern _IO_fpos_t _IO_default_seekpos __P((_IO_FILE*, _IO_fpos_t, _IO_seekflags)); +extern _IO_ssize_t _IO_default_write __P((_IO_FILE*,const void*,_IO_ssize_t)); +extern _IO_ssize_t _IO_default_read __P((_IO_FILE*, void*, _IO_ssize_t)); +extern int _IO_default_stat __P((_IO_FILE*, void*)); +extern _IO_fpos_t _IO_default_seek __P((_IO_FILE*, _IO_off_t, int)); +extern int _IO_default_sync __P((_IO_FILE*)); +#define _IO_default_close ((_IO_close_t)_IO_default_sync) + +extern struct _IO_jump_t _IO_file_jumps; +extern struct _IO_jump_t _IO_streambuf_jumps; +extern struct _IO_jump_t _IO_proc_jumps; +extern struct _IO_jump_t _IO_str_jumps; +extern int _IO_do_write __P((_IO_FILE*, const char*, _IO_size_t)); +extern int _IO_flush_all __P(()); +extern void _IO_cleanup __P(()); +extern void _IO_flush_all_linebuffered __P(()); + +#define _IO_do_flush(_f) \ + _IO_do_write(_f, (_f)->_IO_write_base, \ + (_f)->_IO_write_ptr-(_f)->_IO_write_base) +#define _IO_in_put_mode(_fp) ((_fp)->_flags & _IO_CURRENTLY_PUTTING) +#define _IO_mask_flags(fp, f, mask) \ + ((fp)->_flags = ((fp)->_flags & ~(mask)) | ((f) & (mask))) +#define _IO_setg(fp, eb, g, eg) ((fp)->_IO_read_base = (eb),\ + (fp)->_IO_read_ptr = (g), (fp)->_IO_read_end = (eg)) +#define _IO_setp(__fp, __p, __ep) \ + ((__fp)->_IO_write_base = (__fp)->_IO_write_ptr = __p, (__fp)->_IO_write_end = (__ep)) +#define _IO_have_backup(fp) ((fp)->_IO_save_base != NULL) +#define _IO_in_backup(fp) ((fp)->_flags & _IO_IN_BACKUP) +#define _IO_have_markers(fp) ((fp)->_markers != NULL) +#define _IO_blen(p) ((fp)->_IO_buf_end - (fp)->_IO_buf_base) + +/* Jumptable functions for files. */ + +extern int _IO_file_doallocate __P((_IO_FILE*)); +extern int _IO_file_setbuf __P((_IO_FILE *, char*, _IO_ssize_t)); +extern _IO_fpos_t _IO_file_seekoff __P((_IO_FILE*, _IO_off_t, _IO_seekflags)); +extern _IO_size_t _IO_file_xsputn __P((_IO_FILE*,const void*,_IO_size_t)); +extern int _IO_file_stat __P((_IO_FILE*, void*)); +extern int _IO_file_close __P((_IO_FILE*)); +extern int _IO_file_underflow __P((_IO_FILE *)); +extern int _IO_file_overflow __P((_IO_FILE *, int)); +#define _IO_file_is_open(__fp) ((__fp)->_fileno >= 0) +extern void _IO_file_init __P((_IO_FILE*)); +extern _IO_FILE* _IO_file_attach __P((_IO_FILE*, int)); +extern _IO_FILE* _IO_file_fopen __P((_IO_FILE*, const char*, const char*)); +extern _IO_ssize_t _IO_file_write __P((_IO_FILE*,const void*,_IO_ssize_t)); +extern _IO_ssize_t _IO_file_read __P((_IO_FILE*, void*, _IO_ssize_t)); +extern int _IO_file_sync __P((_IO_FILE*)); +extern int _IO_file_close_it __P((_IO_FILE*)); +extern _IO_fpos_t _IO_file_seek __P((_IO_FILE *, _IO_off_t, int)); +extern void _IO_file_finish __P((_IO_FILE*)); + +/* Other file functions. */ +extern _IO_FILE* _IO_file_attach __P((_IO_FILE *, int)); + +/* Jumptable functions for proc_files. */ +extern _IO_FILE* _IO_proc_open __P((_IO_FILE*, const char*, const char *)); +extern int _IO_proc_close __P((_IO_FILE*)); + +/* Jumptable functions for strfiles. */ +extern int _IO_str_underflow __P((_IO_FILE*)); +extern int _IO_str_overflow __P((_IO_FILE *, int)); +extern int _IO_str_pbackfail __P((_IO_FILE*, int)); +extern _IO_fpos_t _IO_str_seekoff __P((_IO_FILE*,_IO_off_t,_IO_seekflags)); + +/* Other strfile functions */ +extern void _IO_str_init_static __P((_IO_FILE *, char*, int, char*)); +extern void _IO_str_init_readonly __P((_IO_FILE *, const char*, int)); +extern _IO_ssize_t _IO_str_count __P ((_IO_FILE*)); + +extern _IO_size_t _IO_getline __P((_IO_FILE*,char*,_IO_size_t,int,int)); +extern double _IO_strtod __P((const char *, char **)); +extern char * _IO_dtoa __P((double __d, int __mode, int __ndigits, + int *__decpt, int *__sign, char **__rve)); +extern int _IO_outfloat __P((double __value, _IO_FILE *__sb, int __type, + int __width, int __precision, int __flags, + int __sign_mode, int __fill)); + +extern _IO_FILE *_IO_list_all; +extern void (*_IO_cleanup_registration_needed)(); + +#ifndef EOF +#define EOF (-1) +#endif +#ifndef NULL +#if !defined(__cplusplus) || defined(__GNUC__) +#define NULL ((void*)0) +#else +#define NULL (0) +#endif +#endif + +#define FREE_BUF(_B) free(_B) +#define ALLOC_BUF(_S) (char*)malloc(_S) + +#ifndef OS_FSTAT +#define OS_FSTAT fstat +#endif +struct stat; +extern _IO_ssize_t _IO_read __P((int, void*, _IO_size_t)); +extern _IO_ssize_t _IO_write __P((int, const void*, _IO_size_t)); +extern _IO_off_t _IO_lseek __P((int, _IO_off_t, int)); +extern int _IO_close __P((int)); +extern int _IO_fstat __P((int, struct stat *)); + +/* Operations on _IO_fpos_t. + Normally, these are trivial, but we provide hooks for configurations + where an _IO_fpos_t is a struct. + Note that _IO_off_t must be an integral type. */ + +/* _IO_pos_BAD is an _IO_fpos_t value indicating error, unknown, or EOF. */ +#ifndef _IO_pos_BAD +#define _IO_pos_BAD ((_IO_fpos_t)(-1)) +#endif +/* _IO_pos_as_off converts an _IO_fpos_t value to an _IO_off_t value. */ +#ifndef _IO_pos_as_off +#define _IO_pos_as_off(__pos) ((_IO_off_t)(__pos)) +#endif +/* _IO_pos_adjust adjust an _IO_fpos_t by some number of bytes. */ +#ifndef _IO_pos_adjust +#define _IO_pos_adjust(__pos, __delta) ((__pos) += (__delta)) +#endif +/* _IO_pos_0 is an _IO_fpos_t value indicating beginning of file. */ +#ifndef _IO_pos_0 +#define _IO_pos_0 ((_IO_fpos_t)0) +#endif + +#ifdef __cplusplus +} +#endif + +/* check following! */ +#define FILEBUF_LITERAL(CHAIN, FLAGS, FD) \ + { _IO_MAGIC+_IO_LINKED+_IO_IS_FILEBUF+FLAGS, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAIN, &_IO_file_jumps, FD} + +/* Define builtinbuf_vtable as a name for the virtual function table + of the builtinbuf class. */ +#if !defined(builtinbuf_vtable) && defined(__cplusplus) +#ifdef __GNUC__ +extern char builtinbuf_vtable[] + asm (_G_VTABLE_LABEL_PREFIX +#if _G_VTABLE_LABEL_HAS_LENGTH + "10" +#endif + "builtinbuf"); +#else /* !__GNUC__ */ +#if _G_VTABLE_LABEL_HAS_LENGTH +#define builtinbuf_vtable _G_VTABLE_LABEL_PREFIX_ID##10builtinbuf +#else +#define builtinbuf_vtable _G_VTABLE_LABEL_PREFIX_ID##builtinbuf +#endif +extern char builtinbuf_vtable[]; +#endif /* !__GNUC__ */ +#endif /* !defined(builtinbuf_vtable) && defined(__cplusplus) */ + +#if defined(__STDC__) || defined(__cplusplus) +#define _IO_va_start(args, last) va_start(args, last) +#else +#define _IO_va_start(args, last) va_start(args) +#endif + +extern struct _IO_fake_stdiobuf _IO_stdin_buf, _IO_stdout_buf, _IO_stderr_buf; + +#if 1 +#define COERCE_FILE(FILE) /* Nothing */ +#else +/* This is part of the kludge for binary compatibility with old stdio. */ +#define COERCE_FILE(FILE) \ + (((FILE)->_IO_file_flags & _IO_MAGIC_MASK) == _OLD_MAGIC_MASK \ + && (FILE) = *(FILE**)&((int*)fp)[1]) +#endif diff --git a/gnu/lib/libg++/include/new.h b/gnu/lib/libg++/include/new.h new file mode 100644 index 0000000..61bbba5 --- /dev/null +++ b/gnu/lib/libg++/include/new.h @@ -0,0 +1,27 @@ +#ifndef _new_h +#ifdef __GNUG__ +#pragma interface +#endif +#define _new_h 1 + +#include <defines.h> + +#ifndef NO_LIBGXX_MALLOC +#define MALLOC_ALIGN_MASK 7 /* ptrs aligned at 8 byte boundaries */ +#define MALLOC_MIN_OVERHEAD 8 /* 8 bytes of overhead per pointer */ +#endif + +extern "C" fvoid_t *set_new_handler(fvoid_t *); + +#ifdef __GNUG__ +extern fvoid_t *__new_handler; +extern "C" void __default_new_handler(); + +#define NEW(where) new ( where ) +#endif + +// default placement version of operator new +inline void *operator new(size_t, void *place) { return place; } +inline void *operator new[](size_t, void *place) { return place; } + +#endif diff --git a/gnu/lib/libg++/include/parsestream.h b/gnu/lib/libg++/include/parsestream.h new file mode 100644 index 0000000..b168707 --- /dev/null +++ b/gnu/lib/libg++/include/parsestream.h @@ -0,0 +1,154 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. + +Written by Per Bothner (bothner@cygnus.com). */ + +#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 streambuf { + protected: + _IO_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() { 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)*/ diff --git a/gnu/lib/libg++/include/pfstream.h b/gnu/lib/libg++/include/pfstream.h new file mode 100644 index 0000000..687faf6 --- /dev/null +++ b/gnu/lib/libg++/include/pfstream.h @@ -0,0 +1,57 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifndef _PFSTREAM_H +#define _PFSTREAM_H +#ifdef __GNUG__ +#pragma interface +#endif +#include <fstream.h> + +// ipfstream foo("NAME") is like: ifstream foo("NAME"). However, +// if NAME starts *or ends* with a '|', the remainder of NAME is +// evaluated as a shell command (using a procbuf), and all input +// read from foo is whatever that shell writes to its standard output. +// E.g. ipfstream foo("|zcat foo.Z") or ipfstream foo("zcat foo.Z|") +// (These two forms are equivalent.) + +class ipfstream : public ifstream { + public: + ipfstream(const char *name, int mode=ios::in, int prot=0664); +}; + +// opfstream foo("NAME") is like: ofstream foo("NAME"). +// However, if NAME starts with a '|', the remainder of NAME is +// evaluated as a shell command (using a procbuf), and all output +// written to foo is piped to the standard input of that shell. +// E.g. opfstream foo("|more"); + +class opfstream : public ofstream { + public: + opfstream(const char *name, int mode=ios::out, int prot=0664); +}; +#endif /*!_PFSTREAM_H*/ + diff --git a/gnu/lib/libg++/include/procbuf.h b/gnu/lib/libg++/include/procbuf.h new file mode 100644 index 0000000..092d9cf --- /dev/null +++ b/gnu/lib/libg++/include/procbuf.h @@ -0,0 +1,39 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#include <streambuf.h> + +class procbuf : public filebuf { + /* Following fields must match those in struct _IO_proc_file */ + _IO_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(); +}; diff --git a/gnu/lib/libg++/include/regex.h b/gnu/lib/libg++/include/regex.h new file mode 100644 index 0000000..9e404e8 --- /dev/null +++ b/gnu/lib/libg++/include/regex.h @@ -0,0 +1,272 @@ +/* Definitions for data structures callers pass the regex library. + + Copyright (C) 1985, 1989-92 Free Software Foundation, Inc. + +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. +*/ + +#ifndef __REGEXP_LIBRARY +#define __REGEXP_LIBRARY + +#if defined(SHORT_NAMES) || defined(VMS) +#define re_compile_pattern recmppat +#define re_pattern_buffer repatbuf +#define re_registers reregs +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Define number of parens for which we record the beginnings and ends. + This affects how much space the `struct re_registers' type takes up. */ +#ifndef RE_NREGS +#define RE_NREGS 10 +#endif + +#define BYTEWIDTH 8 + + +/* Maximum number of duplicates an interval can allow. */ +#ifndef RE_DUP_MAX /* kludge for AIX, which defines it */ +#define RE_DUP_MAX ((1 << 15) - 1) +#endif + +/* This defines the various regexp syntaxes. */ +extern int obscure_syntax; + + +/* The following bits are used in the obscure_syntax variable to choose among + alternative regexp syntaxes. */ + +/* If this bit is set, plain parentheses serve as grouping, and backslash + parentheses are needed for literal searching. + If not set, backslash-parentheses are grouping, and plain parentheses + are for literal searching. */ +#define RE_NO_BK_PARENS 1 + +/* If this bit is set, plain | serves as the `or'-operator, and \| is a + literal. + If not set, \| serves as the `or'-operator, and | is a literal. */ +#define RE_NO_BK_VBAR (1 << 1) + +/* If this bit is not set, plain + or ? serves as an operator, and \+, \? are + literals. + If set, \+, \? are operators and plain +, ? are literals. */ +#define RE_BK_PLUS_QM (1 << 2) + +/* If this bit is set, | binds tighter than ^ or $. + If not set, the contrary. */ +#define RE_TIGHT_VBAR (1 << 3) + +/* If this bit is set, then treat newline as an OR operator. + If not set, treat it as a normal character. */ +#define RE_NEWLINE_OR (1 << 4) + +/* If this bit is set, then special characters may act as normal + characters in some contexts. Specifically, this applies to: + ^ -- only special at the beginning, or after ( or |; + $ -- only special at the end, or before ) or |; + *, +, ? -- only special when not after the beginning, (, or |. + If this bit is not set, special characters (such as *, ^, and $) + always have their special meaning regardless of the surrounding + context. */ +#define RE_CONTEXT_INDEP_OPS (1 << 5) + +/* If this bit is not set, then \ before anything inside [ and ] is taken as + a real \. + If set, then such a \ escapes the following character. This is a + special case for awk. */ +#define RE_AWK_CLASS_HACK (1 << 6) + +/* If this bit is set, then \{ and \} or { and } serve as interval operators. + If not set, then \{ and \} and { and } are treated as literals. */ +#define RE_INTERVALS (1 << 7) + +/* If this bit is not set, then \{ and \} serve as interval operators and + { and } are literals. + If set, then { and } serve as interval operators and \{ and \} are + literals. */ +#define RE_NO_BK_CURLY_BRACES (1 << 8) + +/* If this bit is set, then character classes are supported; they are: + [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], + [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. + If not set, then character classes are not supported. */ +#define RE_CHAR_CLASSES (1 << 9) + +/* If this bit is set, then the dot re doesn't match a null byte. + If not set, it does. */ +#define RE_DOT_NOT_NULL (1 << 10) + +/* If this bit is set, then [^...] doesn't match a newline. + If not set, it does. */ +#define RE_HAT_NOT_NEWLINE (1 << 11) + +/* If this bit is set, back references are recognized. + If not set, they aren't. */ +#define RE_NO_BK_REFS (1 << 12) + +/* If this bit is set, back references must refer to a preceding + subexpression. If not set, a back reference to a nonexistent + subexpression is treated as literal characters. */ +#define RE_NO_EMPTY_BK_REF (1 << 13) + +/* If this bit is set, bracket expressions can't be empty. + If it is set, they can be empty. */ +#define RE_NO_EMPTY_BRACKETS (1 << 14) + +/* If this bit is set, then *, +, ? and { cannot be first in an re or + immediately after a |, or a (. Furthermore, a | cannot be first or + last in an re, or immediately follow another | or a (. Also, a ^ + cannot appear in a nonleading position and a $ cannot appear in a + nontrailing position (outside of bracket expressions, that is). */ +#define RE_CONTEXTUAL_INVALID_OPS (1 << 15) + +/* If this bit is set, then +, ? and | aren't recognized as operators. + If it's not, they are. */ +#define RE_LIMITED_OPS (1 << 16) + +/* If this bit is set, then an ending range point has to collate higher + or equal to the starting range point. + If it's not set, then when the ending range point collates higher + than the starting range point, the range is just considered empty. */ +#define RE_NO_EMPTY_RANGES (1 << 17) + +/* If this bit is set, then a hyphen (-) can't be an ending range point. + If it isn't, then it can. */ +#define RE_NO_HYPHEN_RANGE_END (1 << 18) + + +/* Define combinations of bits for the standard possibilities. */ +#define RE_SYNTAX_POSIX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR \ + | RE_CONTEXT_INDEP_OPS) +#define RE_SYNTAX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR \ + | RE_CONTEXT_INDEP_OPS | RE_AWK_CLASS_HACK) +#define RE_SYNTAX_EGREP (RE_NO_BK_PARENS | RE_NO_BK_VBAR \ + | RE_CONTEXT_INDEP_OPS | RE_NEWLINE_OR) +#define RE_SYNTAX_GREP (RE_BK_PLUS_QM | RE_NEWLINE_OR) +#define RE_SYNTAX_EMACS 0 +#define RE_SYNTAX_POSIX_BASIC (RE_INTERVALS | RE_BK_PLUS_QM \ + | RE_CHAR_CLASSES | RE_DOT_NOT_NULL \ + | RE_HAT_NOT_NEWLINE | RE_NO_EMPTY_BK_REF \ + | RE_NO_EMPTY_BRACKETS | RE_LIMITED_OPS \ + | RE_NO_EMPTY_RANGES | RE_NO_HYPHEN_RANGE_END) + +#define RE_SYNTAX_POSIX_EXTENDED (RE_INTERVALS | RE_NO_BK_CURLY_BRACES \ + | RE_NO_BK_VBAR | RE_NO_BK_PARENS \ + | RE_HAT_NOT_NEWLINE | RE_CHAR_CLASSES \ + | RE_NO_EMPTY_BRACKETS | RE_CONTEXTUAL_INVALID_OPS \ + | RE_NO_BK_REFS | RE_NO_EMPTY_RANGES \ + | RE_NO_HYPHEN_RANGE_END) + + +/* This data structure is used to represent a compiled pattern. */ + +struct re_pattern_buffer + { + char *buffer; /* Space holding the compiled pattern commands. */ + long allocated; /* Size of space that `buffer' points to. */ + long used; /* Length of portion of buffer actually occupied */ + char *fastmap; /* Pointer to fastmap, if any, or zero if none. */ + /* re_search uses the fastmap, if there is one, + to skip over totally implausible characters. */ + char *translate; /* Translate table to apply to all characters before + comparing, or zero for no translation. + The translation is applied to a pattern when it is + compiled and to data when it is matched. */ + char fastmap_accurate; + /* Set to zero when a new pattern is stored, + set to one when the fastmap is updated from it. */ + char can_be_null; /* Set to one by compiling fastmap + if this pattern might match the null string. + It does not necessarily match the null string + in that case, but if this is zero, it cannot. + 2 as value means can match null string + but at end of range or before a character + listed in the fastmap. */ + }; + + +/* search.c (search_buffer) needs this one value. It is defined both in + regex.c and here. */ +#define RE_EXACTN_VALUE 1 + + +/* Structure to store register contents data in. + + Pass the address of such a structure as an argument to re_match, etc., + if you want this information back. + + For i from 1 to RE_NREGS - 1, start[i] records the starting index in + the string of where the ith subexpression matched, and end[i] records + one after the ending index. start[0] and end[0] are analogous, for + the entire pattern. */ + +struct re_registers + { + int start[RE_NREGS]; + int end[RE_NREGS]; + }; + + + +#if defined(__STDC__) || defined(__cplusplus) + +extern char *re_compile_pattern (const char *, int, struct re_pattern_buffer *); +/* Is this really advertised? */ +extern void re_compile_fastmap (struct re_pattern_buffer *); +extern int re_search (struct re_pattern_buffer *, char*, int, int, int, + struct re_registers *); +extern int re_search_2 (struct re_pattern_buffer *, char *, int, + char *, int, int, int, + struct re_registers *, int); +extern int re_match (struct re_pattern_buffer *, char *, int, int, + struct re_registers *); +extern int re_match_2 (struct re_pattern_buffer *, char *, int, + char *, int, int, struct re_registers *, int); + +#if 0 +/* 4.2 bsd compatibility. */ +extern char *re_comp (char *); +extern int re_exec (char *); +#endif + +#else /* !__STDC__ */ + +#define const /* nothing */ +extern char *re_compile_pattern (); +/* Is this really advertised? */ +extern void re_compile_fastmap (); +extern int re_search (), re_search_2 (); +extern int re_match (), re_match_2 (); + +#if 0 +/* 4.2 bsd compatibility. */ +extern char *re_comp (); +extern int re_exec (); +#endif + +#endif /* __STDC__ */ + + +#ifdef SYNTAX_TABLE +extern char *re_syntax_table; +#endif + +#ifdef __cplusplus +extern int re_max_failures; +} +#endif + +#endif /* !__REGEXP_LIBRARY */ diff --git a/gnu/lib/libg++/include/std.h b/gnu/lib/libg++/include/std.h new file mode 100644 index 0000000..069b522 --- /dev/null +++ b/gnu/lib/libg++/include/std.h @@ -0,0 +1,35 @@ +// 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. +*/ + +#ifndef _std_h +#define _std_h 1 + +#include <_G_config.h> +#include <defines.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> + +extern "C" { +int strcasecmp _G_ARGS((const char*, const char*)); +} + +#endif diff --git a/gnu/lib/libg++/include/stdiostream.h b/gnu/lib/libg++/include/stdiostream.h new file mode 100644 index 0000000..8c8215e --- /dev/null +++ b/gnu/lib/libg++/include/stdiostream.h @@ -0,0 +1,77 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifndef _STDIOSTREAM_H +#define _STDIOSTREAM_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include <iostream.h> +#include <stdio.h> + +class stdiobuf : public filebuf { + protected: + FILE *_file; + public: + FILE* stdiofile() const { return _file; } + stdiobuf(FILE *); + ~stdiobuf(); + int buffered () const { return _flags & _IO_UNBUFFERED ? 0 : 1; } + void buffered (int); + virtual streamsize sys_read(char*, streamsize); + virtual streampos sys_seek(streamoff, _seek_dir); + virtual streamsize sys_write(const char*, streamsize); + virtual int sys_close(); + virtual int sync(); + virtual int overflow(int c = EOF); + streamsize xsputn(const char* s, streamsize n); +}; + +class istdiostream : public istream +{ +private: + stdiobuf _file; +public: + istdiostream (FILE* __f) : _file(__f), istream() { init(&_file); } + stdiobuf* rdbuf()/* const */ { return &_file; } + int buffered () const { return _file.buffered (); } + void buffered (int _i) { _file.buffered (_i); } +}; + +class ostdiostream : public ostream +{ +private: + stdiobuf _file; +public: + ostdiostream (FILE* __f) : _file(__f), ostream() { init(&_file); } + stdiobuf* rdbuf() /* const */ { return &_file; } + int buffered () const { return _file.buffered (); } + void buffered (int _i) { _file.buffered (_i); } +}; + +#endif /* !_STDIOSTREAM_H */ diff --git a/gnu/lib/libg++/include/stream.h b/gnu/lib/libg++/include/stream.h new file mode 100644 index 0000000..488f367 --- /dev/null +++ b/gnu/lib/libg++/include/stream.h @@ -0,0 +1,55 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#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 */ diff --git a/gnu/lib/libg++/include/streambuf.h b/gnu/lib/libg++/include/streambuf.h new file mode 100644 index 0000000..60181a4 --- /dev/null +++ b/gnu/lib/libg++/include/streambuf.h @@ -0,0 +1,455 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#ifndef _STREAMBUF_H +#define _STREAMBUF_H +#ifdef __GNUG__ +#pragma interface +#endif + +/* #define _G_IO_THROW */ /* Not implemented: ios::failure */ + +extern "C" { +#include <libio.h> +} +//#include <_G_config.h> +#ifdef _IO_NEED_STDARG_H +#include <stdarg.h> +#endif +#ifndef _IO_va_list +#define _IO_va_list char * +#endif + +#ifndef EOF +#define EOF (-1) +#endif +#ifndef NULL +#ifdef __GNUC__ +#define NULL ((void*)0) +#else +#define NULL (0) +#endif +#endif + +#ifndef _IO_wchar_t +#define _IO_wchar_t short +#endif + +class istream; /* Work-around for a g++ name mangling bug. Fixed in 2.6. */ +class ostream; class streambuf; + +// In case some header files defines these as macros. +#undef open +#undef close + +extern "C" int __underflow(struct _IO_FILE*); +extern "C" int __overflow(struct _IO_FILE*, int); + +typedef _IO_off_t streamoff; +typedef _IO_fpos_t streampos; +typedef _IO_ssize_t streamsize; + +typedef unsigned long __fmtflags; +typedef unsigned char __iostate; + +struct _ios_fields +{ // The data members of an ios. + // Directly using _strbuf is dangerous, because the vtable + // pointer can be NULL. Use rdbuf() when in doubt. + streambuf *_strbuf; + ostream* _tie; + int _width; + __fmtflags _flags; + _IO_wchar_t _fill; + __iostate _state; + __iostate _exceptions; + int _precision; + + void *_arrays; /* Support for ios::iword and ios::pword. */ +}; + +#define _IOS_GOOD 0 +#define _IOS_EOF 1 +#define _IOS_FAIL 2 +#define _IOS_BAD 4 + +#define _IO_INPUT 1 +#define _IO_OUTPUT 2 +#define _IO_ATEND 4 +#define _IO_APPEND 8 +#define _IO_TRUNC 16 +#define _IO_NOCREATE 32 +#define _IO_NOREPLACE 64 +#define _IO_BIN 128 + +#ifdef _STREAM_COMPAT +enum state_value { + _good = _IOS_GOOD, + _eof = _IOS_EOF, + _fail = _IOS_FAIL, + _bad = _IOS_BAD }; +enum open_mode { + input = _IO_INPUT, + output = _IO_OUTPUT, + atend = _IO_ATEND, + append = _IO_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 = _IO_INPUT, + out = _IO_OUTPUT, + ate = _IO_ATEND, + app = _IO_APPEND, + trunc = _IO_TRUNC, + nocreate = _IO_NOCREATE, + noreplace = _IO_NOREPLACE, + bin = _IOS_BIN }; + enum seek_dir { beg, cur, end}; + // ANSI: typedef enum seek_dir seekdir; etc + // NOTE: If adding flags here, before to update ios::bitalloc(). + enum { skipws=_IO_SKIPWS, + left=_IO_LEFT, right=_IO_RIGHT, internal=_IO_INTERNAL, + dec=_IO_DEC, oct=_IO_OCT, hex=_IO_HEX, + showbase=_IO_SHOWBASE, showpoint=_IO_SHOWPOINT, + uppercase=_IO_UPPERCASE, showpos=_IO_SHOWPOS, + scientific=_IO_SCIENTIFIC, fixed=_IO_FIXED, + unitbuf=_IO_UNITBUF, stdio=_IO_STDIO, + dont_close=_IO_DONT_CLOSE // Don't delete streambuf on stream destruction + }; + enum { // Masks. + basefield=dec+oct+hex, + floatfield = scientific+fixed, + adjustfield = left+right+internal + }; + +#ifdef _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. + _IO_wchar_t fill() const { return (_IO_wchar_t)_fill; } + _IO_wchar_t fill(_IO_wchar_t newf) + {_IO_wchar_t oldf = (_IO_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; + _flags &= ~mask; return oldbits; } + int width() const { return _width; } + int width(int val) { int save = _width; _width = val; return save; } + +#ifdef _IO_THROW + void _throw_failure() const { throw new ios::failure(this); } +#else + void _throw_failure() const { } +#endif + streambuf* rdbuf() const { return _strbuf; } +#ifdef _STREAM_COMPAT + void _IO_fix_vtable(); /* TEMPORARY - for binary compatibility */ + void _IO_fix_vtable() const; /* TEMPORARY - for binary compatibility */ +#endif +#if 0 + streambuf* rdbuf(streambuf *_s) { + streambuf *_old = _strbuf; _strbuf = _s; return _old; } +#endif + 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); } + static fmtflags bitalloc(); + static int xalloc(); + void*& pword(int); + void* pword(int) const; + long& iword(int); + long iword(int) const; + +#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_to = 0) { init(sb, tie_to); } + virtual ~ios(); + void init(streambuf* sb, ostream* tie = 0); +}; + +#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. + +// 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 : private _IO_marker { + friend class streambuf; + void set_offset(int offset) { _pos = offset; } + public: + streammarker(streambuf *sb); + ~streammarker(); + int saving() { return 1; } + int delta(streammarker&); + int delta(); +}; + +extern unsigned __adjust_column(unsigned start, const char *line, int count); + +struct streambuf : public _IO_FILE { // protected?? + friend class ios; + friend class istream; + friend class ostream; + friend class streammarker; + const void *&_vtable() { return *(const void**)((_IO_FILE*)this + 1); } + protected: + static streambuf* _list_all; /* List of open streambufs. */ + _IO_FILE*& xchain() { return _chain; } + void _un_link(); + void _link_in(); + char* gptr() const + { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_base : _IO_read_ptr; } + char* pptr() const { return _IO_write_ptr; } + char* egptr() const + { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_end : _IO_read_end; } + char* epptr() const { return _IO_write_end; } + char* pbase() const { return _IO_write_base; } + char* eback() const + { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_base : _IO_read_base;} + char* base() const { return _IO_buf_base; } + char* ebuf() const { return _IO_buf_end; } + int blen() const { return _IO_buf_end - _IO_buf_base; } + void xput_char(char c) { *_IO_write_ptr++ = c; } + int xflags() { return _IO_file_flags; } + int xflags(int f) {int fl = _IO_file_flags; _IO_file_flags = f; return fl;} + void xsetflags(int f) { _IO_file_flags |= f; } + void xsetflags(int f, int mask) + { _IO_file_flags = (_IO_file_flags & ~mask) | (f & mask); } + void gbump(int n) + { _IO_file_flags & _IO_IN_BACKUP ? (_IO_save_base+=n):(_IO_read_ptr+=n);} + void pbump(int n) { _IO_write_ptr += n; } + void setb(char* b, char* eb, int a=0); + void setp(char* p, char* ep) + { _IO_write_base=_IO_write_ptr=p; _IO_write_end=ep; } + void setg(char* eb, char* g, char *eg) { + if (_IO_file_flags & _IO_IN_BACKUP) _IO_free_backup_area(this); + _IO_read_base = eb; _IO_read_ptr = g; _IO_read_end = eg; } + char *shortbuf() { return _shortbuf; } + + int in_backup() { return _flags & _IO_IN_BACKUP; } + // The start of the main get area: FIXME: wrong for write-mode filebuf? + char *Gbase() { return in_backup() ? _IO_save_base : _IO_read_base; } + // The end of the main get area: + char *eGptr() { return in_backup() ? _IO_save_end : _IO_read_end; } + // The start of the backup area: + char *Bbase() { return in_backup() ? _IO_read_base : _IO_save_base; } + char *Bptr() { return _IO_backup_base; } + // The end of the backup area: + char *eBptr() { return in_backup() ? _IO_read_end : _IO_save_end; } + char *Nbase() { return _IO_save_base; } + char *eNptr() { return _IO_save_end; } + int have_backup() { return _IO_save_base != NULL; } + int have_markers() { return _markers != NULL; } + void free_backup_area(); + void unsave_markers(); // Make all streammarkers !saving(). + int put_mode() { return _flags & _IO_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(); // Leave public for now + virtual int overflow(int c = EOF); // Leave public for now + virtual int doallocate(); + streampos sseekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); + streampos sseekpos(streampos pos, int mode = ios::in|ios::out); + + 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 & _IO_UNBUFFERED ? 1 : 0; } + int linebuffered() { return _flags & _IO_LINE_BUF ? 1 : 0; } + void unbuffered(int i) + { if (i) _flags |= _IO_UNBUFFERED; else _flags &= ~_IO_UNBUFFERED; } + void linebuffered(int i) + { if (i) _flags |= _IO_LINE_BUF; else _flags &= ~_IO_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 _IO_read_end - _IO_read_ptr; } + int out_waiting() { return _IO_write_ptr - _IO_write_base; } + virtual streamsize xsputn(const char* s, streamsize n); + streamsize sputn(const char* s, streamsize n) { return xsputn(s, n); } + streamsize padn(char pad, streamsize n) { return _IO_padn(this, pad, n); } + virtual streamsize xsgetn(char* s, streamsize n); + streamsize sgetn(char* s, streamsize n) { return _IO_sgetn(this, s, n); } + int ignore(int); + virtual int get_column(); + virtual int set_column(int); + long sgetline(char* buf, _IO_size_t n, char delim, int putback_delim); + int sputc(int c) { return _IO_putc(c, this); } + int sbumpc() { return _IO_getc(this); } + int sgetc() { return _IO_peekc(this); } + int snextc() { + if (_IO_read_ptr >= _IO_read_end && __underflow(this) == EOF) + return EOF; + else return _IO_read_ptr++, sgetc(); } + void stossc() { if (_IO_read_ptr < _IO_read_end) _IO_read_ptr++; } + int vscan(char const *fmt0, _IO_va_list ap, ios* stream = NULL); + int scan(char const *fmt0 ...); + int vform(char const *fmt0, _IO_va_list ap); + int form(char const *fmt0 ...); +#if 0 /* Work in progress */ + int column(); // Current column number (of put pointer). -1 is unknown. + void column(int c); // Set column number of put pointer to c. +#endif + virtual streamsize sys_read(char* buf, streamsize size); + virtual streampos sys_seek(streamoff, _seek_dir); + virtual streamsize sys_write(const char*, streamsize); + virtual int sys_stat(void*); // Actually, a (struct stat*) + virtual int sys_close(); +}; + +// A backupbuf is a streambuf with full backup and savepoints on reading. +// All standard streambufs in the GNU iostream library are backupbufs. + +class filebuf : public streambuf { + protected: + 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); + static filebuf *__new(); + ~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 _fileno >= 0; } + int fd() const { return is_open() ? _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); + streamsize xsputn(const char* s, streamsize n); + streamsize xsgetn(char* s, streamsize 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); + // Low-level operations (Usually invoke system calls.) + virtual streamsize sys_read(char* buf, streamsize size); + virtual streampos sys_seek(streamoff, _seek_dir); + virtual streamsize sys_write(const char*, streamsize); + virtual int sys_stat(void*); // Actually, a (struct stat*) + virtual int sys_close(); +}; + +inline void ios::init(streambuf* sb, ostream* tie_to) { + _state = sb ? ios::goodbit : ios::badbit; _exceptions=0; + _strbuf=sb; _tie = tie_to; _width=0; _fill=' '; + _flags=ios::skipws|ios::dec; _precision=6; _arrays = 0; } + +inline ios::~ios() { + if (!(_flags & (unsigned int)ios::dont_close)) delete rdbuf(); } +#endif /* _STREAMBUF_H */ diff --git a/gnu/lib/libg++/include/strfile.h b/gnu/lib/libg++/include/strfile.h new file mode 100644 index 0000000..bff25b1 --- /dev/null +++ b/gnu/lib/libg++/include/strfile.h @@ -0,0 +1,46 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include <libio.h> +#ifdef TODO +Merge into libio.h ? +#endif + +typedef void *(*_IO_alloc_type) __P((_IO_size_t)); +typedef void (*_IO_free_type) __P((void*)); + +struct _IO_str_fields +{ + /* The current length is max(_len, _IO_write_ptr-_IO_write_base). */ + _IO_size_t _len; + _IO_alloc_type _allocate_buffer; + _IO_free_type _free_buffer; +}; + +typedef struct _IO_strfile_ +{ + struct _IO_FILE _f; + const void *_vtable; + struct _IO_str_fields _s; +} _IO_strfile; diff --git a/gnu/lib/libg++/include/strstream.h b/gnu/lib/libg++/include/strstream.h new file mode 100644 index 0000000..3c8fd54 --- /dev/null +++ b/gnu/lib/libg++/include/strstream.h @@ -0,0 +1,109 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifndef __STRSTREAM_H +#define __STRSTREAM_H +#ifdef __GNUG__ +#pragma interface +#endif +#include <iostream.h> +#include <strfile.h> + +class strstreambuf : public streambuf +{ + struct _IO_str_fields _s; + + void init_dynamic(_IO_alloc_type alloc, _IO_free_type free, + int initial_size = 128); + void init_static(char *ptr, int size, char *pstart); + void init_readonly(const char *ptr, int size); + protected: + int is_static() const { return _s._allocate_buffer == (_IO_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)(_IO_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_readonly(ptr, size); } + strstreambuf(const unsigned char *ptr, int size) + { init_readonly((const char*)ptr, size); } + 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_readonly((const char*)ptr, size); } + // Note: frozen() is always true if is_static(). + int frozen() { return _flags & _IO_USER_BUF ? 1 : 0; } + void freeze(int n=1) + { if (!is_static()) + { if (n) _flags |= _IO_USER_BUF; else _flags &= ~_IO_USER_BUF; } } + _IO_ssize_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*)ios::rdbuf(); } + 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){} + _IO_ssize_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){} + _IO_ssize_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*/ diff --git a/gnu/lib/libg++/libg++/ACG.cc b/gnu/lib/libg++/libg++/ACG.cc new file mode 100644 index 0000000..27e7aa2 --- /dev/null +++ b/gnu/lib/libg++/libg++/ACG.cc @@ -0,0 +1,291 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1989 Free Software Foundation + +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 <ACG.h> +#include <assert.h> + +// +// This is an extension of the older implementation of Algorithm M +// which I previously supplied. The main difference between this +// version and the old code are: +// +// + Andres searched high & low for good constants for +// the LCG. +// +// + theres more bit chopping going on. +// +// The following contains his comments. +// +// agn@UNH.CS.CMU.EDU sez.. +// +// The generator below is based on 2 well known +// methods: Linear Congruential (LCGs) and Additive +// Congruential generators (ACGs). +// +// The LCG produces the longest possible sequence +// of 32 bit random numbers, each being unique in +// that sequence (it has only 32 bits of state). +// It suffers from 2 problems: a) Independence +// isnt great, that is the (n+1)th number is +// somewhat related to the preceding one, unlike +// flipping a coin where knowing the past outcomes +// dont help to predict the next result. b) +// Taking parts of a LCG generated number can be +// quite non-random: for example, looking at only +// the least significant byte gives a permuted +// 8-bit counter (that has a period length of only +// 256). The advantage of an LCA is that it is +// perfectly uniform when run for the entire period +// length (and very uniform for smaller sequences +// too, if the parameters are chosen carefully). +// +// ACGs have extremly long period lengths and +// provide good independence. Unfortunately, +// uniformity isnt not too great. Furthermore, I +// didnt find any theoretically analysis of ACGs +// that addresses uniformity. +// +// The RNG given below will return numbers +// generated by an LCA that are permuted under +// control of a ACG. 2 permutations take place: the +// 4 bytes of one LCG generated number are +// subjected to one of 16 permutations selected by +// 4 bits of the ACG. The permutation a such that +// byte of the result may come from each byte of +// the LCG number. This effectively destroys the +// structure within a word. Finally, the sequence +// of such numbers is permuted within a range of +// 256 numbers. This greatly improves independence. +// +// +// Algorithm M as describes in Knuths "Art of Computer Programming", +// Vol 2. 1969 +// is used with a linear congruential generator (to get a good uniform +// distribution) that is permuted with a Fibonacci additive congruential +// generator to get good independence. +// +// Bit, byte, and word distributions were extensively tested and pass +// Chi-squared test near perfect scores (>7E8 numbers tested, Uniformity +// assumption holds with probability > 0.999) +// +// Run-up tests for on 7E8 numbers confirm independence with +// probability > 0.97. +// +// Plotting random points in 2d reveals no apparent structure. +// +// Autocorrelation on sequences of 5E5 numbers (A(i) = SUM X(n)*X(n-i), +// i=1..512) +// results in no obvious structure (A(i) ~ const). +// +// Except for speed and memory requirements, this generator outperforms +// random() for all tests. (random() scored rather low on uniformity tests, +// while independence test differences were less dramatic). +// +// AGN would like to.. +// thanks to M.Mauldin, H.Walker, J.Saxe and M.Molloy for inspiration & help. +// +// And I would (DGC) would like to thank Donald Kunth for AGN for letting me +// use his extensions in this implementation. +// + +// +// Part of the table on page 28 of Knuth, vol II. This allows us +// to adjust the size of the table at the expense of shorter sequences. +// + +static randomStateTable[][3] = { +{3,7,16}, {4,9, 32}, {3,10, 32}, {1,11, 32}, {1,15,64}, {3,17,128}, +{7,18,128}, {3,20,128}, {2,21, 128}, {1,22, 128}, {5,23, 128}, {3,25, 128}, +{2,29, 128}, {3,31, 128}, {13,33, 256}, {2,35, 256}, {11,36, 256}, +{14,39,256}, {3,41,256}, {9,49,256}, {3,52,256}, {24,55,256}, {7,57, 256}, +{19,58,256}, {38,89,512}, {17,95,512}, {6,97,512}, {11,98,512}, {-1,-1,-1} }; + +// +// spatial permutation table +// RANDOM_PERM_SIZE must be a power of two +// + +#define RANDOM_PERM_SIZE 64 +unsigned long randomPermutations[RANDOM_PERM_SIZE] = { +0xffffffff, 0x00000000, 0x00000000, 0x00000000, // 3210 +0x0000ffff, 0x00ff0000, 0x00000000, 0xff000000, // 2310 +0xff0000ff, 0x0000ff00, 0x00000000, 0x00ff0000, // 3120 +0x00ff00ff, 0x00000000, 0xff00ff00, 0x00000000, // 1230 + +0xffff0000, 0x000000ff, 0x00000000, 0x0000ff00, // 3201 +0x00000000, 0x00ff00ff, 0x00000000, 0xff00ff00, // 2301 +0xff000000, 0x00000000, 0x000000ff, 0x00ffff00, // 3102 +0x00000000, 0x00000000, 0x00000000, 0xffffffff, // 2103 + +0xff00ff00, 0x00000000, 0x00ff00ff, 0x00000000, // 3012 +0x0000ff00, 0x00000000, 0x00ff0000, 0xff0000ff, // 2013 +0x00000000, 0x00000000, 0xffffffff, 0x00000000, // 1032 +0x00000000, 0x0000ff00, 0xffff0000, 0x000000ff, // 1023 + +0x00000000, 0xffffffff, 0x00000000, 0x00000000, // 0321 +0x00ffff00, 0xff000000, 0x00000000, 0x000000ff, // 0213 +0x00000000, 0xff000000, 0x0000ffff, 0x00ff0000, // 0132 +0x00000000, 0xff00ff00, 0x00000000, 0x00ff00ff // 0123 +}; + +// +// SEED_TABLE_SIZE must be a power of 2 +// +#define SEED_TABLE_SIZE 32 +static unsigned long seedTable[SEED_TABLE_SIZE] = { +0xbdcc47e5, 0x54aea45d, 0xec0df859, 0xda84637b, +0xc8c6cb4f, 0x35574b01, 0x28260b7d, 0x0d07fdbf, +0x9faaeeb0, 0x613dd169, 0x5ce2d818, 0x85b9e706, +0xab2469db, 0xda02b0dc, 0x45c60d6e, 0xffe49d10, +0x7224fea3, 0xf9684fc9, 0xfc7ee074, 0x326ce92a, +0x366d13b5, 0x17aaa731, 0xeb83a675, 0x7781cb32, +0x4ec7c92d, 0x7f187521, 0x2cf346b4, 0xad13310f, +0xb89cff2b, 0x12164de1, 0xa865168d, 0x32b56cdf +}; + +// +// The LCG used to scramble the ACG +// +// +// LC-parameter selection follows recommendations in +// "Handbook of Mathematical Functions" by Abramowitz & Stegun 10th, edi. +// +// LC_A = 251^2, ~= sqrt(2^32) = 66049 +// LC_C = result of a long trial & error series = 3907864577 +// + +static const unsigned long LC_A = 66049; +static const unsigned long LC_C = 3907864577; +static inline unsigned long LCG(unsigned long x) +{ + return( x * LC_A + LC_C ); +} + + +ACG::ACG(unsigned long seed, int size) +{ + + initialSeed = seed; + + // + // Determine the size of the state table + // + + for (register int l = 0; + randomStateTable[l][0] != -1 && randomStateTable[l][1] < size; + l++); + + if (randomStateTable[l][1] == -1) { + l--; + } + + initialTableEntry = l; + + stateSize = randomStateTable[ initialTableEntry ][ 1 ]; + auxSize = randomStateTable[ initialTableEntry ][ 2 ]; + + // + // Allocate the state table & the auxillary table in a single malloc + // + + state = new unsigned long[stateSize + auxSize]; + auxState = &state[stateSize]; + + reset(); +} + +// +// Initialize the state +// +void +ACG::reset() +{ + register unsigned long u; + + if (initialSeed < SEED_TABLE_SIZE) { + u = seedTable[ initialSeed ]; + } else { + u = initialSeed ^ seedTable[ initialSeed & (SEED_TABLE_SIZE-1) ]; + } + + + j = randomStateTable[ initialTableEntry ][ 0 ] - 1; + k = randomStateTable[ initialTableEntry ][ 1 ] - 1; + + register int i; + for(i = 0; i < stateSize; i++) { + state[i] = u = LCG(u); + } + + for (i = 0; i < auxSize; i++) { + auxState[i] = u = LCG(u); + } + + k = u % stateSize; + int tailBehind = (stateSize - randomStateTable[ initialTableEntry ][ 0 ]); + j = k - tailBehind; + if (j < 0) { + j += stateSize; + } + + lcgRecurr = u; + + assert(sizeof(double) == 2 * sizeof(long)); +} + +ACG::~ACG() +{ + if (state) delete state; + state = 0; + // don't delete auxState, it's really an alias for state. +} + +// +// Returns 32 bits of random information. +// + +unsigned long ACG::asLong() +{ + unsigned long result = state[k] + state[j]; + state[k] = result; + j = (j <= 0) ? (stateSize-1) : (j-1); + k = (k <= 0) ? (stateSize-1) : (k-1); + + short int auxIndex = (result >> 24) & (auxSize - 1); + register unsigned long auxACG = auxState[auxIndex]; + auxState[auxIndex] = lcgRecurr = LCG(lcgRecurr); + + // + // 3c is a magic number. We are doing four masks here, so we + // do not want to run off the end of the permutation table. + // This insures that we have always got four entries left. + // + register unsigned long *perm = & randomPermutations[result & 0x3c]; + + result = *(perm++) & auxACG; + result |= *(perm++) & ((auxACG << 24) + | ((auxACG >> 8)& 0xffffff)); + result |= *(perm++) & ((auxACG << 16) + | ((auxACG >> 16) & 0xffff)); + result |= *(perm++) & ((auxACG << 8) + | ((auxACG >> 24) & 0xff)); + + return(result); +} diff --git a/gnu/lib/libg++/libg++/AllocRing.cc b/gnu/lib/libg++/libg++/AllocRing.cc new file mode 100644 index 0000000..5be1ff0 --- /dev/null +++ b/gnu/lib/libg++/libg++/AllocRing.cc @@ -0,0 +1,110 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1989 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 <std.h> +#include <AllocRing.h> +#include <new.h> + +AllocRing::AllocRing(int max) + :n(max), current(0), nodes(new AllocQNode[max]) +{ + for (int i = 0; i < n; ++i) + { + nodes[i].ptr = 0; + nodes[i].sz = 0; + } +} + +int AllocRing::find(void* p) +{ + if (p == 0) return -1; + + for (int i = 0; i < n; ++i) + if (nodes[i].ptr == p) + return i; + + return -1; +} + + +void AllocRing::clear() +{ + for (int i = 0; i < n; ++i) + { + if (nodes[i].ptr != 0) + { + delete(nodes[i].ptr); + nodes[i].ptr = 0; + } + nodes[i].sz = 0; + } + current = 0; +} + + +void AllocRing::free(void* p) +{ + int idx = find(p); + if (idx >= 0) + { + delete nodes[idx].ptr; + nodes[idx].ptr = 0; + } +} + +AllocRing::~AllocRing() +{ + clear(); +} + +int AllocRing::contains(void* p) +{ + return find(p) >= 0; +} + +static inline unsigned int good_size(unsigned int s) +{ + unsigned int req = s + 4; + unsigned int good = 8; + while (good < req) good <<= 1; + return good - 4; +} + +void* AllocRing::alloc(int s) +{ + unsigned int size = good_size(s); + + void* p; + if (nodes[current].ptr != 0 && + nodes[current].sz >= int(size) && + nodes[current].sz < int(4 * size)) + p = nodes[current].ptr; + else + { + if (nodes[current].ptr != 0) delete nodes[current].ptr; + p = new char[size]; + nodes[current].ptr = p; + nodes[current].sz = size; + } + ++current; + if (current >= n) current = 0; + return p; +} diff --git a/gnu/lib/libg++/libg++/Binomial.cc b/gnu/lib/libg++/libg++/Binomial.cc new file mode 100644 index 0000000..7166e55 --- /dev/null +++ b/gnu/lib/libg++/libg++/Binomial.cc @@ -0,0 +1,34 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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 <builtin.h> +#include <Random.h> +#include <Binomial.h> + +double Binomial::operator()() +{ + int s = 0; + for (int i = 0; i < pN; i++) { + if (pGenerator -> asDouble() < pU) { + s++; + } + } + return(double(s)); +} + diff --git a/gnu/lib/libg++/libg++/BitSet.cc b/gnu/lib/libg++/libg++/BitSet.cc new file mode 100644 index 0000000..397c750 --- /dev/null +++ b/gnu/lib/libg++/libg++/BitSet.cc @@ -0,0 +1,1006 @@ +/* +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. +*/ + +/* + BitSet class implementation + */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <BitSet.h> +#include <std.h> +#include <limits.h> +#include <Obstack.h> +#include <AllocRing.h> +#include <new.h> +#include <builtin.h> +#include <string.h> +#include <strstream.h> + +void BitSet::error(const char* msg) const +{ + (*lib_error_handler)("BitSet", msg); +} + +// globals & constants + +BitSetRep _nilBitSetRep = { 0, 1, 0, {0} }; // nil BitSets point here + +#define ONES ((unsigned short)(~0L)) +#define MAXBitSetRep_SIZE ((1 << (sizeof(short)*CHAR_BIT - 1)) - 1) +#define MINBitSetRep_SIZE 16 + +#ifndef MALLOC_MIN_OVERHEAD +#define MALLOC_MIN_OVERHEAD 4 +#endif + +// break things up into .s indices and positions + + +// mask out bits from left + +static inline unsigned short lmask(int p) +{ + return ONES << p; +} + +// mask out high bits + +static inline unsigned short rmask(int p) +{ + return ONES >> (BITSETBITS - 1 - p); +} + + +inline static BitSetRep* BSnew(int newlen) +{ + unsigned int siz = sizeof(BitSetRep) + newlen * sizeof(short) + + MALLOC_MIN_OVERHEAD; + unsigned int allocsiz = MINBitSetRep_SIZE;; + while (allocsiz < siz) allocsiz <<= 1; + allocsiz -= MALLOC_MIN_OVERHEAD; + if (allocsiz >= MAXBitSetRep_SIZE * sizeof(short)) + (*lib_error_handler)("BitSet", "Requested length out of range"); + + BitSetRep* rep = (BitSetRep *) new char[allocsiz]; + memset(rep, 0, allocsiz); + rep->sz = (allocsiz - sizeof(BitSetRep) + sizeof(short)) / sizeof(short); + return rep; +} + +BitSetRep* BitSetalloc(BitSetRep* old, const unsigned short* src, int srclen, + int newvirt, int newlen) +{ + if (old == &_nilBitSetRep) old = 0; + BitSetRep* rep; + if (old == 0 || newlen >= old->sz) + rep = BSnew(newlen); + else + rep = old; + + rep->len = newlen; + rep->virt = newvirt; + + if (srclen != 0 && src != rep->s) + memcpy(rep->s, src, srclen * sizeof(short)); + // BUG fix: extend virtual bit! 20 Oct 1992 Kevin Karplus + if (rep->virt) + memset(&rep->s[srclen], ONES, (newlen - srclen) * sizeof(short)); + if (old != rep && old != 0) delete old; + return rep; +} + +BitSetRep* BitSetresize(BitSetRep* old, int newlen) +{ + BitSetRep* rep; + if (old == 0 || old == &_nilBitSetRep) + { + rep = BSnew(newlen); + rep->virt = 0; + } + else if (newlen >= old->sz) + { + rep = BSnew(newlen); + memcpy(rep->s, old->s, old->len * sizeof(short)); + rep->virt = old->virt; + // BUG fix: extend virtual bit! 20 Oct 1992 Kevin Karplus + if (rep->virt) + memset(&rep->s[old->len], ONES, (newlen - old->len) * sizeof(short)); + delete old; + } + else + { + rep = old; + if (rep->len < newlen) + memset(&rep->s[rep->len], + rep->virt ? ONES : 0, + (newlen - rep->len) * sizeof(short)); + } + + rep->len = newlen; + + return rep; +} + +// same, for straight copy + +BitSetRep* BitSetcopy(BitSetRep* old, const BitSetRep* src) +{ + BitSetRep* rep; + if (old == &_nilBitSetRep) old = 0; + if (src == 0 || src == &_nilBitSetRep) + { + if (old == 0) + rep = BSnew(0); + else + rep = old; + rep->len = 0; + rep->virt = 0; + } + else if (old == src) + return old; + else + { + int newlen = src->len; + if (old == 0 || newlen > old->sz) + { + rep = BSnew(newlen); + if (old != 0) delete old; + } + else + rep = old; + + memcpy(rep->s, src->s, newlen * sizeof(short)); + rep->len = newlen; + rep->virt = src->virt; + } + return rep; +} + + +// remove unneeded top bits + +inline static void trim(BitSetRep* rep) +{ + int l = rep->len; + unsigned short* s = &(rep->s[l - 1]); + + if (rep->virt == 0) + while (l > 0 && *s-- == 0) --l; + else + while (l > 0 && *s-- == ONES) --l; + rep->len = l; +} + +int operator == (const BitSet& x, const BitSet& y) +{ + if (x.rep->virt != y.rep->virt) + return 0; + int xl = x.rep->len; + int yl = y.rep->len; + + unsigned short* xs = x.rep->s; + unsigned short* ys = y.rep->s; + if (xl<=yl) + { + if (memcmp((void*)xs, (void*)ys, xl * sizeof(short))) + return 0; + for (register int i=xl; i<yl; i++) + if (ys[i]) + return 0; + return 1; + } + else + { + if (memcmp((void*)xs, (void*)ys, yl * sizeof(short))) + return 0; + for (register int i=yl; i<xl; i++) + if (xs[i]) + return 0; + return 1; + } +} + +int operator <= (const BitSet& x, const BitSet& y) +{ + if (x.rep->virt > y.rep->virt) + return 0; + + int xl = x.rep->len; + int yl = y.rep->len; + + unsigned short* xs = x.rep->s; + unsigned short* ys = y.rep->s; + unsigned short* topx = &(xs[xl]); + unsigned short* topy = &(ys[yl]); + + while (xs < topx && ys < topy) + { + unsigned short a = *xs++; + unsigned short b = *ys++; + if ((a | b) != b) + return 0; + } + if (xl == yl) + return x.rep->virt <= y.rep->virt; + else if (xl < yl) + return !x.rep->virt; + else + return y.rep->virt; +} + + +int operator < (const BitSet& x, const BitSet& y) +{ + if (x.rep->virt > y.rep->virt) + return 0; + + int xl = x.rep->len; + int yl = y.rep->len; + + unsigned short* xs = x.rep->s; + unsigned short* ys = y.rep->s; + unsigned short* topx = &(xs[xl]); + unsigned short* topy = &(ys[yl]); + int one_diff = 0; + while (xs < topx && ys < topy) + { + unsigned short a = *xs++; + unsigned short b = *ys++; + unsigned short c = a | b; + if (c != b) + return 0; + else if (c != a) + one_diff = 1; + } + if (xl == yl) + return x.rep->virt < y.rep->virt || + (one_diff && x.rep->virt == y.rep->virt); + else if (xl < yl) + return !x.rep->virt; + else + return y.rep->virt; +} + + + +int BitSet::empty() const +{ + if (rep->virt == 1) + return 0; + + unsigned short* bots = rep->s; + unsigned short* s = &(bots[rep->len - 1]); + while (s >= bots) if (*s-- != 0) return 0; + return 1; +} + + +int BitSet::count(int b) const +{ + if (b == rep->virt) + return -1; + int l = 0; + unsigned short* s = rep->s; + unsigned short* tops = &(s[rep->len]); + if (b == 1) + { + while (s < tops) + { + unsigned short a = *s++; + for (int i = 0; i < BITSETBITS && a != 0; ++i) + { + if (a & 1) + ++l; + a >>= 1; + } + } + } + else + { + unsigned short maxbit = 1 << (BITSETBITS - 1); + while (s < tops) + { + unsigned short a = *s++; + for (int i = 0; i < BITSETBITS; ++i) + { + if ((a & maxbit) == 0) + ++l; + a <<= 1; + } + } + } + return l; +} + +BitSetRep* BitSetcmpl(const BitSetRep* src, BitSetRep* r) +{ + r = BitSetcopy(r, src); + r->virt = !src->virt; + unsigned short* rs = r->s; + unsigned short* topr = &(rs[r->len]); + if (r->len == 0) + *rs = ONES; + else + { + while (rs < topr) + { + unsigned short cmp = ~(*rs); + *rs++ = cmp; + } + } + trim(r); + return r; +} + + +BitSetRep* BitSetop(const BitSetRep* x, const BitSetRep* y, + BitSetRep* r, char op) +{ + int xrsame = x == r; + int yrsame = y == r; + int xv = x->virt; + int yv = y->virt; + int xl = x->len; + int yl = y->len; + int rl = (xl >= yl)? xl : yl; + + r = BitSetresize(r, rl); + unsigned short* rs = r->s; + unsigned short* topr = &(rs[rl]); + + int av, bv; + const unsigned short* as; + const unsigned short* topa; + const unsigned short* bs; + const unsigned short* topb; + + if (xl <= yl) + { + as = (xrsame)? r->s : x->s; + av = xv; + topa = &(as[xl]); + bs = (yrsame)? r->s : y->s; + bv = yv; + topb = &(bs[yl]); + } + else + { + as = (yrsame)? r->s : y->s; + av = yv; + topa = &(as[yl]); + bs = (xrsame)? r->s : x->s; + bv = xv; + topb = &(bs[xl]); + if (op == '-') // reverse sense of difference + op = 'D'; + } + + switch (op) + { + case '&': + r->virt = av & bv; + while (as < topa) *rs++ = *as++ & *bs++; + if (av) + while (rs < topr) *rs++ = *bs++; + else + while (rs < topr) *rs++ = 0; + break; + case '|': + r->virt = av | bv; + while (as < topa) *rs++ = *as++ | *bs++; + if (av) + while (rs < topr) *rs++ = ONES; + else + while (rs < topr) *rs++ = *bs++; + break; + case '^': + r->virt = av ^ bv; + while (as < topa) *rs++ = *as++ ^ *bs++; + if (av) + while (rs < topr) *rs++ = ~(*bs++); + else + while (rs < topr) *rs++ = *bs++; + break; + case '-': + r->virt = av & ~(bv); + while (as < topa) *rs++ = *as++ & ~(*bs++); + if (av) + while (rs < topr) *rs++ = ~(*bs++); + else + while (rs < topr) *rs++ = 0; + break; + case 'D': + r->virt = ~(av) & (bv); + while (as < topa) *rs++ = ~(*as++) & (*bs++); + if (av) + while (rs < topr) *rs++ = 0; + else + while (rs < topr) *rs++ = *bs++; + break; + } + trim(r); + return r; +} + + +void BitSet::set(int p) +{ + if (p < 0) error("Illegal bit index"); + + int index = BitSet_index(p); + int pos = BitSet_pos(p); + + if (index >= rep->len) + { + if (rep->virt) + return; + else + rep = BitSetresize(rep, index+1); + } + + rep->s[index] |= (1 << pos); +} + +void BitSet::clear() +{ + if (rep->len > 0) memset(rep->s, 0, rep->sz * sizeof(short)); + rep->len = rep->virt = 0; +} + +void BitSet::clear(int p) +{ + if (p < 0) error("Illegal bit index"); + int index = BitSet_index(p); + if (index >= rep->len) + { + if (rep->virt == 0) + return; + else + rep = BitSetresize(rep, index+1); + } + rep->s[index] &= ~(1 << BitSet_pos(p)); +} + +void BitSet::invert(int p) +{ + if (p < 0) error("Illegal bit index"); + int index = BitSet_index(p); + if (index >= rep->len) rep = BitSetresize(rep, index+1); + rep->s[index] ^= (1 << BitSet_pos(p)); +} + +void BitSet::set(int from, int to) +{ + if (from < 0 || from > to) error("Illegal bit index"); + + int index1 = BitSet_index(from); + int pos1 = BitSet_pos(from); + + if (rep->virt && index1 >= rep->len) + return; + + int index2 = BitSet_index(to); + int pos2 = BitSet_pos(to); + + if (index2 >= rep->len) + rep = BitSetresize(rep, index2+1); + + unsigned short* s = &(rep->s[index1]); + unsigned short m1 = lmask(pos1); + unsigned short m2 = rmask(pos2); + if (index2 == index1) + *s |= m1 & m2; + else + { + *s++ |= m1; + unsigned short* top = &(rep->s[index2]); + *top |= m2; + while (s < top) + *s++ = ONES; + } +} + +void BitSet::clear(int from, int to) +{ + if (from < 0 || from > to) error("Illegal bit index"); + + int index1 = BitSet_index(from); + int pos1 = BitSet_pos(from); + + if (!rep->virt && index1 >= rep->len) + return; + + int index2 = BitSet_index(to); + int pos2 = BitSet_pos(to); + + if (index2 >= rep->len) + rep = BitSetresize(rep, index2+1); + + unsigned short* s = &(rep->s[index1]); + unsigned short m1 = lmask(pos1); + unsigned short m2 = rmask(pos2); + if (index2 == index1) + *s &= ~(m1 & m2); + else + { + *s++ &= ~m1; + unsigned short* top = &(rep->s[index2]); + *top &= ~m2; + while (s < top) + *s++ = 0; + } +} + +void BitSet::invert(int from, int to) +{ + if (from < 0 || from > to) error("Illegal bit index"); + + int index1 = BitSet_index(from); + int pos1 = BitSet_pos(from); + int index2 = BitSet_index(to); + int pos2 = BitSet_pos(to); + + if (index2 >= rep->len) + rep = BitSetresize(rep, index2+1); + + unsigned short* s = &(rep->s[index1]); + unsigned short m1 = lmask(pos1); + unsigned short m2 = rmask(pos2); + if (index2 == index1) + *s ^= m1 & m2; + else + { + *s++ ^= m1; + unsigned short* top = &(rep->s[index2]); + *top ^= m2; + while (s < top) + { + unsigned short cmp = ~(*s); + *s++ = cmp; + } + } +} + + +int BitSet::test(int from, int to) const +{ + if (from < 0 || from > to) return 0; + + int index1 = BitSet_index(from); + int pos1 = BitSet_pos(from); + + if (index1 >= rep->len) + return rep->virt; + + int index2 = BitSet_index(to); + int pos2 = BitSet_pos(to); + + if (index2 >= rep->len) + { + if (rep->virt) + return 1; + else + { + index2 = rep->len - 1; + pos2 = BITSETBITS - 1; + } + } + + unsigned short* s = &(rep->s[index1]); + unsigned short m1 = lmask(pos1); + unsigned short m2 = rmask(pos2); + + if (index2 == index1) + return (*s & m1 & m2) != 0; + else + { + if (*s++ & m1) + return 1; + unsigned short* top = &(rep->s[index2]); + if (*top & m2) + return 1; + while (s < top) + if (*s++ != 0) + return 1; + return 0; + } +} + +int BitSet::next(int p, int b) const +{ + ++p; + int index = BitSet_index(p); + int pos = BitSet_pos(p); + + int l = rep->len; + + if (index >= l) + { + if (rep->virt == b) + return p; + else + return -1; + } + int j = index; + unsigned short* s = rep->s; + unsigned short a = s[j] >> pos; + int i = pos; + + if (b == 1) + { + for (; i < BITSETBITS && a != 0; ++i) + { + if (a & 1) + return j * BITSETBITS + i; + a >>= 1; + } + for (++j; j < l; ++j) + { + a = s[j]; + for (i = 0; i < BITSETBITS && a != 0; ++i) + { + if (a & 1) + return j * BITSETBITS + i; + a >>= 1; + } + } + if (rep->virt) + return j * BITSETBITS; + else + return -1; + } + else + { + for (; i < BITSETBITS; ++i) + { + if ((a & 1) == 0) + return j * BITSETBITS + i; + a >>= 1; + } + for (++j; j < l; ++j) + { + a = s[j]; + if (a != ONES) + { + for (i = 0; i < BITSETBITS; ++i) + { + if ((a & 1) == 0) + return j * BITSETBITS + i; + a >>= 1; + } + } + } + if (!rep->virt) + return j * BITSETBITS; + else + return -1; + } +} + +int BitSet::prev(int p, int b) const +{ + if (--p < 0) + return -1; + + int index = BitSet_index(p); + int pos = BitSet_pos(p); + + unsigned short* s = rep->s; + int l = rep->len; + + if (index >= l) + { + if (rep->virt == b) + return p; + else + { + index = l - 1; + pos = BITSETBITS - 1; + } + } + + int j = index; + unsigned short a = s[j]; + + int i = pos; + unsigned short maxbit = 1 << pos; + + if (b == 1) + { + for (; i >= 0 && a != 0; --i) + { + if (a & maxbit) + return j * BITSETBITS + i; + a <<= 1; + } + maxbit = 1 << (BITSETBITS - 1); + for (--j; j >= 0; --j) + { + a = s[j]; + for (i = BITSETBITS - 1; i >= 0 && a != 0; --i) + { + if (a & maxbit) + return j * BITSETBITS + i; + a <<= 1; + } + } + return -1; + } + else + { + if (a != ONES) + { + for (; i >= 0; --i) + { + if ((a & maxbit) == 0) + return j * BITSETBITS + i; + a <<= 1; + } + } + maxbit = 1 << (BITSETBITS - 1); + for (--j; j >= 0; --j) + { + a = s[j]; + if (a != ONES) + { + for (i = BITSETBITS - 1; i >= 0; --i) + { + if ((a & maxbit) == 0) + return j * BITSETBITS + i; + a <<= 1; + } + } + } + return -1; + } +} + +int BitSet::last(int b) const +{ + if (b == rep->virt) + return -1; + else + return prev((rep->len) * BITSETBITS, b); +} + + +extern AllocRing _libgxx_fmtq; + +const char* BitSettoa(const BitSet& x, char f, char t, char star) +{ + trim(x.rep); + int wrksiz = (x.rep->len + 1) * BITSETBITS + 2; + char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); + ostrstream stream(fmtbase, wrksiz); + + x.printon(stream, f, t, star); + stream << ends; + return fmtbase; +} + +#if defined(__GNUG__) && !defined(_G_NO_NRV) + +BitSet shorttoBitSet(unsigned short w) return r +{ + r.rep = BitSetalloc(0, &w, 1, 0, 2); trim(r.rep); +} + +BitSet longtoBitSet(unsigned long w) return r; +{ + unsigned short u[2]; + u[0] = w & ((unsigned short)(~(0))); + u[1] = w >> BITSETBITS; + r.rep = BitSetalloc(0, &u[0], 2, 0, 3); + trim(r.rep); +} + +BitSet atoBitSet(const char* s, char f, char t, char star) return r +{ + int sl = strlen(s); + if (sl != 0) + { + r.rep = BitSetresize(r.rep, sl / BITSETBITS + 1); + unsigned short* rs = r.rep->s; + unsigned short a = 0; + unsigned short m = 1; + char lastch = 0; + unsigned int i = 0; + unsigned int l = 1; + for(;;) + { + char ch = s[i]; + if (ch == t) + a |= m; + else if (ch == star) + { + if (r.rep->virt = lastch == t) + *rs = a | ~(m - 1); + else + *rs = a; + break; + } + else if (ch != f) + { + *rs = a; + break; + } + lastch = ch; + if (++i == sl) + { + *rs = a; + break; + } + else if (i % BITSETBITS == 0) + { + *rs++ = a; + a = 0; + m = 1; + ++l; + } + else + m <<= 1; + } + r.rep->len = l; + trim(r.rep); + } + return; +} + +#else + +BitSet shorttoBitSet(unsigned short w) +{ + BitSet r; + r.rep = BitSetalloc(0, &w, 1, 0, 2); trim(r.rep); + return r; +} + +BitSet longtoBitSet(unsigned long w) +{ + BitSet r; + unsigned short u[2]; + u[0] = w & ((unsigned short)(~(0))); + u[1] = w >> BITSETBITS; + r.rep = BitSetalloc(0, &u[0], 2, 0, 3); + trim(r.rep); + return r; +} + +BitSet atoBitSet(const char* s, char f, char t, char star) +{ + BitSet r; + int sl = strlen(s); + if (sl != 0) + { + r.rep = BitSetresize(r.rep, sl / BITSETBITS + 1); + unsigned short* rs = r.rep->s; + unsigned short a = 0; + unsigned short m = 1; + char lastch = 0; + unsigned int i = 0; + unsigned int l = 1; + for(;;) + { + char ch = s[i]; + if (ch == t) + a |= m; + else if (ch == star) + { + if (r.rep->virt = lastch == t) + *rs = a | ~(m - 1); + else + *rs = a; + break; + } + else if (ch != f) + { + *rs = a; + break; + } + lastch = ch; + if (++i == sl) + { + *rs = a; + break; + } + else if (i % BITSETBITS == 0) + { + *rs++ = a; + a = 0; + m = 1; + ++l; + } + else + m <<= 1; + } + r.rep->len = l; + trim(r.rep); + } + return r; +} + +#endif + +ostream& operator << (ostream& s, const BitSet& x) +{ + if (s.opfx()) + x.printon(s); + return s; +} + +void BitSet::printon(ostream& os, char f, char t, char star) const +// FIXME: Does not respect s.width()! +{ + trim(rep); + register streambuf* sb = os.rdbuf(); + const unsigned short* s = rep->s; + const unsigned short* top = &(s[rep->len - 1]); + + while (s < top) + { + unsigned short a = *s++; + for (int j = 0; j < BITSETBITS; ++j) + { + sb->sputc((a & 1)? t : f); + a >>= 1; + } + } + + if (!rep->virt) + { + unsigned short a = *s; + if (rep->len != 0) + { + for (int j = 0; j < BITSETBITS && a != 0; ++j) + { + sb->sputc((a & 1)? t : f); + a >>= 1; + } + } + sb->sputc(f); + } + else + { + unsigned short a = *s; + unsigned short mask = ONES; + unsigned short himask = (1 << (BITSETBITS - 1)) - 1; + if (rep->len != 0) + { + for (int j = 0; j < BITSETBITS && a != mask; ++j) + { + sb->sputc((a & 1)? t : f); + a = (a >> 1) & himask; + mask = (mask >> 1) & himask; + } + } + sb->sputc(t); + } + + sb->sputc(star); +} + +int BitSet::OK() const +{ + int v = rep != 0; // have a rep + v &= rep->len <= rep->sz; // within bounds + v &= rep->virt == 0 || rep->virt == 1; // valid virtual bit + if (!v) error("invariant failure"); + return v; +} + diff --git a/gnu/lib/libg++/libg++/BitString.cc b/gnu/lib/libg++/libg++/BitString.cc new file mode 100644 index 0000000..26331ae --- /dev/null +++ b/gnu/lib/libg++/libg++/BitString.cc @@ -0,0 +1,1606 @@ +/* +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. +*/ + +/* + BitString class implementation + */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <BitString.h> +#include <std.h> +#include <limits.h> +#include <Obstack.h> +#include <AllocRing.h> +#include <new.h> +#include <builtin.h> +#include <strstream.h> + +void BitString::error(const char* msg) const +{ + (*lib_error_handler)("BitString", msg); +} + +// globals + +BitStrRep _nilBitStrRep = { 0, 1, {0} }; + +BitString _nil_BitString; + +#define MINBitStrRep_SIZE 8 +#define MAXBitStrRep_SIZE ((1 << (sizeof(short)*CHAR_BIT - 1)) - 1) + +#ifndef MALLOC_MIN_OVERHEAD +#define MALLOC_MIN_OVERHEAD 4 +#endif + +#define ONES ((_BS_word)(~0L)) +#define MAXBIT (((_BS_word)1) << (BITSTRBITS - 1)) + +/* + * bit manipulation utilities +*/ + +// break things up into .s indices and positions + +inline static int BitStr_len(int l) +{ + return (unsigned)(l) / BITSTRBITS + 1; +} + + +// mask out low bits + +static inline _BS_word lmask(int p) +{ + return ONES _BS_RIGHT p; +} + +// mask out high bits + +static inline _BS_word rmask(int p) +{ + int s = BITSTRBITS - 1 - p; + if (s <= 0) + return ONES; + else + return ONES _BS_LEFT s; +} + + +// mask out unused bits in last word of rep + +inline static void check_last(BitStrRep* r) +{ + int bit_len_mod = r->len & (BITSTRBITS - 1); + if (bit_len_mod) + r->s[r->len / BITSTRBITS] &= ONES _BS_LEFT (BITSTRBITS - bit_len_mod); +} + +// merge bits from next word + +static inline _BS_word borrow_hi(const _BS_word a[], int ind, + int maxind, int p) +{ + if (p == 0) + return a[ind]; + else if (ind < maxind) + return (a[ind] _BS_LEFT p) | (a[ind+1] _BS_RIGHT (BITSTRBITS - p)); + else + return (a[ind] _BS_LEFT p); +} + +// merge bits from prev word + +static inline _BS_word borrow_lo(const _BS_word a[], int ind, + int minind, int p) +{ + _BS_word word = a[ind] _BS_RIGHT (BITSTRBITS - 1 - p); + if (ind > minind) + word |= (a[ind-1] _BS_LEFT (p + 1)); + return word; +} + +// same with bounds check (for masks shorter than patterns) + +static inline _BS_word safe_borrow_hi(const _BS_word a[], int ind, + int maxind, int p) +{ + if (ind > maxind) + return 0; + else if (p == 0) + return a[ind]; + else if (ind == maxind) + return a[ind] _BS_LEFT p; + else + return (a[ind] _BS_LEFT p) | (a[ind+1] _BS_RIGHT (BITSTRBITS - p)); +} + + +// allocate a new rep; pad to near a power of two + +inline static BitStrRep* BSnew(int newlen) +{ + unsigned int siz = sizeof(BitStrRep) + BitStr_len(newlen) * sizeof(_BS_word) + + MALLOC_MIN_OVERHEAD; + unsigned int allocsiz = MINBitStrRep_SIZE;; + while (allocsiz < siz) allocsiz <<= 1; + allocsiz -= MALLOC_MIN_OVERHEAD; + if (allocsiz >= MAXBitStrRep_SIZE * sizeof(_BS_word)) + (*lib_error_handler)("BitString", "Requested length out of range"); + + BitStrRep* rep = (BitStrRep *) new char[allocsiz]; + memset(rep, 0, allocsiz); + rep->sz = + (allocsiz - sizeof(BitStrRep) + sizeof(_BS_word)) / sizeof(_BS_word); + return rep; +} + +inline void +copy_bits (_BS_word* pdst, _BS_size_t dstbit, + const _BS_word* psrc, _BS_size_t srcbit, + _BS_size_t length) +{ + _BS_NORMALIZE (pdst, dstbit); + _BS_NORMALIZE (psrc, srcbit); + _BS_copy (pdst, dstbit, psrc, srcbit, length); +} + +BitStrRep* BStr_alloc(BitStrRep* old, const _BS_word* src, + int startpos, int endp, int newlen) +{ + if (old == &_nilBitStrRep) old = 0; + if (newlen < 0) newlen = 0; + int news = BitStr_len(newlen); + BitStrRep* rep; + if (old == 0 || news > old->sz) + rep = BSnew(newlen); + else + rep = old; + rep->len = newlen; + + if (src != 0 && endp > 0 && (src != rep->s || startpos > 0)) + copy_bits (rep->s, 0, src, startpos, endp - startpos); + + check_last(rep); + + if (old != rep && old != 0) delete old; + + return rep; +} + +BitStrRep* BStr_resize(BitStrRep* old, int newlen) +{ + BitStrRep* rep; + if (newlen < 0) newlen = 0; + int news = BitStr_len(newlen); + if (old == 0 || old == &_nilBitStrRep) + { + rep = BSnew(newlen); + } + else if (news > old->sz) + { + rep = BSnew(newlen); + memcpy(rep->s, old->s, BitStr_len(old->len) * sizeof(_BS_word)); + delete old; + } + else + rep = old; + + rep->len = newlen; + check_last(rep); + return rep; +} + +BitStrRep* BStr_copy(BitStrRep* old, const BitStrRep* src) +{ + BitStrRep* rep; + if (old == src && old != &_nilBitStrRep) return old; + if (old == &_nilBitStrRep) old = 0; + if (src == &_nilBitStrRep) src = 0; + if (src == 0) + { + if (old == 0) + rep = BSnew(0); + else + rep = old; + rep->len = 0; + } + else + { + int newlen = src->len; + int news = BitStr_len(newlen); + if (old == 0 || news > old->sz) + { + rep = BSnew(newlen); + if (old != 0) delete old; + } + else + rep = old; + + memcpy(rep->s, src->s, news * sizeof(_BS_word)); + rep->len = newlen; + } + check_last(rep); + return rep; +} + + +int operator == (const BitString& x, const BitString& y) +{ + return x.rep->len == y.rep->len && + memcmp((void*)x.rep->s, (void*)y.rep->s, + BitStr_len(x.rep->len) * sizeof(_BS_word)) == 0; +} + +int operator <= (const BitString& x, const BitString& y) +{ + unsigned int xl = x.rep->len; + unsigned int yl = y.rep->len; + if (xl > yl) + return 0; + + const _BS_word* xs = x.rep->s; + const _BS_word* topx = &(xs[BitStr_len(xl)]); + const _BS_word* ys = y.rep->s; + + while (xs < topx) + { + _BS_word a = *xs++; + _BS_word b = *ys++; + if ((a | b) != b) + return 0; + } + return 1; +} + +int operator < (const BitString& x, const BitString& y) +{ + unsigned short xl = x.rep->len; + unsigned short yl = y.rep->len; + if (xl > yl) + return 0; + + const _BS_word* xs = x.rep->s; + const _BS_word* ys = y.rep->s; + const _BS_word* topx = &(xs[BitStr_len(xl)]); + const _BS_word* topy = &(ys[BitStr_len(yl)]); + int one_diff = 0; + while (xs < topx) + { + _BS_word a = *xs++; + _BS_word b = *ys++; + _BS_word c = a | b; + if (c != b) + return 0; + else if (c != a) + one_diff = 1; + } + if (one_diff) + return 1; + else + { + while (ys < topy) + if (*ys++ != 0) + return 1; + return 0; + } +} + +int lcompare(const BitString& x, const BitString& y) +{ + return _BS_lcompare_0 (x.rep->s, x.rep->len, y.rep->s, y.rep->len); +} + +int BitString::count(unsigned int b) const +{ + int count = _BS_count (rep->s, 0, rep->len); + if (!b) + count = rep->len - count; + return count; +} + + +BitStrRep* cmpl(const BitStrRep* src, BitStrRep* r) +{ + r = BStr_copy(r, src); + _BS_word* rs = r->s; + _BS_word* topr = &(rs[BitStr_len(r->len)]); + while (rs < topr) + { + _BS_word cmp = ~(*rs); + *rs++ = cmp; + } + check_last(r); + return r; +} + + +BitStrRep* and(const BitStrRep* x, const BitStrRep* y, BitStrRep* r) +{ + int xrsame = x == r; + int yrsame = y == r; + + unsigned int xl = x->len; + unsigned int yl = y->len; + unsigned int rl = (xl <= yl)? xl : yl; + + r = BStr_resize(r, rl); + + _BS_word* rs = r->s; + _BS_word* topr = &(rs[BitStr_len(rl)]); + const _BS_word* xs = (xrsame)? rs : x->s; + const _BS_word* ys = (yrsame)? rs : y->s; + + while (rs < topr) *rs++ = *xs++ & *ys++; + check_last(r); + return r; +} + +BitStrRep* or(const BitStrRep* x, const BitStrRep* y, BitStrRep* r) +{ + unsigned int xl = x->len; + unsigned int yl = y->len; + unsigned int rl = (xl >= yl)? xl : yl; + int xrsame = x == r; + int yrsame = y == r; + + r = BStr_resize(r, rl); + + _BS_word* rs = r->s; + const _BS_word* xs = (xrsame)? rs : x->s; + const _BS_word* topx = &(xs[BitStr_len(xl)]); + const _BS_word* ys = (yrsame)? rs : y->s; + const _BS_word* topy = &(ys[BitStr_len(yl)]); + + if (xl <= yl) + { + while (xs < topx) *rs++ = *xs++ | *ys++; + if (rs != ys) while (ys < topy) *rs++ = *ys++; + } + else + { + while (ys < topy) *rs++ = *xs++ | *ys++; + if (rs != xs) while (xs < topx) *rs++ = *xs++; + } + check_last(r); + return r; +} + + +BitStrRep* xor(const BitStrRep* x, const BitStrRep* y, BitStrRep* r) +{ + unsigned int xl = x->len; + unsigned int yl = y->len; + unsigned int rl = (xl >= yl)? xl : yl; + int xrsame = x == r; + int yrsame = y == r; + + r = BStr_resize(r, rl); + + _BS_word* rs = r->s; + const _BS_word* xs = (xrsame)? rs : x->s; + const _BS_word* topx = &(xs[BitStr_len(xl)]); + const _BS_word* ys = (yrsame)? rs : y->s; + const _BS_word* topy = &(ys[BitStr_len(yl)]); + + if (xl <= yl) + { + while (xs < topx) *rs++ = *xs++ ^ *ys++; + if (rs != ys) while (ys < topy) *rs++ = *ys++; + } + else + { + while (ys < topy) *rs++ = *xs++ ^ *ys++; + if (rs != xs) while (xs < topx) *rs++ = *xs++; + } + check_last(r); + return r; +} + + +BitStrRep* diff(const BitStrRep* x, const BitStrRep* y, BitStrRep* r) +{ + unsigned int xl = x->len; + unsigned int yl = y->len; + int xrsame = x == y; + int yrsame = y == r; + + r = BStr_resize(r, xl); + + _BS_word* rs = r->s; + const _BS_word* xs = (xrsame)? rs : x->s; + const _BS_word* topx = &(xs[BitStr_len(xl)]); + const _BS_word* ys = (yrsame)? rs : y->s; + const _BS_word* topy = &(ys[BitStr_len(yl)]); + + if (xl <= yl) + { + while (xs < topx) *rs++ = *xs++ & ~(*ys++); + } + else + { + while (ys < topy) *rs++ = *xs++ & ~(*ys++); + if (rs != xs) while (xs < topx) *rs++ = *xs++; + } + check_last(r); + return r; +} + + +BitStrRep* cat(const BitStrRep* x, const BitStrRep* y, BitStrRep* r) +{ + unsigned int xl = x->len; + unsigned int yl = y->len; + unsigned int rl = xl + yl; + int xrsame = x == r; + int yrsame = y == r; + + if (yrsame) + { + if (xrsame) + { + r = BStr_resize(r, rl); + copy_bits (r->s, xl, r->s, 0, yl); + } + else + { + BitStrRep* tmp = BStr_copy(0, y); + r = BStr_resize(r, rl); + _BS_copy_0(r->s, x->s, xl); + copy_bits (r->s, xl, tmp->s, 0, yl); + delete tmp; + } + } + else + { + r = BStr_resize(r, rl); + if (!xrsame) _BS_copy_0(r->s, x->s, xl); + copy_bits (r->s, xl, y->s, 0, yl); + } + check_last(r); + return r; +} + +BitStrRep* cat(const BitStrRep* x, unsigned int bit, BitStrRep* r) +{ + unsigned int xl = x->len; + int xrsame = x == r; + r = BStr_resize(r, xl+1); + if (!xrsame) + _BS_copy_0(r->s, x->s, xl); + if (bit) + r->s[BitStr_index(xl)] |= _BS_BITMASK(BitStr_pos(xl)); + else + r->s[BitStr_index(xl)] &= ~(_BS_BITMASK(BitStr_pos(xl))); + check_last(r); + return r; +} + +BitStrRep* lshift(const BitStrRep* x, int s, BitStrRep* r) +{ + int xrsame = x == r; + int xl = x->len; + int rl = xl + s; + if (s == 0) + r = BStr_copy(r, x); + else if (rl <= 0) + { + r = BStr_resize(r, 0); + r->len = 0; + r->s[0] = 0; + } + else if (s > 0) + { + r = BStr_resize(r, rl); + const _BS_word* xs = (xrsame)? r->s : x->s; + copy_bits (r->s, s, xs, 0, xl); + _BS_clear (r->s, 0, s); + } + else if (xrsame) + { + r = BStr_resize(r, xl); + r->len = rl; + copy_bits (r->s, 0, r->s, -s, xl + s); + } + else + { + r = BStr_resize(r, rl); + copy_bits (r->s, 0, x->s, -s, xl + s); + } + check_last(r); + return r; +} + + +void BitString::set(int p) +{ + if (p < 0) error("Illegal bit index"); + if ((unsigned)(p) >= rep->len) rep = BStr_resize(rep, p + 1); + rep->s[BitStr_index(p)] |= _BS_BITMASK(BitStr_pos(p)); +} + +void BitString::assign(int p, unsigned int bit) +{ + if (p < 0) error("Illegal bit index"); + if ((unsigned)(p) >= rep->len) rep = BStr_resize(rep, p + 1); + if (bit) + rep->s[BitStr_index(p)] |= _BS_BITMASK(BitStr_pos(p)); + else + rep->s[BitStr_index(p)] &= ~(_BS_BITMASK(BitStr_pos(p))); +} + +void BitString::clear(int p) +{ + if (p < 0) error("Illegal bit index"); + if ((unsigned)(p) >= rep->len) rep = BStr_resize(rep, p + 1); + rep->s[BitStr_index(p)] &= ~(_BS_BITMASK(BitStr_pos(p))); +} + +void BitString::clear() +{ + if (rep == &_nilBitStrRep) return; + _BS_clear (rep->s, 0, rep->len); +} + +void BitString::set() +{ + if (rep == &_nilBitStrRep) return; + _BS_word* s = rep->s; + _BS_word* tops = &(s[BitStr_len(rep->len)]); + while (s < tops) *s++ = ONES; + check_last(rep); +} + +void BitString::invert(int p) +{ + if (p < 0) error("Illegal bit index"); + if ((unsigned)(p) >= rep->len) rep = BStr_resize(rep, p + 1); + rep->s[BitStr_index(p)] ^= _BS_BITMASK(BitStr_pos(p)); +} + +void BitString::set(int from, int to) +{ + if (from < 0 || from > to) error("Illegal bit index"); + if ((unsigned)(to) >= rep->len) rep = BStr_resize(rep, to+1); + + _BS_size_t len = to - from + 1; + _BS_word* xs = rep->s; + _BS_NORMALIZE (xs, from); + _BS_invert (xs, from, len); +} + +void BitString::clear(int from, int to) +{ + if (from < 0 || from > to) error("Illegal bit index"); + if ((unsigned)(to) >= rep->len) rep = BStr_resize(rep, to+1); + + _BS_size_t len = to - from + 1; + _BS_word* xs = rep->s; + _BS_NORMALIZE (xs, from); + _BS_clear (xs, from, len); +} + +void BitString::invert(int from, int to) +{ + if (from < 0 || from > to) error("Illegal bit index"); + if ((unsigned)(to) >= rep->len) rep = BStr_resize(rep, to+1); + _BS_size_t len = to - from + 1; + _BS_word* xs = rep->s; + _BS_NORMALIZE (xs, from); + _BS_invert (xs, from, len); +} + + +int BitString::test(int from, int to) const +{ + if (from < 0 || from > to || (unsigned)(from) >= rep->len) return 0; + + _BS_size_t len = to - from + 1; + _BS_word* xs = rep->s; + _BS_NORMALIZE (xs, from); + return _BS_any (xs, from, len); +} + +int BitString::next(int p, unsigned int b) const +{ + if ((unsigned)(++p) >= rep->len) + return -1; + + int ind = BitStr_index(p); + int pos = BitStr_pos(p); + int l = BitStr_len(rep->len); + + int j = ind; + const _BS_word* s = rep->s; + _BS_word a = s[j] >> pos; + int i = pos; + + if (b != 0) + { + for (; i < BITSTRBITS && a != 0; ++i) + { + if (a & 1) + return j * BITSTRBITS + i; + a >>= 1; + } + for (++j; j < l; ++j) + { + a = s[j]; + for (i = 0; i < BITSTRBITS && a != 0; ++i) + { + if (a & 1) + return j * BITSTRBITS + i; + a >>= 1; + } + } + return -1; + } + else + { + int last = BitStr_pos(rep->len); + if (j == l - 1) + { + for (; i < last; ++i) + { + if ((a & 1) == 0) + return j * BITSTRBITS + i; + a >>= 1; + } + return -1; + } + + for (; i < BITSTRBITS; ++i) + { + if ((a & 1) == 0) + return j * BITSTRBITS + i; + a >>= 1; + } + for (++j; j < l - 1; ++j) + { + a = s[j]; + if (a != ONES) + { + for (i = 0; i < BITSTRBITS; ++i) + { + if ((a & 1) == 0) + return j * BITSTRBITS + i; + a >>= 1; + } + } + } + a = s[j]; + for (i = 0; i < last; ++i) + { + if ((a & 1) == 0) + return j * BITSTRBITS + i; + a >>= 1; + } + return -1; + } +} + +int BitString::prev(int p, unsigned int b) const +{ + if (--p < 0) + return -1; + + int ind = BitStr_index(p); + int pos = BitStr_pos(p); + + const _BS_word* s = rep->s; + + if ((unsigned)(p) >= rep->len) + { + ind = BitStr_index(rep->len - 1); + pos = BitStr_pos(rep->len - 1); + } + + int j = ind; + _BS_word a = s[j]; + + int i = pos; + _BS_word maxbit = ((_BS_word)1) << pos; + + if (b != 0) + { + for (; i >= 0 && a != 0; --i) + { + if (a & maxbit) + return j * BITSTRBITS + i; + a <<= 1; + } + maxbit = ((_BS_word)1) << (BITSTRBITS - 1); + for (--j; j >= 0; --j) + { + a = s[j]; + for (i = BITSTRBITS - 1; i >= 0 && a != 0; --i) + { + if (a & maxbit) + return j * BITSTRBITS + i; + a <<= 1; + } + } + return -1; + } + else + { + if (a != ONES) + { + for (; i >= 0; --i) + { + if ((a & maxbit) == 0) + return j * BITSTRBITS + i; + a <<= 1; + } + } + maxbit = ((_BS_word)1) << (BITSTRBITS - 1); + for (--j; j >= 0; --j) + { + a = s[j]; + if (a != ONES) + { + for (i = BITSTRBITS - 1; i >= 0; --i) + { + if ((a & maxbit) == 0) + return j * BITSTRBITS + i; + a <<= 1; + } + } + } + return -1; + } +} + + +int BitString::search(int startx, int lengthx, + const _BS_word* ys, int starty, int lengthy) const +{ + const _BS_word* xs = rep->s; + int ylen = lengthy - starty; + int righty = lengthy - 1; + int rev = startx < 0; + if (rev) + { + int leftx = 0; + int rightx = lengthx + startx; + startx = rightx - ylen + 1; + if (ylen == 0) return startx; + if (starty < 0 || righty < 0 || startx < 0 || startx >= lengthx) return -1; + + int xind = BitStr_index(startx); + int xpos = BitStr_pos(startx); + int yind = BitStr_index(starty); + int ypos = BitStr_pos(starty); + + int rightxind = BitStr_index(rightx); + + _BS_word x = borrow_hi(xs, xind, rightxind, xpos); + + int rightyind = BitStr_index(righty); + int rightypos = BitStr_pos(righty); + _BS_word y = borrow_hi(ys, yind, rightyind, ypos); + _BS_word ymask; + if (yind == rightyind) + ymask = rmask(rightypos); + else if (yind+1 == rightyind) + ymask = rmask(BITSTRBITS - ypos + rightypos + 1); + else + ymask = ONES; + + int p = startx; + for (;;) + { + if ((x & ymask) == y) + { + int xi = xind; + int yi = yind; + for (;;) + { + if (++yi > rightyind || ++xi > rightxind) + return p; + _BS_word tx = borrow_hi(xs, xi, rightxind, xpos); + _BS_word ty = borrow_hi(ys, yi, rightyind, ypos); + if (yi == rightyind) + tx &= rmask(rightypos); + else if (yi+1 == rightyind) + tx &= rmask(BITSTRBITS - ypos + rightypos + 1); + if (tx != ty) + break; + } + } + if (--p < leftx) + return -1; + if (--xpos < 0) + { + xpos = BITSTRBITS - 1; + --xind; + } + x = borrow_hi(xs, xind, rightxind, xpos); + } + } + else + { + + int rightx = lengthx - 1; + if (ylen == 0) return startx; + if (starty < 0 || righty < 0 || startx < 0 || startx >= lengthx) return -1; + + int xind = BitStr_index(startx); + int xpos = BitStr_pos(startx); + int yind = BitStr_index(starty); + int ypos = BitStr_pos(starty); + + int rightxind = BitStr_index(rightx); + + _BS_word x = borrow_hi(xs, xind, rightxind, xpos); + _BS_word nextx = (xind >= rightxind) ? 0 : (xs[xind+1] >> xpos); + + int rightyind = BitStr_index(righty); + int rightypos = BitStr_pos(righty); + _BS_word y = borrow_hi(ys, yind, rightyind, ypos); + _BS_word ymask; + if (yind == rightyind) + ymask = rmask(rightypos); + else if (yind+1 == rightyind) + ymask = rmask(BITSTRBITS - ypos + rightypos + 1); + else + ymask = ONES; + + int p = startx; + for (;;) + { + if ((x & ymask) == y) + { + int xi = xind; + int yi = yind; + for (;;) + { + if (++yi > rightyind || ++xi > rightxind) + return p; + _BS_word tx = borrow_hi(xs, xi, rightxind, xpos); + _BS_word ty = borrow_hi(ys, yi, rightyind, ypos); + if (yi == rightyind) + tx &= rmask(rightypos); + else if (yi+1 == rightyind) + tx &= rmask(BITSTRBITS - ypos + rightypos + 1); + if (tx != ty) + break; + } + } + if (++p > rightx) + return -1; + if (++xpos == BITSTRBITS) + { + xpos = 0; + x = xs[++xind]; + nextx = (xind >= rightxind) ? 0 : xs[xind+1]; + } + else + { + x >>= 1; + if (nextx & 1) + x |= MAXBIT; + nextx >>= 1; + } + } + } +} + + +int BitPattern::search(const _BS_word* xs, int startx, int lengthx) const +{ + const _BS_word* ys = pattern.rep->s; + const _BS_word* ms = mask.rep->s; + int righty = pattern.rep->len - 1; + int rightm = mask.rep->len - 1; + + int rev = startx < 0; + if (rev) + { + int leftx = 0; + int rightx = lengthx + startx; + startx = rightx - righty; + + if (righty < 0) return startx; + if (startx < 0 || startx >= lengthx) return -1; + + int xind = BitStr_index(startx); + int xpos = BitStr_pos(startx); + + int rightxind = BitStr_index(rightx); + + int rightmind = BitStr_index(rightm); + int rightyind = BitStr_index(righty); + + _BS_word x = safe_borrow_hi(xs, xind, rightxind, xpos); + _BS_word m = safe_borrow_hi(ms, 0, rightmind, 0); + _BS_word y = safe_borrow_hi(ys, 0, rightyind, 0) & m; + + int p = startx; + for (;;) + { + if ((x & m) == y) + { + int xi = xind; + int yi = 0; + for (;;) + { + if (++yi > rightyind || ++xi > rightxind) + return p; + _BS_word tm = safe_borrow_hi(ms, yi, rightmind, 0); + _BS_word ty = safe_borrow_hi(ys, yi, rightyind, 0); + _BS_word tx = safe_borrow_hi(xs, xi, rightxind, xpos); + if ((tx & tm) != (ty & tm)) + break; + } + } + if (--p < leftx) + return -1; + if (--xpos < 0) + { + xpos = BITSTRBITS - 1; + --xind; + } + x = safe_borrow_hi(xs, xind, rightxind, xpos); + } + } + else + { + + int rightx = lengthx - 1; + + if (righty < 0) return startx; + if (startx < 0 || startx >= lengthx) return -1; + + int xind = BitStr_index(startx); + int xpos = BitStr_pos(startx); + + int rightxind = BitStr_index(rightx); + + int rightmind = BitStr_index(rightm); + int rightyind = BitStr_index(righty); + + _BS_word x = safe_borrow_hi(xs, xind, rightxind, xpos); + _BS_word m = safe_borrow_hi(ms, 0, rightmind, 0); + _BS_word y = safe_borrow_hi(ys, 0, rightyind, 0) & m; + + _BS_word nextx = (xind >= rightxind) ? 0 : (xs[xind+1] >> xpos); + + int p = startx; + for (;;) + { + if ((x & m) == y) + { + int xi = xind; + int yi = 0; + for (;;) + { + if (++yi > rightyind || ++xi > rightxind) + return p; + _BS_word tm = safe_borrow_hi(ms, yi, rightmind, 0); + _BS_word ty = safe_borrow_hi(ys, yi, rightyind, 0); + _BS_word tx = safe_borrow_hi(xs, xi, rightxind, xpos); + if ((tx & tm) != (ty & tm)) + break; + } + } + if (++p > rightx) + return -1; + if (++xpos == BITSTRBITS) + { + xpos = 0; + x = xs[++xind]; + nextx = (xind >= rightxind) ? 0 : xs[xind+1]; + } + else + { + x >>= 1; + if (nextx & 1) + x |= MAXBIT; + nextx >>= 1; + } + } + } +} + +int BitString::match(int startx, int lengthx, int exact, + const _BS_word* ys, int starty, int yl) const +{ + const _BS_word* xs = rep->s; + int ylen = yl - starty; + int righty = yl - 1; + + int rightx; + int rev = startx < 0; + if (rev) + { + rightx = lengthx + startx; + startx = rightx - ylen + 1; + if (exact && startx != 0) + return 0; + } + else + { + rightx = lengthx - 1; + if (exact && rightx - startx != righty) + return 0; + } + + if (ylen == 0) return 1; + if (righty < 0 || startx < 0 || startx >= lengthx) return 0; + + int xi = BitStr_index(startx); + int xpos = BitStr_pos(startx); + int yi = BitStr_index(starty); + int ypos = BitStr_pos(starty); + + int rightxind = BitStr_index(rightx); + int rightyind = BitStr_index(righty); + int rightypos = BitStr_pos(righty); + + for (;;) + { + _BS_word x = borrow_hi(xs, xi, rightxind, xpos); + _BS_word y = borrow_hi(ys, yi, rightyind, ypos); + if (yi == rightyind) + x &= rmask(rightypos); + else if (yi+1 == rightyind) + x &= rmask(BITSTRBITS - ypos + rightypos + 1); + if (x != y) + return 0; + else if (++yi > rightyind || ++xi > rightxind) + return 1; + } +} + +int BitPattern::match(const _BS_word* xs, int startx, + int lengthx, int exact) const +{ + const _BS_word* ys = pattern.rep->s; + int righty = pattern.rep->len - 1; + _BS_word* ms = mask.rep->s; + int rightm = mask.rep->len - 1; + + int rightx; + int rev = startx < 0; + if (rev) + { + rightx = lengthx + startx; + startx = rightx - righty; + if (exact && startx != 0) + return 0; + } + else + { + rightx = lengthx - 1; + if (exact && rightx - startx != righty) + return 0; + } + + if (righty < 0) return 1; + if (startx < 0 || startx >= lengthx) return 0; + + int xind = BitStr_index(startx); + int xpos = BitStr_pos(startx); + int yind = 0; + + int rightxind = BitStr_index(rightx); + int rightyind = BitStr_index(righty); + int rightmind = BitStr_index(rightm); + + for(;;) + { + _BS_word m = safe_borrow_hi(ms, yind, rightmind, 0); + _BS_word x = safe_borrow_hi(xs, xind, rightxind, xpos) & m; + _BS_word y = safe_borrow_hi(ys, yind, rightyind, 0) & m; + if (x != y) + return 0; + else if (++yind > rightyind || ++xind > rightxind) + return 1; + } +} + +BitSubString& BitSubString::operator = (const BitString& y) +{ + if (&S == &_nil_BitString) + return *this; + BitStrRep* targ = S.rep; + + unsigned int ylen = y.rep->len; + int sl = targ->len - len + ylen; + + if (y.rep == targ || ylen > len) + { + BitStrRep* oldtarg = targ; + targ = BStr_alloc(0, 0, 0, 0, sl); + _BS_copy (targ->s, 0, oldtarg->s, 0, pos); + copy_bits (targ->s, pos, y.rep->s, 0, ylen); + copy_bits (targ->s, pos + ylen, oldtarg->s, pos+len, oldtarg->len-pos-len); + delete oldtarg; + } + else if (len == ylen) + copy_bits (targ->s, pos, y.rep->s, 0, len); + else if (ylen < len) + { + copy_bits (targ->s, pos, y.rep->s, 0, ylen); + copy_bits (targ->s, pos + ylen, targ->s, pos + len, targ->len - pos - len); + targ->len = sl; + } + check_last(targ); + S.rep = targ; + return *this; +} + +BitSubString& BitSubString::operator = (const BitSubString& y) +{ + if (&S == &_nil_BitString) + return *this; + BitStrRep* targ = S.rep; + + if (len == 0 || pos >= targ->len) + return *this; + + int sl = targ->len - len + y.len; + + if (y.S.rep == targ || y.len > len) + { + BitStrRep* oldtarg = targ; + targ = BStr_alloc(0, 0, 0, 0, sl); + _BS_copy_0(targ->s, oldtarg->s, pos); + copy_bits (targ->s, pos, y.S.rep->s, y.pos, y.len); + copy_bits (targ->s, pos + y.len, oldtarg->s, pos+len, + oldtarg->len-pos-len); + delete oldtarg; + } + else if (len == y.len) + copy_bits (targ->s, pos, y.S.rep->s, y.pos, y.len); + else if (y.len < len) + { + copy_bits (targ->s, pos, y.S.rep->s, y.pos, y.len); + copy_bits (targ->s, pos + y.len, targ->s, pos + len, + targ->len - pos - len); + targ->len = sl; + } + check_last(targ); + S.rep = targ; + return *this; +} + +BitSubString BitString::at(int first, int len) +{ + return _substr(first, len); +} + +BitSubString BitString::before(int pos) +{ + return _substr(0, pos); +} + +BitSubString BitString::after(int pos) +{ + return _substr(pos + 1, rep->len - (pos + 1)); +} + +BitSubString BitString::at(const BitString& y, int startpos) +{ + int first = search(startpos, rep->len, y.rep->s, 0, y.rep->len); + return _substr(first, y.rep->len); +} + +BitSubString BitString::before(const BitString& y, int startpos) +{ + int last = search(startpos, rep->len, y.rep->s, 0, y.rep->len); + return _substr(0, last); +} + +BitSubString BitString::after(const BitString& y, int startpos) +{ + int first = search(startpos, rep->len, y.rep->s, 0, y.rep->len); + if (first >= 0) first += y.rep->len; + return _substr(first, rep->len - first); +} + + +BitSubString BitString::at(const BitSubString& y, int startpos) +{ + int first = search(startpos, rep->len, y.S.rep->s, y.pos, y.len); + return _substr(first, y.len); +} + +BitSubString BitString::before(const BitSubString& y, int startpos) +{ + int last = search(startpos, rep->len, y.S.rep->s, y.pos, y.len); + return _substr(0, last); +} + +BitSubString BitString::after(const BitSubString& y, int startpos) +{ + int first = search(startpos, rep->len, y.S.rep->s, y.pos, y.len); + if (first >= 0) first += y.len; + return _substr(first, rep->len - first); +} + +BitSubString BitString::at(const BitPattern& r, int startpos) +{ + int first = r.search(rep->s, startpos, rep->len); + return _substr(first, r.pattern.rep->len); +} + + +BitSubString BitString::before(const BitPattern& r, int startpos) +{ + int first = r.search(rep->s, startpos, rep->len); + return _substr(0, first); +} + +BitSubString BitString::after(const BitPattern& r, int startpos) +{ + int first = r.search(rep->s, startpos, rep->len); + if (first >= 0) first += r.pattern.rep->len; + return _substr(first, rep->len - first); +} + +#if defined(__GNUG__) && !defined(_G_NO_NRV) +#define RETURN(r) return +#define RETURNS(r) return r; +#define RETURN_OBJECT(TYPE, NAME) /* nothing */ +#define USE_UNSIGNED 1 /* probably correct */ +#else /* _G_NO_NRV */ +#define RETURN(r) return r +#define RETURNS(r) /* nothing */ +#define RETURN_OBJECT(TYPE, NAME) TYPE NAME; +#define USE_UNSIGNED 0 /* probably old bug */ +#endif + +BitString +common_prefix (const BitString& x, const BitString& y, int startpos) + RETURNS(r) +{ + RETURN_OBJECT(BitString, r); + unsigned int xl = x.rep->len; + unsigned int yl = y.rep->len; + + unsigned int startx, starty; + if (startpos < 0) + { + startx = xl + startpos; + starty = yl + startpos; + } + else + startx = starty = startpos; + + if (startx >= xl || starty >= yl) + RETURN(r); + + const _BS_word* xs = &(x.rep->s[BitStr_index(startx)]); + _BS_word a = *xs++; + unsigned int xp = startx; + + const _BS_word* ys = &(y.rep->s[BitStr_index(starty)]); + _BS_word b = *ys++; + unsigned int yp = starty; + + for(; xp < xl && yp < yl; ++xp, ++yp) + { + _BS_word xbit = ((_BS_word)1) << (BitStr_pos(xp)); + _BS_word ybit = ((_BS_word)1) << (BitStr_pos(yp)); + if (((a & xbit) == 0) != ((b & ybit) == 0)) + break; + if (xbit == MAXBIT) + a = *xs++; + if (ybit == MAXBIT) + b = *ys++; + } + r.rep = BStr_alloc(0, x.rep->s, startx, xp, xp - startx); + RETURN(r); +} + + +BitString +common_suffix (const BitString& x, const BitString& y, int startpos) + RETURNS(r) +{ + RETURN_OBJECT(BitString, r); + unsigned int xl = x.rep->len; + unsigned int yl = y.rep->len; + + unsigned int startx, starty; + if (startpos < 0) + { + startx = xl + startpos; + starty = yl + startpos; + } + else + startx = starty = startpos; + + if (startx >= xl || starty >= yl) + RETURN(r); + + const _BS_word* xs = &(x.rep->s[BitStr_index(startx)]); + _BS_word a = *xs--; + int xp = startx; + + const _BS_word* ys = &(y.rep->s[BitStr_index(starty)]); + _BS_word b = *ys--; + int yp = starty; + + for(; xp >= 0 && yp >= 0; --xp, --yp) + { + _BS_word xbit = ((_BS_word)1) << (BitStr_pos(xp)); + _BS_word ybit = ((_BS_word)1) << (BitStr_pos(yp)); + if (((a & xbit) == 0) != ((b & ybit) == 0)) + break; + if (xbit == 1) + a = *xs--; + if (ybit == 1) + b = *ys--; + } + r.rep = BStr_alloc(0, x.rep->s, xp+1, startx+1, startx - xp); + RETURN(r); +} + +BitString reverse (const BitString& x) + RETURNS(r) +{ + RETURN_OBJECT(BitString, r); + unsigned int yl = x.rep->len; + BitStrRep* y = BStr_resize(0, yl); + if (yl > 0) + { + const _BS_word* ls = x.rep->s; + _BS_word lm = 1; + _BS_word* rs = &(y->s[BitStr_index(yl - 1)]); + _BS_word rm = ((_BS_word)1) << (BitStr_pos(yl - 1)); + for (unsigned int l = 0; l < yl; ++l) + { + if (*ls & lm) + *rs |= rm; + if (lm == MAXBIT) + { + ++ls; + lm = 1; + } + else + lm <<= 1; + if (rm == 1) + { + --rs; + rm = MAXBIT; + } + else + rm >>= 1; + } + } + r.rep = y; + RETURN(r); +} + +BitString +atoBitString (const char* s, char f, char t) + RETURNS(res) +{ + RETURN_OBJECT(BitString, res); + int sl = strlen(s); + BitStrRep* r = BStr_resize(0, sl); + if (sl != 0) + { + unsigned int rl = 0; + _BS_word* rs = r->s; + _BS_word a = 0; + _BS_word m = 1; + unsigned int i = 0; + for(;;) + { + char ch = s[i]; + if (ch != t && ch != f) + { + *rs = a; + break; + } + ++rl; + if (ch == t) + a |= m; + if (++i == sl) + { + *rs = a; + break; + } + else if (i % BITSTRBITS == 0) + { + *rs++ = a; + a = 0; + m = 1; + } + else + m <<= 1; + } + r = BStr_resize(r, rl); + } + res.rep = r; + RETURN(res); +} + +BitPattern +atoBitPattern (const char* s, char f,char t,char x) + RETURNS(r) +{ + RETURN_OBJECT(BitPattern, r); + int sl = strlen(s); + if (sl != 0) + { + unsigned int rl = 0; + r.pattern.rep = BStr_resize(r.pattern.rep, sl); + r.mask.rep = BStr_resize(r.mask.rep, sl); + _BS_word* rs = r.pattern.rep->s; + _BS_word* ms = r.mask.rep->s; + _BS_word a = 0; + _BS_word b = 0; + _BS_word m = 1; + unsigned int i = 0; + for(;;) + { + char ch = s[i]; + if (ch != t && ch != f && ch != x) + { + *rs = a; + *ms = b; + break; + } + ++rl; + if (ch == t) + { + a |= m; + b |= m; + } + else if (ch == f) + { + b |= m; + } + if (++i == sl) + { + *rs = a; + *ms = b; + break; + } + else if (i % BITSTRBITS == 0) + { + *rs++ = a; + *ms++ = b; + a = 0; + b = 0; + m = 1; + } + else + m <<= 1; + } + r.pattern.rep = BStr_resize(r.pattern.rep, rl); + r.mask.rep = BStr_resize(r.mask.rep, rl); + } + RETURN(r); +} + +extern AllocRing _libgxx_fmtq; + +void BitString::printon (ostream& os, char f, char t) const +{ + unsigned int xl = rep->len; + const _BS_word* ptr = rep->s; + register streambuf *sb = os.rdbuf(); + _BS_word a = 0; + + for (unsigned int i = 0; i < xl; ++i) + { + if (i % BITSTRBITS == 0) + a = *ptr++; + sb->sputc((a & 1)? t : f); + a >>= 1; + } +} +const char* BitStringtoa(const BitString& x, char f, char t) +{ + int wrksiz = x.length() + 2; + char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); + ostrstream stream(fmtbase, wrksiz); + + x.printon(stream, f, t); + stream << ends; + return fmtbase; +} + +ostream& operator << (ostream& s, const BitString& x) +{ + if (s.opfx()) + x.printon(s); + return s; +} + +const char* BitPatterntoa(const BitPattern& p, char f,char t,char x) +{ + unsigned int pl = p.pattern.rep->len; + unsigned int ml = p.mask.rep->len; + unsigned int l = (pl <= ml)? pl : ml; + + int wrksiz = l + 2; + char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); + ostrstream stream(fmtbase, wrksiz); + + p.printon(stream, f, t, x); + stream << ends; + return fmtbase; +} + +void BitPattern::printon(ostream& s, char f,char t,char x) const +{ + unsigned int pl = pattern.rep->len; + unsigned int ml = mask.rep->len; + unsigned int l = (pl <= ml)? pl : ml; + register streambuf *sb = s.rdbuf(); + + const _BS_word* ps = pattern.rep->s; + const _BS_word* ms = mask.rep->s; + _BS_word a = 0; + _BS_word m = 0; + + for (unsigned int i = 0; i < l; ++i) + { + if (i % BITSTRBITS == 0) + { + a = *ps++; + m = *ms++; + } + if (m & 1) + sb->sputc((a & 1)? t : f); + else + sb->sputc(x); + a >>= 1; + m >>= 1; + } +} + +ostream& operator << (ostream& s, const BitPattern& x) +{ + if (s.opfx()) + x.printon(s); + return s; +} + + +int BitString::OK() const +{ + int v = rep != 0; // have a rep; + v &= BitStr_len(rep->len) <= rep->sz; // within allocated size + if (!v) error("invariant failure"); + return v; +} + +int BitSubString::OK() const +{ + int v = S.OK(); // valid BitString + v &= pos + len <= S.rep->len; // within bounds of targ + if (!v) S.error("BitSubString invariant failure"); + return v; +} + +int BitPattern::OK() const +{ + int v = pattern.OK() && mask.OK(); + if (!v) pattern.error("BitPattern invariant failure"); + return v; +} + diff --git a/gnu/lib/libg++/libg++/Complex.cc b/gnu/lib/libg++/libg++/Complex.cc new file mode 100644 index 0000000..5aed909 --- /dev/null +++ b/gnu/lib/libg++/libg++/Complex.cc @@ -0,0 +1,256 @@ +/* +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 <Complex.h> +#include <std.h> +#include <builtin.h> + +// error handling + +void default_Complex_error_handler(const char* msg) +{ + cerr << "Fatal Complex arithmetic error. " << msg << "\n"; + exit(1); +} + +one_arg_error_handler_t Complex_error_handler = default_Complex_error_handler; + +one_arg_error_handler_t set_Complex_error_handler(one_arg_error_handler_t f) +{ + one_arg_error_handler_t old = Complex_error_handler; + Complex_error_handler = f; + return old; +} + +void Complex::error(const char* msg) const +{ + (*Complex_error_handler)(msg); +} + +/* from romine@xagsun.epm.ornl.gov */ +Complex /* const */ operator / (const Complex& x, const Complex& y) +{ + double den = fabs(y.real()) + fabs(y.imag()); + if (den == 0.0) x.error ("Attempted division by zero."); + double xrden = x.real() / den; + double xiden = x.imag() / den; + double yrden = y.real() / den; + double yiden = y.imag() / den; + double nrm = yrden * yrden + yiden * yiden; + return Complex((xrden * yrden + xiden * yiden) / nrm, + (xiden * yrden - xrden * yiden) / nrm); +} + +Complex& Complex::operator /= (const Complex& y) +{ + double den = fabs(y.real()) + fabs(y.imag()); + if (den == 0.0) error ("Attempted division by zero."); + double xrden = re / den; + double xiden = im / den; + double yrden = y.real() / den; + double yiden = y.imag() / den; + double nrm = yrden * yrden + yiden * yiden; + re = (xrden * yrden + xiden * yiden) / nrm; + im = (xiden * yrden - xrden * yiden) / nrm; + return *this; +} + +Complex /* const */ operator / (double x, const Complex& y) +{ + double den = norm(y); + if (den == 0.0) y.error ("Attempted division by zero."); + return Complex((x * y.real()) / den, -(x * y.imag()) / den); +} + +Complex /* const */ operator / (const Complex& x, double y) +{ + if (y == 0.0) x.error ("Attempted division by zero."); + return Complex(x.real() / y, x.imag() / y); +} + + +Complex& Complex::operator /= (double y) +{ + if (y == 0.0) error ("Attempted division by zero."); + re /= y; im /= y; + return *this; +} + + +Complex /* const */ exp(const Complex& x) +{ + double r = exp(x.real()); + return Complex(r * cos(x.imag()), + r * sin(x.imag())); +} + +Complex /* const */ cosh(const Complex& x) +{ + return Complex(cos(x.imag()) * cosh(x.real()), + sin(x.imag()) * sinh(x.real())); +} + +Complex /* const */ sinh(const Complex& x) +{ + return Complex(cos(x.imag()) * sinh(x.real()), + sin(x.imag()) * cosh(x.real())); +} + +Complex /* const */ cos(const Complex& x) +{ + return Complex(cos(x.real()) * cosh(x.imag()), + -sin(x.real()) * sinh(x.imag())); +} + +Complex /* const */ sin(const Complex& x) +{ + return Complex(sin(x.real()) * cosh(x.imag()), + cos(x.real()) * sinh(x.imag())); +} + +Complex /* const */ log(const Complex& x) +{ + double h = hypot(x.real(), x.imag()); + if (h <= 0.0) x.error("attempted log of zero magnitude number."); + return Complex(log(h), atan2(x.imag(), x.real())); +} + +// Corrections based on reports from: thc@cs.brown.edu & saito@sdr.slb.com +Complex /* const */ pow(const Complex& x, const Complex& p) +{ + double h = hypot(x.real(), x.imag()); + if (h <= 0.0) x.error("attempted power of zero magnitude number."); + + double a = atan2(x.imag(), x.real()); + double lr = pow(h, p.real()); + double li = p.real() * a; + if (p.imag() != 0.0) + { + lr /= exp(p.imag() * a); + li += p.imag() * log(h); + } + return Complex(lr * cos(li), lr * sin(li)); +} + +Complex /* const */ pow(const Complex& x, double p) +{ + double h = hypot(x.real(), x.imag()); + if (h <= 0.0) x.error("attempted power of zero magnitude number."); + double lr = pow(h, p); + double a = atan2(x.imag(), x.real()); + double li = p * a; + return Complex(lr * cos(li), lr * sin(li)); +} + + +Complex /* const */ sqrt(const Complex& x) +{ + if (x.real() == 0.0 && x.imag() == 0.0) + return Complex(0.0, 0.0); + else + { + double s = sqrt((fabs(x.real()) + hypot(x.real(), x.imag())) * 0.5); + double d = (x.imag() / s) * 0.5; + if (x.real() > 0.0) + return Complex(s, d); + else if (x.imag() >= 0.0) + return Complex(d, s); + else + return Complex(-d, -s); + } +} + + +Complex /* const */ pow(const Complex& x, int p) +{ + if (p == 0) + return Complex(1.0, 0.0); + else if (x == 0.0) + return Complex(0.0, 0.0); + else + { + Complex res(1.0, 0.0); + Complex b = x; + if (p < 0) + { + p = -p; + b = 1.0 / b; + } + for(;;) + { + if (p & 1) + res *= b; + if ((p >>= 1) == 0) + return res; + else + b *= b; + } + } +} + +ostream& operator << (ostream& s, const Complex& x) +{ + return s << "(" << x.real() << ", " << x.imag() << ")" ; +} + +istream& operator >> (istream& s, Complex& x) +{ +#ifdef _OLD_STREAMS + if (!s.good()) + { + return s; + } +#else + if (!s.ipfx(0)) + { + s.clear(ios::failbit|s.rdstate()); // Redundant if using GNU iostreams. + return s; + } +#endif + double r, i; + char ch; + s >> ws; + s.get(ch); + if (ch == '(') + { + s >> r; + s >> ws; + s.get(ch); + if (ch == ',') + { + s >> i; + s >> ws; + s .get(ch); + } + else + i = 0; + if (ch != ')') + s.clear(ios::failbit); + } + else + { + s.putback(ch); + s >> r; + i = 0; + } + x = Complex(r, i); + return s; +} + diff --git a/gnu/lib/libg++/libg++/CursesW.cc b/gnu/lib/libg++/libg++/CursesW.cc new file mode 100644 index 0000000..92bddfe --- /dev/null +++ b/gnu/lib/libg++/libg++/CursesW.cc @@ -0,0 +1,253 @@ +/* +Copyright (C) 1989, 1992 Free Software Foundation + written by Eric Newton (newton@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 <stdio.h> +#include <stdarg.h> +#include <builtin.h> +#ifndef _OLD_STREAMS +#include <strstream.h> +#endif +// Include CurseW.h and/or curses.h *after* iostream includes, +// because curses.h defines a clear macro that conflicts with iostream. Sigh. +#include <CursesW.h> + +#if _G_HAVE_CURSES + +int CursesWindow::count = 0; + +/* + * C++ interface to curses library. + * + */ + +#if !defined(_IO_MAGIC) && !defined(HAVE_VSCANF) &&!defined vsscanf +extern "C" int _doscan(FILE *, const char*, va_list args); + +static int vsscanf(char *buf, const char * fmt, va_list args) +{ + FILE b; +#ifdef _IOSTRG + b._flag = _IOREAD|_IOSTRG; +#else + b._flag = _IOREAD; +#endif + b._base = (unsigned char*)buf; + b._ptr = (unsigned char*)buf; + b._cnt = BUFSIZ; + return _doscan(&b, fmt, args); +} +#endif + +/* + * varargs functions are handled conservatively: + * They interface directly into the underlying + * _doscan, _doprnt and/or vfprintf routines rather than + * assume that such things are handled compatibly in the curses library + */ + +int CursesWindow::scanw(const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); +#ifdef VMS + int result = wscanw(w , fmt , args); +#else /* NOT VMS */ + char buf[BUFSIZ]; + int result = wgetstr(w, buf); + if (result == OK) { + +#ifdef _IO_MAGIC /* GNU iostreams */ + strstreambuf ss(buf, BUFSIZ); + result = ss.vscan(fmt, args); +#else + result = vsscanf(buf, fmt, args); +#endif + } +#endif /* !VMS */ + va_end(args); + return result; +} + +int CursesWindow::mvscanw(int y, int x, const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + char buf[BUFSIZ]; + int result = wmove(w, y, x); + if (result == OK) +#ifdef VMS + result=wscanw(w , fmt , args); +#else /* !VMS */ + { + result = wgetstr(w, buf); + if (result == OK) { +#ifdef _IO_MAGIC /* GNU iostreams */ + strstreambuf ss(buf, BUFSIZ); + result = ss.vscan(fmt, args); +#else + result = vsscanf(buf, fmt, args); +#endif + } + } +#endif /* !VMS */ + va_end(args); + return result; +} + +int CursesWindow::printw(const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + char buf[BUFSIZ]; + vsprintf(buf, fmt, args); + va_end(args); + return waddstr(w, buf); +} + + +int CursesWindow::mvprintw(int y, int x, const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + int result = wmove(w, y, x); + if (result == OK) + { + char buf[BUFSIZ]; + vsprintf(buf, fmt, args); + result = waddstr(w, buf); + } + va_end(args); + return result; +} + +CursesWindow::CursesWindow(int lines, int cols, int begin_y, int begin_x) +{ + if (count==0) + initscr(); + + w = newwin(lines, cols, begin_y, begin_x); + if (w == 0) + { + (*lib_error_handler)("CursesWindow", "Cannot construct window"); + } + + alloced = 1; + subwins = par = sib = 0; + count++; +} + +CursesWindow::CursesWindow(WINDOW* &window) +{ + if (count==0) + initscr(); + + w = window; + alloced = 0; + subwins = par = sib = 0; + count++; +} + +CursesWindow::CursesWindow(CursesWindow& win, int l, int c, + int by, int bx, char absrel) +{ + + if (absrel == 'r') // relative origin + { + by += win.begy(); + bx += win.begx(); + } + + // Even though we treat subwindows as a tree, the standard curses + // library needs the `subwin' call to link to the root in + // order to correctly perform refreshes, etc. + + CursesWindow* root = &win; + while (root->par != 0) root = root->par; + + w = subwin(root->w, l, c, by, bx); + if (w == 0) + { + (*lib_error_handler)("CursesWindow", "Cannot construct subwindow"); + } + + par = &win; + sib = win.subwins; + win.subwins = this; + subwins = 0; + alloced = 1; + count++; +} + + +void CursesWindow::kill_subwindows() +{ + for (CursesWindow* p = subwins; p != 0; p = p->sib) + { + p->kill_subwindows(); + if (p->alloced) + { + if (p->w != 0) + ::delwin(p->w); + p->alloced = 0; + } + p->w = 0; // cause a run-time error if anyone attempts to use... + } +} + +CursesWindow::~CursesWindow() +{ + kill_subwindows(); + + if (par != 0) // Snip us from the parent's list of subwindows. + { + CursesWindow * win = par->subwins; + CursesWindow * trail = 0; + for (;;) + { + if (win == 0) + break; + else if (win == this) + { + if (trail != 0) + trail->sib = win->sib; + else + par->subwins = win->sib; + break; + } + else + { + trail = win; + win = win->sib; + } + } + } + + if (alloced && w != 0) + delwin(w); + + --count; + if (count == 0) + endwin(); + else if (count < 0) // cannot happen! + { + (*lib_error_handler)("CursesWindow", "Too many windows destroyed"); + } +} + +#endif /* _G_HAVE_CURSES */ diff --git a/gnu/lib/libg++/libg++/DLList.cc b/gnu/lib/libg++/libg++/DLList.cc new file mode 100644 index 0000000..87874c3 --- /dev/null +++ b/gnu/lib/libg++/libg++/DLList.cc @@ -0,0 +1,327 @@ +// 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. +*/ + +#ifndef _G_NO_TEMPLATES +#ifdef __GNUG__ +//#pragma implementation +#endif +#include <limits.h> +#include <stream.h> +#include <builtin.h> +#include "DLList.h" + +void BaseDLList::error(const char* msg) +{ + (*lib_error_handler)("DLList", msg); +} + +int BaseDLList::length() const +{ + int l = 0; + BaseDLNode* t = h; + if (t != 0) do { ++l; t = t->fd; } while (t != h); + return l; +} + +// Note: This is an internal method. It does *not* free old contents! + +void BaseDLList::copy(const BaseDLList& a) +{ + if (a.h == 0) + h = 0; + else + { + BaseDLNode* p = a.h; + BaseDLNode* t = copy_node(p->item()); + h = t; + p = p->fd; + while (p != a.h) + { + BaseDLNode* n = copy_node(p->item()); + t->fd = n; + n->bk = t; + t = n; + p = p->fd; + } + t->fd = h; + h->bk = t; + return; + } +} + +void BaseDLList::clear() +{ + if (h == 0) + return; + + BaseDLNode* p = h->fd; + h->fd = 0; + h = 0; + + while (p != 0) + { + BaseDLNode* nxt = p->fd; + delete_node(p); + p = nxt; + } +} + +BaseDLList& BaseDLList::operator = (const BaseDLList& a) +{ + if (h != a.h) + { + clear(); + copy(a); + } + return *this; +} + + +Pix BaseDLList::prepend(const void *datum) +{ + BaseDLNode* t = copy_node(datum); + if (h == 0) + t->fd = t->bk = h = t; + else + { + t->fd = h; + t->bk = h->bk; + h->bk->fd = t; + h->bk = t; + h = t; + } + return Pix(t); +} + +Pix BaseDLList::append(const void *datum) +{ + BaseDLNode* t = copy_node(datum); + if (h == 0) + t->fd = t->bk = h = t; + else + { + t->bk = h->bk; + t->bk->fd = t; + t->fd = h; + h->bk = t; + } + return Pix(t); +} + +Pix BaseDLList::ins_after(Pix p, const void *datum) +{ + if (p == 0) return prepend(datum); + BaseDLNode* u = (BaseDLNode*) p; + BaseDLNode* t = copy_node(datum); + t->bk = u; + t->fd = u->fd; + u->fd->bk = t; + u->fd = t; + return Pix(t); +} + +Pix BaseDLList::ins_before(Pix p, const void *datum) +{ + if (p == 0) error("null Pix"); + BaseDLNode* u = (BaseDLNode*) p; + BaseDLNode* t = copy_node(datum); + t->bk = u->bk; + t->fd = u; + u->bk->fd = t; + u->bk = t; + if (u == h) h = t; + return Pix(t); +} + +void BaseDLList::join(BaseDLList& b) +{ + BaseDLNode* t = b.h; + b.h = 0; + if (h == 0) + h = t; + else if (t != 0) + { + BaseDLNode* l = t->bk; + h->bk->fd = t; + t->bk = h->bk; + h->bk = l; + l->fd = h; + } +} + +int BaseDLList::owns(Pix p) +{ + BaseDLNode* t = h; + if (t != 0 && p != 0) + { + do + { + if (Pix(t) == p) return 1; + t = t->fd; + } while (t != h); + } + return 0; +} + +void BaseDLList::del(Pix& p, int dir) +{ + if (p == 0) error("null Pix"); + BaseDLNode* t = (BaseDLNode*) p; + if (t->fd == t) + { + h = 0; + p = 0; + } + else + { + if (dir < 0) + { + if (t == h) + p = 0; + else + p = Pix(t->bk); + } + else + { + if (t == h->bk) + p = 0; + else + p = Pix(t->fd); + } + t->bk->fd = t->fd; + t->fd->bk = t->bk; + if (t == h) h = t->fd; + } + delete t; +} + +void BaseDLList::del_after(Pix& p) +{ + if (p == 0) + { + del_front(); + return; + } + + BaseDLNode* b = (BaseDLNode*) p; + BaseDLNode* t = b->fd; + + if (b == t) + { + h = 0; + p = 0; + } + else + { + t->bk->fd = t->fd; + t->fd->bk = t->bk; + if (t == h) h = t->fd; + } + delete_node(t); +} + +void BaseDLList::remove_front(void *dst) +{ + if (h == 0) + error("remove_front of empty list"); + else { + BaseDLNode* t = h; + copy_item(dst, t->item()); + if (h->fd == h) + h = 0; + else + { + h->fd->bk = h->bk; + h->bk->fd = h->fd; + h = h->fd; + } + delete_node(t); + } +} + +void BaseDLList::del_front() +{ + if (h == 0) + error("del_front of empty list"); + BaseDLNode* t = h; + if (h->fd == h) + h = 0; + else + { + h->fd->bk = h->bk; + h->bk->fd = h->fd; + h = h->fd; + } + delete_node(t); +} + +void BaseDLList::remove_rear(void *dst) +{ + if (h == 0) + error("remove_rear of empty list"); + else + { + BaseDLNode* t = h->bk; + copy_item(dst, t->item()); + if (h->fd == h) + h = 0; + else + { + t->fd->bk = t->bk; + t->bk->fd = t->fd; + } + delete_node(t); + } +} + +void BaseDLList::del_rear() +{ + if (h == 0) + error("del_rear of empty list"); + BaseDLNode* t = h->bk; + if (h->fd == h) + h = 0; + else + { + t->fd->bk = t->bk; + t->bk->fd = t->fd; + } + delete_node(t); +} + + +int BaseDLList::OK() +{ + int v = 1; + if (h != 0) + { + BaseDLNode* t = h; + long count = LONG_MAX; // Lots of chances to find h! + do + { + count--; + v &= t->bk->fd == t; + v &= t->fd->bk == t; + t = t->fd; + } while (v && count > 0 && t != h); + v &= count > 0; + } + if (!v) error("invariant failure"); + return v; +} +#endif diff --git a/gnu/lib/libg++/libg++/DiscUnif.cc b/gnu/lib/libg++/libg++/DiscUnif.cc new file mode 100644 index 0000000..136ad11 --- /dev/null +++ b/gnu/lib/libg++/libg++/DiscUnif.cc @@ -0,0 +1,29 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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 <builtin.h> +#include <Random.h> +#include <DiscUnif.h> + +double DiscreteUniform::operator()() +{ + long tmp = long(floor(delta * pGenerator -> asDouble())); + return( double(pLow + tmp) ); +} + diff --git a/gnu/lib/libg++/libg++/Erlang.cc b/gnu/lib/libg++/libg++/Erlang.cc new file mode 100644 index 0000000..da3e4e7 --- /dev/null +++ b/gnu/lib/libg++/libg++/Erlang.cc @@ -0,0 +1,32 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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 <builtin.h> +#include <Random.h> +#include <Erlang.h> + +double Erlang::operator()() +{ + double prod = 1.0; + + for (int i = 0; i < k; i++) { + prod *= pGenerator -> asDouble(); + } + return(-log(prod)/a); +} diff --git a/gnu/lib/libg++/libg++/Fix.cc b/gnu/lib/libg++/libg++/Fix.cc new file mode 100644 index 0000000..f067eb3 --- /dev/null +++ b/gnu/lib/libg++/libg++/Fix.cc @@ -0,0 +1,663 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1989 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. +*/ +// +// Fix.cc : variable length fixed point data type class functions +// + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <Fix.h> +#include <std.h> +#include <Obstack.h> +#include <AllocRing.h> +#include <strstream.h> + +// member constants + +const _G_uint16_t Fix::min_length; +const _G_uint16_t Fix::max_length; +const double Fix::min_value; +const double Fix::max_value; + +// default parameters + +_G_uint16_t Fix::default_length = 16; +int Fix::default_print_width = 8; + +Fix::PEH Fix::overflow_handler = Fix::overflow_saturate; + +Fix::Rep Fix::Rep_0 = { 16, 1, 1, { 0 } }; +Fix::Rep Fix::Rep_m1 = { 16, 1, 1, { 0x8000 } }; +Fix::Rep Fix::Rep_quotient_bump = { 16, 1, 1, { 0x4000 } }; + +// error handling + +void +Fix::default_error_handler(const char* msg) +{ + cerr << "Fix: " << msg << "\n"; + abort(); +} + +void +Fix::default_range_error_handler(const char* msg) +{ + cerr << "Fix: range error in " << msg << "\n"; + //abort(); +} + +one_arg_error_handler_t + Fix::error_handler = Fix::default_error_handler, + Fix::range_error_handler = Fix::default_range_error_handler; + +one_arg_error_handler_t +Fix::set_error_handler(one_arg_error_handler_t f) +{ + one_arg_error_handler_t old = error_handler; + error_handler = f; + return old; +} + +one_arg_error_handler_t +Fix::set_range_error_handler(one_arg_error_handler_t f) +{ + one_arg_error_handler_t old = range_error_handler; + range_error_handler = f; + return old; +} + +void +Fix::error(const char* msg) +{ + error_handler(msg); +} + +void +Fix::range_error(const char* msg) +{ + range_error_handler(msg); +} + +// Fix::Rep allocation and initialization functions + +static inline Fix::Rep* +_new_Fix(_G_uint16_t len) +{ + int siz = (((_G_uint32_t) len + 15) >> 4); + if (siz <= 0) siz = 1; + unsigned int allocsiz = (sizeof(Fix::Rep) + (siz - 1) * sizeof(_G_uint16_t)); + Fix::Rep* z = (Fix::Rep*)(new char[allocsiz]); + memset(z, 0, allocsiz); + z->len = len; + z->siz = siz; + z->ref = 1; + return z; +} + +Fix::Rep* +Fix::new_Fix(_G_uint16_t len) +{ + return _new_Fix(len); +} + +Fix::Rep* +Fix::new_Fix(_G_uint16_t len, const Rep* x) +{ + Rep* z = _new_Fix(len); + return copy(x,z); +} + +Fix::Rep* +Fix::new_Fix(_G_uint16_t len, double d) +{ + Rep* z = _new_Fix(len); + + if ( d == max_value ) + { + z->s[0] = 0x7fff; + for ( int i=1; i < z->siz; i++ ) + z->s[i] = 0xffff; + } + else if ( d < min_value || d > max_value ) + range_error("declaration"); + else + { + if (d < 0) + d += 2.0; + d *= 32768; + for ( int i=0; i < z->siz; i++ ) + { + z->s[i] = (_G_uint16_t )d; + d -= z->s[i]; + d *= 65536; + } + if ( d >= 32768 ) + z->s[z->siz-1]++; + } + mask(z); + return z; +} + +// convert to a double + +double +value(const Fix& x) +{ + double d = 0.0; + for ( int i=x.rep->siz-1; i >= 0; i-- ) + { + d += x.rep->s[i]; + d *= 1./65536.; + } + d *= 2.; + return d < 1. ? d : d - 2.; +} + +// extract mantissa to Integer + +Integer +mantissa(const Fix& x) +{ + Integer a = 1, b=1; + for ( int i=0; i < x.rep->siz; i++ ) + { + a <<= 16; + a += x.rep->s[i]; + b <<= 16; + } + return a-b; +} + +// comparison functions + +inline static int +docmp(const _G_uint16_t* x, const _G_uint16_t* y, int siz) +{ + int diff = (_G_int16_t )*x - (_G_int16_t )*y; + while ( --siz && !diff ) + diff = (_G_int32_t )(_G_uint32_t )*++x - (_G_int32_t )(_G_uint32_t )*++y; + return diff; +} + +inline static int +docmpz(const _G_uint16_t* x, int siz) +{ + while ( siz-- ) + if ( *x++ ) return 1; + return 0; +} + +int +Fix::compare(const Rep* x, const Rep* y) +{ + if ( x->siz == y->siz ) + return docmp(x->s, y->s, x->siz); + else + { + int r; + const Rep* longer, *shorter; + if ( x->siz > y->siz ) + { + longer = x; + shorter = y; + r = 1; + } + else + { + longer = y; + shorter = x; + r = -1; + } + int diff = docmp(x->s, y->s, shorter->siz); + if ( diff ) + return diff; + else if ( docmpz(&longer->s[shorter->siz], longer->siz-shorter->siz) ) + return r; + else + return 0; + } +} + +// arithmetic functions + +Fix::Rep* +Fix::add(const Rep* x, const Rep* y, Rep* r) +{ + _G_uint16_t xsign = x->s[0], ysign = y->s[0]; + const Rep* longer, *shorter; + if ( x->len >= y->len ) + longer = x, shorter = y; + else + longer = y, shorter = x; + if ( r == NULL ) + r = new_Fix(longer->len); + for ( int i=r->siz-1; i >= longer->siz; i-- ) + r->s[i] = 0; + for ( ; i >= shorter->siz; i-- ) + r->s[i] = longer->s[i]; + _G_uint32_t sum = 0, carry = 0; + for ( ; i >= 0; i-- ) + { + sum = carry + (_G_uint32_t )x->s[i] + (_G_uint32_t )y->s[i]; + carry = sum >> 16; + r->s[i] = sum; + } + if ( (xsign ^ sum) & (ysign ^ sum) & 0x8000 ) + overflow_handler(r); + return r; +} + +Fix::Rep* +Fix::subtract(const Rep* x, const Rep* y, Rep* r) +{ + _G_uint16_t xsign = x->s[0], ysign = y->s[0]; + const Rep* longer, *shorter; + if ( x->len >= y->len ) + longer = x, shorter = y; + else + longer = y, shorter = x; + if ( r == NULL ) + r = new_Fix(longer->len); + for ( int i=r->siz-1; i >= longer->siz; i-- ) + r->s[i] = 0; + for ( ; i >= shorter->siz; i-- ) + r->s[i] = (longer == x ? x->s[i] : -y->s[i]); + _G_int16_t carry = 0; + _G_uint32_t sum = 0; + for ( ; i >= 0; i-- ) + { + sum = (_G_int32_t )carry + (_G_uint32_t )x->s[i] - (_G_uint32_t )y->s[i]; + carry = sum >> 16; + r->s[i] = sum; + } + if ( (xsign ^ sum) & (~ysign ^ sum) & 0x8000 ) + overflow_handler(r); + return r; +} + +Fix::Rep* +Fix::multiply(const Rep* x, const Rep* y, Rep* r) +{ + if ( r == NULL ) + r = new_Fix(x->len + y->len); + int xsign = x->s[0] & 0x8000, + ysign = y->s[0] & 0x8000; + Fix X(x->len), Y(y->len); + if ( xsign ) + x = negate(x,X.rep); + if ( ysign ) + y = negate(y,Y.rep); + for ( int i=0; i < r->siz; i++ ) + r->s[i] = 0; + for ( i=x->siz-1; i >= 0; i-- ) + { + _G_uint32_t carry = 0; + for ( int j=y->siz-1; j >= 0; j-- ) + { + int k = i + j + 1; + _G_uint32_t a = (_G_uint32_t )x->s[i] * (_G_uint32_t )y->s[j]; + _G_uint32_t b = ((a << 1) & 0xffff) + carry; + if ( k < r->siz ) + { + b += r->s[k]; + r->s[k] = b; + } + if ( k < (int)r->siz + 1 ) + carry = (a >> 15) + (b >> 16); + } + r->s[i] = carry; + } + if ( xsign != ysign ) + negate(r,r); + return r; +} + +Fix::Rep* +Fix::multiply(const Rep* x, int y, Rep* r) +{ + if ( y != (_G_int16_t )y ) + range_error("multiply by int -- int too large"); + if ( r == NULL ) + r = new_Fix(x->len); + for ( int i=r->siz-1; i >= x->siz; i-- ) + r->s[i] = 0; + _G_int32_t a, carry = 0; + for ( ; i > 0; i-- ) + { + a = (_G_int32_t) (_G_uint32_t )x->s[i] * y + carry; + r->s[i] = a; + carry = a >> 16; // assumes arithmetic right shift + } + a = (_G_int32_t) (_G_int16_t )x->s[0] * y + carry; + r->s[0] = a; + a &= 0xffff8000L; + if ( a != 0xffff8000L && a != 0L ) { + r->s[0] = 0x8000 ^ x->s[0] ^ y; + overflow_handler(r); + } + return r; +} + +Fix::Rep* +Fix::divide(const Rep* x, const Rep* y, Rep* q, Rep* r) +{ + int xsign = x->s[0] & 0x8000, + ysign = y->s[0] & 0x8000; + if ( q == NULL ) + q = new_Fix(x->len); + copy(&Rep_0,q); + if ( r == NULL ) + r = new_Fix(x->len + y->len - 1); + if ( xsign ) + negate(x,r); + else + copy(x,r); + Fix Y(y->len); + Rep* y2 = ( ysign ? negate(y,Y.rep) : copy(y,Y.rep) ); + if ( !compare(y2) ) + range_error("division -- division by zero"); + else if ( compare(x,y2) >= 0 ) + if ( compare(x,y2) == 0 && (xsign ^ ysign) != 0 ) + { + copy(&Rep_m1,q); + copy(&Rep_0,r); + } + else + range_error("division"); + else + { + Rep* t; + Fix S(r->len), + W(q->len,&Rep_quotient_bump); + for ( int i=1; i < q->len; i++ ) + { + shift(y2,-1,y2); + subtract(r,y2,S.rep); + int s_status = compare(S.rep); + if ( s_status == 0 ) + { + t = r, r = S.rep, S.rep = t; + break; + } + else if ( s_status > 0 ) + { + t = r, r = S.rep, S.rep = t; + add(q,W.rep,q); + } + shift(W.rep,-1,W.rep); + } + if ( xsign ^ ysign ) + negate(q,q); + } + return q; +} + +Fix::Rep* +Fix::shift(const Rep* x, int y, Rep* r) +{ + if ( r == NULL ) + r = new_Fix(x->len); + if ( y == 0 ) + { + copy (x, r); + return r; + } + + int ay = abs((long) y), + ayh = ay >> 4, + ayl = ay & 0x0f; + int xl, u, ilow, ihigh; + _G_uint16_t *rs; + const _G_uint16_t *xsl, *xsr; + + if ( y > 0 ) + { + rs = r->s; + xsl = x->s + ayh; + xsr = xsl + 1; + xl = ayl; + u = 1; + ihigh = x->siz - ayh - 1; + ilow = 0; + } + else + { + rs = &r->s[r->siz - 1]; + xsr = &x->s[r->siz - 1] - ayh; + xsl = xsr - 1; + xl = 16 - ayl; + u = -1; + ihigh = r->siz - ayh - 1; + ilow = ihigh - x->siz; + } + + int xr = 16 - xl; + _G_uint16_t xrmask = 0xffffL >> xr; + for ( int i=0; i < ilow; i++, rs+=u, xsl+=u, xsr+=u ) + *rs = 0; + for ( ; i < ihigh; i++, rs+=u, xsl+=u, xsr+=u ) + *rs = (*xsl << xl) + ((*xsr >> xr) & xrmask); + *rs = (y > 0 ? (*xsl << xl) : ((*xsr >> xr) & xrmask)); + rs += u; + for ( ; ++i < r->siz; rs+=u ) + *rs = 0; + return r; +} + +Fix::Rep* +Fix::negate(const Rep* x, Rep* r) +{ + if ( r == NULL ) + r = new_Fix(x->len); + _G_uint32_t carry = 1; + for ( int i=r->siz-1; i >= x->siz; i-- ) + r->s[i] = 0; + for ( ; i >= 0; i-- ) + { + _G_uint32_t a = (_G_uint16_t )~x->s[i] + carry; // bug work-around + r->s[i] = a; + carry = a >> 16; + } + return r; +} + +// io functions + +Fix +atoF(const char* a, int len) +{ + return Fix(len,atof(a)); +} + +extern AllocRing _libgxx_fmtq; + +void +Fix::printon(ostream& s, int width) const +{ + double val = value(*this); + int old_precision = s.precision(width-3); + long old_flags = s.setf(ios::fixed, ios::fixed|ios::scientific); + if (val >= 0) + s << ' '; + s.width(width-2); + s << val; + s.precision(old_precision); + s.flags(old_flags); +} + +char* +Ftoa(Fix& x, int width) +{ + int wrksiz = width + 2; + char *fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); + ostrstream stream(fmtbase, wrksiz); + + x.printon(stream, width); + stream << ends; + return fmtbase; +} + +extern Obstack _libgxx_io_ob; + +Fix +Fix::operator %= (int y) +{ + Fix r((int )rep->len + y, *this); return *this = r; +} + +istream& +operator >> (istream& s, Fix& y) +{ + int got_one = 0; + if (!s.ipfx(0)) + { + s.clear(ios::failbit|s.rdstate()); // Redundant if using GNU iostreams. + return s; + } + + char sign = 0, point = 0; + char ch; + s >> ws; + if (!s.good()) + { + s.clear(ios::failbit|s.rdstate()); + return s; + } + while (s.get(ch)) + { + if (ch == '-') + { + if (sign == 0) + { + sign = 1; + _libgxx_io_ob.grow(ch); + } + else + break; + } + if (ch == '.') + { + if (point == 0) + { + point = 1; + _libgxx_io_ob.grow(ch); + } + else + break; + } + else if (ch >= '0' && ch <= '9') + { + got_one = 1; + _libgxx_io_ob.grow(ch); + } + else + break; + } + char * p = (char*)(_libgxx_io_ob.finish(0)); + if (s.good()) + s.putback(ch); + if (!got_one) + s.clear(ios::failbit|s.rdstate()); + else + y = atoF(p); + _libgxx_io_ob.free(p); + return s; +} + +void +show(const Fix& x) +{ + cout << "len = " << x.rep->len << "\n"; + cout << "siz = " << x.rep->siz << "\n"; + cout << "ref = " << x.rep->ref << "\n"; + cout << "man = "; +#ifdef _OLD_STREAMS + cout << Itoa(mantissa(x),16,4*x.rep->siz); +#else + int old_flags = cout.setf(ios::hex, ios::hex|ios::dec|ios::oct); + cout.width(4*x.rep->siz); + cout << mantissa(x); + cout.setf(old_flags, ios::hex|ios::dec|ios::oct); +#endif + cout << "\n"; + cout << "val = " << value(x) << "\n"; +} + +// parameter setting operations + +Fix::PEH Fix::set_overflow_handler(PEH new_handler) +{ + PEH old_handler = overflow_handler; + overflow_handler = new_handler; + return old_handler; +} + +int +Fix::set_default_length(int newlen) +{ + _G_uint16_t oldlen = default_length; + if ( newlen < min_length || newlen > max_length ) + error("illegal length in Fix::set_default_length"); + default_length = newlen; + return oldlen; +} + +// overflow handlers + +void +Fix::overflow_saturate(Rep* r) +{ + if ( (_G_int16_t) r->s[0] > 0 ) + { + r->s[0] = 0x8000; + for ( int i=1; i < r->siz; i++ ) + r->s[i] = 0; + } + else + { + r->s[0] = 0x7fff; + for ( int i = 1; i < (int)r->siz; i++ ) + r->s[i] = 0xffff; + mask(r); + } +} + +void +Fix::overflow_wrap(Rep*) +{} + +void +Fix::overflow_warning_saturate(Rep* r) +{ + overflow_warning(r); + overflow_saturate(r); +} + +void +Fix::overflow_warning(Rep*) +{ + cerr << "Fix: overflow warning\n"; +} + +void +Fix::overflow_error(Rep*) +{ + cerr << "Fix: overflow error\n"; + abort(); +} diff --git a/gnu/lib/libg++/libg++/Fix16.cc b/gnu/lib/libg++/libg++/Fix16.cc new file mode 100644 index 0000000..a66bfbf --- /dev/null +++ b/gnu/lib/libg++/libg++/Fix16.cc @@ -0,0 +1,238 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Kurt Baudendistel (gt-eedsp!baud@gatech.edu) + adapted for libg++ 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. +*/ + +// +// Fix.cc : fixed precision class support functions +// + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <Fix16.h> + +// basic operators too large to be inline + +short Fix16::assign(double d) +{ + if (d == 1.0) + return Fix16_m_max; + else if (d > Fix16_max) + { + short i = Fix16_m_max; + range_error(i); + return i; + } + else if (d < Fix16_min) + { + short i = Fix16_m_min; + range_error(i); + return i; + } + else + return round(Fix16_mult * d); +} + +long Fix32::assign(double d) +{ + if (d == 1.0) + return Fix32_m_max; + else if (d > Fix32_max) + { + long i = Fix32_m_max; + range_error(i); + return i; + } + else if (d < Fix32_min) + { + long i = Fix32_m_min; + range_error(i); + return i; + } + else + return round(Fix32_mult * d); +} + + +Fix32 operator * (const Fix32& a, const Fix32& b) +{ +// break a and b into lo and hi parts, and do a multiple-precision +// multiply, with rounding + + int apos = (a.m >= 0); + unsigned long ua = (apos)? a.m : - a.m; + ua <<= 1; // ua is biased so result will be 31 bit mantissa, not 30: + unsigned long hi_a = (ua >> 16) & ((1 << 16) - 1); + unsigned long lo_a = ua & ((1 << 16) - 1); + + int bpos = (b.m >= 0); + unsigned long ub = (bpos)? b.m : -b.m; + unsigned long hi_b = (ub >> 16) & ((1 << 16) - 1); + unsigned long lo_b = ub & ((1 << 16) - 1); + + unsigned long r = lo_a * lo_b + (1 << 15); + r = (r >> 16) + hi_a * lo_b + lo_a * hi_b + (1 << 15); + r = (r >> 16) + hi_a * hi_b; + long p = (apos != bpos)? -r : r; + return Fix32(p); +} + +Fix16 operator / (const Fix16& a, const Fix16& b) +{ + short q; + int apos = (a.m >= 0); + long la = (apos)? a.m : -a.m; + long scaled_a = la << 15; + int bpos = (b.m >= 0); + short sb = (bpos)? b.m: -b.m; + if (la >= sb) + { + q = (apos == bpos)? Fix16_m_max: Fix16_m_min; + a.range_error(q); + } + else + { + q = scaled_a / sb; + if ((scaled_a % sb) >= (sb / 2)) ++q; + if (apos != bpos) q = -q; + } + return Fix16(q); +} + +Fix32 operator / (const Fix32& a, const Fix32& b) +{ + long q; + int apos = (a.m >= 0); + unsigned long la = (apos)? a.m : -a.m; + int bpos = (b.m >= 0); + unsigned long lb = (bpos)? b.m: -b.m; + if (la >= lb) + { + q = (apos == bpos)? Fix32_m_max: Fix32_m_min; + a.range_error(q); + } + else // standard shift-based division alg + { + q = 0; + long r = la; + + for (int i = 32; i > 0; i--) + { + if ((unsigned)(r) > lb) { + q = (q << 1) | 1; + r -= lb; + } + else + q = (q << 1); + r <<= 1; + } + + if (apos != bpos) q = -q; // Fix sign + } + return Fix32(q); +} + + +// error handling + +void Fix16::overflow(short& i) const +{ + (*Fix16_overflow_handler)(i); +} + +void Fix32::overflow(long& i) const +{ + (*Fix32_overflow_handler)(i); +} + +void Fix16::range_error(short& i) const +{ + (*Fix16_range_error_handler)(i); +} + +void Fix32::range_error(long& i) const +{ + (*Fix32_range_error_handler)(i); +} + +// data definitions + +Fix16_peh Fix16_overflow_handler = Fix16_overflow_saturate; +Fix32_peh Fix32_overflow_handler = Fix32_overflow_saturate; + +Fix16_peh Fix16_range_error_handler = Fix16_warning; +Fix32_peh Fix32_range_error_handler = Fix32_warning; + +//function definitions + +Fix16_peh set_Fix16_overflow_handler(Fix16_peh new_handler) { + Fix16_peh old_handler = Fix16_overflow_handler; + Fix16_overflow_handler = new_handler; + return old_handler; +} + +Fix32_peh set_Fix32_overflow_handler(Fix32_peh new_handler) { + Fix32_peh old_handler = Fix32_overflow_handler; + Fix32_overflow_handler = new_handler; + return old_handler; +} + +void set_overflow_handler(Fix16_peh handler16, Fix32_peh handler32) { + set_Fix16_overflow_handler(handler16); + set_Fix32_overflow_handler(handler32); +} + +Fix16_peh set_Fix16_range_error_handler(Fix16_peh new_handler) { + Fix16_peh old_handler = Fix16_range_error_handler; + Fix16_range_error_handler = new_handler; + return old_handler; +} + +Fix32_peh set_Fix32_range_error_handler(Fix32_peh new_handler) { + Fix32_peh old_handler = Fix32_range_error_handler; + Fix32_range_error_handler = new_handler; + return old_handler; +} + +void set_range_error_handler(Fix16_peh handler16, Fix32_peh handler32) { + set_Fix16_range_error_handler(handler16); + set_Fix32_range_error_handler(handler32); +} + +void Fix16_overflow_saturate(short& i) + { i = (i > 0 ? Fix16_m_min : Fix16_m_max); } +void Fix16_ignore(short&) {} +void Fix16_warning(short&) + { cerr << "warning: Fix16 result out of range\n"; } +void Fix16_overflow_warning_saturate(short& i) + { cerr << "warning: Fix16 result out of range\n"; + Fix16_overflow_saturate(i); } +void Fix16_abort(short&) + { cerr << "error: Fix16 result out of range\n"; abort(); } + +void Fix32_ignore(long&) {} +void Fix32_overflow_saturate(long& i) + { i = (i > 0 ? Fix32_m_min : Fix32_m_max); } +void Fix32_warning(long&) + { cerr << "warning: Fix32 result out of range\n"; } +void Fix32_overflow_warning_saturate(long& i) + { cerr << "warning: Fix32 result out of range\n"; + Fix32_overflow_saturate(i); } +void Fix32_abort(long&) + { cerr << "error: Fix32 result out of range\n"; abort(); } + diff --git a/gnu/lib/libg++/libg++/Fix24.cc b/gnu/lib/libg++/libg++/Fix24.cc new file mode 100644 index 0000000..22e23dc --- /dev/null +++ b/gnu/lib/libg++/libg++/Fix24.cc @@ -0,0 +1,327 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Kurt Baudendistel (gt-eedsp!baud@gatech.edu) + adapted for libg++ 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. +*/ + +// +// Fix24.cc : fixed precision class support functions +// + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <Fix24.h> + +// basic operators too large to be inline + +long Fix24::assign(double d) +{ + if (d == 1.0) + return Fix24_m_max; + else if (d > Fix24_max) + { + long i = Fix24_m_max; + range_error(i); + return i; + } + else if (d < Fix24_min) + { + long i = Fix24_m_min; + range_error(i); + return i; + } + else { + d = (long) (d * (1 << 24) + ((d >= 0)? 0.5 : -0.5)); // Round to 24 bits + return ((long) d) << (Fix24_shift - 24); /* Convert to integer format */ + } +} + +twolongs Fix48::assign(double d) +{ + if (d == 1.0) + return Fix48_m_max; + else if (d > Fix48_max) + { + twolongs i = Fix48_m_max; + range_error(i); + return i; + } + else if (d < Fix48_min) + { + twolongs i = Fix48_m_min; + range_error(i); + return i; + } + else { + twolongs i; + int sign = (d < 0); + +/* First, convert the absolute value of d to a 48-bit integer format */ + if (d < 0) d = -d; + i.u = ((long)(d *= Fix24_mult)) & 0xffffff00; + i.l = ((unsigned long)((d - i.u)* (Fix24_mult / (1 << 7)))) & 0xffffff00; + +/* Calculate the two's complement if d was negative */ + if (sign) { + unsigned long oldlower = i.l; + i.l = (~i.l + 1) & 0xffffff00; + i.u = (~i.u + (((oldlower ^ i.l) & Fix24_msb)? 0 : 1)) & 0xffffff00; + } + return i; + } +} + + +Fix48 operator * (const Fix24& a, const Fix24& b) +{ +// break a and b into lo and hi parts, and do a multiple-precision +// multiply, with rounding + + int apos = (a.m >= 0); + unsigned long ua = (apos)? a.m : - a.m; + ua <<= 1; // ua is biased so result will be 47 bit mantissa, not 46: + unsigned long hi_a = (ua >> 16) & ((1 << 16) - 1); + unsigned long lo_a = ua & ((1 << 16) - 1); + + int bpos = (b.m >= 0); + unsigned long ub = (bpos)? b.m : -b.m; + unsigned long hi_b = (ub >> 16) & ((1 << 16) - 1); + unsigned long lo_b = ub & ((1 << 16) - 1); + + unsigned long + hi_r = hi_a * hi_b, + mi_r = hi_a * lo_b + lo_a * hi_b, + lo_r = lo_a * lo_b, + rl = ((hi_r << 16) & 0x00ffffffL) + (mi_r & 0x00ffffffL) + (lo_r >> 16); + twolongs r; + r.u = (hi_r & 0xffffff00L) + ((mi_r >> 16) & 0x0000ff00L) + + ((rl >> 16) & 0x0000ff00L); + r.l = rl << 8; + + if ( apos != bpos ) { + unsigned long l = r.l; + r.l = -r.l; + r.u = (~r.u + ((l ^ r.l) & Fix24_msb ? 0 : Fix24_lsb)) & 0xffffff00; + } + return r; +} + +Fix24 operator / (const Fix24& a, const Fix24& b) +{ + long q; + int apos = (a.m >= 0); + unsigned long la = (apos)? a.m : -a.m; + int bpos = (b.m >= 0); + unsigned long lb = (bpos)? b.m: -b.m; + if (la >= lb) + { + q = (apos == bpos)? Fix24_m_max: Fix24_m_min; + a.range_error(q); + } + else // standard shift-based division alg + { + q = 0; + long r = la; + + for (int i = 32; i > 0; i--) + { + if ((unsigned)(r) > lb) { + q = (q << 1) | 1; + r -= lb; + } + else + q = (q << 1); + r <<= 1; + } + + q += 0x80; // Round result to 24 bits + if (apos != bpos) q = -q; // Fix sign + } + return (q & ~0xFF); +} + + +Fix48 operator + (const Fix48& f, const Fix48& g) +{ + long lo_r = (f.m.l >> 8) + (g.m.l >> 8); + twolongs r; + r.u = f.m.u + g.m.u + (lo_r & 0x01000000L ? 0x00000100L : 0); + r.l = lo_r << 8; + + if ( (f.m.u ^ r.u) & (g.m.u ^ r.u) & Fix24_msb ) + f.overflow(r); + return r; +} + +Fix48 operator - (const Fix48& f, const Fix48& g) +{ + unsigned lo_r = (f.m.l >> 8) - (g.m.l >> 8); + twolongs r; + r.u = f.m.u - g.m.u - (lo_r & 0x01000000L ? 0x00000100L: 0); + r.l = lo_r << 8; + + if ( ((f.m.u ^ r.u) & (-g.m.u ^ r.u) & Fix24_msb) && g.m.u ) + f.overflow(r); + return r; +} + +Fix48 operator * (const Fix48& a, int b) +{ + twolongs r; + int bpos = (b >= 0); + unsigned ub = (bpos)? b : -b; + if ( ub >= 65536L ) { + r = (bpos)? Fix48_m_max : Fix48_m_min; + a.range_error(r); + } + else { + unsigned long + lo_r = (a.m.l & 0xffff) * ub, + mi_r = ((a.m.l >> 16) & 0xffff) * ub, + hi_r = a.m.u * ub; + r.l = lo_r + (mi_r << 16); + r.u = hi_r + ((mi_r >> 8) & 0x00ffff00L); + if ( !bpos ) { + unsigned long l = r.l; + r.l = -r.l; + r.u = ~r.u + ((l ^ r.l) & Fix24_msb ? 0 : Fix24_lsb); + } + } + return r; +} + +Fix48 operator << (const Fix48& a, int b) +{ + twolongs r; r.u = 0; r.l = 0; + if ( b >= 0 ) + if ( b < 24 ) { + r.u = (a.m.u << b) + ((a.m.l >> (24 - b)) & 0xffffff00L); + r.l = a.m.l << b; + } + else if ( b < 48 ) { + r.u = a.m.l << (b - 24); + } + return r; +} + +Fix48 operator >> (const Fix48& a, int b) +{ + twolongs r; r.u = 0; r.l = 0; + if ( b >= 0 ) + if ( b < 24 ) { + r.l = (a.m.u << (24 - b)) + ((a.m.l >> b) & 0xffffff00L); + r.u = (a.m.u >> b) & 0xffffff00L; + } + else if ( b < 48 ) { + r.l = (a.m.u >> (b - 24)) & 0xffffff00L; + r.u = (a.m.u >> 24) & 0xffffff00L; + } + else { + r.l = (a.m.u >> 24) & 0xffffff00L; + r.u = r.l; + } + return r; +} + +// error handling + +void Fix24::overflow(long& i) const +{ + (*Fix24_overflow_handler)(i); +} + +void Fix48::overflow(twolongs& i) const +{ + (*Fix48_overflow_handler)(i); +} + +void Fix24::range_error(long& i) const +{ + (*Fix24_range_error_handler)(i); +} + +void Fix48::range_error(twolongs& i) const +{ + (*Fix48_range_error_handler)(i); +} + +// data definitions + +Fix24_peh Fix24_overflow_handler = Fix24_overflow_saturate; +Fix48_peh Fix48_overflow_handler = Fix48_overflow_saturate; + +Fix24_peh Fix24_range_error_handler = Fix24_warning; +Fix48_peh Fix48_range_error_handler = Fix48_warning; + +//function definitions + +Fix24_peh set_Fix24_overflow_handler(Fix24_peh new_handler) { + Fix24_peh old_handler = Fix24_overflow_handler; + Fix24_overflow_handler = new_handler; + return old_handler; +} + +Fix48_peh set_Fix48_overflow_handler(Fix48_peh new_handler) { + Fix48_peh old_handler = Fix48_overflow_handler; + Fix48_overflow_handler = new_handler; + return old_handler; +} + +void set_overflow_handler(Fix24_peh handler24, Fix48_peh handler48) { + set_Fix24_overflow_handler(handler24); + set_Fix48_overflow_handler(handler48); +} + +Fix24_peh set_Fix24_range_error_handler(Fix24_peh new_handler) { + Fix24_peh old_handler = Fix24_range_error_handler; + Fix24_range_error_handler = new_handler; + return old_handler; +} + +Fix48_peh set_Fix48_range_error_handler(Fix48_peh new_handler) { + Fix48_peh old_handler = Fix48_range_error_handler; + Fix48_range_error_handler = new_handler; + return old_handler; +} + +void set_range_error_handler(Fix24_peh handler24, Fix48_peh handler48) { + set_Fix24_range_error_handler(handler24); + set_Fix48_range_error_handler(handler48); +} + +void Fix24_overflow_saturate(long& i) + { i = (i > 0 ? Fix24_m_min : Fix24_m_max); } +void Fix24_ignore(long&) {} +void Fix24_warning(long&) + { cerr << "warning: Fix24 result out of range\n"; } +void Fix24_overflow_warning_saturate(long& i) + { cerr << "warning: Fix24 result out of range\n"; + Fix24_overflow_saturate(i); } +void Fix24_abort(long&) + { cerr << "error: Fix24 result out of range\n"; abort(); } + +void Fix48_ignore(twolongs&) {} +void Fix48_overflow_saturate(twolongs& i) + { i = (i.u > 0 ? Fix48_m_min : Fix48_m_max); } +void Fix48_warning(twolongs&) + { cerr << "warning: Fix48 result out of range\n"; } +void Fix48_overflow_warning_saturate(twolongs& i) + { cerr << "warning: Fix48 result out of range\n"; + Fix48_overflow_saturate(i); } +void Fix48_abort(twolongs&) + { cerr << "error: Fix48 result out of range\n"; abort(); } + diff --git a/gnu/lib/libg++/libg++/Geom.cc b/gnu/lib/libg++/libg++/Geom.cc new file mode 100644 index 0000000..0353738 --- /dev/null +++ b/gnu/lib/libg++/libg++/Geom.cc @@ -0,0 +1,30 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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 <builtin.h> +#include <Random.h> +#include <Geom.h> + +double Geometric::operator()() +{ + int samples; + for (samples = 1; pGenerator -> asDouble() < pMean; samples++); + return((double) samples); +} + diff --git a/gnu/lib/libg++/libg++/GetOpt.cc b/gnu/lib/libg++/libg++/GetOpt.cc new file mode 100644 index 0000000..16c647d --- /dev/null +++ b/gnu/lib/libg++/libg++/GetOpt.cc @@ -0,0 +1,253 @@ +/* +Getopt for GNU. +Copyright (C) 1987, 1989 Free Software Foundation, Inc. + +(Modified by Douglas C. Schmidt for use with GNU G++.) +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 +/* AIX requires the alloca decl to be the first thing in the file. */ +#ifdef __GNUC__ +#define alloca __builtin_alloca +#elif defined(sparc) +#include <alloca.h> +extern "C" void *__builtin_alloca(...); +#elif defined(_AIX) +#pragma alloca +#else +char *alloca (); +#endif +#include <GetOpt.h> + +char* GetOpt::nextchar = 0; +int GetOpt::first_nonopt = 0; +int GetOpt::last_nonopt = 0; + +GetOpt::GetOpt (int argc, char **argv, const char *optstring) + :opterr (1), nargc (argc), nargv (argv), noptstring (optstring) +{ + /* Initialize the internal data when the first call is made. + Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind = 1; + optarg = nextchar = 0; + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + ordering = RETURN_IN_ORDER; + else if (getenv ("_POSIX_OPTION_ORDER") != 0) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; +} + +void +GetOpt::exchange (char **argv) +{ + int nonopts_size + = (last_nonopt - first_nonopt) * sizeof (char *); + char **temp = (char **) alloca (nonopts_size); + + /* Interchange the two blocks of data in argv. */ + + memcpy (temp, &argv[first_nonopt], nonopts_size); + memcpy (&argv[first_nonopt], &argv[last_nonopt], + (optind - last_nonopt) * sizeof (char *)); + memcpy (&argv[first_nonopt + optind - last_nonopt], temp, + nonopts_size); + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of theoption characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + A colon in OPTSTRING means that the previous character is an option + that wants an argument. The argument is taken from the rest of the + current ARGV-element, or from the following ARGV-element, + and returned in `optarg'. + + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg'. + + If OPTSTRING starts with `-', it requests a different method of handling the + non-option ARGV-elements. See the comments about RETURN_IN_ORDER, above. */ + +int +GetOpt::operator () (void) +{ + if (nextchar == 0 || *nextchar == 0) + { + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange (nargv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Now skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < nargc + && (nargv[optind][0] != '-' + || nargv[optind][1] == 0)) + optind++; + last_nonopt = optind; + } + + /* Special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != nargc && !strcmp (nargv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange (nargv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = nargc; + + optind = nargc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == nargc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (nargv[optind][0] != '-' || nargv[optind][1] == 0) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = nargv[optind++]; + return 0; + } + + /* We have found another option-ARGV-element. + Start decoding its characters. */ + + nextchar = nargv[optind] + 1; + } + + /* Look at and handle the next option-character. */ + + { + char c = *nextchar++; + char *temp = (char *) strchr (noptstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == 0) + optind++; + + if (temp == 0 || c == ':') + { + if (opterr != 0) + { + if (c < 040 || c >= 0177) + fprintf (stderr, "%s: unrecognized option, character code 0%o\n", + nargv[0], c); + else + fprintf (stderr, "%s: unrecognized option `-%c'\n", + nargv[0], c); + } + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != 0) + { + optarg = nextchar; + optind++; + } + else + optarg = 0; + nextchar = 0; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != 0) + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == nargc) + { + if (opterr != 0) + fprintf (stderr, "%s: no argument for `-%c' option\n", + nargv[0], c); + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = nargv[optind++]; + nextchar = 0; + } + } + return c; + } +} diff --git a/gnu/lib/libg++/libg++/HypGeom.cc b/gnu/lib/libg++/libg++/HypGeom.cc new file mode 100644 index 0000000..50d9586 --- /dev/null +++ b/gnu/lib/libg++/libg++/HypGeom.cc @@ -0,0 +1,30 @@ + +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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 <builtin.h> +#include <Random.h> +#include <HypGeom.h> + +double HyperGeometric::operator()() +{ + double d = (pGenerator -> asDouble() > pP) ? (1.0 - pP) : (pP); + return(-pMean * log(pGenerator -> asDouble()) / (2.0 * d) ); +} + diff --git a/gnu/lib/libg++/libg++/Intdouble.cc b/gnu/lib/libg++/libg++/Intdouble.cc new file mode 100644 index 0000000..8db9061 --- /dev/null +++ b/gnu/lib/libg++/libg++/Intdouble.cc @@ -0,0 +1,142 @@ +/* +Copyright (C) 1988, 1993 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. +*/ + +// Routines for converting between Integers and doubles. +// Split up into a separate file to avoid Integer.o's need +// for libm.a on some systems (including SunOS 4). + +#include <Integer.h> +#include "Integer.hP" +#include <float.h> +#include <math.h> +#include <limits.h> + +#ifndef HUGE_VAL +#ifdef HUGE +#define HUGE_VAL HUGE +#else +#define HUGE_VAL DBL_MAX +#endif +#endif + +// convert to a double + +double Itodouble(const IntRep* rep) +{ + double d = 0.0; + double bound = DBL_MAX / 2.0; + for (int i = rep->len - 1; i >= 0; --i) + { + unsigned short a = I_RADIX >> 1; + while (a != 0) + { + if (d >= bound) + return (rep->sgn == I_NEGATIVE) ? -HUGE_VAL : HUGE_VAL; + d *= 2.0; + if (rep->s[i] & a) + d += 1.0; + a >>= 1; + } + } + if (rep->sgn == I_NEGATIVE) + return -d; + else + return d; +} + +// see whether op double() will work- +// have to actually try it in order to find out +// since otherwise might trigger fp exception + +int Iisdouble(const IntRep* rep) +{ + double d = 0.0; + double bound = DBL_MAX / 2.0; + for (int i = rep->len - 1; i >= 0; --i) + { + unsigned short a = I_RADIX >> 1; + while (a != 0) + { + if (d > bound || (d == bound && (i > 0 || (rep->s[i] & a)))) + return 0; + d *= 2.0; + if (rep->s[i] & a) + d += 1.0; + a >>= 1; + } + } + return 1; +} + +// real division of num / den + +double ratio(const Integer& num, const Integer& den) +{ + Integer q, r; + divide(num, den, q, r); + double d1 = q.as_double(); + + if (d1 >= DBL_MAX || d1 <= -DBL_MAX || sign(r) == 0) + return d1; + else // use as much precision as available for fractional part + { + double d2 = 0.0; + double d3 = 0.0; + int cont = 1; + for (int i = den.rep->len - 1; i >= 0 && cont; --i) + { + unsigned short a = I_RADIX >> 1; + while (a != 0) + { + if (d2 + 1.0 == d2) // out of precision when we get here + { + cont = 0; + break; + } + + d2 *= 2.0; + if (den.rep->s[i] & a) + d2 += 1.0; + + if (i < r.rep->len) + { + d3 *= 2.0; + if (r.rep->s[i] & a) + d3 += 1.0; + } + + a >>= 1; + } + } + + if (sign(r) < 0) + d3 = -d3; + return d1 + d3 / d2; + } +} + +double +Integer::as_double () const +{ + return Itodouble (rep); +} + +int +Integer::fits_in_double () const +{ + return Iisdouble(rep); +} diff --git a/gnu/lib/libg++/libg++/Integer.cc b/gnu/lib/libg++/libg++/Integer.cc new file mode 100644 index 0000000..5f11e6d --- /dev/null +++ b/gnu/lib/libg++/libg++/Integer.cc @@ -0,0 +1,2280 @@ +/* +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. +*/ + +/* + Some of the following algorithms are very loosely based on those from + MIT C-Scheme bignum.c, which is + Copyright (c) 1987 Massachusetts Institute of Technology + + with other guidance from Knuth, vol. 2 + + Thanks to the creators of the algorithms. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <Integer.h> +#include <std.h> +#include <ctype.h> +#include <limits.h> +#include <Obstack.h> +#include <AllocRing.h> +#include <new.h> +#include <builtin.h> +#include "Integer.hP" + +IntRep _ZeroRep = {1, 0, 1, {0}}; +IntRep _OneRep = {1, 0, 1, {1}}; +IntRep _MinusOneRep = {1, 0, 0, {1}}; + + +// utilities to extract and transfer bits + +// get low bits + +inline static unsigned short extract(unsigned long x) +{ + return x & I_MAXNUM; +} + +// transfer high bits to low + +inline static unsigned long down(unsigned long x) +{ + return (x >> I_SHIFT) & I_MAXNUM; +} + +// transfer low bits to high + +inline static unsigned long up(unsigned long x) +{ + return x << I_SHIFT; +} + +// compare two equal-length reps + +inline static int docmp(const unsigned short* x, const unsigned short* y, int l) +{ + int diff = 0; + const unsigned short* xs = &(x[l]); + const unsigned short* ys = &(y[l]); + while (l-- > 0 && (diff = (*--xs) - (*--ys)) == 0); + return diff; +} + +// figure out max length of result of +, -, etc. + +inline static int calc_len(int len1, int len2, int pad) +{ + return (len1 >= len2)? len1 + pad : len2 + pad; +} + +// ensure len & sgn are correct + +inline static void Icheck(IntRep* rep) +{ + int l = rep->len; + const unsigned short* p = &(rep->s[l]); + while (l > 0 && *--p == 0) --l; + if ((rep->len = l) == 0) rep->sgn = I_POSITIVE; +} + + +// zero out the end of a rep + +inline static void Iclear_from(IntRep* rep, int p) +{ + unsigned short* cp = &(rep->s[p]); + const unsigned short* cf = &(rep->s[rep->len]); + while(cp < cf) *cp++ = 0; +} + +// copy parts of a rep + +static inline void scpy(const unsigned short* src, unsigned short* dest,int nb) +{ + while (--nb >= 0) *dest++ = *src++; +} + +// make sure an argument is valid + +static inline void nonnil(const IntRep* rep) +{ + if (rep == 0) + (*lib_error_handler)("Integer", "operation on uninitialized Integer"); +} + +// allocate a new Irep. Pad to something close to a power of two. + +inline static IntRep* Inew(int newlen) +{ + unsigned int siz = sizeof(IntRep) + newlen * sizeof(short) + + MALLOC_MIN_OVERHEAD; + unsigned int allocsiz = MINIntRep_SIZE; + while (allocsiz < siz) allocsiz <<= 1; // find a power of 2 + allocsiz -= MALLOC_MIN_OVERHEAD; + if (allocsiz >= MAXIntRep_SIZE * sizeof(short)) + (*lib_error_handler)("Integer", "Requested length out of range"); + + IntRep* rep = (IntRep *) new char[allocsiz]; + rep->sz = (allocsiz - sizeof(IntRep) + sizeof(short)) / sizeof(short); + return rep; +} + +// allocate: use the bits in src if non-null, clear the rest + +IntRep* Ialloc(IntRep* old, const unsigned short* src, int srclen, int newsgn, + int newlen) +{ + IntRep* rep; + if (old == 0 || newlen > old->sz) + rep = Inew(newlen); + else + rep = old; + + rep->len = newlen; + rep->sgn = newsgn; + + scpy(src, rep->s, srclen); + Iclear_from(rep, srclen); + + if (old != rep && old != 0 && !STATIC_IntRep(old)) delete old; + return rep; +} + +// allocate and clear + +IntRep* Icalloc(IntRep* old, int newlen) +{ + IntRep* rep; + if (old == 0 || newlen > old->sz) + { + if (old != 0 && !STATIC_IntRep(old)) delete old; + rep = Inew(newlen); + } + else + rep = old; + + rep->len = newlen; + rep->sgn = I_POSITIVE; + Iclear_from(rep, 0); + + return rep; +} + +// reallocate + +IntRep* Iresize(IntRep* old, int newlen) +{ + IntRep* rep; + unsigned short oldlen; + if (old == 0) + { + oldlen = 0; + rep = Inew(newlen); + rep->sgn = I_POSITIVE; + } + else + { + oldlen = old->len; + if (newlen > old->sz) + { + rep = Inew(newlen); + scpy(old->s, rep->s, oldlen); + rep->sgn = old->sgn; + if (!STATIC_IntRep(old)) delete old; + } + else + rep = old; + } + + rep->len = newlen; + Iclear_from(rep, oldlen); + + return rep; +} + + +// same, for straight copy + +IntRep* Icopy(IntRep* old, const IntRep* src) +{ + if (old == src) return old; + IntRep* rep; + if (src == 0) + { + if (old == 0) + rep = Inew(0); + else + { + rep = old; + Iclear_from(rep, 0); + } + rep->len = 0; + rep->sgn = I_POSITIVE; + } + else + { + int newlen = src->len; + if (old == 0 || newlen > old->sz) + { + if (old != 0 && !STATIC_IntRep(old)) delete old; + rep = Inew(newlen); + } + else + rep = old; + + rep->len = newlen; + rep->sgn = src->sgn; + + scpy(src->s, rep->s, newlen); + } + + return rep; +} + +// allocate & copy space for a long + +IntRep* Icopy_long(IntRep* old, long x) +{ + int newsgn = (x >= 0); + IntRep* rep = Icopy_ulong(old, newsgn ? x : -x); + rep->sgn = newsgn; + return rep; +} + +IntRep* Icopy_ulong(IntRep* old, unsigned long x) +{ + unsigned short src[SHORT_PER_LONG]; + + unsigned short srclen = 0; + while (x != 0) + { + src[srclen++] = extract(x); + x = down(x); + } + + IntRep* rep; + if (old == 0 || srclen > old->sz) + { + if (old != 0 && !STATIC_IntRep(old)) delete old; + rep = Inew(srclen); + } + else + rep = old; + + rep->len = srclen; + rep->sgn = I_POSITIVE; + + scpy(src, rep->s, srclen); + + return rep; +} + +// special case for zero -- it's worth it! + +IntRep* Icopy_zero(IntRep* old) +{ + if (old == 0 || STATIC_IntRep(old)) + return &_ZeroRep; + + old->len = 0; + old->sgn = I_POSITIVE; + + return old; +} + +// special case for 1 or -1 + +IntRep* Icopy_one(IntRep* old, int newsgn) +{ + if (old == 0 || 1 > old->sz) + { + if (old != 0 && !STATIC_IntRep(old)) delete old; + return newsgn==I_NEGATIVE ? &_MinusOneRep : &_OneRep; + } + + old->sgn = newsgn; + old->len = 1; + old->s[0] = 1; + + return old; +} + +// convert to a legal two's complement long if possible +// if too big, return most negative/positive value + +long Itolong(const IntRep* rep) +{ + if ((unsigned)(rep->len) > (unsigned)(SHORT_PER_LONG)) + return (rep->sgn == I_POSITIVE) ? LONG_MAX : LONG_MIN; + else if (rep->len == 0) + return 0; + else if ((unsigned)(rep->len) < (unsigned)(SHORT_PER_LONG)) + { + unsigned long a = rep->s[rep->len-1]; + if (SHORT_PER_LONG > 2) // normally optimized out + { + for (int i = rep->len - 2; i >= 0; --i) + a = up(a) | rep->s[i]; + } + return (rep->sgn == I_POSITIVE)? a : -((long)a); + } + else + { + unsigned long a = rep->s[SHORT_PER_LONG - 1]; + if (a >= I_MINNUM) + return (rep->sgn == I_POSITIVE) ? LONG_MAX : LONG_MIN; + else + { + a = up(a) | rep->s[SHORT_PER_LONG - 2]; + if (SHORT_PER_LONG > 2) + { + for (int i = SHORT_PER_LONG - 3; i >= 0; --i) + a = up(a) | rep->s[i]; + } + return (rep->sgn == I_POSITIVE)? a : -((long)a); + } + } +} + +// test whether op long() will work. +// careful about asymmetry between LONG_MIN & LONG_MAX + +int Iislong(const IntRep* rep) +{ + unsigned int l = rep->len; + if (l < SHORT_PER_LONG) + return 1; + else if (l > SHORT_PER_LONG) + return 0; + else if ((unsigned)(rep->s[SHORT_PER_LONG - 1]) < (unsigned)(I_MINNUM)) + return 1; + else if (rep->sgn == I_NEGATIVE && rep->s[SHORT_PER_LONG - 1] == I_MINNUM) + { + for (unsigned int i = 0; i < SHORT_PER_LONG - 1; ++i) + if (rep->s[i] != 0) + return 0; + return 1; + } + else + return 0; +} + +// comparison functions + +int compare(const IntRep* x, const IntRep* y) +{ + int diff = x->sgn - y->sgn; + if (diff == 0) + { + diff = x->len - y->len; + if (diff == 0) + diff = docmp(x->s, y->s, x->len); + if (x->sgn == I_NEGATIVE) + diff = -diff; + } + return diff; +} + +int ucompare(const IntRep* x, const IntRep* y) +{ + int diff = x->len - y->len; + if (diff == 0) + { + int l = x->len; + const unsigned short* xs = &(x->s[l]); + const unsigned short* ys = &(y->s[l]); + while (l-- > 0 && (diff = (*--xs) - (*--ys)) == 0); + } + return diff; +} + +int compare(const IntRep* x, long y) +{ + int xl = x->len; + int xsgn = x->sgn; + if (y == 0) + { + if (xl == 0) + return 0; + else if (xsgn == I_NEGATIVE) + return -1; + else + return 1; + } + else + { + int ysgn = y >= 0; + unsigned long uy = (ysgn)? y : -y; + int diff = xsgn - ysgn; + if (diff == 0) + { + diff = xl - SHORT_PER_LONG; + if (diff <= 0) + { + unsigned short tmp[SHORT_PER_LONG]; + int yl = 0; + while (uy != 0) + { + tmp[yl++] = extract(uy); + uy = down(uy); + } + diff = xl - yl; + if (diff == 0) + diff = docmp(x->s, tmp, xl); + } + if (xsgn == I_NEGATIVE) + diff = -diff; + } + return diff; + } +} + +int ucompare(const IntRep* x, long y) +{ + int xl = x->len; + if (y == 0) + return xl; + else + { + unsigned long uy = (y >= 0)? y : -y; + int diff = xl - SHORT_PER_LONG; + if (diff <= 0) + { + unsigned short tmp[SHORT_PER_LONG]; + int yl = 0; + while (uy != 0) + { + tmp[yl++] = extract(uy); + uy = down(uy); + } + diff = xl - yl; + if (diff == 0) + diff = docmp(x->s, tmp, xl); + } + return diff; + } +} + + + +// arithmetic functions + +IntRep* add(const IntRep* x, int negatex, + const IntRep* y, int negatey, IntRep* r) +{ + nonnil(x); + nonnil(y); + + int xl = x->len; + int yl = y->len; + + int xsgn = (negatex && xl != 0) ? !x->sgn : x->sgn; + int ysgn = (negatey && yl != 0) ? !y->sgn : y->sgn; + + int xrsame = x == r; + int yrsame = y == r; + + if (yl == 0) + r = Ialloc(r, x->s, xl, xsgn, xl); + else if (xl == 0) + r = Ialloc(r, y->s, yl, ysgn, yl); + else if (xsgn == ysgn) + { + if (xrsame || yrsame) + r = Iresize(r, calc_len(xl, yl, 1)); + else + r = Icalloc(r, calc_len(xl, yl, 1)); + r->sgn = xsgn; + unsigned short* rs = r->s; + const unsigned short* as; + const unsigned short* bs; + const unsigned short* topa; + const unsigned short* topb; + if (xl >= yl) + { + as = (xrsame)? r->s : x->s; + topa = &(as[xl]); + bs = (yrsame)? r->s : y->s; + topb = &(bs[yl]); + } + else + { + bs = (xrsame)? r->s : x->s; + topb = &(bs[xl]); + as = (yrsame)? r->s : y->s; + topa = &(as[yl]); + } + unsigned long sum = 0; + while (bs < topb) + { + sum += (unsigned long)(*as++) + (unsigned long)(*bs++); + *rs++ = extract(sum); + sum = down(sum); + } + while (sum != 0 && as < topa) + { + sum += (unsigned long)(*as++); + *rs++ = extract(sum); + sum = down(sum); + } + if (sum != 0) + *rs = extract(sum); + else if (rs != as) + while (as < topa) + *rs++ = *as++; + } + else + { + int comp = ucompare(x, y); + if (comp == 0) + r = Icopy_zero(r); + else + { + if (xrsame || yrsame) + r = Iresize(r, calc_len(xl, yl, 0)); + else + r = Icalloc(r, calc_len(xl, yl, 0)); + unsigned short* rs = r->s; + const unsigned short* as; + const unsigned short* bs; + const unsigned short* topa; + const unsigned short* topb; + if (comp > 0) + { + as = (xrsame)? r->s : x->s; + topa = &(as[xl]); + bs = (yrsame)? r->s : y->s; + topb = &(bs[yl]); + r->sgn = xsgn; + } + else + { + bs = (xrsame)? r->s : x->s; + topb = &(bs[xl]); + as = (yrsame)? r->s : y->s; + topa = &(as[yl]); + r->sgn = ysgn; + } + unsigned long hi = 1; + while (bs < topb) + { + hi += (unsigned long)(*as++) + I_MAXNUM - (unsigned long)(*bs++); + *rs++ = extract(hi); + hi = down(hi); + } + while (hi == 0 && as < topa) + { + hi = (unsigned long)(*as++) + I_MAXNUM; + *rs++ = extract(hi); + hi = down(hi); + } + if (rs != as) + while (as < topa) + *rs++ = *as++; + } + } + Icheck(r); + return r; +} + + +IntRep* add(const IntRep* x, int negatex, long y, IntRep* r) +{ + nonnil(x); + int xl = x->len; + int xsgn = (negatex && xl != 0) ? !x->sgn : x->sgn; + int xrsame = x == r; + + int ysgn = (y >= 0); + unsigned long uy = (ysgn)? y : -y; + + if (y == 0) + r = Ialloc(r, x->s, xl, xsgn, xl); + else if (xl == 0) + r = Icopy_long(r, y); + else if (xsgn == ysgn) + { + if (xrsame) + r = Iresize(r, calc_len(xl, SHORT_PER_LONG, 1)); + else + r = Icalloc(r, calc_len(xl, SHORT_PER_LONG, 1)); + r->sgn = xsgn; + unsigned short* rs = r->s; + const unsigned short* as = (xrsame)? r->s : x->s; + const unsigned short* topa = &(as[xl]); + unsigned long sum = 0; + while (as < topa && uy != 0) + { + unsigned long u = extract(uy); + uy = down(uy); + sum += (unsigned long)(*as++) + u; + *rs++ = extract(sum); + sum = down(sum); + } + while (sum != 0 && as < topa) + { + sum += (unsigned long)(*as++); + *rs++ = extract(sum); + sum = down(sum); + } + if (sum != 0) + *rs = extract(sum); + else if (rs != as) + while (as < topa) + *rs++ = *as++; + } + else + { + unsigned short tmp[SHORT_PER_LONG]; + int yl = 0; + while (uy != 0) + { + tmp[yl++] = extract(uy); + uy = down(uy); + } + int comp = xl - yl; + if (comp == 0) + comp = docmp(x->s, tmp, yl); + if (comp == 0) + r = Icopy_zero(r); + else + { + if (xrsame) + r = Iresize(r, calc_len(xl, yl, 0)); + else + r = Icalloc(r, calc_len(xl, yl, 0)); + unsigned short* rs = r->s; + const unsigned short* as; + const unsigned short* bs; + const unsigned short* topa; + const unsigned short* topb; + if (comp > 0) + { + as = (xrsame)? r->s : x->s; + topa = &(as[xl]); + bs = tmp; + topb = &(bs[yl]); + r->sgn = xsgn; + } + else + { + bs = (xrsame)? r->s : x->s; + topb = &(bs[xl]); + as = tmp; + topa = &(as[yl]); + r->sgn = ysgn; + } + unsigned long hi = 1; + while (bs < topb) + { + hi += (unsigned long)(*as++) + I_MAXNUM - (unsigned long)(*bs++); + *rs++ = extract(hi); + hi = down(hi); + } + while (hi == 0 && as < topa) + { + hi = (unsigned long)(*as++) + I_MAXNUM; + *rs++ = extract(hi); + hi = down(hi); + } + if (rs != as) + while (as < topa) + *rs++ = *as++; + } + } + Icheck(r); + return r; +} + + +IntRep* multiply(const IntRep* x, const IntRep* y, IntRep* r) +{ + nonnil(x); + nonnil(y); + int xl = x->len; + int yl = y->len; + int rl = xl + yl; + int rsgn = x->sgn == y->sgn; + int xrsame = x == r; + int yrsame = y == r; + int xysame = x == y; + + if (xl == 0 || yl == 0) + r = Icopy_zero(r); + else if (xl == 1 && x->s[0] == 1) + r = Icopy(r, y); + else if (yl == 1 && y->s[0] == 1) + r = Icopy(r, x); + else if (!(xysame && xrsame)) + { + if (xrsame || yrsame) + r = Iresize(r, rl); + else + r = Icalloc(r, rl); + unsigned short* rs = r->s; + unsigned short* topr = &(rs[rl]); + + // use best inner/outer loop params given constraints + unsigned short* currentr; + const unsigned short* bota; + const unsigned short* as; + const unsigned short* botb; + const unsigned short* topb; + if (xrsame) + { + currentr = &(rs[xl-1]); + bota = rs; + as = currentr; + botb = y->s; + topb = &(botb[yl]); + } + else if (yrsame) + { + currentr = &(rs[yl-1]); + bota = rs; + as = currentr; + botb = x->s; + topb = &(botb[xl]); + } + else if (xl <= yl) + { + currentr = &(rs[xl-1]); + bota = x->s; + as = &(bota[xl-1]); + botb = y->s; + topb = &(botb[yl]); + } + else + { + currentr = &(rs[yl-1]); + bota = y->s; + as = &(bota[yl-1]); + botb = x->s; + topb = &(botb[xl]); + } + + while (as >= bota) + { + unsigned long ai = (unsigned long)(*as--); + unsigned short* rs = currentr--; + *rs = 0; + if (ai != 0) + { + unsigned long sum = 0; + const unsigned short* bs = botb; + while (bs < topb) + { + sum += ai * (unsigned long)(*bs++) + (unsigned long)(*rs); + *rs++ = extract(sum); + sum = down(sum); + } + while (sum != 0 && rs < topr) + { + sum += (unsigned long)(*rs); + *rs++ = extract(sum); + sum = down(sum); + } + } + } + } + else // x, y, and r same; compute over diagonals + { + r = Iresize(r, rl); + unsigned short* botr = r->s; + unsigned short* topr = &(botr[rl]); + unsigned short* rs = &(botr[rl - 2]); + + const unsigned short* bota = (xrsame)? botr : x->s; + const unsigned short* loa = &(bota[xl - 1]); + const unsigned short* hia = loa; + + for (; rs >= botr; --rs) + { + const unsigned short* h = hia; + const unsigned short* l = loa; + unsigned long prod = (unsigned long)(*h) * (unsigned long)(*l); + *rs = 0; + + for(;;) + { + unsigned short* rt = rs; + unsigned long sum = prod + (unsigned long)(*rt); + *rt++ = extract(sum); + sum = down(sum); + while (sum != 0 && rt < topr) + { + sum += (unsigned long)(*rt); + *rt++ = extract(sum); + sum = down(sum); + } + if (h > l) + { + rt = rs; + sum = prod + (unsigned long)(*rt); + *rt++ = extract(sum); + sum = down(sum); + while (sum != 0 && rt < topr) + { + sum += (unsigned long)(*rt); + *rt++ = extract(sum); + sum = down(sum); + } + if (--h >= ++l) + prod = (unsigned long)(*h) * (unsigned long)(*l); + else + break; + } + else + break; + } + if (loa > bota) + --loa; + else + --hia; + } + } + r->sgn = rsgn; + Icheck(r); + return r; +} + + +IntRep* multiply(const IntRep* x, long y, IntRep* r) +{ + nonnil(x); + int xl = x->len; + + if (xl == 0 || y == 0) + r = Icopy_zero(r); + else if (y == 1) + r = Icopy(r, x); + else + { + int ysgn = y >= 0; + int rsgn = x->sgn == ysgn; + unsigned long uy = (ysgn)? y : -y; + unsigned short tmp[SHORT_PER_LONG]; + int yl = 0; + while (uy != 0) + { + tmp[yl++] = extract(uy); + uy = down(uy); + } + + int rl = xl + yl; + int xrsame = x == r; + if (xrsame) + r = Iresize(r, rl); + else + r = Icalloc(r, rl); + + unsigned short* rs = r->s; + unsigned short* topr = &(rs[rl]); + unsigned short* currentr; + const unsigned short* bota; + const unsigned short* as; + const unsigned short* botb; + const unsigned short* topb; + + if (xrsame) + { + currentr = &(rs[xl-1]); + bota = rs; + as = currentr; + botb = tmp; + topb = &(botb[yl]); + } + else if (xl <= yl) + { + currentr = &(rs[xl-1]); + bota = x->s; + as = &(bota[xl-1]); + botb = tmp; + topb = &(botb[yl]); + } + else + { + currentr = &(rs[yl-1]); + bota = tmp; + as = &(bota[yl-1]); + botb = x->s; + topb = &(botb[xl]); + } + + while (as >= bota) + { + unsigned long ai = (unsigned long)(*as--); + unsigned short* rs = currentr--; + *rs = 0; + if (ai != 0) + { + unsigned long sum = 0; + const unsigned short* bs = botb; + while (bs < topb) + { + sum += ai * (unsigned long)(*bs++) + (unsigned long)(*rs); + *rs++ = extract(sum); + sum = down(sum); + } + while (sum != 0 && rs < topr) + { + sum += (unsigned long)(*rs); + *rs++ = extract(sum); + sum = down(sum); + } + } + } + r->sgn = rsgn; + } + Icheck(r); + return r; +} + + +// main division routine + +static void do_divide(unsigned short* rs, + const unsigned short* ys, int yl, + unsigned short* qs, int ql) +{ + const unsigned short* topy = &(ys[yl]); + unsigned short d1 = ys[yl - 1]; + unsigned short d2 = ys[yl - 2]; + + int l = ql - 1; + int i = l + yl; + + for (; l >= 0; --l, --i) + { + unsigned short qhat; // guess q + if (d1 == rs[i]) + qhat = I_MAXNUM; + else + { + unsigned long lr = up((unsigned long)rs[i]) | rs[i-1]; + qhat = lr / d1; + } + + for(;;) // adjust q, use docmp to avoid overflow problems + { + unsigned short ts[3]; + unsigned long prod = (unsigned long)d2 * (unsigned long)qhat; + ts[0] = extract(prod); + prod = down(prod) + (unsigned long)d1 * (unsigned long)qhat; + ts[1] = extract(prod); + ts[2] = extract(down(prod)); + if (docmp(ts, &(rs[i-2]), 3) > 0) + --qhat; + else + break; + }; + + // multiply & subtract + + const unsigned short* yt = ys; + unsigned short* rt = &(rs[l]); + unsigned long prod = 0; + unsigned long hi = 1; + while (yt < topy) + { + prod = (unsigned long)qhat * (unsigned long)(*yt++) + down(prod); + hi += (unsigned long)(*rt) + I_MAXNUM - (unsigned long)(extract(prod)); + *rt++ = extract(hi); + hi = down(hi); + } + hi += (unsigned long)(*rt) + I_MAXNUM - (unsigned long)(down(prod)); + *rt = extract(hi); + hi = down(hi); + + // off-by-one, add back + + if (hi == 0) + { + --qhat; + yt = ys; + rt = &(rs[l]); + hi = 0; + while (yt < topy) + { + hi = (unsigned long)(*rt) + (unsigned long)(*yt++) + down(hi); + *rt++ = extract(hi); + } + *rt = 0; + } + if (qs != 0) + qs[l] = qhat; + } +} + +// divide by single digit, return remainder +// if q != 0, then keep the result in q, else just compute rem + +static int unscale(const unsigned short* x, int xl, unsigned short y, + unsigned short* q) +{ + if (xl == 0 || y == 1) + return 0; + else if (q != 0) + { + unsigned short* botq = q; + unsigned short* qs = &(botq[xl - 1]); + const unsigned short* xs = &(x[xl - 1]); + unsigned long rem = 0; + while (qs >= botq) + { + rem = up(rem) | *xs--; + unsigned long u = rem / y; + *qs-- = extract(u); + rem -= u * y; + } + int r = extract(rem); + return r; + } + else // same loop, a bit faster if just need rem + { + const unsigned short* botx = x; + const unsigned short* xs = &(botx[xl - 1]); + unsigned long rem = 0; + while (xs >= botx) + { + rem = up(rem) | *xs--; + unsigned long u = rem / y; + rem -= u * y; + } + int r = extract(rem); + return r; + } +} + + +IntRep* div(const IntRep* x, const IntRep* y, IntRep* q) +{ + nonnil(x); + nonnil(y); + int xl = x->len; + int yl = y->len; + if (yl == 0) (*lib_error_handler)("Integer", "attempted division by zero"); + + int comp = ucompare(x, y); + int xsgn = x->sgn; + int ysgn = y->sgn; + + int samesign = xsgn == ysgn; + + if (comp < 0) + q = Icopy_zero(q); + else if (comp == 0) + q = Icopy_one(q, samesign); + else if (yl == 1) + { + q = Icopy(q, x); + unscale(q->s, q->len, y->s[0], q->s); + } + else + { + IntRep* yy = 0; + IntRep* r = 0; + unsigned short prescale = (I_RADIX / (1 + y->s[yl - 1])); + if (prescale != 1 || y == q) + { + yy = multiply(y, ((long)prescale & I_MAXNUM), yy); + r = multiply(x, ((long)prescale & I_MAXNUM), r); + } + else + { + yy = (IntRep*)y; + r = Icalloc(r, xl + 1); + scpy(x->s, r->s, xl); + } + + int ql = xl - yl + 1; + + q = Icalloc(q, ql); + do_divide(r->s, yy->s, yl, q->s, ql); + + if (yy != y && !STATIC_IntRep(yy)) delete yy; + if (!STATIC_IntRep(r)) delete r; + } + q->sgn = samesign; + Icheck(q); + return q; +} + +IntRep* div(const IntRep* x, long y, IntRep* q) +{ + nonnil(x); + int xl = x->len; + if (y == 0) (*lib_error_handler)("Integer", "attempted division by zero"); + + unsigned short ys[SHORT_PER_LONG]; + unsigned long u; + int ysgn = y >= 0; + if (ysgn) + u = y; + else + u = -y; + int yl = 0; + while (u != 0) + { + ys[yl++] = extract(u); + u = down(u); + } + + int comp = xl - yl; + if (comp == 0) comp = docmp(x->s, ys, xl); + + int xsgn = x->sgn; + int samesign = xsgn == ysgn; + + if (comp < 0) + q = Icopy_zero(q); + else if (comp == 0) + { + q = Icopy_one(q, samesign); + } + else if (yl == 1) + { + q = Icopy(q, x); + unscale(q->s, q->len, ys[0], q->s); + } + else + { + IntRep* r = 0; + unsigned short prescale = (I_RADIX / (1 + ys[yl - 1])); + if (prescale != 1) + { + unsigned long prod = (unsigned long)prescale * (unsigned long)ys[0]; + ys[0] = extract(prod); + prod = down(prod) + (unsigned long)prescale * (unsigned long)ys[1]; + ys[1] = extract(prod); + r = multiply(x, ((long)prescale & I_MAXNUM), r); + } + else + { + r = Icalloc(r, xl + 1); + scpy(x->s, r->s, xl); + } + + int ql = xl - yl + 1; + + q = Icalloc(q, ql); + do_divide(r->s, ys, yl, q->s, ql); + + if (!STATIC_IntRep(r)) delete r; + } + q->sgn = samesign; + Icheck(q); + return q; +} + + +void divide(const Integer& Ix, long y, Integer& Iq, long& rem) +{ + const IntRep* x = Ix.rep; + nonnil(x); + IntRep* q = Iq.rep; + int xl = x->len; + if (y == 0) (*lib_error_handler)("Integer", "attempted division by zero"); + + unsigned short ys[SHORT_PER_LONG]; + unsigned long u; + int ysgn = y >= 0; + if (ysgn) + u = y; + else + u = -y; + int yl = 0; + while (u != 0) + { + ys[yl++] = extract(u); + u = down(u); + } + + int comp = xl - yl; + if (comp == 0) comp = docmp(x->s, ys, xl); + + int xsgn = x->sgn; + int samesign = xsgn == ysgn; + + if (comp < 0) + { + rem = Itolong(x); + q = Icopy_zero(q); + } + else if (comp == 0) + { + q = Icopy_one(q, samesign); + rem = 0; + } + else if (yl == 1) + { + q = Icopy(q, x); + rem = unscale(q->s, q->len, ys[0], q->s); + } + else + { + IntRep* r = 0; + unsigned short prescale = (I_RADIX / (1 + ys[yl - 1])); + if (prescale != 1) + { + unsigned long prod = (unsigned long)prescale * (unsigned long)ys[0]; + ys[0] = extract(prod); + prod = down(prod) + (unsigned long)prescale * (unsigned long)ys[1]; + ys[1] = extract(prod); + r = multiply(x, ((long)prescale & I_MAXNUM), r); + } + else + { + r = Icalloc(r, xl + 1); + scpy(x->s, r->s, xl); + } + + int ql = xl - yl + 1; + + q = Icalloc(q, ql); + + do_divide(r->s, ys, yl, q->s, ql); + + if (prescale != 1) + { + Icheck(r); + unscale(r->s, r->len, prescale, r->s); + } + Icheck(r); + rem = Itolong(r); + if (!STATIC_IntRep(r)) delete r; + } + rem = abs(rem); + if (xsgn == I_NEGATIVE) rem = -rem; + q->sgn = samesign; + Icheck(q); + Iq.rep = q; +} + + +void divide(const Integer& Ix, const Integer& Iy, Integer& Iq, Integer& Ir) +{ + const IntRep* x = Ix.rep; + nonnil(x); + const IntRep* y = Iy.rep; + nonnil(y); + IntRep* q = Iq.rep; + IntRep* r = Ir.rep; + + int xl = x->len; + int yl = y->len; + if (yl == 0) + (*lib_error_handler)("Integer", "attempted division by zero"); + + int comp = ucompare(x, y); + int xsgn = x->sgn; + int ysgn = y->sgn; + + int samesign = xsgn == ysgn; + + if (comp < 0) + { + q = Icopy_zero(q); + r = Icopy(r, x); + } + else if (comp == 0) + { + q = Icopy_one(q, samesign); + r = Icopy_zero(r); + } + else if (yl == 1) + { + q = Icopy(q, x); + int rem = unscale(q->s, q->len, y->s[0], q->s); + r = Icopy_long(r, rem); + if (rem != 0) + r->sgn = xsgn; + } + else + { + IntRep* yy = 0; + unsigned short prescale = (I_RADIX / (1 + y->s[yl - 1])); + if (prescale != 1 || y == q || y == r) + { + yy = multiply(y, ((long)prescale & I_MAXNUM), yy); + r = multiply(x, ((long)prescale & I_MAXNUM), r); + } + else + { + yy = (IntRep*)y; + r = Icalloc(r, xl + 1); + scpy(x->s, r->s, xl); + } + + int ql = xl - yl + 1; + + q = Icalloc(q, ql); + do_divide(r->s, yy->s, yl, q->s, ql); + + if (yy != y && !STATIC_IntRep(yy)) delete yy; + if (prescale != 1) + { + Icheck(r); + unscale(r->s, r->len, prescale, r->s); + } + } + q->sgn = samesign; + Icheck(q); + Iq.rep = q; + Icheck(r); + Ir.rep = r; +} + +IntRep* mod(const IntRep* x, const IntRep* y, IntRep* r) +{ + nonnil(x); + nonnil(y); + int xl = x->len; + int yl = y->len; + if (yl == 0) (*lib_error_handler)("Integer", "attempted division by zero"); + + int comp = ucompare(x, y); + int xsgn = x->sgn; + + if (comp < 0) + r = Icopy(r, x); + else if (comp == 0) + r = Icopy_zero(r); + else if (yl == 1) + { + int rem = unscale(x->s, xl, y->s[0], 0); + r = Icopy_long(r, rem); + if (rem != 0) + r->sgn = xsgn; + } + else + { + IntRep* yy = 0; + unsigned short prescale = (I_RADIX / (1 + y->s[yl - 1])); + if (prescale != 1 || y == r) + { + yy = multiply(y, ((long)prescale & I_MAXNUM), yy); + r = multiply(x, ((long)prescale & I_MAXNUM), r); + } + else + { + yy = (IntRep*)y; + r = Icalloc(r, xl + 1); + scpy(x->s, r->s, xl); + } + + do_divide(r->s, yy->s, yl, 0, xl - yl + 1); + + if (yy != y && !STATIC_IntRep(yy)) delete yy; + + if (prescale != 1) + { + Icheck(r); + unscale(r->s, r->len, prescale, r->s); + } + } + Icheck(r); + return r; +} + +IntRep* mod(const IntRep* x, long y, IntRep* r) +{ + nonnil(x); + int xl = x->len; + if (y == 0) (*lib_error_handler)("Integer", "attempted division by zero"); + + unsigned short ys[SHORT_PER_LONG]; + unsigned long u; + int ysgn = y >= 0; + if (ysgn) + u = y; + else + u = -y; + int yl = 0; + while (u != 0) + { + ys[yl++] = extract(u); + u = down(u); + } + + int comp = xl - yl; + if (comp == 0) comp = docmp(x->s, ys, xl); + + int xsgn = x->sgn; + + if (comp < 0) + r = Icopy(r, x); + else if (comp == 0) + r = Icopy_zero(r); + else if (yl == 1) + { + int rem = unscale(x->s, xl, ys[0], 0); + r = Icopy_long(r, rem); + if (rem != 0) + r->sgn = xsgn; + } + else + { + unsigned short prescale = (I_RADIX / (1 + ys[yl - 1])); + if (prescale != 1) + { + unsigned long prod = (unsigned long)prescale * (unsigned long)ys[0]; + ys[0] = extract(prod); + prod = down(prod) + (unsigned long)prescale * (unsigned long)ys[1]; + ys[1] = extract(prod); + r = multiply(x, ((long)prescale & I_MAXNUM), r); + } + else + { + r = Icalloc(r, xl + 1); + scpy(x->s, r->s, xl); + } + + do_divide(r->s, ys, yl, 0, xl - yl + 1); + + if (prescale != 1) + { + Icheck(r); + unscale(r->s, r->len, prescale, r->s); + } + } + Icheck(r); + return r; +} + +IntRep* lshift(const IntRep* x, long y, IntRep* r) +{ + nonnil(x); + int xl = x->len; + if (xl == 0 || y == 0) + { + r = Icopy(r, x); + return r; + } + + int xrsame = x == r; + int rsgn = x->sgn; + + long ay = (y < 0)? -y : y; + int bw = ay / I_SHIFT; + int sw = ay % I_SHIFT; + + if (y > 0) + { + int rl = bw + xl + 1; + if (xrsame) + r = Iresize(r, rl); + else + r = Icalloc(r, rl); + + unsigned short* botr = r->s; + unsigned short* rs = &(botr[rl - 1]); + const unsigned short* botx = (xrsame)? botr : x->s; + const unsigned short* xs = &(botx[xl - 1]); + unsigned long a = 0; + while (xs >= botx) + { + a = up(a) | ((unsigned long)(*xs--) << sw); + *rs-- = extract(down(a)); + } + *rs-- = extract(a); + while (rs >= botr) + *rs-- = 0; + } + else + { + int rl = xl - bw; + if (rl < 0) + r = Icopy_zero(r); + else + { + if (xrsame) + r = Iresize(r, rl); + else + r = Icalloc(r, rl); + int rw = I_SHIFT - sw; + unsigned short* rs = r->s; + unsigned short* topr = &(rs[rl]); + const unsigned short* botx = (xrsame)? rs : x->s; + const unsigned short* xs = &(botx[bw]); + const unsigned short* topx = &(botx[xl]); + unsigned long a = (unsigned long)(*xs++) >> sw; + while (xs < topx) + { + a |= (unsigned long)(*xs++) << rw; + *rs++ = extract(a); + a = down(a); + } + *rs++ = extract(a); + if (xrsame) topr = (unsigned short*)topx; + while (rs < topr) + *rs++ = 0; + } + } + r->sgn = rsgn; + Icheck(r); + return r; +} + +IntRep* lshift(const IntRep* x, const IntRep* yy, int negatey, IntRep* r) +{ + long y = Itolong(yy); + if (negatey) + y = -y; + + return lshift(x, y, r); +} + +IntRep* bitop(const IntRep* x, const IntRep* y, IntRep* r, char op) +{ + nonnil(x); + nonnil(y); + int xl = x->len; + int yl = y->len; + int xsgn = x->sgn; + int xrsame = x == r; + int yrsame = y == r; + if (xrsame || yrsame) + r = Iresize(r, calc_len(xl, yl, 0)); + else + r = Icalloc(r, calc_len(xl, yl, 0)); + r->sgn = xsgn; + unsigned short* rs = r->s; + unsigned short* topr = &(rs[r->len]); + const unsigned short* as; + const unsigned short* bs; + const unsigned short* topb; + if (xl >= yl) + { + as = (xrsame)? rs : x->s; + bs = (yrsame)? rs : y->s; + topb = &(bs[yl]); + } + else + { + bs = (xrsame)? rs : x->s; + topb = &(bs[xl]); + as = (yrsame)? rs : y->s; + } + + switch (op) + { + case '&': + while (bs < topb) *rs++ = *as++ & *bs++; + while (rs < topr) *rs++ = 0; + break; + case '|': + while (bs < topb) *rs++ = *as++ | *bs++; + while (rs < topr) *rs++ = *as++; + break; + case '^': + while (bs < topb) *rs++ = *as++ ^ *bs++; + while (rs < topr) *rs++ = *as++; + break; + } + Icheck(r); + return r; +} + +IntRep* bitop(const IntRep* x, long y, IntRep* r, char op) +{ + nonnil(x); + unsigned short tmp[SHORT_PER_LONG]; + unsigned long u; + int newsgn; + if (newsgn = (y >= 0)) + u = y; + else + u = -y; + + int l = 0; + while (u != 0) + { + tmp[l++] = extract(u); + u = down(u); + } + + int xl = x->len; + int yl = l; + int xsgn = x->sgn; + int xrsame = x == r; + if (xrsame) + r = Iresize(r, calc_len(xl, yl, 0)); + else + r = Icalloc(r, calc_len(xl, yl, 0)); + r->sgn = xsgn; + unsigned short* rs = r->s; + unsigned short* topr = &(rs[r->len]); + const unsigned short* as; + const unsigned short* bs; + const unsigned short* topb; + if (xl >= yl) + { + as = (xrsame)? rs : x->s; + bs = tmp; + topb = &(bs[yl]); + } + else + { + bs = (xrsame)? rs : x->s; + topb = &(bs[xl]); + as = tmp; + } + + switch (op) + { + case '&': + while (bs < topb) *rs++ = *as++ & *bs++; + while (rs < topr) *rs++ = 0; + break; + case '|': + while (bs < topb) *rs++ = *as++ | *bs++; + while (rs < topr) *rs++ = *as++; + break; + case '^': + while (bs < topb) *rs++ = *as++ ^ *bs++; + while (rs < topr) *rs++ = *as++; + break; + } + Icheck(r); + return r; +} + + + +IntRep* compl(const IntRep* src, IntRep* r) +{ + nonnil(src); + r = Icopy(r, src); + unsigned short* s = r->s; + unsigned short* top = &(s[r->len - 1]); + while (s < top) + { + unsigned short cmp = ~(*s); + *s++ = cmp; + } + unsigned short a = *s; + unsigned short b = 0; + while (a != 0) + { + b <<= 1; + if (!(a & 1)) b |= 1; + a >>= 1; + } + *s = b; + Icheck(r); + return r; +} + +void (setbit)(Integer& x, long b) +{ + if (b >= 0) + { + int bw = (unsigned long)b / I_SHIFT; + int sw = (unsigned long)b % I_SHIFT; + int xl = x.rep ? x.rep->len : 0; + if (xl <= bw) + x.rep = Iresize(x.rep, calc_len(xl, bw+1, 0)); + x.rep->s[bw] |= (1 << sw); + Icheck(x.rep); + } +} + +void clearbit(Integer& x, long b) +{ + if (b >= 0) + { + if (x.rep == 0) + x.rep = &_ZeroRep; + else + { + int bw = (unsigned long)b / I_SHIFT; + int sw = (unsigned long)b % I_SHIFT; + if (x.rep->len > bw) + x.rep->s[bw] &= ~(1 << sw); + } + Icheck(x.rep); + } +} + +int testbit(const Integer& x, long b) +{ + if (x.rep != 0 && b >= 0) + { + int bw = (unsigned long)b / I_SHIFT; + int sw = (unsigned long)b % I_SHIFT; + return (bw < x.rep->len && (x.rep->s[bw] & (1 << sw)) != 0); + } + else + return 0; +} + +// A version of knuth's algorithm B / ex. 4.5.3.34 +// A better version that doesn't bother shifting all of `t' forthcoming + +IntRep* gcd(const IntRep* x, const IntRep* y) +{ + nonnil(x); + nonnil(y); + int ul = x->len; + int vl = y->len; + + if (vl == 0) + return Ialloc(0, x->s, ul, I_POSITIVE, ul); + else if (ul == 0) + return Ialloc(0, y->s, vl, I_POSITIVE, vl); + + IntRep* u = Ialloc(0, x->s, ul, I_POSITIVE, ul); + IntRep* v = Ialloc(0, y->s, vl, I_POSITIVE, vl); + +// find shift so that both not even + + long k = 0; + int l = (ul <= vl)? ul : vl; + int cont = 1; + for (int i = 0; i < l && cont; ++i) + { + unsigned long a = (i < ul)? u->s[i] : 0; + unsigned long b = (i < vl)? v->s[i] : 0; + for (int j = 0; j < I_SHIFT; ++j) + { + if ((a | b) & 1) + { + cont = 0; + break; + } + else + { + ++k; + a >>= 1; + b >>= 1; + } + } + } + + if (k != 0) + { + u = lshift(u, -k, u); + v = lshift(v, -k, v); + } + + IntRep* t; + if (u->s[0] & 01) + t = Ialloc(0, v->s, v->len, !v->sgn, v->len); + else + t = Ialloc(0, u->s, u->len, u->sgn, u->len); + + while (t->len != 0) + { + long s = 0; // shift t until odd + cont = 1; + int tl = t->len; + for (i = 0; i < tl && cont; ++i) + { + unsigned long a = t->s[i]; + for (int j = 0; j < I_SHIFT; ++j) + { + if (a & 1) + { + cont = 0; + break; + } + else + { + ++s; + a >>= 1; + } + } + } + + if (s != 0) t = lshift(t, -s, t); + + if (t->sgn == I_POSITIVE) + { + u = Icopy(u, t); + t = add(t, 0, v, 1, t); + } + else + { + v = Ialloc(v, t->s, t->len, !t->sgn, t->len); + t = add(t, 0, u, 0, t); + } + } + if (!STATIC_IntRep(t)) delete t; + if (!STATIC_IntRep(v)) delete v; + if (k != 0) u = lshift(u, k, u); + return u; +} + + + +long lg(const IntRep* x) +{ + nonnil(x); + int xl = x->len; + if (xl == 0) + return 0; + + long l = (xl - 1) * I_SHIFT - 1; + unsigned short a = x->s[xl-1]; + + while (a != 0) + { + a = a >> 1; + ++l; + } + return l; +} + +IntRep* power(const IntRep* x, long y, IntRep* r) +{ + nonnil(x); + int sgn; + if (x->sgn == I_POSITIVE || (!(y & 1))) + sgn = I_POSITIVE; + else + sgn = I_NEGATIVE; + + int xl = x->len; + + if (y == 0 || (xl == 1 && x->s[0] == 1)) + r = Icopy_one(r, sgn); + else if (xl == 0 || y < 0) + r = Icopy_zero(r); + else if (y == 1 || y == -1) + r = Icopy(r, x); + else + { + int maxsize = ((lg(x) + 1) * y) / I_SHIFT + 2; // pre-allocate space + IntRep* b = Ialloc(0, x->s, xl, I_POSITIVE, maxsize); + b->len = xl; + r = Icalloc(r, maxsize); + r = Icopy_one(r, I_POSITIVE); + for(;;) + { + if (y & 1) + r = multiply(r, b, r); + if ((y >>= 1) == 0) + break; + else + b = multiply(b, b, b); + } + if (!STATIC_IntRep(b)) delete b; + } + r->sgn = sgn; + Icheck(r); + return r; +} + +IntRep* abs(const IntRep* src, IntRep* dest) +{ + nonnil(src); + if (src != dest) + dest = Icopy(dest, src); + dest->sgn = I_POSITIVE; + return dest; +} + +IntRep* negate(const IntRep* src, IntRep* dest) +{ + nonnil(src); + if (src != dest) + dest = Icopy(dest, src); + if (dest->len != 0) + dest->sgn = !dest->sgn; + return dest; +} + +#if defined(__GNUG__) && !defined(_G_NO_NRV) + +Integer sqrt(const Integer& x) return r(x) +{ + int s = sign(x); + if (s < 0) x.error("Attempted square root of negative Integer"); + if (s != 0) + { + r >>= (lg(x) / 2); // get close + Integer q; + div(x, r, q); + while (q < r) + { + r += q; + r >>= 1; + div(x, r, q); + } + } + return; +} + +Integer lcm(const Integer& x, const Integer& y) return r +{ + if (!x.initialized() || !y.initialized()) + x.error("operation on uninitialized Integer"); + Integer g; + if (sign(x) == 0 || sign(y) == 0) + g = 1; + else + g = gcd(x, y); + div(x, g, r); + mul(r, y, r); +} + +#else +Integer sqrt(const Integer& x) +{ + Integer r(x); + int s = sign(x); + if (s < 0) x.error("Attempted square root of negative Integer"); + if (s != 0) + { + r >>= (lg(x) / 2); // get close + Integer q; + div(x, r, q); + while (q < r) + { + r += q; + r >>= 1; + div(x, r, q); + } + } + return r; +} + +Integer lcm(const Integer& x, const Integer& y) +{ + Integer r; + if (!x.initialized() || !y.initialized()) + x.error("operation on uninitialized Integer"); + Integer g; + if (sign(x) == 0 || sign(y) == 0) + g = 1; + else + g = gcd(x, y); + div(x, g, r); + mul(r, y, r); + return r; +} + +#endif + + + +IntRep* atoIntRep(const char* s, int base) +{ + int sl = strlen(s); + IntRep* r = Icalloc(0, sl * (lg(base) + 1) / I_SHIFT + 1); + if (s != 0) + { + char sgn; + while (isspace(*s)) ++s; + if (*s == '-') + { + sgn = I_NEGATIVE; + s++; + } + else if (*s == '+') + { + sgn = I_POSITIVE; + s++; + } + else + sgn = I_POSITIVE; + for (;;) + { + long digit; + if (*s >= '0' && *s <= '9') digit = *s - '0'; + else if (*s >= 'a' && *s <= 'z') digit = *s - 'a' + 10; + else if (*s >= 'A' && *s <= 'Z') digit = *s - 'A' + 10; + else break; + if (digit >= base) break; + r = multiply(r, base, r); + r = add(r, 0, digit, r); + ++s; + } + r->sgn = sgn; + } + return r; +} + + + +extern AllocRing _libgxx_fmtq; + +char* Itoa(const IntRep* x, int base, int width) +{ + int fmtlen = (x->len + 1) * I_SHIFT / lg(base) + 4 + width; + char* fmtbase = (char *) _libgxx_fmtq.alloc(fmtlen); + char* f = cvtItoa(x, fmtbase, fmtlen, base, 0, width, 0, ' ', 'X', 0); + return f; +} + +ostream& operator << (ostream& s, const Integer& y) +{ +#ifdef _OLD_STREAMS + return s << Itoa(y.rep); +#else + if (s.opfx()) + { + int base = (s.flags() & ios::oct) ? 8 : (s.flags() & ios::hex) ? 16 : 10; + int width = s.width(); + y.printon(s, base, width); + } + return s; +#endif +} + +void Integer::printon(ostream& s, int base /* =10 */, int width /* =0 */) const +{ + int align_right = !(s.flags() & ios::left); + int showpos = s.flags() & ios::showpos; + int showbase = s.flags() & ios::showbase; + char fillchar = s.fill(); + char Xcase = (s.flags() & ios::uppercase)? 'X' : 'x'; + const IntRep* x = rep; + int fmtlen = (x->len + 1) * I_SHIFT / lg(base) + 4 + width; + char* fmtbase = new char[fmtlen]; + char* f = cvtItoa(x, fmtbase, fmtlen, base, showbase, width, align_right, + fillchar, Xcase, showpos); + s.write(f, fmtlen); + delete fmtbase; +} + +char* cvtItoa(const IntRep* x, char* fmt, int& fmtlen, int base, int showbase, + int width, int align_right, char fillchar, char Xcase, + int showpos) +{ + char* e = fmt + fmtlen - 1; + char* s = e; + *--s = 0; + + if (x->len == 0) + *--s = '0'; + else + { + IntRep* z = Icopy(0, x); + + // split division by base into two parts: + // first divide by biggest power of base that fits in an unsigned short, + // then use straight signed div/mods from there. + + // find power + int bpower = 1; + unsigned short b = base; + unsigned short maxb = I_MAXNUM / base; + while (b < maxb) + { + b *= base; + ++bpower; + } + for(;;) + { + int rem = unscale(z->s, z->len, b, z->s); + Icheck(z); + if (z->len == 0) + { + while (rem != 0) + { + char ch = rem % base; + rem /= base; + if (ch >= 10) + ch += 'a' - 10; + else + ch += '0'; + *--s = ch; + } + if (!STATIC_IntRep(z)) delete z; + break; + } + else + { + for (int i = 0; i < bpower; ++i) + { + char ch = rem % base; + rem /= base; + if (ch >= 10) + ch += 'a' - 10; + else + ch += '0'; + *--s = ch; + } + } + } + } + + if (base == 8 && showbase) + *--s = '0'; + else if (base == 16 && showbase) + { + *--s = Xcase; + *--s = '0'; + } + if (x->sgn == I_NEGATIVE) *--s = '-'; + else if (showpos) *--s = '+'; + int w = e - s - 1; + if (!align_right || w >= width) + { + while (w++ < width) + *--s = fillchar; + fmtlen = e - s - 1; + return s; + } + else + { + char* p = fmt; + for (char* t = s; *t != 0; ++t, ++p) *p = *t; + while (w++ < width) *p++ = fillchar; + *p = 0; + fmtlen = p - fmt; + return fmt; + } +} + +char* dec(const Integer& x, int width) +{ + return Itoa(x, 10, width); +} + +char* oct(const Integer& x, int width) +{ + return Itoa(x, 8, width); +} + +char* hex(const Integer& x, int width) +{ + return Itoa(x, 16, width); +} + +istream& operator >> (istream& stream, Integer& val) +{ + if (!stream.ipfx0()) + return stream; + int sign = ' '; + register streambuf* sb = stream.rdbuf(); + int base = 10; + int ndigits = 0; + register int ch = sb->sbumpc(); + while (ch != EOF && isspace(ch)) + ch = sb->sbumpc(); + if (ch == '+' || ch == '-') + { + sign = ch; + ch = sb->sbumpc(); + while (ch != EOF && isspace(ch)) + ch = sb->sbumpc(); + } + if (ch == EOF) goto eof_fail; + if (!(stream.flags() & ios::basefield)) + { + if (ch == '0') + { + ch = sb->sbumpc(); + if (ch == EOF) { } + else 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.rep = Icopy_zero(val.rep); + + 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 + goto done; + } + ndigits++; + switch (base) + { + case 8: + val <<= 3; + break; + case 16: + val <<= 4; + break; + default: + val *= base; + break; + } + val += digit; + ch = sb->sbumpc(); + } + fail: + stream.set(ios::failbit); + done: + if (sign == '-') + val.negate(); + return stream; + eof_fail: + stream.set(ios::failbit|ios::eofbit); + return stream; +} + +int Integer::OK() const +{ + if (rep != 0) + { + int l = rep->len; + int s = rep->sgn; + int v = l <= rep->sz || STATIC_IntRep(rep); // length within bounds + v &= s == 0 || s == 1; // legal sign + Icheck(rep); // and correctly adjusted + v &= rep->len == l; + v &= rep->sgn == s; + if (v) + return v; + } + error("invariant failure"); + return 0; +} + +void Integer::error(const char* msg) const +{ + (*lib_error_handler)("Integer", msg); +} + diff --git a/gnu/lib/libg++/libg++/LogNorm.cc b/gnu/lib/libg++/libg++/LogNorm.cc new file mode 100644 index 0000000..ab60f87 --- /dev/null +++ b/gnu/lib/libg++/libg++/LogNorm.cc @@ -0,0 +1,36 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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 <builtin.h> +#include <Random.h> +#include <Normal.h> + +#include <LogNorm.h> + +// +// See Simulation, Modelling & Analysis by Law & Kelton, pp260 +// +// + +double LogNormal::operator()() +{ + return exp (this->Normal::operator()() ); +} + + diff --git a/gnu/lib/libg++/libg++/MLCG.cc b/gnu/lib/libg++/libg++/MLCG.cc new file mode 100644 index 0000000..cdc1165 --- /dev/null +++ b/gnu/lib/libg++/libg++/MLCG.cc @@ -0,0 +1,103 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1989 Free Software Foundation + +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 <MLCG.h> +// +// SEED_TABLE_SIZE must be a power of 2 +// + + +#define SEED_TABLE_SIZE 32 + +static _G_int32_t seedTable[SEED_TABLE_SIZE] = { +0xbdcc47e5, 0x54aea45d, 0xec0df859, 0xda84637b, +0xc8c6cb4f, 0x35574b01, 0x28260b7d, 0x0d07fdbf, +0x9faaeeb0, 0x613dd169, 0x5ce2d818, 0x85b9e706, +0xab2469db, 0xda02b0dc, 0x45c60d6e, 0xffe49d10, +0x7224fea3, 0xf9684fc9, 0xfc7ee074, 0x326ce92a, +0x366d13b5, 0x17aaa731, 0xeb83a675, 0x7781cb32, +0x4ec7c92d, 0x7f187521, 0x2cf346b4, 0xad13310f, +0xb89cff2b, 0x12164de1, 0xa865168d, 0x32b56cdf +}; + +MLCG::MLCG(_G_int32_t seed1, _G_int32_t seed2) +{ + initialSeedOne = seed1; + initialSeedTwo = seed2; + reset(); +} + +void +MLCG::reset() +{ + _G_int32_t seed1 = initialSeedOne; + _G_int32_t seed2 = initialSeedTwo; + + // + // Most people pick stupid seed numbers that do not have enough + // bits. In this case, if they pick a small seed number, we + // map that to a specific seed. + // + if (seed1 < 0) { + seed1 = (seed1 + 2147483561); + seed1 = (seed1 < 0) ? -seed1 : seed1; + } + + if (seed2 < 0) { + seed2 = (seed2 + 2147483561); + seed2 = (seed2 < 0) ? -seed2 : seed2; + } + + if (seed1 > -1 && seed1 < SEED_TABLE_SIZE) { + seedOne = seedTable[seed1]; + } else { + seedOne = seed1 ^ seedTable[seed1 & (SEED_TABLE_SIZE-1)]; + } + + if (seed2 > -1 && seed2 < SEED_TABLE_SIZE) { + seedTwo = seedTable[seed2]; + } else { + seedTwo = seed2 ^ seedTable[ seed2 & (SEED_TABLE_SIZE-1) ]; + } + seedOne = (seedOne % 2147483561) + 1; + seedTwo = (seedTwo % 2147483397) + 1; +} + +unsigned long MLCG::asLong() +{ + _G_int32_t k = seedOne % 53668; + + seedOne = 40014 * (seedOne-k * 53668) - k * 12211; + if (seedOne < 0) { + seedOne += 2147483563; + } + + k = seedTwo % 52774; + seedTwo = 40692 * (seedTwo - k * 52774) - k * 3791; + if (seedTwo < 0) { + seedTwo += 2147483399; + } + + _G_int32_t z = seedOne - seedTwo; + if (z < 1) { + z += 2147483562; + } + return( (unsigned long) z); +} + diff --git a/gnu/lib/libg++/libg++/NegExp.cc b/gnu/lib/libg++/libg++/NegExp.cc new file mode 100644 index 0000000..8bd6d05 --- /dev/null +++ b/gnu/lib/libg++/libg++/NegExp.cc @@ -0,0 +1,28 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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 <builtin.h> +#include <Random.h> +#include <NegExp.h> + +double NegativeExpntl::operator()() +{ + return(-pMean * log(pGenerator -> asDouble())); +} + diff --git a/gnu/lib/libg++/libg++/Normal.cc b/gnu/lib/libg++/libg++/Normal.cc new file mode 100644 index 0000000..bae43e1 --- /dev/null +++ b/gnu/lib/libg++/libg++/Normal.cc @@ -0,0 +1,60 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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 <builtin.h> +#include <Random.h> +#include <Normal.h> +// +// See Simulation, Modelling & Analysis by Law & Kelton, pp259 +// +// This is the ``polar'' method. +// + +double Normal::operator()() +{ + + if (haveCachedNormal == 1) { + haveCachedNormal = 0; + return(cachedNormal * pStdDev + pMean ); + } else { + + for(;;) { + double u1 = pGenerator -> asDouble(); + double u2 = pGenerator -> asDouble(); + double v1 = 2 * u1 - 1; + double v2 = 2 * u2 - 1; + double w = (v1 * v1) + (v2 * v2); + +// +// We actually generate two IID normal distribution variables. +// We cache the one & return the other. +// + if (w <= 1) { + double y = sqrt( (-2 * log(w)) / w); + double x1 = v1 * y; + double x2 = v2 * y; + + haveCachedNormal = 1; + cachedNormal = x2; + return(x1 * pStdDev + pMean); + } + } + } +} + diff --git a/gnu/lib/libg++/libg++/Obstack.cc b/gnu/lib/libg++/libg++/Obstack.cc new file mode 100644 index 0000000..d661df0 --- /dev/null +++ b/gnu/lib/libg++/libg++/Obstack.cc @@ -0,0 +1,125 @@ +/* +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 <limits.h> +#include <builtin.h> +#include <Obstack.h> + +/* We use subtraction of (char *)0 instead of casting to int + because on word-addressable machines a simple cast to int + may ignore the byte-within-word field of the pointer. */ + +#ifndef __PTR_TO_INT +#define __PTR_TO_INT(P) ((P) - (char *)0) +#endif + +#ifndef __INT_TO_PTR +#define __INT_TO_PTR(P) ((P) + (char *)0) +#endif + +Obstack::Obstack(int size, int alignment) +{ + alignmentmask = alignment - 1; + chunksize = size; + chunk = 0; + nextfree = objectbase = 0; + chunklimit = 0; +} + +void Obstack::_free(void* obj) +{ + _obstack_chunk* lp; + _obstack_chunk* plp; + + lp = chunk; + while (lp != 0 && ((void*)lp > obj || (void*)(lp)->limit < obj)) + { + plp = lp -> prev; + delete [] (char*)lp; + lp = plp; + } + if (lp) + { + objectbase = nextfree = (char *)(obj); + chunklimit = lp->limit; + chunk = lp; + } + else if (obj != 0) + (*lib_error_handler)("Obstack", "deletion of nonexistent obj"); +} + +void Obstack::newchunk(int size) +{ + _obstack_chunk* old_chunk = chunk; + _obstack_chunk* new_chunk; + long new_size; + int obj_size = nextfree - objectbase; + + new_size = (obj_size + size) << 1; + if (new_size < chunksize) + new_size = chunksize; + + new_chunk = chunk = (_obstack_chunk*)(new char[new_size]); + new_chunk->prev = old_chunk; + new_chunk->limit = chunklimit = (char *) new_chunk + new_size; + + memcpy((void*)new_chunk->contents, (void*)objectbase, obj_size); + objectbase = new_chunk->contents; + nextfree = objectbase + obj_size; +} + +void* Obstack::finish() +{ + void* value = (void*) objectbase; + nextfree = __INT_TO_PTR (__PTR_TO_INT (nextfree + alignmentmask) + & ~alignmentmask); + if (nextfree - (char*)chunk > chunklimit - (char*)chunk) + nextfree = chunklimit; + objectbase = nextfree; + return value; +} + +int Obstack::contains(void* obj) // true if obj somewhere in Obstack +{ + for (_obstack_chunk* ch = chunk; + ch != 0 && (obj < (void*)ch || obj >= (void*)(ch->limit)); + ch = ch->prev); + + return ch != 0; +} + +int Obstack::OK() +{ + int v = chunksize > 0; // valid size + v &= alignmentmask != 0; // and alignment + v &= chunk != 0; + v &= objectbase >= chunk->contents; + v &= nextfree >= objectbase; + v &= nextfree <= chunklimit; + v &= chunklimit == chunk->limit; + _obstack_chunk* p = chunk; + // allow lots of chances to find bottom! + long x = LONG_MAX; + while (p != 0 && x != 0) { --x; p = p->prev; } + v &= x > 0; + if (!v) + (*lib_error_handler)("Obstack", "invariant failure"); + return v; +} diff --git a/gnu/lib/libg++/libg++/Poisson.cc b/gnu/lib/libg++/libg++/Poisson.cc new file mode 100644 index 0000000..8d70f17 --- /dev/null +++ b/gnu/lib/libg++/libg++/Poisson.cc @@ -0,0 +1,36 @@ + +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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 <builtin.h> +#include <Random.h> +#include <Poisson.h> + +double Poisson::operator()() +{ + double bound = exp(-1.0 * pMean); + int count = 0; + + for (double product = 1.0; + product >= bound; + product *= pGenerator -> asDouble()) { + count++; + } + return(count - 1); +} diff --git a/gnu/lib/libg++/libg++/RNG.cc b/gnu/lib/libg++/libg++/RNG.cc new file mode 100644 index 0000000..02b7cdf --- /dev/null +++ b/gnu/lib/libg++/libg++/RNG.cc @@ -0,0 +1,131 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1989 Free Software Foundation + +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 <assert.h> +#include <builtin.h> +#include <RNG.h> + +// These two static fields get initialized by RNG::RNG(). +PrivateRNGSingleType RNG::singleMantissa; +PrivateRNGDoubleType RNG::doubleMantissa; + +// +// The scale constant is 2^-31. It is used to scale a 31 bit +// long to a double. +// + +//static const double randomDoubleScaleConstant = 4.656612873077392578125e-10; +//static const float randomFloatScaleConstant = 4.656612873077392578125e-10; + +static char initialized = 0; + +RNG::RNG() +{ + if (!initialized) + { + + assert (sizeof(double) == 2 * sizeof(_G_uint32_t)); + + // + // The following is a hack that I attribute to + // Andres Nowatzyk at CMU. The intent of the loop + // is to form the smallest number 0 <= x < 1.0, + // which is then used as a mask for two longwords. + // this gives us a fast way way to produce double + // precision numbers from longwords. + // + // I know that this works for IEEE and VAX floating + // point representations. + // + // A further complication is that gnu C will blow + // the following loop, unless compiled with -ffloat-store, + // because it uses extended representations for some of + // of the comparisons. Thus, we have the following hack. + // If we could specify #pragma optimize, we wouldn't need this. + // + + PrivateRNGDoubleType t; + PrivateRNGSingleType s; + +#if _IEEE == 1 + + t.d = 1.5; + if ( t.u[1] == 0 ) { // sun word order? + t.u[0] = 0x3fffffff; + t.u[1] = 0xffffffff; + } + else { + t.u[0] = 0xffffffff; // encore word order? + t.u[1] = 0x3fffffff; + } + + s.u = 0x3fffffff; +#else + volatile double x = 1.0; // volatile needed when fp hardware used, + // and has greater precision than memory doubles + double y = 0.5; + do { // find largest fp-number < 2.0 + t.d = x; + x += y; + y *= 0.5; + } while (x != t.d && x < 2.0); + + volatile float xx = 1.0; // volatile needed when fp hardware used, + // and has greater precision than memory floats + float yy = 0.5; + do { // find largest fp-number < 2.0 + s.s = xx; + xx += yy; + yy *= 0.5; + } while (xx != s.s && xx < 2.0); +#endif + // set doubleMantissa to 1 for each doubleMantissa bit + doubleMantissa.d = 1.0; + doubleMantissa.u[0] ^= t.u[0]; + doubleMantissa.u[1] ^= t.u[1]; + + // set singleMantissa to 1 for each singleMantissa bit + singleMantissa.s = 1.0; + singleMantissa.u ^= s.u; + + initialized = 1; + } +} + +float RNG::asFloat() +{ + PrivateRNGSingleType result; + result.s = 1.0; + result.u |= (asLong() & singleMantissa.u); + result.s -= 1.0; + assert( result.s < 1.0 && result.s >= 0); + return( result.s ); +} + +double RNG::asDouble() +{ + PrivateRNGDoubleType result; + result.d = 1.0; + result.u[0] |= (asLong() & doubleMantissa.u[0]); + result.u[1] |= (asLong() & doubleMantissa.u[1]); + result.d -= 1.0; + assert( result.d < 1.0 && result.d >= 0); + return( result.d ); +} + diff --git a/gnu/lib/libg++/libg++/Random.cc b/gnu/lib/libg++/libg++/Random.cc new file mode 100644 index 0000000..572a602 --- /dev/null +++ b/gnu/lib/libg++/libg++/Random.cc @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <Random.h> diff --git a/gnu/lib/libg++/libg++/Rational.cc b/gnu/lib/libg++/libg++/Rational.cc new file mode 100644 index 0000000..3c00b56 --- /dev/null +++ b/gnu/lib/libg++/libg++/Rational.cc @@ -0,0 +1,414 @@ +/* +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 <Rational.h> +#include <std.h> +#include <math.h> +#include <builtin.h> +#include <float.h> + +void Rational::error(const char* msg) const +{ + (*lib_error_handler)("Rational", msg); +} + +static const Integer _Int_One(1); + +void Rational::normalize() +{ + int s = sign(den); + if (s == 0) + error("Zero denominator."); + else if (s < 0) + { + den.negate(); + num.negate(); + } + + Integer g = gcd(num, den); + if (ucompare(g, _Int_One) != 0) + { + num /= g; + den /= g; + } +} + +void add(const Rational& x, const Rational& y, Rational& r) +{ + if (&r != &x && &r != &y) + { + mul(x.num, y.den, r.num); + mul(x.den, y.num, r.den); + add(r.num, r.den, r.num); + mul(x.den, y.den, r.den); + } + else + { + Integer tmp; + mul(x.den, y.num, tmp); + mul(x.num, y.den, r.num); + add(r.num, tmp, r.num); + mul(x.den, y.den, r.den); + } + r.normalize(); +} + +void sub(const Rational& x, const Rational& y, Rational& r) +{ + if (&r != &x && &r != &y) + { + mul(x.num, y.den, r.num); + mul(x.den, y.num, r.den); + sub(r.num, r.den, r.num); + mul(x.den, y.den, r.den); + } + else + { + Integer tmp; + mul(x.den, y.num, tmp); + mul(x.num, y.den, r.num); + sub(r.num, tmp, r.num); + mul(x.den, y.den, r.den); + } + r.normalize(); +} + +void mul(const Rational& x, const Rational& y, Rational& r) +{ + mul(x.num, y.num, r.num); + mul(x.den, y.den, r.den); + r.normalize(); +} + +void div(const Rational& x, const Rational& y, Rational& r) +{ + if (&r != &x && &r != &y) + { + mul(x.num, y.den, r.num); + mul(x.den, y.num, r.den); + } + else + { + Integer tmp; + mul(x.num, y.den, tmp); + mul(y.num, x.den, r.den); + r.num = tmp; + } + r.normalize(); +} + + + + +void Rational::invert() +{ + Integer tmp = num; + num = den; + den = tmp; + int s = sign(den); + if (s == 0) + error("Zero denominator."); + else if (s < 0) + { + den.negate(); + num.negate(); + } +} + +int compare(const Rational& x, const Rational& y) +{ + int xsgn = sign(x.num); + int ysgn = sign(y.num); + int d = xsgn - ysgn; + if (d == 0 && xsgn != 0) d = compare(x.num * y.den, x.den * y.num); + return d; +} + +Rational::Rational(double x) +{ + num = 0; + den = 1; + if (x != 0.0) + { + int neg = x < 0; + if (neg) + x = -x; + + const long shift = 15; // a safe shift per step + const double width = 32768.0; // = 2^shift + const int maxiter = 20; // ought not be necessary, but just in case, + // max 300 bits of precision + int expt; + double mantissa = frexp(x, &expt); + long exponent = expt; + double intpart; + int k = 0; + while (mantissa != 0.0 && k++ < maxiter) + { + mantissa *= width; + mantissa = modf(mantissa, &intpart); + num <<= shift; + num += (long)intpart; + exponent -= shift; + } + if (exponent > 0) + num <<= exponent; + else if (exponent < 0) + den <<= -exponent; + if (neg) + num.negate(); + } + normalize(); +} + + +Integer trunc(const Rational& x) +{ + return x.num / x.den ; +} + + +Rational pow(const Rational& x, const Integer& y) +{ + long yy = y.as_long(); + return pow(x, yy); +} + +#if defined(__GNUG__) && !defined(_G_NO_NRV) + +Rational operator - (const Rational& x) return r(x) +{ + r.negate(); +} + +Rational abs(const Rational& x) return r(x) +{ + if (sign(r.num) < 0) r.negate(); +} + + +Rational sqr(const Rational& x) return r +{ + mul(x.num, x.num, r.num); + mul(x.den, x.den, r.den); + r.normalize(); +} + +Integer floor(const Rational& x) return q +{ + Integer r; + divide(x.num, x.den, q, r); + if (sign(x.num) < 0 && sign(r) != 0) --q; +} + +Integer ceil(const Rational& x) return q +{ + Integer r; + divide(x.num, x.den, q, r); + if (sign(x.num) >= 0 && sign(r) != 0) ++q; +} + +Integer round(const Rational& x) return q +{ + Integer r; + divide(x.num, x.den, q, r); + r <<= 1; + if (ucompare(r, x.den) >= 0) + { + if (sign(x.num) >= 0) + ++q; + else + --q; + } +} + +// power: no need to normalize since num & den already relatively prime + +Rational pow(const Rational& x, long y) return r +{ + if (y >= 0) + { + pow(x.num, y, r.num); + pow(x.den, y, r.den); + } + else + { + y = -y; + pow(x.num, y, r.den); + pow(x.den, y, r.num); + if (sign(r.den) < 0) + { + r.num.negate(); + r.den.negate(); + } + } +} + +#else + +Rational operator - (const Rational& x) +{ + Rational r(x); r.negate(); return r; +} + +Rational abs(const Rational& x) +{ + Rational r(x); + if (sign(r.num) < 0) r.negate(); + return r; +} + + +Rational sqr(const Rational& x) +{ + Rational r; + mul(x.num, x.num, r.num); + mul(x.den, x.den, r.den); + r.normalize(); + return r; +} + +Integer floor(const Rational& x) +{ + Integer q; + Integer r; + divide(x.num, x.den, q, r); + if (sign(x.num) < 0 && sign(r) != 0) --q; + return q; +} + +Integer ceil(const Rational& x) +{ + Integer q; + Integer r; + divide(x.num, x.den, q, r); + if (sign(x.num) >= 0 && sign(r) != 0) ++q; + return q; +} + +Integer round(const Rational& x) +{ + Integer q; + Integer r; + divide(x.num, x.den, q, r); + r <<= 1; + if (ucompare(r, x.den) >= 0) + { + if (sign(x.num) >= 0) + ++q; + else + --q; + } + return q; +} + +Rational pow(const Rational& x, long y) +{ + Rational r; + if (y >= 0) + { + pow(x.num, y, r.num); + pow(x.den, y, r.den); + } + else + { + y = -y; + pow(x.num, y, r.den); + pow(x.den, y, r.num); + if (sign(r.den) < 0) + { + r.num.negate(); + r.den.negate(); + } + } + return r; +} + +#endif + +ostream& operator << (ostream& s, const Rational& y) +{ + if (y.denominator() == 1L) + s << y.numerator(); + else + { + s << y.numerator(); + s << "/"; + s << y.denominator(); + } + return s; +} + +istream& operator >> (istream& s, Rational& y) +{ +#ifdef _OLD_STREAMS + if (!s.good()) + { + return s; + } +#else + if (!s.ipfx(0)) + { + s.clear(ios::failbit|s.rdstate()); // Redundant if using GNU iostreams. + return s; + } +#endif + Integer n = 0; + Integer d = 1; + if (s >> n) + { + char ch = 0; + s.get(ch); + if (ch == '/') + { + s >> d; + } + else + { + s.putback(ch); + } + } + y = Rational(n, d); + return s; +} + +int Rational::OK() const +{ + int v = num.OK() && den.OK(); // have valid num and denom + if (v) + { + v &= sign(den) > 0; // denominator positive; + v &= ucompare(gcd(num, den), _Int_One) == 0; // relatively prime + } + if (!v) error("invariant failure"); + return v; +} + +int +Rational::fits_in_float() const +{ + return Rational (FLT_MIN) <= *this && *this <= Rational (FLT_MAX); +} + +int +Rational::fits_in_double() const +{ + return Rational (DBL_MIN) <= *this && *this <= Rational (DBL_MAX); +} diff --git a/gnu/lib/libg++/libg++/Regex.cc b/gnu/lib/libg++/libg++/Regex.cc new file mode 100644 index 0000000..990f7b8 --- /dev/null +++ b/gnu/lib/libg++/libg++/Regex.cc @@ -0,0 +1,135 @@ +/* +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. +*/ + +/* + Regex class implementation + */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <std.h> +#include <ctype.h> +#include <new.h> +#include <builtin.h> + +extern "C" { +#include <regex.h> +} + +#include <Regex.h> + +Regex::~Regex() +{ + if (buf->buffer) free(buf->buffer); + if (buf->fastmap) free(buf->fastmap); + delete(buf); + delete(reg); +} + +Regex::Regex(const char* t, int fast, int bufsize, + const char* transtable) +{ + int tlen = (t == 0)? 0 : strlen(t); + buf = new re_pattern_buffer; + reg = new re_registers; + if (fast) + buf->fastmap = (char*)malloc(256); + else + buf->fastmap = 0; + buf->translate = (char*)transtable; + if (tlen > bufsize) + bufsize = tlen; + buf->allocated = bufsize; + buf->buffer = (char *)malloc(buf->allocated); + char* msg = re_compile_pattern((const char*)t, tlen, buf); + if (msg != 0) + (*lib_error_handler)("Regex", msg); + else if (fast) + re_compile_fastmap(buf); +} + +int Regex::match_info(int& start, int& length, int nth) const +{ + if ((unsigned)(nth) >= RE_NREGS) + return 0; + else + { + start = reg->start[nth]; + length = reg->end[nth] - start; + return start >= 0 && length >= 0; + } +} + +int Regex::search(const char* s, int len, int& matchlen, int startpos) const +{ + int matchpos, pos, range; + if (startpos >= 0) + { + pos = startpos; + range = len - startpos; + } + else + { + pos = len + startpos; + range = -pos; + } + matchpos = re_search_2(buf, 0, 0, (char*)s, len, pos, range, reg, len); + if (matchpos >= 0) + matchlen = reg->end[0] - reg->start[0]; + else + matchlen = 0; + return matchpos; +} + +int Regex::match(const char*s, int len, int p) const +{ + if (p < 0) + { + p += len; + if (p > len) + return -1; + return re_match_2(buf, 0, 0, (char*)s, p, 0, reg, p); + } + else if (p > len) + return -1; + else + return re_match_2(buf, 0, 0, (char*)s, len, p, reg, len); +} + +int Regex::OK() const +{ +// can't verify much, since we've lost the original string + int v = buf != 0; // have a regex buf + v &= buf->buffer != 0; // with a pat + if (!v) (*lib_error_handler)("Regex", "invariant failure"); + return v; +} + +/* + some built-in Regular expressions +*/ + +const Regex RXwhite("[ \n\t\r\v\f]+", 1); +const Regex RXint("-?[0-9]+", 1); +const Regex RXdouble("-?\\(\\([0-9]+\\.[0-9]*\\)\\|\\([0-9]+\\)\\|\\(\\.[0-9]+\\)\\)\\([eE][---+]?[0-9]+\\)?", 1, 200); +const Regex RXalpha("[A-Za-z]+", 1); +const Regex RXlowercase("[a-z]+", 1); +const Regex RXuppercase("[A-Z]+", 1); +const Regex RXalphanum("[0-9A-Za-z]+", 1); +const Regex RXidentifier("[A-Za-z_][A-Za-z0-9_]*", 1); + diff --git a/gnu/lib/libg++/libg++/RndInt.cc b/gnu/lib/libg++/libg++/RndInt.cc new file mode 100644 index 0000000..c09f1e5 --- /dev/null +++ b/gnu/lib/libg++/libg++/RndInt.cc @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <RndInt.h> diff --git a/gnu/lib/libg++/libg++/SLList.cc b/gnu/lib/libg++/libg++/SLList.cc new file mode 100644 index 0000000..6efd997 --- /dev/null +++ b/gnu/lib/libg++/libg++/SLList.cc @@ -0,0 +1,247 @@ +// 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. +*/ + +#ifndef _G_NO_TEMPLATES +#ifdef __GNUG__ +//#pragma implementation +#endif +#include <limits.h> +#include <stream.h> +#include <builtin.h> +#include "SLList.h" + +void BaseSLList::error(const char* msg) +{ + (*lib_error_handler)("SLList", msg); +} + +int BaseSLList::length() const +{ + int l = 0; + BaseSLNode* t = last; + if (t != 0) do { ++l; t = t->tl; } while (t != last); + return l; +} + +void BaseSLList::clear() +{ + if (last == 0) + return; + + BaseSLNode* p = last->tl; + last->tl = 0; + last = 0; + + while (p != 0) + { + BaseSLNode* nxt = p->tl; + delete_node(p); + p = nxt; + } +} + + +// Note: This is an internal method. It does *not* free old contents! + +void BaseSLList::copy(const BaseSLList& a) +{ + if (a.last == 0) + last = 0; + else + { + BaseSLNode* p = a.last->tl; + BaseSLNode* h = copy_node(p->item()); + last = h; + for (;;) + { + if (p == a.last) + { + last->tl = h; + return; + } + p = p->tl; + BaseSLNode* n = copy_node(p->item()); + last->tl = n; + last = n; + } + } +} + +BaseSLList& BaseSLList::operator = (const BaseSLList& a) +{ + if (last != a.last) + { + clear(); + copy(a); + } + return *this; +} + +Pix BaseSLList::prepend(const void *datum) +{ + return prepend(copy_node(datum)); +} + + +Pix BaseSLList::prepend(BaseSLNode* t) +{ + if (t == 0) return 0; + if (last == 0) + t->tl = last = t; + else + { + t->tl = last->tl; + last->tl = t; + } + return Pix(t); +} + + +Pix BaseSLList::append(const void *datum) +{ + return append(copy_node(datum)); +} + +Pix BaseSLList::append(BaseSLNode* t) +{ + if (t == 0) return 0; + if (last == 0) + t->tl = last = t; + else + { + t->tl = last->tl; + last->tl = t; + last = t; + } + return Pix(t); +} + +void BaseSLList::join(BaseSLList& b) +{ + BaseSLNode* t = b.last; + b.last = 0; + if (last == 0) + last = t; + else if (t != 0) + { + BaseSLNode* f = last->tl; + last->tl = t->tl; + t->tl = f; + last = t; + } +} + +Pix BaseSLList::ins_after(Pix p, const void *datum) +{ + BaseSLNode* u = (BaseSLNode*)p; + BaseSLNode* t = copy_node(datum); + if (last == 0) + t->tl = last = t; + else if (u == 0) // ins_after 0 means prepend + { + t->tl = last->tl; + last->tl = t; + } + else + { + t->tl = u->tl; + u->tl = t; + if (u == last) + last = t; + } + return Pix(t); +} + +void BaseSLList::del_after(Pix p) +{ + BaseSLNode* u = (BaseSLNode*)p; + if (last == 0 || u == last) error("cannot del_after last"); + if (u == 0) u = last; // del_after 0 means delete first + BaseSLNode* t = u->tl; + if (u == t) + last = 0; + else + { + u->tl = t->tl; + if (last == t) + last = u; + } + delete_node(t); +} + +int BaseSLList::owns(Pix p) +{ + BaseSLNode* t = last; + if (t != 0 && p != 0) + { + do + { + if (Pix(t) == p) return 1; + t = t->tl; + } while (t != last); + } + return 0; +} + +int BaseSLList::remove_front(void *dst, int signal_error) +{ + if (last) + { + BaseSLNode* t = last->tl; + copy_item(dst, t->item()); + if (t == last) + last = 0; + else + last->tl = t->tl; + delete_node(t); + return 1; + } + if (signal_error) + error("remove_front of empty list"); + return 0; +} + +void BaseSLList::del_front() +{ + if (last == 0) error("del_front of empty list"); + BaseSLNode* t = last->tl; + if (t == last) + last = 0; + else + last->tl = t->tl; + delete_node(t); +} + +int BaseSLList::OK() +{ + int v = 1; + if (last != 0) + { + BaseSLNode* t = last; + long count = LONG_MAX; // Lots of chances to find last! + do + { + count--; + t = t->tl; + } while (count > 0 && t != last); + v &= count > 0; + } + if (!v) error("invariant failure"); + return v; +} +#endif /*!_G_NO_TEMPLATES*/ diff --git a/gnu/lib/libg++/libg++/SmplHist.cc b/gnu/lib/libg++/libg++/SmplHist.cc new file mode 100644 index 0000000..a1fcd15 --- /dev/null +++ b/gnu/lib/libg++/libg++/SmplHist.cc @@ -0,0 +1,112 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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 <stream.h> +#include <SmplHist.h> +#include <math.h> + +#ifndef HUGE_VAL +#ifdef HUGE +#define HUGE_VAL HUGE +#else +#include <float.h> +#define HUGE_VAL DBL_MAX +#endif +#endif + +const int SampleHistogramMinimum = -2; +const int SampleHistogramMaximum = -1; + +SampleHistogram::SampleHistogram(double low, double high, double width) +{ + if (high < low) { + double t = high; + high = low; + low = t; + } + + if (width == -1) { + width = (high - low) / 10; + } + + howManyBuckets = int((high - low) / width) + 2; + bucketCount = new int[howManyBuckets]; + bucketLimit = new double[howManyBuckets]; + double lim = low; + for (int i = 0; i < howManyBuckets; i++) { + bucketCount[i] = 0; + bucketLimit[i] = lim; + lim += width; + } + bucketLimit[howManyBuckets-1] = HUGE_VAL; /* from math.h */ +} + +SampleHistogram::~SampleHistogram() +{ + if (howManyBuckets > 0) { + delete bucketCount; + delete bucketLimit; + } +} + +void +SampleHistogram::operator+=(double value) +{ + int i; + for (i = 0; i < howManyBuckets; i++) { + if (value < bucketLimit[i]) break; + } + bucketCount[i]++; + this->SampleStatistic::operator+=(value); +} + +int +SampleHistogram::similarSamples(double d) +{ + int i; + for (i = 0; i < howManyBuckets; i++) { + if (d < bucketLimit[i]) return(bucketCount[i]); + } + return(0); +} + +void +SampleHistogram::printBuckets(ostream& s) +{ + for(int i = 0; i < howManyBuckets; i++) { + if (bucketLimit[i] >= HUGE_VAL) { + s << "< max : " << bucketCount[i] << "\n"; + } else { + s << "< " << bucketLimit[i] << " : " << bucketCount[i] << "\n"; + } + } +} + +void +SampleHistogram::reset() +{ + this->SampleStatistic::reset(); + if (howManyBuckets > 0) { + for (register int i = 0; i < howManyBuckets; i++) { + bucketCount[i] = 0; + } + } +} + diff --git a/gnu/lib/libg++/libg++/SmplStat.cc b/gnu/lib/libg++/libg++/SmplStat.cc new file mode 100644 index 0000000..461bea4 --- /dev/null +++ b/gnu/lib/libg++/libg++/SmplStat.cc @@ -0,0 +1,160 @@ +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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 <stream.h> +#include <SmplStat.h> +#include <math.h> + +#ifndef HUGE_VAL +#ifdef HUGE +#define HUGE_VAL HUGE +#else +#include <float.h> +#define HUGE_VAL DBL_MAX +#endif +#endif + +// error handling + +void default_SampleStatistic_error_handler(const char* msg) +{ + cerr << "Fatal SampleStatistic error. " << msg << "\n"; + exit(1); +} + +one_arg_error_handler_t SampleStatistic_error_handler = default_SampleStatistic_error_handler; + +one_arg_error_handler_t set_SampleStatistic_error_handler(one_arg_error_handler_t f) +{ + one_arg_error_handler_t old = SampleStatistic_error_handler; + SampleStatistic_error_handler = f; + return old; +} + +void SampleStatistic::error(const char* msg) +{ + (*SampleStatistic_error_handler)(msg); +} + +// t-distribution: given p-value and degrees of freedom, return t-value +// adapted from Peizer & Pratt JASA, vol63, p1416 + +double tval(double p, int df) +{ + double t; + int positive = p >= 0.5; + p = (positive)? 1.0 - p : p; + if (p <= 0.0 || df <= 0) + t = HUGE_VAL; + else if (p == 0.5) + t = 0.0; + else if (df == 1) + t = 1.0 / tan((p + p) * 1.57079633); + else if (df == 2) + t = sqrt(1.0 / ((p + p) * (1.0 - p)) - 2.0); + else + { + double ddf = df; + double a = sqrt(log(1.0 / (p * p))); + double aa = a * a; + a = a - ((2.515517 + (0.802853 * a) + (0.010328 * aa)) / + (1.0 + (1.432788 * a) + (0.189269 * aa) + + (0.001308 * aa * a))); + t = ddf - 0.666666667 + 1.0 / (10.0 * ddf); + t = sqrt(ddf * (exp(a * a * (ddf - 0.833333333) / (t * t)) - 1.0)); + } + return (positive)? t : -t; +} + +void +SampleStatistic::reset() +{ + n = 0; x = x2 = 0.0; + maxValue = -HUGE_VAL; + minValue = HUGE_VAL; +} + +void +SampleStatistic::operator+=(double value) +{ + n += 1; + x += value; + x2 += (value * value); + if ( minValue > value) minValue = value; + if ( maxValue < value) maxValue = value; +} + +double +SampleStatistic::mean() +{ + if ( n > 0) { + return (x / n); + } + else { + return ( 0.0 ); + } +} + +double +SampleStatistic::var() +{ + if ( n > 1) { + return(( x2 - ((x * x) / n)) / ( n - 1)); + } + else { + return ( 0.0 ); + } +} + +double +SampleStatistic::stdDev() +{ + if ( n <= 0 || this -> var() <= 0) { + return(0); + } else { + return( (double) sqrt( var() ) ); + } +} + +double +SampleStatistic::confidence(int interval) +{ + int df = n - 1; + if (df <= 0) return HUGE_VAL; + double t = tval(double(100 + interval) * 0.005, df); + if (t == HUGE_VAL) + return t; + else + return (t * stdDev()) / sqrt(double(n)); +} + +double +SampleStatistic::confidence(double p_value) +{ + int df = n - 1; + if (df <= 0) return HUGE_VAL; + double t = tval((1.0 + p_value) * 0.5, df); + if (t == HUGE_VAL) + return t; + else + return (t * stdDev()) / sqrt(double(n)); +} + + diff --git a/gnu/lib/libg++/libg++/String.cc b/gnu/lib/libg++/libg++/String.cc new file mode 100644 index 0000000..ad86079 --- /dev/null +++ b/gnu/lib/libg++/libg++/String.cc @@ -0,0 +1,1313 @@ +/* +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. +*/ + +/* + String class implementation + */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include <String.h> +#include <std.h> +#include <ctype.h> +#include <limits.h> +#include <new.h> +#include <builtin.h> + +// extern "C" { +#include <regex.h> +// } + +void String::error(const char* msg) const +{ + (*lib_error_handler)("String", msg); +} + +String::operator const char*() const +{ + return (const char*)chars(); +} + +// globals + +StrRep _nilStrRep = { 0, 1, { 0 } }; // nil strings point here +String _nilString; // nil SubStrings point here + + + + +/* + the following inline fcts are specially designed to work + in support of String classes, and are not meant as generic replacements + for libc "str" functions. + + inline copy fcts - I like left-to-right from->to arguments. + all versions assume that `to' argument is non-null + + These are worth doing inline, rather than through calls because, + via procedural integration, adjacent copy calls can be smushed + together by the optimizer. +*/ + +// copy n bytes +inline static void ncopy(const char* from, char* to, int n) +{ + if (from != to) while (--n >= 0) *to++ = *from++; +} + +// copy n bytes, null-terminate +inline static void ncopy0(const char* from, char* to, int n) +{ + if (from != to) + { + while (--n >= 0) *to++ = *from++; + *to = 0; + } + else + to[n] = 0; +} + +// copy until null +inline static void scopy(const char* from, char* to) +{ + if (from != 0) while((*to++ = *from++) != 0); +} + +// copy right-to-left +inline static void revcopy(const char* from, char* to, short n) +{ + if (from != 0) while (--n >= 0) *to-- = *from--; +} + + +inline static int slen(const char* t) // inline strlen +{ + if (t == 0) + return 0; + else + { + const char* a = t; + while (*a++ != 0); + return a - 1 - t; + } +} + +// minimum & maximum representable rep size + +#define MAXStrRep_SIZE ((1 << (sizeof(short) * CHAR_BIT - 1)) - 1) +#define MINStrRep_SIZE 16 + +#ifndef MALLOC_MIN_OVERHEAD +#define MALLOC_MIN_OVERHEAD 4 +#endif + +// The basic allocation primitive: +// Always round request to something close to a power of two. +// This ensures a bit of padding, which often means that +// concatenations don't have to realloc. Plus it tends to +// be faster when lots of Strings are created and discarded, +// since just about any version of malloc (op new()) will +// be faster when it can reuse identically-sized chunks + +inline static StrRep* Snew(int newsiz) +{ + unsigned int siz = sizeof(StrRep) + newsiz + MALLOC_MIN_OVERHEAD; + unsigned int allocsiz = MINStrRep_SIZE; + while (allocsiz < siz) allocsiz <<= 1; + allocsiz -= MALLOC_MIN_OVERHEAD; + if (allocsiz >= MAXStrRep_SIZE) + (*lib_error_handler)("String", "Requested length out of range"); + + StrRep* rep = (StrRep *) new char[allocsiz]; + rep->sz = allocsiz - sizeof(StrRep); + return rep; +} + +// Do-something-while-allocating routines. + +// We live with two ways to signify empty Sreps: either the +// null pointer (0) or a pointer to the nilStrRep. + +// We always signify unknown source lengths (usually when fed a char*) +// via len == -1, in which case it is computed. + +// allocate, copying src if nonull + +StrRep* Salloc(StrRep* old, const char* src, int srclen, int newlen) +{ + if (old == &_nilStrRep) old = 0; + if (srclen < 0) srclen = slen(src); + if (newlen < srclen) newlen = srclen; + StrRep* rep; + if (old == 0 || newlen > old->sz) + rep = Snew(newlen); + else + rep = old; + + rep->len = newlen; + ncopy0(src, rep->s, srclen); + + if (old != rep && old != 0) delete old; + + return rep; +} + +// reallocate: Given the initial allocation scheme, it will +// generally be faster in the long run to get new space & copy +// than to call realloc + +StrRep* Sresize(StrRep* old, int newlen) +{ + if (old == &_nilStrRep) old = 0; + StrRep* rep; + if (old == 0) + rep = Snew(newlen); + else if (newlen > old->sz) + { + rep = Snew(newlen); + ncopy0(old->s, rep->s, old->len); + delete old; + } + else + rep = old; + + rep->len = newlen; + + return rep; +} + +// like allocate, but we know that src is a StrRep + +StrRep* Scopy(StrRep* old, const StrRep* s) +{ + if (old == &_nilStrRep) old = 0; + if (s == &_nilStrRep) s = 0; + if (old == s) + return (old == 0)? &_nilStrRep : old; + else if (s == 0) + { + old->s[0] = 0; + old->len = 0; + return old; + } + else + { + StrRep* rep; + int newlen = s->len; + if (old == 0 || newlen > old->sz) + { + if (old != 0) delete old; + rep = Snew(newlen); + } + else + rep = old; + rep->len = newlen; + ncopy0(s->s, rep->s, newlen); + return rep; + } +} + +// allocate & concatenate + +StrRep* Scat(StrRep* old, const char* s, int srclen, const char* t, int tlen) +{ + if (old == &_nilStrRep) old = 0; + if (srclen < 0) srclen = slen(s); + if (tlen < 0) tlen = slen(t); + int newlen = srclen + tlen; + StrRep* rep; + + if (old == 0 || newlen > old->sz || + (t >= old->s && t < &(old->s[old->len]))) // beware of aliasing + rep = Snew(newlen); + else + rep = old; + + rep->len = newlen; + + ncopy(s, rep->s, srclen); + ncopy0(t, &(rep->s[srclen]), tlen); + + if (old != rep && old != 0) delete old; + + return rep; +} + +// double-concatenate + +StrRep* Scat(StrRep* old, const char* s, int srclen, const char* t, int tlen, + const char* u, int ulen) +{ + if (old == &_nilStrRep) old = 0; + if (srclen < 0) srclen = slen(s); + if (tlen < 0) tlen = slen(t); + if (ulen < 0) ulen = slen(u); + int newlen = srclen + tlen + ulen; + StrRep* rep; + if (old == 0 || newlen > old->sz || + (t >= old->s && t < &(old->s[old->len])) || + (u >= old->s && u < &(old->s[old->len]))) + rep = Snew(newlen); + else + rep = old; + + rep->len = newlen; + + ncopy(s, rep->s, srclen); + ncopy(t, &(rep->s[srclen]), tlen); + ncopy0(u, &(rep->s[srclen+tlen]), ulen); + + if (old != rep && old != 0) delete old; + + return rep; +} + +// like cat, but we know that new stuff goes in the front of existing rep + +StrRep* Sprepend(StrRep* old, const char* t, int tlen) +{ + char* s; + int srclen; + if (old == &_nilStrRep || old == 0) + { + s = 0; old = 0; srclen = 0; + } + else + { + s = old->s; srclen = old->len; + } + if (tlen < 0) tlen = slen(t); + int newlen = srclen + tlen; + StrRep* rep; + if (old == 0 || newlen > old->sz || + (t >= old->s && t < &(old->s[old->len]))) + rep = Snew(newlen); + else + rep = old; + + rep->len = newlen; + + revcopy(&(s[srclen]), &(rep->s[newlen]), srclen+1); + ncopy(t, rep->s, tlen); + + if (old != rep && old != 0) delete old; + + return rep; +} + + +// string compare: first argument is known to be non-null + +inline static int scmp(const char* a, const char* b) +{ + if (b == 0) + return *a != 0; + else + { + signed char diff = 0; + while ((diff = *a - *b++) == 0 && *a++ != 0); + return diff; + } +} + + +inline static int ncmp(const char* a, int al, const char* b, int bl) +{ + int n = (al <= bl)? al : bl; + signed char diff; + while (n-- > 0) if ((diff = *a++ - *b++) != 0) return diff; + return al - bl; +} + +int fcompare(const String& x, const String& y) +{ + const char* a = x.chars(); + const char* b = y.chars(); + int al = x.length(); + int bl = y.length(); + int n = (al <= bl)? al : bl; + signed char diff = 0; + while (n-- > 0) + { + char ac = *a++; + char bc = *b++; + if ((diff = ac - bc) != 0) + { + if (ac >= 'a' && ac <= 'z') + ac = ac - 'a' + 'A'; + if (bc >= 'a' && bc <= 'z') + bc = bc - 'a' + 'A'; + if ((diff = ac - bc) != 0) + return diff; + } + } + return al - bl; +} + +// these are not inline, but pull in the above inlines, so are +// pretty fast + +int compare(const String& x, const char* b) +{ + return scmp(x.chars(), b); +} + +int compare(const String& x, const String& y) +{ + return scmp(x.chars(), y.chars()); +} + +int compare(const String& x, const SubString& y) +{ + return ncmp(x.chars(), x.length(), y.chars(), y.length()); +} + +int compare(const SubString& x, const String& y) +{ + return ncmp(x.chars(), x.length(), y.chars(), y.length()); +} + +int compare(const SubString& x, const SubString& y) +{ + return ncmp(x.chars(), x.length(), y.chars(), y.length()); +} + +int compare(const SubString& x, const char* b) +{ + if (b == 0) + return x.length(); + else + { + const char* a = x.chars(); + int n = x.length(); + signed char diff; + while (n-- > 0) if ((diff = *a++ - *b++) != 0) return diff; + return (*b == 0) ? 0 : -1; + } +} + +/* + index fcts +*/ + +int String::search(int start, int sl, char c) const +{ + const char* s = chars(); + if (sl > 0) + { + if (start >= 0) + { + const char* a = &(s[start]); + const char* lasta = &(s[sl]); + while (a < lasta) if (*a++ == c) return --a - s; + } + else + { + const char* a = &(s[sl + start + 1]); + while (--a >= s) if (*a == c) return a - s; + } + } + return -1; +} + +int String::search(int start, int sl, const char* t, int tl) const +{ + const char* s = chars(); + if (tl < 0) tl = slen(t); + if (sl > 0 && tl > 0) + { + if (start >= 0) + { + const char* lasts = &(s[sl - tl]); + const char* lastt = &(t[tl]); + const char* p = &(s[start]); + + while (p <= lasts) + { + const char* x = p++; + const char* y = t; + while (*x++ == *y++) if (y >= lastt) return --p - s; + } + } + else + { + const char* firsts = &(s[tl - 1]); + const char* lastt = &(t[tl - 1]); + const char* p = &(s[sl + start + 1]); + + while (--p >= firsts) + { + const char* x = p; + const char* y = lastt; + while (*x-- == *y--) if (y < t) return ++x - s; + } + } + } + return -1; +} + +int String::match(int start, int sl, int exact, const char* t, int tl) const +{ + if (tl < 0) tl = slen(t); + + if (start < 0) + { + start = sl + start - tl + 1; + if (start < 0 || (exact && start != 0)) + return -1; + } + else if (exact && sl - start != tl) + return -1; + + if (sl == 0 || tl == 0 || sl - start < tl || start >= sl) + return -1; + + int n = tl; + const char* s = &(rep->s[start]); + while (--n >= 0) if (*s++ != *t++) return -1; + return tl; +} + +void SubString::assign(const StrRep* ysrc, const char* ys, int ylen) +{ + if (&S == &_nilString) return; + + if (ylen < 0) ylen = slen(ys); + StrRep* targ = S.rep; + int sl = targ->len - len + ylen; + + if (ysrc == targ || sl >= targ->sz) + { + StrRep* oldtarg = targ; + targ = Sresize(0, sl); + ncopy(oldtarg->s, targ->s, pos); + ncopy(ys, &(targ->s[pos]), ylen); + scopy(&(oldtarg->s[pos + len]), &(targ->s[pos + ylen])); + delete oldtarg; + } + else if (len == ylen) + ncopy(ys, &(targ->s[pos]), len); + else if (ylen < len) + { + ncopy(ys, &(targ->s[pos]), ylen); + scopy(&(targ->s[pos + len]), &(targ->s[pos + ylen])); + } + else + { + revcopy(&(targ->s[targ->len]), &(targ->s[sl]), targ->len-pos-len +1); + ncopy(ys, &(targ->s[pos]), ylen); + } + targ->len = sl; + S.rep = targ; +} + + + +/* + * substitution + */ + + +int String::_gsub(const char* pat, int pl, const char* r, int rl) +{ + int nmatches = 0; + if (pl < 0) pl = slen(pat); + if (rl < 0) rl = slen(r); + int sl = length(); + if (sl <= 0 || pl <= 0 || sl < pl) + return nmatches; + + const char* s = chars(); + + // prepare to make new rep + StrRep* nrep = 0; + int nsz = 0; + char* x = 0; + + int si = 0; + int xi = 0; + int remaining = sl; + + while (remaining >= pl) + { + int pos = search(si, sl, pat, pl); + if (pos < 0) + break; + else + { + ++nmatches; + int mustfit = xi + remaining + rl - pl; + if (mustfit >= nsz) + { + if (nrep != 0) nrep->len = xi; + nrep = Sresize(nrep, mustfit); + nsz = nrep->sz; + x = nrep->s; + } + pos -= si; + ncopy(&(s[si]), &(x[xi]), pos); + ncopy(r, &(x[xi + pos]), rl); + si += pos + pl; + remaining -= pos + pl; + xi += pos + rl; + } + } + + if (nrep == 0) + { + if (nmatches == 0) + return nmatches; + else + nrep = Sresize(nrep, xi+remaining); + } + + ncopy0(&(s[si]), &(x[xi]), remaining); + nrep->len = xi + remaining; + + if (nrep->len <= rep->sz) // fit back in if possible + { + rep->len = nrep->len; + ncopy0(nrep->s, rep->s, rep->len); + delete(nrep); + } + else + { + delete(rep); + rep = nrep; + } + return nmatches; +} + +int String::_gsub(const Regex& pat, const char* r, int rl) +{ + int nmatches = 0; + int sl = length(); + if (sl <= 0) + return nmatches; + + if (rl < 0) rl = slen(r); + + const char* s = chars(); + + StrRep* nrep = 0; + int nsz = 0; + + char* x = 0; + + int si = 0; + int xi = 0; + int remaining = sl; + int pos, pl = 0; // how long is a regular expression? + + while (remaining > 0) + { + pos = pat.search(s, sl, pl, si); // unlike string search, the pos returned here is absolute + if (pos < 0 || pl <= 0) + break; + else + { + ++nmatches; + int mustfit = xi + remaining + rl - pl; + if (mustfit >= nsz) + { + if (nrep != 0) nrep->len = xi; + nrep = Sresize(nrep, mustfit); + x = nrep->s; + nsz = nrep->sz; + } + pos -= si; + ncopy(&(s[si]), &(x[xi]), pos); + ncopy(r, &(x[xi + pos]), rl); + si += pos + pl; + remaining -= pos + pl; + xi += pos + rl; + } + } + + if (nrep == 0) + { + if (nmatches == 0) + return nmatches; + else + nrep = Sresize(nrep, xi+remaining); + } + + ncopy0(&(s[si]), &(x[xi]), remaining); + nrep->len = xi + remaining; + + if (nrep->len <= rep->sz) // fit back in if possible + { + rep->len = nrep->len; + ncopy0(nrep->s, rep->s, rep->len); + delete(nrep); + } + else + { + delete(rep); + rep = nrep; + } + return nmatches; +} + + +/* + * deletion + */ + +void String::del(int pos, int len) +{ + if (pos < 0 || len <= 0 || (unsigned)(pos + len) > length()) return; + int nlen = length() - len; + int first = pos + len; + ncopy0(&(rep->s[first]), &(rep->s[pos]), length() - first); + rep->len = nlen; +} + +void String::del(const Regex& r, int startpos) +{ + int mlen; + int first = r.search(chars(), length(), mlen, startpos); + del(first, mlen); +} + +void String::del(const char* t, int startpos) +{ + int tlen = slen(t); + int p = search(startpos, length(), t, tlen); + del(p, tlen); +} + +void String::del(const String& y, int startpos) +{ + del(search(startpos, length(), y.chars(), y.length()), y.length()); +} + +void String::del(const SubString& y, int startpos) +{ + del(search(startpos, length(), y.chars(), y.length()), y.length()); +} + +void String::del(char c, int startpos) +{ + del(search(startpos, length(), c), 1); +} + +/* + * substring extraction + */ + + +SubString String::at(int first, int len) +{ + return _substr(first, len); +} + +SubString String::operator() (int first, int len) +{ + return _substr(first, len); +} + +SubString String::before(int pos) +{ + return _substr(0, pos); +} + +SubString String::through(int pos) +{ + return _substr(0, pos+1); +} + +SubString String::after(int pos) +{ + return _substr(pos + 1, length() - (pos + 1)); +} + +SubString String::from(int pos) +{ + return _substr(pos, length() - pos); +} + +SubString String::at(const String& y, int startpos) +{ + int first = search(startpos, length(), y.chars(), y.length()); + return _substr(first, y.length()); +} + +SubString String::at(const SubString& y, int startpos) +{ + int first = search(startpos, length(), y.chars(), y.length()); + return _substr(first, y.length()); +} + +SubString String::at(const Regex& r, int startpos) +{ + int mlen; + int first = r.search(chars(), length(), mlen, startpos); + return _substr(first, mlen); +} + +SubString String::at(const char* t, int startpos) +{ + int tlen = slen(t); + int first = search(startpos, length(), t, tlen); + return _substr(first, tlen); +} + +SubString String::at(char c, int startpos) +{ + int first = search(startpos, length(), c); + return _substr(first, 1); +} + +SubString String::before(const String& y, int startpos) +{ + int last = search(startpos, length(), y.chars(), y.length()); + return _substr(0, last); +} + +SubString String::before(const SubString& y, int startpos) +{ + int last = search(startpos, length(), y.chars(), y.length()); + return _substr(0, last); +} + +SubString String::before(const Regex& r, int startpos) +{ + int mlen; + int first = r.search(chars(), length(), mlen, startpos); + return _substr(0, first); +} + +SubString String::before(char c, int startpos) +{ + int last = search(startpos, length(), c); + return _substr(0, last); +} + +SubString String::before(const char* t, int startpos) +{ + int tlen = slen(t); + int last = search(startpos, length(), t, tlen); + return _substr(0, last); +} + +SubString String::through(const String& y, int startpos) +{ + int last = search(startpos, length(), y.chars(), y.length()); + if (last >= 0) last += y.length(); + return _substr(0, last); +} + +SubString String::through(const SubString& y, int startpos) +{ + int last = search(startpos, length(), y.chars(), y.length()); + if (last >= 0) last += y.length(); + return _substr(0, last); +} + +SubString String::through(const Regex& r, int startpos) +{ + int mlen; + int first = r.search(chars(), length(), mlen, startpos); + if (first >= 0) first += mlen; + return _substr(0, first); +} + +SubString String::through(char c, int startpos) +{ + int last = search(startpos, length(), c); + if (last >= 0) last += 1; + return _substr(0, last); +} + +SubString String::through(const char* t, int startpos) +{ + int tlen = slen(t); + int last = search(startpos, length(), t, tlen); + if (last >= 0) last += tlen; + return _substr(0, last); +} + +SubString String::after(const String& y, int startpos) +{ + int first = search(startpos, length(), y.chars(), y.length()); + if (first >= 0) first += y.length(); + return _substr(first, length() - first); +} + +SubString String::after(const SubString& y, int startpos) +{ + int first = search(startpos, length(), y.chars(), y.length()); + if (first >= 0) first += y.length(); + return _substr(first, length() - first); +} + +SubString String::after(char c, int startpos) +{ + int first = search(startpos, length(), c); + if (first >= 0) first += 1; + return _substr(first, length() - first); +} + +SubString String::after(const Regex& r, int startpos) +{ + int mlen; + int first = r.search(chars(), length(), mlen, startpos); + if (first >= 0) first += mlen; + return _substr(first, length() - first); +} + +SubString String::after(const char* t, int startpos) +{ + int tlen = slen(t); + int first = search(startpos, length(), t, tlen); + if (first >= 0) first += tlen; + return _substr(first, length() - first); +} + +SubString String::from(const String& y, int startpos) +{ + int first = search(startpos, length(), y.chars(), y.length()); + return _substr(first, length() - first); +} + +SubString String::from(const SubString& y, int startpos) +{ + int first = search(startpos, length(), y.chars(), y.length()); + return _substr(first, length() - first); +} + +SubString String::from(const Regex& r, int startpos) +{ + int mlen; + int first = r.search(chars(), length(), mlen, startpos); + return _substr(first, length() - first); +} + +SubString String::from(char c, int startpos) +{ + int first = search(startpos, length(), c); + return _substr(first, length() - first); +} + +SubString String::from(const char* t, int startpos) +{ + int tlen = slen(t); + int first = search(startpos, length(), t, tlen); + return _substr(first, length() - first); +} + + + +/* + * split/join + */ + + +int split(const String& src, String results[], int n, const String& sep) +{ + String x = src; + const char* s = x.chars(); + int sl = x.length(); + int i = 0; + int pos = 0; + while (i < n && pos < sl) + { + int p = x.search(pos, sl, sep.chars(), sep.length()); + if (p < 0) + p = sl; + results[i].rep = Salloc(results[i].rep, &(s[pos]), p - pos, p - pos); + i++; + pos = p + sep.length(); + } + return i; +} + +int split(const String& src, String results[], int n, const Regex& r) +{ + String x = src; + const char* s = x.chars(); + int sl = x.length(); + int i = 0; + int pos = 0; + int p, matchlen; + while (i < n && pos < sl) + { + p = r.search(s, sl, matchlen, pos); + if (p < 0) + p = sl; + results[i].rep = Salloc(results[i].rep, &(s[pos]), p - pos, p - pos); + i++; + pos = p + matchlen; + } + return i; +} + + +#if defined(__GNUG__) && !defined(_G_NO_NRV) + +String join(String src[], int n, const String& separator) return x; +{ + String sep = separator; + int xlen = 0; + for (int i = 0; i < n; ++i) + xlen += src[i].length(); + xlen += (n - 1) * sep.length(); + + x.alloc(xlen); + + int j = 0; + + for (i = 0; i < n - 1; ++i) + { + ncopy(src[i].chars(), &(x.rep->s[j]), src[i].length()); + j += src[i].length(); + ncopy(sep.chars(), &(x.rep->s[j]), sep.length()); + j += sep.length(); + } + ncopy0(src[i].chars(), &(x.rep->s[j]), src[i].length()); +} + +#else + +String join(String src[], int n, const String& separator) +{ + String x; + String sep = separator; + int xlen = 0; + for (int i = 0; i < n; ++i) + xlen += src[i].length(); + xlen += (n - 1) * sep.length(); + + x.alloc(xlen); + + int j = 0; + + for (i = 0; i < n - 1; ++i) + { + ncopy(src[i].chars(), &(x.rep->s[j]), src[i].length()); + j += src[i].length(); + ncopy(sep.chars(), &(x.rep->s[j]), sep.length()); + j += sep.length(); + } + ncopy0(src[i].chars(), &(x.rep->s[j]), src[i].length()); + return x; +} + +#endif + +/* + misc +*/ + + +StrRep* Sreverse(const StrRep* src, StrRep* dest) +{ + int n = src->len; + if (src != dest) + dest = Salloc(dest, src->s, n, n); + if (n > 0) + { + char* a = dest->s; + char* b = &(a[n - 1]); + while (a < b) + { + char t = *a; + *a++ = *b; + *b-- = t; + } + } + return dest; +} + + +StrRep* Supcase(const StrRep* src, StrRep* dest) +{ + int n = src->len; + if (src != dest) dest = Salloc(dest, src->s, n, n); + char* p = dest->s; + char* e = &(p[n]); + for (; p < e; ++p) if (islower(*p)) *p = toupper(*p); + return dest; +} + +StrRep* Sdowncase(const StrRep* src, StrRep* dest) +{ + int n = src->len; + if (src != dest) dest = Salloc(dest, src->s, n, n); + char* p = dest->s; + char* e = &(p[n]); + for (; p < e; ++p) if (isupper(*p)) *p = tolower(*p); + return dest; +} + +StrRep* Scapitalize(const StrRep* src, StrRep* dest) +{ + int n = src->len; + if (src != dest) dest = Salloc(dest, src->s, n, n); + + char* p = dest->s; + char* e = &(p[n]); + for (; p < e; ++p) + { + int at_word; + if (at_word = islower(*p)) + *p = toupper(*p); + else + at_word = isupper(*p) || isdigit(*p); + + if (at_word) + { + while (++p < e) + { + if (isupper(*p)) + *p = tolower(*p); + /* A '\'' does not break a word, so that "Nathan's" stays + "Nathan's" rather than turning into "Nathan'S". */ + else if (!islower(*p) && !isdigit(*p) && (*p != '\'')) + break; + } + } + } + return dest; +} + +#if defined(__GNUG__) && !defined(_G_NO_NRV) + +String replicate(char c, int n) return w; +{ + w.rep = Sresize(w.rep, n); + char* p = w.rep->s; + while (n-- > 0) *p++ = c; + *p = 0; +} + +String replicate(const String& y, int n) return w +{ + int len = y.length(); + w.rep = Sresize(w.rep, n * len); + char* p = w.rep->s; + while (n-- > 0) + { + ncopy(y.chars(), p, len); + p += len; + } + *p = 0; +} + +String common_prefix(const String& x, const String& y, int startpos) return r; +{ + const char* xchars = x.chars(); + const char* ychars = y.chars(); + const char* xs = &(xchars[startpos]); + const char* ss = xs; + const char* topx = &(xchars[x.length()]); + const char* ys = &(ychars[startpos]); + const char* topy = &(ychars[y.length()]); + for (int l = 0; xs < topx && ys < topy && *xs++ == *ys++; ++l); + r.rep = Salloc(r.rep, ss, l, l); +} + +String common_suffix(const String& x, const String& y, int startpos) return r; +{ + const char* xchars = x.chars(); + const char* ychars = y.chars(); + const char* xs = &(xchars[x.length() + startpos]); + const char* botx = xchars; + const char* ys = &(ychars[y.length() + startpos]); + const char* boty = ychars; + for (int l = 0; xs >= botx && ys >= boty && *xs == *ys ; --xs, --ys, ++l); + r.rep = Salloc(r.rep, ++xs, l, l); +} + +#else + +String replicate(char c, int n) +{ + String w; + w.rep = Sresize(w.rep, n); + char* p = w.rep->s; + while (n-- > 0) *p++ = c; + *p = 0; + return w; +} + +String replicate(const String& y, int n) +{ + String w; + int len = y.length(); + w.rep = Sresize(w.rep, n * len); + char* p = w.rep->s; + while (n-- > 0) + { + ncopy(y.chars(), p, len); + p += len; + } + *p = 0; + return w; +} + +String common_prefix(const String& x, const String& y, int startpos) +{ + String r; + const char* xchars = x.chars(); + const char* ychars = y.chars(); + const char* xs = &(xchars[startpos]); + const char* ss = xs; + const char* topx = &(xchars[x.length()]); + const char* ys = &(ychars[startpos]); + const char* topy = &(ychars[y.length()]); + for (int l = 0; xs < topx && ys < topy && *xs++ == *ys++; ++l); + r.rep = Salloc(r.rep, ss, l, l); + return r; +} + +String common_suffix(const String& x, const String& y, int startpos) +{ + String r; + const char* xchars = x.chars(); + const char* ychars = y.chars(); + const char* xs = &(xchars[x.length() + startpos]); + const char* botx = xchars; + const char* ys = &(ychars[y.length() + startpos]); + const char* boty = ychars; + for (int l = 0; xs >= botx && ys >= boty && *xs == *ys ; --xs, --ys, ++l); + r.rep = Salloc(r.rep, ++xs, l, l); + return r; +} + +#endif + +// IO + +istream& operator>>(istream& s, String& x) +{ + if (!s.ipfx(0) || (!(s.flags() & ios::skipws) && !ws(s))) + { + s.clear(ios::failbit|s.rdstate()); // Redundant if using GNU iostreams. + return s; + } + int ch; + int i = 0; + x.rep = Sresize(x.rep, 20); + register streambuf *sb = s.rdbuf(); + while ((ch = sb->sbumpc()) != EOF) + { + if (isspace(ch)) + break; + if (i >= x.rep->sz - 1) + x.rep = Sresize(x.rep, i+1); + x.rep->s[i++] = ch; + } + x.rep->s[i] = 0; + x.rep->len = i; + int new_state = s.rdstate(); + if (i == 0) new_state |= ios::failbit; + if (ch == EOF) new_state |= ios::eofbit; + s.clear(new_state); + return s; +} + +int readline(istream& s, String& x, char terminator, int discard) +{ + if (!s.ipfx(0)) + return 0; + int ch; + int i = 0; + x.rep = Sresize(x.rep, 80); + register streambuf *sb = s.rdbuf(); + while ((ch = sb->sbumpc()) != EOF) + { + if (ch != terminator || !discard) + { + if (i >= x.rep->sz - 1) + x.rep = Sresize(x.rep, i+1); + x.rep->s[i++] = ch; + } + if (ch == terminator) + break; + } + x.rep->s[i] = 0; + x.rep->len = i; + if (ch == EOF) s.clear(ios::eofbit|s.rdstate()); + return i; +} + + +ostream& operator<<(ostream& s, const SubString& x) +{ + const char* a = x.chars(); + const char* lasta = &(a[x.length()]); + while (a < lasta) + s.put(*a++); + return(s); +} + +// from John.Willis@FAS.RI.CMU.EDU + +int String::freq(const SubString& y) const +{ + int found = 0; + for (unsigned int i = 0; i < length(); i++) + if (match(i,length(),0,y.chars(), y.length())>= 0) found++; + return(found); +} + +int String::freq(const String& y) const +{ + int found = 0; + for (unsigned int i = 0; i < length(); i++) + if (match(i,length(),0,y.chars(),y.length()) >= 0) found++; + return(found); +} + +int String::freq(const char* t) const +{ + int found = 0; + for (unsigned int i = 0; i < length(); i++) + if (match(i,length(),0,t) >= 0) found++; + return(found); +} + +int String::freq(char c) const +{ + int found = 0; + for (unsigned int i = 0; i < length(); i++) + if (match(i,length(),0,&c,1) >= 0) found++; + return(found); +} + + +int String::OK() const +{ + if (rep == 0 // don't have a rep + || rep->len > rep->sz // string oustide bounds + || rep->s[rep->len] != 0) // not null-terminated + error("invariant failure"); + return 1; +} + +int SubString::OK() const +{ + int v = S != (const char*)0; // have a String; + v &= S.OK(); // that is legal + v &= pos + len >= S.rep->len;// pos and len within bounds + if (!v) S.error("SubString invariant failure"); + return v; +} + diff --git a/gnu/lib/libg++/libg++/Uniform.cc b/gnu/lib/libg++/libg++/Uniform.cc new file mode 100644 index 0000000..2bf7259 --- /dev/null +++ b/gnu/lib/libg++/libg++/Uniform.cc @@ -0,0 +1,27 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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 <builtin.h> +#include <Random.h> +#include <Uniform.h> + +double Uniform::operator()() +{ + return( pLow + delta * pGenerator -> asDouble() ); +} diff --git a/gnu/lib/libg++/libg++/Weibull.cc b/gnu/lib/libg++/libg++/Weibull.cc new file mode 100644 index 0000000..02670b9 --- /dev/null +++ b/gnu/lib/libg++/libg++/Weibull.cc @@ -0,0 +1,33 @@ +/* +Copyright (C) 1988 Free Software Foundation + written by Dirk Grunwald (grunwald@cs.uiuc.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 <builtin.h> +#include <Random.h> +#include <Weibull.h> + +// +// See Simulation, Modelling & Analysis by Law & Kelton, pp259 +// +// This is the ``polar'' method. +// + +double Weibull::operator()() +{ + return( pow(pBeta * ( - log(1 - pGenerator -> asDouble()) ), pInvAlpha) ); +} diff --git a/gnu/lib/libg++/libg++/bitand.c b/gnu/lib/libg++/libg++/bitand.c new file mode 100644 index 0000000..7809a11 --- /dev/null +++ b/gnu/lib/libg++/libg++/bitand.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1994 Free Software Foundation + +This file is part of the GNU BitString Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#include "bitprims.h" + +/* Copy LENGTH bits from (starting at SRCBIT) into pdst starting at DSTBIT. + This will work even if psrc & pdst overlap. */ + +void +_BS_and (pdst, dstbit, psrc, srcbit, length) + register _BS_word* pdst; + int dstbit; + register const _BS_word* psrc; + int srcbit; + _BS_size_t length; +{ +#define COMBINE(dst, src) (dst) & (src) +#include "bitdo2.h" +} diff --git a/gnu/lib/libg++/libg++/bitany.c b/gnu/lib/libg++/libg++/bitany.c new file mode 100644 index 0000000..861382f --- /dev/null +++ b/gnu/lib/libg++/libg++/bitany.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1994 Free Software Foundation + +This file is part of the GNU BitString Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com) */ + +#include "bitprims.h" + +int +_BS_any (ptr, offset, length) + register const _BS_word *ptr; + int offset; + _BS_size_t length; +{ +#undef DOIT +#define DOIT(WORD, MASK) if ((WORD) & (MASK)) return 1; +#include "bitdo1.h" + return 0; +} diff --git a/gnu/lib/libg++/libg++/bitblt.c b/gnu/lib/libg++/libg++/bitblt.c new file mode 100644 index 0000000..f7c4322 --- /dev/null +++ b/gnu/lib/libg++/libg++/bitblt.c @@ -0,0 +1,97 @@ +/* Copyright (C) 1994 Free Software Foundation + +This file is part of the GNU BitString Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). + Based on ideas in the X11 MFB server. */ + +#include "bitprims.h" +#define ONES ((_BS_word)(~0)) + +/* Copy LENGTH bits from (starting at SRCBIT) into pdst starting at DSTBIT. + This will work even if psrc & pdst overlap. */ + +void +_BS_blt (op, pdst, dstbit, psrc, srcbit, length) + enum _BS_alu op; + register _BS_word* pdst; + int dstbit; + register const _BS_word* psrc; + int srcbit; + _BS_size_t length; +{ + _BS_word ca1, cx1, ca2, cx2; + switch (op) + { + case _BS_alu_clear: + _BS_clear (pdst, dstbit, length); + return; + case _BS_alu_and: + _BS_and (pdst, dstbit, psrc, srcbit, length); + return; + case _BS_alu_andReverse: + ca1 = ONES; cx1 = 0; ca2 = ONES; cx2 = 0; + break; + case _BS_alu_copy: + _BS_copy (pdst, dstbit, psrc, srcbit, length); + return; + case _BS_alu_andInverted: + ca1 = ONES; cx1 = ONES; ca2 = 0; cx2 = 0; + break; + case _BS_alu_noop: + return; + case _BS_alu_xor: + _BS_xor (pdst, dstbit, psrc, srcbit, length); + return; + case _BS_alu_or: + ca1 = ONES; cx1 = ONES; ca2 = ONES; cx2 = 0; + break; + case _BS_alu_nor: + ca1 = ONES; cx1 = ONES; ca2 = ONES; cx2 = ONES; + break; + case_BS_alu_equiv: + ca1 = 0; cx1 = ONES; ca2 = ONES; cx2 = ONES; + break; + case _BS_alu_invert: + _BS_invert (pdst, dstbit, length); + return; + case _BS_alu_orReverse: + ca1 = ONES; cx1 = ONES; ca2 = 0; cx2 = ONES; + break; + case _BS_alu_copyInverted: + ca1 = 0; cx1 = 0; ca2 = ONES; cx2 = ONES; + break; + case _BS_alu_orInverted: + ca1 = ONES; cx1 = 0; ca2 = ONES; cx2 = ONES; + break; + case _BS_alu_nand: + ca1 = ONES; cx1 = 0; ca2 = 0; cx2 = ONES; + break; + case _BS_alu_set: + _BS_set (pdst, dstbit, length); + return; + } + { +#define COMBINE(dst, src) ((dst) & ((src) & ca1 ^ cx1) ^ ((src) & ca2 ^ cx2)) +#include "bitdo2.h" + } +} diff --git a/gnu/lib/libg++/libg++/bitclear.c b/gnu/lib/libg++/libg++/bitclear.c new file mode 100644 index 0000000..8015843 --- /dev/null +++ b/gnu/lib/libg++/libg++/bitclear.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1994 Free Software Foundation + +This file is part of the GNU BitString Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com) */ + +#include "bitprims.h" + +void +_BS_clear (ptr, offset, length) + register _BS_word *ptr; + int offset; + _BS_size_t length; +{ +#undef DOIT +#define DOIT(WORD, MASK) ((WORD) &= ~(MASK)) +#include "bitdo1.h" +} diff --git a/gnu/lib/libg++/libg++/bitcopy.c b/gnu/lib/libg++/libg++/bitcopy.c new file mode 100644 index 0000000..f0f449c --- /dev/null +++ b/gnu/lib/libg++/libg++/bitcopy.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1994 Free Software Foundation + +This file is part of the GNU BitString Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#include "bitprims.h" + +/* Copy LENGTH bits from (starting at SRCBIT) into pdst starting at DSTBIT. + This will work even if psrc & pdst overlap. */ + +void +_BS_copy (pdst, dstbit, psrc, srcbit, length) + register _BS_word* pdst; + int dstbit; + register const _BS_word* psrc; + int srcbit; + _BS_size_t length; +{ +#define COMBINE(dst, src) (src) +#include "bitdo2.h" +} diff --git a/gnu/lib/libg++/libg++/bitcount.c b/gnu/lib/libg++/libg++/bitcount.c new file mode 100644 index 0000000..9a17d17 --- /dev/null +++ b/gnu/lib/libg++/libg++/bitcount.c @@ -0,0 +1,64 @@ +/* Copyright (C) 1994 Free Software Foundation + +This file is part of the GNU BitString Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com) */ + +#include "bitprims.h" + +/* bit_count[I] is number of '1' bits in I. */ +static const unsigned char +four_bit_count[16] = { + 0, 1, 1, 2, + 1, 2, 2, 3, + 1, 2, 2, 3, + 2, 3, 3, 4}; + +#if !defined(inline) && !defined(__GNUC__) && !defined(__cplusplus) +#define inline +#endif + +static inline int +_BS_count_word (word) + register _BS_word word; +{ + register int count = 0; + while (word > 0) + { + count += four_bit_count[word & 15]; + word >>= 4; + } + return count; +} + +int +_BS_count (ptr, offset, length) + register const _BS_word *ptr; + int offset; + _BS_size_t length; +{ + register int count = 0; +#undef DOIT +#define DOIT(WORD, MASK) count += _BS_count_word ((WORD) & (MASK)); +#include "bitdo1.h" + return count; +} diff --git a/gnu/lib/libg++/libg++/bitinvert.c b/gnu/lib/libg++/libg++/bitinvert.c new file mode 100644 index 0000000..50f0369 --- /dev/null +++ b/gnu/lib/libg++/libg++/bitinvert.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1994 Free Software Foundation + +This file is part of the GNU BitString Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com) */ + +#include "bitprims.h" + +void +_BS_invert (ptr, offset, length) + register _BS_word *ptr; + int offset; + _BS_size_t length; +{ +#undef DOIT +#define DOIT(WORD, MASK) ((WORD) ^= (MASK)) +#include "bitdo1.h" +} diff --git a/gnu/lib/libg++/libg++/bitlcomp.c b/gnu/lib/libg++/libg++/bitlcomp.c new file mode 100644 index 0000000..cbcb22e --- /dev/null +++ b/gnu/lib/libg++/libg++/bitlcomp.c @@ -0,0 +1,92 @@ +/* Copyright (C) 1994 Free Software Foundation + +This file is part of the GNU BitString Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com) */ + +#include "bitprims.h" +#include <stdlib.h> + +/* Return -1, 0, 1 depending on whether (ptr0, len0) is + lexicographically less than, equal, or greater than (ptr1, len1). + Both bitstrings must be left-aligned. */ + +int +_BS_lcompare_0 (ptr0, len0, ptr1, len1) + register _BS_word *ptr0; + _BS_size_t len0; + register _BS_word *ptr1; + _BS_size_t len1; +{ + _BS_size_t nwords0 = len0 / _BS_BITS_PER_WORD; + _BS_size_t nwords1 = len1 / _BS_BITS_PER_WORD; + register _BS_word word0, word1, mask; + _BS_size_t nwords = nwords0 > nwords1 ? nwords1 : nwords0; + for (; nwords != 0; nwords--) + { + word0 = *ptr0++; + word1 = *ptr1++; + if (word0 != word1) + { +#if _BS_BIGENDIAN + return (word0 < word1) ? -1 : 1; +#else + mask = 1; + for (;;) + { + int bit0 = word0 & 1; + int bit1 = word1 & 1; + int diff = bit0 - bit1; + if (diff) + return diff; + word0 >>= 1; + word1 >>= 1; + } +#endif + } + } + len0 -= nwords0 * _BS_BITS_PER_WORD; + len1 -= nwords1 * _BS_BITS_PER_WORD; + if (len0 == 0 || len1 == 0) + return len0 == 0 - len1 == 0; + len0 &= _BS_BITS_PER_WORD - 1; + len1 &= _BS_BITS_PER_WORD - 1; + word0 = *ptr0++ & ~((_BS_word)(~0) _BS_RIGHT len0); + word1 = *ptr1++ & ~((_BS_word)(~0) _BS_RIGHT len1); + if (word0 == word1) + return len0 == len1 ? 0 : len0 < len1 ? -1 : 1; +#if _BS_BIGENDIAN + return (word0 < word1) ? -1 : 1; +#else + for (;;) + { + int bit0 = word0 & 1; + int bit1 = word1 & 1; + int diff = bit0 - bit1; + if (diff) + return diff; + word0 >>= 1; + word1 >>= 1; + } +#endif +} + diff --git a/gnu/lib/libg++/libg++/bitset1.c b/gnu/lib/libg++/libg++/bitset1.c new file mode 100644 index 0000000..96e5ebd --- /dev/null +++ b/gnu/lib/libg++/libg++/bitset1.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1994 Free Software Foundation + +This file is part of the GNU BitString Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com) */ + +#include "bitprims.h" + +void +_BS_set (ptr, offset, length) + register _BS_word *ptr; + int offset; + _BS_size_t length; +{ +#undef DOIT +#define DOIT(WORD, MASK) ((WORD) |= (MASK)) +#include "bitdo1.h" +} diff --git a/gnu/lib/libg++/libg++/bitxor.c b/gnu/lib/libg++/libg++/bitxor.c new file mode 100644 index 0000000..0159bb4 --- /dev/null +++ b/gnu/lib/libg++/libg++/bitxor.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1994 Free Software Foundation + +This file is part of the GNU BitString Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#include "bitprims.h" + +/* Copy LENGTH bits from (starting at SRCBIT) into pdst starting at DSTBIT. + This will work even if psrc & pdst overlap. */ + +void +_BS_xor (pdst, dstbit, psrc, srcbit, length) + register _BS_word* pdst; + int dstbit; + register const _BS_word* psrc; + int srcbit; + _BS_size_t length; +{ +#define COMBINE(dst, src) (dst) ^ (src) +#include "bitdo2.h" +} diff --git a/gnu/lib/libg++/libg++/builtin.cc b/gnu/lib/libg++/libg++/builtin.cc new file mode 100644 index 0000000..6b9abe5 --- /dev/null +++ b/gnu/lib/libg++/libg++/builtin.cc @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <builtin.h> diff --git a/gnu/lib/libg++/libg++/chr.cc b/gnu/lib/libg++/libg++/chr.cc new file mode 100644 index 0000000..d580a62 --- /dev/null +++ b/gnu/lib/libg++/libg++/chr.cc @@ -0,0 +1,37 @@ +/* +Copyright (C) 1990 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 <builtin.h> +#include <AllocRing.h> + +extern AllocRing _libgxx_fmtq; + +char* chr(char ch, int width) +{ + int len = 1; + int wrksiz = len + width + 1; + char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); + char* fmt = fmtbase; + for (int blanks = width - len; blanks > 0; --blanks) + *fmt++ = ' '; + *fmt++ = ch; + *fmt = 0; + return fmtbase; +} diff --git a/gnu/lib/libg++/libg++/compare.cc b/gnu/lib/libg++/libg++/compare.cc new file mode 100644 index 0000000..aae8409 --- /dev/null +++ b/gnu/lib/libg++/libg++/compare.cc @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <compare.h> diff --git a/gnu/lib/libg++/libg++/error.cc b/gnu/lib/libg++/libg++/error.cc new file mode 100644 index 0000000..852b3df --- /dev/null +++ b/gnu/lib/libg++/libg++/error.cc @@ -0,0 +1,58 @@ +/* +Copyright (C) 1990 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 <builtin.h> + +#ifdef __GNUC__ +typedef _VOLATILE_VOID (*NoReturnFunc)(void); +/* Cast abort to a _VOLATILE_VOID function, even if <stdlib.h> differs. +This is to avoid a warning from g++ that a `volatile' function does return. */ +#define ABORT() ((NoReturnFunc)abort)() +#else +#define ABORT abort() +#endif + +_VOLATILE_VOID default_one_arg_error_handler(const char* msg) +{ + fputs("Error: ", stderr); + fputs(msg, stderr); + fputs("\n", stderr); + ABORT(); +} + + +_VOLATILE_VOID default_two_arg_error_handler(const char* kind, const char* msg) +{ + fputs(kind, stderr); + fputs(" Error: ", stderr); + fputs(msg, stderr); + fputs("\n", stderr); + ABORT(); +} + +two_arg_error_handler_t lib_error_handler = default_two_arg_error_handler; + +two_arg_error_handler_t set_lib_error_handler(two_arg_error_handler_t f) +{ + two_arg_error_handler_t old = lib_error_handler; + lib_error_handler = f; + return old; +} + diff --git a/gnu/lib/libg++/libg++/fmtq.cc b/gnu/lib/libg++/libg++/fmtq.cc new file mode 100644 index 0000000..7a9dd7b --- /dev/null +++ b/gnu/lib/libg++/libg++/fmtq.cc @@ -0,0 +1,29 @@ +/* +Copyright (C) 1990 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 <builtin.h> +#include <AllocRing.h> + +// AllocRings are used for output operations +// We guaranteee that the last _libgxx_maxfmt formats +// will be intact + +static const int _libgxx_maxfmt = 20; +AllocRing _libgxx_fmtq(_libgxx_maxfmt); diff --git a/gnu/lib/libg++/libg++/gcd.cc b/gnu/lib/libg++/libg++/gcd.cc new file mode 100644 index 0000000..76ff0ef --- /dev/null +++ b/gnu/lib/libg++/libg++/gcd.cc @@ -0,0 +1,52 @@ +/* +Copyright (C) 1990 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 <builtin.h> + + +/* + common functions on built-in types +*/ + +long gcd(long x, long y) // euclid's algorithm +{ + long a = abs(x); + long b = abs(y); + + long tmp; + + if (b > a) + { + tmp = a; a = b; b = tmp; + } + for(;;) + { + if (b == 0) + return a; + else if (b == 1) + return b; + else + { + tmp = b; + b = a % b; + a = tmp; + } + } +} diff --git a/gnu/lib/libg++/libg++/hash.cc b/gnu/lib/libg++/libg++/hash.cc new file mode 100644 index 0000000..4f16f97 --- /dev/null +++ b/gnu/lib/libg++/libg++/hash.cc @@ -0,0 +1,56 @@ +/* +Copyright (C) 1990 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 <builtin.h> + +/* + some useful hash functions +*/ + +unsigned int hashpjw(const char* x) // From Dragon book, p436 +{ + unsigned int h = 0; + unsigned int g; + + while (*x != 0) + { + h = (h << 4) + *x++; + if ((g = h & 0xf0000000) != 0) + h = (h ^ (g >> 24)) ^ g; + } + return h; +} + +unsigned int multiplicativehash(int x) +{ + // uses a const close to golden ratio * pow(2,32) + return ((unsigned)x) * 2654435767; +} + + +unsigned int foldhash(double x) +{ + union { unsigned int i[2]; double d; } u; + u.d = x; + unsigned int u0 = u.i[0]; + unsigned int u1 = u.i[1]; + return u0 ^ u1; +} + diff --git a/gnu/lib/libg++/libg++/ioob.cc b/gnu/lib/libg++/libg++/ioob.cc new file mode 100644 index 0000000..08409a5 --- /dev/null +++ b/gnu/lib/libg++/libg++/ioob.cc @@ -0,0 +1,32 @@ +/* +Copyright (C) 1990 Free Software Foundation + written by Doug Lea (dl@rocky.oswego.edu) + +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 <Obstack.h> + +// Obstacks are used as an easy way to allocate enough space +// for various builtin input operations + + +Obstack _libgxx_io_ob; diff --git a/gnu/lib/libg++/libg++/lg.cc b/gnu/lib/libg++/libg++/lg.cc new file mode 100644 index 0000000..b5ea5fd --- /dev/null +++ b/gnu/lib/libg++/libg++/lg.cc @@ -0,0 +1,32 @@ +/* +Copyright (C) 1990 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 <builtin.h> + +long lg(unsigned long x) +{ + long l = 0; + while (x > 1) + { + x = x >> 1; + ++l; + } + return l; +} diff --git a/gnu/lib/libg++/libg++/math.cc b/gnu/lib/libg++/libg++/math.cc new file mode 100644 index 0000000..f1a0e52 --- /dev/null +++ b/gnu/lib/libg++/libg++/math.cc @@ -0,0 +1,4 @@ +#ifdef __GNUG__ +#pragma implementation +#endif +#include <math.h> diff --git a/gnu/lib/libg++/libg++/new.cc b/gnu/lib/libg++/libg++/new.cc new file mode 100644 index 0000000..7a707a6 --- /dev/null +++ b/gnu/lib/libg++/libg++/new.cc @@ -0,0 +1,31 @@ +// This may look like C code, but it is really -*- C++ -*- + +/* +Copyright (C) 1989 Free Software Foundation + written by Doug Lea (dl@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 <new.h> + +#if 0 /* ndef NO_LIBGXX_MALLOC */ + +void* operator new(size_t n) +{ + return malloc (n); +} +#endif diff --git a/gnu/lib/libg++/libg++/pow.cc b/gnu/lib/libg++/libg++/pow.cc new file mode 100644 index 0000000..b56a8b7 --- /dev/null +++ b/gnu/lib/libg++/libg++/pow.cc @@ -0,0 +1,70 @@ +/* +Copyright (C) 1990 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 <builtin.h> +#include <math.h> + +double pow(double x, long p) +{ + if (p == 0) + return 1.0; + else if (x == 0.0) + return 0.0; + else + { + if (p < 0) + { + p = -p; + x = 1.0 / x; + } + + double r = 1.0; + for(;;) + { + if (p & 1) + r *= x; + if ((p >>= 1) == 0) + return r; + else + x *= x; + } + } +} + +long pow(long x, long p) +{ + if (p == 0) + return 1; + else if (p < 0 || x == 0) + return 0; + else + { + long r = 1; + for(;;) + { + if (p & 1) + r *= x; + if ((p >>= 1) == 0) + return r; + else + x *= x; + } + } +} diff --git a/gnu/lib/libg++/libg++/regex.cc b/gnu/lib/libg++/libg++/regex.cc new file mode 100644 index 0000000..db23a51 --- /dev/null +++ b/gnu/lib/libg++/libg++/regex.cc @@ -0,0 +1,2757 @@ +/* Extended regular expression matching and search library. + Copyright (C) 1985, 1989-90 Free Software Foundation, Inc. + + This program 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 2, or (at your option) + any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +// This is a translation into C++ of regex.c, the GNU regexp package. + +/* To test, compile with -Dtest. This Dtestable feature turns this into + a self-contained program which reads a pattern, describes how it + compiles, then reads a string and searches for it. + + On the other hand, if you compile with both -Dtest and -Dcanned you + can run some tests we've already thought of. */ + +/* AIX requires the alloca decl to be the first thing in the file. */ +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else +#ifdef sparc +#include <alloca.h> +extern "C" void *__builtin_alloca(...); +#else +#ifdef _AIX +#pragma alloca +#else +char *alloca (); +#endif +#endif +#endif + +#ifdef emacs + +/* The `emacs' switch turns on certain special matching commands + that make sense only in emacs. */ + +#include "config.h" +#include "lisp.h" +#include "buffer.h" +#include "syntax.h" + +#else /* not emacs */ + +#include <_G_config.h> +#include <string.h> +#include <stdlib.h> + +/* Define the syntax stuff, so we can do the \<, \>, etc. */ + +/* This must be nonzero for the wordchar and notwordchar pattern + commands in re_match_2. */ +#ifndef Sword +#define Sword 1 +#endif + +#define SYNTAX(c) re_syntax_table[c] + + +#ifdef SYNTAX_TABLE + +char *re_syntax_table; + +#else /* not SYNTAX_TABLE */ + +static char re_syntax_table[256]; + + +static void +init_syntax_once () +{ + register int c; + static int done = 0; + + if (done) + return; + + memset (re_syntax_table, 0, sizeof re_syntax_table); + + for (c = 'a'; c <= 'z'; c++) + re_syntax_table[c] = Sword; + + for (c = 'A'; c <= 'Z'; c++) + re_syntax_table[c] = Sword; + + for (c = '0'; c <= '9'; c++) + re_syntax_table[c] = Sword; + + done = 1; +} + +#endif /* SYNTAX_TABLE */ +#endif /* emacs */ + +/* We write fatal error messages on standard error. */ +#include <stdio.h> + +/* isalpha(3) etc. are used for the character classes. */ +#include <ctype.h> +/* Sequents are missing isgraph. */ +#ifndef isgraph +#define isgraph(c) (isprint((c)) && !isspace((c))) +#endif + +/* Get the interface, including the syntax bits. */ +#include "regex.h" + + +/* These are the command codes that appear in compiled regular + expressions, one per byte. Some command codes are followed by + argument bytes. A command code can specify any interpretation + whatsoever for its arguments. Zero-bytes may appear in the compiled + regular expression. + + The value of `exactn' is needed in search.c (search_buffer) in emacs. + So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of + `exactn' we use here must also be 1. */ + +enum regexpcode + { + unused=0, + exactn=1, /* Followed by one byte giving n, then by n literal bytes. */ + begline, /* Fail unless at beginning of line. */ + endline, /* Fail unless at end of line. */ + jump, /* Followed by two bytes giving relative address to jump to. */ + on_failure_jump, /* Followed by two bytes giving relative address of + place to resume at in case of failure. */ + finalize_jump, /* Throw away latest failure point and then jump to + address. */ + maybe_finalize_jump, /* Like jump but finalize if safe to do so. + This is used to jump back to the beginning + of a repeat. If the command that follows + this jump is clearly incompatible with the + one at the beginning of the repeat, such that + we can be sure that there is no use backtracking + out of repetitions already completed, + then we finalize. */ + dummy_failure_jump, /* Jump, and push a dummy failure point. This + failure point will be thrown away if an attempt + is made to use it for a failure. A + construct + makes this before the first repeat. Also + use it as an intermediary kind of jump when + compiling an or construct. */ + succeed_n, /* Used like on_failure_jump except has to succeed n times; + then gets turned into an on_failure_jump. The relative + address following it is useless until then. The + address is followed by two bytes containing n. */ + jump_n, /* Similar to jump, but jump n times only; also the relative + address following is in turn followed by yet two more bytes + containing n. */ + set_number_at, /* Set the following relative location to the + subsequent number. */ + anychar, /* Matches any (more or less) one character. */ + charset, /* Matches any one char belonging to specified set. + First following byte is number of bitmap bytes. + Then come bytes for a bitmap saying which chars are in. + Bits in each byte are ordered low-bit-first. + A character is in the set if its bit is 1. + A character too large to have a bit in the map + is automatically not in the set. */ + charset_not, /* Same parameters as charset, but match any character + that is not one of those specified. */ + start_memory, /* Start remembering the text that is matched, for + storing in a memory register. Followed by one + byte containing the register number. Register numbers + must be in the range 0 through RE_NREGS. */ + stop_memory, /* Stop remembering the text that is matched + and store it in a memory register. Followed by + one byte containing the register number. Register + numbers must be in the range 0 through RE_NREGS. */ + duplicate, /* Match a duplicate of something remembered. + Followed by one byte containing the index of the memory + register. */ +#ifdef emacs + before_dot, /* Succeeds if before point. */ + at_dot, /* Succeeds if at point. */ + after_dot, /* Succeeds if after point. */ +#endif + begbuf, /* Succeeds if at beginning of buffer. */ + endbuf, /* Succeeds if at end of buffer. */ + wordchar, /* Matches any word-constituent character. */ + notwordchar, /* Matches any char that is not a word-constituent. */ + wordbeg, /* Succeeds if at word beginning. */ + wordend, /* Succeeds if at word end. */ + wordbound, /* Succeeds if at a word boundary. */ + notwordbound /* Succeeds if not at a word boundary. */ +#ifdef emacs + ,syntaxspec, /* Matches any character whose syntax is specified. + followed by a byte which contains a syntax code, + e.g., Sword. */ + notsyntaxspec /* Matches any character whose syntax differs from + that specified. */ +#endif + }; + + +/* Number of failure points to allocate space for initially, + when matching. If this number is exceeded, more space is allocated, + so it is not a hard limit. */ + +#ifndef NFAILURES +#define NFAILURES 80 +#endif + + +#ifndef SIGN_EXTEND_CHAR +#ifdef __STDC__ +#define SIGN_EXTEND_CHAR(c) ((signed char)(c)) +#else +#define SIGN_EXTEND_CHAR(c) (((c)^128) - 128) /* As in Harbison and Steele. */ +#endif +#endif /* not SIGN_EXTEND_CHAR */ + +/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ +#define STORE_NUMBER(destination, number) \ + { (destination)[0] = (char)((number) & 0377); \ + (destination)[1] = (number) >> 8; } + +/* Same as STORE_NUMBER, except increment the destination pointer to + the byte after where the number is stored. Watch out that values for + DESTINATION such as p + 1 won't work, whereas p will. */ +#define STORE_NUMBER_AND_INCR(destination, number) \ + { STORE_NUMBER(destination, number); \ + (destination) += 2; } + + +/* Put into DESTINATION a number stored in two contingous bytes starting + at SOURCE. */ +#define EXTRACT_NUMBER(destination, source) \ + { (destination) = *(source) & 0377; \ + (destination) += SIGN_EXTEND_CHAR (*(char *)((source) + 1)) << 8; } + +/* Same as EXTRACT_NUMBER, except increment the pointer for source to + point to second byte of SOURCE. Note that SOURCE has to be a value + such as p, not, e.g., p + 1. */ +#define EXTRACT_NUMBER_AND_INCR(destination, source) \ + { EXTRACT_NUMBER (destination, source); \ + (source) += 2; } + + +/* Specify the precise syntax of regexps for compilation. This provides + for compatibility for various utilities which historically have + different, incompatible syntaxes. + + The argument SYNTAX is a bit-mask comprised of the various bits + defined in regex.h. */ + +int +re_set_syntax (int syntax) +{ + int ret; + + ret = obscure_syntax; + obscure_syntax = syntax; + return ret; +} + +/* Set by re_set_syntax to the current regexp syntax to recognize. */ +int obscure_syntax = 0; + + + +/* Macros for re_compile_pattern, which is found below these definitions. */ + +#define CHAR_CLASS_MAX_LENGTH 6 + +/* Fetch the next character in the uncompiled pattern, translating it if + necessary. */ +#define PATFETCH(c) \ + {if (p == pend) goto end_of_pattern; \ + c = * (const unsigned char *) p++; \ + if (translate) c = translate[c]; } + +/* Fetch the next character in the uncompiled pattern, with no + translation. */ +#define PATFETCH_RAW(c) \ + {if (p == pend) goto end_of_pattern; \ + c = * (const unsigned char *) p++; } + +#define PATUNFETCH p-- + + +/* If the buffer isn't allocated when it comes in, use this. */ +#define INIT_BUF_SIZE 28 + +/* Make sure we have at least N more bytes of space in buffer. */ +#define GET_BUFFER_SPACE(n) \ + { \ + while (b - bufp->buffer + (n) >= bufp->allocated) \ + EXTEND_BUFFER; \ + } + +/* Make sure we have one more byte of buffer space and then add CH to it. */ +#define BUFPUSH(ch) \ + { \ + GET_BUFFER_SPACE (1); \ + *b++ = (char) (ch); \ + } + +/* Extend the buffer by twice its current size via reallociation and + reset the pointers that pointed into the old allocation to point to + the correct places in the new allocation. If extending the buffer + results in it being larger than 1 << 16, then flag memory exhausted. */ +#define EXTEND_BUFFER \ + { char *old_buffer = bufp->buffer; \ + if (bufp->allocated == (1L<<16)) goto too_big; \ + bufp->allocated *= 2; \ + if (bufp->allocated > (1L<<16)) bufp->allocated = (1L<<16); \ + bufp->buffer = (char *) realloc (bufp->buffer, bufp->allocated); \ + if (bufp->buffer == 0) \ + goto memory_exhausted; \ + b = (b - old_buffer) + bufp->buffer; \ + if (fixup_jump) \ + fixup_jump = (fixup_jump - old_buffer) + bufp->buffer; \ + if (laststart) \ + laststart = (laststart - old_buffer) + bufp->buffer; \ + begalt = (begalt - old_buffer) + bufp->buffer; \ + if (pending_exact) \ + pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ + } + +/* Set the bit for character C in a character set list. */ +#define SET_LIST_BIT(c) (b[(c) / BYTEWIDTH] |= 1 << ((c) % BYTEWIDTH)) + +/* Get the next unsigned number in the uncompiled pattern. */ +#define GET_UNSIGNED_NUMBER(num) \ + { if (p != pend) \ + { \ + PATFETCH (c); \ + while (isdigit (c)) \ + { \ + if (num < 0) \ + num = 0; \ + num = num * 10 + c - '0'; \ + if (p == pend) \ + break; \ + PATFETCH (c); \ + } \ + } \ + } + +/* Subroutines for re_compile_pattern. */ +static void store_jump (char *from, char opcode, char *to); +static void insert_jump (char op, char *from, char *to, char *current_end); +static void store_jump_n (char *from, char opcode, char *to, unsigned n); +static void insert_jump_n (char, char *, char *, char *, unsigned); +static void insert_op_2 (char, char *, char *_end, int, int); + + +/* re_compile_pattern takes a regular-expression string + and converts it into a buffer full of byte commands for matching. + + PATTERN is the address of the pattern string + SIZE is the length of it. + BUFP is a struct re_pattern_buffer * which points to the info + on where to store the byte commands. + This structure contains a char * which points to the + actual space, which should have been obtained with malloc. + re_compile_pattern may use realloc to grow the buffer space. + + The number of bytes of commands can be found out by looking in + the `struct re_pattern_buffer' that bufp pointed to, after + re_compile_pattern returns. */ + +char * +re_compile_pattern (const char *pattern, int size, struct re_pattern_buffer *bufp) +{ + register char *b = bufp->buffer; + register const char *p = pattern; + const char *pend = pattern + size; + register unsigned c, c1; + const char *p1; + unsigned char *translate = (unsigned char *) bufp->translate; + + /* Address of the count-byte of the most recently inserted `exactn' + command. This makes it possible to tell whether a new exact-match + character can be added to that command or requires a new `exactn' + command. */ + + char *pending_exact = 0; + + /* Address of the place where a forward-jump should go to the end of + the containing expression. Each alternative of an `or', except the + last, ends with a forward-jump of this sort. */ + + char *fixup_jump = 0; + + /* Address of start of the most recently finished expression. + This tells postfix * where to find the start of its operand. */ + + char *laststart = 0; + + /* In processing a repeat, 1 means zero matches is allowed. */ + + char zero_times_ok; + + /* In processing a repeat, 1 means many matches is allowed. */ + + char many_times_ok; + + /* Address of beginning of regexp, or inside of last \(. */ + + char *begalt = b; + + /* In processing an interval, at least this many matches must be made. */ + int lower_bound; + + /* In processing an interval, at most this many matches can be made. */ + int upper_bound; + + /* Place in pattern (i.e., the {) to which to go back if the interval + is invalid. */ + const char *beg_interval = 0; + + /* Stack of information saved by \( and restored by \). + Four stack elements are pushed by each \(: + First, the value of b. + Second, the value of fixup_jump. + Third, the value of regnum. + Fourth, the value of begalt. */ + + int stackb[40]; + int *stackp = stackb; + int *stacke = stackb + 40; + int *stackt; + + /* Counts \('s as they are encountered. Remembered for the matching \), + where it becomes the register number to put in the stop_memory + command. */ + + unsigned regnum = 1; + + bufp->fastmap_accurate = 0; + +#ifndef emacs +#ifndef SYNTAX_TABLE + /* Initialize the syntax table. */ + init_syntax_once(); +#endif +#endif + + if (bufp->allocated == 0) + { + bufp->allocated = INIT_BUF_SIZE; + if (bufp->buffer) + /* EXTEND_BUFFER loses when bufp->allocated is 0. */ + bufp->buffer = (char *) realloc (bufp->buffer, INIT_BUF_SIZE); + else + /* Caller did not allocate a buffer. Do it for them. */ + bufp->buffer = (char *) malloc (INIT_BUF_SIZE); + if (!bufp->buffer) goto memory_exhausted; + begalt = b = bufp->buffer; + } + + while (p != pend) + { + PATFETCH (c); + + switch (c) + { + case '$': + { + const char *p1 = p; + /* When testing what follows the $, + look past the \-constructs that don't consume anything. */ + if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) + while (p1 != pend) + { + if (*p1 == '\\' && p1 + 1 != pend + && (p1[1] == '<' || p1[1] == '>' + || p1[1] == '`' || p1[1] == '\'' +#ifdef emacs + || p1[1] == '=' +#endif + || p1[1] == 'b' || p1[1] == 'B')) + p1 += 2; + else + break; + } + if (obscure_syntax & RE_TIGHT_VBAR) + { + if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS) && p1 != pend) + goto normal_char; + /* Make operand of last vbar end before this `$'. */ + if (fixup_jump) + store_jump (fixup_jump, jump, b); + fixup_jump = 0; + BUFPUSH (endline); + break; + } + /* $ means succeed if at end of line, but only in special contexts. + If validly in the middle of a pattern, it is a normal character. */ + + if ((obscure_syntax & RE_CONTEXTUAL_INVALID_OPS) && p1 != pend) + goto invalid_pattern; + if (p1 == pend || *p1 == '\n' + || (obscure_syntax & RE_CONTEXT_INDEP_OPS) + || (obscure_syntax & RE_NO_BK_PARENS + ? *p1 == ')' + : *p1 == '\\' && p1[1] == ')') + || (obscure_syntax & RE_NO_BK_VBAR + ? *p1 == '|' + : *p1 == '\\' && p1[1] == '|')) + { + BUFPUSH (endline); + break; + } + goto normal_char; + } + case '^': + /* ^ means succeed if at beg of line, but only if no preceding + pattern. */ + + if ((obscure_syntax & RE_CONTEXTUAL_INVALID_OPS) && laststart) + goto invalid_pattern; + if (laststart && p - 2 >= pattern && p[-2] != '\n' + && !(obscure_syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + if (obscure_syntax & RE_TIGHT_VBAR) + { + if (p != pattern + 1 + && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + BUFPUSH (begline); + begalt = b; + } + else + BUFPUSH (begline); + break; + + case '+': + case '?': + if ((obscure_syntax & RE_BK_PLUS_QM) + || (obscure_syntax & RE_LIMITED_OPS)) + goto normal_char; + handle_plus: + case '*': + /* If there is no previous pattern, char not special. */ + if (!laststart) + { + if (obscure_syntax & RE_CONTEXTUAL_INVALID_OPS) + goto invalid_pattern; + else if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + } + /* If there is a sequence of repetition chars, + collapse it down to just one. */ + zero_times_ok = 0; + many_times_ok = 0; + while (1) + { + zero_times_ok |= c != '+'; + many_times_ok |= c != '?'; + if (p == pend) + break; + PATFETCH (c); + if (c == '*') + ; + else if (!(obscure_syntax & RE_BK_PLUS_QM) + && (c == '+' || c == '?')) + ; + else if ((obscure_syntax & RE_BK_PLUS_QM) + && c == '\\') + { + int c1; + PATFETCH (c1); + if (!(c1 == '+' || c1 == '?')) + { + PATUNFETCH; + PATUNFETCH; + break; + } + c = c1; + } + else + { + PATUNFETCH; + break; + } + } + + /* Star, etc. applied to an empty pattern is equivalent + to an empty pattern. */ + if (!laststart) + break; + + /* Now we know whether or not zero matches is allowed + and also whether or not two or more matches is allowed. */ + if (many_times_ok) + { + /* If more than one repetition is allowed, put in at the + end a backward relative jump from b to before the next + jump we're going to put in below (which jumps from + laststart to after this jump). */ + GET_BUFFER_SPACE (3); + store_jump (b, maybe_finalize_jump, laststart - 3); + b += 3; /* Because store_jump put stuff here. */ + } + /* On failure, jump from laststart to b + 3, which will be the + end of the buffer after this jump is inserted. */ + GET_BUFFER_SPACE (3); + insert_jump (on_failure_jump, laststart, b + 3, b); + pending_exact = 0; + b += 3; + if (!zero_times_ok) + { + /* At least one repetition is required, so insert a + dummy-failure before the initial on-failure-jump + instruction of the loop. This effects a skip over that + instruction the first time we hit that loop. */ + GET_BUFFER_SPACE (6); + insert_jump (dummy_failure_jump, laststart, laststart + 6, b); + b += 3; + } + break; + + case '.': + laststart = b; + BUFPUSH (anychar); + break; + + case '[': + if (p == pend) + goto invalid_pattern; + while (b - bufp->buffer + > bufp->allocated - 3 - (1 << BYTEWIDTH) / BYTEWIDTH) + EXTEND_BUFFER; + + laststart = b; + if (*p == '^') + { + BUFPUSH (charset_not); + p++; + } + else + BUFPUSH (charset); + p1 = p; + + BUFPUSH ((1 << BYTEWIDTH) / BYTEWIDTH); + /* Clear the whole map */ + memset (b, 0, (1 << BYTEWIDTH) / BYTEWIDTH); + + if ((obscure_syntax & RE_HAT_NOT_NEWLINE) && b[-2] == charset_not) + SET_LIST_BIT ('\n'); + + + /* Read in characters and ranges, setting map bits. */ + while (1) + { + /* Don't translate while fetching, in case it's a range bound. + When we set the bit for the character, we translate it. */ + PATFETCH_RAW (c); + + /* If set, \ escapes characters when inside [...]. */ + if ((obscure_syntax & RE_AWK_CLASS_HACK) && c == '\\') + { + PATFETCH(c1); + SET_LIST_BIT (c1); + continue; + } + if (c == ']') + { + if (p == p1 + 1) + { + /* If this is an empty bracket expression. */ + if ((obscure_syntax & RE_NO_EMPTY_BRACKETS) + && p == pend) + goto invalid_pattern; + } + else + /* Stop if this isn't merely a ] inside a bracket + expression, but rather the end of a bracket + expression. */ + break; + } + /* Get a range. */ + if (p[0] == '-' && p[1] != ']') + { + PATFETCH (c1); + /* Don't translate the range bounds while fetching them. */ + PATFETCH_RAW (c1); + + if ((obscure_syntax & RE_NO_EMPTY_RANGES) && c > c1) + goto invalid_pattern; + + if ((obscure_syntax & RE_NO_HYPHEN_RANGE_END) + && c1 == '-' && *p != ']') + goto invalid_pattern; + + while (c <= c1) + { + /* Translate each char that's in the range. */ + if (translate) + SET_LIST_BIT (translate[c]); + else + SET_LIST_BIT (c); + c++; + } + } + else if ((obscure_syntax & RE_CHAR_CLASSES) + && c == '[' && p[0] == ':') + { + /* Longest valid character class word has six characters. */ + char str[CHAR_CLASS_MAX_LENGTH]; + PATFETCH (c); + c1 = 0; + /* If no ] at end. */ + if (p == pend) + goto invalid_pattern; + while (1) + { + /* Don't translate the ``character class'' characters. */ + PATFETCH_RAW (c); + if (c == ':' || c == ']' || p == pend + || c1 == CHAR_CLASS_MAX_LENGTH) + break; + str[c1++] = c; + } + str[c1] = '\0'; + if (p == pend + || c == ']' /* End of the bracket expression. */ + || p[0] != ']' + || p + 1 == pend + || (strcmp (str, "alpha") != 0 + && strcmp (str, "upper") != 0 + && strcmp (str, "lower") != 0 + && strcmp (str, "digit") != 0 + && strcmp (str, "alnum") != 0 + && strcmp (str, "xdigit") != 0 + && strcmp (str, "space") != 0 + && strcmp (str, "print") != 0 + && strcmp (str, "punct") != 0 + && strcmp (str, "graph") != 0 + && strcmp (str, "cntrl") != 0)) + { + /* Undo the ending character, the letters, and leave + the leading : and [ (but set bits for them). */ + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT ('['); + SET_LIST_BIT (':'); + } + else + { + /* The ] at the end of the character class. */ + PATFETCH (c); + if (c != ']') + goto invalid_pattern; + for (c = 0; c < (1 << BYTEWIDTH); c++) + { + if ((strcmp (str, "alpha") == 0 && isalpha (c)) + || (strcmp (str, "upper") == 0 && isupper (c)) + || (strcmp (str, "lower") == 0 && islower (c)) + || (strcmp (str, "digit") == 0 && isdigit (c)) + || (strcmp (str, "alnum") == 0 && isalnum (c)) + || (strcmp (str, "xdigit") == 0 && isxdigit (c)) + || (strcmp (str, "space") == 0 && isspace (c)) + || (strcmp (str, "print") == 0 && isprint (c)) + || (strcmp (str, "punct") == 0 && ispunct (c)) + || (strcmp (str, "graph") == 0 && isgraph (c)) + || (strcmp (str, "cntrl") == 0 && iscntrl (c))) + SET_LIST_BIT (c); + } + } + } + else if (translate) + SET_LIST_BIT (translate[c]); + else + SET_LIST_BIT (c); + } + + /* Discard any character set/class bitmap bytes that are all + 0 at the end of the map. Decrement the map-length byte too. */ + while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) + b[-1]--; + b += b[-1]; + break; + + case '(': + if (! (obscure_syntax & RE_NO_BK_PARENS)) + goto normal_char; + else + goto handle_open; + + case ')': + if (! (obscure_syntax & RE_NO_BK_PARENS)) + goto normal_char; + else + goto handle_close; + + case '\n': + if (! (obscure_syntax & RE_NEWLINE_OR)) + goto normal_char; + else + goto handle_bar; + + case '|': + if ((obscure_syntax & RE_CONTEXTUAL_INVALID_OPS) + && (! laststart || p == pend)) + goto invalid_pattern; + else if (! (obscure_syntax & RE_NO_BK_VBAR)) + goto normal_char; + else + goto handle_bar; + + case '{': + if (! ((obscure_syntax & RE_NO_BK_CURLY_BRACES) + && (obscure_syntax & RE_INTERVALS))) + goto normal_char; + else + goto handle_interval; + + case '\\': + if (p == pend) goto invalid_pattern; + PATFETCH_RAW (c); + switch (c) + { + case '(': + if (obscure_syntax & RE_NO_BK_PARENS) + goto normal_backsl; + handle_open: + if (stackp == stacke) goto nesting_too_deep; + + /* Laststart should point to the start_memory that we are about + to push (unless the pattern has RE_NREGS or more ('s). */ + *stackp++ = b - bufp->buffer; + if (regnum < RE_NREGS) + { + BUFPUSH (start_memory); + BUFPUSH (regnum); + } + *stackp++ = fixup_jump ? fixup_jump - bufp->buffer + 1 : 0; + *stackp++ = regnum++; + *stackp++ = begalt - bufp->buffer; + fixup_jump = 0; + laststart = 0; + begalt = b; + break; + + case ')': + if (obscure_syntax & RE_NO_BK_PARENS) + goto normal_backsl; + handle_close: + if (stackp == stackb) goto unmatched_close; + begalt = *--stackp + bufp->buffer; + if (fixup_jump) + store_jump (fixup_jump, jump, b); + if (stackp[-1] < RE_NREGS) + { + BUFPUSH (stop_memory); + BUFPUSH (stackp[-1]); + } + stackp -= 2; + fixup_jump = *stackp ? *stackp + bufp->buffer - 1 : 0; + laststart = *--stackp + bufp->buffer; + break; + + case '|': + if ((obscure_syntax & RE_LIMITED_OPS) + || (obscure_syntax & RE_NO_BK_VBAR)) + goto normal_backsl; + handle_bar: + if (obscure_syntax & RE_LIMITED_OPS) + goto normal_char; + /* Insert before the previous alternative a jump which + jumps to this alternative if the former fails. */ + GET_BUFFER_SPACE (6); + insert_jump (on_failure_jump, begalt, b + 6, b); + pending_exact = 0; + b += 3; + /* The alternative before the previous alternative has a + jump after it which gets executed if it gets matched. + Adjust that jump so it will jump to the previous + alternative's analogous jump (put in below, which in + turn will jump to the next (if any) alternative's such + jump, etc.). The last such jump jumps to the correct + final destination. */ + if (fixup_jump) + store_jump (fixup_jump, jump, b); + + /* Leave space for a jump after previous alternative---to be + filled in later. */ + fixup_jump = b; + b += 3; + + laststart = 0; + begalt = b; + break; + + case '{': + if (! (obscure_syntax & RE_INTERVALS) + /* Let \{ be a literal. */ + || ((obscure_syntax & RE_INTERVALS) + && (obscure_syntax & RE_NO_BK_CURLY_BRACES)) + /* If it's the string "\{". */ + || (p - 2 == pattern && p == pend)) + goto normal_backsl; + handle_interval: + beg_interval = p - 1; /* The {. */ + /* If there is no previous pattern, this isn't an interval. */ + if (!laststart) + { + if (obscure_syntax & RE_CONTEXTUAL_INVALID_OPS) + goto invalid_pattern; + else + goto normal_backsl; + } + /* It also isn't an interval if not preceded by an re + matching a single character or subexpression, or if + the current type of intervals can't handle back + references and the previous thing is a back reference. */ + if (! (*laststart == anychar + || *laststart == charset + || *laststart == charset_not + || *laststart == start_memory + || (*laststart == exactn && laststart[1] == 1) + || (! (obscure_syntax & RE_NO_BK_REFS) + && *laststart == duplicate))) + { + if (obscure_syntax & RE_NO_BK_CURLY_BRACES) + goto normal_char; + + /* Posix extended syntax is handled in previous + statement; this is for Posix basic syntax. */ + if (obscure_syntax & RE_INTERVALS) + goto invalid_pattern; + + goto normal_backsl; + } + lower_bound = -1; /* So can see if are set. */ + upper_bound = -1; + GET_UNSIGNED_NUMBER (lower_bound); + if (c == ',') + { + GET_UNSIGNED_NUMBER (upper_bound); + if (upper_bound < 0) + upper_bound = RE_DUP_MAX; + } + if (upper_bound < 0) + upper_bound = lower_bound; + if (! (obscure_syntax & RE_NO_BK_CURLY_BRACES)) + { + if (c != '\\') + goto invalid_pattern; + PATFETCH (c); + } + if (c != '}' || lower_bound < 0 || upper_bound > RE_DUP_MAX + || lower_bound > upper_bound + || ((obscure_syntax & RE_NO_BK_CURLY_BRACES) + && p != pend && *p == '{')) + { + if (obscure_syntax & RE_NO_BK_CURLY_BRACES) + goto unfetch_interval; + else + goto invalid_pattern; + } + + /* If upper_bound is zero, don't want to succeed at all; + jump from laststart to b + 3, which will be the end of + the buffer after this jump is inserted. */ + + if (upper_bound == 0) + { + GET_BUFFER_SPACE (3); + insert_jump (jump, laststart, b + 3, b); + b += 3; + } + + /* Otherwise, after lower_bound number of succeeds, jump + to after the jump_n which will be inserted at the end + of the buffer, and insert that jump_n. */ + else + { /* Set to 5 if only one repetition is allowed and + hence no jump_n is inserted at the current end of + the buffer; then only space for the succeed_n is + needed. Otherwise, need space for both the + succeed_n and the jump_n. */ + + unsigned slots_needed = upper_bound == 1 ? 5 : 10; + + GET_BUFFER_SPACE ((int) slots_needed); + /* Initialize the succeed_n to n, even though it will + be set by its attendant set_number_at, because + re_compile_fastmap will need to know it. Jump to + what the end of buffer will be after inserting + this succeed_n and possibly appending a jump_n. */ + insert_jump_n (succeed_n, laststart, b + slots_needed, + b, lower_bound); + b += 5; /* Just increment for the succeed_n here. */ + + /* More than one repetition is allowed, so put in at + the end of the buffer a backward jump from b to the + succeed_n we put in above. By the time we've gotten + to this jump when matching, we'll have matched once + already, so jump back only upper_bound - 1 times. */ + + if (upper_bound > 1) + { + store_jump_n (b, jump_n, laststart, upper_bound - 1); + b += 5; + /* When hit this when matching, reset the + preceding jump_n's n to upper_bound - 1. */ + BUFPUSH (set_number_at); + GET_BUFFER_SPACE (2); + STORE_NUMBER_AND_INCR (b, -5); + STORE_NUMBER_AND_INCR (b, upper_bound - 1); + } + /* When hit this when matching, set the succeed_n's n. */ + GET_BUFFER_SPACE (5); + insert_op_2 (set_number_at, laststart, b, 5, lower_bound); + b += 5; + } + pending_exact = 0; + beg_interval = 0; + break; + + + unfetch_interval: + /* If an invalid interval, match the characters as literals. */ + if (beg_interval) + p = beg_interval; + else + { + fprintf (stderr, + "regex: no interval beginning to which to backtrack.\n"); + exit (1); + } + + beg_interval = 0; + PATFETCH (c); /* normal_char expects char in `c'. */ + goto normal_char; + break; + +#ifdef emacs + case '=': + BUFPUSH (at_dot); + break; + + case 's': + laststart = b; + BUFPUSH (syntaxspec); + PATFETCH (c); + BUFPUSH (syntax_spec_code[c]); + break; + + case 'S': + laststart = b; + BUFPUSH (notsyntaxspec); + PATFETCH (c); + BUFPUSH (syntax_spec_code[c]); + break; +#endif /* emacs */ + + case 'w': + laststart = b; + BUFPUSH (wordchar); + break; + + case 'W': + laststart = b; + BUFPUSH (notwordchar); + break; + + case '<': + BUFPUSH (wordbeg); + break; + + case '>': + BUFPUSH (wordend); + break; + + case 'b': + BUFPUSH (wordbound); + break; + + case 'B': + BUFPUSH (notwordbound); + break; + + case '`': + BUFPUSH (begbuf); + break; + + case '\'': + BUFPUSH (endbuf); + break; + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (obscure_syntax & RE_NO_BK_REFS) + goto normal_char; + c1 = c - '0'; + if (c1 >= regnum) + { + if (obscure_syntax & RE_NO_EMPTY_BK_REF) + goto invalid_pattern; + else + goto normal_char; + } + /* Can't back reference to a subexpression if inside of it. */ + for (stackt = stackp - 2; stackt > stackb; stackt -= 4) + if (*stackt == c1) + goto normal_char; + laststart = b; + BUFPUSH (duplicate); + BUFPUSH (c1); + break; + + case '+': + case '?': + if (obscure_syntax & RE_BK_PLUS_QM) + goto handle_plus; + else + goto normal_backsl; + break; + + default: + normal_backsl: + /* You might think it would be useful for \ to mean + not to translate; but if we don't translate it + it will never match anything. */ + if (translate) c = translate[c]; + goto normal_char; + } + break; + + default: + normal_char: /* Expects the character in `c'. */ + if (!pending_exact || pending_exact + *pending_exact + 1 != b + || *pending_exact == 0177 || *p == '*' || *p == '^' + || ((obscure_syntax & RE_BK_PLUS_QM) + ? *p == '\\' && (p[1] == '+' || p[1] == '?') + : (*p == '+' || *p == '?')) + || ((obscure_syntax & RE_INTERVALS) + && ((obscure_syntax & RE_NO_BK_CURLY_BRACES) + ? *p == '{' + : (p[0] == '\\' && p[1] == '{')))) + { + laststart = b; + BUFPUSH (exactn); + pending_exact = b; + BUFPUSH (0); + } + BUFPUSH (c); + (*pending_exact)++; + } + } + + if (fixup_jump) + store_jump (fixup_jump, jump, b); + + if (stackp != stackb) goto unmatched_open; + + bufp->used = b - bufp->buffer; + return 0; + + invalid_pattern: + return "Invalid regular expression"; + + unmatched_open: + return "Unmatched \\("; + + unmatched_close: + return "Unmatched \\)"; + + end_of_pattern: + return "Premature end of regular expression"; + + nesting_too_deep: + return "Nesting too deep"; + + too_big: + return "Regular expression too big"; + + memory_exhausted: + return "Memory exhausted"; +} + + +/* Store a jump of the form <OPCODE> <relative address>. + Store in the location FROM a jump operation to jump to relative + address FROM - TO. OPCODE is the opcode to store. */ + +static void +store_jump (char *from, char opcode, char *to) +{ + from[0] = opcode; + STORE_NUMBER(from + 1, to - (from + 3)); +} + + +/* Open up space before char FROM, and insert there a jump to TO. + CURRENT_END gives the end of the storage not in use, so we know + how much data to copy up. OP is the opcode of the jump to insert. + + If you call this function, you must zero out pending_exact. */ + +static void +insert_jump (char op, char *from, char *to, char *current_end) +{ + register char *pfrom = current_end; /* Copy from here... */ + register char *pto = current_end + 3; /* ...to here. */ + + while (pfrom != from) + *--pto = *--pfrom; + store_jump (from, op, to); +} + + +/* Store a jump of the form <opcode> <relative address> <n> . + + Store in the location FROM a jump operation to jump to relative + address FROM - TO. OPCODE is the opcode to store, N is a number the + jump uses, say, to decide how many times to jump. + + If you call this function, you must zero out pending_exact. */ + +static void +store_jump_n (char *from, char opcode, char *to, unsigned n) +{ + from[0] = opcode; + STORE_NUMBER (from + 1, to - (from + 3)); + STORE_NUMBER (from + 3, n); +} + + +/* Similar to insert_jump, but handles a jump which needs an extra + number to handle minimum and maximum cases. Open up space at + location FROM, and insert there a jump to TO. CURRENT_END gives the + end of the storage in use, so we know how much data to copy up. OP is + the opcode of the jump to insert. + + If you call this function, you must zero out pending_exact. */ + +static void +insert_jump_n (char op, char *from, char *to, char *current_end, unsigned n) +{ + register char *pfrom = current_end; /* Copy from here... */ + register char *pto = current_end + 5; /* ...to here. */ + + while (pfrom != from) + *--pto = *--pfrom; + store_jump_n (from, op, to, n); +} + + +/* Open up space at location THERE, and insert operation OP followed by + NUM_1 and NUM_2. CURRENT_END gives the end of the storage in use, so + we know how much data to copy up. + + If you call this function, you must zero out pending_exact. */ + +static void +insert_op_2 (char op, char *there, char *current_end, int num_1, int num_2) +{ + register char *pfrom = current_end; /* Copy from here... */ + register char *pto = current_end + 5; /* ...to here. */ + + while (pfrom != there) + *--pto = *--pfrom; + + there[0] = op; + STORE_NUMBER (there + 1, num_1); + STORE_NUMBER (there + 3, num_2); +} + + + +/* Given a pattern, compute a fastmap from it. The fastmap records + which of the (1 << BYTEWIDTH) possible characters can start a string + that matches the pattern. This fastmap is used by re_search to skip + quickly over totally implausible text. + + The caller must supply the address of a (1 << BYTEWIDTH)-byte data + area as bufp->fastmap. + The other components of bufp describe the pattern to be used. */ + +void +re_compile_fastmap (struct re_pattern_buffer *bufp) +{ + unsigned char *pattern = (unsigned char *) bufp->buffer; + int size = bufp->used; + register char *fastmap = bufp->fastmap; + register unsigned char *p = pattern; + register unsigned char *pend = pattern + size; + register int j, k; + unsigned char *translate = (unsigned char *) bufp->translate; + + unsigned char *stackb[NFAILURES]; + unsigned char **stackp = stackb; + + unsigned is_a_succeed_n; + + memset (fastmap, 0, (1 << BYTEWIDTH)); + bufp->fastmap_accurate = 1; + bufp->can_be_null = 0; + + while (p) + { + is_a_succeed_n = 0; + if (p == pend) + { + bufp->can_be_null = 1; + break; + } +#ifdef SWITCH_ENUM_BUG + switch ((int) ((enum regexpcode) *p++)) +#else + switch ((enum regexpcode) *p++) +#endif + { + case exactn: + if (translate) + fastmap[translate[p[1]]] = 1; + else + fastmap[p[1]] = 1; + break; + + case unused: + case begline: +#ifdef emacs + case before_dot: + case at_dot: + case after_dot: +#endif + case begbuf: + case endbuf: + case wordbound: + case notwordbound: + case wordbeg: + case wordend: + continue; + + case endline: + if (translate) + fastmap[translate['\n']] = 1; + else + fastmap['\n'] = 1; + + if (bufp->can_be_null != 1) + bufp->can_be_null = 2; + break; + + case jump_n: + case finalize_jump: + case maybe_finalize_jump: + case jump: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + if (j > 0) + continue; + /* Jump backward reached implies we just went through + the body of a loop and matched nothing. + Opcode jumped to should be an on_failure_jump. + Just treat it like an ordinary jump. + For a * loop, it has pushed its failure point already; + If so, discard that as redundant. */ + + if ((enum regexpcode) *p != on_failure_jump + && (enum regexpcode) *p != succeed_n) + continue; + p++; + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + if (stackp != stackb && *stackp == p) + stackp--; + continue; + + case on_failure_jump: + handle_on_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + *++stackp = p + j; + if (is_a_succeed_n) + EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ + continue; + + case succeed_n: + is_a_succeed_n = 1; + /* Get to the number of times to succeed. */ + p += 2; + /* Increment p past the n for when k != 0. */ + EXTRACT_NUMBER_AND_INCR (k, p); + if (k == 0) + { + p -= 4; + goto handle_on_failure_jump; + } + continue; + + case set_number_at: + p += 4; + continue; + + case start_memory: + case stop_memory: + p++; + continue; + + case duplicate: + bufp->can_be_null = 1; + fastmap['\n'] = 1; + case anychar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (j != '\n') + fastmap[j] = 1; + if (bufp->can_be_null) + return; + /* Don't return; check the alternative paths + so we can set can_be_null if appropriate. */ + break; + + case wordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == Sword) + fastmap[j] = 1; + break; + + case notwordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != Sword) + fastmap[j] = 1; + break; + +#ifdef emacs + case syntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == (enum syntaxcode) k) + fastmap[j] = 1; + break; + + case notsyntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != (enum syntaxcode) k) + fastmap[j] = 1; + break; +#endif /* not emacs */ + + case charset: + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) + { + if (translate) + fastmap[translate[j]] = 1; + else + fastmap[j] = 1; + } + break; + + case charset_not: + /* Chars beyond end of map must be allowed */ + for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) + if (translate) + fastmap[translate[j]] = 1; + else + fastmap[j] = 1; + + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) + { + if (translate) + fastmap[translate[j]] = 1; + else + fastmap[j] = 1; + } + break; + } + + /* Get here means we have successfully found the possible starting + characters of one path of the pattern. We need not follow this + path any farther. Instead, look at the next alternative + remembered in the stack. */ + if (stackp != stackb) + p = *stackp--; + else + break; + } +} + + + +/* Like re_search_2, below, but only one string is specified, and + doesn't let you say where to stop matching. */ + +int +re_search (struct re_pattern_buffer *pbufp, + char *string, + int size, + int startpos, + int range, + struct re_registers *regs) +{ + return re_search_2 (pbufp, (char *) 0, 0, string, size, startpos, range, + regs, size); +} + + +/* Using the compiled pattern in PBUFP->buffer, first tries to match the + virtual concatenation of STRING1 and STRING2, starting first at index + STARTPOS, then at STARTPOS + 1, and so on. RANGE is the number of + places to try before giving up. If RANGE is negative, it searches + backwards, i.e., the starting positions tried are STARTPOS, STARTPOS + - 1, etc. STRING1 and STRING2 are of SIZE1 and SIZE2, respectively. + In REGS, return the indices of the virtual concatenation of STRING1 + and STRING2 that matched the entire PBUFP->buffer and its contained + subexpressions. Do not consider matching one past the index MSTOP in + the virtual concatenation of STRING1 and STRING2. + + The value returned is the position in the strings at which the match + was found, or -1 if no match was found, or -2 if error (such as + failure stack overflow). */ + +int +re_search_2 (struct re_pattern_buffer *pbufp, + char *string1, int size1, + char *string2, int size2, + int startpos, + register int range, + struct re_registers *regs, + int mstop) +{ + register char *fastmap = pbufp->fastmap; + register unsigned char *translate = (unsigned char *) pbufp->translate; + int total_size = size1 + size2; + int endpos = startpos + range; + int val; + + /* Check for out-of-range starting position. */ + if (startpos < 0 || startpos > total_size) + return -1; + + /* Fix up range if it would eventually take startpos outside of the + virtual concatenation of string1 and string2. */ + if (endpos < -1) + range = -1 - startpos; + else if (endpos > total_size) + range = total_size - startpos; + + /* Update the fastmap now if not correct already. */ + if (fastmap && !pbufp->fastmap_accurate) + re_compile_fastmap (pbufp); + + /* If the search isn't to be a backwards one, don't waste time in a + long search for a pattern that says it is anchored. */ + if (pbufp->used > 0 && (enum regexpcode) pbufp->buffer[0] == begbuf + && range > 0) + { + if (startpos > 0) + return -1; + else + range = 1; + } + + while (1) + { + /* If a fastmap is supplied, skip quickly over characters that + cannot possibly be the start of a match. Note, however, that + if the pattern can possibly match the null string, we must + test it at each starting point so that we take the first null + string we get. */ + + if (fastmap && startpos < total_size && pbufp->can_be_null != 1) + { + if (range > 0) /* Searching forwards. */ + { + register int lim = 0; + register unsigned char *p; + int irange = range; + if (startpos < size1 && startpos + range >= size1) + lim = range - (size1 - startpos); + + p = ((unsigned char *) + &(startpos >= size1 ? string2 - size1 : string1)[startpos]); + + while (range > lim && !fastmap[translate + ? translate[*p++] + : *p++]) + range--; + startpos += irange - range; + } + else /* Searching backwards. */ + { + register unsigned char c; + + if (string1 == 0 || startpos >= size1) + c = string2[startpos - size1]; + else + c = string1[startpos]; + + c &= 0xff; + if (translate ? !fastmap[translate[c]] : !fastmap[c]) + goto advance; + } + } + + if (range >= 0 && startpos == total_size + && fastmap && pbufp->can_be_null == 0) + return -1; + + val = re_match_2 (pbufp, string1, size1, string2, size2, startpos, + regs, mstop); + if (val >= 0) + return startpos; + if (val == -2) + return -2; + +#ifdef C_ALLOCA + alloca (0); +#endif /* C_ALLOCA */ + + advance: + if (!range) + break; + else if (range > 0) + { + range--; + startpos++; + } + else + { + range++; + startpos--; + } + } + return -1; +} + + + +#ifndef emacs /* emacs never uses this. */ +int +re_match (struct re_pattern_buffer *pbufp, + char *string, + int size, + int pos, + struct re_registers *regs) +{ + return re_match_2 (pbufp, (char *) 0, 0, string, size, pos, regs, size); +} +#endif /* not emacs */ + + +/* The following are used for re_match_2, defined below: */ + +/* Roughly the maximum number of failure points on the stack. Would be + exactly that if always pushed MAX_NUM_FAILURE_ITEMS each time we failed. */ + +int re_max_failures = 2000; + +/* Routine used by re_match_2. */ +static int bcmp_translate (char *, char *, int, unsigned char *); + + +/* Structure and accessing macros used in re_match_2: */ + +struct register_info +{ + unsigned is_active : 1; + unsigned matched_something : 1; +}; + +#define IS_ACTIVE(R) ((R).is_active) +#define MATCHED_SOMETHING(R) ((R).matched_something) + + +/* Macros used by re_match_2: */ + + +/* I.e., regstart, regend, and reg_info. */ + +#define NUM_REG_ITEMS 3 + +/* We push at most this many things on the stack whenever we + fail. The `+ 2' refers to PATTERN_PLACE and STRING_PLACE, which are + arguments to the PUSH_FAILURE_POINT macro. */ + +#define MAX_NUM_FAILURE_ITEMS (RE_NREGS * NUM_REG_ITEMS + 2) + + +/* We push this many things on the stack whenever we fail. */ + +#define NUM_FAILURE_ITEMS (last_used_reg * NUM_REG_ITEMS + 2) + + +/* This pushes most of the information about the current state we will want + if we ever fail back to it. */ + +#define PUSH_FAILURE_POINT(pattern_place, string_place) \ + { \ + short last_used_reg, this_reg; \ + \ + /* Find out how many registers are active or have been matched. \ + (Aside from register zero, which is only set at the end.) */ \ + for (last_used_reg = RE_NREGS - 1; last_used_reg > 0; last_used_reg--)\ + if (regstart[last_used_reg] != (unsigned char *) -1) \ + break; \ + \ + if (stacke - stackp < NUM_FAILURE_ITEMS) \ + { \ + unsigned char **stackx; \ + int len = stacke - stackb; \ + if (len > re_max_failures * MAX_NUM_FAILURE_ITEMS) \ + return -2; \ + \ + /* Roughly double the size of the stack. */ \ + stackx = (unsigned char **) alloca (2 * len \ + * sizeof (unsigned char *));\ + /* Only copy what is in use. */ \ + memcpy (stackx, stackb, len * sizeof (char *)); \ + stackp = stackx + (stackp - stackb); \ + stackb = stackx; \ + stacke = stackb + 2 * len; \ + } \ + \ + /* Now push the info for each of those registers. */ \ + for (this_reg = 1; this_reg <= last_used_reg; this_reg++) \ + { \ + *stackp++ = regstart[this_reg]; \ + *stackp++ = regend[this_reg]; \ + *stackp++ = (unsigned char *) ®_info[this_reg]; \ + } \ + \ + /* Push how many registers we saved. */ \ + *stackp++ = (unsigned char *) last_used_reg; \ + \ + *stackp++ = pattern_place; \ + *stackp++ = string_place; \ + } + + +/* This pops what PUSH_FAILURE_POINT pushes. */ + +#define POP_FAILURE_POINT() \ + { \ + int temp; \ + stackp -= 2; /* Remove failure points. */ \ + temp = (int) *--stackp; /* How many regs pushed. */ \ + temp *= NUM_REG_ITEMS; /* How much to take off the stack. */ \ + stackp -= temp; /* Remove the register info. */ \ + } + + +#define MATCHING_IN_FIRST_STRING (dend == end_match_1) + +/* Is true if there is a first string and if PTR is pointing anywhere + inside it or just past the end. */ + +#define IS_IN_FIRST_STRING(ptr) \ + (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) + +/* Call before fetching a character with *d. This switches over to + string2 if necessary. */ + +#define PREFETCH \ + while (d == dend) \ + { \ + /* end of string2 => fail. */ \ + if (dend == end_match_2) \ + goto fail; \ + /* end of string1 => advance to string2. */ \ + d = string2; \ + dend = end_match_2; \ + } + + +/* Call this when have matched something; it sets `matched' flags for the + registers corresponding to the subexpressions of which we currently + are inside. */ +#define SET_REGS_MATCHED \ + { unsigned this_reg; \ + for (this_reg = 0; this_reg < RE_NREGS; this_reg++) \ + { \ + if (IS_ACTIVE(reg_info[this_reg])) \ + MATCHED_SOMETHING(reg_info[this_reg]) = 1; \ + else \ + MATCHED_SOMETHING(reg_info[this_reg]) = 0; \ + } \ + } + +/* Test if at very beginning or at very end of the virtual concatenation + of string1 and string2. If there is only one string, we've put it in + string2. */ + +#define AT_STRINGS_BEG (d == (size1 ? string1 : string2) || !size2) +#define AT_STRINGS_END (d == end2) + +#define AT_WORD_BOUNDARY \ + (AT_STRINGS_BEG || AT_STRINGS_END || IS_A_LETTER (d - 1) != IS_A_LETTER (d)) + +/* We have two special cases to check for: + 1) if we're past the end of string1, we have to look at the first + character in string2; + 2) if we're before the beginning of string2, we have to look at the + last character in string1; we assume there is a string1, so use + this in conjunction with AT_STRINGS_BEG. */ +#define IS_A_LETTER(d) \ + (SYNTAX ((d) == end1 ? *string2 : (d) == string2 - 1 ? *(end1 - 1) : *(d))\ + == Sword) + + +/* Match the pattern described by PBUFP against the virtual + concatenation of STRING1 and STRING2, which are of SIZE1 and SIZE2, + respectively. Start the match at index POS in the virtual + concatenation of STRING1 and STRING2. In REGS, return the indices of + the virtual concatenation of STRING1 and STRING2 that matched the + entire PBUFP->buffer and its contained subexpressions. Do not + consider matching one past the index MSTOP in the virtual + concatenation of STRING1 and STRING2. + + If pbufp->fastmap is nonzero, then it had better be up to date. + + The reason that the data to match are specified as two components + which are to be regarded as concatenated is so this function can be + used directly on the contents of an Emacs buffer. + + -1 is returned if there is no match. -2 is returned if there is an + error (such as match stack overflow). Otherwise the value is the + length of the substring which was matched. */ + +int +re_match_2 (struct re_pattern_buffer *pbufp, + char *string1_arg, int size1, + char *string2_arg, int size2, + int pos, + struct re_registers *regs, + int mstop) +{ + register unsigned char *p = (unsigned char *) pbufp->buffer; + + /* Pointer to beyond end of buffer. */ + register unsigned char *pend = p + pbufp->used; + + unsigned char *string1 = (unsigned char *) string1_arg; + unsigned char *string2 = (unsigned char *) string2_arg; + unsigned char *end1; /* Just past end of first string. */ + unsigned char *end2; /* Just past end of second string. */ + + /* Pointers into string1 and string2, just past the last characters in + each to consider matching. */ + unsigned char *end_match_1, *end_match_2; + + register unsigned char *d, *dend; + register int mcnt; /* Multipurpose. */ + unsigned char *translate = (unsigned char *) pbufp->translate; + unsigned is_a_jump_n = 0; + + /* Failure point stack. Each place that can handle a failure further + down the line pushes a failure point on this stack. It consists of + restart, regend, and reg_info for all registers corresponding to the + subexpressions we're currently inside, plus the number of such + registers, and, finally, two char *'s. The first char * is where to + resume scanning the pattern; the second one is where to resume + scanning the strings. If the latter is zero, the failure point is a + ``dummy''; if a failure happens and the failure point is a dummy, it + gets discarded and the next next one is tried. */ + + unsigned char *initial_stack[MAX_NUM_FAILURE_ITEMS * NFAILURES]; + unsigned char **stackb = initial_stack; + unsigned char **stackp = stackb; + unsigned char **stacke = &stackb[MAX_NUM_FAILURE_ITEMS * NFAILURES]; + + + /* Information on the contents of registers. These are pointers into + the input strings; they record just what was matched (on this + attempt) by a subexpression part of the pattern, that is, the + regnum-th regstart pointer points to where in the pattern we began + matching and the regnum-th regend points to right after where we + stopped matching the regnum-th subexpression. (The zeroth register + keeps track of what the whole pattern matches.) */ + + unsigned char *regstart[RE_NREGS]; + unsigned char *regend[RE_NREGS]; + + /* The is_active field of reg_info helps us keep track of which (possibly + nested) subexpressions we are currently in. The matched_something + field of reg_info[reg_num] helps us tell whether or not we have + matched any of the pattern so far this time through the reg_num-th + subexpression. These two fields get reset each time through any + loop their register is in. */ + + struct register_info reg_info[RE_NREGS]; + + + /* The following record the register info as found in the above + variables when we find a match better than any we've seen before. + This happens as we backtrack through the failure points, which in + turn happens only if we have not yet matched the entire string. */ + + unsigned best_regs_set = 0; + unsigned char *best_regstart[RE_NREGS]; + unsigned char *best_regend[RE_NREGS]; + + /* Initialize subexpression text positions to -1 to mark ones that no + \( or ( and \) or ) has been seen for. Also set all registers to + inactive and mark them as not having matched anything or ever + failed. */ + for (mcnt = 0; mcnt < RE_NREGS; mcnt++) + { + regstart[mcnt] = regend[mcnt] = (unsigned char *) -1; + IS_ACTIVE (reg_info[mcnt]) = 0; + MATCHED_SOMETHING (reg_info[mcnt]) = 0; + } + + if (regs) + for (mcnt = 0; mcnt < RE_NREGS; mcnt++) + regs->start[mcnt] = regs->end[mcnt] = -1; + + /* Set up pointers to ends of strings. + Don't allow the second string to be empty unless both are empty. */ + if (size2 == 0) + { + string2 = string1; + size2 = size1; + string1 = 0; + size1 = 0; + } + end1 = string1 + size1; + end2 = string2 + size2; + + /* Compute where to stop matching, within the two strings. */ + if (mstop <= size1) + { + end_match_1 = string1 + mstop; + end_match_2 = string2; + } + else + { + end_match_1 = end1; + end_match_2 = string2 + mstop - size1; + } + + /* `p' scans through the pattern as `d' scans through the data. `dend' + is the end of the input string that `d' points within. `d' is + advanced into the following input string whenever necessary, but + this happens before fetching; therefore, at the beginning of the + loop, `d' can be pointing at the end of a string, but it cannot + equal string2. */ + + if (size1 != 0 && pos <= size1) + d = string1 + pos, dend = end_match_1; + else + d = string2 + pos - size1, dend = end_match_2; + + + /* This loops over pattern commands. It exits by returning from the + function if match is complete, or it drops through if match fails + at this starting point in the input data. */ + + while (1) + { + is_a_jump_n = 0; + /* End of pattern means we might have succeeded. */ + if (p == pend) + { + /* If not end of string, try backtracking. Otherwise done. */ + if (d != end_match_2) + { + if (stackp != stackb) + { + /* More failure points to try. */ + + unsigned in_same_string = + IS_IN_FIRST_STRING (best_regend[0]) + == MATCHING_IN_FIRST_STRING; + + /* If exceeds best match so far, save it. */ + if (! best_regs_set + || (in_same_string && d > best_regend[0]) + || (! in_same_string && ! MATCHING_IN_FIRST_STRING)) + { + best_regs_set = 1; + best_regend[0] = d; /* Never use regstart[0]. */ + + for (mcnt = 1; mcnt < RE_NREGS; mcnt++) + { + best_regstart[mcnt] = regstart[mcnt]; + best_regend[mcnt] = regend[mcnt]; + } + } + goto fail; + } + /* If no failure points, don't restore garbage. */ + else if (best_regs_set) + { + restore_best_regs: + /* Restore best match. */ + d = best_regend[0]; + + for (mcnt = 0; mcnt < RE_NREGS; mcnt++) + { + regstart[mcnt] = best_regstart[mcnt]; + regend[mcnt] = best_regend[mcnt]; + } + } + } + + /* If caller wants register contents data back, convert it + to indices. */ + if (regs) + { + regs->start[0] = pos; + if (MATCHING_IN_FIRST_STRING) + regs->end[0] = d - string1; + else + regs->end[0] = d - string2 + size1; + for (mcnt = 1; mcnt < RE_NREGS; mcnt++) + { + if (regend[mcnt] == (unsigned char *) -1) + { + regs->start[mcnt] = -1; + regs->end[mcnt] = -1; + continue; + } + if (IS_IN_FIRST_STRING (regstart[mcnt])) + regs->start[mcnt] = regstart[mcnt] - string1; + else + regs->start[mcnt] = regstart[mcnt] - string2 + size1; + + if (IS_IN_FIRST_STRING (regend[mcnt])) + regs->end[mcnt] = regend[mcnt] - string1; + else + regs->end[mcnt] = regend[mcnt] - string2 + size1; + } + } + return d - pos - (MATCHING_IN_FIRST_STRING + ? string1 + : string2 - size1); + } + + /* Otherwise match next pattern command. */ +#ifdef SWITCH_ENUM_BUG + switch ((int) ((enum regexpcode) *p++)) +#else + switch ((enum regexpcode) *p++) +#endif + { + + /* \( [or `(', as appropriate] is represented by start_memory, + \) by stop_memory. Both of those commands are followed by + a register number in the next byte. The text matched + within the \( and \) is recorded under that number. */ + case start_memory: + regstart[*p] = d; + IS_ACTIVE (reg_info[*p]) = 1; + MATCHED_SOMETHING (reg_info[*p]) = 0; + p++; + break; + + case stop_memory: + regend[*p] = d; + IS_ACTIVE (reg_info[*p]) = 0; + + /* If just failed to match something this time around with a sub- + expression that's in a loop, try to force exit from the loop. */ + if ((! MATCHED_SOMETHING (reg_info[*p]) + || (enum regexpcode) p[-3] == start_memory) + && (p + 1) != pend) + { + register unsigned char *p2 = p + 1; + mcnt = 0; + switch (*p2++) + { + case jump_n: + is_a_jump_n = 1; + case finalize_jump: + case maybe_finalize_jump: + case jump: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p2); + if (is_a_jump_n) + p2 += 2; + break; + } + p2 += mcnt; + + /* If the next operation is a jump backwards in the pattern + to an on_failure_jump, exit from the loop by forcing a + failure after pushing on the stack the on_failure_jump's + jump in the pattern, and d. */ + if (mcnt < 0 && (enum regexpcode) *p2++ == on_failure_jump) + { + EXTRACT_NUMBER_AND_INCR (mcnt, p2); + PUSH_FAILURE_POINT (p2 + mcnt, d); + goto fail; + } + } + p++; + break; + + /* \<digit> has been turned into a `duplicate' command which is + followed by the numeric value of <digit> as the register number. */ + case duplicate: + { + int regno = *p++; /* Get which register to match against */ + register unsigned char *d2, *dend2; + + /* Where in input to try to start matching. */ + d2 = regstart[regno]; + + /* Where to stop matching; if both the place to start and + the place to stop matching are in the same string, then + set to the place to stop, otherwise, for now have to use + the end of the first string. */ + + dend2 = ((IS_IN_FIRST_STRING (regstart[regno]) + == IS_IN_FIRST_STRING (regend[regno])) + ? regend[regno] : end_match_1); + while (1) + { + /* If necessary, advance to next segment in register + contents. */ + while (d2 == dend2) + { + if (dend2 == end_match_2) break; + if (dend2 == regend[regno]) break; + d2 = string2, dend2 = regend[regno]; /* end of string1 => advance to string2. */ + } + /* At end of register contents => success */ + if (d2 == dend2) break; + + /* If necessary, advance to next segment in data. */ + PREFETCH; + + /* How many characters left in this segment to match. */ + mcnt = dend - d; + + /* Want how many consecutive characters we can match in + one shot, so, if necessary, adjust the count. */ + if (mcnt > dend2 - d2) + mcnt = dend2 - d2; + + /* Compare that many; failure if mismatch, else move + past them. */ + if (translate + ? bcmp_translate ((char*)d, (char*)d2, mcnt, translate) + : memcmp (d, d2, mcnt)) + goto fail; + d += mcnt, d2 += mcnt; + } + } + break; + + case anychar: + PREFETCH; /* Fetch a data character. */ + /* Match anything but a newline, maybe even a null. */ + if ((translate ? translate[*d] : *d) == '\n' + || ((obscure_syntax & RE_DOT_NOT_NULL) + && (translate ? translate[*d] : *d) == '\000')) + goto fail; + SET_REGS_MATCHED; + d++; + break; + + case charset: + case charset_not: + { + int not = 0; /* Nonzero for charset_not. */ + register int c; + if (*(p - 1) == (unsigned char) charset_not) + not = 1; + + PREFETCH; /* Fetch a data character. */ + + if (translate) + c = translate[*d]; + else + c = *d; + + if (c < *p * BYTEWIDTH + && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + p += 1 + *p; + + if (!not) goto fail; + SET_REGS_MATCHED; + d++; + break; + } + + case begline: + if ((size1 != 0 && d == string1) + || (size1 == 0 && size2 != 0 && d == string2) + || (d && d[-1] == '\n') + || (size1 == 0 && size2 == 0)) + break; + else + goto fail; + + case endline: + if (d == end2 + || (d == end1 ? (size2 == 0 || *string2 == '\n') : *d == '\n')) + break; + goto fail; + + /* `or' constructs are handled by starting each alternative with + an on_failure_jump that points to the start of the next + alternative. Each alternative except the last ends with a + jump to the joining point. (Actually, each jump except for + the last one really jumps to the following jump, because + tensioning the jumps is a hassle.) */ + + /* The start of a stupid repeat has an on_failure_jump that points + past the end of the repeat text. This makes a failure point so + that on failure to match a repetition, matching restarts past + as many repetitions have been found with no way to fail and + look for another one. */ + + /* A smart repeat is similar but loops back to the on_failure_jump + so that each repetition makes another failure point. */ + + case on_failure_jump: + on_failure: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + PUSH_FAILURE_POINT (p + mcnt, d); + break; + + /* The end of a smart repeat has a maybe_finalize_jump back. + Change it either to a finalize_jump or an ordinary jump. */ + case maybe_finalize_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + { + register unsigned char *p2 = p; + /* Compare what follows with the beginning of the repeat. + If we can establish that there is nothing that they would + both match, we can change to finalize_jump. */ + while (p2 + 1 != pend + && (*p2 == (unsigned char) stop_memory + || *p2 == (unsigned char) start_memory)) + p2 += 2; /* Skip over reg number. */ + if (p2 == pend) + p[-3] = (unsigned char) finalize_jump; + else if (*p2 == (unsigned char) exactn + || *p2 == (unsigned char) endline) + { + register int c = *p2 == (unsigned char) endline ? '\n' : p2[2]; + register unsigned char *p1 = p + mcnt; + /* p1[0] ... p1[2] are an on_failure_jump. + Examine what follows that. */ + if (p1[3] == (unsigned char) exactn && p1[5] != c) + p[-3] = (unsigned char) finalize_jump; + else if (p1[3] == (unsigned char) charset + || p1[3] == (unsigned char) charset_not) + { + int not = p1[3] == (unsigned char) charset_not; + if (c < p1[4] * BYTEWIDTH + && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + /* `not' is 1 if c would match. */ + /* That means it is not safe to finalize. */ + if (!not) + p[-3] = (unsigned char) finalize_jump; + } + } + } + p -= 2; /* Point at relative address again. */ + if (p[-1] != (unsigned char) finalize_jump) + { + p[-1] = (unsigned char) jump; + goto nofinalize; + } + /* Note fall through. */ + + /* The end of a stupid repeat has a finalize_jump back to the + start, where another failure point will be made which will + point to after all the repetitions found so far. */ + + /* Take off failure points put on by matching on_failure_jump + because didn't fail. Also remove the register information + put on by the on_failure_jump. */ + case finalize_jump: + POP_FAILURE_POINT (); + /* Note fall through. */ + + /* Jump without taking off any failure points. */ + case jump: + nofinalize: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + p += mcnt; + break; + + case dummy_failure_jump: + /* Normally, the on_failure_jump pushes a failure point, which + then gets popped at finalize_jump. We will end up at + finalize_jump, also, and with a pattern of, say, `a+', we + are skipping over the on_failure_jump, so we have to push + something meaningless for finalize_jump to pop. */ + PUSH_FAILURE_POINT (0, 0); + goto nofinalize; + + + /* Have to succeed matching what follows at least n times. Then + just handle like an on_failure_jump. */ + case succeed_n: + EXTRACT_NUMBER (mcnt, p + 2); + /* Originally, this is how many times we HAVE to succeed. */ + if (mcnt) + { + mcnt--; + p += 2; + STORE_NUMBER_AND_INCR (p, mcnt); + } + else if (mcnt == 0) + { + p[2] = unused; + p[3] = unused; + goto on_failure; + } + else + { + fprintf (stderr, "regex: the succeed_n's n is not set.\n"); + exit (1); + } + break; + + case jump_n: + EXTRACT_NUMBER (mcnt, p + 2); + /* Originally, this is how many times we CAN jump. */ + if (mcnt) + { + mcnt--; + STORE_NUMBER(p + 2, mcnt); + goto nofinalize; /* Do the jump without taking off + any failure points. */ + } + /* If don't have to jump any more, skip over the rest of command. */ + else + p += 4; + break; + + case set_number_at: + { + register unsigned char *p1; + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + p1 = p + mcnt; + EXTRACT_NUMBER_AND_INCR (mcnt, p); + STORE_NUMBER (p1, mcnt); + break; + } + + /* Ignore these. Used to ignore the n of succeed_n's which + currently have n == 0. */ + case unused: + break; + + case wordbound: + if (AT_WORD_BOUNDARY) + break; + goto fail; + + case notwordbound: + if (AT_WORD_BOUNDARY) + goto fail; + break; + + case wordbeg: + /* Have to check if AT_STRINGS_BEG before looking at d - 1. */ + if (IS_A_LETTER (d) && (AT_STRINGS_BEG || !IS_A_LETTER (d - 1))) + break; + goto fail; + + case wordend: + /* Have to check if AT_STRINGS_BEG before looking at d - 1. */ + if (!AT_STRINGS_BEG && IS_A_LETTER (d - 1) + && (!IS_A_LETTER (d) || AT_STRINGS_END)) + break; + goto fail; + +#ifdef emacs + case before_dot: + if (PTR_CHAR_POS (d) >= point) + goto fail; + break; + + case at_dot: + if (PTR_CHAR_POS (d) != point) + goto fail; + break; + + case after_dot: + if (PTR_CHAR_POS (d) <= point) + goto fail; + break; + + case wordchar: + mcnt = (int) Sword; + goto matchsyntax; + + case syntaxspec: + mcnt = *p++; + matchsyntax: + PREFETCH; + if (SYNTAX (*d++) != (enum syntaxcode) mcnt) goto fail; + SET_REGS_MATCHED; + break; + + case notwordchar: + mcnt = (int) Sword; + goto matchnotsyntax; + + case notsyntaxspec: + mcnt = *p++; + matchnotsyntax: + PREFETCH; + if (SYNTAX (*d++) == (enum syntaxcode) mcnt) goto fail; + SET_REGS_MATCHED; + break; + +#else /* not emacs */ + + case wordchar: + PREFETCH; + if (!IS_A_LETTER (d)) + goto fail; + SET_REGS_MATCHED; + break; + + case notwordchar: + PREFETCH; + if (IS_A_LETTER (d)) + goto fail; + SET_REGS_MATCHED; + break; + +#endif /* not emacs */ + + case begbuf: + if (AT_STRINGS_BEG) + break; + goto fail; + + case endbuf: + if (AT_STRINGS_END) + break; + goto fail; + + case exactn: + /* Match the next few pattern characters exactly. + mcnt is how many characters to match. */ + mcnt = *p++; + /* This is written out as an if-else so we don't waste time + testing `translate' inside the loop. */ + if (translate) + { + do + { + PREFETCH; + if (translate[*d++] != *p++) goto fail; + } + while (--mcnt); + } + else + { + do + { + PREFETCH; + if (*d++ != *p++) goto fail; + } + while (--mcnt); + } + SET_REGS_MATCHED; + break; + } + continue; /* Successfully executed one pattern command; keep going. */ + + /* Jump here if any matching operation fails. */ + fail: + if (stackp != stackb) + /* A restart point is known. Restart there and pop it. */ + { + short last_used_reg, this_reg; + + /* If this failure point is from a dummy_failure_point, just + skip it. */ + if (!stackp[-2]) + { + POP_FAILURE_POINT (); + goto fail; + } + + d = *--stackp; + p = *--stackp; + if (d >= string1 && d <= end1) + dend = end_match_1; + /* Restore register info. */ + last_used_reg = (short) (int) *--stackp; + + /* Make the ones that weren't saved -1 or 0 again. */ + for (this_reg = RE_NREGS - 1; this_reg > last_used_reg; this_reg--) + { + regend[this_reg] = (unsigned char *) -1; + regstart[this_reg] = (unsigned char *) -1; + IS_ACTIVE (reg_info[this_reg]) = 0; + MATCHED_SOMETHING (reg_info[this_reg]) = 0; + } + + /* And restore the rest from the stack. */ + for ( ; this_reg > 0; this_reg--) + { + reg_info[this_reg] = *(struct register_info *) *--stackp; + regend[this_reg] = *--stackp; + regstart[this_reg] = *--stackp; + } + } + else + break; /* Matching at this starting point really fails. */ + } + + if (best_regs_set) + goto restore_best_regs; + return -1; /* Failure to match. */ +} + + +static int +bcmp_translate (char *s1, char *s2, int len, unsigned char *translate) +{ + register unsigned char *p1 = (unsigned char*)s1; + register unsigned char *p2 = (unsigned char*)s2; + while (len) + { + if (translate [*p1++] != translate [*p2++]) return 1; + len--; + } + return 0; +} + + + +/* Entry points compatible with 4.2 BSD regex library. */ + +#if 0 + +static struct re_pattern_buffer re_comp_buf; + +char * +re_comp (char *s) +{ + if (!s) + { + if (!re_comp_buf.buffer) + return "No previous regular expression"; + return 0; + } + + if (!re_comp_buf.buffer) + { + if (!(re_comp_buf.buffer = (char *) malloc (200))) + return "Memory exhausted"; + re_comp_buf.allocated = 200; + if (!(re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH))) + return "Memory exhausted"; + } + return re_compile_pattern (s, strlen (s), &re_comp_buf); +} + +int +re_exec (char *s) +{ + int len = strlen (s); + return 0 <= re_search (&re_comp_buf, s, len, 0, len, + (struct re_registers *) 0); +} +#endif /* not emacs */ + + + +#ifdef test + +#include <stdio.h> + +/* Indexed by a character, gives the upper case equivalent of the + character. */ + +char upcase[0400] = + { 000, 001, 002, 003, 004, 005, 006, 007, + 010, 011, 012, 013, 014, 015, 016, 017, + 020, 021, 022, 023, 024, 025, 026, 027, + 030, 031, 032, 033, 034, 035, 036, 037, + 040, 041, 042, 043, 044, 045, 046, 047, + 050, 051, 052, 053, 054, 055, 056, 057, + 060, 061, 062, 063, 064, 065, 066, 067, + 070, 071, 072, 073, 074, 075, 076, 077, + 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107, + 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, + 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, + 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137, + 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107, + 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, + 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, + 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177, + 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, + 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, + 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, + 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, + 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, + 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, + 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, + 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, + 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, + 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, + 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, + 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, + 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, + 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377 + }; + +#ifdef canned + +#include "tests.h" + +typedef enum { extended_test, basic_test } test_type; + +/* Use this to run the tests we've thought of. */ + +void +main () +{ + test_type t = extended_test; + + if (t == basic_test) + { + printf ("Running basic tests:\n\n"); + test_posix_basic (); + } + else if (t == extended_test) + { + printf ("Running extended tests:\n\n"); + test_posix_extended (); + } +} + +#else /* not canned */ + +/* Use this to run interactive tests. */ + +void +main (int argc, char **argv) +{ + char pat[80]; + struct re_pattern_buffer buf; + int i; + char c; + char fastmap[(1 << BYTEWIDTH)]; + + /* Allow a command argument to specify the style of syntax. */ + if (argc > 1) + obscure_syntax = atoi (argv[1]); + + buf.allocated = 40; + buf.buffer = (char *) malloc (buf.allocated); + buf.fastmap = fastmap; + buf.translate = upcase; + + while (1) + { + gets (pat); + + if (*pat) + { + re_compile_pattern (pat, strlen(pat), &buf); + + for (i = 0; i < buf.used; i++) + printchar (buf.buffer[i]); + + putchar ('\n'); + + printf ("%d allocated, %d used.\n", buf.allocated, buf.used); + + re_compile_fastmap (&buf); + printf ("Allowed by fastmap: "); + for (i = 0; i < (1 << BYTEWIDTH); i++) + if (fastmap[i]) printchar (i); + putchar ('\n'); + } + + gets (pat); /* Now read the string to match against */ + + i = re_match (&buf, pat, strlen (pat), 0, 0); + printf ("Match value %d.\n", i); + } +} + +#endif + + +#ifdef NOTDEF +void +print_buf (struct re_pattern_buffer *bufpbufp) +{ + int i; + + printf ("buf is :\n----------------\n"); + for (i = 0; i < bufp->used; i++) + printchar (bufp->buffer[i]); + + printf ("\n%d allocated, %d used.\n", bufp->allocated, bufp->used); + + printf ("Allowed by fastmap: "); + for (i = 0; i < (1 << BYTEWIDTH); i++) + if (bufp->fastmap[i]) + printchar (i); + printf ("\nAllowed by translate: "); + if (bufp->translate) + for (i = 0; i < (1 << BYTEWIDTH); i++) + if (bufp->translate[i]) + printchar (i); + printf ("\nfastmap is%s accurate\n", bufp->fastmap_accurate ? "" : "n't"); + printf ("can %s be null\n----------", bufp->can_be_null ? "" : "not"); +} +#endif /* NOTDEF */ + +void +printchar (char c) +{ + if (c < 040 || c >= 0177) + { + putchar ('\\'); + putchar (((c >> 6) & 3) + '0'); + putchar (((c >> 3) & 7) + '0'); + putchar ((c & 7) + '0'); + } + else + putchar (c); +} + +void +error (char *string) +{ + puts (string); + exit (1); +} +#endif /* test */ diff --git a/gnu/lib/libg++/libg++/sqrt.cc b/gnu/lib/libg++/libg++/sqrt.cc new file mode 100644 index 0000000..6df9af3 --- /dev/null +++ b/gnu/lib/libg++/libg++/sqrt.cc @@ -0,0 +1,43 @@ +/* +Copyright (C) 1990 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 <builtin.h> +#include <math.h> + +long sqrt(long x) +{ + if (x <= 0) + return 0; // no int error handler, so ... + else if (x == 1) + return 1; + else + { + long r = x >> 1; + long q; + for(;;) + { + q = x / r; + if (q >= r) + return r; + else + r = (r + q) >> 1; + } + } +} diff --git a/gnu/lib/libg++/libg++/str.cc b/gnu/lib/libg++/libg++/str.cc new file mode 100644 index 0000000..bf77c02 --- /dev/null +++ b/gnu/lib/libg++/libg++/str.cc @@ -0,0 +1,38 @@ +/* +Copyright (C) 1990 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 <builtin.h> +#include <AllocRing.h> + +extern AllocRing _libgxx_fmtq; + +char* str(const char* s, int width) +{ + int len = strlen(s); + int wrksiz = len + width + 1; + char* fmtbase = (char *) _libgxx_fmtq.alloc(wrksiz); + char* fmt = fmtbase; + for (int blanks = width - len; blanks > 0; --blanks) + *fmt++ = ' '; + while (*s != 0) + *fmt++ = *s++; + *fmt = 0; + return fmtbase; +} diff --git a/gnu/lib/libg++/libg++/timer.c b/gnu/lib/libg++/libg++/timer.c new file mode 100644 index 0000000..73a856a --- /dev/null +++ b/gnu/lib/libg++/libg++/timer.c @@ -0,0 +1,135 @@ +/* +Copyright (C) 1990, 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. +*/ + +#ifdef __GNUG__ +#pragma implementation +#endif + +/* Timing functions from Doug Schmidt... */ + +/* no such thing as "negative time"! */ +#define TIMER_ERROR_VALUE -1.0 + +/* If this does not work on your system, change this to #if 0, and + report the problem. */ + +#if 1 + +#include <_G_config.h> +#if _G_HAVE_SYS_RESOURCE +#include <sys/time.h> +#include <sys/resource.h> +#endif +#if !_G_HAVE_SYS_RESOURCE || !defined(RUSAGE_SELF) +#define USE_TIMES +#include <sys/param.h> +#include <sys/times.h> +#if !defined (HZ) && defined(CLK_TCK) +#define HZ CLK_TCK +#endif +static struct tms Old_Time; +static struct tms New_Time; +#else +static struct rusage Old_Time; +static struct rusage New_Time; +#endif +static int Timer_Set = 0; + +double +start_timer() +{ + Timer_Set = 1; +#ifdef USE_TIMES + times(&Old_Time); + return((double) Old_Time.tms_utime / HZ); +#else + getrusage(RUSAGE_SELF,&Old_Time); /* set starting process time */ + return(Old_Time.ru_utime.tv_sec + (Old_Time.ru_utime.tv_usec / 1000000.0)); +#endif +} + +/* Returns process time since Last_Time. + If parameter is 0.0, returns time since the Old_Time was set. + Returns TIMER_ERROR_VALUE if `start_timer' is not called first. */ + +double +return_elapsed_time(Last_Time) + double Last_Time; +{ + if (!Timer_Set) { + return(TIMER_ERROR_VALUE); + } + else { + /* get process time */ +#ifdef USE_TIMES + times(&New_Time); +#else + getrusage(RUSAGE_SELF,&New_Time); +#endif + if (Last_Time == 0.0) { +#ifdef USE_TIMES + return((double) (New_Time.tms_utime - Old_Time.tms_utime) / HZ); +#else + return((New_Time.ru_utime.tv_sec - Old_Time.ru_utime.tv_sec) + + ((New_Time.ru_utime.tv_usec - Old_Time.ru_utime.tv_usec) + / 1000000.0)); +#endif + } + else { +#ifdef USE_TIMES + return((double) New_Time.tms_utime / HZ - Last_Time); +#else + return((New_Time.ru_utime.tv_sec + + (New_Time.ru_utime.tv_usec / 1000000.0)) - Last_Time); +#endif + } + } +} + +#ifdef VMS +void sys$gettim(unsigned int*) asm("sys$gettim"); + +getrusage(int dummy,struct rusage* time){ + double rtime; + unsigned int systime[2]; + int i; + sys$gettim(&systime[0]); + rtime=systime[1]; + for(i=0;i<4;i++) rtime *= 256; + rtime+= systime[0]; +/* we subtract an offset to make sure that the number fits in a long int*/ + rtime=rtime/1.0e+7-4.144e+9; + time->ru_utime.tv_sec= rtime; + rtime=(rtime-time->ru_utime.tv_sec)*1.0e6; + time->ru_utime.tv_usec= rtime; +} +#endif +#else /* dummy them out */ + +double start_timer() +{ + return TIMER_ERROR_VALUE; +} + +double return_elapsed_time(double) +{ + return TIMER_ERROR_VALUE; +} + +#endif /* timing stuff */ + + diff --git a/gnu/lib/libg++/libiberty/strerror.c b/gnu/lib/libg++/libiberty/strerror.c new file mode 100644 index 0000000..5c0a58d --- /dev/null +++ b/gnu/lib/libg++/libiberty/strerror.c @@ -0,0 +1,823 @@ +/* Extended support for using errno values. + Copyright (C) 1992 Free Software Foundation, Inc. + Written by Fred Fish. fnf@cygnus.com + +This file is part of the libiberty library. +Libiberty 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. + +Libiberty 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 libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include "ansidecl.h" +#include "libiberty.h" + +#include "config.h" + +#ifndef NEED_sys_errlist +/* Note that errno.h (not sure what OS) or stdio.h (BSD 4.4, at least) + might declare sys_errlist in a way that the compiler might consider + incompatible with our later declaration, perhaps by using const + attributes. So we hide the declaration in errno.h (if any) using a + macro. */ +#define sys_errlist sys_errlist__ +#endif + +#include <stdio.h> +#include <errno.h> + +#ifndef NEED_sys_errlist +#undef sys_errlist +#endif + +/* Routines imported from standard C runtime libraries. */ + +#ifdef __STDC__ +#include <stddef.h> +extern void *malloc (size_t size); /* 4.10.3.3 */ +extern void *memset (void *s, int c, size_t n); /* 4.11.6.1 */ +#else /* !__STDC__ */ +extern char *malloc (); /* Standard memory allocater */ +extern char *memset (); +#endif /* __STDC__ */ + +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +/* Translation table for errno values. See intro(2) in most UNIX systems + Programmers Reference Manuals. + + Note that this table is generally only accessed when it is used at runtime + to initialize errno name and message tables that are indexed by errno + value. + + Not all of these errnos will exist on all systems. This table is the only + thing that should have to be updated as new error numbers are introduced. + It's sort of ugly, but at least its portable. */ + +struct error_info +{ + int value; /* The numeric value from <errno.h> */ + const char *name; /* The equivalent symbolic value */ +#ifdef NEED_sys_errlist + const char *msg; /* Short message about this value */ +#endif +}; + +#ifdef NEED_sys_errlist +# define ENTRY(value, name, msg) {value, name, msg} +#else +# define ENTRY(value, name, msg) {value, name} +#endif + +static const struct error_info error_table[] = +{ +#if defined (EPERM) + ENTRY(EPERM, "EPERM", "Not owner"), +#endif +#if defined (ENOENT) + ENTRY(ENOENT, "ENOENT", "No such file or directory"), +#endif +#if defined (ESRCH) + ENTRY(ESRCH, "ESRCH", "No such process"), +#endif +#if defined (EINTR) + ENTRY(EINTR, "EINTR", "Interrupted system call"), +#endif +#if defined (EIO) + ENTRY(EIO, "EIO", "I/O error"), +#endif +#if defined (ENXIO) + ENTRY(ENXIO, "ENXIO", "No such device or address"), +#endif +#if defined (E2BIG) + ENTRY(E2BIG, "E2BIG", "Arg list too long"), +#endif +#if defined (ENOEXEC) + ENTRY(ENOEXEC, "ENOEXEC", "Exec format error"), +#endif +#if defined (EBADF) + ENTRY(EBADF, "EBADF", "Bad file number"), +#endif +#if defined (ECHILD) + ENTRY(ECHILD, "ECHILD", "No child processes"), +#endif +#if defined (EWOULDBLOCK) /* Put before EAGAIN, sometimes aliased */ + ENTRY(EWOULDBLOCK, "EWOULDBLOCK", "Operation would block"), +#endif +#if defined (EAGAIN) + ENTRY(EAGAIN, "EAGAIN", "No more processes"), +#endif +#if defined (ENOMEM) + ENTRY(ENOMEM, "ENOMEM", "Not enough space"), +#endif +#if defined (EACCES) + ENTRY(EACCES, "EACCES", "Permission denied"), +#endif +#if defined (EFAULT) + ENTRY(EFAULT, "EFAULT", "Bad address"), +#endif +#if defined (ENOTBLK) + ENTRY(ENOTBLK, "ENOTBLK", "Block device required"), +#endif +#if defined (EBUSY) + ENTRY(EBUSY, "EBUSY", "Device busy"), +#endif +#if defined (EEXIST) + ENTRY(EEXIST, "EEXIST", "File exists"), +#endif +#if defined (EXDEV) + ENTRY(EXDEV, "EXDEV", "Cross-device link"), +#endif +#if defined (ENODEV) + ENTRY(ENODEV, "ENODEV", "No such device"), +#endif +#if defined (ENOTDIR) + ENTRY(ENOTDIR, "ENOTDIR", "Not a directory"), +#endif +#if defined (EISDIR) + ENTRY(EISDIR, "EISDIR", "Is a directory"), +#endif +#if defined (EINVAL) + ENTRY(EINVAL, "EINVAL", "Invalid argument"), +#endif +#if defined (ENFILE) + ENTRY(ENFILE, "ENFILE", "File table overflow"), +#endif +#if defined (EMFILE) + ENTRY(EMFILE, "EMFILE", "Too many open files"), +#endif +#if defined (ENOTTY) + ENTRY(ENOTTY, "ENOTTY", "Not a typewriter"), +#endif +#if defined (ETXTBSY) + ENTRY(ETXTBSY, "ETXTBSY", "Text file busy"), +#endif +#if defined (EFBIG) + ENTRY(EFBIG, "EFBIG", "File too large"), +#endif +#if defined (ENOSPC) + ENTRY(ENOSPC, "ENOSPC", "No space left on device"), +#endif +#if defined (ESPIPE) + ENTRY(ESPIPE, "ESPIPE", "Illegal seek"), +#endif +#if defined (EROFS) + ENTRY(EROFS, "EROFS", "Read-only file system"), +#endif +#if defined (EMLINK) + ENTRY(EMLINK, "EMLINK", "Too many links"), +#endif +#if defined (EPIPE) + ENTRY(EPIPE, "EPIPE", "Broken pipe"), +#endif +#if defined (EDOM) + ENTRY(EDOM, "EDOM", "Math argument out of domain of func"), +#endif +#if defined (ERANGE) + ENTRY(ERANGE, "ERANGE", "Math result not representable"), +#endif +#if defined (ENOMSG) + ENTRY(ENOMSG, "ENOMSG", "No message of desired type"), +#endif +#if defined (EIDRM) + ENTRY(EIDRM, "EIDRM", "Identifier removed"), +#endif +#if defined (ECHRNG) + ENTRY(ECHRNG, "ECHRNG", "Channel number out of range"), +#endif +#if defined (EL2NSYNC) + ENTRY(EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized"), +#endif +#if defined (EL3HLT) + ENTRY(EL3HLT, "EL3HLT", "Level 3 halted"), +#endif +#if defined (EL3RST) + ENTRY(EL3RST, "EL3RST", "Level 3 reset"), +#endif +#if defined (ELNRNG) + ENTRY(ELNRNG, "ELNRNG", "Link number out of range"), +#endif +#if defined (EUNATCH) + ENTRY(EUNATCH, "EUNATCH", "Protocol driver not attached"), +#endif +#if defined (ENOCSI) + ENTRY(ENOCSI, "ENOCSI", "No CSI structure available"), +#endif +#if defined (EL2HLT) + ENTRY(EL2HLT, "EL2HLT", "Level 2 halted"), +#endif +#if defined (EDEADLK) + ENTRY(EDEADLK, "EDEADLK", "Deadlock condition"), +#endif +#if defined (ENOLCK) + ENTRY(ENOLCK, "ENOLCK", "No record locks available"), +#endif +#if defined (EBADE) + ENTRY(EBADE, "EBADE", "Invalid exchange"), +#endif +#if defined (EBADR) + ENTRY(EBADR, "EBADR", "Invalid request descriptor"), +#endif +#if defined (EXFULL) + ENTRY(EXFULL, "EXFULL", "Exchange full"), +#endif +#if defined (ENOANO) + ENTRY(ENOANO, "ENOANO", "No anode"), +#endif +#if defined (EBADRQC) + ENTRY(EBADRQC, "EBADRQC", "Invalid request code"), +#endif +#if defined (EBADSLT) + ENTRY(EBADSLT, "EBADSLT", "Invalid slot"), +#endif +#if defined (EDEADLOCK) + ENTRY(EDEADLOCK, "EDEADLOCK", "File locking deadlock error"), +#endif +#if defined (EBFONT) + ENTRY(EBFONT, "EBFONT", "Bad font file format"), +#endif +#if defined (ENOSTR) + ENTRY(ENOSTR, "ENOSTR", "Device not a stream"), +#endif +#if defined (ENODATA) + ENTRY(ENODATA, "ENODATA", "No data available"), +#endif +#if defined (ETIME) + ENTRY(ETIME, "ETIME", "Timer expired"), +#endif +#if defined (ENOSR) + ENTRY(ENOSR, "ENOSR", "Out of streams resources"), +#endif +#if defined (ENONET) + ENTRY(ENONET, "ENONET", "Machine is not on the network"), +#endif +#if defined (ENOPKG) + ENTRY(ENOPKG, "ENOPKG", "Package not installed"), +#endif +#if defined (EREMOTE) + ENTRY(EREMOTE, "EREMOTE", "Object is remote"), +#endif +#if defined (ENOLINK) + ENTRY(ENOLINK, "ENOLINK", "Link has been severed"), +#endif +#if defined (EADV) + ENTRY(EADV, "EADV", "Advertise error"), +#endif +#if defined (ESRMNT) + ENTRY(ESRMNT, "ESRMNT", "Srmount error"), +#endif +#if defined (ECOMM) + ENTRY(ECOMM, "ECOMM", "Communication error on send"), +#endif +#if defined (EPROTO) + ENTRY(EPROTO, "EPROTO", "Protocol error"), +#endif +#if defined (EMULTIHOP) + ENTRY(EMULTIHOP, "EMULTIHOP", "Multihop attempted"), +#endif +#if defined (EDOTDOT) + ENTRY(EDOTDOT, "EDOTDOT", "RFS specific error"), +#endif +#if defined (EBADMSG) + ENTRY(EBADMSG, "EBADMSG", "Not a data message"), +#endif +#if defined (ENAMETOOLONG) + ENTRY(ENAMETOOLONG, "ENAMETOOLONG", "File name too long"), +#endif +#if defined (EOVERFLOW) + ENTRY(EOVERFLOW, "EOVERFLOW", "Value too large for defined data type"), +#endif +#if defined (ENOTUNIQ) + ENTRY(ENOTUNIQ, "ENOTUNIQ", "Name not unique on network"), +#endif +#if defined (EBADFD) + ENTRY(EBADFD, "EBADFD", "File descriptor in bad state"), +#endif +#if defined (EREMCHG) + ENTRY(EREMCHG, "EREMCHG", "Remote address changed"), +#endif +#if defined (ELIBACC) + ENTRY(ELIBACC, "ELIBACC", "Can not access a needed shared library"), +#endif +#if defined (ELIBBAD) + ENTRY(ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library"), +#endif +#if defined (ELIBSCN) + ENTRY(ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted"), +#endif +#if defined (ELIBMAX) + ENTRY(ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries"), +#endif +#if defined (ELIBEXEC) + ENTRY(ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly"), +#endif +#if defined (EILSEQ) + ENTRY(EILSEQ, "EILSEQ", "Illegal byte sequence"), +#endif +#if defined (ENOSYS) + ENTRY(ENOSYS, "ENOSYS", "Operation not applicable"), +#endif +#if defined (ELOOP) + ENTRY(ELOOP, "ELOOP", "Too many symbolic links encountered"), +#endif +#if defined (ERESTART) + ENTRY(ERESTART, "ERESTART", "Interrupted system call should be restarted"), +#endif +#if defined (ESTRPIPE) + ENTRY(ESTRPIPE, "ESTRPIPE", "Streams pipe error"), +#endif +#if defined (ENOTEMPTY) + ENTRY(ENOTEMPTY, "ENOTEMPTY", "Directory not empty"), +#endif +#if defined (EUSERS) + ENTRY(EUSERS, "EUSERS", "Too many users"), +#endif +#if defined (ENOTSOCK) + ENTRY(ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket"), +#endif +#if defined (EDESTADDRREQ) + ENTRY(EDESTADDRREQ, "EDESTADDRREQ", "Destination address required"), +#endif +#if defined (EMSGSIZE) + ENTRY(EMSGSIZE, "EMSGSIZE", "Message too long"), +#endif +#if defined (EPROTOTYPE) + ENTRY(EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket"), +#endif +#if defined (ENOPROTOOPT) + ENTRY(ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available"), +#endif +#if defined (EPROTONOSUPPORT) + ENTRY(EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported"), +#endif +#if defined (ESOCKTNOSUPPORT) + ENTRY(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported"), +#endif +#if defined (EOPNOTSUPP) + ENTRY(EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint"), +#endif +#if defined (EPFNOSUPPORT) + ENTRY(EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported"), +#endif +#if defined (EAFNOSUPPORT) + ENTRY(EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol"), +#endif +#if defined (EADDRINUSE) + ENTRY(EADDRINUSE, "EADDRINUSE", "Address already in use"), +#endif +#if defined (EADDRNOTAVAIL) + ENTRY(EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address"), +#endif +#if defined (ENETDOWN) + ENTRY(ENETDOWN, "ENETDOWN", "Network is down"), +#endif +#if defined (ENETUNREACH) + ENTRY(ENETUNREACH, "ENETUNREACH", "Network is unreachable"), +#endif +#if defined (ENETRESET) + ENTRY(ENETRESET, "ENETRESET", "Network dropped connection because of reset"), +#endif +#if defined (ECONNABORTED) + ENTRY(ECONNABORTED, "ECONNABORTED", "Software caused connection abort"), +#endif +#if defined (ECONNRESET) + ENTRY(ECONNRESET, "ECONNRESET", "Connection reset by peer"), +#endif +#if defined (ENOBUFS) + ENTRY(ENOBUFS, "ENOBUFS", "No buffer space available"), +#endif +#if defined (EISCONN) + ENTRY(EISCONN, "EISCONN", "Transport endpoint is already connected"), +#endif +#if defined (ENOTCONN) + ENTRY(ENOTCONN, "ENOTCONN", "Transport endpoint is not connected"), +#endif +#if defined (ESHUTDOWN) + ENTRY(ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"), +#endif +#if defined (ETOOMANYREFS) + ENTRY(ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice"), +#endif +#if defined (ETIMEDOUT) + ENTRY(ETIMEDOUT, "ETIMEDOUT", "Connection timed out"), +#endif +#if defined (ECONNREFUSED) + ENTRY(ECONNREFUSED, "ECONNREFUSED", "Connection refused"), +#endif +#if defined (EHOSTDOWN) + ENTRY(EHOSTDOWN, "EHOSTDOWN", "Host is down"), +#endif +#if defined (EHOSTUNREACH) + ENTRY(EHOSTUNREACH, "EHOSTUNREACH", "No route to host"), +#endif +#if defined (EALREADY) + ENTRY(EALREADY, "EALREADY", "Operation already in progress"), +#endif +#if defined (EINPROGRESS) + ENTRY(EINPROGRESS, "EINPROGRESS", "Operation now in progress"), +#endif +#if defined (ESTALE) + ENTRY(ESTALE, "ESTALE", "Stale NFS file handle"), +#endif +#if defined (EUCLEAN) + ENTRY(EUCLEAN, "EUCLEAN", "Structure needs cleaning"), +#endif +#if defined (ENOTNAM) + ENTRY(ENOTNAM, "ENOTNAM", "Not a XENIX named type file"), +#endif +#if defined (ENAVAIL) + ENTRY(ENAVAIL, "ENAVAIL", "No XENIX semaphores available"), +#endif +#if defined (EISNAM) + ENTRY(EISNAM, "EISNAM", "Is a named type file"), +#endif +#if defined (EREMOTEIO) + ENTRY(EREMOTEIO, "EREMOTEIO", "Remote I/O error"), +#endif + ENTRY(0, NULL, NULL) +}; + +/* Translation table allocated and initialized at runtime. Indexed by the + errno value to find the equivalent symbolic value. */ + +static const char **error_names; +static int num_error_names = 0; + +/* Translation table allocated and initialized at runtime, if it does not + already exist in the host environment. Indexed by the errno value to find + the descriptive string. + + We don't export it for use in other modules because even though it has the + same name, it differs from other implementations in that it is dynamically + initialized rather than statically initialized. */ + +#ifdef NEED_sys_errlist + +static int sys_nerr; +static const char **sys_errlist; + +#else + +extern int sys_nerr; +extern char *sys_errlist[]; + +#endif + + +/* + +NAME + + init_error_tables -- initialize the name and message tables + +SYNOPSIS + + static void init_error_tables (); + +DESCRIPTION + + Using the error_table, which is initialized at compile time, generate + the error_names and the sys_errlist (if needed) tables, which are + indexed at runtime by a specific errno value. + +BUGS + + The initialization of the tables may fail under low memory conditions, + in which case we don't do anything particularly useful, but we don't + bomb either. Who knows, it might succeed at a later point if we free + some memory in the meantime. In any case, the other routines know + how to deal with lack of a table after trying to initialize it. This + may or may not be considered to be a bug, that we don't specifically + warn about this particular failure mode. + +*/ + +static void +init_error_tables () +{ + const struct error_info *eip; + int nbytes; + + /* If we haven't already scanned the error_table once to find the maximum + errno value, then go find it now. */ + + if (num_error_names == 0) + { + for (eip = error_table; eip -> name != NULL; eip++) + { + if (eip -> value >= num_error_names) + { + num_error_names = eip -> value + 1; + } + } + } + + /* Now attempt to allocate the error_names table, zero it out, and then + initialize it from the statically initialized error_table. */ + + if (error_names == NULL) + { + nbytes = num_error_names * sizeof (char *); + if ((error_names = (const char **) malloc (nbytes)) != NULL) + { + memset (error_names, 0, nbytes); + for (eip = error_table; eip -> name != NULL; eip++) + { + error_names[eip -> value] = eip -> name; + } + } + } + +#ifdef NEED_sys_errlist + + /* Now attempt to allocate the sys_errlist table, zero it out, and then + initialize it from the statically initialized error_table. */ + + if (sys_errlist == NULL) + { + nbytes = num_error_names * sizeof (char *); + if ((sys_errlist = (const char **) malloc (nbytes)) != NULL) + { + memset (sys_errlist, 0, nbytes); + sys_nerr = num_error_names; + for (eip = error_table; eip -> name != NULL; eip++) + { + sys_errlist[eip -> value] = eip -> msg; + } + } + } + +#endif + +} + +/* + +NAME + + errno_max -- return the max errno value + +SYNOPSIS + + int errno_max (); + +DESCRIPTION + + Returns the maximum errno value for which a corresponding symbolic + name or message is available. Note that in the case where + we use the sys_errlist supplied by the system, it is possible for + there to be more symbolic names than messages, or vice versa. + In fact, the manual page for perror(3C) explicitly warns that one + should check the size of the table (sys_nerr) before indexing it, + since new error codes may be added to the system before they are + added to the table. Thus sys_nerr might be smaller than value + implied by the largest errno value defined in <errno.h>. + + We return the maximum value that can be used to obtain a meaningful + symbolic name or message. + +*/ + +int +errno_max () +{ + int maxsize; + + if (error_names == NULL) + { + init_error_tables (); + } + maxsize = MAX (sys_nerr, num_error_names); + return (maxsize - 1); +} + +#ifdef NEED_strerror + +/* + +NAME + + strerror -- map an error number to an error message string + +SYNOPSIS + + char *strerror (int errnoval) + +DESCRIPTION + + Maps an errno number to an error message string, the contents of + which are implementation defined. On systems which have the external + variables sys_nerr and sys_errlist, these strings will be the same + as the ones used by perror(). + + If the supplied error number is within the valid range of indices + for the sys_errlist, but no message is available for the particular + error number, then returns the string "Error NUM", where NUM is the + error number. + + If the supplied error number is not a valid index into sys_errlist, + returns NULL. + + The returned string is only guaranteed to be valid only until the + next call to strerror. + +*/ + +char * +strerror (errnoval) + int errnoval; +{ + char *msg; + static char buf[32]; + +#ifdef NEED_sys_errlist + + if (error_names == NULL) + { + init_error_tables (); + } + +#endif + + if ((errnoval < 0) || (errnoval >= sys_nerr)) + { + /* Out of range, just return NULL */ + msg = NULL; + } + else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL)) + { + /* In range, but no sys_errlist or no entry at this index. */ + sprintf (buf, "Error %d", errnoval); + msg = buf; + } + else + { + /* In range, and a valid message. Just return the message. */ + msg = (char *) sys_errlist[errnoval]; + } + + return (msg); +} + +#endif /* NEED_strerror */ + + +/* + +NAME + + strerrno -- map an error number to a symbolic name string + +SYNOPSIS + + const char *strerrno (int errnoval) + +DESCRIPTION + + Given an error number returned from a system call (typically + returned in errno), returns a pointer to a string containing the + symbolic name of that error number, as found in <errno.h>. + + If the supplied error number is within the valid range of indices + for symbolic names, but no name is available for the particular + error number, then returns the string "Error NUM", where NUM is + the error number. + + If the supplied error number is not within the range of valid + indices, then returns NULL. + +BUGS + + The contents of the location pointed to are only guaranteed to be + valid until the next call to strerrno. + +*/ + +const char * +strerrno (errnoval) + int errnoval; +{ + const char *name; + static char buf[32]; + + if (error_names == NULL) + { + init_error_tables (); + } + + if ((errnoval < 0) || (errnoval >= num_error_names)) + { + /* Out of range, just return NULL */ + name = NULL; + } + else if ((error_names == NULL) || (error_names[errnoval] == NULL)) + { + /* In range, but no error_names or no entry at this index. */ + sprintf (buf, "Error %d", errnoval); + name = (const char *) buf; + } + else + { + /* In range, and a valid name. Just return the name. */ + name = error_names[errnoval]; + } + + return (name); +} + +/* + +NAME + + strtoerrno -- map a symbolic errno name to a numeric value + +SYNOPSIS + + int strtoerrno (char *name) + +DESCRIPTION + + Given the symbolic name of a error number, map it to an errno value. + If no translation is found, returns 0. + +*/ + +int +strtoerrno (name) + const char *name; +{ + int errnoval = 0; + + if (name != NULL) + { + if (error_names == NULL) + { + init_error_tables (); + } + for (errnoval = 0; errnoval < num_error_names; errnoval++) + { + if ((error_names[errnoval] != NULL) && + (strcmp (name, error_names[errnoval]) == 0)) + { + break; + } + } + if (errnoval == num_error_names) + { + errnoval = 0; + } + } + return (errnoval); +} + + +/* A simple little main that does nothing but print all the errno translations + if MAIN is defined and this file is compiled and linked. */ + +#ifdef MAIN + +#include <stdio.h> + +int +main () +{ + int errn; + int errnmax; + const char *name; + char *msg; + char *strerror (); + + errnmax = errno_max (); + printf ("%d entries in names table.\n", num_error_names); + printf ("%d entries in messages table.\n", sys_nerr); + printf ("%d is max useful index.\n", errnmax); + + /* Keep printing values until we get to the end of *both* tables, not + *either* table. Note that knowing the maximum useful index does *not* + relieve us of the responsibility of testing the return pointer for + NULL. */ + + for (errn = 0; errn <= errnmax; errn++) + { + name = strerrno (errn); + name = (name == NULL) ? "<NULL>" : name; + msg = strerror (errn); + msg = (msg == NULL) ? "<NULL>" : msg; + printf ("%-4d%-18s%s\n", errn, name, msg); + } + + return 0; +} + +#endif diff --git a/gnu/lib/libg++/libiberty/strsignal.c b/gnu/lib/libg++/libiberty/strsignal.c new file mode 100644 index 0000000..7acb733 --- /dev/null +++ b/gnu/lib/libg++/libiberty/strsignal.c @@ -0,0 +1,643 @@ +/* Extended support for using signal values. + Copyright (C) 1992 Free Software Foundation, Inc. + Written by Fred Fish. fnf@cygnus.com + +This file is part of the libiberty library. +Libiberty 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. + +Libiberty 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 libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include "ansidecl.h" +#include "libiberty.h" + +#include "config.h" + +#ifdef LOSING_SYS_SIGLIST +#define sys_siglist no_such_symbol +#endif + +#include <stdio.h> +#include <signal.h> + +/* Routines imported from standard C runtime libraries. */ + +#ifdef __STDC__ +#include <stddef.h> +extern void *malloc (size_t size); /* 4.10.3.3 */ +extern void *memset (void *s, int c, size_t n); /* 4.11.6.1 */ +#else /* !__STDC__ */ +extern char *malloc (); /* Standard memory allocater */ +extern char *memset (); +#endif /* __STDC__ */ + +#ifdef LOSING_SYS_SIGLIST +#undef sys_siglist +#endif + + +#ifndef NULL +# ifdef __STDC__ +# define NULL (void *) 0 +# else +# define NULL 0 +# endif +#endif + +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +/* Translation table for signal values. + + Note that this table is generally only accessed when it is used at runtime + to initialize signal name and message tables that are indexed by signal + value. + + Not all of these signals will exist on all systems. This table is the only + thing that should have to be updated as new signal numbers are introduced. + It's sort of ugly, but at least its portable. */ + +struct signal_info +{ + int value; /* The numeric value from <signal.h> */ + const char *name; /* The equivalent symbolic value */ +#ifdef NEED_sys_siglist + const char *msg; /* Short message about this value */ +#endif +}; + +#ifdef NEED_sys_siglist +# define ENTRY(value, name, msg) {value, name, msg} +#else +# define ENTRY(value, name, msg) {value, name} +#endif + +static const struct signal_info signal_table[] = +{ +#if defined (SIGHUP) + ENTRY(SIGHUP, "SIGHUP", "Hangup"), +#endif +#if defined (SIGINT) + ENTRY(SIGINT, "SIGINT", "Interrupt"), +#endif +#if defined (SIGQUIT) + ENTRY(SIGQUIT, "SIGQUIT", "Quit"), +#endif +#if defined (SIGILL) + ENTRY(SIGILL, "SIGILL", "Illegal instruction"), +#endif +#if defined (SIGTRAP) + ENTRY(SIGTRAP, "SIGTRAP", "Trace/breakpoint trap"), +#endif +/* Put SIGIOT before SIGABRT, so that if SIGIOT==SIGABRT then SIGABRT + overrides SIGIOT. SIGABRT is in ANSI and POSIX.1, and SIGIOT isn't. */ +#if defined (SIGIOT) + ENTRY(SIGIOT, "SIGIOT", "IOT trap"), +#endif +#if defined (SIGABRT) + ENTRY(SIGABRT, "SIGABRT", "Aborted"), +#endif +#if defined (SIGEMT) + ENTRY(SIGEMT, "SIGEMT", "Emulation trap"), +#endif +#if defined (SIGFPE) + ENTRY(SIGFPE, "SIGFPE", "Arithmetic exception"), +#endif +#if defined (SIGKILL) + ENTRY(SIGKILL, "SIGKILL", "Killed"), +#endif +#if defined (SIGBUS) + ENTRY(SIGBUS, "SIGBUS", "Bus error"), +#endif +#if defined (SIGSEGV) + ENTRY(SIGSEGV, "SIGSEGV", "Segmentation fault"), +#endif +#if defined (SIGSYS) + ENTRY(SIGSYS, "SIGSYS", "Bad system call"), +#endif +#if defined (SIGPIPE) + ENTRY(SIGPIPE, "SIGPIPE", "Broken pipe"), +#endif +#if defined (SIGALRM) + ENTRY(SIGALRM, "SIGALRM", "Alarm clock"), +#endif +#if defined (SIGTERM) + ENTRY(SIGTERM, "SIGTERM", "Terminated"), +#endif +#if defined (SIGUSR1) + ENTRY(SIGUSR1, "SIGUSR1", "User defined signal 1"), +#endif +#if defined (SIGUSR2) + ENTRY(SIGUSR2, "SIGUSR2", "User defined signal 2"), +#endif +/* Put SIGCLD before SIGCHLD, so that if SIGCLD==SIGCHLD then SIGCHLD + overrides SIGCLD. SIGCHLD is in POXIX.1 */ +#if defined (SIGCLD) + ENTRY(SIGCLD, "SIGCLD", "Child status changed"), +#endif +#if defined (SIGCHLD) + ENTRY(SIGCHLD, "SIGCHLD", "Child status changed"), +#endif +#if defined (SIGPWR) + ENTRY(SIGPWR, "SIGPWR", "Power fail/restart"), +#endif +#if defined (SIGWINCH) + ENTRY(SIGWINCH, "SIGWINCH", "Window size changed"), +#endif +#if defined (SIGURG) + ENTRY(SIGURG, "SIGURG", "Urgent I/O condition"), +#endif +#if defined (SIGIO) + /* "I/O pending" has also been suggested, but is misleading since the + signal only happens when the process has asked for it, not everytime + I/O is pending. */ + ENTRY(SIGIO, "SIGIO", "I/O possible"), +#endif +#if defined (SIGPOLL) + ENTRY(SIGPOLL, "SIGPOLL", "Pollable event occurred"), +#endif +#if defined (SIGSTOP) + ENTRY(SIGSTOP, "SIGSTOP", "Stopped (signal)"), +#endif +#if defined (SIGTSTP) + ENTRY(SIGTSTP, "SIGTSTP", "Stopped (user)"), +#endif +#if defined (SIGCONT) + ENTRY(SIGCONT, "SIGCONT", "Continued"), +#endif +#if defined (SIGTTIN) + ENTRY(SIGTTIN, "SIGTTIN", "Stopped (tty input)"), +#endif +#if defined (SIGTTOU) + ENTRY(SIGTTOU, "SIGTTOU", "Stopped (tty output)"), +#endif +#if defined (SIGVTALRM) + ENTRY(SIGVTALRM, "SIGVTALRM", "Virtual timer expired"), +#endif +#if defined (SIGPROF) + ENTRY(SIGPROF, "SIGPROF", "Profiling timer expired"), +#endif +#if defined (SIGXCPU) + ENTRY(SIGXCPU, "SIGXCPU", "CPU time limit exceeded"), +#endif +#if defined (SIGXFSZ) + ENTRY(SIGXFSZ, "SIGXFSZ", "File size limit exceeded"), +#endif +#if defined (SIGWIND) + ENTRY(SIGWIND, "SIGWIND", "SIGWIND"), +#endif +#if defined (SIGPHONE) + ENTRY(SIGPHONE, "SIGPHONE", "SIGPHONE"), +#endif +#if defined (SIGLOST) + ENTRY(SIGLOST, "SIGLOST", "Resource lost"), +#endif +#if defined (SIGWAITING) + ENTRY(SIGWAITING, "SIGWAITING", "Process's LWPs are blocked"), +#endif +#if defined (SIGLWP) + ENTRY(SIGLWP, "SIGLWP", "Signal LWP"), +#endif +#if defined (SIGDANGER) + ENTRY(SIGDANGER, "SIGDANGER", "Swap space dangerously low"), +#endif +#if defined (SIGGRANT) + ENTRY(SIGGRANT, "SIGGRANT", "Monitor mode granted"), +#endif +#if defined (SIGRETRACT) + ENTRY(SIGRETRACT, "SIGRETRACT", "Need to relinguish monitor mode"), +#endif +#if defined (SIGMSG) + ENTRY(SIGMSG, "SIGMSG", "Monitor mode data available"), +#endif +#if defined (SIGSOUND) + ENTRY(SIGSOUND, "SIGSOUND", "Sound completed"), +#endif +#if defined (SIGSAK) + ENTRY(SIGSAK, "SIGSAK", "Secure attention"), +#endif + ENTRY(0, NULL, NULL) +}; + +/* Translation table allocated and initialized at runtime. Indexed by the + signal value to find the equivalent symbolic value. */ + +static const char **signal_names; +static int num_signal_names = 0; + +/* Translation table allocated and initialized at runtime, if it does not + already exist in the host environment. Indexed by the signal value to find + the descriptive string. + + We don't export it for use in other modules because even though it has the + same name, it differs from other implementations in that it is dynamically + initialized rather than statically initialized. */ + +#ifdef NEED_sys_siglist + +static int sys_nsig; +static const char **sys_siglist; + +#else + +static int sys_nsig = NSIG; +extern const char * const sys_siglist[]; + +#endif + + +/* + +NAME + + init_signal_tables -- initialize the name and message tables + +SYNOPSIS + + static void init_signal_tables (); + +DESCRIPTION + + Using the signal_table, which is initialized at compile time, generate + the signal_names and the sys_siglist (if needed) tables, which are + indexed at runtime by a specific signal value. + +BUGS + + The initialization of the tables may fail under low memory conditions, + in which case we don't do anything particularly useful, but we don't + bomb either. Who knows, it might succeed at a later point if we free + some memory in the meantime. In any case, the other routines know + how to deal with lack of a table after trying to initialize it. This + may or may not be considered to be a bug, that we don't specifically + warn about this particular failure mode. + +*/ + +static void +init_signal_tables () +{ + const struct signal_info *eip; + int nbytes; + + /* If we haven't already scanned the signal_table once to find the maximum + signal value, then go find it now. */ + + if (num_signal_names == 0) + { + for (eip = signal_table; eip -> name != NULL; eip++) + { + if (eip -> value >= num_signal_names) + { + num_signal_names = eip -> value + 1; + } + } + } + + /* Now attempt to allocate the signal_names table, zero it out, and then + initialize it from the statically initialized signal_table. */ + + if (signal_names == NULL) + { + nbytes = num_signal_names * sizeof (char *); + if ((signal_names = (const char **) malloc (nbytes)) != NULL) + { + memset (signal_names, 0, nbytes); + for (eip = signal_table; eip -> name != NULL; eip++) + { + signal_names[eip -> value] = eip -> name; + } + } + } + +#ifdef NEED_sys_siglist + + /* Now attempt to allocate the sys_siglist table, zero it out, and then + initialize it from the statically initialized signal_table. */ + + if (sys_siglist == NULL) + { + nbytes = num_signal_names * sizeof (char *); + if ((sys_siglist = (const char **) malloc (nbytes)) != NULL) + { + memset (sys_siglist, 0, nbytes); + sys_nsig = num_signal_names; + for (eip = signal_table; eip -> name != NULL; eip++) + { + sys_siglist[eip -> value] = eip -> msg; + } + } + } + +#endif + +} + + +/* + +NAME + + signo_max -- return the max signo value + +SYNOPSIS + + int signo_max (); + +DESCRIPTION + + Returns the maximum signo value for which a corresponding symbolic + name or message is available. Note that in the case where + we use the sys_siglist supplied by the system, it is possible for + there to be more symbolic names than messages, or vice versa. + In fact, the manual page for psignal(3b) explicitly warns that one + should check the size of the table (NSIG) before indexing it, + since new signal codes may be added to the system before they are + added to the table. Thus NSIG might be smaller than value + implied by the largest signo value defined in <signal.h>. + + We return the maximum value that can be used to obtain a meaningful + symbolic name or message. + +*/ + +int +signo_max () +{ + int maxsize; + + if (signal_names == NULL) + { + init_signal_tables (); + } + maxsize = MAX (sys_nsig, num_signal_names); + return (maxsize - 1); +} + + +/* + +NAME + + strsignal -- map a signal number to a signal message string + +SYNOPSIS + + const char *strsignal (int signo) + +DESCRIPTION + + Maps an signal number to an signal message string, the contents of + which are implementation defined. On systems which have the external + variable sys_siglist, these strings will be the same as the ones used + by psignal(). + + If the supplied signal number is within the valid range of indices + for the sys_siglist, but no message is available for the particular + signal number, then returns the string "Signal NUM", where NUM is the + signal number. + + If the supplied signal number is not a valid index into sys_siglist, + returns NULL. + + The returned string is only guaranteed to be valid only until the + next call to strsignal. + +*/ + +const char * +strsignal (signo) + int signo; +{ + const char *msg; + static char buf[32]; + +#ifdef NEED_sys_siglist + + if (signal_names == NULL) + { + init_signal_tables (); + } + +#endif + + if ((signo < 0) || (signo >= sys_nsig)) + { + /* Out of range, just return NULL */ + msg = NULL; + } + else if ((sys_siglist == NULL) || (sys_siglist[signo] == NULL)) + { + /* In range, but no sys_siglist or no entry at this index. */ + sprintf (buf, "Signal %d", signo); + msg = (const char *) buf; + } + else + { + /* In range, and a valid message. Just return the message. */ + msg = (const char *) sys_siglist[signo]; + } + + return (msg); +} + + +/* + +NAME + + strsigno -- map an signal number to a symbolic name string + +SYNOPSIS + + const char *strsigno (int signo) + +DESCRIPTION + + Given an signal number, returns a pointer to a string containing + the symbolic name of that signal number, as found in <signal.h>. + + If the supplied signal number is within the valid range of indices + for symbolic names, but no name is available for the particular + signal number, then returns the string "Signal NUM", where NUM is + the signal number. + + If the supplied signal number is not within the range of valid + indices, then returns NULL. + +BUGS + + The contents of the location pointed to are only guaranteed to be + valid until the next call to strsigno. + +*/ + +const char * +strsigno (signo) + int signo; +{ + const char *name; + static char buf[32]; + + if (signal_names == NULL) + { + init_signal_tables (); + } + + if ((signo < 0) || (signo >= num_signal_names)) + { + /* Out of range, just return NULL */ + name = NULL; + } + else if ((signal_names == NULL) || (signal_names[signo] == NULL)) + { + /* In range, but no signal_names or no entry at this index. */ + sprintf (buf, "Signal %d", signo); + name = (const char *) buf; + } + else + { + /* In range, and a valid name. Just return the name. */ + name = signal_names[signo]; + } + + return (name); +} + + +/* + +NAME + + strtosigno -- map a symbolic signal name to a numeric value + +SYNOPSIS + + int strtosigno (char *name) + +DESCRIPTION + + Given the symbolic name of a signal, map it to a signal number. + If no translation is found, returns 0. + +*/ + +int +strtosigno (name) + const char *name; +{ + int signo = 0; + + if (name != NULL) + { + if (signal_names == NULL) + { + init_signal_tables (); + } + for (signo = 0; signo < num_signal_names; signo++) + { + if ((signal_names[signo] != NULL) && + (strcmp (name, signal_names[signo]) == 0)) + { + break; + } + } + if (signo == num_signal_names) + { + signo = 0; + } + } + return (signo); +} + + +/* + +NAME + + psignal -- print message about signal to stderr + +SYNOPSIS + + void psignal (unsigned signo, char *message); + +DESCRIPTION + + Print to the standard error the message, followed by a colon, + followed by the description of the signal specified by signo, + followed by a newline. +*/ + +#ifdef NEED_psignal + +void +psignal (signo, message) + unsigned signo; + char *message; +{ + if (signal_names == NULL) + { + init_signal_tables (); + } + if ((signo <= 0) || (signo >= sys_nsig)) + { + fprintf (stderr, "%s: unknown signal\n", message); + } + else + { + fprintf (stderr, "%s: %s\n", message, sys_siglist[signo]); + } +} + +#endif /* NEED_psignal */ + + +/* A simple little main that does nothing but print all the signal translations + if MAIN is defined and this file is compiled and linked. */ + +#ifdef MAIN + +#include <stdio.h> + +int +main () +{ + int signo; + int maxsigno; + const char *name; + const char *msg; + + maxsigno = signo_max (); + printf ("%d entries in names table.\n", num_signal_names); + printf ("%d entries in messages table.\n", sys_nsig); + printf ("%d is max useful index.\n", maxsigno); + + /* Keep printing values until we get to the end of *both* tables, not + *either* table. Note that knowing the maximum useful index does *not* + relieve us of the responsibility of testing the return pointer for + NULL. */ + + for (signo = 0; signo <= maxsigno; signo++) + { + name = strsigno (signo); + name = (name == NULL) ? "<NULL>" : name; + msg = strsignal (signo); + msg = (msg == NULL) ? "<NULL>" : msg; + printf ("%-4d%-18s%s\n", signo, name, msg); + } + + return 0; +} + +#endif diff --git a/gnu/lib/libg++/libiberty/vasprintf.c b/gnu/lib/libg++/libiberty/vasprintf.c new file mode 100644 index 0000000..b3ba0ca --- /dev/null +++ b/gnu/lib/libg++/libiberty/vasprintf.c @@ -0,0 +1,139 @@ +/* Like vsprintf but provides a pointer to malloc'd storage, which must + be freed by the caller. + Copyright (C) 1994 Free Software Foundation, Inc. + +This file is part of the libiberty library. +Libiberty 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. + +Libiberty 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 libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <stdio.h> +#include <varargs.h> + +#ifdef TEST +int global_total_width; +#endif + +unsigned long strtoul (); +char *malloc (); + +int +vasprintf (result, format, args) + char **result; + char *format; + va_list args; +{ + char *p = format; + /* Add one to make sure that it is never zero, which might cause malloc + to return NULL. */ + int total_width = strlen (format) + 1; + va_list ap = args; + + while (*p != '\0') + { + if (*p++ == '%') + { + while (strchr ("-+ #0", *p)) + ++p; + if (*p == '*') + { + ++p; + total_width += abs (va_arg (ap, int)); + } + else + total_width += strtoul (p, &p, 10); + if (*p == '.') + { + ++p; + if (*p == '*') + { + ++p; + total_width += abs (va_arg (ap, int)); + } + else + total_width += strtoul (p, &p, 10); + } + while (strchr ("hlL", *p)) + ++p; + /* Should be big enough for any format specifier except %s. */ + total_width += 30; + switch (*p) + { + case 'd': + case 'i': + case 'o': + case 'u': + case 'x': + case 'X': + case 'c': + va_arg (ap, int); + break; + case 'f': + case 'e': + case 'E': + case 'g': + case 'G': + va_arg (ap, double); + break; + case 's': + total_width += strlen (va_arg (ap, char *)); + break; + case 'p': + case 'n': + va_arg (ap, char *); + break; + } + } + } +#ifdef TEST + global_total_width = total_width; +#endif + *result = malloc (total_width); + if (*result != NULL) + return vsprintf (*result, format, args); + else + return 0; +} + +#ifdef TEST +void +checkit (va_alist) + va_dcl +{ + va_list args; + char *format; + char *result; + + va_start (args); + format = va_arg (args, char *); + vasprintf (&result, format, args); + if (strlen (result) < global_total_width) + printf ("PASS: "); + else + printf ("FAIL: "); + printf ("%d %s\n", global_total_width, result); +} + +int +main () +{ + checkit ("%d", 0x12345678); + checkit ("%200d", 5); + checkit ("%.300d", 6); + checkit ("%100.150d", 7); + checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\ +777777777777777777333333333333366666666666622222222222777777777777733333"); + checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx"); +} +#endif /* TEST */ diff --git a/gnu/lib/libg++/libio/PlotFile.cc b/gnu/lib/libg++/libio/PlotFile.cc new file mode 100644 index 0000000..a5af5c1 --- /dev/null +++ b/gnu/lib/libg++/libio/PlotFile.cc @@ -0,0 +1,157 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +// This may look like C code, but it is really -*- C++ -*- +/* +Copyright (C) 1988, 1992, 1993 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 the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with GCC to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#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; +} diff --git a/gnu/lib/libg++/libio/SFile.cc b/gnu/lib/libg++/libio/SFile.cc new file mode 100644 index 0000000..24f668b --- /dev/null +++ b/gnu/lib/libg++/libio/SFile.cc @@ -0,0 +1,82 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* +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()->sseekoff(i * sz, ios::beg) == EOF) + set(ios::badbit); + return *this; +} diff --git a/gnu/lib/libg++/libio/builtinbuf.cc b/gnu/lib/libg++/libio/builtinbuf.cc new file mode 100644 index 0000000..d6b9ebb --- /dev/null +++ b/gnu/lib/libg++/libio/builtinbuf.cc @@ -0,0 +1,96 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#ifdef __GNUC__ +#pragma implementation +#endif +#define _STREAM_COMPAT +#include "builtinbuf.h" +#include "iostreamP.h" + +int builtinbuf::overflow(int ch) { return (*_jumps->__overflow)(this, ch); } + +int builtinbuf::underflow() { return (*_jumps->__underflow)(this); } + +streamsize builtinbuf::xsgetn(char* buf, streamsize n) +{ return (*_jumps->__xsgetn)(this, buf, n); } + +streamsize builtinbuf::xsputn(const char* buf, streamsize n) +{ return _jumps->__xsputn (this, buf, n); } + +int builtinbuf::doallocate() { return _jumps->__doallocate(this); } + +builtinbuf::~builtinbuf() { _jumps->__finish(this); } + +int builtinbuf::sync() { return _jumps->__sync(this); } + +streambuf* builtinbuf::setbuf(char *buf, int n) +{ return _jumps->__setbuf (this, buf, n) == 0 ? this : NULL; } + +streampos builtinbuf::seekoff(streamoff off, _seek_dir dir, int mode) +{ + return _jumps->__seekoff (this, off, convert_to_seekflags(dir, mode)); +} + +streampos builtinbuf::seekpos(streampos pos, int mode) +{ + int flags = 0; + if (!(mode & ios::in)) + flags |= _IO_seek_not_in; + if (!(mode & ios::out)) + flags |= _IO_seek_not_out; + return _jumps->__seekpos(this, pos, (_IO_seekflags)flags); +} + +int builtinbuf::pbackfail(int c) +{ return _jumps->__pbackfail(this, c); } + +streamsize builtinbuf::sys_read(char* buf, streamsize size) +{ return _jumps->__read(this, buf, size); } + +streampos builtinbuf::sys_seek(streamoff off, _seek_dir dir) +{ return _jumps->__seek(this, off, dir); } + +streamsize builtinbuf::sys_write(const char* buf, streamsize size) +{ return _jumps->__write(this, buf, size); } + +int builtinbuf::sys_stat(void* buf) // Actually, a (struct stat*) +{ return _jumps->__stat(this, buf); } + +int builtinbuf::sys_close() +{ return _jumps->__close(this); } + +#ifdef _STREAM_COMPAT +/* These methods are TEMPORARY, for binary compatibility! */ +#include <stdlib.h> +void ios::_IO_fix_vtable() const +{ + abort (); +} + +void ios::_IO_fix_vtable() +{ + ((const ios*) this)->_IO_fix_vtable(); +} +#endif diff --git a/gnu/lib/libg++/libio/cleanup.c b/gnu/lib/libg++/libio/cleanup.c new file mode 100644 index 0000000..35c2ef1 --- /dev/null +++ b/gnu/lib/libg++/libio/cleanup.c @@ -0,0 +1,14 @@ +#include "libioP.h" +#if _G_HAVE_ATEXIT +#include <stdlib.h> + +typedef void (*voidfunc) __P((void)); + +static void _IO_register_cleanup () +{ + atexit ((voidfunc)_IO_cleanup); + _IO_cleanup_registration_needed = 0; +} + +void (*_IO_cleanup_registration_needed)() = _IO_register_cleanup; +#endif /* _G_HAVE_ATEXIT */ diff --git a/gnu/lib/libg++/libio/editbuf.cc b/gnu/lib/libg++/libio/editbuf.cc new file mode 100644 index 0000000..87358fa --- /dev/null +++ b/gnu/lib/libg++/libio/editbuf.cc @@ -0,0 +1,717 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. + +Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "libioP.h" +#include "editbuf.h" +#include <stddef.h> +#include <stdlib.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); + } + } +} diff --git a/gnu/lib/libg++/libio/filebuf.cc b/gnu/lib/libg++/libio/filebuf.cc new file mode 100644 index 0000000..6290636 --- /dev/null +++ b/gnu/lib/libg++/libio/filebuf.cc @@ -0,0 +1,199 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. + +Written by Per Bothner (bothner@cygnus.com). */ + +#include "iostreamP.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include "builtinbuf.h" + +void filebuf::init() +{ + _IO_file_init(this); +} + +filebuf::filebuf() +{ + _IO_file_init(this); +} + +/* This is like "new filebuf()", but it uses the _IO_file_jump jumptable, + for eficiency. */ + +filebuf* filebuf::__new() +{ + filebuf *fb = new filebuf; + fb->_jumps = &_IO_file_jumps; + fb->_vtable() = builtinbuf_vtable; + return fb; +} + +filebuf::filebuf(int fd) +{ + _IO_file_init(this); + _IO_file_attach(this, fd); +} + +filebuf::filebuf(int fd, char* p, int len) +{ + _IO_file_init(this); + _IO_file_attach(this, fd); + setbuf(p, len); +} + +filebuf::~filebuf() +{ + if (!(xflags() & _IO_DELETE_DONT_CLOSE)) + close(); + + _un_link(); +} + +filebuf* filebuf::open(const char *filename, ios::openmode mode, int prot) +{ + if (_IO_file_is_open (this)) + 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 = _IO_NO_READS; + else if (mode & (int)ios::in) + posix_mode = O_RDONLY, read_write = _IO_NO_WRITES; + else + posix_mode = 0, read_write = _IO_NO_READS+_IO_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 |= _IO_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; + _fileno = fd; + xsetflags(read_write, _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING); + if (mode & (ios::ate|ios::app)) { + if (sseekoff(0, ios::end) == EOF) + return NULL; + } + _IO_link_in(this); + return this; +} + +filebuf* filebuf::open(const char *filename, const char *mode) +{ + return (filebuf*)_IO_file_fopen(this, filename, mode); +} + +filebuf* filebuf::attach(int fd) +{ + return (filebuf*)_IO_file_attach(this, fd); +} + +streambuf* filebuf::setbuf(char* p, int len) +{ + return _IO_file_setbuf(this, p, len) == 0 ? this : NULL; +} + +int filebuf::doallocate() { return _IO_file_doallocate(this); } + +int filebuf::overflow(int c) +{ + return _IO_file_overflow(this, c); +} + +int filebuf::underflow() +{ + return _IO_file_underflow(this); +} + +int filebuf::do_write(const char *data, int to_do) +{ + return _IO_do_write(this, data, to_do); +} + +int filebuf::sync() +{ + return _IO_file_sync(this); +} + +streampos filebuf::seekoff(streamoff offset, _seek_dir dir, int mode) +{ + return _IO_file_seekoff (this, offset, convert_to_seekflags(dir, mode)); +} + +filebuf* filebuf::close() +{ + return (_IO_file_close_it(this) ? NULL : this); +} + +streamsize filebuf::sys_read(char* buf, streamsize size) +{ + return _IO_file_read(this, buf, size); +} + +streampos filebuf::sys_seek(streamoff offset, _seek_dir dir) +{ + return _IO_file_seek(this, offset, dir); +} + +streamsize filebuf::sys_write(const char *buf, streamsize n) +{ + return _IO_file_write (this, buf, n); +} + +int filebuf::sys_stat(void* st) +{ + return _IO_file_stat (this, st); +} + +int filebuf::sys_close() +{ + return _IO_file_close (this); +} + +streamsize filebuf::xsputn(const char *s, streamsize n) +{ + return _IO_file_xsputn(this, s, n); +} + +streamsize filebuf::xsgetn(char *s, streamsize 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; diff --git a/gnu/lib/libg++/libio/filedoalloc.c b/gnu/lib/libg++/libio/filedoalloc.c new file mode 100644 index 0000000..a85b846 --- /dev/null +++ b/gnu/lib/libg++/libio/filedoalloc.c @@ -0,0 +1,103 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* + * 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, 1992. */ + +#define _POSIX_SOURCE +#include "libioP.h" +#include <sys/types.h> +#include <sys/stat.h> +#ifdef __STDC__ +#include <stdlib.h> +#endif + +/* If this function pointer is non-zero, we should call it. + It's supposed to make sure _IO_cleanup gets called on exit. + We call it from _IO_file_doallocate, since that is likely + to get called by any program that does buffered I/O. */ +void (*_IO_cleanup_registration_needed)(); + +/* + * 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 +_IO_file_doallocate(fp) + register _IO_FILE *fp; +{ + register _IO_size_t size; + int couldbetty; + register char *p; + struct stat st; + + if (_IO_cleanup_registration_needed) + (*_IO_cleanup_registration_needed)(); + + if (fp->_fileno < 0 || fp->_jumps->__stat(fp, &st) < 0) + { + couldbetty = 0; + size = _IO_BUFSIZ; +#if 0 + /* do not try to optimise fseek() */ + fp->_flags |= __SNPT; +#endif + } + else + { + couldbetty = S_ISCHR(st.st_mode); +#if _IO_HAVE_ST_BLKSIZE + size = st.st_blksize <= 0 ? _IO_BUFSIZ : st.st_blksize; +#else + size = _IO_BUFSIZ; +#endif + } + p = ALLOC_BUF(size); + if (p == NULL) + return EOF; + _IO_setb(fp, p, p+size, 1); + if (couldbetty && isatty(fp->_fileno)) + fp->_flags |= _IO_LINE_BUF; + return 1; +} diff --git a/gnu/lib/libg++/libio/fileops.c b/gnu/lib/libg++/libio/fileops.c new file mode 100644 index 0000000..47398a8 --- /dev/null +++ b/gnu/lib/libg++/libio/fileops.c @@ -0,0 +1,735 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* written by Per Bothner (bothner@cygnus.com) */ + +#define _POSIX_SOURCE +#include "libioP.h" +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <errno.h> +#ifndef errno +extern int errno; +#endif + +/* 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 \ + (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET) + + +void +_IO_file_init(fp) + register _IO_FILE *fp; +{ + fp->_offset = _IO_pos_0; + fp->_IO_file_flags |= CLOSED_FILEBUF_FLAGS; + + _IO_link_in(fp); + fp->_fileno = -1; +} + +int +_IO_file_close_it(fp) + register _IO_FILE* fp; +{ + int status; + if (!_IO_file_is_open(fp)) + return EOF; + + _IO_do_flush (fp); + + _IO_unsave_markers(fp); + + status = fp->_jumps->__close(fp); + + /* Free buffer. */ + _IO_setb(fp, NULL, NULL, 0); + _IO_setg(fp, NULL, NULL, NULL); + _IO_setp(fp, NULL, NULL); + + _IO_un_link(fp); + fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS; + fp->_fileno = EOF; + fp->_offset = _IO_pos_0; + + return status; +} + +void +_IO_file_finish(fp) + register _IO_FILE* fp; +{ + if (_IO_file_is_open(fp)) + { + _IO_do_flush (fp); + if (!(fp->_flags & _IO_DELETE_DONT_CLOSE)) + fp->_jumps->__close(fp); + } + _IO_default_finish(fp); +} + +_IO_FILE * +_IO_file_fopen(fp, filename, mode) + register _IO_FILE *fp; + const char *filename; + const char *mode; +{ + int oflags = 0, omode; + int read_write, fdesc; + int oprot = 0666; + if (_IO_file_is_open (fp)) + return 0; + switch (*mode++) { + case 'r': + omode = O_RDONLY; + read_write = _IO_NO_WRITES; + break; + case 'w': + omode = O_WRONLY; + oflags = O_CREAT|O_TRUNC; + read_write = _IO_NO_READS; + break; + case 'a': + omode = O_WRONLY; + oflags = O_CREAT|O_APPEND; + read_write = _IO_NO_READS|_IO_IS_APPENDING; + break; + default: + errno = EINVAL; + return NULL; + } + if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+')) { + omode = O_RDWR; + read_write &= _IO_IS_APPENDING; + } + fdesc = open(filename, omode|oflags, oprot); + if (fdesc < 0) + return NULL; + fp->_fileno = fdesc; + _IO_mask_flags(fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING); + if (read_write & _IO_IS_APPENDING) + if (fp->_jumps->__seekoff(fp, (_IO_off_t)0, _IO_seek_end) == _IO_pos_BAD) + return NULL; + _IO_link_in(fp); + return fp; +} + +_IO_FILE* +_IO_file_attach(fp, fd) + _IO_FILE *fp; + int fd; +{ + if (_IO_file_is_open(fp)) + return NULL; + fp->_fileno = fd; + fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES); + fp->_flags |= _IO_DELETE_DONT_CLOSE; + fp->_offset = _IO_pos_BAD; + return fp; +} + +int +_IO_file_setbuf(fp, p, len) + register _IO_FILE *fp; + char* p; + _IO_ssize_t len; +{ + if (_IO_default_setbuf(fp, p, len) == EOF) + return EOF; + + fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end + = fp->_IO_buf_base; + _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); + + return 0; +} + +int +_IO_do_write(fp, data, to_do) + register _IO_FILE *fp; + const char* data; + _IO_size_t to_do; +{ + _IO_size_t count; + if (to_do == 0) + return 0; + if (fp->_flags & _IO_IS_APPENDING) + /* On a system without a proper O_APPEND implementation, + you would need to sys_seek(0, SEEK_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. */ + fp->_offset = _IO_pos_BAD; + else if (fp->_IO_read_end != fp->_IO_write_base) + { + _IO_pos_t new_pos = fp->_jumps->__seek(fp, fp->_IO_write_base - fp->_IO_read_end, 1); + if (new_pos == _IO_pos_BAD) + return EOF; + fp->_offset = new_pos; + } + count = fp->_jumps->__write(fp, data, to_do); + if (fp->_cur_column) + fp->_cur_column = _IO_adjust_column(fp->_cur_column - 1, data, to_do) + 1; + _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); + fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base; + fp->_IO_write_end = (fp->_flags & _IO_LINE_BUF+_IO_UNBUFFERED) ? fp->_IO_buf_base + : fp->_IO_buf_end; + return count != to_do ? EOF : 0; +} + +int +_IO_file_underflow(fp) + register _IO_FILE *fp; +{ + _IO_ssize_t count; +#if 0 + /* SysV does not make this test; take it out for compatibility */ + if (fp->_flags & _IO_EOF_SEEN) + return (EOF); +#endif + + if (fp->_flags & _IO_NO_READS) + return EOF; + if (fp->_IO_read_ptr < fp->_IO_read_end) + return *(unsigned char*)fp->_IO_read_ptr; + + if (fp->_IO_buf_base == NULL) + _IO_doallocbuf(fp); + + /* Flush all line buffered files before reading. */ + /* FIXME This can/should be moved to genops ?? */ + if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED)) + _IO_flush_all_linebuffered(); + + _IO_switch_to_get_mode(fp); + + count = fp->_jumps->__read(fp, fp->_IO_buf_base, + fp->_IO_buf_end - fp->_IO_buf_base); + if (count <= 0) + { + if (count == 0) + fp->_flags |= _IO_EOF_SEEN; + else + fp->_flags |= _IO_ERR_SEEN, count = 0; + } + fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base; + fp->_IO_read_end = fp->_IO_buf_base + count; + fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end + = fp->_IO_buf_base; + if (count == 0) + return EOF; + if (fp->_offset != _IO_pos_BAD) + _IO_pos_adjust(fp->_offset, count); + return *(unsigned char*)fp->_IO_read_ptr; +} + +int _IO_file_overflow (f, ch) + register _IO_FILE* f; + int ch; +{ + if (f->_flags & _IO_NO_WRITES) /* SET ERROR */ + return EOF; + /* If current reading or no buffer allocated. */ + if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0) + { + /* Allocate a buffer if needed. */ + if (f->_IO_buf_base == 0) + { + _IO_doallocbuf(f); + f->_IO_read_end = f->_IO_buf_base; + f->_IO_write_ptr = f->_IO_buf_base; + } + else /* Must be currently reading. */ + f->_IO_write_ptr = f->_IO_read_ptr; + f->_IO_write_base = f->_IO_write_ptr; + f->_IO_write_end = f->_IO_buf_end; + f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end; + + if (f->_flags & _IO_LINE_BUF+_IO_UNBUFFERED) + f->_IO_write_end = f->_IO_write_ptr; + f->_flags |= _IO_CURRENTLY_PUTTING; + } + if (ch == EOF) + return _IO_do_flush(f); + if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */ + if (_IO_do_flush(f) == EOF) + return EOF; + *f->_IO_write_ptr++ = ch; + if ((f->_flags & _IO_UNBUFFERED) + || ((f->_flags & _IO_LINE_BUF) && ch == '\n')) + if (_IO_do_flush(f) == EOF) + return EOF; + return (unsigned char)ch; +} + +int +_IO_file_sync(fp) + register _IO_FILE* fp; +{ + _IO_size_t delta; + /* char* ptr = cur_ptr(); */ + if (fp->_IO_write_ptr > fp->_IO_write_base) + if (_IO_do_flush(fp)) return EOF; + delta = fp->_IO_read_ptr - fp->_IO_read_end; + if (delta != 0) + { +#ifdef TODO + if (_IO_in_backup(fp)) + delta -= eGptr() - Gbase(); +#endif + _IO_off_t new_pos = fp->_jumps->__seek(fp, delta, 1); + if (new_pos == (_IO_off_t)EOF) + return EOF; + fp->_offset = new_pos; + fp->_IO_read_end = fp->_IO_read_ptr; + } + /* FIXME: Cleanup - can this be shared? */ + /* setg(base(), ptr, ptr); */ + return 0; +} + +_IO_pos_t +_IO_file_seekoff(fp, offset, mode) + register _IO_FILE *fp; + _IO_off_t offset; + _IO_seekflags mode; +{ + _IO_pos_t result; + _IO_off_t delta, new_offset; + long count; + int dir = mode & 3; + + if ((mode & _IO_seek_not_in) && (mode & _IO_seek_not_out)) + dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */ + + /* 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.) + FIXME: simulate mem-papped files. */ + + if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode(fp)) + if (_IO_switch_to_get_mode(fp)) return EOF; + + if (fp->_IO_buf_base == NULL) + { + _IO_doallocbuf(fp); + _IO_setp(fp, fp->_IO_buf_base, fp->_IO_buf_base); + _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); + } + + switch (dir) + { + case _IO_seek_cur: + if (fp->_offset == _IO_pos_BAD) + goto dumb; + /* Adjust for read-ahead (bytes is buffer). */ + offset -= fp->_IO_read_end - fp->_IO_read_ptr; + /* Make offset absolute, assuming current pointer is file_ptr(). */ + offset += _IO_pos_as_off(fp->_offset); + + dir = _IO_seek_set; + break; + case _IO_seek_set: + break; + case _IO_seek_end: + { + struct stat st; + if (fp->_jumps->__stat(fp, &st) == 0 && S_ISREG(st.st_mode)) + { + offset += st.st_size; + dir = _IO_seek_set; + } + else + goto dumb; + } + } + /* At this point, dir==_IO_seek_set. */ + +#ifdef TODO + /* If destination is within current buffer, optimize: */ + if (fp->_offset != IO_pos_BAD && fp->_IO_read_base != NULL) + { + /* Offset relative to start of main get area. */ + _IO_pos_t rel_offset = offset - _fb._offset + + (eGptr()-Gbase()); + if (rel_offset >= 0) + { + if (_IO_in_backup(fp)) + _IO_switch_to_main_get_area(fp); + if (rel_offset <= _IO_read_end - _IO_read_base) + { + _IO_setg(fp->_IO_buf_base, fp->_IO_buf_base + rel_offset, + fp->_IO_read_end); + _IO_setp(fp->_IO_buf_base, fp->_IO_buf_base); + return offset; + } + /* If we have streammarkers, seek forward by reading ahead. */ + if (_IO_have_markers(fp)) + { + int to_skip = rel_offset + - (fp->_IO_read_ptr - fp->_IO_read_base); + if (ignore(to_skip) != to_skip) + goto dumb; + return offset; + } + } + if (rel_offset < 0 && rel_offset >= Bbase() - Bptr()) + { + if (!_IO_in_backup(fp)) + _IO_switch_to_backup_area(fp); + gbump(fp->_IO_read_end + rel_offset - fp->_IO_read_ptr); + return offset; + } + } + + _IO_unsave_markers(fp); +#endif + + /* Try to seek to a block boundary, to improve kernel page management. */ + new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1); + delta = offset - new_offset; + if (delta > fp->_IO_buf_end - fp->_IO_buf_base) + { + new_offset = offset; + delta = 0; + } + result = fp->_jumps->__seek(fp, new_offset, 0); + if (result < 0) + return EOF; + if (delta == 0) + count = 0; + else + { + count = fp->_jumps->__read(fp, fp->_IO_buf_base, + fp->_IO_buf_end - fp->_IO_buf_base); + if (count < delta) + { + /* We weren't allowed to read, but try to seek the remainder. */ + offset = count == EOF ? delta : delta-count; + dir = _IO_seek_cur; + goto dumb; + } + } + _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base+delta, fp->_IO_buf_base+count); + _IO_setp(fp, fp->_IO_buf_base, fp->_IO_buf_base); + fp->_offset = result + count; + _IO_mask_flags(fp, 0, _IO_EOF_SEEN); + return offset; + dumb: + + _IO_unsave_markers(fp); + result = fp->_jumps->__seek(fp, offset, dir); + if (result != EOF) + _IO_mask_flags(fp, 0, _IO_EOF_SEEN); + fp->_offset = result; + _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); + _IO_setp(fp, fp->_IO_buf_base, fp->_IO_buf_base); + return result; +} + +_IO_ssize_t +_IO_file_read(fp, buf, size) + register _IO_FILE* fp; + void* buf; + _IO_ssize_t size; +{ + for (;;) + { + _IO_ssize_t count = _IO_read(fp->_fileno, buf, size); +#ifdef EINTR + if (count == -1 && errno == EINTR) + continue; +#endif + return count; + } +} + +_IO_pos_t +_IO_file_seek(fp, offset, dir) + _IO_FILE *fp; + _IO_off_t offset; + int dir; +{ + return _IO_lseek(fp->_fileno, offset, dir); +} + +int +_IO_file_stat(fp, st) + _IO_FILE *fp; + void* st; +{ + return _IO_fstat(fp->_fileno, (struct stat*)st); +} + +int +_IO_file_close(fp) + _IO_FILE* fp; +{ + return _IO_close(fp->_fileno); +} + +_IO_ssize_t +_IO_file_write(f, data, n) + register _IO_FILE* f; + const void* data; + _IO_ssize_t n; +{ + _IO_ssize_t to_do = n; + while (to_do > 0) + { + _IO_ssize_t count = _IO_write(f->_fileno, data, to_do); + if (count == EOF) + { +#ifdef EINTR + if (errno == EINTR) + continue; + else +#endif + { + f->_flags |= _IO_ERR_SEEN; + break; + } + } + to_do -= count; + data = (void*)((char*)data + count); + } + n -= to_do; + if (f->_offset >= 0) + f->_offset += n; + return n; +} + +_IO_size_t +_IO_file_xsputn(f, data, n) + _IO_FILE *f; + const void *data; + _IO_size_t n; +{ + register const char *s = data; + _IO_size_t to_do = n; + int must_flush = 0; + _IO_size_t count; + + 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. */ + + /* First figure out how much space is available in the buffer. */ + count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */ + if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING)) + { + count = f->_IO_buf_end - f->_IO_write_ptr; + if (count >= n) + { register const char *p; + for (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(f->_IO_write_ptr, s, count); + s += count; + } + else + { + register char *p = f->_IO_write_ptr; + register int i = (int)count; + while (--i >= 0) *p++ = *s++; + } + f->_IO_write_ptr += count; + to_do -= count; + } + if (to_do + must_flush > 0) + { _IO_size_t block_size, dont_write; + /* Next flush the (full) buffer. */ + if (__overflow(f, EOF) == EOF) + return n - to_do; + + /* Try to maintain alignment: write a whole number of blocks. + dont_write is what gets left over. */ + block_size = f->_IO_buf_end - f->_IO_buf_base; + dont_write = block_size >= 128 ? to_do % block_size : 0; + + count = to_do - dont_write; + if (_IO_do_write(f, 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 _IO_default_xsputn handle the general case. */ + if (dont_write) + to_do -= _IO_default_xsputn(f, s+count, dont_write); + } + return n - to_do; +} + +#if 0 +/* Work in progress */ +_IO_size_t +_IO_file_xsgetn(fp, data, n) + _IO_FILE *fp; + void *data; + _IO_size_t n; +{ + register _IO_size_t more = n; + register char *s = data; + for (;;) + { + _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr; /* Data available. */ + if (count > 0) + { + if (count > more) + count = more; + if (count > 20) + { + memcpy(s, fp->_IO_read_ptr, count); + s += count; + fp->_IO_read_ptr += count; + } + else if (count <= 0) + count = 0; + else + { + register char *p = fp->_IO_read_ptr; + register int i = (int)count; + while (--i >= 0) *s++ = *p++; + fp->_IO_read_ptr = p; + } + more -= count; + } +#if 0 + if (! _IO_in put_mode (fp) + && ! _IO_have_markers (fp) && ! IO_have_backup (fp)) + { + /* This is an optimization of _IO_file_underflow */ + if (fp->_flags & _IO_NO_READS) + break; + /* If we're reading a lot of data, don't bother allocating + a buffer. But if we're only reading a bit, perhaps we should ??*/ + if (count <= 512 && fp->_IO_buf_base == NULL) + _IO_doallocbuf(fp); + if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED)) + _IO_flush_all_linebuffered(); + + _IO_switch_to_get_mode(fp); ???; + count = fp->_jumps->__read (fp, s, more); + if (count <= 0) + { + if (count == 0) + fp->_flags |= _IO_EOF_SEEN; + else + fp->_flags |= _IO_ERR_SEEN, count = 0; + } + + s += count; + more -= count; + } +#endif + if (more == 0 || __underflow(fp) == EOF) + break; + } + return n - more; +} +#endif + +struct _IO_jump_t _IO_file_jumps = { + _IO_file_overflow, + _IO_file_underflow, + _IO_file_xsputn, + _IO_default_xsgetn, + _IO_file_read, + _IO_file_write, + _IO_file_doallocate, + _IO_default_pbackfail, + _IO_file_setbuf, + _IO_file_sync, + _IO_file_finish, + _IO_file_close, + _IO_file_stat, + _IO_file_seek, + _IO_file_seekoff, + _IO_default_seekpos, + _IO_default_uflow +}; diff --git a/gnu/lib/libg++/libio/floatconv.c b/gnu/lib/libg++/libio/floatconv.c new file mode 100644 index 0000000..84eb848 --- /dev/null +++ b/gnu/lib/libg++/libio/floatconv.c @@ -0,0 +1,2357 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include <libioP.h> +#ifdef USE_DTOA +/**************************************************************** + * + * The author of this software is David M. Gay. + * + * Copyright (c) 1991 by AT&T. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + ***************************************************************/ + +/* Some cleaning up by Per Bothner, bothner@cygnus.com, 1992, 1993. + Re-written to not need static variables + (except result, result_k, HIWORD, LOWORD). */ + +/* Please send bug reports to + David M. Gay + AT&T Bell Laboratories, Room 2C-463 + 600 Mountain Avenue + Murray Hill, NJ 07974-2070 + U.S.A. + dmg@research.att.com or research!dmg + */ + +/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. + * + * This strtod returns a nearest machine number to the input decimal + * string (or sets errno to ERANGE). With IEEE arithmetic, ties are + * broken by the IEEE round-even rule. Otherwise ties are broken by + * biased rounding (add half and chop). + * + * Inspired loosely by William D. Clinger's paper "How to Read Floating + * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. + * + * Modifications: + * + * 1. We only require IEEE, IBM, or VAX double-precision + * arithmetic (not IEEE double-extended). + * 2. We get by with floating-point arithmetic in a case that + * Clinger missed -- when we're computing d * 10^n + * for a small integer d and the integer n is not too + * much larger than 22 (the maximum integer k for which + * we can represent 10^k exactly), we may be able to + * compute (d*10^k) * 10^(e-k) with just one roundoff. + * 3. Rather than a bit-at-a-time adjustment of the binary + * result in the hard case, we use floating-point + * arithmetic to determine the adjustment to within + * one bit; only in really hard cases do we need to + * compute a second residual. + * 4. Because of 3., we don't need a large table of powers of 10 + * for ten-to-e (just some small tables, e.g. of 10^k + * for 0 <= k <= 22). + */ + +/* + * #define IEEE_8087 for IEEE-arithmetic machines where the least + * significant byte has the lowest address. + * #define IEEE_MC68k for IEEE-arithmetic machines where the most + * significant byte has the lowest address. + * #define Sudden_Underflow for IEEE-format machines without gradual + * underflow (i.e., that flush to zero on underflow). + * #define IBM for IBM mainframe-style floating-point arithmetic. + * #define VAX for VAX-style floating-point arithmetic. + * #define Unsigned_Shifts if >> does treats its left operand as unsigned. + * #define No_leftright to omit left-right logic in fast floating-point + * computation of dtoa. + * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3. + * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines + * that use extended-precision instructions to compute rounded + * products and quotients) with IBM. + * #define ROUND_BIASED for IEEE-format with biased rounding. + * #define Inaccurate_Divide for IEEE-format with correctly rounded + * products but inaccurate quotients, e.g., for Intel i860. + * #define KR_headers for old-style C function headers. + */ + +#ifdef DEBUG +#include <stdio.h> +#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} +#endif + +#ifdef __STDC__ +#include <stdlib.h> +#include <string.h> +#include <float.h> +#define CONST const +#else +#define CONST +#define KR_headers + +/* In this case, we assume IEEE floats. */ +#define FLT_ROUNDS 1 +#define FLT_RADIX 2 +#define DBL_MANT_DIG 53 +#define DBL_DIG 15 +#define DBL_MAX_10_EXP 308 +#define DBL_MAX_EXP 1024 +#endif + +#include <errno.h> +#ifndef __MATH_H__ +#include <math.h> +#endif + +#ifdef Unsigned_Shifts +#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000; +#else +#define Sign_Extend(a,b) /*no-op*/ +#endif + +#if defined(__i386__) || defined(__i860__) || defined(clipper) +#define IEEE_8087 +#endif +#if defined(MIPSEL) || defined(__alpha__) +#define IEEE_8087 +#endif +#if defined(__sparc__) || defined(sparc) || defined(MIPSEB) +#define IEEE_MC68k +#endif + +#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 + +#if FLT_RADIX==16 +#define IBM +#else +#if DBL_MANT_DIG==56 +#define VAX +#else +#if DBL_MANT_DIG==53 && DBL_MAX_10_EXP==308 +#define IEEE_Unknown +#else +Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. +#endif +#endif +#endif +#endif + +typedef _G_uint32_t unsigned32; + +#ifdef IEEE_8087 +#define HIWORD 1 +#define LOWORD 0 +#define TEST_ENDIANNESS /* nothing */ +#else +#if defined(IEEE_MC68k) +#define HIWORD 0 +#define LOWORD 1 +#define TEST_ENDIANNESS /* nothing */ +#else +static int HIWORD = -1, LOWORD; +static void test_endianness() +{ + union doubleword { + double d; + unsigned32 u[2]; + } dw; + dw.d = 10; + if (dw.u[0] != 0) /* big-endian */ + HIWORD=0, LOWORD=1; + else + HIWORD=1, LOWORD=0; +} +#define TEST_ENDIANNESS if (HIWORD<0) test_endianness(); +#endif +#endif + +#if 0 +union { + double d; + unsigned32 x[2]; +} _temp; +#endif +#define word0(x) ((unsigned32 *)&x)[HIWORD] +#if 0 +#define word0(X) (_temp.d = X, _temp.x[HIWORD]) +#define setword0(D,X) (_temp.d = D, _temp.x[HIWORD] = X, D = _temp.d) +#endif +#define word1(x) ((unsigned32 *)&x)[LOWORD] + +/* The following definition of Storeinc is appropriate for MIPS processors. */ +#if defined(IEEE_8087) + defined(VAX) +#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ +((unsigned short *)a)[0] = (unsigned short)c, a++) +#else +#if defined(IEEE_MC68k) +#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ +((unsigned short *)a)[1] = (unsigned short)c, a++) +#else +#define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) +#endif +#endif + +/* #define P DBL_MANT_DIG */ +/* Ten_pmax = floor(P*log(2)/log(5)) */ +/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ +/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ +/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ + +#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(IEEE_Unknown) +#define Exp_shift 20 +#define Exp_shift1 20 +#define Exp_msk1 0x100000 +#define Exp_msk11 0x100000 +#define Exp_mask 0x7ff00000 +#define P 53 +#define Bias 1023 +#define IEEE_Arith +#define Emin (-1022) +#define Exp_1 0x3ff00000 +#define Exp_11 0x3ff00000 +#define Ebits 11 +#define Frac_mask 0xfffff +#define Frac_mask1 0xfffff +#define Ten_pmax 22 +#define Bletch 0x10 +#define Bndry_mask 0xfffff +#define Bndry_mask1 0xfffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 1 +#define Tiny0 0 +#define Tiny1 1 +#define Quick_max 14 +#define Int_max 14 +#define Infinite(x) (word0(x) == 0x7ff00000) /* sufficient test for here */ +#else +#undef Sudden_Underflow +#define Sudden_Underflow +#ifdef IBM +#define Exp_shift 24 +#define Exp_shift1 24 +#define Exp_msk1 0x1000000 +#define Exp_msk11 0x1000000 +#define Exp_mask 0x7f000000 +#define P 14 +#define Bias 65 +#define Exp_1 0x41000000 +#define Exp_11 0x41000000 +#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ +#define Frac_mask 0xffffff +#define Frac_mask1 0xffffff +#define Bletch 4 +#define Ten_pmax 22 +#define Bndry_mask 0xefffff +#define Bndry_mask1 0xffffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 4 +#define Tiny0 0x100000 +#define Tiny1 0 +#define Quick_max 14 +#define Int_max 15 +#else /* VAX */ +#define Exp_shift 23 +#define Exp_shift1 7 +#define Exp_msk1 0x80 +#define Exp_msk11 0x800000 +#define Exp_mask 0x7f80 +#define P 56 +#define Bias 129 +#define Exp_1 0x40800000 +#define Exp_11 0x4080 +#define Ebits 8 +#define Frac_mask 0x7fffff +#define Frac_mask1 0xffff007f +#define Ten_pmax 24 +#define Bletch 2 +#define Bndry_mask 0xffff007f +#define Bndry_mask1 0xffff007f +#define LSB 0x10000 +#define Sign_bit 0x8000 +#define Log2P 1 +#define Tiny0 0x80 +#define Tiny1 0 +#define Quick_max 15 +#define Int_max 15 +#endif +#endif + +#ifndef IEEE_Arith +#define ROUND_BIASED +#endif + +#ifdef RND_PRODQUOT +#define rounded_product(a,b) a = rnd_prod(a, b) +#define rounded_quotient(a,b) a = rnd_quot(a, b) +extern double rnd_prod(double, double), rnd_quot(double, double); +#else +#define rounded_product(a,b) a *= b +#define rounded_quotient(a,b) a /= b +#endif + +#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) +#define Big1 0xffffffff + +#define Kmax 15 + +/* (1<<BIGINT_MINIMUM_K) is the minimum number of words to allocate + in a Bigint. dtoa usually manages with 1<<2, and has not been + known to need more than 1<<3. */ + +#define BIGINT_MINIMUM_K 3 + +struct Bigint { + struct Bigint *next; + int k; /* Parameter given to Balloc(k) */ + int maxwds; /* Allocated space: equals 1<<k. */ + short on_stack; /* 1 if stack-allocated. */ + short sign; /* 0 if value is positive or zero; 1 if negative. */ + int wds; /* Current length. */ + unsigned32 x[1<<BIGINT_MINIMUM_K]; /* Actually: x[maxwds] */ +}; + +#define BIGINT_HEADER_SIZE \ + (sizeof(Bigint) - (1<<BIGINT_MINIMUM_K) * sizeof(unsigned32)) + +typedef struct Bigint Bigint; + +/* Initialize a stack-allocated Bigint. */ + +static Bigint * +Binit +#ifdef KR_headers + (v) Bigint *v; +#else + (Bigint *v) +#endif +{ + v->on_stack = 1; + v->k = BIGINT_MINIMUM_K; + v->maxwds = 1 << BIGINT_MINIMUM_K; + v->sign = v->wds = 0; + return v; +} + +/* Allocate a Bigint with '1<<k' big digits. */ + +static Bigint * +Balloc +#ifdef KR_headers + (k) int k; +#else + (int k) +#endif +{ + int x; + Bigint *rv; + + if (k < BIGINT_MINIMUM_K) + k = BIGINT_MINIMUM_K; + + x = 1 << k; + rv = (Bigint *) + malloc(BIGINT_HEADER_SIZE + x * sizeof(unsigned32)); + rv->k = k; + rv->maxwds = x; + rv->sign = rv->wds = 0; + rv->on_stack = 0; + return rv; +} + +static void +Bfree +#ifdef KR_headers + (v) Bigint *v; +#else + (Bigint *v) +#endif +{ + if (v && !v->on_stack) + free (v); +} + +static void +Bcopy +#ifdef KR_headers + (x, y) Bigint *x, *y; +#else + (Bigint *x, Bigint *y) +#endif +{ + register unsigned32 *xp, *yp; + register int i = y->wds; + x->sign = y->sign; + x->wds = i; + for (xp = x->x, yp = y->x; --i >= 0; ) + *xp++ = *yp++; +} + +/* Make sure b has room for at least 1<<k big digits. */ + +static Bigint * +Brealloc +#ifdef KR_headers + (b, k) Bigint *b; int k; +#else + (Bigint * b, int k) +#endif +{ + if (b == NULL) + return Balloc(k); + if (b->k >= k) + return b; + else + { + Bigint *rv = Balloc (k); + Bcopy(rv, b); + Bfree(b); + return rv; + } +} + +/* Return b*m+a. b is modified. + Assumption: 0xFFFF*m+a fits in 32 bits. */ + +static Bigint * +multadd +#ifdef KR_headers + (b, m, a) Bigint *b; int m, a; +#else + (Bigint *b, int m, int a) +#endif +{ + int i, wds; + unsigned32 *x, y; + unsigned32 xi, z; + + wds = b->wds; + x = b->x; + i = 0; + do { + xi = *x; + y = (xi & 0xffff) * m + a; + z = (xi >> 16) * m + (y >> 16); + a = (int)(z >> 16); + *x++ = (z << 16) + (y & 0xffff); + } + while(++i < wds); + if (a) { + if (wds >= b->maxwds) + b = Brealloc(b, b->k+1); + b->x[wds++] = a; + b->wds = wds; + } + return b; + } + +static Bigint * +s2b +#ifdef KR_headers + (result, s, nd0, nd, y9) + Bigint *result; CONST char *s; int nd0, nd; unsigned32 y9; +#else + (Bigint *result, CONST char *s, int nd0, int nd, unsigned32 y9) +#endif +{ + int i, k; + long x, y; + + x = (nd + 8) / 9; + for(k = 0, y = 1; x > y; y <<= 1, k++) ; + result = Brealloc(result, k); + result->x[0] = y9; + result->wds = 1; + + i = 9; + if (9 < nd0) + { + s += 9; + do + result = multadd(result, 10, *s++ - '0'); + while (++i < nd0); + s++; + } + else + s += 10; + for(; i < nd; i++) + result = multadd(result, 10, *s++ - '0'); + return result; +} + +static int +hi0bits +#ifdef KR_headers + (x) register unsigned32 x; +#else + (register unsigned32 x) +#endif +{ + register int k = 0; + + if (!(x & 0xffff0000)) { + k = 16; + x <<= 16; + } + if (!(x & 0xff000000)) { + k += 8; + x <<= 8; + } + if (!(x & 0xf0000000)) { + k += 4; + x <<= 4; + } + if (!(x & 0xc0000000)) { + k += 2; + x <<= 2; + } + if (!(x & 0x80000000)) { + k++; + if (!(x & 0x40000000)) + return 32; + } + return k; + } + +static int +lo0bits +#ifdef KR_headers + (y) unsigned32 *y; +#else + (unsigned32 *y) +#endif +{ + register int k; + register unsigned32 x = *y; + + if (x & 7) { + if (x & 1) + return 0; + if (x & 2) { + *y = x >> 1; + return 1; + } + *y = x >> 2; + return 2; + } + k = 0; + if (!(x & 0xffff)) { + k = 16; + x >>= 16; + } + if (!(x & 0xff)) { + k += 8; + x >>= 8; + } + if (!(x & 0xf)) { + k += 4; + x >>= 4; + } + if (!(x & 0x3)) { + k += 2; + x >>= 2; + } + if (!(x & 1)) { + k++; + x >>= 1; + if (!x & 1) + return 32; + } + *y = x; + return k; + } + +static Bigint * +i2b +#ifdef KR_headers + (result, i) Bigint *result; int i; +#else + (Bigint* result, int i) +#endif +{ + result = Brealloc(result, 1); + result->x[0] = i; + result->wds = 1; + return result; +} + +/* Do: c = a * b. */ + +static Bigint * +mult +#ifdef KR_headers + (c, a, b) Bigint *a, *b, *c; +#else + (Bigint *c, Bigint *a, Bigint *b) +#endif +{ + int k, wa, wb, wc; + unsigned32 carry, y, z; + unsigned32 *x, *xa, *xae, *xb, *xbe, *xc, *xc0; + unsigned32 z2; + if (a->wds < b->wds) { + Bigint *tmp = a; + a = b; + b = tmp; + } + k = a->k; + wa = a->wds; + wb = b->wds; + wc = wa + wb; + if (wc > a->maxwds) + k++; + c = Brealloc(c, k); + for(x = c->x, xa = x + wc; x < xa; x++) + *x = 0; + xa = a->x; + xae = xa + wa; + xb = b->x; + xbe = xb + wb; + xc0 = c->x; + for(; xb < xbe; xb++, xc0++) { + if (y = *xb & 0xffff) { + x = xa; + xc = xc0; + carry = 0; + do { + z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; + carry = z >> 16; + z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; + carry = z2 >> 16; + Storeinc(xc, z2, z); + } + while(x < xae); + *xc = carry; + } + if (y = *xb >> 16) { + x = xa; + xc = xc0; + carry = 0; + z2 = *xc; + do { + z = (*x & 0xffff) * y + (*xc >> 16) + carry; + carry = z >> 16; + Storeinc(xc, z, z2); + z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; + carry = z2 >> 16; + } + while(x < xae); + *xc = z2; + } + } + for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; + c->wds = wc; + return c; + } + +/* Returns b*(5**k). b is modified. */ +/* Re-written by Per Bothner to not need a static list. */ + +static Bigint * +pow5mult +#ifdef KR_headers + (b, k) Bigint *b; int k; +#else + (Bigint *b, int k) +#endif +{ + static int p05[6] = { 5, 25, 125, 625, 3125, 15625 }; + + for (; k > 6; k -= 6) + b = multadd(b, 15625, 0); /* b *= 5**6 */ + if (k == 0) + return b; + else + return multadd(b, p05[k-1], 0); +} + +/* Re-written by Per Bothner so shift can be in place. */ + +static Bigint * +lshift +#ifdef KR_headers + (b, k) Bigint *b; int k; +#else + (Bigint *b, int k) +#endif +{ + int i; + unsigned32 *x, *x1, *xe; + int old_wds = b->wds; + int n = k >> 5; + int k1 = b->k; + int n1 = n + old_wds + 1; + + if (k == 0) + return b; + + for(i = b->maxwds; n1 > i; i <<= 1) + k1++; + b = Brealloc(b, k1); + + xe = b->x; /* Source limit */ + x = xe + old_wds; /* Source pointer */ + x1 = x + n; /* Destination pointer */ + if (k &= 0x1f) { + int k1 = 32 - k; + unsigned32 z = *--x; + if ((*x1 = (z >> k1)) != 0) { + ++n1; + } + while (x > xe) { + unsigned32 w = *--x; + *--x1 = (z << k) | (w >> k1); + z = w; + } + *--x1 = z << k; + } + else + do { + *--x1 = *--x; + } while(x > xe); + while (x1 > xe) + *--x1 = 0; + b->wds = n1 - 1; + return b; +} + +static int +cmp +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + unsigned32 *xa, *xa0, *xb, *xb0; + int i, j; + + i = a->wds; + j = b->wds; +#ifdef DEBUG + if (i > 1 && !a->x[i-1]) + Bug("cmp called with a->x[a->wds-1] == 0"); + if (j > 1 && !b->x[j-1]) + Bug("cmp called with b->x[b->wds-1] == 0"); +#endif + if (i -= j) + return i; + xa0 = a->x; + xa = xa0 + j; + xb0 = b->x; + xb = xb0 + j; + for(;;) { + if (*--xa != *--xb) + return *xa < *xb ? -1 : 1; + if (xa <= xa0) + break; + } + return 0; + } + +/* Do: c = a-b. */ + +static Bigint * +diff +#ifdef KR_headers + (c, a, b) Bigint *c, *a, *b; +#else + (Bigint *c, Bigint *a, Bigint *b) +#endif +{ + int i, wa, wb; + long borrow, y; /* We need signed shifts here. */ + unsigned32 *xa, *xae, *xb, *xbe, *xc; + long z; + + i = cmp(a,b); + if (!i) { + c = Brealloc(c, 0); + c->wds = 1; + c->x[0] = 0; + return c; + } + if (i < 0) { + Bigint *tmp = a; + a = b; + b = tmp; + i = 1; + } + else + i = 0; + c = Brealloc(c, a->k); + c->sign = i; + wa = a->wds; + xa = a->x; + xae = xa + wa; + wb = b->wds; + xb = b->x; + xbe = xb + wb; + xc = c->x; + borrow = 0; + do { + y = (*xa & 0xffff) - (*xb & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*xa++ >> 16) - (*xb++ >> 16) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(xc, z, y); + } + while(xb < xbe); + while(xa < xae) { + y = (*xa & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*xa++ >> 16) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(xc, z, y); + } + while(!*--xc) + wa--; + c->wds = wa; + return c; + } + +static double +ulp +#ifdef KR_headers + (x) double x; +#else + (double x) +#endif +{ + register long L; + double a; + + L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; +#ifndef Sudden_Underflow + if (L > 0) { +#endif +#ifdef IBM + L |= Exp_msk1 >> 4; +#endif + word0(a) = L; + word1(a) = 0; +#ifndef Sudden_Underflow + } + else { + L = -L >> Exp_shift; + if (L < Exp_shift) { + word0(a) = 0x80000 >> L; + word1(a) = 0; + } + else { + word0(a) = 0; + L -= Exp_shift; + word1(a) = L >= 31 ? 1 : 1 << 31 - L; + } + } +#endif + return a; + } + +static double +b2d +#ifdef KR_headers + (a, e) Bigint *a; int *e; +#else + (Bigint *a, int *e) +#endif +{ + unsigned32 *xa, *xa0, w, y, z; + int k; + double d; +#ifdef VAX + unsigned32 d0, d1; +#else +#define d0 word0(d) +#define d1 word1(d) +#endif + + xa0 = a->x; + xa = xa0 + a->wds; + y = *--xa; +#ifdef DEBUG + if (!y) Bug("zero y in b2d"); +#endif + k = hi0bits(y); + *e = 32 - k; + if (k < Ebits) { + d0 = Exp_1 | y >> Ebits - k; + w = xa > xa0 ? *--xa : 0; + d1 = y << (32-Ebits) + k | w >> Ebits - k; + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + if (k -= Ebits) { + d0 = Exp_1 | y << k | z >> 32 - k; + y = xa > xa0 ? *--xa : 0; + d1 = z << k | y >> 32 - k; + } + else { + d0 = Exp_1 | y; + d1 = z; + } + ret_d: +#ifdef VAX + word0(d) = d0 >> 16 | d0 << 16; + word1(d) = d1 >> 16 | d1 << 16; +#else +#undef d0 +#undef d1 +#endif + return d; + } + +static Bigint * +d2b +#ifdef KR_headers + (result, d, e, bits) Bigint *result; double d; int *e, *bits; +#else + (Bigint *result, double d, int *e, int *bits) +#endif +{ + int de, i, k; + unsigned32 *x, y, z; +#ifdef VAX + unsigned32 d0, d1; + d0 = word0(d) >> 16 | word0(d) << 16; + d1 = word1(d) >> 16 | word1(d) << 16; +#else +#define d0 word0(d) +#define d1 word1(d) +#endif + + result = Brealloc(result, 1); + x = result->x; + + z = d0 & Frac_mask; + d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ + + de = (int)(d0 >> Exp_shift); /* The exponent part of d. */ + + /* Put back the suppressed high-order bit, if normalized. */ +#ifndef IBM +#ifndef Sudden_Underflow + if (de) +#endif + z |= Exp_msk11; +#endif + + if (y = d1) { + if (k = lo0bits(&y)) { + x[0] = y | z << 32 - k; + z >>= k; + } + else + x[0] = y; + i = result->wds = (x[1] = z) ? 2 : 1; + } + else { +#ifdef DEBUG + if (!z) + Bug("Zero passed to d2b"); +#endif + k = lo0bits(&z); + x[0] = z; + i = result->wds = 1; + k += 32; + } +#ifndef Sudden_Underflow + if (de) { +#endif +#ifdef IBM + *e = (de - Bias - (P-1) << 2) + k; + *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask); +#else + *e = de - Bias - (P-1) + k; + *bits = P - k; +#endif +#ifndef Sudden_Underflow + } + else { + *e = de - Bias - (P-1) + 1 + k; + *bits = 32*i - hi0bits(x[i-1]); + } +#endif + return result; + } +#undef d0 +#undef d1 + +static double +ratio +#ifdef KR_headers + (a, b) Bigint *a, *b; +#else + (Bigint *a, Bigint *b) +#endif +{ + double da, db; + int k, ka, kb; + + da = b2d(a, &ka); + db = b2d(b, &kb); + k = ka - kb + 32*(a->wds - b->wds); +#ifdef IBM + if (k > 0) { + word0(da) += (k >> 2)*Exp_msk1; + if (k &= 3) + da *= 1 << k; + } + else { + k = -k; + word0(db) += (k >> 2)*Exp_msk1; + if (k &= 3) + db *= 1 << k; + } +#else + if (k > 0) + word0(da) += k*Exp_msk1; + else { + k = -k; + word0(db) += k*Exp_msk1; + } +#endif + return da / db; + } + +static double +tens[] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22 +#ifdef VAX + , 1e23, 1e24 +#endif + }; + +static double +#ifdef IEEE_Arith +bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; +static double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 }; +#define n_bigtens 5 +#else +#ifdef IBM +bigtens[] = { 1e16, 1e32, 1e64 }; +static double tinytens[] = { 1e-16, 1e-32, 1e-64 }; +#define n_bigtens 3 +#else +bigtens[] = { 1e16, 1e32 }; +static double tinytens[] = { 1e-16, 1e-32 }; +#define n_bigtens 2 +#endif +#endif + + double +_IO_strtod +#ifdef KR_headers + (s00, se) CONST char *s00; char **se; +#else + (CONST char *s00, char **se) +#endif +{ + int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, + e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; + CONST char *s, *s0, *s1; + double aadj, aadj1, adj, rv, rv0; + long L; + unsigned32 y, z; + Bigint _bb, _b_avail, _bd, _bd0, _bs, _delta; + Bigint *bb = Binit(&_bb); + Bigint *bd = Binit(&_bd); + Bigint *bd0 = Binit(&_bd0); + Bigint *bs = Binit(&_bs); + Bigint *b_avail = Binit(&_b_avail); + Bigint *delta = Binit(&_delta); + + TEST_ENDIANNESS; + sign = nz0 = nz = 0; + rv = 0.; + for(s = s00;;s++) switch(*s) { + case '-': + sign = 1; + /* no break */ + case '+': + if (*++s) + goto break2; + /* no break */ + case 0: + /* "+" and "-" should be reported as an error? */ + sign = 0; + s = s00; + goto ret; + case '\t': + case '\n': + case '\v': + case '\f': + case '\r': + case ' ': + continue; + default: + goto break2; + } + break2: + if (*s == '0') { + nz0 = 1; + while(*++s == '0') ; + if (!*s) + goto ret; + } + s0 = s; + y = z = 0; + for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) + if (nd < 9) + y = 10*y + c - '0'; + else if (nd < 16) + z = 10*z + c - '0'; + nd0 = nd; + if (c == '.') { + c = *++s; + if (!nd) { + for(; c == '0'; c = *++s) + nz++; + if (c > '0' && c <= '9') { + s0 = s; + nf += nz; + nz = 0; + goto have_dig; + } + goto dig_done; + } + for(; c >= '0' && c <= '9'; c = *++s) { + have_dig: + nz++; + if (c -= '0') { + nf += nz; + for(i = 1; i < nz; i++) + if (nd++ < 9) + y *= 10; + else if (nd <= DBL_DIG + 1) + z *= 10; + if (nd++ < 9) + y = 10*y + c; + else if (nd <= DBL_DIG + 1) + z = 10*z + c; + nz = 0; + } + } + } + dig_done: + e = 0; + if (c == 'e' || c == 'E') { + if (!nd && !nz && !nz0) { + s = s00; + goto ret; + } + s00 = s; + esign = 0; + switch(c = *++s) { + case '-': + esign = 1; + case '+': + c = *++s; + } + if (c >= '0' && c <= '9') { + while(c == '0') + c = *++s; + if (c > '0' && c <= '9') { + e = c - '0'; + s1 = s; + while((c = *++s) >= '0' && c <= '9') + e = 10*e + c - '0'; + if (s - s1 > 8) + /* Avoid confusion from exponents + * so large that e might overflow. + */ + e = 9999999; + if (esign) + e = -e; + } + else + e = 0; + } + else + s = s00; + } + if (!nd) { + if (!nz && !nz0) + s = s00; + goto ret; + } + e1 = e -= nf; + + /* Now we have nd0 digits, starting at s0, followed by a + * decimal point, followed by nd-nd0 digits. The number we're + * after is the integer represented by those digits times + * 10**e */ + + if (!nd0) + nd0 = nd; + k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; + rv = y; + if (k > 9) + rv = tens[k - 9] * rv + z; + if (nd <= DBL_DIG +#ifndef RND_PRODQUOT + && FLT_ROUNDS == 1 +#endif + ) { + if (!e) + goto ret; + if (e > 0) { + if (e <= Ten_pmax) { +#ifdef VAX + goto vax_ovfl_check; +#else + /* rv = */ rounded_product(rv, tens[e]); + goto ret; +#endif + } + i = DBL_DIG - nd; + if (e <= Ten_pmax + i) { + /* A fancier test would sometimes let us do + * this for larger i values. + */ + e -= i; + rv *= tens[i]; +#ifdef VAX + /* VAX exponent range is so narrow we must + * worry about overflow here... + */ + vax_ovfl_check: + word0(rv) -= P*Exp_msk1; + /* rv = */ rounded_product(rv, tens[e]); + if ((word0(rv) & Exp_mask) + > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) + goto ovfl; + word0(rv) += P*Exp_msk1; +#else + /* rv = */ rounded_product(rv, tens[e]); +#endif + goto ret; + } + } +#ifndef Inaccurate_Divide + else if (e >= -Ten_pmax) { + /* rv = */ rounded_quotient(rv, tens[-e]); + goto ret; + } +#endif + } + e1 += nd - k; + + /* Get starting approximation = rv * 10**e1 */ + + if (e1 > 0) { + if (i = e1 & 15) + rv *= tens[i]; + if (e1 &= ~15) { + if (e1 > DBL_MAX_10_EXP) { + ovfl: + errno = ERANGE; +#if defined(sun) && !defined(__svr4__) +/* SunOS defines HUGE_VAL as __infinity(), which is in libm. */ +#undef HUGE_VAL +#endif +#ifndef HUGE_VAL +#define HUGE_VAL 1.7976931348623157E+308 +#endif + rv = HUGE_VAL; + goto ret; + } + if (e1 >>= 4) { + for(j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + rv *= bigtens[j]; + /* The last multiplication could overflow. */ + word0(rv) -= P*Exp_msk1; + rv *= bigtens[j]; + if ((z = word0(rv) & Exp_mask) + > Exp_msk1*(DBL_MAX_EXP+Bias-P)) + goto ovfl; + if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { + /* set to largest number */ + /* (Can't trust DBL_MAX) */ + word0(rv) = Big0; + word1(rv) = Big1; + } + else + word0(rv) += P*Exp_msk1; + } + + } + } + else if (e1 < 0) { + e1 = -e1; + if (i = e1 & 15) + rv /= tens[i]; + if (e1 &= ~15) { + e1 >>= 4; + for(j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + rv *= tinytens[j]; + /* The last multiplication could underflow. */ + rv0 = rv; + rv *= tinytens[j]; + if (!rv) { + rv = 2.*rv0; + rv *= tinytens[j]; + if (!rv) { + undfl: + rv = 0.; + errno = ERANGE; + goto ret; + } + word0(rv) = Tiny0; + word1(rv) = Tiny1; + /* The refinement below will clean + * this approximation up. + */ + } + } + } + + /* Now the hard part -- adjusting rv to the correct value.*/ + + /* Put digits into bd: true value = bd * 10^e */ + + bd0 = s2b(bd0, s0, nd0, nd, y); + bd = Brealloc(bd, bd0->k); + + for(;;) { + Bcopy(bd, bd0); + bb = d2b(bb, rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ + bs = i2b(bs, 1); + + if (e >= 0) { + bb2 = bb5 = 0; + bd2 = bd5 = e; + } + else { + bb2 = bb5 = -e; + bd2 = bd5 = 0; + } + if (bbe >= 0) + bb2 += bbe; + else + bd2 -= bbe; + bs2 = bb2; +#ifdef Sudden_Underflow +#ifdef IBM + j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3); +#else + j = P + 1 - bbbits; +#endif +#else + i = bbe + bbbits - 1; /* logb(rv) */ + if (i < Emin) /* denormal */ + j = bbe + (P-Emin); + else + j = P + 1 - bbbits; +#endif + bb2 += j; + bd2 += j; + i = bb2 < bd2 ? bb2 : bd2; + if (i > bs2) + i = bs2; + if (i > 0) { + bb2 -= i; + bd2 -= i; + bs2 -= i; + } + if (bb5 > 0) { + Bigint *b_tmp; + bs = pow5mult(bs, bb5); + b_tmp = mult(b_avail, bs, bb); + b_avail = bb; + bb = b_tmp; + } + if (bb2 > 0) + bb = lshift(bb, bb2); + if (bd5 > 0) + bd = pow5mult(bd, bd5); + if (bd2 > 0) + bd = lshift(bd, bd2); + if (bs2 > 0) + bs = lshift(bs, bs2); + delta = diff(delta, bb, bd); + dsign = delta->sign; + delta->sign = 0; + i = cmp(delta, bs); + if (i < 0) { + /* Error is less than half an ulp -- check for + * special case of mantissa a power of two. + */ + if (dsign || word1(rv) || word0(rv) & Bndry_mask) + break; + delta = lshift(delta,Log2P); + if (cmp(delta, bs) > 0) + goto drop_down; + break; + } + if (i == 0) { + /* exactly half-way between */ + if (dsign) { + if ((word0(rv) & Bndry_mask1) == Bndry_mask1 + && word1(rv) == 0xffffffff) { + /*boundary case -- increment exponent*/ + word0(rv) = (word0(rv) & Exp_mask) + + Exp_msk1 +#ifdef IBM + | Exp_msk1 >> 4 +#endif + ; + word1(rv) = 0; + break; + } + } + else if (!(word0(rv) & Bndry_mask) && !word1(rv)) { + drop_down: + /* boundary case -- decrement exponent */ +#ifdef Sudden_Underflow + L = word0(rv) & Exp_mask; +#ifdef IBM + if (L < Exp_msk1) +#else + if (L <= Exp_msk1) +#endif + goto undfl; + L -= Exp_msk1; +#else + L = (word0(rv) & Exp_mask) - Exp_msk1; +#endif + word0(rv) = L | Bndry_mask1; + word1(rv) = 0xffffffff; +#ifdef IBM + continue; +#else + break; +#endif + } +#ifndef ROUND_BIASED + if (!(word1(rv) & LSB)) + break; +#endif + if (dsign) + rv += ulp(rv); +#ifndef ROUND_BIASED + else { + rv -= ulp(rv); +#ifndef Sudden_Underflow + if (!rv) + goto undfl; +#endif + } +#endif + break; + } + if ((aadj = ratio(delta, bs)) <= 2.) { + if (dsign) + aadj = aadj1 = 1.; + else if (word1(rv) || word0(rv) & Bndry_mask) { +#ifndef Sudden_Underflow + if (word1(rv) == Tiny1 && !word0(rv)) + goto undfl; +#endif + aadj = 1.; + aadj1 = -1.; + } + else { + /* special case -- power of FLT_RADIX to be */ + /* rounded down... */ + + if (aadj < 2./FLT_RADIX) + aadj = 1./FLT_RADIX; + else + aadj *= 0.5; + aadj1 = -aadj; + } + } + else { + aadj *= 0.5; + aadj1 = dsign ? aadj : -aadj; +#ifdef Check_FLT_ROUNDS + switch(FLT_ROUNDS) { + case 2: /* towards +infinity */ + aadj1 -= 0.5; + break; + case 0: /* towards 0 */ + case 3: /* towards -infinity */ + aadj1 += 0.5; + } +#else + if (FLT_ROUNDS == 0) + aadj1 += 0.5; +#endif + } + y = word0(rv) & Exp_mask; + + /* Check for overflow */ + + if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { + rv0 = rv; + word0(rv) -= P*Exp_msk1; + adj = aadj1 * ulp(rv); + rv += adj; + if ((word0(rv) & Exp_mask) >= + Exp_msk1*(DBL_MAX_EXP+Bias-P)) { + if (word0(rv0) == Big0 && word1(rv0) == Big1) + goto ovfl; + word0(rv) = Big0; + word1(rv) = Big1; + continue; + } + else + word0(rv) += P*Exp_msk1; + } + else { +#ifdef Sudden_Underflow + if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { + rv0 = rv; + word0(rv) += P*Exp_msk1; + adj = aadj1 * ulp(rv); + rv += adj; +#ifdef IBM + if ((word0(rv) & Exp_mask) < P*Exp_msk1) +#else + if ((word0(rv) & Exp_mask) <= P*Exp_msk1) +#endif + { + if (word0(rv0) == Tiny0 + && word1(rv0) == Tiny1) + goto undfl; + word0(rv) = Tiny0; + word1(rv) = Tiny1; + continue; + } + else + word0(rv) -= P*Exp_msk1; + } + else { + adj = aadj1 * ulp(rv); + rv += adj; + } +#else + /* Compute adj so that the IEEE rounding rules will + * correctly round rv + adj in some half-way cases. + * If rv * ulp(rv) is denormalized (i.e., + * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid + * trouble from bits lost to denormalization; + * example: 1.2e-307 . + */ + if (y <= (P-1)*Exp_msk1 && aadj >= 1.) { + aadj1 = (double)(int)(aadj + 0.5); + if (!dsign) + aadj1 = -aadj1; + } + adj = aadj1 * ulp(rv); + rv += adj; +#endif + } + z = word0(rv) & Exp_mask; + if (y == z) { + /* Can we stop now? */ + L = (long)aadj; + aadj -= L; + /* The tolerances below are conservative. */ + if (dsign || word1(rv) || word0(rv) & Bndry_mask) { + if (aadj < .4999999 || aadj > .5000001) + break; + } + else if (aadj < .4999999/FLT_RADIX) + break; + } + } + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); + Bfree(b_avail); + ret: + if (se) + *se = (char *)s; + return sign ? -rv : rv; + } + +static int +quorem +#ifdef KR_headers + (b, S) Bigint *b, *S; +#else + (Bigint *b, Bigint *S) +#endif +{ + int n; + long borrow, y; + unsigned32 carry, q, ys; + unsigned32 *bx, *bxe, *sx, *sxe; + long z; + unsigned32 si, zs; + + n = S->wds; +#ifdef DEBUG + /*debug*/ if (b->wds > n) + /*debug*/ Bug("oversize b in quorem"); +#endif + if (b->wds < n) + return 0; + sx = S->x; + sxe = sx + --n; + bx = b->x; + bxe = bx + n; + q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ +#ifdef DEBUG + /*debug*/ if (q > 9) + /*debug*/ Bug("oversized quotient in quorem"); +#endif + if (q) { + borrow = 0; + carry = 0; + do { + si = *sx++; + ys = (si & 0xffff) * q + carry; + zs = (si >> 16) * q + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*bx >> 16) - (zs & 0xffff) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(bx, z, y); + } + while(sx <= sxe); + if (!*bxe) { + bx = b->x; + while(--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + if (cmp(b, S) >= 0) { + q++; + borrow = 0; + carry = 0; + bx = b->x; + sx = S->x; + do { + si = *sx++; + ys = (si & 0xffff) + carry; + zs = (si >> 16) + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*bx >> 16) - (zs & 0xffff) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(bx, z, y); + } + while(sx <= sxe); + bx = b->x; + bxe = bx + n; + if (!*bxe) { + while(--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + return q; + } + +/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. + * + * Inspired by "How to Print Floating-Point Numbers Accurately" by + * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101]. + * + * Modifications: + * 1. Rather than iterating, we use a simple numeric overestimate + * to determine k = floor(log10(d)). We scale relevant + * quantities using O(log2(k)) rather than O(k) multiplications. + * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't + * try to generate digits strictly left to right. Instead, we + * compute with fewer bits and propagate the carry if necessary + * when rounding the final digit up. This is often faster. + * 3. Under the assumption that input will be rounded nearest, + * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. + * That is, we allow equality in stopping tests when the + * round-nearest rule will give the same floating-point value + * as would satisfaction of the stopping test with strict + * inequality. + * 4. We remove common factors of powers of 2 from relevant + * quantities. + * 5. When converting floating-point integers less than 1e16, + * we use floating-point arithmetic rather than resorting + * to multiple-precision integers. + * 6. When asked to produce fewer than 15 digits, we first try + * to get by with floating-point arithmetic; we resort to + * multiple-precision integer arithmetic only if we cannot + * guarantee that the floating-point calculation has given + * the correctly rounded result. For k requested digits and + * "uniformly" distributed input, the probability is + * something like 10^(k-15) that we must resort to the long + * calculation. + */ + + char * +_IO_dtoa +#ifdef KR_headers + (d, mode, ndigits, decpt, sign, rve) + double d; int mode, ndigits, *decpt, *sign; char **rve; +#else + (double d, int mode, int ndigits, int *decpt, int *sign, char **rve) +#endif +{ + /* Arguments ndigits, decpt, sign are similar to those + of ecvt and fcvt; trailing zeros are suppressed from + the returned string. If not null, *rve is set to point + to the end of the return value. If d is +-Infinity or NaN, + then *decpt is set to 9999. + + mode: + 0 ==> shortest string that yields d when read in + and rounded to nearest. + 1 ==> like 0, but with Steele & White stopping rule; + e.g. with IEEE P754 arithmetic , mode 0 gives + 1e23 whereas mode 1 gives 9.999999999999999e22. + 2 ==> max(1,ndigits) significant digits. This gives a + return value similar to that of ecvt, except + that trailing zeros are suppressed. + 3 ==> through ndigits past the decimal point. This + gives a return value similar to that from fcvt, + except that trailing zeros are suppressed, and + ndigits can be negative. + 4-9 should give the same return values as 2-3, i.e., + 4 <= mode <= 9 ==> same return as mode + 2 + (mode & 1). These modes are mainly for + debugging; often they run slower but sometimes + faster than modes 2-3. + 4,5,8,9 ==> left-to-right digit generation. + 6-9 ==> don't try fast floating-point estimate + (if applicable). + + Values of mode other than 0-9 are treated as mode 0. + + Sufficient space is allocated to the return value + to hold the suppressed trailing zeros. + */ + + int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, + j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, + spec_case, try_quick; + long L; +#ifndef Sudden_Underflow + int denorm; +#endif + Bigint _b_avail, _b, _mhi, _mlo, _S; + Bigint *b_avail = Binit(&_b_avail); + Bigint *b = Binit(&_b); + Bigint *S = Binit(&_S); + /* mhi and mlo are only set and used if leftright. */ + Bigint *mhi = NULL, *mlo = NULL; + double d2, ds, eps; + char *s, *s0; + static Bigint *result = NULL; + static int result_k; + + TEST_ENDIANNESS; + if (result) { + /* result is contains a string, so its fields (interpreted + as a Bigint have been trashed. Restore them. + This is a really ugly interface - result should + not be static, since that is not thread-safe. FIXME. */ + result->k = result_k; + result->maxwds = 1 << result_k; + result->on_stack = 0; + } + + if (word0(d) & Sign_bit) { + /* set sign for everything, including 0's and NaNs */ + *sign = 1; + word0(d) &= ~Sign_bit; /* clear sign bit */ + } + else + *sign = 0; + +#if defined(IEEE_Arith) + defined(VAX) +#ifdef IEEE_Arith + if ((word0(d) & Exp_mask) == Exp_mask) +#else + if (word0(d) == 0x8000) +#endif + { + /* Infinity or NaN */ + *decpt = 9999; +#ifdef IEEE_Arith + if (!word1(d) && !(word0(d) & 0xfffff)) + { + s = "Infinity"; + if (rve) + *rve = s + 8; + } + else +#endif + { + s = "NaN"; + if (rve) + *rve = s +3; + } + return s; + } +#endif +#ifdef IBM + d += 0; /* normalize */ +#endif + if (!d) { + *decpt = 1; + s = "0"; + if (rve) + *rve = s + 1; + return s; + } + + b = d2b(b, d, &be, &bbits); + i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); +#ifndef Sudden_Underflow + if (i) { +#endif + d2 = d; + word0(d2) &= Frac_mask1; + word0(d2) |= Exp_11; +#ifdef IBM + if (j = 11 - hi0bits(word0(d2) & Frac_mask)) + d2 /= 1 << j; +#endif + + i -= Bias; +#ifdef IBM + i <<= 2; + i += j; +#endif +#ifndef Sudden_Underflow + denorm = 0; + } + else { + /* d is denormalized */ + unsigned32 x; + + i = bbits + be + (Bias + (P-1) - 1); + x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32 + : word1(d) << 32 - i; + d2 = x; + word0(d2) -= 31*Exp_msk1; /* adjust exponent */ + i -= (Bias + (P-1) - 1) + 1; + denorm = 1; + } +#endif + + /* Now i is the unbiased base-2 exponent. */ + + /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 + * log10(x) = log(x) / log(10) + * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) + * log10(d) = i*log(2)/log(10) + log10(d2) + * + * This suggests computing an approximation k to log10(d) by + * + * k = i*0.301029995663981 + * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); + * + * We want k to be too large rather than too small. + * The error in the first-order Taylor series approximation + * is in our favor, so we just round up the constant enough + * to compensate for any error in the multiplication of + * (i) by 0.301029995663981; since |i| <= 1077, + * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, + * adding 1e-13 to the constant term more than suffices. + * Hence we adjust the constant term to 0.1760912590558. + * (We could get a more accurate k by invoking log10, + * but this is probably not worthwhile.) + */ + + ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; + k = (int)ds; + if (ds < 0. && ds != k) + k--; /* want k = floor(ds) */ + k_check = 1; + if (k >= 0 && k <= Ten_pmax) { + if (d < tens[k]) + k--; + k_check = 0; + } + j = bbits - i - 1; + if (j >= 0) { + b2 = 0; + s2 = j; + } + else { + b2 = -j; + s2 = 0; + } + if (k >= 0) { + b5 = 0; + s5 = k; + s2 += k; + } + else { + b2 -= k; + b5 = -k; + s5 = 0; + } + if (mode < 0 || mode > 9) + mode = 0; + try_quick = 1; + if (mode > 5) { + mode -= 4; + try_quick = 0; + } + leftright = 1; + switch(mode) { + case 0: + case 1: + ilim = ilim1 = -1; + i = 18; + ndigits = 0; + break; + case 2: + leftright = 0; + /* no break */ + case 4: + if (ndigits <= 0) + ndigits = 1; + ilim = ilim1 = i = ndigits; + break; + case 3: + leftright = 0; + /* no break */ + case 5: + i = ndigits + k + 1; + ilim = i; + ilim1 = i - 1; + if (i <= 0) + i = 1; + } + /* i is now an upper bound of the number of digits to generate. */ + j = sizeof(unsigned32) * (1<<BIGINT_MINIMUM_K); + /* The test is <= so as to allow room for the final '\0'. */ + for(result_k = BIGINT_MINIMUM_K; BIGINT_HEADER_SIZE + j <= i; + j <<= 1) result_k++; + if (!result || result_k > result->k) + { + Bfree (result); + result = Balloc(result_k); + } + s = s0 = (char *)result; + + if (ilim >= 0 && ilim <= Quick_max && try_quick) { + + /* Try to get by with floating-point arithmetic. */ + + i = 0; + d2 = d; + k0 = k; + ilim0 = ilim; + ieps = 2; /* conservative */ + if (k > 0) { + ds = tens[k&0xf]; + j = k >> 4; + if (j & Bletch) { + /* prevent overflows */ + j &= Bletch - 1; + d /= bigtens[n_bigtens-1]; + ieps++; + } + for(; j; j >>= 1, i++) + if (j & 1) { + ieps++; + ds *= bigtens[i]; + } + d /= ds; + } + else if (j1 = -k) { + d *= tens[j1 & 0xf]; + for(j = j1 >> 4; j; j >>= 1, i++) + if (j & 1) { + ieps++; + d *= bigtens[i]; + } + } + if (k_check && d < 1. && ilim > 0) { + if (ilim1 <= 0) + goto fast_failed; + ilim = ilim1; + k--; + d *= 10.; + ieps++; + } + eps = ieps*d + 7.; + word0(eps) -= (P-1)*Exp_msk1; + if (ilim == 0) { + d -= 5.; + if (d > eps) + goto one_digit; + if (d < -eps) + goto no_digits; + goto fast_failed; + } +#ifndef No_leftright + if (leftright) { + /* Use Steele & White method of only + * generating digits needed. + */ + eps = 0.5/tens[ilim-1] - eps; + for(i = 0;;) { + L = (long)d; + d -= L; + *s++ = '0' + (int)L; + if (d < eps) + goto ret1; + if (1. - d < eps) + goto bump_up; + if (++i >= ilim) + break; + eps *= 10.; + d *= 10.; + } + } + else { +#endif + /* Generate ilim digits, then fix them up. */ + eps *= tens[ilim-1]; + for(i = 1;; i++, d *= 10.) { + L = (long)d; + d -= L; + *s++ = '0' + (int)L; + if (i == ilim) { + if (d > 0.5 + eps) + goto bump_up; + else if (d < 0.5 - eps) { + while(*--s == '0'); + s++; + goto ret1; + } + break; + } + } +#ifndef No_leftright + } +#endif + fast_failed: + s = s0; + d = d2; + k = k0; + ilim = ilim0; + } + + /* Do we have a "small" integer? */ + + if (be >= 0 && k <= Int_max) { + /* Yes. */ + ds = tens[k]; + if (ndigits < 0 && ilim <= 0) { + if (ilim < 0 || d <= 5*ds) + goto no_digits; + goto one_digit; + } + for(i = 1;; i++) { + L = (long)(d / ds); + d -= L*ds; +#ifdef Check_FLT_ROUNDS + /* If FLT_ROUNDS == 2, L will usually be high by 1 */ + if (d < 0) { + L--; + d += ds; + } +#endif + *s++ = '0' + (int)L; + if (i == ilim) { + d += d; + if (d > ds || d == ds && L & 1) { + bump_up: + while(*--s == '9') + if (s == s0) { + k++; + *s = '0'; + break; + } + ++*s++; + } + break; + } + if (!(d *= 10.)) + break; + } + goto ret1; + } + + m2 = b2; + m5 = b5; + if (leftright) { + if (mode < 2) { + i = +#ifndef Sudden_Underflow + denorm ? be + (Bias + (P-1) - 1 + 1) : +#endif +#ifdef IBM + 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3); +#else + 1 + P - bbits; +#endif + } + else { + j = ilim - 1; + if (m5 >= j) + m5 -= j; + else { + s5 += j -= m5; + b5 += j; + m5 = 0; + } + if ((i = ilim) < 0) { + m2 -= i; + i = 0; + } + } + b2 += i; + s2 += i; + mhi = i2b(Binit(&_mhi), 1); + } + if (m2 > 0 && s2 > 0) { + i = m2 < s2 ? m2 : s2; + b2 -= i; + m2 -= i; + s2 -= i; + } + if (b5 > 0) { + if (leftright) { + if (m5 > 0) { + Bigint *b_tmp; + mhi = pow5mult(mhi, m5); + b_tmp = mult(b_avail, mhi, b); + b_avail = b; + b = b_tmp; + } + if (j = b5 - m5) + b = pow5mult(b, j); + } + else + b = pow5mult(b, b5); + } + S = i2b(S, 1); + if (s5 > 0) + S = pow5mult(S, s5); + + /* Check for special case that d is a normalized power of 2. */ + + if (mode < 2) { + if (!word1(d) && !(word0(d) & Bndry_mask) +#ifndef Sudden_Underflow + && word0(d) & Exp_mask +#endif + ) { + /* The special case */ + b2 += Log2P; + s2 += Log2P; + spec_case = 1; + } + else + spec_case = 0; + } + + /* Arrange for convenient computation of quotients: + * shift left if necessary so divisor has 4 leading 0 bits. + * + * Perhaps we should just compute leading 28 bits of S once + * and for all and pass them and a shift to quorem, so it + * can do shifts and ors to compute the numerator for q. + */ + if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) + i = 32 - i; + if (i > 4) { + i -= 4; + b2 += i; + m2 += i; + s2 += i; + } + else if (i < 4) { + i += 28; + b2 += i; + m2 += i; + s2 += i; + } + if (b2 > 0) + b = lshift(b, b2); + if (s2 > 0) + S = lshift(S, s2); + if (k_check) { + if (cmp(b,S) < 0) { + k--; + b = multadd(b, 10, 0); /* we botched the k estimate */ + if (leftright) + mhi = multadd(mhi, 10, 0); + ilim = ilim1; + } + } + if (ilim <= 0 && mode > 2) { + if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { + /* no digits, fcvt style */ + no_digits: + k = -1 - ndigits; + goto ret; + } + one_digit: + *s++ = '1'; + k++; + goto ret; + } + if (leftright) { + if (m2 > 0) + mhi = lshift(mhi, m2); + + /* Compute mlo -- check for special case + * that d is a normalized power of 2. + */ + + if (spec_case) { + mlo = Brealloc(Binit(&_mlo), mhi->k); + Bcopy(mlo, mhi); + mhi = lshift(mhi, Log2P); + } + else + mlo = mhi; + + for(i = 1;;i++) { + dig = quorem(b,S) + '0'; + /* Do we yet have the shortest decimal string + * that will round to d? + */ + j = cmp(b, mlo); + b_avail = diff(b_avail, S, mhi); /* b_avail = S - mi */ + j1 = b_avail->sign ? 1 : cmp(b, b_avail); +#ifndef ROUND_BIASED + if (j1 == 0 && !mode && !(word1(d) & 1)) { + if (dig == '9') + goto round_9_up; + if (j > 0) + dig++; + *s++ = dig; + goto ret; + } +#endif + if (j < 0 || j == 0 && !mode +#ifndef ROUND_BIASED + && !(word1(d) & 1) +#endif + ) { + if (j1 > 0) { + b = lshift(b, 1); + j1 = cmp(b, S); + if ((j1 > 0 || j1 == 0 && dig & 1) + && dig++ == '9') + goto round_9_up; + } + *s++ = dig; + goto ret; + } + if (j1 > 0) { + if (dig == '9') { /* possible if i == 1 */ + round_9_up: + *s++ = '9'; + goto roundoff; + } + *s++ = dig + 1; + goto ret; + } + *s++ = dig; + if (i == ilim) + break; + b = multadd(b, 10, 0); + if (mlo == mhi) + mlo = mhi = multadd(mhi, 10, 0); + else { + mlo = multadd(mlo, 10, 0); + mhi = multadd(mhi, 10, 0); + } + } + } + else + for(i = 1;; i++) { + *s++ = dig = quorem(b,S) + '0'; + if (i >= ilim) + break; + b = multadd(b, 10, 0); + } + + /* Round off last digit */ + + b = lshift(b, 1); + j = cmp(b, S); + if (j > 0 || j == 0 && dig & 1) { + roundoff: + while(*--s == '9') + if (s == s0) { + k++; + *s++ = '1'; + goto ret; + } + ++*s++; + } + else { + while(*--s == '0'); + s++; + } + ret: + Bfree(b_avail); + Bfree(S); + if (mhi) { + if (mlo && mlo != mhi) + Bfree(mlo); + Bfree(mhi); + } + ret1: + Bfree(b); + *s = 0; + *decpt = k + 1; + if (rve) + *rve = s; + return s0; + } +#endif /* USE_DTOA */ diff --git a/gnu/lib/libg++/libio/fstream.cc b/gnu/lib/libg++/libio/fstream.cc new file mode 100644 index 0000000..a9ca9f6 --- /dev/null +++ b/gnu/lib/libg++/libio/fstream.cc @@ -0,0 +1,84 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. + +Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#define _STREAM_COMPAT +extern "C" { +#include "libioP.h" +} +#include <fstream.h> + +fstreambase::fstreambase() +{ + init(filebuf::__new()); +} + +fstreambase::fstreambase(int fd) +{ + init(filebuf::__new()); + _IO_file_attach(rdbuf(), fd); +} + +fstreambase::fstreambase(const char *name, int mode, int prot) +{ + init(filebuf::__new()); + if (!rdbuf()->open(name, mode, prot)) + set(ios::badbit); +} + +fstreambase::fstreambase(int fd, char *p, int l) +{ + init(filebuf::__new()); + _IO_file_attach(rdbuf(), fd); + _IO_file_setbuf(rdbuf(), p, l); +} + +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 diff --git a/gnu/lib/libg++/libio/genops.c b/gnu/lib/libg++/libio/genops.c new file mode 100644 index 0000000..469694c --- /dev/null +++ b/gnu/lib/libg++/libio/genops.c @@ -0,0 +1,867 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Generic or default I/O operations. */ + +#include "libioP.h" +#ifdef __STDC__ +#include <stdlib.h> +#endif +#include <string.h> + +void _IO_un_link(fp) + _IO_FILE *fp; +{ + if (fp->_flags & _IO_LINKED) { + _IO_FILE **f; + for (f = &_IO_list_all; *f != NULL; f = &(*f)->_chain) { + if (*f == fp) { + *f = fp->_chain; + break; + } + } + fp->_flags &= ~_IO_LINKED; + } +} + +void _IO_link_in(fp) + _IO_FILE *fp; +{ + if ((fp->_flags & _IO_LINKED) == 0) { + fp->_flags |= _IO_LINKED; + fp->_chain = _IO_list_all; + _IO_list_all = fp; + } +} + +/* Return minimum _pos markers + Assumes the current get area is the main get area. */ + +_IO_size_t +_IO_least_marker(fp) + register _IO_FILE *fp; +{ + _IO_ssize_t least_so_far = fp->_IO_read_end - fp->_IO_read_base; + register struct _IO_marker *mark; + for (mark = fp->_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 +_IO_switch_to_main_get_area(fp) + _IO_FILE *fp; +{ + char *tmp; + fp->_flags &= ~_IO_IN_BACKUP; + /* Swap _IO_read_end and _IO_save_end. */ + tmp = fp->_IO_read_end; fp->_IO_read_end= fp->_IO_save_end; fp->_IO_save_end= tmp; + /* Swap _IO_read_base and _IO_save_base. */ + tmp = fp->_IO_read_base; fp->_IO_read_base = fp->_IO_save_base; fp->_IO_save_base = tmp; + fp->_IO_read_ptr = fp->_IO_read_base; +} + +/* Switch current get area from main get area to (end of) backup area. */ + +void +_IO_switch_to_backup_area(fp) + register _IO_FILE *fp; +{ + char *tmp; + fp->_flags |= _IO_IN_BACKUP; + /* Swap _IO_read_end and _IO_save_end. */ + tmp = fp->_IO_read_end; fp->_IO_read_end = fp->_IO_save_end; fp->_IO_save_end = tmp; + /* Swap _gbase and _IO_save_base. */ + tmp = fp->_IO_read_base; fp->_IO_read_base = fp->_IO_save_base; fp->_IO_save_base = tmp; + fp->_IO_read_ptr = fp->_IO_read_end; +} + +int +_IO_switch_to_get_mode(fp) + register _IO_FILE *fp; +{ + if (fp->_IO_write_ptr > fp->_IO_write_base) + if (fp->_jumps->__overflow(fp, EOF) == EOF) + return EOF; + if (_IO_in_backup(fp)) + fp->_IO_read_base = fp->_IO_backup_base; + else + { + fp->_IO_read_base = fp->_IO_buf_base; + if (fp->_IO_write_ptr > fp->_IO_read_end) + fp->_IO_read_end = fp->_IO_write_ptr; + } + fp->_IO_read_ptr = fp->_IO_write_ptr; + + fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_read_ptr; + + fp->_flags &= ~_IO_CURRENTLY_PUTTING; + return 0; +} + +void +_IO_free_backup_area(fp) + register _IO_FILE *fp; +{ + if (_IO_in_backup (fp)) + _IO_switch_to_main_get_area(fp); /* Just in case. */ + free (fp->_IO_save_base); + fp->_IO_save_base = NULL; + fp->_IO_save_end = NULL; + fp->_IO_backup_base = NULL; +} + +#if 0 +int +_IO_switch_to_put_mode(fp) + register _IO_FILE *fp; +{ + fp->_IO_write_base = fp->_IO_read_ptr; + fp->_IO_write_ptr = fp->_IO_read_ptr; + /* Following is wrong if line- or un-buffered? */ + fp->_IO_write_end = fp->_flags & _IO_IN_BACKUP ? fp->_IO_read_end : fp->_IO_buf_end; + + fp->_IO_read_ptr = fp->_IO_read_end; + fp->_IO_read_base = fp->_IO_read_end; + + fp->_flags |= _IO_CURRENTLY_PUTTING; + return 0; +} +#endif + +int __overflow(f, ch) + _IO_FILE *f; + int ch; +{ + return f->_jumps->__overflow(f, ch); +} + +static int +save_for_backup (fp) + _IO_FILE *fp; +{ + /* Append [_IO_read_base.._IO_read_end] to backup area. */ + int least_mark = _IO_least_marker(fp); + /* needed_size is how much space we need in the backup area. */ + int needed_size = (fp->_IO_read_end - fp->_IO_read_base) - least_mark; + int current_Bsize = fp->_IO_save_end - fp->_IO_save_base; + int avail; /* Extra space available for future expansion. */ + int delta; + struct _IO_marker *mark; + if (needed_size > current_Bsize) + { + char *new_buffer; + avail = 100; + new_buffer = (char*)malloc(avail+needed_size); + if (new_buffer == NULL) + return EOF; /* FIXME */ + if (least_mark < 0) + { + memcpy(new_buffer + avail, + fp->_IO_save_end + least_mark, + -least_mark); + memcpy(new_buffer +avail - least_mark, + fp->_IO_read_base, + fp->_IO_read_end - fp->_IO_read_base); + } + else + memcpy(new_buffer + avail, + fp->_IO_read_base + least_mark, + needed_size); + if (fp->_IO_save_base) + free (fp->_IO_save_base); + fp->_IO_save_base = new_buffer; + fp->_IO_save_end = new_buffer + avail + needed_size; + } + else + { + avail = current_Bsize - needed_size; + if (least_mark < 0) + { + memmove(fp->_IO_save_base + avail, + fp->_IO_save_end + least_mark, + -least_mark); + memcpy(fp->_IO_save_base + avail - least_mark, + fp->_IO_read_base, + fp->_IO_read_end - fp->_IO_read_base); + } + else if (needed_size > 0) + memcpy(fp->_IO_save_base + avail, + fp->_IO_read_base + least_mark, + needed_size); + } + /* FIXME: Dubious arithmetic if pointers are NULL */ + fp->_IO_backup_base = fp->_IO_save_base + avail; + /* Adjust all the streammarkers. */ + delta = fp->_IO_read_end - fp->_IO_read_base; + for (mark = fp->_markers; mark != NULL; mark = mark->_next) + mark->_pos -= delta; + return 0; +} + +int +__underflow(fp) + _IO_FILE *fp; +{ + if (_IO_in_put_mode(fp)) + if (_IO_switch_to_get_mode(fp) == EOF) return EOF; + if (fp->_IO_read_ptr < fp->_IO_read_end) + return *(unsigned char*)fp->_IO_read_ptr; + if (_IO_in_backup(fp)) + { + _IO_switch_to_main_get_area(fp); + if (fp->_IO_read_ptr < fp->_IO_read_end) + return *fp->_IO_read_ptr; + } + if (_IO_have_markers(fp)) + { + if (save_for_backup (fp)) + return EOF; + } + else if (_IO_have_backup(fp)) + _IO_free_backup_area(fp); + return fp->_jumps->__underflow(fp); +} + +int +__uflow(fp) + _IO_FILE *fp; +{ + if (_IO_in_put_mode(fp)) + if (_IO_switch_to_get_mode(fp) == EOF) return EOF; + if (fp->_IO_read_ptr < fp->_IO_read_end) + return *(unsigned char*)fp->_IO_read_ptr++; + if (_IO_in_backup(fp)) + { + _IO_switch_to_main_get_area(fp); + if (fp->_IO_read_ptr < fp->_IO_read_end) + return *fp->_IO_read_ptr++; + } + if (_IO_have_markers(fp)) + { + if (save_for_backup (fp)) + return EOF; + } + else if (_IO_have_backup(fp)) + _IO_free_backup_area(fp); + return fp->_jumps->__uflow(fp); +} + +void +_IO_setb(f, b, eb, a) + _IO_FILE *f; + char *b; + char *eb; + int a; +{ + if (f->_IO_buf_base && !(f->_flags & _IO_USER_BUF)) + FREE_BUF(f->_IO_buf_base); + f->_IO_buf_base = b; + f->_IO_buf_end = eb; + if (a) + f->_flags &= ~_IO_USER_BUF; + else + f->_flags |= _IO_USER_BUF; +} + +void +_IO_doallocbuf(fp) + register _IO_FILE *fp; +{ + if (fp->_IO_buf_base) + return; + if (!(fp->_flags & _IO_UNBUFFERED)) + if (fp->_jumps->__doallocate(fp) != EOF) + return; + _IO_setb(fp, fp->_shortbuf, fp->_shortbuf+1, 0); +} + +int +_IO_default_underflow (fp) + _IO_FILE *fp; +{ + return EOF; +} + +int +_IO_default_uflow (fp) + _IO_FILE *fp; +{ + int ch = fp->_jumps->__underflow(fp); + if (ch == EOF) + return EOF; + return *(unsigned char*)fp->_IO_read_ptr++; +} + +_IO_size_t +_IO_default_xsputn(f, data, n) + register _IO_FILE *f; + const void *data; + _IO_size_t n; +{ + register const char *s = data; + register _IO_size_t more = n; + if (more <= 0) + return 0; + for (;;) + { + _IO_ssize_t count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */ + if (count > 0) + { + if (count > more) + count = more; + if (count > 20) + { + memcpy(f->_IO_write_ptr, s, count); + s += count; + f->_IO_write_ptr += count; + } + else if (count <= 0) + count = 0; + else + { + register char *p = f->_IO_write_ptr; + register _IO_ssize_t i; + for (i = count; --i >= 0; ) *p++ = *s++; + f->_IO_write_ptr = p; + } + more -= count; + } + if (more == 0 || __overflow(f, (unsigned char)*s++) == EOF) + break; + more--; + } + return n - more; +} + +_IO_size_t +_IO_sgetn(fp, data, n) + _IO_FILE *fp; + void *data; + _IO_size_t n; +{ + /* FIXME handle putback buffer here! */ + return fp->_jumps->__xsgetn(fp, data, n); +} + +_IO_size_t +_IO_default_xsgetn(fp, data, n) + _IO_FILE *fp; + void *data; + _IO_size_t n; +{ + register _IO_size_t more = n; + register char *s = data; + for (;;) + { + _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr; /* Data available. */ + if (count > 0) + { + if (count > more) + count = more; + if (count > 20) + { + memcpy(s, fp->_IO_read_ptr, count); + s += count; + fp->_IO_read_ptr += count; + } + else if (count <= 0) + count = 0; + else + { + register char *p = fp->_IO_read_ptr; + register int i = (int)count; + while (--i >= 0) *s++ = *p++; + fp->_IO_read_ptr = p; + } + more -= count; + } + if (more == 0 || __underflow(fp) == EOF) + break; + } + return n - more; +} + +int +_IO_sync(fp) + register _IO_FILE *fp; +{ + if (fp->_IO_read_ptr == fp->_IO_read_end && fp->_IO_write_ptr == fp->_IO_write_base) + return 0; + return EOF; +} + +int +_IO_default_setbuf(fp, p, len) + register _IO_FILE *fp; + char* p; + _IO_ssize_t len; +{ + if (fp->_jumps->__sync(fp) == EOF) + return EOF; + if (p == NULL || len == 0) + { + fp->_flags |= _IO_UNBUFFERED; + _IO_setb(fp, fp->_shortbuf, fp->_shortbuf+1, 0); + } + else + { + fp->_flags &= ~_IO_UNBUFFERED; + _IO_setb(fp, p, p+len, 0); + } + fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = 0; + fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = 0; + return 0; +} + +_IO_pos_t +_IO_default_seekpos(fp, pos, mode) + _IO_FILE *fp; + _IO_pos_t pos; + _IO_seekflags mode; +{ + return fp->_jumps->__seekoff(fp, _IO_pos_as_off(pos), mode); +} + +int +_IO_default_doallocate(fp) + _IO_FILE *fp; +{ + char *buf = ALLOC_BUF(_IO_BUFSIZ); + if (buf == NULL) + return EOF; + _IO_setb(fp, buf, buf+_IO_BUFSIZ, 1); + return 1; +} + +void +_IO_init(fp, flags) + register _IO_FILE *fp; + int flags; +{ + fp->_flags = _IO_MAGIC|flags; + fp->_IO_buf_base = NULL; + fp->_IO_buf_end = NULL; + fp->_IO_read_base = NULL; + fp->_IO_read_ptr = NULL; + fp->_IO_read_end = NULL; + fp->_IO_write_base = NULL; + fp->_IO_write_ptr = NULL; + fp->_IO_write_end = NULL; + fp->_chain = NULL; /* Not necessary. */ + + fp->_IO_save_base = NULL; + fp->_IO_backup_base = NULL; + fp->_IO_save_end = NULL; + fp->_markers = NULL; + fp->_cur_column = 0; +} + +int +_IO_default_sync (fp) + _IO_FILE *fp; +{ + return 0; +} + +/* The way the C++ classes are mapped into the C functions in the + current implementation, this function can get called twice! */ + +void _IO_default_finish (fp) + _IO_FILE *fp; +{ + struct _IO_marker *mark; + if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF)) + { + FREE_BUF(fp->_IO_buf_base); + fp->_IO_buf_base = fp->_IO_buf_end = NULL; + } + + for (mark = fp->_markers; mark != NULL; mark = mark->_next) + mark->_sbuf = NULL; + + if (fp->_IO_save_base) + { + free (fp->_IO_save_base); + fp->_IO_save_base = NULL; + } + + _IO_un_link(fp); +} + +_IO_pos_t +_IO_default_seekoff(fp, offset, mode) + register _IO_FILE *fp; + _IO_off_t offset; + _IO_seekflags mode; +{ + return _IO_pos_BAD; +} + +int +_IO_sputbackc(fp, c) /* ungetc(c, fp) */ + register _IO_FILE *fp; + int c; +{ + if (fp->_IO_read_ptr > fp->_IO_read_base + && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c) + { + fp->_IO_read_ptr--; + return (unsigned char)c; + } + return fp->_jumps->__pbackfail(fp, c); +} + +int +_IO_sungetc(fp) + register _IO_FILE *fp; +{ + if (fp->_IO_read_ptr > fp->_IO_read_base) + { + fp->_IO_read_ptr--; + return (unsigned char)*fp->_IO_read_ptr; + } + else + return fp->_jumps->__pbackfail(fp, EOF); +} + +#if 0 /* Work in progress */ +void +_IO_set_column(fp, c) + register _IO_FILE *fp; + int c; +{ + if (c == -1) + fp->_collumn = -1; + else + fp->_collumn = c - (fp->_IO_write_ptr - fp->_IO_write_base); +} +#else +int +_IO_set_column(fp, i) + register _IO_FILE *fp; + int i; +{ + fp->_cur_column = i+1; + return 0; +} +#endif + + +unsigned +_IO_adjust_column(start, line, count) + 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 +_IO_get_column(fp) + register _IO_FILE *fp; +{ + if (fp->_cur_column) + return _IO_adjust_column(fp->_cur_column - 1, + fp->_IO_write_base, + fp->_IO_write_ptr - fp->_IO_write_base); + return -1; +} + +int +_IO_flush_all() +{ + int result = 0; + _IO_FILE *fp; + for (fp = _IO_list_all; fp != NULL; fp = fp->_chain) + if (fp->_IO_write_ptr > fp->_IO_write_base + && fp->_jumps->__overflow(fp, EOF) == EOF) + result = EOF; + return result; +} + +void +_IO_flush_all_linebuffered() +{ + _IO_FILE *fp; + for (fp = _IO_list_all; fp != NULL; fp = fp->_chain) + if (fp->_flags & _IO_LINE_BUF) + fp->_jumps->__overflow(fp, EOF); +} + +void +_IO_unbuffer_all () +{ + _IO_FILE *fp; + for (fp = _IO_list_all; fp != NULL; fp = fp->_chain) + if (! (fp->_flags & _IO_UNBUFFERED)) + fp->_jumps->__setbuf(fp, NULL, 0); +} + +void +_IO_cleanup () +{ + _IO_flush_all (); + + /* We currently don't have a reliable mechanism for making sure that + C++ static destructors are executed in the correct order. + So it is possible that other static destructord might want to + write to cout - and they're supposed to be able to do so. + + The following will make the standard streambufs be unbuffered, + which forces any output from late destructors to be written out. */ + _IO_unbuffer_all (); +} + +void _IO_init_marker(marker, fp) + struct _IO_marker *marker; + _IO_FILE *fp; +{ + marker->_sbuf = fp; + if (_IO_in_put_mode(fp)) + _IO_switch_to_get_mode(fp); + if (_IO_in_backup(fp)) + marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end; + else + marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base; + + /* Should perhaps sort the chain? */ + marker->_next = fp->_markers; + fp->_markers = marker; +} + +void +_IO_remove_marker (marker) + register struct _IO_marker * marker; +{ + /* Unlink from sb's chain. */ + register struct _IO_marker **ptr = &marker->_sbuf->_markers; + for (; ; ptr = &(*ptr)->_next) + { + if (*ptr == NULL) + break; + else if (*ptr == marker) + { + *ptr = marker->_next; + return; + } + } +#if 0 + if _sbuf has a backup area that is no longer needed, should we delete + it now, or wait until the next underflow? +#endif +} + +#define BAD_DELTA EOF + +int +_IO_marker_difference(mark1, mark2) + struct _IO_marker *mark1; + struct _IO_marker *mark2; +{ + return mark1->_pos - mark2->_pos; +} + +/* Return difference between MARK and current posistion of MARK's stream. */ +int +_IO_marker_delta(mark) + struct _IO_marker *mark; +{ + int cur_pos; + if (mark->_sbuf == NULL) + return BAD_DELTA; + if (_IO_in_backup(mark->_sbuf)) + cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end; + else + cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base; + return mark->_pos - cur_pos; +} + +int _IO_seekmark(fp, mark, delta) + _IO_FILE *fp; + struct _IO_marker *mark; + int delta; +{ + if (mark->_sbuf != fp) + return EOF; + if (mark->_pos >= 0) + { + if (_IO_in_backup(fp)) + _IO_switch_to_main_get_area(fp); + fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos; + } + else + { + if (!_IO_in_backup(fp)) + _IO_switch_to_backup_area(fp); + fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos; + } + return 0; +} + +void _IO_unsave_markers(fp) + register _IO_FILE *fp; +{ + register struct _IO_marker *mark = fp->_markers; + if (mark) + { +#ifdef TODO + 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); + } +#endif + fp->_markers = 0; + } + + if (_IO_have_backup(fp)) + _IO_free_backup_area(fp); +} + +int +_IO_nobackup_pbackfail(fp, c) + register _IO_FILE *fp; + int c; +{ + if (fp->_IO_read_ptr > fp->_IO_read_base) + fp->_IO_read_ptr--; + if (c != EOF && *fp->_IO_read_ptr != c) + *fp->_IO_read_ptr = c; + return (unsigned char)c; +} + +int +_IO_default_pbackfail(fp, c) + register _IO_FILE *fp; + int c; +{ + if (fp->_IO_read_ptr <= fp->_IO_read_base) + { + /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/ + if (_IO_have_backup(fp) && !_IO_in_backup(fp)) + _IO_switch_to_backup_area(fp); + + if (!_IO_have_backup(fp)) + { + /* No backup buffer: allocate one. */ + /* Use nshort buffer, if unused? (probably not) FIXME */ + int backup_size = 128; + char *bbuf = (char*)malloc(backup_size); + if (bbuf == NULL) + return EOF; + fp->_IO_save_base = bbuf; + fp->_IO_save_end = fp->_IO_save_base + backup_size; + fp->_IO_backup_base = fp->_IO_save_end; + _IO_switch_to_backup_area(fp); + } + else if (fp->_IO_read_ptr <= fp->_IO_read_base) + { + /* Increase size of existing backup buffer. */ + _IO_size_t new_size; + _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base; + char *new_buf; + new_size = 2 * old_size; + new_buf = (char*)malloc(new_size); + if (new_buf == NULL) + return EOF; + memcpy(new_buf+(new_size-old_size), fp->_IO_read_base, old_size); + free (fp->_IO_read_base); + _IO_setg(fp, + new_buf, new_buf+(new_size-old_size), new_buf+new_size); + fp->_IO_backup_base = fp->_IO_read_ptr; + } + } + fp->_IO_read_ptr--; + if (c != EOF && *fp->_IO_read_ptr != c) + *fp->_IO_read_ptr = c; + return (unsigned char)*fp->_IO_read_ptr; +} + +_IO_pos_t +_IO_default_seek(fp, offset, dir) + _IO_FILE *fp; + _IO_off_t offset; + int dir; +{ + return _IO_pos_BAD; +} + +int +_IO_default_stat(fp, st) + _IO_FILE *fp; + void* st; +{ + return EOF; +} + +_IO_ssize_t +_IO_default_read(fp, data, n) + register _IO_FILE* fp; + void* data; + _IO_ssize_t n; +{ + return -1; +} + +_IO_ssize_t +_IO_default_write(fp, data, n) + register _IO_FILE* fp; + const void* data; + _IO_ssize_t n; +{ + return 0; +} + + +#ifdef TODO +#if defined(linux) +#define IO_CLEANUP ; +#endif + +#ifdef IO_CLEANUP + IO_CLEANUP +#else +struct __io_defs { + __io_defs() { } + ~__io_defs() { _IO_cleanup(); } +}; +__io_defs io_defs__; +#endif + +#endif /* TODO */ diff --git a/gnu/lib/libg++/libio/indstream.cc b/gnu/lib/libg++/libio/indstream.cc new file mode 100644 index 0000000..1468d45 --- /dev/null +++ b/gnu/lib/libg++/libio/indstream.cc @@ -0,0 +1,116 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. + +Written by Per Bothner (bothner@cygnus.com). */ + +#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() : NULL; + streambuf *pbuf = (select & ios::out) ? put_stream() : NULL; + 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() : NULL; + streambuf *pbuf = (select & ios::out) ? put_stream() : NULL; + 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 get_ret_val = gbuf ? gbuf->sync() : 0; + streambuf *pbuf = put_stream(); + int put_ret_val = (pbuf && pbuf != gbuf) ? pbuf->sync() : 0; + return get_ret_val || put_ret_val; +} + +int indirectbuf::pbackfail(int c) +{ + return get_stream()->sputbackc(c); +} diff --git a/gnu/lib/libg++/libio/ioextend.cc b/gnu/lib/libg++/libio/ioextend.cc new file mode 100644 index 0000000..bc6a3e1 --- /dev/null +++ b/gnu/lib/libg++/libio/ioextend.cc @@ -0,0 +1,129 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include <iostream.h> + +static int __xalloc = 0; + +int ios::xalloc() +{ + return __xalloc++; +} + +static ios::fmtflags __used_fmt_flags += ios::skipws | ios::left | ios::right | ios::internal +| ios::dec | ios::oct | ios::hex | ios::showbase | ios::showpoint +| ios::uppercase | ios::showpos | ios::scientific | ios::fixed +| ios::unitbuf | ios::stdio | ios::dont_close; + +ios::fmtflags ios::bitalloc() +{ + fmtflags bit_to_try = (fmtflags)1; + for (; bit_to_try; bit_to_try <<= 1) + { + if ((__used_fmt_flags & bit_to_try) == 0) + { + __used_fmt_flags |= bit_to_try; + return bit_to_try; + } + } + return 0; +} + +// NOTE: This implementation of ios::iword and ios::pword assumes +// that these methods are seldom used, so we want to minimize +// the space and time overhead when NOT using these methods. +// +// ANSI specifies two conceptually-infinite arrays, one whose +// elements are longs, and one whose elements are (void*)s. +// We implement this as a single array, each of whose element is +// a (struct ptr_and_long), which has space for both a long and a void*. +// We also specify that (the i field of) the 0'th element of the array +// contains the allocated length of the array (not counting that +// initial element). + +struct ptr_and_long { + void *p; + long i; +}; + +static struct ptr_and_long& +get_array_element(ios& io, int index) +{ + if (index < 0) + io._throw_failure(); + register struct ptr_and_long *array = (ptr_and_long*)io._arrays; + int old_length = array == NULL ? 0 : array[0].i; + if (index >= old_length) + { + register int i; + int new_length = index + 10; + register struct ptr_and_long *new_array + = new ptr_and_long[1 + new_length]; + if (array != NULL) + { + for (i = 1; i <= old_length; i++) + new_array[i] = array[i]; + delete [] array; + } + for (i = old_length + 1; i <= new_length; i++) + { + new_array[i].i = 0; + new_array[i].p = (void*)0; + } + new_array[0].i = new_length; + new_array[0].p = (void*)0; + io._arrays = (void*)new_array; + array = new_array; + } + return array[index+1]; +} + +long& ios::iword(int index) +{ + return get_array_element(*this, index).i; +} + +void*& ios::pword(int index) +{ + return get_array_element(*this, index).p; +} + +long ios::iword(int index) const +{ + if (index < 0) + _throw_failure(); + register struct ptr_and_long *pl_array = (ptr_and_long*)_arrays; + int len = pl_array == NULL ? 0 : pl_array[0].i; + return index >= len ? 0 : pl_array[index+1].i; +} + +void* ios::pword(int index) const +{ + if (index < 0) + _throw_failure(); + register struct ptr_and_long *pl_array = (ptr_and_long*)_arrays; + int len = pl_array == NULL ? 0 : pl_array[0].i; + return index >= len ? 0 : pl_array[index+1].p; +} diff --git a/gnu/lib/libg++/libio/iofclose.c b/gnu/lib/libg++/libio/iofclose.c new file mode 100644 index 0000000..44664d9 --- /dev/null +++ b/gnu/lib/libg++/libio/iofclose.c @@ -0,0 +1,47 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" +#ifdef __STDC__ +#include <stdlib.h> +#endif + +int +_IO_fclose(fp) + register _IO_FILE *fp; +{ + int status = 0; + COERCE_FILE(fp); + if ((fp->_IO_file_flags & _IO_MAGIC_MASK) != _IO_MAGIC) + return EOF; + if (fp->_IO_file_flags & _IO_IS_FILEBUF) + status = _IO_file_close_it(fp); + fp->_jumps->__finish(fp); + if (fp != _IO_stdin && fp != _IO_stdout && fp != _IO_stderr) + { + fp->_IO_file_flags = 0; + free(fp); + } + return status; +} diff --git a/gnu/lib/libg++/libio/iofgetpos.c b/gnu/lib/libg++/libio/iofgetpos.c new file mode 100644 index 0000000..16ecec0 --- /dev/null +++ b/gnu/lib/libg++/libio/iofgetpos.c @@ -0,0 +1,47 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" +#include <errno.h> +/* ANSI explicily requires setting errno to a positive value on failure. */ + +int +_IO_fgetpos(fp, posp) + _IO_FILE* fp; + _IO_fpos_t *posp; +{ + _IO_fpos_t pos; + COERCE_FILE(fp); + pos = _IO_seekoff(fp, 0, _IO_seek_cur|_IO_seek_not_in|_IO_seek_not_out); + if (pos == _IO_pos_BAD) + { +#ifdef EIO + if (errno == 0) + errno = EIO; +#endif + return EOF; + } + *posp = pos; + return 0; +} diff --git a/gnu/lib/libg++/libio/iofread.c b/gnu/lib/libg++/libio/iofread.c new file mode 100644 index 0000000..c72c70f --- /dev/null +++ b/gnu/lib/libg++/libio/iofread.c @@ -0,0 +1,41 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" + +_IO_size_t +_IO_fread(buf, size, count, fp) + void *buf; + _IO_size_t size; + _IO_size_t count; + _IO_FILE* fp; +{ + _IO_size_t bytes_requested = size*count; + _IO_size_t bytes_read; + COERCE_FILE(fp); + if (bytes_requested == 0) + return 0; + bytes_read = _IO_sgetn(fp, (char *)buf, bytes_requested); + return bytes_requested == bytes_read ? count : bytes_read / size; +} diff --git a/gnu/lib/libg++/libio/iofscanf.c b/gnu/lib/libg++/libio/iofscanf.c new file mode 100644 index 0000000..7110401 --- /dev/null +++ b/gnu/lib/libg++/libio/iofscanf.c @@ -0,0 +1,48 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" + +#ifdef __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +int +_IO_fscanf +#ifdef __STDC__ + (_IO_FILE *fp, const char* format, ...) +#else +(fp, format, va_alist) _IO_FILE *fp; char *format; va_dcl +#endif +{ + int ret; + va_list args; + COERCE_FILE(fp); + _IO_va_start(args, format); + ret = _IO_vfscanf(fp, format, args, NULL); + va_end(args); + return ret; +} diff --git a/gnu/lib/libg++/libio/iofsetpos.c b/gnu/lib/libg++/libio/iofsetpos.c new file mode 100644 index 0000000..763fbe6 --- /dev/null +++ b/gnu/lib/libg++/libio/iofsetpos.c @@ -0,0 +1,44 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include <libioP.h> +#include <errno.h> + +int +_IO_fsetpos(fp, posp) + _IO_FILE* fp; + const _IO_fpos_t *posp; +{ + COERCE_FILE(fp); + if (_IO_seekpos(fp, *posp, 0) == _IO_pos_BAD) + { + /*ANSI explicily requires setting errno to a positive value on failure.*/ +#ifdef EIO + if (errno == 0) + errno = EIO; +#endif + return EOF; + } + return 0; +} diff --git a/gnu/lib/libg++/libio/iogetline.c b/gnu/lib/libg++/libio/iogetline.c new file mode 100644 index 0000000..dcaa4a1 --- /dev/null +++ b/gnu/lib/libg++/libio/iogetline.c @@ -0,0 +1,77 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" +#include <string.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). + Does not put a terminating '\0' in buf. + If extract_delim < 0, leave delimiter unread. + If extract_delim > 0, insert delim in output. */ + +_IO_size_t +_IO_getline(fp, buf, n, delim, extract_delim) + _IO_FILE *fp; + char* buf; + _IO_size_t n; + int delim; + int extract_delim; +{ + register char *ptr = buf; + do + { + _IO_ssize_t len = fp->_IO_read_end - fp->_IO_read_ptr; + char *t; + if (len <= 0) + if (__underflow(fp) == EOF) + break; + else + len = fp->_IO_read_end - fp->_IO_read_ptr; + if (len >= n) + len = n; + t = (char*)memchr((void*)fp->_IO_read_ptr, delim, len); + if (t != NULL) + { + _IO_size_t old_len = ptr-buf; + len = t - fp->_IO_read_ptr; + if (extract_delim >= 0) + { + t++; + if (extract_delim > 0) + len++; + } + memcpy((void*)ptr, (void*)fp->_IO_read_ptr, len); + fp->_IO_read_ptr = t; + return old_len + len; + } + memcpy((void*)ptr, (void*)fp->_IO_read_ptr, len); + fp->_IO_read_ptr += len; + ptr += len; + n -= len; + } while (n != 0); + return ptr - buf; +} diff --git a/gnu/lib/libg++/libio/ioignore.c b/gnu/lib/libg++/libio/ioignore.c new file mode 100644 index 0000000..1b26503 --- /dev/null +++ b/gnu/lib/libg++/libio/ioignore.c @@ -0,0 +1,47 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" + +int +_IO_ignore(fp, n) + register _IO_FILE *fp; + _IO_size_t n; +{ + register _IO_size_t more = n; + for (;;) + { + _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr; + if (count > 0) + { + if (count > more) + count = more; + fp->_IO_read_ptr += count; + more -= count; + } + if (more == 0 || __underflow(fp) == EOF) + break; + } + return n - more; +} diff --git a/gnu/lib/libg++/libio/iomanip.cc b/gnu/lib/libg++/libio/iomanip.cc new file mode 100644 index 0000000..bb15f64 --- /dev/null +++ b/gnu/lib/libg++/libio/iomanip.cc @@ -0,0 +1,90 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#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; +} + +template class smanip<int>; +template class smanip<ios::fmtflags>; +template istream& operator>>(istream&, const smanip<int>&); +template istream& operator>>(istream&, const smanip<ios::fmtflags>&); +template ostream& operator<<(ostream&, const smanip<int>&); +template ostream& operator<<(ostream&, const smanip<ios::fmtflags>&); diff --git a/gnu/lib/libg++/libio/iopadn.c b/gnu/lib/libg++/libio/iopadn.c new file mode 100644 index 0000000..84dcee6 --- /dev/null +++ b/gnu/lib/libg++/libio/iopadn.c @@ -0,0 +1,67 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" + +#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'}; + +_IO_ssize_t +_IO_padn(fp, pad, count) + _IO_FILE *fp; + int pad; + _IO_ssize_t count; +{ + char padbuf[PADSIZE]; + const char *padptr; + register int i; + _IO_size_t written = 0, w; + + 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) + { + w = _IO_sputn(fp, padptr, PADSIZE); + written += w; + if (w != PADSIZE) + return written; + } + + if (i > 0) + { + w = _IO_sputn(fp, padptr, i); + written += w; + } + return written; +} diff --git a/gnu/lib/libg++/libio/iopopen.c b/gnu/lib/libg++/libio/iopopen.c new file mode 100644 index 0000000..dfa3482 --- /dev/null +++ b/gnu/lib/libg++/libio/iopopen.c @@ -0,0 +1,221 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* written by Per Bothner (bothner@cygnus.com) */ + +#define _POSIX_SOURCE +#include "libioP.h" +#if _IO_HAVE_SYS_WAIT +#include <signal.h> +#include <unistd.h> +#ifdef __STDC__ +#include <stdlib.h> +#endif +#include <sys/wait.h> + +#ifndef _IO_fork +#define _IO_fork vfork /* defined in libiberty, if needed */ +_IO_pid_t _IO_fork(); +#endif + +#endif /* _IO_HAVE_SYS_WAIT */ + +#ifndef _IO_pipe +#define _IO_pipe pipe +extern int _IO_pipe(); +#endif + +#ifndef _IO_dup2 +#define _IO_dup2 dup2 +extern int _IO_dup2(); +#endif + +#ifndef _IO_waitpid +#define _IO_waitpid waitpid +#endif + +#ifndef _IO_execl +#define _IO_execl execl +#endif +#ifndef _IO__exit +#define _IO__exit _exit +#endif + +struct _IO_proc_file +{ + struct _IO_FILE_plus file; + /* Following fields must match those in class procbuf (procbuf.h) */ + _IO_pid_t pid; + struct _IO_proc_file *next; +}; +typedef struct _IO_proc_file _IO_proc_file; + +static struct _IO_proc_file *proc_file_chain = NULL; + +_IO_FILE * +_IO_proc_open(fp, command, mode) + _IO_FILE* fp; + const char *command; + const char *mode; +{ +#if _IO_HAVE_SYS_WAIT + int read_or_write; + int pipe_fds[2]; + int parent_end, child_end; + _IO_pid_t child_pid; + if (_IO_file_is_open(fp)) + return NULL; + if (_IO_pipe(pipe_fds) < 0) + return NULL; + if (mode[0] == 'r') + { + parent_end = pipe_fds[0]; + child_end = pipe_fds[1]; + read_or_write = _IO_NO_WRITES; + } + else + { + parent_end = pipe_fds[1]; + child_end = pipe_fds[0]; + read_or_write = _IO_NO_READS; + } + ((_IO_proc_file*)fp)->pid = child_pid = _IO_fork(); + if (child_pid == 0) + { + int child_std_end = mode[0] == 'r' ? 1 : 0; + _IO_close(parent_end); + if (child_end != child_std_end) + { + _IO_dup2(child_end, child_std_end); + _IO_close(child_end); + } + /* Posix.2: "popen() shall ensure that any streams from previous + popen() calls that remain open in the parent process are closed + in the new child process." */ + while (proc_file_chain) + { + _IO_close (_IO_fileno ((_IO_FILE *) proc_file_chain)); + proc_file_chain = proc_file_chain->next; + } + + _IO_execl("/bin/sh", "sh", "-c", command, NULL); + _IO__exit(127); + } + _IO_close(child_end); + if (child_pid < 0) + { + _IO_close(parent_end); + return NULL; + } + _IO_fileno(fp) = parent_end; + + /* Link into proc_file_chain. */ + ((_IO_proc_file*)fp)->next = proc_file_chain; + proc_file_chain = (_IO_proc_file*)fp; + + _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES); + return fp; +#else /* !_IO_HAVE_SYS_WAIT */ + return NULL; +#endif +} + +_IO_FILE * +_IO_popen(command, mode) + const char *command; + const char *mode; +{ + _IO_proc_file *fpx = (_IO_proc_file*)malloc(sizeof(_IO_proc_file)); + _IO_FILE *fp = (_IO_FILE*)fpx; + if (fp == NULL) + return NULL; + _IO_init(fp, 0); + fp->_jumps = &_IO_proc_jumps; + _IO_file_init(fp); + ((struct _IO_FILE_plus*)fp)->vtable = NULL; + if (_IO_proc_open (fp, command, mode) != NULL) + return fp; + free (fpx); + return NULL; +} + +int +_IO_proc_close(fp) + _IO_FILE *fp; +{ + /* This is not name-space clean. FIXME! */ +#if _IO_HAVE_SYS_WAIT + int wstatus; + _IO_proc_file **ptr = &proc_file_chain; + _IO_pid_t wait_pid; + int status = -1; + + /* Unlink from proc_file_chain. */ + for ( ; *ptr != NULL; ptr = &(*ptr)->next) + { + if (*ptr == (_IO_proc_file*)fp) + { + *ptr = (*ptr)->next; + status = 0; + break; + } + } + + if (status < 0 || _IO_close(_IO_fileno(fp)) < 0) + return -1; + /* POSIX.2 Rationale: "Some historical implementations either block + or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting + for the child process to terminate. Since this behavior is not + described in POSIX.2, such implementations are not conforming." */ + do + { + wait_pid = _IO_waitpid (((_IO_proc_file*)fp)->pid, &wstatus, 0); + } while (wait_pid == -1 && errno == EINTR); + if (wait_pid == -1) + return -1; + return wstatus; +#else /* !_IO_HAVE_SYS_WAIT */ + return -1; +#endif +} + +struct _IO_jump_t _IO_proc_jumps = { + _IO_file_overflow, + _IO_file_underflow, + _IO_file_xsputn, + _IO_default_xsgetn, + _IO_file_read, + _IO_file_write, + _IO_file_doallocate, + _IO_default_pbackfail, + _IO_file_setbuf, + _IO_file_sync, + _IO_file_finish, + _IO_proc_close, + _IO_file_stat, + _IO_file_seek, + _IO_file_seekoff, + _IO_default_seekpos, + _IO_default_uflow +}; diff --git a/gnu/lib/libg++/libio/ioprims.c b/gnu/lib/libg++/libio/ioprims.c new file mode 100644 index 0000000..4c41ed8 --- /dev/null +++ b/gnu/lib/libg++/libio/ioprims.c @@ -0,0 +1,79 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* I/O OS-level primitives. + Needs to be replaced if not using Unix. + Also needs to be replaced if avoiding name-space pollution + (in which case read would be defined in terms of _IO_read, + rather than vice versa). */ + +#include "libioP.h" +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef TODO +/* Add open, isatty */ +#endif + +_IO_ssize_t +_IO_read (fildes, buf, nbyte) + int fildes; + void *buf; + _IO_size_t nbyte; +{ + return read (fildes, buf, nbyte); +} + +_IO_ssize_t +_IO_write (fildes, buf, nbyte) + int fildes; + const void *buf; + _IO_size_t nbyte; +{ + return write (fildes, buf, nbyte); +} + +_IO_off_t +_IO_lseek (fildes, offset, whence) + int fildes; + _IO_off_t offset; + int whence; +{ + return lseek (fildes, offset, whence); +} + +int +_IO_close (fildes) + int fildes; +{ + return close (fildes); +} + +int +_IO_fstat (fildes, buf) + int fildes; + struct stat *buf; +{ + return fstat (fildes, buf); +} diff --git a/gnu/lib/libg++/libio/ioprintf.c b/gnu/lib/libg++/libio/ioprintf.c new file mode 100644 index 0000000..519785a --- /dev/null +++ b/gnu/lib/libg++/libio/ioprintf.c @@ -0,0 +1,47 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" + +#ifdef __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +int +_IO_printf +#ifdef __STDC__ + (const char* format, ...) +#else +(format, va_alist) char *format; va_dcl +#endif +{ + int ret; + va_list args; + _IO_va_start(args, format); + ret = _IO_vfprintf(_IO_stdout, format, args); + va_end(args); + return ret; +} diff --git a/gnu/lib/libg++/libio/ioseekoff.c b/gnu/lib/libg++/libio/ioseekoff.c new file mode 100644 index 0000000..7ebf183 --- /dev/null +++ b/gnu/lib/libg++/libio/ioseekoff.c @@ -0,0 +1,47 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include <libioP.h> + +_IO_pos_t +_IO_seekoff(fp, offset, flags) + _IO_FILE* fp; + _IO_off_t offset; + _IO_seekflags flags; +{ + int dir = flags & 3; + + /* If we have a backup buffer, get rid of it, since the __seekoff + callback may not know to do the right thing about it. + This may be over-kill, but it'll do for now. TODO */ + + if (_IO_have_backup (fp)) + { + if (dir == _IO_seek_cur && _IO_in_backup (fp)) + offset -= fp->_IO_read_end - fp->_IO_read_ptr; + _IO_free_backup_area (fp); + } + + return fp->_jumps->__seekoff(fp, offset, flags); +} diff --git a/gnu/lib/libg++/libio/ioseekpos.c b/gnu/lib/libg++/libio/ioseekpos.c new file mode 100644 index 0000000..a99b703 --- /dev/null +++ b/gnu/lib/libg++/libio/ioseekpos.c @@ -0,0 +1,41 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include <libioP.h> + +_IO_pos_t +_IO_seekpos(fp, pos, flags) + _IO_FILE* fp; + _IO_pos_t pos; + _IO_seekflags flags; +{ + /* If we have a backup buffer, get rid of it, since the __seekoff + callback may not know to do the right thing about it. + This may be over-kill, but it'll do for now. TODO */ + + if (_IO_have_backup (fp)) + _IO_free_backup_area (fp); + + return fp->_jumps->__seekpos(fp, pos, flags); +} diff --git a/gnu/lib/libg++/libio/iostream.cc b/gnu/lib/libg++/libio/iostream.cc new file mode 100644 index 0000000..db953d4 --- /dev/null +++ b/gnu/lib/libg++/libio/iostream.cc @@ -0,0 +1,813 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUC__ +#pragma implementation +#endif +#define _STREAM_COMPAT +#include <iostream.h> +#include "libioP.h" +#include <stdio.h> /* Needed for sprintf */ +#include <ctype.h> +#include <string.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) +{ + init (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|ios::eofbit); + } + return *this; +} + +istream& istream::seekg(streampos pos) +{ + pos = _strbuf->sseekpos(pos, ios::in); + if (pos == streampos(EOF)) + set(ios::badbit); + return *this; +} + +istream& istream::seekg(streamoff off, _seek_dir dir) +{ + streampos pos + = _IO_seekoff (_strbuf, off, + (_IO_seekflags) + ((int)dir | _IO_seek_not_out | _IO_seek_pos_ignored)); + if (pos == streampos(EOF)) + set(ios::badbit); + return *this; +} + +streampos istream::tellg() +{ +#if 0 + streampos pos = _strbuf->sseekoff(0, ios::cur, ios::in); +#else + streampos pos + = _IO_seekoff (_strbuf, 0, + (_IO_seekflags)(_IO_seek_cur | _IO_seek_not_out)); +#endif + if (pos == streampos(EOF)) + set(ios::badbit); + return pos; +} + +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; +} + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +#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) +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +READ_INT(long long) +READ_INT(unsigned long long) +#endif +#if _G_HAVE_BOOL +READ_INT(bool) +#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. + if (_strbuf->sputc(c) == EOF) + goto failed; +#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) && padding) // Default adjustment. + if (_IO_padn(sb, fill_char, padding) < padding) + goto failed; + if (sb->sputc(c) == EOF) + goto failed; + if (flags() & ios::left && padding) // Left adjustment. + if (_IO_padn(sb, fill_char, padding) < padding) + goto failed; +#endif + osfx(); + } + return *this; + failed: + set(ios::badbit); + 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) && (*buf_ptr != '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)) { + show_base = xdigs + 16; // Either "0X" or "0x". + show_base_len = 2; + } + } + else { // Decimal +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) + // 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. + if (_IO_padn(sbuf, fill_char, padding) < padding) + goto failed; + if (sign < 0 || show_pos) + { + char ch = sign < 0 ? '-' : '+'; + if (sbuf->sputc(ch) < 0) + goto failed; + } + if (show_base_len) + if (_IO_sputn(sbuf, show_base, show_base_len) <= 0) + goto failed; + if (pad_kind == (ios::fmtflags)ios::internal && padding > 0) + if (_IO_padn(sbuf, fill_char, padding) < padding) + goto failed; + if (_IO_sputn (sbuf, buf_ptr, buf_len) != buf_len) + goto failed; + if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment + if (_IO_padn(sbuf, fill_char, padding) < padding) + goto failed; + stream.osfx(); + return; + failed: + stream.set(ios::badbit); + stream.osfx(); +} + +ostream& ostream::operator<<(int n) +{ + if (opfx()) { + int sign = 1; + unsigned int abs_n = (unsigned)n; + if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) + abs_n = -((unsigned)n), sign = -1; + write_int(*this, abs_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; + unsigned long abs_n = (unsigned long)n; + if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) + abs_n = -((unsigned long)n), sign = -1; + write_int(*this, abs_n, sign); + } + return *this; +} + +ostream& ostream::operator<<(unsigned long n) +{ + if (opfx()) + write_int(*this, n, 0); + return *this; +} + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +ostream& ostream::operator<<(long long n) +{ + if (opfx()) { + int sign = 1; + unsigned long long abs_n = (unsigned long long)n; + if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0) + abs_n = -((unsigned long long)n), sign = -1; + write_int(*this, abs_n, sign); + } + return *this; +} + + +ostream& ostream::operator<<(unsigned long long n) +{ + if (opfx()) + write_int(*this, n, 0); + return *this; +} +#endif /*__GNUC__*/ + +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 ((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 prec = precision(); + if (prec <= 0 && !(flags() & ios::fixed)) + prec = 6; /* default */ + + // Do actual conversion. +#ifdef USE_DTOA + if (_IO_outfloat(n, rdbuf(), format_char, width(0), + prec, flags(), + flags() & ios::showpos ? '+' : 0, + fill()) < 0) + set(ios::badbit|ios::failbit); // ?? +#else + int fpprec = 0; // 'Extra' (suppressed) floating precision. + if (prec > MAXFRACT) { + if (flags() & (ios::fixed|ios::scientific) & ios::showpos) + fpprec = prec - MAXFRACT; + prec = MAXFRACT; + } + 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 = '-'; + else if (flags() & ios::showpos) 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. + _IO_sputn (sbuf, 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); +// FIXME: Should we: if (w && len>w) len = w; + char fill_char = fill(); + register streambuf *sbuf = rdbuf(); + register int padding = w > len ? w - len : 0; + if (!(flags() & ios::left) && padding > 0) // Default adjustment. + if (_IO_padn(sbuf, fill_char, padding) != padding) + goto failed; + if (_IO_sputn (sbuf, s, len) != len) + goto failed; + if (flags() & ios::left && padding > 0) // Left adjustment. + if (_IO_padn(sbuf, fill_char, padding) != padding) + goto failed; + osfx(); + } + return *this; + failed: + set(ios::badbit); + osfx(); + return *this; +} + +#if 0 +ostream& ostream::operator<<(const void *p) +{ Is in osform.cc, to avoid pulling in all of _IO_vfprintf by this file. */ } +#endif + +ostream& ostream::operator<<(register streambuf* sbuf) +{ + if (opfx()) + { + char buffer[_IO_BUFSIZ]; + register streambuf* outbuf = _strbuf; + for (;;) + { + _IO_size_t count = _IO_sgetn(sbuf, buffer, _IO_BUFSIZ); + if (count <= 0) + break; + if (_IO_sputn(outbuf, buffer, count) != count) + { + set(ios::badbit); + break; + } + } + osfx(); + } + return *this; +} + +ostream::ostream(streambuf* sb, ostream* tied) +{ + init (sb, tied); + _flags |= ios::dont_close; +} + +ostream& ostream::seekp(streampos pos) +{ + pos = _strbuf->sseekpos(pos, ios::out); + if (pos == streampos(EOF)) + set(ios::badbit); + return *this; +} + +ostream& ostream::seekp(streamoff off, _seek_dir dir) +{ + streampos pos + = _IO_seekoff (_strbuf, off, + (_IO_seekflags) + ((int)dir | _IO_seek_not_in | _IO_seek_pos_ignored)); + if (pos == streampos(EOF)) + set(ios::badbit); + return *this; +} + +streampos ostream::tellp() +{ +#if 1 + streampos pos + = _IO_seekoff (_strbuf, 0, + (_IO_seekflags)(_IO_seek_cur | _IO_seek_not_in)); +#else + streampos pos = _strbuf->sseekoff(0, ios::cur, ios::out); +#endif + if (pos == streampos(EOF)) + set(ios::badbit); + return pos; +} + +ostream& ostream::flush() +{ + if (_strbuf->_jumps->__sync(_strbuf)) + 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 (_IO_sputn(_strbuf, 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) +{ + init (sb, tied); + _flags |= ios::dont_close; +} + +// 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 rdbuf(); + else if (_strbuf->_flags & _IO_IS_FILEBUF) + ((struct filebuf*)rdbuf())->close(); + else if (_strbuf != NULL) + rdbuf()->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 diff --git a/gnu/lib/libg++/libio/iostrerror.c b/gnu/lib/libg++/libio/iostrerror.c new file mode 100644 index 0000000..2833fc7 --- /dev/null +++ b/gnu/lib/libg++/libio/iostrerror.c @@ -0,0 +1,11 @@ +/* This should be replaced by whatever namespace-clean + version of strerror you have available. */ + +extern char *strerror(); + +char * +_IO_strerror(errnum) + int errnum; +{ + return strerror(errnum); +} diff --git a/gnu/lib/libg++/libio/ioungetc.c b/gnu/lib/libg++/libio/ioungetc.c new file mode 100644 index 0000000..7b983ed --- /dev/null +++ b/gnu/lib/libg++/libio/ioungetc.c @@ -0,0 +1,36 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" + +int +_IO_ungetc(c, fp) + int c; + _IO_FILE *fp; +{ + COERCE_FILE(fp); + if (c == EOF) + return EOF; + return _IO_sputbackc(fp, (unsigned char)c); +} diff --git a/gnu/lib/libg++/libio/iovfprintf.c b/gnu/lib/libg++/libio/iovfprintf.c new file mode 100644 index 0000000..feda569 --- /dev/null +++ b/gnu/lib/libg++/libio/iovfprintf.c @@ -0,0 +1,885 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* + * 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 "libioP.h" +#include <string.h> +#ifdef __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +/* + * Define FLOATING_POINT to get floating point. + */ +#ifndef NO_FLOATING_POINT +#define FLOATING_POINT +#endif + +/* end of configuration stuff */ + + +/* + * Helper "class" for `fprintf to unbuffered': creates a + * temporary buffer. */ + +struct helper_file +{ + struct _IO_FILE_plus _f; + _IO_FILE *_put_stream; +}; + +static int +_IO_helper_overflow (fp, c) + _IO_FILE *fp; + int c; +{ + _IO_FILE *target = ((struct helper_file*)fp)->_put_stream; + int used = fp->_IO_write_ptr - fp->_IO_write_base; + if (used) + { + _IO_sputn(target, fp->_IO_write_base, used); + fp->_IO_write_ptr -= used; + } + return _IO_putc (c, fp); +} + +static struct _IO_jump_t _IO_helper_jumps = { + _IO_helper_overflow, + _IO_default_underflow, + _IO_default_xsputn, + _IO_default_xsgetn, + _IO_default_read, + _IO_default_write, + _IO_default_doallocate, + _IO_default_pbackfail, + _IO_default_setbuf, + _IO_default_sync, + _IO_default_finish, + _IO_default_close, + _IO_default_stat, + _IO_default_seek, + _IO_default_seekoff, + _IO_default_seekpos, + _IO_default_uflow +}; + +static int +helper_vfprintf(fp, fmt0, ap) + register _IO_FILE* fp; + char const *fmt0; + _IO_va_list ap; +{ + char buf[_IO_BUFSIZ]; + struct helper_file helper; + register _IO_FILE *hp = (_IO_FILE*)&helper; + int result, to_flush; + + /* initialize helper */ + helper._put_stream = fp; + hp->_IO_write_base = buf; + hp->_IO_write_ptr = buf; + hp->_IO_write_end = buf+_IO_BUFSIZ; + hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS; + hp->_jumps = &_IO_helper_jumps; + + /* Now print to helper instead. */ + result = _IO_vfprintf(hp, fmt0, ap); + + /* Now flush anything from the helper to the fp. */ + if ((to_flush = hp->_IO_write_ptr - hp->_IO_write_base) > 0) + { + if (_IO_sputn(fp, hp->_IO_write_base, to_flush) != to_flush) + return EOF; + } + return result; +} + +#ifdef FLOATING_POINT + +#include "floatio.h" +#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ +#define DEFPREC 6 +extern double modf __P((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 +_IO_vfprintf(fp, fmt0, ap) + register _IO_FILE* fp; + char const *fmt0; + _IO_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 */ + + /* + * BEWARE, these `goto error' on error, and PAD uses `n'. + */ +#define PRINT(ptr, len) \ + do { if (_IO_sputn(fp,ptr, len) != len) goto error; } while (0) +#define PAD_SP(howmany) if (_IO_padn(fp, ' ', howmany) < (howmany)) goto error; +#define PAD_0(howmany) if (_IO_padn(fp, '0', howmany) < (howmany)) goto error; + + /* + * 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 stderr (and other unbuffered Unix files) */ + if (fp->_IO_file_flags & _IO_UNBUFFERED) + return helper_vfprintf(fp, 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 + { + int fmt_flags = 0; + int fill = ' '; + if (flags & ALT) + fmt_flags |= _IO_SHOWPOINT; + if (flags & LADJUST) + fmt_flags |= _IO_LEFT; + else if (flags & ZEROPAD) + fmt_flags |= _IO_INTERNAL, fill = '0'; + n = _IO_outfloat(_double, fp, 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) */ diff --git a/gnu/lib/libg++/libio/iovfscanf.c b/gnu/lib/libg++/libio/iovfscanf.c new file mode 100644 index 0000000..abf1e58 --- /dev/null +++ b/gnu/lib/libg++/libio/iovfscanf.c @@ -0,0 +1,784 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* + * 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, 1993. + Changes copyright Free Software Foundation 1992, 1993. */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <libioP.h> +#include <ctype.h> +#ifdef __STDC__ +#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 */ +#define WIDTH 0x40 /* width */ + +/* + * 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 u_long strtoul __P((const char*, char**, int)); +extern long strtol __P((const char*, char**, int)); +static const u_char *__sccl __P((char *tab, const u_char *fmt)); +#ifndef USE_DTOA +extern double atof(); +#endif + +/* If errp != NULL, *errp|=1 if we see a premature EOF; + *errp|=2 if we an invalid character. */ + +int +_IO_vfscanf(fp, fmt0, ap, errp) + register _IO_FILE *fp; + char const *fmt0; + _IO_va_list ap; + int *errp; +{ + register const u_char *fmt = (const u_char *)fmt0; + register int c; /* character from format, or conversion */ + register _IO_ssize_t width; /* field width, or 0 */ + register char *p; /* points into all kinds of strings */ + register int n; /* handy integer */ + register int flags = 0; /* 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) __P((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 = _IO_getc(fp); + if (c == EOF) { + seen_eof++; + break; + } + if (!isspace(c)) { + _IO_ungetc (c, fp); + 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 = _IO_getc(fp); + if (n == EOF) + goto eof_failure; + if (n != c) { + _IO_ungetc (n, fp); + goto match_failure; + } + nread++; + continue; + + case '*': + if (flags) goto control_failure; + flags = SUPPRESS; + goto again; + case 'l': + if (flags & ~(SUPPRESS | WIDTH)) goto control_failure; + flags |= LONG; + goto again; + case 'L': + if (flags & ~(SUPPRESS | WIDTH)) goto control_failure; + flags |= LONGDBL; + goto again; + case 'h': + if (flags & ~(SUPPRESS | WIDTH)) goto control_failure; + flags |= SHORT; + goto again; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (flags & ~(SUPPRESS | WIDTH)) goto control_failure; + flags |= WIDTH; + 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 (_IO_peekc(fp) == EOF) + goto eof_failure; + + /* + * Consume leading white space, except for formats + * that suppress this. + */ + if ((flags & NOSKIP) == 0) { + n = (unsigned char)*fp->_IO_read_ptr; + while (isspace(n)) { + fp->_IO_read_ptr++; + nread++; + n = _IO_peekc(fp); + 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) { + _IO_size_t sum = 0; + for (;;) { + n = fp->_IO_read_end - fp->_IO_read_ptr; + if (n < (int)width) { + sum += n; + width -= n; + fp->_IO_read_ptr += n; + if (__underflow(fp) == EOF) + if (sum == 0) + goto eof_failure; + else { + seen_eof++; + break; + } + } else { + sum += width; + fp->_IO_read_ptr += width; + break; + } + } + nread += sum; + } else { + _IO_size_t r = + (*fp->_jumps->__xsgetn)(fp, + (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)*fp->_IO_read_ptr]) { + n++, fp->_IO_read_ptr++; + if (--width == 0) + break; + if (_IO_peekc(fp) == 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)*fp->_IO_read_ptr]) { + *p++ = *fp->_IO_read_ptr++; + if (--width == 0) + break; + if (_IO_peekc(fp) == 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)*fp->_IO_read_ptr)) { + n++, fp->_IO_read_ptr++; + if (--width == 0) + break; + if (_IO_peekc(fp) == EOF) { + seen_eof++; + break; + } + } + nread += n; + } else { + p0 = p = va_arg(ap, char *); + while (!isspace((unsigned char)*fp->_IO_read_ptr)) { + *p++ = *fp->_IO_read_ptr++; + if (--width == 0) + break; + if (_IO_peekc(fp) == 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)*fp->_IO_read_ptr; + /* + * 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; + fp->_IO_read_ptr++; + if (_IO_peekc(fp) == 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) _IO_ungetc(*(u_char *)--p, fp); + goto match_failure; + } + c = ((u_char *)p)[-1]; + if (c == 'x' || c == 'X') { + --p; + (void) _IO_ungetc (c, fp); + } + 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)*fp->_IO_read_ptr; + /* + * 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; + fp->_IO_read_ptr++; + if (_IO_peekc(fp) == 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) + _IO_ungetc (*(u_char *)--p, fp); + goto match_failure; + } + /* just a bad exponent (e and maybe sign) */ + c = *(u_char *)--p; + if (c != 'e' && c != 'E') { + (void) _IO_ungetc (c, fp);/* sign */ + c = *(u_char *)--p; + } + (void) _IO_ungetc (c, fp); + } + if ((flags & SUPPRESS) == 0) { + double res; + *p = 0; +#ifdef USE_DTOA + res = _IO_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; +control_failure: +match_failure: + if (errp) + *errp |= 2; +done: + if (errp && seen_eof) + *errp |= 1; + 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(tab, fmt) + 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 */ +} diff --git a/gnu/lib/libg++/libio/isgetline.cc b/gnu/lib/libg++/libio/isgetline.cc new file mode 100644 index 0000000..87722af --- /dev/null +++ b/gnu/lib/libg++/libio/isgetline.cc @@ -0,0 +1,140 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include <libioP.h> +#include "iostream.h" +#include <string.h> + +istream& istream::getline(char* buf, int len, char delim) +{ + _gcount = 0; + if (len <= 0) + { + set(ios::failbit); + return *this; + } + int ch; + if (ipfx1()) + { + streambuf *sb = rdbuf(); + _gcount = _IO_getline(sb, buf, len - 1, delim, -1); + ch = sb->sbumpc(); + if (ch == EOF) + set (_gcount == 0 ? (ios::failbit|ios::eofbit) : ios::eofbit); + else if (ch != (unsigned char) delim) + { + set(ios::failbit); + sb->sungetc(); // Leave delimiter unread. + } + } + else + ch = EOF; + buf[_gcount] = '\0'; + if (ch == (unsigned char)delim) + _gcount++; // The delimiter is counted in the gcount(). + return *this; +} + +istream& istream::get(char* buf, int len, char delim) +{ + _gcount = 0; + if (len <= 0) + { + set(ios::failbit); + return *this; + } + if (ipfx1()) + { + streambuf *sbuf = rdbuf(); + long count = _IO_getline(sbuf, buf, len - 1, delim, -1); + if (count == 0 && sbuf->sgetc() == EOF) + set(ios::failbit|ios::eofbit); + else + _gcount = count; + } + buf[_gcount] = '\0'; + return *this; +} + + +// 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]; + char *ptr; + int ch; + + _IO_size_t count = _IO_getline(sb, buf, CHUNK_SIZE, terminator, -1); + 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 & _IO_EOF_SEEN) { + set(ios::eofbit); + if (_gcount == 0) + set(ios::failbit); + } + } + else { + _gcount = 0; + *s = NULL; + } + return *this; +} diff --git a/gnu/lib/libg++/libio/isgetsb.cc b/gnu/lib/libg++/libio/isgetsb.cc new file mode 100644 index 0000000..2c5397f --- /dev/null +++ b/gnu/lib/libg++/libio/isgetsb.cc @@ -0,0 +1,59 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" +#include "iostream.h" +#include <string.h> + +istream& istream::get(streambuf& sb, char delim /* = '\n' */) +{ + _gcount = 0; + if (ipfx1()) + { + register streambuf* isb = rdbuf(); + for (;;) + { + streamsize len = isb->_IO_read_end - isb->_IO_read_ptr; + if (len <= 0) + if (__underflow(isb) == EOF) + break; + else + len = isb->_IO_read_end - isb->_IO_read_ptr; + char *delimp = (char*)memchr((void*)isb->_IO_read_ptr, delim, len); + if (delimp != NULL) + len = delimp - isb->_IO_read_ptr; + int written = sb.sputn(isb->_IO_read_ptr, len); + isb->_IO_read_ptr += written; + _gcount += written; + if (written != len) + { + set(ios::failbit); + break; + } + if (delimp != NULL) + break; + } + } + return *this; +} diff --git a/gnu/lib/libg++/libio/isscan.cc b/gnu/lib/libg++/libio/isscan.cc new file mode 100644 index 0000000..4e4ef83 --- /dev/null +++ b/gnu/lib/libg++/libio/isscan.cc @@ -0,0 +1,45 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" +#include <iostream.h> +#include <stdarg.h> + +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, _IO_va_list args) +{ + if (ipfx0()) + _strbuf->vscan(format, args, this); + return *this; +} diff --git a/gnu/lib/libg++/libio/osform.cc b/gnu/lib/libg++/libio/osform.cc new file mode 100644 index 0000000..b4d4999 --- /dev/null +++ b/gnu/lib/libg++/libio/osform.cc @@ -0,0 +1,54 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" +#include <iostream.h> +#include <stdarg.h> + +ostream& ostream::form(const char *format ...) +{ + if (opfx()) { + va_list ap; + va_start(ap, format); + _IO_vfprintf(rdbuf(), format, ap); + va_end(ap); + } + return *this; +} + +ostream& ostream::vform(const char *format, _IO_va_list args) +{ + if (opfx()) + _IO_vfprintf(rdbuf(), format, args); + return *this; +} + +ostream& ostream::operator<<(const void *p) +{ + if (opfx()) { + form("%p", p); + osfx(); + } + return *this; +} diff --git a/gnu/lib/libg++/libio/outfloat.c b/gnu/lib/libg++/libio/outfloat.c new file mode 100644 index 0000000..7f4559b --- /dev/null +++ b/gnu/lib/libg++/libio/outfloat.c @@ -0,0 +1,209 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.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 _IO_outfloat(value, sb, type, width, precision, flags, + sign_mode, fill) + double value; + _IO_FILE *sb; + int type; + int width; + int precision; + int flags; + int sign_mode; + int fill; +{ + int count = 0; +#define PUT(x) do {if (_IO_putc(x, sb) < 0) goto error; count++;} while (0) +#define PUTN(p, n) \ + do {int _n=n; count+=_n; if (_IO_sputn(sb, p,_n) != _n) goto error;} while(0) +#define PADN(fill, n) \ + do {int _n = n; count+=_n; if (_IO_padn(sb, fill, _n) != _n) goto error;} while (0) + int pad_kind = flags & (_IO_LEFT|_IO_RIGHT|_IO_INTERNAL); + int skip_zeroes = 0; + int show_dot = (flags & _IO_SHOWPOINT) != 0; + int decpt; + int sign; + int mode; + int exponent_size; + int print_sign; + int trailing_zeroes, useful_digits; + int padding, unpadded_width; + char *p; + char *exponent_start; + register int i; +#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 & _IO_SHOWPOINT)) + skip_zeroes = 1; + type = 'g'; + mode = 2; + break; + } + /* Do the actual convension */ + if (precision == 999 && mode != 3) + mode = 0; + p = _IO_dtoa(value, mode, precision, &decpt, &sign, &end); + useful_digits = end-p; + 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; + } + } + 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). */ + 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; + 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). */ + unpadded_width = + (print_sign != 0) + trailing_zeroes + exponent_size + show_dot + + useful_digits + + (decpt > useful_digits ? decpt - useful_digits + : decpt > 0 ? 0 : 1 - decpt); + + padding = width > unpadded_width ? width - unpadded_width : 0; + if (padding > 0 && pad_kind != _IO_LEFT && pad_kind != _IO_INTERNAL) + PADN(fill, padding); /* Default (right) adjust */ + if (print_sign) + PUT(print_sign); + if (pad_kind == _IO_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 == _IO_LEFT && padding > 0) /* Left adjustment*/ + PADN(fill, padding); + return count; + error: + return EOF; +} diff --git a/gnu/lib/libg++/libio/parsestream.cc b/gnu/lib/libg++/libio/parsestream.cc new file mode 100644 index 0000000..3e986e3 --- /dev/null +++ b/gnu/lib/libg++/libio/parsestream.cc @@ -0,0 +1,317 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. + +Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "libioP.h" +#include "parsestream.h" +#include <stdlib.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 +} diff --git a/gnu/lib/libg++/libio/pfstream.cc b/gnu/lib/libg++/libio/pfstream.cc new file mode 100644 index 0000000..3dfa16f --- /dev/null +++ b/gnu/lib/libg++/libio/pfstream.cc @@ -0,0 +1,92 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "libioP.h" +#include <pfstream.h> +#include <procbuf.h> + +ipfstream::ipfstream(const char *name, int mode, int prot) +{ + const char* p; + + // Look for '| command' (as used by ftp). + for (p = name; *p == ' ' || *p == '\t'; p++) ; + if (*p == '|') { + procbuf *pbuf = new procbuf(); + init(pbuf); + if (!pbuf->open(p+1, mode)) + set(ios::badbit); + return; + } + + // Look for 'command |' + while (*p) p++; // Point to last + while (p[-1] == ' ' || p[-1] == '\t' || p[-1] == '\n') p--; + if (p[-1] == '|') { + // Must remove the final '|'. + p--; +#if !defined (__GNUC__) || defined (__STRICT_ANSI__) + char *command = new char[p-name+1]; +#else + char command[p-name+1]; +#endif + memcpy(command, name, p-name); + command[p-name] = '\0'; + + procbuf *pbuf = new procbuf(); + if (pbuf->open(command, mode)) + set(ios::badbit); +#if !defined (__GNUC__) || defined (__STRICT_ANSI__) + delete command; +#endif + return; + } + + init(new filebuf()); + if (!rdbuf()->open(name, mode, prot)) + set(ios::badbit); +} + +opfstream::opfstream(const char *name, int mode, int prot) +{ + const char *p; + // Look for '| command'. + for (p = name; *p == ' ' || *p == '\t'; p++) ; + if (*p == '|') { + procbuf *pbuf = new procbuf(); + init(pbuf); + if (!pbuf->open(p+1, mode)) + set(ios::badbit); + } + else { + init(new filebuf()); + if (!rdbuf()->open(name, mode, prot)) + set(ios::badbit); + } +} diff --git a/gnu/lib/libg++/libio/procbuf.cc b/gnu/lib/libg++/libio/procbuf.cc new file mode 100644 index 0000000..797bf48 --- /dev/null +++ b/gnu/lib/libg++/libio/procbuf.cc @@ -0,0 +1,51 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#define _POSIX_SOURCE +#include "libioP.h" +#include "procbuf.h" + +procbuf::procbuf(const char *command, int mode) : filebuf() +{ + _IO_proc_open(this, command, (mode & ios::in) ? "r" : "w"); +} + +procbuf *procbuf::open(const char *command, int mode) +{ + return (procbuf*)_IO_proc_open(this, command, (mode & ios::in) ? "r" : "w"); +} + +/* #define USE_SIGMASK */ + +int procbuf::sys_close() +{ + return _IO_proc_close(this); +} + +procbuf::~procbuf() +{ + close(); +} diff --git a/gnu/lib/libg++/libio/sbform.cc b/gnu/lib/libg++/libio/sbform.cc new file mode 100644 index 0000000..42f91e3 --- /dev/null +++ b/gnu/lib/libg++/libio/sbform.cc @@ -0,0 +1,40 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" +#include "streambuf.h" +#include <stdarg.h> + +int streambuf::vform(char const *fmt0, _IO_va_list ap) +{ + return _IO_vfprintf(this, fmt0, ap); +} +int streambuf::form(char const *format ...) +{ + va_list ap; + va_start(ap, format); + int count = _IO_vfprintf(this, format, ap); + va_end(ap); + return count; +} diff --git a/gnu/lib/libg++/libio/sbgetline.cc b/gnu/lib/libg++/libio/sbgetline.cc new file mode 100644 index 0000000..f8ee260 --- /dev/null +++ b/gnu/lib/libg++/libio/sbgetline.cc @@ -0,0 +1,31 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" +#include "streambuf.h" + +long streambuf::sgetline(char* buf, _IO_size_t n, char delim, int extract_delim) +{ + return _IO_getline(this, buf, n, delim, extract_delim); +} diff --git a/gnu/lib/libg++/libio/sbscan.cc b/gnu/lib/libg++/libio/sbscan.cc new file mode 100644 index 0000000..d9af571 --- /dev/null +++ b/gnu/lib/libg++/libio/sbscan.cc @@ -0,0 +1,45 @@ + +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "libioP.h" +#include "streambuf.h" +#include <stdarg.h> + +int streambuf::vscan(char const *fmt0, _IO_va_list ap, ios* stream /* = NULL*/) +{ + int errcode = 0; + int count = _IO_vfscanf(this, fmt0, ap, &errcode); + if (stream) + stream->setstate((ios::iostate)errcode); + return count; +} +int streambuf::scan(char const *format ...) +{ + va_list ap; + va_start(ap, format); + int count = _IO_vfscanf(this, format, ap, NULL); + va_end(ap); + return count; +} diff --git a/gnu/lib/libg++/libio/stdiostream.cc b/gnu/lib/libg++/libio/stdiostream.cc new file mode 100644 index 0000000..eb3dd16 --- /dev/null +++ b/gnu/lib/libg++/libio/stdiostream.cc @@ -0,0 +1,146 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include <stdiostream.h> +#include "libioP.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); +} + +stdiobuf::~stdiobuf() +{ + /* Only needed if we're buffered. Not buffered is the default. */ + _IO_do_flush((_IO_FILE*)this); +} + +streamsize stdiobuf::sys_read(char* buf, streamsize size) +{ + return fread(buf, 1, size, _file); +} + +streamsize stdiobuf::sys_write(const char *buf, streamsize n) +{ + _IO_ssize_t count = fwrite(buf, 1, n, _file); + if (_offset >= 0) + _offset += n; + return count; +} + +streampos stdiobuf::sys_seek(streamoff 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 (_IO_do_flush((_IO_FILE*)this)) + return EOF; + if (!(xflags() & _IO_NO_WRITES)) + if (fflush(_file)) + return EOF; + return 0; +} + +int stdiobuf::overflow(int c /* = EOF*/) +{ + if (filebuf::overflow(c) == EOF) + return EOF; + if (c != EOF) + return c; + return fflush(_file); +} + +streamsize stdiobuf::xsputn(const char* s, streamsize n) +{ + if (buffered ()) + { + // The filebuf implementation of sputn loses. + return streambuf::xsputn(s, n); + } + else + return fwrite (s, 1, n, _file); +} + +void stdiobuf::buffered (int b) +{ + if (b) + { + if (_flags & _IO_UNBUFFERED) + { /* Was unbuffered, make it buffered. */ + _flags &= ~_IO_UNBUFFERED; + } + } + else + { + if (!(_flags & _IO_UNBUFFERED)) + { /* Was buffered, make it unbuffered. */ + setbuf(NULL, 0); + } + } +} diff --git a/gnu/lib/libg++/libio/stdstrbufs.cc b/gnu/lib/libg++/libio/stdstrbufs.cc new file mode 100644 index 0000000..6598c1f --- /dev/null +++ b/gnu/lib/libg++/libio/stdstrbufs.cc @@ -0,0 +1,89 @@ +/* +Copyright (C) 1994 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + + +/* This file provides definitions of _IO_stdin, _IO_stdout, and _IO_stderr + for C++ code. Compare stdfiles.c. + (The difference is that here the vtable field is set to + point to builtinbuf's vtable, so the objects are effectively + of class builtinbuf.) */ + +#include "libioP.h" +#include <stdio.h> + +#ifndef STD_VTABLE +#define STD_VTABLE builtinbuf_vtable +#endif + +#define DEF_STDFILE(NAME, FD, CHAIN, FLAGS) \ + struct _IO_FILE_plus NAME = {FILEBUF_LITERAL(CHAIN, FLAGS, FD), STD_VTABLE} + +DEF_STDFILE(_IO_stdin_, 0, 0, _IO_NO_WRITES); +DEF_STDFILE(_IO_stdout_, 1, &_IO_stdin_.file, _IO_NO_READS); +DEF_STDFILE(_IO_stderr_, 2, &_IO_stdout_.file, + _IO_NO_READS+_IO_UNBUFFERED); + +#ifdef _STDIO_USES_IOSTREAM +_IO_FILE *_IO_list_all = &_IO_stderr_.file; +#else /* !_STDIO_USES_IOSTREAM */ +#include "stdiostream.h" + +struct _IO_fake_stdiobuf { + _IO_FILE file; + const void *vtable; + FILE *stdio_file; +}; + +/* Define stdiobuf_vtable as a name for the virtual function table + of the stdiobuf class. */ +#ifndef stdiobuf_vtable +#ifdef __GNUC__ +extern char stdiobuf_vtable[] + asm (_G_VTABLE_LABEL_PREFIX +#if _G_VTABLE_LABEL_HAS_LENGTH + "8" +#endif + "stdiobuf"); +#else /* !__GNUC__ */ +#if _G_VTABLE_LABEL_HAS_LENGTH +#define stdiobuf_vtable _G_VTABLE_LABEL_PREFIX_ID##8stdiobuf +#else +#define stdiobuf_vtable _G_VTABLE_LABEL_PREFIX_ID##stdiobuf +#endif +extern char stdiobuf_vtable[]; +#endif /* !__GNUC__ */ +#endif /* !stdiobuf_vtable */ + +#define DEF_STDIOFILE(NAME, FD, FILE, FLAGS, CHAIN) \ + struct _IO_fake_stdiobuf NAME = \ + {{ _IO_MAGIC+_IO_LINKED+_IO_IS_FILEBUF+_IO_UNBUFFERED+FLAGS, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAIN, &_IO_streambuf_jumps, FD},\ + stdiobuf_vtable, FILE} + +DEF_STDIOFILE(_IO_stdin_buf, 0, stdin, _IO_NO_WRITES, &_IO_stderr_.file); +DEF_STDIOFILE(_IO_stdout_buf, 1, stdout, _IO_NO_READS, &_IO_stdin_buf.file); +DEF_STDIOFILE(_IO_stderr_buf, 2, stderr, _IO_NO_READS, &_IO_stdout_buf.file); + +_IO_FILE *_IO_list_all = &_IO_stderr_buf.file; +#endif /* !_STDIO_USES_IOSTREAM */ diff --git a/gnu/lib/libg++/libio/stdstreams.cc b/gnu/lib/libg++/libio/stdstreams.cc new file mode 100644 index 0000000..18055a7 --- /dev/null +++ b/gnu/lib/libg++/libio/stdstreams.cc @@ -0,0 +1,143 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#include "libioP.h" +#include "streambuf.h" +#include <stdio.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 _IO_stdin/_IO_stdout/_IO_stderr. + +#include "libio.h" + +#ifdef _STDIO_USES_IOSTREAM +#define CIN_SBUF _IO_stdin_ +#define COUT_SBUF _IO_stdout_ +#define CERR_SBUF _IO_stderr_ +static int use_stdiobuf = 0; +#else +#define CIN_SBUF _IO_stdin_buf +#define COUT_SBUF _IO_stdout_buf +#define CERR_SBUF _IO_stderr_buf +static int use_stdiobuf = 1; +#endif + +#define cin CIN +#define cout COUT +#define cerr CERR +#define clog CLOG +#include "iostream.h" +#undef cin +#undef cout +#undef cerr +#undef clog + +#ifdef __GNUG__ +#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 */ + _IO_ssize_t _gcount; +#else + /* This is supposedly correct for cfront. */ + _IO_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(NAME, SBUF, TIE, EXTRA_FLAGS) \ + _fake_ostream NAME = { {&NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }}; +#define ISTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS) \ + _fake_istream NAME = { {&NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }}; +#else +#define OSTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS) \ + _fake_ostream NAME = { {0, &NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS) }}; +#define ISTREAM_DEF(NAME, SBUF, TIE, EXTRA_FLAGS) \ + _fake_istream NAME = {{0, 0, &NAME.base}, {STD_STR(SBUF, TIE, EXTRA_FLAGS)}}; +#endif + +OSTREAM_DEF(cout, COUT_SBUF, NULL, 0) +OSTREAM_DEF(cerr, CERR_SBUF,(ostream*)&cout, ios::unitbuf) +ISTREAM_DEF(cin, CIN_SBUF, (ostream*)&cout, 0) + +/* Only for (partial) compatibility with AT&T's library. */ +OSTREAM_DEF(clog, CERR_SBUF, (ostream*)&cout, 0) + +// Switches between using _IO_std{in,out,err} and __std{in,out,err}_buf +// for standard streams. This does not normally need to be called +// explicitly, 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) { + cin.base._strbuf = (streambuf*)&_IO_stdin_buf; + cout.base._strbuf = (streambuf*)&_IO_stdout_buf; + cerr.base._strbuf = (streambuf*)&_IO_stderr_buf; + clog.base._strbuf = (streambuf*)&_IO_stderr_buf; + } else { + cin.base._strbuf = (streambuf*)_IO_stdin; + cout.base._strbuf = (streambuf*)_IO_stdout; + cerr.base._strbuf = (streambuf*)_IO_stderr; + clog.base._strbuf = (streambuf*)_IO_stderr; + } + int old_state = use_stdiobuf; + use_stdiobuf = new_state; + return old_state; +#endif +} diff --git a/gnu/lib/libg++/libio/stream.cc b/gnu/lib/libg++/libio/stream.cc new file mode 100644 index 0000000..543071c --- /dev/null +++ b/gnu/lib/libg++/libio/stream.cc @@ -0,0 +1,144 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include <stdarg.h> +#include "libioP.h" +#include "stream.h" +#include "strstream.h" + +static char Buffer[_IO_BUFSIZ]; +#define EndBuffer (Buffer+_IO_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 < (_IO_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); +} diff --git a/gnu/lib/libg++/libio/streambuf.cc b/gnu/lib/libg++/libio/streambuf.cc new file mode 100644 index 0000000..a484572 --- /dev/null +++ b/gnu/lib/libg++/libio/streambuf.cc @@ -0,0 +1,341 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1991, 1992, 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#define _STREAM_COMPAT +#ifdef __GNUG__ +#pragma implementation +#endif +#include "iostreamP.h" +#include <string.h> +#include <stdarg.h> +#include <errno.h> +#ifndef errno +extern int errno; +#endif + +void streambuf::_un_link() { _IO_un_link(this); } + +void streambuf::_link_in() { _IO_link_in(this); } + +int streambuf::switch_to_get_mode() +{ return _IO_switch_to_get_mode(this); } + +void streambuf::free_backup_area() +{ _IO_free_backup_area(this); } + +#if 0 +int streambuf::switch_to_put_mode() +{ return _IO_:switch_to_put_mode(this); } +#endif + +int __overflow(streambuf* sb, int c) +{ + return sb->overflow(c); +} + +int streambuf::underflow() +{ return EOF; } + +int streambuf::overflow(int c /* = EOF */) +{ return EOF; } + +streamsize streambuf::xsputn(register const char* s, streamsize n) +{ return _IO_default_xsputn(this, s, n); } + +streamsize streambuf::xsgetn(char* s, streamsize n) +{ return _IO_default_xsgetn(this, s, n); } + +int streambuf::ignore(int n) +{ + register int more = n; + for (;;) { + int count = _IO_read_end - _IO_read_ptr; // Data available. + if (count > 0) { + if (count > more) + count = more; + _IO_read_ptr += count; + more -= count; + } + if (more == 0 || __underflow(this) == EOF) + break; + } + return n - more; +} + +int streambuf::sync() +{ + if (pptr() == pbase()) + return 0; + return EOF; +} + +int streambuf::pbackfail(int c) +{ + return _IO_default_pbackfail(this, 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); +} + +streampos streambuf::sseekpos(streampos pos, int mode) +{ + return _IO_seekpos (this, pos, convert_to_seekflags (0, mode)); +} + +void streambuf::setb(char* b, char* eb, int a) +{ _IO_setb(this, b, eb, a); } + +int streambuf::doallocate() { return _IO_default_doallocate(this); } + +void streambuf::doallocbuf() { _IO_doallocbuf(this); } + +/* The following are jump table entries that just call the virtual method */ + +static int _IO_sb_overflow(_IO_FILE *fp, int c) +{ return ((streambuf*)fp)->overflow(c); } +static int _IO_sb_underflow(_IO_FILE *fp) +{ return ((streambuf*)fp)->underflow(); } +static _IO_size_t _IO_sb_xsputn(_IO_FILE *fp, const void *s, _IO_size_t n) +{ return ((streambuf*)fp)->xsputn((const char*)s, n); } +static _IO_size_t _IO_sb_xsgetn(_IO_FILE *fp, void *s, _IO_size_t n) +{ return ((streambuf*)fp)->xsgetn((char*)s, n); } +static int _IO_sb_close(_IO_FILE *fp) +{ return ((streambuf*)fp)->sys_close(); } +static int _IO_sb_stat(_IO_FILE *fp, void *b) +{ return ((streambuf*)fp)->sys_stat(b); } +static int _IO_sb_doallocate(_IO_FILE *fp) +{ return ((streambuf*)fp)->doallocate(); } + +static _IO_pos_t _IO_sb_seekoff(_IO_FILE *fp, _IO_off_t pos, _IO_seekflags m) +{ + int mode = ((m & _IO_seek_not_in) ? 0 : ios::in) + + ((m & _IO_seek_not_out) ? 0 : ios::out); + return ((streambuf*)fp)->seekoff(pos, (_seek_dir)((int)m & 3), mode); +} + +static _IO_pos_t _IO_sb_seekpos(_IO_FILE *fp, _IO_pos_t pos, _IO_seekflags m) +{ + int mode = ((m & _IO_seek_not_in) ? 0 : ios::in) + + ((m & _IO_seek_not_out) ? 0 : ios::out); + return ((streambuf*)fp)->seekpos(pos, mode); +} + +static int _IO_sb_pbackfail(_IO_FILE *fp, int ch) +{ return ((streambuf*)fp)->pbackfail(ch); } +static void _IO_sb_finish(_IO_FILE *fp) +{ ((streambuf*)fp)->~streambuf(); } +static _IO_ssize_t _IO_sb_read(_IO_FILE *fp, void *buf, _IO_ssize_t n) +{ return ((streambuf*)fp)->sys_read((char*)buf, n); } +static _IO_ssize_t _IO_sb_write(_IO_FILE *fp, const void *buf, _IO_ssize_t n) +{ return ((streambuf*)fp)->sys_write((const char*)buf, n); } +static int _IO_sb_sync(_IO_FILE *fp) +{ return ((streambuf*)fp)->sync(); } +static _IO_pos_t _IO_sb_seek(_IO_FILE *fp, _IO_off_t off, int dir) +{ return ((streambuf*)fp)->sys_seek(off, (_seek_dir)dir); } +static int _IO_sb_setbuf(_IO_FILE *fp, char *buf, _IO_ssize_t n) +{ return ((streambuf*)fp)->setbuf(buf, n) == NULL ? EOF : 0; } + +/* This callbacks in this jumptable just call the corresponding + virtual function, so that C functions can access (potentially user-defined) + streambuf-derived objects. + Contrast the builtinbuf class, which does the converse: Allow + C++ virtual calls to to be used on _IO_FILE objects that are builtin + (or defined by C code). */ + + +struct _IO_jump_t _IO_streambuf_jumps = { + _IO_sb_overflow, + _IO_sb_underflow, + _IO_sb_xsputn, + _IO_sb_xsgetn, + _IO_sb_read, + _IO_sb_write, + _IO_sb_doallocate, + _IO_sb_pbackfail, + _IO_sb_setbuf, + _IO_sb_sync, + _IO_sb_finish, + _IO_sb_close, + _IO_sb_stat, + _IO_sb_seek, + _IO_sb_seekoff, + _IO_sb_seekpos, + _IO_default_uflow +}; + +streambuf::streambuf(int flags) +{ + _IO_init(this, flags); + _jumps = &_IO_streambuf_jumps; +} + +streambuf::~streambuf() { _IO_default_finish(this); } + +streampos +streambuf::seekoff(streamoff, _seek_dir, int mode /*=ios::in|ios::out*/) +{ + return EOF; +} + +streampos +streambuf::sseekoff(streamoff o , _seek_dir d, int m /*=ios::in|ios::out*/) +{ + return _IO_seekoff (this, o, convert_to_seekflags (d, m)); +} + +int streambuf::sputbackc(char c) +{ + return _IO_sputbackc(this, c); +} + +int streambuf::sungetc() +{ + return _IO_sungetc(this); +} + +#if 0 /* Work in progress */ +void streambuf::collumn(int c) +{ + if (c == -1) + _collumn = -1; + else + _collumn = c - (_IO_write_ptr - _IO_write_base); +} +#endif + + +int streambuf::get_column() +{ + if (_cur_column) + return _IO_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() { return _IO_flush_all (); } + +void streambuf::flush_all_linebuffered() +{ _IO_flush_all_linebuffered(); } + +int streambuf::sys_stat(void *) +{ +#ifdef EIO + errno = EIO; +#endif + return -1; +} + +streamsize streambuf::sys_read(char* buf, streamsize size) +{ + return 0; +} + +streamsize streambuf::sys_write(const char* buf, streamsize size) +{ + return 0; +} + +streampos streambuf::sys_seek(streamoff, _seek_dir) +{ + return EOF; +} + +int streambuf::sys_close() { return 0; /* Suceess; do nothing */ } + +streammarker::streammarker(streambuf *sb) +{ + _IO_init_marker(this, sb); +} + +streammarker::~streammarker() +{ + _IO_remove_marker(this); +} + +#define BAD_DELTA EOF + +int streammarker::delta(streammarker& other_mark) +{ + return _IO_marker_difference(this, &other_mark); +} + +int streammarker::delta() +{ + return _IO_marker_delta(this); +} + +int streambuf::seekmark(streammarker& mark, int delta /* = 0 */) +{ + return _IO_seekmark(this, &mark, delta); +} + +void streambuf::unsave_markers() +{ + _IO_unsave_markers(this); +} + +int ios::readable() { return !(rdbuf()->_flags & _IO_NO_READS); } +int ios::writable() { return !(rdbuf()->_flags & _IO_NO_WRITES); } +int ios::is_open() { return rdbuf() + && (rdbuf()->_flags & _IO_NO_READS+_IO_NO_WRITES) + != _IO_NO_READS+_IO_NO_WRITES; } + +#if defined(linux) +#define IO_CLEANUP +#endif + +#ifdef IO_CLEANUP + IO_CLEANUP +#else +struct __io_defs { + ~__io_defs() { _IO_cleanup (); } +}; +__io_defs io_defs__; +#endif diff --git a/gnu/lib/libg++/libio/strops.c b/gnu/lib/libg++/libio/strops.c new file mode 100644 index 0000000..f507343 --- /dev/null +++ b/gnu/lib/libg++/libio/strops.c @@ -0,0 +1,292 @@ +/* +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +#include "strfile.h" +#include "libioP.h" +#include <string.h> + +#define LEN(fp) (((_IO_strfile*)(fp))->_s._len) + +#ifdef TODO +/* An "unbounded buffer" is when a buffer is supplied, but with no + specified length. An example is the buffer argument to sprintf. + */ +#endif + +void +_IO_str_init_static (fp, ptr, size, pstart) + _IO_FILE *fp; + 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 + int s; + 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. */ + for (s; 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 + } + _IO_setb(fp, ptr, ptr+size, 0); + + fp->_IO_write_base = ptr; + fp->_IO_read_base = ptr; + fp->_IO_read_ptr = ptr; + if (pstart) + { + fp->_IO_write_ptr = pstart; + fp->_IO_write_end = ptr+size; + fp->_IO_read_end = pstart; + } + else + { + fp->_IO_write_ptr = ptr; + fp->_IO_write_end = ptr; + fp->_IO_read_end = ptr+size; + } + LEN(fp) = size; + /* A null _allocate_buffer function flags the strfile as being static. */ + (((_IO_strfile*)(fp))->_s._allocate_buffer) = (_IO_alloc_type)0; +} + +void +_IO_str_init_readonly (fp, ptr, size) + _IO_FILE *fp; + const char *ptr; + int size; +{ + _IO_str_init_static (fp, (char*)ptr, size, NULL); + fp->_IO_file_flags |= _IO_NO_WRITES; +} + +int _IO_str_overflow (fp, c) + register _IO_FILE* fp; + int c; +{ + int flush_only = c == EOF; + _IO_size_t pos = fp->_IO_write_ptr - fp->_IO_write_base; + _IO_size_t get_pos = fp->_IO_read_ptr - fp->_IO_read_base; + if (fp->_flags & _IO_NO_WRITES) + return flush_only ? 0 : EOF; + if (pos > LEN(fp)) LEN(fp) = pos; + if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING)) + { + pos = get_pos; + fp->_flags |= _IO_CURRENTLY_PUTTING; + get_pos = LEN(fp); + } + if (pos >= _IO_blen(fp) + flush_only) + { + if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */ + { +#ifdef TODO + if (indefinite size) + { + fp->_IO_buf_end += 512; + } + else +#endif + return EOF; + } + else + { + char *new_buf; + _IO_size_t new_size = 2 * _IO_blen(fp); + new_buf + = (char*)(*((_IO_strfile*)fp)->_s._allocate_buffer)(new_size); + if (new_buf == NULL) + { + /* __ferror(fp) = 1; */ + return EOF; + } + memcpy(new_buf, fp->_IO_buf_base, _IO_blen(fp)); +#if 0 + if (lenp == &LEN(fp)) /* use '\0'-filling */ + memset(new_buf + pos, 0, blen() - pos); +#endif + if (fp->_IO_buf_base) + { + (*((_IO_strfile*)fp)->_s._free_buffer)(fp->_IO_buf_base); + /* Make sure _IO_setb won't try to delete _IO_buf_base. */ + fp->_IO_buf_base = NULL; + } + _IO_setb(fp, new_buf, new_buf + new_size, 1); + fp->_IO_write_base = new_buf; + } + fp->_IO_write_end = fp->_IO_buf_end; + } + + fp->_IO_write_ptr = fp->_IO_buf_base + pos; + + fp->_IO_read_base = fp->_IO_buf_base; + fp->_IO_read_ptr = fp->_IO_buf_base + get_pos;; + fp->_IO_read_end = fp->_IO_buf_base + LEN(fp);; + + if (!flush_only) + *fp->_IO_write_ptr++ = (unsigned char) c; + return c; +} + +int +_IO_str_underflow (fp) + register _IO_FILE* fp; +{ + _IO_size_t ppos = fp->_IO_write_ptr - fp->_IO_write_base; + if (ppos > LEN(fp)) LEN(fp) = ppos; + if ((fp->_flags & _IO_TIED_PUT_GET) && (fp->_flags & _IO_CURRENTLY_PUTTING)) + { + fp->_flags &= ~_IO_CURRENTLY_PUTTING; + fp->_IO_write_ptr = fp->_IO_write_end; + } + fp->_IO_read_end = fp->_IO_read_base + LEN(fp); + if (fp->_IO_read_ptr < fp->_IO_read_end) + return *fp->_IO_read_ptr; + else + return EOF; +} + +_IO_ssize_t +_IO_str_count (fp) + register _IO_FILE *fp; +{ + _IO_ssize_t put_len = fp->_IO_write_ptr - fp->_IO_write_base; + if (put_len < ((_IO_strfile*)fp)->_s._len) + put_len = ((_IO_strfile*)fp)->_s._len; + return put_len; +} + +_IO_pos_t +_IO_str_seekoff(fp, offset, mode) + register _IO_FILE *fp; + _IO_off_t offset; + _IO_seekflags mode; +{ + _IO_ssize_t cur_size = _IO_str_count(fp); + _IO_pos_t new_pos = EOF; + int dir = mode & 3; + + /* Move the get pointer, if requested. */ + if (!(mode & _IO_seek_not_in)) + { + switch (dir) + { + case _IO_seek_end: + offset += cur_size; + break; + case _IO_seek_cur: + offset += fp->_IO_read_ptr - fp->_IO_read_base; + break; + default: /* case _IO_seek_set: */ + break; + } + if (offset < 0 || (_IO_size_t)offset > cur_size) + return EOF; + fp->_IO_read_ptr = fp->_IO_read_base + offset; + fp->_IO_read_end = fp->_IO_read_base + cur_size; + new_pos = offset; + } + + /* Move the put pointer, if requested. */ + if (!(mode & _IO_seek_not_out)) + { + switch (dir) + { + case _IO_seek_end: + offset += cur_size; + break; + case _IO_seek_cur: + offset += fp->_IO_write_ptr - fp->_IO_write_base; + break; + default: /* case _IO_seek_set: */ + break; + } + if (offset < 0 || (_IO_size_t)offset > cur_size) + return EOF; + fp->_IO_write_ptr = fp->_IO_write_base + offset; + new_pos = offset; + } + return new_pos; +} + +int +_IO_str_pbackfail(fp, c) + register _IO_FILE *fp; + int c; +{ + if ((fp->_flags & _IO_NO_WRITES) && c != EOF) + return EOF; + return _IO_default_pbackfail(fp, c); +} + +void +_IO_str_finish(fp) + register _IO_FILE* fp; +{ + if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF)) + (((_IO_strfile*)fp)->_s._free_buffer)(fp->_IO_buf_base); + fp->_IO_buf_base = NULL; + + _IO_default_finish(fp); +} + +struct _IO_jump_t _IO_str_jumps = { + _IO_str_overflow, + _IO_str_underflow, + _IO_default_xsputn, + _IO_default_xsgetn, + _IO_default_read, + _IO_default_write, + _IO_default_doallocate, + _IO_str_pbackfail, + _IO_default_setbuf, + _IO_default_sync, + _IO_str_finish, + _IO_default_close, + _IO_default_stat, + _IO_default_seek, + _IO_str_seekoff, + _IO_default_seekpos, + _IO_default_uflow +}; diff --git a/gnu/lib/libg++/libio/strstream.cc b/gnu/lib/libg++/libio/strstream.cc new file mode 100644 index 0000000..c17d683 --- /dev/null +++ b/gnu/lib/libg++/libio/strstream.cc @@ -0,0 +1,133 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 1993 Free Software Foundation + +This file is part of the GNU IO Library. This library 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 2, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Per Bothner (bothner@cygnus.com). */ + +#ifdef __GNUG__ +#pragma implementation +#endif +#include "iostreamP.h" +#include "strstream.h" +#include <string.h> + +static void* default_alloc(_IO_size_t size) +{ + return (void*)new char[size]; +} + +static void default_free(void* ptr) +{ + delete [] (char*)ptr; +} + +/* Set to use the _IO_str_jump jumptable, for efficiency */ + +#define SET_STR_JUMPS(STRBUF) \ + (STRBUF)->_jumps = &_IO_str_jumps,\ + (STRBUF)->_vtable() = builtinbuf_vtable; + +istrstream::istrstream(const char *cp, int n) +{ + init(new strstreambuf(cp, n)); + SET_STR_JUMPS(_strbuf); +} + +ostrstream::ostrstream() +{ + init(new strstreambuf()); + SET_STR_JUMPS(_strbuf); +} + +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)); + SET_STR_JUMPS(_strbuf); +} + +char *strstreambuf::str() +{ + freeze(1); + return base(); +} + +_IO_ssize_t strstreambuf::pcount() { return _IO_str_count (this); } + +int strstreambuf::overflow(int c /* = EOF */) +{ + return _IO_str_overflow (this, c); +} + +int strstreambuf::underflow() +{ + return _IO_str_underflow(this); +} + + +void strstreambuf::init_dynamic(_IO_alloc_type alloc, _IO_free_type free, + int initial_size) + +{ + _s._len = 0; + if (initial_size < 16) + initial_size = 16; + _s._allocate_buffer = alloc ? alloc : default_alloc; + _s._free_buffer = free ? free : default_free; + char * buf = (char*)(*_s._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) +{ + _IO_str_init_static (this, ptr, size, pstart); +} + +void strstreambuf::init_readonly (const char *ptr, int size) +{ + _IO_str_init_readonly (this, ptr, size); +} + +strstreambuf::~strstreambuf() +{ + if (_IO_buf_base && !(_flags & _IO_USER_BUF)) + (_s._free_buffer)(_IO_buf_base); + _IO_buf_base = NULL; +} + +streampos strstreambuf::seekoff(streamoff off, _seek_dir dir, + int mode /*=ios::in|ios::out*/) +{ + return _IO_str_seekoff (this, off, convert_to_seekflags(dir, mode)); +} + +int strstreambuf::pbackfail(int c) +{ + return _IO_str_pbackfail (this, c); +} |