/*
	File:	scon.c
	Author:	John van Groningen
	At:		University of Nijmegen
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#ifdef SOLARIS
# include <unistd.h>
#endif

#define GC_FLAGS
#ifndef SOLARIS
# define MARKING_GC
#endif

#define MY_PATH_MAX 1025

char appl_path[MY_PATH_MAX];
char home_path[MY_PATH_MAX];

void set_home_and_appl_path (char *command)
{
	char *p;
	int r;

	realpath (getenv ("HOME"),home_path);
	
#if 1
# ifdef SOLARIS
	p=getexecname();
	if (p!=NULL){
		realpath (p,appl_path);
		*strrchr (appl_path,'/')='\0';
	} else
		appl_path[0]='\0';
# else
	r=readlink ("/proc/self/exe",appl_path,MY_PATH_MAX-1);
	if (r>=0){
		appl_path[r]='\0';
		
		p=strrchr (appl_path,'/');
		if (p!=NULL)
			*p='\0';
	} else
		appl_path[0]='\0';
# endif
#else
	p=strchr (command,'/');
  
	if (p!=NULL){
		realpath (command,appl_path);
		*strrchr (appl_path,'/')='\0';
	} else {
		char *path,*file_found_p;
		int colon_i;

		path=(char *)getenv("PATH");

		file_found_p=NULL;

		while (path!=NULL && file_found_p==NULL){
			char *next,try_path[MY_PATH_MAX];
			
			next=strchr (path,':');
			if (next==NULL)
				colon_i=strlen(path);
			else
				colon_i=next-path;

			strncpy (try_path,path,colon_i);
			try_path[colon_i]='\0';
			
			strcat (try_path,"/");
			strcat (try_path,command);
			
			file_found_p=(char *)realpath (try_path,appl_path);

			path=next;
			if (path!=NULL)
				++path;
		}

		if (file_found_p==NULL)
			*appl_path='\0';
		else
			*strrchr(appl_path,'/')='\0';
	}
#endif
}

#if defined (SOLARIS) || defined (I486)
extern long ab_stack_size,heap_size,flags;
#else
extern long stack_size,heap_size,flags;
#endif

/*
extern long ab_stack_size=512*1024,heap_size=2048*1024,flags=8;
*/
#ifdef MARKING_GC
extern long heap_size_multiple,initial_heap_size;
#endif

void w_print_char (char c)
{	
	putchar (c);
}

void w_print_text (register char *s,unsigned long length)
{
	register int l;
	
	l=length;
	if (l)
		do {
			putchar (*s);
			++s;
		} while (--l);
}

void ew_print_char (char c)
{
	putc (c,stderr);
}

void ew_print_text (register char *s,unsigned long length)
{
	register int l;
	
	l=length;
	if (l)
		do {
			putc (*s,stderr);
			++s;
		} while (--l);
}

int w_get_char()
{
	return getchar();
}

#define is_digit(n) ((unsigned)((n)-'0')<(unsigned)10)

int w_get_int (int *i_p)
{
	int c,negative;
	unsigned int i;
	
	c=getchar();
	while (c==' ' || c=='\t' || c=='\n')
		c=getchar();
	
	negative=0;
	if (c=='+')
		c=getchar();
	else
		if (c=='-'){
			c=getchar();
			negative=1;
		}
	
	if (!is_digit (c)){
		if (c!=EOF)
			ungetc (c,stdin);

		*i_p=0;
		return 0;
	}
	
	i=c-'0';
	while (c=getchar(),is_digit (c)){
		i+=i<<2;
		i+=i;
		i+=c-'0';
	};

	if (negative)
		i=-i;

	if (c!=EOF)
		ungetc (c,stdin);

	*i_p=i;
	return -1;
}

int w_get_real (double *r_p)
{
	char s[256+1];
	int c,dot,digits,result,n;
	
	n=0;
	
	c=getchar();
	while (c==' ' || c=='\t' || c=='\n')
		c=getchar();
	
	if (c=='+')
		c=getchar();
	else
		if (c=='-'){
			s[n++]=c;
			c=getchar();
		}
	
	dot=0;
	digits=0;
	
	while (is_digit (c) || c=='.'){
		if (c=='.'){
			if (dot){
				dot=2;
				break;
			}
			dot=1;
		} else
			digits=-1;
		if (n<256)
			s[n++]=c;
		c=getchar();
	}

	result=0;
	if (digits)
		if (dot==2 || ! (c=='e' || c=='E'))
			result=-1;
		else {
			if (n<256)
				s[n++]=c;
			c=getchar();
			
			if (c=='+')
				c=getchar();
			else
				if (c=='-'){
					if (n<256)
						s[n++]=c;
					c=getchar();
				}
			
			if (is_digit (c)){
				do {
					if (n<256)
						s[n++]=c;
					c=getchar();
				} while (is_digit (c));

				result=-1;
			}
		}

	if (n>=256)
		result=0;

	if (c!=EOF)
		ungetc (c,stdin);

	*r_p=0.0;
	
	if (result){
		s[n]='\0';
		if (sscanf (s,"%lg",r_p)!=1)
			result=0;
	}
	
	return result;
}

