
;
; PRNTLN - PRLN00 - PRINT LINE NUMBER
;	REGISTERS USED - R0,R1,R2,R3,R4.
;
PRLN00:	SUB	#10,SP		;DESTINATION
	MOV	SP,R0		;  IS ON THE STACK
	MOV	LINENO,R1	;SOURCE
	ITOA			;CONVERT TO ASCII
	MOV	SP,R0		;PRINT THE RESULTING
	TST	(R0)+		;  DROPING THE FIRST TWO DIGITS
	CLRB	7(SP)		;    SET THE END OF THE NUMBER
	PRINTL			;PRINT NUMBER
	ADD	#10,SP		;RESTORE THE STACK
	RTS	PC
;
; MULSIX - MLS00, MULTIPLY R0 BY SIX.  REGISTERS USED - R0.
;
MLS00:	CLC			;WIPE OUT A CARRY
	ASL	R0		;MULTIPLY BY TWO
	MOV	R0,-(SP)	;SAVE IT
	ASL	R0		;NOW MAKE IT 4X
	ADD	(SP)+,R0	;4X+2X=6X
	RTS	PC
;
; TXTADR - TXT00, GET EVEN START OF USER STORAGE TO R3
;	REGISTERS USED - R3.
;
TXT00:	MOV	ENDTXT,R3	;GET END OF TEXT
	INC	R3
	ASR	R3		;ROUND
	CLC			; IT
	ASL	R3		;  UP TO NEXT EVEN ADDRESS
	RTS	PC
;
; TWOCHR - TWO00, PACK NEXT TWO CHARACTERS IN R4.
;	REGISTERS USED - R1,R2,R4.
;
TWO00:	SKIP			;GET FIRST CHARACTER
	MOV	R2,R4		;PUT IT IN
	SWAB	R4		; HIGH BYTE OF R4
	SKIP			;GET SECOND CHARACTER
	BIS	R2,R4		; AND PACK IT TOO.
	RTS	PC
;
; MOVSTK - MOVS00, MOVE REGISTERS R4,R3, AND R2 ON THE STACK
;
MOVS00:	MOV	R3,-(SP)	;PUT
	MOV	R2,-(SP)	; THE
	MOV	4(SP),-(SP)	;  STUFF
	MOV	R4,6(SP)	;   ON THE STACK
	CMP	R5,SP		;DID WE OVERFLOW?
	BHIS	MOVS01		; YES
	RTS	PC		; NO
MOVS01:	OVFERR			;OVERFLOW
; PDP-11 BASIC, COMMAND EXECUTION ROUTINES
;
; LIST - LIST00, LIST THE SOURCE TEXT
;	REGISTERS USED - R0,R1,R2,R3,R4,R5.
;
LIST00:	CLRUSR
	GETNUM			;GET THE PARAMETERS
	MOV	R3,R0
	BNE	LIST03
LIST05:	MOV	USR,R3
	TST	R4		;IS SECOND PARAMETER ZERO ALSO?
	BNE	LIST07		;NO
LIST04:	MOV	R5,R4
LIST01:	TST	CTRLP		;DID HE TYPE SOMETHING JUST NOW?
	BNE	LIST14		;YES, QUIT WHAT IS GOING ON
	MOVB	(R3)+,R2	;GET CHARACTER
	CMPB	R2,#140		;IS IT A PACKED VERB?
	BLT	LIST08		;JUMP IF NOT
	SUB	#140,R2		;GENERATE VERB NUMBER
	MOV	#INIT11,R0	;GET PROTOTYPE LIST
	MOV	R2,R1
LIST09:	DEC	R1		;DECREMENT VERB COUNT
	BLT	LIST11		;IF FOUND GO PRINT THE VERB
LIST10:	CMPB	(R0)+,#'$	;FIND PROTOTYPE END TO GET TO
	BNE	LIST10		; THE NEXT
	BR	LIST09		;  VERB IN THE LIST
LIST11:	MOVB	(R0)+,R2	;GET A CHARACTER
	CMPB	R2,#'$		;QUIT IF END OF PROTOTYPE
	BEQ	LIST01
	PRINTC			;OTHERWISE TYPE THE CHARACTER
	BR	LIST11
LIST08:	CMPB	R2,#12		;LINE TERMINATOR?
	BEQ	LIST02
	PRINTC
	BR	LIST01		;RE-LOOP
LIST02:	CRLF			;OUTPUT <CR,LF>
	CMP	R3,R4
	BLO	LIST01
	TST	SAVF		;IS THIS A SAVE?
	BEQ	LIST15		;NO
	CLR	R2		;YES, PUNCH 64 BLANK FRAMES
	MOV	#100,R1
LIST16:	PRINTC			;PUNCH A BLANK FRAME
	DEC	R1
	BNE	LIST16		;OUTPUT 64 FRAMES
