/* theusual.h
 *
 * Recommendations:
 *- declare char,short,float args to functions as types Dchar,Dshort,Dfloat
 *- typedef Dchar/Dshort/Dfloat as int,double.  declaring args as chars
 *  does not add to efficiency; declaring args as floats rather than
 *  doubles is dangerous (see below)-only do this in inner loops.
 *- function which takes, returns void: Zvoid foo(Zvoid)
 *- unspec: Zunspec
 *- introduce new types as Ztype_t 
 *
 * Ansi strategy:
 * SGI Ansi will pass float as float only if the function is DEFINED
 *   using the new parameter-list style.  This style wont compile in k&r,
 *   while the new PROTOTYPES can be desguised as k&r thru Zproto(()).
 *   Also, passing float/char/short arguments without eleveation is
 *   dangerous - all invokers must have access to the correct prototype.
 *   Lastly, elk cannot identify a function which is really expecting
 *   floats, vs. one which expects floats cast to doubles.
 *   So, keep using old definitions, but new declarations - Sgi will
 *   do old elevations but do type checking on these.
 *  Unless a highly critical function...
 *
 *  I.E., use floats in calling sequence only in local functions WITHIN
 *  a file.  all externally visible functions should be double.
 *  C.F. Dfloat.
 *  Thus, a declaration for a float foo(float) will be Dfloat foo(Dfloat)
 *  (The return value would be ok as float, except for elk)
 *
 * note irix ansi cpp defines __ANSI_CPP__
 *
 * modified
 * 11nov        improvements for gcc
 * 30jun	U_int/etc
 * 20june       include stdlib on sun
 * 9apr         Zconst,zprototypes.h
 * 7apr         Zunspec
 * 24mar        sgi4d
 * 30oct        Dfloat,Dint
 * (mac mpw)
 */

#ifndef THEUSUAL_H
#define THEUSUAL_H

/* all important environment init */
#define Einit()	
#define Efinit()

/* environment config */

/* gcc understands void, prototypes,
 * also has stdarg, Eansiincludes on its default -I path unless reset.
 * Warning - gcc defs for exit,abort are different than in sun stdlib.h.
 * Beware of the -ansi flag: standard defines such as sparc,unix,etc.
 * are not provided, but __sparc__,etc. are.
 */
#ifdef __GNUC__
# define Egcc           1
# ifdef __STDC__
#  define Eansi         1
# else
#  define Eansi         0
# endif
# define Eansiproto     1
# define proc void
# define Estdarg        1
# define Evarargs       0
# define Eansiincludes  1
# define Eunix		1
/* sparc,unix,etc. are not defined if -ansi flag is given,
 * but gcc defines __sparc__,etc. */
# if __sparc__
#  define Esparc        1
# endif /*sparc*/
  /* UGH: exit and abort have conflicting definitions on the sun;
     must get rid of the stdlib.h declarations if compiling mixed cc/gcc
     */
#  define exit junk1
#  define abort junk2
#   include <stdlib.h>
#  undef exit
#  undef abort
#endif /*GNUC*/


#if (sparc || Esparc)
# define Esparc         1
# define Eunix		1
# define Ebsd		1
# define Esys5sm        1       /* sysv style shared memory */
# define Evaxorder	0
# define E68Korder 	1
# if !__GNUC__
#   define Evarargs       1
#   define Estdarg        0
#   define Eansiincludes  0
# endif
# define Evprintf	1	/* has vprintf() routines */
# define Ebinarystream  0       /* has fopen(path,"wb" */
# define EfloatC(f)	(float)f
  /* the most efficient float type */
  typedef float Efloat;
  /* variable precision code should still use Flotype. rename Eflotype? */
  /* gcc (and ANSI?) want prototypes to be declared as the type they
   * elevate to, e.g. chars must be declared as ints, floats as doubles
   * in the prototype ONLY (can be declared as char/float in the function).
   * I think SGI compiler can deal with float prototypes.
   * D* typedefs preserve information, used in arguments in prototypes.
   * But not in return values.
   */
  typedef double Dfloat;
  typedef int Dchar;
  typedef int Dshort;
# define Efltconst 	0	/* allows 0.0F? now obsolete-use EfloatC() */
# define Emulticconst	0
  /* do NOT include stdlib.h: it is incorrect e.g. exit(),
     and w/o prototypes it does not help much anyway */
  /*#  include <stdlib.h>*/
#endif /*sparc*/


