/* Operating system specific stuff */


#include "params.h"
#include "gambit.h"
#include "os.h"
#include "mem.h"
#include "strings.h"
#include "opcodes.h"


OS_FILE os_stdin, os_stdout, os_stderr;
#ifdef NO_EMUL_M68881
long os_M68020 = 1, os_M68881 = 1; /* Assume M68020/30 processor and M68881/2
#else
long os_M68020 = 0, os_M68881 = 0; /* Assume M68000 processor, no FPU */
#endif
char *os_err = "";


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

/* This section includes machine dependent code. */

#include "os_amiga.c"

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

/*
  The code that is fairly machine independent is included here.  Machine
  dependent actions are signaled by calls to `internal' procedures.
*/


#define MAX_STDOUT_BUF_LEN 256

static char stdout_buf[MAX_STDOUT_BUF_LEN];
static long stdout_buf_len = 0;
static char digits[] = "0123456789abcdef";


static void print_char( f, c )
OS_FILE f;
char c;
{ if (f == os_stdout)
  { stdout_buf[stdout_buf_len++] = c;
    if (c == '\n')
    { os_file_write( os_stdout, stdout_buf, stdout_buf_len );
      stdout_buf_len = 0;
    }
    else if (stdout_buf_len == MAX_STDOUT_BUF_LEN) stdout_buf_len--;
  }
  else
  { char buf[1];
    buf[0] = c;
    os_file_write( f, buf, 1L );
  }
}


static void print_str( f, str )
OS_FILE f;
char *str;
{ if (f == os_stdout)
    while (*str != '\0')
    { stdout_buf[stdout_buf_len++] = *str;
      if (*str++ == '\n')
      { os_file_write( os_stdout, stdout_buf, stdout_buf_len );
        stdout_buf_len = 0;
      }
      else if (stdout_buf_len == MAX_STDOUT_BUF_LEN) stdout_buf_len--;
    }
  else
  { long len = 0;
    while (str[len] != '\0') len++;
    os_file_write( f, str, len );
  }
}


static void print_int( f, n, radix )
OS_FILE f;
long n;
long radix;
{ char buf[12];
  char *p = buf;
  long x, m;
  if (n < 0) { *p++ = '-'; n = -n; }
  x = n; m = 1;
  while (x >= radix) { x = x / radix; m = m * radix; }
  while (m > 0)
  { long d = n / m;
    *p++ = digits[d];
    n = n - d * m;
    m = m / radix;
  }
  *p++ = '\0';
  print_str( f, buf );
}


void os_file_printf( f, str, val )
OS_FILE f;
char *str;
long val;
{ char *p = str;
  while ((*p != '\0') && (*p != '%')) print_char( f, *(p++) );
  if (*(p++) == '%')
  { switch (*p++)
    { case '%': print_char( f, '%' );         break;
      case 's': print_str( f, (char *)val );  break;
      case 'd': print_int( f, val, 10L );     break;
      case 'x': print_int( f, val, 16L );     break;
    }
    print_str( f, p );
  }
}


void os_warn( msg, val )
char *msg;
long val;
{ os_file_printf( os_stdout, msg, val );
}


void os_notify_gc_begin( id, report )
long id;
long report;
{ os_notify_gc_begin_internal();
  if (report)
    os_warn( "[GC start on processor %d]\n", id );
}


void os_notify_gc_end( id, heap_mid, heap_bot, free_bot, free_top, report )
long id;
char *heap_mid, *heap_bot, *free_bot, *free_top;
long report;
{ if (report)
  { long total = heap_mid - heap_bot;
    long free = free_top - free_bot;
    long usage = total - free;
    long usage_ratio_times_1000 = usage/(total/1000);
    os_warn( "[GC end on processor %d", id );
    os_warn( ", heap usage = %dK", usage/K );
    os_warn( " (%d", usage_ratio_times_1000/10 );
    os_warn( ".%d", usage_ratio_times_1000%10 );
    os_warn( "%%)]\n", 0L );
  }
  os_notify_gc_end_internal();
}


int main( argc, argv, envp )
int argc;
char *argv[], *envp[];
{
  return main_internal( argc, argv, envp );
}


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