/*
** _main() function for vbcc-Amiga-PowerPC
**
** based on machines/m68k/libsrc/_main.c by Volker Barthelmann
**
**
** V0.3 18-Oct-97 phx
**      Opens the dos.library and initializes DOSBase.
**      IsInteractive() is available now. startup.s was improved
**      to work with stdin/stdout redirection and to supply us
**      with SysBase.
** V0.2 07-Oct-97 phx
**      There is no IsInteractive() in the PowerUp-Kernel. Also, the
**      current startup code only works with CONSOLE:.
** V0.1 04-Oct-97 phx
**      adapted
*/

#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>

#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/libraries.h>
#include <powerup/gcclib/powerup_protos.h>


/* from startup.s */
extern char *_stdin,*_stdout,*_stderr;
extern struct ExecBase *SysBase;

FILE *stdin,*stdout,*stderr,*_firstfile=0,*_lastfile=0;
struct __exitfuncs *__firstexit;
struct Library *DOSBase = NULL;


extern int main(int, char **);
extern void _exit();



/* Three AmigaOS library calls are required in this startup code */

static LONG IsInteractive(BPTR file)
{
  struct Caos MyCaos;

  MyCaos.d1 = (ULONG)file;
  MyCaos.M68kCacheMode = IF_CACHEFLUSHALL;
  MyCaos.PPCCacheMode = IF_CACHEFLUSHALL;
  MyCaos.caos_Un.Offset = -216;
  MyCaos.a6 = (ULONG)DOSBase;
  return((LONG)PPCCallOS(&MyCaos));
}


static struct Library *OpenLibrary(UBYTE *name,unsigned long ver)
{
  struct Caos MyCaos;

  MyCaos.a1 = (ULONG)name;
  MyCaos.d0 = ver;
  MyCaos.M68kCacheMode = IF_CACHEFLUSHALL;
  MyCaos.PPCCacheMode = IF_CACHEFLUSHALL;
  MyCaos.caos_Un.Offset = -552;
  MyCaos.a6 = (ULONG)SysBase;
  return((struct Library *)PPCCallOS(&MyCaos));
}


static void CloseLibrary(struct Library *libbase)
{
  struct Caos MyCaos;

  MyCaos.a1 = (ULONG)libbase;
  MyCaos.M68kCacheMode = IF_CACHEFLUSHALL;
  MyCaos.PPCCacheMode = IF_CACHEFLUSHALL;
  MyCaos.caos_Un.Offset = -414;
  MyCaos.a6 = (ULONG)SysBase;
  PPCCallOS(&MyCaos);
}


void exit(int returncode)
/* exit() function for the vbcc-Amiga-PowerPC version */
{
  struct __exitfuncs *p=__firstexit;

  while(p) {
    p->func();  /* execute atexit() routines */
    p=p->next;
  }
  while(_firstfile && !fclose(_firstfile));  /* close all open files */
  _freemem();  /* free all memory */
  if (DOSBase)
    CloseLibrary(DOSBase);
  _exit(returncode);
}


void _main(int argc, char **argv)
{
  if (!(DOSBase = OpenLibrary("dos.library",36)))
    exit(EXIT_FAILURE);
  stdin = (FILE *)malloc(sizeof(FILE));
  stdout = (FILE *)malloc(sizeof(FILE));
  stderr = (FILE *)malloc(sizeof(FILE));
  if(!stdin || !stdout || !stderr)
    exit(EXIT_FAILURE);
  stdin->filehandle = _stdin;
  stdin->flags = _READABLE;
  if (IsInteractive((BPTR)_stdin))
    stdin->flags |= _UNBUF;
  stdout->filehandle = _stdout;
  stdout->flags = _WRITEABLE;
  if (IsInteractive((BPTR)_stdout))
    stdout->flags |= _LINEBUF;
  stderr->filehandle = _stderr;
  stderr->flags = _WRITEABLE;
  if (IsInteractive((BPTR)_stderr))
    stderr->flags |= _UNBUF;
  stdin->pointer = stdout->pointer = stderr->pointer=0;
  stdin->base = stdout->base = stderr->base = 0;
  stdin->count = stdout->count = stderr->count = 0;
  stdin->bufsize = stdout->bufsize = stderr->bufsize = 0;
  stdin->prev = 0;
  stdin->next = stdout;
  stdout->prev = stdin;
  stdout->next = stderr;
  stderr->prev = stdout;
  stderr->next = 0;
  _firstfile = stdin;
  _lastfile = stderr;
  exit(main(argc,argv));
}
