/********************************************
* BASEC ANSI Library by William Yu (c)1998
*   Other libraries:
*      DOS, GRAPHICS, MM
********************************************/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <assert.h>
#include "keywords.h"

//#define DEBUG

struct dependent
  {
     byte keyid;
     short int num;
  }
  depend[100];

struct arraylist             // Array
  {
    double *value;
  }
  intarray[100];

struct arrayclist             // Array
  {
    char *value;
  }
  *chararray[100];

char *charstack[2000];       // Pointers to string in memory
dword stringsize[2000];
double *intstack[2000];    // Pointers to integers in memory
int arrshift[100];         // shift to starting point 0
int arrcshift[100];         // shift to starting point 0
int depend_stack=0;
dword gosubs[100];
int gosub_stack=0;
int returnval[50];
int return_stack=0;

dword data_seg;  // Save start of DATA SEGMENT
dword cur_dseg;
dword type_seg;  // Save start of TYPE SEGMENT

word freefile = 1;
byte freefp[101];
FILE *fpointers[101];
FILE *fp;                    // Keep track of position

double v_timer;

int screen_mode;

double evaluate_ex();
int    evaluate_strexpr(char* string);
int    eval_logical(int ex, double ex_stack[], long int *ex_stack_top);
int    PRINT_Handler(int crlf);
int    DIM_Handler();
int    IF_Handler();
int    STEP_Handler();
int    GOTO_Handler();
int    GOSUB_Handler();
int    RETURN_Handler();
double TAN_Handler();
double COS_Handler();
double SIN_Handler();
int    STRING_Handler(char* string);
int    LEFT_Handler(char* string);
int    RIGHT_Handler(char* string);
int    LCASE_Handler(char* string);
int    UCASE_Handler(char* string);


int PRINT_Handler(int crlf) {
/*************************************************************
* PRINT Statement
*************************************************************/
  char *string;

  switch (fgetc(fp))
    {
      case DT_NONE:
         cprintf("\r\n");
         fflush(stdout);
         break;
      case DT_STREXPR:
         string = (char*)malloc(2048);
         evaluate_strexpr(string);
         cprintf("%s",string);
         fflush(stdout);
         free(string);
         break;
      case DT_EXPRESSION:
         //cprintf("expression\n");
         if (crlf == TRUE)
           cprintf("%-1.6g\n",evaluate_ex());
         else
           cprintf("%-1.6g",evaluate_ex());
         fflush(stdout);
         break;
    }

  return 0;

} /** End PRINT_HANDLER **/


int DIM_Handler() {
/*************************************************************
* DIM Statement
*************************************************************/
  word length_str;
  word var_position;
  int start,end,temp;

  switch (fgetc(fp))
    {
      case DT_ARRAY:
         start = evaluate_ex();
         end = evaluate_ex();
         if (end < start)
         {
           temp = start;
           start = end;
           end = temp;
         }
         //cprintf("%d %d\n",start,end);
         switch (fgetc(fp))
           {
             case DT_STRING:
               length_str = evaluate_ex();
               fread(&var_position, 2, 1, fp);
               arrcshift[var_position] = (0 - start);
               chararray[var_position] = (struct arrayclist *)malloc(4*(end - start+1));
               for (temp=0;temp<=(end-start);temp++)
                   (chararray[var_position]+(temp*4))->value = (char *)calloc(1,255);
               break;
             case DT_INTEGER:
               fread(&var_position, 2, 1, fp);
               arrshift[var_position] = (0 - start);
               intarray[var_position].value = (double *)calloc((end-start+1),8);
               break;
           }
         break;
      case DT_STRING:
         length_str = evaluate_ex();
         fread(&var_position, 2, 1, fp);
         if (charstack[var_position] == NULL)
           {
             if (length_str == 0)
               charstack[var_position] = (char*)calloc(1,1024);
             else
               charstack[var_position] = (char*)calloc(1,length_str+1);
             stringsize[var_position] = length_str;
           }
         break;
      case DT_BYTE:
         fread(&var_position, 2, 1, fp);
         intstack[var_position] = (double*)calloc(1, 8);
         break;
      case DT_INTEGER:
         fread(&var_position, 2, 1, fp);
         if (intstack[var_position] == NULL)
           intstack[var_position] = (double*)calloc(1, 8);
         break;
    }
    /** END SWITCH **/

  return 0;
}


int IF_Handler() {
/************************************************************
*  IF Statement
*************************************************************/
  dword address;
  char* string=(char*)malloc(2048);
  int returned;

  if (fgetc(fp) == DT_STREXPR)
  {
     returned = evaluate_strexpr(string);
     if (returned == FALSE)
     {
       fread(&address,4,1,fp);
       //cprintf("address: %d\n",address);
       fseek(fp, address, SEEK_CUR);
     }
     else if (returned == TRUE)
     {
       fread(&address,4,1,fp);
     }
  }
  else
  {
     if (evaluate_ex() == FALSE)
     {
       fread(&address,4,1,fp);
       //cprintf("address: %d\n",address);
       fseek(fp, address, SEEK_CUR);
     }
     else
       fread(&address,4,1,fp);
  }

  free(string);
  return 0;

}


int GOTO_Handler() {
  long int address;

  fread(&address,4,1,fp);
  //cprintf("address %ld\n",address);
  fseek(fp, address, SEEK_CUR);

  return 0;

}


int GOSUB_Handler() {
  long int address;

  fread(&address,4,1,fp);
  gosubs[gosub_stack++] = ftell(fp);
  //cprintf("address %d\n",address);
  fseek(fp, address, SEEK_CUR);

  return 0;
}

int RETURN_Handler() {

  gosub_stack--;
  fseek(fp, gosubs[gosub_stack], SEEK_SET);

  return 0;
}


int STEP_Handler()
{
  long int temp_int;

  switch (fgetc(fp))
  {
     case DT_VARINT:
       depend[depend_stack].keyid = DT_VARINT;
       fread(&temp_int,2,1,fp);
       depend[depend_stack++].num = temp_int;
       break;
     case DT_INTEGER:
       depend[depend_stack].keyid = DT_INTEGER;
       fread(&depend[depend_stack++].num,2,1,fp);
       break;
  }

  return 0;
}


int LEFT_Handler(char* varstring)
{
  char *string=(char*)malloc(2048);
  int n,i;

  evaluate_strexpr(string);

  n = evaluate_ex();

  for (i=0;i<n;i++)
  {
     varstring[i] = string[i];
  }
  varstring[i] = 0;

  free(string);
  return 0;
}


int RIGHT_Handler(char* varstring)
{
  char *string=(char*)malloc(2048);
  int i,n,x;

  evaluate_strexpr(string);

  n = evaluate_ex();

  x=strlen(string)-n;
  if (x<0) x=0;
  for (i=x;i<strlen(string);i++)
  {
     varstring[i-x] = string[i];
  }
  varstring[i-x] = 0;

  free(string);
  return 0;
}


int MID_Handler(char* varstring)
{
  char *string=(char*)malloc(2048);
  int n1,n2,i,x;

  evaluate_strexpr(string);

  n1 = evaluate_ex();
  n2 = evaluate_ex() + n1;

  x=n1-1;
  if (x<0) x=0;
  if ((n2-1) > strlen(string)) n2 = strlen(string)+1;
  for (i=x;i<n2-1;i++)
  {
     varstring[i-x] = string[i];
  }
  varstring[i-x] = 0;

  free(string);
  return 0;
}

int LTRIM_Handler(char *text)
  {
     int i,n=0,first=TRUE;
     char *string=malloc(2048);

     evaluate_strexpr(string);

     if (strlen(string) == 0) { text[0] = 0; return 0; }

     for (i=0;i<strlen(string);i++)
       {
         if (string[i] == ' ')
           {
             if (first != TRUE)
                text[n++] = ' ';
           }
         else
           {
             first = FALSE;
             text[n++] = string[i];
           }
       }

     text[n] = 0;
     return 0;
  }
