         Q L   H A C K E R ' S   J O U R N A L
      ===========================================
           Supporting  All  QL  Programmers
      ===========================================
         #21                        June 1995
      
    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
     swensotc@ss2.sews.wpafb.af.mil
     tswenson@dgis.dtic.dla.mil

EDITOR'S FORUMN

   This issue of the QHJ is a little smaller that I would
like.  I've been busy getting ready for the QL show in Oak
Ridge, Tennesse.  This is the same show that has been held
in Newport, Rhode Island, but Bob Dyl wanted to try a
different place this year.

   I've been busy making some distribution disks of some QL
programming freeware, verifying the entries in the Sinclair
Internet Resources List, printing up this list, printing up
a hard copy of the QHJ, MausNet, and Z88 e-mail lists,
spending a week on a trip to Pensacola, Florida (It's
tougher when you travel with 2 kids), and all the other QL
related stuff I do normally.

   For those QHJ readers on the net (which is most), you
might know that the QL Mailing list that was maintained by
Beppe Zannetti is no more and has been sort of absorbed into
the QHJ e-mail list.  I've also been asked to break out the
MausNet readers out of the e-mail list.  Due to bandwidth
restrictions, it turns out that it is better to mail the QHJ
to one MausNet reader and have him post it to the MausNet QL
newsgroup.  So that others can use either of these mailing
lists, I plan to put them on the QL Anon-FTP servers (those
in Finland, Norway, and Italy).

   I've noticed that the Sinclair (Spectrum/ T/S 2068)
mailing list is now gone.  This means that T/S 2068 and
Spectrum users have no mailing lists.  I've also noticed
more ZX81 interest on comp.sys.sinclair, some from people
that have recently picked up older machines at a flea
market (or boot sale for those on the other side of the
pond), and others that have discovered the various
emulators available.

   I would like to start a Master Sinclair E-Mail list.  I
hope to create an Archive database with users names, e-mail
addresses, and what computer they have.  From this
database, I can generate any e-mail list I want (with names
or just the e-mail address).  If you know of anyone out
there that would like to be on a Master Sinclair list, have
them send me an e-mail note.  It is the ZX81, Spectrum, T/S
2068, and Z88 users that I need the most.  I think I've got
most of the QL users out there.

   I don't plan to make these mailing lists into a LISTSERV
type of system (collecting then redistributing Sinclair
e-mail message), but more as a phone book to look up
Sinclair persons and to use when wanting to do a mass
mailing (instead of a USENET posting).

   As mentioned above, I've prepared a more up-to-date
Sinclair Internet Resources List.  It contains a list of
Sinclair FTP sites, Gopher sites, World Wide Web Sites,
Mailing lists, USENET Newsgroups, etc.  Like the e-mail
lists, I will put a copy on the three Anon-FTP servers.

   One project that I am thinking about working is an other
version of the Structured SuperBasic (SSB) filter.  For
those that don't know SSB lets you write SuperBasic
programs with no line number and indenting, and will add
the line numbers for you.  I'm thinking about adding
support similar to that found in the C preprocessor, such
as; #define, #ifdef, #end, #elseif, etc.  I also plan to
compile the program and make it all available on the three
Anon-FTP servers.  I'm looking to see if there is any
interest out there for this.  Let me know.

   In QHJ #19 was an article on the Soundex algorithm.  For
some odd reason I could not get the code to compile.  I know
I had to be missing something.  Peter Tillier found what I
was missing.  In the comment preceding the FOR statement, it
is terminated with a * and not a */.  This comments out a
bunch of code until the next */.  Don't you hate it when
it's the little things that get you.
 
   Per-Erik Forssen of Sweden, where my great grandparents
came from, has provided the QHJ with it's first article
dealing with assembly language.  I'm glad to have it, since
a number of you commented in the readers survey that you
wanted to see articles on assembly.


QHJ FREEWARE AWARDS

   Last Issue I introduced the QHJ Freeware Awards and asked
for votes on programs for each category.  My original idea
was to decide the awards myself, but I felt it would be a
good idea to get your input.  Well, after getting only one
response, I did have to decide the awards myself.  At least
I gave it a shot.

   Below is the list of categories and the winners.  After
each category I will give a short discussion on why I chose
that particular winner.

   Since this is the first year for these awards, I have
expanded the criteria for consideration to include any
Freeware program up to this point.

   Best Pointer Environment Program:
   
      MineField by Phillipe Troin
      
   Of all of the Freeware PE programs I have seen,
