Table Of Contents Editor's Forum ........................................ 1 Structured SuperBasic ................................. 2 Ratcliff/Obershelp Pattern Matching ................... 7 The Quebec Link ....................................... 9 Pursuit of a Public Domain C Compiler ................. 9 Minix on the QL ....................................... 10 Editor's Forum By Tim Swenson Welcome to the first issue of the QL Hacker's Journal. This publication is meant to fill the gap in publications already available. There are a number of good magazines that cover programming, but, due to popularity, do not cover the QL. There are also some good User Group Newletters that cover the QL, but are not the right forum for discussing in-depth programming. This Journal is designed as a forum for serious QL programmers to discuss various topics dealing with programming. In short, this journal will cover topics related to programming in general, but focusing on the QL. My dealings with computers is not just with the QL. I use computers of various makes and operating systems when I am at work. I happen to like other Operating Systems besides QDOS, it's just that I enjoy working with and programming on the QL. It's got a great character that makes it a wonderfull hacker's machine. For the price, it is still the best little computer available. Before I go more about the Journal, I thought I would give you a little backgroud on my background. I first bought a Sinclair ZX81, back in November of 1981. I recieved a B.S. Degree in Computer Science in 1987, from Cal State University, Hayward (Hayward is just south of Oakland). I have used a number of different computers in school and at work. Presently I am an officer in the USAF working in the Pentagon. I do computer support for the Office of the Secratary of Defence. I know both MS-DOS and UNIX fairly well (I do not consider myself a guru in either). I am a computer collector with my computer collection presently standing at 28 computers. I subscribe to Dr. Dobb's Journal and the C User's Journal at home, and Unix Today!, Unix Review, and PC-Week at work. Since I don't do any programming at work, I must fill that craving at home. I like to program in SuperBasic, but will dabble in C. I hope to make this Journal a fairly regular publication. Between work, home, programming, and being the editor for the Capital Area Timex Sinclair (CATS) User's Group, I will try to find time to work on the next issue. I do page 1 hope to have a large number of readers send in thier latest programs and projects. I know I find it very interesting to know what some other programmer is doing. I am always amazed at what people are doing with the QL. As far as subscriptions go, I'm pretty flexable about this. I'm doing this for the fun of it. I'm printing only a few newsletters per issue (or is that will?). I'm not too worried about subscriptions, I'm more worried about getting good articles and programs. If you feel that you should send something my way, send an article or a program. That's worth more than any subscriptions. Well, enough with the introduction. I hope you find the journal interesting. Please write and let me know what you think. Your letters will help balance out the bills and junk mail I get. Structured SuperBasic By Tim Swenson Most of the SuperBasic programs presented in this newsletter will be written in Structured SuperBasic. I created Structured SuperBasic because I found regular SuperBasic to be hard to read. I love the fact that SuperBasic supports a number of structured programming constructs, but it still requires ugly line numbers. The Structured SuperBasic filter takes a program written in Structured SuperBasic and outputs a regular SuperBasic program. The best way to really describe Structured SuperBasic is to include the documentation that comes with the filter program. Below is that documentation. Structured SuperBasic Version 2.3 By Timothy Swenson INTRODUCTION Structured SuperBasic (SSB) is another way of writing SuperBasic programs. It allows programmers to write SuperBasic programs without line numbers and with white space between blocks. SSB is essentially a filter. It takes in a program file that is written in SSB and outputs a program file that is in SuperBasic. SSB programs are written using a text editor, be it ED, THE EDITOR, MicroEMACS, or even Quill. This the SuperBasic version of the program was compiled using QLiberator to create the executable version. This package consists of a number of files: SSB_SSB - SSB version of program SSB_BAS - SuperBasic version of program SSB_DOC - Program Documentation (Due to a problem with QLiberator, I am unable to provide an executable copy of this program. If you are able to get this program to compile and run properly, I would like to have a copy) DEFINITION OF STRUCTURED SUPERBASIC Structured SuperBasic is defined below: Line Numbers Line numbers are not used in SSB. SuperBasic code is entered without line numbers. page 2 Indenting SSB lines may be indented. This indenting will be retained in the SuperBasic output file. Blank Lines Blank lines are ignored by the program and are not passed to the SuperBasic program. Blank lines are used to make the program structure clearer. Include Statements SSB does support include statements so that a program can be distributed across a number of files. Include statements can be placed any where in a file, but they must start in column 1. The syntax is: #include flp1_file_name #INCLUDE flp1_file_name The case of the letters must be the same. #Include will not work. The program expects the file name to start one space after the include statement and end with the end of line. You may use any drive or device type. Labels Labels are used for GOTOs and GOSUBs. Labels are started with an @ sign then the label name, such as @loop. The program is case sensitive about labels. @LOOP is not the same as @loop. If the program comes across an unknown label, it will notify you and then skip the label. The place-defining label must start in the first column and may have nothing after it. All other label references must be placed at the end of a line. The program does not check to see of a label is connected to a GOTO or GOSUB statement. You may not use the @ symbol in your program, except for labels. The program allows up to 30 labels, of length 15. You may change the SuperBasic version of the program to however many labels you need. SSB makes a limitation that you may not use the @ character in any of your programs. Use CHR$(64) in its place. If you want the following line: IF a$="@" THEN ..... use the next line: IF a$=CHR$(64) THEN .... It will work every time. Remarks SSB uses two different type of remark statements. Both remark statements start with remark characters and continues to the end of the line. The remark characters must be the first non-space characters in the line. ## This remark statement puts a REMARK line in the SuperBasic program. Do not use a ## remark in a line by itself. ** This remark statement is ignored by the program. No remark statement is passed to the SuperBasic program. Other The SSB program does absolutely no syntax checking on the input program. If the program has syntax errors, when the output file is loaded into SuperBasic, those lines with the errors will start with the SuperBasic keywork MISTAKE. USE OF THE STRUCTURED SUPERBASIC FILTER PROGRAM page 3 The SSB program may be started by LRUN (for the SuperBasic version) or EXEC or EXEC_W (for the executable version). Both programs are exactly the same. The executable version of the program was created using the QLiberator SuperBasic compiler. Once the program starts you will be asked for the name of the input file name. This is the SSB program file. The entire file name including drive must be entered. Then you will be prompted for the output file name. Like the input file name, you must enter the drive. If the input file does not exist or if the output file exists the program will bomb out. The program will then prompt you for the starting line number and the line increments. You must enter both numbers. The program does not provide defaults. Now the program will make two passes through the input file. As each pass is run, you will see a grey character for each 10 lines processed by the program. This will allow you to see that the program is working. When the program is done, the output file will ready to be loaded into SuperBasic and run. ADVANTAGES OF STRUCTURED SUPERBASIC SSB gives one the advantage of writing SuperBasic code without having to worry about any line numbers. If you go back and insert some code in a section, you need not waste time wasting time renumbering the lines. SSB is designed to writing longer programs that require them to be easy to read. It is designed for those programmers that write most of the code before running any of it. SSB does bring about the same restrictions that compilers do, that being, making changes to the code, run the SSB filter program (like a compiler) and then load and run the program. If you make any changes to the program while in SuperBasic, you must make the same changes to the SSB code. EXAMPLE STRUCTURED SUPERBASIC PROGRAM ## This is a sample SSB program. ** This line will not be passed to ** the SuperBasic program. ** This program prints the numbers from ** 0 to 19. let x=0 @loop let x=x+1 print x if x<20 then goto @loop stop This is the Structured SuperBasic filter program written in Structured SuperBasic. It is a good example of how easy SSB is to read over regular SuperBasic. ## Strutured SuperBasic Filter ## Author: Timothy Swensn ## Date Created: 16 Oct 1990 ## Date Revised: 16 Oct 1990 ## This program takes in SSB code and outputs a file page 4 ## that is runnable in SuperBasic ## Init Variables DIM label$(30,16) DIM label(30) label_var = 1 num_count = 0 file_num = 5 OPEN #3,con_300x150a100x0_32 BORDER #3,2,4 PAPER #3,0 : INK #3,4 : CLS #3 PRINT #3," STRUCTURED SUPERBASIC FILTER" PRINT #3," Version 2.3" PRINT #3," by Timothy Swenson" PRINT #3 INPUT #3,"Enter input file: ";in_file$ INPUT #3,"Enter output file: ";out_file$ INPUT #3,"Enter Starting Line Number: ";line_num_d INPUT #3,"Enter Increment for Line Numbers: ";line_delta line_num = line_num_d PRINT #3," PASS 1" pass_one in_file$, file_num PRINT #3 PRINT #3," PASS 2" line_num = line_num_d num_count = 0 file_num = 5 DELETE out_file$ OPEN_NEW #4,out_file$ pass_two in_file$, file_num CLOSE #4 PRINT #3 PRINT #3,"Program Done" CLOSE #3 STOP DEFine PROCedure pass_one (in_file$, file_num) OPEN_IN #file_num,in_file$ REPeat pass_1 num_count = num_count + 1 IF (num_count MOD 10) = 0 THEN PRINT #3,CHR$(1); INPUT #file_num,in$ IF EOF(#file_num) THEN EXIT pass_1 IF LEN(in$)=0 THEN END REPeat pass_1 temp=first_char IF in$(temp TO temp+1)="**" THEN END REPeat pass_1 IF in$(1)=CHR$(64) THEN label$(label_var) = in$ label(label_var) = line_num label_var = label_var + 1 ELSE page 5 IF in$(1 to 8)="#include" or in$(1 to 8)="#INCLUDE" THEN pass_one in$(10 to ), file_num+1 ELSE line_num = line_num + line_delta END IF END IF END REPeat pass_1 CLOSE #file_num END DEFine pass_one DEFine PROCedure pass_two (in_file$, file_num) OPEN_IN #file_num,in_file$ REPeat pass_2 num_count = num_count + 1 IF (num_count MOD 10) = 0 THEN PRINT #3,CHR$(1); INPUT #file_num,in$ IF EOF(#file_num) THEN EXIT pass_2 IF LEN(in$)=0 THEN END REPeat pass_2 temp=first_char IF in$(1)=CHR$(64) THEN END REPeat pass_2 IF in$(temp TO temp+1)="**" THEN END REPeat pass_2 IF in$(temp TO temp+1)="##" THEN PRINT #4,line_num;" remark ";in$(1 TO temp-1);in$(temp+2 TO ) ELSE temp= CHR$(64) INSTR in$ IF temp<>0 THEN a$ = in$(temp TO ) temp2 = 0 @label1 temp2 = temp2 + 1 IF temp2 > 30 THEN PRINT #3,"Warning - Label ";a$;" Not Found" END REPeat pass_2 END IF IF label$(temp2) <> a$ THEN GO TO @label1 PRINT #4,line_num;" ";in$(1 TO temp-1);label(temp2) ELSE IF in$(1 to 8)="#include" or in$(1 to 8)="#INCLUDE" THEN pass_two in$(10 to), file_num+1 ELSE PRINT #4,line_num;" ";in$ END IF END IF END IF line_num = line_num + line_delta END REPeat pass_2 CLOSE #file_num END DEFine pass_two DEFine FuNction first_char LOCal count count=0 @label2 count=count+1 IF in$(count)=" " THEN GO TO @label2 RETurn count END DEFine first_char Ratcliff/Obershelp Pattern Matching page 6 By Tim Swenson In the July 1988 Issue of "Dr. Dobb's Journal", there is an article on Ratcliff/Obershelp pattern matching. This algorithm is designed to compare two strings and return a percentage of how close they are to each other. A result of 67 means that the two strings are 67% alike. This algorithm can be used to compare a misspelled word with a number of possible correct words. The word with the highest percentage alike is taken to be the correct spelling of the word. The program is a good example of how to use recursion in SuperBasic. The program takes the two words and finds the greatest common string (GCS) between them. For each string, it takes the part of the word to the left and right of the GCS and does it again with them. Let's take a look at the two words "pennsylvania" and "pencilvaneya". The GCS is "lvan." The program then takes the left most strings, "pennsy" and "penci", and processes them. The GCS is now "pen". Since there is nothing to the left of the GCS, the program then tries the right hand side, "nsy" and "ci." With these two strings, there is no GCS. The program then goes up the tree and tries the other right hand strings, "ia" and "eya". This goes on until the whole string is analysed. Since the program is a function, it return a value to a variable. It is to be used like this: LET x = percent_alike(a$,b$) It can take a literal string or a string variable as oan arguement. This is also valid: LET x = percent_alike("sofware","softwear") One little caveot about the program. It is case sensitive, so you should convert the two strings to either all upper case, or all lower case. DEFine FuNction percent_alike(a$,b$) LOCal total total = num_alike(a$,b$) RETURN int( total/(LEN(a$)+LEN(b$))*100) END DEFine percent_alike DEFine FuNction num_alike (a$, b$) LOCal total, temp$, a1, a2, b1, b2, large$ total = 0 IF a$=b$ THEN RETURN LEN(a$)*2 IF LEN(a$)=1 AND LEN(b$)=1 THEN RETURN 0 ** make a$ the shortest string IF LEN(a$) > LEN(b$) THEN temp$ = a$ a$ = b$ b$ = temp$ ENDIF ** If a$ = one char and b$ > one char IF LEN(a$)=1 THEN RETURN (a$ INSTR b$) page 7 large$ = find_gt_com$ (a$, b$) IF large$ = "" THEN RETURN 0 length = LEN(large$) total = length*2 a1 = large$ INSTR a$ a2 = a1 + length b1 = large$ INSTR b$ b2 = b1 + length IF (a1>1) OR (b1>1) THEN total = total+num_alike (a$(1 TO (a1-1)), b$(1 TO (b1-1))) ENDIF IF (a2<>LEN(a$)+1) OR (b2<>LEN(b$)+1) THEN total = total+num_alike (a$(a2 TO), b$(b2 TO)) ENDIF RETURN total END DEFine percent_alike DEFine FuNction find_gt_com$ (a$, b$) LOCAL temp$, i, j, temp, large$ IF LEN(a$) > LEN(b$) THEN temp$ = a$ a$ = b$ b$ = temp$ ENDIF LET large$="" FOR i = 1 TO LEN(a$) FOR j = i TO LEN(a$) temp = a$(i TO j) INSTR b$ IF (temp<>0) AND (LEN(a$(i TO j))>LEN(large$)) THEN large$=a$(i to j) END FOR j END FOR i RETURN large$ END DEFINE find_gt_com The Quebec Link By Real Gagnon [ These are excerpts from "The Quebec Link" column in the Sinc-Link Newsletter from the Toronto T/S Users Group.] Default device on the QL Say you are writting a program and it is important to know from which device the user is running it. What can you do? If the user's QL is equipped with TOOLKIT II, then it is possible to set the default devices for the program and the data and retrieve them with the functions PROGD$ and DATAD$. But if the user doesn't set default devices then we are out of luck. One solution to this problem is to look in the system variable area to determine from which device the QL was booted. The following function, BOOT_DEVICE$, will retrieve that information. page 8 DEFine FuNction BOOT_DEVICE$ pointer1=PEEK_L(164096)+16 pointer2=PEEK_L(pointer1)+36 length=PEEK_W(pointer2) b$="" FOR i=0 TO length b$=b$&CHR$(PEEK(i+length+pointer2)) END FOR i RETurn b$&"1_" END DEFine The first variable, POINTER1, contains SV_FSDEF which gives us the address of the file system physical definition. From this address, we read the variable POINTER2, called FS.NMLEN in the QL Technical Guide. This word gives us the length of the boot device name. From that point, all we have to do is to read the device name with the PEEK function. Type in the function BOOT_DEVICE$ and try the following command to test it: PRINT "QL booted from ";BOOT_DEVICE$ For example, the BOOT_DEVICE$ function can be used in a menu program to detect from which device the QL was booted from. Pursuit of a Public Domain C Compiler By Tim Swenson Mark Wahl, at student at UC Berkeley, has been looking into a public domain C compiler that can be ported to the QL. As some of you may already know, the only public domain C compiler for the QL is the Small C compiler available from the Quanta Library. Small C only supports a subset of C and not the full language. Metecomco Lattice C supports full C, but it is a commercial package that is partially hardware based. Even with out copyright laws, it would be difficult to distribute. Mark has looked into two different compilers, the GNU C compiler GCC and one called c68 written for the Atari ST. Due to the size of the source for the GNU C compiler, Mark has not had a chance to really investigate if a port will work. On the c68 compiler, he has tried to compile it with the Lattice C compiler, but recieved an error message stating "Too many variables." Due to his work load at school, Mark can not decicate too much time in pursuing this effort too quickly. If anyone is interested in taking up the challenge, contact the QHJ and we'll put you in touch with Mark. Minix on the QL By Tim Swenson For those that don't know what Minix is; Minix is a small Unix like operating system written by Andrew Tannenbaum to be used as an instructional aide in Operating System classes. Felix Croes started working on porting Minix to the QL from the Atari ST version. Erwin Dondorp (dondorp@fwi.uva.nl) has taken over the task. He reports that he has Minix version 1.5.5 running successfully. After much pestering, Erwin has decided to allow me to be a beta tester for the project. He has promised to send a disk with QL Minix, but so far my mailbox has yet to recieve such a package. I'll keep pestering him and keep you informed. One interesting item about Minix/QL is that, unlike other versions, it does not take over the QL. Minix/QL is just another job running under QDOS. Basically it is a Multitasking OS running under another Multitasking OS. page 9 page 10