home *** CD-ROM | disk | FTP | other *** search
Text File | 1985-03-11 | 23.3 KB | 1,328 lines |
- ORG 0
- NAM SMALL-C INTERPRETER
- OPT NOP,NOG
- *
- * LAST UPDATE 9-SEP-82
- *
- JMP BEGIN START THE INTERPRETER
-
- * AN INDIRECT CALL TABLE
- NOP PUT ON A BOUNDARY OF 4
- FCB 86
- JMP fclose+1
- FCB 86
- JMP fopen+1
- FCB 86
- JMP getc+1
- FCB 86
- JMP getchar+1
- FCB 86
- JMP gets+1
- FCB 86
- JMP putc+1
- FCB 86
- JMP putchar+1
- FCB 86
- JMP puts+1
- NOP
- JMP RTSC
- FCB 86
- JMP isalpha+1
- FCB 86
- JMP isdigit+1
- FCB 86
- JMP isalnum+1
- FCB 86
- JMP islower+1
- FCB 86
- JMP isupper+1
- FCB 86
- JMP isspace+1
- FCB 86
- JMP toupper+1
- FCB 86
- JMP tolower+1
- FCB 86
- JMP strclr+1
- FCB 86
- JMP strlen+1
- FCB 86
- JMP strcpy+1
- FCB 86
- JMP strcat+1
- FCB 86
- JMP strcmp+1
- RMB 4*4 ROOM FOR 4 MORE
-
- LIB FLEXPTRS
-
- NFILES EQU 4 MAX NO OF DISK FILES OPEN AT ONCE
- PC RMB 2 PSEUDO PROGRAM COUNTER
- R1A RMB 1 WORKING 16 BIT
- R1B RMB 1 --REGISTER
- DFLAG FCB NFILES-1 DIVIDE ROUTINE FLAG
- STEMP RMB 2 TEMP STORAGE FOR STACK POINTER
- X1TMP RMB 2 TEMP STORAGE FOR X REG
- X2TMP RMB 2 ... DITTO ...
- FCBPTR RMB 2 POINTER INTO FCB TABLE
- FCBTBL FDB FCB TABLE OF FCB POINTERS
- RMB NFILES*2 ROOM FOR THE REST
-
-
-
- ***************************************************
-
- BEGIN LDX #FCBTBL+2 POINT TO FCB ADDRESSES
- LDA A #NFILES-1
- STA A DFLAG INIT COUNTER
- LDA A $AC2B GET TOP OF MEMORY
- LDA B $AC2C
-
- BLOOP SUB B #$40 SUBTR 320 (SIZE OF FCB)
- SBC A #1
- STA A 0,X SAVE FCB ADDRESS
- INX
- STA B 0,X
- INX
- DEC DFLAG DONE ???
- BNE BLOOP
-
- CLR 0,X MARK END OF TABLE
- CLR 1,X
- STA A STEMP TOP OF STACK AREA
- STA B STEMP+1
- LDX STEMP
- TXS SET STACK POINTER
-
- LDX #FCBTBL POINT TO TABLE OF FCB ADDRESSES
- Init STX FCBPTR
- LDX 0,X GET FCB ADDRESS
- BEQ Initend QUIT IF END OF TABLE
- CLR 2,X MARK AS NOT IN USE
- LDX FCBPTR
- INX
- INX
- BRA Init
-
- Initend LDX #$800
- BRA NEXT2 START THE INTERPRETATION
-
- **************************************************************
- *
- * THE HEART OF THE INTERPRETER--- NEXT INSTRUCTION FETCHER.
- *
- BUMP2 LDX PC GET PROG COUNTER
- BUMP2A INX INCR BY 2
- INX
- BRA NEXT1 FETCH NEXT INSTRUCTION
-
- NEXT LDX PC
- NEXT1 STA A R1A SAVE THE WORK
- STA B R1B --REGISTER
- NEXT2 LDA B 0,X GET THE PSEUDO-INSTRUCTION
- INX (B CONTAINS A TABLE OFFSET)
- STX PC SAVE NEW PC
- STA B JJJ+2 SAVE AS PAGE OFFSET
- LDA B R1B RESTORE
- JJJ LDX JTABLE POINT TO ROUTINE (SELF MODIFYING CODE)
- JMP 0,X GO EXECUTE THE PSEUDO-INSTR.
-
- **************************************************************
- * THE JUMP TABLE *
- **************************************************************
-
- ORG *+255/256*256 MUST START ON A PAGE BOUNDARY
-
- JTABLE FDB LD1IM #0
- FDB LD1SOFF #1
- FDB LD1 #2
- FDB LDB1 #3
- FDB LD1R #4
- FDB LDB1R #5
- FDB ST1 #6
- FDB STB1 #7
- FDB ST1SP #8
- FDB STB1SP #9
- FDB PUSHR1 #10
- FDB EXG1 #11
- FDB JMPL #12
- FDB BRZL #13
- FDB JSRL #14
- FDB JSRSP #15
- FDB RTSC #16
- FDB MODSP #17
- FDB DBL1 #18
- FDB ADDS #19
- FDB SUBFST #20
- FDB MUL1 #21
- FDB DIV1 #22
- FDB MOD #23
- FDB ORS #24
- FDB XORS #25
- FDB ANDS #26
- FDB ASRS #27
- FDB ASLS #28
- FDB NEGR #29
- FDB NOTR #30
- FDB INCR #31
- FDB DECR #32
- FDB ZEQ #33
- FDB ZNE #34
- FDB ZLT #35
- FDB ZLE #36
- FDB ZGT #37
- FDB ZGE #38
- FDB ULT #39
- FDB ULE #40
- FDB UGT #41
- FDB UGE #42
- FDB ASMC #43
-
- *************************************************************
- *-------------------------
- * #0 LOAD REG WITH IMMED. VALUE
- LD1IM LDX PC
- LDA A 0,X HIGH BYTE
- LDA B 1,X LOW BYTE
- JMP BUMP2A
-
- *-------------------------
- * #1 LOAD STACK ADDRESS + OFFSET INTO REG
- LD1SOFF STS R1A SAVE STACK VALUE
- LDX PC
- LDA A 0,X GET OFFSET
- LDA B 1,X -- VALUE
- SEC
- ADC B R1B ADD OFFSET + 1
- ADC A R1A
- JMP BUMP2A
-
- *-------------------------
- * #2 LOAD WORD @ ADDRESS
- LD1 LDX PC
- LDX 0,X GET ADDRESS
- LD1A LDA A 0,X GET WORD
- LDA B 1,X
- JMP BUMP2
-
- *-------------------------
- * #3 LOAD BYTE @ ADDRESS
- LDB1 LDX PC
- LDX 0,X GET ADDRESS
- CLR A
- LDA B 0,X GET BYTE
- BPL LDB1A
- COM A SIGN EXTEND
- LDB1A JMP BUMP2
-
- *-------------------------
- * #4 LOAD WORD INDIRECT (ADDR IN REG)
- LD1R LDX R1A GET ADDRESS
- LDA A 0,X GET WORD
- LDA B 1,X
- JMP NEXT
-
- *-------------------------
- * #5 LOAD BYTE INDIRECT (ADDR IN REG)
- LDB1R LDX R1A
- CLR A
- LDA B 0,X GET BYTE
- BPL LDB1RA
- COM A
- LDB1RA JMP NEXT
-
- *-------------------------
- * #6 STORE WORD @ ADDRESS
- ST1 LDX PC
- LDX 0,X GET ADDRESS
- STA A 0,X STORE WORD
- STA B 1,X
- JMP BUMP2
-
- *-------------------------
- * #7 STORE BYTE @ ADDRESS
- STB1 LDX PC
- LDX 0,X GET ADDR
- STA B 0,X STORE BYTE
- JMP BUMP2
-
- *-------------------------
- * #8 STORE WORD @ ADDRESS ON STACK
- ST1SP TSX STACK TO INDEX
- LDX 0,X GET ADDRESS
- STA A 0,X STORE WORD
- STA B 1,X
- INS
- INS POP STACK
- JMP NEXT
-
- *-------------------------
- * #9 STORE BYTE @ ADDRESS ON STACK
- STB1SP TSX
- LDX 0,X
- STA B 0,X STORE BYTE
- INS POP ...
- INS
- JMP NEXT
-
- *-------------------------
- * #10 PUSH WORD ON STACK
- PUSHR1 PSH B
- PSH A
- LDX PC
- JMP NEXT2
-
- *-------------------------
- * #11 SWAP REG AND TOP OF STACK
- EXG1 TSX
- LDX 0,X GET VALUE ON STACK
- STX R1A SAVE
- INS
- INS
- PSH B
- PSH A REG ON STACK
- LDA A R1A NEW REG
- LDA B R1B
- LDX PC
- JMP NEXT2
-
- *-------------------------
- * #12 JUMP TO LABEL
- JMPL LDX PC
- JMP1 LDX 0,X GET ADDRESS (NEW PC)
- JMP NEXT2
-
- *-------------------------
- * #13 JUMP TO LABEL IF FALSE
- BRZL ORA A R1B SET FLAGS
- BEQ JMPL IF REG=0 -- JUMP
- JMP BUMP2 ELSE, PROCEED
-
- *-------------------------
- * #14 CALL TO LABEL
- JSRL LDX PC
- INX ADJUST RETURN
- INX -- ADDRESS
- DES
- STS *+5 *** SELF MODIFYING CODE ***
- DES
- STX $FFFF PUSH RETURN ADDRESS
- BRA JMPL
-
- *-------------------------
- * #15 CALL TO TOP OF STACK
- JSRSP TSX POINT TO STACK
- LDX 0,X GET ADDRESS (NEW PC)
- INS POP
- INS
- LDA B PC+1 GET RETURN ADDRESS
- PSH B
- LDA B PC
- PSH B SAVE RETURN ADDRESS
- JMP NEXT2
-
- *-------------------------
- * #16 RETURN TO CALLER
- RTSC TSX
- LDX 0,X GET ADDRESS
- INS POP
- INS
- JMP NEXT1
-
- *-------------------------
- * #17 MODIFY THE STACK POINTER
- MODSP LDX PC
- LDA A 0,X GET VALUE
- LDA B 1,X
- STS STEMP
- ADD B STEMP+1 ADD STACK POINTER
- ADC A STEMP
- STA A STEMP
- STA B STEMP+1
- LDS STEMP NEW STACK POINTER
- LDA A R1A RESTORE REGISTER
- LDA B R1B
- JMP BUMP2A
-
- *---------------------------
- * #18 DOUBLE THE PRIMARY REGISTER
- DBL1 ASL B
- ROL A
- JMP NEXT
-
- *---------------------------
- * #19 ADD REG AND TOP OF STACK (THEN POP)
- ADDS TSX
- ADD B 1,X DO THE ADD
- ADC A 0,X
- JMP POPS POP & RETURN
-
- *---------------------------
- * #20 SUBTRACT REG FROM TOP OF STACK
- SUBFST PUL A GET VALUE OFF STACK
- PUL B
- SUB B R1B SUBTRACT REGISTER
- SBC A R1A
- JMP NEXT
-
- *---------------------------
- * #21 MULTIPLY TOP OF STACK BY REG (RESULT IN REG)
- MUL1 PSH B
- PSH A REG ON STACK
- LDA A #16
- PSH A SET COUNTER
- CLR A
- CLR B
- TSX POINT TO DATA
-
- M2 ROR 3,X SHIFT MULTIPLIER
- ROR 4,X
- DEC 0,X DONE ?
- BMI M4
- BCC M3
- ADD B 2,X
- ADC A 1,X
-
- M3 ROR A
- ROR B SHIFT RESULT
- BRA M2 AND LOOP
-
- M4 INS CLEAN STACK
- INS
- INS
- PUL A GET RESULT
- PUL B
- JMP NEXT
-
- *-----------------------------
- * #22 DIVIDE THE TOP OF STACK BY REG --- RESULT IN REG.
- DIV1 BSR BDIV DO THE BASIC DIVIDE
- LDA A DFLAG GET SIGN FLAG
- AND A #1 MASK OFF BIT ZERO
- PUL A GET RESULT
- PUL B
- BEQ DIV1R
-
- DIV1N BSR NEGATE NEGATE THE VALUE IN A,B
-
- DIV1R JMP NEXT
-
- *-----------------------------
- * #23 DIVIDE TOP OF STACK BY REG --- REMAINDER IN REG
- MOD BSR BDIV
- INS CLEAN STACK
- INS
- PSH A TEMP SAVE
- LDA A DFLAG GET SIGN FLAG
- BPL MOD1
- COM A
-
- MOD1 AND A #1 MASK OFF BIT 0
- PUL A
- BNE DIV1N IF BIT 0 SET, NEGATE
-
- JMP NEXT
-
- *****************************************************
- * BASIC 16 BIT DIVIDE ROUTINE
- * ENTER WITH: DIVIDEND ON STACK
- * DIVISOR IN A,B
- * EXIT WITH: QUOTIENT ON STACK
- * REMAINDER IN A,B
- * SIGN FLAG IN DFLAG
- *
- BDIV CLR DFLAG
- TST A CHECK DIVISOR SIGN
- BPL BDIV1
-
- INC DFLAG ADJUST SIGN FLAG
- BSR NEGATE TAKE ABSOLUTE VALUE
-
- BDIV1 PSH B FORCE ON STACK
- PSH A
- LDA A #17 BIT COUNTER
- PSH A
- TSX POINT TO DATA
- LDA A 5,X CHECK SIGN
- BPL BDIV2 -- OF DIVIDEND
-
- COM DFLAG ADJUST FLAG
- LDA B 6,X
- BSR NEGATE
- STA A 5,X
- STA B 6,X
-
- BDIV2 CLR A
- CLR B
-
- * MAIN DIVIDE LOOP (UNSIGNED)
-
- UDIV1 CMP A 1,X
- BHI UDIV3
- BCS UDIV2
- CMP B 2,X
- BCC UDIV3
-
- UDIV2 CLC
- BRA UDIV4
-
- UDIV3 SUB B 2,X
- SBC A 1,X
- SEC
-
- UDIV4 ROL 6,X
- ROL 5,X
- DEC 0,X
- BEQ UDIV5
-
- ROL B
- ROL A
- BCC UDIV1
- BRA UDIV3
-
- UDIV5 INS
- INS
- INS
- RTS
-
- *----------------------------------------
- * NEGATE THE VALUE IN A,B
- NEGATE COM A
- COM B
- ADD B #1
- ADC A #0
- RTS
-
- *----------------------------------
- * #24 INCLUSIVE OR THE TOP OF STACK AND REG.
- ORS TSX
- ORA A 0,X
- ORA B 1,X
- POPS INS POP THE STACK
- INS
- JMP NEXT
-
- *----------------------------------
- * #25 EXCLUSIVE OR ......
- XORS TSX
- EOR A 0,X
- EOR B 1,X
- BRA POPS
-
- *----------------------------------
- * #26 AND .........
- ANDS TSX
- AND A 0,X
- AND B 1,X
- BRA POPS
-
- *----------------------------------
- * #27 ARITH. SHIFT RIGHT THE TOP OF STACK
- ASRS TSX
- AND B #$1F MAX REASONABLE SHIFT
- BEQ ASRS2
-
- ASRS1 ASR 0,X
- ROR 1,X
- DEC B
- BNE ASRS1
-
- ASRS2 PUL A GET THE RESULT
- PUL B
- JMP NEXT
-
- *--------------------------------
- * #28 ARITH. SHIFT LEFT THE TOP OF STACK
- ASLS TSX
- AND B #$1F
- BEQ ASRS2
-
- ASLS1 ASL 1,X
- ROL 0,X
- DEC B
- BNE ASLS1
-
- BRA ASRS2
-
- *--------------------------------
- * #29 NEGATE THE REGISTER
- NEGR BSR NEGATE
- JMP NEXT
-
- *--------------------------------
- * #30 COMPLEMENT THE REGISTER
- NOTR COM A
- COM B
- JMP NEXT
-
- *--------------------------------
- * #31 ADD 1 TO REG
- INCR ADD B #1
- ADC A #0
- JMP NEXT
-
- *--------------------------------
- * #32 SUBTRACT 1 FROM REG
- DECR SUB B #1
- SBC A #0
- JMP NEXT
-
- *****************************************************
- *
- * BASIC COMPARE INSTRUCTION SUBROUTINE
- * Compare the top of Stack to Register and set Condition codes
- *
- * Signed compare -- Carry reflects the sign of difference
- * (set means: top of stack < A,B )
- *
- SCMP TSX
- LDA A 2,X GET TOP OF STACK
- LDA B 3,X
- SUB B R1B SET CONDITION
- SBC A R1A ... FLAGS
- BPL STCMP1 SKIP IF PLUS
-
- STA B R1B TEMP SAVE
- ORA A R1B SET/RESET ZERO FLAG
- SEC AND SET CARRY
- RTS
-
- STCMP1 STA B R1B
- ORA A R1B
- CLC CLEAR THE CARRY
- RTS
- *
- * Unsigned compare, Carry set if top of stack < A,B
- *
- BCMP TSX
- LDA A 2,X GET TOP OF STACK
- LDA B 3,X
- CMP A R1A CHECK TOP BYTE
- BNE BCMP1
- CMP B R1B
- BCMP1 RTS
-
-
- *-------------------------------
- * #33 TEST FOR EQUALITY
- ZEQ BSR BCMP
- BEQ TRUE
- BRA FALSE
-
- *-------------------------------
- * #34 TEST FOR NOT-EQUAL
- ZNE BSR BCMP
- BNE TRUE
- BRA FALSE
-
- *-------------------------------
- * #35 TEST FOR LESS THAN
- ZLT BSR SCMP
- BCS TRUE
- BRA FALSE
-
- *-------------------------------
- * #36 TEST FOR LESS THAN OR EQUAL
- ZLE BSR SCMP
- BLS TRUE
- BRA FALSE
-
- *-------------------------------
- * #37 TEST FOR GREATER THAN
- ZGT BSR SCMP
- BHI TRUE
- BRA FALSE
-
- *-------------------------------
- * #38 TEST FOR GREATER THAN OR EQUAL
- ZGE BSR SCMP
- BCC TRUE
- BRA FALSE
-
- *-------------------------------
- * #39 TEST FOR LESS THAN (UNSIGNED)
- ULT BSR BCMP
- BCS TRUE
- BRA FALSE
-
- *-------------------------------
- * #40 TEST FOR LESS THAN OR EQUAL (UNSIGNED)
- ULE BSR BCMP
- BLS TRUE
- BRA FALSE
-
- *-------------------------------
- * #41 TEST FOR GREATER THAN (UNSIGNED)
- UGT BSR BCMP
- BHI TRUE
- BRA FALSE
-
- *------------------------------
- * #42 TEST FOR GREATER THAN OR EQUAL (UNSIGNED)
- UGE BSR BCMP
- BCC TRUE
-
- FALSE CLR B RETURN FALSE
- BRA TRUE1
-
- TRUE LDA B #1 RETURN TRUE
-
- TRUE1 CLR A
- JMP POPS POP STACK AND PROCEED
-
- *-------------------------------------
- * #43 SWITCH TO EXECUTABLE (ASSEMBLY) CODE
- ASMC LDX PC POINT TO CODE
- JMP 0,X GO EXECUTE IT
-
- ***********************************************************
- *
- * RUN-TIME SUBROUTINE LIBRARY
- *
- ***********************************************************
-
- * fopen(file-name, "type")
- * Open a File..........
- fopen FCB 86 SWITCH TO INLINE CODE
- LDX #FCBTBL-2 POINT TO FCB ADDRESSES TABLE
-
- NXTFIL INX
- INX
- STX FCBPTR SAVE POINTER
- LDX 0,X GET FCB ADDRESS
- BEQ NOFILE
- TST 2,X BUSY ?
- BEQ GODOIT NO,
- LDX FCBPTR ELSE, NEXT IN LINE
- BRA NXTFIL
-
- NOFILE LDX #FMSG POINT TO MESSAGE
- JSR PSTRNG PRINT IT
- JMP WARMS --AND BACK TO FLEX
-
- GODOIT STX R1A SAVE FCB ADDRESS
- TSX
- LDX 4,X POINT TO FILE NAME
- STX $AC14 SAVE IN LINE BUFFER POINTER
- LDX R1A GET FCB POINTER
- JSR GETFIL GET FILE SPEC
- BCS FERROR REPORT IF ERROR
- TSX
- LDX 2,X POINT TO MODE
- LDA A #1
- LDA B #'w' OPEN FOR WRITE
- CMP B 0,X -- ????
- BEQ OWRITE YES,
-
- * DEFAULT TO OPEN FOR READ
-
- LDX R1A POINT TO FCB
- STA A 0,X STORE IN FCB
- JSR FMS DO THE OPEN
- BEQ FEXIT
-
- FERROR JSR RPTERR REPORT THE TYPE OF ERROR
- JSR FMSCLS CLOSE ALL OPEN FILES
- JMP WARMS RETURN TO FLEX
-
- * OK, OPEN FOR WRITE
-
- OWRITE LDA A #2 CODE FOR WRITE
- LDX R1A GET FCB ADDRESS
- STA A 0,X
- JSR FMS TRY AN OPEN
- BEQ FEXIT IF SUCCESSFULL--DONE
-
- LDA A 1,X GET ERROR STATUS
- CMP A #3 ALREADY EXISTS ?
- BNE FERROR NO--SOME OTHER ERROR
-
- LDA A #12 DELETE THE EXISTING FILE
- STA A 0,X
- JSR FMS
- BNE FERROR
- LDA A 36,X FIX NAME
- STA A 4,X
- BRA OWRITE
-
- FEXIT TSX
- LDX 2,X POINT TO MODE AGAIN
- LDA B 1,X GET OPTIONAL CHAR
- CMP B #'u UNCOMPRESSED (BINARY) ???
- BNE FEXIT1 NO, SO SKIP
-
- LDA B #$FF
- LDX R1A
- STA B 59,X SET FLAG IN FCB
-
- FEXIT1 LDA A R1A RETURN THE FCB POINTER
- LDA B R1B
-
- JMP RTSC RETURN TO INTERPRETER
-
- *-------------------------------------------------
-
- * fclose(unit)
- * CLOSE A FILE
- fclose FCB 86 SWITCH TO IN-LINE
- TSX
- LDX 2,X POINT TO FCB
- LDA A #4 CLOSE CODE
- STA A 0,X
- JSR FMS DO THE CLOSE
- BNE FERROR
- CLR A
- LDA B #1 OK CODE
- JMP RTSC RETURN TO INTERPRETER....
-
- *--------------------------------------------------
-
- * getc(unit) read a byte from file
- * return a char, else a -1 if EOF
-
- getc FCB 86
- TSX
- LDX 2,X POINT TO FCB
- JSR FMS GET BYTE
- BEQ CHOK
-
- LDA A 1,X GET ERROR
- CMP A #8 EOF ?
- BNE FERROR
-
- LDA A #$FF LOAD EOF INDICATOR
-
- CHOK TAB COPY CHAR IN A
- CHOK1 CLR A
- TST B
- BPL GETC1
-
- COM A SIGN EXTEND
-
- GETC1 JMP RTSC
-
- *----------------------------------------------
-
- * putc(c,unit) write to file
-
- putc FCB 86
- TSX
- LDA A 5,X GET CHAR
- LDX 2,X GET FCB ADDR
- PSH A SAVE CHAR
- JSR FMS
- BNE FERROR
- PUL B GET CHAR
- BRA CHOK1
-
- *-----------------------------------------------
- FMSG FCC 'NO MORE FILES MAY BE OPENED.'
- FCB $0D,$0A,4
- *-----------------------------------------------
-
- * getchar() get a char from standard input
-
- getchar FCB 86
- JSR GETCHR
- CMP A #$0D CR ???
- BEQ GETCH1 SKIP IF TRUE
-
- CMP A #$1A COMPARE TO CNTRL-Z (EOF)
- BNE CHOK NO
- LDA B #$FF YES...
- BRA CHOK1 RETURN -1
-
- GETCH1 LDA A #$0A LOAD A LF
- JSR PUTCHR ECHO IT
- LDA B #$0D
- BRA CHOK1
-
- *-----------------------------------------------
-
- * putchar(c) write a char to standard output
-
- putchar FCB 86
- TSX
- LDA A 3,X GET THE CHAR
- PSH A SAVE CHAR
- CMP A #$0D IS IT A CR ?
- BEQ PUTC2 YES, SKIP
- JSR PUTCHR ELSE, OUTPUT IT
- PUTC1 PUL B RESTORE CHAR
- BRA CHOK1
-
- PUTC2 JSR PCRLF OUTPUT CR/LF PAIR
- BRA PUTC1
-
- *----------------------------------------------
-
- * gets(buffer) get a char string into buffer
-
- gets FCB 86
- TSX
- LDX 2,X GET START OF BUFFER
- CLR B
-
- GETS1 JSR GETCHR READ A CHAR
- CMP A $AC00 BACKSPACE ?
- BNE GETS2
-
- LDA A #$20
- JSR PUTCHR
- LDA A #$08
- JSR PUTCHR
- TST B BEGINNING OF LINE ?
- BEQ GETS1 YES,
-
- DEC B ELSE,
- DEX ADJUST LINE POINTER
- BRA GETS1
-
- GETS2 CMP A $AC01 DELETE LINE CHAR ?
- BNE GETS3
-
- LDA A #$0D CR...
- JSR PUTCHR
- LDA A #$0A LF...
- JSR PUTCHR
- BRA gets+1 GO TRY AGAIN....
-
- GETS3 STA A 0,X GOOD CHAR--STORE IN BUFFER
- INX AND BUMP POINTER
- INC B AND COUNTER
-
- CMP A #$0D IS IT A CR ?
- BNE GETS1 NO
-
- DEX
- CLR 0,X MARK END OF STRING WITH A NULL
- STX R1A SAVE POINTER VALUE
- LDA A R1A GET IT INTO WORK
- LDA B R1B .. REG
- TSX
- SUB B 3,X RETURN LENGTH
- SBC A 2,X --OF BUFFER
- GETS4 JMP RTSC
-
- *----------------------------------------------
- * puts(string) print a string on the terminal
- puts FCB 86
- TSX
- LDX 2,X GET STRING ADDRESS
- PLOOP LDA A 0,X GET THE CHAR
- BEQ GETS4 IF END OF STRING--QUIT
- CMP A #'\ SPECIAL CHAR ?
- BNE PLOOP1 NO, SKIP
- BSR SPECIAL YES, INTERPRET
- CMP A #$0D IS IT A CR (NEWLINE)
- BNE PLOOP1 NO--SKIP
- JSR PCRLF YES PRINT CR/LF PAIR
- BRA PLOOP2
- PLOOP1 JSR PUTCHR PRINT IT
- PLOOP2 INX BUMP POINTER
- BRA PLOOP
-
-
- * This subroutine interprets the backslash (\) sequence.
-
- SPECIAL INX
- LDA A 0,X GET NEXT CHAR
- CMP A #'b
- BNE SP1
- LDA A #08 BACKSPACE
- BRA SPEXIT
- SP1 CMP A #'f
- BNE SP2
- LDA A #$0C FORMFEED
- BRA SPEXIT
- SP2 CMP A #'n
- BNE SP3
- LDA A #$0D NEWLINE
- BRA SPEXIT
- SP3 CMP A #'\ BACKSLASH
- BEQ SPEXIT
- CMP A #'' SINGLE QUOTE
- BEQ SPEXIT
- CMP A #'" DOUBLE QUOTE
- BEQ SPEXIT
- CMP A #'x START OF HEX SEQUENCE
- BEQ SPHEX
- CMP A #'0 OCTAL SEQUENCE ?
- BLT SPERR
- CMP A #'7
- BLE SPOCTAL YES
-
- SPERR DEX BACKUP THE POINTER
- LDA A 0,X RESTORE CHAR
- SPEXIT RTS RETURN
-
- SPOCTAL LDA B #3
- STA B DFLAG SAVE COUNTER
- CLR B
-
- SPOCT1 SUB A #'0 CONVERT TO DIGIT
- ASL B SHIFT ACCUM
- ASL B
- ASL B
- ABA ADD IN NEW DIGIT
- TAB SAVE
- DEC DFLAG
- BEQ SPBYE IF MAX COUNT--EXIT
- INX
- LDA A 0,X GET NEXT CHAR
- CMP A #'0 VERIFY IF OCTAL
- BLT SPFINI
- CMP A #'7
- BLE SPOCT1 YES, CONTINUE
-
- SPFINI DEX BACKUP
- SPBYE TBA GET ACCUM CHAR
- RTS
-
- SPHEX LDA B #2
- STA B DFLAG
- CLR B
-
- SPHEXL INX
- LDA A 0,X GET NEXT CHAR
- CMP A #'0 VERIFY IF HEX
- BLT SPFINI ..
- CMP A #'9 ..
- BLE SPHEX2 ..
- CMP A #'A ..
- BLT SPFINI ..
- CMP A #'F ..
- BLE SPHEX1 ..
- CMP A #'a ..
- BLT SPFINI ..
- CMP A #'f ..
- BGT SPFINI ..
- SUB A #$20 YES IT IS HEX
- SPHEX1 SUB A #7
- SPHEX2 SUB A #'0
- ASL B
- ASL B
- ASL B
- ASL B
- ABA
- TAB
- DEC DFLAG
- BEQ SPBYE MAX COUNT REACHED ???
- BRA SPHEXL NO, LOOP
-
-
- *----------------------------------------------
- *
- *
- * Test if given char is alpha *
- * isalpha(c)
- * char c;
- * { c=c&127;
- * return(((c>='a')&(c<='z'))|
- * ((c>='A')&(c<='Z'))|
- * (c='_'));
- * }
- *
- isalpha FCB 86 switch to assembly
- TSX
- LDA B 3,X get char
- BSR alPHA
- JMP RTSC
- *
- *---------------------------------------------
- * Test if given char is numeric *
- *
- * isdigit(c)
- * char c;
- * { c=c&127;
- * return((c>='0')&(c<='9'));
- * }
- *
- isdigit FCB 86
- TSX
- LDA B 3,X
- BSR nuMERIC
- JMP RTSC
- *
- *----------------------------------------------
- * Test if given char is alphanumeric *
- *
- * isalnum(c)
- * char c;
- * { return((alpha(c)|(numeric(c)));
- * }
- *
- isalnum FCB 86
- TSX
- LDA B 3,X get char
- BSR alPHA check if alpha
- TSX
- PSH B save result
- LDA B 3,X get char again
- BSR nuMERIC check if decimal
- TSX
- ORA B 0,X fix flag
- INS clean stack
- JMP RTSC
- *
- *
- alPHA CLR A
- AND B #$7F
- CMP B #'a
- BLT alPHA1
- CMP B #'z
- BLE alYES
- alPHA1 CMP B #'A
- BLT alPHA2
- CMP B #'Z
- BLE alYES
- alPHA2 CMP B #'_
- BEQ alYES
- *
- alNO CLR B
- RTS
- *
- alYES LDA B #1
- RTS
- *
- *
- nuMERIC CLR A
- AND B #$7F
- CMP B #'0
- BLT alNO
- CMP B #'9
- BLE alYES
- BRA alNO
- *
- *-----------------------------------------------
- * islower(c)
- * char c; returns TRUE if c is lower case alpha,
- * FALSE otherwise.
- *
- islower FCB 86 SWITCH TO IN-LINE
- TSX
- LDA B 3,X GET CHAR
- AND B #$7F
- CLR A
- CMP B #'a
- BLT ISNO
- CMP B #'z
- BLE ISYES
- *
- ISNO CLR B
- JMP RTSC RETURN FALSE
- *
- ISYES LDA B #1
- JMP RTSC RETURN TRUE
- *
- *----------------------------------------------
- * isupper(c)
- * char c; return TRUE if c is upper case alpha.
- *
- isupper FCB 86
- TSX
- LDA B 3,X
- AND B #$7F
- CLR A
- CMP B #'A
- BLT ISNO
- CMP B #'Z
- BLE ISYES
- BRA ISNO
- *
- *-----------------------------------------------
- * isspace(c)
- * char c; return TRUE if a "white space" char
- *
- isspace FCB 86
- TSX
- LDA B 3,X GET CHAR
- AND B #$7F
- CLR A
- CMP B #' SPACE ?
- BEQ ISYES
- CMP B #$0D CR ???
- BEQ ISYES
- CMP B #$0A LF ???
- BEQ ISYES
- CMP B #$09 HOR TAB ???
- BEQ ISYES
- BRA ISNO
- *
- *----------------------------------------------
- * toupper(c)
- * char c; make c an upper case char if lower
- * case alpha
- *
- toupper FCB 86
- TSX
- LDA B 3,X
- LDA A 2,X
- BNE TOUPP1 SKIP IF MSB'S NOT ZERO
- CMP B #'a
- BLT TOUPP1
- CMP B #'z
- BGT TOUPP1
- SUB B #$20 CONVERT TO UPPER CASE
- TOUPP1 JMP RTSC
- *
- *---------------------------------------------
- * tolower(c)
- * char c; convert to lower case if upper case alpha.
- *
- tolower FCB 86
- TSX
- LDA B 3,X
- LDA A 2,X
- BNE TOLOW1
- CMP B #'A
- BLT TOLOW1
- CMP B #'Z
- BGT TOLOW1
- ADD B #$20 CONVERT TO LOWER CASE
- TOLOW1 JMP RTSC
- *
- *---------------------------------------------
- * strclr(s,n)
- * char *s; int n; clear a string of n bytes.
- *
- strclr FCB 86
- TSX
- LDA A 2,X GET LENGTH OF STRING
- LDA B 3,X
- LDX 4,X POINT TO STRING
- TST B
- BEQ SCLR2
-
- SCLR1 CLR 0,X
- INX
- DEC B
- BNE SCLR1
- SCLR2 TST A
- BEQ SCLR3
- DEC A
- BRA SCLR1
-
- SCLR3 JMP RTSC
- *
- *-----------------------------------------------
- * return the length of a string
- *
- * strlen(s)
- * char *s;
- * { char *t;
- * t=s;
- * while (*s) s++;
- * return (s-t);
- * }
- *
- strlen FCB 86
- TSX
- LDX 2,X point to string
- CLR A preset counter
- CLR B
- *
- strlLP TST 0,X look for NULL
- BEQ strlRT found !!
- INX
- ADD B #1 bump counter
- ADC A #0
- BRA strlLP
- *
- strlRT JMP RTSC
- *
- *------------------------------------------------
- * strcpy(s1,s2)
- * char *s1, *s2; copy s2 into s1.
- *
- strcpy FCB 86
- TSX
- LDX 4,X POINT TO S1
- STX X1TMP SAVE POINTER
- TSX
- LDX 2,X POINT TO S2
-
- SCPY1 LDA B 0,X
- INX
- STX X2TMP
- LDX X1TMP
- STA B 0,X
- BEQ SCLR3 END OF STRING ???
- INX
- STX X1TMP
- LDX X2TMP
- BRA SCPY1
- *
- *------------------------------------------------
- * strcat(s1,s2)
- * char *s1, *s2; s2 is concatenated onto s1.
- *
- strcat FCB 86
- TSX
- LDX 2,X
- STX X2TMP SAVE POINTER TO S2
- TSX
- LDX 4,X POINT TO S1
-
- SCAT1 TST 0,X LOOK FOR END OF STRING
- BEQ SCAT2
- INX
- BRA SCAT1
-
- SCAT2 STX X1TMP SAVE POINTER
- LDX X2TMP
- LDA B 0,X
- INX
- STX X2TMP
- LDX X1TMP
- STA B 0,X
- BEQ SCAT3
- INX
- BRA SCAT2
-
- SCAT3 JMP RTSC
- *
- *--------------------------------------------
- * strcmp(s1,s2)
- * char *s1, *s2; returns: 0 if s1 = s2
- * <0 if s1 < s2
- * >0 if s1 > s2
- *
- strcmp FCB 86
- TSX
- LDX 2,X POINT TO S2
- STX X2TMP
- TSX
- LDX 4,X POINT TO S1
-
- SCMP1 LDA A 0,X GET S1 CHAR
- BEQ SCMP3
- INX
- STX X1TMP
- LDX X2TMP
- LDA B 0,X
- BEQ SCMP2
- SBA COMPARE BY SUBTRACTING
- BNE SCMP3
- INX
- STX X2TMP
- LDX X1TMP
- BRA SCMP1
-
- SCMP2 CLR A
-
- SCMP3 TAB
- BMI SCMP4
- CLR A
- JMP RTSC
-
- SCMP4 LDA A #$FF SIGN EXTEND
- JMP RTSC
- *
- *
- *****************************************************
- *
- HERE EQU * END OF INTERPRETER
- *
- END