PET
Relative File
Field Separator
T. A. Zucal
Field Separator
T. A. Zucal
A few lines of BASIC and a small machine language routine solve some speed and syntax problems faced when accessing relative records. For PET/CBMs with 4.0 BASIC and disk.
Often relative files can become more efficient if each record is broken down into fields. When of a fixed length, these fields are easily handled at reasonable speed. But when you attempt to bring fields of variable length in from the file, the coding can get messy. It is necessary to use the LEN( ) function to count bytes, always remembering to add the extra byte for the field delimiter. In addition, this method will not adequately handle commas or colons.
An alternative is to use one string for the entire record, and then to separate the fields using the MID$() function in conjunction with the field delimiters. But this method works only if the record length is 80 bytes or less. This is not too bad, but again commas and colons present problems. A third alternative into use GET#, which will handle colons and commas, but is extremely slow.
Solving The Problem
All of this can be bypassed with a minor addition to the machine code of Jim Butterfield's "String Thing" (COMPUTE!, November 1982) and a couple of lines of BASIC. This method will handle all characters at a reasonable speed and with no confusion.
The BASIC loader program moves the machine language code to high memory and works with any size memory. You should copy for later use the SYS memory locations which the loader displays on screen. However, the test program will also adjust itself to any size machine. The delimiter used in this version is the backslash - the slash located above the "I" on graphic keyboards. If you prefer, you can choose any other character by changing the 92 in DATA line number 270 to the PETASCII value of the character desired.
The test program will create a relative file with two records. Record #1 is used by the field separator routine; record #2 is used by the byte count and GET# methods. Each record is exactly the same number of bytes to permit a fair speed test.
When this test is run on all three options, you will notice that the Field Separator Method is approximately 12 jiffies faster than byte counting and 85 jiffies faster than the GET# method. However, the GET# is the only other method which will handle colons and commas without a hassle. So, this method will save you one minute for every 42 records read and will handle all types of input. Even if your fields don't contain the problem characters, you still save 20 seconds for every 100 records.
Program 1: Loader For Field Separator Routine
120 REM ** FIELD SEPARATOR FOR RELATIVE FI
LES
125 REM
130 PRINT"{CLEAR}{02 DOWN}NOW LOADING"
135 REM *** FIND CURRENT TOP OF MEMORY
140 MM=PEEK(52)+PEEK(53)*256
145 REM *** CALCULATE & SET NEW TOP OF MEM
ORY
150 M=MM-129:GOSUB315
155 POKE52,L%:POKE53,H%
160 REM *** LOAD PROGRAM FROM DATA
165 FORI=MM-128TOMM-53
170 READA%
175 REM *** ADJUST DATA FOR MEMORY SIZE
180 IFI=MM-110THENM=MM-52:GOSUB315:A%=L%
185 IFI=MM-109THENA%=H%:LS%=L%:HS%=H%
190 IFI=MM-68THENA%=L%
195 IFI=MM-67THENA%=H%
200 IFI=MM-63THENM=MM-51:GOSUB315:A%=L%
205 IFI=MM-62THENA%=H%
210 IFI=MM-59THENA%=LS%
215 IFI=MM-58THENA%=HS%
220 IFI=MM-54THENM=MM-79:GOSUB315:A%=L%
225 IFI=MM-53THENA%=H%
230 POKEI,A%
235 POKE32862,A%
240 NEXTI
245 DATA160,2,177,42,153,134,0,200
250 DATA192,6,208,246,152,72,160,0
255 DATA152,153,204,127,200,192,51,208
260 DATA248,104,168,162,1,32,198,255
265 DATA32,228,255,201,13,240,15,164
270 DATA139,145,137,200,132,139,201,92
275 DATA240,7,196,136,208,234,76,204
280 DATA255,152,72,172,204,127,165,139
285 DATA153,205,127,200,140,204,127,104
290 DATA168,76,177,127
295 PRINT"{CLEAR}"
300 PRINT"FIELD SEPARATOR LOADED"
305 PRINT"{DOWN}CALL WITH SYS"PEEK(52)+256
*PEEK(53)+1
310 END
315 H%=M/256:L%=M-H%*256:RETURN
Program 2: Test Of Separator Routine
100 REM ** FIELD SEPARATOR TEST PROGRAM
105 REM ** STRING MUST BE FIRST VARIABLE
110 A$="ABCDEFGHIJKLMNOPQ"
115 A$=A$+A$+A$+A$+A$
120 A$=A$+A$+A$
125 REM ** FOR RELATIVE FILES STRING IS SA
FE SET AT MAXIMUM, (255) AS ABOVE
130 REM ** SET UP RELFILE WITH 2 RECORDS
135 REM ** BOTH RECORDS HAVE SAME CHARACTE
R COUNT
140 PRINT"{CLEAR}{03 DOWN}CREATING RELATIV
E FILE, 'RELFILE "'
145 DOPEN#1,"RELFILE",D0,L254
150 P$="RECORD1**FIELD-1\THIS IS FIELD #2\
FIELD #3\PET/CBM ++++\FIELD #5\"
155 P$=P$+"###FIELD 6###\YOU CAN HAVE UP T
O\50 FIELDS BUT ARE LIMITED\"
160 P$=P$+"TO 254 CHARACTERS, PLUS\THE RET
URN AT THE END."
165 RECORD#1,1
170 PRINT#1,P$
175 R$=CHR$(13)
180 P$="RECORD1**FIELD-1"+R$+"THIS IS FIEL
D #2"+R$+"FIELD #3"+R$+"PET/CBM +
+++"
185 P$=P$+R$+"FIELD #5"+R$+"###FIELD 6###"
+R$+"YOU CAN HAVE UP TO"+R$
190 P$=P$+"50 FIELDS BUT ARE LIMITED"+R$+"
TO 254 CHARACTERS, PLUS"+R$
195 P$=P$+"THE RETURN AT THE END."+R$+"END
"
200 RECORD#1,2
205 PRINT#1,P$
210 DCLOSE#1
215 REM
220 DIMF$(50)
225 REM ** JUMP TO MENU FOR TESTING
230 GOTO320
235 REM ** THE FOLLOWING IS THE ACTUAL USA
GE ROUTINE
240 ML=PEEK(52)+1+256*PEEK(53)
245 DT=ML+76
250 DOPEN#1,"RELFILE"
255 TM=TI
260 RECORD#1,1
265 SYSML
270 PRINT"{CLEAR}{DOWN}STRING THING METHOD
RUNNING{DOWN}"
275 NF=PEEK(DT)+1:POKEDT+NF,PEEK(139)+1
280 FORI=lTONF
285 F$(I)=MID$(A$,PEEK(DT+I-1)+1,PEEK(DT+I
)-PEEK(DT+I-1)-1)
290 PRINTF$(I)
295 NEXTI
300 REM ** END OF ACTUAL ROUTINE
305 PRINT"{DOWN}THE TIME FOR INPUT, SEPARA
TION, AND PRINTING OF THE ABO
VE WAS";
310 PRINT"{REV}"TI-TM"{OFF}JIFFIES."
315 DCLOSE#1
320 PRINT"{DOWN}TO TIME THESE OPTIONS HIT -
NUMBER DESIRED"
325 PRINT"{REV}BUT WAIT FOR DRIVE TO STOP -
FOR FAIR TEST{OFF}"
330 PRINT"{DOWN} 1-GET#"
335 PRINT" 2-BYTE COUNTING"
340 PRINT" 3-STRING THING WITH FIELD SEPAR
ATOR"
345 PRINT" 4-QUIT"
350 GETR$:IFR$=""THEN350
355 IFVAL(R$)<1ORVAL(R$)>4THEN320
360 ONVAL(R$)GOT0370,440,240,495
365 REM ** STANDARD GET#
370 PRINT"{CLEAR}{DOWN}STANDARD GET#{DOWN}
"
375 DOPEN#1,"RELFILE"
380 TM=TI
385 I=1
390 Q$=""
395 RECORD#1,2
400 GET#1,R$:IFR$=CHR$(13)THEN410
405 Q$=Q$+R$:GOTO400
410 IFQ$="END"THEN420
415 PRINTQ$:F$(I)=Q$:Q$="":I=I+1:GOTO400
420 PRINT"{DOWN}THE TIME WAS{REV}"TI-TM"{O
OFF}JIFFIES FOR GET#."
425 DCLOSE#1
430 GOTO320
435 REM ** BYTE COUNT
440 PRINT"{CLEAR}{DOWN}BYTE COUNT METHOD N
OW RUNNING{DOWN}"
445 DOPEN#1,"RELFILE"
450 TM=TI
455 BY=1:I=1
460 RECORD#1,2,(BY)
465 INPUT#1,F$(I)
470 BY=BY+LEN(F$(I))+1
475 IFF$(I)<>"END"THENPRINTF$(I):I=I+1:GOT
O460
480 PRINT"{DOWN}THE TIME WAS{REV}"TI-TM"{
OFF}JIFFIES AND THE COMMA CAUSED
A PROBLEM"
485 DCLOSE#1
490 GOTO320
495 STOP