LIST15:	JMP	INIT26
LIST03:	MOV	R4,-(SP)	;SAVE R4
	FINDLN			;FIND START LINE
	MOV	(SP)+,R4	;RESTORE R4
	CMP	R1,R5		;NO SUCH LINE?
	BHI	LIST05		;NO SUCH LINE FOUND
	MOV	R1,R3		;START ADDRESS TO R3
LIST07:	CMP	R4,R0		;CHECK LAST ARGUMENT AGAINST FIRST
	BLE	LIST06		;JUMP IF .LE. FIRST ARGUMENT
	MOV	R4,R0
	MOV	R3,-(SP)	;
	FINDLN			;GET POSITION OF SECOND LINE
	BNE	LIST12
	MOV	(SP)+,R3
	CMP	R1,R5		;AT END OF TEXT?
	BHI	LIST04		;YES
LIST06:	SRCHLF			;NO, FIND END OF CURRENT LINE
LIST13:	MOV	R1,R4
	BR	LIST01
LIST12:	MOV	(SP)+,R3
	CMP	R1,R5
	BHI	LIST04
	BR	LIST13
LIST14:	JMP	INIT01
;
; DELETE, DEL00, DELETE TEXT AS SPECIFIED BY THE COMMAND PARAMETERS
;	REGISTERS USED - R0,R1,R2,R3,R4,R5.
;
DEL00:	CLRUSR			;CLEAR THE USER AREA JUST IN CASE
	GETNUM			;GET THE PARAMETERS
	MOV	USR,R1		;SET TO START OF USER AREA
	TST	R4		;IS SECOND PARAMETER PRESENT?
	BNE	DEL05		;YES
	MOV	R3,R4		;NO
DEL05:	MOV	R4,-(SP)	;R4=SECOND PARAMETER
	MOV	R3,-(SP)	;R3=FIRST PARAMETER
DEL01:	SRCHLF			;FIND THE NEXT LINE
DEL03:	CMP	R1,R5		;ALL DONE?
	BHIS	DEL02		;YES
	MOV	R1,-(SP)	;SAVE POINTER
	ATOI
	MOV	(SP)+,R1	;RESTORE IT
	CMP	R0,@SP		;COMPARE LINE NUMBERS
	BLT	DEL01
	CMP	R0,2(SP)	;COMPARE WITH END OF LIST
	BGT	DEL02
	SQUISH			;DELETE ONE LINE
	BR	DEL03
DEL02:	CMP	(SP)+,(SP)+	;POP TWO WORDS FROM STACK
	BR	INIT00
DEL04:	CLRUSR			;CLEAR USER SPACE FIRST
	FINDLN			;FIND THE LINE NUMBER
	BNE	INIT03		;NO SUCH LINE
	SQUISH			;FOUND, DELETE IT
	BR	INIT03
;
; PDP-11 BASIC - COMMAND/STATEMENT INTERPRETER
;	REGISTERS USED - R0,R1,R2,R3,R4,R5
;
INIT02:	JSR	PC,SKIP00	;GET THE NEXT CHARACTER
	CMPB	#':,R2		;IS THIS A CONTINUATION?
	BEQ	INIT10		;JUMP IF YES
	CMPB	#12,R2		;IS IT A LINE FEED
	BEQ	INIT03		;JUMP IF YES
	ILCERR			;ILLEGAL CHARACTER TERMINATING STMT.
INIT03:	TST	RUNF		;IS RUN MODE SET
	BEQ	INIT04		;JUMP IF NOT
	TST	ENDTXT		;IS USER AREA SET UP?
	BEQ	INIT19		;NO, DO DIFFERENT TEST
	CMP	R1,ENDTXT	;IS THE TEXT POINTER TOO FAR ALONG?
	BR	INIT20
INIT19:	CMP	R1,R5
INIT20:	BHIS	STOP03		;JUMP IF YES
INIT13:	JSR	PC,ATOI00	;FIND REAL LINE NUMBER
	MOV	R0,LINENO
	BR	INIT10
RESTRT:	MOV	USR,R5		;RESTART ENTRY - CLEAR USER AREA
	INC	R5		; AND FAKE A
	CLR	ENDTXT		;  CTRL P.
INIT01:	MOV	ENDUSR,SP	;ON ^P CLEAR A
	CLR	OLDF		; FEW
	CLR	CTRLP		;   THINGS
	CLR	LINENO		;CLEAR THE LINE NUMBER
	MOV	#1,ECHO
	CRLF			;    AND NEATLY FINISH UP
INIT26:	CLR	SAVF		;CLEAR THE SAVE FLAG TOO
INIT00:	CLR	RUNF		;CLEAR RUN FLAG TO START
	MOV	#RDY00,R0	;TELL USER THAT
	PRINTL			;ALL IS READY