/** END LTRIM **/

int RTRIM_Handler(char *text)
  {
     int i;
     char *string=malloc(2048);

     evaluate_strexpr(string);

     strcpy(text,string);

     if (strlen(text) == 0) return 0;

     for (i=strlen(text)-1;i>=0;i--)
       {
         if (text[i]!=' ')
           {
              text[i+1] = 0;
              return 0;
           }
       }

     return 0;
  }
/** END RTRIM **/

int INSTR_Handler(word start_pos, const char *string, const char *findstr)
{
      char *p;
      word pos;

      if (start_pos == 0) start_pos = 1;

      if (start_pos > strlen(string))
            return 0;
      else  pos = start_pos - 1;    /* BASIC offsets are one-based, not
                                       zero-based as in C               */

      if (NULL != (p = strstr(string + pos, findstr)))
            return (int)(p - (char *)string) + 1; /* Position 0 = position 1 */
      else  return 0;
}


int VAL_Handler(double* num)
{
  char *string=(char*)malloc(1048);

  evaluate_strexpr(string);

  *num = atof(string);

  free(string);

  return *num;
}


int GETS_Handler(char* string)
{
  int ch;
  word i,num;

  num = evaluate_ex();

  for (i=0;i<num;i++)
    {
      ch = getchar();
      if (ch == EOF || ch == '\n') break;
      string[i] = ch;
    }
  string[i] = 0;

  return 0;
}


int STR_Handler(char* string)
{
  double num = evaluate_ex();

  sprintf(string,"%-1.6g",num);

  return 0;
}

int CHR_Handler(char* string)
{
  byte num;

  num = evaluate_ex();

  string[0] = num;
  string[1] = 0;

//  *num = atof(string);

  //return *num;
  return 0;
}


int ASC_Handler(double* num)
{
  char *string=(char*)malloc(1048);

  evaluate_strexpr(string);

  *num = string[0];

  free(string);

  return *num;
}


double COS_Handler()
{
  return cos(evaluate_ex());
}
double SIN_Handler()
{
  return sin(evaluate_ex());
}
double TAN_Handler()
{
  return tan(evaluate_ex());
}


double LOG_Handler()
{
  return log(evaluate_ex());
}
double LOG10_Handler()
{
  return log10(evaluate_ex());
}

double EXP_Handler()
{
  return exp(evaluate_ex());
}

double SQR_Handler()
{
  return sqrt(evaluate_ex());
}

double ABS_Handler()
{
  return fabs(evaluate_ex());
}

int STRING_Handler(char* string)
{
  int num1, num2;
  char *str = (char*)malloc(32000);

  num1 = evaluate_ex();

  switch (fgetc(fp))
    {
      case DT_EXPRESSION:
        num2 = evaluate_ex();
        break;
      case DT_STREXPR:
        evaluate_strexpr(str);
        num2 = str[0];
        break;
    }

  memset(string,num2,num1);
  string[num1] = 0;
  
  free(str);
  return 0;
}


int UCASE_Handler(char *string)
{
  int i, max;
  char *str = (char*)malloc(32767);

  evaluate_strexpr(str);
  max = strlen(str);

  for (i=0;i<max;i++)
    {
      string[i] = toupper(str[i]);
    }
  string[i] = 0;
  
  free(str);
  return 0;
}


int LCASE_Handler(char *string)
{
  int i, max;
  char *str = (char*)malloc(32767);

  evaluate_strexpr(str);
  max = strlen(str);

  for (i=0;i<max;i++)
    {
      string[i] = tolower(str[i]);
    }
  string[i] = 0;
  
  free(str);
  return 0;
}

int ENVIRON_Handler(char *string)
{
  char *str = (char*)malloc(2048);

  evaluate_strexpr(str);
  str[strlen(str)] = 0;

  if (getenv(str) == NULL)
    string[0] = 0;
  else
    strcpy(string, getenv(str));

  free(str);
  return 0;
}

int LEN_Handler()
{
  int i;
  char *str = (char*)malloc(32767);

  evaluate_strexpr(str);
  i = strlen(str);
  free(str);
  return i;
}

int TAB_Handler(char *string)
{
  int i,n = evaluate_ex();

  for (i=0;i<n;i++)
    {
      string[i] = ' ';
    }
  string[i] = 0;
  
  return 0;
}


int RANDOMIZE_Handler()
  {
    time_t t;

    srand((unsigned) time(&t));
  
    return 0;
  }
/** END RANDOMIZE_HANDLER **/

double RND_Handler()
  {
    double i = evaluate_ex();

    if (i == 0)
      {
        return (double)((rand()%10)*10000 + (rand()%10)*1000 + (rand()%10)*100 + (rand()%10)*10 + (rand()%10))/100000;
        //return ((double)modf((float)10/((rand()%100)+1)*16, &i));
      }
    else
      return (rand() % (int)i);
  }
/** END RND_HANDLER **/

int INT_Handler()
  {
    return ((short int)floor(evaluate_ex()));
  }
long int CLNG_Handler()
  {
    return ((long int)evaluate_ex());
  }
float CSNG_Handler()
  {
    return ((float)evaluate_ex());
  }
double CDBL_Handler()
  {
    return (evaluate_ex());
  }

int CINT_Handler()
  {
    double i = evaluate_ex(),n;

    if (modf(i, &n) >= .5)
      {
        n++;
      }

    return ((short int)n);
  }

double FIX_Handler()
  {
    double i = evaluate_ex(),n;

    modf(i, &n);

    return (n);
  }


int SLEEP_Handler()
  {
    float i = evaluate_ex(), end;
    int start;

    if (i == 0) i = 1000;  // DOS Only

    start = clock();
    end = start + (i*CLOCKS_PER_SEC);

    while (clock() < end)
      {
         //DOS Only
         if (kbhit() != 0) { getkey(); break; }
      }

    return 0;
  }
/** END SLEEP_HANDLER **/


int read_line(char *text, dword n)
  {
    int ch,i=0;

    if (n==0) n=1024;

    while ((ch = getchar()) != '\n' && ch != EOF)
      if (i < n)
        text[i++] = ch;

    text[i] = 0;
    return i;
  }


int INPUTSTR_Handler()
{
  word var;
  char *string;

  switch (fgetc(fp))
    {
      case DT_FUNCTION:
        fgetc(fp);fgetc(fp);
        DIM_Handler();
        INPUTSTR_Handler();
        break;
      case DT_STRING:
        fread(&var,2,1,fp);    
        if (stringsize[var] == 0)
          {
            charstack[var] = realloc(charstack[var],1024);
          }
        read_line(charstack[var],stringsize[var]);
        break;
      case DT_INTEGER:
        fread(&var,2,1,fp);
        string = malloc(1024);
        read_line(string,1024);
        *intstack[var] = (short int)atoi(string);
        free(string);
        break;
      case DT_LONGINT:
        fread(&var,2,1,fp);
        string = malloc(1024);
        read_line(string,1024);
        *intstack[var] = (long int)atol(string);
        free(string);
        break;
      case DT_BYTE:
        fread(&var,2,1,fp);
        string = malloc(1024);
        read_line(string,1024);
        *intstack[var] = (byte)atoi(string);
        free(string);
        break;
      case DT_WORD:
        fread(&var,2,1,fp);
        string = malloc(1024);
        read_line(string,1024);
        *intstack[var] = (word)atol(string);
        free(string);
        break;
      case DT_DWORD:
        fread(&var,2,1,fp);
        string = malloc(1024);
        read_line(string,1024);
        *intstack[var] = (dword)atol(string);
        free(string);
        break;
      case DT_SINGLE:
        fread(&var,2,1,fp);
        string = malloc(1024);
        read_line(string,1024);
        *intstack[var] = (float)atof(string);
        free(string);
        break;
      case DT_DOUBLE:
        fread(&var,2,1,fp);
        string = malloc(1024);
        read_line(string,1024);
        *intstack[var] = (double)atof(string);
        free(string);
        break;
    }
  
  return 0;
}

