One of the things that has always amazed me about the QL was the ability to load a binary file and have a bunch of new keyboards available in SuperBasic. In most computers that had Basic built in, the language was static and had no way to extend itself. Other languages (like C, Fortran, or Pascal) used libraries of functions and procedures to extend the capability of the library.
The first major loadable extension to the QL was ToolKit. From then on the term toolkit has been used in reference to loadable extensions. Popular toolkits are ToolKitII (TKII), DIY ToolKit, and DJToolKit.
I knew that the first of these toolkits were written in Assembly, but I did not know that they could be created by Qliberator. It seems that QDOS executables and extensions are real close in format and when compiled right, they can be interchangeable. This means that an executable can also be loaded as an extension.
To figure out how to create a toolkit, I grabbed a simple function, Qliberator, and gave it a try. The function is included below:
10 REMark $$external
100 DEFine FuNction upper$(up$)
110 LOCal x, temp
120 FOR x = 1 TO LEN(up$)
130 temp = CODE(up$(x))
140 IF temp > 96 AND temp < 123 THEN up$(x)=CHR$(temp-32)
150 NEXT x
160 RETurn up$
170 END DEFine
The function takes any string and converts it to all upper case letters. The $$external is a compiler directive to Qliberator that tells it that the next function or procedure needs to be available outside of the executable. For each procedure or function that you want to turn into an extension, you would have to put the $$external directive in front of it.
If I was to put an additional line in the program,
180 PRINT upper$("This is a test")
then when I executed the program, line 180 would be executed. If I LRESPRed the program, the keyword upper$ would be made available.
When compiling the program it is a good idea to turn WINDS off, since the extension will have no channels open. Otherwise 3 channels will be opened for it, wasting them. To lower the size of the binary file, turning off NAMES and LINES might be a good idea. Note that the case of the function or procedure will be maintained in the extension. In my example, the name that will show up when entering EXTRAS is “upper$” (all lower case). If I defined the function a UPPER$, then “UPPER$” would show up in the EXTRAS command. By convention, extensions should be done in all upper case.
If you will be running the extension on a system that already has the Qlib runtimes loaded, then compile the program without runtimes. If you don’t know if the Qlib runtimes will be available, compile it with the runtimes included. It is a good idea to compile both ways and let the user decide which one they need. The example program when compiled without the Qlib runtimes was 594 bytes. With the Qlib runtimes it was 11,146 bytes. The runtimes take up a fair bit of space.
If you load an extension that does not have the Qlib runtimes on a system where the Qlib runtimes are not loaded, you will not get an error message when you LRESPR the extension. When you call the extension is when the error will occur. The exact error message is:
Error "Runtimes Missing !"
Once you have compiled an extension, all that is needed is to LREPSR it and test it out. Remember that you can’t LRESPR while any jobs, other than Job 0 (SuperBasic), is running.