         Q L   H A C K E R ' S   J O U R N A L
      ===========================================
           Supporting  All  QL  Programmers
      ===========================================
         #1                        January 1991
      
    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
     5615 Botkins Rd 
     Huber Heights, OH 45424 USA
     (513) 233-2178
     swensontc@mail.serve.com
     http://www.serve.com/swensont/

         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
