/*
   File: cdl3rts.h
   Defines support routines for the generated code and runtime system
   Copyright (C) 2000-2006 C.H.A. Koster
  
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
   
   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   Library General Public License for more details.
   
   You should have received a copy of the GNU Library General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
   MA 02111-1307, USA

   CVS ID: "$Id$"
*/
#ifndef cdl3rts_h
#define cdl3rts_h

#include <stdio.h>

/* Define _PROTOTYPE macro since the codegenerator still generates instantiations */
#define _PROTOTYPE(function,params) function params

/* Exported variables */
extern long attaches;
extern long detaches;
extern long modulenr;
extern long linenr;

/*
   A value is typedef'd as a long *. The C version uses this type as follows:

   Depending on the type implemented, it is cast to a long for type INT,
   to a float for type REAL or it points to a structure allocated in the
   heap. In this case, the actual location that a value is pointing to
   uses bits 31-10 for holding the reference count and bits 9-0 to
   indicate the type alternative (tag). Some predefined types use these
   alternative bits to indicate their special nature. Tag 1023 is used
   to indicate values of type TEXT, in which case value[1] is used to
   give the actual length and value[2] to hold a pointer to a zero
   terminated array of characters. Tag 1022 is used to indicate values
   of type FILE (defined in predef.h and predefrts.c). In all other
   cases the actual value is a proper CDL3 type. In this case the tag
   indicates the chosen alternative of this type and value[i] holds
   the i^th component of the structure.

   The version when generating assembler instead of C uses a somewhat
   optimized version of this scheme.
*/
#define ALTBITS 10
#define ZEROBITS 4
#define LENBITS 16 

#define Tag(r,t) (((r) << ALTBITS) | (t))
#define UndefinedTag(r) ((((r)+1) << ALTBITS) - 1)
#define Alternative(v) ((v)[0]&((1 << ALTBITS) - 1))
#define Part(v,i) ((value)((v)[i]))
#define Refs(v) (((long)(v)[0]) >> ALTBITS)

#define DecrRefs(v) (v ? ((v)[0] -= (1 << ALTBITS)) : 0)
#define Attach(v)   ((v)[0] += (1 << ALTBITS))
#define Free(v,s) freemem(v,s)
#define Create(v,t,l) {*(v) = getmem(l + 1); **(v) = Tag(0, t);}
#define Set(v,p,x) ((*(v))[p] = (long)(x))
#define Write(t) fprintf(stderr,t)
#define Concat(v1,v2) concat(v1,v2)
#define Length(s) ((s+sizeof(value)-1)/sizeof(value))
#define Addr(v,i) address(v,i)
#define Abort(i,t) abort_rts(i,t)
#define Exit() quit(1) 

/* COMPATABILITY MACROS */
#define join(v,t,l) {(v) = getmem(l+1);*(v) = Tag(0,t);}
#define attach(v) Attach(v)
#define set(v,p,x) ((v)[p] = (long)(x))
#define TextLength(v) ((v)[1])
#define Text(v) V_TEXT(v)
#define Int(v)  V_INT(v)
#define File(v) V_FILE(v)

/* GENERIC MACROS */
#define ATTACH(v) Attach(v)
#define WRITE(t) Write(t)

/*
   For every implemented type TYPE the following names, either defined
   as a macro or as a function call must be present in the runtime
   system:

   T_TYPE: Defines the special tag (only needed for TEXT and FILE)
   A_TYPE: Defines the attach operation for the type
   C_TYPE: Defines the creation of a value of the type
   D_TYPE: Defines the detach operation for the type
   V_TYPE: Gives the actual value (only needed for special types)
   W_TYPE: Writes the value of the type
   EQ_TYPE: Defines the equality test between two values of the type
*/

/* EXTERNAL TYPE TEXT */
#define T_TEXT  ((1 << ALTBITS) - 1) 
#define C_TEXT(t) ctext(t)

#ifdef CDLASM
#define V_TEXT(v)  ((char *)((v)+2))
/* EQ_TEXT and D_TEXT(v) is defined in predefrts.c */
#else
#define V_TEXT(v)  ((char *)((v)[2]))
#define D_TEXT(v) if (v!=NULL) if (Refs(v)==0) {  Free((value)V_TEXT(v),L_TEXT(v)); Free(v,3); } else DecrRefs(v)
#define EQ_TEXT(v1,v2) (strcmp(V_TEXT(v1),V_TEXT(v2))==0)
#endif

#define A_TEXT(v) ATTACH(v)
#define W_TEXT(v) WRITE(V_TEXT(v))
#define L_TEXT(v) Length(TextLength(v)+1)

/* EXTERNAL TYPE REAL */
#define C_REAL(v) ((value)(float)(l))
#define V_REAL(v) ((float)(v))
#define EQ_REAL(v1,v2) ((V_REAL(v1)==V_REAL(v2))
#define D_REAL(v)
#define A_REAL(v)
#define W_REAL(v) fprintf(stderr,"%f",V_REAL(v))

/* EXTERNAL TYPE INT */
#define C_INT(l) ((value)(long)(l))
#define V_INT(v) ((long)(v))
#define EQ_INT(v1,v2) (Int(v1)==Int(v2))
#define D_INT(v)
#define A_INT(v)
#define W_INT(v) fprintf(stderr,"%ld",V_INT(v)) 

typedef long * value;

extern int argument_count;
extern char ** arguments;

/* Exported routines */
value *address (value *array,long index);
value ctext (char *t);
value getmem (long size);
void freemem (value v,long size);
value concat (value s1,value s2);
void start_rts (int argc,char * argv[]);
void abort_rts (long line, char* module_name);
void stop_rts ();
void quit (int e);

#endif /* cdl3rts_h */
