Classic Computer Magazine Archive A.N.A.L.O.G. ISSUE 69 / FEBRUARY 1989 / PAGE 70

screen shotVARIABLE
NAME
TABLE
EDITOR


by Earl Davidson

I have a tendency to change my mind about variable names as I write programs. However, changing the name of a variable which is used many times throughout a program can be a pain, since BASIC provides no command to do this for us, and there is no search-and-replace function. I wrote the Variable Name Table Editor to give me an easier way to change variable names. It reads the header and Variable Name Table (VNT) from a SAVEd file, allows each variable name to be edited, then writes a new file to disk.
    As an Atari BASIC program is entered, each text line we type with the BASIC editor goes through a process often called precompiling. BASIC converts the line into a tokenized format which can be interpreted during program execution much faster than the text line we enter could be interpreted. The tokenized version of the line is placed into the Statement Table (ST). Other tables are built during this pre-compile process: the Variable Name Table (VNT), the Variable Value Table (VVT), and the String/Array Table.
    If the line entered contains a new variable, its name is added to the VNT, and information about the variable is placed into the VVT. If the variable is a string or array, it is added to the String/Array Table. In the tokenized version of the program line, the variable is represented by a one-byte token. This value of this byte is the position of the variable in the VNT, plus 128 ($80). A BASIC program may have only 128 variables, and their tokens range sequentially from 128 to 255 ($80 to $FF).
    The VNT is maintained by BASIC for the convenience of the programmer. It is used only by the LIST statement. When the program, or a portion of it, is listed, the variable token is used as an index into the VNT and the variable name is displayed. The variable name may be any length. It must consist of uppercase letters and numbers and must begin with a letter. This gives us considerable freedom to use descriptive variable names so that our programs are easier to read.
    When a program is written to disk using the LIST command, the file is exactly the same as if the program is listed to the screen. When it is later entered with the ENTER command, BASIC pre-compiles each line and builds the various tables just as if it were being typed in.
    However, when a program is written to disk using the SAVE command, the file consists of a 14-byte header and the various tables that have been built. The Statement Table is saved in its tokenized format. When the file is later entered with the LOAD command, the header portion of the file is used by the operating system as an index to the various tables and the tables are simply read and placed into the appropriate place in RAM.
    While we are entering a program, if we change a variable's name, the new name is placed into the VNT. The original name remains in the table, even if it is no longer used by the program. The only way to clear the original name and free up RAM and variable space is to LIST the program to disk, type NEW, and ENTER it back into memory, which creates a new VNT using only the variable names encountered in the file.

Changing the name of a variable
which is used many times throughout
a program can be a pain, so I wrote
Variable Name Table Editor
to make it easier.



Using VNT Editor
    When VNT Editor is run, a menu of four items is presented: Read file, Write file, Edit Variable Names, and Change All. First you must read the file you wish to modify. When editing the variable names, you should be careful to use valid names if you wish to be able to edit the program later. Although BASIC places no restriction on the length of variable names, VNT Editor limits you to 30 characters per name which should be sufficient. Replacing a short name with a long one can also cause problems later if the new name results in program lines that are longer than the BASIC editor will accept. Once you have completed your changes, write the file out to a new filename. The new file may then be LOADed as usual.
    VNT Editor does not force you to use valid variable names nor does it check for duplicate names. There may be occasions where you do not wish to use valid names. If your program uses all of RAM and you need a few more bytes you might wish to change all variable names to one letter names. BASIC will allow only 26 (A to Z) and considers the dollar sign on strings and the parentheses on arrays as part of the variable name. The Change All option allows you to change all variables' names to the same one-character name,which could save you several hundred bytes in a large program.
    If you have a program which you do not want other users to modify for some reason, you may change variable names to special characters. The resulting file will run properly, but if a line containing an invalid variable name is edited, an error will result which cannot be corrected. Try changing all variable names to a string of 30 question marks. The resulting file will run correctly, but when LISTed, will appear very strange.
    If you create a file with invalid or duplicate variable names, be sure to keep a copy of your original file for future use.