MineField stands well above them.  MineField looks and
feels like a professional PE program.  It uses a number of
PE features in the same manner that other PE progams do
(like QPAC2).  A number of different mouse cursors are
used.  The skull and crossbones cursor when you lose and
the thumbs up cursor when you win are nice touches.  I've
seen some other freeware PE games, but none look as
excellent as MineField.  It's design and development shows
an in-depth knowledge of the PE by Phillipe.  If you wanted
a program as an example of how to do PE programs, MineField
would be that example.

   Best Non-Pointer Environment Program
   
      QED by Jan Bredenbeek
      
   I know this program has been around a while, but as far
as an impact in the QL community, I think few programs have
gone as far as QED.  QED is the standard text editor
distributed with any program package that needs one (like
C68, Intergroup Freeware Exchange, etc).

   Best Port to QL
   
      ZIP/UNZIP by Erik Slagter
      
   There were a lot of contenders in this category.  A large
number of programs have been ported to the QL.  Most have
been ported directly, with some consideration for the
special needs of the QL.  ZIP/UNZIP has taken the
functionality of the most popular archiving program, brought
it to the QL, and added support for the QDOS header
information so that executables will archive well.

   Best Language or Language Utility
   
      C68 by Dave Walker
   
   No other compiler has done as much for the QL as C68. 
C68 has provided many users a full K&R C compiler which
allows them to either write their own programs or port
programs to the QL.  C68 is a very comprehensive and
complete C compiler.

   Best Programmer
   
      Jonathan Hudson
      
   Jonathan Hudson has written programs that have dominated
communications on the QL.  QeM, QTPI, and QFAX are the
standards in QL communications.  Jonathan has consistantly
written solid programs with few bugs.

   Well, there they are.  The First Annual QL Hacker's
Journal Freeware Awards.  I have made up some award
certificates (I had to learn Page Designer 3 to do it) and I
will mail them to all of the award winners.

   Next year I would like to keep the contenders down to
just those programs released in 1995 - mid-96 timeframe.  I
would also like to get a little more input from you the
reader.  I don't mind coming up with my own winners, but I
do not get a chance use all freeware programs, so I can't
make a very informed decision.


QDOS FILTERS
   By Per-Erik Forssen
   
   Filter programs are common in the UNIX world, but they
are found to a varying extent on other platforms (such as
QDOS) as well. In QDOS filters were introduced in 1984 with
the QL-Toolkit (which later turned into Toolkit II). A
filter program is typically a program that reads a stream
of characters and makes some simple operation on it before
passing it on. This function is not too different from what
a filter attached to a water pipe will accomplish, thus the
name filter. Filters may be connected in chains to perform
more complex operations. Examples of what filters can do
are converting the character stream to uppercase,
encrypting it with a supplied key, etc. From QDOS a filter
is started like this:

  EX UPCASE,ram1_infile,ram2_outfile

   The EX command is an enhanced version of EXEC that can
pass arguments to the started programs. In this case the
files 'ram1_infile' and 'ram2_outfile' are opened and the
channel ID's are passed to the program (placed on the (A7)
stack).

   Our example filter will strip the input stream from ANSI
ESC-codes. ESC-codes are produced by software generating
output to a terminal. The name ESC-code is due to all codes
starting with the ESC char, chr$(27). After that comes a
varying number of argument chars. ESC-codes will, when
recieved by the terminal, alter some of it's settings. One
code will for example switch to underline mode( chr$(27);
'[4m'; ), while another will turn this mode off. This
program will only remove some of the ESC-codes.

*
* A filter to strip _log files from ESC sequences
* Current version only strips codes generated by the UNIX
* 'nn' program Release 6.5.0 #8 (NOV),
*    Kim F. Storm, 1991
* This program is (C) 1995 Per-Erik Forssen
* Should assemble with Qmac, other assemblers will need
*    other directives.
*
*   QDOS standard equates
*
myself     equ        -1
forever    equ        -1
err.nc     equ        -1
err.ef     equ        -10
mt.frjob   equ        $05
io.fstrg   equ        $03
io.sbyte   equ        $05
ut.err0    equ        $ca
*
*   equates special for this program
*
bufsz      equ        8000
ch_lf      equ        $0A
ch_cr      equ        $0D
ch_esc     equ        $1B
ch_brace   equ        $5B
*
*  Macro to step through the read buffer
*
NEXTCHAR   MACRO
[.lab]     move.b  (a2)+,d1     ; get next char
           subq.w  #1,d2        ; decrement count
           ENDM

           section program
           data    8192         ; 8K data space
*
           bra.s   ESCstrip
           dc.b    '1.00'       ; program version
           dc.w    $4afb        ; standard job
           dc.w    8            ; program name
           dc.b    'ESCstrip'
           ds.w    0            ; word align