double GET_SWAPint(word *var_position, long int *arr_offset)
  {
     switch (fgetc(fp))
       {
         case DT_FUNCTION:
           fgetc(fp);fgetc(fp);  // we know what it is, for now
           DIM_Handler();
           return GET_SWAPint(var_position,arr_offset);
         case DT_ARRAY:
           fread(var_position,2,1,fp);
           *arr_offset = evaluate_ex();
           return *(intarray[*var_position].value+(arrshift[*var_position]+(*arr_offset)));
         case DT_INTEGER:
           fread(var_position,2,1,fp);
           return *intstack[*var_position];
           break;
       }

     return 0;
  }
/** END GET_SWAPINT **/


int GET_SWAPstr(char *string, word *var_position, long int *arr_offset)
  {
     switch (fgetc(fp))
       {
         case DT_FUNCTION:
           fgetc(fp);fgetc(fp);  // we know what it is, for now
           DIM_Handler();
           GET_SWAPstr(string, var_position, arr_offset);
           return 0;
         case DT_ARRAY:
           fread(var_position,2,1,fp);
           *arr_offset = evaluate_ex();
           strcpy(string,(chararray[*var_position]+(arrcshift[*var_position]+(*arr_offset))*4)->value);
           return 0;
         default:
           fread(var_position,2,1,fp);
           strcpy(string, charstack[*var_position]);
           break;
       }
     return 0;
  }
/** END GET_SWAPSTR **/


int SWAP_Handler()
  {
     double n1,n2,temp;
     word var1,var2;
     long int arr_offset,arr_offset2;
     char *string1,*string2;

     switch (fgetc(fp))
       {
         case DT_ARRAY:
           switch (fgetc(fp))
             {
               case DT_INTEGER:
                 n1 = GET_SWAPint(&var1,&arr_offset);
                 n2 = GET_SWAPint(&var2,&arr_offset2);
                 temp = n1;
                 n1 = n2;
                 n2 = temp;
                 *(intarray[var1].value+(arrshift[var1]+(arr_offset))) = n1;
                 *(intarray[var2].value+(arrshift[var2]+(arr_offset2))) = n2;
                 break;
               case DT_STRING:
                 string1 = (char*)malloc(1024);
                 string2 = (char*)malloc(1024);
                 GET_SWAPstr(string1,&var1,&arr_offset);
                 GET_SWAPstr(string2,&var2,&arr_offset2);
                 strcpy((chararray[var1]+(arrcshift[var1]+(arr_offset))*4)->value,string2);
                 strcpy((chararray[var2]+(arrcshift[var2]+(arr_offset2))*4)->value,string1);
                 free(string2);
                 free(string1);
                 break;
             }
           break;
         case DT_EXPRESSION:
           n1 = GET_SWAPint(&var1,&arr_offset);
           n2 = GET_SWAPint(&var2,&arr_offset2);
           temp = n1;
           n1 = n2;
           n2 = temp;
           *intstack[var1] = n1;
           *intstack[var2] = n2;
           break;
         case DT_STREXPR:
           string1 = (char*)malloc(1024);
           string2 = (char*)malloc(1024);
           GET_SWAPstr(string1,&var1,&arr_offset);
           GET_SWAPstr(string2,&var2,&arr_offset2);
           strcpy(charstack[var1],string2);
           strcpy(charstack[var2],string1);
           free(string2);
           free(string1);
           break;
       }

     return 0;
  }
/** END SWAP_HANDLER **/


int READ_Handler()
  {
    word var_position;
    char *string = (char*)calloc(1,4096);
    dword address;
    word word_num,temp_int;
    double doub_num;

    switch (fgetc(fp))
      {
             case DT_ARRAY:
                switch (fgetc(fp))
                  {
                    case DT_STRING:
                      fread(&var_position,2,1,fp);
                      temp_int = evaluate_ex();
                      address = ftell(fp);
                      fseek(fp, cur_dseg, SEEK_SET);
                      fread(&word_num,2,1,fp);
                      fread(string,word_num,1,fp);
                      cur_dseg = ftell(fp);
                      fseek(fp, address, SEEK_SET);
                      strcpy((chararray[var_position]+(arrcshift[var_position]+temp_int)*4)->value, string);
                      break;
                    case DT_INTEGER:
                      fread(&var_position,2,1,fp);
                      temp_int = evaluate_ex();
                      address = ftell(fp);
                      fseek(fp, cur_dseg, SEEK_SET);
                      fread(&word_num,2,1,fp);
                      fread(string,word_num,1,fp);
                      cur_dseg = ftell(fp);
                      fseek(fp, address, SEEK_SET);
                      doub_num = atof(string);
                      *(intarray[var_position].value+(arrshift[var_position]+temp_int)) = doub_num;
                      break;
                  }
                break;
             case DT_FUNCTION:
                fgetc(fp);fgetc(fp);
                DIM_Handler();
                READ_Handler();
                break;
             case DT_STRING:
                fread(&var_position,2,1,fp);
                address = ftell(fp);
                fseek(fp, cur_dseg, SEEK_SET);
                fread(&word_num,2,1,fp);
                fread(string,word_num,1,fp);
                cur_dseg = ftell(fp);
                fseek(fp, address, SEEK_SET);
                if (stringsize[var_position] == 0)
                  {
                    charstack[var_position] = realloc(charstack[var_position], strlen(string)+1);
                    strncpy(charstack[var_position], string, strlen(string)+1);
                  }
                else
                  {
                    strncpy(charstack[var_position], string, stringsize[var_position]);
                    charstack[var_position][stringsize[var_position]] = 0;
                  }
                free(string);
                break;
             case DT_BYTE:
                fread(&var_position,2,1,fp);
                address = ftell(fp);
                fseek(fp, cur_dseg, SEEK_SET);
                fread(&word_num,2,1,fp);
                fread(string,word_num,1,fp);
                cur_dseg = ftell(fp);
                fseek(fp, address, SEEK_SET);
                *intstack[var_position] = (byte)atoi(string);
                //cprintf("var: %d, val: %d\n",var_position,*intstack[var_position]);
                break;
             case DT_INTEGER:
                fread(&var_position,2,1,fp);
                address = ftell(fp);
                fseek(fp, cur_dseg, SEEK_SET);
                fread(&word_num,2,1,fp);
                fread(string,word_num,1,fp);
                cur_dseg = ftell(fp);
                fseek(fp, address, SEEK_SET);
                *intstack[var_position] = (short int)atoi(string);
                break;
             case DT_WORD:
                fread(&var_position,2,1,fp);
                address = ftell(fp);
                fseek(fp, cur_dseg, SEEK_SET);
                fread(&word_num,2,1,fp);
                fread(string,word_num,1,fp);
                cur_dseg = ftell(fp);
                fseek(fp, address, SEEK_SET);
                *intstack[var_position] = (word)atol(string);
                break;
             case DT_DWORD:
                fread(&var_position,2,1,fp);
                address = ftell(fp);
                fseek(fp, cur_dseg, SEEK_SET);
                fread(&word_num,2,1,fp);
                fread(string,word_num,1,fp);
                cur_dseg = ftell(fp);
                fseek(fp, address, SEEK_SET);
                *intstack[var_position] = (dword)atol(string);
                break;
             case DT_LONGINT:
                fread(&var_position,2,1,fp);
                address = ftell(fp);
                fseek(fp, cur_dseg, SEEK_SET);
                fread(&word_num,2,1,fp);
                fread(string,word_num,1,fp);
                cur_dseg = ftell(fp);
                fseek(fp, address, SEEK_SET);
                *intstack[var_position] = (long int)atol(string);
                break;
             case DT_SINGLE:
                fread(&var_position,2,1,fp);
                address = ftell(fp);
                fseek(fp, cur_dseg, SEEK_SET);
                fread(&word_num,2,1,fp);
                fread(string,word_num,1,fp);
                cur_dseg = ftell(fp);
                fseek(fp, address, SEEK_SET);
                *intstack[var_position] = (float)atof(string);
                break;
             case DT_DOUBLE:
                fread(&var_position,2,1,fp);
                address = ftell(fp);
                fseek(fp, cur_dseg, SEEK_SET);
                fread(&word_num,2,1,fp);
                fread(string,word_num,1,fp);
                cur_dseg = ftell(fp);
                fseek(fp, address, SEEK_SET);
                *intstack[var_position] = atof(string);
                break;
             case DT_EXT:
                fread(&var_position,2,1,fp);
                address = ftell(fp);
                fseek(fp, cur_dseg, SEEK_SET);
                fread(&word_num,2,1,fp);
                fread(string,word_num,1,fp);
                cur_dseg = ftell(fp);
                fseek(fp, address, SEEK_SET);
                *intstack[var_position] = atof(string);
                break;
      }
      /** END SWITCH **/

    free(string);
    return 0;
  }