Program Explanation
    VNT Editor is straightforward, with no tricks or complicated routines. Remarks are not referenced, so you may omit them if you like.
    The Read File routine begins on Line 810. Line 830 reads the 14 -byte header for the file. Line 840 checks the first two bytes. They should both be decimal zero if the file is a SAVEd BASIC program. The third and fourth bytes contain an offset (from zero) from the end of the header to the beginning of the VNT+256. VNTSTART is set to this value in Line 850. The offset to the end of the VNT is one less than the start of the VVT. Line 860 assigns this value to VNTEND.
    The seventh and eighth bytes of the header contain the offset to the beginning of the VVT+256. VNTSTART is set to this value in Line 870. The offset to the end of the VVT is one less than the start of the ST. Line 880 assigns this value to VNTEND. The ninth and tenth bytes contain the offset to the beginning of the ST+256. Line 890 assigns this value to STSTART. The 13th and 14th bytes contain the offset to the end of the ST+256. Line 900 assigns this value to STEND.
    The fifth, sixth, 11th and 12th bytes of the header are not used by BASIC or VNT Editor.
    The VNT, as determined by VNTSTART AND VNTEND, is read and placed in the string VNT$. The length of VNT$ is stored in VNTLEN1 for use later. After editing the variable names, a new file is written by the routine beginning at Line 1010. Line 1040 checks to insure the destination filename is not the same as the source filename. The current length of VNT$ is stored in VNTLEN2 in Line 1060, and the difference between VNTLEN1 and VNTLEN2 is stored in CHANGE in Line 1070. The offsets found in HEADER$ are updated by the value of CHANGE in Lines 1080-1160.
    Line 1180 writes the HEADER$ to the new file. Line 1190 writes the new VNT$ to the new file. Line 1210 reads the old header and VNT from the old file and discards them. Line 1230 is a loop which reads a byte from the old file and writes it to the new file until the end of the old file is reached.
    Other sections of the program should be self-explanatory.
    VNT Editor will provide you with a new way to view and manipulate the VNT of your BASIC programs. The extra control and flexibility will be convenient on many programs and could be very helpful on larger programs using a large number of variables.

    Earl Davidson has been an avid Atari enthusiast for marry years. He is an active member of the Atari Users Group of Albany, GA, and as one of the owners of SoSoft, he wrote the user's manual for InSyst!, a small business inventory program for 8-bit Ataris.


LISTING 1: BASIC

HY 10 REM ******************************
RK 20 REM * VARIABLE MAKE TABLE EDITOR *
RU 30 REM *      by Earl Davidson      *
OH 40 REM *       Copyright 1988       *
SM 50 REM *    BY ANALOG COMPUTING     *
ID 60 REM ******************************
BN 60 REM
CO 70 GRAPHICS 0:POKE 710,0:POKE 709,0:PO
   KE 752,1:GOTO 1340
BF 80 REM
IA 90 REM *** GET KEY FROM KEYBOARD
QM 100 REM
ZE 110 ? "_←";:GET #1,KEY:KEY$=CHR$(KEY):
   RETURN
QQ 120 REM
NA 130 REM *** CLEAR LAST THREE LINES
QU 140 REM
QM 150 FOR J=21 TO 23:POSITION 1,J:? BL$;
   :NEXT J:RETURN
QY 160 REM
SR 170 REM *** BORDER
RC 180 REM
FX 190 FOR I=3 TO 17:POSITION 1,I:? BORDE
   R$:NEXT I:RETURN
ON 200 REM
RA 210 REM *** GET FILESPEC
QR 220 REM
GD 230 POSITION 2,21:? "ENTER FILESPEC: "
   ;
QV 240 REM
ZC 250 REM *** GET LINE
QZ 260 REM
ON 270 WORK$="":CHNUM=1
PY 280 GOSUB 110:KEY$=CHR$(KEY):IF KEY=15
   5 THEN ? " ";:RETURN
IZ 290 IF KEY=27 THEN CHNUM=0:WORKS="":?
   " ":RETURN
JL 300 IF KEY>127 THEN KEY=KEY-128:KEYS=C
   HR$(KEY)
QR 310 IF KEY=30 OR KEY=126 THEN IF CHNUM
   >2 THEN CHNUM=CHNUM-1.? " ";CHRS(126)
   ;:GOTO 280
EU 320 IF KEY=30 OR KEY=126 THEN IF CHNUM
   =2 THEN CHNUM=1:WORK$="":? " ";CHR$(1
   26);:GOTO 280
JS 330 IF KEY>26 AND KEY<32 OR KEY>124 TH
   EN ? CHR$(253);:GOTO 280
YB 340 IF CHNUM<MAXL THEN ? KEY$;:WORK$(C
   HNUM,CHNUM)=KEY$:CHNUM=CHNUM+1:GOTO 28
   0
MT 350 ? CHR$(253);:GOTO 280
RA 360 REM
GL 370 REM *** MENU FOR EDIT ROUTINE
RE 380 REM
OJ 390 IF SOURCES="NONE" THEN GOSUB 1720:
   GOTO 1520
