#include <iostream.h>
#include <fstream.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <conio.h>

#include "list.h"

const int  MAXBUFF= 512;
char _line[MAXBUFF];

typedef struct
{
 char *replace;
 char *with;
 int special;
} SIMPLE_REPLACE;

#define T_NOT_SPECIAL 0
#define T_INCLUDE 1
#define T_ASSIGN 2

SIMPLE_REPLACE simple_replace[]=
{
 {"INCLUDE", ".include", T_INCLUDE},
 {"EQU", " = ", T_ASSIGN},
 {"FDB", ".dw", T_NOT_SPECIAL},
 {"FCB", ".db", T_NOT_SPECIAL},
 {"FCC", ".ascii", T_NOT_SPECIAL},
 {"END", "; END", T_NOT_SPECIAL},
 {"LIST", "; LIST", T_NOT_SPECIAL},
 {"SETDP", "; SETDP", T_NOT_SPECIAL},
 {NULL,NULL}
};
char *line=_line;
char *alternate_var;
char *var;
ZeigerListe <char> program;
ZeigerListe <char> cnt;

void cnt_from_list(void);
int do_comments=1;

int main( int argc, char* argv[] )
{
 int line_counter=0;              // bei welcher Zeile sind wir gerade, nicht sicher, ob diese immer stimmt
 cout <<"\nCalling of";
 for (int ii=0;ii<argc;ii++)
  cout <<" "<<argv[ii];
 cout << "\n";
 if ( argc < 3 )
 {
  cout << "Usage: transl <infile> <outfile> <comment>\n";
  return 1;
 }
 if (argc>3) do_comments=0;
 if (!strcmp(argv[1],argv[2]))
 {
  cout << "<infile> == <outfile>, NOT ALLOWED\n";
  return 1;
 }
 ifstream inFile( argv[1] );
 ofstream outFile( argv[2] );


 // read program
 while( inFile.getline( line, MAXBUFF ) )  // read file
 {
  char *newline=(char *)malloc(MAXBUFF+1);
  if (newline==NULL)
  {
   printf("\nMalloc Error!");
   exit(1);
  } // if (newline==NULL)
  strcpy(newline,line);
  program.append(newline);
 } // while( inFile.getline( line, MAXBUFF ) )
 inFile.close();


 cnt_from_list();


 // write program
 cnt.first();
 while (cnt.isLast()==false)
 {
  outFile << cnt.retrieve() << "\n";
  cnt.removeWithElementDelete();
 } //while (cnt.isLast()==false)
 outFile.close();

 program.first();
 while (program.isLast()==false)
 {
  program.removeWithElementDelete();
 } //while (program.isLast()==false)
 return 0;
}

void insert_before(char *line, char *insert)
{
 static char _line[MAXBUFF];
 strcpy(_line,line);
 line[0]=0;
 strcat(line,insert);
 strcat(line,_line);
}
/* NOT parser specific yet, uses fgets and fputs instead of PARSE_END_OF_LINE */
/* replace every occurence of define with value */
int replace(char * line, char * define, char * value)
{
 static char _line[MAXBUFF];
 char *pos;
 int posi=0;
 int replaced=0;
 pos=line;
 pos=strstr(pos,define);
 while (pos)
 {
  replaced++;
  posi=pos-line;
  strcpy(_line,line);
  *strstr(_line+posi,define)=(char)0;
  strcat(_line,value);
  strcat(_line,pos+strlen(define));
  strcpy(line,_line);
  pos=line+posi+strlen(value);
  pos=strstr(pos,define);
 } // while ((pos=strstr(pos,define)))
 return replaced;
}
void remove_current_char(char * string)
{
 while (*string!=0)
 {
  *string=(*(string+1));
  string++;
 }
}

void remove_all_spaces(char *string)
{
 while (*string!=0)
 {
  if (isspace(*string))
   remove_current_char(string);
  else
   string++;
 }
}

void cnt_from_list(void)
{
 int i;
 char *newline=NULL;
 char *last_address="0000";
 int in_symbol_table=false;
 int after_symbol=false;
 int in_prog=false;

 program.first();
 while (program.isLast()==false)
 {
  i=0;
  line=program.retrieve();
  if (strstr(line,"Symbol   Value        Decimal"))
  {
   in_symbol_table=true;
  }
  if (strstr(line,"labels used"))
  {
   in_symbol_table=false;
   after_symbol=true;
  }
  if (in_symbol_table==true)
  {
   if (strstr(line,":"))
   {
    if (!strstr(line," <macro>"))
    {
     char *label;
     char *address;
     char *testline;
     int lpos=program.getPos();
     int is_equ=false;
     int is_label=false;
     label=strdup(line);
     strtok(label,":");
     remove_all_spaces(label);
     address=strdup(1+strstr(line,"$"));
     *(address+4)=0;
     if (!strstr(line,"-"))
     {
      if (*address>='c') is_label=true;
     }
     else
     {
      remove_current_char(address);
      remove_current_char(address);
     }
     while (program.isLast()==false)
     {
      i=0;
      testline=program.retrieve();
      if (strstr(testline,label))
      {
       if (*(strstr(testline,label)+strlen(label))==':')
       {
        is_label=true;
        if (is_equ==true) break;
       }
       else if (strstr(testline,"#"))
       {
         is_equ=true;
        if (is_label==true) break;
       }
      }
      program.next();
     } //while (program.isLast()==false)

     if (is_equ==true)
     {
      newline=(char *)malloc(MAXBUFF+1);
      if (newline==NULL)
      {
       printf("\nMalloc Error!");
       exit(1);
      } // if (newline==NULL)
      sprintf(newline,"EQU \"%s\" 0x%s ",label,address);
      cnt.append(newline);
     }
//     else is_label=true;
     if (is_label==true)
     {
      newline=(char *)malloc(MAXBUFF+1);
      if (newline==NULL)
      {
       printf("\nMalloc Error!");
       exit(1);
      } // if (newline==NULL)
      sprintf(newline,"LABEL   0x%s \"%s\"",address,label);
      cnt.append(newline);
     }
     free(label);
     free(address);
     program.setPos(lpos); // 0..ende-1


    }
   }
  } //if (in_symbol_table==true)
  if (after_symbol==true)
  {
   if (*(line+5)==':')
   {
    char *address=strdup(line);
    in_prog=true;

    *(address+4)=0;
    if (do_comments==1)
    if (strstr(line,";"))
    {
     char *comment=strdup(strstr(line,";"));
     newline=(char *)malloc(MAXBUFF+1);
     if (newline==NULL)
     {
      printf("\nMalloc Error!");
      exit(1);
     } // if (newline==NULL)
     sprintf(newline,"COMMENT   0x%s \"%s\"",address,comment);
     cnt.append(newline);
     free(comment);
    }
    strcpy (last_address,address);
    free(address);

   } // if (*(line+5)==':')
   else
   {
    if (in_prog==true)
    {
     if (do_comments==1)
     if (strstr(line,";"))
     {
      char *comment=strdup(strstr(line,";"));
      newline=(char *)malloc(MAXBUFF+1);
      if (newline==NULL)
      {
       printf("\nMalloc Error!");
       exit(1);
      } // if (newline==NULL)
      sprintf(newline,"COMMENT_LINE   0x%s \"%s\"",last_address,comment);
      cnt.append(newline);
      free(comment);
     }
    } //if (in_prog==true)
   }
  }

//0000 : 67204743452031..                      DB      "g GCE 1998", $80  ; 'g'

  program.next();
 } //while (program.isLast()==false)
}
