Easy File Input:
The String Thing
Jim Butterfield
Associate Editor
For Upgrade and 4.0 BASIC PET/CBM, String Thing solves the problems created by INPUT # and is faster.
Files are easy to handle, but sometimes the INPUT# statement is too clever. It looks so carefully at the material coming in from the file that it can overprocess your information. The INPUT # statement:
- —trims spaces from the front of the data;
- —trims quotation marks from front and back;
- —gives trouble if you want to input over 80 characters;
- —drops commas and following information; and
- —drops colons and following information.
You often don't want such things to happen when you are reading a file. But the alternative is to use GET# statements, and they are slow.
Some years ago, Bill McLean, of B.M.B. Compuscience, wrote a String Thing to get around these problems and speed up input. It worked well on Upgrade ROMs, but the transition to 4.0 systems was uncomfortable; strings are stored in a different way in the newer BASIC, and the code needed major surgery. Extra code is needed in order to avoid falling prey to a berserk garbage collection routine. This made the job rather complex and called for two different versions for the two different ROM sets.
New And Improved?
It seems to be time to unearth a new String Thing, one that will work without change on both Upgrade and 4.0 BASIC PETs and CBMs. This way, your program can still move between machines without difficulty. But there's a problem: since different BASIC versions store strings in different ways, how can we make one program compatible with all?
The trick is this: instead of trying to build a new string, we'll re-use an old one. We must be careful: if the string we are recycling is only ten characters long, we must be sure we don't try to put 11 new characters into it.
How To Use It
The program listing comes in two parts: setting up the String Thing and using it. There are two things we need to do in order to set up: define the program's first variable as a string (in the example, A$), making sure that it's long enough to hold any input that we might want to catch (in this case, up to 255 bytes); and then POKEing the String Thing program into place. This setup takes place in lines 70 to 260.
Now that we have String Thing in place, we need to use it. That's the easy part: we just give SYS 896, and the program performs the equivalent of INPUT# 1,A$ without the problems of INPUT. You may remember that we set A$ to a very long string; it will keep its length, but we can find out how many characters have been read by checking PEEK(139). String Thing uses location 139 to record how many characters it has received. If the first thing to come from the file is a RETURN character, this value will be zero, indicating no data characters received. On the other hand, if we fill the string space completely and still have not seen a RETURN, we'll stop at that point. The next call to String Thing will get more of the same sequence.
Some usage hints: Try to leave a string that is at least one character longer than the data you expect. If PEEK(139) ends up equal to the string length, we haven't seen the RETURN character yet-better to leave extra room. Remember that all the things that happen with an INPUT# will happen with String Thing, such as ST signalling end of file. Don't try to change your string variable (in this case, A$) as the program runs; copy the information out to another variable if you need it, e.g., X$=LEFT$(A$,PEEK(139)). String Thing isn't location sensitive; you can move it to some other location with little trouble.
String Thing will work correctly in reading files from cassette tape or disk. Just change the OPEN statement to suit. You won't notice the speed advantage on tape, of course, but you may still benefit from the improved logic handling. String Thing works splendidly with Relative disk files. Position to the record you want in the usual way, with RECORD#1, and then substitute the SYS statement for the INPUT#1.
Try the following demonstration program. You can change the file name in line 400 to any sequential file of your own, or you can write a demonstration file using the following direct statements:
OPEN 1,8,3, "file,s,w" PRINT#1, "line 1, with comma" PRINT#1, "mission: impossible" PRINT#1, CHR$(34); "quotes";CHR$(34) FOR j = 1 to 40 : PRINT#1,j; : NEXT j : PRINT#1 PRINT#1,"spaced out" CLOSE 1
If you like, try getting this DATA back using INPUT # statements.
Now for String Thing:
70 REM ** STRING THING (PET/CBM) ** 75 REM ** UPGRADE AND 4.0 BASIC ** 80 REM ** JIM BUTTERFIELD ** 90 REMARK: STRING MUST BE FIRST VARIABLE 100 A$ = "ABCDEFGHIJKLMNOPQ" 110 A$ = A$+A$+A$+A$+A$ 120 A$ = A$+A$+A$ 130 REM ABOVE SETS STRING FOR MAX (255) 200 DATA 160, 2, 177, 42, 153, 134, 0, 200, 192, 6 210 DATA 208, 246, 162, 1, 32, 198, 255 220 DATA 32, 228, 255, 201, 13, 240, 11, 164, 139, 145 230 DATA 137, 200, 132, 139, 196, 136, 208, 238, 76, 204, 255 250 FOR J = 896 To 933 : READ X : POKE J, X : T = T + X : NEXT J 260 IF T <>5517 THEN STOP 400 OPEN 1, 8, 2, "FILE" (OR DOPEN#1, "FILE") 410 REM: NEXT SYS SAME AS ‘INPUT#1, A$’ 420 SYS 896 425 REM: 1 = SIZE OF INPUT (COULD BE 0) 430 L = PEEK (139) 440 PRINT LEFT$ (A$, 1) 450 IF ST = 0 GOTO 420 460 CLOSE 1 (OR DCLOSE)
Alternate Versions
For VIC and Commodore 64 machines, we may once again choose between cassette tape and disk. I've written the disk version below; to get a cassette version, you'll need to do a little juggling. That's because the String Thing program sits in the cassette buffer; it will need to be moved elsewhere if you need to use tape.
Now for the String Thing program:
70 REM ** STRING THING ** 75 REM ** VIC AND COMMODORE 64 ** 80 REM ** JIM BUTTERFIELD ** 90 REM STRING MUST BE FIRST VARIABLE 100 A$ = "ABCDEFGHIJKLMNOPQ" 110 A$ = A$ + A$ + A$ + A$ + A$ 120 A$ = A$ + A$ + A$ 130 REM ABOVE SETS STRING FOR MAX (255) 200 DATA 160,2,177,45,153,137,0,200,192,6 210 DATA 208,246,162,1,32,198,255 220 DATA 32,228,255,201,13,240,11,164,142,145 230 DATA 140,200,132,142,196,139,208,238,76,204,255 250 FOR J = 896 TO 933 : READ X : POKE J,X:T=T + X : NEXT J 260 IF T<> 5535 THEN STOP 400 OPEN 1,8,3, "FILE" 420 SYS 896 425 REM: 1 = SIZE OF INPUT (COULD BE 0) 430 L = PEEK (142) 440 PRINT LEFTS (A$, 1) 450 IF ST = 0 GOTO 420 460 CLOSE 1
If you have an Original ROM machine, you can't handle disk. Even tape files have certain problems. If you plan to write and read files, you will be much better off if you upgrade your machine to Upgrade ROM. This can be done with a chip change. Even so, let's show that String Thing can be made to work here: we'll read a tape on an Original ROM system.
You may write a demonstration file TO tape in exactly the same way as before, except that you must change the OPEN statement TO:
OPEN 1, 1, 1, "file" 70 REM ** STRING THING ** 75 REM ** ORIGINAL ROM BASIC ** 80 REM ** JIM BUTTERFIELD ** 90 REM STRING MUST BE FIRST VARIABLE 100 A$ = "ABCDEFGHIJKLMNOPQ" 110 A$ = A$ + A$ + A$ + A$ + A$ 120 A$ = A$ + A$ + A$ 130 REM ABOVE SETS STRING FOR MAXIMUM (255) 200 DATA 160,2,177,124,153,216,0,200,192,6 210 DATA 208,246,162,1,32,198,255 220 DATA 32,228,255,201,13,240,11,164,221,145 230 DATA 219,200,132,221,196,218,208,238,76,204,255 250 FOR J = 896 TO 933 : READ X : POKE J,X : T + X : NEXT J 260 IF T <>6009 THEN STOP 400 OPEN 1,1,0, "FILE" 410 REM: NEXT SYS SAME AS ‘INPUT#1, A$’ 420 SYS 896 422 REM: ST LOGIC CHANGE 423 IF ST = 0 GOTO 460 425 REM : 1 = SIZE OF INPUT (COULD BE 0) 430 L = PEEK (221) 440 PRINT LEFTS (A$, 1) 450 GOTO 420 460 CLOSE 1
Assembly Listing
For those who would like to track the machine language, here's the assembly version of the program. The version is Upgrade/4.0 ROMs (the first BASIC program).
0380 A0 02 LDY #2 Copy string… 0382 B1 2A LOOP1 LDA (VARTAB),Y info TO work 0384 99 86 00 STA WORK,Y area 0387 C8 INY ..Four bytes 0388 C0 06 CPY #6 038A D0 F6 BNE LOOP1 038C A2 01 LDX #1 Connect file #1 038E 20 C6 FF JSR CHKIN ..as input. 0391 20 E4 FF LOOP2 JSR GETIN Get character 0394 C9 0D CMP #$0D Return? 0396 F0 0B BEQ QUIT Yes, quit 0398 A4 8B LDY COUNT No, get pointer 039A 91 89 STA (STRING),Y ..and stash char 039C C8 INY Count it 039D 84 8B STA COUNT Save count 039F C4 88 CPY LENGTH Full string? 3A1 D0 EE BNE LOOP2 Nope, do more 03A3 4C CC FF JMP CLRCHN Disconnect&quit
String Thing solves many file input problems: in particular, long data blocks and special characters become very simple. It's as fast as INPUT, but for most purposes it's better.
Copyright © 1982 Jim Butterfield