YG 400 POSITION 14,1:? "Page ";PAGE+1;" o
   f ";INT(NUMVAR/15)+1;" "
WJ 410 POSITION 1 2:? "
   "
UX 420 GOSUB 190
ML 430 POSITION 1,18:? "
   "
GH 440 POSITION 1,19:? "    
    "
UN 450 GOSUB 540
LO 460 POSITION 2,20:? "Choice?
      ";:POSITION 10 20
EB 470 GOSUB 110:? KEY$;
AE 480 IF KEY$="E" THEN ? "dit";:GOTO 610
NE 490 IF KEY$="N" THEN ? "ext";:PAGE=PAG
   E+(PAGE(MAXPAGE):OS5UB 540:GOTO 460
LN 500 IF KEY$="P" THEN ? "evious";:PAGE=
   PAGE-(PAGE>0):GOSUB 540:GOTO 460
FG 510 IF KEY$="M" THEN ? "enu";:GOTO 142
   0
XD 520 IF KEY=27 OR KEY=155 THEN POSITION
    10,20:? "Menu";:GOTO 1428
PI 530 GOTO 460
XE 540 POSITION 19,1:? PAGE+1
NT 550 POSITION 2 3:LONUM=1+PAGE*15:HINUM
   =15+PAGE*15:BLANK=0:IF HINUM>NUMVAR TH
   EN BLANK=HINUM-NUMVAR:HINUM=NUMUAR
JL 560 FOR I=LONUM TO HINUM:WORK$=BL$:LM=
   1:IF I<100 THEN LM=2:IF I<10 THEN LM=3
SE 570 VAR$=UNT$(VNUM(I),VNUM(I+1)-1):VAR
   L=LEN(VAR$):CH=ASC(VAR$(VARL)):CH=CH-1
   28:VAR$(VARL)=CHR$(CH)
XA 580 WORK$(LM,3)=STR$(I):WORK$(5,4+LEN(
   VAR$))=VAR$:? WORK$:NEXT I
FO 590 IF BLANK THEN FOR I=1 TO BLANK:? B
   L$:NEXT I
ZC 600 RETURN
NJ 610 POSITION 2,20:? "Edit variable #?
      ":POSITION 19,20
HU 620 MARL=4:GOSUB 270:IF WORKS="" THEN
   GOSUB 150:GOTO 460
EU 630 TRAP 640:I=VAL(WORK$):IF I>0 AND I
   <1+NUMVAR THEN GOTO 650
SE 640 ? CHR$(253):POSITION 2,21:? "
   ":GOSUB 1650:GOSUB 150:GOTO
   610
EH 650 TRAP 40000:POSITION 1,21:? ""
   ;
SD 660 VAR$=VNT$(VNUM(I),VNUM(I+1)-1):VAR
   L=LEN(VAR$):CH=ASC(VAR$(VARL)):CH=CH-1
   28:VAR$(VARL)=CHR$(CH)
XN 670 WORK$=BL$(1,30):WORK$(1,LEN(VAR$))
   =VAR$:? WORK$
MW 680 P05ITION 1,22:? "";:MAXL=31:G
   OSUB 270:IF WORK$="" THEN GOTO 770
IK 690 VARL1=LEN(WORK$):WORK$(VARL1+1)=BL
   $(VARL1+1,32):POSITION 6,I-(PAGE*15)+2
   :? WORK$;
EB 700 WORK$=WORK$(1,VARL1):CH=ASC(WORK$(
   VARL1)):CH=CH+128
CE 710 WORK$(VARL1)=CHR$(CH)
RQ 720 CHANGE=VARL1-VARL
WM 730 IF I=NUMVAR THEN VNT$=VNT$(1,(VNUM
   (I)-1)):VNT$(VNUM(I))=WORK$:GOTO 760
UQ 740 VNT1$=VNTS(VNUM(I+1),LEN(UNT$))
DI 750 VNT$(VNUM(1))=WORK$:VNT$(LEN(VNT$)
   +1)=VNT1$
BP 760 FOR J=I+1 TO NUMVAR+1:VNUM(J)=VNUM
   (J)+CHANGE:NEXT J
HP 770 GOSUB 150:GOTO 460
RI 780 REM
TY 790 REM *** READ FILE ROUTINE
QT 800 REM
GH 810 TRAP 1690:VNT$="":SOURCE$="":NUMVA
   R=0:MAXL=16:GOSUB 230:IF WORK$="" THEN
    GOSUB 150:SOURCE$="NONE":GOTO 1520
DK 820 SOURCE$=WORK$:POSITION 2,21:? "
       READING";:CLOSE #2:OPEN #2,4,0,SOU
   RCE$:I=1
FO 830 FOR I=1 TO 14:GET #2,A:HEADER$(I,I
   )=CHR$(A):NEXT I
