#define CPRINT_DEF
#include "mit2mot.config.h"

static int error_counter;
static int machine;
static FILE *null_device=NULL;
FILE *fd_out;
extern FILE *yyin;
static int buffer_usage = 0;
static int buffer_overflow = 0; /* FALSE */
#define MC_68010 1
#define MC_68020 2
#define MC_68881 4

void yyparse(void);

int main(int argc,const char ** argv)
{
unsigned short n,i,arg_no;
int flags;
char buffer[128];
const char *source;
#define HELP 1
#define ASM_SUFFIX 2

#ifdef YYDEBUG
extern yydebug;
yydebug = 0;
#endif

yyin = stdin;
fd_out = stdout;
flags = 0;
n=1;
for (arg_no=1; n<argc && arg_no>0 && arg_no<3; n++)
  { 
  if (strcmp("-",argv[n])==0)
    arg_no++;
  else if (strcmp("--",argv[n])==0)
    SetDraussen();
  else if (strcmp("-c",argv[n])==0)
    SetDraussen();
#ifdef YYDEBUG
  else if (strcmp("-d",argv[n])==0)
    yydebug = 1;
#endif
  else if (strcmp("-h",argv[n])==0)
    {
    flags |= HELP;
    n++;
    break;
    }
  else if (strcmp("-a",argv[n])==0)
    flags |= ASM_SUFFIX;
  else if (arg_no==1) 
    {
    if ((yyin=fopen(argv[n],"r"))==NULL) arg_no=0;
    else 
      {
      arg_no++;
      if (flags&ASM_SUFFIX)
        {
        source=argv[n];
        strncpy(buffer,argv[n],120);
        i=strlen(buffer);
        if (i>2)
          if (strcmp(".s",buffer+i-2)==0)
            *(buffer+i-2)=0;
        strcat(buffer,".asm");
        if ((fd_out=fopen(buffer,"w"))==NULL) arg_no=0;
        else arg_no++;
        }
      }        
    }
  else if (arg_no==2)
    {
    if ((fd_out=fopen(argv[n],"w"))==NULL) arg_no=0;
    else arg_no++;
    }
  }
if (arg_no==0 ) /* Fall 1: Fehler beim oeffnen. */
  fprintf(stderr,"Die Datei kann nicht geoeffnet werden.\n");
else if (!(flags&HELP)&&(n<=argc))
  /* Fall 2: alles klar zum kovertieren. */
  {
  if (arg_no==3 && flags&ASM_SUFFIX)
    fprintf(stderr,"mit2mot: converting %s to %s.\n",source,buffer);
  cprintfclear();  /* Intialisieren des cprintf - Buffers */
  lexnextline();   /* Intitialisieren des Zeilen - Buffers im lex.
                      Die Zeilen werden gebuffert fuer:
                      a. Fehlermeldungen */
  error_counter=0; /* Intitialisieren des Fehlerzaehlers */
  fprintf(fd_out,"\tfar code\n\tfar data\n");
  yyparse();       /* Starten von "bison"(c) */
  PrintLabels();
  fprintf(fd_out,";ERRORS: %d\n",error_counter);
  if (buffer_overflow) 
    fprintf(stdout,";WARNING: Buffer-Ueberlauf. \n%s\n",
        ";         Bemerkungen wurden teilweise abgeschnitten." );
  if (machine&MC_68020)
    fprintf(fd_out,";MACHINE: mc68020\n");
  else if (machine&MC_68010)
    fprintf(fd_out,"MACHINE: mc68010\n");
  if (machine&MC_68881)
    fprintf(fd_out,";MACHINE: mc68881\n");
/*fprintf(fd_out,";Buffer usage of cprintf-buffer=%d\n",buffer_usage);*/
  fprintf(stderr,";mit2mot: ERRORS <stderr>: %d\n",error_counter);
  if (buffer_overflow)
    fprintf(stdout,"mit2mot: WARNING <stderr>: buffer overflow. "
      " comments have been cutted." );
  if (yyin!=stdin) fclose(yyin);
  if (fd_out!=stdout) fclose(fd_out);
  }
else /* Fall 3: Help oder falsche Eingabe */
  {
  fprintf(stderr,
"USAGE:                                                                         \n"
"  mit2mot [-c]                              converts standard input to		\n"
"                                            standard output			\n"
"  mit2mot [-c] <filename.s>                 converts `filename.s' and sends the\n"
"                                            result to standard output.		\n"
"  mit2mot [-c] -a <filename.s>              converts `filename.s'              \n"
"                                            to `filename.asm'                  \n"
"  mit2mot [-c] <input-file> <output-file>   converts `input-file' to           \n"
"                                            to `output-file'                   \n"
"  mit2mot -h                                prints usage text			\n"
"                                                                               \n"
"OPTIONS:									\n"
"  The option -c changes the syntax for immediate addresses                     \n"
"  in the output (prints `-2(a0)' instead of `(-2,a0)'.                         \n"
"  The option -h prints a usage text.                                           \n"
);
  exit(0);
  }
exit(0);
}

/* die Funktionen Setmc...()  setzen Flags wenn die
   verschiedenen Prozessortypen erkannt wurden */
