As COMAL allows long variable names the second statement is like saying 'Set the variable FORI equal to the value I TO 10'. As you cannot have a value 1TO10 COMAL would create an error message. As there are no long variable names in BASIC this confusion cannot arise.
Printed output can appear a bit confused sometimes because the use of',' and ';' as separators is slightly different than in BASIC. In BASIC you are stuck with print zones of 10 characters with ',' being used to jump from zone to zone. In COMAL you can set the zone width (ZONEx in early versions, ZONE xx in later versions) but the default is 0 so jumping between zones is not apparent until you specifically set a value for ZONE.
If you are writing long programs try and split the routines up into PROCs if possible. You can then test each PROC separately before testing the whole program. This will make for easier debugging.
The use of secondary addresses to control the 4022 printer.
The full syntax for the OPEN command is:
OPEN FILE <file num>,"<filename>",UNIT <device no>,<secondary address>,<mode>
e.g. OPEN FILE 4,"",UNIT 4,7,WRITE will open a file to the printer with secondary address 7
If it doesn't work I guess I would write a couple of PROCs. One to stuff
some rnachine code in a suitable place (the second cassette buffer?) which
when called will set the primary address, filename and- secondary address
in the appropriate place of the memory map and then do a JSR through the
jump vector in the kernal vector table to open a file.
The second PROC would be used instead of OPEN FILE and call the machine
code previously set up.
The load address is the start address in memory that a program may be
loaded into.
If you save a COMAL program as a sequential file, by means of the LIST
command, then it does not matter where the program was loaded in memory.
It can be read into another version of COMAL, by the ENTER or MERGE command
(depending on COMAL version). If there are any bits of syntax that are
not understood by the version of COMAL doing the reading then an error
message will be flagged and you can REM out the line to ensure the full
program file is read. The result will be a COMAL program in memory coded
in the binary syntax of the COMAL version not ASCII. You could use this
technique to transfer a COMAL program from a PET COMAL to a C64 COMAL.
It would not matter if the C64 used a 4040 or 1541 disk drive as the two
are compatible. However if the PET used an 8050 you would not be able to
read the result into a C64 using a 1541 because the two disk drives have
incompatible recording formats.
COMAL | BASIC |
0010 CASE A OF | 10 ON A GOTO 30.40 |
0020 WHEN 1 | 20 PRINT"A IS OUT OF Range":GOTO 50 |
0030 PRINT"A IS ODD" | 30 PRINT"A IS ODD":GOTO 50 |
0040 WHEN 2 | 40 PRINT"A IS EVEN" |
0050 PRINT"A IS EVEN" | 50 ,,,,,,,,,,,,,,,,,,,,,, |
0060 OTHERWISE | |
0070 PRINT"A IS OUT OF RANGE" | |
0080 ENDCASE | |
|
|
A:=1; B:=2 | A=1:B=2 |
CHAIN "FILENAME" | LOAD"0:FILENAME".8:RUN |
CLOSE | DCLOSE |
CON | CONT |
DEL 100 | 100 [RETURN] |
DIM MATRIX(0:100,0:10) | DIM MATRIX(100,10) |
A DIV B | INT(A/B) |
|
|
0010 EXEC SUBPROGRAM | 10 GOSUB 100 |
; | ; |
0100 PROC SUBPROGRAM | 100 ,,,,,,, |
; | ; |
0200 ENDPROC SUBPROGRAM | 200 < RETURN> |
|
|
0100 PROC FNR(X) | 100 DEF FNR(X)=INT(X*100+.5) |
0110 FNR:=INT(X*100+.5) | |
0120 ENDPROC FNR | |
NO:=FALSE | NO=0 |
FOR I=1 TO 10 DO PRINT I | FOR I=1 TO 10:PRINT I:NEXT |
|
|
0010 FOR I=1 TO 1O DO | 10 FOR T=1 TO 10 |
0020 PRINT I | 20 PRINT I |
0030 PRINT I*2 | 30 PRINT I*2 |
0040 NEXT I | 40 NEXT |
|
|
0010 GOTO FINISH | 10 GOTO 110 |
; | ; |
0100 FINISH: | ; |
0110 PRINT"END OF PROGRAM" | 110 PRINT"END OF PROGRAM" |
|
|
0010 IF A=B THEN | 10 IF A=B THEN PRINT"A EQUALS B":GOTO40 |
0020 PRINT"A EQUALS B" | 20 IF A>B THEN PRINT"A GREATER THAN B":GOTO 40 |
0030 ELIF A>B THEN | 30 PRINT"A LESS THAN B" |
0040 PRINT"A GREATER THAN B" | 40 ;;;;; |
0050 ELSE | |
0060 PRINT"A LESS THAN B" | |
0070 ENDIF | |
|
|
INPUT"WHAT IS NUMBER? ":NO | INPUT"WHAT IS NUMBER";NO |
LOAD"FILENAME" | LOAD"O:FILENAME",8 |
A MOD B | A- NT(A/B)*B |
OPEN 2,"FILENAME",READ | OPEN2,8,8,"0:FILENAME.SEQ,R" |
OPEN 2,"FILENAME",WRITE | OPEN2,8,8,"0:FILENAME.SEQ,W" |
OPEN 2,"FILENAME",APPEND | APPEND#2,"FILENAME" |
OPEN 2,"FILENAME",RANDOM 100 | DOPEN#2,"FILENAME",L100 |
ORD("A") | ASC("A") |
SELECT OUTPUT "LP" | OPEN1,4:CMD1 |
followed by | followed by |
SELECT OUTPUT "DS" | PRINT#1:CLOSE1 |
PRINT A$;B$;C$ | PRINT A$;" ";B$;" ";C$ |
PRINT A$,B$ | PRINT A$;B$ |
|
|
0010 ZONE:=10 | PRINT A,B |
0020 PRINT A.B | |
|
|
0010 REPEAT | 10 I=I+1 |
0020 I:=I+1 | 20 PRINT I |
0030 PRINT I | 30 IF I<>10 GOTO 10 |
0040 UNTIL I=10 | |
A=RND(X,Y) | A=X+INT((Y-X+1)*RND(0)) |
A=RND(0) | A=RND(0) |
|
|
SAVE"FILENAME" | SAVE"O:FILENAME",8 |
SIZE | PRINT FRE(0) |
STATUS | OPEN15 8.15:INPUT#15.A$,B$, CS.D$:PRINT A$;BS;C$;D$: CLOSE15 |
PRINT STATUS(2) | (e.g.)INPUT#Z.A$:INPUT#15,ER :PRINT ER |
NO:=TRUE | NO=1 |
|
|
0010 WHILE I>0 DO | 10 IF I<=0 GOTO 50 |
0020 NO:=NO+I | 20 NO=NO+I |
0030 I:=I-1 | 30 I=I-1 |
0040 ENDWHILE | 40 GOTO 10 |
0050 PRINT NO | 50 PRINT NO |
|
|
READ FILE 2:A$ | INPUT#2,A$ |
WRITE FILE 2:A$ | PRINT#2,A$ |
READ FILE 4,12,3:A$ | RECORD#4,12,3:INPUT#4,A$ |
WRITE FILE 4,12,:A$ | RECORD#4,12,3:PRINT#4.A$ |
EDIT | LIST |
CAT | CATALOG |
CAT O | CATALOG DO |
CAT 1 | CATALOG D1 |
|
|
PRINT NAME$(1:N) | PRINT LEFT$(NAMES,N) |
PRINT NAME$(M:N) | PRINT MID$(NAME$,M,N) |
PRINT NAME$(END-N+1:N) | PRINT RIGHT$(NAME$,N) |
|
|
A# (integer variable) | A% |
N.B. This uses less storage than A | N.B. This uses same storage as A |
1) AUTO is a command which will generate line numbers automatically.
e.g. AUTO generates 10,20,30 |
AUTO 100 generates 100,110,120 |
AUTO 100,5 generates 100,105,110 |
2) The CASE command is far more versatile than a replacement for ON...GOSUB. The expression to be tested can be a string expression or logical expression as well as being numerical as in BASIC. In addition where BASIC expects the values taken by the expression to be sequential the CASE command will allow ANY values:
0010 CASE COLOUR$ OF |
0020 WHEN "RED","YELLOW","BLUE" |
0030 PRINT COLOUR$;"IS A PRIMARY COLOUR" |
0040 OTHERWISE |
0050 PRINT COLOUR$;"IS A MIXED COLOUR" |
0060 ENDCASE |
4) Array handling in COMAL is extremely powerful. The DIM statement
of COMAL equivalent to that of BASIC looks clumsy but consider that in
COMAL the index of an array can range from ANY integer to ANY larger integer:
e.g. DIM FIELD(-3:7) declares a one dimension array with indices from
-3 to 7 inclusive.
e.g. DIM NUMBER(6) declares an array with indices 1 to 6 inclusive (there
is NOT a 0 element as in BASIC unless declared specifically).
In COMAL the maximum length of a string MUST be defined
e.g. DIM NAME$ OF 10 declares a string of maximum length 10 characters.
e.g. DIM NAME$(2:5,3:7) OF 10 declares a string two dimensional array
of 20 elements. each with maximum length 10 characters.
N.B. ALL array variables MUST be dimensioned. There are no defaults
as in BASIC.
5) The ENTER command can be used to merge previously LISTed files into
the current program:
e.g. ENTER"FILENAME" will merge FILENAME from disk into the current
program. Lines will be overwritten and reordered as necessary:
e.g. ENTER"FILENAME",1 will take the file named FILENAME from cassette
and merge ir ith the current program.
6) EOD - This is a logical variable which is TRUE when the last item in DATA statements is READ.
7) EOF(X) - This is a logical variable which is TRUE when the last item from channel X is taken..
8) EXEC is more than a replacement for GOSUB. Together with the PROC command e have a very powerful feature. Parameters can be passed to a subroutine. Variables used in a subroutine can be global to the whole program (in which case changes made to the variables in the subroutine will be recognised in the main program), or local to the subroutine (in which case the main program will not recognise any parameters used in the subprogram). All parameters to a subprogram are local unless identified as REF parameters. As output parameters must be recognised by the main program they must be defined as REF parameters. For space limitations all arrays must be defined as REF parameters:
0010 I:=2 ; J:=3 ; D:=5 |
0020 EXEC MULT(I,J,K) |
0030 PRINT K,D |
0040 END |
0050 PROC MULT(A,B,REF C) CLOSED |
0060 D:=A*B |
0070 C:=A*A+B*B+2*D |
0080 ENDPROC MULT |
The PROC used as a function is also more powerful than the BASIC DEF
FN. In BASIC one can only use 1 line to define the function. In COMAL one
can use as many lines as necessary.
9) The IN function. used with strings determines whether one string
is contained within another and returns the position of the first character
if so. If the string is not found 3 value of O is returned:
0005 DIM NAME$ OF 9 |
0010 NAME$:="FREDERICK" |
0020 A:=RICK IN NAME$ |
0030 B:="DAVE" IN NAME$ |
0040 PRINT A.B |
The above example will result in A being 6 and B being 0. |
11) The command LABEL will cause a label to be placed on a line. For example you can type either of the 2 statements below and the COMAL interpreter will accept it in the same way:
12) The LIST command under COMAL has 2 special features, Firstly it
invokes automatic indenting of lines for readability. It is not necessary
to type the lines indented it is done automatically. Secondly one can LIST
to a file on the disk or cassette. This file can subsequently be merged
into any existing program by the ENTER command:
LIST"FILENAME" lists the current program to disk under the same FILENAME.
LIST"FILENAME",1 lists the current program to cassette under the name
FILENAME.
LIST 10-50,"FILENAME" will list lines 10 to 50 inclusive to disk under
the name FILENAME.
13) The RENUM command will renumber an entire program. It has the same syntax as the AUTO command.
14, The RUN command is similar to that of BASIC with one notable exception. variables are NOT reset to zero or null. Thus no assumptions should be made on the values of undeclared variables in a program.
15) In comparing the BASIC PRINT command with the COMAL equivalent. COMAL looks clumsy. In reality COMAL is much more flexible. BASIC has fixed print zones of length 10. In COMAL one can vary the zone length by the ZONE command:
e.g. ZONE:=5 will cause items separated by commas in print lists to
be printed in zones of 5-character length.
The default value of ZONE length is O and not 10 as in BASIC. Thus
a comma will cause no separation of variables until zone length has been
redefined. In COMAL a semicolon between print items will ALWAYS print 1
space between those items, whether they are numeric or string. It is a
true space unlike BASIC which for numerals will print a cursor right after
the value. This appears like a space but in reality is not.
16) In COMAL variable names or labels can be up to 16 characters in length. The first character must be a letter and all 16 are recognised unlike BASIC where only the first 2 are recognised. In COMAL it does not matter if a variable name includes a COMAL keyword. Thus variable names can be chosen which have meaning. One side effect of this is that COMAL keywords must be typed with a following space. Otherwise it will be regarded as a variable name and a syntax error will probably result. One other COMAL restriction on variable names is that the same name CANNOT be used for two different variable types. For example the variables A and A$ cannot appear in the same segment of program.
17) I have mentioned above that one need not type the spaces necessary to cause line indentation. They are added automatically when the program is LISTed. There are other things that need not be typed as well. Here is the complete list:
The ':' preceding the '=' in assignment statements. The 'OF' in 'CASE...OF'
statements
. The 'DO' in 'FOR...DO' or 'WHILE...DO' statements provided the 'DO'
is the last word in the statement.
The 'THEN' in 'IF...THEN' or 'ELIF...THEN' statements provided the
'THEN' is the last word in the statement.
The procedure name following the 'ENDPROC' statement.
In all the above cases the COMAL interpreter will automatically add
the relevant words if they have been omitted.
18) The 'REM' command is accepted in COMAL but the interpreter will replace it with //. REM or // can be used at the end of a COMAL statement or be on a line of its own.
19) It has been stated above that variables cannot be assumed to be
null at the start of a program. There is therefore a need for a command
which will set a string variable to a blank. The following example will
illustrate: SPACE$(1:60):="" will set the string SPACE$ of sixty characters
length to a blank. Another facility on string handling is that if a single
character is to be referenced it can be done simply as the following example
shows:
NAME$(5) refers to the 5th character of NAME$. It is not necessary
to say NAME$(5:1).
Thus when the length value is 1 it may be omitted.
As can be seen from the above COMAL has many features that BASIC does not have. I have left until last one of the most important features:
There is syntax checking on input . The interpreter will even leave the cursor at the point where the error is recognised so that the line can be modified quickly before continuing. This means all the statements of a COMAL program are checked for syntax before it is RUN. In BASIC they are not checked until run time and it is up to the programmer to ensure all the lines are executed and checked. This is not at all easy on long and complicated BASIC programs with many loops and branches. To sum up COMAL is an extremely powerful language compared with BASIC which results in easy to read, easy to maintain programs.
Here is a list of BASIC commands not supported by COMAL:
BACKUP | CLR. | CMD | COLLECT |
CONCAT | COPY | GET | HEADER |
ON...GOTO | RENAME | SCRATCH | VERIFY |
WAIT. | POS | STR$ | TIME |
TIME$ | USR | VAL. |
It will be seen that most of the commands not implemented are BASIC4 disk management commands. The equivalent BASIC2 sequences also do not appear to exist. I find this somewhat surprising as the means to decode tne commands is available in the BASIC ROM.
Here is list of oddities I have found in using COMAL:
1) The command BASIC causes a system error although it is a valid COMAL command.
2) PRINT USING is not implemented. In my opinion the saddest point about using COMAL,
3) SAVE or LOAD to cassette does not work. The commands function but on reloading the file reads as gibberish.
4) When a program with indented lines is ENTERed an error occurs on lines with DIM statements. Just ignore the error. Type <return> over the displayed line and all will continue normally.
5) When a program is ENTERed from tape an EOF error occurs as a matter of course. It is not really an error.
6) ZONE:=1 does not work correctly (it works as if ZONE:=2). Use ZONE:=0 and it works like ZONE:=1 !
7) Do NOT send disk commands when a disk is not switched on. A system crash will occur if you do !
8) DEBUG, while being a COMAL command causes a system error If anybody finds any other problems or has any suggestions as to resolving the above or why they happen, please let me know.
COMAL FOR THE 8096
In this article I want to talk about the additionaL COMAL commands
available in the 8096 versions of COMAL
Unless stated otherwise they apply to versions 1.01, 1.02, and the COMAL board version. Version 1.02 represents the full COMAL implementation.
1) It is now possible to say PRINT AT 5,16: SALARY This will print the value of SALARY starting at row 5, column 16. This can also be combined with USING as e.g.
2) BASIC is identical to 0.12 in that a warm reset is carried out. It assumes a BASIC4 machine so would not be valid with a COMAL board in a new ROM PET.
3) The CAT command has been extended to a full specification as follows:
4) CURSOR row,col moves the cursor to the given row and column.
5) DEBUG will jump to monitor, but the routine has a bug in it so you are not advised to use it.
6) DELETE "O:FILENAME" will scratch the file FILENAME from drive 0. The drive number must be given for the command to work This command is also supported by 0.12.
7) ENDFUNC was described for 0.12 last Newsletter. It is not available in 1.01.
8) ENDLOOP is described under the LOOP command. It is not supported by 1.01.
9) ESC was described for 0.12 last Newsletter.
10) EXIT is described under the LOOP command, It is not supported by 1.01.
11) FUNC was described for 0.12 last Newsletter, It is not supported by 1.01.
12) GET$(1,6) will get 6 characters from the logical file number 1 which has been previously opened for READ. One can GET characters from the keyboard by using a file number of O (which need not be opened). Note that at least one character must be returned. Use KEYS(q.v.) if no key press is a possibility. I am unclear as to whether this command is supported by 1.01. GET$ certainly exists in 1.01 but it may act like KEY$.
13) GLOBAL is provided in 1.01 only and allows a CLOSED procedure to use variables from outside. To do this they are defined as GLOBAL inside the procedure.
14) IMPORT is the equivalent of GLOBAL in 1.02 and the COMAL board.
15) INTERRUPT PR0CNAME will execute the procedure PROCNAME if a signal is sensed on the SRQ line of the IEEE bus.
16) KEY$ will return the last ' 17) LOOP is a new structure introduced on 1.02 and the COMAL board.
A set of instructions enclosed by LOOP and ENDLOOP will execute continuously.
Obviously there must bea way out of the loop. This is by an EXIT command
(or possibly EXITIF command, as this may be implemented instead in the
final version).
19) NULL is as for 0.12 described last Newsletter.
20) OBJLOAD "FILENAME" will load the file FILENAME into top of memory
and lower COMAL pointers accordingly. One can load from tape by adding
a unit number (,1).
21) OPTION 9*4096 will recognise the COMAL-compatible machine code procedures
written in ROM starting at $9000. OPTION can be used to access any start
address, so machine code procedures can be written, loaded with OBJLOAD
and recognised via OPTION. Unfortunately I have not seen any instructions
on how to implement machine code procedures to use with this powerful facility.
22) PRINT USING is fully supported by these COMAL versions.
23) RENUM is extended:
RENUM 500; 1000,5 will renumber lines from line 500 to the end of the
program starting line 1000 in steps of 5. This extension is not implemented
in 1.01.
24) RESTORE LABEL will restore the DATA pointer to the first DATA item
after the line labelled LABEL.
25) RETURN is as defined for 0.12 in the last Newsletter.
26) SAFE will make a program unlistable. I am not sure if this is implemented
in 1.02. In my opinion it shouldn't be implemented at all !
27) LOAD, ENTER, LIST,' SAVE to tape are supported by these COMAL versions.
28) SETEXEC is as described for 0.12 last Newsletter.
29) SETTIME 123 will set the jiffy clock to 123. This is only available
on 1 .01 .
30) SPC$ is supported by these COMAL versions and acts like the BASIC
equivalent.
31) STATUS$ is similar to DS$ in BASIC4. In version 0.11 or 0.12 STATUS
acts like PRINT STATUS$.
32) STOP "MESSAGE" will print the text tMESSAGE' when tne STOP command
is executed. This i s not supported by 1 .01.
33) STR$, the BASIC function, is supporred by these COMAL versions.
34) TIME holds the value of the jiff' clock. The 1.01 SETTIME is mimicked
in other versions bv TIME 123.
35) TO can be used for readability in the LIST command on 1 .02 or the
COMAL board:
LIST 10-266 TO "FILENAME" is identicaL to LIST 10-266,"FILENAME"
36) TRAP is as described for 0.12 last Newsletter.
37) VAL and VERIFY are exactly as the BASIC equivalents.
38) READ FILE, WRITE FILE, INPUT and PRINT to random access files are
supported
39) COMAL uses file numbers 1 and 255 for its own use (1 for disk, 255
for printer) so do NOT use these numbers in your programs.
As you can see from the above, these versions of COMAL introduce all
the missing items from the earlier software versions. They also provide
some very useful extensions and further enhance the suitability of COMAL
over BASIC. While the COMAL board is not cheap it certainly will provide
a much better programming language than the original BASIC while still
allowing BASIC to be used when required. By the time you read this I should
have version 1.02 for 8096 computers available on 4040 or 8050 disks.
LOOP
A$=KEY$
IF A$="A" THEN EXIT (or EXITIF A$="A")
ENDLOOP
will wait until 'A' is pressed.
Brian Grainger.
(or checkout the download section of this website ;-)
back
to the front page