Coding
I wanted to touch on some basic IO access via TurboForth to continue from last months newsletter.
I have been in contact with Mark Wills to get an example of some basic File IO. Mark put the below together for publishing in this months newsletter. Thanks Mark, this will help a lot of us have a better understanding of TurboForth File IO.
1 2 3 4 5 6 7
..................................................................
Opening Text Files in TurboForth
--------------------------------
Chris recently asked me how simple file I/O is done in TurboForth, so here is a quick article to show how to read a text file (DV80) from disk.
If you have any experience with file I/O in TI Basic or Extended Basic then you will find that getting ready tp open a file in particular is very different in TurboForth. However, once the file has been opened, it's all quite natural; not that different from Basic.
The code shows the procedure. Everything you need to know/do to open a DV80 file for input. The code is heavily commented. A pure versionof the code, with all the comments removed is given later.
If you don't know anything about Forth, the the best place to start is here:
turboforth.net/about_forth.html
The above link builds on very first principles. Then, when you have read that, have a look at the tutorials on TurboForth.net:
turboforth.net/tutorials/tutorials.html
The tutorials start from the very first basic principles and build up in complexity.
So, here's the code to open a DV80 file and display it:
Lines of text with a preceding \ are comments and are ignored by
TurboForth...
\ first, create a file buffer. This is used to hold information
\ about the file(s) we want to work with.
\ using the word FBUF: we're going to create a file buffer called fileIn.
\ Once defined, fileIn exists as a word just like any other word. When
\ used in a program/word, it will push the address of its buffer to the
\ stack.
FBUF: fileIn
\ now, create a buffer to hold the lines of text/data that is read in
\ from the file. Here, we create a buffer called buffer, with a size
\ of 82 bytes (chars).
CREATE buffer 82 CHARS ALLOT
\ now define a word called typeFile. This is where all the work
\ will be done...
: typeFile ( -- )
\ now we're going to use the word FILE to define the name of the file
\ that we want to open, and its type. FILE needs two things:
\ a string containing the file name and file characteristics, and the
\ file buffer to use. As can be seen below, were giving a string and
\ also the file buffer fileIn to FILE. FILE will then build a PAB
\ (peripheral access block) in the buffer. All subsequent file ops on
\ this file will use fileIn as a reference.
S" DSK1.TEST.TXT DV80SI" fileIn FILE
\ in the string above, DV80SI simply informs the file system that we
\ want to open the file as *D*isplay *V*ariable 80, for *S*equential
\ *I*nput. There are other modes. They are all described here:
\ turboforth.net/lang_ref/view_word.asp?ID=265
\ now, we can use #OPEN to physically open the file. Of course, #OPEN
\ needs to know which file to open. Where is that? It's in the file
\ buffer that we called fileIn - so we supply that to #OPEN
fileIn #OPEN
\ #OPEN pushes a value to the stack to tell us if the OPEN command
\ worked or not. If the open *failed* then it pushes TRUE (-1) to the
\ stack. If the open succeeds, then it pushes 0 (false) to the stack.
\ we use that value from the stack in the following IF statement. Note
\ that the IF *removes* the value on the stack that #OPEN placed there
\ for us. So, if the value on the stack is TRUE the code inside the
\ IF...THEN block will execute.
IF
." Could not open the file."
ABORT \ abort will return us back to the command line
THEN
BEGIN
\ here, we use #EOF? to determine if we're at the end of the file or
\ not. Which file? #EOF? needs to know which file we're talking about.
\ again, that information is in the buffer fileIn.
fileIn #EOF? NOT WHILE
\ so, while the file is NOT at the end of the file, we use #GET to read
\ a single line of text from the file. #GET needs to know which file
\ to read from (fileIn) and it also needs to know where to put the line
\ of text that it gets from the file. At the very top of the code we
\ defined an 82 byte buffer, called buffer. Recall that specifying the
\ name of the buffer causes it to push its address to the stack. This
\ is used by #GET
buffer fileIn #GET
\ #GET pushes true to the stack if it could NOT read from the file.
\ So, we use that value with IF and abort with an error message if the
\ #GET failed.
IF
." Could not read from file"
ABORT
THEN
\ if we get to here, then #GET succeeded, and the line of text is in
\ the buffer called buffer. The *first byte* of that buffer contains
\ the length of the string that was read in from the file.
\ COUNT takes the address of the buffer, reads the first byte, and
\ pushes the length of the string, plus the address of the first byte
\ of the string to the stack.
buffer COUNT
\ we then use TYPE (which requires the address of the string, and the
\ length of the string (how convenient - COUNT just put them on the
\ stack for us!) to type (print) the string to the screen. CR then does
\ a carriage return, which moves the screen position down to the next
\ line.
TYPE CR
\ having done that, we're ready to repeat the whole process. REPEAT
\ causes a jump back up to the word BEGIN. Thus all words/code
\ between BEGIN and REPEAT will be repeated. When #EOF? detects an
\ end of file condition, then the code after WHILE will NOT execute
\ and the program jumps to the code AFTER the word REPEAT.
REPEAT
\ when we read the end of the file the program flow jumps down to here.
\ we simply use #CLOSE to ask it to close our file, and we're done.
fileIn #CLOSE
." All done" CR
;
Phew!
The code, with all the comments removed, looks like this:
FBUF: fileIn
CREATE buffer 82 CHARS ALLOT
: typeFile ( -- )
S" DSK1.TEST.TXT DV80SI" fileIn FILE
fileIn #OPEN
IF
." Could not open the file."
ABORT \ abort will return us back to the command line
THEN
BEGIN
buffer fileIn #GET
IF
." Could not read from file"
ABORT
THEN
buffer COUNT
TYPE CR
REPEAT
fileIn #CLOSE
." All done" CR
;
The above code can be pasted straight into Classic99 and executed immediately. You'll need to give a name of an extant file on one of your disks, of course! Just type ‘typefile’ and it will open the file and display it.