Subject: Q L H A C K E R ' S J O U R N A L

From: [email-masked] ("Mauricio Tavares")
Date: Tue, 11 Jan 1994 13:37:02 GMT

Forwarded message:
>From [email-masked] Mon Jan 10 15:56:17 1994
Date: Mon, 10 Jan 94 15:55:25 EST
From: [email-masked] (TIMOTHY C. SWENSON)
Message-Id: <9401102055.AA18167@ss1>
To: [email-masked]

         Q L   H A C K E R ' S   J O U R N A L
      ===========================================
           Supporting  All  QL  Programmers
      ===========================================
         #16                        January 1994
      
    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
     [email-masked]
     [email-masked]
     [email-masked]

EDITOR'S FORUM

   Again another issue has taken longer than I wanted to
come out.  Since the last issue one important thing has
happened to further complicate my life.  Her name is Ashlyn
Nicole; 7 Lbs 2 oz, born 23 November at 5:17 PM.

   Recently I attended a local book sale, that had a good
selection of computer books.  I was able to pick up a few
books that I wanted to add to my library.  Namely, "Mythical
Man-Month" and "Software Tools in Pascal".  I picked up a
few that looked interesting and worth the small price.  I
did pick up a copy of "The Elements of Programming Style"
real cheap and am willing to send it to the first person to
respond. I've already got a copy, but I could not pass on
picking it up for 80 cents, especially when it still retails
for over $25.

   I do have some news items.  Recently on USENET a new
newsgroup has been created, called comp.sys.sinclair.  This
newsgroup is aimed at the discussion of all Sinclair
computers, although the majority of traffic has been on the
Spectrum.  I have seen some relatively new QLer's looking
for sources of software and hardware.  I will be posting
future issues of the QHJ to the newsgroup, hoping to expand
the readership.

   As some of you may know, another part of my computer
hobby is collecting older computers.  I have recently found
a new group that shares the same interest.  The Historical
Computer Society puts out a bi-monthly newsletter called
"Historically Brewed".  It has articles talking about older
computers.  Issue number 3 was Dec 93/Jan 94, so they are
fairly new.  If you are interested, the address is:
   Historical Computer Society
   10928 Ted Williams Place
   El Paso, TX 79934 USA
   
   Before I finish, I would like to thank Emiliano Barbaini
for contributing an article for this issue.  He also worked
on the natural language C program that I asked for help on. 
I will be providing this in a future issue.

QUILL READER
   By Emiliano Barbaini

   One of the major defects of QUILL is the lack of an
"EXPORT" function. Only after release 2.35, PSION added the
export command. But also in this case, if we want ascii
text from a doc, we have to :

                1) load QUILL
                2) load the document
                3) select the export option
                4) export the document
                5) quit QUILL
                6) load an ascii editor

   If we don't have the 2.35 version, we can print the
document to a filename, with an appropriate printer driver.
In both case, there is not a simple way.

   My solution is a QUILL filter. A filter, in UNIX, is a
little program that applies some rules to an input file to
obtain output : for example a program that translates all
lowercase characters to uppercase.

   For the QUILL filter, is not a simple matter, for many
reasons :

   1) Quill does not append a newline after each line, but
only a '\0' (character code zero) after each paragraph.

   2) There are many control codes, i.e. character code 9
for tab, code 14 for signaling the end of document and so
on.

   3) The line width, indent and so on, is a mystery (for
me least).

   So, I arbitrarily decided on a line length of 70 chars
and a page length of 60 lines , and to discard any control
code except :

	9           tabulation
        14          end of document
        12          new page
        32 to 127 : ASCII code

        The flow of the program is as follows:

   In the first section, there is the declaration of some
useful variables :

#define WIDTH    70     /** width of a line           **/
#define MAXLINE  60     /** Nr of lines for page      **/
#define HTAB      5     /** tab length                **/
#define PAR_SIZE 32768  /** max size for paragraph **/
char *Paragraph;
int Page   = 1;         /** Start printing at page =1 **/
int Nlines = 1;         /** number of lines, max 60   **/
int count;
FILE *output;  These two variables are 'file pointers' :
FILE *input;   with them it is possible to access a file.

   Next, came the "main" function : each C program must to
