/* generic bigforth loader in C is used for OS/2, Linux and Windows 95 */ #ifdef linux #define _GNU_SOURCE #endif #if defined(BSD) || defined(linux) || defined(DARWIN) #ifndef unix #define unix #endif #endif #include #include #include #include #include #ifdef unix #include #endif #ifdef _WIN32 #include HFILE sinp, sout, serr; #endif #define max(a, b) (a > b) ? a : b; #define VERBOSE int verbose=0; #ifdef VERBOSE # ifdef _WIN32 # define PRINTV(x...) if(verbose) { char buf[100]; sprintf(buf, x), \ _hwrite(sout, buf, strlen(buf)); } # define PRINTVX(n, x...) if(verbose>=n) { char buf[100]; sprintf(buf, x), \ _hwrite(sout, buf, strlen(buf)); } # else # define PRINTV(x...) if(verbose) fprintf(stderr, x) # define PRINTVX(n, x...) if(verbose>=n) fprintf(stderr, x) # endif #else # define PRINTV(x...) # define PRINTVX(n, x...) #endif /* OS-dependend part: bigFORTH needs the following file system and memory management primitives for loading: get amount of availabe memory allocate: read, write, stack and execute open file by name (r/o, binary) seek in a file to absolute position read in a number of bytes close the file */ #define CLEN(string) string,strlen(string) #ifdef OS2 /* create OS/2 loader */ #define INCL_SUB #define INCL_DOS #include #define OSFILE HFILE #define available_mem(size) (size=0x01000000) #define alloc_mem(size,heap) DosAllocMem((void *)&(heap), size, fALLOC) /* (heap=(int *) sbrk(size)) */ #define open_by_name(name,handle) \ ({ \ ULONG usAction=OPEN_ACTION_FAIL_IF_NEW; \ DosOpen(name, &handle, &usAction, 0L, 0, FILE_OPEN, 0x00C0, 0L); \ }) #define seek_to(handle,pos) \ ({ \ long dummy; \ DosSetFilePtr(handle, pos, FILE_BEGIN, &dummy); \ dummy; \ }) #define read_bytes(handle,to,size) \ ({ \ long dummy; \ DosRead(handle, to, size, &dummy); \ dummy; \ }) #define close_file(handle) DosClose(handle); #define PANIC(string) \ ({ \ long dummy; \ DosWrite(1, CLEN(string), &dummy); \ }) #define LOADER #endif /* OS/2 */ #ifdef unix /* Create Unix loader */ #include #include #include #include #include /* #include */ #include #define OSFILE int int bytes=0; static void* heapstart=(void*)0x10000000; #define available_mem(size) (size=0x01000000) #define alloc_mem(size,heap) (heap=(int *)mmap(heapstart, size, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0)); heapstart+=size; #define open_by_name(name,handle) (handle=open(name, O_RDONLY)) #define seek_to(handle,pos) ({ long _pos = pos; if(bytes!=_pos) lseek(handle, _pos, SEEK_SET); bytes=_pos; }) #define read_bytes(handle,to,size) (bytes+=read(handle, to, size)) #define close_file(handle) (close(handle)) #define PANIC(string) \ (write(fileno(stderr), CLEN(string))) #define LOADER #endif #ifdef _WIN32 /* Generic loader */ #define OSFILE HFILE #define available_mem(size) (size=0x0100000) #ifndef STACK_ALLOC static void* heapstart=(void*)0x10000000; #define alloc_mem(size,heap) (heap=(int *) VirtualAlloc(heapstart, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)); heapstart+=size; #else int * stackalloc(int size) { asm("movl 8(%ebp),%eax\n\ stlop: cmpl $0,(%esp)\n\ addl $-0x1000,%esp\n\ addl $-0x1000,%eax\n\ jb stlop\n\ movl %esp,%eax\n\ leave\n\ ret"); } #define alloc_mem(size,heap) (heap=stackalloc(size+0x1000)) #endif #define open_by_name(name,handle) (handle=_lopen(name, OF_READ)) #define seek_to(handle,pos) (_llseek(handle, pos, FILE_BEGIN)) #define read_bytes(handle,to,size) (_lread(handle, to, size)) #define close_file(handle) (_lclose(handle)) #define PANIC(string) \ (_hwrite(serr, string, strlen(string))) #define PANIC1(string, n) \ ({ char buf[100], sprintf(buf, string, n); \ _hwrite(serr, buf, strlen(buf)) }) #undef linux #define LOADER #endif /* end OS-dependend part */ typedef int BIGFORTH(int *, char *, void **); typedef int THROW(int); typedef BIGFORTH *PBIGFORTH; typedef THROW *PTHROW; char * cstring(char * string) { static char name[32]; memcpy(name, string+1, (int)(*string) & 0x1F); name[(int)(*string)]=0; return name; } static char bigforth_header[] = #ifdef OS2 "\353\137" #ifdef MINOS "\062" #else "\040" #endif "ANS bigFORTH 386-OS/2 rev. " #include "version.h" #ifdef MINOS "+MINOS rev. " #include "minos-version.h" #endif "\022compiled 24jan97py" #endif #ifdef unix "\353\137" #ifdef MINOS "\062" #else "\041" #endif "ANS bigFORTH 386-Linux rev. " #include "version.h" #ifdef MINOS "+MINOS rev. " #include "minos-version.h" #endif "\024compiled " VERSION_DATE "py" #endif #ifdef _WIN32 "\353\137" #ifdef MINOS "\062" #else "\041" #endif "ANS bigFORTH 386-Win32 rev. " #include "version.h" #ifdef MINOS "+MINOS rev. " #include "minos-version.h" #endif "\024compiled " VERSION_DATE "py" #endif "\011#00001py " "\035(c) 1990-2003 by Bernd Paysan" #ifdef MINOS "\016MINOS+bigFORTH" #else "\016plain bigFORTH" #endif ; #define DEFAULTDICT 0x0080000 int bfdat[10]= { 0, /* mroot */ 0, /* heaps */ DEFAULTDICT, /* dictionary size */ 0x00080000, /* Minimal */ 0x04000000, /* Maximal */ 0x00020000, /* Stacklen */ 1, /* argc */ 0, /* argv */ 0, /* env */ 0x00010000, /* Return stack len */ }; int recovery[32]; char fpdump[108]; jmp_buf throw_jmp_buf; #define mroot ((int **)bfdat)[0] #define heaps ((int **)bfdat)[1] #define memdat (bfdat+2) #define stlen (bfdat[5]) #define argc_ (bfdat[6]) #define argv_ ((char ***)bfdat)[7] #define env_ ((char ***)bfdat)[8] #define dict_ bfdat[2] #define rstack_ bfdat[9] #ifdef _WIN32 #define hinst_ *((HINSTANCE *)(((int *)bfdat)+9)) #define cmdsh_ ((int *)bfdat)[10] #define win_ ((int *)bfdat)[11] #define gc_ ((int *)bfdat)[12] #define sp_ ((int *)bfdat)[13] #endif char fileerr[8]="where's "; char file[1024]; char* linkinfo; void makeempty(int * block, int n) /* Marks the n bytes long block at block */ { PRINTVX(5, "Blocking %08x size %08x\n", (int)block, n); block[1]=0; block[0]=n; *(int *)(((char *)block)+n-sizeof(int))=n; } int * bf_alloc(int * free, int n) /* returns next free: free+2 is pointer for object! */ { int m; PRINTVX(4, "Allocate %08x size %08x\n", (int)free, n); n=(n+0x1B) & -0x10; if(*free < n) { PANIC("Running out of Memory!\n"); exit(1); } m=*free-n; makeempty(free,n); free[1]=-1; free=(int *)((int)free+n); makeempty((int *)free,m); return free; } int * find_module(char * name, int date, int * module) { int * retmodule; PRINTVX(4, "Trying to find %s hash %08x", cstring(name), date); PRINTVX(4, " in module %s (%08lx), cs %08x\n", cstring(((char*)module)+0x30), (long) module, module[5]); if(!memcmp(name,"\003nil",4)) return NULL; do { if(module[5]==date && !memcmp(name,((char *)module)+0x30,1+*name)) return module; PRINTVX(5, "Not found on this trial %s\n", cstring(((char*)module)+0x30)); if(module[2] && (retmodule = find_module(name, date, (int *)(module[2])))) return retmodule; else module=(int *)(module[4]); } while(module!=NULL); return NULL; } void bf_link(int * this, int * that, unsigned short * thread) { PRINTVX(3, "Linking %s ", cstring(((char*)this)+0x30)); PRINTVX(3, "with %s\n", that ? cstring(((char*)that)+0x30) : "nil"); asm("pushal\n\ movl 0x10(%ebp),%ebx\n\ movl 0x08(%ebp),%esi\n\ movl 0x0C(%ebp),%ebp\n\ movw (%ebx),%ax\n\ shll $16,%eax\n\ movw 4(%ebx),%ax\n\ pushl %ebx\n\ movw 2(%ebx),%bx\n\ shll $16,%ebx\n\ call linkthread\n\ popl %ebx\n\ movw 6(%ebx),%ax\n\ movw 2(%ebx),%bx\n\ shll $16,%ebx\n\ call linkrel\n\ popal"); } void linkit(char * nametable) { unsigned short tablesize; int namesize; int *this, *that; char* endtable; while(*((unsigned short *)nametable)) { tablesize = *((unsigned short *)nametable); nametable += sizeof(short); PRINTVX(2, "Link module %s, table size %04x\n",cstring(nametable),tablesize); endtable=nametable+tablesize; namesize = ((int)*nametable)+1; this=that=find_module(nametable, *(int *)(nametable + namesize), mroot); PRINTVX(3, "Module %s found\n", cstring(((char*)this)+0x30)); nametable += namesize + sizeof(int); bf_link(this, that, (unsigned short *)nametable); nametable += 4*sizeof(short); while(((unsigned int)nametable < (unsigned int)endtable) && that) { namesize = 1 + *nametable; that=find_module(nametable, *(int *)(nametable + namesize), mroot); nametable += namesize; if(that) nametable += sizeof(int); bf_link(this, that, (unsigned short *)nametable); nametable += 4*sizeof(short); PRINTVX(4, "Table rest length %04x\n",(int)endtable - (int)nametable); } } } int * loadmod(int * freemem, OSFILE handle, int * modptr, long filepos) { int * module; PRINTVX(3, "Loading to %08x from %08x module %08x pos %08lx\n", (int)freemem, (int)handle, (int)modptr, filepos); do { if(filepos) seek_to(handle, filepos); module=freemem+3; read_bytes(handle, module, 8L); if(module[1] == DEFAULTDICT) { PRINTVX(4, "Replace dict size %x with %x\n", module[1], dict_); module[1] = dict_; } PRINTVX(3, "Load Module with size %08x and DP %08x\n",module[1],module[0]); freemem=bf_alloc(freemem, module[1] + ((module[1]-1) >> 3) + 1 + sizeof(int)); memset(((char *)module)+module[1], 0, ((module[1]-1)>>3) + 1); module[-1]=1; read_bytes(handle, module+2, module[0] - 2*sizeof(int)); PRINTV("Loaded module %s\n", cstring((char*)module+0x30)); read_bytes(handle, linkinfo, 2); PRINTVX(3, "Loading link table %04x\n",*(unsigned short *)linkinfo); read_bytes(handle, linkinfo+2, *(unsigned short *)linkinfo); linkinfo += 2 + *(unsigned short *)linkinfo; if(modptr == NULL) { mroot=module; } else { int* parent = modptr-2; while(parent[4]) parent=(int *)parent[4]; parent[4]=(int)module; module[3]=(int)modptr; } { int submodule=module[2]; module[2]=0; if(submodule) freemem=loadmod(freemem, handle, module, submodule); } filepos=module[4]; PRINTVX(4, "Loading next module at %08lx to %08lx\n", filepos, (long) freemem); module[4]=0; } while(filepos); return freemem; } /* This loader is used for OSes with dynamic link libraries (such as Windows, OS/2 or Linux), and therefore it presents a wrapper for DLL loading The wrapper runs over a table containing the following functionality: - LoadModule - GetProcAddr for standard module loading - type - getkey - at - at? - form - bye for kernal basic IO and optionally - set_recovery for basic exception recovery. */ #ifdef OS2 /* Create OS/2-specific wrapper */ long bf_getkey(flag) { KBDKEYINFO inRecord; KbdCharIn(&inRecord, flag ? 0 : 1, 0); /* Read Key, but don't wait */ if(inRecord.fbStatus) return ((inRecord.chChar) | (inRecord.chScan << 8) | (inRecord.fsState << 16)); else return 0L; } void bf_type(long length, char * addr) { long dummy; DosWrite(0, addr, length, &dummy); } long bf_at_query() { unsigned short row, col; VioGetCurPos (&row, &col, 0); return ((long)row << 16) | (long)col; } static long form=0; long bf_form() { VIOMODEINFO mode; if(form == 0) { if(VioGetMode (&mode, 0)) { mode.row=25; mode.col=80; } form = (mode.row << 16) | (long)mode.col; } return form; } void bf_at(int col, int row) { VioSetCurPos (row, col, 0); } long bf_get_library(int length, char * addr) { char name[length+1]; HMODULE lib; int rc; memcpy(name, addr, length); name[length]=0; rc=DosLoadModule("", 0, name, &lib); return (rc ? 0 : lib); } long bf_proc_addr(HMODULE lib, int length, char * addr) { char name[length+1]; PFN proc; int rc; memcpy(name, addr, length); name[length]=0; rc=DosQueryProcAddr (lib, 0, name, &proc); return (long)(rc ? 0 : proc); } void prep_terminal() { KBDINFO kbdinfo; KbdGetStatus(&kbdinfo, 0); kbdinfo.fsMask = (kbdinfo.fsMask & 0xFFF0) | 6; /* noecho, raw mode */ KbdSetStatus(&kbdinfo, 0); (void)bf_form(); } void deprep_terminal() { KBDINFO kbdinfo; KbdGetStatus(&kbdinfo, 0); kbdinfo.fsMask = (kbdinfo.fsMask & 0xFFF0) | 0xA; /* noecho, cooked mode */ KbdSetStatus(&kbdinfo, 0); } void bf_bye(int ret) { deprep_terminal(); exit(ret); } void install_signal_handlers() { /* dummy */ } #endif /* OS/2 specific wrapper */ #ifdef unix #include #include #include #include #include #include #include #ifndef VMIN #include #endif extern int errno; static struct termios otio; int readline_echoing_p = 1; #ifndef CTRL #define CTRL(key) ((key)^'@') #endif static int eof_char = CTRL('D'); static int terminal_prepped = 0; static unsigned long cout=0, maxcur=0; void get_winsize() { unsigned short rows=0, cols=0; #ifdef TIOCGWINSZ struct winsize size; if (ioctl (1, TIOCGWINSZ, (char *) &size) >= 0) { rows = size.ws_row; cols = size.ws_col; } #endif if((rows == 0) || (cols == 0)) { char *s; if ((s=getenv("LINES"))) { rows=atoi(s); } if ((s=getenv("COLUMNS"))) { cols=atoi(s); } } if (rows==0) rows=24; if (cols==0) cols=80; maxcur = ((long)rows << 16) | (long)cols; } static void change_winsize(int sig, siginfo_t *info, void *_) { // signal(sig,change_winsize); #ifdef TIOCGWINSZ get_winsize(); #endif } void prep_terminal(); long get_screenpos() { unsigned short row=0, col=0; char inchar; if(!terminal_prepped) prep_terminal(); write(fileno(stdin), "\033[6n", 4); while(read(fileno(stdin), &inchar, 1) && inchar !='R') { switch(inchar) { case '\033': break; case '[': break; case ';': row=col; col=0; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': col=col*10+inchar-'0'; break; default: /* something went wrong */ break; } } row--; col--; return ((long)row << 16) | (long)col; } void prep_terminal () { int tty = fileno (stdin); struct termios tio; sigset_t set, oset; if (terminal_prepped) return; setlocale(LC_ALL, ""); sigemptyset (&set); sigemptyset (&oset); sigaddset (&set, SIGINT); sigprocmask (SIG_BLOCK, &set, &oset); tcgetattr (tty, &tio); otio = tio; readline_echoing_p = (tio.c_lflag & ECHO); tio.c_lflag &= ~(ICANON | ECHO); if (otio.c_cc[VEOF] != _POSIX_VDISABLE) eof_char = otio.c_cc[VEOF]; if ((tio.c_cflag & CSIZE) == CS8) tio.c_iflag &= ~(ISTRIP | INPCK); tio.c_iflag &= ~(ICRNL | INLCR); tio.c_lflag |= ISIG; tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; tio.c_cc[VLNEXT] = _POSIX_VDISABLE; tcsetattr (tty, TCSADRAIN, &tio); tcflow (tty, TCOON); terminal_prepped = 1; sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); #ifdef CLEAR_SCREEN write(fileno(stdin), "\033[2J\033[H", 7); cout = 0; #else if(isatty(tty)) { cout = get_screenpos(); } #endif get_winsize(); } void deprep_terminal () { int tty = fileno (stdin); sigset_t set, oset; if (!terminal_prepped) return; sigemptyset (&set); sigemptyset (&oset); sigaddset (&set, SIGINT); sigprocmask (SIG_BLOCK, &set, &oset); tcsetattr (tty, TCSADRAIN, &otio); tcflow (tty, TCOON); terminal_prepped = 0; sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); } long pending = -1L; long key_avail (stream) FILE *stream; { int tty = fileno (stream); long chars_avail = pending; int result; if(!terminal_prepped) prep_terminal(); result = ioctl (tty, FIONREAD, &chars_avail); return chars_avail; } unsigned char getkey(stream) FILE *stream; { int result; unsigned char c; if(!terminal_prepped) prep_terminal(); if (pending < 0) { result = read (fileno (stream), &c, sizeof (char)); if (result == sizeof (char)) return c; if (errno != EINTR) return (4); if (result == 0) return (0); } result = (int) pending; pending = -1L; return result; } long bf_getkey(int flag) { return((flag || key_avail(stdin)) ? (long)getkey(stdin) : 0L); } long bf_at_query() { if(!terminal_prepped) prep_terminal(); return cout; } long bf_form() { if(!maxcur) get_winsize(); return maxcur; } void bf_type(long length, char * addr) { int i; write(fileno(stdout), addr, length); for(i=0; i>= 0x10; cout++; if(cout >= (maxcur >> 0x10)) cout = (maxcur >> 0x10) -1; cout <<= 0x10; break; default: cout++; break; } } void bf_at(int col, int row) { char buf[20]; if(cout != (unsigned int)((row << 16) | col)) { sprintf(buf,"\033[%d;%dH", row+1, col+1); write(fileno(stdout), buf, strlen(buf)); cout = (row << 16) | col; } } long bf_get_library(int length, char * addr) { char name[length+1]; memcpy(name, addr, length); name[length]=0; PRINTVX(2, "Open dynamic library %s\n", name); return (long)dlopen(name, RTLD_LAZY | RTLD_GLOBAL); /* NOW */ } long bf_proc_addr(long lib, int length, char * addr) { char name[length+1]; memcpy(name, addr, length); name[length]=0; PRINTVX(3, "Get symbol %s\n", name); return (long)dlsym((void *)lib, name); } void bf_bye(int ret) { deprep_terminal(); exit(ret); } static void graceful_exit (int sig, siginfo_t *info, void *_) { fprintf (stderr, "\n\n%s.\n", strsignal (sig)); deprep_terminal(); exit (0x80|sig); } #ifdef __FreeBSD__ #include static void signal_throw(int sig, siginfo_t *info, ucontext_t *uap) { int code; mcontext_t *sigc = &(uap->uc_mcontext); long *dump1, *dump2, *dump3; struct { int signal; int throwcode; } *p, throwtable[] = { { SIGINT, -28 }, /* { SIGFPE, -55 }, */ { SIGBUS, -23 }, { SIGSEGV, -9 }, }; dump1 = (long*)&(sigc->mc_edi); dump2 = ((long*)(recovery))+1; dump3 = (long*)(sigc->mc_fpstate); memcpy(dump2, dump1, 8*sizeof(long)); dump2[3] = sigc->mc_esp; dump2 += 8; *dump2++ = sigc->mc_eip; *dump2++ = sigc->mc_cs; *dump2++ = sigc->mc_eflags; *dump2++ = sigc->mc_trapno; if(dump3) { memcpy(fpdump, (char*)(dump3), 108); *dump2-- = (long)fpdump; } else { *dump2-- = (long)0; } for (code=-256-sig, p=throwtable; psignal) { code = p->throwcode; break; } #if 1 if(sig == SIGFPE) { switch(info->si_code) { #ifdef FPE_INTDIV case FPE_INTDIV: code=-10; break; /* integer divide by zero */ #endif #ifdef FPE_INTOVF case FPE_INTOVF: code=-11; break; /* integer overflow */ #endif case FPE_FLTDIV: code=-42; break; /* floating point divide by zero */ case FPE_FLTOVF: code=-43; break; /* floating point overflow */ case FPE_FLTUND: code=-54; break; /* floating point underflow */ case FPE_FLTRES: code=-41; break; /* floating point inexact result */ #if 0 /* defined by Unix95, but unnecessary */ case FPE_FLTINV: /* invalid floating point operation */ case FPE_FLTSUB: /* subscript out of range */ #endif default: code=-55; break; } } #endif longjmp(throw_jmp_buf,code); /* or use siglongjmp ? */ } #endif #ifdef linux static void signal_throw(int sig, siginfo_t *info, void *_) { int code; struct sigcontext * sigc = (struct sigcontext *)((int *)(info+1)+5); long *dump1, *dump2, *dump3; struct { int signal; int throwcode; } *p, throwtable[] = { { SIGINT, -28 }, /* { SIGFPE, -55 }, */ { SIGBUS, -23 }, { SIGSEGV, -9 }, }; dump1 = (long*)&(sigc->edi); dump2 = ((long*)(recovery))+1; dump3 = (long*)(sigc->fpstate); memcpy(dump2, dump1, 8*sizeof(long)); dump2[3] = sigc->esp_at_signal; dump2 += 8; *dump2++ = sigc->eip; *dump2++ = sigc->cs; *dump2++ = sigc->eflags; *dump2++ = sigc->trapno; if(dump3) { memcpy(fpdump, (char*)(dump3), 108); *dump2-- = (long)fpdump; } else { *dump2-- = (long)0; } for (code=-256-sig, p=throwtable; psignal) { code = p->throwcode; break; } #if 1 if(sig == SIGFPE) { switch(info->si_code) { #ifdef FPE_INTDIV case FPE_INTDIV: code=-10; break; /* integer divide by zero */ #endif #ifdef FPE_INTOVF case FPE_INTOVF: code=-11; break; /* integer overflow */ #endif case FPE_FLTDIV: code=-42; break; /* floating point divide by zero */ case FPE_FLTOVF: code=-43; break; /* floating point overflow */ case FPE_FLTUND: code=-54; break; /* floating point underflow */ case FPE_FLTRES: code=-41; break; /* floating point inexact result */ #if 0 /* defined by Unix95, but unnecessary */ case FPE_FLTINV: /* invalid floating point operation */ case FPE_FLTSUB: /* subscript out of range */ #endif default: code=-55; break; } } #endif longjmp(throw_jmp_buf,code); /* or use siglongjmp ? */ } #endif #ifdef DARWIN #include static void signal_throw(int sig, siginfo_t *info, ucontext_t *uap) { int code; long *dump1, *dump2, *dump3; struct { int signal; int throwcode; } *p, throwtable[] = { { SIGINT, -28 }, /* { SIGFPE, -55 }, */ { SIGBUS, -23 }, { SIGSEGV, -9 }, }; dump1 = (long*)&(uap->uc_mcontext->__ss.__edi); dump2 = ((long*)(recovery))+1; dump3 = (long*)&(uap->uc_mcontext->__fs); memcpy(dump2, dump1, 8*sizeof(long)); dump2[3] = uap->uc_mcontext->__ss.__esp; dump2 += 8; *dump2++ = uap->uc_mcontext->__ss.__eip; *dump2++ = uap->uc_mcontext->__ss.__cs; *dump2++ = uap->uc_mcontext->__ss.__eflags; *dump2++ = uap->uc_mcontext->__es.__trapno; if(dump3) { memcpy(fpdump, (char*)(dump3), 108); *dump2-- = (long)fpdump; } else { *dump2-- = (long)0; } for (code=-256-sig, p=throwtable; psignal) { code = p->throwcode; break; } #if 1 if(sig == SIGFPE) { switch(info->si_code) { #ifdef FPE_INTDIV case FPE_INTDIV: code=-10; break; /* integer divide by zero */ #endif #ifdef FPE_INTOVF case FPE_INTOVF: code=-11; break; /* integer overflow */ #endif case FPE_FLTDIV: code=-42; break; /* floating point divide by zero */ case FPE_FLTOVF: code=-43; break; /* floating point overflow */ case FPE_FLTUND: code=-54; break; /* floating point underflow */ case FPE_FLTRES: code=-41; break; /* floating point inexact result */ #if 0 /* defined by Unix95, but unnecessary */ case FPE_FLTINV: /* invalid floating point operation */ case FPE_FLTSUB: /* subscript out of range */ #endif default: code=-55; break; } } #endif longjmp(throw_jmp_buf,code); /* or use siglongjmp ? */ } #endif static void termprep (int sig, siginfo_t *info, void *_) { // signal(sig,termprep); terminal_prepped=0; } void install_signal_handler(int sig, void (*handler)(int, siginfo_t *, void *)) /* installs three-argument signal handler for sig */ { struct sigaction action; action.sa_sigaction=handler; sigemptyset(&action.sa_mask); action.sa_flags=SA_RESTART|SA_NODEFER|SA_SIGINFO|SA_ONSTACK; /* pass siginfo */ sigaction(sig, &action, NULL); } void install_signal_handlers (void) { static short sigs_to_throw [] = { #ifdef SIGBREAK SIGBREAK, #endif #ifdef SIGINT SIGINT, #endif #ifdef SIGILL SIGILL, #endif #ifdef SIGEMT SIGEMT, #endif #ifdef SIGFPE SIGFPE, #endif #ifdef SIGIOT SIGIOT, #endif #ifdef SIGSEGV SIGSEGV, #endif #ifdef SIGALRM SIGALRM, #endif #ifdef SIGPIPE SIGPIPE, #endif #ifdef SIGPOLL SIGPOLL, #endif #ifdef SIGPROF SIGPROF, #endif #ifdef SIGBUS SIGBUS, #endif #ifdef SIGSYS SIGSYS, #endif #ifdef SIGTRAP SIGTRAP, #endif #ifdef SIGURG SIGURG, #endif #ifdef SIGUSR1 SIGUSR1, #endif #ifdef SIGUSR2 SIGUSR2, #endif #ifdef SIGVTALRM SIGVTALRM, #endif #ifdef SIGXFSZ SIGXFSZ, #endif }; static short sigs_to_quit [] = { #ifdef SIGHUP SIGHUP, #endif #ifdef SIGQUIT SIGQUIT, #endif #ifdef SIGABRT SIGABRT, #endif #ifdef SIGTERM SIGTERM, #endif #ifdef SIGXCPU SIGXCPU, #endif }; unsigned int i; #define DIM(X) (sizeof (X) / sizeof *(X)) /* for (i = 0; i < DIM (sigs_to_ignore); i++) signal (sigs_to_ignore [i], SIG_IGN); */ for (i = 0; i < DIM (sigs_to_throw); i++) install_signal_handler (sigs_to_throw [i], signal_throw); for (i = 0; i < DIM (sigs_to_quit); i++) install_signal_handler (sigs_to_quit [i], graceful_exit); #ifdef SIGCONT install_signal_handler (SIGCONT, termprep); #endif #ifdef SIGWINCH install_signal_handler (SIGWINCH, change_winsize); #endif } #endif /* Linux specific wrapper */ #ifdef _WIN32 int terminal_prepped=0; void prep_terminal() { #ifndef WIN_MAIN sinp=GetStdHandle(STD_INPUT_HANDLE); sout=GetStdHandle(STD_OUTPUT_HANDLE); serr=GetStdHandle(STD_ERROR_HANDLE); #else #ifdef VERBOSE serr=sout=_lcreat("test.out", 0); #endif #endif terminal_prepped=1; } void deprep_terminal() { } static unsigned long cout=0, maxcur=0; void get_winsize() { maxcur = ((long)24 << 16) | (long)80; } long bf_getkey(int flag) { #ifndef WIN_MAIN INPUT_RECORD conin; int n; if(!PeekConsoleInput(sinp, &conin, 1, &n)) return 0; if(!n || !ReadConsoleInput(sinp, &conin, 1, &n)) return 0; if(n && (conin.EventType == KEY_EVENT) && conin.Event.KeyEvent.bKeyDown) return conin.Event.KeyEvent.uChar.AsciiChar; else #endif return 0; } long bf_at_query() { if(!terminal_prepped) prep_terminal(); return cout; } long bf_form() { if(!maxcur) get_winsize(); return maxcur; } void bf_type(long length, char * addr) { int i; #if !defined(WIN_MAIN) || defined(VERBOSE) _hwrite(sout, addr, length); #endif #ifndef WIN_MAIN for(i=0; i>= 0x10; cout++; if(cout >= (maxcur >> 0x10)) cout = (maxcur >> 0x10) -1; cout <<= 0x10; break; default: cout++; break; } #endif } void bf_at(int col, int row) { #ifndef WIN_MAIN COORD curpos; curpos.X=col; curpos.Y=row+1; SetConsoleCursorPosition(sout, curpos); cout = (row << 16) | col; #endif } long bf_get_library(int length, char * addr) { char name[32]; long ret; memcpy(name, addr, length); name[length]=0; if((ret=(long)GetModuleHandle(name))) return ret; return(long)LoadLibrary(name); } long bf_proc_addr(long lib, int length, char * addr) { char name[32]; memcpy(name, addr, length); name[length]=0; return (long)GetProcAddress((HMODULE)lib, name); } void bf_bye(int ret) { deprep_terminal(); exit(ret); } char * strsignal(int sig) { static char signal[5]; sprintf(signal,"%d",sig); return signal; } /* static void graceful_exit (int sig) { PANIC1 ("\n\n%s.\n", strsignal (sig)); deprep_terminal(); exit (0x80|sig); } */ void install_signal_handlers() { /* dummy */ } #endif void * function_table[9] = { bf_get_library, bf_proc_addr, bf_type, bf_getkey, bf_at_query, bf_at, bf_form, bf_bye, (void *) recovery }; void go_bigforth() { int throw_code; int throw_to; install_signal_handlers(); recovery[0] = 0; recovery[12] = -1; if ((throw_code=setjmp(throw_jmp_buf))) { throw_to = recovery[0]; if(throw_to) ((PTHROW)throw_to)(throw_code); else { #ifdef _WIN32 char buf[100]; sprintf (buf, "\n\nbigforth: %s.\n", strsignal (throw_code)); _hwrite(serr, buf, strlen(buf)); #else fprintf (stderr, "\n\nbigforth: %s.\n", strsignal (throw_code)); #endif deprep_terminal(); exit (0x80|throw_code); } } else ((PBIGFORTH)mroot[6])(bfdat, &bigforth_header[0], function_table); } int convsize(char *s, long elemsize, int * param) /* converts s of the format [0-9]+[bekMG]? (e.g. 25k) into the number of bytes. the letter at the end indicates the unit, where e stands for the element size. default is e */ { char *endp; int n; n = strtoul(s, &endp, 0); if (endp!=NULL) { switch(*endp++) { case 'b': break; case 'k': n<<=10; break; case 'M': n<<=20; break; case 'G': n<<=30; break; default: endp--; case 'e': n*=elemsize; break; } } else { n*=elemsize; } *param = n; if(endp != NULL && *endp==',') { return endp+1-s; } else { return 0; } } static char * helpstring = "Usage: %s [engine options] ['--'] [image arguments]\n\ Engine Options:\n\ -h, --help Print this message and exit\n\ -v, --verbose Print debugging information during startup\n\ -i FILE, --image-file FILE Use image FILE instead of `%s.fi'\n\ -m SIZE, --mem-size SIZE Specify Forth heap size\n\ -s SIZE, --stack-size SIZE Specify stack size\n\ -r SIZE, --rstack-size SIZE Specify return stack size\n\ -d SIZE, --dictionary-size SIZE Specify Forth dictionary size\n\ SIZE arguments consist of an integer followed by a unit. The unit can be\n\ `b' (byte), `e' (element; default), `k' (KB), `M' (MB), or `G' (GB)\n\ "; #define ARG2 { argv[2] = argv[0]; argc -= 2; argv += 2; continue; } #define ARG1 { argv[1] = argv[0]; argc--; argv++; continue; } #define ARGN(n) \ if(n>0) { argv[n] = argv[0]; argc -= n; argv += n; continue; } \ else { argv[1] += -n; continue; } int checkarg(char ** argv, char * argstring, int * param) { int n; if(argv[1][0] == '-' && argv[1][1] == argstring[0]) { if(argv[1][2] == '=') { n = convsize(argv[1]+3, 1, param); return n ? -(n+3) : 1; } else if(argv[1][2] == '\0') { n = convsize(argv[2], 1, param); return 2; } else return 0; } else if(!strncmp(argv[1], "--", 2) && !strncmp(argv[1]+2, argstring, strlen(argstring))) { if(argv[1][2+strlen(argstring)] == '=') { n = convsize(argv[1]+3+strlen(argstring), 1, param); return n ? -(n+strlen(argstring)) : 1; } else if(argv[1][2+strlen(argstring)] == '\0') { convsize(argv[2], 1, param); return 2; } else return 0; } return 0; } #define CHECK_ARGS() \ while(argc > 1) { int n; \ if((n=checkarg(argv, "mem-size", memdat+2))) { ARGN(n); } \ else if((n=checkarg(argv, "stack-size", memdat+3))) { ARGN(n); } \ else if((n=checkarg(argv, "rstack-size", &rstack_))) { \ memdat[2] = max(memdat[2], 2*rstack_); \ ARGN(n); } \ else if((n=checkarg(argv, "dictionary-size", &dict_))) { \ memdat[2] = max(memdat[2], 2*dict_); \ ARGN(n); } \ else if(!strncmp(argv[1], "--image-file=", 13)) { \ strcpy(file, argv[1]+13); \ ARG1; \ } \ else if(!strncmp(argv[1], "-i=", 3)) { \ strcpy(file, argv[1]+3); \ ARG1; \ } \ else if(!strcmp(argv[1], "--image-file") || !strcmp(argv[1], "-i")) { \ strcpy(file, argv[2]); \ ARG2; \ } \ if(argc > 1) { \ if (!strcmp(argv[1], "--verbose") || !strcmp(argv[1], "-v")) { \ verbose++; \ ARG1; \ } else if(!strcmp(argv[1], "--")) { \ ARG1; \ break; \ } else if(!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) { \ printf(helpstring, argv[0], argv[0]); \ break; \ } else { \ break; \ } \ } else { \ break; \ } \ } #ifdef _WIN32 #ifdef WIN_MAIN int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) #else int main(int argc, char ** argv, char **env) #endif { int freemem, reg; int* nextfree; OSFILE handle; #ifdef WIN_MAIN char * arg[100]; char * env[100]; char ** argv, *args, *oldargs; int argc = 0; argv = arg; { int i, n; char *envs=GetEnvironmentStrings(); for(i=0; i<100; i++) { n=strlen(envs); if(n==0) { env[i] = NULL; break; }; env[i] = envs; envs = envs + n + 1; } } prep_terminal(); argv[0] = args = oldargs = GetCommandLine(); { int i, n = strlen(args); char sep_mode = '\0'; for(i=0; i 1 && argv[1][0]=='#' && argv[1][1]=='#') { static char args[200]; int i; PRINTV("Concatenate ## arguments\n"); args[0] = 0; for(i=1; i>2)-4]=0; heaps[(freemem>>2)-3]=0; makeempty(heaps,freemem-4*sizeof(int)); nextfree=heaps; linkinfo = (char *)(heaps+2); nextfree=bf_alloc(nextfree,stlen); open_by_name(file, handle); nextfree=loadmod(nextfree, handle, NULL, 0L); close_file(handle); *((short *) linkinfo) = 0; linkit((char *)(heaps+2)); #ifdef CLEAR_SCREEN cout = 0; bf_at_query(); #else #ifdef _WIN32 bf_at_query(); #endif #endif go_bigforth(); deprep_terminal(); exit(0); } #else int main(int argc, char ** argv, char **env) { int freemem; int* nextfree; OSFILE handle; strcpy(file,argv[0]); #if (defined OS2) || (defined _WIN32) if(!memcmp(".exe", file+strlen(file)-4, 4)) file[strlen(file)-4]=0; #endif strcpy(file+strlen(file),".fi"); CHECK_ARGS(); #ifdef _WIN32 if(argc > 1 && argv[1][0]=='#' && argv[1][1]=='#') { static char args[200]; int i; PRINTV("Concatenate ## arguments\n"); args[0] = 0; for(i=1; i>2)-4]=0; heaps[(freemem>>2)-3]=0; makeempty(heaps,freemem-4*sizeof(int)); nextfree=heaps; linkinfo = (char *)(heaps+2); nextfree=bf_alloc(nextfree,stlen); open_by_name(file, handle); if(handle < 0) { char * path = getenv("BIGFORTH_PATH") ?: INSTDIR; char buf[strlen(path)+strlen(file)+2]; int i=0; if(path && (file[0] == '/')) { for(i=strlen(file); i>=0 && file[i] != '/'; i--); } strcpy(buf, path); strcpy(buf+strlen(buf), "/"); strcpy(buf+strlen(buf), file+i); open_by_name(buf, handle); if(handle < 0) { write(fileno(stderr), CLEN("Could not open image file ")); write(fileno(stderr), CLEN(buf)); write(fileno(stderr), CLEN("\n")); exit(-1); } } nextfree=loadmod(nextfree, handle, NULL, 0L); close_file(handle); *((short *) linkinfo) = 0; linkit((char *)(heaps+2)); #ifdef CLEAR_SCREEN write(fileno(stdin), "\033[2J\033[H", 7); cout = 0; bf_at_query(); #endif go_bigforth(); deprep_terminal(); exit(0); } #endif