RN 840 IF HEADER$(1,1)<>CHR$(0) AND HEADE
   R$(2,2)<>CHR$(0) THEN GOTO 1730
DL 850 VNTSTART=(ASC(HEADER$(3,3))+ASC(HE
   ADER$(4,4))*256)-256
JS 860 VNTEND=(ASC(HEADER$(7,7))+ASC(HEAD
   ER$(8,8))*256)-256-1
CF 870 VVTSTART=(ASC(HEADER$(7,7))+ASC(HE
   ADER$(8,8))*256)-256
DD 880 VVTEND=(ASC(HEADER$(9,9))+ASC(HEAD
   ER$(10,10))*256)-256-1
HZ 890 STSTART=(ASC(HEADER$(9,9))+ASC(HEA
   DER$(10,10))*256)-256
QB 900 STEND=(ASC(HEADER$(13,13))+ASC(HEA
   DER$(14,14))*256)-256
JS 910 FOR I=(VNTSTART+1) TO VNTEND:GET #
   2,A:VNT$(I,I)=CHR$(A):NEXT I:CLOSE #2
PU 920 VNTLEN1=LEN(VNT$):REM
  
FZ 930 VNUM(1)=1:I=2
AN 940 FOR J=1 TO VNTLEN1:IF ASC(VNT$(J,J
   ))>127 THEN VNUM(I)=J+1:I=I+1
GT 950 NEXT J
TR 960 NUMVAR=I-2:MAXPAGE=INT(NUMUAR/15):
   PAGE=0
W5 970 GOSUB 150:GOTO 1520
RK 980 REM
TU 990 REM *** WRITE FILE ROUTINE
HW 1000 REM
WB 1010 IF SOURCE$="NONE" THEN GOSUB 1720
   :GOTO 1520
GJ 1020 MAXL=16:GOSUB 230:DESTINATION$=WO
   RK$
DS 1030 IF WORK$="" THEN GOSUB 150:GOTO 1
   520
OD 1040 IF SOURCE$=DESTINATION$ THEN GOSU
   B 1740:GOTO 1010
FR 1050 POSITION 2,21:? "       WRITING";
EU 1060 VNTLEN2=LEN(VNT$):REM
  
DO 1070 CHANGE=VNTLEN2-VNTLEN1
FV 1080 VVTSTART=VVTSTART+CHANGE
PC 1090 VVTSTARTHI=INT(VVTSTART/256):HEAD
   ER$S(8,8)=CHR$(VVTSTARTHI+1)
OH 1100 VVTSTARTLO=VVTSTART-(VVTSTARTHI*2
   56):HEADER$(7,7)=CHR$(VVTSTARTLO)
LR 1110 STSTART=STSTART+CHANGE
DU 1120 STSTARTHI=INT(STSTART/256):HEADER
   $(10,10)=CHR$(STSTARTHI+1)
MS 1130 STSTARTLO=STSTART-(STSTARTHI*256)
   :HEADERS(9,9)=CHR$(STSTARTLO)
ES 1140 STEND=STEND+CHANGE
FW 1150 STENDHI=INT(STEND/256):HEADER$(14
   ,14)=CHR$(STENDHI+1)
QI 1160 5TENDLO=STEND-(STENDHI*256):HEADE
   R$(13,13)=CHR$(STENDLO)
IK 1170 TRAP 1700:CLOSE #3:OPEN #3,8,0,DE
   STINATION$
OP 1180 FOR I=1 TO 14:A=ASC(HEADER$(I,I))
   :PUT #3,A:NEXT I:REM WRITE NEW HEADER
YL 1190 FOR I=1 TO LEN(VNT$):A=ASC(VNT$(I
   ,I)):PUT #3,A:NEXT I:REM WRITE NEW VNT
WB 1200 CLOSE #2:OPEN #2,4,0,SOURCE$
MU 1210 FOR I=1 TO VNTLEN1+14:GET #2,A:NE
   XT I:REM THROW AWAY OLD UNT AND HEADER
OE 1220 TRAP 1240
RF 1230 GET #2,A:PUT #3,A:GOTO 1230:REM R
   EAD REMAINDER OF FILE AND WRITE IT TO
   NEW FILE
XC 1240 CLOSE #2:CLOSE #3:GOSUB 150:GOTO
   1520
