-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathBASIC5.S#000000
3495 lines (3495 loc) · 60 KB
/
BASIC5.S#000000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;
; PROCESSOR TECHNOLOGY BASIC-5
; USING ZILOG OPCODES, COURTESY OF A SED FILE
;
; SYSTEM GLOBAL EQUATES
;
BDOS EQU 0005H ;ADDRESS OF JUMP TO BDOS
CONIN EQU 1 ;CONSOLE IN
CONOUT EQU 2 ;CONSOLE OUT
CONSTS EQU 11 ;CONSOLE STATUS
FPSIZ EQU 5
LINLEN EQU 73 ;# OF CHARS IN LEGAL INPUT LINE
FP123 EQU FPSIZ-2
FPNIB EQU FP123*2
DIGIT EQU FPNIB/2
CR EQU 15Q ;CARRIAGE RETURN
NULL EQU 0
LF EQU 12Q ;LINE FEED
ESC EQU 3Q ;CONTROL C
EOF EQU 1 ;END OF FILE
BELL EQU 7 ;BELL CHARACTER
STESIZ EQU 2+FPSIZ ;SYMBOL TABLE ELEMENT SIZE
OPBASE EQU '('
FTYPE EQU 1 ;CONTROL STACK FOR ENTRY TYPE
FORSZ EQU FPSIZ*2+2+2+1 ;'FOR' CONTROL STACK ENTRY SIZE
GTYPE EQU 2 ;CONTROL STACK GOSUB ENTRY TYPE
ETYPE EQU 0 ;CONTROL STACK UNDERFLOW TYPE
UMINUS EQU 61Q ;UNARY MINUS
;
; STARTUP BASIC SYSTEM
;
ORG 100H
;
START: LD SP,CMNDSP
XOR A
LD (NULLCT),A ;NULL COUNT.
LD HL,BASEND ;START OF USER MEMORY
LD (BOFA),HL ;IS RIGHT AFTER THE BASIC CODE.
LD HL,(BDOS+1) ;THE ADDRESS OF BDOS IS
DEC HL ; ** Bobbi / Qkumba fix **
LD (MEMTOP),HL ;THE END OF USER MEMORY.
ST0: LD HL,PLS ;"PROGRAM LOADED?" MESSAGE
CALL PRNT
CALL INLINE
LD A,(IBUF)
;
; OPTIONAL ENTRY POINT FOR TAPE OR DISK ROUTINES
;
; ALLOWS DIRECT PROGRAM INPUT FROM HIGH SPEED DEVICES
; SEE OPERATING INSTRUCTIONS FOR PROPER IMPLEMENTATION
;
STAR1: CP 'N'
JP Z,ST1 ;IF NO PROGRAM CLEAR AND INITIALIZE
CP 'Y'
JP NZ,ST0
LD HL,(BOFA)
ST2: LD A,(HL) ;FIND END OF PROGRAM
CP EOF
JP Z,ST3
CALL ADR
JP ST2
ST3: LD (EOFA),HL
CALL CCLEAR
JP ST4
ST1: CALL CSCR
ST4: LD A,2*FPNIB
LD (INFES),A
; INITIALIZE RANDOM NUMBER
LD DE,FRAND
LD HL,RANDS
CALL VCOPY ;FRAND=RANDOM NUMBER SEED
;
; COMMAND PROCESSOR
;
CMND1: CALL CRLF2
LD HL,RDYS ;PRINT READY MESSAGE
CALL PRNT
CMNDR: LD A,1 ;SET DIRECT INPUT FLAG
LD (DIRF),A
LD SP,CMNDSP
CALL CRLF
CMND2: CALL INLINE ;GET INPUT LINE FROM OPERATOR
CALL PP ;PRE-PROCESS IT
JP C,CMND3
CALL LINE ;LINE NUMBER...GO EDIT
JP CMND2
CMND3: CALL CMND4
JP CMNDR
CMND4: LD HL,IBUF ;POINT TO COMMAND OR STATEMENT
LD (TXA),HL
CALL GC
AND 240Q
CP 240Q ;CHECK FOR COMMAND
LD DE,CMNDD
JP Z,ISTA1 ;PROCESS COMMAND
CALL ISTAT ;PROCESS STATEMENT (IF ALLOWED)
CALL GCI
CP CR
RET Z
E1: LD BC,'BS'
JP ERROR
; ERROR MESSAGE PRINTOUT
E3: LD BC,'BA'
JP ERROR
E4: LD BC,'CS'
JP ERROR
E5: LD BC,'OB'
JP ERROR
E6: LD BC,'DM'
;
ERROR: PUSH BC
CALL CRLF
POP BC
CALL CHOUT
LD B,C
CALL CHOUT
LD HL,ERS
ERM1: CALL PRNT
LD A,(DIRF)
OR A
JP NZ,CMND1
LD HL,INS
CALL PRNT
; FIND LINE NUMBER
LD HL,(BOFA)
ERM2: LD B,H
LD C,L
LD E,(HL)
LD D,0
ADD HL,DE
EX DE,HL
LD HL,TXA
CALL DCMP
EX DE,HL
JP C,ERM2
INC BC
LD A,(BC)
LD L,A
INC BC
LD A,(BC)
LD H,A
LD DE,IBUF ;USE IBUF TO ACCUMULATE THE LINE NUMBER STRING
CALL CNS
LD A,CR
LD (DE),A
LD HL,IBUF
CALL PRNTCR
JP CMND1
;
; LINE EDITOR
;
LINE: LD HL,(BOFA) ;CHECK FOR EMPTY FILE
FIN: LD A,(HL) ;CHECK IF APPENDING LINE AT END
DEC A
JP Z,APP
EX DE,HL
INC DE
LD HL,(IBLN) ;GET INPUT LINE NUMBER
EX DE,HL
CALL DCMP ;COMPARE WITH FILE LINE NUMBER
DEC HL
JP C,INSR ;LESS THAN
JP Z,INSR ;EQUAL
LD A,(HL) ;LENGTH OF LINE
CALL ADR ;JUMP FORWARD
JP FIN
; APPEND LINE AT END CASE
APP: LD A,(IBCNT) ;DON'T APPEND NULL LINE
CP 4
RET Z
CALL FULL ;CHECK FOR ROOM IN FILE
LD HL,(EOFA) ;PLACE LINE IN FILE
CALL IMOV
LD (HL),EOF
LD (EOFA),HL
RET
; INSERT LINE IN FILE CASE
INSR: LD B,(HL) ;OLD LINE COUNT
LD (INSA),HL ;INSERT LINE POINTER
LD A,(IBCNT) ;NEW LINE COUNT
JP C,LT ;JMP IF NEW LINE # NOT = OLD LINE NUMBER
SUB 4
JP Z,LT1 ;TEST IF SHOULD DELETE NULL LINE
ADD A,4
LT1: SUB B
JP Z,LIN1 ;LINE LENGTHS EQUAL
JP C,GT
; EXPAND FILE FOR NEW OR LARGER LINE
LT: LD B,A
LD A,(IBCNT)
CP 4 ;DON'T INSERT NULL LINE
RET Z
LD A,B
CALL FULL
LD HL,(INSA)
CALL NMOV
LD HL,(EOFA)
EX DE,HL
LD (EOFA),HL
INC BC
CALL RMOV
JP LIN1
; CONTRACT FILE FOR SMALLER LINE
GT: CPL
INC A
CALL ADR
CALL NMOV
EX DE,HL
LD HL,(INSA)
CALL NZ,LMOV
LD (HL),EOF
LD (EOFA),HL
; INSERT CURRENT LINE INTO FILE
LIN1: LD HL,(INSA)
LD A,(IBCNT)
CP 4
RET Z
; INSERT CURRENT LINE AT ADDR HL
IMOV: LD DE,IBCNT
LD A,(DE)
LD C,A
LD B,0
; COPY BLOCK FROM BEGINNING
; HL IS DEST ADDR, DE IS SOURCE ADDR, BC IS COUNT
LMOV: LD A,(DE)
LD (HL),A
INC DE
INC HL
DEC BC
LD A,B
OR C
JP NZ,LMOV
RET
; COPY BLOCK STARTING AT END
; HL IS DEST, DE IS SOURCE, BC IS COUNT
RMOV: LD A,(DE)
LD (HL),A
DEC HL
DEC DE
DEC BC
LD A,B
OR C
JP NZ,RMOV
RET
; COMPUTE FILE MOVE COUNT
; BC GETS (EOFA) - (HL), RET Z SET MEANS ZERO COUNT
NMOV: LD A,(EOFA)
SUB L
LD C,A
LD A,(EOFA+1)
SBC A,H
LD B,A
OR C
RET
; ADD A TO HL
ADR: ADD A,L
LD L,A
RET NC
INC H
RET
; CHECK FOR FILE OVERFLOW, LEAVES NEW EOFA IN DE
; A HAS INCREASE IN SIZE
FULL: LD HL,(EOFA)
CALL ADR
EX DE,HL
LD HL,MEMTOP
CALL DCMP
JP NC,E8
RET
;
; COMMANDS
;
CSCR: LD HL,(BOFA)
LD (HL),EOF
LD (EOFA),HL
; "CLEAR"
CCLEAR: LD HL,(EOFA) ;CLEAR FROM EOFA TO MEMTOP
INC HL
LD (MATA),HL
EX DE,HL
LD HL,MEMTOP ;END OF ASSIGNED MEMORY
CCLR1: XOR A
LD (DE),A
CALL DCMP
INC DE
JP NZ,CCLR1
LD HL,(MEMTOP)
LD (STAA),HL
LD HL,CSTKL+CSTKSZ-1
LD (HL),ETYPE
LD (CSTKA),HL
LD HL,ASTKL+ASTKSZ+FPSIZ-1
LD (ASTKA),HL
RET
; "NULL"
CNULL: CALL INTGER
JP C,E3 ;NO ARGUMENT SUPPLIED
LD A,L
LD (NULLCT),A
JP CMND1
; "LIST"
CLIST: CALL GC
CP CR
LD DE,0
JP Z,CL0 ;JUMP IF NO ARGUMENT SUPPLIED
CALL INTGER ;ERROR DEFAULT IS LIST
CL0: LD HL,(BOFA)
CL1: LD A,(HL)
DEC A
RET Z
INC HL
CALL DCMP
DEC HL ;POINT TO COUNT CHAR AGAIN
JP C,CL2
JP Z,CL2
; INCREMENT TO NEXT LINE
LD A,(HL)
CALL ADR
JP CL1
CL2: PUSH DE
LD DE,IBUF ;AREA TO UNPREPROCESS TO
CALL UPPL
INC HL
PUSH HL
LD HL,IBUF
CALL PRNTCR
CALL PCHECK
CALL CRLF
POP HL
POP DE
JP CL1
; "RUN"
CRUN: CALL CCLEAR
LD HL,(BOFA)
LD A,(HL)
DEC A ;CHECK FOR NULL PROGRAM
JP Z,ENDX
INC HL
INC HL
INC HL
LD (TXA),HL
LD (RTXA),HL ;POINTER FOR 'READ' STATEMENT
XOR A
LD (DIRF),A ;CLEAR DIRECT FLAG AND FALL THROUGH TO DRIVER
CALL CRLF
;
; INTERPRETER DRIVER
;
ILOOP: CALL PCHECK
CALL ISTAT ;INTERPRET CURRENT STATEMENT
CALL JOE ;TEST FOR JUNK ON END
JP NC,ILOOP ;CONTINUE IF NOT AT END OF PROGRAM
JP ENDX ;EXECUTE END STATEMENT
; INTERPRET STATEMENT LOCATED BY TXA
ISTAT: CALL GC ;GET FIRST NON BLANK
OR A
JP P,LET ;MUST BE LET IF NOT RW
CP IRWLIM ;IS IT AN INITIAL RW
JP NC,E1
LD DE,STATD ;STATEMENT DISPATCH TABLE BASE
ISTA1: CALL GCI ;ADVANCE TEXT POINTER
AND 37Q
RLCA ;MULTIPLY BY TWO PREPARING FOR TABLE LOOKUP
LD L,A
LD H,0
ADD HL,DE
CALL LHLI
JP (HL) ;BRANCK TO STATEMENT OR COMMAND
;
; STATEMENTS
;
; "LET"
LET: CALL VAR ;CHECK FOR VARIABLE
JP C,E1
PUSH HL ;SAVE VALUE ADDRESS
LD B,EQRW
CALL EATC
CALL EXPRB
POP DE ;DESTINATION ADDRESS
CALL POPA1 ;COPY EXPR VALUE TO VARIABLE
RET ;******* CALL, RET???!!!****************
; "FOR"
SFOR: CALL DIRT
CALL VAR ;CONTROL VARIABLE
JP C,E1
PUSH HL ;CONTROLVARIABLE VALUE ADDRESS
LD B,EQRW
CALL EATC
CALL EXPRB ;INITIAL VALUE
POP DE ;VARIABLE VALUE ADDRESS
PUSH DE ;SAVE
CALL POPA1 ;SET INITIAL VALUE
LD B,TORW ;RW FOR 'TO'
CALL EATC
CALL EXPRB ;LIMIT VALUE COMPUTATION
CALL GC ;CHECK NEXT CHARACTER FOR POSSIBLE STEP EXPR
CP STEPRW
JP Z,FOR1
; USE STEP OF 1
LD DE,FPONE
CALL PSHA1
JP FOR2
; COMPUTE STEP VALUE
FOR1: CALL GCI ;EAT THE STEP RW
CALL EXPRB ;THE STEP VALUE
; HERE THE STEP AND LIMIT ARE ON THE ARG STACK
FOR2: LD DE,-2 ;PREPARE TO ALLOCATE 2 BYTES ON CONTROL STACK
CALL PSHCS ;RETURNS ADDRESS OF THOSE 2 BYTES IN HL
EX DE,HL
CALL JOE ;TEST FOR JUNK ON END
JP C,E4 ;NO "FOR" STATEMENT AT END OF PROGRAM
EX DE,HL ;DE HAS LOOP TEST ADDR, HL HAS CONTROL STACK ADR
LD (HL),D ;HIGH ORDER TEXT ADDRESS BYTE
DEC HL
LD (HL),E ;LOW ORDER TEXT ADDRESS BYTE
LD DE,-FPSIZ ;ALLOCATE SPACE FOR LIMIT ON CONTROL STACK
CALL PSHCS
PUSH HL ;ADDR ON CONTROL STACK FOR LIMIT
LD DE,-FPSIZ ;ALLOCATE SPACE FOR STEP ON CONTROL STACK
CALL PSHCS
CALL POPAS ;COPY STEP VALUE TO CONTROL STACK
POP DE ;CONTROL STACK ADDR FOR LIMIT VLAUE
CALL POPA1 ;LIMIT VALUE TO CONTROL STACK
LD DE,-3 ;ALLOCATE SPACE FOR TEST ADDRESS AND CS ENTRY
CALL PSHCS
POP DE ;CONTROL VARIABLE ADDRESS
LD (HL),D ;HIGH ORDER BYTE OF CONTROL VAR ADDR
DEC HL
LD (HL),E ;LOW ORDER BYTE
DEC HL
LD (HL),FTYPE ;SET CONTROL STACK ENTRY TYPE FOR "FOR"
JP NEXT5 ;GO FINISH OFF CAREFULLY
; "NEXT"
NEXT: CALL DIRT
LD HL,(CSTKA) ;CONTROL STACK ADDRESS
LD A,(HL) ;STACK ENTRY TYPE BYTE
DEC A ;MUST BE FOR TYPE ELSE ERROR
JP NZ,E4 ;IMPROPER NEXTING ERROR
INC HL ;CONTROL STACK POINTER TO CONTROL VAR ADDR
PUSH HL
CALL VAR ;CHECK VARIABLE, IN CASE USER WANTS
JP C,NEXT1 ;SKIP CHECK IF VAR NOT THERE
EX DE,HL
POP HL ;CONTROL VARIABLE ADDRESS
PUSH HL ;SAVE IT AGAIN
CALL DCMP
JP NZ,E4 ;IMPROPER NESTING IF NOT THE SAME
NEXT1: POP HL ;CONTROL VARIABLE ADDRESS
PUSH HL
PUSH HL
LD DE,FPSIZ+2-1 ;COMPUTE ADDRESS TO STEP VALUE
ADD HL,DE
EX (SP),HL ;NOW ADDRESS TO VAR IN HL
CALL LHLI ;VARIABLE ADDRESS
LD B,H ;COPY VAR ADDRESS TO BC
LD C,L
POP DE ;STEP VALUE ADDRESS
PUSH DE
CALL FADD ;DO INCREMENT
POP HL ;STEP VALUE
DEC HL ;POINT TO SIGN OF STEP VALUE
LD A,(HL) ;SIGN 0=POS, 1=NEG
LD DE,FPSIZ+1
ADD HL,DE ;PUTS LIMIT ADDRESS IN HL
EX DE,HL
POP HL ;VARIABLE ADDRESS
CALL LHLI ;GET ADDRESS
PUSH DE ;SAVE CONTROL STACK POINTER TO GET TEXT ADDR
OR A ;SET CONDITIONS BASED ON SIGN OF STEP VALUE
JP Z,NEXT2 ;REVERSE TEST ON NEGATIVE STEP VALUE
EX DE,HL
NEXT2: LD B,H ;SET UP ARGS FOR COMPARE
LD C,L
CALL RELOP ;TEST <=
POP DE ;TEXT ADDRESS
JP M,NEXT3 ;STILL SMALLER?
JP Z,NEXT3 ;JUMP IF WANT TO CONTINUE LOOP
; TERMINATE LOOP
LD HL,3 ;REMOVE CSTACK ENTRY
ADD HL,DE
LD (CSTKA),HL
RET
NEXT3: INC DE ;TEXT ADDRESS
EX DE,HL
CALL LHLI ;GET TEXT ADDRESS IN HL
; ITERATE, SKIPPING NORMAL JUNK ON END TEST AT ILOOP
NEXT4: EX DE,HL ;SAVE NEW TEXT ADDRESS IN DE
CALL JOE
EX DE,HL
NEXT6: LD (TXA),HL
NEXT5: LD HL,ILOOP
EX (SP),HL
RET ;TO DISPATCHER SKIPPING JOE CALL THERE
; "IF"
SIF: LD B,1 ;SPECIFY PRINCIPAL OPERATOR IS RELATIONAL
CALL EXPB1
LD HL,(ASTKA) ;ADDRESS ON BOOLEAN VALUE ON ARG STACK
INC (HL) ;SETS ZERO CONDITION IF RELATIONAL TEST TRUE
PUSH AF ;SAVE CONDITIONS TO TEST LATER
CALL POPAS ;REMOVE VALUE FROM ARG STACK COPY TO SELF
POP AF
JP NZ,REM ;IF TEST FALSE TREAT REST OF STATEMENT AS REM
; TEST SUCCEEDED
LD B,THENRW
CALL EATC
CALL INTGER ;CHECK IF LINE NUMBER IS DESIRED ACTION
JP C,ISTAT
JP GOTO1
; "GOTO"
SGOTO: XOR A
LD (DIRF),A ;CLEAR DIRECT STATEMENT FLAG
CALL INTGER ;RETURNS INTEGER IN HL IF LINE NUMBER PRESENT
JP C,E1 ;SYNTAX ERROR NO LINE NUMBER
GOTO1: EX DE,HL ;LN IN DE
CALL FINDLN ;RETURNS TEST ADDRESS POINTS TO COUNT VALUE
GOTO2: INC HL
INC HL
INC HL ;ADVANCE TEXT POINTER PAST LINE NUMBER ANDCOUNT
JP NEXT4
; "GOSUB"
GOSUB: CALL DIRT
LD DE,-3 ;CREATE CONTROL STACK ENTRY
CALL PSHCS
PUSH HL ;SAVE STACK ADDRESS
CALL INTGER
JP C,E1
EX DE,HL ;LINE NUMBER TO DE
CALL JOE
LD B,H
LD C,L
POP HL ;STACK ADDRESS
LD (HL),B ;STACK RETURN ADDRESS RETURNED BY JOE
DEC HL
LD (HL),C
DEC HL
LD (HL),GTYPE ;MAKE CONTROL STACK ENTRY TYPE "GOSUB"
CALL FINDLN
INC HL
INC HL
INC HL
JP NEXT6
; "RETURN"
RETRN: CALL DIRT
LD (DIRF),A ;CLEARS DIRF IN ACC IS CLEAR
LD HL,(CSTKA)
RET1: LD A,(HL)
OR A ;CHECK FOR STACK EMPTY
JP Z,E4
CP GTYPE ;CHECK FOR GOSUB TYPE
JP Z,RET2
; REMOVE FOR TYPE ENTRY FROM STACK
LD DE,FORSZ
ADD HL,DE
JP RET1
; FOUND A GTYPE STACK ENTRY
RET2: INC HL
LD E,(HL) ;LOW ORDER TEXT ADDRESS
INC HL
LD D,(HL) ;HIGH ORDER TEXT ADDRESS
INC HL ;ADDRESS OF PREVIOUS CONTROL STACK ENTRY
LD (CSTKA),HL
EX DE,HL ;PUT TEXT ADDRESS IN HL
LD A,(HL) ;ADDRESS POINTS TO EOF IF GOSUB WAS LAST LINE
DEC A ;END OF FILE?
JP NZ,NEXT4
JP ENDX
; "DATA" AND "REM"
DATA: CALL DIRT ;DATA STATEMENT ILLEGAL AS DIRECT
REM: CALL GCI
CP CR
JP NZ,REM
DEC HL ;BACKUP POINTER SO NORMAL JOE WILL WORK
LD (TXA),HL
RET
; "DIM"
DIM: CALL NAME ;LOOK FOR VARIABLE NAME
JP C,E1
LD A,C ;PREPARE TURN ON 80H BIT TO SIGNIFY MATRIX
OR 80H
LD C,A
CALL STLK
JP NC,E6 ;ERROR IF NAME ALREADY EXISTS
PUSH HL ;SYMBOL TABLE ADDRESS
LD B,LPARRW
CALL EATC
CALL EXPRB
LD B,')'
CALL EATC
CALL PFIX ;RETURN INTEGER IN DE
LD HL,MATUB ;MAXIMUM SIZE FORM MATRIX
CALL DCMP
JP NC,E6
POP HL ;SYMBOL TABLE ADDRESS
CALL DIMS
CALL GC ;SEE IF MORE TO DO
CP ','
RET NZ
CALL GCI ;EAT THE COMMA
JP DIM
; "STOP"
STOP: CALL DIRT
STOP1: CALL CRLF2
LD (BRKCHR),A
LD HL,STOPS
JP ERM1
; "END"
ENDX EQU CMND1
; "READ"
READ: CALL DIRT
LD HL,(TXA)
PUSH HL ;SAVE TXA TEMPORARILY
LD HL,(RTXA) ;THE 'READ' TXA
READ0: LD (TXA),HL
CALL GCI
CP ','
JP Z,READ2 ;PROCESS INPUT VALUE
CP DATARW
JP Z,READ2
DEC A
JP Z,READ4
; SKIP TO NEXT LINE
CALL REM ;LEAVES ADDRESS OF LAST CR IN HL
INC HL
LD A,(HL)
DEC A
JP Z,READ4
INC HL
INC HL
INC HL ;HL NOW POINTS TO FIRST BYTE ON NEXT LINE
JP READ0
; PROCESS VALUE
READ2: CALL EXPRB
CALL GC
CP ',' ;SKIP JOE TEST IF COMMA
JP Z,READ3
; JUNK ON END TEST
CALL JOE
READ3: LD HL,(TXA)
LD (RTXA),HL ;SAVE NEW "READ" TEXT ADDRESS
POP HL ;REAL TXA
LD (TXA),HL
CALL VAR
JP C,E1
CALL POPAS ;PUT READ VALUE INTO VARIABLE
CALL GC
CP ',' ;CHECK FOR ANOTHER VARIABLE
RET NZ
CALL GCI ;EAT THE COMMA
JP READ
READ4: POP HL ;PROGRAM TXA
LD (TXA),HL
LD BC,'RD'
JP ERROR
; "RESTORE"
RESTOR: LD HL,(BOFA) ;BEGINNING OF FILE POINTER
INC HL
INC HL
INC HL
LD (RTXA),HL
RET
; "PRINT"
PRINT: CALL GC
CP CR ;CHECK FOR STAND ALONE PRINT
JP Z,CRLF
PRIN2: CP '"'
JP Z,PSTR ;PRINT THE STRING
CP TABRW
JP Z,PTAB ;TABULATION
CP '%'
JP Z,PFORM ;SET FORMAT
CP CR
RET Z
CP ';'
RET Z
CALL EXPRB ;MUST BE EXPRESSION TO PRINT
LD DE,FPSINK
CALL POPA1 ;POP VALUE TO FPSINK
LD A,(PHEAD)
CP 56
CALL NC,CRLF ;DO CRLF IF PRINT HEAD IS PAST 56
LD HL,FPSINK
CALL FPOUT
LD B,' '
CALL CHOUT
PR1: CALL GC ;GET DELIMITER
CP ','
JP NZ,CRLF
PR0: CALL GCI
CALL GC
JP PRIN2
PSTR: CALL GCI ;GOBBLE THE QUOTE
CALL PRNT ;PRINT UP TO DOUBLE QUOTE
INC HL ;MOVE POINTER PAST DOUBLE QUOTE
LD (TXA),HL
JP PR1
PFORM: LD A,2*FPNIB
LD (INFES),A
CALL GCI ;GOBBLE PREVIOUS CHAR
PFRM1: CALL GCI
LD HL,INFES
CP '%' ;DELIMITER
JP Z,PR1
LD B,80H
CP 'Z' ;TRAILING ZEROS?
JP Z,PF1
LD B,1
CP 'E' ;SCIENTIFIC NOTATION?
JP Z,PF1
CALL NMCHK
JP NC,E1
SUB '0' ;NUMBER OF DECIMAL PLACES
RLCA
LD B,A
LD A,(HL)
AND 301Q
LD (HL),A
PF1: LD A,(HL)
OR B
LD (HL),A
JP PFRM1
PTAB: CALL GCI ;GOBBLE TAB RW
LD B,LPARRW
CALL EATC
CALL EXPRB
LD B,')'
CALL EATC
CALL PFIX
PTAB1: LD A,(PHEAD)
CP E
JP NC,PR1
LD B,' '
CALL CHOUT
JP PTAB1
; "INPUT"
INPUT: CALL GC
CP ','
JP Z,NCRLF
CALL CRLF
INP0: LD B,'?'
CALL CHOUT
LINP: CALL INLINE
LD DE,IBUF
IN1: PUSH DE ;SAVE FOR FPIN
CALL VAR
JP C,E1
POP DE
LD B,0
LD A,(DE)
CP '+' ;LOOK FOR LEADING PLUS OR MINUS ON INPUT
JP Z,IN2
CP '-'
JP NZ,IN3
LD B,1
IN2: INC DE
IN3: PUSH BC
PUSH HL
CALL FPIN ;INPUT FP NUMBER
JP C,INERR
POP HL
DEC HL
POP AF
LD (HL),A
CALL GC
CP ','
RET NZ ;DONE IF NO MORE
CALL GCI ;EAT THE COMMA
LD A,B ;GET THE TERMINATOR TO A
CP ','
JP Z,IN1 ;GET THE NEXT INPUT VALUE FROM STRING
; GET NEW LINE FROM USER
LD B,'?'
CALL CHOUT
JP INP0
NCRLF: CALL GCI
JP LINP ;NOW GET LINE
INERR: LD BC,'IN'
JP ERROR
;
; EVALUATE AN EXPRESSION FROM TEXT
; HL TAKE OP TABLE ADDR OF PREVIOUS OPERATOR (NOT CHANGED)
; RESULT VALUE LEFT ON TOP OF ARG STACK, ARGF LEFT TRUE
;
EXPRB: LD B,0
EXPB1: LD HL,OPBOL
XOR A
LD (RELTYP),A
; ZERO IN B MEANS PRINCIPAL OPERATOR MAY NOT BE RELATIONAL
EXPR: PUSH BC
PUSH HL ;PUSH OPTBA
XOR A
LD (ARGF),A
EXPR1: LD A,(ARGF)
OR A
JP NZ,EXPR2
CALL VAR ;LOOK FOR VARIABLE PERHAPS SUBSCRIPTED
CALL NC,PSHAS
JP NC,EXPR2
CALL CONST
JP NC,EXPR2
CALL GC
CP LPARRW
LD HL,OPLPAR
JP Z,XLPAR
; ISN'T OR SHOULDN'T BE AN ARGUMENT
EXPR2: CALL GC
CP 340Q ;CHECK FOR RESERVED WORD OPERATOR
JP NC,XOP
CP 300Q ;CHECK FOR BUILT IN FUNCTION
JP NC,XBILT
; ILLEGAL EXPRESSION CHARACTER
POP HL ;GET OPTBA
LD A,(ARGF)
OR A
JP Z,E1
XDON1: POP AF
LD HL,RELTYP ;CHECK IF LEGAL PRINCIPAL OPERATOR
CP (HL)
RET Z
JP E1
XOP: AND 37Q ;CLEANS OFF RW BITS
LD HL,(ARGF) ;TEST FOR ARGF TRUE
DEC L
JP Z,XOP1
; ARGF WAS FALSE, UNARY OPS ONLY POSSIBILITY
CP '-'-OPBASE
JP Z,XOPM
CP '+'-OPBASE
JP NZ,E1
CALL GCI ;EAT THE '+'
JP EXPR1
XOPM: LD A,UMINUS-OPBASE
XOP1: CALL OPADR
POP DE ;PREVIOUS OPTBA
LD A,(DE)
CP (HL)
JP NC,XDON1 ;NON-INCREASING PRECEDENCE
; INCREASING PRECEDENCE CASE
PUSH DE ;SAVE PREVIOUS OPTBA
PUSH HL ;SAVE CURRENT OPTBA
CALL GCI ;TO GOBBLE OPERATOR
POP HL
PUSH HL
LD B,0 ;SPECIFY NON-RELATIONAL
CALL EXPR
POP HL
; HL HAS OPTBA ADDRESS
; SET UP ARGS AND PERFORM OPERATION ACTION
XOP2: PUSH HL
LD A,(HL)
LD HL,(ASTKA)
LD B,H
LD C,L
AND 1
JP NZ,XOP21
; DECREMENT STACK POINTER BY ONE VALUE BINARY CASE
LD DE,FPSIZ
ADD HL,DE
LD (ASTKA),HL
LD D,H
LD E,L
XOP21: LD HL,EXPR1
EX (SP),HL ;CHANGE RETURN LINK
INC HL ;SKIP OVER PRECEDENCE
CALL LHLI ;LOAD ACTION ADDRESS
JP (HL)
;
; ACTION ROUTINE CONVENTION
; DE LEFT ARG AND RESULT FOR BINARY
; BC RIGHT ARG FOR BINARY, ARG AND RESULT FOR UNARY
;
; INTRINSIC FUNCTION PROCESSING
;
XBILT: CALL GCI ;EAT TOKEN
AND 77Q ;CLEAN OFF RW BITS
LD HL,(ARGF) ;BUILT IN FUNCTION MUST COME AFTER OPERATOR
DEC L
JP Z,E1
CALL OPADR ;OPTBA TO HL
XLPAR: PUSH HL
LD B,LPARRW
CALL EATC
CALL EXPRB
LD B,')'
CALL EATC
POP HL ;CODE FOR BUILT-IN FUNCTION
JP XOP2
; COMPUTE OPTABLE ADDRESS FOR OPERATOR IN ACC
OPADR: LD C,A
LD B,0
LD HL,OPTAB
ADD HL,BC
ADD HL,BC
ADD HL,BC ;OPTAB ENTRY ADDR IS 3*OP+BASE
RET
;
; PREPROCESSOR, UN-PREPROCESSOR
; PREPROCESS LINE IN IBUF BACK INTO IBUF
; SETS CARRY IF LINE HAS NO LINE NUMBER
; LEAVES CORRECT LENGTH OF LINE AFTER PREPROCESSING IN IBCN
; IF THERE IS A LINE NUMBER, IT IS LOCATED AT IBLN=IBUF-2
; TXA IS CLOBBERED
;
PP: LD HL,IBUF ;FIRST CHARACTER OF INPUT LINE
LD (TXA),HL ;SO GCI WILL WORK
CALL INTGER ;SETS CARRY IF NO LINE NUMBER
LD (IBLN),HL ;STORE LINE NUMBER VALUE(EVEN IF NONE)
PUSH AF ;SAVE STATE OF CARRY BIT FOR RETURNING
LD HL,(TXA) ;ADDRESS OF NEXT CHARACTER IN IBUF
LD C,4 ;SET UP INITIAL VALUE FOR COUNT
LD DE,IBUF ;INITIALIZE WRITE POINTER
; COME HERE TO CONTINUE PREPROCESSING
PPL: PUSH DE
LD DE,RWT ;BASE OF RWT
PPL1: PUSH HL ;SAVE TEXT ADDRESS
LD A,(DE) ;RW VALUE FOR THIS ENTRY IN RWT
LD B,A ;SAVE IN B IN CASE OF MATCH
PPL2: INC DE ;ADVANCE ENTRY POINTER TO NEXT BYTE
LD A,(DE) ;GET NEXT CHARACTER FROM ENTRY
CP (HL) ;COMPARE WITH CHARACTER IN TEXT
JP NZ,PPL3
INC HL ;ADVANCE TEXT POINTER
JP PPL2 ;CONTINUE COMPARISON
; COME HERE WHEN COMPARISON OF BYTE FAILED
PPL3: OR A
JP M,PPL6 ;JUMP IF FOUND MATCH
; SCAN TO BEGINNING ON NEXT ENTRY
PPL4: INC DE ;ADVANCE ENTRY POINTER
LD A,(DE) ;NEXT BYTE IS EITHER CHARACTER OR RW BYTE
OR A
JP P,PPL4 ;KEEP SCANNING IF NOT RW BYTE
; NOW SEE IF AT END OF TABLE, AND FAIL OR RETURN CONDITION
POP HL ;RECOVER ORIGINAL TEXT POINTER
XOR -1 ;CHECK FOR END OF TABLE BYTE
JP NZ,PPL1 ;CONTINUE SCAN OF TABLE
; DIDN'T FIND AN ENTRY AT THE GIVER TEXT ADR
POP DE
LD A,(HL) ;GET THE TEXT CHARACTER
CP CR ;CHECK FOR END OF LINE
JP Z,PPL8 ;GO CLEAN UP AND RETURN
LD (DE),A
INC DE
INC C
INC HL ;ADVANCE TEXT POINTER
CP '"' ;CHECK FOR QUOTED STRING POSSIBILITY
JP NZ,PPL ;RESTART RWT SEARCH AT NEXT CHARACTER POSITION
; HERE WE HAVE A QUOTED STRING, SO EAT TILL ENDQUOTE
PPL5: LD A,(HL) ;NEXT CHARACTER
CP CR
JP Z,PPL8 ;NO STRING ENDQUOTE, LET INTERPRETER WORRY
LD (DE),A
INC DE
INC C
INC HL ;ADVANCE TEXT POINTER
CP '"'
JP Z,PPL ;BEGIN RWT SCAN FROM NEW CHARACTER POSITION
JP PPL5
; FOUND MATCH SO PUT RW VALUE IN TEXT
PPL6: POP AF ;REMOVE UNNEEDED TEST POINTER FROM STACK
POP DE
LD A,B
LD (DE),A
INC DE
INC C
JP PPL
; COME HERE WHEN DONE
PPL8: LD A,CR
LD (DE),A
LD HL,IBCNT ;SET UP COUNT IN CASE LINE OF LINE NUMBER
LD (HL),C
POP AF ;RESTORE CARRY CONDITION (LINE NUMBER FLAG)
RET
;
; UN-PREPROCESS LINE ADDRESSES IN HL TO DE BUFFER
; RETURN SOURCE ADDRESS OF CR IN HL ON RETURN
;
UPPL: INC HL ;SKIP OVER COUNT BYTE
PUSH HL ;SAVE SOURCE TEXT POINTER
CALL LHLI ;LOAD LINE NUMBER VALUE
CALL CNS ;CONVERT LINE NUMBER
LD A,' '
LD (DE),A ;PUT BLANK AFTER LINE NUMBER
INC DE ;INCREMENT DESTINATION POINTER
POP HL
INC HL ;INCREMENT H PAST LINE NUMBER
UPP0: INC HL
LD A,(HL) ;NEXT TOKEN IN SOURCE
OR A
JP M,UPP1 ;JUMP IF TOKEN IS RW
LD (DE),A ;PUT CHARACTER IN BUFFER
CP CR ;CHECK FOR DONE
RET Z
INC DE ;ADVANCE DESTINATION BUFFER ADDRESS
JP UPP0
; COME HERE WHEN RW BYTE DETECTED IN SOURCE
UPP1: PUSH HL ;SAVE SOURCE POINTER
LD HL,RWT ;BASE OF RWT
UPP2: CP (HL) ;SEE IF RW MATCHED RWT ENTRY
INC HL ;ADVANCE RWT POINTER
JP NZ,UPP2 ;CONTINUE LOOKING IF NOT FOUND
; FOUND MATCH, ENTRY POINTER LOCATES FIRST CHARACTER