unsigned long w_get_text (register char *string,unsigned long max_length)
{
	register int length;
	
	fgets (string,(int)max_length,stdin);
	
	for (length=0; length<max_length; ++length)
		if (string[length]=='\0')
			break;
	
	return length;
}

void w_print_string (char *s)
{
	fputs (s,stdout);
}

void ew_print_string (char *s)
{
	fputs (s,stderr);
}

void w_print_int (int n)
{
	printf ("%d",n);
}

void ew_print_int (int n)
{
	fprintf (stderr,"%d",n);
}

void w_print_real (double r)
{
	printf ("%.15g",r);
}

void ew_print_real (double r)
{
	fprintf (stderr,"%.15g",r);
}

static long parse_size (register char *s)
{
	register int c;
	register long n;
	
	c=*s++;
	if (c<'0' || c>'9'){
		printf ("Digit expected in argument\n");
		exit (-1);
	}
	
	n=c-'0';
	
	while (c=*s++,c>='0' && c<='9')
		n=n*10+(c-'0');
	
	if (c=='k' || c=='K'){
		c=*s++;
		n<<=10;
	} else if (c=='m' || c=='M'){
		c=*s++;
		n<<=20;
	}
	
	if (c!='\0'){
		printf ("Error in argument\n");
		exit (-1);
	}
	
	return n;
}

#ifdef MARKING_GC
static long parse_integer (register char *s)
{
	register int c;
	register long n;

	c=*s++;
	if (c<'0' || c>'9'){
		printf ("Digit expected in argument\n");
		exit (-1);
	}

	n=c-'0';

	while (c=*s++,c>='0' && c<='9')
		n=n*10+(c-'0');

	if (c!='\0'){
		printf ("Error in integer");
		exit (-1);
	}
	
	return n;
}
#endif

int global_argc;
char **global_argv;

int execution_aborted;
int return_code;

int main (int argc,char **argv)
{
	int arg_n;

	execution_aborted=0;
	return_code=0;
	
	set_home_and_appl_path (argv[0]);
	
	for (arg_n=1; arg_n<argc; ++arg_n){
		char *s;
		
		s=argv[arg_n];
		if (*s!='-')
			break;

		++s;
		if (!strcmp (s,"h")){
			++arg_n;
			if (arg_n>=argc){
				printf ("Heapsize missing\n");
				return -1;
			}
			heap_size=parse_size (argv[arg_n]);
		} else if (!strcmp (s,"s")){
			++arg_n;
			if (arg_n>=argc){
				printf ("Stacksize missing\n");
				return -1;
			}
#if defined (SOLARIS) || defined (I486)
			ab_stack_size=parse_size (argv[arg_n]);
#else
			stack_size=parse_size (argv[arg_n]);
#endif
		} else if (!strcmp (s,"b"))
			flags |= 1;
		else if (!strcmp (s,"sc"))
			flags &= ~1;
		else if (!strcmp (s,"t"))
			flags |= 8;
		else if (!strcmp (s,"nt"))
			flags &= ~8;
		else if (!strcmp (s,"gc"))
			flags |= 2;
		else if (!strcmp (s,"ngc"))
			flags &= ~2;
		else if (!strcmp (s,"st"))
			flags |= 4;
		else if (!strcmp (s,"nst"))
			flags &= ~4;
		else if (!strcmp (s,"nr"))
			flags |= 16;
#ifdef MARKING_GC
		else if (!strcmp (s,"gcm"))
			flags |= 64;
		else if (!strcmp (s,"gcc"))
			flags &= ~64;
		else if (!strcmp (s,"gci")){
			++arg_n;
			if (arg_n>=argc){
				printf ("Initial heap size missing\n");
				exit (-1);
			}
			initial_heap_size=parse_size (argv[arg_n]);
		} else if (!strcmp (s,"gcf")){
			++arg_n;
			if (arg_n>=argc){
				printf ("Next heap size factor missing\n");
				exit (-1);
			}
			heap_size_multiple=parse_integer (argv[arg_n])<<8;
		}	
#endif
		else
			break;
	}

	--arg_n;
	argv[arg_n]=argv[0];
	global_argv=&argv[arg_n];
	global_argc=argc-arg_n;

	abc_main();

	if (return_code==0 && execution_aborted!=0)
		return_code= -1;

	return return_code;
}
