/* ---------------------------------------------------------------------- */
/*                   Copyright (C) 1991 by Natrlich!                     */
/*                      This file is copyrighted!                         */
/*                Refer to the documentation for details.                 */
/* ---------------------------------------------------------------------- */
#define TEST 0                   /* may fail on big MACROS    */
/* these aren't actually _MAXIMAL_ values,but 'malloc' values */
/* if your malloc only allocates 64K and you don't want to go */
/* for farmalloc (as in MesS-DOS), figure values that keep    */
/* sizeof( struct) *  _MAXIMAL_ + 256 to < 0xFFFF             */
/* The values look very suggestively, like the higher the     */
/* better but actually 1/2 1/4 or even 1/8 won't reduce the   */
/* speed dramatically                                         */
/* too small values may actually CRASH your system            */
#if ! VERSION && TEST
# define LABMAX    10L           /* #global labels            */
# define LLABMAX   10L           /* #local labels             */
# define STRMAX    0x100L        /* #bytes for strings        */
# define EXPMAX    0x40L         /* #expressions              */
# define FIXMAX    0x10L         /* #forward ref fixes        */
# define LEXPMAX   0x10L         /* #lexpression              */
# define REFMAX    0x80L         /* #forward refs             */
# define MACTOKMAX 0x100L        /* #token in macro buffer    */
# define NBUFSIZ   0x1000L       /* #bytes file buffer space  */
# define SEGMAX    10L           /* #code segments            */
# define IMMMAX    50L           /* #immediate patch pointers */
#else
# define LABMAX    1000L         /* #global labels            */
# define LLABMAX   100L          /* #local labels             */
# define STRMAX    0x2000L       /* #bytes for strings        */
# define EXPMAX    0x400L        /* #expressions              */
# define FIXMAX    0x40L         /* #forward ref fixes        */
# define LEXPMAX   0x200L        /* #lexpression              */
# define REFMAX    0x80L         /* #forward refs             */
# define MACTOKMAX 0x1000L       /* #token in macro buffer    */
# define NBUFSIZ   0x2000L       /* #bytes file buffer space  */
# define SEGMAX    50L           /* #code segments            */
# define IMMMAX    100L          /* #immediate patch pointers */
#endif
/* ---------------------------------------------------------- */
#define MAXMODULE 0xFE00L        /* 64K address space on 6502 */
#if OS == UNIX
# define LIBMAX   0x80000L       /* Library maximum size 512K */
#endif
#if OS == MSDOS
# define LIBMAX   0x40000L
#endif

#define MAXFLOATS 32             /* #floats in one line       */
#define MACSPACE  (MACTOKMAX * (sizeof( int) + sizeof( lword)))

#if __NSTDC__ && __TURBOC__
void huge   *nmalloc( lword),
            nfree( void huge *);
#else
void huge   *nmalloc();
void        nfree();
#endif
/* ---------------------------------------------------------- */
/*          Copyright (c) 1990 by Natrlich!                  */
/* ---------------------------------------------------------- */
/* This is a generic function so to speak (it is of course    */
/* just a simple macro) that builds a custom mallocer for a   */
/* structure. The benefits are:                               */
/*       Speed                                                */
/*       Garbage collectability                               */
/*       Fragmentation                                        */
/* The detriments (?) are:                                    */
/*       No "free()"                                          */
/*         Not all that portable if it isn't ANSI-C.          */
/*       <space> ## <space> used to stand here, but some        */
/*      Compilers can't take it.                              */
/* ---------------------------------------------------------- */
#if ! STATISTICS

#if CANCONCAT

#define make_mallocer( type, max, fun_name)                       \
typedef struct _ ## type ## _m                                        \
{                                                                 \
   long            free;                                          \
   type huge       *tab;                                          \
   struct _ ## type ## _m huge  *before;                              \
} type ## _m;                                                       \
                                                                  \
type ## _m huge * ## type ## _h = 0;                                    \
                                                                  \
