summaryrefslogtreecommitdiff
path: root/scon.c
diff options
context:
space:
mode:
Diffstat (limited to 'scon.c')
-rw-r--r--scon.c843
1 files changed, 843 insertions, 0 deletions
diff --git a/scon.c b/scon.c
new file mode 100644
index 0000000..15a9e4b
--- /dev/null
+++ b/scon.c
@@ -0,0 +1,843 @@
+/*
+ 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 STACK_OVERFLOW_EXCEPTION_HANDLER
+#define USE_CR2
+
+#ifdef STACK_OVERFLOW_EXCEPTION_HANDLER
+# include <signal.h>
+# ifdef LINUX
+# include <sys/resource.h>
+# endif
+# ifdef SOLARIS
+# include <ucontext.h>
+# include <procfs.h>
+# endif
+# include <fcntl.h>
+# include <sys/mman.h>
+#endif
+
+long min_write_heap_size;
+
+#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
+
+#ifdef STACK_OVERFLOW_EXCEPTION_HANDLER
+struct sigaction old_sa;
+
+extern int stack_overflow (void);
+extern int *halt_sp;
+
+# ifdef LINUX
+extern int *a_stack_guard_page;
+int *below_stack_page;
+
+void *allocate_memory_with_guard_page_at_end (int size)
+{
+ int alloc_size;
+ char *p,*end_p;
+
+ alloc_size=(size+4096+4095) & -4096;
+
+ p=malloc (alloc_size);
+ if (p==NULL)
+ return p;
+
+ end_p=(char*)(((int)p+size+4095) & -4096);
+ mprotect (end_p,4096,PROT_NONE);
+
+ return p;
+}
+
+# ifdef USE_CR2
+static void clean_exception_handler (int s,struct sigcontext sigcontext)
+{
+ if (
+ (((int)sigcontext.cr2 ^ (int)below_stack_page) & -4096)==0 ||
+ (((int)sigcontext.cr2 ^ (int)a_stack_guard_page) & -4096)==0)
+ {
+ sigcontext.eip=(int)&stack_overflow;
+ sigcontext.esp=(int)halt_sp;
+ } else {
+ sigaction (SIGSEGV,&old_sa,NULL);
+ /*
+ if (old_sa.sa_handler==SIG_DFL || old_sa.sa_handler==SIG_IGN)
+ sigaction (SIGSEGV,&old_sa,NULL);
+ else
+ old_sa.sa_sigaction (s,sigcontext);
+ */
+ }
+}
+# else
+static void clean_exception_handler_info (int s,struct siginfo *siginfo_p,void *p);
+
+static void clean_exception_handler_context (int s,struct sigcontext sigcontext)
+{
+ struct sigaction sa;
+
+ sigcontext.eip=(int)&stack_overflow;
+ sigcontext.esp=(int)halt_sp;
+
+ sigemptyset (&sa.sa_mask);
+ sa.sa_sigaction=&clean_exception_handler_info;
+ sa.sa_flags= SA_ONSTACK | SA_RESTART | SA_SIGINFO;
+
+ sigaction (SIGSEGV,&sa,NULL);
+}
+
+static void clean_exception_handler_info (int s,struct siginfo *siginfo_p,void *p)
+{
+ struct sigaction sa;
+
+ if (
+ (((int)siginfo_p->si_addr ^ (int)below_stack_page) & -4096)==0 ||
+ (((int)siginfo_p->si_addr ^ (int)a_stack_guard_page) & -4096)==0)
+ {
+ struct sigaction sa;
+
+ sigemptyset (&sa.sa_mask);
+ sa.sa_handler=&clean_exception_handler_context;
+ sa.sa_flags= SA_ONSTACK | SA_RESTART;
+
+ sigaction (SIGSEGV,&sa,NULL);
+ } else {
+ if (old_sa.sa_handler==SIG_DFL || old_sa.sa_handler==SIG_IGN)
+ sigaction (SIGSEGV,&old_sa,NULL);
+ else
+ old_sa.sa_sigaction (s,siginfo_p,p);
+ }
+}
+# endif
+
+static void install_clean_exception_handler (void)
+{
+ char proc_map_file_name[64];
+ int proc_map_fd,a;
+ struct sigaction sa;
+ stack_t sig_s;
+ int *sig_stack;
+
+ sprintf (proc_map_file_name,"/proc/%d/maps",getpid());
+
+ proc_map_fd=open (proc_map_file_name,O_RDONLY);
+
+ if (proc_map_fd<0)
+ return;
+
+ for (;;){
+ static char m[17];
+ unsigned int b,e;
+
+ if (read (proc_map_fd,m,17)==17 && m[8]=='-'){
+ int i;
+
+ b=0;
+ e=0;
+ for (i=0; i<8; ++i){
+ int c;
+
+ c=m[i];
+ b=b<<4;
+ if ((unsigned)(c-'0')<10)
+ b+=c-'0';
+ else if ((unsigned)((c & ~32)-'A')<26)
+ b+=(c & ~32)-('A'-10);
+ else
+ break;
+
+ c=m[9+i];
+ e=e<<4;
+ if ((unsigned)(c-'0')<10)
+ e+=c-'0';
+ else if ((unsigned)((c & ~32)-'A')<26)
+ e+=(c & ~32)-('A'-10);
+ else
+ break;
+ }
+
+ if (i==8){
+ if ((unsigned)&a - (unsigned)b < (unsigned)(e-b)){
+ struct rlimit rlimit;
+
+ if (getrlimit (RLIMIT_STACK,&rlimit)==0){
+ below_stack_page=(int*)((int)e-rlimit.rlim_cur-4096);
+ break;
+ }
+ }
+ continue;
+ }
+ }
+
+ {
+ char c;
+
+ c='\0';
+ while (read (proc_map_fd,&c,1)==1 && c!='\n')
+ ;
+
+ if (c=='\n')
+ continue;
+ }
+
+ close (proc_map_fd);
+ return;
+ }
+
+ close (proc_map_fd);
+
+ sig_stack=malloc (MINSIGSTKSZ);
+
+ if (sig_stack==NULL)
+ return;
+
+ sig_s.ss_flags=0;
+ sig_s.ss_size=MINSIGSTKSZ;
+ sig_s.ss_sp=sig_stack;
+
+ sigaltstack (&sig_s,NULL);
+
+ sigemptyset (&sa.sa_mask);
+# ifdef USE_CR2
+ sa.sa_sigaction=&clean_exception_handler;
+ sa.sa_flags= SA_ONSTACK | SA_RESTART;
+# else
+ sa.sa_sigaction=&clean_exception_handler_info;
+ sa.sa_flags= SA_ONSTACK | SA_RESTART | SA_SIGINFO;
+# endif
+
+ sigaction (SIGSEGV,&sa,&old_sa);
+}
+# else
+# ifdef DETECT_SYSTEM_STACK_OVERFLOW
+int *below_stack_page;
+# endif
+int *stack_guard_page;
+
+void *allocate_stack (int size)
+{
+ int alloc_size,size_a8192;
+ char *p,*end_p;
+
+ size=(size+3) & -4;
+ size_a8192=(size+8191) & -8192;
+ alloc_size=8192+(size_a8192<<1)+8192;
+
+ p=malloc (alloc_size);
+ if (p==NULL)
+ return NULL;
+
+ end_p=(char*)(((int)p+size+8191) & -8192);
+
+ mprotect (end_p,8192,PROT_NONE);
+
+ stack_guard_page=(int*)end_p;
+
+ return (void*)stack_guard_page;
+}
+
+void clean_exception_handler (int s,struct siginfo *siginfo_p,ucontext_t *ucontext_p)
+{
+ struct sigaction sa;
+ mcontext_t *mcontext_p;
+
+ if (
+# ifdef DETECT_SYSTEM_STACK_OVERFLOW
+ (((int)siginfo_p->si_addr ^ (int)below_stack_page) & -8192)==0 ||
+# endif
+ (((int)siginfo_p->si_addr ^ (int)stack_guard_page) & -8192)==0)
+ {
+ mcontext_p=&ucontext_p->uc_mcontext;
+# ifdef DETECT_SYSTEM_STACK_OVERFLOW
+ if (mcontext_p->gwins!=NULL){
+ int wi,wo,n_windows;
+
+ n_windows=mcontext_p->gwins->wbcnt;
+ wo=0;
+ for (wi=0; wi<n_windows; ++wi){
+ int *register_window_p;
+
+ register_window_p=mcontext_p->gwins->spbuf[wi];
+ if (((((int)register_window_p ^ (int)below_stack_page)) & -8192) != 0){
+ /*
+ struct rwindow *rwindow_p;
+ int i;
+
+ rwindow_p=&mcontext_p->gwins->wbuf[wi];
+ for (i=0; i<8; ++i){
+ register_window_p[i]=rwindow_p->rw_local[i];
+ register_window_p[8+i]=rwindow_p->rw_in[i];
+ }
+ */
+ if (wi!=wo)
+ mcontext_p->gwins->wbuf[wo]=mcontext_p->gwins->wbuf[wi];
+ ++wo;
+ }
+ }
+ mcontext_p->gwins->wbcnt=wo;
+ }
+# endif
+
+ mcontext_p->gregs[REG_PC]=(int)&stack_overflow;
+ mcontext_p->gregs[REG_nPC]=(int)&stack_overflow+4;
+ mcontext_p->gregs[REG_G5]=(int)halt_sp;
+ } else {
+ if (old_sa.sa_sigaction==SIG_DFL || old_sa.sa_sigaction==SIG_IGN)
+ sigaction (SIGSEGV,&old_sa,NULL);
+ else
+ old_sa.sa_sigaction (s,siginfo_p,ucontext_p);
+ }
+}
+
+static void install_clean_exception_handler (void)
+{
+ struct sigaction sa;
+# ifdef DETECT_SYSTEM_STACK_OVERFLOW
+ char proc_map_file_name[64];
+ struct prmap prmap;
+ stack_t sig_s;
+ int proc_map_fd,a,*sig_stack;
+
+ sprintf (proc_map_file_name,"/proc/%d/rmap",getpid());
+
+ proc_map_fd=open (proc_map_file_name,O_RDONLY);
+
+ if (proc_map_fd<0)
+ return;
+
+ do {
+ if (read (proc_map_fd,&prmap,sizeof (prmap))!=sizeof (prmap)){
+ close (proc_map_fd);
+ return;
+ }
+ } while (! ((unsigned)&a - (unsigned)prmap.pr_vaddr < (unsigned)prmap.pr_size));
+
+ close (proc_map_fd);
+
+ below_stack_page=(int*)((int)prmap.pr_vaddr-8192);
+
+ sig_stack=malloc (MINSIGSTKSZ);
+
+ if (sig_stack==NULL)
+ return;
+
+ sig_s.ss_flags=0;
+ sig_s.ss_size=MINSIGSTKSZ;
+ sig_s.ss_sp=sig_stack;
+
+ sigaltstack (&sig_s,NULL);
+# endif
+
+ sigemptyset (&sa.sa_mask);
+ sa.sa_sigaction=&clean_exception_handler;
+# ifdef DETECT_SYSTEM_STACK_OVERFLOW
+ sa.sa_flags= SA_ONSTACK | SA_RESTART | SA_SIGINFO;
+# else
+ sa.sa_flags= SA_RESTART | SA_SIGINFO;
+# endif
+
+ sigaction (SIGSEGV,&sa,&old_sa);
+}
+# endif
+#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;
+
+#ifdef TIME_PROFILE
+char time_profile_file_name_suffix[]=" Time Profile.pcl";
+
+void create_profile_file_name (unsigned char *profile_file_name_string)
+{
+ char *profile_file_name;
+ int r;
+
+ profile_file_name=&profile_file_name_string[8];
+
+ r=readlink ("/proc/self/exe",profile_file_name,MY_PATH_MAX-1);
+ if (r>=0){
+ int length_file_name,size_time_profile_file_name_suffix;
+
+ profile_file_name[r]='\0';
+
+ size_time_profile_file_name_suffix=sizeof (time_profile_file_name_suffix);
+ length_file_name=0;
+ while (profile_file_name[length_file_name]!='\0')
+ ++length_file_name;
+
+ if (length_file_name+size_time_profile_file_name_suffix>MY_PATH_MAX)
+ length_file_name=MY_PATH_MAX-size_time_profile_file_name_suffix;
+
+ strcat (&profile_file_name[length_file_name],time_profile_file_name_suffix);
+ *(unsigned int*)&profile_file_name_string[4] = length_file_name+size_time_profile_file_name_suffix-1;
+ } else {
+ strcpy (profile_file_name,&time_profile_file_name_suffix[1]);
+ *(unsigned int*)&profile_file_name_string[4] = sizeof (time_profile_file_name_suffix)-1;
+ }
+}
+#endif
+
+int execution_aborted;
+int return_code;
+
+int main (int argc,char **argv)
+{
+ int arg_n;
+
+ execution_aborted=0;
+ return_code=0;
+
+#ifdef STACK_OVERFLOW_EXCEPTION_HANDLER
+ install_clean_exception_handler();
+#endif
+
+ 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;
+}