/*
File: wcon.c
Author: John van Groningen
At: University of Nijmegen
*/
#include <float.h>
#define GC_FLAGS
#define STACK_OVERFLOW_EXCEPTION_HANDLER
#ifdef WINDOWS
# include <windows.h>
# define ULONG unsigned long
# define DosWrite(f,p,l,lp) WriteFile ((HANDLE)f,p,l,lp,NULL)
# define DosRead(f,p,l,lp) ReadFile ((HANDLE)f,p,l,lp,NULL)
# define OS(w,o) w
# define StdInput std_input_handle
# define StdOutput std_output_handle
# define StdError std_error_handle
# ifdef TIME_PROFILE
# define TCHAR char
# if 0
typedef struct _WIN32_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
TCHAR cFileName[ MAX_PATH ];
TCHAR cAlternateFileName[ 14 ];
} WIN32_FIND_DATA;
# endif
# endif
# include "wfileIO3.h"
#else
# define INCL_DOSFILEMGR
# include <os2.h>
# define OS(w,o) o
# define StdInput 0
# define StdOutput 1
# define StdError 2
#endif
#define SHOW_EXECUTION_TIME_MASK 8
#define NO_RESULT_MASK 16
#ifdef WINDOWS
HANDLE std_input_handle,std_output_handle,std_error_handle;
int console_window_visible,console_allocated,console_flag=0;
int std_input_from_file=0;
int std_output_to_file=0;
extern void init_std_io_from_or_to_file (void);
#endif
extern int c_entier (double);
extern double c_log10 (double);
extern double c_pow (double,double);
extern long ab_stack_size,heap_size,flags;
static void print_char (char c,OS(HANDLE,int) file_number)
{
ULONG n_chars;
if (c==10){
c=13;
DosWrite (file_number,&c,1,&n_chars);
c=10;
}
DosWrite (file_number,&c,1,&n_chars);
}
static void print_text (char *s,unsigned long length,OS(HANDLE,int) file_number)
{
ULONG n_chars;
int n;
n=0;
while (n!=length)
if (s[n]!=10)
++n;
else {
char c;
if (n>0)
#ifdef WINDOWS
/* workaround for bug in windows */
{
char *s_p;
int i;
s_p=s;
i=n;
do {
if (DosWrite (file_number,s_p,i,&n_chars)!=0 || GetLastError()!=ERROR_NOT_ENOUGH_MEMORY || n_chars==i)
break;
if (n_chars==0){
int m;
m=i;
do
m=m>>1;
while (m>0 && !DosWrite (file_number,s_p,m,&n_chars) && GetLastError()==ERROR_NOT_ENOUGH_MEMORY && n_chars==0);
if (n_chars==0)
return;
}
i-=n_chars;
s_p+=n_chars;
} while (i>0);
}
#else
DosWrite (file_number,s,n,&n_chars);
#endif
c=13;
DosWrite (file_number,&c,1,&n_chars);
s+=n;
length-=n;
n=1;
}
if (length>0)
#ifdef WINDOWS
{
/* workaround for bug in windows */
char *s_p;
int i;
s_p=s;
i=length;
do {
if (DosWrite (file_number,s_p,i,&n_chars)!=0 || GetLastError()!=ERROR_NOT_ENOUGH_MEMORY || n_chars==i)
break;
if (n_chars==0){
int m;
m=i;
do
m=m>>1;
while (m>0 && !DosWrite (file_number,s_p,m,&n_chars) && GetLastError()==ERROR_NOT_ENOUGH_MEMORY && n_chars==0);
if (n_chars==0)
return;
}
i-=n_chars;
s_p+=n_chars;
} while (i>0);
}
#else
DosWrite (file_number,s,length,&n_chars);
#endif
}
#ifdef WINDOWS
static void make_console_window_visible ()
{
if (!console_window_visible){
if (console_flag==0 ||
std_input_handle==INVALID_HANDLE_VALUE || std_input_handle==NULL ||
std_output_handle==INVALID_HANDLE_VALUE || std_output_handle==NULL ||
std_error_handle==INVALID_HANDLE_VALUE || std_error_handle==NULL)
{
console_allocated=AllocConsole();
if (std_input_handle==INVALID_HANDLE_VALUE || std_input_handle==NULL)
std_input_handle=GetStdHandle (STD_INPUT_HANDLE);
if (std_output_handle==INVALID_HANDLE_VALUE || std_output_handle==NULL
|| GetFileType (std_output_handle)==FILE_TYPE_UNKNOWN /* hack for windows 2000/XP */
)
std_output_handle=GetStdHandle (STD_OUTPUT_HANDLE);
if (std_error_handle==INVALID_HANDLE_VALUE || std_error_handle==NULL)
std_error_handle=GetStdHandle (STD_ERROR_HANDLE);
}
console_window_visible=1;
}
}
#endif
void w_print_char (char c)
{
#ifdef WINDOWS
if (std_output_to_file){
file_write_char (c,&file_table[1]);
return;
}
if (!console_window_visible)
make_console_window_visible();
#endif
print_char (c,StdOutput);
}
void w_print_text (char *s,unsigned long length)
{
#ifdef WINDOWS
if (std_output_to_file){
file_write_characters (s,length,&file_table[1]);
return;
}
if (!console_window_visible)
make_console_window_visible();
#endif
print_text (s,length,StdOutput);
}
void ew_print_char (char c)
{
#ifdef WINDOWS
if (!console_window_visible)
make_console_window_visible();
#endif
print_char (c,StdError);
}
void ew_print_text (char *s,unsigned long length)
{
#ifdef WINDOWS
if (!console_window_visible)
make_console_window_visible();
#endif
print_text (s,length,StdError);
}
static int next_stdin_character=-1;
int w_get_char (void)
{
ULONG n_chars;
char c;
#ifdef WINDOWS
if (std_input_from_file)
return file_read_char (&file_table[1]);
if (!console_window_visible)
make_console_window_visible();
#endif
if (next_stdin_character==-1){
do {
DosRead (StdInput,&c,1,&n_chars);
if (n_chars>0 && c!=13)
return c;
} while (n_chars>0);
return -1;
} else {
c=next_stdin_character;
next_stdin_character=-1;
return c;
}
}
#define is_digit(n) ((unsigned)((n)-'0')<(unsigned)10)
int w_get_int (int *i_p)
{
int c,negative;
unsigned int i;
#ifdef WINDOWS
if (std_input_from_file)
return file_read_int (&file_table[1],i_p);
#endif
c=w_get_char();
while (c==' ' || c=='\t' || c=='\n')
c=w_get_char();
negative=0;
if (c=='+')
c=w_get_char();
else
if (c=='-'){
c=w_get_char();
negative=1;
}
if (!is_digit (c)){
next_stdin_character=c;
*i_p=0;
return 0;
}
i=c-'0';
while (c=w_get_char(),is_digit (c)){
i+=i<<2;
i+=i;
i+=c-'0';
};
if (negative)
i=-i;
next_stdin_character=c;
*i_p=i;
return -1;
}
char *convert_string_to_real (char *string,double *r_p)
{
int neg,has_digits,has_dot;
char *s_p,*end_s;
long scale;
double d;
s_p=string;
neg=0;
if (*s_p=='+')
++s_p;
else if (*s_p=='-'){
neg = 1;
++s_p;
}
has_digits=0;
has_dot=0;
scale=0;
d=0.0;
for (;;){
if (*s_p== '.' && !has_dot){
++s_p;
has_dot=1;
} else if ((unsigned)(*s_p-'0') < (unsigned)10){
if (!has_digits){
d=(double)(*s_p - '0');
has_digits=1;
} else {
if (d >= 1e18)
++scale;
else
d = d*10.0 + (double)(*s_p - '0');
}
++s_p;
if (has_dot)
--scale;
} else
break;
}
if (!has_digits){
*r_p=0.0;
return string;
}
end_s=s_p;
if ((*s_p & ~0x20)=='E'){
int neg_exponent;
++s_p;
neg_exponent=0;
if (*s_p=='+')
++s_p;
else if (*s_p=='-'){
neg_exponent=1;
++s_p;
}
if ((unsigned)(*s_p-'0') < (unsigned)10){
int exponent;
exponent=*s_p++ - '0';
while ((unsigned)(*s_p-'0') < (unsigned)10)
exponent=exponent*10 + *s_p++ - '0';
if (neg_exponent)
scale -= exponent;
else
scale += exponent;
end_s=s_p;
}
}
if (scale!=0 && d!=0.0)
d *= c_pow (10.0,(double)scale);
if (neg)
d=-d;
*r_p=d;
return end_s;
}
int w_get_real (double *r_p)
{
char s[256+1];
int c,dot,digits,result,n;
#ifdef WINDOWS
if (std_input_from_file)
return file_read_real (&file_table[1],r_p);
#endif
n=0;
c=w_get_char();
while (c==' ' || c=='\t' || c=='\n')
c=w_get_char();
if (c=='+')
c=w_get_char();
else
if (c=='-'){
s[n++]=c;
c=w_get_char();
}
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=w_get_char();
}
result=0;
if (digits)
if (dot==2 || ! (c=='e' || c=='E'))
result=-1;
else {
if (n<256)
s[n++]=c;
c=w_get_char();
if (c=='+')
c=w_get_char();
else
if (c=='-'){
if (n<256)
s[n++]=c;
c=w_get_char();
}
if (is_digit (c)){
do {
if (n<256)
s[n++]=c;
c=w_get_char();
} while (is_digit (c));
result=-1;
}
}
if (n>=256)
result=0;
next_stdin_character=c;
*r_p=0.0;
if (result){
s[n]='\0';
result= convert_string_to_real (s,r_p)==&s[n];
}
return result;
}
unsigned long w_get_text (char *string,unsigned long max_length)
{
ULONG length;
length=0;
#ifdef WINDOWS
if (std_input_from_file){
unsigned long length;
length=max_length;
return file_read_characters (&file_table[1],&length,string);
}
if (!console_window_visible)
make_console_window_visible();
#endif
if (max_length==0)
return length;
if (next_stdin_character!=-1){
*string++=next_stdin_character;
next_stdin_character=-1;
--max_length;
++length;
}
while (max_length>0){
ULONG r_length;
int s,d;
DosRead (StdInput,string,max_length,&r_length);
s=0;
d=0;
while (s<r_length){
char c;
c=string[s];
++s;
if (c!=13){
string[d]=c;
++d;
}
}
length += d;
if (r_length!=max_length)
break;
string += d;
max_length -= d;
}
return length;
}
void w_print_string (char *s)
{
char *p;
#ifdef WINDOWS
if (std_output_to_file){
for (p=s; *p!=0; ++p)
;
file_write_characters (s,p-s,&file_table[1]);
return;
}
if (!console_window_visible)
make_console_window_visible();
#endif
for (p=s; *p!=0; ++p)
;
print_text (s,p-s,StdOutput);
}
void ew_print_string (char *s)
{
char *p;
#ifdef WINDOWS
if (!console_window_visible)
make_console_window_visible();
#endif
for (p=s; *p!=0; ++p)
;
print_text (s,p-s,StdError);
}
static void print_integer (int n,OS(HANDLE,int) file_number)
{
char s[16];
int length;
unsigned int m;
ULONG n_chars;
if (n<0)
m=-n;
else
m=n;
length=16;
while (m>=10){
unsigned int r;
r=m/10;
s[--length]=48+m-r*10;
m=r;
}
s[--length]=48+m;
if (n<0)
s[--length]='-';
DosWrite (file_number,&s[length],16-length,&n_chars);
}
void w_print_int (int n)
{
#ifdef WINDOWS
if (std_output_to_file){
file_write_int (n,&file_table[1]);
return;
}
if (!console_window_visible)
make_console_window_visible();
#endif
print_integer (n,StdOutput);
}
void ew_print_int (int n)
{
#ifdef WINDOWS
if (!console_window_visible)
make_console_window_visible();
#endif
print_integer (n,StdError);
}
int xam_and_fstsw (double d)
{
int i;
#if 0
asm ("fxam ; fstsw %%ax" : : "f" (d) : "%ax");
asm ("movzwl %%ax,%0" : "=g" (i) : );
#else
asm ("fxam ; fstsw %%ax; movzwl %%ax,%0" : "=g" (i) : "t" (d) : "%ax");
#endif
return i;
}
#if 0
int fbstp (double d,char *buffer)
{
# if 0
asm ("movl %0,%%eax ; fbstp (%%eax) ; fld1" : : "g" (buffer) , "f" (d) : "%eax");
# else
asm ("fbstp (%0)" : : "r" (buffer) , "t" (d) : "st");
# endif
}
#endif
#define N_DIGITS 15
#if 1
static unsigned int dtoi_divmod_1e9 (double d,unsigned int *rem_p)
{
double a[1];
unsigned int q,r;
# if 1
asm (
"fistpq (%3); "
"movl $1000000000,%%ebx; "
"movl 4(%3),%%edx; "
"movl (%3),%%eax; "
"divl %%ebx; "
: "=&a" (q), "=&d" (r) : "t" (d), "r" (a)
: "%ebx","st"
);
# else
asm (
"fistpq (%3); "
"movl $1000000000,%%ebx; "
"movl 4(%3),%%edx; "
"movl (%3),%%eax; "
"divl %%ebx; "
"movl %%eax,%0"
: "&=g" (q), "&=d" (r) : "t" (d), "r" (a)
: "%eax","%ebx","%ecx","%edx","st"
);
# endif
*rem_p=r;
return q;
}
static unsigned int to14_18 (int i)
{
int r;
asm (
"mov $0x0a7c5ac48,%%eax; " // 2^18 / 1e5 * 2^30 rounded up
"mull %1; " // Divide by 1e5,
"shr $30,%%eax; " // converting it into
"lea 1(%%eax,%%edx,4),%0" // 14.18 fixed-point format
: "=r" (r) : "g" (i)
: "%eax","%edx"
);
return r;
}
static unsigned int to4_28 (int i)
{
int r;
asm (
"mov $0xabcc7712,%%eax; " // 2^28 / 1e8 * 2^30 rounded up
"mull %1; " // Divide by 1e8
"shr $30,%%eax; " // converting it into
"lea 1(%%eax,%%edx,4),%0" // 4.28 fixed-point format
: "=r" (r) : "g" (i)
: "%eax","%edx"
);
return r;
}
static void d_to_a (double d,char *s)
{
unsigned int i1,i2,n,r;
n=dtoi_divmod_1e9 (d,&r);
i2=to4_28 (r);
s[6]=(i2>>28)+'0';
i1=to14_18 (n);
i2=(i2 & 0xfffffff)*5;
s[7]=(i2>>27)+'0';
s[0]=(i1>>18)+'0';
i2=(i2 & 0x7ffffff)*5;
s[8]=(i2>>26)+'0';
i1=(i1 & 0x3ffff)*5;
s[1]=(i1>>17)+'0';
i2=(i2 & 0x3ffffff)*5;
s[9]=(i2>>25)+'0';
i1=(i1 & 0x1ffff)*5;
s[2]=(i1>>16)+'0';
i2=(i2 & 0x1ffffff)*5;
s[10]=(i2>>24)+'0';
i1=(i1 & 0xffff)*5;
s[3]=(i1>>15)+'0';
i2=(i2 & 0xffffff)*5;
s[11]=(i2>>23)+'0';
i1=(i1 & 0x7fff)*5;
s[4]=(i1>>14)+'0';
i2=(i2 & 0x7fffff)*5;
s[12]=(i2>>22)+'0';
i1=(i1 & 0x3fff)*5;
s[5]=(i1>>13)+'0';
i2=(i2 & 0x3fffff)*5;
s[13]=(i2>>21)+'0';
s[15]='\0';
i2=(i2 & 0x1fffff)*5;
s[14]=(i2>>20)+'0';
}
#endif
char *convert_real_to_string (double d,char *s_p)
{
double scale_factor;
int exponent,n;
unsigned int fpu_status;
fpu_status = xam_and_fstsw (d);
switch (fpu_status & 0x4500){
case 0x500:
if (fpu_status & 0x200)
*s_p++='-';
s_p[0]='#';
s_p[1]='I';
s_p[2]='N';
s_p[3]='F';
s_p[4]='\0';
return s_p+4;
case 0x100:
s_p[0]='#';
s_p[1]='N';
s_p[2]='A';
s_p[3]='N';
s_p[4]='\0';
return s_p+4;
case 0x4100:
if (fpu_status & 0x200)
*s_p++='-';
s_p[0]='#';
s_p[1]='E';
s_p[2]='M';
s_p[3]='P';
s_p[4]='\0';
return s_p+4;
}
if (d<0){
d=-d;
*s_p++ = '-';
}
if (d==0){
*s_p++ = '0';
*s_p = '\0';
return s_p;
}
if (d<1e4){
if (d<1e0){
if (d<1e-4){
exponent=c_entier (c_log10 (d));
if (N_DIGITS-exponent>=308){
d=d*1e20;
scale_factor=c_pow (10.0,N_DIGITS-1-20-exponent);
} else {
scale_factor=c_pow (10.0,N_DIGITS-1-exponent);
}
} else {
if (d<1e-2){
if (d<1e-3){
exponent=-4;
scale_factor=1e18;
} else {
exponent=-3;
scale_factor=1e17;
}
} else {
if (d<1e-1){
exponent=-2;
scale_factor=1e16;
} else {
exponent=-1;
scale_factor=1e15;
}
}
}
} else {
if (d<1e2){
if (d<1e1){
exponent=0;
scale_factor=1e14;
} else {
exponent=1;
scale_factor=1e13;
}
} else {
if (d<1e3){
exponent=2;
scale_factor=1e12;
} else {
exponent=3;
scale_factor=1e11;
}
}
}
} else {
if (d<1e8){
if (d<1e6){
if (d<1e5){
exponent=4;
scale_factor=1e10;
} else {
exponent=5;
scale_factor=1e9;
}
} else {
if (d<1e7){
exponent=6;
scale_factor=1e8;
} else {
exponent=7;
scale_factor=1e7;
}
}
} else if (d<1e12){
if (d<1e10){
if (d<1e9){
exponent=8;
scale_factor=1e6;
} else {
exponent=9;
scale_factor=1e5;
}
} else {
if (d<1e11){
exponent=10;
scale_factor=1e4;
} else {
exponent=11;
scale_factor=1e3;
}
}
} else {
exponent=c_entier (c_log10 (d));
scale_factor=c_pow (10.0,N_DIGITS-1-exponent);
}
}
d *= scale_factor;
if (d<1e14){
d *= 10.0;
--exponent;
}
#if 1
d_to_a (d,s_p);
#else
{
unsigned char bcd_buffer[16];
int i,j;
fbstp (d,bcd_buffer);
j=14;
for (i=0; i<7; ++i){
unsigned char bcd_byte;
bcd_byte=bcd_buffer[i];
s_p[j] ='0'+(bcd_byte & 0xf);
s_p[j-1]='0'+((bcd_byte & 0xf0)>>4);
j-=2;
}
s_p[j] ='0'+(bcd_buffer[i] & 0xf);
}
#endif
s_p+=N_DIGITS;
if (exponent>(N_DIGITS-1) || exponent<-4){
int exponent_d10;
for (n=-1; n>=-(N_DIGITS-1); --n)
s_p[n+1]=s_p[n];
s_p[-(N_DIGITS-1)]='.';
++s_p;
while (s_p[-1]=='0')
--s_p;
if (s_p[-1]=='.')
--s_p;
*s_p++ = 'e';
if (exponent>=0)
*s_p++ = '+';
else {
*s_p++ = '-';
exponent= -exponent;
}
if (exponent>=100){
int exponent_d100;
exponent_d100=exponent/100;
*s_p++ = '0'+exponent_d100;
exponent -= 100*exponent_d100;
}
exponent_d10=exponent/10;
*s_p++ = '0'+exponent_d10;
*s_p++ = '0'+exponent-10*exponent_d10;
} else {
if (exponent>=-1){
for (n=-1; n>=exponent-(N_DIGITS-1); --n)
s_p[n+1]=s_p[n];
s_p[exponent-(N_DIGITS-1)]='.';
++s_p;
} else {
for (n=-1; n>=-N_DIGITS; --n)
s_p[n-exponent]=s_p[n];
s_p[-N_DIGITS] = '.';
for (n=exponent; n<-1; ++n)
s_p[-(N_DIGITS-1)+(n-exponent)] = '0';
s_p+= -exponent;
}
while (s_p[-1]=='0')
--s_p;
if (s_p[-1]=='.')
--s_p;
}
*s_p='\0';
return s_p;
}
void w_print_real (double r)
{
char s[32],*end_s;
#ifdef WINDOWS
if (std_output_to_file){
file_write_real (r,&file_table[1]);
return;
}
if (!console_window_visible)
make_console_window_visible();
#endif
end_s=convert_real_to_string (r,s);
print_text (s,end_s-s,StdOutput);
}
void ew_print_real (double r)
{
char s[32],*end_s;
#ifdef WINDOWS
if (!console_window_visible)
make_console_window_visible();
#endif
end_s=convert_real_to_string (r,s);
print_text (s,end_s-s,StdError);
}
#ifdef WINDOWS
void wait_for_key_press (VOID)
{
DWORD console_mode;
SetConsoleTitleA ("press any key to exit");
GetConsoleMode (std_input_handle,&console_mode);
SetConsoleMode (std_input_handle,console_mode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT));
{
ULONG n_chars;
char c;
n_chars=1;
DosRead (StdInput,&c,1,&n_chars);
}
SetConsoleMode (std_input_handle,console_mode);
}
#endif
int free_memory (void *p)
{
#ifdef WINDOWS
if (GlobalFree (p)==NULL)
return 0;
else
return GetLastError();
#else
return DosFreeMem (p);
#endif
}
void *allocate_memory (int size)
{
#ifdef WINDOWS
return LocalAlloc (GMEM_FIXED,size);
#else
APIRET rc;
void *pb;
rc=DosAllocMem (&pb,size,fALLOC);
if (rc!=0)
return NULL;
else
return pb;
#endif
}
#if defined (WINDOWS) && defined (STACK_OVERFLOW_EXCEPTION_HANDLER)
void *allocate_memory_with_guard_page_at_end (int size)
{
int alloc_size;
DWORD old_protect;
char *p,*end_p;
alloc_size=(size+4096+4095) & -4096;
p=LocalAlloc (GMEM_FIXED,alloc_size);
if (p==NULL)
return p;
end_p=(char*)(((int)p+size+4095) & -4096);
if (!VirtualProtect (end_p,4096,PAGE_READWRITE | PAGE_GUARD,&old_protect))
VirtualProtect (end_p,4096,PAGE_NOACCESS,&old_protect);
return p;
}
#endif
static long parse_size (char *s)
{
int c;
long n;
c=*s++;
if (c<'0' || c>'9'){
w_print_string ("Digit expected in argument\n");
return -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'){
w_print_string ("Error in argument\n");
return -1;
}
return n;
}
#ifdef GC_FLAGS
static long parse_integer (register char *s)
{
register int c;
register long n;
c=*s++;
if (c<'0' || c>'9'){
w_print_string ("Digit expected in argument\n");
return (-1);
}
n=c-'0';
while (c=*s++,c>='0' && c<='9')
n=n*10+(c-'0');
if (c!='\0'){
w_print_string ("Error in integer");
return (-1);
}
return n;
}
#endif
int global_argc;
char **global_argv;
#ifdef DLL
extern void abc_main (void *);
#else
extern void abc_main (void);
#endif
#define EQ_STRING1(s,c1) ((s)[0]==(c1) && (s)[1]=='\0')
#define EQ_STRING2(s,c1,c2) ((s)[0]==(c1) && (s)[1]==(c2) &&(s)[2]=='\0')
#define EQ_STRING3(s,c1,c2,c3) ((s)[0]==(c1) && (s)[1]==(c2) && (s)[2]==(c3) && (s)[3]=='\0')
#ifdef WINDOWS
extern long heap_size_multiple;
extern long initial_heap_size;
# define MINIMUM_HEAP_SIZE_MULTIPLE ((2*256)+128)
# define MAXIMUM_HEAP_SIZE_MULTIPLE (100*256)
#endif
void (*exit_tcpip_function) (void);
#ifdef WINDOWS
int execution_aborted;
int return_code;
#endif
#ifdef STACK_OVERFLOW_EXCEPTION_HANDLER
extern __stdcall LONG clean_exception_handler (struct _EXCEPTION_POINTERS *exception_p);
#endif
#ifdef DLL
int clean_main (int heap_size_param,int flags_param,int ab_stack_size_param,void *start_address,int argc,char **argv)
#else
# ifdef CLIB
int main (int argc,char **argv)
# else
int clean_main (void)
# endif
#endif
{
int arg_n;
#ifndef CLIB
char **argv,*arg_p,*arg_p_copy,*command_p;
int argc;
argc=0;
command_p=GetCommandLineA();
if (command_p==NULL || *command_p=='\0')
command_p="?";
{
char c;
arg_p=command_p;
while ((c=*arg_p)!=0){
while (c==' ' || c=='\t' || c=='\n' || c=='\r')
c = * ++arg_p;
if (c=='\0')
break;
++argc;
if (c=='\"'){
do {
c = * ++arg_p;
} while (!(c=='\0' || c=='\"'));
if (c=='\"')
c = * ++arg_p;
} else {
while (!(c=='\0' || c==' ' || c=='\t' || c=='\n' || c=='\r'))
c = * ++arg_p;
}
if (c=='\0')
break;
++arg_p;
}
}
argv=LocalAlloc (GMEM_FIXED,argc*sizeof (char*));
arg_p_copy=LocalAlloc (GMEM_FIXED,(1+arg_p-command_p)*sizeof (char));
argc=0;
arg_p=command_p;
if (argv==NULL || arg_p_copy==NULL){
argv=&arg_p;
argc=1;
} else {
char c;
while ((c=*arg_p)!='\0'){
while (c==' ' || c=='\t' || c=='\n' || c=='\r')
c=* ++arg_p;
if (c=='\0')
break;
argv[argc++]=arg_p_copy;
if (c=='\"'){
c = * ++arg_p;
while (!(c=='\0' || c=='\"')){
*arg_p_copy++ = c;
c = * ++arg_p;
}
if (c=='\"')
c = * ++arg_p;
} else {
while (!(c=='\0' || c==' ' || c=='\t' || c=='\n' || c=='\r')){
*arg_p_copy++ = c;
c = * ++arg_p;
}
}
*arg_p_copy++ = '\0';
if (c=='\0')
break;
++arg_p;
}
}
#endif
exit_tcpip_function=NULL;
#ifdef WINDOWS
execution_aborted=0;
return_code=0;
#endif
#ifdef DLL
heap_size=heap_size_param;
flags=flags_param;
ab_stack_size=ab_stack_size_param;
#endif
#ifdef WINDOWS
std_input_handle=GetStdHandle (STD_INPUT_HANDLE);
std_output_handle=GetStdHandle (STD_OUTPUT_HANDLE);
if (flags & 128)
std_error_handle=CreateFileA ("Messages",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
else
std_error_handle=GetStdHandle (STD_ERROR_HANDLE);
std_input_from_file = GetFileType (std_input_handle)==FILE_TYPE_DISK;
std_output_to_file = GetFileType (std_output_handle)==FILE_TYPE_DISK;
if (std_input_from_file || std_output_to_file)
init_std_io_from_or_to_file();
console_window_visible=flags & NO_RESULT_MASK ? 0 : 1;
if (heap_size_multiple<MINIMUM_HEAP_SIZE_MULTIPLE)
heap_size_multiple=MINIMUM_HEAP_SIZE_MULTIPLE;
if (heap_size_multiple>MAXIMUM_HEAP_SIZE_MULTIPLE)
heap_size_multiple=MAXIMUM_HEAP_SIZE_MULTIPLE;
#endif
for (arg_n=1; arg_n<argc; ++arg_n){
char *s;
s=argv[arg_n];
if (*s!='-')
break;
++s;
if (EQ_STRING1 (s,'h')){
long s;
++arg_n;
if (arg_n>=argc){
w_print_string ("Heapsize missing\n");
return -1;
}
s=parse_size (argv[arg_n]);
if (s<0)
return -1;
heap_size=s;
} else if (EQ_STRING1 (s,'s')){
long s;
++arg_n;
if (arg_n>=argc){
w_print_string ("Stacksize missing\n");
return -1;
}
s=parse_size (argv[arg_n]);
if (s<0)
return -1;
ab_stack_size=s;
} else if (EQ_STRING1 (s,'b'))
flags |= 1;
else if (EQ_STRING2 (s,'s','c'))
flags &= ~1;
else if (EQ_STRING1 (s,'t'))
flags |= SHOW_EXECUTION_TIME_MASK;
else if (EQ_STRING2 (s,'n','t'))
flags &= ~SHOW_EXECUTION_TIME_MASK;
else if (EQ_STRING2 (s,'g','c'))
flags |= 2;
else if (EQ_STRING3 (s,'n','g','c'))
flags &= ~2;
else if (EQ_STRING2 (s,'s','t'))
flags |= 4;
else if (EQ_STRING3 (s,'n','s','t'))
flags &= ~4;
else if (EQ_STRING2 (s,'n','r'))
flags |= NO_RESULT_MASK;
#ifdef GC_FLAGS
else if (EQ_STRING3 (s,'g','c','m'))
flags |= 64;
else if (EQ_STRING3 (s,'g','c','c'))
flags &= ~64;
else if (EQ_STRING3 (s,'g','c','i')){
int s;
++arg_n;
if (arg_n>=argc){
w_print_string ("Initial heap size missing\n");
return -1;
}
s=parse_size (argv[arg_n]);
if (s<0)
return -1;
initial_heap_size=s;
} else if (EQ_STRING3 (s,'g','c','f')){
int i;
++arg_n;
if (arg_n>=argc){
w_print_string ("Next heap size factor missing\n");
return -1;
}
i=parse_integer (argv[arg_n]);
if (i<0)
return -1;
heap_size_multiple=i<<8;
}
#endif
#ifdef WINDOWS
else if (EQ_STRING3 (s,'c','o','n'))
console_flag=1;
#endif
else
break;
}
--arg_n;
argv[arg_n]=argv[0];
global_argv=&argv[arg_n];
global_argc=argc-arg_n;
#ifdef STACK_OVERFLOW_EXCEPTION_HANDLER
SetUnhandledExceptionFilter (&clean_exception_handler);
#endif
#ifdef DLL
abc_main (start_address);
#else
abc_main();
#endif
if (exit_tcpip_function!=NULL)
exit_tcpip_function();
#ifdef WINDOWS
# if 1
if ( (!(flags & NO_RESULT_MASK) || (flags & SHOW_EXECUTION_TIME_MASK) || execution_aborted || (console_window_visible && !console_allocated) ) && !console_flag)
# else
if ( (!(flags & NO_RESULT_MASK) || (flags & SHOW_EXECUTION_TIME_MASK) || execution_aborted) && !console_flag)
# endif
wait_for_key_press();
if (std_output_to_file)
flush_file_buffer (&file_table[1]);
if (return_code==0 && execution_aborted)
return_code= -1;
#endif
#ifndef CLIB
ExitProcess (return_code);
#endif
#ifdef WINDOWS
return return_code;
#else
return 0;
#endif
}
#ifdef TIME_PROFILE
char time_profile_file_name_suffix[]=" Time Profile.pcl";
#define MAX_PATH_LENGTH 256
void create_profile_file_name (unsigned char *profile_file_name_string)
{
char *time_profile_file_name_p,*time_profile_file_name_suffix_p,*profile_file_name,*p;
int length_time_profile_file_name,time_profile_file_name_suffix_length,i;
time_profile_file_name_p=global_argv[0];
profile_file_name=&profile_file_name_string[8];
for (p=time_profile_file_name_p; *p!='\0'; ++p)
;
length_time_profile_file_name=p-time_profile_file_name_p;
if (time_profile_file_name_p[0]=='\"' && length_time_profile_file_name>1 && time_profile_file_name_p[length_time_profile_file_name-1]=='\"'){
++time_profile_file_name_p;
length_time_profile_file_name-=2;
}
for (i=0; i<length_time_profile_file_name; ++i)
profile_file_name[i]=time_profile_file_name_p[i];
profile_file_name[length_time_profile_file_name]='\0';
if (length_time_profile_file_name<=MAX_PATH_LENGTH){
WIN32_FIND_DATA find_data;
HANDLE find_first_file_handle;
find_first_file_handle=FindFirstFileA (profile_file_name,&find_data);
if (find_first_file_handle!=INVALID_HANDLE_VALUE){
char *file_name_p,*p;
int file_name_length;
file_name_p=find_data.cFileName;
for (p=file_name_p; *p!='\0'; ++p)
;
file_name_length=p-file_name_p;
for (p=profile_file_name+length_time_profile_file_name; p>profile_file_name && p[-1]!='\\' && p[-1]!='/'; --p)
;
if ((p-profile_file_name)+file_name_length<=MAX_PATH_LENGTH){
for (i=0; i<file_name_length; ++i)
p[i]=file_name_p[i];
p[i]='\0';
length_time_profile_file_name=&p[i]-profile_file_name;
}
FindClose (find_first_file_handle);
}
}
p=&profile_file_name[length_time_profile_file_name];
if (length_time_profile_file_name>3 && p[-4]=='.' && p[-3]=='e' && p[-2]=='x' && p[-1]=='e')
length_time_profile_file_name-=4;
time_profile_file_name_suffix_p=time_profile_file_name_suffix;
time_profile_file_name_suffix_length=sizeof (time_profile_file_name_suffix);
if (length_time_profile_file_name+time_profile_file_name_suffix_length>MAX_PATH_LENGTH){
time_profile_file_name_suffix_length=MAX_PATH_LENGTH-length_time_profile_file_name;
time_profile_file_name_suffix_p=&time_profile_file_name_suffix_p[sizeof (time_profile_file_name_suffix)-time_profile_file_name_suffix_length];
}
p=profile_file_name+length_time_profile_file_name;
for (i=0; i<=time_profile_file_name_suffix_length; ++i)
p[i]=time_profile_file_name_suffix_p[i];
*(unsigned int*)(&profile_file_name_string[4])=length_time_profile_file_name+time_profile_file_name_suffix_length;
}
#endif
#ifdef WRITE_HEAP
# include "iwrite_heap.c"
#endif