home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 1 / RISC_DISC_1.iso / pd_share / code / bascomp / Manual next >
Encoding:
Text File  |  1994-07-17  |  86.1 KB  |  2,309 lines

  1. A BasicV compressor and
  2. cross-referencer for RISC OS
  3. v1.40 17th July 1993
  4. Copyright © Cy Booker, 1992−1994
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23. Program
  24. and
  25. Documentation
  26.  
  27.  
  28.  
  29. by
  30.  
  31.  
  32.  
  33. Cy Booker
  34.  
  35. 86 Church View
  36.  
  37. Main Road
  38.  
  39. Crockenhill
  40.  
  41. Swanley
  42.  
  43. Kent
  44.  
  45. BR8 8JW
  46.  
  47. U.K.
  48.  
  49.  
  50.  
  51. “Typeset” using Impression v2.14 and Publisher v4.01
  52.  
  53. Menus grabbed by GrabMenu
  54.  
  55. Musical entertainment provided by Frank Zappa
  56.  
  57.  
  58.  
  59. 1 Overview    1
  60.  
  61. 1.1 Disclaimer    1
  62.  
  63. 1.2 Synopsis    1
  64.  
  65. 1.3 Features    1
  66.  
  67. 1.4 Documentation    2
  68.  
  69. 1.5 Compressing your first file    3
  70.  
  71. 1.6 Example speed    3
  72.  
  73. 1.7 Example compression    4
  74.  
  75. 2 BasCompress    5
  76.  
  77. 2.1 Overview    5
  78.  
  79. 2.2 Jargon    5
  80.  
  81. 2.3 Basic    5
  82.  
  83. 2.4 Numbers    6
  84.  
  85. 2.5 SWI's    6
  86.  
  87. 2.6 Star commands    7
  88.  
  89. 2.7 Assembler    7
  90.  
  91. 2.8 Routines    7
  92.  
  93. 2.8.1 Main program    8
  94.  
  95. 2.8.2 Start and end    8
  96.  
  97. 2.8.3 Conditional routine end    8
  98.  
  99. 2.8.4 END and ERROR    9
  100.  
  101. 2.8.5 LOCAL ERROR    9
  102.  
  103. 2.9 Multi-line structures    10
  104.  
  105. 2.10 Libraries    11
  106.  
  107. 2.10.1 Multiply-defined routines in libraries    11
  108.  
  109. 2.11 Label reduction    12
  110.  
  111. 2.12 Line numbers    13
  112.  
  113. 2.12.1 Output line numbers    14
  114.  
  115. 2.13 Multi-line output    14
  116.  
  117. 2.14 DATA    14
  118.  
  119. 2.15 Re-compressing    15
  120.  
  121. 3 Cross-referencing    17
  122.  
  123. 3.1 Overview    17
  124.  
  125. 3.1.1 What's cross-referenced    17
  126.  
  127. 3.1.2 What's output    17
  128.  
  129. 3.1.3 Messages    17
  130.  
  131. 3.2 Level of detail    18
  132.  
  133. 3.2.1 Routine definition    18
  134.  
  135. 3.2.2 Routine calls    19
  136.  
  137. 3.2.3 Routine called by    19
  138.  
  139. 3.2.4 Variable declaration    19
  140.  
  141. 3.2.5 Variable assignment    19
  142.  
  143. 3.2.6 Variable reference    19
  144.  
  145. 3.3 Order    20
  146.  
  147. 4 The front end    21
  148.  
  149. 4.1 Starting    21
  150.  
  151. 4.2 Overview    21
  152.  
  153. 4.2.1 Icon bar icon    21
  154.  
  155. 4.3 Control window    22
  156.  
  157. 4.4 Main menu    23
  158.  
  159. 4.5 Input    24
  160.  
  161. 4.6 Output    26
  162.  
  163. 4.7 Log    29
  164.  
  165. 4.8 Special files    31
  166.  
  167. 4.9 Cross-reference    32
  168.  
  169. 4.10 Choices Dialogue Box    36
  170.  
  171. 5 The back end    39
  172.  
  173. 5.1 Invoking    39
  174.  
  175. 5.2 Installing    39
  176.  
  177. 5.3 Environment variables    40
  178.  
  179. 5.4 The CLI parameters    41
  180.  
  181. 5.4.1 Input    41
  182.  
  183. 5.4.2 Output    42
  184.  
  185. 5.4.2.1 Output listing    42
  186.  
  187. 5.4.3 Log    43
  188.  
  189. 5.4.4 Special    43
  190.  
  191. 5.4.5 Cross-reference    43
  192.  
  193. 5.4.5.1 What    44
  194.  
  195. 5.4.5.2 How much    44
  196.  
  197. 5.4.5.3 Order    45
  198.  
  199. 5.5 Error handling    46
  200.  
  201. 5.6 Escape handling    46
  202.  
  203. 5.7 Hourglass    46
  204.  
  205. 6 Special files    47
  206.  
  207. 6.1 Why    47
  208.  
  209. 6.2 Files    47
  210.  
  211. 6.3 Format    48
  212.  
  213. 6.3.1 Routines    48
  214.  
  215. 6.3.2 Globals    48
  216.  
  217. 6.3.3 Labels    49
  218.  
  219. 6.3.3.1 Verbatim    50
  220.  
  221. 6.3.3.2 Comma separated    50
  222.  
  223. 6.3.3.3 Full pathname    51
  224.  
  225. 6.3.3.4 Wimp menu    51
  226.  
  227. 6.3.4 Variables as regular expressions    51
  228.  
  229. 6.3.4.1 Example patterns    52
  230.  
  231. 6.3.4.2 Limitations    53
  232.  
  233. 6.3.5 Libraries    53
  234.  
  235. 6.3.6 Include files    54
  236.  
  237. 6.4 Limitations    54
  238.  
  239. 7 Errors    57
  240.  
  241. 7.1 Overview    57
  242.  
  243. 7.2 Warnings    57
  244.  
  245. 7.3 Errors    63
  246.  
  247. 7.4 Run-time errors    69
  248.  
  249. 7.4.1 Unknown or missing variable    69
  250.  
  251. 7.4.2 No such function/procedure    69
  252.  
  253. 7.4.3 Missing ENDIF    69
  254.  
  255. 7.4.4 Logical errors    70
  256.  
  257. 7.5 Internal errors    70
  258.  
  259. 8 Loose ends    73
  260.  
  261. 8.1 Memory usage    73
  262.  
  263. 8.2 Missing THEN    73
  264.  
  265. 8.3 Cross-reference    74
  266.  
  267. 8.4 Statistics    75
  268.  
  269. 8.5 Uncompressed output    75
  270.  
  271. 8.6 Label reduction    76
  272.  
  273. 8.7 Executable    76
  274.  
  275. Appendix A: Messages    77
  276.  
  277. A.1 Internationalism united    77
  278.  
  279. A.2 Format    77
  280.  
  281. Appendix B: Regular expressions    79
  282.  
  283. B.1 Definition    79
  284.  
  285.  
  286.  
  287.  
  288.  
  289. 1 Overview
  290.  
  291. 1.1 Disclaimer
  292.  
  293. 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.
  294.  
  295. 1.2 Synopsis
  296.  
  297. 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.
  298.  
  299. (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).
  300.  
  301. 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..
  302.  
  303. 1.3 Features
  304.  
  305. The main features of BasCompress can be summarised as follows:
  306.  
  307.     •    Checks all multi-line IFs have a matching ENDIF
  308.  
  309.     •    Checks all CASE's have a matching ENDCASE
  310.  
  311.     •    Checks all WHILE's have a matching ENDWHILE
  312.  
  313.     •    Checks the ellipsis/quotes/brackets on each statement
  314.  
  315.     •    It doesn't balk at the use of line numbers (too much)
  316.  
  317.     •    Loads in explicit LIBRARY files
  318.  
  319.     •    Checks every routine exits cleanly
  320.  
  321.     •    Checks for multiply-defined routines
  322.  
  323.     •    Produces a full cross-reference on all variables and routines, with four levels of detail, and user-definable ordering
  324.  
  325.     •    Variable/routine name reduction, targetting the most used to be the shortest
  326.  
  327.     •    Remove all redundant spaces and REMarks
  328.  
  329.     •    Remove all between-routine junk
  330.  
  331.     •    Concatenation of output lines
  332.  
  333.     •    Remove unused code
  334.  
  335.     •    Reduces numbers to their shortest form
  336.  
  337.     •    Converts SYS and SWI strings to numbers
  338.  
  339.     •    Optional “special” file to handle EVALuated variables/functions, and implicitly loaded library files
  340.  
  341.     •    "special" file allows variables to be defined as regular expressions
  342.  
  343.     •     It is fast
  344.  
  345.  
  346.  
  347. In other words it does all you would expect, a bit more, and all at a very respectable speed.
  348.  
  349. 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.
  350.  
  351. 1.4 Documentation
  352.  
  353. 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 §3, a chapter on the powerful cross-referencing available.  Not until §4 is the program itself described, the Wimp front end application.  The back end application, accessible from the CLI is §5.  Special files, their format and use are detailed in §6.  §7 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, §8 contains miscellanea, the junk that doesn't categorise too easily.
  354.  
  355. 1.5 Compressing your first file
  356.  
  357. 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.
  358.  
  359. First of all drag the Log file icon to a Filer window (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.
  360.  
  361. 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.
  362.  
  363. 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 Filer window and start again.
  364.  
  365. 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 :-)
  366.  
  367. Voila, a compressed basic file has been produced.
  368.  
  369. 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).
  370.  
  371. Now read §2.
  372.  
  373. 1.6 Example speed
  374.  
  375. 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.
  376.  
  377. 1.7 Example compression
  378.  
  379. Here's how well BasCompress handles compressing an early version of the Wimp front end application:
  380.  
  381.     192742    Total input size
  382.  
  383.     29659    Maximum compression
  384.  
  385.     29706    No decimal number analysis
  386.  
  387.     31129    No SWI name analysis
  388.  
  389.     35103    No concatenation of output lines
  390.  
  391.     47421    No removal of unused code
  392.  
  393.     51950    No reduction of labels
  394.  
  395. The later ones are not accumulative, the non-reduction of labels (only) really does add on 57% to the output program size!
  396.  
  397.  
  398.  
  399. 2 BasCompress
  400.  
  401. 2.1 Overview
  402.  
  403. This chapter concerns itself with Basic, and what BasCompress expects (and does) to it.
  404.  
  405. 2.2 Jargon
  406.  
  407. The following terms will be used quite frequently, so I'll explain what is meant by them:
  408.  
  409.     routine    a procedure or function
  410.  
  411.     variable    an (integer | real | string)[array]
  412.  
  413.     label        the name of a routine or variable
  414.  
  415.     name    a label with its (pre | post)fix
  416.  
  417.  
  418.  
  419. E.g. the following table might help
  420.  
  421.     name    label
  422.  
  423.     PROC_Zappa    _Zappa
  424.  
  425.     Frank%    Frank
  426.  
  427.     Cy$()    Cy
  428.  
  429. 2.3 Basic
  430.  
  431. 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.
  432.  
  433. Only one Basic file is parsed (but see §2.10).
  434.  
  435. 2.4 Numbers
  436.  
  437. 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.
  438.  
  439. 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.
  440.  
  441. Analysis of hexadecimal and binary numbers is always done, as this does not require any floating point math.
  442.  
  443. 2.5 SWI's
  444.  
  445. 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.
  446.  
  447. 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!)
  448.  
  449. 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").
  450.  
  451. Both SYS calls (in Basic) and SWI calls (in assembler) are converted.
  452.  
  453. 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.
  454.  
  455. 2.6 Star commands
  456.  
  457. 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", "...".
  458.  
  459. 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.
  460.  
  461. 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.
  462.  
  463. 2.7 Assembler
  464.  
  465. 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.
  466.  
  467. 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.
  468.  
  469. Note that the single space left after some mnemonics is necessary, without it the Basic assembler will refuse to work.
  470.  
  471. 2.8 Routines
  472.  
  473. 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).
  474.  
  475. 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.
  476.  
  477. 2.8.1 Main program
  478.  
  479. 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.
  480.  
  481. 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.
  482.  
  483. 2.8.2 Start and end
  484.  
  485. The start of a Basic routine is very easily detected, it is a line that starts with DEF FN or DEF PROC.
  486.  
  487. 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.
  488.  
  489. 2.8.3 Conditional routine end
  490.  
  491. For example, consider the following function:
  492.  
  493.     DEF FNmin(a, b)
  494.  
  495.       IF a>b THEN =b ELSE =a
  496.  
  497. 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.
  498.  
  499. So what BasCompress does is to ignore exits from a routine that occur on the same line as an IF.
  500.  
  501. But, in the above example, the next line will be thought to be inside the function min.  This usually results in a cascade of warning/error messages being generated.  The only cure for it is to amend the offending function.  The simplest way is to just put a dummy terminator in, e.g.
  502.  
  503.     DEF FNmin(a, b)
  504.  
  505.       IF a>b THEN =b ELSE =a
  506.  
  507.     = 0
  508.  
  509. Better yet, would be to code it “properly”:
  510.  
  511.     DEF FNmin(a, b)
  512.  
  513.       IF a>b THEN a=b
  514.  
  515.     = a
  516.  
  517.  
  518.  
  519. 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 §2.9.
  520.  
  521. 2.8.4 END and ERROR
  522.  
  523. 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 afterwards.
  524.  
  525. 2.8.5 LOCAL ERROR
  526.  
  527. BasCompress fully recognises local error handlers, and will force the next input line to start a new output line accordingly.
  528.  
  529. 2.9 Multi-line structures
  530.  
  531. BasCompress keeps track of the current nesting level of all multi-line structures:
  532.  
  533.     •    CASE ... ENDCASE
  534.  
  535.     •    IF THEN ... ENDIF
  536.  
  537.     •    REPEAT ... UNTIL
  538.  
  539.     •    WHILE ... ENDWHILE
  540.  
  541. 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.
  542.  
  543. 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.
  544.  
  545. Secondly, and just as less seriously, BasicV is rather lax in it's attitude towards multi-line structures.  For example:
  546.  
  547.     REPEAT
  548.  
  549.       i += 1
  550.  
  551.       CASE x(i) OF
  552.  
  553.       WHEN 1:
  554.  
  555.         IF do_it THEN
  556.  
  557.           UNTIL FALSE:ENDPROC
  558.  
  559.         ENDIF
  560.  
  561.         ...
  562.  
  563.       ...
  564.  
  565.       ENDCASE
  566.  
  567.     UNTIL i>max_i
  568.  
  569. 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.
  570.  
  571. 2.10 Libraries
  572.  
  573. 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.
  574.  
  575. 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 §6.
  576.  
  577. All LIBRARY files are only ever scanned once, even if it is included many times.
  578.  
  579. 2.10.1 Multiply-defined routines in libraries
  580.  
  581. 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!
  582.  
  583. 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.
  584.  
  585. 2.11 Label reduction
  586.  
  587. 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.
  588.  
  589. 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.
  590.  
  591. 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!
  592.  
  593. 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 §6 for more info.
  594.  
  595. 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.
  596.  
  597. 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.
  598.  
  599. BasCompress can handle any number of labels, well as many as could fit into 16Mb of RAM :-)
  600.  
  601. 2.12 Line numbers
  602.  
  603. 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).
  604.  
  605. Obviously, line numbers found in any library files are faulted as there is no valid reason for them being there.
  606.  
  607. 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.
  608.  
  609. 2.12.1 Output line numbers
  610.  
  611. 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.
  612.  
  613. 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.
  614.  
  615. 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.
  616.  
  617. 2.13 Multi-line output
  618.  
  619. 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.
  620.  
  621. 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.
  622.  
  623. 2.14 DATA
  624.  
  625. 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.
  626.  
  627. Please note that variables used as DATA will require the use of Special files.
  628.  
  629. 2.15 Re-compressing
  630.  
  631. Although at first sight the notion of compressing an already compressed file may seem a waste of time, in actual fact it is not.
  632.  
  633. 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.
  634.  
  635. If the output is fed back into BasCompress these extra colons will be removed, as it will be obvious that they are truly redundant.
  636.  
  637. This is best achieved by first compressing 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.
  638.  
  639.  
  640.  
  641. 3 Cross-referencing
  642.  
  643. 3.1 Overview
  644.  
  645. 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).
  646.  
  647. Note that the cross-referencing of variables and routines is completely independent.
  648.  
  649. 3.1.1 What's cross-referenced
  650.  
  651. 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.
  652.  
  653. 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.
  654.  
  655. 3.1.2 What's output
  656.  
  657. 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.
  658.  
  659. 3.1.3 Messages
  660.  
  661. 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):-
  662.  
  663.     Name    Show label and its' qualifying string (“%s%s”)
  664.  
  665.     Comma    Separates distinct references (“, ”)
  666.  
  667.     SemiColon    Separates similar references (“; ”)
  668.  
  669. 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:
  670.  
  671.     Name:    \n\t%s%s
  672.  
  673.     Comma:    \n\t
  674.  
  675.     SemiColon:    ,% 
  676.  
  677. 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)
  678.  
  679. 3.2 Level of detail
  680.  
  681. There are four levels of detail supported by BasCompress:
  682.  
  683.     None    suppresses output, obvious really
  684.  
  685.     Existence    useful to just list the name of all the labels used
  686.  
  687.     Global    gives the additional information of a count of the label usage
  688.  
  689.     Routine    reports only each separate routine where a reference was made, this is probably the most useful option
  690.  
  691.     Line    details the exact statement for every reference
  692.  
  693. 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.
  694.  
  695. Note that the main program itself is treated internally as a procedure, and so appears in the routine cross-reference.
  696.  
  697. 3.2.1 Routine definition
  698.  
  699. This gives the file and line numbers of the start and end of the routine.
  700.  
  701. 3.2.2 Routine calls
  702.  
  703. Lists the names of the routines called by this routine, and the line number of the call.
  704.  
  705. 3.2.3 Routine called by
  706.  
  707. Lists the names of the routines that calls this routine, and the line number of the call.
  708.  
  709. If the list is empty then BasCompress knows that this routine is not needed in the output program, and so will not include it.
  710.  
  711. 3.2.4 Variable declaration
  712.  
  713. Where a label was “declared”.  By this BasCompress means it is a formal parameter of a routine, or explicitly declared as LOCAL.
  714.  
  715. 3.2.5 Variable assignment
  716.  
  717. When ever a variable appears at the start of a statement.  This includes assembler statements.
  718.  
  719. Note that BasCompress sometimes thinks variable assignments are references.  This happens in the following cases:
  720.  
  721.     •    variable is passed to a routine with RETURN parameters
  722.  
  723.     •    assignment after a one-line IF that is without a THEN
  724.  
  725. Here's an example of the later:
  726.  
  727.     IF x<y x=y
  728.  
  729. 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 §8.2.
  730.  
  731. 3.2.6 Variable reference
  732.  
  733. Any other instance of a variable other than the above two is taken to be a reference.
  734.  
  735. BasCompress will not recognise the fact that x += 1 is actually both an assignment and a reference.
  736.  
  737. BasCompress will also fail to recognise that var!0 = 1 only references var and does not assign to it.
  738.  
  739. 3.3 Order
  740.  
  741. 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!
  742.  
  743. You can sort in either direction - top to bottom, or the more usual bottom to top.
  744.  
  745. These are the following sort types currently supported:
  746.  
  747.     Name    in Ascii order
  748.  
  749.     Type    for routines: function, procedure
  750.  
  751.             for variables: integer, real, string, integer array, real array, string array
  752.  
  753.     Dictionary    by name, but as it would appear in a dictionary
  754.  
  755.     Location    the location of the reference
  756.  
  757.     Usage    for routines: number of times it is called
  758.  
  759.             for variables: sum of the assignments and the references
  760.  
  761. Note the needed for multi-level sorting.  You would normally sort labels by name, and type; and references by name, type, and location.
  762.  
  763. 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.
  764.  
  765.  
  766.  
  767. 4 The front end
  768.  
  769. 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.
  770.  
  771. 4.1 Starting
  772.  
  773. A standard Archimedes application, just double-click the Filer icon to install the application onto the icon bar.
  774.  
  775. For foreign users, see the appendix A describing the Message file .
  776.  
  777. 4.2 Overview
  778.  
  779. Because the back end works on, and produces, a number of whole files the format of this application is slightly unorthodox.
  780.  
  781. Basically you use the standard Risc-Os method of dragging file icons to Filer windows (to define the output files), and then drag a basic file onto the application to invoke the back end application to compress it.  This generates the new log, cross-reference, and output files.
  782.  
  783. Not all of the output files need to be defined.  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.
  784.  
  785. 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.
  786.  
  787. 4.2.1 Icon bar icon
  788.  
  789. The icon bar icon shows some messages while the back end is active.  This gives a visual reference to what is going on.
  790.  
  791. Clicking SELECT on the icon bar icon brings the control window to the front of the window stack.
  792.  
  793. Clicking ADJUST in the icon bar icon re-loads the last input file, using the new options.  This is extremely handy.
  794.  
  795. 4.3 Control window
  796.  
  797.  
  798.  
  799.  
  800.  
  801. 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.
  802.  
  803. 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.
  804.  
  805. 4.4 Main menu
  806.  
  807.  
  808.  
  809.  
  810.  
  811. There is only one menu.
  812.  
  813. 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.
  814.  
  815. 4.5 Input
  816.  
  817.  
  818.  
  819.  
  820.  
  821. This sub-menu defines various parameters affecting BasCompress's analysis of the input file.
  822.  
  823. Allow multiply-defined routines
  824.  
  825. 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.
  826.  
  827. Ticking this option allows a routine to be defined more than once, with only warnings being given.  See §2.10.1.
  828.  
  829. Report multiple exits from a routine
  830.  
  831. 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 §2.8.3.
  832.  
  833. Parse numbers
  834.  
  835. This toggles whether BasCompress will try to reduce a string of decimal digits.  Hexadecimal and binary numbers are always compressed.  See §2.4.
  836.  
  837. Convert SWIs to numbers
  838.  
  839. There doesn't appear to be any reason to disable this.  See §2.5.
  840.  
  841. Force malformed SWI's to generate error
  842.  
  843. 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 §2.5.
  844.  
  845. Report unknown SWI's
  846.  
  847. 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 §2.5.
  848.  
  849. Process as a library file
  850.  
  851. 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.
  852.  
  853. 4.6 Output
  854.  
  855.  
  856.  
  857.  
  858.  
  859. 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.
  860.  
  861. By default all compression is on.
  862.  
  863. Save as
  864.  
  865. This leads to a standard dialogue box, used to define the basic file that will be produced if the input is analysed without error.
  866.  
  867. Concatenate lines
  868.  
  869. 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 §2.13.
  870.  
  871. Remove unused routines
  872.  
  873. 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.
  874.  
  875. List
  876.  
  877. 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.
  878.  
  879. Reduce variable names
  880.  
  881.  
  882.  
  883.  
  884.  
  885. 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 §2.11.
  886.  
  887. 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 §8.12.
  888.  
  889. Reduce routine names
  890.  
  891.  
  892.  
  893.  
  894.  
  895. By default, all procedure and function names are reduced.  The only conceivable use 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.
  896.  
  897. 4.7 Log
  898.  
  899.  
  900.  
  901.  
  902.  
  903. 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.
  904.  
  905. Save as
  906.  
  907. 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.
  908.  
  909.  
  910.  
  911. Statistics
  912.  
  913. This shows how many of each type of variable and routine there is altogether in the program.  This includes all deleted labels.
  914.  
  915.  
  916.  
  917. EVAL keyword
  918.  
  919. DATA keyword
  920.  
  921. READ keyword
  922.  
  923. 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.
  924.  
  925. List input
  926.  
  927. 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.
  928.  
  929. 4.8 Special files
  930.  
  931.  
  932.  
  933.  
  934.  
  935. 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.
  936.  
  937. 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.
  938.  
  939. Warn undefined
  940.  
  941. 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.
  942.  
  943. Show expansion
  944.  
  945. 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.
  946.  
  947. 4.9 Cross-reference
  948.  
  949.  
  950.  
  951.  
  952.  
  953. From here you define all aspects of the (rather large) cross-referencing sub-system.
  954.  
  955. Save as
  956.  
  957. 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.
  958.  
  959. Include deleted
  960.  
  961. 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.
  962.  
  963. Reference order
  964.  
  965. 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.
  966.  
  967. Variables
  968.  
  969. Routines
  970.  
  971.  
  972.  
  973.  
  974.  
  975. These two items lead into identical sub-menus.  They allow the cross-referencing to be defined for both independently.
  976.  
  977. Verbosity
  978.  
  979. This leads to a sub-menu where you can define the level of detail of the cross-referencing information.  See §3.2.
  980.  
  981. Types
  982.  
  983. 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.
  984.  
  985. Order
  986.  
  987.  
  988.  
  989.  
  990.  
  991. 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 recurses on each smaller and smaller sub-sequence to the columns on the right.
  992.  
  993. Obviously, it isn't much use having two columns sorting by the same criteria, so BasCompress will not allow you to select it.
  994.  
  995. 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 :-)
  996.  
  997. 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 :-)
  998.  
  999. 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!
  1000.  
  1001. Ordering by location is only meaningful for references.  Using this option for variables or routines will result in a (seemingly) random order.
  1002.  
  1003. The Dict. standards for dictionary, and is similar to Name, except instead of ordering by ASCII, order as it would appear in a... (guess).
  1004.  
  1005. 4.10 Choices Dialogue Box
  1006.  
  1007.  
  1008.  
  1009.  
  1010.  
  1011. This dialogue bog 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..
  1012.  
  1013. Set
  1014.  
  1015. 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.
  1016.  
  1017. Cancel
  1018.  
  1019. This disregards any edits you have made to the above options.
  1020.  
  1021. Save full
  1022.  
  1023. 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.
  1024.  
  1025.  
  1026.  
  1027. Save
  1028.  
  1029. 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.
  1030.  
  1031. Default
  1032.  
  1033. 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.
  1034.  
  1035. Run BasCompressed file
  1036.  
  1037. 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 :-)
  1038.  
  1039. Load log file
  1040.  
  1041. 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.
  1042.  
  1043. Load cross-reference file
  1044.  
  1045. Same as the above option, but loads the cross-reference file generated, if any.
  1046.  
  1047. Name output as <Main>
  1048.  
  1049. 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.
  1050.  
  1051. Output file leaf name same as input
  1052.  
  1053. 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.
  1054.  
  1055. Use outline fonts in dialogue boxes
  1056.  
  1057. 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 :(
  1058.  
  1059. Note that for historical reasons changes to this option are not updated immediately but only take effect the next time BasCompress is run.
  1060.  
  1061.  
  1062.  
  1063. 5 The back end
  1064.  
  1065. This chapter describes the underlying CLI program, and how to use it effectively.
  1066.  
  1067. By default all text output is to the screen.  This can be redirected to separate log and cross-reference files, as required.
  1068.  
  1069. 5.1 Invoking
  1070.  
  1071. Double-clicking on the application directory from a Filer window will automatically start up the Wimp front end application.  This is because no parameters were passed to the !Run file.
  1072.  
  1073. 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.
  1074.  
  1075. 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).
  1076.  
  1077. Also required to be resident is the authors' own library module: CAssembler.
  1078.  
  1079. These modules are automatically loaded if not resident.
  1080.  
  1081. 5.2 Installing
  1082.  
  1083. 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.
  1084.  
  1085. 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.
  1086.  
  1087. 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.
  1088.  
  1089. 5.3 Environment variables
  1090.  
  1091. 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.
  1092.  
  1093. BasCompress$Options
  1094.  
  1095.         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.
  1096.  
  1097. BasCompress$Output
  1098.  
  1099.         The name of the tokenised basic file produced.
  1100.  
  1101. BasCompress$Log
  1102.  
  1103.         The name of the log file produced.
  1104.  
  1105. BasCompress$XRef
  1106.  
  1107.         The name of the cross-reference file produced.
  1108.  
  1109. BasCompress$Special
  1110.  
  1111.         The name of the special file(s) input (a comma separated list).
  1112.  
  1113. BasCompress$Path
  1114.  
  1115.         A comma separated list of directories used to find Special files
  1116.  
  1117. It should be noted that the front end application resets all of these variables (except the Path), so keep this in mind.
  1118.  
  1119. 5.4 The CLI parameters
  1120.  
  1121. The ordering of the parameters has been carefully set up so there is usually no need to name any parameters.
  1122.  
  1123.     BasCompress [-In] <file>
  1124.  
  1125.          [[-Out <file>]
  1126.  
  1127.          [[-Special] <files>]
  1128.  
  1129.          [[-Log] <file>]
  1130.  
  1131.          [[-XRefFile] <file>]
  1132.  
  1133.          [[-XRef] <n>]
  1134.  
  1135.          ...
  1136.  
  1137. So for normal work you would have set up BasCompress$Options and you'd just do BasCompress @.MyProg @.Result @.Special @.Log "" 0.
  1138.  
  1139. There is a -Help option to display a brief description of the available options.
  1140.  
  1141. As with all all native Archimedes applications, switches toggle the previous state (OS_ReadArgs does not allow -f and +f).
  1142.  
  1143. 5.4.1 Input
  1144.  
  1145.  
  1146.  
  1147. -In <file>    this must always be given
  1148.  
  1149. -Library    ignore undefined routines & main program (OFF) §2.8.1
  1150.  
  1151. -MultiDEF    allow multiple definitions of the same routine (OFF) §2.10.1
  1152.  
  1153. -Number    analyse decimal numbers (needs FPEmulator) (ON) § 2.4
  1154.  
  1155. -SWI        convert SWI strings to numbers (ON) §2.5
  1156.  
  1157. -SWIBad    fault malformed SWI names (OFF) §2.5
  1158.  
  1159. -SWIExist    report unknown SWI strings (ON) §2.5
  1160.  
  1161. -WEndRtn    report conditional exits (ON) §2.8.3
  1162.  
  1163. 5.4.2 Output
  1164.  
  1165.  
  1166.  
  1167. -ListOut <n>    echo output in screen mode <n> (OFF)
  1168.  
  1169. -Out <file>    output file (see BasCompress$Output)
  1170.  
  1171. -ReduceVar <type>
  1172.  
  1173. -ReduceRtn <type>
  1174.  
  1175. -Reduce <type>    reduce these types of labels (irsIRSpf) §2.11
  1176.  
  1177. -Single    no concatenation of output lines (OFF) §2.13
  1178.  
  1179. -Unused    delete unused routines and variables (ON) §2.8
  1180.  
  1181.  
  1182.  
  1183. <type> is a string of these letters:
  1184.  
  1185.     p    procedure
  1186.  
  1187.     f    function
  1188.  
  1189.     r    real variable
  1190.  
  1191.     i    integer variable
  1192.  
  1193.     s    string variable
  1194.  
  1195.     R    real array variable
  1196.  
  1197.     I    integer array variable
  1198.  
  1199.     S    string array variable
  1200.  
  1201. 5.4.2.1 Output listing
  1202.  
  1203. 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.
  1204.  
  1205. 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.
  1206.  
  1207. There isn't really much use for this option, as the time taken to scroll the screen takes far too long.
  1208.  
  1209. 5.4.3 Log
  1210.  
  1211.  
  1212.  
  1213. -DATA        log lines containing DATA (ON)
  1214.  
  1215. -EVAL        log lines containing EVAL (ON)
  1216.  
  1217. -Goto        log lines containing line numbers (ON)
  1218.  
  1219. -List        echo input to log (OFF)
  1220.  
  1221. -Log <file>    output file (see BasCompress$Log)
  1222.  
  1223. -READ        log lines containing READ (ON)
  1224.  
  1225. -Stats        log program statistics (ON)
  1226.  
  1227. 5.4.4 Special
  1228.  
  1229.  
  1230.  
  1231. -Special <files>    use comma list of <file> to resolve implicit usages (see BasCompress$Special and BasCompress$Path)
  1232.  
  1233. -UnusedS    report undefined special routines (OFF)
  1234.  
  1235. -WSpLabel    report label expansion results (OFF)
  1236.  
  1237. 5.4.5 Cross-reference
  1238.  
  1239.  
  1240.  
  1241. -XRefFile <file>    output file (see BasCompress$XRef)
  1242.  
  1243. 5.4.5.1 What
  1244.  
  1245.  
  1246.  
  1247. -Deleted    xref includes deleted variables and routines (OFF)
  1248.  
  1249. -XIncVar <type>
  1250.  
  1251. -XIncRtn <type>
  1252.  
  1253. -XInc <type>    xref these types of labels (irsIRSpf) §3.1.1
  1254.  
  1255.  
  1256.  
  1257. <type> is a string of these letters:
  1258.  
  1259.     p    procedure
  1260.  
  1261.     f    function
  1262.  
  1263.     r    real variable
  1264.  
  1265.     i    integer variable
  1266.  
  1267.     s    string variable
  1268.  
  1269.     R    real array variable
  1270.  
  1271.     I    integer array variable
  1272.  
  1273.     S    string array variable
  1274.  
  1275. 5.4.5.2 How much
  1276.  
  1277.  
  1278.  
  1279. -XRef <n>    level of xref detail for both routines and variables §3.2
  1280.  
  1281. -XRtn <n>    level of xref detail for routines (0)
  1282.  
  1283. -XVar <n>    level of xref detail for variables (0)
  1284.  
  1285.  
  1286.  
  1287. <n> evaluates to a number from 0 to 4:
  1288.  
  1289.     0    None
  1290.  
  1291.     1    Existence - name
  1292.  
  1293.     2    Global - name / count
  1294.  
  1295.     3    Routine - reference to routine level
  1296.  
  1297.     4    Line - reference to line level
  1298.  
  1299. 5.4.5.3 Order
  1300.  
  1301.  
  1302.  
  1303. -Sort <sort>    order of all variable, routine, and reference sorting §3.3
  1304.  
  1305. -SRef <sort>    order of cross–references (NTP)
  1306.  
  1307. -SRtn <sort>    order of routines (TN)
  1308.  
  1309. -SVar <sort>    order of variables (TN)
  1310.  
  1311.  
  1312.  
  1313. <sort> is a string of these letters:
  1314.  
  1315.     N    sort by name
  1316.  
  1317.     T    sort by type
  1318.  
  1319.     D    sort by name (in dictionary sense)
  1320.  
  1321.     P    sort by position in source
  1322.  
  1323.     U    sort by usage
  1324.  
  1325. e.g. to sort by usage, name, then type = “UNT”.
  1326.  
  1327. Lower case letters order top to bottom.
  1328.  
  1329. 5.5 Error handling
  1330.  
  1331. By errors, it is meant system errors (i.e. those generated by calls to the operating system).
  1332.  
  1333. 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.
  1334.  
  1335. Errors occurring before the log file is opened are reported to the screen.
  1336.  
  1337. In any case, an error safely closes all files opened by this application.
  1338.  
  1339. 5.6 Escape handling
  1340.  
  1341. As with error handling, this is fairly primitive.
  1342.  
  1343. BasCompress can be aborted at any time, terminating immediately after closing all open files.
  1344.  
  1345. 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).
  1346.  
  1347. 5.7 Hourglass
  1348.  
  1349. The hourglass is used to indicate BasCompress's progress.
  1350.  
  1351. 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.
  1352.  
  1353. During cross referencing, there is no percentage, but the bottom L.E.D. is on.
  1354.  
  1355. Finally, during program output an accurate percentage is displayed, with the top L.E.D. on.
  1356.  
  1357.  
  1358.  
  1359. 6 Special files
  1360.  
  1361. 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.
  1362.  
  1363. 6.1 Why
  1364.  
  1365. Special files are used to tell BasCompress how to cope with the following types of situation:
  1366.  
  1367.     •    EVAL("Variable")
  1368.  
  1369.     •    DATA Variable
  1370.  
  1371.     •    LIBRARY "%."+ RoutineParameter$
  1372.  
  1373.     •    EVAL("FN_"+ RoutineParameter$)
  1374.  
  1375. Because BasCompress reduces labels (see §2.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.
  1376.  
  1377. 6.2 Files
  1378.  
  1379. 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.
  1380.  
  1381. 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.
  1382.  
  1383. 6.3 Format
  1384.  
  1385. The format of a Special file is fairly simple.
  1386.  
  1387. Basically, (for variables) all you're trying to tell BasCompress is:
  1388.  
  1389.     •    routine X has a string in parameter Y
  1390.  
  1391.     •    inside routine X there is an EVAL
  1392.  
  1393.     •    this constructs a new label Z from Y
  1394.  
  1395.     •    don't reduce this label Z
  1396.  
  1397. So all you do is give the name and expected parameters of a routine and tell BasCompress how to construct label Z.
  1398.  
  1399. 6.3.1 Routines
  1400.  
  1401. You give the name of a routine by:
  1402.  
  1403.     procedure foo(1)
  1404.  
  1405. or,
  1406.  
  1407.     function bar(,1)
  1408.  
  1409. The brackets are necessary if a routine doesn't have any parameters.
  1410.  
  1411. 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.
  1412.  
  1413. These prototypes are checked against what is actually found in the program proper, and an appropriate error generated if they don't match.
  1414.  
  1415. There can be up to ten distinct string parameters [0-9], but you'll probably only ever need just one.
  1416.  
  1417. 6.3.2 Globals
  1418.  
  1419. 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.
  1420.  
  1421. 6.3.3 Labels
  1422.  
  1423. First of all an example:
  1424.  
  1425.     PROC_List(a, "Zappa", "Good")
  1426.  
  1427.     ...
  1428.  
  1429.     :
  1430.  
  1431.     DEF PROC_List(RETURN x, y$, z$)
  1432.  
  1433.       IF EVAL("Frank_"+ y$)<>0 THEN
  1434.  
  1435.           x += EVAL("FN_"+ z$+ "_Name(Cy%)")
  1436.  
  1437.       ENDIF
  1438.  
  1439.     ENDPROC
  1440.  
  1441. this would be implemented as:
  1442.  
  1443.     procedure _List(, 1, 2)
  1444.  
  1445.       real Frank_\1
  1446.  
  1447.       function _\2_Name
  1448.  
  1449.       integer Cy%
  1450.  
  1451. 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.
  1452.  
  1453. 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.
  1454.  
  1455. The following table shows the exact words to use - note they must be lower case:
  1456.  
  1457.     real    a real variable e.g. pi_by_2
  1458.  
  1459.     integer    an integer variable, e.g. count%
  1460.  
  1461.     string    a string variable, e.g name$
  1462.  
  1463.     real_array    a real array variable, e.g. times()
  1464.  
  1465.     integer_array    an integer variable, e.g. books%()
  1466.  
  1467.     string_array    a string variable, e.g. titles$()
  1468.  
  1469.     procedure    a procedure, e.g. PROC_total
  1470.  
  1471.     function    a function, e.g. FNmin
  1472.  
  1473.     library    load library file, e.g. %.Wimp
  1474.  
  1475. BasCompress can currently interpret the simple string in a number of ways.  These template expansion types are:
  1476.  
  1477. 6.3.3.1 Verbatim
  1478.  
  1479. \<n>    causes the formal parameter <n> to be substituted verbatim.
  1480.  
  1481. 6.3.3.2 Comma separated
  1482.  
  1483. ,<n>    treats parameter <n> as a comma separated list of strings to substitute, with optional spaces after each comma.
  1484.  
  1485. Each value is extracted from the string in turn.  Note that the string is expected to contain real variables only, i.e. no %, $, or (.
  1486.  
  1487. For example:
  1488.  
  1489.     PROC_Music("Zappa,Varese,Stravinsky,Belew)
  1490.  
  1491.     ...
  1492.  
  1493.     :
  1494.  
  1495.     DEF PROC_Music(p$)
  1496.  
  1497.     LOCAL i, dummy
  1498.  
  1499.       i = INSTR(p$, ",")
  1500.  
  1501.       WHILE i>0
  1502.  
  1503.         dummy = EVAL("FN_"+ LEFT$(p$, i-1))
  1504.  
  1505.         p$ = MID$(p$, i+1)
  1506.  
  1507.         i = INSTR(p$, ",")
  1508.  
  1509.       ENDWHILE
  1510.  
  1511.     ENDPROC
  1512.  
  1513. could get coded as:
  1514.  
  1515.     procedure _Music(1)
  1516.  
  1517.       function _,1
  1518.  
  1519. 6.3.3.3 Full pathname
  1520.  
  1521. @<n>    parameter <n> is considered as a full pathname, and just the leaf name is substituted.
  1522.  
  1523. For an example see §6.3.4 below.
  1524.  
  1525. 6.3.3.4 Wimp menu
  1526.  
  1527. »<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.
  1528.  
  1529. It is assumed that the implicit variables are all of the same type.  If not just define several rules, one for each type.
  1530.  
  1531. For example
  1532.  
  1533.     PROC_menu("Prog,Info>Info%,dSave as>SaveAs,Quit")
  1534.  
  1535. may get coded as follows:
  1536.  
  1537.     procedure _menu(1)
  1538.  
  1539.       integer »1
  1540.  
  1541.       real »1
  1542.  
  1543. 6.3.4 Variables as regular expressions
  1544.  
  1545. 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.
  1546.  
  1547. Special variables so specified can not contain any parameter substitution commands.  They also behave in a slightly different manner.
  1548.  
  1549. 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.
  1550.  
  1551. 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.
  1552.  
  1553. 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.
  1554.  
  1555. 6.3.4.1 Example patterns
  1556.  
  1557. Here's how you would write the above example in a special file:
  1558.  
  1559.     procedure dummy()
  1560.  
  1561.         real Wimp_.*
  1562.  
  1563. 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.
  1564.  
  1565. Another frequent case is when variables have the same postfix - eg the pattern:
  1566.  
  1567.     integer .*CMOS\>
  1568.  
  1569. 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.
  1570.  
  1571. 6.3.4.2 Limitations
  1572.  
  1573. 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.
  1574.  
  1575. 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.
  1576.  
  1577. 6.3.5 Libraries
  1578.  
  1579. As well as labels, libraries may be implicit.  For example, here's a simple library handler:
  1580.  
  1581.     PROC_Load_Library("<Basic$Lib>.Wimp", 2)
  1582.  
  1583.     ...
  1584.  
  1585.     :
  1586.  
  1587.     DEF PROC_Load_Library(f$, v)
  1588.  
  1589.     LOCAL x
  1590.  
  1591.       LIBRARY file$
  1592.  
  1593.       x = EVAL("FN_Init_"+ FNleaf(f$))
  1594.  
  1595.       IF EVAL("Version_"+ FNleaf(f$))<v THEN
  1596.  
  1597.         ERROR 1, "Library too old"
  1598.  
  1599.       ENDIF
  1600.  
  1601.     ENDPROC
  1602.  
  1603. 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:
  1604.  
  1605.     procedure _Load_Library(1,)
  1606.  
  1607.       library \1
  1608.  
  1609.       function _Init_@1
  1610.  
  1611.       real Version_@1
  1612.  
  1613. Note the use of @<n> to extract the leaf name.
  1614.  
  1615. In the output program the entire statement containing the LIBRARY is removed.
  1616.  
  1617. 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 §2.10).
  1618.  
  1619. 6.3.6 Include files
  1620.  
  1621. 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...
  1622.  
  1623.     #include mylibs
  1624.  
  1625. 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).
  1626.  
  1627. 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.
  1628.  
  1629. 6.4 Limitations
  1630.  
  1631. 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.
  1632.  
  1633. 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 :-(
  1634.  
  1635. 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.
  1636.  
  1637.  
  1638.  
  1639. 7 Errors
  1640.  
  1641. 7.1 Overview
  1642.  
  1643. 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:
  1644.  
  1645.     file 1234 warning 3: message
  1646.  
  1647. 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.
  1648.  
  1649. Warnings report non-fatal deficiencies.  Errors report a major problem, and will stop any output file being generated.
  1650.  
  1651. As with all text used by BasCompress, these error texts are held in the Messages file.
  1652.  
  1653. 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.
  1654.  
  1655. 7.2 Warnings
  1656.  
  1657. Most of the warnings are self explanatory.
  1658.  
  1659.  
  1660.  
  1661.     1    Expecting PROC or FN after DEF
  1662.  
  1663. In standard Basic, these are the only valid things after a DEF.  This warning has never been encountered in debugged source!
  1664.  
  1665.  
  1666.  
  1667.     2    DEF inside a routine
  1668.  
  1669. 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>).
  1670.  
  1671.  
  1672.  
  1673.     3    Unexpected period ‘.’
  1674.  
  1675. 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.
  1676.  
  1677.  
  1678.  
  1679.     4    Mismatched quotes ‘"’
  1680.  
  1681. Every line should have matching quotes.
  1682.  
  1683.  
  1684.  
  1685.     5    Malformed hexadecimal number
  1686.  
  1687. It is expected that a digit or a letter [0-9a-fA-F] comes after an &.
  1688.  
  1689.  
  1690.  
  1691.     6    Malformed binary number
  1692.  
  1693. It is expected that a 0 or 1 comes after a %.
  1694.  
  1695.  
  1696.  
  1697.     7    Line number reference found
  1698.  
  1699. This is given if line numbers are found in any libraries, since there is no valid reason for them being there.
  1700.  
  1701.  
  1702.  
  1703.     8    Expecting routine name after PROC or FN
  1704.  
  1705. A non-label character was found after one of these tokens.  This very unlikely.
  1706.  
  1707.  
  1708.  
  1709.     9    ENDPROC not at end of procedure
  1710.  
  1711. 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>).
  1712.  
  1713.  
  1714.  
  1715.     10    = not at end of function
  1716.  
  1717. 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>).
  1718.  
  1719.  
  1720.  
  1721.     11    Code found on last line of function
  1722.  
  1723. 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.
  1724.  
  1725.  
  1726.  
  1727.     12    Expecting a string after LIBRARY/INSTALL
  1728.  
  1729. 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.
  1730.  
  1731.  
  1732.  
  1733.     13    OVERLAY file(s) not scanned
  1734.  
  1735. The OVERLAY keyword is not supported by BasCompress.
  1736.  
  1737.  
  1738.  
  1739.     14    Unexpected ‘[’
  1740.  
  1741. A running total of square brackets is kept.  This indicates that something like “LDR R0, [[R1...]” was found.
  1742.  
  1743.  
  1744.  
  1745.     15    Unexpected ‘]’
  1746.  
  1747. A running total of square brackets is kept.  This indicates that something like “LDR R0, [R1...]]” was found.
  1748.  
  1749.  
  1750.  
  1751.     16    ENDPROC inside a %s structure
  1752.  
  1753. Found a conditional exit from a procedure - this indicates a bad programming style.
  1754.  
  1755.  
  1756.  
  1757.     17    = inside a %s structure
  1758.  
  1759. Found a conditional exit from a function - this indicates a bad programming style.
  1760.  
  1761.  
  1762.  
  1763.     18    Conditional %%s
  1764.  
  1765. Found a conditional termination of a multi-line structure - this indicates a bad programming style.
  1766.  
  1767. This may occur on lines like the following:
  1768.  
  1769.     IF x>0 THEN WHILE x>0:y+=FNy(x):x-=1:ENDWHILE
  1770.  
  1771. 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.
  1772.  
  1773.  
  1774.  
  1775.     19    Too many ‘(’ found
  1776.  
  1777. A running total of ellipsis is kept.  This indicates something like “(1+2)(” was found.
  1778.  
  1779.  
  1780.  
  1781.     20    Unexpected ‘)’ found
  1782.  
  1783. A running total of ellipsis is kept.  This indicates something like “(1+2))” was found.
  1784.  
  1785.  
  1786.  
  1787.     21    Routine %s already defined at %s
  1788.  
  1789. This warns about multiply-defined routines.  Since there are sometimes very good reasons for doing this this warning can be suppressed.
  1790.  
  1791.  
  1792.  
  1793.     22    Malformed decimal number
  1794.  
  1795. 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.
  1796.  
  1797.  
  1798.  
  1799.     23    The (global) special routine %s is not defined anywhere
  1800.  
  1801. This speaks for itself.  It is only generated if the user has asked for it, as it is not usually relevant.
  1802.  
  1803.  
  1804.  
  1805.     24    SWI name missing, or not simple
  1806.  
  1807. 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.
  1808.  
  1809.  
  1810.  
  1811.     25    SWI ‘%s’ is unknown
  1812.  
  1813. 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.
  1814.  
  1815.  
  1816.  
  1817.     26    Can't change to screen mode %d
  1818.  
  1819. If the listing Mode could not be found, but a suitable alternative was possible.
  1820.  
  1821.  
  1822.  
  1823.     27    Special variable %s has been used
  1824.  
  1825.     28    Special routine %s has been used
  1826.  
  1827.     29    Special library %s has been used
  1828.  
  1829. 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.
  1830.  
  1831.  
  1832.  
  1833. 7.3 Errors
  1834.  
  1835. 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.
  1836.  
  1837.  
  1838.  
  1839.     2    ENDPROC found in a function
  1840.  
  1841. 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.
  1842.  
  1843.  
  1844.  
  1845.     3    = found in a procedure
  1846.  
  1847. 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.
  1848.  
  1849.  
  1850.  
  1851.     4    Routine %s already defined at %s
  1852.  
  1853. It's either an error or a warning (21), and this is the error.
  1854.  
  1855.  
  1856.  
  1857.     5    File error: %s
  1858.  
  1859. 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.
  1860.  
  1861.  
  1862.  
  1863.     6    End of file in middle of routine
  1864.  
  1865. It is invalid for a routine to span across a file boundary.
  1866.  
  1867.  
  1868.  
  1869.     7    Too many files (>254)
  1870.  
  1871. I can't foresee anyone getting this error message!  It is unlikely that this limitation would be lifted, either.
  1872.  
  1873.     8    Undefined routine: %s (used %s)
  1874.  
  1875. 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.
  1876.  
  1877.  
  1878.  
  1879.     9    Undefined variable: %s (used %s)
  1880.  
  1881. Not generated.
  1882.  
  1883.  
  1884.  
  1885.     10    FOR not at start of statement
  1886.  
  1887. This may be of some use - not much, but what the hey?  (Maybe be on a one-line IF)?
  1888.  
  1889.  
  1890.  
  1891.     11    Escape pressed, parsing aborted
  1892.  
  1893. Not generated.  Escapes just terminate program immediately in the current version.
  1894.  
  1895.  
  1896.  
  1897.     12    File %s does not have a Basic file type
  1898.  
  1899. 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?)
  1900.  
  1901.  
  1902.  
  1903.     13    File %s is too small to be a Basic type
  1904.  
  1905. A rudimentary check on each Basic file is done - this is generated if it fails.
  1906.  
  1907.  
  1908.  
  1909.     14    File is corrupted/not basic
  1910.  
  1911. 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.
  1912.  
  1913.  
  1914.  
  1915.     15    Escape pressed, xref aborted
  1916.  
  1917. Not generated.  Escapes just terminate program immediately in the current version.
  1918.  
  1919.  
  1920.  
  1921.     16    Escape pressed, compression aborted
  1922.  
  1923. Not generated.  Escapes just terminate program immediately in the current version.
  1924.  
  1925.  
  1926.  
  1927.     17    Unexpected %s in a %s structure
  1928.  
  1929. 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.
  1930.  
  1931.  
  1932.  
  1933.     18    Unexpected %s
  1934.  
  1935. As error 17 above, but obviously outside any surrounding structure.
  1936.  
  1937.  
  1938.  
  1939.     19    End of file in middle of assembler
  1940.  
  1941. A special case of error 6, i.e. a routine did not end before the end of a file was found.
  1942.  
  1943.  
  1944.  
  1945.     20    OTHERWISE not at start of line
  1946.  
  1947. A simple error for a simple mistake.
  1948.  
  1949.  
  1950.  
  1951.     21    WHEN not at start of line
  1952.  
  1953. A simple error for a simple mistake.
  1954.  
  1955.     22    Computed GOTO/GOSUB found
  1956.  
  1957. Now, I ask you, is this how to program?  BasCompress will refuse to work with such things, and who can blame it?
  1958.  
  1959.  
  1960.  
  1961.     23    INSTALL/LIBRARY not at start of line
  1962.  
  1963. This indicates a syntax error, probably.  Or maybe an IF without a THEN, who knows?
  1964.  
  1965.  
  1966.  
  1967.     24    INSTALL/LIBRARY can not be on a conditional line
  1968.  
  1969. If you must, then split into a multi-line IF and try again.
  1970.  
  1971.  
  1972.  
  1973.     25    The special routine ‘%s’ was declared as having different parameters from those found here
  1974.  
  1975. The number of parameters do not match - probably a wrong number of commas in the Special file.
  1976.  
  1977.  
  1978.  
  1979.     26    The special routine ‘%s’ wants a string constant for one of its' parameters
  1980.  
  1981. This program only handles very simple constant string expressions, and this error indicates that the expression was not simple enough.
  1982.  
  1983.  
  1984.  
  1985.     27    Line too long (max 256)
  1986.  
  1987. This seems a reasonable upper limit on the line length of a Special file.
  1988.  
  1989.  
  1990.  
  1991.     28    Line ‘%s’ is not of a recognised form
  1992.  
  1993. 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.
  1994.  
  1995.     29    Label ‘%s’ is invalid
  1996.  
  1997. In Special files, the label probably starts with a digit, or some such.
  1998.  
  1999.  
  2000.  
  2001.     30    Parameter list ‘%s’ is invalid
  2002.  
  2003. In Special files: what more needs to be said?
  2004.  
  2005.  
  2006.  
  2007.     31    Parameter list ‘%s’ contains a duplicate
  2008.  
  2009. In Special files: it is not exactly meaningful to have two or more parameters assigned to the same expansion number is it?
  2010.  
  2011.  
  2012.  
  2013.     32    Implicit label substitution overflowed
  2014.  
  2015. 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!
  2016.  
  2017.  
  2018.  
  2019.     33    Too many special routines (max 255)
  2020.  
  2021. A perfectly reasonable limit it seems.  This could easily be extended, though.
  2022.  
  2023.  
  2024.  
  2025.     34    Unable to load special file (not Text?)
  2026.  
  2027. Or maybe it wasn't found.  Only Text files are accepted.
  2028.  
  2029.  
  2030.  
  2031.     35    SWI name missing, or not simple
  2032.  
  2033. 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.
  2034.  
  2035.  
  2036.  
  2037.     36    Illegal screen mode
  2038.  
  2039. If the listing mode could not be found, and no suitable alternative was possible, then this error is generated.
  2040.  
  2041.  
  2042.  
  2043.     37    Bad main program, unterminated %s structure
  2044.  
  2045. 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.
  2046.  
  2047.  
  2048.  
  2049.     38    Can't find closing ellipsis in special routine parameter
  2050.  
  2051. 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.
  2052.  
  2053.  
  2054.  
  2055.     39    Bad char `%c' following > or : in special routine parameter
  2056.  
  2057. During label expansion, BasCompress expects the label to be terminated by a comma or the EOS.  This indicates that this condition was not satisfied.
  2058.  
  2059.  
  2060.  
  2061. 7.4 Run-time errors
  2062.  
  2063. Here is some help with possible errors that BasCompress may introduce to the compressed Basic output.
  2064.  
  2065. 7.4.1 Unknown or missing variable
  2066.  
  2067. The quick and easy method to solve this problem is to turn of all label reduction.  This is not recommend, as it makes the use of BasCompress almost worthless.
  2068.  
  2069. This error has been generated because you have not told BasCompress about the side effects of an EVAL or DATA statements.  See §2.11 for why this produces the error, and §6 for how to cure it.
  2070.  
  2071. 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.
  2072.  
  2073. 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.
  2074.  
  2075. 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.
  2076.  
  2077. 7.4.2 No such function/procedure
  2078.  
  2079. This occurs for exactly the same reasons as detailed in §7.4.1 above.
  2080.  
  2081. 7.4.3 Missing ENDIF
  2082.  
  2083. These errors are generated very rarely, but they are just possible.  Consider the following code:
  2084.  
  2085.     IF FN_SaveFile THEN :::REM comment
  2086.  
  2087. What BasCompress could produce, although it does tries not to, is:
  2088.  
  2089.     IFFNxTHEN
  2090.  
  2091. 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.
  2092.  
  2093. 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.
  2094.  
  2095. 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.
  2096.  
  2097. 7.4.4 Logical errors
  2098.  
  2099. 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.
  2100.  
  2101. 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.
  2102.  
  2103. 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.
  2104.  
  2105. 7.5 Internal errors
  2106.  
  2107. 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:
  2108.  
  2109.         Error(s) during parsing
  2110.  
  2111. This should never appear, as it is an internal error used to indicate an erroneous parsing stage.
  2112.  
  2113.  
  2114.  
  2115.         Invalid sort character '%c'
  2116.  
  2117.         Sort string too long
  2118.  
  2119.         Invalid type character `%c'
  2120.  
  2121. These indicate rudimentary errors on the parameters passed on the CLI.
  2122.  
  2123.  
  2124.  
  2125.         Invalid option in system variable BasCompress$Options
  2126.  
  2127. 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.
  2128.  
  2129.  
  2130.  
  2131.         1.1
  2132.  
  2133.         ...
  2134.  
  2135.         10.1
  2136.  
  2137. 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.
  2138.  
  2139.  
  2140.  
  2141. 8 Loose ends
  2142.  
  2143. 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.
  2144.  
  2145. 8.1 Memory usage
  2146.  
  2147. 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.
  2148.  
  2149. 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.
  2150.  
  2151. Also all the source is kept in RAM, and all the output.
  2152.  
  2153. 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 :-)
  2154.  
  2155. If enough people request it then BasCompress may be upgraded to include the option of smaller initial hash-tables and demand-loading the source - a simple hack & slap.
  2156.  
  2157. 8.2 Missing THEN
  2158.  
  2159. 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:
  2160.  
  2161.     IF x<>0E%=1
  2162.  
  2163. 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.
  2164.  
  2165. A similar problem is the following BasCompress produced line:
  2166.  
  2167.     WHILE x<>0E%=2
  2168.  
  2169. The cure for this is to always separate the expression from the first statement of a WHILE compound by a colon.
  2170.  
  2171.  
  2172.  
  2173. 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:
  2174.  
  2175.     IF a=b=c THEN P."hello"
  2176.  
  2177. Intuition get's it wrong.  Basic treats this as:
  2178.  
  2179.     IF (a=b) THEN =c ...
  2180.  
  2181. 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.
  2182.  
  2183. 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.
  2184.  
  2185. 8.3 Cross-reference
  2186.  
  2187. 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 :-)
  2188.  
  2189. Also handy could be some ordering based on label length, or even the (approximate) size of a routine.
  2190.  
  2191. 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.
  2192.  
  2193. 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.
  2194.  
  2195. 8.4 Statistics
  2196.  
  2197. There are loads more statistics that could be done;
  2198.  
  2199.     •    libraries that aren't needed
  2200.  
  2201.     •    variables only ever declared (e.g. LOCALised but never used)
  2202.  
  2203.     •    variables only ever assigned to once (constants)
  2204.  
  2205.     •    lines where the memory indirection operators ?, | and ! are used
  2206.  
  2207.     •    don't log all the deleted routines and variables, just count them
  2208.  
  2209.     •    give a percentage of the code that is unused
  2210.  
  2211.     •    percentage compression achieved on the used code
  2212.  
  2213.     •    lines containing any user-defined basic token (e.g. PRINT)
  2214.  
  2215.     •    time taken to load, parse, cross-reference, compress, write
  2216.  
  2217. 8.5 Uncompressed output
  2218.  
  2219. 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.
  2220.  
  2221. 8.6 Label reduction
  2222.  
  2223. 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.
  2224.  
  2225. 8.7 Executable
  2226.  
  2227. 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.
  2228.  
  2229. 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?
  2230.  
  2231.  
  2232.  
  2233. Appendix A: Messages
  2234.  
  2235. A.1 Internationalism united
  2236.  
  2237. 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.
  2238.  
  2239. 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.
  2240.  
  2241. A.2 Format
  2242.  
  2243. 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.
  2244.  
  2245.     •    Comments start with a #
  2246.  
  2247.     •    Messages names start on a new line, and end in a colon
  2248.  
  2249.     •    Messages start at the first non-space after the colon, and finish at the end of the line
  2250.  
  2251.     •    Spaces can be done as “% ”
  2252.  
  2253.     •    Percents can be included using “%%”
  2254.  
  2255.     •    The “parameter”s %s and %d are supplied by BasCompress, these are standard C printf() strings
  2256.  
  2257.     •    The standard C escape sequences \b, \t, \n, \r, \xXX, \000, etc. can be used to insert those characters inside the messages
  2258.  
  2259.     •    A message may be a selection: starts with a “%?” and consists of a comma separated list of alternatives
  2260.  
  2261.  
  2262.  
  2263.  
  2264.  
  2265.  
  2266.  
  2267. Appendix B: Regular expressions
  2268.  
  2269. B.1 Definition
  2270.  
  2271. 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”:
  2272.  
  2273.         .     any character
  2274.  
  2275.         ^     start of line
  2276.  
  2277.         $     end of line
  2278.  
  2279.         [...] set of characters*
  2280.  
  2281. Any other character matches itself
  2282.  
  2283. There are also modifiers:
  2284.  
  2285.         |    or, “re1|re2” match either RE1 or RE2
  2286.  
  2287.         ~    not, “~c” matches anything but the next character
  2288.  
  2289.         +    many, “re+” matches RE repeated one or more times
  2290.  
  2291.         *    repeat, “re+” matches RE repeated zero or more times
  2292.  
  2293.         ?    optional, “re?” matches RE repeated zero or one times
  2294.  
  2295. Parenthesis () can be used to group REs
  2296.  
  2297. Finally, there are memories:
  2298.  
  2299.         \{   start recording
  2300.  
  2301.         \}   end recording, and place in next memory (starts with 1)
  2302.  
  2303.         \<n> \1, ... \9 will then match the corresponding memory
  2304.  
  2305. * character sets:
  2306.  
  2307. 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.
  2308.  
  2309.