/** END READ_HANDLER **/


void RESTORE_Handler()
  {
    cur_dseg = data_seg;
  }
/** END RESTORE_HANDLER **/


int GET_Var()
  {
    int i=fgetc(fp);

    if (i==DT_FUNCTION)
      {
        fgetc(fp);fgetc(fp);  /** skip ID_ANSI, IK_DIM **/
        DIM_Handler();
        i=GET_Var();
      }

    return i;
  }

void GET_File_Handler()
  {
    int i=evaluate_ex();
    int p=evaluate_ex();
    double      double_num;
    float       single_num;
    long int    long_num;
    short int   int_num;
    byte        byte_num;
    word        word_num;
    dword       dword_num;
    long double ext_num;
    word var_position,len;
    char *string = (char*)calloc(1,4096);

    if (freefp[i] == 0)
      {
        cprintf("Calling GET without OPENing file!  Abnormal termination...\n");
        exit(EXIT_FAILURE);
      }

    if (p > 0) fseek(fpointers[i], p-1, SEEK_SET);

    switch (GET_Var())
      {
             case DT_STRING:
                fread(&var_position,2,1,fp);
                len = strlen(charstack[var_position]);
                fread(string,len,1,fpointers[i]);
                strncpy(charstack[var_position], string, strlen(string)+1);
                break;
             case DT_BYTE:
                fread(&var_position,2,1,fp);
                fread(&byte_num,1,1,fpointers[i]);
                *intstack[var_position] = byte_num;
                break;
             case DT_INTEGER:
                fread(&var_position,2,1,fp);
                fread(&int_num,2,1,fpointers[i]);
                *intstack[var_position] = int_num;
                break;
             case DT_LONGINT:
                fread(&var_position,2,1,fp);
                fread(&long_num,4,1,fpointers[i]);
                *intstack[var_position] = long_num;
                break;
             case DT_WORD:
                fread(&var_position,2,1,fp);
                fread(&word_num,2,1,fpointers[i]);
                *intstack[var_position] = word_num;
                break;
             case DT_DWORD:
                fread(&var_position,2,1,fp);
                fread(&dword_num,4,1,fpointers[i]);
                *intstack[var_position] = dword_num;
                break;
             case DT_SINGLE:
                fread(&var_position,2,1,fp);
                fread(&single_num,4,1,fpointers[i]);
                *intstack[var_position] = single_num;
                break;
             case DT_DOUBLE:
                fread(&var_position,2,1,fp);
                fread(&double_num,8,1,fpointers[i]);
                *intstack[var_position] = double_num;
                break;
             case DT_EXT:
                fread(&var_position,2,1,fp);
                fread(&ext_num,10,1,fpointers[i]);
                *intstack[var_position] = ext_num;
                break;
      }
      /** END SWITCH **/

    free(string);

  }
/** END GET_FILE_HANDLER **/

void PUT_File_Handler()
  {
    int i=evaluate_ex();
    int p=evaluate_ex();
    double      double_num;
    float       single_num;
    long int    long_num;
    short int   int_num;
    byte        byte_num;
    word        word_num;
    dword       dword_num;
    long double ext_num;
    word var_position,len;
    char *string = (char*)calloc(1,4096);

    if (freefp[i] == 0)
      {
        cprintf("Calling PUT without OPENing file!  Abnormal termination...\n");
        exit(EXIT_FAILURE);
      }

    if (p > 0) fseek(fpointers[i], p-1, SEEK_SET);

    switch (GET_Var())
      {
             case DT_STRING:
                fread(&var_position,2,1,fp);
                len = strlen(charstack[var_position]);
                strncpy(string, charstack[var_position], len+1);
                fwrite(string,len,1,fpointers[i]);
                break;
             case DT_BYTE:
                fread(&var_position,2,1,fp);
                byte_num = *intstack[var_position];
                fwrite(&byte_num,1,1,fpointers[i]);
                break;
             case DT_INTEGER:
                fread(&var_position,2,1,fp);
                int_num = *intstack[var_position];
                fwrite(&int_num,2,1,fpointers[i]);
                break;
             case DT_LONGINT:
                fread(&var_position,2,1,fp);
                long_num = *intstack[var_position];
                fwrite(&long_num,4,1,fpointers[i]);
                break;
             case DT_WORD:
                fread(&var_position,2,1,fp);
                word_num = *intstack[var_position];
                fwrite(&word_num,2,1,fpointers[i]);
                break;
             case DT_DWORD:
                fread(&var_position,2,1,fp);
                dword_num = *intstack[var_position];
                fwrite(&dword_num,4,1,fpointers[i]);
                break;
             case DT_SINGLE:
                fread(&var_position,2,1,fp);
                single_num = *intstack[var_position];
                fwrite(&single_num,4,1,fpointers[i]);
                break;
             case DT_DOUBLE:
                fread(&var_position,2,1,fp);
                double_num = *intstack[var_position];
                fwrite(&double_num,8,1,fpointers[i]);
                break;
             case DT_EXT:
                fread(&var_position,2,1,fp);
                ext_num = *intstack[var_position];
                fwrite(&ext_num,10,1,fpointers[i]);
                break;

      }

    free(string);

  }
/** END PUT_FILE_HANDLER **/

void OPEN_Handler()
  {
    char *access = (char *)malloc(1);
    char *filename = (char *)calloc(1,1024);
    int filenum;
    word i;

    evaluate_strexpr(access);
    filenum = evaluate_ex();

    if (freefp[filenum] == 1)
      {
        cprintf("File number already in use!  Abnormal termination...\n");
        exit(EXIT_FAILURE);
      }

    evaluate_strexpr(filename);
    freefp[filenum] = 1;

    fpointers[filenum] = fopen(filename,"rb+");
    if (fpointers[filenum] == NULL)
       {
         fclose(fpointers[filenum]);
         fpointers[filenum] = fopen(filename,"w");
         fclose(fpointers[filenum]);
         fpointers[filenum] = fopen(filename,"rb+");
         //cprintf("File not found, %s\n",filename);
         //exit(EXIT_FAILURE);
       }

    for (i=1;i<101;i++)
      if (freefp[i] == 0)
        {
          freefile = i;
          break;
        }
  }
/** END OPEN_Handler **/


void CLOSE_Handler()
  {
    int filenum;
    word i;

    filenum = evaluate_ex();

    if (filenum == 0)
      {
        for (i=1;i<101;i++)
          if (freefp[i] == 1)
            {
              fclose(fpointers[i]);
              freefp[i] = 0;
              break;
            }
        freefile = 1;
      }
    else
      {
        fclose(fpointers[filenum]);
        freefp[filenum] = 0;
        for (i=1;i<101;i++)
          if (freefp[i] == 0)
            {
              freefile = i;
              break;
            }
      }
  }
/** END CLOSE_Handler **/


int EOF_Handler()
  {
    int i=evaluate_ex();

    return (feof(fpointers[i]));
  }

