/* 
   Copyright 1994-2003 Free Software Foundation, Inc.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 
   USA

   You may contact the author at:

   mailto::camille@bluegrass.net

   or by snail mail at:

   David Lindauer
   850 Washburn Ave Apt 99
   Louisville, KY 40222
*/
#include <windows.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

extern char _import _iob ;

static int *_xceptblkptr;
short _basefpmask = 0x1332 ;
int _RTL_DATA _argc, _RTL_DATA __argc;
char _RTL_DATA **_argv,_RTL_DATA **__argv;
char *_passed_name ;
char _RTL_DATA **_environ;

FILE _RTL_DATA *__stdin ;
FILE _RTL_DATA *__stdout ;
FILE _RTL_DATA *__stderr ;
FILE _RTL_DATA *__stdaux ;
FILE _RTL_DATA *__stdprn ;

void __crtexit(int n)
{
	exit(n);
}
static int PASCAL _xceptionhandle(PEXCEPTION_RECORD er, void *frame,
			PCONTEXT context, void *dispatchercontext)
{

	int signum = -1,rv = 0;
	switch(er->ExceptionCode) {
		case EXCEPTION_ACCESS_VIOLATION:
		case EXCEPTION_DATATYPE_MISALIGNMENT:
		case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
			signum = SIGSEGV;
			break ;
		case EXCEPTION_PRIV_INSTRUCTION:
			signum = SIGILL;
			break ;
      case EXCEPTION_BREAKPOINT:
         // IF they really want to put a breakpoint in, let them but mmove on
         return EXCEPTION_CONTINUABLE ;
		case EXCEPTION_SINGLE_STEP:
			break ;
		case EXCEPTION_FLT_DENORMAL_OPERAND:
		case EXCEPTION_FLT_DIVIDE_BY_ZERO:
		case EXCEPTION_FLT_INEXACT_RESULT:
		case EXCEPTION_FLT_INVALID_OPERATION:
		case EXCEPTION_FLT_OVERFLOW:
		case EXCEPTION_FLT_STACK_CHECK:
		case EXCEPTION_FLT_UNDERFLOW:
			signum = SIGFPE ;
			break ;
		case EXCEPTION_INT_DIVIDE_BY_ZERO:
			break ;
		case EXCEPTION_INT_OVERFLOW:
			break ;
		case EXCEPTION_NONCONTINUABLE_EXCEPTION:
		case EXCEPTION_INVALID_DISPOSITION:
			break ;
		case EXCEPTION_STACK_OVERFLOW:
			break ;
	}
	if (signum != -1)
		rv = !raise(signum);

   if (rv) {
		EXCEPTION_POINTERS xx;
		xx.ExceptionRecord = er ;
		xx.ContextRecord = context ;
		return UnhandledExceptionFilter(&xx) ;
	} else
		return EXCEPTION_CONTINUABLE ;
}
void PASCAL __xceptinit(int *block)
{
	_xceptblkptr = block ;
	asm mov eax,[block]
   asm mov [eax+4],offset _xceptionhandle
	asm mov	ecx,fs:[0]
	asm mov [eax],ecx
	asm mov fs:[0],eax
}
void PASCAL __xceptrundown(void)
{
	asm mov eax,[_xceptblkptr]
   asm cmp eax,fs:[0]
  asm jnz nounset
	asm mov eax,[eax]
	asm mov fs:[0],eax
nounset:
	return ;
}
void PASCAL __llfpinit(void)
{
//   asm finit ;
  // _control87(_basefpmask,0x1fff) ;
}
#pragma startup argset 15



FILE *_RTL_FUNC  __getStream(int stream)
{
   if (stream < 5)
      return &_iob + 32 * stream ;
   else
      return 0 ;
}
extern void __GetMainArgs(void *,void *,void*,int) ;

void __threadinit(void)
{
}
static void argset(void)
{
   __stdin = __getStream(0) ;
   __stdout = __getStream(1) ;
   __stderr = __getStream(2) ;
   __stdaux = __getStream(3) ;
   __stdprn = __getStream(4) ;
   __GetMainArgs(&_argc,&_argv,&_environ,0) ;
   __argc = _argc ;
   __argv = _argv ;
}