Q L H A C K E R ' S J O U R N A L =========================================== Supporting All QL Programmers =========================================== #34 December 2001 The QL Hacker's Journal (QHJ) is published by Tim Swenson as a service to the QL Community. The QHJ is freely distributable. Past issues are available on disk, via e-mail, or via the Anon-FTP server, garbo.uwasa.fi. The QHJ is always on the look out for article submissions. QL Hacker's Journal c/o Tim Swenson 2455 Medallion Dr. Union City, CA 94587 swensont@lanset.com http://www.geocities.com/SiliconValley/Pines/5865/ EDITOR'S FORUMN For the second time in the life of the QHJ, I have allowed a whole year to go between issues. When I started the QHJ 10 years ago, I knew something like this might happen, therefore I made the QHJ a free publication. This has kept any off any outside pressure to get the next issue out. I really only have to deal with my own pressure. I think we all have cycles of dedication to projects. Sometimes when we start a project we can't put it down, other times we can't pick it up. For the last year I really have not had the drive to do some programming. Other tasks have filled my time and interest. Even with some forced time off from work (yea, I'm one of the victims of the failed new economy), I have not really spent time doing programming work. But, I have found the time to brush off an old issue that I've been working on for almost 9 months. I took the time to sit down and finish it. This issue focuses on freeware release of TURBO, the SuperBasic compiler. I've been involved with the release by editing the manuals for both TURBO and the TURBO Toolkit. I remembering hearing about the possible re-release of TURBO in QL Today back in early 2000. At the QL 2000 show in October 2000, I happened to run across George Gwilt. I asked him about TURBO and hinted that I'd like to get a copy, if possible. Soon I had TURBO and George's Pointer Environment TURBO Kit, TurboPTR. Not being a previous TURBO user, I needed a manual to figure out how to use it. Simon Goodwin send me his original manuals, which I edited to reflect the new TURBO. I plan to use TURBO for all my pogramming projects. I'm hoping that a totally freeware SuperBasic development package (TURBO, TURBO Toolkit, TURBO Config, and TurboPTR) will encourage a more QLer's to start programming (kind of like what C68 did for C programming on the QL). As of this issue, I plan to make the QHJ an electronic only publication and sent out a print copy. This pretty much only affects the US readers, as I sent very few issues outside the US. I believe that most readers have a way to access the QHJ via web or e-mail. TURBO COMPILER TURBO, the SuperBasic compiler, has been updated and released for almost a year. Simon Goodwin is the original author with a few others contributing to the final released product, by Digital Precision. George Gwilt has taken the source code and updated the program to work on the newer QDOS and SMSQ/E systems. TURBO comes in the following packages: - TURBO Toolkit 3.31 - TURBO 4.10 - TURBO and TURBO ToolKit manuals - TURBO Config - TurboPTR - TURBO Utilities - Task Commander TURBO Toolkit (TTK) has been updated by Mark Knight and must be loaded for TURBO to run. The manuals for TURBO and TURBO Toolkit have been updated to reflect the new versions. TURBO Config and TurboPTR are new tools written by George Gwilt. TURBO Utilities is a collection of tools for use with TURBO compiled programs. Task Commander is a tool that allows a TURBO compiled program to become a KEYWORD. Like Qliberator, TURBO compiles off a program already loaded into SuperBasic. Unlike Qlib, a work file does not need to be created first. TURBO is comprised of two parts, the parser and the code generator. They are two separate executables, but are linked when using the CHARGE TTK keyword. The parser has the main user interface to TURBO. In the parser the user can change various compile options, including where the destination executable will go and the runtime name of the executable (as displayed by the JOBS command). A lot of the compile options can be set within the SuperBasic program itself, using TTK keywords starting with TURBO_, like TURBO_taskn, TURBO_buffersz, TURBO_objfil, and TURBO_repfil. Other commands like IMPLICIT$ and IMPLICIT% inform TURBO how to treat variables. 'IMPLICIT% var1, var2' tells TURBO to treat these variables as interger variables (var1%, var2%). By default, SuperBasic variables are treated as floating point, but TURBO knows that most variables do not need to be floating point and that most programmers do not take the time to use the percent sign in their programs. The IMPLICIT% allows the programmer to continue to not use the percent sign, but tells TURBO to handle the variable as an integer, thereby saving space (integers are smaller than floats) and runtime. Major Differences with Qlib: 1 - No Linking of Extensions (Toolkits) TURBO does not support the linking of SuperBasic extensions into an executable. With Qlib, the extension can be linked and become part of the executable. The major reason for doing this is to include commercial extensions (like Qmenu, and QPTR), into an executable without having to distribute the extension separately. If an extension has to be distributed separately, then a license fee is usually required by the owner of the extension. It is also done not to require that an extension is loaded before the executable is run. If you have an extension that you think the user will rarely use and not want to install, linking into the executable makes it transparent to the user. The downside is that if the extension gets updated, then the older version will stay in the executable. Keeping the extension out of the executable will allow the extension to be updated and not require a recompile. Some older QL programs are rendered inoperable due to an older extension clashing with SMSQ/E. 2 - Fussier about SuperBasic Qlib can compile almost any SuperBasic that would run on the QL. TURBO is fussier about what SuperBasic code it will compile. An example is how file names are used. In SuperBasic a file name does not need to have quotes around it. In TURBO, they are needed. Qlib - open #3,win1_file_ext TURBO - open #3,'win1_file_ext' Plus TURBO has a number of keywords (from TURBO Toolkit) that help TURBO know more about the application. They have a tendency to give the program a more TURBO feel. With Qlib, any compiler directives are put in REMark statements and not using keywords. 3 - Executable Speed The major benefit that TURBO has over Qlib, is that resultant executable is faster than one compiled by Qlib. I had no first hand knowledge of this difference so I decided to compile a program with both Qlib and TURBO and compile the time it took to run the program. For the test I used the Ratcliff/Obershelp Pattern Matching algorithm as listed in QHJ #1. The main function is percent_alike(). The program I wrote called the fuction 1000 times, using the arguments of Pennsylvania and Pencilvania. Since I was using a Q40 as a test machine, I needed the program to run long enough to give me some meaningfull numbers. 1000 times turned out to be long enough. Here is a table of the results: SBASIC 12 secs. Qlib 8 secs. TURBO 5 secs. The test program is below: 100 LET x = DATE 110 OPEN #3,scr_100x100a100x100 120 BORDER #3,2,2: INK #3,4: PAPER #3,0 : CLS #3 130 FOR l = 1 to 1000 140 LET wordpercent = percent_alike("pennsylvania", "pencilvaneya") 150 END FOR l 160 LET y = DATE 170 PRINT #3,"Time : ";y-x 180 FOR z = 1 TO 4000 : LET test = COS(z) : END FOR z 190 CLOSE #3 200 DEFine FuNction percent_alike(a$,b$) 210 LOCal total 220 total = num_alike(a$,b$) 230 RETURN int( total/(LEN(a$)+LEN(b$))*100) 240 END DEFine percent_alike 250 DEFine FuNction num_alike (a$, b$) 260 LOCal total, temp$, a1, a2, b1, b2, large$ 270 total = 0 280 IF a$=b$ THEN RETURN LEN(a$)*2 290 IF LEN(a$)=1 AND LEN(b$)=1 THEN RETURN 0 300 IF LEN(a$) > LEN(b$) THEN 310 temp$ = a$ 320 a$ = b$ 330 b$ = temp$ 340 ENDIF 350 IF LEN(a$)=1 THEN RETURN (a$ INSTR b$) 360 large$ = find_gt_com$ (a$, b$) 370 IF large$ = "" THEN RETURN 0 380 length = LEN(large$) 390 total = length*2 400 a1 = large$ INSTR a$ 410 a2 = a1 + length 420 b1 = large$ INSTR b$ 430 b2 = b1 + length 440 IF (a1>1) OR (b1>1) THEN 450 total = total+num_alike (a$(1 TO (a1-1)), b$(1 TO (b1-1))) 460 ENDIF 470 IF (a2<>LEN(a$)+1) OR (b2<>LEN(b$)+1) THEN 480 total = total+num_alike (a$(a2 TO), b$(b2 TO)) 490 ENDIF 500 RETURN total 510 END DEFine percent_alike 520 DEFine FuNction find_gt_com$ (a$, b$) 530 LOCAL temp$, i, j, temp, large$ 540 IF LEN(a$) > LEN(b$) THEN 550 temp$ = a$ 560 a$ = b$ 570 b$ = temp$ 580 ENDIF 590 LET large$="" 600 FOR i = 1 TO LEN(a$) 610 FOR j = i TO LEN(a$) 620 temp = a$(i TO j) INSTR b$ 630 IF (temp<>0) AND (LEN(a$(i TO j))>LEN(large$)) THEN large$=a$(i to j) 640 END FOR j 650 END FOR i 660 RETURN large$ 670 END DEFINE find_gt_com In general, using TURBO takes a little more work than using Qliberator. Both can compile simple progams without any changes. TURBO gives the programmer a little more control over the end product with a variety of commands that control how the executable is compiled. The end result is that TURBO is more powerful than Qliberator, but the power comes at the price of needing to know more about TURBO to get to that power. The TURBO manuals do a pretty good job of documenting TURBO and the use of the various TURBO Toolkit commands. In some places it does go into a little too much detail for the average programmer. Converting from Qlib to TURBO can take time and be a little painfull. For some there may not be a need to convert over, as QLib may be working just fine for them. But, as TURBO keeps being updated, the Qlib user may hit a problem with Qlib on newer platforms. Plus, I think there is an advantage to using a freeware compiler. TURBO CONFIG TURBO does not support standard Qjump Config Blocks. George Gwilt has created TURBO Config, a tool that allows Config blocks to be added to TURBO compiled programs. After creating some data statements that get merged with the source code, another tool takes the Config block information and adds it to the compiled program. T_CONFIG_DATA is the program that takes your Config bock definition and creates two files. The first is the data statements with dummy data holders. The second fiile is the actual data that will be put into the Config block. T_CONFIG_LOAD is the program that takes the Config block data and puts it into the compiled program. The process goes something like this: - Write your program. - Use T_CONFIG_DATA to create the DATA statements and to define the data. - Merge the DATA statements with your program. - Compile the program. - Use T_CONFIG_LOAD to load the Config block data into the executable. The Config block data is read by using READ statements and selecting the right item by using RESTORE statements. Due to the way strings are stored, they must be read twice, with the second read getting the real string. Below is an example: 10 RESTORE 1000 20 READ int1 30 READ int2 40 RESTORE 1004 50 READ string1$ : READ string1$ 60 RESOTRE 1006 70 READ string2$ : READ string2$ 100 PRINT "Int #1: ";int1 110 PRINT "Int #2: ";int2 120 PRINT "String #1: ";string1$ 130 PRINT "String #2: ";string2$ 140 STOP 998 DATA "$'#*","ctest !!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" 1000 DATA -4444: REMark First Integer 1002 DATA -4444: REMark Second Integer 1004 DATA "XX","00000000000" 1006 DATA "XX","11111111111" TurboPTR TURBO is not compatible with all SuperBasic extensions, esp. those with array paramaters or return values through parameters. QPTR is one such set of extensions. So, to create Pointer Environment programs using TURBO, George Gwilt has written TurboPTR, which is a freeware replacement to QPTR. TurboPTR is comprised of the following elements: TPTR - a set of extensions TPTR_BAS - a set of SuperBasic routines that get merged with your program. TPTR_SETF.TASK - a program that helps setup the window definitions (inc. sprites and such). TurboPRT also comes with some example sprites and three example programs. I'm not a PE programmer so I can't say much about TurboPTR other than I hope to find the time to try it out. TASK COMMANDER Task Commander is a utility that will convert a TURBO compiled program into a resident extension or Toolkit, that can be RESPRed and seen as a new keyword in SuperBacis. Task Commander will produce a keyword that will produce the same effect as EXEC or EX. Task Commander is not designed for creating library extension with many keywords. The program is fairly simple and only does this one thing. Documentation comes with the program that quickly explains how to use the program and even how it works. TURBO UTILITIES Another zip file contains a number of other TURBO utilites: LIBRARY MANAGER, DATASPACE and Utility_Task. The zip file does not come with documentation, and briefly explains the programs: LIBRARY MANAGER - pulls out procedures from large SuperBasic programs. DATASPACE - used to ajust the data space requirements in programs already compiled. Utility_task - Neat little utility program that does three things: Charager Graphics Editor, Sound Effects Editor, and Toolkit Default Editor. TURBO SUPPORT PAGE To assist in the support of TURBO, I've created a TURBO Support Page on my web page. The page will list the various reported bugs to both TURBO and TURBO Toolkit. Each bug will list what it is, what platform the bug has been seen on (QDOS, SMSQ/E, etc), and the status of work on the bug. Using this page should take some work off of George Gwilt and leave him to concentrate on actually fixing bugs. My web page is: www.geocities.com/SiliconValley/Pines/5865 or www.geocities.com/svenqhj/ Since Geocities was bought by Yahoo, you can also use a Yahoo name instead of the longer original Geocities layout. BETTERBASIC AND CROSSREF BetterBasic and CrossRef are two SuperBasic programming utilities written by Chas Dillon (of THE EDITOR fame). Chas has released these two programs into the Public Domain. He has released the source code but not any executables. I decided to take the two programs, see what changes they needed to be compiled with the new TURBO, compile them, and make them available. Both compiled without a problem. [documentation ?] BetterBasic is a SuperBasic structure analyzing tool that does sort of a grammer check on a SuperBasic program, making changes as it sees fit and making recommendations for other areas. Looking at the source code, it looks like it will also handle a form of IBM basic (I'm guessing GW-BASIC) as the program was modified in 1992 to handle "IBM". CrossRef is a cross reference generator for SuperBasic programs. It generates a three part report on the program. Part one being an index listing of all program variables, procedures and functions. The second part is a listing of system and extension command/functions. The third part is a listing of "suspicious" variables, functions, or procedures. An optional fourth report provides a procedure trace giving a dynamic call hierarchy. Both BetterBasic and CrossRef are available off my web site: www.geocities.com/SiliconValley/Pines/5856/ DISK TEXT SEARCH UTILITY Over the years, to keep various e-mails and newsgroup postings, I've printed them out and kept them at home. I've thought about storing them as files on disk, but finding the information I need would not be too easy. I was looking for a utility that would search the files on disk, find files with from a search string, display the files, showing the lines where the search string was found. While at SGI, we had a tool that did this and it was used heavily by the technical support teams. Creating something similar on the QL could be difficult if building it from scratch. Being a Unix user for years, I know that it is easier to build a new tools by hooking together a number of existing tools. On the QL the Unix search utility GREP is available. It has options to report back the file name, the line number, and the line of text, where a search string has been found. Now I needed a way to view the information in such a way as to browse through it. HTML and an HTML browser was not quite the way to go. Dilwyn Jones had written a text browser, that allows links to other files, but it does not allow links to specific lines with a file. After some badgering by myself and Darren Branaugh, Dilwyn has now added that feature to his VIEWER program (as of version 1.20). So, with a tool to search files and a tool to display the results, all this is left to write is a program that links the two together. Listed below is that program. Basically, here is what the program does. The user enters a search string. The program then calls GREP with the command line options to report back the name of the file, the line number on which the string is found and the line itself. The program searches all '_txt' files in a given directory. The results of the GREP are sent to a tempory file on RAM1_. The program then reads in this file, creating proper links for VIEWER. Since VIEWER is not designed for lines greater than 80 characters, the line in which the string is found, is shortened to about 30 or so characters. The program then calls VIEWER with the links file as an argument. Using VIEWER the user can then browse through the results of the search, looking to find the right text file. There is one possible major drawback with the way the program is written. Since the program has to wait for GREP to finish executing before it can continue, it uses EXEC_W instead of EXEC to execute the program. If there are other multitasking programs, this might interfere with them. It would be possible to write a polling routine to wait for GREP to finish, but would complicate the simple program. A more polished version would find a proper solution to the problem. For those interested, GREP can be found in the C68 distribution and VIEWER is available off of Dilwyn Jones' web page. 100 PRINT "Enter Search String" 110 INPUT search$ 120 cmd_line$ = "-n "&search$&" *txt > ram1_temp_txt" 130 EXEC_W grep;cmd_line$ 140 OPEN #4,ram1_temp_txt 150 OPEN_NEW #5,ram1_link_txt 160 REPeat loop 170 INPUT #4,in$ 180 IF EOF(#4) THEN EXIT loop 190 x = ":" INSTR in$ 200 file$ = in$( 1 TO x-1) 210 in$ = in$ (x+1 TO ) 220 x = ":" INSTR in$ 230 line_num$ = in$(1 TO x-1) 240 text$ = in$(x+1 TO ) 250 x = search$ INSTR text$ 260 length = LEN(text$) 270 IF x > 15 THEN 280 first = 15 290 ELSE 300 first = x-1 310 END IF 320 IF length > x+15 THEN 330 last = 15 340 ELSE 350 last = length 360 END IF 370 text$ = text$(x-first TO x+last) 380 PRINT #5,"<<";file$;"$";text$;"@";line_num$;">>" 390 END REPeat loop 400 CLOSE #4 410 CLOSE #5 420 DELETE ram1_temp_txt 430 EXEC_W flp1_viewer_rtm;"ram1_link_txt"