/* ---------------------------------------------------------------------- */
/*                   Copyright (C) 1991 by Natrlich!                     */
/*                      This file is copyrighted!                         */
/*                Refer to the documentation for details.                 */
/* ---------------------------------------------------------------------- */
#define _TO_UPPER_
#include "defines.h"
#include "nasm.h"
#undef DEBUG 
#include "debug.h"
#include <setjmp.h>
#include NMALLOC_H
#include "buffer.h"
#ifndef NULL
# define NULL  ((void *) 0)
#endif

#if __NSTDC__
extern int     (*gettoken)( void);
#else
extern int     (*gettoken)();
#endif

#if STATISTICS
extern long    _mused;
#endif
extern byte    c;
extern int     freshflag;     /* might not be really needed here */
extern jmp_buf   eof_panic;
void  dummy()  { }
                                    /* if we are in a string */
static byte  zero[16] = { 0, 0, 0, 0, '"' };
static buffer nil_buffer =
{
   0, 0,
   (byte huge *) zero, (byte huge *) zero,
   NULL,
   NULL,
   16L, 16L,
   0,
   0,
   0, BUF_AUX,
   (void (*)(buffer *)) dummy,         /* **-PORT #1-** */
   (void (*)(buffer *)) dummy,         /* **-PORT #1-** */
   (int  (*)(void))     nilexer        /* **-PORT #1-** */
};


buffer huge  *bp = &nil_buffer,
       huge  *hp;

#if ! VERSION
void kill_buffer( hp)
register buffer huge  *hp;
{
    hp = bp;                   /* get buffer to be freed           */
    if( bp = bp->before)       /* New buffer is the one before     */
    {
       if( (hp->type ^ bp->type) & BUF_TYPEMASK)
          freshflag = 1;
       bp->next = 0;           /* of course only if there was one  */
       gettoken = (int (*)(void)) bp->get;  /* new input routine */
    }                          /* **-PORT #1-** 1 line up          */
    (*hp->done)(hp);           /* Call cleanup action (almost OO)  */
    if( hp->type & BUF_FREE)   /* dynamic buffer struct ? then     */
       nfree( (void huge *) hp); /* Remove buffer struct           */
}
#endif

#if ! DEBUG
/* ---------------------------------------------------------- */
/* Don't let a PASCALler near this (ain't thaaat bad, though) */
/* These routines only work for ASM65. The method is somewhat */
/* objectoriented, but will fail, when the buffer element size*/
/* differs (as it does with ASM65). So how come it worx ??    */
/* ---------------------------------------------------------- */
byte  input()
{
   register buffer huge *P = bp;

   if( P->remain--)                    /* Something left ?        */
      return( *P->p++);                /* then return that        */
   (*P->multi.fill)( P);               /* try refilling           */
   if( P->remain--)                    /* Something left ?        */
      return( *P->p++);                /* then return that        */
   kill_buffer(hp);                    /* Install new buffer      */
   return( '\n');                      /* LF for safety           */
}
#else

#define xreturn( val)               \
{                                   \
   byte  foo = (val);      \
                                    \
   IMESS("Returning '%c'", foo, 1); \
   LEAVE();                         \
   return( foo);                    \
}

byte  input()
{
   int   val;

   ENTER("input");
   if( bp->remain--)                    /* Something left ?        */
      xreturn( *bp->p++);               /* then return that        */
   MESS("Trying to fill buffer...");
   (*bp->multi.fill)( bp);              /* try refilling           */
   if( bp->remain--)                    /* Something left ?        */
      xreturn( *bp->p++);               /* then return that        */
   MESS("Trying to kill buffer...");
   dump_buffer( bp);
   kill_buffer(hp);                     /* Install new buffer      */
   xreturn( '\n');                      /* LF for safety           */
}
#endif


