Writing Programs
There have been many books and magazine articles written about how to write SuperBASIC programs, so we do not intend to cover the basic principles here. The main section detailing the various keywords available to the SuperBASIC programmer contains many useful examples and we suggest that you work through those examples, making sure that you understand how they work and trying to improve them if possible.
In this section, we look at some of the major problems which can face the SuperBASIC programmer and hope to provide some guidance as to how you can overcome those problems and ensure that the programs which you write can be used successfully on all implementations of the QL’s operating system.
Compiling SuperBASIC Programs
Digital Precision’s Supercharge and Turbo compilers are not able to compile some keywords` (eg. those which allow arrays as parameters) while Liberation Software’s QLiberator can compile every additional keyword which makes sense in a compiled program. Although programs compiled with Qliberator will be slower than those compiled with Turbo, the fact that Turbo has not been updated for a number of years (and still contains certain bugs) means that Qliberator may be a better option. This is a matter of fact which we consider worth mentioning for the benefit of Supercharge and Turbo users, it is not intended as a hidden advertisement for QLiberator.
Note
While the above was certainly true when the first paper version of this manual was printed, progress has been made, as the following correction from George Gwilt explains:
For versions of TURBO earlier than 4.21 machine procedures or functions that modify their parameter values, process arrays (other than single strings), manipulate the stored program text, or rely on other interpreter data structures (such as the name table and name list) will not work when compiled. The majority of add-on commands do not do this, and consequently work perfectly.
For TURBO v4.21 and later none of these restrictions apply except for the reliance on the name list.
On the other hand, if you are a Minerva freak, use the Pointer Environment in your programs or want to ensure that your programs will run on SMSQ/E, then you might just find that QLiberator is the better compiler.
As you look through the book, you will find that many keywords act differently on the various implementations of SuperBASIC. To overcome this problem, we suggest that programs which are designed to run on various implementations of the QL, should be compiled, as subject to the comment below, Compilers ensure that programs will run on any system (provided that all keywords used by the program are available on that implementation).
If you want to write programs which use built-in functions only if they are available, you will need to use Qliberator which does not report an error until you try to use an undefined keyword (Turbo and SuperCharge both refuse to load the program in this instance).
Together with the use of the VER$ function, you can easily write programs which work on all implementations of the QL making use of extra facilities which may be available on some versions of the operating system.
One thing of which you must be careful when compiling programs to run on other implementations is the various notes and warnings given for some keywords. Some keywords cannot be compiled and others may have bugs on various implementations which are not fixed by the compiler (refer to the compiler’s manual to see if they rectify the bugs). One of the main culprits of this is the CURSOR command which will reject the use of five parameters on pre-MG ROMs.
Turbo does tend to include its own code to overcome any incompatibility problems with standard QL ROM keywords, whereas Qliberator tends to use the native routines on the operating system on which it is running.
Another thing to bear in mind when writing programs for use with a compiler is that you should really ensure that the program opens all of its own windows and does not assume that any channels are already open. You will also need to remember to DIMension any strings used by the program to ensure that the program works the same way as it does under the Interpreter when compiled (see DIM for an explanation of the way in which strings are treated in various circumstances).
It is also useful to include your own error trapping routines in a compiled program (such as WHEN ERRor) - most compiler error messages are very unhelpful when seen by a user of a program and in particular, there is a problem with programs compiled with Turbo and Supercharge in that they do not wait for the user to press a key after reporting an error before stopping the compiled program. This is fine on a standard QL, as the final display of the program is left on screen - however, under the Pointer Environment, unless the program is started with the command EXEP flp1_test_obj,u (or similar), then the Pointer Environment removes every last trace of the program from the screen when it stops. Also, if any machine code Procedures or Functions report an error, then the error may not be reported and the program may just ‘hang’ if #0 is not open.
One of the main problems with compiled programs is the Cache provided with 68020 processors (and faster). Caches cause problems with machine code which modifies itself (normally to enhance speed). Whereas programs compiled with Qliberator should be okay (depending on the toolkits used within them), TURBO compiled programs are normally self- modifying. However, provided that a program is compiled under TURBO with the BRIEF directive then it will run provided that the cache is switched off for the first 0.3 seconds after EXECing the program - for example, if a program causes problems, use:
10 CACHE_OFF
20 EX flp1_PROGRAM_exe
30 PAUSE 15
40 CACHE_ON
Refer to CACHE_ON and CACHE_OFF for further details.
One of the other differences between TURBO compiled programs and Qliberator compiled programs is that the former all make assumptions about the start of the screen and system variables. However, there is a public domain program by Davide Santachiara called Turbostart which resolves these problems by altering compiled programs.
Writing Programs to Run Under the Pointer Environment
It is not as difficult as it first may seem to write programs to run under the Pointer Environment, unless you intend your program to use the Pointer and Menu facilities provided by the Pointer Environment.
Basically, any program which has been written with the intention of multitasking will work under the Pointer Environment. However, the program should not attempt to tie up the QL’s resources unless it is using them (for example, do not open a printer channel until you need to send output to it) and then close the channel once all output has been sent. It is also useful to allow the user to add their own facilities such as a mouse through amending the boot program.
A SuperBASIC program will of course only multitask if it is compiled (see Section 4.1) or if the user has Minerva or SMSQ/E which provide multitasking SuperBASIC interpreters.
Multitasking Programs
If you write a program which is to run under the Pointer Environment, it is useful to remember some rules:
There is no need to activate the cursor on the program - when the program is PICKed by the user, then any open con_ channel is automatically activated. You may however, still wish to do this if the program is to be able to run without the Pointer Environment.
If any part of the job’s OUTLN is overlapped by other programs, then the job will not be able to access and scr_ or con_ channels (it will wait until the program is activated). This can be overcome with PIE_ON / PEON or by starting the program with EXEP (using the U parameter). You can check if a program can write to a screen channel with PEND.
As soon as the program ends (with STOP or RJOB) then all of its windows will be removed from the screen, again unless you have used EXEP with the U parameter.