INIT04:	CLR	CTRLP		;TURN OFF CONTROL P.
	PACK			;GET A COMMAND
	SKIP			;GET THE FIRST CHARACTER
	CMP	R2,#12		;IGNORE IF ONLY A TERMINATOR
	BEQ	INIT04
	MOV	#WORK,R1	;GET TEXT POINTER
	ATOI			;GET INTERNAL LINE NUMBER
	CMPB	@R1,#12		;CALL IT A DELETE IF NO
	BEQ	DEL04		; VERB WAS TYPED
INIT05:	MOV	R1,R3		;SAVE THE TEXT POINTER
	MOV	#INIT11,R0	;GET ADDRESS OF PROTOTYPES
	CLR	R2		;CLEAR JUMP POINTER FLAG
INIT06:	CMPB	(R3)+,#' 	;IS CHARACTER A SPACE?
	BEQ	INIT06		;IGNORE SPACES
	CMPB	-(R3),(R0)+	;DOES CHARACTER MATCH PROTOTYPE
	BNE	INIT08		;NO
	INC	R3		;YES, GET NEXT CHARACTER
	CMPB	@R0,#'$		;IS NEXT CHARACTER THE TERMINATOR?
	BEQ	INIT14		;IF SO, EXIT SUCCESSFULLY
	BR	INIT06		;GO BACK
INIT08:	CMPB	(R0)+,#'$	;SKIP TO START OF NEXT
	BNE	INIT08		;  PROTOTYPE
	CMPB	@R0,#'$		;TWO IN A ROW?
	BEQ	INIT09		;YES, END OF LIST
	MOV	R1,R3		;RESET TEXT POINTER
	INC	R2		;INCREMENT JUMP POINTER
	BR	INIT06		;RE-LOOP
INIT10:	TST	CTRLP		;QUIT IF
	BNE	INIT01		; ^P WAS TYPED A LITTLE WHILE AGO
	JSR	PC,SKIP00	;GET VERB
	SUB	#140,R2		;GET ADDRESS DISPLACEMENT
	BMI	INIT09
	ASL	R2
	JMP	@INIT12(R2)	;GO DO IT
STOP03:	JMP	STOP00
INIT09:	UNRERR			;UNRECOGNIZED STATEMENT
INIT14:	ADD	#140,R2		;GENERATE SPECIAL BYTE
	MOVB	R2,(R1)+	;STORE IT IN THE TEXT
	MOV	R1,R4		;REMEMBER PLACE IN LINE
INIT15:	MOVB	@R3,(R1)+	;PACK
	CMPB	(R3)+,#12	; LINE UP TIGHT
	BNE	INIT15
	CMPB	R2,#143		;IS IT A "REM"ARK?
	BEQ	INIT27		;QUIT IF IT IS
	CMP	R2,#155		;IS THIS LINE AN "IF"?
	BNE	INIT18		;NO, EXIT.
	MOV	R4,R1		;START SCAN FOR "THEN"
INIT16:	SKIP
	CMPB	R2,#'T		;IT STARTS WITH A "T"
	BNE	INIT17
	SKIP
	CMPB	R2,#'H		;FOLLOWED BY AN "H"
	BNE	INIT17
	SKIP
	CMPB	R2,#'E		;THEN AN "E"
	BNE	INIT17
	SKIP
	CMPB	R2,#'N		;FINALLY AN "N"
	BNE	INIT17		;GO BACK AND SCRUNCH IT TOO
INIT21:	SKIP			;MAKE LEADING BLANKS SAFE
	DEC	R1		;BEFORE MODIFYING STATEMENT
	MOV	R1,R4		;THIS KEEPS ME FROM AN INFINITE LOOP
	TSTCH			;IF THE "THEN" IS FOLLOWED BY A
	BEQ	INIT18		;  NUMBER IT IS LEGAL
	BR	INIT05
INIT17:	CMPB	R2,#12		;END OF LINE?
	BEQ	INIT27		;NO
	CMPB	R2,#':		;ALTERNATE END OF LINE?
	BNE	INIT16		;NO
INIT18:	MOV	R4,R1		;RESET THE POINTER
INIT23:	CMPB	@R1,#'"		;IS CHARACTER START OF QUOTE STRING?
	BEQ	INIT24		;YES
	CMPB	(R1)+,#':	;NO, IS IT A STATEMENT SEPARATOR?
	BEQ	INIT21		;YES
	CMPB	-(R1),#12	;THEN IS IT A TERMINATOR?
	BEQ	INIT22		;YES
INIT25:	INC	R1		;NO
	BR	INIT23
INIT24:	INC	R1
	CMPB	@R1,#'"		;IS THIS THE SECOND "?
	BEQ	INIT25		;YES
	CMPB	@R1,#12		;NO, END OF LINE?
	BNE	INIT24		;NO
	UNMERR			;UNMATCHED QUOTES IN LINE