CZ 1250 POSITION 2,20:? "Change All to (<
   C/R) to EXIT): ":POSITION 5,21:MAXL=30
   :GOSUB 270
EF 1260 IF WORK$="" THEN GOSUB 150:GOTO 1
   520
XH 1270 A=ASC(WORK$(LEN(WORK$))):A=A+128:
   WORK$(LEN(WORK$))=CHR$(A)
DG 1280 VNT$="":VNT$=WORK$:VNUM(2)=LEN(WO
   RK$)+1:FOR I=2 TO NUMVAR:VNT$(LEN(VNT$
   )+1)=WORK$:VNUM(I+1)=LEN(VNT$)+1
FU 1290 NEXT I
QU 1300 POSITION 5,21:? BL$:GOTO 1520
IF 1310 REM
TS 1320 REM *** INITIALIZATION
IL 1330 REM
WE 1340 DIM KEY$(I),VNT$(3840),VNT1$(3840
   ),MEADER$(14),BL$(36),SOURCE$(15),DEST
   INATION$(15) WORK$(40),VNUM(128)
QX 1350 DIM VAR$(30),BORDER$(30)
BS 1360 BL$=" ":BL$(36)=BL$:BL$(2)=BL$
KV 1370 SOURCE$="NONE":BORDER$=CHR$(153):
   BORDER$(2)=BL$:BORDER$(38,38)=CHR$(25)
   :FIRST=1
XE 1380 OPEN #1,4,8,"K:":REM OPEN KEYBOAR
   D
JD 1390 REM
JW 1400 REM *** MAIN MENU
IH 1410 REM
FQ 1420 TRAP 40000:POKE 752 1:POSITION 1
   0:? "
  
XW 1430 POSITION 1,1:? BL$;

HT 1440 POSITION 1,2:? "
   "
AB 1450 GOSUB 190
GD 1460 POSITION 1,18:? "
    "
SH 1470 POSITION 1,19:? " 
        "
PX 1480 POKE 82,3:POSITION 14,4:? "INSTRU
   CTIONS":POSITION 14,5:? ""
FD 1490 ? "READ the Variable Name Table f
   rom":? "a SAVED Basic program."
TL 1500 ? :? "Edit individual variables o
   r":? "change all the variables at once
   ."
YT 1510 ? :? "Then WRITE the modified pro
   gram":? "to a new disk file.":POKE 82,
   2
WB 1520 TRAP 1420:POSITION 9,15:? "File l
   oaded: ";SOURCE$;BL$(1,15-LEN(SOURCE$)
   );
MF 1530 POSITION 9,16:? "# variables: ";N
   UMVAR;BL$(1,5);
VE 1540 POKE 709,12
LS 1550 POSITION 2,20:? "Choice? ";BL$(1,
   24);:POSITION 10,20:IF FIRST THEN FIRS
   T=0:KEY$="R":? KEYS;:GOTO 1570
VA 1560 GOSUB 110:POSITION 10,20:? KEY$;
EV 1570 IF KEY$="R" THEN ? "ead File":GOT
   O 810
OT 1580 IF KEY$="E" THEN ? "dit VNT":GOTO
    390
JQ 1590 IF KEY$="W" THEN ? "rite File":GO
   TO 1010
EX 1600 IF KEY$="C" THEN ? "hange All":GO
   TO 1250
OU 1610 ? CHR$(253);:GOTO 1550
IO 1620 REM
XF 1630 REM *** WAIT LOOP
IU 1640 REM
AM 1650 FOR J=1 TO 156:NEXT J:RETURN
JA 1660 REM
FP 1670 REM *** DISK ERROR ROUTINES
JG 1680 REM
FI 1690 SOURCE$="NONE":NUMVAR=0
BI 1700 CLOSE #2:CLOSE #3:POSITION 2,22:?
    " ";PEEK(195);"  ";PEEK(
   186)+256*PEEK(187)
XJ 1710 FOR I=101 TO 255 STEP 2:SOUND 8,I
   ,10,10:NEXT I:SOUND 0,0,0,0:GOSUB 150:
   GOTO 1520
OX 1720 POSITION 2,22:? CHR$(253);"
   ";:GOSUB 1658:GOSUB 158:RETUR
   N
ZM 1730 P05ITION 2,22:? CHRS(253);"
   ":GOSUB 1650:GOSUB 150:SOURC
   E ="NONE":NUMVAR=0:GOTO 1520
RM 1740 POSITION 2,22:? CHRS(253);"
   ":;? "";:
   GOSUB 1650:GOSUB 150:RETURN