double LOF_Handler()
  {
    int i=evaluate_ex();
    long int address, lof;

    address = ftell(fpointers[i]);

    fseek(fpointers[i],0,SEEK_END);
    lof = ftell(fpointers[i]);

    fseek(fpointers[i],address,SEEK_SET);

    return lof;
  }

double LOC_Handler()
  {
    int i=evaluate_ex();

    return ftell(fpointers[i]);
  }

void SEEK_Handler()
  {
    int i=evaluate_ex();
    dword address=evaluate_ex();

    if (freefp[i] == 0)
      {
        cprintf("Calling SEEK without OPENing file!  Abnormal termination...\n");
        exit(EXIT_FAILURE);
      }

    fseek(fpointers[i],address-1,SEEK_SET);
  }
/** END SEEK_Handler **/

void KILL_Handler()
  {
    char *filename = (char *)calloc(1,1024);

    evaluate_strexpr(filename);
    remove(filename);

  }
/** END KILL_Handler **/

void SHELL_Handler()
{
  char *str = (char*)malloc(2048);

  evaluate_strexpr(str);
  str[strlen(str)] = 0;

  system(str);

  free(str);
}

void ANSI_Library() {
// PRINT, OPEN,

  switch (fgetc(fp))
  {
      case IK_PRINT:
         //cprintf("PRINT\n");
         if (screen_mode == 0)
           PRINT_Handler(TRUE);
         else
           {
             GPRINT_Handler(TRUE);
           }
         break;
      case IK_PRINT_NOCRLF:
         //cprintf("PRINT_nocrlf\n");
         if (screen_mode == 0)
           PRINT_Handler(FALSE);
         else
           {
             GPRINT_Handler(FALSE);
           }
         break;
      case IK_DIM:
         //cprintf("DIM\n");
         DIM_Handler();
         break;
      case IK_IF:
         //cprintf("IF\n");
         IF_Handler();
         break;
      case IK_GOTO:
         //cprintf("GOTO\n");
         GOTO_Handler();
         break;
      case IK_GOSUB:
         //cprintf("GOSUB\n");
         GOSUB_Handler();
         break;
      case IK_RETURN:
         //cprintf("RETURN\n");
         RETURN_Handler();
         break;
      case IK_STEP:
         //cprintf("STEP\n");
         STEP_Handler();
         break;
      case IK_INPUTSTR:
         //cprintf("INPUT\n");
         INPUTSTR_Handler();
         break;
      case IK_SWAP:
         //cprintf("SWAP\n");
         SWAP_Handler();
         break;
      case IK_RANDOMIZE:
         //cprintf("RANDOMIZE\n");
         RANDOMIZE_Handler();
         break;
      case IK_READ:
         READ_Handler();
         break;
      case IK_RESTORE:
         RESTORE_Handler();
         break;
      case IK_SLEEP:
         SLEEP_Handler();
         break;
      case IK_OPEN:
         OPEN_Handler();
         break;
      case IK_GET:
         GET_File_Handler();
         break;
      case IK_PUT:
         PUT_File_Handler();
         break;
      case IK_SEEK:
         SEEK_Handler();
         break;
      case IK_CLOSE:
         CLOSE_Handler();
         break;
      case IK_KILL:
         KILL_Handler();
         break;
      case IK_SHELL:
         SHELL_Handler();
         break;
  }

} /** Endof ANSI_Library **/


int eval_logical(int ex, double ex_stack[], long int *ex_stack_top)
{
  double integer;
  double integer2;

   switch (ex)
   {
      case EX_LESSEQ:
           (*ex_stack_top)--;
           integer = ex_stack[*ex_stack_top];
           if (*ex_stack_top != 0)
             {
               (*ex_stack_top)--;
               integer2 = ex_stack[*ex_stack_top];
             }
           else
             integer2 = 0;
           //cprintf("value: %d and %d\n",integer,integer2);
           //cprintf("LESSEQ INT2: %d  INT1: %d\n",integer2,integer);
           if (integer2 <= integer)
              ex_stack[*ex_stack_top] = TRUE;
           else
              ex_stack[*ex_stack_top] = FALSE;
           break;
      case EX_GREATEREQ:
           (*ex_stack_top)--;
           integer = ex_stack[*ex_stack_top];
           if (*ex_stack_top != 0)
             {
               (*ex_stack_top)--;
               integer2 = ex_stack[*ex_stack_top];
             }
           else
             integer2 = 0;
           //cprintf("EQ INT2: %d  INT1: %d\n",integer2,integer);
           if (integer2 >= integer)
              ex_stack[*ex_stack_top] = TRUE;
           else
              ex_stack[*ex_stack_top] = FALSE;
           break;
   }

   return ex_stack[*ex_stack_top];
}


void string_deconcat(char *str1, char *str2)
  {
  }


