[gnu.g++.bug] bug report 14: fatal signal 4 received

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
----------------------------------------------------------------------------