void Setmc68010(void)	{ machine|=MC_68010; }
void Setmc68020(void)	{ machine|=MC_68020; }
void Setmc68881(void)	{ machine|=MC_68881; }

static int c_pos;
static char buffer[ CPRINTF_BUFFER+CPRINTF_RESERVE ];
#ifndef NULL_DEVICE
static char dummy_buffer[1024];
#endif

void cprintfclear(void)		{
                                  c_pos=0;
                                }
/* Loeschen des cprintf - Buffers */

char *cprintf(const char * format,const char *  arg1,const char *  arg2,const char * arg3,const char * arg4,const char * arg5,const char * arg6,const char * arg7,const char * arg8, const char * arg9 , const char * arg10, const char * arg11, const char * arg12 )
/* cprintf() ergibt eine Zeichenkette, die wie bei printf() 
   erzeugt wird. Die Zeichenkette wird in einen internen buffer
   geschrieben. Der Zeiger auf den Buffer ist das Ergebnis. 
   Aehnliche Funktion: cprintfappend();
*/
{
char *ret_value;
int len;
static int not_warned = 1;

    ret_value=buffer+c_pos;
    sprintf(ret_value, format, arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12);
    len=strlen( ret_value );
    c_pos = c_pos+len+1;
    if (c_pos>buffer_usage) buffer_usage=c_pos;
    if (buffer_usage>CPRINTF_BUFFER+CPRINTF_RESERVE/2 && not_warned)
      {
      fprintf(stderr,
        "Warnung: Der interne Buffer koennte demnaechst ueberlaufen.\n"
        "  Laeuft der Buffer ueber, bricht das Programm ab.\n"
        "  Sie muessen dann entweder die Zeilen im Source teilen, oder\n"
        "  im File mit2mot.config.h die Werte CPRINTF_BUFFER und\n"
        "  C_PRINTF_RESERVE erhoehen - dann neu Ubersetzen.\n");
      not_warned=0;
      }
    if (buffer_usage>CPRINTF_BUFFER+(CPRINTF_RESERVE*3)/2)
      {
      fprintf(stderr,"FATAL-ERROR: Buffer ueberlauf.\n");
      exit(1);
      }
    return ret_value;
}

void cprintf_char( char zeich )
/* Haengt ein einzelnes Zeichen hinten an den cprintf_buffer.
   Diese Funktion ist nur sinnvoll in Kombination mit
   der Funktion cprintfappendinit. Es ist nicht garantiert, dass
   die Zeichenkette mit einem \0 Character (0-Zeichen) endet.
   Daher muss die Konstrunktion von Zeichenketten mit
   der Funktion cprintf_char() wie folgt aussehen:
       zeichenkette=cprintfappendinit();
       cprintf_char( zeichen );
       ...
       cprintf_char( (char)0 ); 
   Laeuft der Buffer ueber, werden die letzten Zeichen einfach
   abgeschnitten (keine Fehlermeldung). */
{
  buffer[c_pos-1]=zeich;
  if (c_pos<CPRINTF_REMARK_BUFFER) c_pos++;
  else buffer_overflow = 1; /* TRUE */
  if (c_pos>buffer_usage) buffer_usage=c_pos;
}

char *cprintfappendinit()
{
char *ret_value;
ret_value=buffer+c_pos;
*ret_value=0;
c_pos++;
return ret_value;
}

void cprintfappend(const char * format,const char *  arg1,const char * arg2, const char * arg3,const char * arg4,const char * arg5,const char * arg6,const char * arg7,const char * arg8, const char * arg9 , const char * arg10, const char * arg11 , const char * arg12 )
/* Arbeitet wie cprintf(), jedoch wird das 0 Character des letzten Strings
   ueberschrieben. So kann man ein "anhaengen" an die letzte Zeichenkette
   realisieren, ohne dass der Buffer superschnell ueberlaeuft. Bei
   cprintfappend() sollte nicht auf den letzten von cprintf() erzeugten
   String zugegriffen werden, da die Routine sonst zu Fehlern fuehrt.
   Das Aufrufmuster zur benutzung von cprintfappend() sieht wie folgt aus:
        result=cprintfappendinit(); Initialisieren des Anfangs des Strings
        for (i=0; i<10; i++)        Die Schleife erzeugt eine Listen von
          cprintfappend("%d,");        Zahlen von 0 bis 9
        printf(result);             Gibt "0,1,2,3,4,5,6,7,8,9," aus. 
*/
{
if (c_pos>0) c_pos--;
cprintf( format, arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12);
}

int yywrap(void)
/* yywrap() wird von lex aufgerufen, wenn ein lesen von stdin einen
   EOF (End Of File) ergibt. Ist das Ergebnis 0, so kann erneut weiter
   von stdin gelesen werden, sonst muss das Ergebnis 1 sein. */
{
return 1;
}

void yyerror(char *s)
/* yyerror() wird von bison(c) bei Parser-Fehlern oder bei
   Speicher-Ueberlauf-Fehlern aufgerufen */
{
fprintf(fd_out,";ERROR: %s\n",s);
error_counter++;  /* Zaehlen der Fehler, Ausgabe der Fehlermeldung
                     geschieht in bison */
}
