back to the front page

 To the ICPUG website & online journal


The following articles were first published in the ICPUG journal and are aimed to give you some idea of what commands are available for use in the COMAL language. It is very similar to BASIC but there are differences which can cause confusion to the new user.

The most likely source of error for users used to BASIC is that COMAL needs spaces between its commands and any parameters it takes.
e.g. FOR I = 1 TO 10
not FORI=ITO10

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 - COMMANDS WHICH HAVE BASIC EQUIVALENTS
By Brian Grainger

In the following article I will show on the left side of the page some COMAL statements. On the right side of the page I will show how the same result is obtained in BASIC. In this way you should be able to see how to convert BASIC programs into COMAL and also get some idea of the use of some of the COMAL commands. I shall show the COMAL statements as they would appear on the screen should they be listed. As you will see in the article on features unique to COMAL. it is not necessary to type all you see. It still works if you do though.
 
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 
Some of the COMAL examples above may !look clumsy compared with the BASIC equivalents. This is because r have contrived to present exact equivalents. In practice the COMAL program would be written bearing in mind the use of the COMAL commands. not the use of the BASIC equivalents. Some of the COMAL commands shown above have extra uses. See the article on features unique to COMAL.

COMAL - COMMANDS WITHOUT BASIC EQUIVALENTS

In this article I shall be looking at the features of COMAL which are not available in BASIC. I will introduce ! some new commands as well as different forms of commands ! already discussed. Finally I want to discuss the ! relationship between what needs to be typed and what COMAL i will automatically fill in for itself. All COMAL examples will be shown as if they were listed on the screen. Having said hat let us get underway with the features unique to COMAL:

 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
Automatic line numbering is turned off by pressing to a line number.

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 
3) The DEL command can also be used for block deletions. Syntax is identical to the BASIC LIST command:
e.g. DEL 100-250 will delete all lines from 100 to 250 inclusive.

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 EXEC command will cause MULT to be executed ith A replaced by I B replaced by J and C replaced by K. Because C is a REF parameter the value will be kept by K when the procedure is complete. As the procedure heading has the word CLOSED appended all variables used by the procedure are local and can take the same identity as those elsewhere in the program with no confusion. If the program above is RUN you will find D is printed as 5 not 6 which would be the value if the D in the procedure had any effect. If the word CLOSED had been omitted then D would have been global and D would be printed as 6. The storage used for local variables is dynamic so that on exit from the subroutine the storage is released for other use.

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.
10) The INPUT command is bombproof. It does not exit if a <return> is pressed. It will also accept commas and colons etc. in string input. If a list of strings are being input, it does mean that each variable must be separated by <return>.

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:

0010 LABEL START
or
0010 START:
When listing the program it is the second form that will be listed" We can now use the label START as a reference in a GOTO statement:
N.B. No other statements can occur on a labelled line.

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.

COMAL - BASIC COMMANDS WITHOUT COMAL EQUIVALENTS

In this article on COMAL I want to do two things. Firstly I want to identify those BASIC commands which are not included in COMAL and do not have COMAL equivalents, Secondly I want to identify some problems I have found in using COMAL (rev 0.11) whether in using the BASIC2 or BASIC4 version.

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.
In addition to the above commands. shortforms are not allowed in COMAL In particular '?' does not mean PRINT.

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.

PRINT AT 5,16: USING "####.##": SALARY
The AT command is not available in .01.

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:

CAT [<drive}][,<unit}] [<pattern>]
An example is CAT 0,9 "COM*" which ill display all files beginning COM from drive O of disk unit 9. This extension is not available in 1.01. Hitting the space bar will puse the listing.

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.

PROC TEST CLOSED
GLOBAL VAR1,VAR2
.....
will allow the procecure to use VAR1 and VAR2 which are defined outside 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).

LOOP
A$=KEY$
IF A$="A" THEN EXIT (or EXITIF A$="A") 
ENDLOOP
will wait until 'A' is pressed.
18) LIST will support the option:
LIST PROCNAME
this will only list the procedure PROCNAME. Pressing the 'space' key will pause listing until pressed again. I; LISTing to a file, version 1.02 will expect a drive number as part of the file name. These options are not supported by 1.01. LISTed files in 1.01,1.02 and the board COMAL will be sequential files rather than PRG files as in 0.11.

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.

Brian Grainger.

(or checkout the download section of this website ;-)


 back to the front page

 To the ICPUG website & online journal