         Q L   H A C K E R ' S   J O U R N A L
      ===========================================
           Supporting  All  QL  Programmers
      ===========================================
         #9                       June 1992 
      
    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/

Editor's Forumn

   For those readers that have Internet access, Timo Salmi
of Findland has started an Anon-FTP QL Server,
garbo.uwasa.fi (128.214.81.1).  Garbo is already an MS-DOS
server but Timo has set aside a section for the QL. To
start things off, he has uploaded a number of his programs.

   I have uploaded back issues of the QHJ to the server and
plan to upload most of the freeware stuff that I have (if
it's not too large to transfer to MS-DOS disk).  I am trying
to get Dave Walker, the porter of C68, to upload the C68
files to Garbo.uwasa.fi.  Odds are that most of the files
will be archived somehow, but these archivers will be
available on the server (I'll put them there).

   I have two documents/files that might be of interest to
QLer's.  The first is the Computer Language List.  This is a
document maintained by Bill Kinnersley of the University of
Kansas, that documents all known computer languages.  The
first version of the document that I recieved had 1300
languages listed.  Where as the most recent version has 1700
languages.

   A lot of the languages are from the early days of
computers and most never got out of the lab.  To make the
list, the language must have been pulished in some sort of
tech journal, report, magazine, book, etc.

   The other document is the Jargon File.  This is a
compiled list of computer related jargon words and thier
meanings as related to computers.  Over the years this
document has spawned off two books, the most recent being
the "Hacker's Dictionary."  The version of the Jargon file
that I have is should have about 90% of what the book does.

   The Jargon File documents the history of the words,
including who started them and where they started.  I've
found it interesting from the view point of computer
history, but it also have me a better idea of the "real"
definition of a number of computer terms.

   Both documents are available via the Internet, but for
those without Internet access (or Anon-FTP access), I can
provide them on disk.

   One thing that I have been doing the last couple of
months, is writing to any magazine that misuses the term
Hacker.  I'm trying to get the press to stop using the term
Hacker when they talk about crackers or computer criminals. 
Now the general public thinks that Hackers are nothing but a
bunch of kids breaking into computer systems, wreaking havoc.

   Michael McClary posted an article to Usenet that really
sums up the whole issue:

{begin quote
   A computer "hacker" is a gifted programmer, capable of
substituting skil and persistence for quality software tools.

   A computer "cracker" is a person who defeats system
security measures, for whatever reason.  Some crakcing is
done for legitimate reasons, such as testing system security
or honing programming skills.  Much more is done to obtain
unauthorized access.

   A computer "vandal" is a person who uses his computer
access, however obtained, to damage other people's data,
programs, or computer access.

   A computer "pirate" is a person who obtains improper
financial reward for someone else's data or programs,
regardless how they obtained them.

   Saying "hacker" when you mean "cracker", "vandal", or
"pirate" is like saying "cowboy" when you mean "cattle
rustler."  Just as nearly all cattle rustlers are cowboys
but few cowboys are cattle rustlers, nearly all crackers are
hackers but few hackers are crackers.

end quote}

   So the next time you see some article in the popular
press misusing the term Hacker, write a letter to the
editor letting them know that they are not using the term
correctly.  So far I have had "Defense News"  and "CIO"
have published my letter to the editor on this very matter.
 
New Public Domain/Freeware QL Software
  By Tim Swenson
  
  In the past few months I have recieved some disks
containing public domain and Freeware software for the QL. 
The disks came from Howard Clase of Canada, and Franz
Herrmann of Germany.

  For the record, Freeware software is software that is
copyright by the author, but everyone is free to copy and
distribute the software.  Code from Freeware programs can
not be used in any commercial program.  With Public Domain
software, the author gives up all rights to the program. 
The Freeware concept is heavily encouraged and used the the
FreeSoftware Foundation.

  Here is a list of the stuff from Franz:
  
    Intergroup Freeware Exchange Database -  We have
recieved this once before, but the executable program that
provided easy access to the database would not execute.  Now
everything is running fine.
    The IFE is functionally like the Quanta Library, but
encompasses a number of QL User Groups, most of them in Europe.

    QED Text Editor - This editor, written by Jan
Bredenbeek, looks like it is based on the Metacomco text
editor ED.  From looking at the help file for QED, I could
see that the command set is almost the same as ED.

    ZOO, HAR, LHX - These three programs are archiving
programs, much like the well known PKZIP suite of programs. 
Where as PKZIP is used mostly for MS-DOS (but being ported
to other platforms) ZOO, HAR, and LHX are used widely on a
variety of systems.  All three allow you to pack a number of
files into a single compressed file.
    File compression is great for uploading a number of
files to a BBS as one file, and for putting more data on disks
to be sent via the mail.
    All three programs come with source code.  This is
convenient for those that want to study the file compression
algorithm or tinker with the program.

    The group also has a copy of QLUNZIP, a program that
will unzip files that have been archived using PKZIP.

    FLEX and YACC -  FLEX and YACC are two utilties that
are used in creating compilers and interpreters.  FLEX is a
Freeware version of the Unix utility LEX.  FLEX is used to
create the code for a lexical analyser.  YACC ( short for
Yet Another Compiler Compiler) is used to create the code
for a parser.  These two tools have been used for years in
the Unix environment.  Learning either one of these programs
on the QL also means that your experience is portable to
other systems.

    PROFF - PROFF is a portable version of the Unix text
formatter ROFF.  ROFF is the basis of the other Unix text
formatters, TROFF and NROFF.

    MKTYPES - This is a suite of programs used to create
function declarations in C programs.  This is then used in
compiling all modules of your program, allowing type
checking across modules.  For the die-hard C programmer.

     OCCC - This is a file that contains the winners of the
Obfuscated C Contest from 1985 on to about 1991(?).  When
unarchived, it's a large number of files.  Obfuscated means
to make unclear or hard to understand.  Althought some may
say that C is already obfuscated, there is a contest that
takes it to the limit.  One category is "the hardest / most
obscure way to do a simple item."

  As you can see from the files from Franz, C is being used
a lot to port programs to the QL, plus Unix is one of the
primary sources for programs.  This comes from three facts:
    1.  C programs are very portable when written properly.
    2.  Unix, because of it different dialects, has stressed
C portablity.
    3.  Unix has a wealth of Freeware software (with source
code ) ready for porting to a new computer.  Most MS-DOS
programs do not come with source code.  If they do, they are
too MS-DOSed to be portable.

   From Howard Clase comes a number of programs that he has
had published in QL World and has made publicly avaiable. 
Where Franz has focused on C, Howard's programs focus on
SuperBasic.  These descriptions are short because I have
not had the time to evaluate each package.  The
descriptions are based on quick readings of the _doc files.

   Here is a list of the packages:

   FTIDY - File Tidy.  A program to copy files and tidy up
your file system.

   DIR_EDIT - Directory Edit.  "Allows you to edit the
directory of a device."  Not too sure what this means.

   GRAPH - Graph Plot Library for inclusion into your own
programs.  Loads and is used like Toolkit II or other
SuperBasic extensions.

   FOUNTS - Fonts for the QL for use in your programs.  A
number of different fonts are included as examples.

   GLAZIER - A screen/window design package for programmers.
 Allows the user to draw windows on the screen and Glazier
will produce the SuperBasic code for those windows.

   PROCS - A number of misc. SuperBasic procedures for use
in your own programs.

   MISC - A number of short SuperBasic programs.
   
   This is the disk for those of you that are into
SuperBasic programming.  The utilities included can expand
the capabilities of your programs and skills.

Both of the two disks are available from the QHJ.

Software Engineering and
OOPS on the QL?
      By Tim Swenson
   
   Through subscriptions at work and home, I read a number
of computer magazines, including Dr. Dobb's Journal (DDJ),
C Users Journal, Unix Review, Sun World, and Info-World. 
These magazines discuss programming, programming trends,
and programming utilities/software.

   Two of the leading topics of discussions have been Object
Oriented Programming (OOP) and Software Engineering, which
includes Computer Aided Softwawre Engineering (CASE).

   Most of my programming at work is short scripts/programs
that are used as short term utilities ( because I am the
only one willing to tackle AWK, Perl, and Shell Scripts). 
But I don't get to do any "serious" programming that would
allow me to explore these new areas of computers.

   Because of this practical lack of experience, I still
do not have a firm understanding of CASE and especially
OOPs.  We've all heard about both in the press and the how
they both will be the panacea of all computing ills.

   I've tried to muddle through articles that supposedly
explain what OOPs is, but they all introduce concepts with
out any tie to past knowledge.  We all learn about some new
item by comparing it with an old item.  Our basis of the new
item is founded on what we know of the old item (note that
I'm trying to avoid the term "object").  All of the articles
on OOPs make no attempt to show what an OO program is by
comparing it with one that is not.  They sort of jump into
the middle of things as if all of their definitions of
object, class, hierarchy, etc, are clear to all.  I believe
it was Jeff Dunteman of DDJ that said "Object Oriented
Programming with be the hottest item in the 90's, but no one
will know what it is.", or something to that affect.

   With CASE or just SE, I have not run across any general
utilities that easily take high level psuedo-code and turn
it into a code.  We do have a number of specialized
utilities, like YACC and LEX mentioned above, but most
articles seem to describe an entire environment that allows
code to be built from putting flow-chart boxes on the screen.

   Where I'm leading to is this: I'm looking for examples of
either OOPs or CASE on the QL, even if it's very limited
examples drummed up for demo purposes only.  I feel the QL
should be a usefull tool for exploring both of these
concepts.  I'm not saying that I want to embrace either of
these concepts, I just want enough experience and knowledge
with the concepts to form an opinion other than "I dunno."

    Know I know we've got some sharp people out there
working on QLs (other wise we would not have C68 and other
great software).  I'm hoping that someone out there knows
enough about either one of these concepts to explain it to
me and other QL programmers.  Or for those more masochistic
minded, go figure these out for yourself and report back to
us on what you find.  


Random Dot Stereograms
   By Herb Schaaf
   
   Random  Dot Stereograms (RDS) can give  the illusion of
depth if you have binocular vision.  Instead of the 
usual pair of stereoscopic pictures, a single 'picture' 
is made with several swaths side by side, interleaved so as
to provide the brain with depth clues when you gaze at
the dots in a certain way.  It takes a little blinking
and practice, but when it 'snaps-in' to view the effect is
marvelous.  Once seen, it is fairly easy to find again.

   The best width for a swath is about half the distance
between your eyes, say an inch or so.  I have been using
seven swaths, so  that a RDS can be made on the screen that
is about 7 inches wide and 6 inches high, and the effect is
pleasing.  I've done two so far, one a 'splash' like
ripples in a pond and another of a  pretzel.  I've  enjoyed
working out the procedures and functions in SuperBasic, and
a RDS only takes a minute or so to develop.  Maybe I'll get
(or take) the time to try it in C to speed things up, or
even do animation in 3D!  

   I've tried other swath widths, dot sizes, dot densities,
and dot quantities, so you can too!  A dot size of 1 pixel
used to now  and then 'hang' the QL into limbo, but since I
added a missing END IF it has been OK. Pixels of size 4 are
pretty good, and faster. A density of 1% or even less will
work!  The minimum number of dots per swath seems to be
around 42 or so. 

   There is a short program "eyefuse3" to calibrate your
setup for the range of separation that you can accomodate. 
See how close and how far you can still fuse two images
into three, and then pick a middle value for your swath
width.    

   Simple objects like a sphere are probably easier to find
for the beginner, but splashes, pretzles, and saddles, etc.
are fun. Some simpler DEFine FuNctions are included.    
Enjoy!

eyefuse3:

100 REMark eyefuse3
125 WTV
126 PAPER 4 :INK 0
127 CLS
135 xo = 50: yo = 50
137 sep = 100
145 n = 8
155 bk = 1
165 explain
175 PAPER 0 : INK 6
180 CLS
200 FOR ac = 1 TO n
210 FOR dn = 1 TO n
220 BLOCK bk*1.5,bk,xo+ac*bk*1.5,yo+dn*bk,                      
        ((ac MOD 2 + dn MOD 2) MOD 2)*4
222 BLOCK bk*1.5,bk,100+xo+ac*bk*1.5,yo+dn*bk,                  
        ((((ac MOD 2 + dn MOD 2) MOD 2)-1)*-1)*2
230 END FOR dn 
240 END FOR ac 
247 CURSOR xo+n*1.5,yo :PRINT;"o" 
248 CURSOR sep+xo+n*1.5,yo :PRINT;"O" 
249 AT 16,2:PRINT;"use <-- and --> keys" 
250 AT 17,2:PRINT;" to change separation" 
251 AT 19,2:PRINT " hold ESC key to exit" 
255 REPeat moves 
257 AT 10,15: PRINT;sep;"  " 
258 CURSOR xo+sep , yo 
260 IF INKEY$(-1) = CHR$(192) : PAN -1,4 :sep=sep-1
270 IF INKEY$(-1) = CHR$(200) : PAN 1,4 :sep=sep+1 
280 IF INKEY$(-1) == CHR$(27) : EXIT moves 
290 END REPeat moves
300 DEFine PROCedure explain 
310 PRINT " If you have
binocular vision and can see fairly well"\ 
320 PRINT "with either eye, it is possible that you may be
 able"\ 
330 PRINT "to 'see' objects in depth on your QL monitor
 screen"\\ 
340 PRINT "This exercise will 'calibrate' your eyes and your
 VDU"\ 
350 PRINT\"Make a note of the separation distance in pixels
 when"\ 
360 PRINT "you find it easiest to fuse the two little
 checker boards" 
365 PRINT "into THREE little checkerboards." 
370 PRINT "If you see 3 that's great; If you see two or
 four, change"\ 
380 PRINT "something: tilt your head, blink, move away from 
 or closer"\ 
390 PRINT "to the screen, change eye-glasses, etc. while 
 trying the"\ 
400 PRINT "various pixel separations"\ 
410 PRINT "The big 'O' will dominate the little 'o' when you 
 have"\ 
420 PRINT "good super-imposition and the center checkerboard
 will"\
425 PRINT "be olive-drab"\\"Touch [SPACE BAR] to continue"
435 PAUSE 
445 END DEFine explain 
455 REMark end of eyefuse3

RDSphere_QLHJ_bas

100 REMark   RDSphere_QLHJ_bas
110 REMark H.L Schaaf  May 9,1992
120 REMark ref. Mathematica Journal  Winter 1991 V.1,N.3,
 p.69-75
130 REMark 'Random Dot Stereograms' by Dror Bar-Natan @
Princeton
140 REMark    dror@math.princeton.edu
150 ipl_dis = -20 :REMark image plane displacement, +
 is closer
160 obj_dis = 10 :REMark object displacement, - is more
 distant
170 iwide =360 : ihigh =240 : REMark image width and
 height
180 ytox = 4/3 : REMark y to x aspect ratio of QL blocks
190 swide = 60 : REMark swath width
200 zscale = 8 : REMark adjust for depth of Z axis
210 MODE 4 : CSIZE#2,1,0:CSIZE#0,0,0
220 WINDOW#1, iwide+8,256,0,0 :PAPER 0 : INK 7
230 WINDOW#2,144,190,368,0  : BORDER#2,2,2
240 PAPER#2,4 : INK #2,0
250 WINDOW#0 ,144,64,368,192 :BORDER #0,2,4
260 nk = 7 : REMark ink color 7 = white
270 CLS#0 : CLS#2 : CLS#1
280 REMark fill in with blocks
290 :
300 REMark ask for density and block size
310 INPUT#2; " % density ? ";dens : density = dens/100
320 INPUT #2;"Block size ? ";bk
330 hb = bk/2 : REMark half block
340 :
350 d_begin = DATE    : REMark start timer
360 :
370 ac = swide DIV bk : REMark blocks across (columns)
380 ns = 2*ac         : REMark allow for left shifts
390 dn = ihigh DIV bk : REMark blocks down (rows)
395 :
400 REMark create random pattern for first swath
404 RANDOMISE(32000)
410 DIM rdot%(density*ac*dn)
415 cnt = DIMN(rdot%)
417 FOR i = 0 TO cnt
418 rdot%(i) = RND (0 TO ac*dn)
419 END FOR i
420 :
580 REMark recap
590 PRINT#2\\"  "; :UNDER#2, 1
600 PRINT#2;"Swath Data:" : UNDER#2, 0
610 PRINT#2;"   ";ac;" across"
620 PRINT#2;"  ";dn;" down"
630 PRINT#2;" ";ac*dn;" total"
640 PRINT #2;" ";cnt;" dots/swath"
650 PRINT #2;" ";(INT(10000*cnt/(ac*dn)))/100;" %
 density"
660 :
670 REMark create swaths
680 DIM swaths%(cnt,ns)
690 :
700 REMark put random pattern into first swath
710 REMark  y values go into zeroth elements
720 FOR count = 0 TO cnt
730 i = rdot%(count) DIV (ac)
740 j = rdot%(count) - i*(ac)
750         swaths%(count,0)=i*bk
760         swaths%(count,1)=j*bk
765         BLOCK bk,bk,swaths%(count,1),swaths%(count
,0),nk
770 END FOR count
780 :
790 REMark create guides to help get proper 'focus'
800 gdlx=(iwide-swide)/2 : gdly=ihigh+6
810 gdrx=(iwide+swide)/2 : gdry=gdly
820 BLOCK 8,8,gdlx,gdly,nk
830 BLOCK 4,4,gdlx+2,gdly+2,0
840 BLOCK 8,8,gdrx,gdry,nk
850 BLOCK 4,4,gdrx+2,gdry+2,0
860 :
870 REMark geometric reference coordinates
880 xcntr=(iwide-swide)/2 : ycntr = ihigh/2
890 :
900 REMark a function to return the 3D value
910 DEFine FuNction sphere(x,y)
920 LOCal xs,ys,xx,yy
930 radius = 8*8
940 diam = 2*radius
950 diamsq = diam*diam
960 xs=ABS(xcntr-(x+hb))
970 ys=ABS(ycntr-(y+hb))*ytox
980 xy = (xs*xs+ys*ys)
990 IF xy > diamsq
1000     offset = ipl_dis
1010       ELSE 
1020         zz = diamsq-xy
1030         z=SQRT(zz)
1040         offset = z + obj_dis
1050 END IF 
1060 RETurn offset DIV zscale
1070 END DEFine 
1080 :
1090 REMark build remaining swaths
1100 OVER 1
1110 FOR i = 0 TO cnt
1120   FOR j = 2 TO ns
1130        ZD = sphere(swaths%(i,j-1),swaths%(i,0))
1140        swaths%(i,j)=swide+(swaths%(i,j-1)) - ZD
1150     IF ((swaths%(i,j)+bk)>iwide) : EXIT j
1160     BLOCK bk,bk,swaths%(i,j),swaths%(i,0),nk
1170   END FOR j
1180 END FOR i
1190 :
1200 d_end = DATE :REMark stop timer
1210 d_lap = d_end - d_begin
1220 PRINT #2\\" Elapsed time:"\"  ";d_lap;" seconds"
1230 :
1240 REMark save screen
1250 SBYTES_O ram2_rds_scr,2^17,2^15
1260 PRINT #2\\" sbytes saved to"\"  ram2_rds_scr"
1270 :
1280 STOP

Following are some other DEFine Functions: 
   (Change line 1130 to suit)

A Pyramid of sorts:

900 REMark a function to return the 3D value
910 DEFine FuNction pyr(x,y)
920 LOCal xs,ys,xx,yy
930 baseline = 150
960 xs=ABS(xcntr-(x+hb))
970 ys=ABS(ycntr-(y+hb))*ytox
980 xy = (xs+ys)
990 IF xy > baseline
1000     offset = ipl_dis
1010       ELSE 
1020         zz = baseline-xy
1040         offset = zz + obj_dis
1050 END IF 
1060 RETurn offset DIV zscale
1070 END DEFine 

Imagine a Phillips head cavity ?

900 REMark a function to return the 3D value
910 DEFine FuNction phlhd(x,y)
920 LOCal xs,ys,xx,yy
930 baseline = 80
960 xs=ABS(xcntr-(x+hb))
970 ys=ABS(ycntr-(y+hb))*ytox
980 xy = SQRT(xs*ys)
990 IF xy > baseline
1000     offset = ipl_dis
1010       ELSE 1020         zz = xy - baseline
1040         offset = zz + obj_dis
1050 END IF 
1060 RETurn offset DIV zscale
1070 END DEFine 

Fan-blades making an X  ?

900 REMark a function to return the 3D value
910 DEFine FuNction xvane(x,y)
920 LOCal xs,ys,xx,yy
930 baseline = 50
960 xs=ABS(xcntr-(x+hb))
970 ys=ABS(ycntr-(y+hb))*ytox
980 xy = (xs-ys)
990 IF ABS(xy) > baseline
1000     offset = ipl_dis
1010       ELSE 
1020         zz = baseline - xy
1040         offset = zz + obj_dis
1050 END IF 
1060 RETurn offset DIV zscale
1070 END DEFine 

Diamond shape (similar to pyramid)

900 REMark a function to return the 3D value
910 DEFine FuNction diamond(x,y)
920 LOCal xs,ys,xx,yy
930 baseline = 100
960 xs=ABS(xcntr-(x+hb))
970 ys=ABS(ycntr-(y+hb))*ytox
980 xy = (2*xs+3*ys)/5
990 IF xy > baseline
1000     offset = ipl_dis
1010       ELSE 
1020         zz = baseline - xy
1040         offset = zz + obj_dis
1050 END IF 
1060 RETurn offset DIV zscale
1070 END DEFine 

Sinc - the classic splash, change scales for sombrero 

900 REMark a function to return the 3D value
910 DEFine FuNction sinc(x,y)
920 LOCal xs,ys,xx,yy
960 xs=ABS(xcntr-(x+hb))/swide
970 ys=ABS(ycntr-(y+hb))*ytox/swide
980 xy = SQRT(xs*xs+ys*ys)/2
1020         z = 2*PI*xy
1040         offset = 2*swide*(SIN(z)/z)
1050 END IF 
1060 RETurn offset DIV zscale
1070 END DEFine 


  P.S.  I'm especially proud of my 'pretzle' sometimes
known as the Escher knot.  If there is interest let the
Editor know, and we will show you the complicated way I did
it.  Even better, show us your interesting RDS FuNctions
etc.! 


Infix to Postfix
  By Tim Swenson
  
  In the March 1992 issue of "The C Users Journal", Rex
Jaeschke has a column called "Doctor C's Pointers".  He has
been running a series of articles on data structures in C. 
In one of the column on stacks, he presents a infix notation
to postfix notation translator/convertor.

   Infix notation is what is used in C, Pascal, Basic, etc. 
It looks like what we all learned in Algebra I.  A equation
would look like this: ( 3 + 7 ) - 8.

   Postfix notation is more stack oriented.  It is used in
HP calculators, the languages Forth and Postscript, and is
also called Reverse Polish Notation (RPN).  (Infix notation
is sometimes called Polish Notation after it's Polish
inventor)  The above equation would look like this: 3 7 + 8 -.

   The C program belows takes in an infix equation and
converts it to a postfix equation.  Sample input would be:

   c - d * e + f
   (c - d * e) + f
   (((a - b) / (c + d)) * e)
  
   The program has a #define TRACE that allows you to see
the process as it goes along.

  
  intopost1_c:
  
/* File: intopost1_c
   fuctions for pushing and popping
*/
   
#define STACK_SIZE 30

static int stack[STACK_SIZE];

static int stack_ptr = 0;

push(value)
  int value;
{

#ifdef TRACE
  printf("pushing: %c\n",value);
#endif

   if ( stack_ptr == STACK_SIZE )
      printf("Stack is full\n");
   else
      stack[stack_ptr++] = value;
}

pop()
{
   if (stack_ptr == 0) {
      printf("Stack is empty\n");
      return(0);
   }

#ifdef TRACE
  printf("popping: %c\n",stack[stack_ptr-1]);
#endif

   return stack[--stack_ptr];
}

intopost2_c:
  
#include <ctype_h>

/*-----------------------------------------------------

FUNCTION: intopost - converts infix to postfix

A. Push a ( on the stack.  This sentinel allows us to 
detect when we have flushed out the stack on completion in
step I.

B. Ingnore white space.

C. Pass alphabetic characters through to postfix list.

D. Push any ( on the stack. These sentinels allows us to
detect when we have flushed out the stack when handling )
and operators.

E. Have a ) so pop off the stack and put into postfix list
until a ( is popped.  Discard that (.

F. Have a * or /.  Pop off any operators of equal or higher
precedence and put them into postfix list.  If a ( or lower
precedence operator (such as + or -) is popped, put it back
and stop looking.  Push new * or/.

G. Have a + or -.  Pop off any operators of equal or higher
precedence (that include all of them) and put them into
postfix list.  If a ( is popped, put it back and stop
looking.  Push new + or -.

H. Report unknown character on input.

I. Have processed all input characters.  Now flush stack
until we find the matching ( put there in step A.

J. Terminate the postfix list.

-----------------------------------------------------
*/

intopost( infix, postfix)
  char *infix, *postfix;
{

  int st;
  
/* A */  push ('(');
         while (*infix != '\0') {

#ifdef TRACE
  printf("*infix: %c\n",*infix);
#endif

/* B */     if ( isspace(*infix)) {
               ;
	    }
/* C */     else if (isalpha(*infix)) {
               *postfix++ = *infix;
	    }
/* D */     else if (*infix == '(') {
               push('(');
	    }
/* E */     else if (*infix == ')') {
               while ((st = pop()) != '(')
	          *postfix++ = st;
	    }
/* F */     else if (*infix == '*' || *infix == '/') {
               while (1) {
	          if ((st = pop()) == '(' || st == '+'
	                  || st == '-') {
	             push(st);
	    	     break;
	          }
	          *postfix++ = st;
	       }
	       push(*infix);
   	    }
/* G */     else if (*infix == '+' || *infix == '-') {
               while (1) {
	          if ((st = pop()) == '(') {
	             push(st);
		     break;
	          }
	          *postfix++ = st;
	       }
	       push(*infix);
	    }
/* H */     else {
               printf("Unknown input character %c\n",
	       *infix);
	    }
	 
	    ++infix;
	    continue;
         }
/* I */  while ((st = pop()) != '(')
            *postfix++ = st;
	   
/* J */  *postfix = '\0';

}

intopost3_c:
   
/* convert infix notation to postfix notation */

#define TRACE

#include <stdio_h>
#include "intopost1_c"
#include "intopost2_c"

main()
{
   char infix_str[200];
   char postfix_str[200];
   
   while (1) {
      printf("Enter Infix: ");
      if (gets(infix_str) == NULL)
          break;
	  
      intopost(infix_str, postfix_str);
      printf("   postfix: %s\n", postfix_str);
   }
   
   return 0;
}
   

Fletcher's Checksum
   By Tim Swenson
   
   The May issue of "Dr Dobb's Journal" focused on data
communications and included articles on checksums.  One
article covered Fletcher's Checksum, an algorithm faster
than CRC and just as reliable as CRC, except it handles
smaller blocks than CRC.  CRC checksum will catch a 2 bit
error in a 65,535 bit message, where as Fetcher will catch
a 2 bit error in a 2040 bit message.  The one thing I
noticed about the algorithm was how easy it was to
implement.

   Fletcher's Checksum is really two 8-bit checksums.  This
makes the algorithm easy to implement on any platform. 
Plus you only have to deal with two bytes instead of a 32
bit number, which would involve determining what order the
32 bit number is spread across bytes.

   Below is a SuperBasic version of the checksum program. 
The function calc_fletcher calculates the Fletcher Checksum
for a string of characters, calculates the "opposite"
checksum, and appends it to the end of the string.

   What I mean by "opposite" checksum is this:  after the
checksum is calculated (the two bytes), two other bytes are
calculated so that when the whole message is processed at
the recieving end, the checksum will equal 0.  If the
message is equal to say 10, the -10 is added to the message
to bring the whole thing to 0.

   The check_fletcher function calculates the Fletcher
Checksum on the message (string) and returns it.  If it
returns 0, then the message was received with no errors,
else there was some error in the message.

   Those that are interested in 680XX assembly programming
should check out the article.  The text shows the algorithm
in both C and 68000 assembly.  The author then goes on to
optimize both the C code and 68000 assembly code.  The
program goes from 17 lines of 68000 code to 4 lines of 68000
code.

** Fletcher's Checksum
**   Structured SuperBasic program
**

string1$ = "This is test of Fletcher's Checksum"

string2$ = calc_fletcher$ (string1$)

results = check_fletcher(string2$)

IF results = 0 THEN
   PRINT "Checksum is OK"
ELSE
   PRINT "Checksum is Bad"

DEFine FuNCtion calc_fletcher$ ( str$ )
 LOCal x, sum1, sum2, check1, check2, length

   sum1 = 0
   sum2 = 0
   length = LEN(str$)

   FOR x = 1 TO length
      sum1 = ( sum1 + CODE(str$(x)) ) MOD 255
      sum2 = ( sum1 + sum2 ) MOD 255
   NEXT x

   check1 = 255 - (( sum1 + sum2 ) MOD 255 )
   check2 = 255 - (( sum1 + check1 ) MOD 255 )

   str$ = str$ & CHR$(check1) & CHR$(check2)
   RETURN str$
END DEFine calc_fletcher

DEFine FuNction check_fletcher ( str$ )
  LOCal sum1, sum2, x, length

   sum1 = 0
   sum2 = 0
   length = LEN(str$)

   FOR x = 1 TO length
      sum1 = ( sum1 + CODE(str$(x)) ) MOD 255
      sum2 = ( sum1 + sum2 ) MOD 255
   NEXT x

   RETURN sum1+sum2
END DEFine check_fletcher