/* Just to convert lower case to upper case ... */
byte  _uptable[] =
{
   0x00,0x01,0x02,0x03,  0x04,0x05,0x06,0x07,
   0x08,0x09,0x0A,0x0B,  0x0C,0x0D,0x0E,0x0F,     /* 0x00 */
   0x10,0x11,0x12,0x13,  0x14,0x15,0x16,0x17,
   0x18,0x19,0x1A,0x1B,  0x1C,0x1D,0x1E,0x1F,     /* 0x10 */
   0x20,0x21,0x22,0x23,  0x24,0x25,0x26,0x27,
   0x28,0x29,0x2A,0x2B,  0x2C,0x2D,0x2E,0x2F,     /* 0x20 */
   0x30,0x31,0x32,0x33,  0x34,0x35,0x36,0x37,
   0x38,0x39,0x3A,0x3B,  0x3C,0x3D,0x3E,0x3F,     /* 0x30 */

   0x40,0x41,0x42,0x43,  0x44,0x45,0x46,0x47,
   0x48,0x49,0x4A,0x4B,  0x4C,0x4D,0x4E,0x4F,     /* 0x40 */
   0x50,0x51,0x52,0x53,  0x54,0x55,0x56,0x57,
   0x58,0x59,0x5A,0x5B,  0x5C,0x5D,0x5E,0x5F,     /* 0x50 */
   0x40,0x41,0x42,0x43,  0x44,0x45,0x46,0x47,
   0x48,0x49,0x4A,0x4B,  0x4C,0x4D,0x4E,0x4F,     /* 0x40 */
   0x50,0x51,0x52,0x53,  0x54,0x55,0x56,0x57,
   0x58,0x59,0x5A,0x7B,  0x7C,0x7D,0x7E,0x7F,     /* 0x70 */

   0x80,0x81,0x82,0x83,  0x84,0x85,0x86,0x87,
   0x88,0x89,0x8A,0x8B,  0x8C,0x8D,0x8E,0x8F,     /* 0x80 */
   0x90,0x91,0x92,0x93,  0x94,0x95,0x96,0x97,
   0x98,0x99,0x9A,0x9B,  0x9C,0x9D,0x9E,0x9F,     /* 0x90 */
   0xA0,0xA1,0xA2,0xA3,  0xA4,0xA5,0xA6,0xA7,
   0xA8,0xA9,0xAA,0xAB,  0xAC,0xAD,0xAE,0xAF,     /* 0xA0 */
   0xB0,0xB1,0xB2,0xB3,  0xB4,0xB5,0xB6,0xB7,
   0xB8,0xB9,0xBA,0xBB,  0xBC,0xBD,0xBE,0xBF,     /* 0xB0 */

   0xC0,0xC1,0xC2,0xC3,  0xC4,0xC5,0xC6,0xC7,
   0xC8,0xC9,0xCA,0xCB,  0xCC,0xCD,0xCE,0xCF,     /* 0xC0 */
   0xD0,0xD1,0xD2,0xD3,  0xD4,0xD5,0xD6,0xD7,
   0xD8,0xD9,0xDA,0xDB,  0xDC,0xDD,0xDE,0xDF,     /* 0xD0 */
   0xE0,0xE1,0xE2,0xE3,  0xE4,0xE5,0xE6,0xE7,
   0xE8,0xE9,0xEA,0xEB,  0xEC,0xED,0xEE,0xEF,     /* 0xE0 */
   0xF0,0xF1,0xF2,0xF3,  0xF4,0xF5,0xF6,0xF7,
   0xF8,0xF9,0xFA,0xFB,  0xFC,0xFD,0xFE,0xFF,     /* 0xF0 */
};

#if VERSION
byte _input()
{
   register buffer huge *P = bp;

   (*P->multi.fill)( P);               /* try refilling           */
   if( P->remain--)                    /* Something left ?        */
      return( *P->p++);                /* then return that        */
   kill_buffer(hp);                    /* Install new buffer      */
   return( '\n');                      /* LF for safety           */
}
#endif

byte  uinput() { return( _uptable[ input()]); }

/* ------------------------------------------------------------ */
/* very much unfortunate is the interplay between us and yacc   */
/* when it comes to doing includes. Gives me the wish to dump   */
/* Yacc and write something myself...                           */
/* ------------------------------------------------------------ */
static int     btok;
static lword   bval;
extern lword   yylval;

static buffer sfi =
{
   0, 0,
   (byte *) &btok, (byte *) &btok,
   NULL,
   NULL,
   1L, 1L,
   0,
   0,
   0, BUF_AUX | BUF_TOKEN,
   (void (*)(buffer *)) dummy,         /* **-PORT #1-** */
   (void (*)(buffer *)) dummy,         /* **-PORT #1-** */
   (int  (*)(void))     lexer          /* **-PORT #1-** */
};



get_sfi()
{
   ENTER("get_sfi");
   (bp = bp->before)->next = 0;
   gettoken = (int (*)(void)) bp->get; /* **-PORT #1-** */
   yylval   = bval;
   LEAVE();
   return( btok);
}


void  fix_include( tok, val)
int      tok;
lword    val;
{
   ENTER("fix_include");
   btok       = tok;
   bval       = val;
   sfi.name   = bp->name;
   sfi.line   = bp->line;
   sfi.before = bp;
   sfi.next   = 0;
   bp         = bp->next = &sfi;
   gettoken   = get_sfi;
   LEAVE();
}

