
     
 Y8888bo                .d88oo                                                
  88[ 88[              d8`  `8                                                
  88[ ]8P             ]8P    `[                                               
  88[ 88`  .ooo  .oo. d8[     `.oo,  oo.oo oo, .o,oo   oo.o  ooo  .oo. .oo.
  88888o   8[]8[ 88 Y 88[     .8``8['88"Y8P"88 Y8P 8b `88P8`d8 8b 88 Y 88 Y
  88[ `88  " ]8[ 88b` 88[     88  88 88 ]8[ 88 ]8[ 88[ 88  ]8P""" 88b` 88b'
  88[  88[ oP]8[ `888 Y8b    .88  88`88 ]8[ 88 ]8[ 88[ 88  ]8[    '888 `888
  88[ ]88`]8[]8[]  Y8[`88,   dY8  88 88 ]8[ 88 ]8[ 88` 88  ]8b   ]  Y88  Y8[
 o888888" `8b/8b,bodP  'Y8boP``YbdP`.88,d8b.88,]88o8" .88,  Y8bo` bodP bodP
                                               ]8[
                                               ]8[
                                               ""`

                            v2.0 14th March 1997
                
                        Program and documentation by
                
                                 Cy Booker
                              86 Church View
                                  BR8 8JW
                                   U.K.
                
                    Internet: bc@cheepnis.demon.co.uk

              Musical entertainment provided by Frank Zappa






































 ============================================================ BasCompress ==== 




     [1]        Overview  . . . . . . . . . . . . . . . . . . . . .  1
     [1.1]      Disclaimer  . . . . . . . . . . . . . . . . . . . .  1
     [1.2]      Synopsis  . . . . . . . . . . . . . . . . . . . . .  1
     [1.3]      Features  . . . . . . . . . . . . . . . . . . . . .  2
     [1.4]      Documentation . . . . . . . . . . . . . . . . . . .  3
     [1.5]      Compressing your first file . . . . . . . . . . . .  3
     [1.6]      Example speed . . . . . . . . . . . . . . . . . . .  3
     [1.7]      Example compression . . . . . . . . . . . . . . . .  4
     [2]        BasCompress . . . . . . . . . . . . . . . . . . . .  5
     [2.1]      Overview  . . . . . . . . . . . . . . . . . . . . .  5
     [2.2]      Jargon  . . . . . . . . . . . . . . . . . . . . . .  5
     [2.3]      Basic . . . . . . . . . . . . . . . . . . . . . . .  5
     [2.4]      Numbers . . . . . . . . . . . . . . . . . . . . . .  5
     [2.5]      SWI's . . . . . . . . . . . . . . . . . . . . . . .  6
     [2.6]      Star commands . . . . . . . . . . . . . . . . . . .  6
     [2.7]      Assembler . . . . . . . . . . . . . . . . . . . . .  7
     [2.8]      Routines  . . . . . . . . . . . . . . . . . . . . .  7
     [2.8.1]    Main program  . . . . . . . . . . . . . . . . . . .  7
     [2.8.2]    Start and end of a routine  . . . . . . . . . . . .  8
     [2.8.3]    Routine end detection . . . . . . . . . . . . . . .  8
     [2.8.4]    END and ERROR . . . . . . . . . . . . . . . . . . .  9
     [2.8.5]    LOCAL ERROR . . . . . . . . . . . . . . . . . . . .  9
     [2.9]      Multi-line structures . . . . . . . . . . . . . . .  9
     [2.10]     Libraries . . . . . . . . . . . . . . . . . . . . . 10
     [2.10.1]   Multiply-defined routines in libraries  . . . . . . 11
     [2.11]     Label reduction . . . . . . . . . . . . . . . . . . 11
     [2.12]     Line numbers  . . . . . . . . . . . . . . . . . . . 12
     [2.12.1]   Output line numbers . . . . . . . . . . . . . . . . 12
     [2.13]     Multi-line output . . . . . . . . . . . . . . . . . 13
     [2.14]     DATA  . . . . . . . . . . . . . . . . . . . . . . . 13
     [2.15]     Re-compressing  . . . . . . . . . . . . . . . . . . 13
     [2.16]     Constant variables  . . . . . . . . . . . . . . . . 14
     [2.16.1]   Caveat  . . . . . . . . . . . . . . . . . . . . . . 15
     [2.17]     ASC compression . . . . . . . . . . . . . . . . . . 15
     [2.18]     Overlays  . . . . . . . . . . . . . . . . . . . . . 16
     [2.18.1]   Overlay specification . . . . . . . . . . . . . . . 16
     [2.18.2]   Inline comments . . . . . . . . . . . . . . . . . . 16
     [2.18.3]   Example of overlays . . . . . . . . . . . . . . . . 17
     [2.18.4]   OVERLAYs and re-compressing . . . . . . . . . . . . 17
     [2.19]     NEXT compression  . . . . . . . . . . . . . . . . . 17
     [2.20]     Keeping initial REM statements  . . . . . . . . . . 18
     [2.21]     TOP handling  . . . . . . . . . . . . . . . . . . . 18
     [2.22]     Output type . . . . . . . . . . . . . . . . . . . . 19
     [2.22.1]   Squeezed output . . . . . . . . . . . . . . . . . . 19
     [2.22.2]   Command line parameters . . . . . . . . . . . . . . 19
     [3]        Cross-referencing . . . . . . . . . . . . . . . . . 20
     [3.1]      Overview  . . . . . . . . . . . . . . . . . . . . . 20
     [3.1.1]    What's cross-referenced . . . . . . . . . . . . . . 20
     [3.1.2]    What's output . . . . . . . . . . . . . . . . . . . 20
     [3.1.3]    Messages  . . . . . . . . . . . . . . . . . . . . . 20
     [3.2]      Level of detail . . . . . . . . . . . . . . . . . . 21
     [3.2.1]    Routine definition  . . . . . . . . . . . . . . . . 21
     [3.2.2]    Routine calls . . . . . . . . . . . . . . . . . . . 21
     [3.2.3]    Routine called by . . . . . . . . . . . . . . . . . 22





 ============================================================ BasCompress ==== 




     [3.2.4]    Variable declaration  . . . . . . . . . . . . . . . 22
     [3.2.5]    Variable assignment . . . . . . . . . . . . . . . . 22
     [3.2.6]    Variable reference  . . . . . . . . . . . . . . . . 22
     [3.3]      Order . . . . . . . . . . . . . . . . . . . . . . . 23
     [4]        The front end . . . . . . . . . . . . . . . . . . . 24
     [4.1]      Installation  . . . . . . . . . . . . . . . . . . . 24
     [4.1.1]    Installing throwback  . . . . . . . . . . . . . . . 24
     [4.2]      Starting  . . . . . . . . . . . . . . . . . . . . . 24
     [4.3]      Overview  . . . . . . . . . . . . . . . . . . . . . 25
     [4.3.1]    Icon bar icon . . . . . . . . . . . . . . . . . . . 25
     [4.4]      Control window  . . . . . . . . . . . . . . . . . . 25
     [4.5]      Main menu . . . . . . . . . . . . . . . . . . . . . 26
     [4.6]      Input . . . . . . . . . . . . . . . . . . . . . . . 26
     [4.7]      Output  . . . . . . . . . . . . . . . . . . . . . . 27
     [4.8]      Log . . . . . . . . . . . . . . . . . . . . . . . . 29
     [4.9]      Special files . . . . . . . . . . . . . . . . . . . 30
     [4.10]     Cross-reference . . . . . . . . . . . . . . . . . . 31
     [4.11]     Choices Dialogue Box  . . . . . . . . . . . . . . . 32
     [5.1]      Invoking  . . . . . . . . . . . . . . . . . . . . . 35
     [5.2]      Installing  . . . . . . . . . . . . . . . . . . . . 35
     [5.3]      Environment variables . . . . . . . . . . . . . . . 36
     [5.3.1]    DDEUtils and long command lines . . . . . . . . . . 36
     [5.4]      The CLI parameters  . . . . . . . . . . . . . . . . 37
     [5.4.1]    Input . . . . . . . . . . . . . . . . . . . . . . . 37
     [5.4.2]    Output  . . . . . . . . . . . . . . . . . . . . . . 38
     [5.4.2.1]  Output listing  . . . . . . . . . . . . . . . . . . 38
     [5.4.3]    Log . . . . . . . . . . . . . . . . . . . . . . . . 39
     [5.4.4]    Special . . . . . . . . . . . . . . . . . . . . . . 39
     [5.4.5]    Cross-reference . . . . . . . . . . . . . . . . . . 39
     [5.4.5.1]  What gets cross-referenced  . . . . . . . . . . . . 39
     [5.4.5.2]  How much cross-referencing to be done . . . . . . . 40
     [5.4.5.3]  Order of cross-referencing  . . . . . . . . . . . . 40
     [5.5]      Error handling  . . . . . . . . . . . . . . . . . . 40
     [5.6]      Escape handling . . . . . . . . . . . . . . . . . . 41
     [5.7]      Hourglass . . . . . . . . . . . . . . . . . . . . . 41
     [6]        Special files . . . . . . . . . . . . . . . . . . . 42
     [6.1]      Why need special files? . . . . . . . . . . . . . . 42
     [6.2]      The Special file  . . . . . . . . . . . . . . . . . 42
     [6.3]      Format of a Special file  . . . . . . . . . . . . . 43
     [6.3.1]    Defining routines . . . . . . . . . . . . . . . . . 43
     [6.3.2]    Defining globals  . . . . . . . . . . . . . . . . . 43
     [6.3.3]    Labels  . . . . . . . . . . . . . . . . . . . . . . 44
     [6.3.3.1]  Verbatim  . . . . . . . . . . . . . . . . . . . . . 44
     [6.3.3.2]  Comma separated . . . . . . . . . . . . . . . . . . 45
     [6.3.3.3]  Full pathname . . . . . . . . . . . . . . . . . . . 45
     [6.3.3.4]  Wimp menu . . . . . . . . . . . . . . . . . . . . . 45
     [6.3.4]    Variables as regular expressions  . . . . . . . . . 46
     [6.3.4.1]  Example patterns  . . . . . . . . . . . . . . . . . 46
     [6.3.4.2]  Limitations . . . . . . . . . . . . . . . . . . . . 47
     [6.3.5]    Libraries . . . . . . . . . . . . . . . . . . . . . 47
     [6.3.6]    Overlays  . . . . . . . . . . . . . . . . . . . . . 48
     [6.3.7]    Include files . . . . . . . . . . . . . . . . . . . 48
     [6.4]      Limitations . . . . . . . . . . . . . . . . . . . . 48
     [7]        Errors  . . . . . . . . . . . . . . . . . . . . . . 49





 ============================================================ BasCompress ==== 




     [7.1]      Overview  . . . . . . . . . . . . . . . . . . . . . 49
     [7.2]      Warnings  . . . . . . . . . . . . . . . . . . . . . 49
     [7.3]      Errors  . . . . . . . . . . . . . . . . . . . . . . 54
     [7.4]      Run-time errors . . . . . . . . . . . . . . . . . . 59
     [7.4.1]    Unknown or missing variable . . . . . . . . . . . . 59
     [7.4.2]    No such function/procedure  . . . . . . . . . . . . 59
     [7.4.3]    Missing ENDIF . . . . . . . . . . . . . . . . . . . 59
     [7.4.4]    Invalid RETURN actual parameter . . . . . . . . . . 60
     [7.4.5]    Syntax error  . . . . . . . . . . . . . . . . . . . 60
     [7.4.6]    Logical errors  . . . . . . . . . . . . . . . . . . 60
     [7.5]      Internal errors . . . . . . . . . . . . . . . . . . 61
     [8]        Loose ends  . . . . . . . . . . . . . . . . . . . . 62
     [8.1]      Memory usage  . . . . . . . . . . . . . . . . . . . 62
     [8.2]      Missing THEN  . . . . . . . . . . . . . . . . . . . 63
     [8.3]      Cross-reference . . . . . . . . . . . . . . . . . . 64
     [8.4]      Statistics  . . . . . . . . . . . . . . . . . . . . 64
     [8.5]      Uncompressed output . . . . . . . . . . . . . . . . 64
     [8.6]      Label reduction . . . . . . . . . . . . . . . . . . 65
     [8.7]      Executable  . . . . . . . . . . . . . . . . . . . . 65
     [A]        Messages  . . . . . . . . . . . . . . . . . . . . . 66
     [A.1]      Internationalism united . . . . . . . . . . . . . . 66
     [A.2]      Format  . . . . . . . . . . . . . . . . . . . . . . 66
     [B]        Regular expressions . . . . . . . . . . . . . . . . 67
     [B.1]      Definition  . . . . . . . . . . . . . . . . . . . . 67



































 ============================================================ BasCompress ====



 [1] Overview
     
     
 [1.1] Disclaimer
     
     This program is supplied "as is".  No warranty, express or implied,
     of the  merchantability of this program or its fitness for any
     particular purpose is given.  In no circumstances shall the author,
     or any provider or distributor of this program, be liable for any
     damage, loss of profits, or any indirect or consequential loss
     arising out of the use of this program.
     
     
 [1.2] Synopsis
     
     BasCompress takes as input a tokenised basic file, analyses it on a
     routine-by-routine basis, and outputs a cross-reference and a
     compressed tokenised basic file.
     
     (It was written because none of the currently available Basic
     squashers handled the side effects of EVAL, removed unused routines,
     or discarded the junk inbetween routines, and they were all far too
     slow).
     
     It consists of two programs, a Wimp-based front end, and a CLI-based
     back end.  The former is ideal for occasional use, while the later is
     better for scripts, make files, etc..































                                  Page   1

 ============================================================ BasCompress ====



 [1.3] Features
     
     The main features of BasCompress can be summarised as follows:

         o   Checks all multi-line IFs have a matching ENDIF
         o   Checks all CASE's have a matching ENDCASE
         o   Checks all WHILE's have a matching ENDWHILE
         o   Checks the ellipsis/quotes/brackets on each statement
         o   It doesn't balk at the use of line numbers (too much)
         o   Loads in explicit LIBRARY files
         o   Checks every routine exits cleanly
         o   Checks for multiply-defined routines
         o   Produces a full cross-reference on all variables and
             routines, with four levels of detail, and user-definable
             ordering
         o   Variable/routine name reduction, targeting the most used to
             be the shortest
         o   Remove all redundant spaces and REMarks
         o   Remove all between-routine junk
         o   Concatenation of output lines
         o   Remove unused code
         o   Reduces numbers to their shortest form
         o   Converts SYS and SWI strings to numbers
         o   Converts ASC("s") to the equivalent number
         o   Compresses/removes constant variables
         o   Handles DIM x!24 32
         o   Optional "special" file to handle EVALuated variables and
             functions, and implicitly loaded library files
         o   "special" file allows variables to be defined as regular
             expressions
         o   It is fast
     
     In other words it does all you would expect, a bit more, and all at a
     very respectable speed.
     
     All those syntax checks may seem superfluous until you realise that
     most error handling code isn't always as fully debugged as it should
     be.




















                                  Page   2

 ============================================================ BasCompress ====



 [1.4] Documentation
     
     This document is split into several sections.  First a full
     description of exactly what this program does to, and expects of, the
     input.  This is followed by S3, a chapter on the powerful cross-
     referencing available.  Not until S4 is the program itself described,
     the Wimp front end application.  The back end application, accessible
     from the CLI is S5.  Special files, their format and use are detailed
     in S6.  S7 is what this author wishes every program documentation
     had, a complete list of errors and reasons why they occurred, and
     more importantly --- some hints on how to get rid of them.  Finally,
     S8 contains miscellanea, the junk that doesn't categorise too easily.
     
     
 [1.5] Compressing your first file
     
     Run the application.  This will install the Wimp front end onto the
     icon bar icon and open the control window to the center of the screen.
     
     First of all drag the Log file icon to a directory display (not
     another application, sorry).  This file will contain information
     about the actions of the compression process.  Now drag a Basic file
     onto the control window, to compress it.
     
     With the default options this Basic file will be analysed, the log
     file created and then automatically loaded into your resident text
     editor.  If this is Edit, then don't close the Log window for now.
     
     Even if the Basic file was analysed without error, no output file was
     produced because none was defined.  Just drag the output file icon
     from the control window onto a directory display and start again.
     
     Now, because Edit still had a view of the Log file, this was
     automatically updated, using the current window size.  This gives an
     extremely usable environment!
     
     Voila, a compressed basic file has been produced.
     
     If the log file reports any EVAL or DATA statements were found, it is
     possible that the program may not run.  See the chapter on Special
     files for a way to handle this.  (The quick way is to disable all
     variable and routine label reduction).
     
     Now read S2.
     
     
 [1.6] Example speed
     
     It takes BasCompress less than 20s to compress itself.  This needs 4
     special files, contains 40-odd source files (including libraries)
     totalling just over 450K, and compresses it down to 100K.  And all
     this on an Arm2 off of the standard 440 hard-disc, with all the I/O
     overhead that that involves.





                                  Page   3

 ============================================================ BasCompress ====



 [1.7] Example compression
     
     Here's how well BasCompress handles compressing an early version of
     the Wimp front end application:
     
             192742  Total input size
             29659   Maximum compression
             29706   No decimal number analysis
             31129   No SWI name analysis
             35103   No concatenation of output lines
             47421   No removal of unused code
             51950   No reduction of labels
     
     The later ones are not accumulative, the non-reduction of labels
     (only) really does add on 57% to the output program size!











































                                  Page   4

 ============================================================ BasCompress ====



 [2] BasCompress
     
     
 [2.1] Overview
     
     This chapter concerns itself with Basic, and what BasCompress expects
     (and does) to it.
     
     
 [2.2] Jargon
     
     The following terms will be used quite frequently, so I'll explain
     what is meant by them:
     
             routine         a procedure or function
             variable        an (integer | real | string)[array]
             label           the name of a routine or variable
             name            a label with its (pre | post)fix
     
     E.g. the following table might help
     
             name            label
             PROC_Zappa      _Zappa
             Frank%          Frank
             Cy$()           Cy
     
     
 [2.3] Basic
     
     BasCompress will only except fully tokenised basic files, it does not
     accept text files.  This program only knows about the tokens present
     in Basic V, v1.04.  The behaviour of this program on Basic files on a
     version greater than this is undefined.
     
     Only one Basic file is parsed (but see S2.10).
     
     
 [2.4] Numbers
     
     BasCompress will interpret all numbers and try to output them in as
     compact a form as possible.  This is most effective on long binary
     numbers, but can shorten many large decimal values as well.
     
     The analysis and output of (decimal) numbers requires the floating
     point emulator.  For this reason this can be turned off, just in case
     you are very short on memory.
     
     Analysis of hexadecimal and binary numbers is always done, as this
     does not require any floating point math.

     Note that BasCompress tries to output numbers in the hexadecimal
     format whenever possible.  One artifact of this is assembler source
     where the registers get converted to &e, etc.





                                  Page   5

 ============================================================ BasCompress ====



 [2.5] SWI's
     
     Acorn's interface to the operating system, the SWI is an elegant self-
     documenting system.  However, for interpreted languages like Basic,
     the translation of a SWI name to a SWI number is relatively time-
     consuming.
     
     BasCompress will try to do this translation, leaving just a number.
     This provides both large space and large execution savings,
     particularly for Wimp programs that use SWI's during screen redraw
     (that's all of them!)
     
     In order for BasCompress to translate the SWI name, it must be a
     simple constant string expression.  If it isn't, or it can't
     translate it, then it is left as it is --- thus providing an (almost)
     fool-proof conversion.  (A possible case of a complex string constant
     would be SYS "X"+ "OS_ReadC").
     
     Both SYS calls (in Basic) and SWI calls (in assembler) are converted.
     
     Note also that the any modules used by the program should be resident
     at the time of compression, otherwise the SWI's will be unknown and
     thus BasCompress will leave them as strings.  This is an easy mistake
     to make, and results in slower and longer compacted files being
     produced.  This cases ud detected, and generates a suitable warning.
     
     
 [2.6] Star commands
     
     A backward compatibility feature of Basic V is it's allowance of
     *Commands anywhere in Basic.  Modern programs should really put this
     in an OSCLI("..."), or better yet a SYS "OS_CLI", "...".
     
     However, since this is allowed, some programmers use it to introduce
     comments in programs by using the *| comment construct.  BasCompress
     will remove these lines completely.  It will also remove all
     unnecessary *'s and spaces.
     
     If this results in a complete removal of the statement, BasCompress
     may produce incorrect code if (and only if) this *command was just
     after an (explicit) THEN.  Since this is extremely bad programming
     practised, this author felt the benefits gained far outweigh the
     possible side-effects.















                                  Page   6

 ============================================================ BasCompress ====



 [2.7] Assembler
     
     BasCompress fully understands and compacts assembler statements.  As
     part of this process, BasCompress also checks that the square bracket
     "[]" count on each statement is valid --- which may be useful for
     detecting bugs in conditionally assembled code.
     
     All R0..R15 registers get translated to 0..15, this saves a lot of
     space.  Also the integer EQU's can be renamed to DC's.
     
     Note that the single space left after some mnemonics is necessary,
     without it the Basic assembler will refuse to work.

     BasCompress also recognises (and compresses to) the `&' derivative
     of DCW and the `=' derivative of EQUS and DCB.
     
     
 [2.8] Routines
     
     It is important to understand that BasCompress treats a program as a
     group of routines.  Because of this it can remove any junk inbetween
     routines, i.e. comments not explicitly starting with a REM, that
     other squashers leave behind (and even try to analyse --- producing
     many, many errors).
     
     Note that this behaviour, removing junk between routines, can be
     disabled in cases where BasCompress is unable to detect the end of
     a routine.  See below for details of why BasCompress can get
     confused.

     Because a record is kept of what happens inside a routine, it is
     possible to conclude that a routine isn't actually needed in the
     output file --- and so none of the routines that it calls are needed
     that bit less as well.  Thus BasCompress can remove ALL unused
     routines from the output file.  This is a very powerful feature.


 [2.8.1] Main program
     
     BasicV does not provide a clearly defined method for distinguishing
     the end of the main program, and the start of the subroutines.
     BasCompress treats everything from the start of the first file to the
     first routine definition (DEF PROC or DEF FN) to be the main
     program.  This isn't ideal, as many main programs consists of an
     infinite loop followed by junk --- however there is no easy way of
     recognising the true end of the main program, so you have to live
     with it as it is.
     
     If you wish to compress library files separately, i.e. files that do
     not contain a main routine at the start of a file, then this is
     easily accommodated.  There is a menu item
     `Input->Process as a library file' which toggles this feature.






                                  Page   7

 ============================================================ BasCompress ====



 [2.8.2] Start and end of a routine
     
     The start of a Basic routine is very easily detected, it is a line
     that starts with DEF FN or DEF PROC.
     
     However, the end of a routine isn't so easy to detect.  In the ideal
     world, every routine will have one, and only one exit that is a
     simple ENDPROC, or = <expr> on a line of its' own.  However, we all
     live in the real world, and things are more complicated than that.
     
     
 [2.8.3] Routine end detection
     
     For example, consider the following function:
     
             DEF FNmin(a, b)
               IF a>b THEN =b ELSE =a
     
     Now, the only way for BasCompress to recognise this construct is if
     it kept track of all branches of a conditional.  This would involve a
     major upgrade, and would make the program just a code-generation pass
     away from a true compiler.
     
     BasCompress has two separate ways of dealing with this, a `smart' way
     and a `dumb' way.   The dumb method is to ignore routine ends all
     together.  The smart method is to ignore exits from a routine that
     occur:

                o       on the same line as an IF
                o       an the same line as an ON ERROR
                o       inside a multi-line construct

     By default BasCompress is `smart'.  To disable this use the CLI
     switch -Dumb, or tick menu item
     `Input->Ignore exits from a routine (`dumb')'.

     Each method has its' own merits.  The smart method means that
     because BasCompress knows when the routine has ended, it can skip any
     inter-routine junk.  The dumb method is extremely useful for coping
     with legacy code that confuses BasCompress `smart' algorithms.

     When in `smart' mode BasCompress will think that the next line, in
     the above example will be inside the function min.  This usually
     results in a cascade of warning/error messages being generated.  The
     only long-time cure for this is to amend the offending function.  The
     simplest way is to just put a dummy terminator in, e.g.
     
             DEF FNmin(a, b)
               IF a>b THEN =b ELSE =a
             = 0








                                  Page   8

 ============================================================ BasCompress ====



     Better yet, would be to code it "properly":
     
             DEF FNmin(a, b)
               IF a>b THEN a=b
             = a
     
     There is also the problem of programs that prematurely terminate
     routines inside, say, a case structure.  This happens quite often,
     because it makes for much shorter code, and so BasCompress recognises
     this, see S2.9.
     
     
 [2.8.4] END and ERROR
     
     Currently BasCompress does not recognise the fact that a routine may
     end with the END command, nor an unconditional ERROR.  Since these
     are examples of bad-programming anyway, these are easily worked
     around by just adding a redundant ENDPROC or =0 after the last line.
     
     
 [2.8.5] LOCAL ERROR
     
     BasCompress fully recognises local error handlers, and will force the
     next input line to start a new output line accordingly.
     
     
 [2.9] Multi-line structures
     
     When in `smart' mode (see S2.8.3) BasCompress keeps track of the
     current nesting level of all multi-line structures:
     
             o       CASE ... ENDCASE
             o       IF THEN ... ENDIF
             o       REPEAT ... UNTIL
             o       WHILE ... ENDWHILE
     
     It does this primarily to detect conditional exiting from a routine.
     For example, if an ENDPROC or = <expr> is detected inside such a
     structure, then BasCompress knows it isn't the true end of the
     routine, and so will ignore it.  A very useful side-effect of this is
     that BasCompress detects programming errors in the use of these
     constructs, errors that the run time Basic interpreter allows
     through.  These very often are genuine program mistakes, usually
     inside error-handling code that is not fully debugged.
     
     However, there are two caveats to this.  Firstly, in order for
     BasCompress to do this it must assume that the start of any multi-
     line structure is not inside a one-line IF construct.  Unfortunately,
     some programmers put a quick WHILE ... ENDWHILE loop in a one-line
     IF.  BasCompress does not handle this correctly and this line needs
     to be split into a true multi-line IF.







                                  Page   9

 ============================================================ BasCompress ====



     Secondly, and just as less seriously, BasicV is rather lax in it's
     attitude towards multi-line structures.  For example:
     
             REPEAT
               i += 1
               CASE x(i) OF
               WHEN 1:
                 IF do_it THEN
                   UNTIL FALSE:ENDPROC
                 ENDIF
                 ...
               ...
               ENDCASE
             UNTIL i>max_i
     
     Here, BasicV will rather carelessly execute the UNTIL, even though it
     isn't at the same nesting level as the matching REPEAT.  BasCompress
     is not so lenient and it will refuse point blank to handle such
     code.  It is another example of bad programming being used, and
     should be re-coded in another way.

     If you need to compress such code then put BasCompress in it's `dumb'
     mode.

     
     
 [2.10] Libraries
     
     The use of the LIBRARY call is recognised.  It causes the appropriate
     file to be appended to the queue of files to be parsed, and the
     entire LIBRARY statement to be removed from the output.
     
     For this to work, BasCompress assumes a simple string constant
     follows the LIBRARY.  If this is not the case and it uses a
     variable/routine parameter then you will need to set up a Special
     file.  This will tell BasCompress what to expect the variable to be
     so it can load the correct file.  Please refer to the S6.
     
     All LIBRARY files are only ever scanned once, even if it is included
     many times.
     
     Of course, the loading of libraries will mean that the current
     directory and/or some system variables (e.g. App$Dir) may need to be
     set up --- otherwise BasCompress will not be able to locate the 
     library file.













                                  Page  10

 ============================================================ BasCompress ====



 [2.10.1] Multiply-defined routines in libraries
     
     Note that the loading of libraries, as performed by BasCompress is
     not exactly the same as the order that BasicV would have loaded them
     in.  This could only cause a problem if multiply-defined routines
     exist, and further more these multiple definitions are themselves in
     library files, not the main file.  If this situation does arise, then
     the kludge is: include the library containing the preferred
     definition twice, once before and once after the LIBRARY containing
     the unwanted definition.  This will work because BasCompress will use
     the first loaded, and the uncompressed program would use the second!
     
     
 [2.11] Label reduction
     
     A lot of the time that BasicV takes to interpret a program is spent
     looking up variable names.  BasCompress will attempt to reduce the
     long labels down to size, often producing dramatic space and speed
     improvements.  The algorithm used ensures that the most used
     variables are chosen for the shortest variable names, and the names
     themselves are chosen so as to spread evenly across the name-space.
     
     Did you note the word attempt in the above paragraph?  This is
     because basic is an interpreted language and provides the powerful
     commands EVAL and DATA, allowing expressions to be evaluated in the
     current context.  For instance EVAL("zappa%") would yield the value
     of the variable zappa%.  But, if BasCompress had reduced this
     variable down to, say, A% in the rest of the program (because  it
     analysed the program in a different context) then what happens at run-
     time is you get a variable not found error.
     
     There are two solutions to this very common problem.  The first is to
     disable label reduction on all variables of the type that are used in
     EVAL or DATA statements.  This is extremely wasteful, but the only
     option available in other squashers.  With BasCompress there is a
     much more elegant solution --- you can specify all the labels that
     must not be reduced.  Further more, these variables can be implied
     from the parameters passed to a routine!
     
     For example, many Wimp-based programs will have a menu-construction
     suite of routines.  These will be passed a string that describes the
     menu.  Inside this string will be references to variables that at run-
     time will point to more information (sub-menus or windows usually).
     With BasCompress, you can get it to analyse all these strings,
     extract the variables, and then reduce all other variables apart from
     those.  This is a very powerful feature.  See the S6 for more info.
     
     Note that BasCompress goes to the trouble of making sure that it
     never produces one of the "built-in" register labels used by the
     assembler (R0-R15, pc).  On other basic squashers this can lead to
     VERY obscure bugs.







                                  Page  11

 ============================================================ BasCompress ====



     Also worth mentioning is that any labels accessed inside deleted
     routines are automatically removed from the list of labels to
     reduce.  This produces better results than just reducing all labels
     found.
     
     BasCompress can handle any number of labels, well as many as could
     fit into available memory!

     
 [2.12] Line numbers
     
     Normally line numbers are an anathema but there does exist a valid
     reason for using them in BasicV, and so line number handling has been
     included in BasCompress.  The reason why line numbers may be needed
     is if a program claims more memory though the use of the END=<expr>
     construct.  This has the unfortunate side-effect of removing all
     routine level info, so you have to GOTO the main program loop).
     
     Obviously, line numbers found in any library files are faulted as
     there is no valid reason for them being there.
     
     Note that in short programs it is just possible that there will be a
     GOTO to a destination outside both the main program and all other
     routines.  Currently BasCompress does not handle this (rather rare)
     case.  As a kludge, surround the offending code in a dummy routine.
     
     
 [2.12.1] Output line numbers
     
     If no line numbers were found then line numbering is easy.  For
     single-file programs the line numbers keep to their original values,
     even if multi-line compaction is enabled.  For multi-file programs
     the output file starts from 1 and increases in steps of 1.
     
     If line numbers were found then the line numbers in the original
     program are used for the original program part, and thereafter line
     numbers increment in steps of one for any further libraries.
     
     Unfortunately BasicV only allows line numbers up to around 65000
     odd.  This could possibly be a problem if the original program has
     line numbers up to, say, 64000, and includes quite a few library
     files.  This is one of the few possible errors that are not checked
     for, as the possibility of it occurring are just so remote.















                                  Page  12

 ============================================================ BasCompress ====



 [2.13] Multi-line output
     
     Normally as many statements are compressed onto one output line as
     will fit.  This produces the smallest files as the overhead that
     Basic imposes on each line is reduced by quite a bit.
     
     However, it can produce code that runs slower.  This is because it
     appears BasicV only notes the statement number of an implicit jump
     (e.g. after a FOR, WHILE, or REPEAT).  And so if this is on statement
     56 of a line, say, then it has to scan all along the line to find
     where to continue execution.  This situation may be recognised in a
     future upgrade by forcing the statement after one of these cases to
     start on a new line.
     
     
 [2.14] DATA
     
     BasCompress recognises the possibility that DATA may not reside
     inside a routine.  All "unlinked" DATA statements will still be
     included in the output file, but only if there is some code left that
     will READ it.
     
     Please note that variables used as DATA will require the use of
     Special files.
     
     
 [2.15] Re-compressing
     
     Although at first sight the notion of compressing an already
     compressed file may seem a waste of time, in actual fact it is not.
     
     This is because BasCompress compresses a whole line at a time, and
     then merges together two or more lines.  This isn't done quite as
     optimally as possible, and sometimes extra colons are inserted.
     
     If the output is fed back into BasCompress these extra colons will be
     removed, as it will be obvious that they are truly redundant.
     
     If constant variable substitution is enabled (S2.16) then quite often
     a second pass reveals more constant variables!
     
     The best way to double-compress is to first compress with reduction
     of function and procedure names only (thus ensuring `special'
     routines only parsed once), and then a second time with full
     reduction of variable names.

     If you are using BasCompress to generate a distributable file (for
     instance your latest commercial/shareware executable) then you
     should give serious consideration to using this re-compression
     technique.  It only takes a little while to set up a script (Obey)
     file to perform this at a (double) click of a file.







                                  Page  13

 ============================================================ BasCompress ====



 [2.16] Constant variables
     
     New to version 1.50 of BasCompress is the handling of `constant'
     variables.  By this it is meant a string/real/integer variable (not
     an array) that is:
     
             o       only ever assigned once
             o       never declared (ie LOCAL, or routine parameter)
             o       the assignment is `simple'
     
     By simple it is meant very simple!  Currently the only types that are
     recognised are:
     
             o       integer number, base 10
             o       real number
             o       hexadecimal number
             o       string
     
     Although nowhere near the full types of basic expressions, the above
     list does cover the most common case in libraries where one generally
     has a lot of variables used to give `names' to constants.
     
     When BasCompress finds such a variable it does two things:
     
             o       Remove the definition
             o       Replace all occurrences of the variable name with its'
                     definition.
     
     This has the advantage that it leaves more room in the symbol table
     for variables that are actually used as variables.  It should also
     speed up the programs' execution.
     
     Note that variables that have been compressed is this way are listed
     as `unused' in the log file.
     
     If you have enabled `Process as a library' then BasCompress will
     silently disable constant variable analysis.

     Note that for this feature to work BasCompress needs to recognise
     all types of variable assignment, including SWAP, MOUSE TO, and
     RETURN parameters in routines.  This used to be a problem, but
     BasCompress has been updated to account for all of these cases.
















                                  Page  14

 ============================================================ BasCompress ====



 [2.16.1] Caveat

     There is one important caveat with constant variable handling.  This
     occurs if the definition of the constant variable is longer than the
     variable name itself.  This most often happens with long string
     constants, although can happen with some integer values.

     The problem occurs when BasCompress comes to `remove' the variable
     and substitute the longer definition.  In rare circumstances (most
     noticably on already compressed source) this can cause a line longer
     than 256 bytes (a BasicV limitation) to be generated.

     The solution to such cases is to defined the variable in the special
     file (see S6.)  See also S3.2.5.


 [2.17] ASC compression
     
     In many programs that deal with text you will see expressions of the
     form:
     
             IF (c%>=ASC("0") AND c%<=ASC("9")) THEN
              ...
             ENDIF
     
     This looks very nice, but executes relatively slowly.  BasCompress
     now understands constructs of this form and will compress this down
     to:
     
             IF(A%>=48ANDA%<=57) THEN
              ...
             ENDIF
     
     Which is both textually shorter and is much faster to execute.
     
     To be more exact BasCompress understands the following:
     
             ASC [(]* string [)]*
     
     where spaces are swallowed and the string is a Basic format string.
     Also the brackets must match!

















                                  Page  15

 ============================================================ BasCompress ====



 [2.18] Overlays

     Overlays are a way of `dynamically' loading groups of orthogonal
     routines that BASIC supports.  The main advantage is that their use
     can, with careful program design, significantly reduce the memory
     requirements of an application.
     
     One oft cited example is in a `document' handler, you only ever
     need to load, save, or print at one time.  Therefore these
     separate functions (which could be quite complex) could each be
     handled in different source files, and all three specified in an
     OVERLAY command.  The net result is that the application will
     only require as much memory as the largest overlay, rather than
     the total size of all overlays.
     

 [2.18.1] Overlay specification

     The OVERLAY command is not understood by BasCompress.  However,
     overlays are supported, through the use of special files (see S6),
     or through inline comments (see below).
     
     When specifying an overlay file, if no directory separator is given
     (`.') then the directory of the input file is used.  This is usually
     sufficient, unless you store overlays in a subdirectory.

     When output, each overlay file is output to the same directory as
     the main program (and all its' libraries).  There is no support for
     placing the overlays in sub-directories of the output directory.

     Note that this means you MUST ensure that the output directory is
     different from the input directory, otherwise the overlay files
     will become (silently) overwritten with their compressed version.

     For every overlay file an output file is always generated, even if
     BasCompress has removed all the routines inside it.


 [2.18.2] Inline comments

     BasCompress `understands' comments of the form:
     
                REM BasCompress:Overlay: <overlay file>

     Note that case IS significant.  This tells BasCompress to parse the
     specified file as an overlay, always.  There is no condition
     attached to this (such as only parsing the overlay if this routine
     is actually used).

     If you require more control of which overlay files are parsed you
     will need to use a special file.







                                  Page  16

 ============================================================ BasCompress ====



 [2.18.3] Example of overlays

     Imagine an application has overlay files called "Load", "Save", and
     "Print".  These are all in the `application' directory <App$Dir>.

         REM >App
         DIM lib$(3)
         lib$() = "<App$Dir>.Load", "<App$Dir>.Save", "<App$Dir>.Print"
         OVERLAY lib$()
         REM BasCompress:Overlay: Load
         REM BasCompress:Overlay: SCSI::HardDrive4.$.AppSource.Save
         REM BasCompress:Overlay: Print
         ...
         PROC_Load_Document(doc%)
         PROC_Save_Document(doc%)
         PROC_Print_Document(doc%)

     Then, with the system variable App$Dir set up appropriately the
     source and the BasCompress'ed files will execute as expected.


 [2.18.4] OVERLAYs and re-compressing

     If you wish to compress a program that uses overlays more than once
     (see S2.15), and it contains inline comments then you need to take
     care.

     There are two solutions.  One involves the use of an environment
     variable in the inline comment:

                REM BasCompress:OverLay <App$Dir>.overlay

     which needs to change between compressions.  The other depends on
     the comments being in the `main program' (see S2.20).  Here you can
     force BasCompress to keep initial REMs on the first pass, and remove
     them on the second pass!


 [2.19] NEXT compression

     Basic supports a shorthand method of terminating FOR loops, by
     omitting the variable name after the NEXT statement.  While
     developing programs this is of dubious value, as it stops the
     interpreter from spotting possible mismatched FOR/NEXT's.
 
     However, for compressed programs it is a good idea to remove the
     variable, as it (obviously) reduces the program size.  It also
     speeds the program up, as the Basic interpreter no longer has to
     check that the correct variable has been placed after the NEXT.









                                  Page  17

 ============================================================ BasCompress ====



     BasCompress will `swallow' real and integer loop variables.  It will
     also concatenate adjacent NEXT's to use a comma, eg.

                NEXT a%:NEXT b%:PRINT ASC("A")

     will be compressed down to

                NEXT,:PRINT65
 
     This only works if the NEXT's are on the same line, however.  If you
     want as much compression as possible, you should process the file
     twice (see S2.15), as on the second pass most NEXT's will be on the
     same line.


 [2.20] Keeping initial REM statements

     The file that BasCompress is usually the file that gets distributed
     to third parties (ie an applications' !RunImage file).  It would be
     nice if you could incorporate into this some copyright message.
 
     One way to achieve this is to tell BasCompress to retain all 
     `initial' REM statements.  These are comments that are

        o       before the first routine definition
        o       on a line by themselves
        o       begin with REM (not *|, or ;)


 [2.21] TOP handling

     Basic supports a pseudo-variable called `TOP'.  When read, it returns
     the topmost byte of memory.  Unfortunately Basic does not use a token
     to encode this variable, but uses the token for `TO' and the letter
     `P'.
 
     Basic has no problem with this, as it knows when to expect a proper
     `TO' (after a FOR <var>=<expr>, or after a SYS).  Unfortunately
     BasCompress does not know this, and so can not distinguish between a
     true `TOP' and a `TO P' without a space.
 
     This does matter if constant variable deletion is enabled, because
     BasCompress will not `see' the P after the TO and if the P is other-
     wise constant, will be substituted everywhere else.
 
     Unfortunately there is no solution, other than to ensure that your
     source code never contains the sequence `TOP', which can be done by
     ensuring that you have spaces after the TO.  (Note that `TOPizza' is
     OK, as is `TOP%').
 
     As far as BasCompress output is concerned, this is not a problem, as
     the Basic interpreter knows how to handle these cases anyway.






                                  Page  18

 ============================================================ BasCompress ====



 [2.22] Output type

     Ordinarily BasCompress will produce a standard tokenised Basic file.
     However, it is a common requirement to further "protect" the
     program, and this can be done by making the file an "absolute"
     program.

     An "absolute" program consists of some machine code stuck onto the
     front of the tokenised basic.  When executed the code "enters" BBC
     Basic and starts executing the program.

     Thus, for all intents and purposes they are identical --- you can
     double click either from a directory display, and your original
     Basic code will be executed the same.


 [2.22.1] Squeezed output

     Going one stage further in trying to "protect" your code,
     BasCompress now supports squeeze'ing the absolute file.  This
     has the added benefit of making the file smaller on disc, and hence
     quicker to load (especially from a floppy).

     However, the actual program that squeeze's the absolute file is
     copyright Acorn.  But do not despair --- you already own a copy of
     it!

     The squeeze program can be found in your copy of the Patch
     application, in the directory "!Patch.Library".  Copy the "squeeze"
     file in this directory into the directory "$.Library".  (Or
     anywhere in your Run$Path).


 [2.22.2] Command line parameters

     There is a problem with using an absolute program in place of a
     tokenised file --- the command line is different.

     The details are pretty horrible --- it is necessary for the
     machine code stub to `remember' the command line, then invoke
     Basic.  The backend compressor will have inserted a single line
     of basic that picks up this command line (in the system variable
     BasCompress$CLI) and updates the CLI with it.

     Thus by the time the first line of *your* Basic executes, then
     a call to SYS "OS_GetEnv" will return the correct value.

     Note that if the absolute code was envoked with an extended
     command line (ie using DDEUtils) then this will NOT be handled.
     If you require this feature then please contact the author.








                                  Page  19

 ============================================================ BasCompress ====



 [3] Cross-referencing
     
     
 [3.1] Overview
     
     The cross-referencing of a large program can provide many useful
     insights, providing you can organise the output so as not to swamp
     you with "useless" information.  To this end you can control what
     gets include, the level of detail, and the ordering (with many types
     of ordering available).
     
     Note that the cross-referencing of variables and routines is
     completely independent.
     
     
 [3.1.1] What's cross-referenced
     
     The cross-reference contains only the routines and variables that
     will be included in the output file.  Since dead code is usually
     removed, you have to tell BasCompress to keep in all would-be deleted
     stuff if you need a complete cross-reference.
     
     You can also control exactly what types of labels are included.
     Usually you'd keep the default (everything), but sometimes you don't
     care about all the real variables, say, and this is easily catered
     for.
     
     
 [3.1.2] What's output
     
     The result of the cross-referencing is sent to the cross-reference
     file, or the screen if none is specified.  Since this is a lot of
     data, you will almost certainly want to use a file.  The front end
     application has the ability to automatically load this into the
     resident text editor.
     
     
 [3.1.3] Messages
     
     The formatting of the cross-reference is defined using the external
     Messages file.  By altering the following messages you can tailor the
     output of the program dramatically (see appendix A for description of
     format of messages) :-
     
             Name            Show label and its' qualifying string ("%s%s")
             Comma           Separates distinct references (", ")
             SemiColon       Separates similar references ("; ")
     










                                  Page  20

 ============================================================ BasCompress ====



     They are currently set up to produce "one-line-per entry".  However,
     it is possible to change these three so that every distinct reference
     appears on each separate line, vis-a-vis:
     
             Name:           \n\t%s%s
             Comma:          \n\t
             SemiColon:      ,% 
     
     But note, you will probably need to alter all the titles used so that
     they start rather than end with a newline.  (The \t expands to a tab
     character, this is usually better than many spaces, since cross-
     reference files are large enough as it is)
     
     
 [3.2] Level of detail
     
     There are four levels of detail supported by BasCompress:
     
             None            suppresses output, obvious really
             Existence       useful to just list the name of all the
                             labels used
             Global          gives the additional information of a count
                             of the label usage
             Routine         reports only each separate routine where a
                             reference was made, this is probably the most
                             useful option
             Line            details the exact statement for every
                             reference
     
     For the last two, each label has separate lists.  For routines there
     is: defined, calls, called by; and for variables there is: declared,
     assigned, and referenced.
     
     Note that the main program itself is treated internally as a
     procedure, and so appears in the routine cross-reference.
     
     
 [3.2.1] Routine definition
     
     This gives the file and line numbers of the start and end of the
     routine.
     
     
 [3.2.2] Routine calls
     
     Lists the names of the routines called by this routine, and the line
     number of the call.











                                  Page  21

 ============================================================ BasCompress ====



 [3.2.3] Routine called by
     
     Lists the names of the routines that calls this routine, and the line
     number of the call.
     
     If the list is empty then BasCompress knows that this routine is not
     needed in the output program, and so will not include it.
     
     
 [3.2.4] Variable declaration
     
     Where a label was "declared".  By this BasCompress means it is a
     formal parameter of a routine, or explicitly declared as LOCAL.
     
     
 [3.2.5] Variable assignment
     
     When ever a variable appears at the start of a statement.  This
     includes assembler statements.
     Note that BasCompress sometimes thinks variable assignments are
     references.  This happens in the following cases:
     
             o       variable is passed to a routine with RETURN parameters
             o       assignment after a one-line IF that is without a THEN
     
     Here's an example of the later:
     
             IF x<y x=y
     
     Because Bascompress doesn't try to understand the conditional, it
     doesn't know that a new statement has started and so can't categorise
     the second reference to x as an assignment.  See S8.2.
     
     
 [3.2.6] Variable reference
     
     Any other instance of a variable other than the above two is taken to
     be a reference.
     
     BasCompress will not recognise the fact that x += 1 is actually both
     an assignment and a reference.
     
     BasCompress will also fail to recognise that var!0 = 1 only
     references var and does not assign to it.














                                  Page  22

 ============================================================ BasCompress ====



 [3.3] Order
     
     There are many uses you can put to a list of labels, provided you can
     order them in the way you need.  BasCompress allows you to specify as
     many levels of sorting as you would need, with all the types of
     ordering that are relevant to the labels!
     
     You can sort in either direction --- top to bottom, or the more usual
     bottom to top.
     
     These are the following sort types currently supported:
     
             Name            in Ascii order
             Type            for routines: function, procedure
                             for variables: integer, real, string, integer
                             array, real array, string array
             Dictionary      by name, but as it would appear in a
                             dictionary
             Location        the location of the reference
             Usage           for routines: number of times it is called
                             for variables: sum of the assignments and the
                             references
     
     Note the needed for multi-level sorting.  You would normally sort
     labels by name, and type; and references by name, type, and location.
     
     Trying to sort labels by location has no meaning, and will result in
     a seemingly random order.  So it is not possible to list routines in
     the order they were defined in.





























                                  Page  23

 ============================================================ BasCompress ====



 [4] The front end
     
     This describes the Wimp front end application.  This allows the user
     to set up the parameters for the back end program in a friendly way.
     

 [4.1] Installation

     By default the front end enables throwback.  This is a technique
     where a command line utility (eg the BasCompress back end engine)
     can communicate errors to a wimp application, such as SrcEdit, Zap,
     or StrongED.

     This causes the wimp application to display the errors in a window,
     where the user chooses an error/warning and the editor displays the
     appropriate source line, ready for editing.


 [4.1.1] Installing throwback

     For throwback to work, you require a support module called DDEUtils.
     This is an Acorn module that acts between the command line utility
     and the wimp application throwback server.

     Unfortunately, in order to distribute DDEUtils requires a Binary
     Distribution License from Acorn.  Therefore only developers may
     distribute this module.

     Luckily, BasCompress comes with a (partial) functional replacement,
     called DDEUtilsCy.  This supports all of the DDEUtils API, but has
     no functionality for any Prefix code (if you don't understand this
     then it doesn't concern you).  It also requires the use of an Obey
     script to initialise some system variables.

     Because DDEUtilsCy only contains a subset of the real DDEUtils'
     functionality, the !BC.!Run file goes to great lengths to ensure
     that if the user has the real DDEUtils module, then this is used in
     stead of the replacement.


 [4.2] Starting
     
     A standard Archimedes application, just double-click the application
     icon in the directory display to install it onto the icon bar.
     
     For foreign users, see the appendix A describing the Message file.












                                  Page  24

 ============================================================ BasCompress ====



 [4.3] Overview
     
     Because the back end works on, and produces, a number of whole files
     the format of this application is slightly unorthodox.
     
     Basically you use the standard RISC OS method of dragging file icons
     to directory displays (to define the output files), and then drag a
     BASIC file onto the front end to invoke the back end application to
     compress it.  This generates the new log, cross-reference, and output
     files.
     
     Not all of the types of output files need to be generated.  Usually
     there is no need for a cross-reference.  But, you will almost
     certainly want the log file defined, as otherwise you would not know
     what errors occurred, or anything else.
     
     It is almost a pre-requisite to have Edit running alongside this
     front end in order for you to view the log that the back end
     application produces.  The loading of this log will normally be
     automatic.
     
     
 [4.3.1] Icon bar icon
     
     The icon bar icon shows some messages while the back end is active.
     This gives a visual reference to what is going on.
     
     Clicking SELECT on the icon bar icon brings the control window to the
     front of the window stack.
     
     Clicking ADJUST in the icon bar icon re-loads the last input file,
     using the new options.  This is extremely handy for trying out new
     options on a file that generated an error.
     
     
 [4.4] Control window
     
     This is automatically opened to the center of the screen when the
     application starts.  It allows you to quickly set up all the files to
     be used, and as a side effect it gives you the chance to open a menu
     somewhere other than in the bottom right of the screen!.  The left-
     most three icon groups act just like the save as dialogue boxes to be
     found on the menu.
     
     The special file is defined by dragging a Text file onto this
     window.  More special files can be defined by editing the text field,
     appending a comma separated list of file names.











                                  Page  25

 ============================================================ BasCompress ====



 [4.5] Main menu
     
     There is only one menu.
     
     Because the sub-menus are rather on the large side, it is recommended
     that you bring the menu up over the control window.  This was the
     main reason for having a control window, as a convenient anchor for
     the menu.
     
     
 [4.6] Input
     
     This sub-menu defines various parameters affecting BasCompress's
     analysis of the input file.
     
     
  Ignore exits from a routine (`dumb')

     BasCompress has two strategies for detecting the end of a routine, a
     `smart' method (the default) and a `dumb' method.  The smart method
     will keep track of multi-line statements to detect an actual end of
     routine, the dumb method just parses until the next DEF FN/PROC.

     When enabled BasCompress will use the `dumb' method.  See S2.16.


  Allow multiply-defined routines

     It is better to leave this option un-ticked, so that if a routine is
     defined more than once an error is generated.  This is the default.
     
     Ticking this option allows a routine to be defined more than once,
     with only warnings being given.  See S2.10.1.
     

  Force malformed SWI's to generate error

     Malformed SWI's are those that aren't simple strings, e.g. "X"+
     "Wimp_Poll".  With this enabled these generate an error, otherwise
     just a warning.  See S2.5.
     
     This item will be disabled if `Convert SWIs to numbers' item in the
     output sub-menu is turned on.
     
     
  Process as a library file

     This option allows the input file to be treated as a library file.
     This means that no main program is expected, and any undefined
     variables and routines do not generate an error.  Of course, using
     this option is usually pointless without also disabling all label
     reductions.
     
     When turned on this item disables the item `Compress constant
     variables' in the output sub-menu, as it is usually not very useful
     to have both these items enabled!


                                  Page  26

 ============================================================ BasCompress ====



 [4.7] Output
     
     This sub-menu allows you to tailor how much compression is applied to
     the output programs.  Redundant spaces and comments are always
     removed, since there seems little point in using BasCompress without
     doing this.
     
     By default all compression is on.
     
     
  Save as

     This leads to a standard dialogue box, used to define the basic file
     that will be produced if the input is analysed without error.

     Note that currently the only way to determine whether a Basic,
     Absolute, or Squeezed file is produced is from the main control
     window.
     

  Keep initial REMs

     This feature is useful for retaining copyright messages in the
     BasCompressed file.  By `inital' it is meant everything up to the
     first routine definition.  See S2.20.


  Concatenate lines

     Forces as many statements as possible onto each output line.  This is
     usually very desirable as it produces quite substantially shorter
     code, but at the possible loss of a bit of execution speed.  See S2.
     13.
     
     
  Remove unused routines

     Because BasCompress can work out exactly which routines are, and are
     not needed in the final program, then it can remove unused routines.
     This is the default, and there is little point in disabling it, other
     than creating a full cross-reference.
     
     
  Remove constant variables

     BasCompress can recognise `constant' variables, those that are only
     assigned once and have a very simple definition.  This helps to
     reduce symbol table overloading.  See S2.16.
     
     This item will be disabled if `Process as a library file' in the
     Input sub-menu is turned on.







                                  Page  27

 ============================================================ BasCompress ====

     
     
  Remove constant ASC()

     When enabled this feature will recognise constructs of the form
     ASC("string") and ASC"s" and compress them down to the appropriate
     numbers.  See S2.17.


  Remove NEXT variables

     BasCompress supports BasicV's use of unnamed NEXT statement in a
     FOR/NEXT loop.  It can remove any variables it finds after a NEXT
     statement, and cocatenate adjacent NEXT statements.  See S2.19.


  Convert SWIs to numbers

     There doesn't appear to be any reason to disable this.  See S2.5.
     
     When turned off this will cause the following two items to be
     disabled.
     
     
  Parse numbers

     This toggles whether BasCompress will try to reduce a string of
     decimal digits.  Hexadecimal and binary numbers are always
     compressed.  See S2.4.

  List

     This leads to a simple sub-menu where you can specify the screen mode
     to use.  When enabled, as BasCompress produces the output file it
     will switch to that screen mode and scroll the source and output in
     two separate columns.  Although "pretty", it is also pretty useless,
     as this takes at least an order of magnitude longer to do, what with
     all that screen scrolling and printing.

     Note that if throwback is enabled (as it is by default) then the back
     end is actually run in a TaskWindow.  Thus the `listing' is actually
     output to a task window.  Thus showing the complete uselessness of
     this feature!
     
     
  Reduce variable names

     By default, all variable types are reduced.  The only conceivable use
     for disabling the reduction of these would be to circumvent the use
     of EVAL or DATA variables, although BasCompress provides a much
     better method, via the use of Special files.  See S2.11.
     
     The final option, `E' suppression is used to stop BasCompress
     shortening any variables to a name beginning with an `E'.  For the
     reason why this might be desirable, see S8.2.





                                  Page  28

 ============================================================ BasCompress ====



  Reduce routine names

     By default, all procedure and function names are reduced.  The only
     reason for disabling the reduction of these would be to circumvent
     the use of function names used inside an EVAL construct, although
     BasCompress provides a much better method to handle this, via the use
     of Special files.
     
     
 [4.8] Log
     
     The log sub-menu controls what additional information may be inserted
     into the log file, along with the name of all files scanned and any
     warnings and errors.
     
     
  Save as

     This leads to a standard save as dialogue box, used to define the
     file to which the log will be dumped.  This will be a standard Text
     file.
     
     
  Report multiple exits

     BasCompress needs to know when each and every routine ends.  If it
     finds more than one exit it will report it.  For large programs this
     can produce many warnings, and so these warnings can be disabled.
     See S2.8.3.

     This item will be disabled if you have selected `Ignore exits from a
     routine (`dumb')', in the input menu.
     

  Report unknown SWI's

     In order for BasCompress to convert a SWI string to a number the
     Module must be resident at the time of compression.  If the module is
     not resident, then this warning will be given.  This toggles the
     appearance of such warnings, and is usually left enabled.  See S2.5.
     
     This item will be disabled if `Convert SWIs to numbers' in the output
     menu is turned on.
     

  Report OVERLAY usage

     Because the parameter to an OVERLAY statement is a string array, it
     is not possible for BasCompress to know which files should be
     OVERLAY'ed.  Therefore BasCompress emits a warning when it sees the
     token.

     If your program uses overlays then please read S2.18.





                                  Page  29

 ============================================================ BasCompress ====



  Report TOP usage

     BasCompress is unable to distinguish between the pseudo-variable
     `TOP' and a possible sequence `TO P' (without the space) which can
     occur in a FOR loop.  See S2.21.


  Statistics

     This shows how many of each type of variable and routine there is
     altogether in the program.  This includes all deleted labels.
     
     
  EVAL keyword, DATA keyword, READ keyword

     These will list out every line that contains such a keyword,
     indicating where BasCompress may introduce errors because of its'
     reduction of labels.  Note that only the use of these keywords
     outside special routines is reported, as it is assumed the use of the
     keyword was fully handled by the Special file.  Further note that
     DATA found outside any routine is just reported as unlinked.
     
     
  List input

     With this option ticked, the input basic is also listed inside the
     log file.  This produces humongous files, as this is plain text Basic
     not tokenised Basic.



 [4.9] Special files
     
     Special files are used to help BasCompress to handle the EVALuation
     of variables.  A special file consisting of a list of routines that
     are expected to contain this keyword, and/or a secondary list of any
     particular labels that must not be reduced.
     
     The writable menu item allows you to type in a full pathname.  It is
     easier just to drag the file onto the control window, though.
     
     
  Warn undefined

     Normally it wouldn't matter that you have told BasCompress about
     special routines that aren't used in the input file.  However there
     is still this option that will report superfluous definitions found
     in Special files.










                                  Page  30

 ============================================================ BasCompress ====



  Show expansion

     With this item ticked, every special label constructed will generate
     a warning message into the log file.  This can be useful for showing
     what you think should appear, and what BasCompress thinks should
     appear.

     

 [4.10] Cross-reference
     
     From here you define all aspects of the (rather large) cross-
     referencing sub-system.
     
     
  Save as

     This leads to a standard save as dialogue box, used to define the
     file to which the cross-reference will be dumped.  This will be a
     standard Text file.
     
     
  Include deleted

     When ticked, this will force all the superfluous routines and
     variables to be included in the cross-reference.  This is usually not
     such a good idea, as the process of deletion removes all the
     reference information.  For a full cross-reference, also disable the
     removal of unused routines (see Output), which leaves this
     information in tact.


  Reference order

     This leads to an order dialogue box (see below) used to set the
     sorting criteria for the references.  This is probably best left as
     the default: Name, Type, Location.
     
     
  Variables, Routines

     These two items lead into identical sub-menus.  They allow the cross-
     referencing to be defined for both independently.
     
     
  Verbosity

     This leads to a sub-menu where you can define the level of detail of
     the cross-referencing information.  See S3.2.









                                  Page  31

 ============================================================ BasCompress ====



  Types

     Used to define what types of variables or routines are included in
     the cross-reference.  Usually this would be all types, but sometimes
     you might only want to know about the integers, say.  Just de-tick
     all the others.

     
  Order

     This dialogue box is quite complicated.  Basically, you are trying to
     define several layers of ordering.  First of all everything is sorted
     according to the left hand column.  Now BasCompress goes through
     these sorted items looking for a sequence of items that are the same,
     according to this ordering.  Now, for each sequence found it will
     sort them again using whatever you have defined in column two.  This
     recurse on each smaller and smaller sub-sequences to the columns on
     the right.
     
     Obviously, it isn't much use having two columns sorting by the same
     criteria, so BasCompress will not allow you to select it.
     
     You can delete a column by ADJUST clicking on the ordering already
     used.  This will cause all columns to the right to shuffle one column
     to the left (this is quite a pleasing graphical effect!)
     
     It isn't possible to have a "blank" column.  If you attempt to create
     a blank column then your new column will be shifted to the left (yet
     another pleasing graphical effect!)
     
     It is possible to delete all columns.  This will cause the output to
     appear in a seemingly random order.  Not much use, apart from seeing
     how good the hashing function is!

     Ordering by location is only meaningful for references.  Using this
     option for variables or routines will result in a (seemingly) random
     order.
     
     The Dict. standards for dictionary, and is similar to Name, except
     instead of ordering by ASCII, order as it would appear in a...
     (guess).
     
     
 [4.11] Choices Dialogue Box
     
     This dialogue box controls aspects of the front end application
     itself, not the back end.  It grabs the input focus so that some
     keyboard short cuts can be used, must notably RETURN and ESCAPE.
     Also the bottom row of buttons can be pressed using F2, F3, etc..
     
     
  Set

     This accepts the above values for the current session of
     BasCompress.  For the effects to be permanent use either Save or Save
     full.  Also see the note below about using outline fonts in dialogue
     boxes.

                                  Page  32

 ============================================================ BasCompress ====



  Cancel

     This disregards any edits you have made to the above options.

     
  Save full

     Along with all the expected switches and sort ordering, also saved
     with the choices are the default names of the log, cross-reference
     and output files.  This option saves the full pathname of each of
     these files, and would be used while developing a project, to save
     dragging the log and output files each session.
     
     
  Save

     As Save full but only the leaf names of the log, cross-reference and
     output files are saved.  This is handy for more generic
     environments.  For instance, if you always call your Wimp programs
     Wimp, then to make a standard application from this, the output file
     would be !RunImage, and this would be a better default to have than
     Output.
     
     
  Default

     This sets up everything to a default state, for when you've made a
     complete mess of the options.  This default state can also be
     achieved by deleting the Choices file inside !BC.!fe, and restarting
     the application.

     
  Run BasCompress'ed file

     With this option ticked whenever an output file is specified it is
     immediately executed after being generated.  This is useful while
     constructing a Special file, so the program can proceed and report
     the missing variables found!)


  Load log file

     If a log file was specified then this is "opened" immediately after
     it is generated.  On a properly set up system this would cause Edit
     to be loaded up automatically if necessary, and replace any version
     currently held if Edit is already resident.  Multi-tasking at its
     best.  Note that if you edit the "old" log file, then this smoothness
     is ruined, because Edit will open up a new window containing the new
     version.  C'est la vie.
     
     
  Load cross-reference file

     Same as the above option, but loads the cross-reference file
     generated, if any.



                                  Page  33

 ============================================================ BasCompress ====



  Name output as <Main>

     This is a kludge to reduce the size of both cross-reference and log
     files.  As any Wimp application must use the full pathname of every
     file, this is what is passed to the back end application.  However
     this causes the full pathname to be printed in every error message
     and reference.  As a stop gap, this front end can be told to set the
     environment variable <Main> to the full pathname, and pass this to
     the back end application.  It does mean you don't see the actual name
     of the file being processed, but that usually isn't a problem as you
     know that anyway.
     
     
  Output file leaf name same as input

     This option is useful when compressing lots of files from one
     directory to another, for example having compressed versions of all
     your library files.  Having defined the output directory, the full
     pathname is constructed from this directory and the leaf name of the
     input file, saving quite a bit of typing.


  Use outline fonts in dialogue boxes

     BasCompress comes with two versions of all its' windows - with and
     without outline fonts.  Users of low-resolution monitors may prefer
     to use the system font versions.  Also, RiscPC users may have to use
     the "System font" windows for two reasons: first because the
     fontified windows use fonts at a different size (slightly larger for
     low resolution users) which looks ugly but more importantly because
     of a bug in the Window Manager that causes clicks on (genuine) font
     icons to cause the Wimp to "forget" the text font :(
     
     Note that for historical reasons changes to this option are not
     updated immediately but only take effect the next time BasCompress is
     run.






















                                  Page  34

 ============================================================ BasCompress ====



5 The back end
     
     
     This chapter describes the underlying CLI program, and how to use it
     effectively.
     
     By default all text output is to the screen.  This can be redirected
     to separate log and cross-reference files, as required.
     
     
 [5.1] Invoking
     
     Double-clicking on the application directory from a directory display
     will automatically start up the Wimp front end application.  This is
     because no parameters were passed to the !Run file.
     
     If any parameters are passed to the application, i.e. you activated
     it from a command shell then the back end application is called
     direct.
     
     This application requires the floating point emulator module to be
     resident.  This is automatically loaded from the current system
     resources.  (Floating point arithmetic is only used to analyse and
     output decimal numbers, this can be disabled and so there will be no
     need to load the floating point emulator --- this is not a
     recommended procedure, though).
     
     Also required to be resident is the authors' own library module:
     CAssembler.
     
     These modules are automatically loaded if not resident.
     

 [5.2] Installing
     
     There are two methods of installing BasCompress for easy use from a
     shell.  One is to just install the application onto your Run$Path,
     and use it by *!BC file.
     
     This has the disadvantage in that you must remember the !.  The much
     better alternative is to use the Alias$BasCompress that is set up for
     you in the !Boot file.  Thus it is only required to run this !Boot
     file in your boot-up sequence, and then call BasCompress by
     *BasCompress file.
     
     In both the above it is essential that the !Run file gets executed,
     as this ensures auxiliary modules are resident and checks that there
     will be enough memory to start the application.










                                  Page  35

 ============================================================ BasCompress ====



 [5.3] Environment variables
     
     Because the CLI limits command lines to (a paltry) 256 bytes, several
     tricks were used in order to make the front end application work
     effectively with the back end program (with full pathnames).  These
     can be put to great advantage for CLI users.  In all cases an unset,
     or empty variable is ignored.
     
     BasCompress$Options
                     This should be a string of the same format as a
                     normal parameter set, except missing the name of the
                     input file (of course).  With this you can override
                     any of the built-in default values with your own
                     preferred set.
     
     BasCompress$Out
                     The name of the tokenised basic file produced.
     
     BasCompress$Log
                     The name of the log file produced.
     
     BasCompress$XRef
                     The name of the cross-reference file produced.
     
     BasCompress$Special
                     The name of the special file(s) input (a comma
                     separated list).
     
     BasCompress$Path
                     A comma separated list of directories used to find
                     Special files
     
     It should be noted that the front end application resets all of these
     variables (except the Path), so keep this in mind.
     
     
 [5.3.1] DDEUtils and long command lines

     BasCompress knows about the long command lines supported by the
     DDEUtils module.  This is a method of passing a command line larger
     than 256 bytes to a child process.

     This provides a much more elegant solution than the use of
     environment variables.  The Wimp front end application now uses this
     feature if throwback is enabled, but uses the environment variables
     otherwise.












                                  Page  36

 ============================================================ BasCompress ====



 [5.4] The CLI parameters
     
     The ordering of the parameters has been carefully set up so there is
     usually no need to name any parameters.
     
             BasCompress [-In] <file>
                      [[-Out <file>]
                      [[-Special] <files>]
                      [[-Log] <file>]
                      [[-XRefFile] <file>]
                      [[-XRef] <n>]
                      ...
     
     So for normal work you would have set up BasCompress$Options and
     you'd just do BasCompress @.MyProg @.Result @.Special @.Log "" 0.
     There is a -Help option to display a brief description of the
     available options.
     
     As with all all native Archimedes applications, switches toggle the
     previous state (OS_ReadArgs does not allow -f and +f).
     
     
 [5.4.1] Input

     -Dumb                   ignore ENDPROCs (OFF) S2.8.3
     -In <file>              this must always be given
     -Library                ignore undefined routines & main program
                             (OFF) S2.8.1
     -MultiDEF               allow multiple definitions of the same
                             routine (OFF) S2.10.1
     -SWIBad                 fault malformed SWI names (OFF) S2.5



























                                  Page  37

 ============================================================ BasCompress ====



 [5.4.2] Output
     
     -ASC                    decompose ASC("X") to number (ON) S2.16
     -CLI                    prefix code to write env with
                             BasCompress$CLI (OFF) S2.22
     -CVar                   constant variables are compressed (ON) S2.17
     -InitialREM             keep REMs before first routine def (OFF)
                             S2.20
     -ListOut <n>            echo output in screen mode <n> (OFF) S4.6
     -NEXTs                  remove NEXT variables (ON) S2.19 
     -Number                 analyse decimal numbers (needs FPEmulator)
                             (ON) S2.4
     -Out <file>             output file (see BasCompress$Output)
     -ReduceVar <type>
     -ReduceRtn <type>
     -Reduce <type>          reduce these types of labels (irsIRSpf) S2.11
     -Single                 no concatenation of output lines (OFF) S2.13
     -SWI                    convert SWI strings to numbers (ON) S2.5
     -Unused                 delete unused routines and variables (ON)
                             S2.8
     
     <type> is a string of these letters:
             p       procedure
             f       function
             r       real variable
             i       integer variable
             s       string variable
             R       real array variable
             I       integer array variable
             S       string array variable


 [5.4.2.1] Output listing
     
     First the mode is selected (-1 would select the current mode), and an
     appropriate warning or error generated if that mode is not
     available.  Next a blue-on-white colour scheme is selected.  Then the
     display is split into two columns, with the left column about 61% of
     the screen wide (80 columns in mode 16).  The source listing is
     scrolled here.  On the right column the output is scrolled.
     
     The source listing does not include any deleted routines, but does
     include all inter-routine junk.  The output listing is as per the
     output file, in its' entirety.  The right column is only updated each
     time a whole line has been amassed, which could take a while if
     maximum compression is selected.
     
     There isn't really much use for this option, as the time taken to
     scroll the screen takes far too long.









                                  Page  38

 ============================================================ BasCompress ====



 [5.4.3] Log
     
     -DATA                   log lines containing DATA (ON)
     -EVAL                   log lines containing EVAL (ON)
     -Goto                   log lines containing line numbers (ON)
     -List                   echo input to log (OFF)
     -Log <file>             output file (see BasCompress$Log)
     -OVERLAY                suppress warnings if see `OVERLAY' (OFF)
                             S2.18
     -READ                   log lines containing READ (ON)
     -Stats                  log program statistics (ON)
     -SWIExist               report unknown SWI strings (ON) S2.5
     -TOP                    suppress warnings if see `TOP' (OFF) S2.21
     -WEndRtn                report conditional exits (ON) S2.8.3

     
 [5.4.4] Special
     
     -Special <files>        use comma list of <file> to resolve implicit
                             usages (see BasCompress$Special and
                             BasCompress$Path)
     -UnusedS                report undefined special routines (OFF)
     -WSpLabel               report label expansion results (OFF)


 [5.4.5] Cross-reference
     
     -XRefFile <file>        output file (see BasCompress$XRef)

     
 [5.4.5.1] What gets cross-referenced
     
     -Deleted                xref includes deleted variables and routines
                             (OFF)
     -XIncVar <type>
     -XIncRtn <type>
     -XInc <type>            xref these types of labels (irsIRSpf) S3.1.1
     
     <type> is a string of these letters:
             p       procedure
             f       function
             r       real variable
             i       integer variable
             s       string variable
             R       real array variable
             I       integer array variable
             S       string array variable











                                  Page  39

 ============================================================ BasCompress ====



 [5.4.5.2] How much cross-referencing to be done
     
     -XRef <n>       level of xref detail for both routines and variables
                     S3.2
     -XRtn <n>       level of xref detail for routines (0)
     -XVar <n>       level of xref detail for variables (0)
     
     <n> evaluates to a number from 0 to 4:
             0       None
             1       Existence --- name
             2       Global --- name / count
             3       Routine --- reference to routine level
             4       Line --- reference to line level
     
     
 [5.4.5.3] Order of cross-referencing
     
     -Sort <sort>    order of all variable, routine, and reference sorting
                     S3.3
     -SRef <sort>    order of cross-references (NTP)
     -SRtn <sort>    order of routines (TN)
     -SVar <sort>    order of variables (TN)
     
     <sort> is a string of these letters:
             N       sort by name
             T       sort by type
             D       sort by name (in dictionary sense)
             P       sort by position in source
             U       sort by usage
     
     e.g. to sort by usage, name, then type = "UNT".
     
     Lower case letters order top to bottom.



 [5.5] Error handling
     
     By errors, it is meant system errors (i.e. those generated by calls
     to the operating system).
     
     Admittedly, error handling is quite primitive in BasCompress.  All
     calls to the operating system are tested for error condition, and if
     set this is immediately propagated all the way back to the user, with
     an appropriate message dumped in the log file.
     
     Errors occurring before the log file is opened are reported to the
     screen.
     
     In any case, an error safely closes all files opened by this
     application.







                                  Page  40

 ============================================================ BasCompress ====



 [5.6] Escape handling
     
     As with error handling, this is fairly primitive.
     
     BasCompress can be aborted at any time, terminating immediately after
     closing all open files.
     
     Note that during the middle of program output the Basic file will be
     Type'd to Data, as a safeguard against loading it into BasicV.  (This
     does not handle zero-length files very well --- it hangs the
     machine).
     
     
 [5.7] Hourglass
     
     The hourglass is used to indicate BasCompress's progress.
     
     During parsing, the percentage shows how much has already been
     analysed.  Note that because BasCompress can not know the total
     length of input beforehand, the percentage may actually go backwards
     as LIBRARY statements are parsed.
     
     During cross referencing, there is no percentage, but the bottom
     L.E.D. is on.
     
     Finally, during program output an accurate percentage is displayed,
     with the top L.E.D. on.































                                  Page  41

 ============================================================ BasCompress ====



 [6] Special files
     
     
     This chapter explains the format of the Special files.  These are
     auxiliary Text files used to give BasCompress some more information
     to help it compress better.  See also the examples supplied on disc.
     
     
 [6.1] Why need special files?
     
     Special files are used to tell BasCompress how to cope with the
     following types of situation:
     
             o       EVAL("Variable")
             o       DATA Variable
             o       LIBRARY "%."+ RoutineParameter$
             o       EVAL("FN_"+ RoutineParameter$)
             o       definitions from RETURN parameters
             o       OVERLAYs

     Because BasCompress reduces labels (see S2.11) using a global
     context, at run-time when BasicV tries to find these labels in the
     current context, it fails.  Special files tell BasCompress which
     labels not to compress, either explicitly as in the first two cases
     or above, or implicitly (from routine parameters) as in the later two.

     You may also need to tell BasCompress about variables that it thinks
     are constant, but actually get assigned as a result of a RETURN
     parameter in a routine.
     
     
 [6.2] The Special file
     
     Special files are just plain Text files, in the format specified
     below.  BasCompress allows more than one Special file to be defined
     (using a comma separated list), but it is far easier to use the
     #include directive inside a Special file, as shown below.
     
     Special files are found using the environment variable
     BasCompress$Path.  By default this is not set up, but you may like to
     create a sub-directory BasCompress in your library and set this
     variable to ",%.BasCompress." in your boot-up sequence (note the
     trailing dot, as with all path variables).  Here you would keep the
     one or two special files that handle your particular set of library
     files, and BasCompress will find them for you without you having to
     type in a full pathname every time.












                                  Page  42

 ============================================================ BasCompress ====



 [6.3] Format of a Special file
     
     The format of a Special file is fairly simple.
     
     Basically, (for variables) all you're trying to tell BasCompress is:
     
             o       routine X has a string in parameter Y
             o       inside routine X there is an EVAL
             o       this constructs a new label Z from Y
             o       don't reduce this label Z
     
     So all you do is give the name and expected parameters of a routine
     and tell BasCompress how to construct label Z.
     
     
 [6.3.1] Defining routines
     
     You give the name of a routine by:
     
             procedure foo(1)
     
     or,
     
             function bar(,1)
     
     The brackets are necessary if a routine doesn't have any parameters.
     
     The procedure definition above tells BasCompress to expect a (simple)
     string expression to be passed to the procedure foo at every call, as
     the sole parameter.  The function definition says the first parameter
     is not important, but the second parameter will be a simple string.
     
     These prototypes are checked against what is actually found in the
     program proper, and an appropriate error generated if they don't
     match.
     
     There can be up to ten distinct string parameters [0-9], but you'll
     probably only ever need just one.
     
     
 [6.3.2] Defining globals
     
     Sometimes the EVAL isn't in any particular routine (or is used inside
     a nested routine structure not amenable to the above simplification),
     so you'd like to give the name of the labels not to reduce just
     once.  This is easy because at the start of each Special file,
     BasCompress puts an implicit declaration of the main program as a
     routine, with no parameters.  So you'd just start defining the global
     labels as normal routine labels.









                                  Page  43

 ============================================================ BasCompress ====



 [6.3.3] Labels
     
     First of all an example:
     
             PROC_List(a, "Zappa", "Good")
             ...
             :
             DEF PROC_List(RETURN x, y$, z$)
               IF EVAL("Frank_"+ y$)<>0 THEN
                       x += EVAL("FN_"+ z$+ "_Name(Cy%)")
               ENDIF
             ENDPROC
     
     this would be implemented as:
     
             procedure _List(, 1, 2)
               real Frank_\1
               function _\2_Name
               integer Cy%
     
     Note the spaces to the left of the implicit declarations, and the
     case of the keywords as both of these are important.  Also note the
     need to declare Cy% as another variable that must not be shortened.
     
     There is no attempt to verify that the <n> used was declared in the
     parameter list, but all undeclared <n> are reset to the empty
     string.  Also there is only rudimentary checking done on the
     expansion template, so be sensible.
     
     The following table shows the exact words to use --- note they must
     be lower case:
     
             real            a real variable e.g. pi_by_2
             integer         an integer variable, e.g. count%
             string          a string variable, e.g name$
             real_array      a real array variable, e.g. times()
             integer_array   an integer variable, e.g. books%()
             string_array    a string variable, e.g. titles$()
             procedure       a procedure, e.g. PROC_total
             function        a function, e.g. FNmin
             library         load library file, e.g. %.Wimp
     
     BasCompress can currently interpret the simple string in a number of
     ways.  These template expansion types are:
     
     
 [6.3.3.1] Verbatim
     
     \<n>    causes the formal parameter <n> to be substituted verbatim.









                                  Page  44

 ============================================================ BasCompress ====



 [6.3.3.2] Comma separated
     
     ,<n>    treats parameter <n> as a comma separated list of strings to
             substitute, with optional spaces after each comma.
     
     Each value is extracted from the string in turn.  Note that the
     string is expected to contain real variables only, i.e. no %, $, or (.
     
     For example:
     
             PROC_Music("Zappa,Varese,Stravinsky,Belew)
             ...
             :
             DEF PROC_Music(p$)
             LOCAL i, dummy
               i = INSTR(p$, ",")
               WHILE i>0
                 dummy = EVAL("FN_"+ LEFT$(p$, i-1))
                 p$ = MID$(p$, i+1)
                 i = INSTR(p$, ",")
               ENDWHILE
             ENDPROC
     
     could get coded as:
     
             procedure _Music(1)
               function _,1
     
     
 [6.3.3.3] Full pathname
     
     @<n>    parameter <n> is considered as a full pathname, and just the
             leaf name is substituted.
     
     For an example see S6.3.4 below.
     
     
 [6.3.3.4] Wimp menu

    [note this uses the guillemotright glyph (character 187), but will be
    represented here as `>>'.]

     >><n>   <n> is taken to be a Wimp menu string.  This means that after
             ">" and ":" a variable name is expected, terminated by a
             comma or the EOS.
     
     It is assumed that the implicit variables are all of the same type.
     If not just define several rules, one for each type.
     For example
     
             PROC_menu("Prog,Info>Info%,dSave as>SaveAs,Quit")
     
     may get coded as follows:
     
             procedure _menu(1)
               integer >>1
               real >>1

                                  Page  45

 ============================================================ BasCompress ====



 [6.3.4] Variables as regular expressions
     
     As well as the above special meta-characters BasCompress will now
     allow you to specify special variables (not routines or libraries) as
     a regular expression (a fancy wildcard expression).  This means that
     instead of specifying one variable, you specify any variables that
     match a pattern.
     
     Special variables so specified can not contain any parameter
     substitution commands.  They also behave in a slightly different
     manner.
     
     To process special variables defined as regular expressions
     BasCompress must use a separate pass, between parsing and output.
     This scans every variable (of the particular type) to see if it
     matches the specified pattern.  If so, then the variable is flagged
     as being un-renamable - as expected.
     
     So what is a regular expression, and why would you want to use it?
     For a full description of regular expressions please see Appendix B,
     but all the useful features (two of them!) will be shown in the
     examples below.
     
     You would want to use regular expressions to specify a range of
     variables with the same sort of name - instead of specifying every
     single one individually.  Eg say you have defined many constants such
     as `Wimp_Initialise', `Wimp_CloseDown', `Wimp_GetRectangle', etc. and
     then used these constants in some DATA statements.  Instead of having
     a (long) list of these variable names in the special file you would
     recognise that all of the variables begin with the pattern `Wimp_'
     and tell BasCompress to mark all such variables as unrenamable.
     
     
 [6.3.4.1] Example patterns
     
     Here's how you would write the above example in a special file:
     
         procedure dummy()
             real Wimp_.*
     
     the important bit being the ".*".  This should be read as "any
     character", "repeated 0 or more times".  Ie as long as a variable
     starts with the five characters "Wimp_" the pattern is matched.
     
     Another frequent case is when variables have the same postfix --- eg
     the pattern:
     
             integer .*CMOS\>
     
     would match all integers that end ("\>" means "match end of
     variable") in the letters CMOS, ie MosROMFrugalCMOS%, FontMaxCMOS%,
     etc...  The specification that CMOS be at the end stops, say,
     MyCMOSvar% being matched by the pattern, as it otherwise would if
     this were not included.




                                  Page  46

 ============================================================ BasCompress ====



 [6.3.4.2] Limitations
     
     Although a regular expression may be defined dependent on a special
     routine being called, this fact is currently ignored - all special
     variables specified using a regular expression are used during the
     pass.  For this reason it is probably worthwhile to place all wild-
     card specifications as global - ie in the main program section of the
     special file.  This limitation will not last long.
     
     Currently a variable that is recognised as matching a pattern is
     flagged as being referenced from the main program (in the cross
     reference) and not inside the special routine that specified the
     wildcard - but this will change in a later version.
     
     
 [6.3.5] Libraries

     As well as labels, libraries may be implicit.  For example, here's a
     simple library handler:
     
             PROC_Load_Library("<Basic$Lib>.Wimp", 2)
             ...
             :
             DEF PROC_Load_Library(f$, v)
             LOCAL x
               LIBRARY file$
               x = EVAL("FN_Init_"+ FNleaf(f$))
               IF EVAL("Version_"+ FNleaf(f$))<v THEN
                 ERROR 1, "Library too old"
               ENDIF
             ENDPROC
     
     Well, in real life you'd set up error handlers and note which
     libraries have already been loaded, but you get the idea.  This could
     be coded as follows:
     
             procedure _Load_Overlay(1,)
               library \1
               function _Init_@1
               real Version_@1
     
     Note the use of @<n> to extract the leaf name.
     
     In the output program the entire statement containing the LIBRARY is
     removed.
     
     Note that because BasCompress analyses the program in a linear
     fashion, the order of library routines may well be different from
     that used in the uncompressed program, (see S2.10).









                                  Page  47

 ============================================================ BasCompress ====



 [6.3.6] Overlays

     Overlays may be specified as inline comments (S2.18.2) or in the
     special file.

     For most common purposes inline comments will suffice, but for complex
     programs that possibly use routines to specify members of the string
     array passed to OVERLAY, then you may use the special file keyword
     `overlay' to handle such cases.

     For example:

             procedure _Load_Library(1,)
               overlay scsi::cheepnis.$.source.code.app.\1

     would be a typical use.


 [6.3.7] Include files
     
     It is possible for special files to include other special files.
     Thus you will probably set up BasCompress$Path and a special file to
     handle your own set of standard libraries, and then...
     
             #include mylibs
     
     somewhere in the special file for each particular program.  (Note
     that there are no spaces to the left of the #include, and don't put
     any quotes on the name either).
     
     Nesting level is not limited, and you can recurse.  This will result
     in an infinite loop, with the only resort being to press escape to
     quit, and then examine the log file.
     
     
 [6.4] Limitations
     
     There can only be 250 odd total Special routines defined.  If any one
     actually reaches this limit, then contact the author, it's easy to
     alter --- at the expense of a slight increase in memory usage.
     
     There is of course one major limitation in that you have to specify
     the name of all the special files before processing the program.  It
     would be nice to set up a system whereby if the program (maybe
     implicitly) loads in library X, then load up special file Y.  However
     this would require re-finding all calls to the (new) Special
     routines --- something that seems quite hard to do, sigh.
     
     Finally, you'd like to be able to take into account the scope of the
     variables so only the use of variables in scope are not reduced.  But
     since BasicV only has one scope, this is not possible to implement
     safely, without some explicit help from the programmer by marking the
     scope of variables in some way.





                                  Page  48

 ============================================================ BasCompress ====



 [7] Errors
     
     
 [7.1] Overview
     
     Errors and warnings can be generated at various stages of the game.
     They all look the same and are all sent to the current log (file /
     screen).  The format is:
     
             file 1234 warning 3: message
     
     If there is no filename, then it indicates the error is global  in
     scope, for example the "undefined routine" error generated when all
     files have been parsed.
     
     Warnings report non-fatal deficiencies.  Errors report a major
     problem, and will stop any output file being generated.
     
     As with all text used by BasCompress, these error texts are held in
     the Messages file.
     
     It is worth pointing out that many warnings and errors may be
     generated after the seemingly innocent warnings 9 and 10.  This means
     that BasCompress may have lost touch with what routine is being
     defined, and starts interpreting the junk inbetween routines as
     genuine code.  So do check the log file from the start.
     
     
 [7.2] Warnings
     
     Most of the warnings are self explanatory.
     

  1:Expecting PROC or FN after DEF

     In standard Basic, these are the only valid things after a DEF.  This
     warning has never been encountered in debugged source!
     

  2:DEF inside a routine

     This is generated because an earlier routine did not exit cleanly,
     and the program believes you are still in this routine.  You need to
     fix the errant routine by terminating it properly, or simply
     appending a dummy routine end (ENDPROC or = <expr>).

     Alternatively put BasCompress into `dumb' mode --- see S2.8.3.


  3:Unexpected period `.'

     A period on it's own is treated as the start of a number (e.g. ".
     7").  This warning is generated if a statement starts with a period
     and it is not in the assembler.




                                  Page  49

 ============================================================ BasCompress ====



  4:Mismatched quotes `"'

     Every line should have matching quotes.
     

  5:Malformed hexadecimal number

     It is expected that a digit or a letter [0-9a-fA-F] comes after an &.
     

  6:Malformed binary number

     It is expected that a 0 or 1 comes after a %.
     

  7:Line number reference found

     This is given if line numbers are found in any libraries, since there
     is no valid reason for them being there.
     

  8:Expecting routine name after PROC or FN

     A non-label character was found after one of these tokens.  This very
     unlikely.
     
  9:ENDPROC not at end of procedure

     This is generated if ENDPROC is found on a line containing an IF, i.
     e. it is ambiguous as to whether this is the genuine end of the
     procedure.  Most of the time this causes no problems, but for short
     routines where this is the only way it exits then BasCompress will
     get confused as to the exact end of the routine.  In this case you
     must either re-code the routine (recommended) or insert a dummy
     routine terminator (ENDPROC or = <expr>).

     Alternatively put BasCompress into `dumb' mode --- see S2.8.3.


  10:= not at end of function

     This is generated if an "= <expr>" is found on a line containing an
     IF, i.e. it is ambiguous as to whether this is the genuine end of the
     function.  Most of the time this causes no problems, but for short
     routines where this is the only way it exits then BasCompress will
     get confused as to the exact end of the routine.  In this case you
     must either re-code the routine (recommended) or insert a dummy
     routine terminator (ENDPROC or = <expr>).

     Alternatively put BasCompress into `dumb' mode --- see S2.8.3.








                                  Page  50

 ============================================================ BasCompress ====



  11:Code found on last line of function

     There were more statements on the same line as the terminating "=
     <expr>" statement.  Since these will never be executed by Basic then
     they should be removed.  This warning could well turn up quite often
     if BasCompress is fed the output of other squashers.
     

  12:Expecting a string after LIBRARY/INSTALL

     In order to be able to load in libraries BasCompress expects a simple
     constant string expression to follow these keywords.  If this is not
     the case then you will need to set up a Special file to handle this
     situation.  This warning is suppressed if inside a Special routine.
     

  13:OVERLAY not parsed, use special file or inline comment

     The OVERLAY keyword can not be parsed by BasCompress and needs
     some help.  See S2.18.
     

  14:Unexpected `['

     A running total of square brackets is kept.  This indicates that
     something like "LDR R0, [[R1...]" was found.
     

  15:Unexpected `]'

     A running total of square brackets is kept.  This indicates that
     something like "LDR R0, [R1...]]" was found.
     

  16:ENDPROC inside a %s structure

     Found a conditional exit from a procedure --- this indicates a bad
     programming style.

     Alternatively put BasCompress into `dumb' mode --- see S2.8.3.


  17:= inside a %s structure

     Found a conditional exit from a function --- this indicates a bad
     programming style.

     Alternatively put BasCompress into `dumb' mode --- see S2.8.3.










                                  Page  51

 ============================================================ BasCompress ====



  18:Conditional %s

     Found a conditional termination of a multi-line structure --- this
     indicates a bad programming style.

     This may occur on lines like the following:
     
             IF x>0 THEN WHILE x>0:y+=FNy(x):x-=1:ENDWHILE
     
     Unfortunately BasCompress does not like this because it expects all
     multi-line constructs to start unconditionally.  To cure this split
     the one-line IF into a multi-line IF.

     Alternatively put BasCompress into `dumb' mode --- see S2.8.3.


  19:Too many `(' found

     A running total of ellipsis is kept.  This indicates something like
     "(1+2)(" was found.
     

  20:Unexpected `)' found

     A running total of ellipsis is kept.  This indicates something like
     "(1+2))" was found.
     

  21:Routine %s already defined at %s

     This warns about multiply-defined routines.  Since there are
     sometimes very good reasons for doing this this warning can be
     suppressed.
     

  22:Malformed decimal number

     A bad decimal number was found.  A decimal number is something
     beginning with a digit or a period and continuing as expected.  The
     form of the number is always checked, but the compression may be
     turned off.
     

  23:The (global) special routine %s is not defined

     anywhere
     This speaks for itself.  It is only generated if the user has asked
     for it, as it is not usually relevant.
     

  24:SWI name missing, or not simple

     It is normal to just have a string, variable, or number immediately
     after a SYS (SWI).  This indicates that found something else ---
     which may indicate a syntax error.



                                  Page  52

 ============================================================ BasCompress ====



  25:SWI `%s' is unknown

     The operating system has no record of what this SWI means.  This
     indicates that either the module is not loaded at the time of
     compression, or it is misspelt.  BasCompress will leave it as it is,
     producing longer and slower code.
     

  26:Can't change to screen mode %d

     If the listing Mode could not be found, but a suitable alternative
     was possible.
     
  27:Special variable %s has been used
  28:Special routine %s has been used
  29:Special library %s has been used
  30:Special overlay %s has been used

     These warnings are generated if the user has turned them on.  They
     show the results of label expansion done at the instance of a call to
     a Special routine.

  31:Found TOP, treated as `TOP' and not `TO P'

     BasCompress may fail to remove a constant variable `P' if this
     warning occurs.  See S2.21.
































                                  Page  53

 ============================================================ BasCompress ====



 [7.3] Errors
     
     Any errors encountered will stop the final output phase, but the
     program will soldier on parsing, so you can rectify all the errors in
     one hit.
     

  2:ENDPROC found in a function

     This invariably follows warning 2, about DEF found inside a routine,
     which itself follows a warning 10, because the previous function did
     not terminate cleanly.
     
     A quick fix is to put BasCompress into `dumb' mode --- see S2.8.3.


  3:= found in a procedure

     This invariably follows  warning 2, about DEF found inside a routine,
     which itself follows a warning 9, because the previous procedure did
     not terminate cleanly.
     
     A quick fix is to put BasCompress into `dumb' mode --- see S2.8.3.


  4:Routine %s already defined at %s

     It's either an error or a warning (21), and this is the error.


  5:File error: %s

     Since there is minimal file accessing done (files are loaded in one
     hit), this usually just reports not being able to find a particular
     file/invalid file name --- it is dependent on the underlying filing
     system.
     

  6:End of file in middle of routine

     It is invalid for a routine to span across a file boundary.
     

  7:Too many files (>254)

     I can't foresee anyone getting this error message!  It is unlikely
     that this limitation would be lifted, either.


  8:Undefined routine: %s (used %s)

     Generated after all files have been parsed, it warns of routines used
     but never defined.  These are usually obscure routines only called in
     error handlers.  If you know for sure that this routine will never be
     called, just put an empty version in your main file to suppress this
     error.


                                  Page  54

 ============================================================ BasCompress ====



  9:Undefined variable: %s (used %s)

     Not generated.
     

  10:FOR not at start of statement

     This may be of some use --- not much, but what the hey?  (Maybe be on
     a one-line IF)?
     

  11:Escape pressed, parsing aborted

     Not generated.  Escapes just terminate program immediately in the
     current version.
     

  12:File %s does not have a Basic file type

     This program only accepts tokenised Basic files --- maybe the file is
     just not Type'd correctly.  (Could be that it was saved under the CFS
     or some such, and you only gave the SCSIFS?)
     

  13:File %s is too small to be a Basic type

     A rudimentary check on each Basic file is done --- this is generated
     if it fails.
     

  14:File is corrupted/not basic

     Each line of tokenised Basic has a header.  As the file is parsed
     each header is checked and if invalid this error is generated and
     parsing of the file is aborted.
     

  15:Escape pressed, xref aborted

     Not generated.  Escapes just terminate program immediately in the
     current version.
     

  16:Escape pressed, compression aborted

     Not generated.  Escapes just terminate program immediately in the
     current version.











                                  Page  55

 ============================================================ BasCompress ====



  17:Unexpected %s in a %s structure

     This detects any foul-ups in multi-lined structures.  The Basic
     interpreter allows some of these through without reporting an error.
     These errors allow you to fix the (very probably) mistakes.  See
     warning 18.

     A quick fix is to put BasCompress into `dumb' mode --- see S2.8.3.


  18:Unexpected %s

     As error 17 above, but obviously outside any surrounding structure.
     

  19:End of file in middle of assembler

     A special case of error 6, i.e. a routine did not end before the end
     of a file was found.
     

  20:OTHERWISE not at start of line

     A simple error for a simple mistake.
     

  21:WHEN not at start of line

     A simple error for a simple mistake.
     

  22:Computed GOTO/GOSUB found

     Now, I ask you, is this how to program?  BasCompress will refuse to
     work with such things, and who can blame it?
     

  23:INSTALL/LIBRARY not at start of line

     This indicates a syntax error, probably.  Or maybe an IF without a
     THEN, who knows?
     

  24:INSTALL/LIBRARY can not be on a conditional line

     If you must, then split into a multi-line IF and try again.
     

  25:The special routine `%s' was declared as having different parameters
     from those found here

     The number of parameters do not match --- probably a wrong number of
     commas in the Special file.





                                  Page  56

 ============================================================ BasCompress ====



  26:The special routine `%s' wants a string constant for one of its'
     parameters

     This program only handles very simple constant string expressions,
     and this error indicates that the expression was not simple enough.
     

  27:Line too long (max 256)

     This seems a reasonable upper limit on the line length of a Special
     file.
     

  28:Line `%s' is not of a recognised form

     Syntax error for the Special file line.  Note that if you specified a
     Text file full of control codes and such, then you may only get to
     read the last few words of this message.
     

  29:Label `%s' is invalid

     In Special files, the label probably starts with a digit, or some
     such.
     

  30:Parameter list `%s' is invalid

     In Special files: what more needs to be said?
     

  31:Parameter list `%s' contains a duplicate

     In Special files: it is not exactly meaningful to have two or more
     parameters assigned to the same expansion number is it?
     

  32:Implicit label substitution overflowed

     When a call to a Special routine is found, the label templates get
     expanded using the actual parameters passed.  This error shows
     BasCompress checks for overflow in its' internal buffers!
     

  33:Too many special routines (max 255)

     A perfectly reasonable limit it seems.  This could easily be
     extended, though.
     

  34:Unable to load special file (not Text?)

     Or maybe it wasn't found.  Only Text files are accepted.





                                  Page  57

 ============================================================ BasCompress ====



  35:SWI name missing, or not simple

     It is normal to just have a string, variable, or number immediately
     after a SYS (SWI).  This indicates that found something else ---
     which may indicate an error.
     

  36:Illegal screen mode

     If the listing mode could not be found, and no suitable alternative
     was possible, then this error is generated.
     

  37:Bad main program, unterminated %s structure

     This is a special case, if the first routine found (DEF PROC, or
     DEF FN) was inside a multi-line structure.  This indicates an error
     in the main program.
     
     A quick fix is to put BasCompress into `dumb' mode --- see S2.8.3.


  38:Can't find closing ellipsis in special routine parameter

     During label expansion, BasCompress found a label ending in (, which
     it took to mean the start of an array index.  No closing ) was found
     before the end of the string.
     

  39:Bad char `%c' following > or : in special routine parameter

     During label expansion, BasCompress expects the label to be
     terminated by a comma or the EOS.  This indicates that this condition
     was not satisfied.
     

  40:Called routine `%s' with wrong number of parameters

     BasCompress keeps note of the number of parameters a routine is
     defined with, and can detect when an attempt is made to use the
     routine with the wrong number of parameters.

















                                  Page  58

 ============================================================ BasCompress ====



 [7.4] Run-time errors
     
     Here is some help with possible errors that BasCompress may introduce
     to the compressed Basic output.
     
     
 [7.4.1] Unknown or missing variable
     
     The quick and easy method to solve this problem is to turn off all
     label reduction.  This is not recommend, as it makes the use of
     BasCompress almost worthless.
     
     This error has been generated because you have not told BasCompress
     about the side effects of an EVAL or DATA statements.  See S2.11 for
     why this produces the error, and S6 for how to cure it.
     In essence you have to go through the program, locate the EVAL's and
     possibly the DATA statements as well, (look in the log file for
     exactly where to find these), and then build a Special file to tell
     BasCompress how to handle these.
     
     Usually this entails defining some "global" labels that will never be
     reduced, although sometimes it is possible to build a more
     sophisticated parameter-based rule.
     
     It may just be possible that this error is generated inside
     assembler.  If so, then this indicates an error on BasCompress'
     part.  Examples of such should be sent to the author for inclusion in
     upgrades.  This possibility is extremely remote as BasCompress has
     been tested with a wide range of sources, but most cases where it has
     failed in the past has been in this area.
     
     

 [7.4.2] No such function/procedure
     
     This occurs for exactly the same reasons as detailed in S7.4.1 above.


 [7.4.3] Missing ENDIF
     
     These errors are generated very rarely, but they are just possible.
     Consider the following code:
     
             IF FN_SaveFile THEN :::REM comment
     
     What BasCompress could produce, although it does tries not to, is:
     
             IFFNxTHEN
     
     Obviously this is wrong, wrong, wrong.  From a simple one-line
     conditional (that does nothing), BasCompress has produced a multi-
     line conditional construct where there shouldn't be any, and without
     the ENDIF.





                                  Page  59

 ============================================================ BasCompress ====



     Since this situation is fairly rare, and BasCompress does handle it
     most of the time, it is not likely to be remedied --- unless enough
     people request it.
     
     The work around is to not to ignore the return value from the
     function, which is probably an error status (indicating a very lazy
     programmer!), but to assign it to a variable, and then act on it
     accordingly.


 [7.4.4] Invalid RETURN actual parameter

    If the program compresses OK but when run comes up with an error:
    
                    `Invalid RETURN actual parameter'
    
    then ensure that menu item `Input->Remove constant variables' is
    disabled.  The proper way to deal with this is to use a special file
    on the variable, see the manual.  See S2.8.3.


 [7.4.5] Syntax error

    If this occurs then ensure that menu item
    `Output->Reduce variable names->`E' suppression' is ticked. See S8.2.


 [7.4.6] Logical errors
     
     By this it is meant that a program doesn't generate any overt errors,
     it's just that it doesn't do the same as it did before compression.
     
     BasCompress has been tested quite thoroughly with a wide source of
     Basic programs, and it is hoped that all of these exceptional cases
     have been noted and duly handled.  However if you do get this type of
     error, it is still probably because of EVAL and DATA being used with
     undeclared (and probably short, e.g. A%, x, etc.) variables.  These
     variables may have been "renamed" by BasCompress, or even re-mapped
     to different variables, and hence contain an invalid value.
     
     If it is not because of this, then the author would appreciate it if
     an example of the incorrectly compressed source was sent in, so
     BasCompress could be updated to handle that case.















                                  Page  60

 ============================================================ BasCompress ====



 [7.5] Internal errors
     
     These are "system" errors generated by BasCompress itself.  These
     messages are hard-coded into the executable, and use the error number
     chunk &DCBC0 to &DCBFF:
     
                     Error(s) during parsing
     
     This should never appear, as it is an internal error used to indicate
     an erroneous parsing stage.
                     Invalid sort character `%c'
                     Sort string too long
                     Invalid type character `%c'
     
     These indicate rudimentary errors on the parameters passed on the CLI.
     
                     Invalid option in system variable BasCompress$Options
     
     Indicates an invalid system variable.  Unfortunately it is not
     possible to show exactly what was wrong with it, just that some part
     of it was wrong.
     
                     1.1
                     ...
                     10.1
     
     These errors should never be generated.  They indicate where
     BasCompress has found some inconsistencies in its' own internal data
     structures.  Any occurrences of such should be sent, along with the
     source that produced them, to the author for correcting in future
     upgrades.

     This can be sent by Email to bascompress@cheepnis.demon.co.uk.

























                                  Page  61

 ============================================================ BasCompress ====



 [8] Loose ends
     
     The fact that this chapter exists shows that I'm no good at
     documentation!  It mainly describes features that may (or may not)
     get implemented in future upgrades.
     
     
 [8.1] Memory usage
     
     Let's face it boys and girls, this program eats RAM like nobody's
     business.  It's really just a fact of life for 32-bit/RISC machines.
     
     This is compounded by the need for some oomph (technical term) in the
     program execution stakes.  To this end most things are kept on two
     separate lists --- e.g. if a routine X calls Y then this is recorded
     both in X's calls list, and Y's called by list.  This bit of
     redundancy probably doubles the speed of cross referencing, so it was
     felt worth it.
     
     Also all the source is kept in RAM, and all the output.
     
     There is some consideration to low-memory users in that the hash
     table sizes grow on request, but then again they start pretty big
     anyway!

     Good job that RAM prices are low.  In September 1996 one could
     get 32Mb SIMMS for a Risc PC at 110 UKP. 































                                  Page  62

 ============================================================ BasCompress ====



 [8.2] Missing THEN
     
     Basic allows the programmer to omit a THEN statement when used on a
     single-line IF compound.  However, this can cause problems.  Because
     BasCompress removes all spaces, if the condition ended with a digit,
     and the statement after the (missing) THEN starts with an `E' then
     Basic gets confused - thinking a real number (in exponent format) has
     been given.  Eg the BasCompress produced line:
     
             IF x<>0E%=1
     
     is wrong.  There should be a space after the 0.  This is very rare.
     A temporary cure is to stop BasCompress shortening any variables to
     names starting with an `E'.  Although this will solve most problems,
     there is still the unresolved problem of the un-shortened variables.
     The only cure is to make sure the THEN is always used.
     
     A similar problem is the following BasCompress produced line:
     
             WHILE x<>0E%=2
     
     The cure for this is to always separate the expression from the first
     statement of a WHILE compound by a colon.
     
     While testing this program, it became evident that the missing THEN
     was part of a general problem --- skipping a Basic expression.  This
     is harder than at first seems, because there is no point at where you
     can say "yes, here is the end", as you can in a procedural call, say
     (e.g. you've found a comma, close ellipse and the bracket and quote
     count is zero).  E.g. how would you handle this:
     
             IF a=b=c THEN P."hello"
     
     Intuition get's it wrong.  Basic treats this as:
     
             IF (a=b) THEN =c ...
     
     Which means you have to build a tree/stack.  But, once you can do
     this then this program could become quite interesting.  It could
     evaluate constant sub-expressions.  This could produce some very
     compact stuff, as you'd also be able to substitute constant variables
     with their values, and even eliminate dead code.  I.e. debugging
     stuff that would never be executed because it is known that, say,
     Debug is always FALSE.
     
     But, tie that in with a bit more knowledge of the structure of the
     Basic, and it is almost easy to generate not tokenised Basic, but
     code.  Well, I'm sure if enough people register, it will give this
     author the incentive to develop BasCompress into the fastest (and
     cheapest) Basic compiler.








                                  Page  63

 ============================================================ BasCompress ====



 [8.3] Cross-reference
     
     It would be nice to have a toggle between multi-line and single-line
     (the current) output.  This is fairly easy to do, but it'll require
     some experimentation!
     
     Also handy could be some ordering based on label length, or even the
     (approximate) size of a routine.
     
     Some rationalisation of the messages used is in order, too.
     Currently the program outputs some line feeds of its' own accord,
     which is decidedly against the grain.
     
     How about not listing the file that a routine is in?  Or just the
     leaf of the filename.  This would reduce the size of the output by
     quite a lot.  The former would require the user to cross-reference
     (the cross-reference!) to find the file of the reference, though.
     
     
 [8.4] Statistics
     
     There are loads more statistics that could be done;
     
             o       libraries that aren't needed
             o       variables only ever declared (e.g. LOCALised but
                     never used)
             o       variables only ever assigned to once (constants)
             o       lines where the memory indirection operators ?, | and
                     ! are used
             o       don't log all the deleted routines and variables,
                     just count them
             o       give a percentage of the code that is unused
             o       percentage compression achieved on the used code
             o       lines containing any user-defined basic token (e.g.
                     PRINT)
             o       time taken to load, parse, cross-reference, compress,
                     write
     
     
 [8.5] Uncompressed output
     
     It would have been nice if there was an option to just remove the
     unused routines and merge all the libraries into one big file.  This
     would give a nice listable program containing only the routines
     used.  However this is currently unpossible, as BasCompress was never
     intended to produce anything but compressed code.  (There are many
     places where "skip until hit non-space" is hard-coded, and it would
     take a rather long time to rationalise these so you could toggle it
     on/off.)  Oh well.









                                  Page  64

 ============================================================ BasCompress ====



 [8.6] Label reduction
     
     The reduction of labels isn't always as good as it could be.
     Currently BasCompress only judges the fitness of a label to be
     reduced on its' global usage.  A better algorithm would take into
     consideration the nesting level of each usage, and use this to bias
     the reduction of labels towards those used inside loops.
     
     
 [8.7] Executable
     
     The current situation, with two separate applications is far from
     ideal.  A better situation would be to have the back end program
     inside a module.  This would have the added bonus of not needing to
     load in the Messages file every time it is run.
     
     Better yet would be to have the whole thing as one big Wimp
     application.  Here many extras are possible because there would be
     direct access to the cross-reference database.  For example it could
     create graphs of variable name distribution, provide the cross-
     reference in it's own window, where you could filter it given user
     criteria (such as name matching a regexp AND usage>3).  But I don't
     think so, do you?



































                                  Page  65

 ============================================================ BasCompress ====



 [A] Messages
     
 [A.1] Internationalism united
     
     For users of a foreign extractment, the Messages directory contains
     the country-specific text files.  Copy Default, to (say) Iceland and
     edit the messages, and if that is the configured country of the
     machine, then those messages will be loaded.  Note it is sensible to
     keep a Default file as this will be loaded if no file of the
     configured country could be found.
     
     If you do make a translated messages file, the author would
     appreciate it greatly if you could send it in so every one can
     benefit.
     
     
 [A.2] Format
     
     The message format is fairly obvious --- just look at them to see
     what can and can't be done, but here's a quick summary.

             o       Comments start with a #
             o       Messages names start on a new line, and end in a
                     colon
             o       Messages start at the first non-space after the
                     colon, and finish at the end of the line
             o       Spaces can be done as "% "
             o       Percents can be included using "%%"
             o       The "parameter"s %s and %d are supplied by
                     BasCompress, these are standard C printf() strings
             o       The standard C escape sequences \b, \t, \n, \r, \xXX,
                     \000, etc. can be used to insert those characters
                     inside the messages
             o       A message may be a selection: starts with a "%?" and
                     consists of a comma separated list of alternatives























                                  Page  66

 ============================================================ BasCompress ====




 [B] Regular expressions
     
     
 [B.1] Definition
     
     A regular expression (RE) is a fancy wild-carding system - i.e.  you
     don't need exact matches.  A regular expression is really a
     mini-programming language with the following "commands":
     
             .     any character
             ^     start of line
             $     end of line
             [...] set of characters(*)
     
     Any other character matches itself
     
     There are also modifiers:
     
             |    or, "re1|re2" match either RE1 or RE2
             ~    not, "~c" matches anything but the next character
             +    many, "re+" matches RE repeated one or more times
             *    repeat, "re+" matches RE repeated zero or more times
             ?    optional, "re?" matches RE repeated zero or one times
     
     Parenthesis () can be used to group REs
     
     Finally, there are memories:
     
             \{   begin recording
             \}   end recording, and place in next memory (starts with 1)
             \<n> \1, ... \9 will then match the corresponding memory
     

 (*) character sets:
     
     Character sets are used to match one of a group of characters.  All
     characters are taken literally except "-", "]", and "\".  The "-"
     indicates a range, unless it is the first or last character, or the
     first character after a previous range.  The "\" can be used to
     include a "]" or a "-" in the set.

