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