Listing of file='TINYC.SRC;05' on disk='vmedia/chip_10-sector.ccvf'
; TITLE TINY-C VERSION 80-01-03, NOVEMBER 1980 ORG 8200H TORG EQU $ ; ERROR CODES STATERR EQU 1 CURSERR EQU 2 SYMERR EQU 3 RPARERR EQU 5 RANGERR EQU 6 CLASERR EQU 7 SYNXERR EQU 9 LVALERR EQU 14 PUSHERR EQU 16 TMFUERR EQU 17 TMVRERR EQU 18 TMVLERR EQU 19 LINKERR EQU 20 ARGSERR EQU 21 LBRCERR EQU 22 MCERR EQU 24 SYMERRA EQU 26 KILL EQU 99 VLEN EQU 3 ;ALLOCATION LENGTH OF SYMBOLS CR EQU 13 ;CARRIAGE RETURN LF EQU 10 ;LINE-FEED ERS EQU 11 ;ERASE-LINE (VT) FF EQU 12 ;ERASE-PAGE (FORM-FEED) ASCRET EQU CR ;END-OF-LINE CHARACTER ; * ENTRY POINTS START: JMP COLD JMP WARM JMP HOT ; TAILORING VECTOR ECHO: DB 1 ; 0==SUPPRESSES ECHOING JMP INCH ; * I/O VECTORS * JMP OUTCH JMP CHRDY JMP FOPEN JMP FREAD JMP FWRITE JMP FCLOSE JMP MCESET PRBEGIN:NOP NOP RET STBEGIN:NOP NOP RET PRDONE: NOP NOP RET ; MC TOOLS XMCESET:JMP MCESET XTOPTOI:JMP TOPTOI XPUSHK: JMP PUSHK MCARGS: DB 0 ESCAPE: DB 27 ; ESCAPE CHARACTER EFREE EQU 0000H ; HIGHEST USABLE RAM +1 BSTACK: DW BFREE ; SPACE ALLOCATION ESTACK: DW -BFREE-80H+5 BFUN: DW BFREE+80H EFUN: DW -BFREE-100H+6 BVAR: DW BFREE+100H EVAR: DW -BFREE-100H-SPACE/8+VLEN+6 BPR: DW BFREE+100H+SPACE/8 EPR: DW -EFREE+100H MSTACK: DW EFREE ; STANDARD CELLS ERR: DW 0 ERRAT: DW 0 LEAVE: DB 0 BRAKE: DB 0 TOP: DW 0 NXTVAR: DW 0 CURFUN: DW 0 CURGLBL:DW 0 FNAME: DW 0 LNAME: DW 0 STCURS: DW 0 CURSOR: DW 0 PRUSED: DW 0 PROGEND:DW 0 APPLVL: DB 0 ; LITERALS BALPHS EQU $ ; BEGIN ALPHABETICS XIF: DB 'IF',0 XELS: DB 'ELSE',0 XINT: DB 'INT',0 XCHAR: DB 'CHAR',0 XWHI: DB 'WHILE',0 XRET: DB 'RETURN',0 XBRK: DB 'BREAK',0 XENDL: DB 'ENDLIBRARY',0 XR: DB 'R' XG: DB 'G' XX: DB 'X' DB 0FFH ; END OF ALPHABETICS LB: DB '[',0 RB: DB ']',0 LPAR: DB '(',0 RPAR: DB ')',0 COMMA: DB ',',0 NEWLINE:DB CR,0 CMNT: DB '/' XSTAR: DB '*',0 SEMI: DB ';',0 XPCNT: DB '%',0 XSLASH: DB '/',0 XPLUS: DB '+',0 XMINUS: DB '-',0 LT: DB '<',0 GT: DB '>',0 NOTEQ: DB '!=',0 EQEQ: DB '=' XEQ: DB '=',0 GE: DB '>=',0 LE: DB '<=',0 XNL: DB ASCRET,0 ; EQ PERFORMS TOP-1:=TOP EQ: CALL TOPTOI PUSH D CALL POPST ORA A JZ EQ2 MVI C,2 EQ2: MOV A,B CPI 'L' JNZ EQERR XCHG POP D MOV M,E DCR C JZ PUSHK INX H MOV M,D JMP PUSHK EQERR: CALL ESET DB LVALERR POP D JMP PUSHK ; BC:=-BC DNEG: MOV A,C CMA MOV C,A MOV A,B CMA MOV B,A INX B RET ; DIFFERENCE BETWEEN TWO TOP VALUES INTO DE TOPDIF: CALL POPTWO ; DE:=DE-BC DSUB: MOV A,E SUB C MOV E,A MOV A,D SBB B MOV D,A ORA E MOV A,D RLC RET ; DE:=BC+DE DADD: MOV A,C ADD E MOV E,A MOV A,B ADC D MOV D,A ORA E MOV A,D RLC RET ; DE:=BC*DE DMPY: LXI H,0 DM2: MOV A,C RRC JNC DM3 DAD D DM3: CALL BCRS JNZ DM4 XCHG RET DM4: CALL DELS JNZ DM2 XCHG RET ; SHIFT BC RIGHT BCRS: XRA A MOV A,B RAR MOV B,A MOV A,C RAR MOV C,A ORA B RET ; SHIFT DE LEFT DELS: XRA A ; ROTATE DE LEFT RDEL: MOV A,E RAL MOV E,A MOV A,D RAL MOV D,A ORA E RET ; DE,HL:=DE/BC DREM: MOV A,D XRA B PUSH PSW MOV A,D ORA A CM DENEG MOV A,B ORA A CM DNEG MVI A,16 PUSH PSW XCHG LXI D,0 DR2: DAD H CALL RDEL JZ DR3 CALL DCMP JM DR3 MOV A,L ORI 1 MOV L,A CALL DSUB DR3: POP PSW DCR A JZ DR4 PUSH PSW JMP DR2 DR4: POP PSW RP CALL DENEG XCHG CALL DENEG XCHG RET ; DE:=DE/BC DDIV: CALL DREM XCHG RET ; DE:=-DE DENEG: MOV A,D CMA MOV D,A MOV A,E CMA MOV E,A INX D RET ; COMPARE DE AND BC DCMP: MOV A,E SUB C MOV A,D SBB B RET ; STACK TOOLS ; TOPTOI POPS TOP OF STACK INTO DE TOPTOI: CALL POPST STA TPCLASS MOV A,B CPI 'A' JZ TT2 XCHG MOV E,M INX H MOV D,M TT2: DCR C RNZ LDA TPCLASS ORA A RNZ MOV A,E RLC SBB A MOV D,A RET TPCLASS:DB 0 ; POPS TWO FROM STACK, BC:=TOP,DE:=NEXT POPTWO: CALL TOPTOI PUSH D CALL TOPTOI POP B RET ; POPS THE STACK INTO A,B,C,DE. NEW TOP IN HL POPST: LHLD TOP MOV A,M INX H MOV B,M INX H MOV C,M INX H MOV E,M INX H MOV D,M PUSH B LXI B,-9 DAD B POP B SHLD TOP RET ; PUSHES CONSTANT 1. PONE: LXI D,1 JMP PUSHK ; PUSHES CONSTANT 0. PZERO: LXI D,0 ; PUSHES CONSTANT IN DE PUSHK: XRA A MVI B,'A' MVI C,2 ; PUSHES CLASS (A), LVALUE (B), SIZE (C), STUFF (DE) ; ONTO STACK. PUSHST: LHLD TOP PUSH D LXI D,5 DAD D SHLD TOP XCHG LHLD ESTACK DAD D XCHG POP D JC PERR MOV M,A INX H MOV M,B INX H MOV M,C INX H MOV M,E INX H MOV M,D RET PERR: CALL ESET DB PUSHERR RET ; ESET SETS ERR UNLESS ONE IS ALREADY SET ESET: LDA ERR XTHL ORA A JZ ES2 INX H XTHL RET ES2: MOV A,M INX H XTHL STA ERR LHLD CURSOR SHLD ERRAT RET ; STORE 0'S FROM (DE) THRU (HL) INCLUSIVE ZERO: MVI B,0 ; STORE (B) FROM (DE) THRU (HL) INCLUSIVE BZAP: MOV A,L SUB E MOV A,H SBB D RC MOV M,B DCX H JMP BZAP ; PRINT STRING STARTING AT (HL), TERMINATED BY NULL BYTE PS: MOV A,M ORA A RZ CALL OUTCH INX H JMP PS END2 EQU $ ; @@@@ SCAN TOOLS @@@@ LITX: LHLD CURSOR ;RSS04 JMP LIT4 ;RSS04 LIT: CALL BLANKS ;RSS01 LIT4: LDAX D ORA A JZ MATCH CMP M INX D INX H JZ LIT4 XRA A ORA A RET MATCH: SHLD CURSOR CMA ORA A RET ; ADVANCES CURSOR OVER BLANKS. PUTS CURSOR IN HL BLANKS: LHLD CURSOR LOOP: MOV A,M ;RSS01 INX H ;RSS01 CPI ' ' ;RSS01 JZ LOOP ;RSS01 CPI ' ' ;RSS01 JZ LOOP ;RSS01 DCX H ;RSS01 SHLD CURSOR RET ; SKIPS OVER BALANCED L-R DELIMITERS, (ASSUMING THE FIRST ; 1 DELIMITER IS ALREADY MATCHED.) SKIP: MVI D,1 SK2: MOV A,M CMP B JZ SKL CMP C JNZ SKNEXT DCR D JNZ SKNEXT INX H SHLD CURSOR STC CMC RET SKL: INR D SKNEXT: INX H XCHG PUSH H LHLD PROGEND DAD D POP H XCHG JNC SK2 CALL ESET DB CURSERR STC RET ; TESTS FOR LEGAL IDENTIFIER CHARACTER ALEGAL: CPI '_' ;RSS04 RZ ;RSS04 CPI '0' RM CPI '9'+1 JM YESA ; TEST IF (A) IS ALPHA. PLUS ON YES ALPHA: CPI 'A' RM CPI 'Z'+1 JM YESA CPI 'a' RM CPI 'z'+1 JM YESA CMA ORA A RET YESA: XRA A RET ; MATCHES A VARIABLE OR FUNCTION NAME. SETS FNAME. SYMNAME:CALL BLANKS SHLD FNAME MOV A,M CALL ALPHA JM SY3 SY2: INX H MOV A,M CALL ALEGAL ;RSS04 JP SY2 SHLD CURSOR DCX H SHLD LNAME RET SY3: XRA A RET ; MATCHES 3 KINDS OF CONSTANTS, SETTING FNAME CONST: CALL BLANKS MOV A,M CPI '+' JZ CN2 CPI '-' JZ CN2 CPI '0' JM CN3 CPI '9'+1 JP CN3 CN2: SHLD FNAME CN4: INX H MOV A,M CPI '0' JM CN5 CPI '9'+1 JM CN4 CN5: SHLD CURSOR DCX H SHLD LNAME MVI A,1 RET CN3: CPI '"' JNZ CN6 INX H SHLD FNAME CN7: MOV A,M ORA A JZ CN8 SBI '"' JZ CN8 INX H XCHG LHLD PROGEND DAD D XCHG JNC CN7 JMP CNERR CN8: MOV M,A DCX H SHLD LNAME MVI A,2 ORA A INX H INX H SHLD CURSOR RET CN6: CPI 27H JNZ CN9 INX H SHLD FNAME CN12: MOV A,M CPI 27H JZ CN11 INX H XCHG LHLD PROGEND DAD D XCHG JNC CN12 JMP CNERR CN11: MVI A,3 ORA A INX H SHLD CURSOR RET CN9: XRA A RET CNERR: CALL ESET DB CURSERR RET ; SKIPS OVER REMARKS AND/OR END-OF-LINES IN ANY ORDER REM: LXI D,NEWLINE CALL LIT JZ RE2 RE3: MOV A,M CPI LF JNZ REM INX H SHLD CURSOR JMP REM RE2: LXI D,CMNT CALL LITX ;RSS04 RZ MVI B,1 MVI C,ASCRET CALL SKIP RC JMP RE3 ; HL POINT TO START OF DIGIT STRING ATON: XCHG LXI H,0 AN2: LDAX D SUI 48 JC AN3 CPI 10 JNC AN3 MOV B,H MOV C,L DAD H DAD H DAD B DAD H MOV C,A MVI B,0 DAD B INX D JMP AN2 AN3: XCHG RET ; HL POINTS TO BEGINNING OF ASCII INTEGER AISGN: DB 0 ATOI: XRA A STA AISGN AI6: MOV A,M CPI ' ' JNZ AI2 INX H JMP AI6 AI2: CPI '-' JNZ AI3 STA AISGN INX H AI3: CPI '+' JNZ AI4 INX H AI4: CALL ATON LDA AISGN ORA A RZ JMP DENEG ; @@@@ SYMBOL TOOLS @@@@ ; ALLOCATE REFERENCE IN FUNB FOR VARIABLE OF A FUNCTION NEWFUN: LHLD CURFUN LXI D,6 DAD D SHLD CURFUN XCHG LHLD EFUN DAD D XCHG JNC NF2 CALL ESET DB TMFUERR RET NF2: LDA NXTVAR MOV M,A SUI 6+VLEN MOV C,A LDA NXTVAR+1 INX H MOV M,A SBI 0 INX H MOV M,C INX H MOV M,A LDA PRUSED INX H MOV M,A LDA PRUSED+1 INX H MOV M,A RET ; DEALLOCATE VARIABLE OF LAST FUNCTION FUNDONE:LHLD CURFUN MOV A,M STA NXTVAR INX H MOV A,M STA NXTVAR+1 INX H INX H INX H MOV A,M STA PRUSED INX H MOV A,M STA PRUSED+1 LXI D,-11 DAD D SHLD CURFUN RET ; ALLOCATE A VARIABLE. CALL IN A, SIZE IN B, LEN IN DE ; PASSED VALUE IN HL CLASS: DB 0 ; TEMPS USED BY NEWVAR OBSIZE: DB 0 PASSED: DW 0 LEN: DW 0 FVAL: DW 0 KF: DW 0 NEWVAR: STA CLASS MOV A,B STA OBSIZE SHLD PASSED XCHG SHLD LEN LHLD NXTVAR CALL CANON INX H LDA CLASS MOV M,A INX H LDA OBSIZE MOV M,A INX H LDA LEN MOV M,A INX H LDA LEN+1 MOV M,A INX H SHLD FVAL LDA CLASS ORA A JZ NR2 LHLD PASSED MOV A,L ORA H JNZ NR3 NR2: LHLD PRUSED INX H SHLD KF XCHG LHLD FVAL MOV M,E INX H MOV M,D LHLD LEN XCHG LHLD PRUSED LDA OBSIZE DAD D DCR A JZ NR7 DAD D NR7: SHLD PRUSED XCHG LHLD EPR DAD D XCHG JNC NR4 CALL ESET DB TMVLERR RET NR4: LHLD KF XCHG LHLD PRUSED CALL ZERO JMP NR5 NR3: LHLD FVAL LDA PASSED MOV M,A INX H LDA PASSED+1 MOV M,A JMP NR6 NR5: LDA CLASS ORA A JNZ NR6 LHLD PASSED MOV A,H ORA L JZ NR6 XCHG LHLD KF MOV M,E INX H MOV M,D NR6: LHLD CURFUN INX H INX H LDA NXTVAR MOV M,A INX H LDA NXTVAR+1 MOV M,A LHLD NXTVAR LXI D,6+VLEN DAD D SHLD NXTVAR XCHG LHLD EVAR DAD D XCHG LHLD FVAL RNC CALL ESET DB TMVRERR RET ; ADRVAL LOOKS UP A SYMBOL POINTED TO BY FNAME,LNAME CSIZE: DB 0 ; CANONICAL STORAGE ;RSS04 CPTR: DW 0 ;RSS04 PVAR: DW 0 AREA: DB 0 SFUN: DW 0 LAST: DW 0 ADDRVAL:LHLD CURFUN SHLD SFUN LXI H,CSIZE ;RSS04 CALL CANON XRA A STA AREA AD8: LHLD SFUN MOV E,M INX H MOV D,M INX H MOV C,M INX H MOV B,M XCHG SHLD PVAR MOV H,B MOV L,C SHLD LAST LHLD PVAR LDA CSIZE ; B:=CSIZE ;RSS04 MOV B,A ;RSS04 AD2: LDA LAST SUB L LDA LAST+1 SBB H JC AD3 MOV A,B ;RSS04 CMP M ; SIZES MATCH? ;RSS04 JNZ AD5A ; NO ;RSS04 INX H ;RSS04 MOV E,M ; DE:=@HL ;RSS04 INX H ;RSS04 MOV D,M ;RSS04 MOV C,B ; C:=CSIZE ;RSS04 LHLD CPTR ; HL:=CPTR ;RSS04 AD4: LDAX D CMP M JNZ AD5 DCR C INX D INX H JNZ AD4 LHLD PVAR ; RESET HL ;RSS04 INX H ;RSS04 INX H ;RSS04 INX H ;RSS04 MOV A,M INX H MOV B,M INX H MOV E,M INX H MOV D,M INX H ORA A JZ AD9 CPI 'E' RNZ AD9: PUSH D MOV E,M INX H MOV D,M XCHG POP D RET AD5: LHLD PVAR AD5A: LXI D,VLEN+6 DAD D SHLD PVAR JMP AD2 AD3: LDA AREA ORA A JNZ AD6 LHLD CURGLBL AD7: SHLD SFUN INR A STA AREA JMP AD8 AD6: CPI 2 JP ADERR LHLD BFUN JMP AD7 ADERR: CALL ESET DB SYMERRA RET ; CANONICALIZES SYMBOL FROM FNAME TO LNAME INCLUSIVE CANON: XCHG ; SAVE DESTINATION ;RSS04 LHLD FNAME ;RSS04 XCHG ;RSS04 LDA LNAME ; A:=SIZE ;RSS04 SUB E ;RSS04 INR A ;RSS04 MOV M,A ; SAVE SIZE ;RSS04 INX H ;RSS04 MOV M,E ; SAVE ADDRESS ;RSS04 INX H ;RSS04 MOV M,D ;RSS04 RET ; ASGN IS THE EXPRESSION EVALUATOR. ASGN: CALL RELN LXI D,XEQ CALL LIT JZ A2 CALL ASGN LDA ERR ORA A CZ EQ A2: LDA ERR ORA A JZ A3 XRA A RET A3: DCR A RET ; A RELN IS AN EXPR OR A COMPARISON OF EXPRS. RELN: CALL EXPR LXI D,LE CALL LIT JZ R2 CALL EXPR CALL TOPDIF JZ PONE JC PONE JMP PZERO R2: LXI D,GE CALL LITX ;RSS04 JZ R3 CALL EXPR CALL TOPDIF JZ PONE JNC PONE JMP PZERO R3: LXI D,EQEQ CALL LITX ;RSS04 JZ R4 CALL EXPR CALL TOPDIF JZ PONE JMP PZERO R4: LXI D,NOTEQ CALL LITX ;RSS04 JZ R5 CALL EXPR CALL TOPDIF JNZ PONE JMP PZERO R5: LXI D,GT CALL LITX ;RSS04 JZ R6 CALL EXPR CALL TOPDIF JZ PZERO JC PZERO JMP PONE R6: LXI D,LT CALL LITX ;RSS04 RZ CALL EXPR CALL TOPDIF JC PONE JMP PZERO ; AN EXPR IS A TERM OR SUM (DIFF) OF TERMS. EXPR: LXI D,XMINUS CALL LIT JZ EX2 CALL TERM CALL TOPTOI MOV A,E CMA MOV E,A MOV A,D CMA MOV D,A INX D CALL PUSHK JMP EX3 EX2: LXI D,XPLUS CALL LITX ;RSS04 CALL TERM EX3: LDA ERR ORA A RNZ LXI D,XPLUS CALL LIT JZ EX4 CALL TERM CALL POPTWO CALL DADD CALL PUSHK JMP EX3 EX4: LXI D,XMINUS CALL LITX ;RSS04 RZ CALL TERM CALL POPTWO CALL DSUB CALL PUSHK JMP EX3 ; A TERM IS A FACTOR OR A PRODUCT OF FACTORS TERM: CALL FACTOR TE2: LDA ERR ORA A RNZ LXI D,XSTAR CALL LIT JZ TE3 CALL FACTOR CALL POPTWO CALL DMPY CALL PUSHK JMP TE2 TE3: CALL REM LXI D,XSLASH CALL LIT JZ TE4 CALL FACTOR CALL POPTWO CALL DDIV CALL PUSHK JMP TE2 TE4: LXI D,XPCNT CALL LITX ;RSS04 RZ CALL FACTOR CALL POPTWO CALL DREM CALL PUSHK JMP TE2 ; A FACTOR IS A ASGN, CONST., VAR. REF. OR FUN. REF. FACTOR: LXI D,LPAR CALL LIT JZ FA2 CALL ASGN LXI D,RPAR CALL LIT RNZ CALL ESET DB RPARERR RET FA2: CALL CONST JZ FA5 CPI 1 JNZ FA3 LHLD FNAME CALL ATOI JMP PUSHK FA3: CPI 2 JNZ FA4 MVI A,1 MVI B,'A' MVI C,1 LHLD FNAME XCHG JMP PUSHST FA4: XRA A MVI B,'A' MVI C,1 LHLD FNAME MOV E,M JMP PUSHST FA5: CALL SYMNAME JZ FA6 LHLD FNAME INX H LDA LNAME CMP L JNZ FA7 LDA LNAME+1 CMP H JNZ FA7 MOV A,M CPI 'C' JNZ FA7 DCX H MOV A,M CPI 'M' JNZ FA7 LXI H,0 JMP ENTER FA7: CALL ADDRVAL SHLD FWHERE STA CLASS MOV A,B STA OBSIZE XCHG SHLD LEN MOV A,D ORA E JZ FA8 LDA CLASS CPI 'E' JZ FA9 LXI D,LPAR CALL LIT JZ FA10 LDA CLASS DCR A STA CLASS JP FA11 CALL ESET DB CLASERR RET FA11: LHLD FWHERE MOV E,M INX H MOV D,M PUSH D LHLD LEN PUSH H LHLD CLASS PUSH H CALL ASGN POP H SHLD CLASS POP H SHLD LEN POP H SHLD FWHERE RZ LXI D,RPAR CALL LIT CALL TOPTOI XCHG SHLD SUBSCR XCHG LHLD LEN MOV A,L DCR A ORA H JZ FA12 LDA CLASS ORA A JNZ FA12 ORA D JM SUBERR MOV B,H MOV C,L CALL DSUB JC FA12 SUBERR: CALL ESET DB RANGERR FA12: LHLD SUBSCR XCHG LHLD FWHERE LDA OBSIZE FA13: DCR A JM FA14 DAD D JMP FA13 FA14: SHLD FWHERE FA10: LDA OBSIZE MOV C,A LDA CLASS MVI B,'L' LHLD FWHERE XCHG JMP PUSHST FA9: LHLD FWHERE JMP ENTER FA8: CALL ESET DB SYMERR RET FA6: CALL ESET DB SYNXERR RET FWHERE: DW 0 ; LOCALS USED BY ASGN SUBSCR: DW 0 ; SKIPST SKIPS OVER A (POSSIBLY COMPOUND) STATEMENT SKIPST: CALL REM LXI D,LB CALL LIT JZ SS2 MVI B,'[' MVI C,']' CALL SKIP JMP REM SS2: LXI D,XIF CALL LITX ;RSS04 JNZ SS6 LXI D,XWHI CALL LITX ;RSS04 SS7: JZ SS3 SS6: LXI D,LPAR CALL LIT MVI B,'(' MVI C,')' CALL SKIP CALL SKIPST LXI D,XELS CALL LIT CNZ SKIPST JMP REM SS3: LHLD CURSOR SS4: MOV A,M CPI ASCRET JZ SS8 CPI ']' JZ SS8 CPI ';' JZ SS5 INX H XCHG LHLD PROGEND DAD D XCHG JNC SS4 JMP REM SS5: INX H SS8: SHLD CURSOR JMP REM ; VALLOC PARSES ONE VARIABLE BEHIND INT OR CHAR AND MAKES ; ALLOCATION AND SYMBOL ENTRY. TYPE: DB 0 VPASSED:DW 0 VCLASS: DB 0 ALEN: DW 0 VALLOC: STA TYPE SHLD VPASSED CALL SYMNAME JZ V2 XRA A STA VCLASS LXI D,LPAR CALL LIT JZ V3 LHLD FNAME PUSH H LHLD LNAME PUSH H LDA VCLASS INR A PUSH PSW CALL ASGN POP PSW STA VCLASS POP H SHLD LNAME POP H SHLD FNAME LDA ERR ORA A RNZ LXI D,RPAR CALL LIT CALL TOPTOI INX D XCHG SHLD ALEN JMP V5 V3: LXI H,1 SHLD ALEN V5: LDA TYPE MVI B,1 CPI 'C' JZ V7 INR B V7: LDA VCLASS LHLD ALEN XCHG LHLD VPASSED JMP NEWVAR V2: CALL ESET DB SYMERR RET ; @@@@ TINY - C INTERPRETER @@@@ ; ST INTERPRETS A POSSIBLY COMPOUND STATEMENT ST: CALL QUIT LDA ERR ORA A RNZ CALL REM CALL STBEGIN ST2: LHLD CURSOR SHLD STCURS CALL DECL JNZ REM LXI D,LB CALL LIT JZ TIF CALL REM CMPND: LDA ERR MOV B,A LDA LEAVE ORA B MOV B,A LDA BRAKE ORA B RNZ LXI D,RB CALL LIT JNZ REM CALL ST JMP CMPND TIF: LXI D,XIF CALL LITX ;RSS04 JZ TWHI LXI D,LPAR CALL LIT CALL ASGN RZ LXI D,RPAR CALL LIT CALL TOPTOI MOV A,D ORA E JZ IF2 CALL ST LXI D,XELS CALL LIT CNZ SKIPST RET IF2: CALL SKIPST LXI D,XELS CALL LIT CNZ ST RET TWHI: LXI D,XWHI CALL LITX ;RSS04 JZ TSEM LXI D,LPAR CALL LIT CALL ASGN RZ LXI D,RPAR CALL LIT CALL TOPTOI MOV A,D ORA E JZ WH2 LHLD STCURS PUSH H LHLD CURSOR PUSH H CALL ST POP H SHLD OBJT POP H SHLD AGIN LDA BRAKE ORA A JZ WH3 LHLD OBJT SHLD CURSOR CALL SKIPST XRA A STA BRAKE RET WH3: LHLD AGIN SHLD CURSOR RET WH2: CALL SKIPST RET TSEM: LXI D,SEMI CALL LITX ;RSS04 JNZ REM TRET: LXI D,XRET CALL LITX ;RSS04 JZ TBRK LXI D,SEMI CALL LIT JNZ TR2 LXI D,XNL CALL LITX ;RSS04 JNZ TR2 CALL ASGN JMP TR4 TR2: CALL PZERO TR4: MVI A,1 STA LEAVE RET TBRK: LXI D,XBRK CALL LITX ;RSS04 JZ TASG MVI A,1 STA BRAKE RET TASG: CALL ASGN JZ STER CALL TOPTOI LXI D,SEMI CALL LIT JMP REM STER: CALL ESET DB STATERR RET OBJT: DW 0 AGIN: DW 0 ; DECL TEST FOR AND INTERPRETS DECLARATIONS DECL: LXI D,XCHAR CALL LIT JZ TINT CH2: MVI A,'C' LXI H,0 CALL VALLOC LXI D,COMMA CALL LIT JNZ CH2 CH3: LXI D,SEMI CALL LIT MVI A,07FH ORA A RET TINT: LXI D,XINT CALL LITX ;RSS04 RZ IN2: MVI A,'I' LXI H,0 CALL VALLOC LXI D,COMMA CALL LIT JNZ IN2 JMP CH3 ; QUIT CATCHES INTERRUPTS (ESC KEY) AT APPL LEVEL. QUIT: LDA APPLVL ORA A RZ CALL CHRDY RZ MOV B,A LDA ESCAPE CMP B RNZ CALL INCH CALL ESET DB KILL RET ; EVALUATE ARGUMENTS OF A FUNCTION. NARGS: DB 0 WHERE: DW 0 ARG: DW 0 ENTER: SHLD WHERE XRA A STA NARGS LHLD TOP LXI D,5 DAD D SHLD ARG LXI D,LPAR CALL LIT LXI D,RPAR CALL LIT JNZ ARGSDNE LHLD CURSOR MOV A,M CPI ']' JZ ARGSDNE CPI ';' JZ ARGSDNE CPI ASCRET JZ ARGSDNE CPI '/' JZ ARGSDNE EN2: LDA ERR ORA A RNZ LHLD ARG PUSH H LHLD WHERE PUSH H LHLD NARGS PUSH H CALL ASGN POP H MOV A,L POP H SHLD WHERE POP H SHLD ARG INR A STA NARGS LXI D,COMMA CALL LIT JNZ EN2 LXI D,RPAR CALL LITX ;RSS04 ARGSDNE:LDA ERR ORA A RNZ LHLD WHERE MOV A,H ORA L JNZ EN3 LDA NARGS CALL MC RET EN3: LHLD CURSOR PUSH H LHLD STCURS PUSH H LHLD WHERE SHLD CURSOR CALL NEWFUN EN4: CALL REM LXI D,XINT CALL LIT JZ EN5 EN6: LHLD ARG MVI B,'I' CALL SETARG LHLD ARG LXI D,5 DAD D SHLD ARG LXI D,COMMA CALL LIT JNZ EN6 LXI D,SEMI CALL LITX ;RSS04 JMP EN4 EN5: LXI D,XCHAR CALL LITX ;RSS04 JZ EN7 EN8: LHLD ARG MVI B,'C' CALL SETARG LHLD ARG LXI D,5 DAD D SHLD ARG LXI D,COMMA CALL LIT JNZ EN8 LXI D,SEMI CALL LITX JMP EN4 EN7: LHLD TOP LXI D,5 DAD D LDA ARG CMP L JZ EN9 POP D POP H SHLD CURSOR PUSH H PUSH D CALL ESET DB ARGSERR EN9: LXI H,NARGS DCR M JM EN11 CALL POPST JMP EN9 EN11: LDA ERR ORA A CZ ST LDA LEAVE ORA A CZ PZERO XRA A STA LEAVE POP H SHLD STCURS POP H SHLD CURSOR CALL FUNDONE LHLD TOP INX H MOV A,M CPI 'A' RZ CALL TOPTOI JMP PUSHK ; HL POINT INTO STACK TO AN ARG. B IS TYPE. SETARG: PUSH B MOV B,M INX H MOV A,M INX H MOV C,M INX H MOV E,M INX H MOV D,M CPI 'A' JZ SE2 XCHG MOV E,M INX H MOV D,M SE2: MOV A,C DCR A ORA B JNZ SE3 MOV A,E RLC SBB A MOV D,A SE3: POP B MOV A,B XCHG JMP VALLOC ; SCANS PROGRAM AND ALLOCATE ALL EXT. IN NEXT FCTN LAYER. LINK: CALL NEWFUN LI2: LDA ERR ORA A RNZ LHLD CURSOR INX H INX H XCHG LHLD PROGEND DAD D XCHG RC CALL REM LXI D,LB CALL LIT JZ LIDCL MVI B,'[' MVI C,']' CALL SKIP JMP LI2 LIDCL: CALL DECL JNZ LI2 LXI D,XENDL CALL LIT JZ LISYM CALL NEWFUN JMP LI2 LISYM: CALL SYMNAME JZ LIERR MVI A,'E' MVI B,2 MVI E,1 MVI D,0 LHLD CURSOR CALL NEWVAR LHLD CURSOR MVI A,'[' LI3: CMP M JZ LI4 INX H XCHG LHLD PROGEND DAD D XCHG JNC LI3 CALL ESET DB LBRCERR RET LI4: SHLD CURSOR CALL SKIPST JMP LI2 LIERR: CALL ESET DB LINKERR RET ; MOVE -(BC) BYTES FROM (HL) TO (DE) MOVE: MOV A,M STAX D INX D INX H INR C JNZ MOVE INR B JNZ MOVE RET ; @@@@ IT ALL STARTS HERE @@@@ FCSSP: DW 0 ; ORIGINAL SP ;RSS01 COLD: LDA FCSSP+1 ; OLD STACK SET? ;RSS01 ORA A ;RSS01 JNZ CL1 ;RSS01 LXI H,0 ;RSS01 DAD SP ;RSS01 SHLD FCSSP ;RSS01 CL1: LHLD MSTACK SPHL CL2: LXI B,-10 LHLD BPR XCHG LXI H,INST CALL MOVE LHLD BPR LXI D,9 DAD D CALL HLNEG SHLD PROGEND CL3: MVI A,0C3H ;RSS01 STA HOTVEC ;RSS01 LXI H,HOTSTRT ;RSS01 SHLD HOTVEC+1 ;RSS01 STA KBVEC ;RSS01 LXI H,KBINT ;RSS01 SHLD KBVEC+1 ;RSS01 MVI A,31 ;RSS01 STA KBDFL ;RSS01 LXI H,0 ;RSS01 SHLD KBRPTR ;RSS01 CALL LOGO WARM: CALL LOADER HOT: CALL LOGO LHLD PROGEND CALL HLNEG SHLD PRUSED LHLD BPR SHLD CURSOR LHLD BFUN LXI D,6 DAD D SHLD CURGLBL LXI D,-12 DAD D SHLD CURFUN LHLD BVAR SHLD NXTVAR LHLD BSTACK LXI D,-5 DAD D SHLD TOP XRA A MOV H,A MOV L,A STA ERR SHLD ERRAT STA LEAVE STA BRAKE CALL LINK CALL NEWFUN LHLD BPR SHLD CURSOR CALL PRBEGIN CALL ST ; THIS EXECUTES THE SYSTEM PROGRAM CALL PRDONE LDA ERR ;RSS01 ORA A ;RSS01 JNZ DONERR ;RSS01 CALL PX ;RSS01 DB LF,ERS,'DONE',CR,LF,0 ;RSS01 JMP WARM ;RSS01 ;RSS01 DONERR: CALL PX ;RSS01 DB LF,ERS,'ERROR ',0 ;RSS01 LHLD ERR ;RSS01 XCHG ;RSS01 CALL PN ;RSS01 CALL PX ;RSS01 DB ' ON LINE ',0 ;RSS01 LHLD BPR ;RSS01 XCHG ;RSS01 LHLD ERRAT ;RSS01 MVI A,ASCRET ;RSS01 PUSH H ;RSS01 PUSH D ;RSS01 CALL COUNTCH ;RSS01 PUSH B ;RSS01 MOV E,C ;RSS01 MOV D,B ;RSS01 INX D ;RSS01 CALL PN ;RSS01 CALL PX ;RSS01 DB LF,ERS,0 ;RSS01 POP B ;RSS01 POP D ;RSS01 POP H ;RSS01 MVI A,ASCRET ;RSS01 CALL SCANN ;RSS01 MOV B,A ;RSS01 DONE1: INX D ;RSS01 CALL CMPHD ;RSS01 JNZ DONE2 ;RSS01 CALL PX ;RSS01 DB '`',0 ;RSS01 DONE2: LDAX D ;RSS01 ORA A ;RSS01 JNZ DONE3 ;RSS01 MVI A,'"' ;RSS01 DONE3: CALL OUTCH ;RSS01 CMP B ;RSS01 JNZ DONE1 ;RSS01 JMP WARM INST: DB '[MAIN();]',0 LOADER: LXI H,BUFF CALL PX ;RSS01 DB LF,ERS,'TC>',0 ;RSS01 D2: CALL INCH MOV M,A CPI 26 ;RSS01 JZ D3 CPI 127 ;RSS04 JZ D3 ;RSS04 CALL OUTCH ;RSS01 CPI CR JZ DOIT INX H JMP D2 D3: LXI D,-BUFF-1 PUSH H DAD D POP H JNC D2 DCX H CALL PX ;RSS01 DB 26,' ',26,0 ;RSS01 JMP D2 DOIT: MVI M,0 LDA BUFF+1 MOV B,A LDA XR CMP B JZ LOAD LDA XX CMP B JZ TCEXIT LDA XG CMP B RZ CALL PX ;RSS01 DB '???',0 ;RSS01 JMP LOADER LOAD: LXI H,BUFF+3 LXI D,1 LXI B,LOADUNIT ;RSS01 MVI A,1 CALL FOPEN JNZ LOADER LXI H,0 ; START AT BLOCK 0 ;RSS02 SHLD BLOCKN ;RSS02 LHLD PROGEND ; XBC:=ALLOW LEN. ;RSS02 XCHG ;RSS02 LHLD EPR ;RSS02 CALL HLNEG ;RSS02 DAD D ;RSS02 SHLD XBC ;RSS02 XCHG ;RSS02 CALL HLNEG ; BUF:=BASE ADDRESS ;RSS02 SHLD BUF ;RSS02 LXI B,LOADUNIT ;RSS02 CALL BREAD ; READ FILE ;RSS02 DAD D ;RSS02 MVI M,0 ;RSS02 CALL HLNEG ;RSS02 SHLD PROGEND ;RSS02 JMP LOADER BUFF: DS 40 ; PRINT (DE) AS SIGNED INTEGER PN: LXI H,BUFF CALL ITOA MVI M,0 LXI H,BUFF JMP PS ; CONVERT (DE) TO ASCII SIGNED INTEGER ITOA: MOV A,D ORA A JP NTOA CALL DENEG MVI M,'-' INX H ; CONVERT (DE) TO ASCII UNSIGNED INTEGER NTOA: MOV A,D ORA E JNZ NT2 MVI M,'0' INX H RET NT2: XRA A PUSH PSW NT3: LXI B,10 PUSH H CALL DDIV MOV A,L POP H ADI '0' PUSH PSW MOV A,D ORA E JNZ NT3 NT4: POP PSW RZ MOV M,A INX H JMP NT4 ; PRINT THE COPYRIGHT MESSAGE ON THE TERMINAL. LOGO: CALL PX ;RSS01 CPMSG: DB LF,11,'RALFARITHMS TINY-C V2.2',CR,LF,0 RET ;RSS01 ; MOVE THE BLOCK (DE)...(HL) INCLUSIVE (BC) BYTES MOVEBL: MOV A,B ORA A JM MOVEDN ORA C RZ MOVEUP: SHLD FROMPTR DAD B XCHG LDA FROMPTR CMA ADD L MOV C,A LDA FROMPTR+1 CMA ADC H MOV B,A LHLD FROMPTR MU2: MOV A,M STAX D DCX H DCX D INR C JNZ MU2 INR B JNZ MU2 RET MOVEDN: XCHG SHLD FROMPTR DAD B LDA FROMPTR SUB E MOV C,A LDA FROMPTR+1 SBB D MOV B,A DCX B XCHG LHLD FROMPTR JMP MOVE FROMPTR:DW 0 ; SCAN FOR THE NTH OCCURANCE OF A CHARACTER IN A BLOCK SCANN: PUSH PSW XCHG SC2: MOV A,C ORA B JZ SC9 MOV A,E SUB L MOV A,D SBB H JC SC9 POP PSW PUSH PSW CMP M JNZ SC3 DCX B SC3: INX H JMP SC2 SC9: DCX H XCHG POP PSW RET ; COUNT THE OCCURANCES OF A CHARACTER IN A BLOCK. COUNTCH:LXI B,0 PUSH PSW CC2: MOV A,L SUB E MOV A,H SBB D JC CC9 POP PSW PUSH PSW CMP M DCX H JNZ CC2 INX B JMP CC2 CC9: POP PSW RET ; MACHINE CALL ROUTINE TO INTERFACE TO 8080 CODED ROUTINES MC: STA MCARGS CALL TOPTOI LXI H,-1000 DAD D JC USERMC MOV A,E CPI 1 JZ MC1 CPI 2 JZ MC2 CPI 3 JZ MC3 CPI 4 JZ MC4 CPI 5 JZ MC5 CPI 6 JZ MC6 CPI 7 JZ MC7 CPI 8 JZ MC8 CPI 9 JZ MC9 CPI 10 JZ MC10 CPI 11 JZ MC11 CPI 12 JZ MC12 CPI 13 JZ MC13 CPI 14 JZ MC14 MCESET: CALL ESET DB MCERR RET ; PUT A CHARACTER TO SCREEN MC1: CALL TOPTOI CALL PUSHK MOV A,E JMP OUTCH ; GET A CHARACTER FROM KEYBOARD MC2: CALL INCH MOV B,A LDA APPLVL ORA A JZ USEIT LDA ESCAPE CMP B JNZ USEIT CALL ESET DB KILL USEIT: LDA ECHO ORA A MOV A,B CNZ OUTCH MOV E,A XRA A MOV D,A JMP PUSHK ; FILE OPEN(R/W,NAME,FSIZE,UNIT) MC3: CALL TOPTOI PUSH D CALL TOPTOI PUSH D CALL TOPTOI PUSH D CALL TOPTOI MOV A,E ORA D POP H POP D POP B CALL FOPEN MC3A: LXI D,0 MOV E,A JMP PUSHK ; READ BLOCK(WHERE2,UNIT) MC4: CALL TOPTOI PUSH D CALL TOPTOI XCHG POP B CALL FREAD MC4A: JZ MC4P ;RSS02 LXI D,-1 MOV E,A MC4P: JMP PUSHK ; WRITE BLOCK(1ST BYTE,LAST BYTE,UNIT) MC5: CALL TOPTOI PUSH D CALL TOPTOI PUSH D CALL TOPTOI XCHG POP D POP B CALL FWRITE JMP MC3A ;RSS04 ; CLOSE FILE(UNIT) MC6: CALL TOPTOI MOV C,E MOV B,D CALL FCLOSE JMP PZERO ; MOVE A BLOCK UP OR DOWN(FIRST,LAST,K) MC7: CALL TOPTOI PUSH D CALL TOPTOI PUSH D CALL TOPTOI POP H POP B CALL MOVEBL JMP PZERO ; COUNT # INSTANCES OF CHARACTER IN BLOCK(FIRST,LAST,CH) MC8: CALL TOPTOI PUSH D CALL TOPTOI PUSH D CALL TOPTOI POP H POP B MOV A,C CALL COUNTCH MOV E,C MOV D,B JMP PUSHK ; SCAN FOR NTH OCCURANCE OF CH(FIRST,LAST,CH,CNT ADDRESS) MC9: CALL TOPTOI PUSH D CALL TOPTOI PUSH D CALL TOPTOI PUSH D CALL TOPTOI POP H POP B MOV A,C XTHL MOV C,M INX H MOV B,M DCX H XTHL PUSH D CALL SCANN POP H MOV A,E SUB L MOV E,A MOV A,D SBB H MOV D,A POP H MOV M,C INX H MOV M,B JMP PUSHK ; TRAP TO MONITOR 4.0 FOR DEBUGGING. MC10: DB 0FFH RET ; ENTERS AN APPLICATION PROGRAM. MC11: LHLD CURSOR PUSH H LHLD PROGEND PUSH H LHLD PRUSED PUSH H LHLD CURGLBL PUSH H CALL TOPTOI XCHG PUSH H SHLD CURSOR CALL TOPTOI XCHG SHLD PRUSED CALL HLNEG SHLD PROGEND CALL LINK LHLD CURFUN SHLD CURGLBL CALL TOPTOI XCHG SHLD CURSOR CALL NEWFUN CALL TOPTOI PUSH D LXI H,APPLVL INR M PUSH H LDA ERR ORA A JNZ DONE CALL PRBEGIN CALL ST CALL PRDONE DONE: POP H DCR M CALL FUNDONE CALL FUNDONE LHLD CURSOR LDA ERR ORA A JZ MCEN2 LHLD ERRAT MCEN2: XCHG POP H POP B MOV A,E SUB C MOV E,A MOV A,D SBB B MOV D,A LDA ERR MOV M,A XRA A INX H MOV M,A INX H MOV M,E INX H MOV M,D POP H SHLD CURGLBL POP H SHLD PRUSED POP H SHLD PROGEND POP H SHLD CURSOR XRA A STA ERR JMP PZERO ; TEST IF KEYBOARD CHAR READY MC12: CALL CHRDY MVI D,0 MOV E,A JMP PUSHK ; PRINT RAM, FROM AND TO ADDRESSES MC13: CALL TOPTOI PUSH D CALL TOPTOI XCHG POP D LOOP13: MOV A,E SUB L MOV A,D SBB H JC PZERO MOV A,M ORA A JNZ EC13 MVI A,'"' EC13: CALL OUTCH INX H JMP LOOP13 ; PRINT A SIGNED INTEGER MC14: CALL TOPTOI PUSH D CALL PN POP D JMP PUSHK ; @@@@ COMPUCOLOR I/O ROUTINES @@@@ HOTVEC EQU 81BFH ; ESC ^ HOT START VECTOR KBVEC EQU 81C5H ; KEYBOARD INPUT ROUT. VECTOR KBDFL EQU 81DFH ; KEYBOARD INPUT FLAG BYTE KBSIZE EQU 32 ; LOOKAHEAD SIZE (POWER OF 2) FILSIZE EQU 256 ; NORMAL FILE BUFFER SIZE OUTCH EQU 3392H ; OUTPUT ROUTINE EMESS EQU 262DH ; FCS ERROR ROUTINE PFSPC EQU 3077H ; PARSE FILE SPECIFIER OPEN EQU 2DABH ; OPEN FILE RWSEQI EQU 30C6H ; REWIND INPUT FILE INSEQO EQU 30E7H ; INITIALIZE OUTPUT FILE CLSEQO EQU 3136H ; CLOSE OUTPUT FILE ADHLA EQU 3518H ; ADD A TO HL SUBHD EQU 3459H ; HL:=HL-DE CMPHD EQU 344DH ; COMPARE HL WITH DE UNSIGNED CMPDH EQU 3453H ; COMPARE DE WITH HL UNSIGNED NEGH EQU 3524H ; NEGATE HL HLNEG EQU NEGH ;RSS01 GAREC EQU 3257H ; GET RECORD PTREC EQU 3285H ; PUT RECORD RBLKI EQU 31F9H ; READ BLOCK ;RSS02 WBLKI EQU 31F6H ; WRITE BLOCK ;RSS02 GTBYT EQU 322CH ; GET BYTE ;RSS02 FOPT EQU 0 FATR EQU 1 FNAM EQU 2 FTYP EQU 8 FVER EQU 11 FSBK EQU 12 FSIZ EQU 14 FLBC EQU 16 FLAD EQU 17 FSAT EQU 19 FSPR EQU 21 FDBK EQU 22 FDEN EQU 23 FAUX EQU 24 FHAN EQU 26 FFCN EQU 28 FDRV EQU 29 FBLK EQU 30 FBUF EQU 32 FXBC EQU 34 FPTR EQU 36 FPBE EQU 38 ; PRINT INLINE STRING PX: XTHL ; GET STRING POINTER PUSH PSW ; SAVE REGISTERS CALL PS ; PRINT OUT STRING INX H ; JUMP OVER THE 0 POP PSW ; RESTORE REGISTERS XTHL RET HOTSTRT:LHLD MSTACK ; HOT START ADDITION SPHL JMP CL3 TCEXIT: MVI B,0 ; SET FOR NO ERROR LHLD FCSSP ; LOAD ORIGINAL STACK SPHL RET ; RETURN TO FCS ; USER MC CALLS USERMC: MOV A,L ; A:=MC#-1000 CPI 1 JZ MC1001 CPI 2 JZ MC1002 CPI 3 JZ MC1003 CPI 4 JZ MC1004 CPI 5 JZ MC1005 CPI 6 JZ MC1006 JMP MCESET ; OUTPUT(PORT#,VALUE) MC1001: CALL POPTWO ; GET PORT# AND VALUE LXI H,MC1001A+1 MOV M,E ; STORE PORT# IN INSTRUCTION MOV A,C ; OUTPUT C TO PORT MC1001A:OUT 00 JMP PZERO ; INPUT(PORT#) MC1002: CALL TOPTOI ; GET PORT# LXI H,MC1002A+1 MOV M,E ; STORE PORT# IN INSTRUCTION MC1002A:IN 00 ; INPUT FROM PORT MVI D,0 ; DE:=VALUE MOV E,A JMP PUSHK ; GETBYTE(UNIT) MC1003: CALL TOPTOI ; BC:=UNIT# MOV B,D MOV C,E CALL GBYTE ; READ BYTE JMP MC4A ; BREAD(FIRST BYTE,LAST BYTE,BLOCK#,UNIT) MC1004: CALL POPOFF ; POP ARGUMENTS INTO BLOCKN CALL BREAD ; READ BLOCKS JMP MC4A ; BWRITE(FIRST BYTE,LAST BYTE,BLOCK#,UNIT) MC1005: CALL POPOFF ; POP ARGUMENTS INTO BLOCKN CALL BWRITE ; WRITE BLOCKS JMP MC4A ; FPBADR(UNIT) MC1006: CALL TOPTOI ; * GET FPB ADDRESS * MOV B,D MOV C,E CALL FADDR ; GET ADDRESS XCHG JMP PUSHK INCH: CALL CHRDY ; * INPUT CHARACTER * JZ INCH PUSH PSW LDA KBRPTR INR A ANI KBSIZE-1 STA KBRPTR POP PSW RET CHRDY: PUSH H ; * TEST FOR CHARACTER * LHLD KBRPTR MOV A,L SUB H JZ CHRDY1 MOV A,L LXI H,KBUFF CALL ADHLA MOV A,M ORA A JNZ CHRDY1 INR A CHRDY1: POP H RET KBINT: PUSH H ; * KEYBOARD INTERRUPT ROUTINE * PUSH PSW LHLD KBRPTR MOV A,H INR A ANI KBSIZE-1 CMP L JZ KBINT1 STA KBWPTR MOV A,H LXI H,KBUFF CALL ADHLA MOV M,E KBINT1: POP PSW POP H RET FOPEN: CALL SETFPB ; * OPEN A FILE * DCR A MOV M,A STA IOFLAG XCHG ; DE:=#FPB POP H ; HL:=#FILE SPECIFIER LXI B,DEFAULT CALL PFSPC ; PARSE FILE SPEC. JC FERR ; ERROR? LHLD FPBCUR ; HL:=#FPB CALL OPEN ; OPEN FILE JC FERR ; ERROR? PUSH H ; SAVE FPB LXI D,FBUF DAD D XCHG LHLD FPBPTR ; MOVE BUFFER INFO INTO FPB LXI B,-4 CALL MOVE POP H ; RESTORE FPB LDA IOFLAG ; CHECK READ OR WRITE ORA A ; READ? JZ FOPEN1 ; YES CALL INSEQO ; NO, INITIALIZE FOR WRITE JMP FCHECK FOPEN1: CALL RWSEQI ; INITIALIZE FOR READ JMP FCHECK FREAD: CALL SETFPB ; * READ A RECORD * POP B ; BC:=#BUFFER PUSH B LXI D,256 ; DE:=LENGTH OF BUFFER CALL GAREC ; READ RECORD POP H FREAD1: JNC FOK ; NO ERRORS? JNZ FERR ; NON-EOF ERROR? SBB A ; A:=-1 RET FWRITE: CALL SETFPB ; * WRITE A RECORD * POP B ; BC:=#BUFFER CALL DSUB ; DE:=LENGTH INX D CALL PTREC ; PUT RECORD FCHECK: JC FERR ; ERROR? FOK: XRA A ; A:=0, CARRY:=0 RET FERR: CALL PX DB CR,LF,0 CALL EMESS ; CALL FCS ERROR MESSAGE CALL PX DB 'ON UNIT ',0 FERR1: LHLD IOUNIT XCHG CALL PN CALL PX DB CR,LF,0 XRA A INR A RET FCLOSE: CALL SETFPB ; * CLOSE FILE * MOV A,M ORA A CNZ CLSEQO ; CLOSE IF WRITING POP H JMP FCHECK GBYTE: CALL SETFPB ; * GET SINGLE BYTE * CALL GTBYT MOV E,A ; STORE BYTE POP H JMP FREAD1 BREAD: CALL SETFPB ; * READ BLOCKS * CALL SETBLK ; SETUP FPB CALL RBLKI BREAD1: POP H ; RESTORE HL JC FERR ; ERROR? PUSH H ; NO, DE:=ACTUAL TRANSFER SIZE LHLD FPBCUR LXI D,FAUX DAD D MOV E,M INX H MOV D,M POP H JMP FOK BWRITE: CALL SETFPB ; * WRITE BLOCKS * CALL SETBLK ; SET FPB CALL WBLKI JMP BREAD1 FADDR: CALL SETFPB ; * GET FPB ADDR. * RET SETFPB: XTHL PUSH H ; SNEAK HL ONTO STACK PUSH PSW MOV A,C STA IOUNIT ; SAVE I/O UNIT # DCR A JM SETERR ; TOO LOW? CPI NUNITS ; TOO HIGH JP SETERR ; YES ADD A ; CONVERT TO 3 WORD RECORD OFFSET MOV B,A ADD B ADD B LXI H,FPBTBL CALL ADHLA ; HL:=# OF # OF FPB PUSH D MOV E,M INX H MOV D,M INX H SHLD FPBPTR ; STORE POINTER TO BUFFER INFO XCHG ; HL:=#FPB SHLD FPBCUR POP D POP PSW RET ; NORMAL RETURN SETERR: CALL PX DB CR,LF,'ILLEGAL UNIT ',0 POP PSW POP H ; POP RETURN POP H ; POP THE HIDDEN HL JMP FERR1 SETBLK: PUSH H ; * SETUP FPB * LXI D,FBLK DAD D LXI D,BLOCKN XCHG LXI B,-6 CALL MOVE POP H RET POPOFF: CALL TOPTOI ; * SAVE PARAMS IN BLOCKN * PUSH D ; UNIT CALL TOPTOI ; BLOCK # XCHG SHLD BLOCKN CALL TOPTOI ; LAST BYTE PUSH D CALL TOPTOI ; FIRST BYTE POP H CALL SUBHD INX H SHLD XBC ; LENGTH XCHG SHLD BUF ; BASE ADDR. POP B ; UNIT RET ; DATA STRUCTURES DEFAULT:DB 'SRC' FPBCUR: DW 0 ; CURRENT FPB ADDRESS FPBPTR: DW 0 ; POINTER TO BUFFER INFO. IOFLAG: DW 0 ; READ/WRITE FLAG IOUNIT: DW 0 ; I/O UNIT # BLOCKN: DW 0 ; BLOCK # BUF: DW 0 ; BLOCK BUFFER XBC: DW 0 ; BLOCK SIZE FPBTBL: DW FPB1,FPBF1,FPBF2-FPBF1 DW FPB2,FPBF2,FPBF3-FPBF2 DW FPB3,FPBF3,FPBF4-FPBF3 DW FPB4,FPBF4,FPBF5-FPBF4 DW FPB1,FPBF1,FPBF5-FPBF1 NUNITS EQU ($-FPBTBL)/6 LOADUNIT EQU NUNITS FPB1: DS FPBE FPB2: DS FPBE FPB3: DS FPBE FPB4: DS FPBE FPBF1: DS FILSIZE FPBF2: DS FILSIZE FPBF3: DS FILSIZE FPBF4: DS FILSIZE FPBF5 EQU $ KBRPTR: DB 0 ; KEYBOARD READ POINTER KBWPTR: DB 0 ; KEYBOARD WRITE POINTER KBUFF: DS KBSIZE ; KEYBOARD LOOK AHEAD BUFFER TCEND EQU $ BFREE EQU TCEND SPACE EQU EFREE-BFREE END START