ESCstrip   lea.l   0(a6,a4.l),a6 ; set buffer pointer
           move.w  (sp)+,d7     ; pop no of chan id's
           subq.w  #2,d7        ; should be be two
           bne.s   ESC_exit
           move.l  (sp)+,a0     ; input chan
           move.l  (sp)+,a4     ; output chan
*
ESC_fstrg  moveq   #io.fstrg,d0 ; fetch a string
           move.w  #bufsz,d2    ; maximum size
           moveq   #10,d3       ; wait up to a fifth of
	                          a second
           move.l  a6,a1        ; place it in buffer
           trap    #3
           move.l  d0,d4        ; keep error code
           move.w  d1,d2        ; and string length
           beq.s   ESC_errtst   ; null string?
*
           move.l  a6,a2        ; reset buffer pointer

ESC_loop   NEXTCHAR
           cmp.b   #ch_cr,d1    ; ignore CR
           beq.s   ESC_loop
           cmp.b   #ch_esc,d1   ; at an ESC-code ?
           bne.s   ESC_send
           NEXTCHAR
           cmp.b   #ch_brace,d1
           bne.s   ESC_psend
           NEXTCHAR
           bsr.s   SKIP_NUM
           cmp.b   #'m',d1
           beq.s   ESC_lfsend
           cmp.b   #'H',d1
           beq.s   ESC_loop
           cmp.b   #'J',d1
           beq.s   ESC_loop
           cmp.b   #'K',d1
           beq.s   ESC_loop
           cmp.b   #';',d1
           bne.s   ESC_psend
           bsr.s   SKIP1_NUM
*
ESC_lfsend moveq   #ch_lf,d1    ; send a line feed instead
           bsr.s   BPUT
           bra.s   ESC_next

ESC_psend  move.b  d1,d5        ; esc code unresolved;
           moveq   #ch_esc,d1 ;let it pass through filter
           bsr.s   BPUT
           move.b  d5,d1
ESC_send   bsr.s   BPUT
*
ESC_next   tst.w   d2
           bgt.s   ESC_loop
*
ESC_errtst move.l  d4,d0        ; test the return from read
           beq.s   ESC_fstrg
           addq.l  #-err.nc,d4 ;not enough time to finish?
           beq.s   ESC_fstrg
           cmp.l   #err.ef-err.nc,d4 ; end of file?
           bne.s   ESC_exit
           moveq   #0,d0      ; yes; exit without errors
*
ESC_exit   move.w     ut.err0,a2  ; signal error in
				    SuperBASIC #0
           jsr        (a2)
           move.l     d0,d3    ; return status to owner
           moveq      #mt.frjob,d0       ; force remove
           moveq      #myself,d1         ; myself
           trap       #1
*
*    Subroutines
*    SKIP_NUM  skips 0 or more digits in string
*    SKIP1_NUM skips 1 or more
*
SKIP_NUM
SN_loop    cmp.b      #'0',d1
           blt.s      SN_end
           cmp.b      #'9',d1
           bgt.s      SN_end
SKIP1_NUM  NEXTCHAR
           bra.s      SN_loop
SN_end     rts                 ; number is now skipped
*
*    BPUT sends char in d1.b to output
*
BPUT       movem.l    a1/d1,-(a7)
           exg        a4,a0         ; use output chan
           moveq      #forever,d3   ; timeout for write
           moveq      #io.sbyte,d0
           trap       #3
           exg        a4,a0         ; use input chan
           movem.l    (a7)+,a1/d1
           rts
           end

   The program includes many of the programming features
used in assembler. For example the equ statements:

myself     equ        -1

   This corresponds to the C #define statements, i.e. all
occurrences of 'myself' will be replaced with '-1' at
assembly. Then we have macros:

