
/******************************************************************************
* MODULE     : basic.gen.h
* DESCRIPTION: see basic.gen.cc
* COPYRIGHT  : (C) 1999  Joris van der Hoeven
*******************************************************************************
* This software falls under the GNU general public license and comes WITHOUT
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
* If you don't have this file, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
******************************************************************************/

#include <tm_configure.gen.h>

#module basic
#import tm_configure
#include <stdlib.h>
#include <iostream.h>

#define DEBUG(x)
#define bool int
#define FALSE 0
#define TRUE 1
typedef int SI;
typedef void* pointer;

void* operator new (register size_t s);
void  operator delete (register void* ptr);
void* operator new[] (register size_t s);
void  operator delete[] (register void* ptr);
int   mem_used ();
void  mem_info ();
bool  debug (int which, bool write_flag= FALSE);

extern int concrete_count;
struct concrete_struct {
  int ref_count;
  inline concrete_struct (): ref_count (1) { DEBUG(concrete_count++); }
  inline ~concrete_struct () { DEBUG(concrete_count--); }
};

extern int abstract_count;
struct abstract_struct {
  int ref_count;
  inline abstract_struct (): ref_count (0) { DEBUG(abstract_count++); }
  inline ~abstract_struct () { DEBUG(abstract_count--); }
};

inline SI min (SI i, SI j) { if (i<j) return i; else return j; }
inline SI max (SI i, SI j) { if (i>j) return i; else return j; }
inline double min (double i, double j) { if (i<j) return i; else return j; }
inline double max (double i, double j) { if (i>j) return i; else return j; }

enum display_control { INDENT, UNINDENT, HRULE, LF };
ostream& operator << (ostream& out, display_control ctrl);

#endmodule // basic

/******************************************************************************
* indirect structures
******************************************************************************/

#module concrete (T, R)
R* rep;
public:
inline T (const T& x);
inline ~T ();
inline R* operator -> ();
inline T& operator = (T x);
#endmodule // concrete

#module abstract (T, R)
#import concrete (T, R)
inline T (R* rep);
#endmodule // abstract

#module code_concrete (T, R)
inline T::T (const T& x): rep(x.rep) { rep->ref_count++; }
inline T::~T () { if ((--rep->ref_count)==0) delete rep; }
inline R* T::operator -> () { return rep; }
inline T& T::operator = (T x) {
  x.rep->ref_count++;
  if ((--rep->ref_count)==0) delete rep;
  rep=x.rep;
  return *this;
}
#endmodule // code_concrete

#module code_abstract (T, R)
#import code_concrete (T, R)
inline T::T (R* rep2): rep (rep2) { rep->ref_count++; }
#endmodule // code_abstract

/******************************************************************************
* null indirect structures
******************************************************************************/

#module concrete_null (T, R)
R* rep;
public:
inline T ();
inline T (const T& x);
inline ~T ();
inline R* operator -> ();
inline T& operator = (T x);
inline friend bool nil (T x);
#endmodule // concrete_null

#module abstract_null (T, R)
#import concrete_null (T, R)
inline T (R* rep);
#endmodule // abstract_null

#module code_concrete_null (T, R)
inline T::T (): rep(NULL) {}
inline T::T (const T& x): rep(x.rep) { if (rep!=NULL) rep->ref_count++; }
inline T::~T () { if ((rep!=NULL) && ((--rep->ref_count)==0)) delete rep; }
inline R* T::operator -> () { return rep; }
inline T& T::operator = (T x) {
  if (x.rep!=NULL) x.rep->ref_count++;
  if ((rep!=NULL) && ((--rep->ref_count)==0)) delete rep;
  rep=x.rep;
  return *this;
}
inline bool nil (T x) { return x.rep==NULL; }
#endmodule // code_concrete_null

#module code_abstract_null (T, R)
#import code_concrete_null (T, R)
inline T::T (R* rep2): rep(rep2) { if (rep!=NULL) rep->ref_count++; }
#endmodule // code_abstract_null

/******************************************************************************
* extensions
******************************************************************************/

#module extend (B, T, R)
#import abstract (T, R)
inline T (B& x);
inline operator B ();
#endmodule // extend

#module code_extend (B, T, R)
#import code_abstract (T, R)
inline T::T (B& x): rep ((R*) x.rep) { rep->ref_count++; }
inline T::operator B () { return B (rep); }
#endmodule // code_extend

#module extend_null (B, T, R)
#import abstract_null (T, R)
inline T (B& x);
inline operator B ();
#endmodule // extend_null

#module code_extend_null (B, T, R)
#import code_abstract_null (T, R)
inline T::T (B& x): rep ((R*) x.rep) { if (rep!=NULL) rep->ref_count++; }
inline T::operator B () { return B (rep); }
#endmodule // code_extend_null