type *fun_name()                                                  \
{                                                                 \
   register type ## _m huge *p;                                     \
                                                                  \
   if( (p = type ## _h) && p->free--)                               \
      return( p->tab++);                                          \
   p         = nmalloc( (lword) (sizeof(type ## _m) +               \
                                       max * sizeof( type)));     \
   p->free   = max - 1;                                           \
   p->tab    = (type *) ((char huge *) p + sizeof( type ## _m));    \
   p->before = (type ## _m *) type ## _h;                             \
   type ## _h  = p;                                                 \
   return( p->tab++);                                             \
}
#else
#define make_mallocer( type, max, fun_name)                       \
typedef struct _/**/type/**/_m                                    \
{                                                                 \
   long            free;                                          \
   type huge       *tab;                                          \
   struct _/**/type/**/_m huge *before;                           \
} type/**/_m;                                                     \
                                                                  \
type/**/_m huge */**/type/**/_h = 0;                              \
                                                                  \
type *fun_name()                                                  \
{                                                                 \
   register type/**/_m huge *p;                                   \
                                                                  \
   if( (p = type/**/_h) && p->free--)                             \
      return( p->tab++);                                          \
   p         = nmalloc((lword) (sizeof(type/**/_m)+               \
                                       max * sizeof( type)));     \
   p->free   = max - 1;                                           \
   p->tab    = (type *) ((char huge *) p + sizeof( type/**/_m));  \
   p->before = (type/**/_m *) type/**/_h;                         \
   type/**/_h = p;                                                \
   return( p->tab++);                                             \
}
#endif

#else

#if CANCONCAT
#define make_mallocer( type, max, fun_name)                       \
typedef struct _ ## type ## _m                                        \
{                                                                 \
   long            free;                                          \
   type huge       *tab;                                          \
   struct _ ## type ## _m huge *before;                               \
} type ## _m;                                                       \
                                                                  \
type ## _m huge * ## type ## _h = 0;                                    \
                                                                  \
type *fun_name()                                                  \
{                                                                 \
   register type ## _m huge *p;                                     \
   extern   word        _a_ ## type,                                \
                        _m_ ## type;                                \
   extern   lword       _s_ ## type;                                \
                                                                  \
   _a_ ## type++;                                                   \
   if( (p = type ## _h) && p->free--)                               \
      return( p->tab++);                                          \
   _m_ ## type++;                                                   \
   _s_ ## type = sizeof(type ## _m) + max * sizeof( type);            \
   p         = nmalloc( (lword) (sizeof(type ## _m) +               \
                                       max * sizeof( type)));     \
   p->free   = max - 1;                                           \
   p->tab    = (type *) ((char huge *) p + sizeof( type ## _m));    \
   p->before = (type ## _m *) type ## _h;                             \
   type ## _h  = p;                                                 \
   return( p->tab++);                                             \
}
#else
#define make_mallocer( type, max, fun_name)                       \
typedef struct _/**/type/**/_m                                    \
{                                                                 \
   long            free;                                          \
   type huge       *tab;                                          \
   struct _/**/type/**/_m huge *before;                           \
} type/**/_m;                                                     \
                                                                  \
type/**/_m huge */**/type/**/_h = 0;                              \
                                                                  \
type *fun_name()                                                  \
{                                                                 \
   register type/**/_m huge  *p;                                  \
   extern   word        _a_/**/type,                              \
                        _m_/**/type;                              \
   extern   lword       _s_/**/type;                              \
                                                                  \
   _a_/**/type++;                                                 \
   if( (p = type/**/_h) && p->free--)                             \
      return( p->tab++);                                          \
   _m_/**/type++;                                                 \
   _s_/**/type = sizeof(type/**/_m) + max * sizeof( type);        \
   p         = nmalloc((lword) sizeof(type/**/_m)+                \
                                       max * sizeof( type)));     \
   p->free   = max - 1;                                           \
   p->tab    = (type *) ((char huge *) p + sizeof( type/**/_m));  \
   p->before = (type/**/_m *) type/**/_h;                         \
   type/**/_h = p;                                                \
   return( p->tab++);                                             \
}
#endif
#endif

#if ! STATISTICS

#if CANCONCAT

#define dup_mallocer( type, max, fun_name, id)                    \
type ## _m huge   * id ## type ## _h = 0;                               \
                                                                  \
type *fun_name()                                                  \
{                                                                 \
   register type ## _m huge *p;                                     \
                                                                  \
   if( (p = id ## type ## _h) && p->free--)                           \
      return( p->tab++);                                          \
   p         = nmalloc((lword) (sizeof(type ## _m) +                \
                                       max * sizeof( type)));     \
   p->free   = max - 1;                                           \
   p->tab    = (type *) ((char huge *) p + sizeof( type ## _m));    \
   p->before = (type ## _m *) id ## type ## _h;                         \
   id ## type ## _h = p;                                              \
   return( p->tab++);                                             \
}
#else
#define dup_mallocer( type, max, fun_name, id)                    \
                                                                  \
type/**/_m huge  *id/**/type/**/_h = 0;                           \
                                                                  \
type *fun_name()                                                  \
{                                                                 \
   register type/**/_m huge *p;                                   \
                                                                  \
   if( (p = id/**/type/**/_h) && p->free--)                       \
      return( p->tab++);                                          \
   p         = nmalloc((lword) (sizeof(type/**/_m)+               \
                                       max * sizeof( type)));     \
   p->free   = max - 1;                                           \
   p->tab    = (type *) ((char huge *) p + sizeof( type/**/_m));  \
   p->before = (type/**/_m *) id/**/type/**/_h;                   \
   id/**/type/**/_h = p;                                          \
   return( p->tab++);                                             \
}
#endif

#else

#if CANCONCAT
#define dup_mallocer( type, max, fun_name, id)                    \
type ## _m huge  * id ## type ## _h = 0;                                \
                                                                  \
type *fun_name()                                                  \
{                                                                 \
   register type ## _m huge *p;                                     \
   extern   word        _a_ ## id ## type,                            \
                        _m_ ## id ## type;                            \
   extern   lword       _s_ ## id ## type;                            \
                                                                  \
   _a_ ## id ## type++;                                               \
   if( (p = id ## type ## _h) && p->free--)                           \
      return( p->tab++);                                          \
   _m_ ## id ## type++;                                               \
   _s_ ## id ## type = sizeof(type ## _m) + max * sizeof( type);        \
   p         = nmalloc( (lword) (sizeof(type ## _m) +               \
                                       max * sizeof( type)));     \
   p->free   = max - 1;                                           \
   p->tab    = (type *) ((char huge *) p + sizeof( type ## _m));    \
   p->before = (type ## _m *) id ## type ## _h;                         \
   id ## type ## _h = p;                                              \
   return( p->tab++);                                             \
}
#else
#define dup_mallocer( type, max, fun_name, id)                    \
type/**/_m huge  *id/**/type/**/_h = 0;                           \
                                                                  \
type *fun_name()                                                  \
{                                                                 \
   register type/**/_m huge *p;                                   \
   extern   word        _a_/**/id/**/type,                        \
                        _m_/**/id/**/type;                        \
   extern   lword       _s_/**/id/**/type;                        \
                                                                  \
   _a_/**/id/**/type++;                                           \
   if( (p = id/**/type/**/_h) && p->free--)                       \
      return( p->tab++);                                          \
   _m_/**/id/**/type++;                                           \
   _s_/**/id/**/type = sizeof(type/**/_m) + max * sizeof( type);  \
   p         = nmalloc((lword) (sizeof(type/**/_m)+               \
                                       max * sizeof( type)));     \
   p->free   = max - 1;                                           \
   p->tab    = (type *) ((char huge *) p + sizeof( type/**/_m));  \
   p->before = (type/**/_m *) id/**/type/**/_h;                   \
   id/**/type/**/_h = p;                                          \
   return( p->tab++);                                             \
}
#endif
#endif
