PCjs Machines

Home of the original IBM PC emulator for browsers.

Logo

PC-SIG Diskette Library (Disk #381)

[PCjs Machine "ibm5160"]

Waiting for machine "ibm5160" to load....

Information about “BASIC AIDS NO 4”

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

BASICAID.BAS

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.DOC


                            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.


FILES381.TXT

------------------------------------------------------------------------
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

TBASIC.ASM

;***************************************************************
;*
;*
;*      	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

TBASIC.DOC







                             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

Directory of PC-SIG Library Disk #0381

 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