int evaluate_strexpr(char* string)
{
  byte keyid;
  char *temp_string=(char*)malloc(10000);
  word temp_int;
  char* strex_stack[100];           // Expression stack
  int integer,integer2;
  int strex_stack_top=0;
  int return_stack = 0;
  short int int_num,long_num;

  //strex_stack[0] = (char *)malloc(2048);

  while ((keyid=fgetc(fp)) != DT_NONE)
  {
     switch (keyid)
     {
        case DT_VARSTR:
           fread(&temp_int,2,1,fp);
           strex_stack[strex_stack_top] = (char*)malloc(strlen(charstack[temp_int])+1024);
           strcpy(strex_stack[strex_stack_top++], charstack[temp_int]);
           //cprintf("from var: %s\n",strex_stack[strex_stack_top-1]);
           break;
        case DT_STRING:
           fread(&temp_int,2,1,fp);
           strex_stack[strex_stack_top] = (char*)malloc(temp_int+1024);
           fgets(temp_string,temp_int+1,fp);
           strcpy(strex_stack[strex_stack_top++], temp_string);
           //cprintf("from str: %s\n",strex_stack[strex_stack_top-1]);
           break;
        case DT_FUNCTION:
           strex_stack[strex_stack_top] = (char*)calloc(1,10000);
           switch (fgetc(fp))
           {
              case ID_ANSI:
                switch(fgetc(fp))
                {
                   case IK_DIM:
                     free(strex_stack[strex_stack_top]);
                     DIM_Handler();
                     break;
                   case IK_LEFT:
                     LEFT_Handler(strex_stack[strex_stack_top++]);
                     break;
                   case IK_RIGHT:
                     RIGHT_Handler(strex_stack[strex_stack_top++]);
                     break;
                   case IK_MID:
                     MID_Handler(strex_stack[strex_stack_top++]);
                     break;
                   case IK_STR:
                     STR_Handler(strex_stack[strex_stack_top++]);
                     break;
                   case IK_GETS:
                     GETS_Handler(strex_stack[strex_stack_top++]);
                     break;
                   case IK_CHR:
                     CHR_Handler(strex_stack[strex_stack_top++]);
                     break;
                   case IK_STRING:
                     STRING_Handler(strex_stack[strex_stack_top++]);
                     break;
                   case IK_LCASE:
                     LCASE_Handler(strex_stack[strex_stack_top++]);
                     break;
                   case IK_UCASE:
                     UCASE_Handler(strex_stack[strex_stack_top++]);
                     break;
                   case IK_TAB:
                     TAB_Handler(strex_stack[strex_stack_top++]);
                     break;
                   case IK_LTRIM:
                     LTRIM_Handler(strex_stack[strex_stack_top++]);
                     break;
                   case IK_RTRIM:
                     RTRIM_Handler(strex_stack[strex_stack_top++]);
                     break;
                   case IK_ENVIRON:
                     ENVIRON_Handler(strex_stack[strex_stack_top++]);
                     break;
                }
                break;
              case ID_DOS:
                switch(fgetc(fp))
                  {
                    case IK_INPUT:
                      INPUT_Handler(strex_stack[strex_stack_top++]);
                      break;
                    case IK_INKEY:
                      INKEY_Handler(strex_stack[strex_stack_top++]);
                      break;
                  }
                break;
           }
           break;
        case DT_ARRAY:
           switch (fgetc(fp))
             {
               case DT_STRING:
                 strex_stack[strex_stack_top] = (char*)malloc(1024);
                 fread(&int_num,2,1,fp);
                 long_num = evaluate_ex();
                 strcpy(strex_stack[strex_stack_top++],(chararray[int_num]+(arrcshift[int_num]+long_num)*4)->value);
                 break;
             }
           break;
        case OP_ADD:
           //cprintf("add, stack = %d\n",strex_stack_top);
           strex_stack_top--;
           strcpy(temp_string, strex_stack[strex_stack_top]);
           if (strex_stack_top != 0)
           {
              free(strex_stack[strex_stack_top--]);
              strcat(strex_stack[strex_stack_top++],temp_string);
           }
           break;
        case OP_MINUS:
           //cprintf("sub, stack = %d\n",strex_stack_top);
           strex_stack_top--;
           strcpy(temp_string, strex_stack[strex_stack_top]);

           strex_stack_top--;
           strstr(strex_stack[strex_stack_top],temp_string);
           if (strex_stack_top != 0)
           {
              free(strex_stack[strex_stack_top--]);
              strcat(strex_stack[strex_stack_top++],temp_string);
           }
           break;
        case OP_AND:
           return_stack--;
           integer = returnval[return_stack];
           if (return_stack != 0)
           {
              return_stack--;
              integer2 = returnval[return_stack];
           }
           else
              integer2 = 0;
           //cprintf("OR INT2: %d  INT1: %d\n",integer2,integer);
           returnval[return_stack++] = (integer2 & integer);
           break;
        case OP_OR:
           return_stack--;
           integer = returnval[return_stack];
           if (return_stack != 0)
           {
              return_stack--;
              integer2 = returnval[return_stack];
           }
           else
              integer2 = 0;
           //cprintf("OR INT2: %d  INT1: %d\n",integer2,integer);
           returnval[return_stack++] = (integer2 | integer);
           break;
        case EX_EQUAL:
           //cprintf("EX_EQUAL\n");
           strex_stack_top--;
           strcpy(temp_string, strex_stack[strex_stack_top]);
           if (strex_stack_top != 0)
             {
               free(strex_stack[strex_stack_top--]);
               if (strcmp(temp_string,strex_stack[strex_stack_top]) == 0)
                  returnval[return_stack++] = TRUE;
               else
                  returnval[return_stack++] = FALSE;
             }
           else
             returnval[return_stack++] = TRUE;
           strex_stack_top++;
           break;
        case EX_GREATER:
           //cprintf("EX_GREATER\n");
           strex_stack_top--;
           strcpy(temp_string, strex_stack[strex_stack_top]);
           if (strex_stack_top != 0)
             {
               free(strex_stack[strex_stack_top--]);
               if (strcmp(temp_string,strex_stack[strex_stack_top]) < 0)
                  returnval[return_stack++] = TRUE;
               else
                  returnval[return_stack++] = FALSE;
             }
           else
             returnval[return_stack++] = TRUE;
           strex_stack_top++;
           break;
        case EX_LESS:
           //cprintf("EX_LESS\n");
           strex_stack_top--;
           strcpy(temp_string, strex_stack[strex_stack_top]);
           if (strex_stack_top != 0)
             {
               free(strex_stack[strex_stack_top--]);
               if (strcmp(temp_string,strex_stack[strex_stack_top]) > 0)
                  returnval[return_stack++] = TRUE;
               else
                  returnval[return_stack++] = FALSE;
             }
           else
             returnval[return_stack++] = TRUE;
           strex_stack_top++;
           break;
        case EX_LESSEQ:
           //cprintf("EX_LESS\n");
           strex_stack_top--;
           strcpy(temp_string, strex_stack[strex_stack_top]);
           if (strex_stack_top != 0)
             {
               free(strex_stack[strex_stack_top--]);
               if (strcmp(temp_string,strex_stack[strex_stack_top]) >= 0)
                  returnval[return_stack++] = TRUE;
               else
                  returnval[return_stack++] = FALSE;
             }
           else
             returnval[return_stack++] = TRUE;
           strex_stack_top++;
           break;
        case EX_GREATEREQ:
           //cprintf("EX_LESS\n");
           strex_stack_top--;
           strcpy(temp_string, strex_stack[strex_stack_top]);
           if (strex_stack_top != 0)
             {
               free(strex_stack[strex_stack_top--]);
               if (strcmp(temp_string,strex_stack[strex_stack_top]) <= 0)
                  returnval[return_stack++] = TRUE;
               else
                  returnval[return_stack++] = FALSE;
             }
           else
             returnval[return_stack++] = TRUE;
           strex_stack_top++;
           break;
        case EX_NOTEQUAL:
           //cprintf("EX_LESS\n");
           strex_stack_top--;
           strcpy(temp_string, strex_stack[strex_stack_top]);
           if (strex_stack_top != 0)
             {
               free(strex_stack[strex_stack_top--]);
               if (strcmp(temp_string,strex_stack[strex_stack_top]) != 0)
                  returnval[return_stack++] = TRUE;
               else
                  returnval[return_stack++] = FALSE;
             }
           else
             returnval[return_stack++] = TRUE;
           strex_stack_top++;
           break;

     }
  }

  strex_stack_top = 0;
  return_stack = 0;
  if (strex_stack[0] == NULL) strex_stack[0] = (char*)calloc(1,1);
  strcpy(string,strex_stack[0]);
  free(strex_stack[0]);
  free(temp_string);

  return returnval[0];
}