INIT22:	INC	R1
INIT27:	MOV	R1,R3		;SAVE END OF LINE POINTER
	MOV	#WORK,R1	;YES, CONTINUE MAIN LOOP
	SKIP			;GET FIRST CHARACTER
	TSTCH			;IS IT NUMERIC?
	BEQ	ASSM00		;YES, GO ASSEMBLE LINE
	DEC	R1		;OTHERWISE DO IT IMMEDIATELY
	BR	INIT10
;
; ASSEMBLE LINE OF CODE INTO WORKING STORAGE - TRANSFER TO USER AREA
;	REGISTERS USED - R0,R1,R2,R3,R4.
;
ASSM00:	CLRUSR			;CLEAR USER SPACE IF ANY
	MOV	#WORK,R1	;GET STORAGE ADDRESS
	SUB	R1,R3		;GET LINE LENGTH
	MOV	R3,-(SP)	;SAVE IT
	ATOI			;ASCII TO INTEGER IN R0
	TST	R0		;IS LINE NUMBER ZERO?
	BEQ	ASSM02		;YES, DISALLOWED
	CMP	R0,#17777	;LINE NUMBER .GT. 8191?
	BGT	ASSM02	;YES, DISALLOWED
	FINDLN			;LOOK FOR LINE NUMBER IN TEXT
	BNE	ASSM01		;DON'T DELETE LINE
	SQUISH			;DELETE TEXT LINE TO TERMINATOR
ASSM01:	MOV	(SP)+,R3	;RESTORE LINE LENGTH
INS00:	CLRUSR			;CLEAR USER SPACE IF ANY
	MOV	R3,R0
	TSTOK			;ENOUGH ROOM IN USER STORAGE?
	BHIS	INS01		;YES
	OVFERR			;OVERFLOW ERROR
INS04:	ADD	R0,R5		;UPDATE TEXT POINTER
	BR	INS05
INS01:	CMP	R1,R5		;IS POINTER AT END OF TEXT?
	BHIS	INS04		;JUMP IF YES
	MOV	R5,R2
	ADD	R0,R5		;MOVE STORAGE POINTER
	MOV	R5,R4
INS02:	MOVB	-(R2),-(R4)	;SHIFT THE TEXT AROUND
	CMP	R1,R2		;DONE?
	BLOS	INS02		;NO, DO IT AGAIN
INS05:	MOV	#WORK,R2
INS03:	MOVB	@R2,(R1)+	;INSERT NEW TEXT
	CMPB	(R2)+,#12	;CHECK FOR LINE TERMINATOR
	BNE	INS03
	JMP	INIT03
ASSM02:	LNNERR			;BAD LINE NUMBER
;
INIT11:	.ASCII	/LIST$LET$READ$REM$RUN$RESTORE$/
	.ASCII	/RETURN$DATA$DIM$DELETE$PRINT$GOSUB$/
	.ASCII	/GOTO$IF$FOR$NEXT$INPUT$SAVE$STOP$END$DEF$/
	.ASCII	/OLD$RANDOMIZE$$/
	.EVEN
;
INIT12:	LIST00		;LIST - 140
	LET00		;LET - 141
	READ00		;READ - 142
	REM00		;REMARK - 143
	RUN00		;RUN - 144
	RES00		;RESTORE - 145
	RET00		;RETURN - 146
	REM00		;DATA - HANDLE LIKE REMARK - 147
	DIM00		;DIM - 150
	DEL00		;DELETE - 151
	PR00		;PRINT - 152
	GOSB00		;GOSUB - 153
	GOTO00		;GOTO - 154
	IF00		;IF - 155
	FOR00		;FOR - 156
	NEXT00		;NEXT - 157
	INP00		;INPUT - 160
	SAVE00		;SAVE - 161
	STOP00		;STOP - 162
	STOP00		;END - 163
	DEF00		;DEFINE - 164
	OLD00		;OLD - 165
	RND01		;RANDOMIZE - 166
;
RDY00:	.ASCII	/READY/
RDY01:	.BYTE	15,12,0
	.EVEN
;
; STOP - STOP AND END STATEMENTS - TELL USER PROGRAM IS DONE
;	REGISTERS USED - R0,R1,R2,R3,R4
;
STOP00:	CRLF
	MOV	#STOP01,R0	;TELL USER
	PRINTL			;  THAT ALL HAS STOPPED
	PRNTLN			;   AT SOME FUNNY PLACE
	CRLF			;AND THEN
STOP02:	CLR	LINENO
	JMP	INIT00		; ASK WHAT NEXT
STOP01:	.ASCII	/STOP AT LINE /

	.EOT			;END OF TAPE 3
