Home of the original IBM PC emulator for browsers.
[PCjs Machine "ibm5160"]
Waiting for machine "ibm5160" to load....
The BASICAID program will compress a BASIC program (by removing extra
spaces, etc.), expand a program, and generate a cross reference of
BASIC reserved words. The TBASIC program allows the creation and
execution of TINY BASIC programs. TINY BASIC is a limited version of
the BASIC language. Included is an internal TINY BASIC editor.
System Requirements: Some programs require BASIC
How to Start: Type BASICAID or TBASIC and press <ENTER> to start
either program. To read DOC files, enter TYPE filename.ext and press
<ENTER>.
Suggested Registration: $10.00
File Descriptions:
BASICAID BAS BASIC source file for BASICAID.EXE
BASICAID EXE Multi-fuction BASIC programmers utility
BASICAID DOC Documentation for BASICAID.EXE
TBASIC COM TINY BASIC language. A very limited subset of BASIC
TBASIC ASM Source code for TBASIC.COM
BRENTBAS UM BRENTBAS.EXE Users Manual
BRENTBAS EXE A translator from a structured BASIC to Microsoft BASIC
TBASIC DOC Documentation for TBASIC.COM
10 GOTO 280
20 GOTO 24440 ' LAST STATEMENT IN THE PROGRAM
30 '
40 'BASICAID (V2.0) ----------- MAY 7, 1984 10 PM EST
50 '
60 '
70 '
80 'BY JAMES MORGAN
90 ' 1749 AMERICANA BLVD 23-G
100 ' ORLANDO FLA. 32809 WORK PH: (305) - 826-7297
110 '
120 '*********************************************************************
130 ' A LIMITED LICENSE IS GRANTED TO ALL USERS OF THIS PROGRAM
140 ' TO MAKE COPIES OF THIS PROGRAM AND DISTRIBUTE THEM TO OTHERS
150 ' ON THE FOLLOWING CONDITIONS:
160 ' 1. THE LIMITED LICENSE NOTICE , AUTHOR INFO. AND
170 ' COPYRIGHT MESSAGES ARE NOT REMOVED OR ALTERED.
180 '
190 ' 2. NO FEE IS TO BE CHARGED FOR COPYING OR DISTRIBUTING
200 ' THE PROGRAM WITHOUT AN EXPRESSED WRITTEN AGREEMENT
210 ' WITH JAMES MORGAN OR HIS REPRESENTATIVES.
220 '
230 ' Copyright (c) 1983 by JAMES P MORGAN
240 '*********************************************************************
250 '
260 '
270 '
280 CLOSE
290 CLEAR
300 ON ERROR GOTO 0
310 SCREEN 0,0,0
320 WIDTH 80
330 COLOR 7,0
340 KEY OFF
350 OPTION BASE 1
360 DEFINT A-Z
370 TRUE=-1
380 FALSE=0
390 EJECT=0
400 FREE!=0
410 B$=STRING$(255,0)
420 C$=STRING$(255," ")
430 BYTE$=" "
440 P$=STRING$(255," ")
450 S$=STRING$(255," ")
460 T$=STRING$(255," ")
470 H$=STRING$(255," ")
480 SP$=STRING$(255," ")
490 SB$=STRING$(255," ")
500 CURLNUM$=STRING$(255," ")
510 S=0
520 I=0
530 J=0
540 K=0
550 L=0
560 E=0
570 I1=0
580 S1=0
590 SL=0
600 N!=0
610 N#=0
620 TWO.FIFTY.SIX!=256!
630 REMOVE.UNREFERENCED.LINENOS=0
640 SINGLE.PREC!=32768!
650 SINGLE.PREC!=SINGLE.PREC!-1
660 ZERO#=0#
670 NUM.RECS=0
680 REM1$="REM "
690 IF1$="IF "
700 DATA1$="DATA "
710 APOST$=CHR$(39)
720 QUOTE$=CHR$(34)
730 VER$="C" ' CHANGE TO "C" IF PROGRAM COMPILED
740 CR$=CHR$(13)
750 DIM CK$(124)
760 DIM CF$(37)
770 DIM DK$(30)
780 DIM DF$(6)
790 FOR I=1 TO 124
800 READ CK$(I)
810 NEXT
820 FOR I=1 TO 37
830 READ CF$(I)
840 NEXT
850 FOR I=1 TO 30
860 READ DK$(I)
870 NEXT
880 FOR I=1 TO 6
890 READ DF$(I)
900 NEXT
910 DIM EQ$(21)
920 EQ$(1)="BAD FILE NUMBER"
930 EQ$(2)="FILE NOT FOUND"
940 EQ$(3)="BAD FILE MODE"
950 EQ$(4)="FILE ALREADY OPEN"
960 EQ$(6)="DEVICE I/O ERROR"
970 EQ$(7)="FILE ALREADY EXISTS"
980 EQ$(10)="DISK FULL"
990 EQ$(11)="END OF FILE"
1000 EQ$(12)="BAD RECORD NUMBER"
1010 EQ$(13)="BAD FILE NAME"
1020 EQ$(16)="TOO MANY FILES"
1030 EQ$(19)="DISK WRITE PROTECTED"
1040 EQ$(20)="DISK NOT READY"
1050 EQ$(21)="DISK MEDIA ERROR"
1060 DIM ERRMSG$(6)
1070 ERRMSG$(1)="INVALID OR MISSING LINE NUMBER OR BINARY FILE USED AS INPUT"
1080 ERRMSG$(2)="LINE NUMBER WITH NO BASIC STATEMENT"
1090 ERRMSG$(3)="INPUT PROGRAM CONTAINS A BLANK LINE OR ONE WAS GENERATED"
1100 ERRMSG$(4)="LITERAL STRING BOUND IN QUOTES MISSING TERMINATING QUOTE"
1110 ERRMSG$(5)="CURRENT LINE NUMBER NOT GREATER THAN PREVIOUS LINE NUMBER"
1120 ERRMSG$(6)="LINE NUMBER TABLE IS FULL, TOO MANY LOGIC BRANCH REFERENCES"
1130 FREECNT=0
1140 BEEPCNT=3
1150 BEEPLOOP=600
1160 LPRNT=0
1170 GOSUB 14310 'TOGGLE CAPSLOCK ON
1180 GOSUB 11700 'WHAT KIND OF VIDEO ADAPTER
1190 GOSUB 11850 'display Soft-SHARE logo
1200 GOSUB 12120 'REQUEST RUNTIME OPTIONS
1210 START$=""
1220 FINISH$=""
1230 S=1
1240 ROWLINES=10
1250 PAGESIZE=50
1260 FREELMT=10
1270 LINECNT=0
1280 PRVLNUM=-32768!
1290 CURLINE!=0
1300 '
1310 IF RUNTYPE<3 GOTO 1470
1320 IF RUNTYPE>4 GOTO 1470
1330 READ RESCNT
1340 DIM RESWRD$(158) ' RESWRD$(153) FIXED IF COMPILED
1350 DIM WORDFLAG(158) ' WORDFLAG(153) FIXED IF COMPILED
1360 FOR I=1 TO RESCNT
1370 READ RESWRD$(I),WORDFLAG(I)
1380 NEXT
1390 '
1400 DNMCNT=500
1410 IF RUNTYPE=4 THEN DNMCNT=RESCNT
1420 DIM DATANAME$(500) ' DATANAME$(100) FIXED IF COMPILED
1430 FOR X=1 TO DNMCNT
1440 DATANAME$=""
1450 NEXT
1460 '
1470 IF RUNTYPE<2 GOTO 1630
1480 NUMLINES=1
1490 DIMLINE=500
1500 IF RUNTYPE=4 THEN DIMLINE=RESCNT
1510 YCNT=4
1520 IF ACTUAL.RUNTYPE=5 THEN YCNT=4
1530 DIM REF.LINENOS(1,300)
1540 FOR X=1 TO 300
1550 REF.LINENOS(1,X)=-32768!
1560 NEXT
1570 DIM LINENOS(500,4) ' LINENOS(100,50) FIXED IF COMPILED
1580 FOR X=1 TO DIMLINE
1590 LINENOS(X,1)=-32768!
1600 LINENOS(X,2)=0
1610 NEXT
1620 '
1630 CLS
1640 ON ERROR GOTO 0
1650 LOCATE 2,1,1
1660 PRINT "ENTER THE BASIC PROGRAM NAME TO BE PROCESSED"
1670 PRINT
1680 GOSUB 12610 'FLUSH KEYBOARD BUFFERS
1690 INPUT "PROGRAM NAME : ",BASPGM$
1700 IF LEN(BASPGM$)<1 GOTO 1630
1710 IF LEN(BASPGM$)>8 GOTO 1630
1720 LOCATE 5,1,0
1730 FOR I=1 TO 24 - CSRLIN
1740 PRINT STRING$(79," ")
1750 NEXT
1760 GOSUB 1940 'CLEAR 24-25
1770 LOCATE 6,1,1
1780 BEEP
1790 PRINT "WHAT DRIVE IS THE FILE ON, (PRESS ENTER FOR DEFAULT DRIVE)"
1800 PRINT
1810 PRINT "DRIVE : ";
1820 GOSUB 12610 'FLUSH BUFFERS
1830 DRIVE$=INKEY$
1840 IF DRIVE$="" GOTO 1830
1850 IF DRIVE$=CR$ THEN DRIVE$="":GOTO 2010
1860 IF LEN(DRIVE$)>1 GOTO 1720
1870 IF DRIVE$=CHR$(27) GOTO 17570
1880 IF DRIVE$<"A" GOTO 1720
1890 IF DRIVE$>"Z" GOTO 1720
1900 PRINT DRIVE$;
1910 DRIVE$=DRIVE$+":"
1920 GOTO 2010
1930 '
1940 LOCATE 24,1
1950 PRINT STRING$(79," ");
1960 LOCATE 25,1,0
1970 PRINT STRING$(79," ");
1980 LOCATE,,1
1990 RETURN
2000 '
2010 DSN$=DRIVE$+BASPGM$+".BAS"
2020 ON ERROR GOTO 5690
2030 PHASE=1
2040 PRINT
2050 FILES DSN$
2060 GOSUB 20370 'CHECK TYPE STORED PGM
2070 IF READY.TO.RETURN=0 GOTO 17570
2080 IF TYPE.STORED.PGM>252 GOTO 2110
2090 ON ERROR GOTO 0
2100 OPEN DSN$ FOR INPUT AS 1
2110 IF (RUNTYPE=1) OR (ACTUAL.RUNTYPE=5) GOTO 2120 ELSE GOTO 2170
2120 OUTFILE$="TEMPFILE.BAS"
2130 IF RUNTYPE=1 THEN REASON$="EXPANDING PROGRAM" ELSE REASON$="COMPRESSING PROGRAM"
2140 GOSUB 13300 'OPEN OUTPUT FILE
2150 GOTO 2210
2160 '
2170 IF ACTUAL.RUNTYPE>4 GOTO 2210
2180 REASON$="CREATING LINE NUMBER FILE"
2190 GOSUB 13790 'OPEN LINE NO FILE
2200 '
2210 START$=TIME$
2220 LOCATE 25,1,0
2230 PRINT "PROCESSING LINE NUMBER = ";
2240 IF TYPE.STORED.PGM>252 GOTO 2270
2250 IF READY.TO.RETURN=255 GOTO 6140
2260 IF EOF(1) GOTO 6140
2270 GOSUB 2410 ' READ INPUT BASIC PROGRAM
2280 IF LEN.B=0 GOTO 6140
2290 L=LEN.B
2300 GOSUB 5290 ' FIND END OF THE BASIC INPUT LINE
2310 E=BEND
2320 GOSUB 3630 ' ISOLATE LINE NUMBER AND FIND FIRST STATEMENT
2330 IF BEGIN=0 GOTO 2250
2340 'PRINT HEADINGS FOR LINE NUMBER CROSS REFERENCE
2350 GOSUB 11640 ' PRINT LINE NUMBER CURRENTLY PROCESSING
2360 GOSUB 2780 ' SEPARATE LINE INTO ONE OR MORE STATEMENTS
2370 GOTO 2250
2380 '
2390 ' READ THE BASIC PROGRAM TO BE EXPANDED/COMPRESSED/XREFERENCED
2400 '
2410 IF TYPE.STORED.PGM<>255 GOTO 2460
2420 GOSUB 17750 'BUILD ASCII STRING FORM TOKENIZED BASIC PROGAM
2430 IF READY.TO.RETURN GOTO 2510
2440 IF READY.TO.RETURN<>255 GOTO 17570
2450 GOTO 2510
2460 ON ERROR GOTO 2550
2470 LINE INPUT#1,TEMP.B$
2480 ON ERROR GOTO 0
2490 MID$(B$,1)=TEMP.B$
2500 LEN.B=LEN(TEMP.B$)
2510 RETURN
2520 '
2530 ' ERROR HANDLING ROUTINE ON THE INPUT (BASIC PROGRAM)
2540 '
2550 ROW=CSRLIN
2560 COLUMN=POS(0)
2570 GOSUB 5840 'DETERMINE TYPE OF FILE ERROR
2580 RESUME 2590
2590 ON ERROR GOTO 0
2600 GOSUB 1940 'CLEAR 24-25
2610 LOCATE 25,1,1
2620 COLOR 15
2630 PRINT "READ ON BASIC PROGRAM FAILED. ";M$;
2640 M$=" "
2650 LOCATE 24,1
2660 PRINT "CORRECT PROBLEM AND PRESS ANY KEY TO CONTINUE";
2670 GOSUB 12610 'FLUSH BUFFERS
2680 KEYIN$=INKEY$
2690 IF LEN(KEYIN$)=0 GOTO 2680
2700 IF KEYIN$=CHR$(27) GOTO 17570
2710 COLOR 7
2720 GOSUB 1940 'CLEAR 24-25
2730 LOCATE ROW,COLUMN,0
2740 GOTO 2410
2750 '
2760 ' SEPARATE BASIC STATEMENTS INTO ONE OR MORE STATEMENTS
2770 '
2780 S=BEGIN
2790 FOR I=S TO E
2800 MID$(BYTE$,1,1)=MID$(B$,I,1)
2810 IF BYTE$=QUOTE$ GOTO 5550 ' START OF NON-NUMERIC CHAR. STRING FOUND
2820 IF BYTE$="'" GOTO 3430 ' TERMINATING REMARK ON THE LINE
2830 IF BYTE$<>":" GOTO 3290
2840 '
2850 ' A ":" WAS FOUND INDICATING THAT THERE ARE MULTIPLE STATEMENTS ON THIS LINE
2860 '
2870 IF I-S<1 GOTO 3070 ' THROW AWAY ":" THAT ARE NEXT TO EACH OTHER
2880 MID$(P$,1)=MID$(B$,S,I-S)
2890 LEN.P=I-S
2900 IF RUNTYPE=1 GOTO 2930
2910 GOSUB 7260 'ISOLATE DATA NAMES AND LINE NUMBERS
2920 IF (RUNTYPE=1) OR (ACTUAL.RUNTYPE=5) GOTO 2930 ELSE GOTO 2980
2930 GOSUB 4850 'ADD LINE NO TO STATEMENT
2940 IF ACTUAL.RUNTYPE=5 GOTO 2960
2950 IF LPRNT THEN LPRINT MID$(P$,1,LEN.P)
2960 GOSUB 4920 'WRITE A NEW BASIC LINE
2970 LINENO=LINENO + 1
2980 GOSUB 11640 'PRINT CURRENT LINE NO
2990 TEMP.CURLNUM$=STR$(LINENO + SINGLE.PREC!)
3000 ITSLEN=LEN(TEMP.CURLNUM$)-1
3010 MID$(CURLNUM$,1)=RIGHT$(TEMP.CURLNUM$,ITSLEN)
3020 LEN.CURLNUM=ITSLEN
3030 PRVLNUM=LINENO
3040 '
3050 ' THE ":" WAS FOUND, NOW SCAN FOR FIRST NON.BLANK CHAR.
3060 '
3070 S=I+1
3080 IF E-S<1 GOTO 3410 'WE ARE THRU WITH THIS LINE
3090 MID$(BYTE$,1,1)=MID$(B$,S,1)
3100 IF BYTE$<=" " THEN I=S:GOTO 3070
3110 '
3120 ' CHECK IF "REM" OR "IF" STATEMENT IMBEDDED ON THIS LINE
3130 '
3140 IF (BYTE$<>"I") AND (BYTE$<>"R") GOTO 2790
3150 IF BYTE$<>"I" GOTO 3230
3160 MID$(C$,1)=MID$(B$,S,3)
3170 LEN.C=LEN.B-S+1
3180 IF LEN.C>3 THEN LEN.C=3
3190 GOSUB 3460 'CHECK IF "IF"
3200 IF MID$(C$,1,LEN.C)=IF1$ GOTO 3430
3210 GOTO 2790
3220 '
3230 MID$(C$,1)=MID$(B$,S,4)
3240 LEN.C=LEN.B-S+1
3250 IF LEN.C>4 THEN LEN.C=4
3260 GOSUB 4970 'CHECK IF "REM"
3270 IF MID$(C$,1,LEN.C)=REM1$ GOTO 3430
3280 GOTO 2790
3290 NEXT I
3300 '
3310 MID$(P$,1)=MID$(B$,S,I-S)
3320 LEN.P=I-S
3330 IF RUNTYPE=1 GOTO 3360
3340 GOSUB 7260 'ISOLATE DATA NAMES AND LINE NUMBERS
3350 IF (RUNTYPE=1) OR (ACTUAL.RUNTYPE=5) GOTO 3360 ELSE GOTO 3400
3360 GOSUB 4850 'ADD LINE NO TO STATEMENT
3370 IF ACTUAL.RUNTYPE=5 GOTO 3390
3380 IF LPRNT THEN LPRINT MID$(P$,1,LEN.P)
3390 GOSUB 4920 ' WRITE THE NEW BASIC LINE
3400 GOSUB 11640 'PRINT CURRENT LINE NO.
3410 RETURN
3420 '
3430 I=E+1
3440 GOTO 3310
3450 '
3460 IF LEN.C<2 THEN RETURN
3470 IF MID$(C$,1,2)<>"IF" THEN RETURN
3480 IF LEN.C<3 THEN RETURN
3490 IF MID$(C$,3,1)=" " THEN RETURN
3500 IF MID$(C$,3,1)="." THEN RETURN
3510 IF ASC(MID$(C$,3,1))<48 GOTO 3560
3520 IF ASC(MID$(C$,3,1))>90 GOTO 3560
3530 IF (ASC(MID$(C$,3,1))>57) AND (ASC(MID$(C$,3,1))<65) GOTO 3560
3540 RETURN
3550 '
3560 MID$(C$,1)="IF "
3570 LEN.C=3
3580 RETURN
3590 '
3600 ' ISOLATE LINE NUMBER AND FIND START OF BASIC STATEMENT(S)
3610 '
3620 ' FIND THE FIRST NON-BLANK CHAR.
3630 BEGIN=0
3640 MID$(CURLNUM$,1)=STRING$(6," ")
3650 FOR I=1 TO E
3660 MID$(BYTE$,1,1)=MID$(B$,I,1)
3670 IF BYTE$>" " GOTO 3690
3680 NEXT I
3690 S=I
3700 MID$(P$,1)=STRING$(255," ")
3710 LEN.P=0
3720 '
3730 ' SCAN UNTIL FIRST NON-NUMERIC CHAR (BUILDING LINE NUMBER)
3740 '
3750 FOR I=S TO E
3760 MID$(BYTE$,1,1)=MID$(B$,I,1)
3770 IF BYTE$<"0" GOTO 3830
3780 IF BYTE$>"9" GOTO 3830
3790 LEN.P=LEN.P+1
3800 MID$(P$,LEN.P,1)=BYTE$
3810 NEXT I
3820 ' DO WE HAVE A INVALID LINE NUMBER
3830 IF I=E THEN ERRNO=1:GOTO 5470
3840 IF LEN.P>5 THEN ERRNO=1:GOTO 5470
3850 IF LEN.P>0 GOTO 3950
3860 '
3870 ' UNNUBMBERED BASIC STATEMENT, SUPPLY A LINE NO.
3880 '
3890 CURLINE!=PRVLNUM+32767+ZERO#+1
3900 IF CURLINE!=0 THEN CURLINE!=1
3910 TEMP.CURLNUM$=STR$(CURLINE!)
3920 ITSLEN=LEN(TEMP.CURLNUM$)-1
3930 LEN.P=ITSLEN
3940 MID$(P$,1)=RIGHT$(TEMP.CURLNUM$,ITSLEN)
3950 MID$(CURLNUM$,1)=STRING$(6," ")
3960 MID$(CURLNUM$,1)=MID$(P$,1,LEN.P)
3970 LEN.CURLNUM=LEN.P
3980 CURLINE!=VAL(MID$(CURLNUM$,1,LEN.CURLNUM))
3990 LINENO=CURLINE! - 32767
4000 IF (RUNTYPE=1) OR (ACTUAL.RUNTYPE=5) THEN GOTO 4010 ELSE GOTO 4020
4010 IF LINENO<=PRVLNUM THEN ERRNO=5:GOTO 5470
4020 PRVLNUM=LINENO
4030 '
4040 ' SCAN UNTIL WE FIND THE FIRST NON-BLANK CHAR (FIND FIRST BASIC STATEMENT)
4050 '
4060 S=I
4070 FOR I=S TO E
4080 MID$(BYTE$,1,1)=MID$(B$,I,1)
4090 IF BYTE$>" " GOTO 4120
4100 NEXT I
4110 IF I=E THEN ERRNO=2:GOTO 5470
4120 BEGIN=I
4130 IF BYTE$=":" GOTO 4680 ' REMOVE ALL LEADING ":"
4140 IF BYTE$="'" GOTO 4710 ' THIS MUST BE A COMMENT STATEMENT
4150 '
4160 ' CHECK IF THE LINE BEGINS AS A "REM" OR "DATA" OR "IF" STATEMENT
4170 '
4180 IF (BYTE$<>"R") AND (BYTE$<>"D") AND (BYTE$<>"I") THEN RETURN
4190 IF BYTE$<>"R" GOTO 4270
4200 MID$(C$,1)=MID$(B$,I,4)
4210 LEN.C=LEN.B-I+1
4220 IF LEN.C>4 THEN LEN.C=4
4230 GOSUB 4970 'CHECK IF "REM"
4240 IF MID$(C$,1,LEN.C)=REM1$ GOTO 4710
4250 RETURN
4260 '
4270 IF BYTE$<>"I" GOTO 4350
4280 MID$(C$,1)=MID$(B$,I,3)
4290 LEN.C=LEN.B-I+1
4300 IF LEN.C>3 THEN LEN.C=3
4310 GOSUB 3460 'CHECK IF "IF"
4320 IF MID$(C$,1,LEN.C)=IF1$ GOTO 4710
4330 RETURN
4340 '
4350 MID$(C$,1)=MID$(B$,I,5)
4360 LEN.C=LEN.B-I+1
4370 IF LEN.C>5 THEN LEN.C=5
4380 GOSUB 5120 'CHECK IF "DATA"
4390 IF MID$(C$,1,LEN.C)<>DATA1$ THEN RETURN
4400 DATA.INX=I
4410 GOSUB 4450 'CHECK IF ONLY "DATA" ON THIS STATEMENT
4420 IF DATA.SINGLE GOTO 4710
4430 RETURN
4440 '
4450 DATA.SINGLE=-1
4460 FOR DATA.INX=DATA.INX TO E
4470 MID$(BYTE$,1,1)=MID$(B$,DATA.INX,1)
4480 IF BYTE$=QUOTE$ THEN GOSUB 4620:GOTO 4460
4490 IF BYTE$=":" GOTO 4530
4500 NEXT DATA.INX
4510 RETURN
4520 '
4530 DATA.INX=DATA.INX+1
4540 IF DATA.INX>E THEN RETURN
4550 MID$(BYTE$,1,1)=MID$(B$,DATA.INX,1)
4560 IF BYTE$=":" THEN MID$(B$,DATA.INX,1)=" ":GOTO 4530
4570 IF BYTE$="'" THEN RETURN
4580 IF BYTE$>" " THEN DATA.SINGLE=0:RETURN
4590 MID$(B$,DATA.INX,1)=" "
4600 GOTO 4530
4610 '
4620 DATA.INX=DATA.INX+1
4630 IF DATA.INX>E THEN RETURN
4640 MID$(BYTE$,1,1)=MID$(B$,DATA.INX,1)
4650 IF BYTE$=QUOTE$ THEN DATA.INX=DATA.INX+1:RETURN
4660 GOTO 4620
4670 '
4680 MID$(B$,I,1)=" "
4690 GOTO 4060
4700 '
4710 BEGIN=0
4720 S=I
4730 MID$(P$,1)=MID$(B$,S)
4740 LEN.P=LEN.B-S+1
4750 IF RUNTYPE=1 GOTO 4780
4760 GOSUB 7260 'ISOLATE DATA NAMES AND LINE NUMBERS
4770 IF (RUNTYPE=1) OR (ACTUAL.RUNTYPE=5) THEN GOTO 4780 ELSE GOTO 4820
4780 GOSUB 4850 'ADD LINE NO TO STATEMENT
4790 IF ACTUAL.RUNTYPE=5 GOTO 4810
4800 IF LPRNT THEN LPRINT MID$(P$,1,LEN.P)
4810 GOSUB 4920 ' CREATE (WRITE) THE NEW BASIC LINE
4820 GOSUB 11640 'PRINT CURRENT LINE NO
4830 RETURN
4840 '
4850 LEN.P=LEN.P+LEN.CURLNUM+1
4860 MID$(P$,LEN.CURLNUM+2)=MID$(P$,1)
4870 MID$(P$,1,LEN.CURLNUM+1)=MID$(CURLNUM$,1,LEN.CURLNUM+1)
4880 RETURN
4890 '
4900 ' CREATE (WRITE) THE NEW BASIC LINE(S)
4910 '
4920 ON ERROR GOTO 5910
4930 PRINT#2,MID$(P$,1,LEN.P)
4940 ON ERROR GOTO 0
4950 RETURN
4960 '
4970 IF LEN.C<3 THEN RETURN
4980 GOSUB 5390 'CONVERT TO UPPER CASE
4990 IF MID$(C$,1,3)<>"REM" THEN RETURN
5000 IF LEN.C=3 GOTO 5080
5010 IF MID$(C$,4,1)=" " THEN RETURN
5020 IF MID$(C$,4,1)="." THEN RETURN
5030 IF ASC(MID$(C$,4,1))<48 GOTO 5080
5040 IF ASC(MID$(C$,4,1))>90 GOTO 5080
5050 IF (ASC(MID$(C$,4,1))>57) AND (ASC(MID$(C$,4,1))<65) GOTO 5080
5060 RETURN
5070 '
5080 MID$(C$,1)="REM "
5090 LEN.C=4
5100 RETURN
5110 '
5120 IF LEN.C<4 THEN RETURN
5130 GOSUB 5390 'CONVERT TO UPPER CASE
5140 IF MID$(C$,1,4)<>"DATA" THEN RETURN
5150 IF LEN.C=4 GOTO 5230
5160 IF MID$(C$,5,1)=" " THEN RETURN
5170 IF MID$(C$,5,1)="." THEN RETURN
5180 IF ASC(MID$(C$,5,1))<48 GOTO 5230
5190 IF ASC(MID$(C$,5,1))>90 GOTO 5230
5200 IF (ASC(MID$(C$,5,1))>57) AND (ASC(MID$(C$,5,1))<65) GOTO 5230
5210 RETURN
5220 '
5230 MID$(C$,1)="DATA "
5240 LEN.C=5
5250 RETURN
5260 '
5270 ' FIND TRUE END OF A STATEMENT LINE
5280 '
5290 GOSUB 16990 'CHECK FOR DOUBLE QUOTES, ALSO COMPRESS INPUT LINE
5300 FOR I=L TO 1 STEP -1 ' START AT END OF THE LINE
5310 MID$(BYTE$,1,1)=MID$(B$,I,1)
5320 IF BYTE$<>" " GOTO 5340
5330 NEXT I
5340 IF I=1 THEN ERRNO=3:GOTO 5470
5350 L=I
5360 BEND=I
5370 RETURN
5380 '
5390 IF TYPE.STORED.PGM >252 THEN RETURN
5400 FOR J=1 TO LEN.C
5410 MID$(C$,J,1)=CHR$(ASC(MID$(C$,J,1)) AND 95)
5420 NEXT
5430 RETURN
5440 '
5450 ' ALMOST ALL ERRORS DETECTED WHILE SCANNING PROGRAM SHOULD COME TO HERE
5460 '
5470 PRINT
5480 PRINT "error - check logic or data"
5490 PRINT
5500 PRINT ERRMSG$(ERRNO)
5510 GOTO 17570
5520 '
5530 ' SCAN OVER STRING LITERALS BOUND IN QUOTES
5540 '
5550 K=I+1
5560 FOR J=K TO E
5570 MID$(BYTE$,1,1)=MID$(B$,J,1)
5580 IF BYTE$=QUOTE$ GOTO 5660
5590 NEXT J
5600 '
5610 PRINT
5620 PRINT "PROGRAM TRAP REACHED"
5630 STOP
5640 END
5650 '
5660 I=J
5670 GOTO 3290
5680 '
5690 PRINT
5700 PRINT "** ERROR ";ERR;" ACCESSING ";DSN$
5710 IF ERR=53 THEN PRINT DSN$;" NOT ON DISKETTE"
5720 RESUME 5730
5730 ON ERROR GOTO 0
5740 PRINT
5750 PRINT "PRESS ANY KEY TO CONTINUE"
5760 GOSUB 12610 'FLUSH BUFFERS
5770 KEYIN$=INKEY$
5780 IF KEYIN$="" GOTO 5770
5790 IF KEYIN$=CHR$(27) GOTO 17570
5800 GOTO 1630
5810 '
5820 ' WHAT TYPE OF BASIC ERROR WAS FOUND, MOSTLY CONCERNED WITH FILE ERRORS
5830 '
5840 IF ERR<52 THEN M$="":GOTO 5860
5850 M$=EQ$(ERR-51)
5860 IF M$="" THEN M$="BASIC ERROR "+STR$(ERR)
5870 RETURN
5880 '
5890 ' ERROR HANDLING ROUTINES FOR THE OUTPUT BASIC PROGRAM
5900 '
5910 ROW=CSRLIN
5920 COLUMN=POS(0)
5930 GOSUB 5840 'GET TYPE ERR
5940 RESUME 5950
5950 ON ERROR GOTO 0
5960 GOSUB 1940 'CLEAR 24-25
5970 LOCATE 25,1,1
5980 COLOR 15
5990 PRINT "EXPANDED PROGRAM WRITE FAILED. ";M$;
6000 M$=" "
6010 LOCATE 24,1
6020 PRINT "CORRECT PROBLEM AND PRESS ANY KEY TO CONTINUE";
6030 GOSUB 12610 'FLUSH BUFFERS
6040 KEYIN$=INKEY$
6050 IF LEN(KEYIN$)=0 GOTO 6040
6060 IF KEYIN$=CHR$(27) GOTO 17570
6070 COLOR 7
6080 GOSUB 1940 'CLEAR 24-25
6090 LOCATE ROW,COLUMN,0
6100 GOTO 4920
6110 '
6120 ' END-OF-FILE ROUTINES
6130 '
6140 CLS
6150 IF RUNTYPE<>2 GOTO 6300
6160 GOSUB 10010 ' SORT THE LINE NUMBER REFERENCES
6170 IF ACTUAL.RUNTYPE=5 GOTO 6370
6180 GOSUB 10610 ' PRINT HEADINGS FOR LINE NUMBER REFERENCES
6190 FOR X=1 TO NUMLINES
6200 IF LINENOS(X,1)=-32768! GOTO 6220
6210 GOSUB 6550 ' PRINT LINE NUMBER REFERENCES
6220 NEXT
6230 FOR I=1 TO 2
6240 LPRINT
6250 NEXT
6260 LPRINT "NOTE: LINE NUMBER APPLIES TO ANY line-number REFERENCED BY A :"
6270 LPRINT
6280 LPRINT " GOTO, GOSUB, RESUME, RESTORE, RETURN, RUN, THEN, ELSE OR ERL STATEMENT"
6290 LPRINT
6300 IF RUNTYPE<3 GOTO 6370
6310 GOSUB 11060 ' SORT THE DATA NAME TABLE
6320 GOSUB 11440 ' PRINT THE LISTING HEADINGS
6330 FOR X=1 TO NUMLINES
6340 IF DATANAME$(X)="" GOTO 6360
6350 GOSUB 6550 ' PRINT THE LINE NUMBER REFERENCES
6360 NEXT
6370 PRINT
6380 FINISH$=TIME$
6390 PRINT "PROGRAM START TIME = ";START$
6400 PRINT "PROGRAM FINISH TIME = ";FINISH$
6410 PRINT DSN$;" SUCCESSFULLY PROCESSED..."
6420 PRINT
6430 IF ACTUAL.RUNTYPE=5 GOTO 14410
6440 GOSUB 6470 'RESET PRINTER
6450 GOTO 17570
6460 '
6470 IF EJECT=0 GOTO 6500
6480 LPRINT CHR$(18) + CHR$(12)
6490 WIDTH "LPT1:",80
6500 RETURN
6510 '
6520 '
6530 ' PRINT LINE NUMBER REFERENCES
6540 '
6550 TOCNT=0
6560 REF.LINENOS(1,1)=LINENOS(X,1)
6570 REF.LINENOS(1,2)=0
6580 REF.LINENOS(1,3)=LINENOS(X,3)
6590 GOSUB 6900
6600 TOCNT=REF.LINENOS(1,2)
6610 TABPOS=3
6620 IF RUNTYPE=2 GOTO 6660
6630 IF LINECNT>PAGESIZE THEN GOSUB 11440
6640 GOTO 6670
6650 '
6660 IF LINECNT>PAGESIZE THEN GOSUB 10610
6670 LPRINT
6680 IF RUNTYPE=2 GOTO 6730
6690 LPRINT DATANAME$(X)
6700 LINECNT=LINECNT + 1
6710 GOTO 6750
6720 '
6730 CURLINE!=REF.LINENOS(1,1) + SINGLE.PREC!
6740 LPRINT CURLINE!;
6750 TABPOS=20
6760 L=1
6770 FOR I=1 TO ROWLINES
6780 CURLINE!=REF.LINENOS(1,L+3) + SINGLE.PREC!
6790 LPRINT TAB(TABPOS) CURLINE!;
6800 L=L + 1
6810 IF L>TOCNT GOTO 6840
6820 TABPOS=TABPOS + 8
6830 NEXT I
6840 TABPOS=20
6850 LPRINT
6860 LINECNT=LINECNT + 2
6870 IF L<=TOCNT GOTO 6770
6880 RETURN
6890 '
6900 SEARCH.LINENO=LINENOS(X,1)
6910 FOR SRCH.INX1=1 TO NUM.RECS
6920 ON ERROR GOTO 10370
6930 IO.ADDR=6
6940 GET #3,SRCH.INX1
6950 ON ERROR GOTO 0
6960 X1=CVI(DSK.LINETO$)
6970 X2=CVI(DSK.LINENO$)
6980 IF X1<>SEARCH.LINENO GOTO 7030
6990 IF TOCNT=0 GOTO 7010
7000 IF X2=REF.LINENOS(1,TOCNT+3) GOTO 7030
7010 TOCNT=TOCNT+1
7020 REF.LINENOS(1,TOCNT+3)=X2
7030 NEXT
7040 REF.LINENOS(1,2)=TOCNT
7050 GOSUB 7080
7060 RETURN
7070 '
7080 IF TOCNT=1 THEN RETURN
7090 LAST=TOCNT
7100 GAP=LAST\2
7110 WHILE GAP>0
7120 FOR I=GAP+1 TO LAST
7130 J=I-GAP
7140 WHILE J>0
7150 IF REF.LINENOS(1,J+3)<=REF.LINENOS(1,J+GAP+3) THEN J=0:GOTO 7180
7160 SWAP REF.LINENOS(1,J+3),REF.LINENOS(1,J+GAP+3)
7170 J=J-GAP
7180 WEND
7190 NEXT
7200 GAP=GAP\2
7210 WEND
7220 RETURN
7230 '
7240 ' ISOLATE DATANAMES/RESERVED WORDS AND LINE NUMBERS
7250 '
7260 MID$(SP$,1)=MID$(P$,1,LEN.P)
7270 LEN.SP=LEN.P
7280 SL=LEN.SP
7290 IF MID$(SP$,1,1)="'" GOTO 7510
7300 GOSUB 7610 'CHECK IF "REM"
7310 IF MID$(SP$,1,4)=REM1$ GOTO 7510
7320 GOSUB 7760 'CHECK IF "IF"
7330 IF MID$(SP$,1,5)=DATA1$ GOTO 7560
7340 GOSUB 7930 'REMOVE STRING LITERALS
7350 FOR I1=1 TO SL
7360 V=ASC(MID$(SP$,I1,1))
7370 IF V=46 GOTO 7460 ' "."
7380 IF V=38 GOTO 7460 ' "&"
7390 IF V<48 GOTO 7450 ' "0"
7400 IF V>90 GOTO 7450 ' "Z"
7410 IF V>64 GOTO 7460 ' "@"
7420 IF V>57 GOTO 7450 ' "9"
7430 GOTO 7460
7440 '
7450 MID$(SP$,I1,1)=" "
7460 NEXT I1
7470 GOSUB 8180 'FIND END OF LINE
7480 GOSUB 8270 'PARSE OUT RESERVED WORD/LINE NOS/DATA NAMES
7490 RETURN
7500 '
7510 MID$(SP$,1,4)="REM"
7520 LEN.SP=3
7530 SL=LEN.SP
7540 GOTO 7480
7550 '
7560 MID$(SP$,1,4)="DATA"
7570 LEN.SP=4
7580 SL=LEN.SP
7590 GOTO 7480
7600 '
7610 IF LEN.SP<3 THEN RETURN
7620 IF MID$(SP$,1,3)<>"REM" THEN RETURN
7630 IF LEN.SP=3 GOTO 7710
7640 IF MID$(SP$,4,1)=" " THEN RETURN
7650 IF MID$(SP$,4,1)="." THEN RETURN
7660 IF ASC(MID$(SP$,4,1))<48 GOTO 7710
7670 IF ASC(MID$(SP$,4,1))>90 GOTO 7710
7680 IF (ASC(MID$(SP$,4,1))>57) AND (ASC(MID$(SP$,4,1))<65) GOTO 7710
7690 RETURN
7700 '
7710 MID$(SP$,1)="REM "
7720 LEN.SP=4
7730 SL=LEN.SP
7740 RETURN
7750 '
7760 IF LEN.SP<4 THEN RETURN
7770 IF MID$(SP$,1,4)<>"DATA" THEN RETURN
7780 IF LEN.SP=4 GOTO 7860
7790 IF MID$(SP$,5,1)=" " THEN RETURN
7800 IF MID$(SP$,5,1)="." THEN RETURN
7810 IF ASC(MID$(SP$,5,1))<48 GOTO 7860
7820 IF ASC(MID$(SP$,5,1))>90 GOTO 7860
7830 IF (ASC(MID$(SP$,5,1))>57) AND (ASC(MID$(SP$,5,1))<65) GOTO 7860
7840 RETURN
7850 '
7860 MID$(SP$,1)="DATA "
7870 LEN.SP=5
7880 SL=LEN.SP
7890 RETURN
7900 '
7910 ' REMOVE STRING LITERALS BOUND IN QUOTES AND COMMENTS
7920 '
7930 S1=1
7940 FOR I1=S1 TO SL
7950 MID$(BYTE$,1,1)=MID$(SP$,I1,1)
7960 IF BYTE$=QUOTE$ GOTO 8010
7970 IF BYTE$="'" GOTO 8130
7980 NEXT I1
7990 GOTO 8180
8000 '
8010 MID$(SP$,I1,1)=" "
8020 FOR I1=I1 TO SL
8030 MID$(BYTE$,1,1)=MID$(SP$,I1,1)
8040 IF BYTE$=QUOTE$ GOTO 8090
8050 MID$(SP$,I1,1)=" "
8060 NEXT I1
8070 GOTO 8180
8080 '
8090 MID$(SP$,I1,1)=" "
8100 S1=I1
8110 GOTO 7940
8120 '
8130 MID$(SP$,I1,1)=" "
8140 MID$(SP$,1)=MID$(SP$,1,I1)
8150 LEN.SP=I1
8160 SL=LEN.SP
8170 '
8180 FOR I1=SL TO 1 STEP -1
8190 MID$(BYTE$,1,1)=MID$(SP$,I1,1)
8200 IF BYTE$<>" " GOTO 8220
8210 NEXT I1
8220 MID$(SP$,1)=MID$(SP$,1,I1)
8230 LEN.SP=I1
8240 SL=LEN.SP
8250 RETURN
8260 '
8270 S1=1
8280 GOSUB 8770 'GET A WORD
8290 IF LEN.C=0 GOTO 8370
8300 IF C$<"A" GOTO 8280
8310 IF RUNTYPE=2 GOTO 8610
8320 GOSUB 8410 'BINARY SEARCH OF RESERVED WORD TABLE
8330 IF FOUND=1 GOTO 8610
8340 IF RUNTYPE<>3 GOTO 8280
8350 GOSUB 9190 'ADD DATANAMES/LINENOS TO THEIR TABLES
8360 GOTO 8280
8370 RETURN
8380 '
8390 ' BINARY SEARCH OF RESERVED WORD TABLE
8400 '
8410 FOUND=0
8420 LOW!=1
8430 HIGH!=RESCNT
8440 HALF=FIX((HIGH!/2) + .5)
8450 NOW=HALF
8460 IF MID$(C$,1,LEN.C)=RESWRD$(NOW) GOTO 8580
8470 IF MID$(C$,1,LEN.C)<RESWRD$(NOW) GOTO 8550
8480 LOW!=NOW + 1
8490 IF LOW!>HIGH! GOTO 8590
8500 IF HIGH!<LOW! GOTO 8590
8510 NUW=FIX((HIGH!-LOW!)/2! + .5)
8520 NOW=NUW+LOW!
8530 GOTO 8460
8540 '
8550 HIGH!=NOW - 1
8560 GOTO 8490
8570 '
8580 FOUND=1
8590 RETURN
8600 '
8610 IF MID$(C$,1,LEN.C)="GOTO" GOTO 9050
8620 IF MID$(C$,1,LEN.C)="GOSUB" GOTO 9050
8630 IF MID$(C$,1,LEN.C)="RESUME" GOTO 8930
8640 IF MID$(C$,1,LEN.C)="THEN" GOTO 8930
8650 IF MID$(C$,1,LEN.C)="ELSE" GOTO 8930
8660 IF MID$(C$,1,LEN.C)="ERL" GOTO 8930
8670 IF MID$(C$,1,LEN.C)="RESTORE" GOTO 8930
8680 IF MID$(C$,1,LEN.C)="RETURN" GOTO 8930
8690 IF MID$(C$,1,LEN.C)="RUN" GOTO 8930
8700 IF RUNTYPE<>4 GOTO 8280
8710 IF WORDFLAG(NOW)=0 GOTO 8280
8720 GOSUB 9190 'ADD TO TABLE
8730 GOTO 8280
8740 '
8750 ' GET A WORD
8760 '
8770 MID$(C$,1)=STRING$(255," ")
8780 LEN.C=0
8790 FOR I1=S1 TO SL
8800 MID$(BYTE$,1,1)=MID$(SP$,I1,1)
8810 IF BYTE$<>" " GOTO 8830
8820 NEXT I1
8830 MID$(C$,1)=STRING$(255," ")
8840 LEN.C=0
8850 FOR I1=I1 TO SL
8860 IF MID$(SP$,I1,1)=" " GOTO 8900
8870 LEN.C=LEN.C+1
8880 MID$(C$,LEN.C,1)=MID$(SP$,I1,1)
8890 NEXT I1
8900 S1=I1
8910 RETURN
8920 '
8930 IF RUNTYPE<>4 GOTO 8960
8940 IF WORDFLAG(NOW)=0 GOTO 8960
8950 GOSUB 9190 'ADD TO TABLE
8960 S1=I1
8970 IF RUNTYPE<>2 GOTO 8280
8980 GOSUB 8770 'GET A WORD
8990 IF LEN.C=0 GOTO 9030
9000 IF ASC(C$)>64 GOTO 8310
9010 GOSUB 9190 'ADD TO TABLE
9020 GOTO 8280
9030 RETURN
9040 '
9050 IF RUNTYPE<>4 GOTO 9080
9060 IF WORDFLAG(NOW)=0 GOTO 9080
9070 GOSUB 9190 'ADD TO TABLE
9080 S1=I1
9090 IF RUNTYPE<>2 GOTO 8280
9100 GOSUB 8770 'GET A WORD
9110 IF LEN.C=0 GOTO 9150
9120 IF ASC(C$)>64 GOTO 8310
9130 GOSUB 9190 'ADD TO TABLE
9140 GOTO 9100
9150 RETURN
9160 '
9170 ' ADD DATENAMES AND/OR LINE NUMBERS TO THEIR RESPECTIVE TABLES
9180 '
9190 IF RUNTYPE<>4 GOTO 9260
9200 X=NOW
9210 DATANAME$(X)=MID$(C$,1,LEN.C)
9220 NUMLINES=RESCNT
9230 LINETO=X-SINGLE.PREC!
9240 GOTO 9470
9250 '
9260 IF RUNTYPE<>2 GOTO 9370
9270 LINETO=VAL(MID$(C$,1,LEN.C)) - SINGLE.PREC!
9280 FOR X=1 TO DIMLINE
9290 IF LINENOS(X,1)=LINETO GOTO 9350
9300 IF LINENOS(X,1)=-32768! GOTO 9340
9310 NEXT X
9320 GOTO 9960
9330 '
9340 NUMLINES=X
9350 GOTO 9470
9360 '
9370 IF RUNTYPE<>3 GOTO 5470
9380 FOR X=1 TO DNMCNT
9390 IF DATANAME$(X)="" GOTO 9440
9400 IF DATANAME$(X)=MID$(C$,1,LEN.C) GOTO 9460
9410 NEXT X
9420 GOTO 9960
9430 '
9440 DATANAME$(X)=MID$(C$,1,LEN.C)
9450 NUMLINES=X
9460 LINETO=X-SINGLE.PREC!
9470 LINENOS(X,1)=LINETO
9480 LINENOS(X,3)=X
9490 Z=LINENOS(X,2)
9500 IF Z=1 AND ACTUAL.RUNTYPE=5 GOTO 9560
9510 IF LINENOS(X,4)=LINENO GOTO 9560
9520 LINENOS(X,4)=LINENO
9530 LINENOS(X,2)=LINENOS(X,2) + 1
9540 IF ACTUAL.RUNTYPE=5 GOTO 9560
9550 GOSUB 9580 'WRITE LINE NO FILE RECORD
9560 RETURN
9570 '
9580 GOSUB 9680 'CHECK LINE NO FILE STATUS
9590 LSET DSK.LINETO$=MKI$(LINETO)
9600 LSET DSK.LINENO$=MKI$(LINENO)
9610 NUM.RECS=NUM.RECS+1
9620 ON ERROR GOTO 10370
9630 IO.ADDR=1
9640 PUT #3,NUM.RECS
9650 ON ERROR GOTO 0
9660 RETURN
9670 '
9680 IF LINENOS.XRF.OPEN.STATUS=-1 THEN RETURN
9690 LINENOS.XRF.OPEN.STATUS=-1
9700 M$=""
9710 ON ERROR GOTO 9780
9720 LINENO.FILE$=LINEDRIVE$+"LINENOS.XRF"
9730 OPEN LINENO.FILE$ AS #3 LEN=4
9740 FIELD #3,2 AS DSK.LINETO$,2 AS DSK.LINENO$
9750 ON ERROR GOTO 0
9760 RETURN
9770 '
9780 GOSUB 5840 'GET TYPE ERR
9790 RESUME 9800
9800 ON ERROR GOTO 0
9810 LINENOS.XRF.OPEN.STATUS=0
9820 GOSUB 1940 'CLEAR 24-25
9830 LOCATE 25,1,1
9840 COLOR 15
9850 PRINT REASON$;" OPEN ON ";"LINENOS.XRF";" FAILED. ";M$;
9860 LOCATE 24,1
9870 PRINT "CORRECT PROBLEM AND PRESS ANY KEY TO CONTINUE";
9880 GOSUB 12610 'FLUSH BUFFERS
9890 KEYIN$=INKEY$
9900 IF KEYIN$="" GOTO 9890
9910 IF KEYIN$=CHR$(27) GOTO 17570
9920 GOSUB 1940 'CLEAR 24-25
9930 LOCATE ROW,COLUMN,0
9940 GOTO 9750
9950 '
9960 ERRNO=6
9970 GOTO 5470
9980 '
9990 ' SORT LINE NUMBER TABLE
10000 '
10010 PRINT "START - LINE NUMBER TABLE SORT : ";TIME$
10020 GOSUB 11780 'GET YOUR ATTN.
10030 ROW=CSRLIN
10040 COLUMN=POS(0)
10050 LOCATE 25,1,0
10060 PRINT STRING$(79," ");
10070 LOCATE 25,1,0
10080 PRINT "** SORTING";
10090 LAST=NUMLINES
10100 GAP=LAST\2
10110 WHILE GAP>0
10120 FOR I=GAP+1 TO LAST
10130 J=I-GAP
10140 WHILE J>0
10150 IF LINENOS(J,1)<=LINENOS(J+GAP,1) THEN J=0:GOTO 10200
10160 SWAP LINENOS(J,1),LINENOS(J+GAP,1)
10170 SWAP LINENOS(J,2),LINENOS(J+GAP,2)
10180 SWAP LINENOS(J,3),LINENOS(J+GAP,3)
10190 J=J-GAP
10200 WEND
10210 LOCATE 25,1,0
10220 PRINT " ";
10230 LOCATE 25,1,0
10240 PRINT "** SORTING";
10250 NEXT
10260 GAP=GAP\2
10270 WEND
10280 LOCATE 25,1,0
10290 PRINT STRING$(79," ");
10300 LOCATE ROW,COLUMN,1
10310 PRINT
10320 PRINT "FINISH- LINE NUMBER TABLE SORT : ";TIME$
10330 GOSUB 11780 'GET YOUR ATTN.
10340 PRINT
10350 RETURN
10360 '
10370 ROW=CSRLIN
10380 COLUMN=POS(0)
10390 GOSUB 5840 'GET TYPE RR
10400 RESUME 10410
10410 GOSUB 1940 'CLEAR 24-25
10420 LOCATE 25,1,1
10430 COLOR 15
10440 PRINT "INPUT/OUTPUT ERROR ON FILE :";LINENOS.FILE$;" : ";M$;
10450 M$=" "
10460 LOCATE 24,1
10470 PRINT "CORRECT PROBLEM AND PRESS ANY KEY TO CONTINUE";
10480 GOSUB 12610 'FLUSH BUFFERS
10490 KEYIN$=INKEY$
10500 IF KEYIN$="" GOTO 10490
10510 IF KEYIN$=CHR$(27) GOTO 17570
10520 COLOR 7
10530 GOSUB 1940 'CLEAR 24-25
10540 LOCATE ROW,COLUMN,0
10550 IF IO.ADDR=1 GOTO 9640
10560 IF IO.ADDR=6 GOTO 6940
10570 PRINT "PROGRAM TRAP REACHED - RANDOM IO ROUTINES"
10580 STOP
10590 END
10600 '
10610 LPRINT.STRING$=CHR$(13)+CHR$(12)
10620 GOSUB 10790 'PRINT THE STRING
10630 LPRINT.STRING$="PROGRAM : "+DSN$+SPACE$(75)+DATE$+" @ "+TIME$
10640 GOSUB 10790
10650 LPRINT.STRING$=""
10660 GOSUB 10790
10670 LPRINT.STRING$=SPACE$(35)+"LINE NUMBER CROSS-REFERENCE"
10680 GOSUB 10790
10690 LPRINT.STRING$=""
10700 GOSUB 10790
10710 LPRINT.STRING$=" LINE"
10720 GOSUB 10790
10730 LPRINT.STRING$="NUMBER -------REFERENCES------REFERENCES------REFERENCES------REFERENCES------"
10740 GOSUB 10790
10750 ON ERROR GOTO 0
10760 LINECNT=8
10770 RETURN
10780 '
10790 ON ERROR GOTO 10860
10800 LPRINT LPRINT.STRING$
10810 ON ERROR GOTO 0
10820 RETURN
10830 '
10840 ' ERROR HANDLING ROUTINE FOR THE PRINTER
10850 '
10860 IF ERR=24 THEN RESUME 10790
10870 IF ERR<>27 THEN 11000
10880 CLS
10890 BEEP
10900 BEEP
10910 PRINT
10920 PRINT "PRINTER NOT READY OR OUT OF PAPER"
10930 PRINT "READY THE PRINTER, AND PRESS ANY KEY TO CONTINUE"
10940 GOSUB 12610 'FLUSH BUFFERS
10950 KEYIN$=INKEY$
10960 IF KEYIN$="" GOTO 10950
10970 IF KEYIN$=CHR$(27) GOTO 17570
10980 RESUME 10790
10990 '
11000 PRINT
11010 PRINT "BASIC ERROR : ";ERR;" AT LINE NO. : ";ERL
11020 GOTO 17570
11030 '
11040 ' SORT DATANAME TABLE
11050 '
11060 IF RUNTYPE=4 GOTO 11400
11070 PRINT "START - DATA NAME TABLE SORT : ";TIME$
11080 GOSUB 11780 'GET YOUR ATTN.
11090 ROW=CSRLIN
11100 COLUMN=POS(0)
11110 LOCATE 25,1,0
11120 PRINT STRING$(79," ");
11130 LOCATE 25,1,0
11140 PRINT "** SORTING";
11150 LAST=NUMLINES
11160 GAP=LAST\2
11170 WHILE GAP>0
11180 FOR I=GAP+1 TO LAST
11190 J=I-GAP
11200 WHILE J>0
11210 IF DATANAME$(J)<=DATANAME$(J+GAP) THEN J=0:GOTO 11270
11220 SWAP DATANAME$(J),DATANAME$(J+GAP)
11230 SWAP LINENOS(J,1),LINENOS(J+GAP,1)
11240 SWAP LINENOS(J,2),LINENOS(J+GAP,2)
11250 SWAP LINENOS(J,3),LINENOS(J+GAP,3)
11260 J=J-GAP
11270 WEND
11280 LOCATE 25,1,0
11290 PRINT " ";
11300 LOCATE 25,1,0
11310 PRINT "** SORTING";
11320 NEXT
11330 GAP=GAP\2
11340 WEND
11350 LOCATE 25,1,0
11360 PRINT STRING$(79," ");
11370 LOCATE ROW,COLUMN,1
11380 PRINT "FINISH- DATA NAME TABLE SORT : ";TIME$
11390 GOSUB 11780 'GET YOUR ATTN.
11400 RETURN
11410 '
11420 ' PRINT HEADINGS FOR THE DATANAME CROSS REFERENCE
11430 '
11440 LPRINT.STRING$=CHR$(13)+CHR$(12)
11450 GOSUB 10790 'PRINT THE STRING
11460 LPRINT.STRING$="PROGRAM : "+DSN$+SPACE$(75)+DATE$+" @ "+TIME$
11470 GOSUB 10790
11480 LPRINT.STRING$=""
11490 GOSUB 10790
11500 IF RUNTYPE=3 THEN LPRINT.STRING$=SPACE$(35)+"DATA NAME CROSS-REFERENCE":GOSUB 10790
11510 IF RUNTYPE=4 THEN LPRINT.STRING$=SPACE$(30)+"RESERVED WORD CROSS-REFERENCE":GOSUB 10790
11520 LPRINT.STRING$=""
11530 GOSUB 10790
11540 IF RUNTYPE=3 THEN LPRINT.STRING$=" DATA":GOSUB 10790
11550 IF RUNTYPE=4 THEN LPRINT.STRING$=" RESERVED":GOSUB 10790
11560 IF RUNTYPE=3 THEN LPRINT.STRING$=" NAME ------REFERENCES------REFERENCES------REFERENCES------REFERENCES------":GOSUB 10790
11570 IF RUNTYPE=4 THEN LPRINT.STRING$=" WORD ------REFERENCES------REFERENCES------REFERENCES------REFERENCES------":GOSUB 10790
11580 ON ERROR GOTO 0
11590 LINECNT=8
11600 RETURN
11610 '
11620 ' PRINT THE LINE NUMBER THAT IS CURRENTLY PROCESSING
11630 '
11640 LOCATE 25,29,0
11650 PRINT MID$(CURLNUM$,1,LEN.CURLNUM);
11660 RETURN
11670 '
11680 ' SEE WHAT KIND OF ADAPTER IS ON THIS SYSTEM
11690 '
11700 DEF SEG=0
11710 IBMMONO=0
11720 IF (PEEK(&H410) AND &H30)=&H30 THEN IBMMONO=1
11730 CURSOR.STOP=7
11740 IF IBMMONO=1 THEN CURSOR.STOP=13
11750 LOCATE,,,0,CURSOR.STOP
11760 RETURN
11770 '
11780 FOR BEEP1=1 TO BEEPCNT
11790 BEEP
11800 FOR BEEP2=1 TO BEEPLOOP
11810 NEXT BEEP2
11820 NEXT BEEP1
11830 RETURN
11840 '
11850 COLOR 7,0
11860 CLS
11870 LOCATE 4,30
11880 PRINT "Software solutions by ";
11890 LOCATE 9,33
11900 PRINT "Soft-SHARE (tm)";
11910 LOCATE 14,15
11920 PRINT "Soft-SHARE , a limited user suppored concept similar to";
11930 LOCATE 15,15
11940 PRINT "FreeWare (c) in that a small contribution is asked but";
11950 LOCATE 16,15
11960 PRINT "not required, to support the authors efforts. If you ";
11970 LOCATE 17,15
11980 PRINT "find this Soft-SHARE product of value a $10 donation is";
11990 LOCATE 18,15
12000 PRINT "asked.. else you are asked to pass it on in its original";
12010 LOCATE 19,15
12020 PRINT "unmodified form. Send comments, updates , donations, or ";
12030 LOCATE 20,15
12040 PRINT "requests for compiled version (with prepaid mailer), to";
12050 LOCATE 22,15
12060 PRINT " James Morgan, 1749 AMERICANA 23-G, ORLANDO FLA 32809";
12070 LOCATE 24,27:PRINT "(press any key to continue)";
12080 KEYIN$=INKEY$:IF KEYIN$="" GOTO 12080
12090 RETURN
12100 '
12110 LOCATE 22,20
12120 COLOR 0,7
12130 CLS
12140 COLOR 0,7
12150 PRINT " ******************************"
12160 PRINT " * BASIC PROGRAM PROCESSOR *"
12170 PRINT " ******************************"
12180 PRINT
12190 PRINT " By James Morgan
12200 PRINT
12210 PRINT " OPTION DESCRIPTION"
12220 PRINT " ------ ---------------------------"
12230 PRINT
12240 PRINT " 1 EXPAND ........BASIC PROGRAM"
12250 PRINT " 2 LINE NUMBER ...CROSS REFERENCE"
12260 PRINT " 3 DATA NAME .....CROSS REFERENCE"
12270 PRINT " 4 RESERVED WORD .CROSS REFERENCE"
12280 PRINT " 5 COMPRESS ......BASIC PROGRAM"
12290 PRINT " 9 EXIT ..........PROGRAM"
12300 PRINT
12310 PRINT
12320 COLOR 31,0
12330 ROW=CSRLIN
12340 COLUMN=POS(0)
12350 GOSUB 12580
12360 GOSUB 11780 'GET YOUR ATTN
12370 GOSUB 12610 'FLUSH BUFFERS
12380 KEYIN$=INKEY$
12390 IF KEYIN$="" GOTO 12380
12400 IF LEN(KEYIN$)<>1 THEN BEEP:GOTO 12120
12410 COLOR 15,0
12420 PRINT KEYIN$
12430 IF VAL(KEYIN$)<1 THEN BEEP:GOTO 12120
12440 IF VAL(KEYIN$)=9 THEN COLOR 7,0:CLS:GOTO 17570
12450 IF VAL(KEYIN$)>5 THEN BEEP:GOTO 12120
12460 RUNTYPE=VAL(KEYIN$)
12470 ACTUAL.RUNTYPE=RUNTYPE
12480 IF ACTUAL.RUNTYPE=1 THEN GOSUB 12740
12490 IF ACTUAL.RUNTYPE=5 THEN GOSUB 12740:GOSUB 13050
12500 IF LPRNT THEN GOSUB 12680:GOTO 12530
12510 IF ACTUAL.RUNTYPE=1 OR ACTUAL.RUNTYPE=5 GOTO 12530
12520 GOSUB 12680 'INITIALIZE PRINTER
12530 IF RUNTYPE=5 THEN RUNTYPE=2
12540 ON ERROR GOTO 0
12550 COLOR 7,0
12560 RETURN
12570 '
12580 PRINT " SELECT AND ENTER OPTION ";
12590 RETURN
12600 '
12610 DEF SEG=0
12620 POKE 1050,PEEK(1052) ' FLUSH SYSTEM KEYBOARD BUFFER
12630 DEF SEG
12640 IF VER$="C" THEN RETURN
12650 POKE 106,0 ' FLUSH BASIC INTERNAL KEYBOARD BUFFER
12660 RETURN
12670 '
12680 WIDTH "LPT1:",132
12690 LPRINT.STRING$=CHR$(15)
12700 GOSUB 10790
12710 EJECT=-1
12720 RETURN
12730 '
12740 PRINT
12750 PRINT
12760 SROW=ROW
12770 SCOLUMN=COLUMN
12780 ROW=CSRLIN
12790 COLUMN=POS(0)
12800 LOCATE SROW,SCOLUMN
12810 COLOR 15,0
12820 GOSUB 12580
12830 COLOR 0,7
12840 LOCATE ROW,COLUMN,0
12850 PRINT STRING$(79," ");
12860 LOCATE ROW,COLUMN,1
12870 COLOR 15,0
12880 PRINT "DO YOU WANT ";
12890 IF ACTUAL.RUNTYPE=1 THEN PRINT "AN EXPANDED ";
12900 IF ACTUAL.RUNTYPE=5 THEN PRINT "A COMPRESSED ";
12910 PRINT "PROGRAM LISTING ALSO? (Y OR N) > ";
12920 GOSUB 12610 'FLUSH BUFFERS
12930 ANS$=INKEY$
12940 IF ANS$="" GOTO 12930
12950 IF LEN(ANS$)<>1 THEN BEEP:GOTO 12930
12960 IF ANS$=CHR$(27) GOTO 17570
12970 COLOR 15,0
12980 PRINT ANS$;
12990 COLOR 0,7
13000 IF ANS$="N" THEN RETURN
13010 IF ANS$<>"Y" THEN BEEP:GOTO 12840
13020 LPRNT=-1
13030 RETURN
13040 '
13050 LOCATE CSRLIN+2,1
13060 SROW=ROW
13070 SCOLUMN=COLUMN
13080 ROW=CSRLIN
13090 COLUMN=POS(0)
13100 LOCATE SROW,SCOLUMN
13110 COLOR 0,7
13120 LOCATE ROW,COLUMN,0
13130 PRINT STRING$(79," ");
13140 LOCATE ROW,COLUMN,1
13150 COLOR 15,0
13160 PRINT "DO YOU WANT TO REMOVE UNREFERENCED LINE NUMBERS : ";
13170 GOSUB 12610 'FLUSH BUFFERS
13180 ANS$=INKEY$
13190 IF ANS$="" GOTO 13180
13200 IF LEN(ANS$)<>1 THEN BEEP:GOTO 13180
13210 IF ANS$=CHR$(27) GOTO 17570
13220 COLOR 15,0
13230 PRINT ANS$;
13240 COLOR 0,7
13250 IF ANS$="N" THEN RETURN
13260 IF ANS$<>"Y" THEN BEEP:GOTO 13120
13270 REMOVE.UNREFERENCED.LINENOS=-1
13280 RETURN
13290 '
13300 ROW=CSRLIN
13310 COLUMN=POS(0)
13320 LOCATE ROW,COLUMN,0
13330 FOR I=1 TO 24 - ROW
13340 PRINT STRING$(79," ")
13350 NEXT
13360 GOSUB 1940 'CLEAR 24-25
13370 OUTDRIVE$=""
13380 LOCATE ROW,COLUMN,1
13390 BEEP
13400 PRINT
13410 PRINT "CREATING OUTPUT FILE : "+OUTFILE$+" WHILE "+REASON$
13420 PRINT
13430 PRINT "WHAT DRIVE IS THE FILE TO BE ON (PRESS ENTER FOR DEFAULT)"
13440 PRINT "DRIVE : ";
13450 GOSUB 12610
13460 OUTDRIVE$=INKEY$
13470 IF OUTDRIVE$="" GOTO 13460
13480 IF OUTDRIVE$=CHR$(27) GOTO 17570
13490 IF LEN(OUTDRIVE$)<>1 THEN BEEP:GOTO 13460
13500 IF OUTDRIVE$=CR$ THEN OUTDRIVE$="":GOTO 13570
13510 IF OUTDRIVE$<"A" THEN BEEP:GOTO 13460
13520 IF OUTDRIVE$>"Z" THEN BEEP:GOTO 13460
13530 PRINT OUTDRIVE$;
13540 OUTDRIVE$=OUTDRIVE$+":"
13550 GOTO 13570
13560 '
13570 ON ERROR GOTO 13620
13580 OPEN OUTDRIVE$+OUTFILE$ FOR OUTPUT AS #2
13590 ON ERROR GOTO 0
13600 RETURN
13610 '
13620 GOSUB 5840 'GET TYPE ERR
13630 RESUME 13640
13640 ON ERROR GOTO 0
13650 GOSUB 1940 'CLEAR 24-25
13660 LOCATE 25,1,1
13670 COLOR 15
13680 PRINT REASON$;" FILE OPEN ON ";OUTFILE$;" FAILED. ";M$;
13690 LOCATE 24,1
13700 PRINT "CORRECT PROBLEM AND PRESS ANY KEY TO CONTINUE";
13710 GOSUB 12610 'FLUSH BUFFERS
13720 KEYIN$=INKEY$
13730 IF KEYIN$="" GOTO 13720
13740 IF KEYIN$=CHR$(27) GOTO 17570
13750 GOSUB 1940 'CLEAR 24-25
13760 LOCATE ROW,COLUMN,0
13770 GOTO 13320
13780 '
13790 ROW=CSRLIN
13800 COLUMN=POS(0)
13810 LOCATE ROW,COLUMN,0
13820 FOR I=1 TO 24 - ROW
13830 PRINT STRING$(79," ")
13840 NEXT
13850 GOSUB 1940 'CLEAR 25-25
13860 LINEDRIVE$=""
13870 LOCATE ROW,COLUMN,1
13880 PRINT
13890 PRINT "CREATING OUTPUT FILE : "+"LINENOS.XRF"+" WHILE "+REASON$
13900 PRINT
13910 PRINT "WHAT DRIVE IS THE FILE TO BE ON (PRESS ENTER FOR DEFAULT)"
13920 PRINT "DRIVE : ";
13930 GOSUB 12610 'FLUSH BUFFERS
13940 LINEDRIVE$=INKEY$
13950 IF LINEDRIVE$="" GOTO 13940
13960 IF LINEDRIVE$=CHR$(27) GOTO 17570
13970 IF LEN(LINEDRIVE$)<>1 THEN BEEP:GOTO 13940
13980 IF LINEDRIVE$=CR$ THEN LINEDRIVE$="":GOTO 14030
13990 IF LINEDRIVE$<"A" THEN BEEP:GOTO 13940
14000 IF LINEDRIVE$>"Z" THEN BEEP:GOTO 13940
14010 PRINT LINEDRIVE$;
14020 LINEDRIVE$=LINEDRIVE$+":"
14030 ON ERROR GOTO 14100
14040 KILL LINEDRIVE$+"LINENOS.XRF"
14050 ON ERROR GOTO 0
14060 GOSUB 9680 'OPEN LINE NO FILE
14070 IF M$<>"" GOTO 13810
14080 RETURN
14090 '
14100 ERR.NO=ERR
14110 RESUME 14120
14120 ON ERROR GOTO 0
14130 IF ERR.NO=53 GOTO 14060
14140 GOSUB 1940 'CLEAR 24-25
14150 LOCATE 25,1
14160 PRINT "** ERROR ";ERR.NO;" ACCESSING ";"LINENOS.XRF";
14170 LOCATE 24,1
14180 PRINT "CORRECT PROBLEM AND PRESS ANY KEY TO CONTINUE";
14190 GOSUB 12610 'FLUSH BUFFERS
14200 KEYIN$=INKEY$
14210 IF KEYIN$="" GOTO 14200
14220 IF KEYIN$=CHR$(27) GOTO 17570
14230 LOCATE 24,1
14240 PRINT STRING$(79," ");
14250 GOSUB 1940 'CLEAR 24-25
14260 LOCATE ROW,COLUMN,1
14270 GOTO 14030
14280 '
14290 ' SET CAPSLOCK ON
14300 '
14310 DEF SEG=&H40
14320 POKE &H17,PEEK(&H17) OR 64
14330 DEF SEG
14340 RETURN
14350 '
14360 '*************************************************************************
14370 '* *
14380 '* LOGIC TO COMPRESS A BASIC PROGRAM *
14390 '* *
14400 '*************************************************************************
14410 FREECNT=0
14420 FREE!=FRE("")
14430 MID$(S$,1)=STRING$(255," ")
14440 LEN.S=0
14450 X=1
14460 ON ERROR GOTO 0
14470 PHASE=2
14480 CLOSE
14490 TYPE.STORED.PGM=32
14500 OPEN OUTDRIVE$+OUTFILE$ FOR INPUT AS 1
14510 OUTFILE$="TEMPCOMP.BAS"
14520 REASON$="COMPRESSING PROGRAM"
14530 GOSUB 13300 'CREATE COMPRESSED FILE
14540 START$=TIME$
14550 LOCATE 25,1,0
14560 PRINT "PROCESSING LINE NUMBER = ";
14570 IF EOF(1) GOTO 16670
14580 GOSUB 2460 'READ EXPANDED BASIC PROGRAM FILE
14590 L=LEN.B
14600 GOSUB 5300 'FIND END OF LINE
14610 E=BEND
14620 GOSUB 14670 'ISOLATE LINE NUMBER AND FIND START OF BASIC STATEMENT
14630 GOTO 15100
14640 '
14650 ' ISOLATE LINE NUMBER AND FIND START OF BASIC STATEMENT(S)
14660 '
14670 MID$(CURLNUM$,1)=STRING$(255," ")
14680 LEN.CURLNUM=0
14690 FOR I=1 TO E
14700 MID$(BYTE$,1,1)=MID$(B$,I,1)
14710 IF BYTE$>" " GOTO 14730
14720 NEXT I
14730 S=I
14740 MID$(P$,1)=STRING$(255," ")
14750 LEN.P=0
14760 FOR I=S TO E
14770 MID$(BYTE$,1,1)=MID$(B$,I,1)
14780 IF BYTE$<"0" GOTO 14830
14790 IF BYTE$>"9" GOTO 14830
14800 LEN.P=LEN.P+1
14810 MID$(P$,LEN.P,1)=BYTE$
14820 NEXT I
14830 IF I=E THEN ERRNO=1:GOTO 5470
14840 IF LEN.P<1 THEN ERRN0=1:GOTO 5470
14850 IF LEN.P>5 THEN ERRNO=1:GOTO 5470
14860 MID$(CURLNUM$,1)=MID$(P$,1,LEN.P)
14870 LEN.CURLNUM=LEN.P
14880 GOSUB 11640 'PRINT CURRENT LINE NO
14890 CURLINE!=VAL(MID$(CURLNUM$,1,LEN.CURLNUM))
14900 LINENO=(CURLINE! - 32767)
14910 S=I
14920 GOSUB 15030 'SEE IF LINE NO REFREENCED
14930 FOR I=S TO E
14940 MID$(BYTE$,1,1)=MID$(B$,I,1)
14950 IF BYTE$>" " GOTO 14980
14960 NEXT I
14970 IF I=E THEN ERRNO=2:GOTO 5470
14980 S=I
14990 MID$(P$,1)=MID$(B$,S)
15000 LEN.P=LEN.B-S+1
15010 RETURN
15020 '
15030 EQUAL.LINENOS=FALSE
15040 FOR X=X TO NUMLINES
15050 IF LINENO=LINENOS(X,1) THEN EQUAL.LINENOS=-1:RETURN
15060 IF LINENO<LINENOS(X,1) THEN RETURN
15070 NEXT X
15080 RETURN
15090 '
15100 ADD=0
15110 REMPOS=0
15120 IFPOS=0
15130 IF EQUAL.LINENOS GOTO 16740
15140 ADD=-1
15150 IF MID$(P$,1,1)="'" GOTO 14570
15160 IF MID$(P$,1,3)="REM" GOTO 15430
15170 IF MID$(P$,1,4)="DATA" GOTO 15510
15180 GOSUB 15960
15190 IF ADD=0 THEN GOSUB 15630 'WRITE COMPRESSED LINE
15200 IF LEN.S=0 THEN GOSUB 15320:GOTO 15290 'PREFIX STATEMENT WITH LINE NO
15210 IF LEN.S>252 THEN ADD=0:GOTO 15190
15220 TOTAL.LEN=LEN.S+LEN.P + 1
15230 IF TOTAL.LEN>253 THEN ADD=0:GOTO 15190
15240 LEN.S=LEN.S+1
15250 MID$(S$,LEN.S)=":"
15260 LEN.S=LEN.S+1
15270 MID$(S$,LEN.S)=MID$(P$,1,LEN.P)
15280 LEN.S=LEN.S+LEN.P-1
15290 IF IFPOS<>0 THEN GOSUB 15630 'WRITE COMPRESSED LINE
15300 GOTO 14570
15310 '
15320 IF REMOVE.UNREFERENCED.LINENOS=0 GOTO 15340
15330 IF EQUAL.LINENOS=0 GOTO 15360
15340 MID$(S$,1)=MID$(CURLNUM$,1,LEN.CURLNUM)
15350 LEN.S=LEN.CURLNUM
15360 LEN.S=LEN.S+1
15370 MID$(S$,LEN.S)=" "
15380 LEN.S=LEN.S+1
15390 MID$(S$,LEN.S)=MID$(P$,1,LEN.P)
15400 LEN.S=LEN.S+LEN.P-1
15410 RETURN
15420 '
15430 IF LEN.P<4 GOTO 14570
15440 IF MID$(P$,4,1)=" " GOTO 14570
15450 IF MID$(P$,4,1)="." GOTO 15180
15460 IF ASC(MID$(P$,4,1))<48 GOTO 14570
15470 IF ASC(MID$(P$,4,1))>90 GOTO 14570
15480 IF (ASC(MID$(P$,4,1))>57) AND (ASC(MID$(P$,4,1))<65) GOTO 14570
15490 GOTO 15180
15500 '
15510 IF LEN.P<5 GOTO 14570
15520 IF MID$(P$,5,1)=" " GOTO 15590
15530 IF MID$(P$,5,1)="." GOTO 15180
15540 IF ASC(MID$(P$,5,1))<48 GOTO 15590
15550 IF ASC(MID$(P$,5,1))>90 GOTO 15590
15560 IF (ASC(MID$(P$,5,1))>57) AND (ASC(MID$(P$,5,1))<65) GOTO 15590
15570 GOTO 15180
15580 '
15590 IFPOS=1
15600 ADD=0
15610 GOTO 15190
15620 '
15630 IF LEN.S=0 THEN RETURN
15640 GOSUB 15690 'WRITE COMPRESSED RECORD
15650 MID$(S$,1)=STRING$(255," ")
15660 LEN.S=0
15670 RETURN
15680 '
15690 ON ERROR GOTO 15750
15700 PRINT#2,MID$(S$,1,LEN.S)
15710 ON ERROR GOTO 0
15720 IF LPRNT THEN LPRINT MID$(S$,1,LEN.S)
15730 RETURN
15740 '
15750 ROW=CSRLIN
15760 COLUMN=POS(0)
15770 GOSUB 5840 'GET TYPE ERR
15780 RESUME 15790
15790 ON ERROR GOTO 0
15800 GOSUB 1940 'CLEAR 24-25
15810 LOCATE 25,1,1
15820 COLOR 15
15830 PRINT "COMPRESSED PROGRAM WRITE FAILED. ";M$;
15840 M$=" "
15850 LOCATE 24,1
15860 PRINT "CORRECT PROBLEM AND PRESS ANY KEY TO CONTINUE";
15870 GOSUB 12610 'FLUSH BUFFERS
15880 KEYIN$=INKEY$
15890 IF KEYIN$="" GOTO 15880
15900 IF KEYIN$=CHR$(27) GOTO 17570
15910 COLOR 7
15920 GOSUB 1940 'CLEAR 24-25
15930 LOCATE ROW,COLUMN,0
15940 GOTO 15690
15950 '
15960 I=1
15970 MID$(H$,1)=MID$(P$,1,LEN.P)
15980 LEN.H=LEN.P
15990 FOR I=I TO LEN.P
16000 IF MID$(P$,I,1)=QUOTE$ GOTO 16050
16010 IF MID$(P$,I,1)="'" GOTO 16160
16020 NEXT I
16030 GOTO 16300
16040 '
16050 MID$(H$,I,1)=" "
16060 I=I + 1
16070 FOR I=I TO LEN.P
16080 MID$(H$,I,1)=" "
16090 IF MID$(P$,I,1)=QUOTE$ THEN I=I + 1:GOTO 15990
16100 NEXT I
16110 PRINT
16120 PRINT "PROGRAM TRAP REACHED"
16130 STOP
16140 END
16150 '
16160 MID$(P$,1)=MID$(P$,1,I - 1)
16170 LEN.P=I-1
16180 L=LEN.P
16190 FOR I=L TO 1 STEP -1
16200 IF MID$(P$,I,1)<>" " GOTO 16250
16210 NEXT I
16220 ERRNO=3
16230 GOTO 5470
16240 '
16250 MID$(P$,1)=MID$(P$,1,I)
16260 LEN.P=I
16270 MID$(H$,1)=MID$(H$,1,I)
16280 LEN.H=I
16290 L=LEN.P
16300 GOSUB 16360 'REMOVE ANY UNNECESSARY CHARS. FROM STATEMENT
16310 IFPOS=INSTR(1,MID$(H$,1,LEN.H),"IF ")
16320 REMPOS=INSTR(1,MID$(H$,1,LEN.H),"REM ")
16330 IF REMPOS<>0 THEN GOSUB 16490
16340 RETURN
16350 '
16360 FOR I=1 TO LEN.H
16370 V=ASC(MID$(H$,I,1))
16380 IF V=46 GOTO 16430 '"."
16390 IF V<48 GOTO 16460 '"0"
16400 IF V>90 GOTO 16460 '"Z"
16410 IF V>64 GOTO 16430 '"@"
16420 IF V>57 GOTO 16460 '"9"
16430 NEXT I
16440 RETURN
16450 '
16460 MID$(H$,I,1)=" "
16470 GOTO 16430
16480 '
16490 MID$(P$,1)=MID$(P$,1,REMPOS - 1)
16500 LEN.P=REMPOS-1
16510 MID$(H$,1)=MID$(H$,1,REMPOS - 1)
16520 LEN.H=REMPOS-1
16530 L=LEN.P
16540 FOR I=L TO 1 STEP -1
16550 IF MID$(P$,I,1)<>" " THEN 16600
16560 NEXT I
16570 ERRNO=3
16580 GOTO 5470
16590 '
16600 MID$(P$,1)=MID$(P$,1,I)
16610 LEN.P=I
16620 MID$(H$,1)=MID$(H$,1,I)
16630 LEN.H=I
16640 L=LEN.P
16650 RETURN
16660 '
16670 GOSUB 15630 'SEE IF ANYTHING LEFT IN BUFFER
16680 FINISH$=TIME$
16690 PRINT
16700 PRINT "COMPRESS PROCESSING FINISHED AT : ";FINISH$
16710 PRINT "COMPRESS PROCESSING STARTED AT : ";START$
16720 GOTO 17570
16730 '
16740 IF MID$(P$,1,1)="'" THEN IFPOS=1:GOTO 15190
16750 IF MID$(P$,1,3)="REM" GOTO 16790
16760 IF MID$(P$,1,4)="DATA" GOTO 16910
16770 GOTO 15180
16780 '
16790 IF LEN.P<4 GOTO 16870
16800 IF MID$(P$,4,1)="." GOTO 15180
16810 IF MID$(P$,4,1)=" " GOTO 16870
16820 IF ASC(MID$(P$,4,1))<48 GOTO 16870
16830 IF ASC(MID$(P$,4,1))>90 GOTO 16870
16840 IF (ASC(MID$(P$,4,1))>57) AND (ASC(MID$(P$,4,1))<65) GOTO 16870
16850 GOTO 15180
16860 '
16870 ADD=0
16880 IFPOS=1
16890 GOTO 15190
16900 '
16910 IF LEN.P<5 GOTO 16870
16920 IF MID$(P$,5,1)="." GOTO 15180
16930 IF MID$(P$,5,1)=" " GOTO 16870
16940 IF ASC(MID$(P$,5,1))<48 GOTO 16870
16950 IF ASC(MID$(P$,5,1))>90 GOTO 16870
16960 IF (ASC(MID$(P$,5,1))>57) AND (ASC(MID$(P$,5,1))<65) GOTO 16870
16970 GOTO 15180
16980 '
16990 I=1
17000 FOR I=I TO LEN.B
17010 MID$(BYTE$,1,1)=MID$(B$,I,1)
17020 IF BYTE$=QUOTE$ GOTO 17290
17030 IF BYTE$="'" THEN L=LEN.B:RETURN
17040 IF I>1 THEN IF BYTE$=":" AND MID$(B$,I-1,1)=":" THEN MID$(B$,I,1)=" "
17050 IF BYTE$<" " THEN MID$(B$,I,1)=" "
17060 IF BYTE$>CHR$(122) THEN MID$(B$,I,1)=" "
17070 IF (ACTUAL.RUNTYPE=5) OR (RUNTYPE=1) GOTO 17080 ELSE GOTO 17090
17080 IF BYTE$=" " GOTO 17380 'REMOVE EXTRANEOUS SPACES
17090 IF BYTE$>CHR$(96) THEN MID$(B$,I,1)=CHR$(ASC(BYTE$) AND 95)
17100 IF (BYTE$<>"D") AND (BYTE$<>"R") GOTO 17240
17110 IF BYTE$<>"R" GOTO 17190
17120 MID$(C$,1)=MID$(B$,I,4)
17130 LEN.C=LEN.B-I+1
17140 IF LEN.C>4 THEN LEN.C=4
17150 GOSUB 4970 'CHECK IF "REM"
17160 IF MID$(C$,1,LEN.C)=REM1$ THEN L=LEN.B:RETURN
17170 GOTO 17240
17180 '
17190 MID$(C$,1)=MID$(B$,I,5)
17200 LEN.C=LEN.B-I+1
17210 IF LEN.C>5 THEN LEN.C=5
17220 GOSUB 5120 'CHECK IF "DATA"
17230 IF MID$(C$,1,LEN.C)=DATA1$ THEN L=LEN.B:RETURN
17240 NEXT I
17250 '
17260 L=LEN.B
17270 RETURN
17280 '
17290 FOR I=I+1 TO LEN.B
17300 IF MID$(B$,I,1)=QUOTE$ THEN I=I+1:GOTO 17000
17310 NEXT I
17320 IF LEN.B>253 THEN ERRNO=5:GOTO 5470
17330 LEN.B=LEN.B+1 'ADD MISSING END QUOTE (")
17340 MID$(B$,LEN.B,1)=QUOTE$
17350 L=LEN.B
17360 RETURN
17370 '
17380 IF I=1 GOTO 17240
17390 IF I>=LEN.B THEN L=LEN.B:RETURN
17400 MID$(SB$,1)=MID$(B$,1,I)
17410 LEN.SB=I
17420 FOR J=I+1 TO LEN.B
17430 IF MID$(B$,J,1)<>" " GOTO 17460
17440 NEXT
17450 IF J>=LEN.B GOTO 17260
17460 MID$(BYTE$,1,1)=MID$(SB$,LEN.SB-1,1)
17470 IF INSTR("=:,(<>*/\;^",BYTE$)<>0 THEN MID$(SB$,1)=LEFT$(SB$,LEN.SB-1):LEN.SB=LEN.SB-1
17480 MID$(BYTE$,1,1)=MID$(B$,J,1)
17490 IF MID$(SB$,LEN.SB,1)=" " THEN IF INSTR("=:,)<>*/\^;",BYTE$)<>0 THEN MID$(SB$,1)=LEFT$(SB$,LEN.SB-1):LEN.SB=LEN.SB-1
17500 I=LEN.SB+1
17510 MID$(SB$,LEN.SB+1)=MID$(B$,J)
17520 LEN.SB=LEN.SB+(LEN.B-J+1)
17530 MID$(B$,1)=LEFT$(SB$,LEN.SB)
17540 LEN.B=LEN.SB
17550 GOTO 17000
17560 '
17570 ON ERROR GOTO 0
17580 CLOSE
17590 PRINT
17600 BEEP
17610 KEYIN$=""
17620 PRINT "PRESS ENTER TO EXIT PROGRAM"
17630 GOSUB 12610 'FLUSH BUFFERS
17640 KEYIN$=INKEY$
17650 IF KEYIN$="" GOTO 17640
17660 IF LEN(KEYIN$)<>1 GOTO 17640
17670 IF KEYIN$<>CR$ GOTO 17640
17680 CLEAR
17690 COLOR 7,0
17700 CLS
17710 END
17720 '*
17730 '* PROCESS TOKENIZED BASIC PROGRAM
17740 '*
17750 READY.TO.RETURN=0
17760 ON ENTRY.POINT GOTO 17820,17870,18050,18070,17970
17770 OPEN DSN$ AS #1 LEN=2
17780 FIELD #1,2 AS PGM.BYTE$
17790 GOSUB 19730 'GET BEGINNING LINE ATTR.
17800 IF TYPE.READ=1 GOTO 17870
17810 '
17820 GOSUB 19730
17830 B=A
17840 GOSUB 19730
17850 NEXT.OFFSET!=B+(TWO.FIFTY.SIX!*A) 'BYPASS NEXT LINE POINTER ATTR X'00' BYTE
17860 '
17870 IF NEXT.OFFSET!=0 GOTO 19660
17880 GOSUB 19730 'GET THE LINE NUMBER FOR THIS STATEMENT
17890 B=A
17900 GOSUB 19730
17910 LINE.NO!=B+(TWO.FIFTY.SIX!*A)
17920 MID$(T$,1)=STRING$(255," ")
17930 LEN.T=0
17940 GOSUB 20180
17950 IF READY.TO.RETURN THEN ENTRY.POINT=5:RETURN
17960 '
17970 MID$(T$,1)=STR$(LINE.NO!)
17980 MID$(T$,1)=MID$(T$,2)
17990 LEN.T=LEN(STR$(LINE.NO!))-1
18000 GOSUB 20180
18010 IF READY.TO.RETURN THEN ENTRY.POINT=3:RETURN
18020 '
18030 '***** IDENTIFY TOKENS *****
18040 '
18050 GOSUB 19730
18060 '
18070 IF A<128 GOTO 18560
18080 '***** KEYWORDS *****
18090 IF A=143 GOTO 18360 'REMARK ?
18100 IF A=132 GOTO 18520 ' DATA?
18110 IF A<253 THEN X=252:ELSE X=A:GOSUB 19730
18120 ON X-251 GOTO 18150,18190,18230,18270
18130 GOTO 20340
18140 '
18150 MID$(T$,1)=CK$(A-128)
18160 LEN.T=LEN(CK$(A-128))
18170 GOTO 18310 'CASSETTE KEYWORD
18180 '
18190 MID$(T$,1)=DF$(A-128)
18200 LEN.T=LEN(DF$(A-128))
18210 GOTO 18310 'DISK FUNCTION
18220 '
18230 MID$(T$,1)=DK$(A-128)
18240 LEN.T=LEN(DK$(A-128))
18250 GOTO 18310 'DISK KEYWORD
18260 '
18270 MID$(T$,1)=CF$(A-128)
18280 LEN.T=LEN(CF$(A-128))
18290 GOTO 18310 'CASSETTE FUNCTION
18300 '
18310 GOSUB 20180
18320 IF READY.TO.RETURN THEN ENTRY.POINT=3:RETURN
18330 GOTO 18050
18340 '
18350 '***** REMARK *****
18360 MID$(T$,1)="'"
18370 LEN.T=1
18380 GOSUB 19730
18390 IF A<>217 THEN GOSUB 20290
18400 GOSUB 19730
18410 IF TYPE.READ=1 THEN IF EOL=0 THEN GOSUB 20290:GOTO 18400:ELSE GOTO 18470
18420 IF A<>0 THEN GOSUB 20290:GOTO 18400
18430 GOSUB 20180
18440 IF READY.TO.RETURN THEN ENTRY.POINT=1:RETURN
18450 GOTO 17820
18460 '
18470 GOSUB 20180
18480 IF READY.TO.RETURN THEN ENTRY.POINT=2:RETURN
18490 GOTO 17870
18500 '
18510 '***** DATA *****
18520 MID$(T$,1)="DATA"
18530 LEN.T=4
18540 GOTO 18310
18550 '
18560 IF A<65 OR A>90 GOTO 18660
18570 '**** NAME *****
18580 MID$(T$,1)=MID$(C$,1,LEN.C)
18590 LEN.T=LEN.C
18600 GOSUB 19730
18610 IF (A>64 AND A<91) OR (A>47 AND A<58) OR A=46 OR A=33 OR A=35 OR A=36 OR A=37 THEN GOSUB 20290:GOTO 18600
18620 GOSUB 20180
18630 IF READY.TO.RETURN THEN ENTRY.POINT=4:RETURN
18640 GOTO 18070
18650 '
18660 IF A<>14 GOTO 18760
18670 '***** LINE NUMBER *****
18680 GOSUB 19730
18690 B=A
18700 GOSUB 19730
18710 MID$(T$,1)=STR$(B+(TWO.FIFTY.SIX!*A))
18720 MID$(T$,1)=MID$(T$,2)
18730 LEN.T=LEN(STR$(B+(TWO.FIFTY.SIX!*A)))-1
18740 GOTO 18310
18750 '
18760 IF A<>34 GOTO 18930
18770 '***** LITERAL CONSTANT *****
18780 MID$(T$,1)=MID$(C$,1,LEN.C)
18790 LEN.T=LEN.C
18800 GOSUB 19730
18810 IF TYPE.READ=1 THEN IF EOL=-1 GOTO 18850:ELSE GOSUB 20290:IF A<>34 GOTO 18800:ELSE GOTO 18850
18820 IF A=0 THEN GOTO 18430
18830 GOSUB 20290
18840 IF A<>34 GOTO 18800
18850 GOSUB 20180
18860 IF TYPE.READ=1 AND EOL=-1 GOTO 18900
18870 IF READY.TO.RETURN THEN ENTRY.POINT=3:RETURN
18880 GOTO 18050
18890 '
18900 IF READY.TO.RETURN THEN ENTRY.POINT=2:RETURN
18910 GOTO 17870
18920 '
18930 IF A<17 OR A>26 GOTO 19000
18940 '***** 1 DECIMAL DIGIT CONSTANT *****
18950 MID$(T$,1)=STR$(A-17)
18960 MID$(T$,1)=MID$(T$,2)
18970 LEN.T=LEN(STR$(A-17))-1
18980 GOTO 18310
18990 '
19000 IF A<>15 GOTO 19080
19010 '***** 1 BYTE INTERGER CONSTANT *****
19020 GOSUB 19730
19030 MID$(T$,1)=STR$(A)
19040 MID$(T$,1)=MID$(T$,2)
19050 LEN.T=LEN(STR$(A))-1
19060 GOTO 18310
19070 '
19080 IF A<>28 GOTO 19180
19090 '***** 2 BYTE SIGNED INTERGER *****
19100 GOSUB 19730
19110 B=A
19120 GOSUB 19730
19130 MID$(T$,1)=STR$(B+(TWO.FIFTY.SIX!*A))+"%"
19140 MID$(T$,1)=MID$(T$,2)
19150 LEN.T=LEN(STR$(B+(TWO.FIFTY.SIX!*A)))
19160 GOTO 18310
19170 '
19180 IF A<>29 GOTO 19320
19190 '***** 4 BYTE FLOATING POINT *****
19200 MID$(T$,1)=STRING$(255," ")
19210 LEN.T=0
19220 X=VARPTR(N!)
19230 FOR I=0 TO 3
19240 GOSUB 19730
19250 POKE X+I,A
19260 NEXT
19270 MID$(T$,1)=STR$(N!)+"!"
19280 MID$(T$,1)=MID$(T$,2)
19290 LEN.T=LEN(STR$(N!))
19300 GOTO 18310
19310 '
19320 IF A<>31 GOTO 19460
19330 '***** 8 BYTE FLOATING POINT *****
19340 MID$(T$,1)=STRING$(255," ")
19350 LEN.T=0
19360 X=VARPTR(N#)
19370 FOR I=0 TO 7
19380 GOSUB 19730
19390 POKE X+I,A
19400 NEXT
19410 MID$(T$,1)=STR$(N#)+"#"
19420 MID$(T$,1)=MID$(T$,2)
19430 LEN.T=LEN(STR$(N#))
19440 GOTO 18310
19450 '
19460 IF A<>11 AND A<>12 GOTO 19570
19470 '***** 2 BYTE HEX/OCTAL INTERGER *****
19480 A.TYPE=A
19490 GOSUB 19730
19500 B=A
19510 GOSUB 19730
19520 C!=B+(A*TWO.FIFTY.SIX!)
19530 IF A.TYPE=12 THEN MID$(T$,1)="&H"+HEX$(C!) ELSE MID$(T$,1)="&O"+OCT$(C!)
19540 IF A.TYPE=12 THEN LEN.T=2+LEN(HEX$(C!)) ELSE LEN.T=2+LEN(OCT$(C!))
19550 GOTO 18310
19560 '
19570 IF (A>43 AND A<60) OR A=32 OR A=35 OR A=40 OR A=41 OR A=91 OR A=93 THEN MID$(T$,1)=MID$(C$,1,LEN.C):LEN.T=LEN.C:GOTO 18310
19580 IF A>0 THEN MID$(T$,1)=MID$(C$,1,LEN.C):LEN.T=LEN.C:GOTO 18310
19590 IF TYPE.READ=1 AND EOL=-1 GOTO 17870
19600 IF A=0 GOTO 17820
19610 '***** OTHER *****
19620 IF A>96 AND A<122 THEN GOTO 20340 'LOWER CASE LETTERS ARE IMPOSSIBLE
19630 IF A<11 OR A=13 OR A=15 OR A=16 OR A=30 THEN GOTO 20340 'IMPOSSIBLE
19640 GOTO 20340 'WASN'T AN ASCII VALUE
19650 '
19660 MID$(T$,1)=STRING$(255," ")
19670 LEN.T=0
19680 GOSUB 20180
19690 CLOSE#1
19700 READY.TO.RETURN=255
19710 RETURN
19720 '
19730 IF TYPE.READ=1 GOTO 19770
19740 GOSUB 20070
19750 RETURN
19760 '
19770 EOL=0
19780 IF FIRST.TIME=0 GOTO 19810
19790 IF CURRENT.OFFSET!<>NEXT.OFFSET! GOTO 19970
19800 CURRENT.OFFSET!=NEXT.OFFSET!
19810 GOSUB 20070
19820 IF FIRST.TIME=0 AND A=255 GOTO 19840
19830 IF A<>0 GOTO 20010
19840 GOSUB 20070
19850 B=A
19860 GOSUB 20070
19870 NEXT.OFFSET!=B+(TWO.FIFTY.SIX!*A)
19880 PREVIOUS.OFFSET!=NEXT.OFFSET!
19890 CURRENT.OFFSET!=CURRENT.OFFSET!+3
19900 MID$(C$,1)=CHR$(0)
19910 LEN.C=1
19920 A=0
19930 EOL=-1
19940 FIRST.TIME=-1
19950 RETURN
19960 '
19970 GOSUB 20070
19980 CURRENT.OFFSET!=CURRENT.OFFSET!+1
19990 RETURN
20000 '
20010 CLOSE
20020 PRINT
20030 PRINT "DID NOT FIND EXPECTED HEX '00' NEW LINE DELIMITER"
20040 GOTO 20340
20050 '
20060 '
20070 IF BYTE.PTR<>0 GOTO 20100
20080 BYTE.PTR=1
20090 GET #1
20100 MID$(C$,1)=MID$(PGM.BYTE$,BYTE.PTR,1)
20110 LEN.C=1
20120 A=ASC(C$)
20130 BYTE.PTR=BYTE.PTR+1
20140 IF BYTE.PTR>2 THEN BYTE.PTR=0
20150 TOTAL.BYTES.READ!=TOTAL.BYTES.READ!+1
20160 RETURN
20170 '
20180 IF LEN.T=0 GOTO 20260
20190 IF LEN.S=0 GOTO 20230
20200 IF (MID$(T$,1,1)=":") AND (MID$(S$,LEN.S,1)=":") THEN MID$(T$,1)=STRING$(255," "):LEN.T=0:RETURN
20210 IF (MID$(T$,1,LEN.T)="ELSE") THEN IF (MID$(S$,LEN.S,1)=":") AND (MID$(S$,LEN.S-1,1)=" ") THEN MID$(S$,1)=LEFT$(S$,LEN.S-1):LEN.S=LEN.S-1
20220 IF LEN.S+LEN.T>253 THEN PRINT:PRINT MID$(S$,1,LEN.S):PRINT MID$(T$,1,LEN.T):PRINT "THE PRECEEDING TWO LINE WOULD BE GREATER THAN 253 CHARACTERS":PRINT "THIS CAN OCCUR ONLY IF TOKENIZED LINE EXPANDED INCORRECTLY":CLOSE:GOTO 20340
20230 LEN.S=LEN.S+1
20240 MID$(S$,LEN.S)=MID$(T$,1,LEN.T)
20250 LEN.S=LEN.S+LEN.T-1
20260 IF LEN.T=0 THEN IF LEN.S>0 THEN MID$(B$,1)=MID$(S$,1,LEN.S):LEN.B=LEN.S:LEN.S=0:MID$(S$,1)=STRING$(255," "):READY.TO.RETURN=-1
20270 RETURN
20280 '
20290 LEN.T=LEN.T+1
20300 MID$(T$,LEN.T)=MID$(C$,1,LEN.C)
20310 LEN.T=LEN.T+LEN.C-1
20320 RETURN
20330 '
20340 READY.TO.RETURN=0
20350 RETURN
20360 '
20370 TYPE.READ=0
20380 READY.TO.RETURN=0
20390 OPEN DSN$ AS #1 LEN=1
20400 FIELD #1,1 AS PGM.BYTE$
20410 GET #1,1
20420 IF EOF(1) THEN CLOSE:GOTO 20340
20430 TYPE.STORED.PGM=ASC(PGM.BYTE$)
20440 IF TYPE.STORED.PGM=253 THEN CLS:CLOSE:PRINT:PRINT "PROGRAM NOT STORED AS TEXT OR TOKENIZED, UNPROTECTED, BASIC FILE":GOTO 20340
20450 IF TYPE.STORED.PGM<>254 THEN CLOSE:READY.TO.RETURN=-1:RETURN
20460 GET #1,2
20470 IF EOF(1) THEN CLOSE:GOTO 20340
20480 A=ASC(PGM.BYTE$)
20490 GET #1,3
20500 IF EOF(1) THEN CLOSE:GOTO 20340
20510 FIRST.OFFSET!=A+(TWO.FIFTY.SIX!*ASC(PGM.BYTE$))
20520 IF FIRST.OFFSET!=0 THEN CLOSE:GOTO 20340
20530 HIGH.OFFSET.BYTE$=PGM.BYTE$
20540 PASS=1
20550 REC.CNT=6
20560 FOR REC.CNT=REC.CNT TO 300
20570 GET #1,REC.CNT
20580 IF EOF(1) GOTO 20610
20590 IF PGM.BYTE$=HIGH.OFFSET.BYTE$ GOTO 20690
20600 NEXT REC.CNT
20610 IF PASS=2 GOTO 20820
20620 PASS=2
20630 IF ASC(HIGH.OFFSET.BYTE$)=255 GOTO 20820
20640 B=ASC(HIGH.OFFSET.BYTE$)
20650 B=B+1
20660 HIGH.OFFSET.BYTE$=CHR$(B)
20670 GOTO 20550
20680 '
20690 GET #1,REC.CNT-2
20700 IF ASC(PGM.BYTE$)<>0 THEN REC.CNT=REC.CNT+1:GOTO 20560
20710 GET #1,REC.CNT-1
20720 A=ASC(PGM.BYTE$)
20730 NEXT.OFFSET!=A+(TWO.FIFTY.SIX!*ASC(HIGH.OFFSET.BYTE$))
20740 IF NEXT.OFFSET!<=FIRST.OFFSET! THEN REC.CNT=REC.CNT+1:GOTO 20560
20750 INITIAL.OFFSET!=FIRST.OFFSET!-(REC.CNT-3)
20760 CURRENT.OFFSET!=INITIAL.OFFSET!
20770 NEXT.OFFSET!=FIRST.OFFSET!
20780 PREVIOUS.OFFSET!=INITIAL.OFFSET!
20790 TYPE.READ=1
20800 GOTO 20830
20810 '
20820 TYPE.READ=0
20830 CLOSE
20840 READY.TO.RETURN=-1
20850 RETURN
20860 '
20870 DATA "END"
20880 DATA "FOR"
20890 DATA "NEXT"
20900 DATA "DATA"
20910 DATA "INPUT"
20920 DATA "DIM"
20930 DATA "READ"
20940 DATA "LET"
20950 DATA "GOTO"
20960 DATA "RUN"
20970 DATA "IF"
20980 DATA "RESTORE"
20990 DATA "GOSUB"
21000 DATA "RETURN"
21010 DATA "REM"
21020 DATA "STOP"
21030 DATA "PRINT"
21040 DATA "CLEAR"
21050 DATA "LIST"
21060 DATA "NEW"
21070 DATA "ON"
21080 DATA "WAIT"
21090 DATA "DEF"
21100 DATA "POKE"
21110 DATA "CONT"
21120 DATA "?"
21130 DATA "?"
21140 DATA "OUT"
21150 DATA "LPRINT"
21160 DATA "LLIST"
21170 DATA "?"
21180 DATA "WIDTH"
21190 DATA "ELSE"
21200 DATA "TRON"
21210 DATA "TROFF"
21220 DATA "SWAP"
21230 DATA "ERASE"
21240 DATA "EDIT"
21250 DATA "ERROR"
21260 DATA "RESUME"
21270 DATA "DELETE"
21280 DATA "AUTO"
21290 DATA "RENUM"
21300 DATA "DEFSTR"
21310 DATA "DEFINT"
21320 DATA "DEFSNG"
21330 DATA "DEFDBL"
21340 DATA "LINE"
21350 DATA "WHILE"
21360 DATA "WEND"
21370 DATA "CALL"
21380 DATA "?"
21390 DATA "?"
21400 DATA "?"
21410 DATA "WRITE"
21420 DATA "OPTION"
21430 DATA "RANDOMIZE"
21440 DATA "OPEN"
21450 DATA "CLOSE"
21460 DATA "LOAD"
21470 DATA "MERGE"
21480 DATA "SAVE"
21490 DATA "COLOR"
21500 DATA "CLS"
21510 DATA "MOTOR"
21520 DATA "BSAVE"
21530 DATA "BLOAD"
21540 DATA "SOUND"
21550 DATA "BEEP"
21560 DATA "PSET"
21570 DATA "PRESET"
21580 DATA "SCREEN"
21590 DATA "KEY"
21600 DATA "LOCATE"
21610 DATA "?"
21620 DATA "TO"
21630 DATA "THEN"
21640 DATA "TAB("
21650 DATA "STEP"
21660 DATA "USR"
21670 DATA "FN"
21680 DATA "SPC("
21690 DATA "NOT"
21700 DATA "ERL"
21710 DATA "ERR"
21720 DATA "STRING$"
21730 DATA "USING"
21740 DATA "INSTR"
21750 DATA "'"
21760 DATA "VARPTR"
21770 DATA "CSRLIN"
21780 DATA "POINT"
21790 DATA "OFF"
21800 DATA "INKEY$"
21810 DATA "?"
21820 DATA "?"
21830 DATA "?"
21840 DATA "?"
21850 DATA "?"
21860 DATA "?"
21870 DATA "?"
21880 DATA ">"
21890 DATA "="
21900 DATA "<"
21910 DATA "+"
21920 DATA "-"
21930 DATA "*"
21940 DATA "/"
21950 DATA "^"
21960 DATA "AND"
21970 DATA "OR"
21980 DATA "XOR"
21990 DATA "EQV"
22000 DATA "IMP"
22010 DATA "MOD"
22020 DATA "\"
22030 DATA "?"
22040 DATA "?"
22050 DATA "?"
22060 DATA "?"
22070 DATA "?"
22080 DATA "?"
22090 DATA "?"
22100 DATA "?"
22110 DATA "LEFT$"
22120 DATA "RIGHT$"
22130 DATA "MID$"
22140 DATA "SGN"
22150 DATA "INT"
22160 DATA "ABS"
22170 DATA "SQR"
22180 DATA "RND"
22190 DATA "SIN"
22200 DATA "LOG"
22210 DATA "EXP"
22220 DATA "COS"
22230 DATA "TAN"
22240 DATA "ATN"
22250 DATA "FRE"
22260 DATA "INP"
22270 DATA "POS"
22280 DATA "LEN"
22290 DATA "STR$"
22300 DATA "VAL"
22310 DATA "ASC"
22320 DATA "CHR$"
22330 DATA "PEEK"
22340 DATA "SPACE$"
22350 DATA "OCT$"
22360 DATA "HEX$"
22370 DATA "LPOS"
22380 DATA "CINT"
22390 DATA "CSGN"
22400 DATA "CDBL"
22410 DATA "FIX"
22420 DATA "PEN"
22430 DATA "STICK"
22440 DATA "STRIG"
22450 DATA "EOF"
22460 DATA "LOC"
22470 DATA "LOF"
22480 DATA "FILES"
22490 DATA "FIELD"
22500 DATA "SYSTEM"
22510 DATA "NAME"
22520 DATA "LSET"
22530 DATA "RSET"
22540 DATA "KILL"
22550 DATA "PUT"
22560 DATA "GET"
22570 DATA "RESET"
22580 DATA "COMMON"
22590 DATA "CHAIN"
22600 DATA "DATE$"
22610 DATA "TIME$"
22620 DATA "PAINT"
22630 DATA "COM"
22640 DATA "CIRCLE"
22650 DATA "DRAW"
22660 DATA "PLAY"
22670 DATA "TIMER"
22680 DATA "IOCTL"
22690 DATA "MKDIR"
22700 DATA "SHELL"
22710 DATA "VIEW"
22720 DATA "PMAP"
22730 DATA "ERDEV"
22740 DATA "CHDIR"
22750 DATA "RMDIR"
22760 DATA "ENVIRON"
22770 DATA "WINDOW"
22780 DATA "CVI"
22790 DATA "CVS"
22800 DATA "CVD"
22810 DATA "MKI$"
22820 DATA "MKS$"
22830 DATA "MKD$"
22840 '
22850 DATA 158
22860 DATA "ABS",2
22870 DATA "AND",1
22880 DATA "ASC",3
22890 DATA "ATN",2
22900 DATA "AUTO",9
22910 DATA "BEEP",1
22920 DATA "BLOAD",9
22930 DATA "BSAVE",9
22940 DATA "CALL",4
22950 DATA "CDBL",1
22960 DATA "CHAIN",4
22970 DATA "CHR",3
22980 DATA "CINT",1
22990 DATA "CIRCLE",1
23000 DATA "CLEAR",1
23010 DATA "CLOSE",1
23020 DATA "CLS",1
23030 DATA "COLOR",1
23040 DATA "COM",1
23050 DATA "COMMON",4
23060 DATA "CONT",9
23070 DATA "COS",2
23080 DATA "CSNG",1
23090 DATA "CSRLIN",1
23100 DATA "CVD",1
23110 DATA "CVI",1
23120 DATA "CVS",1
23130 DATA "DATA",0
23140 DATA "DATE",1
23150 DATA "DEF",1
23160 DATA "DEFDBL",1
23170 DATA "DEFINT",1
23180 DATA "DEFSNG",1
23190 DATA "DEFSTR",1
23200 DATA "DELETE",9
23210 DATA "DIM",1
23220 DATA "DRAW",1
23230 DATA "EDIT",9
23240 DATA "ELSE",0
23250 DATA "END",1
23260 DATA "ENVIRON",1
23270 DATA "EOF",1
23280 DATA "EQV",1
23290 DATA "ERASE",1
23300 DATA "ERDEV",1
23310 DATA "ERL",1
23320 DATA "ERR",1
23330 DATA "ERROR",1
23340 DATA "EXP",2
23350 DATA "FIELD",1
23360 DATA "FILES",9
23370 DATA "FIX",1
23380 DATA "FOR",4
23390 DATA "FRE",1
23400 DATA "GET",1
23410 DATA "GOSUB",4
23420 DATA "GOTO",4
23430 DATA "HEX",3
23440 DATA "IF",1
23450 DATA "IMP",1
23460 DATA "INKEY",1
23470 DATA "INP",1
23480 DATA "INPUT",1
23490 DATA "INSTR",4
23500 DATA "INT",2
23510 DATA "IOCTL",1
23520 DATA "KEY",1
23530 DATA "KILL",9
23540 DATA "LEFT",3
23550 DATA "LEN",3
23560 DATA "LET",0
23570 DATA "LINE",1
23580 DATA "LIST",9
23590 DATA "LLIST",9
23600 DATA "LOAD",9
23610 DATA "LOC",1
23620 DATA "LOCATE",1
23630 DATA "LOF",1
23640 DATA "LOG",2
23650 DATA "LPOS",1
23660 DATA "LPRINT",1
23670 DATA "LSET",1
23680 DATA "MERGE",9
23690 DATA "MID",3
23700 DATA "MKD",3
23710 DATA "MKI",3
23720 DATA "MKS",3
23730 DATA "MOD",2
23740 DATA "MOTOR",1
23750 DATA "NAME",9
23760 DATA "NEW",9
23770 DATA "NEXT",4
23780 DATA "NOT",0
23790 DATA "OCT",3
23800 DATA "OFF",1
23810 DATA "ON",0
23820 DATA "OPEN",1
23830 DATA "OPTION",1
23840 DATA "OR",0
23850 DATA "OUT",1
23860 DATA "PAINT",1
23870 DATA "PEEK",1
23880 DATA "PEN",1
23890 DATA "PLAY",1
23900 DATA "PMAP",1
23910 DATA "POINT",1
23920 DATA "POKE",1
23930 DATA "POS",1
23940 DATA "PRESET",1
23950 DATA "PRINT",1
23960 DATA "PSET",1
23970 DATA "PUT",1
23980 DATA "RANDOMIZE",2
23990 DATA "READ",1
24000 DATA "REM",1
24010 DATA "RENUM",9
24020 DATA "RESET",1
24030 DATA "RESTORE",1
24040 DATA "RESUME",4
24050 DATA "RETURN",4
24060 DATA "RIGHT",3
24070 DATA "RND",2
24080 DATA "RSET",1
24090 DATA "RUN",4
24100 DATA "SAVE",9
24110 DATA "SCREEN",1
24120 DATA "SGN",2
24130 DATA "SHELL",1
24140 DATA "SIN",2
24150 DATA "SOUND",1
24160 DATA "SPACE",3
24170 DATA "SPC",3
24180 DATA "SQR",2
24190 DATA "STEP",0
24200 DATA "STICK",1
24210 DATA "STOP",1
24220 DATA "STR",3
24230 DATA "STRIG",1
24240 DATA "STRING",1
24250 DATA "SWAP",1
24260 DATA "SYSTEM",9
24270 DATA "TAB",0
24280 DATA "TAN",2
24290 DATA "THEN",0
24300 DATA "TIME",1
24310 DATA "TO",0
24320 DATA "TROFF",1
24330 DATA "TRON",1
24340 DATA "USING",1
24350 DATA "USR",4
24360 DATA "VAL",3
24370 DATA "VARPTR",1
24380 DATA "WAIT",1
24390 DATA "WEND",1
24400 DATA "WHILE",1
24410 DATA "WIDTH",1
24420 DATA "WRITE",1
24430 DATA "XOR",0
24440 END
BASICAID
THE BASIC PROGRAMMERS FRIEND
VERSION 2.0
MAY, 1984
(SUPERCEEDS V1.0 dated 1983)
A Soft-SHARE product
BY
JAMES P. MORGAN
1749 AMERICANA BLVD APT 23-G
ORLANDO FLA. 32809
PH 305-826-7297
THIS IS A MAJOR ENHANCEMENT OF V1.0, I HAVE DEBUGGED IT AS MUCH AS MY LIMITED
TIME WILL PERMIT. IF YOU ENCOUNTER ANY BUGS OR PROBLEMS PLEASE DROP A LINE. I
WILL RESPOND WITH ANY FIXES OR UPDATES AS SOON AS POSSIBLE. VERSION 2.0 NOW
ALLOWS A TOKENIZED BASIC PROGRAM TO BE USED AS INPUT (WITHOUT THE ',P' OPTION).
WILL STILL TAKE AN ASCII SAVED VERSION (WITH ',A' OPTION) AS INPUT.
HAVE YOU EVER ACQUIRED A BASIC PROGRAM FROM A FRIEND AND SPENT ALOT OF
TIME JUST TRYING TO UNTANGLE THE PROGRAM LOGIC AND STATEMENTS, OF COURSE YOU
HAVE.
SINCE EACH PERSONS PROGRAMMING STYLE IS DIFFERENT , SUCH AS SPACING, INDEN-
TATION AND SUCH, YOU COULD USE YOUR TIME BETTER IF ALL PROGRAMS WERE ABOUT
THE SAME STYLE.
ARE YOU A OPTIMIZATION AND SPEED NUT , AS I AM, ESPECIALLY WHEN RUNNING
A PROGRAM UNDER THE INTERPRETER. I DONT'T LIKE TO WAIT A SECOND LONGER THAN
NECESSARY. OF COURSE BY NOW I USE THE BASIC COMPILER AS MUCH AS POSSIBLE,
SINCE I WOULD RATHER WAIT 2 MINUTES THAN HAVE TO WAIT 20 MINUTES TO SEE
THE RESULTS OF MY SWEAT , BLOOD AND LOST SLEEP.
I HAVE SEEN SEVERAL PACKAGES , NOT ALL WITH THE SAME FUNCTIONS OR
RANGE SELLING FROM 20 TO 80 DOLLARS. WELL THIS IS 1 YEARS WORTH OF WORK
, TO YOU FOR FREE ,IF YOU DESIRE.
YOU ASK WHAT WILL THIS PROGRAM DO FOR ME, PAY MY TAXES MAYBE. WELL
NO, IT WON'T PAY YOUR TAXES BUT IT SHOULD MAKE YOUR LIFE A LITTLE EASIER.
AS A BASIC OVERVIEW THE PROGRAM WILL, COMPRESS A BASIC PROGRAM AND REMOVE
REMARKS, EXPAND A PROGRAM BY THAT I MEAN IT WILL SEPARATE MULTIPLE STATEMENTS
PER BASIC LINE INTO ONE OR MORE STATEMENTS, GENEREATE CROSS REFERENCES ON
PROGRAM VARIABLES AND BASIC RESERVED WORDS, AND PROBABLY THE MOST IMPORTANT
WILL GENERATE A CROSS REFERENCE SHOWING ALL REFERENCES TO A SPECIFIC LINE NUMBER,
THAT WERE REFERENCED BY A GOTO,GOSUB,ELSE,THEN,ERL,RESTORE OR RESUME STATEMENT.
YOU CAN THEN FIND ALL VARIABLES, AREAS OF CODE AND SUCH THAT ARE NOT
REFERENCED (AND REMOVE FOR STORAGE SAVINGS) AS WELL AS AN OVERVIEW OF
PROGRAM FLOW TO FIND OUT HOW THE PROGRAM GOT TO A SPECIFIC LINE NUMBER.
EACH FUNCTIONAL OPTION OF THE PROGRAM IS DISCUSSED BELOW:
1). EXPAND A BASIC PROGRAM
----------------------
WILL EXPAND A COMPRESSED PROGRAM, ONE THAT HAS MULTIPLE
BASIC STATEMENTS PER LINE, SEPARATED BY A ":" INTO ONE OR
MORE UNIQUELY NUMBERED BASIC LINES WITH ONE OR MORE STATEMENTS
PER LINE.
DURING THE EXPANDING SOME TEXT COMPRESSION WILL BE DONE,
TO REMOVE EXTRANEOUS SPACES AND SUCH.
ALSO AN EXPANDED LISTING CAN BE REQUESTED, THAT WILL BE PRINTED
DURING THE EXPANSION.
AN EXPANDED, OUTPUT DISK FILE, CALLED "TEMPFILE.BAS" WILL
BE CREATED ALSO. RENAME THE "TEMPFILE.BAS" IF YOU WANT TO SAVE
IT AS THE NEW VERSION OF YOUR PROGRAM.
NOTE THAT THE INPUT BASIC PROGRAM BEING EXPANDED MUST BE
SUFFICIENTLY SEQUENCED TO ALLOW THE INSERTION OF NEW LINES
OR THE PROGAM WILL END WITH SUCH A MESSAGE. FOR EXAMPLE IF
THERE ARE 7 BASIC STATEMENTS ON A LINE, SEPARATED BY ":",
THEN IF THE ORIGINAL PROGRAM WAS NUMBER BY 5'S THE PROGRAM
WILL SEPARATE THE LINE INTO 6 MORE BASIC LINES EACH WITH A
LINE NUMBER 1 GREATER THAN THE PREVIOUS LINE NUMBER.
IF YOU ARE PROCESSING AN UNNUMBERED BASIC PROGRAM, OR ONE
GENERATED WITH UNREFERENCED LINE NUMBERS REMOVED, A NEW LINE
NUMBER WILL BE ASSIGNED TO THE UNNUMBERED STATEMENT.
2). COMPRESS A BASIC PROGRAM
------------------------
WILL COMPRESS TEXT (REMOVE EXTRANEOUS SPACES AND ":" AND SUCH)
AS WELL AS COMBINE SEPARATE BASIC LINES INTO SINGLE LINES WITH
AS MANY LOGICAL STATEMENTS PER LINE AS POSSIBLE, OR OPTIONALLY
REMOVE UNREFREENCED LINE NUMBERS FROM THE COMPRESSED PROGRAM
FOR USE WITH "/N" OPTION OF THE BASIC COMPILER.
BY LOGICAL I MEAN THAT ANY "REMARK" OR "IF" OR "DATA" STATEMENTS
WILL NOT HAVE LINES ADDED TO THEM.
ALSO ANY LINE REFERENCED BY A LOGIC BRANCH (GOTO,GOSUB..ECT) WILL
NOT BE APPENDED TO ANY OTHER LINE.
YOU MAY REQUEST A LISTING OF THE COMPRESSED PROGRAM BE PRODUCED
DURING THE COMPRESSION RUN, BUT WILL SLOW THE PROGRAM DOWN, UNLESS
YOU HAVE A SPOOLER.
A COMPRESSED PROGRAM , DISK FILE, NAMED "TEMPCOMP.BAS" IS
CREATED. DON'T FORGET TO RENAME "TEMPCOMP.BAS" IF YOU WANT IT
TO BE YOUR NEW WORKING VERSION.
ALSO , FOR VERSION 2.0, A TEMP. EXPANDED FILE , "TEMPFILE.BAS",
IS ALSO CREATED TO SPEED UP THE COMPRESS LOGIC SO THAT IS WILL NOT
HAVE TO REPEAT THE EXPANSION LOGIC AND DO AS MUCH ERROR CHECKING.
3). DATANAME AND RESERVED WORD CROSS REFERENCE
------------------------------------------
WILL PRINT A CROSS REFERENCE OF BASIC RESERVED WORDS (SUCH AS
GOTO,PRINT,CALL..ECT). RESERVED WORDS CAN BE ADDED OR DELETED
BY CHANGING THE PROGRAM DATA STATEMENTS AT THE END OF THE PROGRAM.
AS YOU ADD OR DELETE RESERVED WORDS KEEP THEM IN ALPHABETIC ORDER,
SINCE THE PROGRAM TABLES THEM AND DOES A BINARY SEARCH ON THE TABLE.
ALSO CHANGE THE FIRST DATA STATEMENT, THIS IS A COUNT OF THE NUMBER
OF RESERVED WORDS TO READ AND "DIM" TABLES.
YOU WILL SEE A NUMERIC VALUE AFTER EACH RESERVED WORD ON THE DATA
STATEMENTS. IF THE VALUE IS ZERO THE RESERVED WORD WILL BE RECOGNI-
ZED AS SUCH BUT ANY REFERENCES WILL BE IGNORED AND NOT PRINTED.
THERE ARE SEVERAL NUMERIC VALUES, AFTER THE RESERVED WORDS.
I STARTED TO GROUP THE WORDS ACCORDING TO TYPE AND FUNCTION (
I/O,BRANCH,STRING,FUNCTION..ECT) AND PROVIDE AND OPTION AS TO WHAT
FUNCTIONAL CLASS OF RESERVED WORDS WOULD BE X-REFERENCED. YOU MAY
IMPLEMENT THIS IF YOU DESIRE.
FOR EXAMPLE, IT WOULD BE NICE TO SEE A X-REFERENCE OF ONLY
LOGIC BRANCH VERBS (GOTO,GOSUB,CALL...ECT), THEN YOU COULD SEE
WHERE PROGRAM CONTROL WOULD BE TRANSFERED TO.
WILL PRINT A CROSS REFERENCE (ASCENDING ON VARIABLE NAME) OF ALL
USER DEFINED PROGRAM VARIABLES.
THIS WOULD BE GREAT FOR FINDING STATEMENTS THAT DEFINE OR MODIFY
A VARIABLE.
ANY TYPE OF BASIC EXPLICIT VARIABLE STATE ,SUCH AS "!" OR "#" OR
"%" OR "$" ARE IGNORED, ONLY THE VARIABLE NAME WHICH CONSISTS OF THE
CHARACTERS "A-Z","." AND "0-9" ARE CONSIDERED A UNIQUE NAME.
YOU MAY HAVE NOTICED THAT A VARIABLE NAME MAY BE DEFINED AS BEING
ONE OF SEVERAL VARIABLE TYPES. FOR EXAMPLE "A!" , "A#" , "A%", "A$"
, "A(" WHERE "A(" IS PART OF A "DIM", WOULD ALL BE RECOGNIZED TO THE
CROSS REFERENCE AS THE SAME VARIABLE, BUT DIFFERENT BY BASIC.
OH BY THE WAY, YOU MAY DEFINE A VARIABLE WITH A TERMINATING "."
TO ALSO MAKE IT UNIQUE. FOR EXAMPLE "SPACES" IS A RESERVED WORD,
BUT "SPACES." OR "SPACES.$" OR "SPACES.%" ARE PROCESSED BY BASIC
AS USER DEFINED VARIABLES. I JUST DISCOVERED IT AND THOUGHT IT
WAS A NEAT WAY TO GET AROUND SOME RESTRICTIONS.
ALSO YOU COULD HAVE THE FOLLOWING CODE AND IT WOULD WORK:
10 DIM A(10)
20 A=0
30 FOR A=1 TO 10
40 A(A)=A
50 NEXT A
60 END
CONFUSING BUT NEAT, HUH.
4). LINE NUMBER CROSS REFERENCE
---------------------------
WILL PRODUCE A (ASCENDING BY LINE NUMBER) CROSS REFERENCE,
LISTING ANY LINE NUMBER THAT WAS REFERENCE BY ANOTHER LINE NUMBER
AND THE REFERENCING LINE NUMBER.
THIS LINE NUMBER CROSS REFERENCE TABLE IS ALSO USED IN THE
OPTION TO COMPRESS A PROGRAM. SO THAT WE DONT THROW AWAY "REMARK"
LINES THAT ARE BRANCHED TO.
YOU SHOULD USE THE LISTINGS PRODUCED TO CHANGE THE PROGRAM LOGIC
SUCH THAT IS DOES NOT BRANCH TO ANY NON-EXECUTABLE BASIC STATEMENTS.
THEY JUST SLOW THE PROGRAM DOWN AND MAKE IT HARD TO CHANGE LOGIC
SINCE REMOVING A REMARK MIGHT CAUSE AN ERROR, DURING RUN TIME OR
RENUMBERING.
I AM ALL FOR ALOT OF COMMENTS IN A PROGRAM, SINCE I HARDLY EVER
REMEMBER WHAT THE PROGRAM DOES, IF I PICK IT UP 6 MONTHS LATER,
OR I TRY TO MODIFY SOMEONE ELSES PROGRAM.
ALSO THE REMARKS TAKE UP PART OF THE "64K" THAT BASIC RUNS IN, SINCE
THEY ARE STORED EXACTLY AS SEEN ON THE SCREEN, NOT IN ANY TOKENIZED
FORM.
ALSO NOT BRANCHING TO "REMARKS" WILL ALLOW THE COMPRESS OPTION
TO REMOVE THAT STATEMENT FROM THE OUTPUT COMPRESSED FILE.
THIS RESULTS IN SAVINGS IN MEMORY WHEN THE PROGRAM IS STORED OR
LOADED, BUT PRIMARILY WHEN USING THE BASIC COMPILER.
THE BASIC COMPILER MAINTAINS A LINK LIST OF LINE NUMBERS. IF YOU
DO ANY TYPE OF "ON ERROR" CHECKING IN YOUR BASIC PROGRAM, EACH LINE
NUMBER , UNDER THESE CONDITIONS , RESULTS IN 4 OR MORE BYTES TO BE
USED IN THE ".OBJ" (OBJECT) FILE CREATED BY THE COMPILE. YOU COULD SEE
WHY COMPRESSING THE PRODUCION VERSION OF THE PROGRAM COULD RESULT IN
MEMORY AND SPEED SAVINGS.A LINK LIST MUST BE SEARCH AND IF YOUR PROGAM
WAS 500 LINES THEN (500 * (4+)) BYTES MUST BE USED JUST TO MAINTAIN
THE LINE NUMBER LIST. ALSO IF YOU RUN INTO THE OLD "0 BYTES REMAINING"
MESSAGE, COMPRESSING WITH THE OPTION TO REMOVE UNREFERENCED LINE
NUMBERS (ESPECIALLY WITH /E/X OPTIONS) RESULTS IN A LARGE SAVING,
SUCH THAT MANY TIMES TOU CAN WRITE A LARGER PROGRAM.
**************************************************************************
MACHINE REQUIREMENTS: 64K MINIMUM
--------------------- BASIC
MONOCROME/COLOR DISPLAY
DISK DRIVE [REAL AND/OR VIRTUAL(RAM)]
MX-80 EPSON PRINTER (OPTIONAL)
RUNNING THE PROGRAM:
--------------------
TO RUN USING BASIC ---- INVOKE BASIC FROM DOS AND LOAD AND RUN
WHILE IN DOS KEY IN --- BASIC/F:3/C:0
IF PROGRAM COMPILED--- THEN JUST TYPE IN THE PROGRAM NAME YOU
GIVE IT WHEN YOU LINKED THE PROGRAM
ADDITIONAL COMMENTS:
--------------------
IF YOU COMPILE THIS PROGRAM YOU MUST CHANGE
ANY "DIM" STATEMENTS TO A FIXED VALUE, ALSO
DONT FORGET TO CHANGE THE ASSOCIATED "DIM"
VARIABLE NAME TO AGREE WITH THE FIXED VALUE
YOU ASSIGN TO THE ARRAY.
ALSO CHANGE THE STRING VARAIBLE "VER$" TO
A "C" TO INDICATE THE PROGRAM IS RUNNING AS
COMPILED, SINCE THE PROGRAM DOES POKE INTO
SOME BASIC AREAS ( TO CLEAR KEYBOARD BUFFER)
THAT ARE NOT THERE AFTER THE PROGRAM HAS BEEN
COMPILED. YOU ARE ASKING FOR TROUBLE IF YOU DON'T.
***************************************************************************
IN CLOSING
----------
I WOULD APPRECIATE ANY COMMENTS AS TO ENHANCEMENTS, BUGS, OR GENERAL
USAGE.
THIS IS A PRODUCT of Soft-SHARE (tm) and A $10 CONTRIBUTION IS ASKED BUT
IS NOT REQUIRED..PLEASE PASS THE PROGRAM ON IN ITS UNMODIFIED VERSION
ONLY.
I HOPE THIS LITTLE CONTRIBUTION WILL HELP YOU.
This disk copy was originally provided by "The Public Library",
the software library of the Houston Area League of PC Users.
Programs are available from the Public Library at $2 per disk
on user-provided disks. To get a listing of the disks in the
Public Library, send a self-addressed, stamped envelope to
Nelson Ford, P.O.Box 61565, Houston, TX 77208.
------------------------------------------------------------------------
Disk No 381 BASIC Aids V1 DS
------------------------------------------------------------------------
Useful programmers utilities and Tiny Basic programs.
BASICAID BAS BASIC source file for BASICAID.EXE.
BASICAID DOC Documentation for BASICAID.EXE.
BASICAID EXE Multi-fuction BASIC programmers utility.
BRENTBAS EXE A translator from a structured BASIC to Microsoft BASIC.
BRENTBAS UM BRENTBAS.EXE Users Manual.
TBASIC ASM Source code for TBASIC.COM.
TBASIC COM TINY BASIC language a very limited subset of the
Dartmouth BASIC language.
TBASIC DOC Documentation for TBASIC.COM.
PC Software Interest Group (PC-SIG)
1030 E Duane, Suite J
Sunnyvale, CA 94086
(408) 730-9291
;***************************************************************
;*
;*
;* TINY BASIC FOR INTEL 8086
;*
;*
;* VERSION: 1.1
;*
;* BY
;*
;* MICHAEL SULLIVAN
;* BASED
;* ON
;* LI-CHEN WANG'S
;*
;* 8080 TINY BASIC
;*
;*
;* 27 JUNE 1982
;*
;* @COPYLEFT
;* ALL WRONGS RESERVED
;*
;* NOTE:
;* 8080 REGISTERS HAVE BEEN MAPPED AS FOLLOWS:
;*
;* 8080 8086
;* -------------------------------------
;*
;* BC <-> CX
;* DE <-> DX
;* HL <-> BX
;*
;*
;* VERS 1.1 - SUPPORT MS-DOS INTERUPT I/O
;* IMPROVE RND ACTION
;* SUPPORT TIME AND DATE FROM MS-DOS
;*
;**************************************************************
;
;
ORG 100H ;STANDARD MS-DOS START ADDR.
START:
MOV SP,STACK ;SET UP STACK
MOV DX,MSG1 ;GET SIGN-ON MSG
CALL PRTSTG ;SEND IT
MOV B,[BUFFER-2],80H ;INIT CMD LINE BUFFER
;
; MAIN
;
; THIS IS THE MAIN LOOP THAT COLLECTS THE TINY BASIC PROGRAM
; AND STORES IT IN MEMORY.
;
; AT START, IT PRINTS OUT "(CR)OK(LF)", AND INITIALIZES THE
; STACK AND SOME OTHER INTERNAL VARIABLES. THEN IT PROMPTS
; ">" AND READS A LINE. IF THE LINE STARTS WITH A NONZERO
; NUMBER, THIS NUMBER IS THE LINE NUMBER. THE LINE NUMBER
; (IN 16 BIT BINARY) AND THE REST OF THE LINE (INCLUDING
; ITS (CR))IS STORED IN MEMORY. IF A LINE WITH THE SAME
; LINE NUMBER IS ALREADY THERE, IT IS REPLACED BY THE NEW
; ONE. IF THE REST OF THE LINE CONSISTS OF A (CR) ONLY, IT
; IS STORED AND ANY EXISTING LINE WITH THE SAME LINE
; NUMBER IS DELETED.
;
; AFTER A LINE IS INSERTED, REPLACED, OR DELETED, THE
; PROGRAM LOOPS BACK AND ASKS FOR ANOTHER LINE. THIS LOOP
; WILL BE TERMINATED WHEN IT READS A LINE WITH ZERO OR NO
; LINE NUMBER: CONTROL IS THEN TRANSFERED TO "DIRECT".
;
; THE TINY BASIC PROGRAM SAVE AREA STARTS AT THE MEMORY
; LOCATION LABELED "TXTBGN" AND ENDS AT "TXTEND". WE ALWAYS
; FILL THIS AREA STARTING AT "TXTBGN", THE UNFILLED PORTION
; POINTED TO BY THE CONTENTS OF THE MEMORY LOCATION LABELED
; "TXTUNF".
;
; THE MEMORY LOCATION "CURRNT" POINTS TO THE LINE NUMBER
; THAT IS CURRENTLY BEING INTERPRETED. WHILE WE AR IN THIS
; LOOP OR WHILE WE ARE INTERPRETING A DIRECT COMMAND
; (SEE NEXT SECTION), "CURRNT" SHOULD POINT TO A 0.
;
RSTART:
MOV SP,STACK ;SET STACK POINTER
ST1:
CALL CRLF
MOV DX,OK ;DE->STRING
SUB AL,AL
CALL PRTSTG ;PRINT PROMPT
MOV W,[CURRNT],0 ;CURRENT LINE # = 0
ST2:
MOV W,[LOPVAR],0
MOV W,[STKGOS],0
ST3:
MOV AL,'>' ;PROMPT ">" NOW
CALL GETLN ;READ A LINE
PUSH DI ;DI -> END OF LINE
ST3A:
MOV DX,BUFFER ;DX -> BEGINNING OF LINE
CALL TSTNUM ;TEST IF IT'S A NUMBER
MOV AH,0
CALL IGNBLNK
OR BX,BX ;BX:= VALUE OF # OR 0 IF NO # FOUND
POP CX ;CX -> END OF LINE
JNZ ST3B
JMP DIRECT
ST3B:
DEC DX
DEC DX
MOV AX,BX ;GET LINE #
MOV DI,DX
STOW ;VALUE OF LINE # THERE
PUSH CX
PUSH DX ;BX,DX -> BEGIN,END
MOV AX,CX
SUB AX,DX
PUSH AX ;AX:= # BYTES IN LINE
CALL FNDLN ;FIND THIS LINE IN SAVE
PUSH DX ;AREA, DX -> SAVE AREA
JNZ ST4 ;NZ:NOT FOUND, INSERT
PUSH DX ;Z:FOUND, DELERE IT
CALL FNDNXT ;FIND NEXT LINE
;DE -> NEXT LIE
POP CX ;CX -> LINE TO BE DELETED
MOV BX,[TXTUNF] ;BX -> UNFILLED SAVE AREA
CALL MVUP ;MOVE UP TO DELETE
MOV BX,CX ;TXTUNF -> UNFILLED AREA
MOV [TXTUNF],BX ;UPDATE
ST4:
POP CX ;GET READY TO INSERT
MOV BX,[TXTUNF] ;BUT FIRST CHECK IF
POP AX ;AX = # CHARS IN LINE
PUSH BX ;IS 3 (LINE # AND CR)
CMP AL,3 ;THEN DO NOT INSERT
JZ RSTART ;MUST CLEAR THE STACK
ADD AX,BX ;COMPUTE NEW TSTUNF
MOV BX,AX ;BX -> NEW UNFILLED AREA
ST4A:
MOV DX,TXTEND ;CHECK TO SEE IF THERE
CMP BX,DX ;IS ENOUGH SPACE
JC ST4B ;SORRY, NO ROOM FOR IT
JMP QSORRY
ST4B:
MOV [TXTUNF],BX ;OK, UPDATE TXTUNF
POP DX ;DX -> OLD UNFILLED AREA
CALL MVDOWN
POP DX ;DX -> BEGIN, BX -> END
POP BX
CALL MVUP ;MOVE NEW LINE TO SAVE AREA
JP ST3
TSTV: MOV AH,64 ;TEST VARIABLES
CALL IGNBLNK
JC RET
TSTV1:
JNZ TV1 ;NOT @ ARRAY
CALL PARN ;@ SHOULD BE FOLLOWED
ADD BX,BX
JNC SS1B ;IS INDEX TOO BIG?
JMP QHOW
SS1B: PUSH DX ;WILL IT OVERWRITE
XCHG DX,BX ;TEXT?
CALL SIZE ;FIND SIZE OF FREE
CMP BX,DX ;AND CHECK THAT
JNC SS1A ;IFF SO, SAY "SORRY"
JMP ASORRY
SS1A:
MOV BX,VARBGN ;IFF NOT, GET ADDRESS
SUB BX,DX ;OF @(EXPR) AND PUT IT
POP DX ;IN HL
RET ;C FLAG IS CLEARED
TV1:
CMP AL,27 ;NOT @, IS IT A TO Z?
CMC:
;IFF NOT, RETURN C FLAG
JC RET ;IFF NOT, RETURN C FLAG
INC DX
TV1A:
MOV BX,VARBGN ;COMPUTE ADDRESS OF
MOV AH,0 ;CLEAR UPPER BYTE
ADD AX,AX ;AX:=AX*2 (WORD STORAGE)
ADD BX,AX ;BX:=VARBGN+2*AL
RET ;USE CARRY AS ERROR INDICATOR
;
; TSTNUM - AT ENTRY DX -> BUFFER OF ASCII CHARACTERS
;
TSTNUM:
MOV BX,0 ;****TSTNUM****
MOV CH,BH ;TEST IFF THE TEXT IS
MOV AH,0 ;FOR CMP IN IGNBLNK
CALL IGNBLNK ;A NUMBER.
TN1:
CMP AL,'0' ;IFF NOT, RETURN 0 IN
JC RET ;B AND HL
CMP AL,':' ;IFF NUMBERS, CONVERT
JNC RET ;TO BINARY IN BX AND
MOV AL,0F0H ;SET AL TO # OF DIGITS
AND AL,BH ;IFF BH>255, THERE IS NO
JNZ QHOW ;ROOM FOR NEXT DIGIT
INC CH ;CH COUNTS NUMBER OF DIGITS
PUSH CX
MOV AX,BX ;BX:=10*BX+(NEW DIGIT)
MOV CX,10
PUSH DX ;SAVE DX
MUL AX,CX
MOV BX,AX ;PARTIAL RESULT NOW IN BX
POP DX ;RESTORE
MOV SI,DX
LODB ;ASCII DIGIT IN AL NOW
SUB AL,48 ;CONVERT TO BINARY
MOV AH,0
ADD BX,AX ;FULL RESULT NOW IN BX
POP CX
LODB ;REPEAT FOR MORE DIGITS
LAHF ;SAVE FLAGS
INC DX
SAHF ;RESTORE FLAGS
JNS TN1 ;QUIT IF NO NUM OR OVERFLOW
QHOW:
PUSH DX ;****ERROR: "HOW?"****
AHOW:
MOV DX,HOW
JMP ERROR
HOW:
DB 'HOW?',0DH
OK:
DB 'OK',0DH
WHAT:
DB 'WHAT?',0DH
SORRY:
DB 'SORRY',0DH
;
;*
;**********************************************************
;*
;* *** TABLES *** DIRECT *** & EXEC ***
;*
;* THIS SECTION OF THE CODE TESTS A STRING AGAINST A TABLE.
;* WHEN A MATCH IS FOUND, CONTROL IS TRANSFERRED TO THE SECTION
;* OF CODE ACCORDING TO THE TABLE.
;*
;* AT 'EXEC' DX SHOULD POINT TO THE STRING AND BX SHOULD POINT
;* TO THE TABLE-1. AT 'DIRECT', DX SHOULD POINT TO THE STRING,
;* BX WILL BE SET UP TO POINT TO TAB1-1, WHICH IS THE TABLE OF
;* ALL DIRECT AND STATEMENT COMMANDS.
;*
;* A '.' IN THE STRING WILL TERMINATE THE TEST AND THE PARTIAL
;* MATCH WILL BE CONSIDERED AS A MATCH. E.G., 'PR.',
;* 'PRI.', 'PRIN.', OR 'PRINT' WILL ALL MATCH 'PRINT'.
;*
;* THE TABLE CONSISTS OF ANY NUMBER OF ITEMS. EACH ITEM
;* IS A STRING OF CHARACTERS WITH BIT 7 SET TO 1 IN LAST CHAR
;* A JUMP ADDRESS IS STORED FOLLOWING EACH CHARACTER ENTRY.
;*
;* END OF TABLE IS AN ITEM WITH A JUMP ADDRESS ONLY. IF THE
;* STRING DOES NOT MATCH ANY OF THE OTHER ITEMS, IT WILL
;* MATCH THIS NULL ITEM AS DEFAULT. THE DEFAULT IS INDICATED
;* BY FOLLOWING THE 80H DEFAULT INDICATOR.
;*
TAB1: EQU $ ;DIRECT COMMANDS
DM 'LIST'
DW LIST ;EXECUTION ADDRESSES
DM 'EDIT'
DW EDIT
DM 'E'
DW EDIT ;HAVE SHORT FORM DEFINED ALSO
DM 'RUN'
DW RUN
DM 'NEW'
DW NEW
DM 'LOAD'
DW DLOAD
DM 'SAVE'
DW DSAVE
DM 'BYE' ;GO BACK TO DOS (EXIT TBASIC)
DW BYE
TAB2: EQU $ ;DIRECT/STATEMENT
DM 'NEXT'
DW NEXT ;EXECUTION ADDRESSES
DM 'LET'
DW LET
DM 'OUT'
DW OUTCMD
DM 'POKE'
DW POKE
DM 'WAIT'
DW WAITCM
DM 'IF'
DW IFF
DM 'GOTO'
DW GOTO
DM 'GOSUB'
DW GOSUB
DM 'RETURN'
DW RETURN
DM 'REM'
DW REM
DM 'FOR'
DW FOR
DM 'INPUT'
DW INPUT
DM 'PRINT'
DW PRINT
DM 'STOP'
DW STOP
DB 128 ;SIGNALS END
;REMEMBER TO MOVE DEFAULT DOWN.
DW DEFLT ;LAST POSIBILITY
TAB4: EQU $ ;FUNCTIONS
DM 'RND'
DW RND
DM 'INP'
DW INP
DM 'PEEK'
DW PEEK
DM 'USR'
DW USR
DM 'ABS'
DW ABS
DM 'SIZE'
DW SIZE
DB 128 ;SIGNALS END
;YOU CAN ADD MORE FUNCTIONS BUT REMEMBER
;TO MOVE XP40 DOWN
DW XP40
TAB5: EQU $ ;"TO" IN "FOR"
DM 'TO'
TAB5A: DW FR1
DB 128
DW QWHAT
TAB6: EQU $ ;"STEP" IN "FOR"
DM 'STEP'
TAB6A: DW FR2
DB 128
DW FR3
TAB8: EQU $ ;RELATION OPERATORS
DM '>='
DW XP11 ;EXECUTION ADDRESS
DM '#'
DW XP12
DM '>'
DW XP13
DM '='
DW XP15
DM '<='
DW XP14
DM '<'
DW XP16
DB 128
DW XP17
;
; END OF PARSER ACTION TABLE
;
;
; AT ENTRY BX -> COMMAND TABLE (ABOVE)
; DX -> COMMAND LINE (I.E. "BUFFER")
;
DIRECT:
MOV BX,TAB1-1 ;***DIRECT***
;*
EXEC: EQU $ ;***EXEC***
EX0:
MOV AH,0
CALL IGNBLNK ;IGNORE LEADING BLANKS
PUSH DX ;SAVE POINTER
MOV SI,DX
EX1: LODB ;GET CHAR WHERE DX ->
INC DX ;PRESERVE POINTER
CMP AL,'.' ;WE DECLARE A MATCH
JZ EX4
INC BX
MOV AH,[BX]
AND AH,127 ;STRIP BIT 7
CMP AL,AH ;COMPARISON NOW EASY
JZ EX2
; NO MATCH - CHECK NEXT ENTRY
EX0A: CMP B,[BX],128 ;BYTE COMPARE
JNC EX0B
INC BX
JP EX0A
; AT THIS POINT HAVE LAST LETTER
EX0B: ADD BX,3 ;GET PAST EXECUTION ADDRESS
CMP B,[BX],128 ;FOUND DEFAULT?
JZ EX3A ;IF SO, EXECUTE DEFAULT
DEC BX ;CORRECT FOR PRE-INCREMENT
POP DX ;RESTORE POINTER
JP EX0 ;LOOK SOME MORE FOR A MATCH
EX4: INC BX
CMP B,[BX],128
JC EX4
JP EX3
;
EX3A: DEC SI
JP EX3 ;CORRECT SI FOR DEFAULT EXECUTION
EX2: CMP B,[BX],128 ;END OF RESERVED WORD?
JC EX1 ;NO - CHECK SOME MORE
; AT THIS POINT NEED TO GET EXECUTION ADDRESS
EX3: INC BX ;BX -> EXECUTION ADDRESS
POP AX ;CLEAR STACK
MOV DX,SI ;RESET POINTER
JMP [BX] ;DO IT
;*
;
;
; WHAT FOLLOWS IS THE CODE TO ECECUTE DIRECT AND STATEMENT COM-
; MANDS. CONTROL IS TRANSFERED TO THESE POINTS VIA THE COMMAND
; TABLE LOOKUP CODE OF 'DIRECT' AND 'EXEC' IN THE LAST SECTION.
; AFTER THE COMMAND IS EXECUTED, CONTROL IS TRANSFERRED TO
; OTHER SECTIONS AS FOLLOWS:
;
; FOR 'LIST','NEW', ANS 'STOP': GO BACK TO 'RSTART'
;
; FOR 'RUN',: GO EXECUTE THE FIRST STORED LINE IFF ANY; ELSE
; GO BACK TO RSTART.
;
; FOR 'GOTO' AND 'GOSUB': GO EXECUTE THE TARGET LINE.
;
; FOR 'RETURN' AND 'NEXT': GO BACK TO SAVED RETURN LINE.
;
; FOR ALL OTHERS: IFF 'CURRNT' -> 0, GO TO 'RSTART', ELSE
; GO EXECUTE NEXT COMMAND. (THIS IS DONE
; IN 'FINISH'.)
;
;
; ****NEW****STOP****RUN (& FRIENDS)****GOTO****
;
; 'NEW(CR)' SETS 'TXTUNF' TO POINT TO 'TXTBGN'
;
; 'STOP(CR)' GOES BACK TO 'RSTART'
;
; 'RUN(CR)' FINDS THE FIRST STROED LINE, STORES ITS ADDRESS
; (IN 'CURRNT'), AND START TO EXECUTE IT. NOTE THAT ONLY
; THOSE COMMANDS IN TAB2 ARE LEGAL FOR STORED PROGRAMS.
;
; THERE ARE THREE MORE ENTRIES IN 'RUN':
;
; 'RUNNXL' FINDS NEXT LINE, STORES ITS ADDR AND EXEC IT.
; 'RUNTSL' STORES THE ADDRESS OF THIS LINE AND EXECUTES IT
; 'RUNSML' CONTINUES THE EXECUTION ON SAME LINE.
;
; 'GOTO(EXPR)' EVALUATES THE EXPRESSION, FINDS THE TARGET LINE,
; AND JUMPS TO 'RUNTSL' TO DO IT.
;
; 'DLOAD' LOADS A NAMES PROGRAM FROM DISK (ANYNAME.TBI)
;
; 'DSAVE' SAVES A NAMES PROGRAM ON DISK
;
; 'FCBSET' SETS UP THE MSDOS FILE CONTROL BLOCK FOR SUBSEQUENT
; DISK I/O.
;
;
NEW:
MOV W,[TXTUNF],TXTBGN
;
STOP:
CALL ENDCHK ;****STOP(CR)****
JMP RSTART
;
RUN:
CALL ENDCHK ;****RUN(CR)****
MOV DX,TXTBGN ;FIRST SAVED LINE
;
RUNNXL:
MOV BX,0 ;****RUNNXL****
CALL FNDLNP ;FIND WHATEVER LINE
JNC RUNTSL ;C: PASSED TXTUNF, QUIT
JMP RSTART
;
RUNTSL:
XCHG DX,BX ;****RUNTSL****
MOV [CURRNT],BX ;SET 'CURRNT"->LINE #
XCHG DX,BX
INC DX
INC DX
;
RUNSML:
CALL CHKIO ;****RUNSML****
MOV BX,TAB2-1 ;FIND COMMAND IN TABLE 2
JMP EXEC ;AND EXECUTE IT
;
GOTO:
CALL EXP ;****GOTO(EXPR)****
PUSH DX ;SAVE FOR ERROR ROUTINE
CALL ENDCHK ;MUST FIND A 0DH (CR)
CALL FNDLN ;FIND THE TARGET LINE
JZ GT1 ;NO SUCH LINE #
JMP AHOW
GT1: POP AX
JP RUNTSL ;GO DO IT
;
; BDOS EQUATES (FOR MS-DOS)
;
BYE: EQU 0 ;BDOS EXIT ADDRESS
FCB: EQU 5CH
SETDMA: EQU 26
OPEN: EQU 15
READD: EQU 20
WRITED: EQU 21
CLOSE: EQU 16
MAKE: EQU 22
BCONIN: EQU 10 ;BUFFERED CONSOLE INPUT
DELETE: EQU 19
CONOUT: EQU 2 ;CONSOLE OUTPUT
CONST: EQU 11 ;CONSOLE STATUS
;
;
DLOAD:
MOV AH,0
CALL IGNBLNK ;IGNORE BLANKS
PUSH BX ;SAVE H
CALL FCBSET ;SET UP FILE CONTROL BLOCK
PUSH DX ;SAVE THE REST
PUSH CX ;SAVE THE REST
MOV DX,FCB ;GET FCB ADDR
MOV AH,OPEN ;PREPARE TO OPEN FILE
INT 33 ;CALL MS-DOS TO OPEN FILE
CMP AL,0FFH ;IS IT THERE?
JNZ DL1 ;NO, SEND ERROR
JMP QHOW
DL1: XOR AL,AL ;CLEAR A
MOV [FCB+32],AL ;START AT RECORD 0
MOV DX,TXTBGN ;GET BEGINNING
LOAD:
PUSH DX ;SAVE DMA ADDRESS
MOV AH,SETDMA
INT 33 ;CALL MS-DOS TO SET DAM ADDR
MOV AH,READD
MOV DX,FCB
INT 33 ;CALL MS-DOS TO READ SECTOR
CMP AL,1 ;DONE?
JC RDMORE ;NO, READ MORE
JZ LL1
LOAD1: JMP QHOW ;BAD READ OR NO DELIMITER
LL1: MOV AH,CLOSE
MOV DX,FCB
INT 33 ;CALL MS-DOS TO CLOSE FILE
POP BP ;DMA ADDR IN BP
SUB BP,100H ;BACKUP
MOV CX,100H ;MAX LOOPS
RDM1: INC BP ;PRE INC
CMP W,[BP],0 ;FOUND DELIMITER?
LOOPNZ RDM1 ;KEEP LOOKING
CMP CL,0 ;MAC LOOPS EXECUTED?
JZ LOAD1 ;GIVE ERROR IF SO
MOV [TXTUNF],BP ;UPDATE POINTER
POP CX ;GET OLD REG BACK
POP DX ;GET OLD REG BACK
POP BX ;GET OLD REG BACK
CALL FINISH ;FINISH
RDMORE:
POP DX ;GET DMA ADDR
MOV BX,80H ;GET 128
ADD BX,DX ;ADD IT TO DMA ADDR
XCHG DX,BX ;BACK IN D
JMP LOAD ;AND READ SOME MORE
;
DSAVE:
CMP W,[TXTUNF],TXTBGN ;SEE IF ANYTHING TO SAVE
JNZ DS1A
JMP QWHAT
DS1A:
MOV BP,[TXTUNF]
MOV W,[BP],0 ;SET DELIMITER
MOV AH,0
CALL IGNBLNK ;IGNORE BLANKS
PUSH BX ;SAVE BX
CALL FCBSET ;SETUP FCB
PUSH DX
PUSH CX ;SAVE OTHERS
MOV DX,FCB
MOV AH,DELETE
INT 33 ;CALL MS-DOS TO ERASE FILE
MOV DX,FCB
MOV AH,MAKE
INT 33 ;CALL MS-DOS TO MAKE A NEW ONE
CMP AL,0FFH ;IS THERE SPACE?
JNZ DS1
JMP QHOW ;NO, ERROR
DS1: XOR AL,AL ;CLEAR A
MOV [FCB+32],AL ;START AT RECORD 0
MOV DX,TXTBGN ;GET BEGINNING
SAVE:
PUSH DX ;SAVE DMA ADDR
MOV AH,SETDMA
INT 33 ;CALL MS-DOS TO SET DMA ADDR
MOV AH,WRITED
MOV DX,FCB
INT 33 ;CALL MS-DOS TO WRITE SECTOR
OR AL,AL ;SET FLAGS
JZ SS1 ;IF NOT ZERO, ERROR
JMP QHOW
SS1: POP DX ;GET DMA ADDR BACK
MOV AX,DX
CMP AX,[TXTUNF] ;SEE IF DONE
JZ SAVDON
JNC SAVDON ;JUMP IF DONE
WRITMOR:
MOV BX,80H
ADD BX,DX
XCHG DX,BX ;GET IT TO D
JP SAVE
SAVDON:
MOV AH,CLOSE
MOV DX,FCB
INT 33 ;CALL MS-DOS TO CLOSE FILE
POP CX ;GET REGS BACK
POP DX ;GET REGS BACK
POP BX ;GET REGS BACK
CALL FINISH
;
FCBSET:
MOV BX,FCB ;GET FCB ADDR
MOV B,[BX],0 ;CLEAR ENTRY TYPE
FNCLR:
INC BX
MOV B,[BX],' ' ;CLEAR TO SPACE
MOV AX,FCB+8
CMP AX,BX ;DONE?
JNZ FNCLR ;NO, DO IT AGAIN
INC BX
MOV B,[BX],'T' ;SET FILE TYPE TO 'TBI'
INC BX
MOV B,[BX],'B'
INC BX
MOV B,[BX],'I'
EXRC:
INC BX
MOV B,[BX],0
MOV AX,FCB+15
CMP AX,BX
JNZ EXRC ;NO, CONTINUE
MOV BX,FCB+1 ;GET FILENAME START
FN:
MOV SI,DX
LODB ;GET CHAR
CMP AL,0DH ;IS IT A 'CR'
JZ RET ;YES, DONE
CMP AL,'!' ;LEGAL CHAR?
JNC FN1 ;NO, SEND ERROR
JMP QWHAT
FN1: CMP AL,'[' ;AGAIN
JC FN2 ;DITTO
JMP QWHAT
FN2: MOV [BX],AL ;SAVE IT IN FCB
INC BX
INC DX
MOV AX,FCB+9
CMP AX,BX ;LAST?
JNZ FN ;NO, CONTINUE
RET ;TRUNCATE AT EIGHT CHARS
;
;
; ****LIST**** AND ****PRINT**** AND ****EDIT****
;
; LIST HAS TWO FORMS:
; 'LIST(CR)' LISTS ALL SAVED LINES
; 'LIST #(CR)' START LIST AT THIS LINE #
; YOU CAN STOP LISTING BY CONTROL C KEY
;
; PRINT COMMAND IS 'PRINT ....;' OR 'PRINT ....(CR)'
; WHERE '....' IS A LIST OF EXPRESIONS, FORMATS, BACKARROWS, AND
; STRINGS. THESE ITEMS ARE SEPERATED BY COMMAS.
;
; A FORMAT IS A POUND SIGN FOLLOWED BY A NUMBER. IT CONTROLS THE
; NUMBER OF SPACES THE VALUE OF AN EXPRESSION IS TO BE PRINTED.
; TED. IT STAYS EFFECTIVE FOR THE REST OF THE PRINT, UNLESS
; CHANGED BY ANOTHER FORMAT. IF NO FORMAT SPEC, 6 POSITIONS
; WILL BE USED.
;
; A STRING IS QUOTED IN A PAIR OF SINGLE QUOTES OR DOUBLE
; QUOTES.
;
; A BACK-ARROW MEANS GENERATE A (CR) WITHOUT (LF).
;
; A (CRLF) IS GENERATED AFTER THE ENTIRE LIST HAS BEEN PRINT OR
; IF THE LIST IS A NULL LIST. HOWEVER IF THE LIST ENDED WITH A
; COMMA, NO (CR) IS GENERATED.
;
;
LIST:
CALL TSTNUM ;TEST IFF THERE IS A #
CALL ENDCHK ;IFF NO # WE GET A 0
CALL FNDLN ;FIND THIS OR NEXT LINE
LS1:
JNC LS2 ;C: PASSED TXTUNF
JMP RSTART
LS2: CALL PRTLN ;PRINT THE LINE
CALL CHKIO ;SEE IF ^X OR ^C
CALL FNDLNP ;FIND NEXT LINE
JP LS1 ;LOOP BACK
;
;
EDIT:
CALL TSTNUM ;TEST IF THERE IS A #
CALL ENDCHK ;AT END?
CALL FNDLN ;FIND SPEC LINE OR NEXT LINE
PUSH DX ;SAVE LINE #
JNC ED2 ;C: PASSED TXTUNF
POP DX ;THROW AWAY LINE #
ED1: JMP RSTART
ED2:
CALL PRTLN ;PRINT THE LINE
POP DX ;GET LINE # BACK
MOV B,[OCSW],0 ;DIRECT OUTPUT TO BUFFER
MOV B,[BUFFER-1],0 ;CLEAR CHAR COUNT
MOV B,[PRTLN1+1],4 ;PRINT ONE LESS SPACE
MOV DI,BUFFER ;PREPARE TO MOVE
CALL PRTLN
MOV B,[OCSW],0FFH ;REDIRECT OUTPUT TO CONSOLE
DEC [BUFFER-1] ;AVOID CR?
MOV B,[PRTLN1+1],5 ;RESTORE PRTLN
JMP ST3 ;PROMPT AND GETLINE ONLY
PRINT:
MOV CL,6 ;C:= # OF SPACES
MOV AH,';' ;CHECK FOR ';' IN IGNBLNK
CALL IGNBLNK ;IGNORE BLANKS
JNZ PR2 ;JUMP IF ';' NOT FOUND
CALL CRLF ;GIVE CR,LF AND
JMP RUNSML ;CONTINUE SAME LINE
PR2:
MOV AH,0DH
CALL IGNBLNK
JNZ PR0
CALL CRLF ;ALSO GIVE CRLF AND
JMP RUNNXL ;GOTO NEXT LINE
PR0:
MOV AH,'#'
CALL IGNBLNK
JNZ PR1
CALL EXP ;YES, EVALUATE EXPR
MOV CL,BL ;AND SAVE IT IN C
JP PR3 ;LOOK FOR MORE TO PRINT
PR1:
CALL QTSTG ;OR IS IT A STRING?
JP PR8 ;IFF NOT, MUST BE EXPRESSION
PR3:
MOV AH,','
CALL IGNBLNK
JNZ PR6
CALL FIN ;IN THE LIST
JP PR0 ;LIST CONTINUES
PR6:
CALL CRLF ;LIST ENDS
CALL FINISH
PR8:
CALL EXP ;EVAL THE EXPR
PUSH CX
CALL PRTNUM ;PRINT THE VALUE
POP CX
JP PR3 ;MORE TO PRINT?
;
;
; ****GOSUB**** AND ****RETURN****
;
; 'GOSUB (EXPR);' OR 'GOSUB EXPR(CR)' IS LIKE THE 'GOTO' COMMAND
; EXCEPT THAT THE CURRENT TEXT POINTER, STACK POINTER ETC. ARE
; SAVED SO THAT EXECUTION CAN BE CONTINUED AFTER THE SUBROUTINE
; 'RETURN'. IN ORDER THAT 'GOSUB' CAN BE NESTED (AND EVEN RECUR-
; SIVE), THE SAVE AREA MUST BE STACKED. THE STACK POINTER IS
; SAVED IN 'STKGOS'. THE OLD 'STKGOS' IS SAVED IN THE STACK. IF
; WE ARE IN THE MAIN ROUTINE, 'STKGOS' IS ZERO (THIS WAS DONE BY
; THE "MAIN" SECTION OF THE CODE), BUT WE STILL SAVE IT AS
; A FLAG FOR NO FURTHER RETURNS.
;
; 'RETURN(CR)' UNDOES EVERYTHING THAT 'GOSUB' DID, AND THUS RE-
; TURNS THE EXECUTION TO THE COMMAND AFTER THE MOST RECENT 'GO-
; SUB'. IFF 'STKGOS' IS ZERO, IT INDICATES THAT WE NEVER HAD A
; 'GOSUB' AND IS THUS AN ERROR.
;
;
GOSUB:
CALL PUSHA ;SAVE THE CURRENT 'FOR'
CALL EXP ;PARAMETERS
PUSH DX
CALL FNDLN ;FIND THE TARGET LINE
JZ GS1 ;NOT THERE, SAY "HOW?"
JMP AHOW
GS1: MOV BX,[CURRNT] ;FOUND IT, SAVE OLD
PUSH BX ;'CURRNT' OLD 'STKGOS'
MOV BX,[STKGOS]
PUSH BX
MOV BX,0 ;AND LOAD NEW ONES
MOV [LOPVAR],BX
ADD BX,SP
MOV [STKGOS],BX
JMP RUNTSL ;THEN RUN THAT LINE
RETURN:
CALL ENDCHK ;THERE MUST BE A 0DH
MOV BX,[STKGOS] ;OLD STACK POINTER
OR BX,BX
JNZ RET1 ;SO, WE SAY: "WHAT?"
JMP QWHAT
RET1: XCHG BX,SP ;ELSE RESTORE IT
POP BX ;ELSE RESTORE IT
MOV [STKGOS],BX ;AND THE OLD 'STKGOS'
POP BX
MOV [CURRNT],BX ;AND THE OLD 'CURRNT'
POP DX ;OLD TEXT POINTER
CALL POPA ;OLD "FOR" PARAMETERS
CALL FINISH ;AND WE ARE BACK HOME
;
;
; ****FOR**** AND ****NEXT****
;
;
; 'FOR' HAS TWO FORMS:
; 'FOR VAR=EXP1 TO EXP2 STEP EXP3'
; 'FOR VAR=EXP1 TO EXP2'
; THE SECOND FORM MEANS THE SAME AS THE FIRST FORM WITH EXP3=1.
;
; TBI WILL FIND THE VARIABLE VAR AND SET ITS VALUE TO THE CUR-
; RENT VALUE OF EXP1. IT ALSO EVALUATES EXP2 AND EXP3 AND
; SAVES ALL OF THESE TOGETHER WITH THE TEXT POINTER ETC IN
; THE 'FOR' SAVE AREA, WHICH CONSISTS OF 'LOPVAR', 'LOPINC',
; 'LOPLMT', 'LOPLN', AND 'LOPPT'. IFF THERE IS ALREADY SOME-
; THING IN THE SAVE AREA (THIS IS INDICATED BY A NON-ZERO
; 'LOPVAR'), THEN THE OLD SAVE AREA IS SAVED IN THE STACK BE-
; FORE THE NEW ONE OVERWRITES IT.
;
; TBI WILL THEN DIG IN THE STACK AND FIND OUT IFF THIS
; SAME VARIABLE WAS USED IN ANOTHER CURRENTLY ACTIVE FOR
; LOOP. IT THAT IS THE CASE THEN THE OLD 'FOR' LOOP IS DE-
; IVATED (PURGED FROM THE STACK).
;
; 'NEXT VAR' SERVES AS THE LOGICAL (NOT NECESSARILLY PHYSICAL)
; END OF THE 'FOR' LOOP. THE CONTROL VARIABLE VAR. IS CHECKED
; WITH THE 'LOPVAR'. IFF THEY ARE NOT THE SAME, TBI DIGGS IN
; THE STACK TO FIND THE RIGHT ONE AND PURGES ALL THOSE THAT
; DID NOT MATCH. EITHER WAY, TBI THEN ADDS THE 'STEP' TO THAT
; VARIABLE AND CHECKS THE RESULT WITH THE LIMIT. IFF IT IS
; WITHIN THE LIMIT, CONTROL LOOPS BACK TO THE COMMAND FOLLOW-
; ING THE 'FOR'. IFF OUTSIDE THE LIMIT, THE SAVE AREA IS PURG-
; ED AND EXECUTION CONTINUES.
;
;
FOR:
CALL PUSHA ;SAVE THE OLD SAVE AREA
CALL SETVAL ;SET THE CONTROL VAR.
DEC BX
MOV [LOPVAR],BX ;SAVE TGAT
MOV BX,TAB5-1 ;USE 'EXEC' TO LOOK
JMP EXEC ;FOR THE WORD 'TO'
FR1:
CALL EXP ;EVALUATE THE LIMIT
MOV [LOPLMT],BX ;SAVE THAT
MOV BX,TAB6-1 ;USED 'EXEC' TO LOOK
JMP EXEC ;FOR THE WORD 'STEP'
FR2:
CALL EXP ;FOUND IT, GET STEP
JP FR4 ;FOUND IT, GET STEP
FR3:
MOV BX,1 ;NOT FOUND, SET TO ONE
FR4:
MOV [LOPINC],BX ;SAVE THAT TOO
FR5:
MOV BX,[CURRNT] ;SAVE CURRENT LINE #
MOV [LOPLN],BX
XCHG DX,BX ;AND TEXT POINTER
MOV [LOPPT],BX
MOV CX,10 ;DIG INTO STACK TO
MOV BX,[LOPVAR] ;FIND 'LOPVAR'
XCHG DX,BX
MOV BX,CX ;BX:=10 NOW
ADD BX,SP
JP FR7A
FR7:
ADD BX,CX
FR7A: MOV AX,[BX] ;GET THAT OLD 'LOPVAR'
OR AX,AX
JZ FR8 ;0 SAYS NO MORE IN IT
CMP AX,DX ;SAME AS THIS ONE?
JNZ FR7
XCHG DX,BX
MOV BX,0 ;THE OTHER HALF?
ADD BX,SP
MOV CX,BX
MOV BX,10
ADD BX,DX
CALL MVDOWN ;AND PURGE 10 WORDS
XCHG BX,SP ;IN THE STACK
FR8:
MOV BX,[LOPPT] ;JOB DONE, RESTORE DE
XCHG DX,BX
CALL FINISH ;AND CONTINUE
;
NEXT:
CALL TSTV ;GET ADDR OF VAR
JNC NX4 ;NO VARIABLE, "WHAT?"
JMP QWHAT
NX4: MOV [VARNXT],BX ;YES, SAVE IT
NX0:
PUSH DX ;SAVE TEXT POINTER
XCHG DX,BX
MOV BX,[LOPVAR] ;GET VAR IN 'FOR'
MOV AL,BH
OR AL,BL ;0 SAY NEVER HAD ONE
JNZ NX5 ;SO WE ASK: "WHAT?"
JMP AWHAT
NX5: CMP DX,BX ;ELSE WE CHECK THEM
JZ NX3 ;OK, THEY AGREE
POP DX ;NO, LET'S SEE
CALL POPA ;PURGE CURRENT LOOP
MOV BX,[VARNXT] ;AND POP ONE LEVEL
JMP NX0 ;GO CHECK AGAIN
NX3:
MOV DL,[BX] ;COME HERE WHEN AGREED
INC BX
MOV DH,[BX] ;DE = VAL OF VAR
MOV BX,[LOPINC]
PUSH BX
ADD BX,DX
XCHG DX,BX ;ADD ONE STEP
MOV BX,[LOPVAR] ;PUT IT BACK
MOV [BX],DL
INC BX
MOV [BX],DH
MOV BX,[LOPLMT] ;HL-> LIMIT
POP AX
XCHG AH,AL
OR AX,AX
JNS NX1 ;STEP > 0
XCHG DX,BX
NX1:
CALL CKHLDE ;COMPARE WITH LIMIT
POP DX ;RESTORE TEXT POINTER
JC NX2 ;OUTSIDE LIMIT
MOV BX,[LOPLN] ;WITHIN LIMIT, GO
MOV [CURRNT],BX ;BACK TO THE SAVED
MOV BX,[LOPPT] ;'CURRNT' AND TEXT
XCHG DX,BX ;POINTER
CALL FINISH ;POINTER
NX2:
CALL POPA ;PURGE THIS LOOP
CALL FINISH
;
;
; ****REM**** AND ****IF**** AND ****LET*****
;
;
; 'REM' CAN BE FOLLOWED BY ANYTHING AND IS IGNORED BY TBI. TBI
; TREATS IT LIKE AN 'IF' WITH A FALSE CONDITION.
;
; 'IF' IS FOLLOWED BY AN EXPR. AS A CONDITION AND ONE OR MORE
; COMMANDS (INCLUDING OTHER 'IF'S) SEPERATED BY SEMI-COLONS.
; NOTE THAT THE WORD 'THEN' IS NOT USED. TBI EVALUATES THE
; EXPR. IFF IT IS NON-ZERO, EXECUTION CONTINUES. IFF THE EXPR.
; IS ZERO, THE COMMANDS THAT FOLLOW ARE IGNORED AND EXECUTION
; CONTINUES AT THE NEXT LINE.
;
; 'IPUT' COMMANS IS LIKE THE 'PRINT' COMMAND, AND IS FOLLOWED
; BY A LIST OF ITEMS. IFF THE ITEM IS A STRING IN SINGLE OR
; DOUBLE QUOTES, OR IS A BACK-ARROW, IT HAS THE SAME EFFEDT AS
; PRINTED OUT FOLLOWED BY A COLON. THEN TBI WAITS FOR AN EXPR.
; TO BE TYPEN IN. THE VARIABLE IS THEN SET TO THE VALUE OF
; THIS EXPR. IFF THE VARIABLE IS PROCEDED BY A STRING PRINTED
; FOLLOWED BY A COLON. TBI THEN WAITS FOR INPUT EXPR. AND SETS
; THE VARIABLE TO THE VALUE OF THE EXPR.
;
; IFF THE INPUT EXPR. IS INVALID, TBI WILL PRINT "WHAT?" ,
; "HOW?",OR "SORRY" AND REPRINT THE PROMPT AND REDO THE INPUT.
; THE EXECUTION WILL NOT TERMINATE UNLESS YOU TYPE CONTROL-C .
; THIS IS HANDLED IN 'INPERR'.
;
; 'LET' IS FOLLOWED BY A LIST OF ITEMS SEPERATED BY COMMAS .
; EACH ITEM CONSISTS OF A VARIABLE, AN EQUAL SIGN, AND AN
; EXPR. TBI EVALUATES THE EXPR. AND SETS THE VARIABLE TO THAT
; VALUE. TBI WILL ALSO HANDLE 'LET' COMMAND WITHOUT THE WORD
; 'LET'. THIS IS DONE BY 'DEFLT'.
;
;
;
REM:
MOV BX,0 ;****REM****
JP IFF1A ;JUMP AROUND EXPR
;
IFF:
CALL EXP ;****IF****
IFF1A: CMP BX,0 ;IS THE EXPR = 0?
JZ IFF1 ;NO, CONTINUE
JMP RUNSML
IFF1: CALL FNDSKP ;YES, SIKP REST OF LINE
JC IFF2 ;YES, SIKP REST OF LINE
JMP RUNTSL
IFF2: JMP RSTART ;YES, SIKP REST OF LINE
;
INPERR:
MOV BX,[STKINP] ;****INPERR****
XCHG BX,SP ;RESTORE OLD STACK POINTER
POP BX ;AND OLD 'CURRNT'
MOV [CURRNT],BX
POP DX
POP DX ;REDO INPUT
;
INPUT: EQU $ ;****INPUT****
IP1:
PUSH DX ;SAVE IN CASE OF ERROR
CALL QTSTG ;IS NEXT ITEM A STRING?
JP IP2 ;NO
CALL TSTV ;YES, BUT FOLLOWED BY A
JC IP4 ;VARIABLE? NO.
JP IP3 ;YES. INPUT VAR.
IP2:
PUSH DX ;SAVE FOR 'PRTSTG'
CALL TSTV ;MUST BE A VAR NOW
JNC IP2A ;"WHAT" IT IS NOT!
JMP QWHAT
IP2A: MOV SI,DX
LODB ;GET READY FOR 'RTSTG'
MOV CL,AL
SUB AL,AL
MOV DI,DX
STOB
POP DX
CALL PRTSTG ;PRINT STRING AS PROMPT
MOV AL,CL
DEC DX
MOV DI,DX
STOB
IP3:
PUSH DX
XCHG DX,BX
MOV BX,[CURRNT] ;ALSO SAVE 'CURRNT'
PUSH BX
MOV BX,IP1
MOV [CURRNT],BX ;NEG NUMBER AS FLAG
MOV [STKINP],SP
PUSH DX ;OLD HL
MOV AL,':' ;PRINT THIS TOO
CALL GETLN ;AND GET A LINE
IP3A:
MOV DX,BUFFER ; POINTS TO BUFFER
CALL EXP ;EVALUATE INPUT
NOP ;CAN BE 'CALL ENDCHK'
NOP ;CAN BE 'CALL ENDCHK'
NOP ;CAN BE 'CALL ENDCHK'
POP DX ;OK,GET OLD HL
XCHG DX,BX ;OK,GET OLD HL
MOV [BX],DX
POP BX ;GET OLD 'CURRNT'
MOV [CURRNT],BX
POP DX ;AND GET OLD TEXT POINTER
IP4:
POP AX
MOV AH,','
CALL IGNBLNK
JNZ IP5
JP IP1 ;YES, MORE ITEMS
IP5:
CALL FINISH
;
DEFLT:
MOV SI,DX
LODB ;****DEFLT****
CMP AL,0DH ;EMPTY LINE IS OK
JZ LT1 ;ELSE IT IS 'LET'
;
LET:
CALL SETVAL ;****LET****
MOV AH,','
CALL IGNBLNK
JNZ LT1
JP LET ;ITEM BY ITEM
LT1:
CALL FINISH ;UNTIL FINISH
;
;
; ****EXPR****
;
; 'EXPR' EVALUATES ARITHMETICAL OR LOGICAL EXPRESSIONS.
; <EXPR>::=<EXPR2>
; <EXPR2><REL.OP><EXPR2>
;
; WHERE <REL.OP> IS ONE OF THE OPERATORS IN TAB8 AND THE RE-
; SULT OF THESE OPERATIONS IS 1 IFF TRUE AND 0 IFF FALSE.
;
; <EXPR2>::=(+ OR -)<EXPR3>(+ OR -<EXPR3>(....)
;
; WHERE () ARE OPTIONAL AND (....) ARE OPTIONAL REPEATS.
;
; <EXPR3>::=<EXPR4>(<* OR /><EXPR4>)(....)
; <EXPR4>::=<VARIABLE>
; <FUNCTION>
; (<EXPR>)
;
; <EXPR> IS RECURSIVE SO THAT VARIABLE '@' CAN HAVE AN EXPR
; AS INDEX, FUCTIONS CAN HAVE AN <EXPR> AS ARGUMENTS, AND
; <EXPR4> CAN BE AN <EXPR> IN PARANTHESES.
;
;
EXP: CALL EXPR2
PUSH BX
EXPR1:
MOV BX,TAB8-1 ;LOOKUP REL.OP
JMP EXEC ;GO DO IT
XP11:
CALL XP18
JC RET ;NO RETURN HL=0
MOV BL,AL ;YES, RETURN HL=1
RET
XP12:
CALL XP18
JZ RET ;FALSE, RETURN HL=0
MOV BL,AL ;TRUE, RETURN HL=1
RET
XP13:
CALL XP18 ;REL.OP '>'
JZ RET ;FALSE
JC RET ;ALSO FALSE, HL=0
MOV BL,AL ;TRUE, HL=1
RET
XP14:
CALL XP18 ;REL OP '<='
MOV BL,AL ;SET HL=1
JZ RET ;REL. TRUE, RETURN
JC RET ;REL. TRUE, RETURN
MOV BL,BH ;ELSE SET HL=0
RET
XP15:
CALL XP18 ;REL OP '='
JNZ RET ;FALSE, RETURN HL=0
MOV BL,AL ;ELSE SET HL=1
RET
XP16:
CALL XP18 ;REL.OP '<'
JNC RET ;FALSE, RETURN HL=0
MOV BL,AL ;ELSE SET HL=1
RET
XP17:
POP BX ;NOT REL OP
RET ;RETURN HL=<EPTR2>
XP18:
MOV AL,CL ;SUBROUTINE FOR ALL
POP BX ;REL.OP'S
POP CX ;REL.OP'S
PUSH BX ;REVERSE TOP OF STACK
PUSH CX ;REVERSE TOP OF STACK
MOV CL,AL
CALL EXPR2 ;GET 2ND EXPRESSION
XCHG DX,BX ;VALUE IN DE NOW
POP AX
PUSH BX
MOV BX,AX ;LAST 3 INSTR FOR XTHL INST!
CALL CKHLDE ;COMPARE 1ST WITH SECOND
POP DX
MOV BX,0 ;SET HL=0, A=1
MOV AL,1 ;SET HL=0, A=1
RET
;
EXPR2:
MOV AH,'-'
CALL IGNBLNK ;NEGATIVE SIGN?
JNZ XP21
MOV BX,0 ;YES, FAKE '0-'
JP XP26 ;TREAT LIKE SUBTRACT
XP21:
MOV AH,'+' ;POSITIVE SIGN?
CALL IGNBLNK
XP22:
CALL EXPR3 ;1ST <EXPR3>
XP23:
MOV AH,'+'
CALL IGNBLNK ;ADD?
JNZ XP25 ;NOTE OFFSET WHAS 21 BYTES IN 8080 VERSION
PUSH BX ;YES, SAVE VALUE
CALL EXPR3 ;GET 2ND <EXPR3>
XP24:
XCHG DX,BX ;2ND IN DE
POP AX ;THIS + NEXT 2 LINES FOR 8080 XTHL INST!!
PUSH BX
MOV BX,AX ;BX <-> [SP] NOW, [SP]->BUFFER,BX=OLD EXPR3
ADD BX,DX
POP DX
JNO XP23 ;CHECK FOR OVERFLOW
XP24A: JMP QHOW ;ELSE WE HAVE OVERFLOW
XP25:
MOV AH,'-'
CALL IGNBLNK ;SUBTRACT?
JNZ RET
XP26: PUSH BX ;YES, SAVE 1ST <EXPR3>
CALL EXPR3 ;GET 2ND <EXPR3>
CALL CHGSGN
JP XP24
;
EXPR3:
CALL EXPR4 ;GET 1ST <EXPR4>
XP31:
MOV AH,'*'
CALL IGNBLNK ;MULTIPLY?
JNZ XP34
PUSH BX ;YES, SAVE 1ST
CALL EXPR4 ;AND GET 2ND <EXPR4>
XCHG DX,BX ;2ND IN DE NOW
POP AX ;SUBSITUTE FOR 8080 XTHL
PUSH BX
IMUL AX,DX ;AX:=AX*DX
JO XP32 ;SEE INTEL BOOK ON OVERFLOW FLAG
MOV BX,AX ;RESULT NOW IN BX
JP XP35 ;LOOK FOR MORE
XP34:
MOV AH,'/'
CALL IGNBLNK ;DIVIDE?
JNZ RET
PUSH BX ;YES, SAVE 1ST <EXPR4>
CALL EXPR4 ;AND GET SECOND ONE
XCHG DX,BX ;PUT 2ND IN DE
POP AX ;REPLACEMENT FOR XTHL
PUSH BX
MOV BX,AX
OR DX,DX
JNZ XP34A ;SAY "HOW?"
XP32: JMP AHOW
XP34A: CALL DIVIDE ;USE SUBROUTINE
MOV BX,CX ;GET RESULT
MOV CX,6 ;SIX SPACES
XP35:
POP DX ;AND TEXT POINTER
JP XP31 ;LOOK FOR MORE TERMS
;
EXPR4:
MOV BX,TAB4-1 ;FIND FUCNTION IN TAB4
JMP EXEC ;AND GOT DO IT
XP40:
CALL TSTV ;NO, NOT A FUNCTION
JC XP41 ;NOR A VARIABLE
MOV AL,[BX] ;VARIABLE
LAHF
INC BX
SAHF
MOV BH,[BX] ;VALUE IN HL
MOV BL,AL ;VALUE IN HL
RET
XP41:
CALL TSTNUM ;OR IS IT A NUMBER?
MOV AL,CH ;# OF DIGITS
OR AL,AL
JNZ RET ;OK
PARN:
MOV AH,'('
CALL IGNBLNK ;NO DIGIT, MUST BE
JNZ PARN1
CALL EXP ;"(EXPR)"
PARN1: MOV AH,')'
CALL IGNBLNK ;"(EXPR)"
JNZ XP43 ;******WHY CHECK THIS?******
XP42:
RET
XP43:
JMP QWHAT ;ELSE SAY: "WHAT?"
;
RND:
CALL PARN ;****RND(EXPR)****
OR BX,BX
JNS RND1 ;MUST BE POSITIVE
JNZ RND1 ;AND NON-ZERO
JMP QHOW
RND1:
PUSH CX
PUSH DX
MOV AH,2CH ;GET TIME
INT 33 ;ASK MS-DOS
MOV AX,327
MOV DH,0
MUL AX,DX ; 0<=AX<=32700
XCHG DX,BX
MOV BX,AX
CALL DIVIDE ;RND(N)=MOD(M,N)+1
POP DX
POP CX
INC BX
RET
;
ABS:
CALL PARN ;****ABS(EXPR)****
CALL CHKSGN ;CHECK SIGN
OR AX,BX
JNS RET ;OK
JMP QHOW ;SO SAY: "HOW?"
SIZE:
MOV BX,[TXTUNF] ;****SIZE****
PUSH DX ;GET THE NUMBER OF FREE
XCHG DX,BX ;BYTES BETWEEN 'TXTUNF'
SIZEA:
MOV BX,VARBGN ;AND 'VARBGN'
SUB BX,DX
POP DX
RET
;
;
; ****OUT**** AND ****INP**** AND ****WAIT**** AND
; ****POKE**** AND ****PEEK**** AND ****USR****
;
;
; 'OUT I,J(,K,L)'
;
; OUTPUTS EXPRESSION 'J' TO PORT 'I', AND MAY BE REPEATED AS
; IN DATA 'L' TO PORT 'K' AS MANY TIMES AS NEEDED. THIS COM-
; MAND MODIFIES *, A SMALL SECTION OF CODE ABOVE ADDRESS 2K.
;
; 'INP (I)'
;
; THIS FUNCTION RETURNDS DATA READ FROM INPUT PORT 'I' AS
; ITS VALUE. IT ALSO MODIFIES CODE JUST ABOVE 2K.
;
; 'WAIT I,J,K'
;
; THIS COMMAND READS THE STATUS OF PORT 'I', EXCLUSIVE OR'S
; THE RESULT WITH 'K', IF THE RESULT IS ONE, OR IF NOT WITH
; ZERO, AND'S WITH 'J' AND RETURNS WHEN THE RESULT IS NON-
; ZERO. ITS MODIFIED CODE IS ALSO ABOVE 2K.
;
; 'POKE I,J(,K,L)
;
; THIS COMMAND WORKS LIKE OUT EXCEPT THAT IT PUTS DATA 'J'
; INTO MEMORY LOCATION 'I'.
;
; 'PEEK (I)'
;
; THIS FUNCTION WORKS LIKE INP EXCEPT THAT IT PUTS DATA 'J'
; FROM MEMORY LOCATION 'I'.
;
; 'USR(I(,J))'
;
; USR CALL A MACHINE LANGUAGE SUBROUTINE AT LOCATION 'I' IF
; THE OPTIONAL PARAMETER 'J' IS USED ITS VALUE IS PASSED IN
; HL. THE VALUE OF THE FUNCTION SHOULD BE RETURNED IN HL.
;
;
OUTCMD:
CALL EXP
MOV AL,BL
MOV [OUTIO+1],AL
MOV AH,','
CALL IGNBLNK
JZ OUT1 ;FOUND MORE TO WORK ON
JMP QWHAT
OUT1: CALL EXP
MOV AL,BL
CALL OUTIO
MOV AH,','
CALL IGNBLNK
JNZ OUTCMD1
JP OUTCMD
OUTCMD1:CALL FINISH
WAITCM:
CALL EXP
MOV AL,BL
MOV [WAITIO+1],AL
MOV AH,','
CALL IGNBLNK
JZ WT1
JMP QWHAT
WT1: CALL EXP
PUSH BX
MOV AH,','
CALL IGNBLNK
JNZ WAIT1
CALL EXP
MOV AL,BL
POP BX
MOV BL,AL
JP WAIT2
WAIT1: MOV BH,0
WAIT2: JMP WAITIO
INP:
CALL PARN
MOV AL,BL
MOV [INPIO+1],AL
MOV BX,0
JMP INPIO
JP QWT
POKE:
CALL EXP
PUSH BX
MOV AH,','
CALL IGNBLNK
JZ POK1
JMP QWHAT
POK1: CALL EXP
MOV AL,BL
POP BX
MOV [BX],AL
MOV AH,','
CALL IGNBLNK
JNZ POK2
JP POKE
POK2: CALL FINISH
PEEK:
CALL PARN
MOV BL,[BX]
MOV BH,0
RET
JMP QWHAT
USR:
PUSH CX
MOV AH,'('
CALL IGNBLNK
JNZ QWT
CALL EXP ;EXPR
MOV AH,')'
CALL IGNBLNK ;EXPR
JNZ PASPRM
PUSH DX
MOV DX,USRET
PUSH DX
PUSH BX
RET ;CALL USR ROUTINE
PASPRM:
MOV AH,','
CALL IGNBLNK
JNZ USRET1
PUSH BX
CALL EXP
MOV AH,')'
CALL IGNBLNK
JNZ USRET1
POP CX
PUSH DX
MOV DX,USRET
PUSH DX
PUSH CX
RET ;CALL USR ROUTINE
USRET:
POP DX
USRET1: POP CX
RET
QWT: JMP QWHAT
;
;
; ****DIVIDE**** AND ****CHKSGN****
; ****CHKSGN**** AND ****CKHLDE****
;
;
; 'DIVIDE DIVIDES BX BY DX, RESULT IN CX, REMAINDER IN BX
;
; 'CHKSGN' CHECKS SIGN OF BX. IFF +, NO CHANGE. IFF -, CHANGE
; SIGN AND FLIP SIGN OF C
;
; 'CHGSGN' CHANGES SIGN OF BX AND CL UNCONDITIONALLY.
;
; 'CKHLDE' CHECK SIGN OF BX AND DX. IFF DIFFERENT, BX AND DX
; ARE INTERCHANGED. IFF SAME SIGN, NOT INTERCHANGED. EITHER
; CASE, BX AND DX ARE THEN COMPARED TO SET THE FLAGS.
;
;
DIVIDE:
PUSH DX ;PRESERVE DX ACCROSS CALL
PUSH DX
XOR DX,DX
POP CX
MOV AX,BX
IDIV AX,CX
MOV CX,AX ;QUOTIENT
MOV BX,DX ;REMAINDER
POP DX ;DX RESTORED
RET
;
CHKSGN:
OR BX,BX ;SET FLAGS TO CHECK SIGN
JNS RET ;IFF -, CHANGE SIGN
;
CHGSGN:
NOT BX ;****CHGSGN****
INC BX
XOR CH,128
RET
;
CKHLDE:
MOV AL,BH
XOR AL,DH ;SAME SIGN?
JNS CK1 ;YES, COMPARE
XCHG DX,BX
CK1:
CMP BX,DX
RET
;
;
; ****SETVAL**** AND ****FIN**** AND ****ENDCHK****
; ****ERROR**** AND FRIENDS
;
;
; 'SETVAL' EXPECTS A VARIABLE, FOLLOWED BY AN EQUAL SIGN AND
; THEN AN EXPR. IT EVALUATES THE EXPR AND SETS THE VARIABLE
; TO THAT VALUE.
;
; 'FIN' CHECKS THE END OF A COMMAND. IFF IT ENDED WITH ";" ,
; EXECUTION CONTINUES. IFF IT ENDED WITH A CR, IT FINDS THE
; NEXT LINE AND CONTINUES FROM THERE.
;
; 'ENDCHK' CHECKS IFF A COMMAND IS ENDED WITH A CR, THIS IS
; REQUIRED IN CERTAIN COMMANDS. (GOTO, RETURN, AND STOP,ETC)
;
; 'ERROR' PRINTS THE STRING POINTED BY DX (AND ENDS WITH A
; CR). IT THEN PRINTS THE LINE POINTED BY 'CURRNT' WITH A ?.
; INSERTED AT WHERE THE OLD TEXT POINTER (SHOULD BE ON TOP
; OF THE STACK) POINTS TO. EXECUTION OF TB IS STOPPED AND
; TBI IS RESTARTED. HOWEVER, IFF 'CURRNT' -> ZERO (INDICAT -
; ING A DIRECT COMMAND), THE DIRECT COMMAND IS NOT PRINTED ,
; AND IFF 'CURRNT' -> NEGATIVE # (INDICATING 'INPUT' COMMAND
; THE INPUT LINE IS NOT PRINTED AND EXECUTION IS NOT TERMIN-
; ATED BUR CONTINUED AT 'INPERR').
;
; RELATED TO 'ERROR' ARE THE FOLLOWING:
;
; 'QWHAT' SAVES TEXT POINTER IN STACK AND GETS MESSAGE
; "WHAT?"
; 'AWHAT' JUST GETS MESSAGE "WHAT?" AND JUMPS TO ERROR
;
; 'QSORRY' AND 'ASORRY' DO THE SAME KIND OF THING.
;
; 'QHOW' AND 'AHOW' IN THE ZERO PAGE SECTION ALSO DO
; THIS.
;
;
SETVAL:
CALL TSTV ;SEE IT IT'S A VARIABLE
JC QWHAT ;"WHAT" NO VARIABLE
PUSH BX ;SAVE ADDR OF VARIABLE
MOV AH,'='
CALL IGNBLNK
JNZ SV1
CALL EXP
MOV CX,BX ;VALUE IN CX NOW
POP BX ;GET ADDR
MOV [BX],CL ;SAVE VALUE
INC BX
MOV [BX],CH ;SAVE VALUE
RET
SV1:
JMP QWHAT ;NO '=' SIGN
;
FIN:
MOV AH,';'
CALL IGNBLNK
JNZ FI1
POP AX
JMP RUNSML
FI1:
MOV AH,0DH
CALL IGNBLNK
JNZ RET
POP AX
JMP RUNNXL ;RUN NEXT LINE
FI2:
RET ;ELSE RETURN TO CALLER
;
ENDCHK:
MOV AH,0DH ;END WITH CR?
CALL IGNBLNK
JZ RET ;OK, ELSE SAY "WHAT?"
;
QWHAT:
PUSH DX ;****QWHAT****
AWHAT:
MOV DX,WHAT ;****AWHAT****
ERROR:
SUB AL,AL ;****ERROR****
CALL PRTSTG ;PRINT 'WHAT?','HOW?'
POP DX
MOV SI,DX
LODB
PUSH AX ;SAVE THE CHARACTER
SUB AL,AL ;AND PUT A ZERO THERE
MOV DI,DX
STOB
MOV BX,[CURRNT] ;GET CURRENT LINE #
CMP W,[CURRNT],0 ;DIRECT COMMAND?
JNZ ERR1 ;IFF ZERO, JUST RESTART
JP ERR2 ;SAVE A BYTE
ERR1: MOV AL,[BX] ;IFF NEGATIVE,
OR AL,AL
JNS ERR1A
JMP INPERR ;REDO INPUT
ERR1A: CALL PRTLN ;ELSE PRINT THE LINE
DEC DX
POP AX
MOV DI,DX
STOB ;RESTORE THE CHAR
MOV AL,63 ;PRINT A '?'
CALL CHROUT
SUB AL,AL ;AND THE REST OF THE
CALL PRTSTG ;LINE
ERR2: JMP RSTART
QSORRY:
PUSH DX ;****QSORRY****
ASORRY:
MOV DX,SORRY ;****ASORRY****
JP ERROR
;
;
; ****GETLN**** AND ****FNDLN****
;
;
; 'GETLN' READS AN INPUT LINE INTO 'BUFFER'. IT FIRST PROMPTS
; THE CHARACTER IN A (GIVEN BY THE CALLER), THEN IT FILLS THE
; BUFFER AND ECHOS IT. IT USES BDOS PRIMITIVES TO ACCOMPLISH
; THIS. ONCE A FULL LINE IS READ IN, 'GETLN' RETURNS.
;
; 'FNDLN' FINDS A LINE WITH A GIVEN LINE #(IN BX) IN THE TEXT
; SAVE AREA. DX IS USED AS THE TEXT POINTER. IFF THE LINE IS
; FOUND, DX WILL POINT TO THE BEGINNING OF THAT LINE IFF THAT
; LINE (I.E. THE LOW BYTE OF THE LINE #), AND FLAGS ARE NC&Z.
; IFF THAT LINE IS NOT THERE AND A LINE WITH A HIGHER LINE #
; IS FOUND, DX POINTS TO THERE AND FLAGS ARE NC&NZ. IFF WE
; REACHED THE END OF TEXT SAVE AREA AND CANNOT FIND THE LINE,
; FLAGS ARE C&NZ.
; 'FNDLN' WILL INITIALIZE DX TO THE BEGINNING OF THE TEXT
; SAVE AREA TO START THE SEARCH. SOME OTHER ENTRIES OF THIS
; ROUTINE WILL NOT INITIALIZE DX AND DO THE SEARCH.
;
; 'FNDLNP' WILL START WITH DX AND SEARCH FOR THE LINE #.
;
; 'FNDNXT' WILL BUMP DX BY 2, FIND A 0DH AND THEN START THE
; SEARCH.
; 'FNDSKP' USES DX TO FIND A CR, AND THEN STARTS THE SEARCH.
;
;
;
GETLN:
CALL CHROUT ;****GETLN****
GL1:
MOV DX,BUFFER-2
PUSH DX
MOV AH,BCONIN ;BUFFERED CONSOLE INPUT
INT 33 ;CALL MS-DOS
POP DX
ADD DL,[BUFFER-1]
INC DX
INC DX
INC DX
MOV DI,DX ;FOR CONSISTANCY
PUSH DX
CALL CRLF ;NEED CRLF
POP DX
RET ;WE'VE GOT A LINE
;
; AT ENTRY BX -> LINE # TO BE FOUND
;
FNDLN:
OR BX,BX ;CHECK SIGN OF BX
JNS FND1 ;IT CAN'T BE -
JMP QHOW ;ERROR
FND1: MOV DX,TXTBGN
;
FNDLNP:
FL1:
PUSH BX ;SAVE LINE #
MOV BX,[TXTUNF] ;CHECK IFF WE PASSED END
DEC BX
CMP BX,DX ;SUBSTITUTE FOR CALL 4
POP BX ;GET LINE # BACK
JC RET ;C, NZ PASSED END
MOV SI,DX
LODW
CMP AX,BX
JC FL2
RET ;NC,Z:FOUND;NC,NZ:NOT FOUND
;
FNDNXT: ;****FNDNXT****
INC DX
FL2:
INC DX
;
FNDSKP:
MOV SI,DX
LODB ;****FNDSKP****
CMP AL,0DH ;TRY TO FIND CR
JNZ FL2 ;KEEP LOOKING
INC DX
JP FL1 ;CHECK IFF END OF TEXT
;
;
; **** PRTSTG **** QTSTG **** PRTNUM **** PRTLN ****
;
;
; 'PRTSTG PRINTS A STRING POINTED TO BY DX. IT STOPS PRINTING
; AND RETURNS TO CALLER WHEN EITHER A 0DH IS PRINTED OR WHEN
; THE NEXT BYTE IS THE SAMES AS WHAT WAS IN A ( GIVEN BY THE
; CALLER). OLD AL IS STORED IN CH, OLD CH IS LOST.
;
; 'QTSTG' LOOKS FOR A BACK-SLASH, SINGLE QUOTE, OR DOUBLE
; QUOTE. IFF NONE OF THESE, RETURN TO CALLER. IF BACK SLASH \
; OUTPUT A ODH WITHOUT A LF. IFF SINGLE OR DOUBLE QUOTE,PRINT
; THE STRING IN THE QUOTE AND DEMANDS A MATCHING UNQUOTE. AF-
; TER THE PRINTING THE NEXT 3 BYTES OF THE CALLER IS SKIPPED
; OVER (USUALLY A JMP INSTRUCTION).
;
; 'PRTNUM' PRINTS THE NUMBER IN HL. LEADING BLANKS ARE ADDED
; IFF NEEDED TO PAD THE NUMBER OF SPACES TO THE NUMBER IN C.
; NOWEVER, IFF THE NUMBER OF DIGITS IS LARGER THAN THE NUMBER
; IN C, ALL DIGITS ARE PRINTED ANYWAY. NEGATIVE SIGN IS ALSO
; PRINTED AND COUNTED IN, POSITIVE SIGN IS NOT.
;
; 'PRTLN' PRINTS A SAVED TEXT LINE WITH LINE # AND ALL.
;
;
;
PRTSTG:
MOV CH,AL ;****PRTSTG****
PS1:
MOV SI,DX
LODB ;GET A CHAR
LAHF ;PRESERVE FLAGS
INC DX
SAHF ;RESTORE FLAGS
CMP AL,CH ;SAME AS OLD A?
JNZ PS2 ;YES, RETURN
RET
PS2: CALL CHROUT ;ELSE, PRINT IT
CMP AL,0DH ;WAS IT A CR?
JNZ PS1 ;NO, NEXT
RET
;
QTSTG:
MOV AH,'"'
CALL IGNBLNK
JNZ QT3
MOV AL,34 ;IT IS A '"'
QT1:
CALL PRTSTG ;PRINT UNTIL ANOTHER
CMP AL,0DH ;WAS LAST ONE A CR?
POP BX ;RETURN ADDRESS
JNZ QT2 ;WAS CR, RUN NEXT LINE
JMP RUNNXL
QT2:
INC BX ;SKIPS TWO BYTES ON RETURN!!!!
INC BX
JMP BX ;JUMP TO ADDRESS IN BX
QT3:
MOV AH,39 ;IS IT A SINGLE QUOTE (')?
CALL IGNBLNK
JNZ QT4
MOV AL,39 ;YES, DO SAME
JP QT1 ;AS IN ' " '
QT4:
MOV AH,'\'
CALL IGNBLNK ;IS IT BACK-SLASH?('\')
JNZ QT5
MOV AL,141 ;YES, 0DH WITHOUT LF!
CALL CHROUT ;DO IT TWICE
CALL CHROUT ;TO GIVE TTY ENOUGH TIME
POP BX ;RETURN ADDRESS
JP QT2
QT5:
RET ;NONE OF THE ABOVE
;
; ON ENTRY BX = BINARY #,CL = # SPACES
;
PRTNUM:
PUSH DX ;****PRTNUM****
MOV DX,10 ;DECIMAL
PUSH DX ;SAVE AS A FLAG
MOV CH,DH ;CH=SIGN
DEC CL ;CL=SPACES
CALL CHKSGN ;CHECK SIGN
JNS PN1 ;NO SIGN
MOV CH,45 ;CH=SIGN
DEC CL ;'-' TAKES SPACE
PN1:
PUSH CX ;SAVE SIGN % SPACE
PN2:
CALL DIVIDE ;DIVIDE BX BY 10 (IN DX)
OR CX,CX ;CX HAS QUOTIENT
JZ PN3 ;YES, WE GOT ALL
POP AX ;GET SIGN AND SPACE COUNT
PUSH BX ;SAVE REMAINDER
DEC AL ;DEC SPACE COUNT
PUSH AX ;SAVE NEW SIGN AND SPACE COUNT
MOV BX,CX ;MOVE RESULT TO BX
JP PN2 ;AND DIVIDE BY 10
PN3:
POP CX ;WE GOT ALL DIGITS IN
PN4:
DEC CL ;THE STACK
MOV AL,CL ;LOOK AT SPACE COUNT
OR AL,AL
JS PN5 ;NO LEADING BLANKS
MOV AL,32 ;LEADING BLANKS
CALL CHROUT
JP PN4
PN5:
MOV AL,CH ;PRINT SIGN
CALL CHROUT ;MAYBE, OR NULL
MOV DL,BL ;LAST REMAINDER IN E
PN6:
MOV AL,DL ;CHECK DIGIT IN E
CMP AL,10 ;10 IS FLAG FOR NO MORE
POP DX
JZ RET ;IFF SO, RETURN
ADD AL,48 ;ELSE CONVERT TO ASCII
CALL CHROUT ;AND PRINT THE DIGIT
JP PN6 ;GO BACK FOR MORE
;
PRTLN:
MOV SI,DX
LODW
MOV BX,AX
INC DX
INC DX ;MOVE POINTER
PRTLN1: MOV CL,5 ;PRINT 5 DIGIT LINE #
CALL PRTNUM
MOV AL,32 ;FOLLOWED BY A BLANK
CALL CHROUT
SUB AL,AL ;AND THEN THE TEXT
CALL PRTSTG
RET
;
;
;
; **** MVUP **** MVDOWN **** POPA **** PUSHA ****
;
; 'MVUP' MOVES A BLOCK UP FROM WHERE DX -> WHERE CX -> UNTIL
; DX = BX
;
; 'MVDOWN' MOVES A BLOCK DOWN FROM WHERE DX -> TO WHERE BX->
; UNTIL DX = CX.
;
; 'POPA' RESTORES THE 'FOR' LOOP VAR SAVE AREA FROM THE STACK.
;
; 'PUSHA' STACKS THE 'FOR' LOOP VARIABLE SAVE AREA IN THE STACK
;
;
MVUP:
CMP DX,BX ;***MVUP***
JZ RET ;DE = HL, RETURN
MOV SI,DX
LODB ;GET ONE BYTE
MOV DI,CX
STOB ;MOVE IT
INC DX
INC CX
JP MVUP ;UNTIL DONE
;
MVDOWN:
CMP DX,CX
JZ RET ;YES, RETURN
MD1:
LAHF
DEC DX
DEC BX
MOV SI,DX
LODB ;BOTH POINTERS AND
MOV [BX],AL ;THEN DO IT
JP MVDOWN ;LOOP BACK
;
POPA:
POP CX ;CX = RETURN ADDR
POP BX ;RESTORE LOPVAR, BUT
MOV [LOPVAR],BX ;=0 MEANS NO MORE
OR BX,BX
JZ PP1 ;YES, GO RETURN
POP BX ;NO, RESTORE OTHERS
MOV [LOPINC],BX
POP BX
MOV [LOPLMT],BX
POP BX
MOV [LOPLN],BX
POP BX
MOV [LOPPT],BX
PP1:
PUSH CX ;CX = RETURN ADDR
RET
;
PUSHA:
MOV BX,STKLMT ;****PUSHA****
CALL CHGSGN
POP CX ;CX=RET ADDR
ADD BX,SP
JC PUSHB ;YES, SORRY FOR THAT.
JMP QSORRY
PUSHB: MOV BX,[LOPVAR] ;ELSE SAVE LOOP VARS
OR BX,BX ;THAT WILL BE ALL
JZ PU1
MOV BX,[LOPPT] ;ELSE, MORE TO SAVE
PUSH BX
MOV BX,[LOPLN] ;ELSE, MORE TO SAVE
PUSH BX
MOV BX,[LOPLMT]
PUSH BX
MOV BX,[LOPINC]
PUSH BX
MOV BX,[LOPVAR]
PU1:
PUSH BX
PUSH CX ;CX = RETURN ADDR
RET
;
;
; **** OUTC **** CHKIO ****
;
;
; THESE ARE THE ONLY I/O ROUTINES IN TBI.
;
;
; 'CHKIO' CHECKS THE INPUT, IFF NO INPUT, IT WILL RETURN TO THE
; CALLER WITH THE Z FLAG SET. IFF THERE IS INPUT, THE Z FLAG IS
; CLEARED AND THE INPUT BYRE IS IN A. HOWEVER, IFF THE INPUT IS
; A CONTROL-O, THE 'OCSW' IS COMPLIMENTED, AND THE Z FLAG IS RE-
; TURNED. IFF A CONTROL-C IS READ, 'CHKIO' WILL RESTART TBI AND
; DOES NOT RETURN TO THE CALLER.
;
CRLF: MOV AL,0DH ;****CRLF****
CHROUT:
CMP [OCSW],0
JZ COUT1 ;SEE IF OUTPUT REDIRECTED
PUSH CX ;SAVE CX ON STACK
PUSH DX ;AND DX
PUSH BX ;AND BX TOO
MOV [OUTCAR],AL ;SAVE CHATACTER
MOV DL,AL ;PUT CHAR IN E FOR CP/M
MOV AH,CONOUT ;CONSOLE OUTPUT
INT 33 ;CALL MS-DOS AND OUTPUT CHAR
MOV AL,[OUTCAR] ;GET CHAR. BACK
CMP AL,0DH ;WAS IT A 'CR'?
JNZ DONE ;NO,DONE
MOV DL,0AH ;GET LINEFEED
MOV AH,CONOUT ;CONSOLE OUTPUT AGAIN
INT 33 ;CALL MS-DOS
DONE:
MOV AL,[OUTCAR] ;GET CHAR BACK
IDONE:
POP BX ;GET H BACK
POP DX ;AND D
POP CX ;THEN H
RET ;DONE AT LAST
COUT1:
CMP B,AL,0 ;IS IT NULL?
JZ RET ;SKIP IT
STOB ;STORE AL (CHAR) IN BUFFER
INC [BUFFER-1] ;INCREMENT COUNTER
RET ;DONE
CHKIO:
PUSH CX ;SAVE B ON STACK
PUSH DX ;AND D
PUSH BX ;THEN H
MOV AH,CONST ;GET CONSOLE STATUS WORD
INT 33 ;CALL MS-DOS
OR AL,AL ;SET FLAGS
JNZ CI1 ;IF READY, GET CHAR
JP IDONE ;RESTORE AND RETURN
CI1:
MOV AH,1 ;CALL THE BDOS
INT 33 ;CALL MS-DOS
CI2:
CMP AL,18H ;IS TI CONTROL-X?
JNZ IDONE ;RETURN AND RESTORE IF NOT
JMP RSTART ;YES, RESTART TBI
LSTROM: EQU $ ;ALL ABOVE CAN BE ROM
OUTIO:
OUTB 0FFH
RET
WAITIO:
INB 0FFH
XOR AL,BH
AND AL,BL
JZ WAITIO
CALL FINISH
INPIO:
INB 0FFH
MOV BL,AL
RET
;
;
; IGNBLNK
;
; DEBLANKS WHERE DX->
; IF (DX)=AH THEN DX:=DX+1
;
IGNBLNK:MOV SI,DX
IGN1: LODB ;GET CHAR IN AL
CMP AL,32 ;IGNORE BLANKS
JNZ IGN2 ;IN TEXT (WHERE DX ->)
INC DX
JP IGN1
IGN2: CMP AL,AH ;IS SEARCH CHARACTER FOUND AT (DX)?
JNZ RET ;NO, RETURN, POINTER (DX) STAYS
LAHF ;SAVE RESULTS OF COMPARISON
INC DX ;INC POINTER IF CHARACTER MATCHES
SAHF ;RETURN RESULT OF COMPARISON TO FLAGS
RET
;
FINISH: POP AX
CALL FIN ;CHECK END OF COMMAND
JMP QWHAT ;PRINT "WHAT?" IFF WRONG
;
OUTCAR:
DB 0 ;OUTPUT CHAR STORAGE
OCSW:
DB 0FFH ;OUTPUT SWITCH
CURRNT:
DW 0 ;POINTS TO CURRENT LINE
STKGOS:
DW 0 ;SAVES SP IN 'GOSUB'
VARNXT:
DW 0 ;TEMP STORAGE
STKINP:
DW 0 ;SAVES SP IN 'INPUT'
LOPVAR:
DW 0 ;'FOR' LOOP SAVE AREA
LOPINC:
DW 0 ;INCREMENT
LOPLMT:
DW 0 ;LIMIT
LOPLN:
DW 0 ;LINE NUMBER
LOPPT:
DW 0 ;TEST POINTER
RANPNT:
DW 0 ;RANDOM NUMBER POINTER
TXTUNF:
DW TXTBGN ;-> UNFILLED TEXT AREA
TXTBGN: DS 1
MSG1: DB '8086 TINY BASIC V1.1 27 JUNE 82',0DH
ORG 2000H ;MISC STORAGE, INCLUDING STACK
TXTEND: EQU $ ;TEST AREA SAVE AREA ENDS
VARBGN:
DS 54 ;VARIABLE @(0)
DB 80 ;MAX CHARS IN BUFFER
DB 0 ;CHAR COUNT
BUFFER:
DS 80 ;BUFFER MUST BE AFTER TEXT AREA
BUFEND: EQU $
DS 400 ;EXTRA BYTES FOR STACK
STKLMT: DS 100 ;TOP LIMIT FOR STACK
STACK: EQU $ ;STACK STARTS HERE
END
8086 TINY BASIC USER'S GUIDE
INTRODUCTION
The TINY BASIC language originated in the pages of Dr. DOBB'S
JOURNAL and PEOPLE'S COMPUTER COMPANY in late 1975 and early 1976. Fed
by the enthusiasm of early computer hobbyists and by the challenges
and oportunities created by the early microcomputer chips, the idea of
a tiny basic interpreter quickly gained popularity and acceptance. The
language was a stripped down version of the ever-popular Dartmouth
BASIC with the proviso that it be "useful" with a minimum of then very
expensive memory. Additionally, TINY BASIC had to be ROMable since
mass storage at that time consisted of reels of teletype punch paper
tape, often punched at the unbearably slow rate of ten characters per
second.
The TINY BASIC language supports a very limited subset of the
Dartmouth BASIC language. It does not compare at all with the large
floating point BASIC's that have been released for almost all eight
bit microcomputer chips. It does not support strings. Then, why 8086
TINY BASIC? Well, the size is still small (2700 bytes), it is
efficient and easy to learn, and it is still ROMable. All of this
implies that the language is still useful in at least two important
applications: education and dedicated control.
The present version of TINY BASIC is based on Li-Chen Wang's
Palo Alto 8080 TINY BASIC as published in the May 1976 issue of DR.
DOBB'S JOURNAL. Dr. Wang's version of TINY BASIC was chosen for its
remarkable resiliance and simplicity. It has been optimized for the
8086 and it takes advantage of the hardware multiply and divide that
the 8086 affords. Other enhancements include the use of the host
operating system's line editing facilities and the LOAD and SAVE
facilities, which, in the 8080 version, are due to unknown authors.
The 8086 implementation is due to Michael E. Sullivan of Financial
Software, 54 Grove Street, Haddonfield, NJ, 08033.
THE LANGUAGE
Numbers
In TINY BASIC, all number are integers and must be within the
range of -32767 .. 32767.
1
Variables
There are 26 scalar variables donoted by the letters A through
Z. The one array variable is denoted by '@(I)'. Its dimension is
limited by the size of the TINY BASIC program. See the description of
the SIZE function.
Functions
There are five functions in TINY BASIC.
ABS(X) - Returns the absolute vaulue of the variable X.
INP(X) - Returns data read from input port X. (0<=X<=255)
PEEK(X)- Returns the contents of memory location X. (-32767<=X<=32767)
RND(X) - Returns a random number between 1 and X (inclusive).
SIZE - Returns the number of bytes left unused by the program.
Arithmetic and Comparison Operators
The following operators are supported:
/ - integer divide (fractional results not returned)
* - integer multiply
- - subtract
+ - add
> - compare if greater than
< - compare if less than
= - compare if equal to
NOTE: multiple assignment statements are not supported,
i.e., "LET A=B=O" is interpreted by TINY BASIC as
meaning "set A to the result of comparing B with O".
# - compare if not equal to
>= - compare if greater than or equal to
<= - compare if less than or equal to
The +,-,*, and / operations return a value within the range -32767 ..
32767. TINY BASIC works exclusively with decimal numbers. In order to
represent the full range of numbers between 0 and 0FFFFH the
2
properties of two's complement arithemtic should be understood. For
example, in order to PEEK at memory location 0FFFFH, the parameter -0
should be used as the PEEK function argument. Notice that the PEEK
operation (as well as other address referenced operations) are all
relative to the current data segment, which should be the same as the
code segment.
All compare operations result in a 1 if the comparison is true
and a 0 if it is false.
Expressions
Expressions are formed with numbers, variables, and functions
with arithmetic and compare operators between them. + and - signs can
also be used at the beginning of an expression. The value of an
expression is evaluated from left to right, except that the * and /
operators are always given precedence, with + and -, and then the
compare operators following, in that order. Parentheses can be used
to alter the order of evaluation in the standard algabraic sense.
Statements
A TINY BASIC statement consists of a statement number between 1
and 32767 followed by one or more commands (see Commands below).
Commands in the same statement are seperated by a semi-colon ";".If
the "GOTO", "STOP", and "RETURN" commands are used then they must be
the last command in that statement.
Program
A TINY BASIC program consists of one or more statements. When
the direct command (see Direct Commands below) "RUN" is issued, the
statement with the lowest statement number is executed first, then the
one with the next lowest statement number, etc. The "GOTO", "GOSUB",
"STOP", and "RETURN" commands can alter this normal sequence. Within
any statement the execution takes place from left to right. The "IF"
command can cause remaining commands within the same statement to be
skipped.
Abbreviations and Blanks
TINY BASIC statements and commands may use blanks freely, except
that numbers, command key words, and function names may not have
embedded blanks.
All TINY BASIC command key words and function names may be
abbreviated by following the abbreviation with a period. For example,
"PR.", "PRI.", and "PRIN." all stand for "PRINT". The word "LET" in
the LET command may be ommited.
3
Editor
TINY BASIC contains a useful text editor for entering and
correcting TINY BASIC programs. All of the line editing features of
the host operating system are used. In order to correct an existing
TINY BASIC statement, that statement must be re-entered. Statements
may be deleted by simply typing their statement number, followed by a
CR. Corrections may be verified by typing LIST nnnn and striking the
control-X key to terminate the LIST process.
ERROR MESSAGES
There are only three error messages in TINY BASIC. When an error
is encountered the error message itself is printed, followed by the
statement causing the program error with a "?" inserted at the point
where the error is detected. Control is then passed to the TINY BASIC
monitor. A synopsis of the three error conditions follow.
-- WHAT?
WHAT?
210 P?TINT "THIS"
WHAT? indicates that TINY BASIC did not understand the statement
or command. In the example above, the command PRINT was mistyped on
statement number 210.
-- HOW?
HOW?
260 LET A=32000+5000?
HOW? indicates that TINY BASIC understands but cannot execute
the statement or command. In the example above, the sum of the numbers
exceeds 32767.
-- SORRY
SORRY
SORRY indicates that TINY BASIC understand but cannot execute
the statement or command due to insufficient memory. One cure is to
rephrase the TINY BASIC program in acceptable abbreviations.
4
STATEMENT COMMANDS
TINY BASIC statement commands are listed below with examples.
Remember that commands can be concatenated with semi-colons. In order
to store any given statement, you must precede that statement with a
statement number between 1 and 32767. Statement numbers are NOT shown
in the examples.
LET command
LET A=234-5*6;A=A/2;X=A-100;@(X+9)=A-1
The LET command assigns the value of an expression to the
specified variable. In the example above, the variable "A" assumes
the value of the expression "234-5*6", or "204". Then the variable "A"
assumes the value "102". Next, the variable "X" is set to the value of
the expression "A-100", or "2". The last command assigns the value
"101" to the array variable "@(11)". The "LET" portion of the LET
command is optional, i.e., the following examples are true:
A=10
C=5*3/5;C=C*5
REM Command
REM ANYTHING CAN BE WRITTEN AFTER "REM"
The REM command is ignored by TINY BASIC. It is used by
experienced programmers to comment BASIC programs. A program comment
is used by programmers to remind themselves of the logic of a program
section. All good programs are invariably commented.
PRINT Command
PRINT
PRINT will cause a carriage-return (CR) and a line-feed (LF) on
the output device.
PRINT A*3+1,"ABC"
This form of the PRINT command will print the value of the
expression A*3+1 on the output device, followed by the string ABC on
the same line. Note that single (') or double quotes (") may be used
to denote character strings, but that pairs must be mached.
PRINT A*3+1,"ABC",
This form of the PRINT command will produce the same results as
the previous example except that the normal CR-LF is inhibited by the
trailing comma at the end of the statement. This allows other PRINT
5
commands to print on the same line.
PRINT A,B,#3,C,D,E,#10,F,G
This form of the PRINT command demonstrates format control. The
format character # is used to indicate the number of leading spaces to
be printed before a number. The default number is 6. Once the # format
is invoked it is active for the remainder of the statement unless
overridden by a subsequent format specifier, as in the example.
PRINT 'ABC',\,'XXX'
The back-slash (\) character is used to cause a CR without a LF.
In this example, the string ABC is printed followed by the string XXX
on top of the original ABC.
INPUT Command
INPUT A,B
The INPUT statement is used to acquire input data during program
execution. In the example above, TINY BASIC will print A: and wait
for a number to be typed at the console terminal. Next, TINY BASIC
will print B: and wait for another number to be typed at the console
terminal. In this example the variables A and B will assume the values
of the appropiate input values. The INPUT statement will accept
expressions as well as numbers as input.
INPUT 'WHAT IS THE WEIGHT'A,"AND SIZE"B
In this example TINY BASIC will print the string WHAT IS THE
WEIGHT: and wait for operator input. Next, the string AND SIZE: will
be printed, on the same line, and TINY BASIC will wait for operator
input.
INPUT A,'STRING',\,"ANOTHER STRING",B
TINY BASIC will react to the back-slash character (\) in this
example in the same fashion as in the PRINT command. The second string
will overwrite the first string STRING.
IF Command
IF A<B LET X=3;PRINT 'THIS STRING'
The IF command works with the comparison operators (enumerated
above) to check the validity of the specified comparison condition. In
this example, if the comparison A<B is true, then the balance of the
commands in the statement are executed. However, if the comparison
tests false, then the balance of the commands in the statement are NOT
executed and control passes to the statement with the next highest
statement number.
6
IF A<B GOTO 100
This example illustrates a common use of the IF command and the
GOTO (see below) command. If the comparison tests true control is
passed to statement number 100, otherwise execution passes to the
statement with the next highest statement number.
GOTO Command
GOTO 120
This statement is used to modify the normal sequence of
execution of TINY BASIC statements. In this example, control is passed
unconditionally to statement number 120. The GOTO command cannot be
followed by a semi-colon and other commands within the same statement.
It must appear as the last command in any given statement.
GOTO A*10+B
This form of the GOTO is called a "computed GOTO". In this case,
control is passed to the statement number represented by the
expression that follows "GOTO".
GOSUB Command
GOSUB 120
The GOSUB command is used to invoke a subroutine at the
specified statement number (120 in the example). Control is passed to
statement number 120 and execution continues. A RETURN command (see
below) is used, within the subroutine, to cause TINY BASIC to pass
control to the statement that immediatly follows the GOSUB command
that caused the subroutine to execute. The GOSUB command cannot be
followed by any other commands within the same statement and it must
be the last command within any given statement. GOSUB commands can be
nested, limited by the size of the stack space (see below).
GOSUB A*10+B
In this example, the subroutine at the statement number equal to
the value of the expression is executed. This form of the statement
will cause a different subroutine to be executed depending upon the
value of the expression that follows "GOSUB".
RETURN Command
RETURN
The RETURN command causes execution to resume at the statement
that follows the GOSUB that caused the current subroutine to be
executed. It must be the last command of any given statement.
7
FOR Command
FOR X=1 TO 10
PRINT 'HELLO'
NEXT X
The FOR command is used to set up execution loops. In the TINY
BASIC program segment above the statement PRINT 'HELLO' is executed 10
times since it is placed between the FOR statement and the NEXT
statement. The NEXT X statement (see below) has the effect of
incrementing X by one and passing control to the FOR statement. If the
new value of X is still less than or equal to 10, the TINY BASIC
statements between FOR and NEXT are executed again. This process
repeats until X is incremented past the loop termination value (10 in
the example above).
FOR X=1 TO 10 STEP 2
PRINT 'HELLO'
NEXT X
In the above variant of the FOR command the loop increment has
been changed from 1 (the default) to 2 by means of the STEP clause. In
this case, the program fragment would only print HELLO five times if
executed.
FOR commands can be nested, that is, one FOR loop can contain
other FOR loops provided that the loop variables (the variable X in
the examples) are diferent,. If a new FOR command with the same loop
variable as that of an old FOR command is encountered, the old FOR
will be terminated.
NEXT Command
NEXT X
The NEXT command is part of the FOR command and is used to cause
loop variables to be incremented by the increment specified by the
STEP clause (default is 1) and to pass control to the appropiate TINY
BASIC FOR loop. The variable specified by the NEXT command (X in the
example) is used to specify the correct FOR loop.
POKE Command
POKE A,B
The POKE command is used to place data B into memory address A.
This command may be repeated as follows:
POKE A,B,C,D
In the above example, data B is placed in memory location A, then data
8
D is placed in memory location C. All variables may be expressions. Be
careful not to POKE TINY BASIC itself!
USR Command
USR(I,J)
The USR Command is actually a built-in TINY BASIC subroutine
call that permits linkage to machine language subroutines. All 8086
registers are available for use by the machine language subroutine. It
is the responsibility of the machine language routine to execute a RET
instruction. In the example above, a machine language routine at
address I is called. J is an optional parameter that, if present, will
be passed in register BX to the subroutine.
WAIT Command
WAIT I,J,K
The WAIT command is used to cause TINY BASIC execution to pause
and wait for a specified value at an 8086 input port. In the example
above, the value at input port I is read, exclusive OR'd with the
value of the expression J, and the result is then AND'd with the value
of expression K. WAIT will return only if the final result is
non-zero. WAIT provides an easy-to-use mechanism to cause TINY BASIC
to pause its execution and wait for a specified external event. J is
assumed to be 0 if not specified.
STOP Command
STOP
This command stops the execution of a TINY BASIC program and
passes control to the TINY BASIC monitor. It can appear many times in
a program but it must be the last command in any given statement.
DIRECT COMMANDS
Direct commands are those commands that can be invoked only by
the operator when TINY BASIC is in command mode (i.e. in response to
the '>' prompt). All statement commands (those listed above) can be
invoked while in command mode. Typing a control-C while in command or
monitor mode will cause TINY BASIC to terminate. Control is then
passed to the host operating system monitor.
Recall that a statment consists of a statement number followed
by one or more commands. If the statement number is missing, or if it
is 0, the command will be executed immediatly after typing the
9
terminating CR. The following commands can be used as direct commands;
they CANNOT be used as part of a TINY BASIC statement.
RUN Command
RUN
The RUN command causes execution of the stored TINY BASIC
program. Execution will commence at the lowest numbered statement and
continue until there are either no more statements to execute or a
STOP command is found. A long TINY BASIC program may be terminated by
typing control-X at the console. This passes control the the TINY
BASIC monitor. A control-C may be typed at any time also, then TINY
BASIC is terminated and control is passed to the host operating
system.
LIST Command
LIST
The LIST command is used to display the current TINY BASIC
program on the operator's console. The statements will be listed in
numerical order. If LIST is followed by an expression (e.g. LIST 200)
the listing will commence with statements following the specified
statement, inclusive.
NEW Command
NEW
The NEW command deletes the current program from TINY BASIC's
memory.
SAVE Command
SAVE FILENAME
The SAVE command saves the current TINY BASIC program on the
logged in disk with the specified filename FILENAME. The default
filetype is ".TBI". If there is insufficient room on the disk, the
SAVE command responds with "HOW?".
LOAD Command
LOAD FILENAME
The LOAD command loads the specified TINY BASIC program from the
logged in disk into the program area. Any program residing within TINY
BASIC prior to the LOAD operation is lost. If the specified program is
not found on the disk, or if there is insufficient room for the
10
program, LOAD responds with "HOW?". The filetype is assumed to be
".TBI".
BYE Command
BYE
The BYE command terminates TINY BASIC. Control is passed back to
the host operating system.
TINY BASIC OPERATION
TINY BASIC is initiated from the host operating system's command
mode like any other transient command. TINY BASIC will sign-on,
announce 'OK', and then prompt '>' awaiting operator interaction. An
example follows:
A:TBASIC
8086 TINY BASIC V1.0
OK
>
In the example above the program 'TBASIC.COM' was found on the
logged-in disk ('A' in the example). TINY BASIC then commenced
execution by first announcing itself and then prompting '>' for
operator input.
TINY BASIC utilizes all of the host operating system's line
editing facilities. For example, if an operator wished to cancel a
line typed to TINY BASIC, he need only type a control-X, etc. If hard
copy of a TINY BASIC session is desired, control-P and control-N will
toggle the printer, if it exists.
At present, saved TINY BASIC programs can be edited only with
the internal TINY BASIC editor. Programs prepared by an external
editor can not be read by TINY BASIC.
11
supported:
/ - i
Volume in drive A has no label
Directory of A:\
BASICAID BAS 66469 5-31-84 10:49p
BASICAID DOC 12716 5-31-84 11:32p
BASICAID EXE 65786 5-19-84 9:12p
BRENTBAS EXE 32464 2-09-85 8:56a
BRENTBAS UM 23317 2-09-85 10:24a
FILES381 TXT 845 7-08-85 2:40p
TBASIC ASM 46816 6-28-82 9:04p
TBASIC COM 2795 6-28-82 9:06p
TBASIC DOC 25344 7-27-81
9 file(s) 276552 bytes
43008 bytes free