double evaluate_ex()
{
  byte keyid;
  double integer;
  double integer2;
  double      double_num;
  float       single_num;
  long int    long_num;
  short int   int_num;
  byte        byte_num;
  word        word_num;
  dword       dword_num;
  long double ext_num;
  double ex_stack[100];           // Expression stack
  long int ex_stack_top=0;
  char *string;
  char *findstr;

  ex_stack[0] = 0;

  while ((keyid=fgetc(fp)) != DT_NONE)
  {
     switch (keyid)
     {
        case DT_VARINT:
           fread(&word_num,2,1,fp);
           //cprintf("varint %d and value %d\n",temp_int,*intstack[temp_int]);
           ex_stack[ex_stack_top++] = *intstack[word_num];
           break;
        case DT_BYTE:
           fread(&byte_num,1,1,fp);
           ex_stack[ex_stack_top++] = byte_num;
           break;
        case DT_WORD:
           fread(&word_num,2,1,fp);
           ex_stack[ex_stack_top++] = word_num;
           break;
        case DT_DWORD:
           fread(&dword_num,4,1,fp);
           ex_stack[ex_stack_top++] = dword_num;
           break;
        case DT_INTEGER:
           fread(&int_num,2,1,fp);
           ex_stack[ex_stack_top++] = int_num;
           break;
        case DT_LONGINT:
           fread(&long_num,4,1,fp);
           ex_stack[ex_stack_top++] = long_num;
           break;
        case DT_SINGLE:
           fread(&single_num,4,1,fp);
           ex_stack[ex_stack_top++] = single_num;
           break;
        case DT_DOUBLE:
           fread(&double_num,8,1,fp);
           ex_stack[ex_stack_top++] = double_num;
           break;
        case DT_EXT:
           fread(&ext_num,10,1,fp);
           ex_stack[ex_stack_top++] = ext_num;
           break;
        case DT_ARRAY:
           switch (fgetc(fp))
             {
               case DT_INTEGER:
                 fread(&word_num,2,1,fp);
                 long_num = evaluate_ex();
                 //cprintf("%ld\n",long_num);
                 ex_stack[ex_stack_top++] = *(intarray[word_num].value+(arrshift[word_num]+long_num));
                 break;
             }
           break;
        case DT_FUNCTION:
           switch (fgetc(fp))
           {
              case ID_ANSI:
                 switch (fgetc(fp))
                 {
                    case IK_VAL:
                       VAL_Handler(&double_num);
                       ex_stack[ex_stack_top++] = double_num;
                       break;
                    case IK_ASC:
                       ASC_Handler(&double_num);
                       ex_stack[ex_stack_top++] = double_num;
                       break;
                    case IK_COS:
                       ex_stack[ex_stack_top++] = COS_Handler();
                       break;
                    case IK_SIN:
                       ex_stack[ex_stack_top++] = SIN_Handler();
                       break;
                    case IK_TAN:
                       ex_stack[ex_stack_top++] = TAN_Handler();
                       break;
                    case IK_SQR:
                       ex_stack[ex_stack_top++] = SQR_Handler();
                       break;
                    case IK_ABS:
                       ex_stack[ex_stack_top++] = ABS_Handler();
                       break;
                    case IK_LOG:
                       ex_stack[ex_stack_top++] = LOG_Handler();
                       break;
                    case IK_LOG10:
                       ex_stack[ex_stack_top++] = LOG10_Handler();
                       break;
                    case IK_EXP:
                       ex_stack[ex_stack_top++] = EXP_Handler();
                       break;
                    case IK_LEN:
                       ex_stack[ex_stack_top++] = LEN_Handler();
                       break;
                    case IK_RND:
                       ex_stack[ex_stack_top++] = RND_Handler();
                       break;
                    case IK_INT:
                       ex_stack[ex_stack_top++] = INT_Handler();
                       break;
                    case IK_FIX:
                       ex_stack[ex_stack_top++] = FIX_Handler();
                       break;
                    case IK_CINT:
                       ex_stack[ex_stack_top++] = CINT_Handler();
                       break;
                    case IK_CDBL:
                       ex_stack[ex_stack_top++] = CDBL_Handler();
                       break;
                    case IK_CSNG:
                       ex_stack[ex_stack_top++] = CSNG_Handler();
                       break;
                    case IK_CLNG:
                       ex_stack[ex_stack_top++] = CLNG_Handler();
                       break;
                    case IK_EOF:
                       ex_stack[ex_stack_top++] = EOF_Handler();
                       break;
                    case IK_LOF:
                       ex_stack[ex_stack_top++] = LOF_Handler();
                       break;
                    case IK_LOC:
                       ex_stack[ex_stack_top++] = LOC_Handler();
                       break;
                    case IK_FREEFILE:
                       ex_stack[ex_stack_top++] = freefile;
                       break;
                    case IK_TIMER:
                       v_timer = clock();
                       ex_stack[ex_stack_top++] = (double)v_timer/CLOCKS_PER_SEC;
                       break;
                    case IK_INSTR:
                       string = (char*)malloc(2048);
                       findstr = (char*)malloc(2048);
                       word_num = evaluate_ex();
                       evaluate_strexpr(string);
                       evaluate_strexpr(findstr);
                       ex_stack[ex_stack_top++] = INSTR_Handler(word_num, string, findstr);
                       free(findstr);
                       free(string);
                 }
                 break;
              case ID_GRAPHICS:
                 switch (fgetc(fp))
                   {
                     case IK_POINT:
                       ex_stack[ex_stack_top++] = POINT_Handler();
                       break;
                   }
                 break;
              case ID_MM:
                 switch (fgetc(fp))
                   {
                     case IK_RUNMP3:
                       //ex_stack[ex_stack_top++] = RUNMP3_Handler();
                       break;
                     case IK_BITRATEMP3:
                       //ex_stack[ex_stack_top++] = BITRATEMP3_Handler();
                       break;
                     case IK_SAMPRATEMP3:
                       //ex_stack[ex_stack_top++] = SAMPRATEMP3_Handler();
                       break;
                     case IK_POLLSIZEMP3:
                       //ex_stack[ex_stack_top++] = POLLSIZEMP3_Handler();
                       break;
                     case IK_STEREOMP3:
                       //ex_stack[ex_stack_top++] = STEREOMP3_Handler();
                       break;
                   }
                 break;

           }
           break;           
        case EX_DEPEND:
           if (depend[depend_stack-1].keyid == DT_VARINT)
             integer = *intstack[depend[depend_stack-1].num];
           else
             integer = depend[depend_stack-1].num;
           if (integer > 0)
           {
              if (eval_logical(EX_LESSEQ, ex_stack, &ex_stack_top) == FALSE)
                 depend_stack--;
           }
           else
           {
              if (eval_logical(EX_GREATEREQ, ex_stack, &ex_stack_top) == FALSE)
                 depend_stack--;
           }
           break;
        case OP_ADD:
           ex_stack_top--;
           integer = ex_stack[ex_stack_top];
           if (ex_stack_top != 0)
           {
              ex_stack_top--;
              integer2 = ex_stack[ex_stack_top];
           }
           else
              integer2 = 0;
           //cprintf("ADD INT2: %d  INT1: %d\n",integer2,integer);
           ex_stack[ex_stack_top++] = integer2 + integer;
           break;
        case OP_MINUS:
                       ex_stack_top--;
                       integer = ex_stack[ex_stack_top];
                       if (ex_stack_top != 0)
                       {
                         ex_stack_top--;
                         integer2 = ex_stack[ex_stack_top];
                       }
                       else
                         integer2 = 0;
                       //cprintf("SUB INT2: %d  INT1: %d\n",integer2,integer);
                       ex_stack[ex_stack_top++] = integer2 - integer;
                       break;
                     case OP_MULT:
                       ex_stack_top--;
                       integer = ex_stack[ex_stack_top];
                       if (ex_stack_top != 0)
                       {
                         ex_stack_top--;
                         integer2 = ex_stack[ex_stack_top];
                       }
                       else
                         integer2 = 0;
                       //cprintf("MUL INT2: %g  INT1: %g\n",integer2,integer);
                       ex_stack[ex_stack_top++] = integer2 * integer;
                       break;
                     case OP_DIVIDE:
                       ex_stack_top--;
                       integer = ex_stack[ex_stack_top];
                       if (ex_stack_top != 0)
                       {
                         ex_stack_top--;
                         integer2 = ex_stack[ex_stack_top];
                       }
                       else
                         integer2 = 0;
                       //cprintf("DIV INT2: %d  INT1: %d\n",integer2,integer);
                       if (integer == 0)
                         ex_stack[ex_stack_top] = 0;
                       else
                         ex_stack[ex_stack_top] = integer2 / integer;
                       ex_stack_top++;
                       break;
                     case OP_POWER:
                       ex_stack_top--;
                       integer = ex_stack[ex_stack_top];
                       if (ex_stack_top != 0)
                       {
                         ex_stack_top--;
                         integer2 = ex_stack[ex_stack_top];
                       }
                       else
                         integer2 = 0;
                       //cprintf("POW INT2: %d  INT1: %d\n",integer2,integer);
                       ex_stack[ex_stack_top++] = pow(integer2, integer);
                       break;
                     case OP_AND:
                       ex_stack_top--;
                       integer = ex_stack[ex_stack_top];
                       if (ex_stack_top != 0)
                       {
                         ex_stack_top--;
                         integer2 = ex_stack[ex_stack_top];
                       }
                       else
                         integer2 = 0;
                       //cprintf("AND INT2: %d  INT1: %d\n",integer2,integer);
                       ex_stack[ex_stack_top++] = ((int)integer2 & (int)integer);
                       break;
                     case OP_OR:
                       ex_stack_top--;
                       integer = ex_stack[ex_stack_top];
                       if (ex_stack_top != 0)
                       {
                         ex_stack_top--;
                         integer2 = ex_stack[ex_stack_top];
                       }
                       else
                         integer2 = 0;
                       //cprintf("OR INT2: %d  INT1: %d\n",integer2,integer);
                       ex_stack[ex_stack_top++] = ((int)integer2 | (int)integer);
                       break;
                     case OP_XOR:
                       ex_stack_top--;
                       integer = ex_stack[ex_stack_top];
                       if (ex_stack_top != 0)
                       {
                         ex_stack_top--;
                         integer2 = ex_stack[ex_stack_top];
                       }
                       else
                         integer2 = 0;
                       //cprintf("XOR INT2: %d  INT1: %d\n",integer2,integer);
                       ex_stack[ex_stack_top++] = ((int)integer2 ^ (int)integer);
                       break;
                     case OP_NOT:
                       if (ex_stack_top != 0)
                       {
                         ex_stack_top--;
                         integer = ex_stack[ex_stack_top];
                       }
                       else
                         integer = 0;
                       //cprintf("NOT INT: %d\n",integer);
                       ex_stack[ex_stack_top++] = ~((int)integer);
                       break;
        case OP_MOD:
           ex_stack_top--;
           integer = ex_stack[ex_stack_top];
           if (ex_stack_top != 0)
             {
               ex_stack_top--;
               integer2 = ex_stack[ex_stack_top];
             }
           else
             integer2 = 0;
           //cprintf("MOD INT2: %d  INT1: %d\n",(int)integer2,(int)integer);
           if (integer == 0)
              ex_stack[ex_stack_top] = 0;
           else
              ex_stack[ex_stack_top] = (int)integer2 % (int)integer;
           ex_stack_top++;
           break;
        case EX_EQUAL:
           ex_stack_top--;
           integer = ex_stack[ex_stack_top];
           if (ex_stack_top != 0)
             {
               ex_stack_top--;
               integer2 = ex_stack[ex_stack_top];
               if (integer2 == integer)
                  ex_stack[ex_stack_top] = -1;
               else
                  ex_stack[ex_stack_top] = FALSE;
             }
           else
             ex_stack[ex_stack_top] = FALSE;
           //cprintf("EQ INT2: %d  INT1: %d\n",integer2,integer);
           ex_stack_top++;
           break;
        case EX_GREATER:
           ex_stack_top--;
           integer = ex_stack[ex_stack_top];
           if (ex_stack_top != 0)
             {
               ex_stack_top--;
               integer2 = ex_stack[ex_stack_top];
             }
           else
             integer2 = 0;
           //cprintf("EQ INT2: %d  INT1: %d\n",integer2,integer);
           if (integer2 > integer)
              ex_stack[ex_stack_top] = -1;
           else
              ex_stack[ex_stack_top] = FALSE;
           ex_stack_top++;
           break;                       
        case EX_LESS:
           ex_stack_top--;
           integer = ex_stack[ex_stack_top];
           if (ex_stack_top != 0)
             {
               ex_stack_top--;
               integer2 = ex_stack[ex_stack_top];
             }
           else
             integer2 = 0;
           //cprintf("EQ INT2: %d  INT1: %d\n",integer2,integer);
           if (integer2 < integer)
              ex_stack[ex_stack_top] = -1;
           else
              ex_stack[ex_stack_top] = FALSE;
           ex_stack_top++;
           break;
        case EX_NOTEQUAL:
           ex_stack_top--;
           integer = ex_stack[ex_stack_top];
           if (ex_stack_top != 0)
             {
               ex_stack_top--;
               integer2 = ex_stack[ex_stack_top];
             }
           else
             integer2 = 0;
           //cprintf("EQ INT2: %d  INT1: %d\n",integer2,integer);
           if (integer2 != integer)
              ex_stack[ex_stack_top] = -1;
           else
              ex_stack[ex_stack_top] = FALSE;
           ex_stack_top++;
           break;
        case EX_GREATEREQ:
           eval_logical(EX_GREATEREQ, ex_stack, &ex_stack_top);
           ex_stack_top++;
           break;
        case EX_LESSEQ:
           eval_logical(EX_LESSEQ, ex_stack, &ex_stack_top);
           ex_stack_top++;
           break;
     }
  }
  //cprintf("hmm %d\n",ex_stack[ex_stack_top-1]);
  ex_stack_top = 0;

  return ex_stack[0];
}


