/* Included by os.c */

/* AMIGA LATTICE-C stuff */

#include "struct.h"


#include "intuition/intuition.h"
#include "exec/exec.h"
/* #include "graphics/gfxbase.h" */

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <fcntl.h>

#define HZ 60
#define TICKS_PER_SEC HZ


static long start_real_time;


void os_quit()
{ exit(0);
}


long os_nb_processors()
{ return 1;
}


long os_fork_on_processors( n )
long n;
{ return 0;
}


static char *malloc8( length ) /* alloc of blocks starting at an octuple adr */
long length;
{ char *ptr;
  ptr = (char *)malloc( length+7 );
  if (ptr != NULL) ptr = (char *) ceiling8(ptr); /* get octuple addr. */
  return ptr;
}


char *os_shared_malloc8( len, processor, cont )
long len;
long processor;
void (*cont)();
{
  cont( (char *)malloc8( len ) );
}


char *os_shared_copy_malloc8( len_share, len_copy, processor, cont )
long len_share, len_copy;
long processor;
void (*cont)();
{ long aligned_len_share ;
  long len;
  char *ptr;

  aligned_len_share = (long)ceiling8( len_share );
  len = aligned_len_share + len_copy;
  ptr = malloc8( len );
  if (ptr != NULL) ptr = ptr + aligned_len_share - len_share;
  cont( ptr );
}


void os_block_copy( src, dst, len )
char *src, *dst;
long len;
{ register char *p1 = src, *p2 = dst;
  register long i = len;
  while (i > 0) { *(p2++) = *(p1++); i--; }
}



void os_flush_caches()
{

#define INSTR_CACHE_LENGTH_IN_K 64
#define DATA_CACHE_LENGTH_IN_K  8

  short *start = (short *)pstate->heap_old;
  short *p = start;
  long i;
  
  if (os_M68020 > 0) {
    for (i=((long)INSTR_CACHE_LENGTH_IN_K)*K/2-1; i>0; i--) *p++ = NOP_OP;
    *p++ = RTS_OP;
    for (i=((long)DATA_CACHE_LENGTH_IN_K)*K/2; i>0; i--) *p++ = 0;

    ((void (*)())start)();
  }
}


void os_flush_writes()
{
}


long os_clock()
{ unsigned int clock[2];
  long new_time;

  timer( clock ) ;  /* clock[0] is seconds; clock[1] is microSeconds */

  new_time = clock[0] + (clock[1] / 1000) ;

  return (new_time);
}


long os_real_time_clock()
{ unsigned int clock[2];
  long new_time;

  timer( clock ) ;  /* clock[0] is seconds; clock[1] is microSeconds */

  new_time = clock[0] + (clock[1] / 1000) ;

  return (new_time - start_real_time) ;
}


long os_clock_to_msec( ticks )
long ticks;
{ return ticks * 1000 / TICKS_PER_SEC ;
}


void os_cpu_times( buf )
long *buf;
{ unsigned int clock[2];
  timer(clock);
  buf[0] = clock[0];            /* Seconds */
  buf[1] = (clock[1] / 1000);   /* microSeconds */
}


long os_ticks_to_msec( ticks )
long ticks;
{ return ticks * 1000 / TICKS_PER_SEC;
}


static void (*intr_action)();
static void (*timer_action)();
static void (*io_action)();
static void (*fatal_action)();


static void fatal_signal( pc, sp, kind )
long pc, sp;
char *kind;
{ os_warn( "Fatal signal %s, terminating...\n", (long)kind );
  os_quit();
}


static void signal_trap( sig )
int sig;
{ long pc = 0, sp = 0;
  char *kind;
  void (*action)();
  if (sig == SIGINT)
  { signal(SIGINT, signal_trap);
    intr_action( pc, sp, "SIGINT" );
    return;
  }
  switch (sig)
  {/* case SIGABRT: kind = "SIGABRT"; break; */
/*    case SIGILL:  kind = "SIGILL";  break; */
    case SIGFPE:  kind = "SIGFPE";  break;
/*    case SIGSEGV: kind = "SIGSEGV"; break; */
/*    case SIGTERM: kind = "SIGTERM"; break; */
    default:      kind = "???";     break;
  }
  action = fatal_action;
  fatal_action = fatal_signal;
  signal( sig, signal_trap );
  action( pc, sp, kind );
}


