BoolU4 AssignBit(U1 *field,U8 bit,U8 val) { if (val) return Bts(field,bit); else return Btr(field,bit); } void PortNop() { InP(0x379); //This is an innoculous ISA (parallel port) //access which should take //fixed time on all machines. //It takes 1.66uS } void Exit() { Bts(&Fs->task_flags,TSSf_KILL_TASK); while (TRUE) SwapInNext; } void Kill(TssStruct *tss) { Bts(&tss->task_flags,TSSf_KILL_TASK); } void SimpleTimerIrq() { U8 old_flags=GetFlags; Cli; jiffies++; sys_timer+=SYS_TIMER0_PERIOD+1; SetFlags(old_flags); } U8 ReadSysTimer() { U8 i,old_flags=GetFlags; U8 result; Cli; OutP(0x43,0); //Latch Timer0 i=InP(0x40); i+=(InP(0x40)<<8); result=sys_timer+SYS_TIMER0_PERIOD-i; SetFlags(old_flags); return result; } U8 ExceptDepth(TssStruct *tss=NULL) { U8 result=0; ExceptStruct *tempt; if (!tss) tss=Fs; tempt=tss->next_except; while (tempt!=&tss->next_except) { result++; tempt=tempt->next; } return result; } asm { CP_TEST_EXCEPT:: MOV EAX,U4 FS:[TSS_LAST_EXCEPT] MOV EBP,U4 EXCEPT_EBP[EAX] MOV ESI,U4 EXCEPT_ESI[EAX] MOV EDI,U4 EXCEPT_EDI[EAX] CALL U4 EXCEPT_HANDLER_START[EAX] RET CP_CATCH_EXCEPT:: MOV EAX,U4 FS:[TSS_LAST_EXCEPT] MOV EDX,U4 EXCEPT_HANDLER_SKIP[EAX] MOV ESP,U4 EXCEPT_ESP[EAX] JMP EDX CP_SAVE_EXCEPT_ESI_EDI:: PUSH EBP MOV EBP,ESP MOV EAX,SF_PARAM1[EBP] MOV U4 EXCEPT_ESI[EAX],ESI MOV U4 EXCEPT_EDI[EAX],EDI POP EBP RET }; LTextern CP_TEST_EXCEPT void TestExcept(); LTextern CP_CATCH_EXCEPT void TakeExcept(); LTextern CP_SAVE_EXCEPT_ESI_EDI void SaveExceptRegs(ExceptStruct *t); exe {NoRegVar(ON);} void SysTry(U1 *start_label,U1 *skip_label,U8 my_ebp,U8 my_esp) { U4 *ptr=GetBasePtr; ExceptStruct *tempt=MAlloc(sizeof(ExceptStruct)); tempt->handler_start=start_label; tempt->handler_skip=skip_label; tempt->esp=my_esp+8; tempt->ebp=my_ebp; SaveExceptRegs(tempt); InsQue(tempt,Fs->last_except); } void SysCatch() { ExceptStruct *tempt=Fs->last_except; RemQue(tempt); Free(tempt); } void throw(...) { ExceptStruct *tempt=Fs->last_except; U8 i; AdamLog("Depth:%02X Tsk:%08X throw(", ExceptDepth(Fs),Fs); //TODO: fix compiler--"(FS)" for (i=0;iexcept_argc=argc; Fs->except_argv=argv; Fs->except_ebp=GetBasePtr; Fs->catch_except=FALSE; while (tempt!=&Fs->next_except) { TestExcept; if (Fs->catch_except) TakeExcept; SetBasePtr(Fs->except_ebp); RemQue(tempt); Free(tempt); tempt=Fs->last_except; } PutSysText("ST_UNHANDLED_EXCEPTION"); while (TRUE) SwapInNext; } exe {NoRegVar(OFF);} void KbdCmdSend(U8 port, U1 val) { U8 timeout; for (timeout=50000; (InP(KEYB_CTRL)&2) && timeout;timeout--) PortNop; if (timeout) OutP(port, val); else throw(EXCEPT_LOCAL); } I8 KbdCmdRead() { U8 timeout; for (timeout=50000; timeout; timeout--) { if (InP(KEYB_CTRL) & 1) return InP(KEYB_PORT); else PortNop; } return -1; } void KbdCmdFlush() { I8 i; for (i=0;i<1000;i++) { if (InP(KEYB_CTRL) & 1) { InP(KEYB_PORT); i=0; } else PortNop; } } void KbdSetLEDs(U8 sc) { U8 old_flags=GetFlags; U1 v=0; AssignBit(&v,0,Bt(&sc,SCf_SCROLL)); AssignBit(&v,1,Bt(&sc,SCf_NUM)); AssignBit(&v,2,Bt(&sc,SCf_CAPS)); Cli; KbdCmdSend(KEYB_PORT,0xED); KbdCmdSend(KEYB_PORT,v); SetFlags(old_flags); } void KbdMouseCmdAck(U1 val) { U1 b; U8 timeout=32; BoolU4 cont=TRUE; while (cont && timeout) { try { KbdCmdSend(KEYB_CTRL,0xD4); KbdCmdSend(KEYB_PORT,val); b=KbdCmdRead; if (b==0xFA) cont=FALSE; } catch Fs->catch_except=TRUE; timeout--; } if (cont) throw(EXCEPT_LOCAL); } void InitKeyboard() { KbdCmdSend(KEYB_PORT,0xF0); KbdCmdSend(KEYB_PORT,0x02); KbdSetLEDs(sys_cur_scan_code); } U1 scan_code_map[0x100]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,SC_SHIFT,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,SC_CR,SC_CTRL,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0x35,0,0,0,SC_ALT,0,0,0,0,0,0, 0,0,0,0,0,0,0,SC_HOME,SC_CURSOR_UP,SC_PAGE_UP,0,SC_CURSOR_LEFT,0,SC_CURSOR_RIGHT,0,SC_END, SC_CURSOR_DOWN,SC_PAGE_DOWN,SC_INSERT,SC_DELETE,0,0,0,0,0,0,0,0,SC_GUI,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; U1 num_lock_map[0x100]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,8,9,10,0,5,6,7,0,2, 3,4,11,0x34,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,SC_CR,SC_CTRL,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0x35,0,0,0,SC_ALT,0,0,0,0,0,0, 0,0,0,0,0,0,0,SC_HOME,SC_CURSOR_UP,SC_PAGE_UP,0,SC_CURSOR_LEFT,0,SC_CURSOR_RIGHT,0,SC_END, SC_CURSOR_DOWN,SC_PAGE_DOWN,SC_INSERT,SC_DELETE,0,0,0,0,0,0,0,0,SC_GUI,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; asm {CP_KBD_HANDLER::} void KbdHandler() { void kbd_hand2(); U8 sc=sys_cur_scan_code&~0x1FF, sc2=InP(KEYB_PORT),sc3,sc_raw; Bts(&sys_irq_flags,1); if (sc2==0xE0) { sys_cur_scan_code|=SCF_PRIOR_E0; return; } AssignBit(&sc2,SCf_KEY_UP,sc2 & 0x80); AssignBit(&sc2,SCf_E0_PREFIX,Btr(&sc,SCf_PRIOR_E0)); sc_raw=sc2; if (sc & SCF_NUM) { if (sc3=num_lock_map[sc2.u1[0]]) sc2.u1[0]=sc3; } else { if (sc3=scan_code_map[sc2.u1[0]]) sc2.u1[0]=sc3; } if (sc2==SC_SHIFT) { sc|=SCF_SHIFT; goto new_key_done; } if (sc2==SC_SHIFT+SCF_KEY_UP) { sc&=~SCF_SHIFT; goto new_key_done; } if (sc2==SC_CTRL) { sc|=SCF_CTRL; goto new_key_done; } if (sc2==SC_CTRL+SCF_KEY_UP) { sc&=~SCF_CTRL; goto new_key_done; } if (sc2==SC_ALT) { sc|=SCF_ALT; goto new_key_done; } if (sc2==SC_ALT+SCF_KEY_UP) { sc&=~SCF_ALT; goto new_key_done; } if (sc2==SC_CAPS) goto new_key_done; if (sc2==SC_CAPS+SCF_KEY_UP) { sc^=SCF_CAPS; KbdSetLEDs(sc); goto new_key_done; } if (sc2==SC_NUM) goto new_key_done; if (sc2==SC_NUM+SCF_KEY_UP) { sc^=SCF_NUM; KbdSetLEDs(sc); goto new_key_done; } if (sc2==SC_SCROLL) goto new_key_done; if (sc2==SC_SCROLL+SCF_KEY_UP) { sc^=SCF_SCROLL; KbdSetLEDs(sc); goto new_key_done; } if (sc & SCF_CTRL && sc & SCF_ALT) { if (sc2==SC_DELETE) { Bts(&sys_flags,SYSf_CTRL_ALT_DEL); goto mostly_done; } if (sc2==1) { Bts(&sys_flags,SYSf_CTRL_ALT_ESC); goto mostly_done; } if (sc2==15) { Bts(&sys_flags,SYSf_CTRL_ALT_TAB); goto mostly_done; } if (sc2==0x2D) { Bts(&sys_flags,SYSf_CTRL_ALT_X); goto mostly_done; } if (sc2==0x2E) { Bts(&sys_flags,SYSf_CTRL_ALT_C); goto mostly_done; } } new_key_done: sc|=SCF_NEW_KEY; mostly_done: sys_cur_scan_code=sc|sc2; sys_cur_raw_scan_code=sc|sc_raw; if (kbd_hand2=ext[EXT_IRQ01]) kbd_hand2(); Btr(&sys_irq_flags,1); } U8 DivU8(U8 n1,U8 n2) { U8 r_lo=n1,r_hi=0; U8 i; for (i=0;i<64;i++) { if (r_lo & 0x8000000000000000) { r_hi<<=1; r_hi++; } else r_hi<<=1; r_lo<<=1; if (r_hi>=n2) { r_hi-=n2; r_lo++; } } return r_lo; } I8 DivI8(I8 n1,I8 n2) { U8 r_lo,r_hi=0; U8 i; BoolU4 signed; if (n1<0) { signed=TRUE; n1=-n1; } else signed=FALSE; if (n2<0) { signed=!signed; n2=-n2; } r_lo=n1; for (i=0;i<64;i++) { if (r_lo & 0x8000000000000000) { r_hi<<=1; r_hi++; } else r_hi<<=1; r_lo<<=1; if (r_hi>=n2) { r_hi-=n2; r_lo++; } } return (signed) ? -r_lo:r_lo; } U8 ModU8(U8 n1,U8 n2) { U8 r_lo=n1,r_hi=0; U8 i; for (i=0;i<64;i++) { if (r_lo & 0x8000000000000000) { r_hi<<=1; r_hi++; } else r_hi<<=1; r_lo<<=1; if (r_hi>=n2) { r_hi-=n2; r_lo++; } } return r_hi; } I8 ModI8(I8 n1,I8 n2) { U8 r_lo,r_hi=0; U8 i; BoolU4 signed; if (n1<0) { signed=TRUE; n1=-n1; } else signed=FALSE; if (n2<0) { signed=!signed; n2=-n2; } r_lo=n1; for (i=0;i<64;i++) { if (r_lo & 0x8000000000000000) { r_hi<<=1; r_hi++; } else r_hi<<=1; r_lo<<=1; if (r_hi>=n2) { r_hi-=n2; r_lo++; } } return (signed) ? -r_hi:r_hi; } LTDate BootTime() //Roughly 49,710ths of a second since boot { return DivU8(ReadSysTimer<<14,1833333*3*3*3/125); } U2 RandU2() //TODO: fix this { LTDate i=BootTime; rnd_SEED^=MulU8(rnd_SEED,0x56234)+i.date^i.time^jiffies+ModU8(rnd_SEED,0x7635); return rnd_SEED.u2[0]; } U8 RandU4() { U8 result=0; result.u2[0]=RandU2; result.u2[1]=RandU2; return result; } I8 ToUpper(I8 ch) { if (ch>='a' && ch<='z') return ch+'A'-'a'; else return ch; } I8 AtoI(I1 *st,I8 radix=10,I1 **end_ptr=NULL) { BoolU4 neg=FALSE; I1 ch; I8 result=0,k=0; if (radix<2||radix>36) return 0; while (*st==CH_SPACE || *st==CH_SHIFT_SPACE || *st==CH_TAB) st++; if (*st=='-') { st++; neg=TRUE; } if (*st=='+') st++; while (ch=ToUpper(*st++)) { k++; if (radix==10) { if (ch>='0' && ch<='9') result=MulI8(result,10)+ch-'0'; else if (k==2 && !result) { if (ch=='X') radix=16; else if (ch=='B') radix=2; else if (ch=='o') radix=8; else break; } else break; } else if (radix>10) { if (ch>='0' && ch<='9') result=MulI8(result,radix)+ch-'0'; else if (ch>='A' && ch<='A'+radix-11) result=MulI8(result,radix)+ch-'A'+10; else break; } else { if (ch>='0' && ch<='0'+radix-1) result=MulI8(result,radix)+ch-'0'; else break; } } if (end_ptr) *end_ptr=st-1; return (neg)? -result:result; } void BusyWait(U8 uS) //Loosely timed { U8 i; for (i=0;ilast_lex->flags,LFf_EXTERNS_TO_IMPORTS,val); } BoolU4 KeepPrivate(BoolU4 val) { return AssignBit(&Fs->last_lex->flags,LFf_KEEP_PRIVATE,val); } BoolU4 PTrace(BoolU4 val) { return AssignBit(&Fs->last_lex->flags,LFf_PARSE_TRACE,val); } BoolU4 OTrace(BoolU4 val) { return AssignBit(&Fs->last_lex->flags,LFf_OPT_TRACE,val); } BoolU4 CTrace(BoolU4 val) { return AssignBit(&Fs->last_lex->flags,LFf_COMPILE_TRACE,val); } BoolU4 LTrace(BoolU4 val) { return AssignBit(&Fs->last_lex->flags,LFf_LEX_TRACE,val); } BoolU4 NoRegVar(BoolU4 val) { return AssignBit(&Fs->last_lex->flags,LFf_NO_REG_VAR,val); } BoolU4 Echo(BoolU4 val) { return AssignBit(&Fs->last_lex->flags,LFf_ECHO,val); } BoolU4 SysEcho(BoolU4 val) { return AssignBit(&Fs->last_lex->flags,LFf_ECHO,val); } BoolU4 Silent(BoolU4 val) { return AssignBit(&Fs->crt_flags,CRTf_SILENT,val); } BoolU4 Preempt(BoolU4 val) { return AssignBit(&sys_flags,SYSf_PREEMPTIVE,val); } BoolU4 SysDbg(BoolU4 val) { return AssignBit(&sys_flags,SYSf_DEBUG,val); } BoolU4 IsSysDbg() { return Bt(&sys_flags,SYSf_DEBUG); } BoolU4 Raw(BoolU4 val) { if (val) { OutP(VGA_SC_INDEX,VGA_MAP_MASK); OutP(VGA_SC_DATA,0x0F); } return AssignBit(&sys_flags,SYSf_RAW_CRT_OUT,val); } BoolU4 IsRaw() { return Bt(&sys_flags,SYSf_RAW_CRT_OUT); } U1 *Caller() { U4 *bp=GetBasePtr; bp=*bp+4; return *bp; } U1 *CallerCaller() { U4 *bp=GetBasePtr; bp=*bp; bp=*bp+4; return *bp; } void DbgStr(I1 *st,U8 mS=100) { BoolU4 old_flags=GetFlags; BoolU4 old_raw; Cli; old_raw=Raw(ON); cout "DbgStr(",st,")"; BusyWait(mS<<10); SetFlags(old_flags); Raw(old_raw); } void DbgNum(U8 num,U8 mS=100) { BoolU4 old_flags=GetFlags; BoolU4 old_raw; Cli; old_raw=Raw(ON); cout "DbgNum(",num,")"; BusyWait(mS<<10); SetFlags(old_flags); Raw(old_raw); } void DbgF(double d,U8 mS=100) { BoolU4 old_flags=GetFlags; BoolU4 old_raw; Cli; old_raw=Raw(ON); cout "DbgF(",d,")"; BusyWait(mS<<10); SetFlags(old_flags); Raw(old_raw); } void DbgAdd(U4 *add,U8 mS=100) { BoolU4 old_flags=GetFlags; BoolU4 old_raw; Cli; old_raw=Raw(ON); PrintF("DbgAdd(%P)",add); BusyWait(mS<<10); SetFlags(old_flags); Raw(old_raw); } void DbgD(U4 *add,U8 cnt=0x80,U8 mS=100) { BoolU4 old_flags=GetFlags; BoolU4 old_raw; Cli; old_raw=Raw(ON); D(add,cnt); BusyWait(mS<<10); SetFlags(old_flags); Raw(old_raw); } void DbgDm(U4 *add,U8 cnt=0x80,U8 mS=100) { BoolU4 old_flags=GetFlags; BoolU4 old_raw; Cli; old_raw=Raw(ON); Dm(add,cnt); BusyWait(mS<<10); SetFlags(old_flags); Raw(old_raw); } SysHashEntry *FindLocalHash(I1 *st,U8 mask) { return FindHashEntry(st,Fs->hash_table,mask); } void Beeps(U8 j,BoolU4 busy) { U8 i,f; for (i=0;i<8;i++) { if (Bt(&j,i+24)) { f=200; if (Bt(&j,i+8)) f+=400; if (Bt(&j,i+16)) f+=800; Sound(f); if (busy) { if (Bt(&j,i)) BusyWait(300000); else BusyWait(100000); } else { if (Bt(&j,i)) Sleep(400); else Sleep(150); } Sound(0); } if (busy) BusyWait(150000); else Sleep(300); } } void UnrecoverableSysError(U8 j) { Cli; while (TRUE) { Beeps(j,TRUE); Raw(ON); coutln "Unrecoverable SysError:",j; BusyWait(500000); } } asm {CP_BREAK::} void Break() { ReleaseTaskPartitions; IntFlushMsgs; throw(EXCEPT_BREAK); } void ThrowDivide(U1 *eip) { throw(EXCEPT_ARITHMETIC,eip); } void ThrowFloating(U1 *eip) { throw(EXCEPT_FLOATING,eip); } SysHashEntry *FindPSect(U8 add,I8 *offset) { SysHashEntry *result=NULL,*temph; SysHashTable *h=Fs->hash_table; ClassStruct *tempc; U8 i,best=0x8000,j; while (h) { for (i=0;i<=h->mask;i++) { temph=h->body[i]; while (temph) { if (temph->type&HTT_FUNCTION) { tempc=temph; j=tempc->executable_address; } else j=temph->user0; j=add-j; if (temph->type&(HTT_SYS_SYMBOL|HTT_FUNCTION)) { if (jnext; } } h=h->next; } *offset=best; return result; } U8 GetS(I1 *buf,U8 size) { I8 ch; I1 *buf2; U8 i=0; void my_SysGetS(); if (!size || !buf) return 0; i=FindExtern("SysGetS"); if (i) { my_SysGetS=i; buf2=my_SysGetS(); if (StrLen(buf2)>size-1) { MemCpy(buf,buf2,size-1); buf[size-1]=0; } else StrCpy(buf,buf2); i=StrLen(buf); Free(buf2); } else { while (TRUE) { ch=GetKey; if (ch==CH_CR) { PutChar(ch); break; } if (ch==CH_BACKSPACE) { if (i>0) { i--; PutChar(ch); } } else { if (i