baud@GATECH.EDU (Kurt Baudendistel) (10/10/88)
BUG REPORT 14
BEHAVIOR:
fatal signal 4 received by compiler.
COMPILER VERSION: GNU C++ compiler driver, version 1.25.0
INPUT FILES:
Fix.cc
Fix.h
type.h
COMMAND LINE: g++ -v -g -c Fix.cc
/usr/local/lib/gcc-cpp+ -v -I . -I ./include -I /dsp/mcclellan/baud/c++/include -I /usr/local/lib/g++-include -undef -D__GNU__ -D__GNUG__ -Dvax -Dunix Fix.cc /tmp/cc013738.cpp
GNU CPP version 1.25.0
/usr/local/lib/gcc-c++ /tmp/cc013738.cpp -quiet -dumpbase Fix.cc -noreg -version -G -o /tmp/cc013738.s
g++: Program c++ got fatal signal 4.
FILE NAMES:
tm.h = tm-vax.h
md = vax.md
MACHINE: vax 11/780 with BRL UNIX (4.2 BSD)
SOURCE FILES:
----------------------------------------------------------------------------
#include <Fix.h>
#include <Obstack.h>
#include <std.h>
// default parameters
uint16 Fix_default_length = 16;
uint16 Fix_set_default_length(uint16 newlen)
{
uint16 oldlen = Fix_default_length;
Fix_default_length = newlen;
return oldlen;
}
// error handling
void default_Fix_error_handler(char* msg)
{
cerr << "Fatal Fix error. " << msg << "\n";
abort();
}
one_arg_error_handler_t Fix_error_handler = default_Fix_error_handler;
one_arg_error_handler_t set_Fix_error_handler(one_arg_error_handler_t f)
{
one_arg_error_handler_t old = Fix_error_handler;
Fix_error_handler = f;
return old;
}
void Fix::error(char* msg)
{
(*Fix_error_handler)(msg);
}
// compare two equal-length reps
inline static int docmp(uint16* x, uint16* y, int siz)
{
int diff = (int16 )*x - (int16 )*y;
while ( siz-- && !diff )
diff = (int32 )(uint32 )*++x - (int32 )(uint32 )*++y;
return diff;
}
// compare rep to zero
inline static int docmpz(uint16* x, int siz)
{
while ( siz-- )
if ( *x++ ) return 1;
return 0;
}
// allocate a new _Frep
static _Fix new_Frep(int len, _Fix x = NULL )
{
int siz = (len + 15) >> 4;
unsigned allocsiz = sizeof(_Frep) + (siz - 1) * sizeof(uint16);
_Fix z = (_Fix ) (malloc(allocsiz));
if (z == 0)
(*Fix_error_handler)("Out of memory.");
z->len = len;
z->siz = siz;
z->ref = 1;
if ( x != NULL )
{
uint16 *zs = z->s, *xs = x->s;
int imax = z->siz <? x->siz;
for ( int i=0; i < imax; i++ )
*zs++ = *xs++;
if ( imax != z->siz )
for ( ; i < z->siz; i++ )
*zs++ = 0;
mask(z);
}
return z;
}
// convert to a double
double Fix::operator double()
{
double d = 0.0;
for (int i = rep->siz - 1; i >= 0; --i)
{
d += rep->s[i];
d *= 1./32768.;
}
d *= 2.;
return d >= 1. ? d : d - 2.;
}
// comparison functions
int compare(Fix x, Fix y)
{
if ( x.rep->siz == y.rep->siz )
return docmp(x.rep->s, y.rep->s, x.rep->siz);
else
{
int r;
_Frep longer, shorter;
if ( x.rep->siz > y.rep->siz )
{
longer = x.rep;
shorter = y.rep;
r = 1;
}
else
{
longer = y.rep;
shorter = x.rep;
r = -1;
}
int diff = docmp(x.rep->s, y.rep->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 add(_Fix x, _Fix y, _Fix r)
{
_Fix longer, shorter;
if ( x->len >= y->len )
longer = x, shorter = y;
else
longer = y, shorter = x;
if ( r == NULL )
r = new_Frep(longer->len);
for ( int i=r->siz; i > longer->siz; i-- )
r->s[i] = 0;
for ( ; i > shorter->siz; i-- )
r->s[i] = longer->s[i];
uint32 carry = 0, sum;
for ( ; i >= 0; i-- )
{
sum = carry + longer->s[i] + shorter->s[i];
carry = sum >> 16;
r->s[i] = sum & _Fix_mask;
}
if ( (x->s[0] ^ sum) & (y->s[0] ^ sum) & _Fix_msb )
(*Fix_overflow_handler)(result);
return r;
}
_Fix subtract(_Fix x, _Fix y, _Fix r)
{
_Fix longer, shorter;
if ( x->len >= y->len )
longer = x, shorter = y;
else
longer = y, shorter = x;
if ( r == NULL )
r = new_Frep(longer->len);
for ( int i=r->siz; i > longer->siz; i-- )
r->s[i] = 0;
for ( ; i > shorter->siz; i-- )
r->s[i] = longer->s[i];
uint32 carry = 0, sum;
for ( ; i >= 0; i-- )
{
sum = carry + longer->s[i] - shorter->s[i];
carry = sum >> 16 ? _Fix_borrow: 0;
r->s[i] = sum & _Fix_mask;
}
if ( (x->s[0] ^ sum) & (y->s[0] ^ sum) & _Fix_msb )
(*Fix_overflow_handler)(result);
return r;
}
Fix operator * (Fix x, Fix y)
{
_Frep result(x.rep->len + y.rep->len - 1);
for ( int i=0; i < result->siz; i++ )
result->s[i] = 0;
for ( i=x.rep->siz; i >= 0; i-- )
{
int carry = 0;
for ( int j=y.rep->siz; j >= 0; j-- )
{
uint32 a = x.rep->s[i] * y.rep->s[i];
uint32 b = result->s[i+j+1] + ((a << 1) & 0xffff) + carry;
result->s[i+j+1] = b & 0xffff;
carry = ((a >> 15) & 0x1ffff) + (b >> 16);
}
result->s[i] = carry & 0xffff;
if ( carry >> 16 )
for ( int k=i-1; k >=0; k-- )
result->s[i]--;
}
return Fix(result);
}
//??
Fix shift(Fix x, int y)
{
int xl = x.rep->len;
if (xl == 0 || y == 0)
{
r = x;
return;
}
int xrsame = x.rep == r.rep;
int rsgn = x.rep->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;
r.setlength(rl);
r.rep->sgn = rsgn;
uint16* botr = r.rep->s;
uint16* botx = (xrsame)? botr : x.rep->s;
uint16* rs = &(botr[rl - 1]);
uint16* xs = &(botx[xl - 1]);
uint32 a = 0;
while (xs >= botx)
{
a = up(a) | ((uint32)(*xs--) << sw);
*rs-- = extract(down(a));
}
*rs-- = extract(a);
while (rs >= botr)
*rs-- = 0;
}
else
{
int rl = xl - bw;
if (rl <= 0)
r.copy(_Fix_Zero);
else
{
r.setlength(rl);
r.rep->sgn = rsgn;
int rw = I_SHIFT - sw;
uint16* rs = r.rep->s;
uint16* topr = &(rs[rl]);
uint16* botx = (xrsame)? rs : x.rep->s;
uint16* xs = &(botx[bw]);
uint16* topx = &(botx[xl]);
uint32 a = (uint32)(*xs++) >> sw;
while (xs < topx)
{
a |= (uint32)(*xs++) << rw;
*rs++ = extract(a);
a = down(a);
}
*rs++ = extract(a);
while (rs < topr)
*rs++ = 0;
}
}
r.checklength();
}
//??
Fix Fix::operator -()
{
Fix x;
x.copy(rep->s, rep->len, !rep->sgn);
return x;
}
extern Obstack _libgxx_io_ob;
extern char* _libgxx_io_oblast;
//??
char* Itoa(Fix x, int base = 10, int width = 0)
{
if (_libgxx_io_oblast) _libgxx_io_ob.free(_libgxx_io_oblast);
int wrksiz = (x.rep->len + 1) * I_SHIFT * 4 + 1 + width;
_libgxx_io_ob.blank(wrksiz);
_libgxx_io_oblast = (char*)(_libgxx_io_ob.finish());
char* obbase = _libgxx_io_oblast;
char* e = obbase + wrksiz - 1;
char* s = e;
*--s = 0;
int xsgn = sign(x);
if (xsgn == 0)
*--s = '0';
else
{
Fix z = abs(x);
// split division by base into two parts:
// first divide by biggest power of base that fits in an uint16,
// then use straight signed div/mods from there.
// find power
int bpower = 1;
uint16 b = base;
uint16 maxb = I_MAXNUM / base;
while (b < maxb)
{
b *= base;
++bpower;
}
int rem;
for(;;)
{
divide(z, b, z, rem);
if (z.rep->len == 0)
{
while (rem != 0)
{
char ch = rem % base;
rem /= base;
if (ch >= 10)
ch += 'a' - 10;
else
ch += '0';
*--s = ch;
}
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 (xsgn < 0) *--s = '-';
int w = e - s - 1;
while (w++ < width)
*--s = ' ';
return s;
}
//??
istream& operator >> (istream& s, Fix y)
{
int got_one = 0;
if (!s.readable())
{
s.error();
return s;
}
if (_libgxx_io_oblast) _libgxx_io_ob.free(_libgxx_io_oblast);
char sgn = 0;
char ch;
s >> WS;
while (s.good())
{
s.get(ch);
if (ch == '-')
{
if (sgn == 0)
{
sgn = 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));
_libgxx_io_oblast = p;
if (s.good())
s.unget(ch);
if (!got_one)
s.error();
else
y = atoI(p);
return s;
}
----------------------------------------------------------------------------
#ifndef _Fix_h
#define _Fix_h 1
#include <stream.h>
#include <stddef.h>
#include <type.h>
#include <Integer.h>
#define _Fix_mask 0xffff
#define _Fix_msb 0x8000
#define _Fix_borrow 0xffffffff
#define _Fix_min_length 1
#define _Fix_max_length 65535
extern uint16 Fix_default_length;
struct _Frep // internal Fix representation
{
uint16 len; // length in bits
uint16 siz; // allocated storage
int16 ref; // reference count
uint16 s[1]; // represented as ushort array starting here
};
typedef struct _Frep* _Fix;
class Fix
{
_Fix rep;
Fix(_Fix);
void unique();
void copy(int, uint16*);
friend int compare(_Fix, _Fix);
friend void mask(_Fix);
friend _Fix new_Frep(int, _Fix = NULL);
friend _Fix add(_Fix, _Fix, _Fix = NULL);
friend _Fix subtract(_Fix, _Fix, _Fix = NULL);
friend _Fix multiply(_Fix, _Fix, _Fix = NULL);
friend _Fix multiply(_Fix, long, _Fix = NULL);
friend _Fix divide(_Fix, _Fix, _Fix = NULL);
friend _Fix shift(_Fix, int, _Fix = NULL);
public:
Fix();
Fix(Fix&);
Fix(double&);
Fix(int);
Fix(int, Fix&);
Fix(int, double&);
~Fix();
Fix operator = (Fix&);
Fix operator = (double&);
friend int operator == (Fix&, Fix& );
friend int operator != (Fix&, Fix&);
friend int operator < (Fix&, Fix&);
friend int operator <= (Fix&, Fix&);
friend int operator > (Fix&, Fix&);
friend int operator >= (Fix&, Fix&);
Fix operator - ();
friend Fix operator + (Fix&, Fix&);
friend Fix operator - (Fix&, Fix&);
friend Fix operator * (Fix&, Fix&);
friend Fix operator / (Fix&, Fix&);
friend Fix operator * (Fix&, long);
friend Fix operator % (Fix&, long);
friend Fix operator << (Fix&, long);
friend Fix operator >> (Fix&, long);
friend Fix operator <? (Fix&, Fix&); // min
friend Fix operator >? (Fix&, Fix&); // max
Fix operator += (Fix&);
Fix operator -= (Fix&);
Fix operator *= (Fix&);
Fix operator /= (Fix&);
Fix operator *= (long);
Fix operator %= (long);
Fix operator <<=(long);
Fix operator >>=(long);
// builtin Fix functions
friend Fix abs(Fix&); // absolute value
friend int sgn(Fix&); // returns -1, 0, +1
// coercion & conversion
friend Integer mantissa(Fix&);
friend double value(Fix&);
friend char* Ftoa(Fix&, int base = 10, int width = 0);
friend Fix atoF(const char*);
friend istream& operator >> (istream&, Fix&);
friend ostream& operator << (ostream&, Fix&);
// miscellany
void error(char* msg);
};
// error handlers
extern void default_Fix_error_handler(char*);
extern one_arg_error_handler_t Fix_error_handler;
extern one_arg_error_handler_t
set_Fix_error_handler(one_arg_error_handler_t f);
//#ifdef __OPTIMIZE__
inline void Fix::unique()
{
if ( rep->ref > 1 )
{
rep->ref--;
rep = new_Frep(rep->len,rep);
}
}
inline void Fix::copy(int l, uint16* t)
{
uint16 *s = rep->s;
while ( l-- )
*s++ = *t++;
}
inline Fix::Fix()
{
rep = new_Frep(Fix_default_length);
}
inline Fix::Fix(int len)
{
if ( len < _Fix_min_length || len > _Fix_max_length )
error("illegal length in Fix declaration");
rep = new_Frep(len);
}
inline Fix::Fix(Fix& y)
{
rep = y.rep, rep->ref++;
}
inline Fix::Fix(int len, Fix& y)
{
if ( len < _Fix_min_length || len > _Fix_max_length )
error("illegal length in Fix declaration");
else if ( len == y.rep->len )
rep = y.rep, rep->ref++;
else
rep = new_Frep(len,y.rep);
}
inline Fix::~Fix()
{
if ( --rep->ref <= 0 ) delete rep;
}
inline Fix Fix::operator = (Fix& y)
{
if ( --rep->ref <= 0 ) delete rep;
if ( rep->len == y.rep->len )
rep = y.rep, rep->ref++;
else
copy(rep->len,y.rep->s);
return *this;
}
inline int operator == (Fix& x, Fix& y)
{
return compare(x.rep, y.rep) == 0;
}
inline int operator != (Fix& x, Fix& y)
{
return compare(x.rep, y.rep) != 0;
}
inline int operator < (Fix& x, Fix& y)
{
return compare(x.rep, y.rep) < 0;
}
inline int operator <= (Fix& x, Fix& y)
{
return compare(x.rep, y.rep) <= 0;
}
inline int operator > (Fix& x, Fix& y)
{
return compare(x.rep, y.rep) > 0;
}
inline int operator >= (Fix& x, Fix& y)
{
return compare(x.rep, y.rep) >= 0;
}
inline int sgn(Fix& x)
{
return (x.rep->len == 0) ? 0 : ( x.rep->s[0] & _Fix_msb ? 1 : -1 );
}
inline Fix operator + (Fix& x, Fix& y)
{
_Fix r = add(x.rep, y.rep); return r;
}
inline Fix operator - (Fix& x, Fix& y)
{
_Fix r = subtract(x.rep, y.rep); return r;
}
inline Fix operator * (Fix& x, Fix& y)
{
_Fix r = multiply(x.rep, y.rep); return r;
}
inline Fix operator * (Fix& x, long y)
{
_Fix r = multiply(x.rep, y); return r;
}
inline Fix operator / (Fix& x, Fix& y)
{
_Fix r = divide(x.rep, y.rep); return r;
}
inline Fix Fix::operator += (Fix& y)
{
unique(); add(this->rep, y.rep, this->rep); return *this;
}
inline Fix Fix::operator -= (Fix& y)
{
unique(); subtract(this->rep, y.rep, this->rep); return *this;
}
inline Fix Fix::operator *= (Fix& y)
{
unique(); multiply(this->rep, y.rep, this->rep); return *this;
}
inline Fix Fix::operator *= (long y)
{
unique(); multiply(this->rep, y, this->rep); return *this;
}
inline Fix Fix::operator /= (Fix& y)
{
unique(); divide(this->rep, y.rep, this->rep); return *this;
}
inline Fix operator % (Fix& x, long y)
{
Fix r(x.rep->len + y, x); return r;
}
inline Fix Fix::operator %= (long y)
{
Fix r(rep->len + y, *this); return *this = r;
}
inline Fix operator << (Fix& x, long y)
{
_Fix rep = shift(x.rep, y); return rep;
}
inline Fix operator >> (Fix& x, long y)
{
_Fix rep = shift(x.rep, -y); return rep;
}
inline Fix Fix::operator <<= (long y)
{
unique(); shift(this->rep, y, this->rep); return *this;
}
inline Fix Fix::operator >>= (long y)
{
unique(); shift(this->rep, -y, this->rep); return *this;
}
inline Fix operator <? (Fix& x, Fix& y)
{
if (compare(x.rep, y.rep) <= 0) return x; else return y;
}
inline Fix operator >? (Fix& x, Fix& y)
{
if (compare(x.rep, y.rep) >= 0) return x; else return y;
}
inline Fix abs(Fix& y)
{
return y >= 0 ? y : -y;
}
inline ostream& operator << (ostream& s, Fix& y)
{
return s << Ftoa(y);
}
inline void mask (_Fix x)
{
x->s[x->siz - 1] &= 0xffff << (16 - x->len & 0x000f);
}
inline Fix atoF(const char* s)
{
return atof(s);
}
//#endif
#endif
----------------------------------------------------------------------------
//
// type.h : machine type definitions
//
#ifndef TYPEH
#define TYPEH
typedef short int int16;
typedef long int int32;
typedef unsigned short int uint16;
typedef unsigned long int uint32;
typedef unsigned int uint;
typedef unsigned char byte;
#endif
----------------------------------------------------------------------------