#if (SgiAnsi || ((mips || __mips__) && (__STDC__ || __EXTENSIONS__)))
# define SgiAnsi        1
# define Emips          1
# define Esgi           1
# define Evarargs	0	/* has varargs.h */
# define Estdarg        1	/* has ansi stdarg.h */
# define Eansiincludes  1       /* has stdlib.h, etc. */
# define Evprintf	1	/* has vprintf() routines */
# define Eansi		1
# define Eansiproto	1
# define Eansistring	1	/* has "" "" string concat, vs backslash */
# define Ebinarystream  1       /* ? fopen(path,"rb") */
# define EfloatC(x)	x ## f
  /* the most efficient float type */
  typedef float Efloat;
  /* variable precision code should still use Flotype. rename Eflotype? */
  /* gcc (and ANSI?) want prototypes to be declared as the type they
   * elevate to, e.g. chars must be declared as ints, floats as doubles
   * in the prototype ONLY (can be declared as char/float in the function).
   * SGI compiler can deal with float prototypes, but elk cannot!
   * all-around safer to use old c-style argument promotion Except
   * in the innermost of loops.
   * D* typedefs preserve information, used in prototypes.   */
  typedef double Dfloat;
  typedef int Dchar;
  typedef int Dshort;

# define Eunix		1
# define Ebsd		0   /* should ? */
# define EsysV          1
# define Eiris		1
# define Esys5sm        1       /* sysv style shared memory */
# define Efltconst 	0	/* allows 0.0F? now obsolete-use EfloatC() */
# define Emulticconst	0
# define Evaxorder	0       /* not sure */
# define E68Korder 	1
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
#endif /*SgiAnsi*/


#if (mips && !SgiAnsi)
# define Emips          1
# define Esgi           1
# define Evarargs	1	/* has varargs.h */
# define Estdarg        0	/* has ansi stdarg.h */
# define Eansiincludes  0       /* has stdlib.h, etc. */
# define Evprintf	1	/* has vprintf() routines */
# define Eansi		0
# define Eansiproto	1
# define Eansistring	0	/* has "" "" string concat, vs backslash */
# define Ebinarystream  1       
# define EfloatC(f)	(float)(f)
  /* the most efficient float type */
  typedef float Efloat;
  /* variable precision code should still use Flotype. rename  Eflotype? */
  /* gcc (and ANSI?) want prototypes to be declared as the type they
   * elevate to, e.g. chars must be declared as ints, floats as doubles
   * in the prototype ONLY (can be declared as char/float in the function).
   * I think SGI compiler can deal with float prototypes.
   * D* typedefs preserve information, used in prototypes.
   */
  typedef double Dfloat;
  typedef int Dchar;
  typedef int Dshort;
# define Eunix		1
# define Ebsd		0   /* should ? */
# define EsysV          1
# define Eiris		1
# define Esys5sm        1       /* sysv style shared memory */
# define Efltconst 	0	/* allows 0.0F? now obsolete-use EfloatC() */
# define Emulticconst	0
# define Evaxorder	0
# define E68Korder 	1
#endif /*mips*/

/**** types ****/
#if Eansi
  typedef void *UNSPEC;
  typedef void *Zunspec;        /* use Zvoid as returnvalue, Zunspec */
                                /* in functions */
# define proc void
# define Zvoid void
# define Zconst const
  typedef void (vfunction)();   /* pointer to procedure */
#else
  typedef char *UNSPEC;
  typedef char *Zunspec;
# define proc
# define Zvoid
# define Zconst
  typedef int (vfunction)();
#endif
/* types.h is in sys/ on some systems, not on others */
typedef unsigned int U_int;
typedef unsigned short U_short;
typedef unsigned char U_char;

/* allow both new, old style function definitions. must declare
        int f(int a,float b)
   as
        int ZDECLARE2(f,int,a,float,b)
 */
#include <zprototypes.h>

#if Eansiproto
# define Zproto(x) x
#else
# define Zproto(x) ()
#endif

#if (Emc68020|Esparc|Emips|(Emac&&Empw))
# define int4 int
# define int2 short
# define bool4 int
#endif
#if (Emac&&Elsc)
# define int4 long
# define int2 int
# define bool4 long
#endif
# ifndef int4
:error
#endif

/* existing code uses some of these names, e.g. TRUE, byte, proc.
 * could z* to avoid conflicts.  tried this, looked ugly.
 * easier to just #undef these in conflicting cases.
 */
#define FALSE 0
#define TRUE  1
#define bool int
#define global
#define forward
#define local static
typedef int4 (function)();
typedef char *Zaddr;
typedef unsigned char Zbyte;

#if Enoalloc
# define Memalloc(n) malloc(n)
# define Memfree(a)  free(a)
#else
# define Memalloc(n) alloca(n)
# define Memfree(a)
#endif

#define Zmultichar(a,b,c,d) (unsigned long)(((a)<<24)|((b)<<16)|((c)<<8)|(d)) 

#ifdef ztrace
#    define Ztrace(x)    printf x
#else
#    define Ztrace(x)
#endif
#ifdef ztrace2
#    define Ztrace2(x)   printf x
#else
#    define Ztrace2(x)
#endif

#include <math.h>

#ifndef EOF
# include <stdio.h>
#endif

#include <libz.h>

#define VERALIGN(ptr,n) assert(((((int4)ptr)/n)*n)==n)

#endif /*THEUSUAL_H*/