NEXTCHAR   MACRO
[.lab]     move.b     (a2)+,d1          ; get next char
           subq.w     #1,d2             ; decrement count
           ENDM

   This corresponds to the C++ inline functions (or perhaps
some more advanced C #define directives). All occurences of
NEXTCHAR in the code will be replaced by the instructions
between MACRO and ENDM. A macro can have arguments, but
this feature is not used here.

   Then we have the BPUT, SKIP_NUM and SKIP1_NUM
subroutines. They work much like functions, only that the
argument passing is implicit. You will have to decide for
each subroutine that for example registers D1 to D4 are
arguments, and the result is returned in D0.

   For those who have never seen assembler before, see this
as a brief introduction to how assembler programming
works. For others, here is a neat way to write filters for
QDOS.

  Vintrosa Sweden 
  Per-Erik Forssen
  Email: d92perfo@und.ida.liu.se


JOYFU OR FIND THE MISSING CONTRUCT

   JOYFU when sounded out means "Joyful, with no L" or as
it is really supposed to be sounded out "Joyfull Noel."  The
lack of an L turns one word into two.

   This is sort of an interesting introduction to missing
letters or contructs.  I happen to read a DoD journal
called "CrossTalk, The Journal of Defense Software
Engineering."  Most of the journal is either on Ada or
above my head.  The best part of the journal is the
"Curmudgeon's Corner."  It's a sort of rambling article,
written by Robert Bliss, talking about software topics.

   In this last issue, Robert talks about missing letters. 
Robert writes:

   "The intentional omission of words was the motivation
behind Georges Perec's 1969 novel 'La Disparition.'  The
author created a lipogram, a work in which something is
prohibited, in this case any word containing the letter E. 
Perec wrote the work in French, which uses E for almost
everything.  When he completed 'La Disparition', Georges
Perec realized he now had an abundance of unused words
containing the the E left over.  So he wrote his next work,
'Les Revenentes', with E as the only vowel used.  (Do you
ever get the feeling that some people have far too much
time on their hands?)"

   Robert then ponders how interesting it would be to write
software where a contruct is prohibited.  I know that the
GOTO command has suffered this prohibition in the past with
a number of very well known articles.  But, would it be
possible to write something with out a FOR loop, or a WHILE
statement.  I doubt that you could write something without
a IF statement, but it might be possible.

   An interesting demonstration of this would be a few code
segments that would demonstrate how one would build a
replacement for any particular contruct.  How you would
write a FOR loop with a WHILE statement, how you would
write a WHILE statement with a FOR statement, etc.  I
remember back in Computer Architectures class we were told
that an entire computer could be constructed of only NOR
gates.  They showed how every other gate (OR, AND, XOR,
NOT, etc) could be constructed with a number of NOR gates
(I think it was the NOR gate).

   I'm hoping someone will take this challenge and produce
a some code.  It's the little puzzles like this that make
programming fun.


LANGUAGE DESIGN PRINCIPLES

   Jon Bentley has been around computers for years, spending
most of his time with AT&T Bell Labs (the birth place of
Unix and C).  In an article in "Unix Review", Jon mentions
some guidelines on building languages.  I thought these
guidelines also apply to writing other programs, so I
thought I would pass them along.  The items below are taken
from the article.  My comments are in []'s.

   [ Jon discussed his ideas with a few major points listed
below.]

   A Zoo of Examples.  Start with the zoo to define your
problem, use it for testing throughout development, and put
the best examples into the documentation.

      * If you are doing a graphing program, start of with
a number of example graphs that you want to be able to
create using your program.  Use them to help you decide
what type of features you want your program to support.

   [You could also think of all of the strange cases in
which your program might blow up at.  This would provide a
good zoo of examples.]

   A Working Description.  Create a one- or two-page
outline of your Language to ensure a cohesive design.

   [ Clearly defining your problem at the start will have
headaches in the design and coding process.]

   The User's Manual.  Document your language or GUI's goals 
and architecture from the user's perspective.

      * To create a program that is designed for the user,
write your documentation first, describing how you want the
program to run, and then write your code based on this. 
It's too easy to take short cuts in programming, because
it's easy to implement and not easy to use.

   [ Writing the manual afterwards may base the
functionality on the program and not how it's supposed to
interact with the user.  Focus on your user interface and
functionality, then work on the code.]

    [ A sidebar to the article had a listing of Language
Design Principles that complement the article.] 

Language Design Principles.

   - Design Goals.  Before you design a carefully study the
problem you are trying to solve. An old rule of thumb
states that the first 10% of programming effort provides
90% of the functionality; can you make do with a small
implementation that cheaply provides the fir 90%, or do you
have to use more powerfull tools to get to 99.9%.

   - Simplicity.  Keep you language as simple as possible. 
A smaller system is easier for its implementers to design,
build, document, and maintain and is easier for its users
to learn and use.

   - Yardsticks of Design.  Here are some desirable
properties of interfaces:

      -- Orthogonality: keep unrelated features unrelated.
      
      -- Generality: use an operation for many purposes.
      
      -- Parsimony: delete unneeded operations.
      
      -- Completeness: make the system implement all
operations of interest.

      -- Similarity: make the interface as suggestive as
possible.
      
      -- Extensibility: make sure the system can grow.
      
      -- Openness: let the user "escape" to use related tools.
      
   - The Design Process.  Like other great software,
languages are grown, not built.  Start with a solid, simple
design expressed in a succinct notation.  Before
implementing the language, test your design by performing a
wide variety of operations.  After the system is up and
running, interate designs to add features as dictated by
your customer's needs.

