Chapter
Four
Program Editor
The Atari keyboard is the master Control panel for
Atari BASIC. Everything BASIC does has its origins at this control panel. The Program
Editor's job is to service the control panel and respond to the commands that come
from it. The editor gets a line from the user at the keyboard; does some preliminary
processing on the line; passes the line to the pre-compiler for further processing;
inserts, deletes, or replaces the line in the Statement Table; calls the Program
Executor when necessary; and then waits to receive the user's next line input. Line
Processing
The Program Editor, which starts at $A060, begins its process by resetting the 6502
CPU stack. Resetting the CPU stack is a drastic operation that can only occur at
the beginning of a logical process. Each time Atari BASIC prepares to get a new line
from the user, it restarts its entire logical process. Getting a Line The
Program Editor gets a user's line by calling CIO. The origin of the line is transparent
to the Program Editor. The line may have been typed in at the keyboard or entered
from some external device like the disk (if the ENTER command was given). The Program
Editor simply calls CIO and asks it to put a line of not more than 255 bytes into
the buffer pointed to by INBUFF (sF3). INBUFF points to the 128-byte area defined
at LBUFF ($580). The OS'S screen editor, which is involved in getting a line from
the keyboard, will not pass BASIC a line that is longer than 120 bytes. Normally,
then, the 128-byte buffer at LBUFF is big enough to contain the user's line. Sometimes,
however, if a line was originally entered from the keyboard with few blanks and many
abbreviations, then LISTed to and re-ENTERed from the disk, an input line may be
longer than 128 bytes. When this happens, data in the $600 page is overlaid. A LINE
TOO LONG error will not necessarily 25
Chapter
Four
occur at this point. A LINE TOO LONG error occurs only if the Pre-compiler
exceeds its stack while processing the line or if the tokenized line OUTBUFF exceeds
256 bytes. These overflows depend on the complexity of the line rather than on its
actual length. When CIO has put a line into the line buffer (LBUFF) and the Program
Editor has regained control, it checks to see if the user has changed his mind and
hit the break key. If the user did indeed hit break, the Program Editor starts over
and asks CIO for another line. Flags and Indices In order to help control
its processing, the Program Editor uses flags and indices. These must be given initial
values. CIX and COX. The index CIX (sF2) is used to access the user's input
line in the line buffer (LBUFF), while COX ($94) is used to access the tokenized
statement in the output buffer (OUTBUFF). These buffers and their indices are also
used by the pre-compiler. The indices are initialized to zero to indicate the beginning
of the buffers. DIRFLG. This flag byte ($A6) is used by the editor to remember
whether a line did or did not have a line number, and also to remember if the pre-compiler
found an error in that line. DIRFLG is initialized to zero to indicate that the line
has a line number and that the pre-compiler has not found an error. MAXCIX.
This byte ($9F) is maintained in case the line contains a syntax error. It indicates
the displacement into LBUFF of the error. The character at this location will then
be displayed in inverse video. The Program Editor gives this byte the same initial
value as CIX, which is zero. SVVNTP. The pointer to the current top of the
Variable Name Table (VNTD) is saved as SVVNTP (SAD) so that if there is a syntax
error in this line, any variables that were added can be removed. If a user entered
an erroneous line, such as 100 A=XAND B, the variable XAND would already have been
added to the variable tables before the syntax error was discovered. The user probably
meant to enter 100 A=X AND B, and, since there can only be 128 variables in BASIC,
he probably does not want the variable XAND using up a place in the variable tables.
The Program Editor uses SVVNTP to find the entry in the Variable Name Table soit
can be removed. 26
Chapter
Four
SVVYTE. The process used to indicate which variable entries
to remove from the Variable Value Table in case of error is different. The number
of new variables in the line (SVVVTE1$B1) is initialized to zero. The Program Pre-compiler
increments the value every time it adds a variable to the Variable Value Table. If
a syntax error is detected, this number is multiplied by eight (the number of bytes
in each entry on the Variable Value Table) to get the number of bytes to remove,
counting backward from the most recent value entered. Handling Blanks In many
places in the BASIC language, blanks are not significant. For example, 100 IFX=6THENGOTO500
has the same meaning as 100 IF X = 6 THEN GOTO 500. The Program Editor, using the
SKIPBLANK routine ($DBA1), skips over unnecessary blanks. Processing the Line
Number Once the editor has skipped over any leading blanks, it begins to examine
the input line, starting with the line number. The floating point package is called
to determine if a line number is present, and, if so, to convert the ATASCII line
number to a floating point number. The floating point number is converted to an integer,
saved in TSLNUM for later use, and stored in the tokenized line in the output buffer
(OUTBUFF). The routine used to store data into OUTBUFF is called :SETCODE ($A2C8).
When :SETCODE stores a byte into OUTBUFF, it also increments COX, that buffer's index.
BASIC could convert the ATASCII line number directly to an integer, but the routine
to do this would not be used any other time. Routines to convert ATASCII to floating
point and floating point to integer already exist in BASIC for other purposes. Using
these existing routines conserves ROM space. An interesting result of this sequence
is that it is valid to enter a floating point number as a line number. For example,
100.1, 10.9, or 2.05E2 are valid line numbers. They would be converted to 100, 11,
and 205 respectively If the input line does not start with a line number, the line
is considered to be a direct statement. DIRFLG is set to $80 so 27
Chapter
Four
that the editor can remember this fact. The line number is set to
32768 ($8000). This is one larger than the largest line number a user is allowed
to enter. BASIC later makes use of this fact in processing the direct statement.
Line length. The byte after the line number in the tokenized line in OUTBUFF
is reserved so that the line length (actually the displacement to the next line)
can be inserted later. (See Chapter 2.) The routine :SETCODE is called to reserve
the byte by incrementing (COX) to indicate the next byte. Saving erroneous lines.
In the byte labeled STMSTART, the Program Editor saves the index intQ the line buffer
(LBUFF) of the first non-blank character after the line number. This index is used
only if there is a syntax error, so that all the characters in the erroneous line
can be moved into the tokenized line buffer and from there into the Statement Table.
There are advantages to saving an erroneous line in the Statement Table, because
you can LIST the error line later. The advantage is greatest, not when entering a
program at the keyboard, but when entering a program originally written in a different
BASIC on another machine (via a modem, perhaps). Then, when a line that is not correct
in Atari BASIC is entered, the line is flagged and stored - not discarded. The user
can later list the program, find the error lines, and re-enter them with the correct
syntax for Atari BASIC. Deleting lines. If the input line consists solely
of a line number, the Program Editor deletes the line in the Statement Table which
has that line number. The deletion is done by pointing to the line in the Statement
Table, getting its length, and calling CONTRACT. (See Chapter 3.) Statement Processing The user's input
line may consist of one or more statements. The Program Editor repeats a specific
set of functions for each statement in the line. Initializing The current
index (COX) into the output buffer (OUTBUFF) is saved in a byte called STMLBD. A
byte is reserved in OUTBUFF by the routine :SETCODE. Later, the value in 28
Chapter
Four
STMLBD will be used to access this byte, and the statement length
(the displacement to the next statement) will be stored here. Recognizing the
Statement Name After the editor calls SKBLANK to skip blanks, it processes the
statement name, now pointed to by the input index (CIX). The editor calls the routine
SEARCH ($A462) to look for this statement name in the Statement Name Table. SEARCH
saves the table entry number of this statement name into location STENUM. The entry
number is also the Statement Name Token value, and it is stored into the tokenized
output buffer (OUTBUFF) as such by :SETCODE. The SEARCH routine also saves the address
of the entry in SRCADR for use by the pre-compiler. If the first word in the statement
was not found in the Statement Name Table, the editor assumes that the statement
is an implied LET, and the appropriate token is stored. It is left to the pre-compiler
to determine if the statement has the correct syntax for LET The editor now gives
control to the pre-compiler, which places the appropriate tokens in OUTBUFF, increments
the indices CIX and COX to show current locations, and indicates whether a syntax
error was detected by setting the 6502 carry flag on if there was an error and clearing
the carry flag if there was not. (See Chapter 5.) If a Syntax Error Is Detected
If the 6502 carry flag is set when the editor regains control, the editor does error
processing. In MAXCIX, the pre-compiler stored the displacement into LBUFF at which
it detected the error. The Program Editor changes the character at this location
to inverse video. The character in inverse video may not be the point of error from
your point of view, but it is where the pre-compiler detected an error. For example,
assume you entered X YAND Z. You probably meant to enter X Y AND Z, and therefore
would consider the error to be between Y and AND. However, since YAND is a valid
variable name, X=YAND is a valid BASIC statement. The pre-compiler doesn't know there
is an error until it encounters B. The value of highlighting the error with inverse
29
Chapter
Four
video is that it gives the user an approximation of where the error
is. This can be a big advantage, espedally if the input line contained multiple statements
or complex expressions. The next thing the editor does when a syntax error has been
detected is set a value in DIRFLG to indicate this fact for future reference. Since
the DIRE LG byte also indicates whether this is a direct statement, the error indicator
of $40 is ORed with the value already in DIRELG. The editor takes the value that
it saved in STMSTRT and puts it into CIX so that CIX now points to the start of the
first statement in the input line in LBUFF. STMLBD is set to indicate the location
of the first statement length byte in OUTBUFF. (A length will be stored into OUTBUFF
at this displacement at a later time.) The editor sets the index into OUTBUFF (COX)
to indicate the Statement Name Token of the first statement in OUTBUFF, and stores
a token at that location to indicate that this line has a syntax error. The entire
line (after the line number) is moved into OUTBUFF. At this point COX indicates the
end of the line in OUTBUFF. (Later, the contents of OUTBUFF will be moved to the
Statement Table.) This is the end of the special processing for an erroneous line.
The process that follows is done for both correct and erroneous lines. Final Statement
processing During initial line processing, the Program Editor saved in STMLBD
a value that represents the location in OUTBUFF at which the statement length (displacement
to the next statement) should be stored. The Program Editor now retrieves that value
from STMLBD. Using this value as an index, the editor stores the value from COX in
OUTBUFF as the displacement to the next statement The Program Editor checks the next
character in LBUFF. If this character is not a carriage return (indicating end of
the line), then the statement processing is repeated. When the carriage return is
found, COX will be the displacement to the next line. The Program Editor stores COX
as the line length at a displacement of two into OUTBUFF. 30
Chapter
Four
Statement Table Processing The final tokenized form of the line exists in OUTBUFF at
this point. The Program Editor's next task is to insert or replace the line in the
Statement Table. The Program Editor first needs to create the correct size hole in
the Statement Table. The editor calls the GETSTMT routine ($A9A2) to find the address
where this line should go in the Statement Table. If a line with the same line number
already exists, the routine returns with the address in STMCUR and with the 6502
carry flag off. Otherwise, the routine puts the address where the new line should
be inserted in the Statement Table into STMCUR and turns on the 6502 carry flag.
(See Chapter 6.) If the line does not exist in the Statement Table, the editor loads
zero into the 6502 accumulator. If the line does exist, the editor calls the GETLL
routine ($A9DD) to put the line length into the accumulator. The editor then compares
the length of the line already in the Statement Table (old line) with the length
of the line in OUTBUFF (new line). If more room is needed in the Statement Table,
the editor calls the EXPLOW ($A87F; see Chapter 3). If less space is needed for the
new line, it calls a routine to point to the next line (GNXTL, at location $A9D0;
see Chapter 6), and then calls the CONTLOW ($A8FB; see Chapter 3). Now that we have
the right size hole, the tokenized line is moved from OUTBUFF into the Statement
Table at the location indicated by STMCUR. Line Wrap-up After the line has been added to the Statement Table, the
editor checks DIRFLG for the syntax error indicator. If the second most significant
bit ($40) is on, then there is an error. Error Wrap-up If there is an error,
the editor removes any variables that were added by this line by getting the number
of bytes that were added to the Variable Name Table and the Variable Value Table
from SVVNTP and SVVVTE. It then calls CONTRACT ($A8FD) to remove the bytes from each
table. Next, the editor lists the line. The Statement Name Token, which was set to
indicate an error, causes the word "ERROR" 31
Chapter
Four
to be printed. An inverse video character indicates where the error
was detected. The editor now waits for you to enter another line. Handling Correct
Lines If the line was syntactically correct, the editor again examines DIRFLG.
In earlier processing, the most significant bit ($80) of this byte was set on if
the line was a direct statement. If it is not a direct statement, then the editor
is finished with the line, and it waits for another input line. If the line is a
direct statement, earlier processing already assigned it a line number of 32768 ($8000),
one larger than the largest line number a user can enter. Since lines are arranged
in the Statement Table in ascending numerical order, this line will have been inserted
at the end of the table. The current statement pointer (STMCUR-$8A $8B) points to
this line. The Program Editor transfers control to a Program Executor routine, Execution
Control (EXECNL at location $A95F), which will handle the execution of the direct
statement. (See Chapter 6.) 32
<-Chapter
03Chapter 05->