long break_proc()  /* for Lattice/Amiga's onbreak() funciton */
{
  intr_action( 0, 0, "BREAK" );
  return( 0 ) ; /* continue execution */
}


void os_install_trap_handlers( intr_proc, timer_proc, io_proc, fatal_proc )
void (*intr_proc)();
void (*timer_proc)();
void (*io_proc)();
void (*fatal_proc)();
{ intr_action = intr_proc;
  timer_action = timer_proc;
  io_action = io_proc;
  signal(SIGINT, signal_trap);
  signal(SIGFPE, SIG_IGN);
  if (fatal_proc != (void (*)())0)
  { fatal_action = fatal_proc;
/*    signal(SIGABRT,signal_trap); */
/*    signal(SIGILL, signal_trap); */
/*    signal(SIGSEGV,signal_trap); */
/*    signal(SIGTERM,signal_trap); */
  }
  else
    fatal_action = fatal_signal;
}


long os_poll_events( result )
long *result;
{ return 0;
}


char *os_expand_filename( str )
char *str;
{ int len;
  if (str == NULL) return NULL;
  len = string_length( str );
  if ((len>1) && (str[0]=='~') && (str[1]=='/'))
  { char *home = (char *)getenv( "HOME" );
    if (home == NULL) return NULL;
    return string_append( home, &str[1] );
  }
  return str;
}


static long file_open( name, flags )
char *name;
char *flags;
{ FILE *f;
  f = fopen( name, flags );
  if (f == NULL)
    return -1;
  else
    return (long)f;
}


OS_FILE os_file_open_input( name )
char *name;
{ return (OS_FILE)file_open( name, "r" );
}


OS_FILE os_file_open_output( name )
char *name;
{ return (OS_FILE)file_open( name, "w" );
}


OS_FILE os_file_open_input_output( name )
char *name;
{ return (OS_FILE)file_open( name, "rw" );
}


long os_file_length( f )
OS_FILE f;
{ /* for the AMIGA/LATTICE */
  long  orig_pos, end_pos;

  orig_pos = lseek( ((FILE *)f)->_file, 0L, 1 ) ;  /* ftell() */
  end_pos  = lseek( ((FILE *)f)->_file, 0L, 2 ) ;  /* find the end */
  lseek( ((FILE *)f)->_file, orig_pos, 0 ) ;       /* reset */
  return( end_pos ) ;
}


long os_file_read_ready( f )
OS_FILE f;
{ return 1;
}


long os_file_read( f, ptr, n )
OS_FILE f;
char *ptr;
long n;
{ if (!os_file_read_ready( f ))
    return -1;
  else {
    int i = fread( ptr, 1, n, (FILE *)f );
    if (i == 0) clearerr((FILE *) f) ;
    return( i ) ;
  }
}


long os_file_write( f, ptr, n )
OS_FILE f;
char *ptr;
long n;
{/*@@ return fwrite( ptr, (size_t)1, (size_t)n, (FILE *)f ); @@*/
  long rc;
  rc = fwrite( ptr, (unsigned long)1, (unsigned long)n, (FILE *)f );
  fflush( (FILE *)f );
  return rc;
}


long os_file_close( f )
OS_FILE f;
{ return fclose( (FILE *)f );
}


void os_file_block_read( f )
OS_FILE f;
{
}


void os_file_block_write( f )
OS_FILE f;
{
}


extern void os_set_timer_interval( interval )
long interval;
{
}


void os_profil( buff, bufsiz, offset, shift )
short *buff;
long bufsiz, offset;
long shift;
{
}


static void os_notify_gc_begin_internal()
{
}


static void os_notify_gc_end_internal()
{
}



long os_get_next_event( event )
char *event;
{ return 0;
}


long os_handle_event( event )
char *event;
{ return 0;
}

void os_init()
{
}


extern void main_gambit();


static int main_internal( argc, argv, envp )
int argc;
char *argv[], *envp[];
{ unsigned int clock[2];
#ifdef LATTICE
  static char *fake_envp[1] = { NULL };
  envp = fake_envp ;
#endif

  timer( clock ); /* clock[0]: Seconds; clock[1]: microSeconds */

  start_real_time = clock[0] + (clock[1] / 1000);

  os_stdin  = (OS_FILE)stdin;
  os_stdout = (OS_FILE)stdout;
  os_stderr = (OS_FILE)stderr;


  main_gambit( argc, argv, envp );

  return 0;
}


/*---------------------------------------------------------------------------*/