void VARIABLE_Library() {
  word var_position;
  char *string;
  int temp_int;

  switch (fgetc(fp))
  {
      case IK_ASSIGNMENT:
         switch (fgetc(fp))
         {
             case DT_ARRAY:
                switch (fgetc(fp))
                  {
                    case DT_STRING:
                      fread(&var_position,2,1,fp);
                      temp_int = evaluate_ex();
                      string = (char*)calloc(1,1024);
                      evaluate_strexpr(string);
                      strcpy((chararray[var_position]+(arrcshift[var_position]+temp_int)*4)->value, string);
                      free(string);
                      break;
                    case DT_INTEGER:
                      fread(&var_position,2,1,fp);
                      temp_int = (int)evaluate_ex();
                      *(intarray[var_position].value+(arrshift[var_position]+temp_int)) = evaluate_ex();
                      break;
                  }
                break;
             case DT_STRING:
                fread(&var_position,2,1,fp);
                string = (char*)malloc(32768);
                evaluate_strexpr(string);
                if (stringsize[var_position] == 0)
                  {
                    charstack[var_position] = realloc(charstack[var_position], strlen(string)+1);
                    strncpy(charstack[var_position], string, strlen(string)+1);
                  }
                else
                  {
                    strncpy(charstack[var_position], string, stringsize[var_position]);
                    charstack[var_position][stringsize[var_position]] = 0;
                  }
                free(string);
                //STRING_Handler();
                break;
             case DT_BYTE:
                fread(&var_position,2,1,fp);
                *intstack[var_position] = (byte)evaluate_ex();
                //cprintf("var: %d, val: %d\n",var_position,*intstack[var_position]);
                break;
             case DT_INTEGER:
                fread(&var_position,2,1,fp);
                *intstack[var_position] = (short int)evaluate_ex();
                break;
             case DT_WORD:
                fread(&var_position,2,1,fp);
                *intstack[var_position] = (word)evaluate_ex();
                break;
             case DT_DWORD:
                fread(&var_position,2,1,fp);
                *intstack[var_position] = (dword)evaluate_ex();
                break;
             case DT_LONGINT:
                fread(&var_position,2,1,fp);
                *intstack[var_position] = (long int)evaluate_ex();
                break;
             case DT_SINGLE:
                fread(&var_position,2,1,fp);
                *intstack[var_position] = (float)evaluate_ex();
                break;
             case DT_DOUBLE:
                fread(&var_position,2,1,fp);
                *intstack[var_position] = evaluate_ex();
                break;
             case DT_EXT:
                fread(&var_position,2,1,fp);
                *intstack[var_position] = evaluate_ex();
                break;
         }
         //fseek(fp, savepos, SEEK_SET);
         break;
  }
}


int main (int argc, char *argv[]) {
        dword len_byte_code;
        byte  Lib_ID,i;

        v_timer = clock();
        screen_mode = 0;
        fp = fopen(argv[0], "rb");
        fseek(fp, -8L, SEEK_END);
        fread(&data_seg,4,1,fp);
        fread(&len_byte_code,4,1,fp);
        #if defined(DEBUG)
          cprintf("Byte code length: %d\n",len_byte_code);
          cprintf("Data segment:     %d\n",data_seg);
        #endif

        fseek(fp, -(len_byte_code+data_seg+8), SEEK_END);
        data_seg = ftell(fp) + len_byte_code;
        cur_dseg = data_seg;

        for (i=0;i<101;i++)     /** reset free file pointers **/
          freefp[i] = 0;

        while ((Lib_ID = fgetc(fp)) != 255)
        {
          switch (Lib_ID)
          {
            case ID_ANSI:
               ANSI_Library();
               break;
            case ID_DOS:
               DOS_Library();
               break;
            case ID_GRAPHICS:
               GRAPHICS_Library();
               break;
            //case ID_MM:
            //   MM_Library();
            //   break;
            case ID_VARIABLE:
               VARIABLE_Library();
               break;
          }
        }
        //cprintf(argv[0]);
        fclose(fp);

  return 0;
}