have a main function. The main function takes 2 parameters:

     argc : an integer. The numbers of parameters passed to
the program via command line plus one, the program name

     argv : a pointer to character array that holds the
parameters.
         argv[0] is the program name
         argv[1] is the first parameter
         .. and so on ...

main(register int rage, register char *argv[])
{

   The following declare an integer to be 'register' : this
value is assigned by the compiler to a 68000 register. This
allows for short code and better performance, but only 8
variables may be declared as register.

register int ch;         /** character analyzed **/

   Next we allow a max paragraph of 32K chars :
    Paragraph = (char *)malloc(32768);
          /** request for a 32K buffer **/
   Paragraph is an array, that can be 32768 characters
long.

   Now we try to open a filename, that is the first
parameter : if this fails, a message is written to standard
error, and then the program exits. Otherwise, the variable
'input' points to the filename. The first parameter must be
present and it is the QUILL file to be translated.

    if ( (input=fopen(argv[1],"r")) == NULL )
    {
         fprintf(stderr,"I cannot open the input file
	  !!\n");
         exit(1);
    }

   Then, we test if the number of parameters is greater
than 2 : if yes, we try to open 'write only' a second
filename. That becomes the output of the filter. Otherwise
the output is standard output.
   NOTE : if you have the C68 v 4.01 compiler, the same job
can be performed in the following way : "qreader QUILL.doc
>filename" (this is the Unix syntax ).

    output = stdout ;
    if (argc>2)
    {
         if ( (output=fopen(argv[2],"w")) == NULL )
         {
              fprintf(stderr,"I cannot open the output
	       file !!\n");
              exit(1);
         }
    }

   The getc function reads a character from input; it stops
at the end of the file. If the character is an ASCII code
(characters from 32 to 127), it is stored in the Paragraph
array, else it was decoded as follows : if ch is equal to
14, execute the 'End_of_Document' function, if ch is equal
to 12, execute a 'Newpage' function  ... and so on : it is
a SELect ON ch statement !

    while( (ch=getc(input)) != EOF )
    {
        if (ch==14)              End_of_Document();
        if (ch==12)              Newpage();
        if (ch==0)               Newparagraph();
        if (ch==9)               Htab();
        if (ch>=32 && ch<=127)   Paragraph[count++]=ch;
    }

   The statement count++ increments the variable count : it
is a concise form for "count=count+1".

}

   The Htab function is called when a character code 9 is
recognised in the input file. It evaluates the number of
blanks to be added to the current line .

void Htab()
{
register int blank,j;

   count % 5 => count=count MOD 5 , this is the number of
blank to be added for the next tab.

   blank=count % 5;
   for (j=0;j<blank;j++)
      Paragraph[count++]=' ';
   return;

   This function appends a '\0' to the Paragraph array,
calls 'right_justify' function, prints an 'end of document'
message and exits from the program.

void End_of_Document()
{
    Paragraph[count]='\0';
    right_justify(Paragraph);
    fprintf (output, "\n ----- End of Document -----\n");
    exit(0);
}

   This function appends a '\0' to the Paragraph array,
calls 'right_justify' function, prints an 'new page'
message and returns to main after cleaned some variables :
the Paragraph array, the count and Nlines. Putting a '\0'
at the start of Paragraph array is the C equivalent of
Paragraph$="" on SuperBASIC : that is declaring a void
string, because a C string ends with '\0'.

void Newpage()
{
    Paragraph[count]='\0';
    right_justify(Paragraph);
    fprintf(output,"\n ----- End of Page  %2d -----\n",Page++);
    Paragraph[0]='\0';
    count=0;
    Nlines=1;
    return;
}

   The following two functions are used by right_justify
function, and are described below.

void Newparagraph()
{
    Paragraph[count]='\0';
    right_justify(Paragraph);
    Paragraph[0]='\0';
    count=0;
    return;
}

void Check_Nlines()
{
   if ( Nlines++ > MAXLINE )
    {
        Nlines=1;
        fprintf(output,"\n ----- End of Page  %2d -----\n",Page++);
    }
    return;
}
/**/

   This is the most important function : it takes a
parameter (the Paragraph array) and outputs it in lines no
longer than WIDTH char, without splitting the words. If a
Paragraph contains more than MAXLINE lines, the function
Newpage is called : this action is performed by Check_Lines
function.

void right_justify(register char *stringa)
{
register int j,k;            /** 'for' variables **/
int pos = 0;
int start_pos = 0;
int len;

   If Paragraph is shorter than a line, it will be printed,
then the function returns to main.

    len=strlen(stringa);
    if (len<=WIDTH)
    {
        fprintf (output,"%s\n",stringa);
        Check_Nlines();
        return;
    }
   Otherwise the Paragraph array will be splitted in
lines ...

    pos=WIDTH;
    while(start_pos<len)
    {
        if ( pos > len )
        {
            for (j=start_pos;j<=len;j++)
                putc(stringa[j], output);
            putc('\n', output);
            Check_Nlines();
            return;
        }
        if ( stringa[pos] != ' ' )
            pos--;
        else {
            for (j=start_pos,k=0;j<=pos;j++,k++)
                 putc(stringa[j], output);
            putc('\n', output);
            Check_Nlines();
            start_pos+=k ;
            pos=start_pos + k;
        }
    }
    return;
}

   For the future : I hope to discover the internal
structure of QUILL documents (indents, margins and so on).
If this happens, I can write a postscript driver for
QUILL documents.

   I hope that the explanation was clear. For further
details, contact me at E-mail :
          [email-masked].

   Full text of the program:

/******************************************************/
/********** quill reader : a simple filter ************/
/********** vs 1.08 08 Oct. 1993           ************/
/********** Emiliano Barbaini              ************/
/********** E-mail  [email-masked]  *****/
/******************************************************/
#include <stdio.h>
#include <string.h>

void right_justify();
void End_of_Document();
void Newpage();
void Newparagraph();
void Htab();
void Check_Nlines();

#define WIDTH    70     /** width of a line           **/
#define MAXLINE  60     /** Nr of lines for page      **/
#define HTAB      5     /** tab length                **/
#define PAR_SIZE 32768  /** max size for a paragraph **/

char *Paragraph;
int Page   = 1;         /** Start printing at page =1 **/
int Nlines = 1;         /** number of lines, max 60   **/
int count;
FILE *output;              /** output channel **/
FILE *input;               /** input channel  **/

main(register int argc, register char *argv[])
{
register int ch;         /** character analized **/

    Paragraph = (char *)malloc(32768);
          /** request for a 32K buffer **/

    if ( (input=fopen(argv[1],"r")) == NULL )
    {
      fprintf(stderr,"I cannot open the input file !!\n");
      exit(1);
    }
    output = stdout ;
    if (argc>2)
    {
         if ( (output=fopen(argv[2],"w")) == NULL )
         {
              fprintf(stderr,"I cannot open the output
	       file !!\n");
              exit(1);
          }
    }

    while( (ch=getc(input)) != EOF )
    {
        if (ch==14)              End_of_Document();
        if (ch==12)              Newpage();
        if (ch==0)               Newparagraph();
        if (ch==9)               Htab();
        if (ch>=32 && ch<=127) Paragraph[count++]=ch;
    }
}
void Htab()
{
register int blank,j;

   blank=count % 5;
   for (j=0;j<blank;j++)
      Paragraph[count++]=' ';
   return;
}
void End_of_Document()
{
    Paragraph[count]='\0';
    right_justify(Paragraph);
    fprintf (output, "\n ----- End of Document -----\n");
    exit(0);
}
void Newpage()
{
    Paragraph[count]='\0';
    right_justify(Paragraph);
    fprintf(output,"\n ----- End of Page  %2d -----\n",
      Page++);
    Paragraph[0]='\0';
    count=0;
    Nlines=1;
    return;
}
void Newparagraph()
{
    Paragraph[count]='\0';
    right_justify(Paragraph);
    Paragraph[0]='\0';
    count=0;
    return;
}

void Check_Nlines()
{
   if ( Nlines++ > MAXLINE )
    {
        Nlines=1;
        fprintf(output,"\n ----- End of Page  %2d -----\n",
	  Page++);
    }
    return;
}
/**/

void right_justify(register char *stringa)
{
register int j,k;            /** 'for' variables **/
int pos = 0;
int start_pos = 0;
int len;

    len=strlen(stringa);
    if (len<=WIDTH)
    {
        fprintf (output,"%s\n",stringa);
        Check_Nlines();
        return;
    }
    pos=WIDTH;
    while(start_pos<len)
    {
        if ( pos > len )
        {
            for (j=start_pos;j<=len;j++)
                putc(stringa[j], output);
            putc('\n', output);
            Check_Nlines();
            return;
        }
        if ( stringa[pos] != ' ' )
            pos--;
        else {
            for (j=start_pos,k=0;j<=pos;j++,k++)
                 putc(stringa[j], output);
            putc('\n', output);
            Check_Nlines();
            start_pos+=k ;
            pos=start_pos + k;
        }
    }
    return;
}
/******************************************************/

DICE PERCENTAGES
   By Tim Swenson
   
   I'm still distracted by my other hobby, wargaming.  In
tying the two together, I thought about dice, percentages,
and To-Hit rolls.

   In gaming a To-Hit roll is a die roll, where your try to
roll a certain value or less.  For example, for a To-Hit
roll of 10 with 2 six-sided die (2d6), you would have to
roll a die total of 10 or less.

   In designing a game or gaming system, it's easy to
determine the chances that something will happen by purely
guessing the general percent chance that you feel that it
will happen.  The difficult part is translating that into
terms of die.  Some designers use a 10- or 20-sided die to
work out the nice percentages, but others prefer to stick to
6-sided dice because of how common they are.

   I wrote a short program that will take a given number of
6-sided dice and print out the possible die rolls with the
percent change that that number will come up, and the
percent change that that number or less will come up (the
To-Hit roll).

** dice_ssb
** This program will simulate a number of 6
** sided dice.  It will determine what
** percentage chance a certain number
** has of rolling, and what percentage
** a number or lower has of rolling.

dice = 2

DIM array(dice+1)
DIM total_array(6^dice)

** Calculation Section

** Set all dice to 1
FOR x = 1 to dice
   array(x) = 1
NEXT x

** Set first dice to 0 so that it will
**   INC to 1 in first run through the
**   program.
array(1) = 0

FOR y = 1 TO 6^dice
   array(1) = array(1)+1
   total = 0

   FOR x = 1 TO dice
      IF array(x) = 7 THEN
         array(x) = 1
         array(x+1) = array(x+1)+1
      END IF
   total = total+array(x)
   NEXT x
   total_array(total) = total_array(total)+1
NEXT y

** Report Section

total = 0

FOR x = dice TO 6*dice

   temp1 = INT((total_array(x)/6^dice)*100)
   total = total + total_array(x)
   temp2 = int(((total)/6^dice)*100)
   print "Die roll of ";x;"   ";total_array(x);"   ";
     temp1;"    ";temp2

NEXT x

QL ANON-FTP SERVER

   I have recently found a QL FTP site that allows the
storage of binary files.  The site name is:
       maya.dei.unipd.it
   I am guessing that it is being run by one of the Zannetti
brothers in Italy.  The key advantage of this FTP site is
the fast distribution of QL software.  As an example,
version 4 of C68 is on the site.  Below is a listing of the
files avaiable. 

  C68
-rwxr--r--   303356 Dec  5  1992 c68disk1.zoo
-rwxr--r--   243545 Dec  5  1992 c68disk2.zoo
-rwxr--r--   210370 Dec 13  1992 c68disk3.zoo

 C68.version4
-r--r--r--     2482 Oct 23 09:38 C68.bugs
-r--r--r--      172 Oct 19 16:59 C68.readme
-r--r--r--   295480 Oct 19 16:59 runtime1.zoo
-r--r--r--   296381 Oct 19 16:59 runtime2.zoo
-r--r--r--   223647 Oct 19 17:00 runtime3.zoo

  CLUBS
-rw-r--r--     3970 Oct 13  1992 qlpdita.txt
-rw-r--r--    10930 Oct 13  1992 sinqldbf.zip
-rw-r--r--    42158 Oct 13  1992 sinqltxt.zip

  COMPRESS
-rw-r--r--    41506 Oct 13  1992 arc.exe
-rw-r--r--    59078 Oct 13  1992 qlarc.uue
-rw-r--r--    10099 Oct 13  1992 qlunarc.uue
-rw-r--r--     7075 Oct 13  1992 qlunarc.zip
-rw-r--r--    53431 Oct 13  1992 qlunzip.uue
-rw-r--r--    37428 Oct 13  1992 qlunzip.zip
-rw-r--r--     5749 Oct 13  1992 qz.uue
-rw-r--r--     6994 Oct 13  1992 unzip96.exe

  DME3
-r--r--r--       38 Jan 11  1993 000_README
drwxr-xr-x      512 Jan 11  1993 DME2
-rw-r--r--   129329 Jan 11  1993 hdk1_dme3.zoo

 DME2
-r--r--r--       38 Nov 26  1992 000_README
-r--r--r--    97862 Nov 26  1992 dme2.zoo

   DOCS
-rw-r--r--      446 Oct 13  1992 000IBM_TO_QL
-rw-r--r--      371 Oct 13  1992 000README
-rwxr--r--     1172 Oct 13  1992 000_MAILING_LI
-rw-r--r--     2327 Oct 13  1992 000index
-r--r--r--    36741 Oct 13  1992 QLAW.doc
-rw-r--r--    10196 Oct 13  1992 minix.txt
-rw-r--r--     2847 Oct 13  1992 myqlpd
-rw-r--r--    11099 Oct 13  1992 op_sys.txt
-rw-r--r--     3178 Oct 13  1992 project
-rw-r--r--     7454 Oct 13  1992 qlnet.txt

 FSH_v2
drwxr-xr-x      512 Apr 20  1993 OLD
-r--r--r--   181690 Apr 20  1993 fshv2.zip
-r--r--r--    36857 Apr 20  1993 fshv2Src.zip

 HARD_DISK
-rw-r--r--      650 Nov 25  1992 000_README
-rw-r--r--   279405 Nov 25  1992 qlhd.zoo

 KERMIT
-rw-r--r--      122 Dec 28  1992 000_README
-r--r--r--   106314 Dec 28  1992 bcplkerm.td0
-r--r--r--   129948 Dec 28  1992 c_kermit.td0
-r--r--r--    93607 Dec 28  1992 teledisk.zip

 NEWZOO
-rw-r--r--    20372 Oct 13  1992 bilf
-rw-r--r--    25844 Oct 13  1992 fiz
-rw-r--r--     4227 Oct 13  1992 fiz.man
-rw-r--r--    77382 Oct 13  1992 ooz
-rw-r--r--   187517 Oct 13  1992 source.zoo
-rw-r--r--    85354 Oct 13  1992 zoo
-rw-r--r--    50140 Oct 13  1992 zoo.man
-rw-r--r--     8160 Oct 13  1992 zoo.readme

 QLDB3
-rw-r--r--     5448 Oct 13  1992 qldb.txt
-rw-r--r--     8192 Oct 13  1992 qldbase.doc
-rw-r--r--    12686 Oct 13  1992 qldbase.exe
-rw-r--r--     6967 Oct 13  1992 qldbase.pas
-rw-r--r--    12686 Oct 13  1992 qldbita.exe

 QLSCR41
-rw-r--r--       72 Oct 13  1992 000README
-rw-r--r--   115957 Oct 13  1992 qlscr41.tar.Z

 QLTOOLS16
-rw-r--r--       54 Nov  8 11:20 000-README
-rw-r--r--    17384 Nov  8 11:18 qltools.1.6.tar.Z

 QLUTIL
-rw-r--r--     5983 Oct 13  1992 qimi223.asm
-rw-r--r--      434 Oct 13  1992 qimi223.cde
-rw-r--r--     6047 Oct 13  1992 qimi229.asm
-rw-r--r--      442 Oct 13  1992 qimi229.cde
-rw-r--r--     3985 Oct 13  1992 qlutil.txt
-rw-r--r--     4228 Oct 13  1992 quits.txt
-rw-r--r--     1033 Oct 13  1992 sysbase.asm
-rw-r--r--      104 Oct 13  1992 sysbase.cde
-rw-r--r--     5335 Oct 13  1992 trumpwar.asm
-rw-r--r--      184 Oct 13  1992 trumpwar.cde
-rw-r--r--     4385 Oct 13  1992 wreset.asm
-rw-r--r--      154 Oct 13  1992 wreset.cde

 QUILL2ASCII
-r--r--r--     4236 Oct 19 17:07 quill_reader

 ROGUE
-rwxr--r--      958 Mar  4  1993 000-README
-r--r--r--     4678 Mar  1  1993 FACT_asm
-r--r--r--    98677 Feb 26  1993 rogue.zoo

 SCHEME
-r--r--r--      276 Oct 19 17:01 00readme
-r--r--r--    44126 Oct 19 17:01 hobb.zoo
-r--r--r--    64105 Oct 19 17:01 jacal.zoo
-r--r--r--    30761 Oct 19 17:01 jacman.zoo
-r--r--r--     4364 Oct 19 17:01 readme.scm
-r--r--r--   200462 Oct 19 17:01 scmexe.zoo
-r--r--r--   179164 Oct 19 17:01 scmsourc.zoo

 TIFF
-rwx------      171 Oct 13  1992 00INDEX
-r--r--r--    10273 Oct 13  1992 beppe.uue
-r--r--r--    18592 Oct 13  1992 qltiff.uue
-r--r--r--    18275 Oct 13  1992 unipd.uue

 XLISP
-r--r--r--      464 Nov 16 15:30 00readme
-r--r--r--     5247 Nov 16 15:31 readme
-r--r--r--    80330 Nov 16 15:31 xldoc1.zoo
-r--r--r--   130741 Nov 16 15:31 xldoc2.zoo
-r--r--r--   139256 Nov 16 15:31 xlexe.zoo
-r--r--r--   140422 Nov 16 15:33 xlsrc.zoo

 incoming
-rw-rw-rw-   384694 Dec 11 13:39 C68unix.tar.gz

 old
drwxr-xr-x      512 Nov  8 11:19 QLTOOLS14
drwxr-xr-x      512 Nov 17 10:07 XLISP

PROLOG INTERPRETER: A SECOND LOOK
   A Review by Tim Swenson
   
   Back in QHJ #13 I have a cursory review of the Prolog
interpreter written by Hans Lub.  I said that when I found
the book that the interpreter was based upon, I could look
into it further.  Well, I found the book; The Art of Prolog
by Sterling and Shapiro.

   Even though Hans described the book as excellent, I
found it a bit heavy.  "The Art of Prolog" is your typical
college textbook.  It is not designed to be an easy
introduction to Prolog, but delves a little more in to the
theory of logic programming and Prolog.  Don't expect to
pick it up and read it lightly.

   The documentation for the interpreter is 10 pages long. 
A seperate document detailing all of the keywords or
predicates is an additional 5 pages.  The documentation is
designed only to cover the interpreter and not the language.
 It does a fine job of covering how to use the interpreter
and delves into the nitty-gritty.  It covers error messages,
limitations, sone do's and don'ts, using tracing, and any
peculiarities of the program.

   It comes with a few example programs, which I did not
really look at in the first review.  These example programs
demonstrate the robustness of the interpreter.  When the
interpreter is described as a learning tool and not a
platform for porting Prolog programs to the QL, I figured
the interpreter would be only able to handle some simple,
short programs.

   One example program is an interpreter of a language
called Monica.  There is even an example Monica program.  An
interpreter can can write another interpreter is more than
just a learning tool.

   A couple of example programs are directly from the book,
with a few minor changes to fit the interpreter and add a
few nice touches.

   I compared the list of system predicates for the
interpreter and those in the book.  The interpreter is
missing a few predicates, but seems to have most of the
important ones.  As mentioned above, any programs taken from
the book would have to be slightly adjusted.

   The interpreter itself is easy to use.  It is designed to
handle the QJUMP pointer interface, but can be run with out
it.  The interpreter does prefer extra memory, but there is
a version to run in 128K.  Start up is easy and it quickly
gives you the "?" prompt.

   When I ran the Eliza example program, I thought it was a
bit slow, but after I ran it with the Trace function on, I
saw how much processing the interpreter was doing.  I take
back any comments that I might have made about it's speed. 
It's not blazingly fast, but it's no dog either.

   The interpreter does have some QDOS screen predicates so
you can "pretty" up your programs.  CLS, INK, UNDER, PAPER,
CSIZE, WINDOW, and AT are supported.  Beware of changing the
ink in a program and then running trace.  Your trace output
will be shown in the new ink color.  Red text on black was a
bit hard to read.

   The interpreter is configurable.  You can change the
names of the help and start up files.  You can add to the
start up file and add any of your own "subroutines", sort of
like the way MicroEmacs boots up.  You can even change the
size of the interpreter screen (something that I previously
said could not be done).

   The interpreter is sort of shareware and freeware.  There
is no implied limit on how long you can use the program with
out paying the 10 pound fee, but registering will give you
the source code and an advanced user manual.  The program is
dated March 1990 so I don't know if the auther is still
supporting it.

   Some of the books that I've seen on Prolog describe the
language as a language of rules and facts.  This leads you
to believe that Prolog is more for AI work and not general
computing.  The examples that come with the interpreter and
described in the book dispell this belief.  One example
program is Quick Sort done in Prolog.  If Prolog can do
Quick Sort, then it can probably be adapted to most
computing needs.

   I did find Prolog a bit difficult to read.  The facts and
rules can be easy to read, especially with the simple examples:
     male (X) <- father (X, Y).
     father (john, mary).
But the code for Quick Sort and some other examples were
beyond me.  I guess if you can read Lisp, then you will have
no problem reading Prolog.  If not, find a good book and
spend a few hours with it.

QHJ READER SURVEY

   In the time that I've been doing the QHJ I have received
responses like "good job", "nice work", but very little
actual comments (good or bad) on the overall content of the
QHJ.  In thinking of what to put into this issue, the idea
of a reader survey popped in to my head.

   I am hoping that a number of you will respond to the
survey and help me is figuring out what direction the QHJ
should take.  I would like to know what sort of articles you
prefer and want.  I want to know what languages you prefer. 
I want to know the level of programming knowledge you know. 
All of this will help me figure out what sort of people read
the QHJ.

   In the past I've just guessed at what to cover.  I've put
in articles that I found interesting.  I've included stuff
that I thought others would find interesting.  But, it's
always been a guess.

Programming Questions:

   What languages do you program in?
     [ List language in order of preference and rank
      your knowledge of each on a scale of 1-5 ]

   What compiler/interpreter do you use?

   What languages would you like to see covered?

   State your areas of interest in programming?

   How much time do you program?
      In a day?
      In a week?
      In a month?

   Do you program professionally?

   What level of training have you had in programming?
      Self-taught?
      A few classes?
      College?

   What is your favorite text editor?

QHJ Related Questions:

   What languages would you like to see covered?

   What areas of programming would you like to see covered?

   Do you prefer code intensive articles?

   Do you prefer more verbose articles?

   Do you prefer the hard-copy or the electronic version?

   How many other persons read your copy of the QHJ?
   
   Would you be interested in a QHJ T-shirt?

QL Environment Questions:

   Do you use the Pointer Environment?

   Do you use ToolKit II?

   Do you use other computers?