home *** CD-ROM | disk | FTP | other *** search
/ AMIGA PD 1 / AMIGA-PD-1.iso / Programme_zum_Heft / Programmieren / Kurztests / PascalPCQ / Pascal.DOC < prev    next >
Text File  |  1992-08-18  |  151KB  |  3,736 lines

  1. ===================================================================
  2.  
  3.                       PCQ Pascal version 1.2
  4.                  A Pascal compiler for the Amiga
  5.                          by Patrick Quaid
  6.  
  7.  
  8. ===================================================================
  9.  
  10. PCQ Pascal is a simple Pascal compiler for the Amiga personal
  11. computer.  This version is freely distributable, which means that
  12. I retain the copyright to the compiler, the runtime library, the
  13. source of the compiler and runtime library, as well as this
  14. documentation.  It can all be freely distributed as long as you
  15. don't charge too much (see the last section for more information).
  16. There is now a registered version of the compiler available - also
  17. see the last section for more information about it.  To summarize
  18. the compiler's features:
  19.  
  20. The bad:
  21.  
  22.     o  The compiler doesn't support sets.
  23.     o  It isn't compatible with Turbo Pascal, although it's getting
  24.            closer.
  25.     o  Some things are slightly different from Standard Pascal.
  26.     o  The compiler gets knocked for a loop by most errors.
  27.  
  28. The good:
  29.  
  30.     o  It works.
  31.     o  It supports include files.
  32.     o  It allows for separate compilation, although you have to
  33.            do the checking (this isn't Modula-2, after all).
  34.     o  It supports records, enumerated types, pointers, arrays,
  35.            and C strings.
  36.     o  Type casts as found in Modula-2 is supported.  In other
  37.            words, something like "Byte('d')" is legal.
  38.     o  Several features from Turbo and Quick Pascal, such as Exit
  39.            procedures, operators such as Shl and Shr, and typed
  40.            constants, are supported.
  41.     o  You can have as many const, var, type, procedure and
  42.            function blocks as you want, in any order.
  43.     o  It's free!
  44.  
  45.  
  46.  
  47.  
  48.  
  49. ===================================================================
  50.  
  51.                         Table of Contents
  52.  
  53. ===================================================================
  54.  
  55.  
  56. This manual is designed to be read with a file reader or text
  57. editor, so this table of contents is based on line numbers rather
  58. than page numbers.  See the last section about getting a
  59. page-oriented version.
  60.  
  61.  
  62.         Section                                   Line Number
  63.      -----------------------------------------------------------
  64.  
  65.         Installing PCQ .............................  162
  66.             What have I got here? ..................  166
  67.             How do I make a work disk? .............  207
  68.         Compiling a program ........................  376
  69.         Incompatibilities ..........................  512
  70.  
  71.         PCQ Programs ...............................  581
  72.         Reserved Words .............................  596
  73.         Pascal Program Structure ...................  625
  74.  
  75.         Type Declarations ..........................  698
  76.             Numeric Types ..........................  732
  77.             Other Ordinal Types ....................  765
  78.             Pointer Types ..........................  791
  79.             File Types .............................  808
  80.             Type Compatibility .....................  831
  81.  
  82.         Constant Declarations ......................  860
  83.             Typed Constants ........................  896
  84.             Standard Constants .....................  971
  85.  
  86.         Variable Declarations ...................... 1015
  87.             Standard Variables ..................... 1048
  88.  
  89.         Procedure & Function Declarations .......... 1101
  90.             Parameter Passing ...................... 1132
  91.             Forward Procedures & Functions ......... 1176
  92.             External Routines ...................... 1202
  93.             Standard Procedures .................... 1225
  94.             Standard Functions ..................... 1369
  95.  
  96.         Label Declarations ......................... 1543
  97.  
  98.         Expressions ................................ 1567
  99.             Evaluation Order & Short Circuits ...... 1733
  100.             Constant Expressions ................... 1788
  101.             Variable References .................... 1798
  102.  
  103.         Statements ................................. 1836
  104.             If Statements .......................... 1856
  105.             While Statements ....................... 1881
  106.             Repeat Statements ...................... 1897
  107.             For Statements ......................... 1916
  108.             Case Statements ........................ 1960
  109.             With Statements ........................ 1993
  110.             Compound Statements .................... 2029
  111.             Assignment Statements .................. 2045
  112.             Procedure Calls ........................ 2058
  113.             Return Statements ...,.................. 2084
  114.             Goto Statements ........................ 2104
  115.  
  116.         Input/Output ............................... 2137
  117.             Pascal IO .............................. 2142
  118.             Text and Typed Files ................... 2180
  119.             Opening Files .......................... 2230
  120.             Writing to Files ....................... 2324
  121.             Reading from Files ..................... 2391
  122.             File Buffers ........................... 2475
  123.             IO Checking ............................ 2539
  124.             Standard IO ............................ 2566
  125.  
  126.         Strings .................................... 2641
  127.             Allocating String Space ................ 2677
  128.             Using Escape Characters ................ 2724
  129.             StringLib .............................. 2763
  130.  
  131.         Memory Management .......................... 2777
  132.             HeapError .............................. 2813
  133.  
  134.         Exit Procedures ............................ 2847
  135.             Runtime Errors ......................... 2892
  136.  
  137.         Compiler Directives ........................ 2964
  138.  
  139.         Type Casts ................................. 3098
  140.  
  141.         Small Initialization Code .................. 3142
  142.  
  143.         External Files ............................. 3206
  144.  
  145.         Notes to Assembly Programmers .............. 3279
  146.  
  147.         Errors ..................................... 3310
  148.  
  149.         Sources .................................... 3341
  150.  
  151.         Improvements on the Burner ................. 3428
  152.  
  153.         Update History ............................. 3455
  154.  
  155.         Other Notes, Copyright & My Address ........ 3669
  156.  
  157.  
  158.  
  159.  
  160. ===================================================================
  161.  
  162.                           Installing PCQ
  163.  
  164. ===================================================================
  165.  
  166.  What have I got here?
  167. -----------------------
  168.  
  169. What is included in the PCQ distribution depends on where you got
  170. it from.  If you got the disk from me, it most likely includes
  171. everything.  If you downloaded it, it probably does not include
  172. several common files, nor does it include the source for the
  173. compiler or runtime library.  It does, however, contain some
  174. combination of the following:
  175.  
  176.         Pascal          The compiler itself
  177.         Peep            The peephole optimizer
  178.         Pascal.DOC      This documentation file
  179.         Announcement    Description of the registered version
  180.         Readme.PCQ      A short description of PCQ
  181.         PCQ.lib         The runtime library
  182.         Include.LZH     The include file library, compressed with
  183.                         the LHArc program.
  184.         Examples.LZH    Several example programs, also compressed
  185.                         with LHArc.
  186.         IDList.LZH      A directory for the include files
  187.         PCQ.ced         An Arexx program that lets you compile,
  188.                         assemble, link and view errors all within
  189.                         CygnusEd Professional.
  190.         A68k            Charlie Gibbs' assembler (1)
  191.         A68k.doc        The documentation for A68k (1)
  192.         A68k2do.txt     Improvements planned for A68k (1)
  193.         History.log     Version-by-version changes of A68k (1)
  194.  
  195.         Blink           The Software Distillery linker (1)
  196.         Blink.doc       The documentation for Blink (1)
  197.  
  198.     (1) These files are often omitted from the BBS archive version
  199.         of the distribution to cut download times.  They are
  200.         already available on most systems, but if you are
  201.         uploading PCQ to a system, you might want to point out
  202.         that A68k and Blink are also necessary, and verify that
  203.         they are also available.
  204.  
  205.  
  206.  
  207.  How do I make a work disk?
  208. ----------------------------
  209.  
  210. Glad you asked.  The answer is that I don't know.  There are
  211. jillions of different system configurations out there, so I can't
  212. tell you exactly how to set your system up.  But I can give you
  213. some general guidelines.
  214.  
  215. First of all, somewhere in your command path you are going to need
  216. the compiler, assembler, linker, and a text editor.  Normally
  217. these would go in the C:  directory, but if you use the AmigaDOS
  218. PATH command, they can go in any of the path directories.
  219.  
  220. If you don't have a text editor, I heartily recommend CygnusEd
  221. Professional from ASDG.  TxEd is supposed to be about as good, but
  222. I've never used it.  Programmers on a budget can use MEMACS from
  223. the Extras disk, ED from the Workbench disk, or a variety of
  224. freely distributable editors like DME.  ED isn't a great choice,
  225. MEMACS is fair, and from what I hear DME is really good.  Take
  226. your pick.
  227.  
  228. The other file you'll definitely need is the runtime library,
  229. which can go anywhere.  I keep mine in my work directory, but
  230. others like to keep it in their LIBS:  directory.  It's up to you,
  231. but don't forget where you put it.
  232.  
  233. These files are all absolutely necessary for even the simplest
  234. programs.  If you want to use any Amiga routines, or use special
  235. routines from PCQ.lib, you will also need to install the include
  236. file library.  This is where it gets a bit hairy, because the set
  237. of include files is just under 800 disk blocks (a little less than
  238. 400k).  That's half a floppy disk right there.  The size of these
  239. files is going to make it awfully hard to use the complete system
  240. on single drive systems.  If you want to install the Include files
  241. you'll also need to find a copy of LHArc (or one of the compatible
  242. archivers).  LHArc is available on virtually all bulletin boards,
  243. so you shouldn't have much of a problem finding a copy (if you
  244. have not yet done so, do yourself a favor and buy a modem.  It's
  245. the best investment you'll make).
  246.  
  247. So how do we organize all this stuff?  It depends on your system,
  248. of course, but here's a few examples.  If you want to install the
  249. program on a hard drive, you could try the following.  First, copy
  250. Pascal, A68k, and Blink to your C:  directory (also copy a text
  251. editor if one is not already there).  Then create a work
  252. directory.  Copy PCQ.lib to this new directory.  Now make a
  253. subdirectory of your work directory called something like
  254. "Include".  It's actually not necessary that it's a subdirectory,
  255. but it will help you keep your disk structure straight.  Then use
  256. the AmigaDOS ASSIGN command to make an assignment of Include:  to
  257. your new include directory.  Now you want to uncompress the
  258. include file library into your new include directory, with a
  259. command like:
  260.  
  261.         LHArc -x -r x DistributionDisk:Include Include:
  262.  
  263. Use the actual path of the include archive, or course.  Every time
  264. you use the compiler, you should be sure to properly ASSIGN the
  265. Include:  directory - you'll probably want to put that assignment
  266. in the startup-sequence or an initialization script.
  267.  
  268.  
  269. If you have one disk drive, I recommend the following disk
  270. structure.  The problem here is that I don't have a one-drive
  271. system on which to test this, so you may have to adjust it
  272. somewhat.
  273.  
  274.     Root:
  275.         PCQ.lib
  276.         C (dir)
  277.             A68k                             Assign
  278.             Avail                            Blink
  279.             CD                               Copy
  280.             Date                             Delete
  281.             Echo                             Ed
  282.             Else                             EndCLI
  283.             EndIf                            EndSkip
  284.             Execute                          Failat
  285.             If                               Info
  286.             Join                             Lab
  287.             List                             LoadWB
  288.             Makedir                          NewShell
  289.             Pascal                           Path
  290.             Prompt                           Protect
  291.             Quit                             Relabel
  292.             Rename                           Resident
  293.             Run                              SetPatch
  294.             Stack                            Type
  295.         Libs (dir)
  296.             diskfont.library                 icon.library
  297.             mathtrans.library                version.library
  298.         Devs (dir)
  299.             ramdrive.device                  system-configuration
  300.         S (dir)
  301.             Startup-Sequence                 Make
  302.         L (dir)
  303.             Disk-Validator                   Newcon-Handler
  304.             Port-Handler                     Ram-Handler
  305.             Shell-Seg                        
  306.         Include (dir)
  307.             All the include files...
  308.         Trashcan (dir)
  309.  
  310.  
  311.  
  312. To make this sort of disk, first make a copy of a standard
  313. Workbench disk.  Then prune away everything, and I mean
  314. everything, that you don't absolutely need.  You'll note for
  315. example that the list above doesn't even have the serial.device
  316. and the parallel.device, so you can't use your modem or printer.
  317. These sorts of sacrifices will have to be made.  Next, copy
  318. Pascal, A68k and Blink to the :c  directory, then copy Make to the
  319. :s  directory and PCQ.lib to the new disk's root.  Make a new
  320. directory called Include, then CD to it.  Uncompress the Include
  321. file directory by using the following command:
  322.  
  323.     LHArc -x -r x Distribution:Include WorkDisk:Include/
  324.  
  325. Use the actual path for LHArc and the archive itself.  You might
  326. have to run Install on the disk to make it bootable, but you'll
  327. have yourself a barely usable work disk for Pascal.  You will have
  328. virtually no free space, so you'll have to edit and compile files
  329. in RAM:, copying them to a separate disk as often as possible.  It
  330. will be a hard life.  If you are only writing very simple,
  331. standard Pascal programs, which use none of the Amiga's special
  332. features, you can leave out the include directory (thus freeing up
  333. nearly 400k), but you won't be able to create very interesting
  334. programs.  Single drive users probably have several tricks up
  335. their sleeves to get around disk space problems, so if you know of
  336. a better plan, by all means use it.
  337.  
  338. If you have two disks, I would recommend a setup similar to the
  339. single drive system.  Move the include directory to the second
  340. disk, however, and flesh out the system files on the boot disk (so
  341. you can use your printer, especially).  Use the ~400k of free
  342. space on your second drive as your work area.  This is the sort of
  343. setup I used when I originally developed PCQ.
  344.  
  345. If you have lots of RAM (say, a megabyte or more), you might want
  346. to copy some of this stuff into RAM:  or RAD:  to free up work
  347. space.  For example, if you have one megabyte of RAM you might be
  348. able to copy the entire Include directory to the RAM:  disk and
  349. still have enough memory to compile medium sized programs.
  350.  
  351. The one optional part of the system is the peephole optimizer,
  352. Peep.  This program takes the assembly output of the compiler and
  353. makes it somewhat more efficient and slightly smaller.  If you are
  354. compiling on floppy disks you'll probably want to skip it, but if
  355. you are working in RAM or on a hard disk it's doesn't add much to
  356. the compilation time.  Peep should be copied to the same place as
  357. Pascal.
  358.  
  359. However you end up configuring your system, you'll have to
  360. define the Include:  assignment to point to your include file
  361. directory.  This assignment is just the convention I used in the
  362. include files and example programs - it's not part of the compiler
  363. itself, in other words - so if you are willing to modify all the
  364. include files you can use whatever assignment you like.  The only
  365. other assignment of interest is the T:  directory.  This one is
  366. automatically created by AmigaDOS, and since it is used by the
  367. Make script to store intermediate files, assigning it to a RAM:
  368. directory speeds up the whole compilation cycle dramatically.
  369.  
  370.  
  371.  
  372.  
  373.  
  374. ===================================================================
  375.  
  376.                        Compiling a Program
  377.  
  378. ===================================================================
  379.  
  380. Turning a Pascal source file into an executable program is (at
  381. last count) a four step process.  You start off with your source
  382. code (one of the example programs, for example), which probably
  383. ends with ".p".  The first step is to use the compiler to turn
  384. this source file into an equivalent assembly language program.  To
  385. do this, invoke the compiler with the following command format:
  386.  
  387.         Pascal InputPascal OutputAssembly [-q] [-s] [-b]
  388.  
  389. "InputPascal" should be replaced with the complete filename
  390. (including path, if necessary) of your source file, and
  391. "OutputAssembly" is the filename (optionally with a path) of the
  392. assembly language output file.  I normally use the extension
  393. ".asm" on the output file.  The command line arguments can be
  394. placed anywhere on the command line, in upper or lower case, and
  395. have the following meaning:
  396.  
  397.      -q      Run in "quiet" mode, i.e. the compiler does not
  398.              write anything to the screen except error
  399.              messages.  This makes it easier to parse the
  400.              output of the compiler in an ARexx script, for
  401.              example.
  402.  
  403.      -s      Small initialization.  Small programs use a
  404.              different initialization routine that does not
  405.              have all the overhead of the standard routine,
  406.              but it means that you will not be able to use any
  407.              Pascal IO (e.g Writeln(), Readln(), etc).
  408.  
  409.      -b      Disable short-circuit Boolean expressions.
  410.              Normally, PCQ abandons evaluation of a Boolean
  411.              expression as soon as its overall value becomes
  412.              known (if the left side of an AND expression is
  413.              false, for example, there is no point in
  414.              evaluating the right side).  Thus some parts of
  415.              the program will not be executed.  This option
  416.              forces PCQ to fully evaluate all Boolean
  417.              expressions.
  418.  
  419. The second step takes the assembly language file and creates a new
  420. file that's slightly more efficient.  This is done using the
  421. program Peep, which is invoked with the following command format:
  422.  
  423.         Peep InputAssembly OutputAssembly
  424.  
  425. I normally use the extension ".s" for assembly files that have
  426. been run through the peephole optimizer, but it is entirely up to
  427. you.
  428.  
  429. The third step takes the .asm or .s file and creates an object
  430. file.  An object file is mostly the same machine-readable
  431. instructions and data as the executable file, but it does not
  432. contain all the routines the final program will need.  The
  433. assembler, in this case Charlie Gibbs' A68k, converts assembly
  434. language programs to object files, and is invoked with the
  435. following command line:
  436.  
  437.         A68k InputAssembly OutputObject
  438.  
  439. A68k is a very powerful, flexible program with lots of options -
  440. be sure to read its documentation file for a complete description.
  441.  
  442. If all these steps finished without errors, you can link the
  443. object file to all the routines in the runtime library it needs to
  444. be an executable program.  The Software Distillery linker, Blink,
  445. handles this part of the process.  It is invoked with the
  446. following command line:
  447.  
  448.         Blink InputObject to OutputExec library PCQ.lib
  449.  
  450. Blink also has many options, and comes with a documentation file
  451. that completely explains them.  Note that you might have to use a
  452. full path to specify where PCQ.lib is - if it's in the LIBS:
  453. directory, for example, you would use LIBS:PCQ.lib instead.
  454.  
  455. You now have, finally, a finished executable file.  That seems
  456. like a lot of steps, and a lot to remember, just to make one
  457. program.  It is.  Therefore I use, and have included in the
  458. distribution, a couple of AmigaDOS scripts that automate the whole
  459. process.  The first is called Make, and it compiles a program in
  460. the T:  directory, leaving just the executable program on the
  461. disk.  It looks like this:
  462.  
  463.                 .key source
  464.                 Pascal <source>.p T:<source>.asm
  465.                 A68k T:<source>.asm T:<source>.o
  466.                 Delete T:<source>.asm
  467.                 Blink T:<source>.o to <source> library PCQ.lib
  468.                 Delete T:<source>.o
  469.  
  470. You'll note that my preferences for extensions are built in to
  471. this script - the Pascal file ends in .p, the assembly language
  472. file ends in .asm, and the object file ends in .o.  If you prefer
  473. other names, just change the script.  Also note that you might
  474. have to change the script if your compiler, assembler and linker
  475. are not on the normal path, or if PCQ.lib is not in the current
  476. directory (in both cases, just use the complete path in place of
  477. the file name).  To run this script, you just invoke it like this:
  478.  
  479.         Make ProgramName
  480.  
  481. Note that you leave off any extensions.  If everything works OK,
  482. you'll have an executable program called ProgramName left in the
  483. current directory.  One problem with this script is that you can't
  484. use any command line options on the compiler.  I actually have
  485. several different versions of Make scripts that handle all the
  486. combinations I use.
  487.  
  488. The other script, OMake, is virtually the same, except it also
  489. invokes the peephole optimizer to make slightly more efficient
  490. programs.  It looks like:
  491.  
  492.                 .key source
  493.                 Pascal <source>.p T:<source>.asm
  494.                 Peep T:<source>.asm T:<source>.s
  495.                 Delete T:<source>.asm
  496.                 A68k T:<source>.s T:<source>.o
  497.                 Delete T:<source>.s
  498.                 Blink T:<source>.o to <source> library PCQ.lib
  499.                 Delete T:<source>.o
  500.  
  501. Again, you might have to make modifications to suit your set up.
  502. If you are working on a fairly complex project, you will probably
  503. find it convenient to make a set of specialized scripts to
  504. automate the compile-assemble-link process.
  505.  
  506.  
  507.  
  508.  
  509.  
  510. ===================================================================
  511.  
  512.                         Incompatibilities
  513.  
  514. ===================================================================
  515.  
  516.     PCQ Pascal is incompatible with standard Pascal, and by
  517. extension Turbo Pascal, in several ways.  Briefly, they are:
  518.  
  519.     (1) Sets are not supported.
  520.     (2) The standard Pascal declaration of pointers to records is
  521.         not supported.  For example, the following syntax is legal
  522.         in standard Pascal:
  523.  
  524.             type
  525.                 WindowPtr = ^Window;
  526.                 Window = record
  527.                     NextWindow : WindowPtr;
  528.                     ...
  529.  
  530.         That's an exception in standard Pascal - the only time you
  531.         can use an identifier before you declare it.  In PCQ
  532.         Pascal, that syntax will fail with an Unknown ID error.
  533.         In its place, use something of this form:
  534.  
  535.            type
  536.                Window = record
  537.                    NextWindow : ^Window;
  538.                    ....
  539.                end;
  540.                WindowPtr = ^Window;
  541.  
  542.     (3) Variant records are not supported.
  543.     (4) The familiar syntax for specifying a single quote
  544.         character constant, which in standard Pascal looks like
  545.         '''', is not supported.  Instead PCQ Pascal uses C escape
  546.         conventions, which are explained in the section called
  547.         Strings.
  548.     (5) The way you open a file is different from Standard Pascal,
  549.         although once it's open the commands are basically the
  550.         same.
  551.  
  552.  
  553. Although PCQ Pascal was not designed to be compatible with Turbo
  554. Pascal, in order to make porting programs easier I'll point out a
  555. few of the more important differences (in addition to those
  556. above).
  557.  
  558.     (1) PCQ Pascal handles strings completely differently from
  559.         Turbo Pascal.  PCQ strings are similar to C strings, which
  560.         are not as easy to manipulate as Turbo strings.  In fact,
  561.         PCQ strings are the most difficult of the three.  They are
  562.         fully explained in the Strings section.
  563.     (2) In a PCQ Pascal function, assigning a value to the
  564.         function name causes you to leave the function.  In Turbo
  565.         Pascal, the function name is treated as a write-only
  566.         variable, and you have to use the Exit command explicitly.
  567.         All the examples in the Pascal Report skirt the issue by
  568.         assigning the value as the last statement.
  569.     (3) Speaking of Exit, Exit in PCQ Pascal quits the program,
  570.         whereas in Turbo it quits the current function or
  571.         procedure.  Turbo's "Exit" is like PCQ's "return", and
  572.         Turbo's "Halt" is like PCQ's "Exit".  Got that?
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579. ===================================================================
  580.  
  581.                            PCQ Programs
  582.  
  583. ===================================================================
  584.  
  585. For the most part, PCQ Pascal programs look very much like
  586. standard Pascal programs.  Apart from the incompatibilities
  587. described above, in fact, PCQ should compile plain Pascal programs
  588. directly.  PCQ makes several extensions to Pascal, however, so in
  589. order to explain them I'll go over what is and is not allowed in
  590. PCQ programs.
  591.  
  592.  
  593.  
  594. ===================================================================
  595.  
  596.                           Reserved Words
  597.  
  598. ===================================================================
  599.  
  600. Reserved words are symbols that cannot be used as identifiers in
  601. your program.  They have special meaning to the compiler, and
  602. cannot be overridden.  The reserved words of PCQ are as follows:
  603.  
  604.             and         for         procedure
  605.             array       forward     program
  606.             begin       function    record
  607.             by          goto        repeat
  608.             case        if          return
  609.             const       in          set
  610.             div         label       then
  611.             do          mod         to
  612.             downto      not         type
  613.             else        of          until
  614.             end         or          var
  615.             external    packed      while
  616.             file        private     with
  617.  
  618. As you can see, even the unimplemented stuff is reserved.
  619.  
  620.  
  621.  
  622.  
  623. ===================================================================
  624.  
  625.                      Pascal Program Structure
  626.  
  627. ===================================================================
  628.  
  629. The normal structure of Pascal programs is as follows:
  630.  
  631.  
  632. <Program> ::= Program <Identifier> ; <Block>.  |
  633.               Program <Identifier> (<Identifier List>); <Block>.
  634.  
  635. <Block>   ::= <Declarations> begin <Statements> end |
  636.               begin <Statements> end
  637.  
  638. <Identifier List> ::= <Identifier> , <Identifier List> |
  639.                       <Identifier>
  640.  
  641.  
  642. Does everyone read Backus-Naur?  The idea is that the objects to
  643. the left of the definition sign ::= are being defined by the rule
  644. to the right.  Objects in angle brackets are defined elsewhere in
  645. the list, and the vertical bar character separates alternatives.
  646. Everything else is to be taken literally.  Thus a Pascal program
  647. begins with the literal word Program, followed by an identifier,
  648. followed by a semicolon, followed by a block (whatever that is),
  649. and ending with a period.  On the other hand, it can also consist
  650. of Program followed by an identifier, followed by a left
  651. parenthesis, followed by an identifier list, followed by a right
  652. parenthesis, a semicolon, a block, and finally a period.  Once you
  653. get used to them, BNF diagrams will tell you exactly what you need
  654. to know about the syntax of a program.  BNF grammars can also be
  655. represented as "railroad diagrams", and if this weren't a
  656. text-only document I'd be using them instead.
  657.  
  658. We've left a few things undefined, so we better start filling it
  659. out.
  660.  
  661. <Declarations> ::= <Declaration> , <Declarations> | <Declaration>
  662.  
  663. <Declaration> ::= <Type Declaration>      |
  664.                   <Constant Declaration>  |
  665.                   <Variable Declaration>  |
  666.                   <Label Declaration>     |
  667.                   <Procedure Declaration> |
  668.                   <Function Declaration>
  669.  
  670. Note that standard Pascal imposes an order on the declarations:
  671. it says there should be one constant block, followed by one type
  672. block, etc.  PCQ Pascal removes that restriction, so you can have
  673. as many declarations in whatever order you see fit.
  674.  
  675. Subject to the definition of the rest of those objects, this is
  676. the format for any normal PCQ Pascal program.  There is an
  677. exception (of course):  the separately compilable file.  Turbo
  678. Pascal provides a Unit structure so you can write, compile and
  679. debug units, then use them in many programs.  PCQ provides a
  680. similar, although not as powerful, feature in the form of external
  681. files.  Consider the following extension of our basic rule:
  682.  
  683. <Program> ::= Program <Identifier>; <Block>.  |
  684.               Program <Identifier> (<Identifier List>); <Block>. |
  685.               External ; <Declarations>
  686.  
  687. According to this, an external file is just the reserved word
  688. External followed by a semicolon, then a series of procedures,
  689. functions, whatever.  See the section called External Files for
  690. more information.
  691.  
  692.  
  693.  
  694.  
  695.  
  696. ===================================================================
  697.  
  698.                         Type Declarations
  699.  
  700. ===================================================================
  701.  
  702. Type declarations take the following form:
  703.  
  704. <Type Declaration> ::= Type <Type Definitions>;
  705.  
  706. <Type Definitions> ::= <Type Definition>; <Type Definitions> |
  707.                        <Type Definition>
  708.  
  709. <Type Definition>  ::= <Identifier> = <Type Specification>
  710.  
  711. <Type Specification> ::= <Identifier>                      |
  712.                          <Range>                           |
  713.                          ^<Type Specification>             |
  714.                          (<Identifier List>)               |
  715.                          <Array Definition>                |
  716.                          <Record Definition>               |
  717.                          file of <Type Specification>
  718.  
  719. <Range> ::= <Constant Expression> .. <Constant Expression>
  720.  
  721. <Array Definition> ::= array [<Range>] of <Type Specification> |
  722.                        array <Identifier> of <Type Specification>
  723.  
  724. <Record Definition> ::= record <Variable Definitions> end
  725.  
  726.  
  727. Once you digest the BNF, I think you'll find that straight-
  728. forward.  Constant expressions are discussed in the Expressions
  729. section below - for now let's look at the types that are
  730. predefined in PCQ Pascal.
  731.  
  732.  Numeric Types
  733. ---------------
  734.  
  735. PCQ Pascal supports a variety of numeric types that should give
  736. you the flexibility you need to carry out whatever math you might
  737. require.  The types, from smallest to largest range, are:
  738.  
  739. Byte      This is a 1-byte, unsigned integer, capable of holding
  740.           a value from 0 to 255.
  741.  
  742. Short     A Short is a 2 byte (16 bit) signed integer, with a range
  743.           of -32768 to 32767.
  744.  
  745. Integer   Integer is the largest ordinal type.  It holds a 32-bit
  746.           signed integer, with a range of about -2 billion to 
  747.           2 billion.
  748.  
  749. Real      A floating point value, in Motorola Fast Floating Point
  750.           format.  A Real value is 4 bytes (32 bits), and can
  751.           express floating point values from about 10 x 10^18 to
  752.           about 5 x 10^-20, positive or negative.  I'm not sure
  753.           what the accuracy of FFP is, but I wouldn't count on
  754.           more than 5 or 6 digits.
  755.  
  756. The numeric types are interchangeable in expressions.  If you use
  757. two different types in, for example, a plus expression, the
  758. compiler will automatically promote both values to the smallest
  759. "container type".  A container type is a numeric type whose range
  760. covers both of the arguments.  For example, the result of adding a
  761. Short to an Integer is an Integer.  The result of most binary
  762. operations involving Real values will be a real value.
  763.  
  764.  
  765.  Other Ordinal Types
  766. ---------------------
  767.  
  768. Integers, Shorts and Bytes are all Ordinal types.  This means they
  769. are discrete values that can be represented exactly in binary
  770. (unlike floating point values, which are approximated).  The other
  771. ordinal types are:
  772.  
  773. Char        A one-byte value, stored as the ASCII value.
  774.  
  775. Boolean     Also one byte long, a Boolean value is either -1 (all
  776.             binary ones) for true, or 0 for false.  Anything else
  777.             could produce unpredictable results.  Incidentally,
  778.             the Boolean type can be considered an enumerated type
  779.             with the values True and False.  In most
  780.             implementations False < True and Succ(False) = True,
  781.             but not in PCQ.
  782.  
  783. Enumerated  The values of an enumerated type are specified within
  784.             the program.  If there are 256 or fewer values, the
  785.             enumerated type will be stored in one byte.  If there
  786.             are more, it will be stored in two bytes.  In either
  787.             case, each enumeration is associated with an integer
  788.             value, starting with 0.
  789.  
  790.  
  791.  Pointer Types
  792. ---------------
  793.  
  794. Pointer types hold the address of another variable.  They are all
  795. 32-bit values.  The predefined pointer types are:
  796.  
  797. Address     Address is a special pointer type that is compatible
  798.             with all other pointer types.  It should not be
  799.             dereferenced, but you can use it to avoid cumbersome
  800.             type casts.
  801.  
  802. String      The String type in PCQ is actually defined as a
  803.             pointer to char, although it has other special
  804.             qualities like allowing array-like subscripts.
  805.             Strings are explained in the section called Strings.
  806.  
  807.  
  808.  File Types
  809. ------------
  810.  
  811. Files in PCQ are based on normal AmigaDOS files, but provide
  812. automatic buffering and access to the handy Pascal IO routines
  813. (Writeln, et al).  File variables come in two varieties:
  814.  
  815. Text        A Text file is any normal ASCII file (this
  816.             documentation, for example.
  817.  
  818. Typed Files A typed file, declared as "File of Type", only stores
  819.             values of the given type.  If you issue a Write()
  820.             command on a typed file, PCQ will output the actual
  821.             binary representation of the object to the file.  For
  822.             example, if you have a "File of Integer", the typed
  823.             file will store each Integer as a four-byte binary 
  824.             representation.  A text file, on the other hand, will
  825.             store each Integer as a series of ASCII characters
  826.             from '0' to '9'.  You cannot use Writeln and Readln on
  827.             typed files.
  828.  
  829.  
  830.  
  831.  Type Compatibility
  832. --------------------
  833.  
  834. There are two kinds of type checking.  One is for normal type
  835. compatibility.  That's used for comparing arguments in an
  836. expression, or for formal and actual value parameters.  The second
  837. kind checks for identical types, and is used for more strict
  838. circumstances: in assignment operations and between formal and
  839. actual parameters passed by reference (using the VAR keyword).
  840. PCQ Pascal is, relative to Standard Pascal, generous in its
  841. enforcement of these rules.  For simple type compatibility, the two
  842. types have to pass on of the following tests:
  843.  
  844.       o  They are the same type, or
  845.       o  They are both number types (real, integer, etc), or
  846.       o  They are both arrays with the same size range and the
  847.          element types are compatible, or
  848.       o  They are both pointers to compatible types, or
  849.       o  They are both files of compatible types.
  850.  
  851. Synonym types (e.g. "TYPE ByteSynonym = Byte") are considered
  852. identical types.  For the more strict type identity check, remove
  853. the second rule.
  854.  
  855.  
  856.  
  857.  
  858. ===================================================================
  859.  
  860.                   Constant Declarations
  861.  
  862. ===================================================================
  863.  
  864.  
  865. Constants are normally declared in the Standard Pascal fashion,
  866. which looks like the following in BNF:
  867.  
  868. <Const Block> ::= Const <Const Declarations>;
  869.  
  870. <Const Declarations> ::= <Const Declaration> |
  871.                          <Const Declaration> ; <Const Declarations>
  872.  
  873. <Const Declaration> ::= <Identifier> = <Constant Expression> |
  874.                         <Identifier> : <Type Specification> =
  875.                                         <Typed Constant Value>
  876.  
  877. <Typed Constant Value> ::= <Constant Expression>      |
  878.                            ( <Constant Expressions> ) |
  879.                            @ <Identifier>
  880.  
  881. Constant expressions will be defined below, but you can think of
  882. them as any normal expression that can be completely evaluated
  883. during the compilation (i.e. they use no user-defined functions
  884. and access no variables).
  885.  
  886. Normal constants are easy to understand - they are just like
  887. read-only variables, but they actually take up no memory.  The
  888. constant value is just inserted in the program instead of the
  889. identifier.  Since they are formed by constant expressions, normal
  890. constants can only have a few different types:  integer, real,
  891. char, Boolean, string and array of char.  They can't have any
  892. user-defined type, and can't be record or array types.
  893.  
  894.  
  895.  
  896.  Typed Constants
  897. -----------------
  898.  
  899. That's where typed constants come in.  Typed constants are best
  900. thought of as pre-initialized variables, and they can be of any
  901. type you can define, besides file types.  I have no idea why Turbo
  902. Pascal decided that these objects should be called constants
  903. rather than variables, but I'm following their lead.  Your program
  904. loads with these values already in place, and they will not be
  905. refreshed until the program is reloaded.  They will, therefore,
  906. screw up resident programs if used incorrectly.
  907.  
  908. One handy side effect is that variables local to some procedure
  909. can retain their value throughout a program's execution (like
  910. static variables in C, right?).  In other words, if you declare a
  911. typed constant within a procedure, it will not be accessible to
  912. any code outside of that scope, and it will not lose its value
  913. between calls to the procedure.  Looks like a local, acts like a
  914. global.
  915.  
  916. Declaring typed constants is error prone, and you invariably spend
  917. most of the time counting a list of numbers or trying to match
  918. parentheses or something equally mind-numbing.  Nonetheless, they
  919. are awfully handy.  The syntax corresponds to the second
  920. alternative of the <Const Declaration>, but that doesn't tell the
  921. whole story.  Perhaps it's best to look at some examples:
  922.  
  923.     Type
  924.         ExampleRec = record
  925.                          Field1 : Integer;
  926.                          Field2 : Char;
  927.                          Field3 : Boolean;
  928.                          Field4 : ^Integer;
  929.                          Field5 : Array [-1..1] of Byte;
  930.                      end;
  931.         MultiDim = Array [0..1,0..1] of Integer;
  932.  
  933.     Const
  934.         Message1 : String = "An example string";
  935.         Message2 : Array [0..9] of Char = 'String2   ';
  936.         Message3 : Array [0..9] of Char = ('a','b','c','d','e',
  937.                                            'f','g','h','i','j');
  938.         Value1   : Integer = 456;
  939.         Record1  : ExampleRec =
  940.                         (34, 'r', True, @Value1, (34,56,12));
  941.         Multi1   : MultiDim = ((34,12), (45,15));
  942.  
  943.  
  944. Note that all the "Message" constants and Value1 could also be
  945. specified as normal constants.  Message1 and Value1, in that case,
  946. would not take up any memory, but Messages 2 and 3 would be the
  947. same.  The format of the Message3 declaration is typical for
  948. arrays, but the Message2 format is a special abbreviation for
  949. arrays of char.
  950.  
  951. There are several differences between this and Turbo Pascal's
  952. syntax (all, if I may say so, in favor of PCQ).  First of all,
  953. definitions of constant records in Turbo Pascal requires that you
  954. use the field identifier, followed by a colon, the value, and
  955. possibly a semicolon.  That's far too cumbersome for me, so I just
  956. use the same idea as arrays:  you specify each field, separated by
  957. commas, in order.
  958.  
  959. The second difference with Turbo Pascal is that, until version 6.0,
  960. it only allowed pointer types to be initialized to Nil.  PCQ
  961. Pascal allows you to initialize a pointer type as Nil, or as the
  962. address of a preceding global variable or typed constant.  To do
  963. this, you normally use the '@' operator, which returns the address
  964. of a specified variable.
  965.  
  966. The last difference is that you can use some typed constant values
  967. in subsequent constant expressions.  You can't use any structured
  968. types (i.e. records and arrays), but you can use integers, reals,
  969. and other so-called "simple" types.
  970.  
  971.  Standard Constants
  972. --------------------
  973.  
  974. There are several standard constants (i.e. they are built in to
  975. the compiler itself - you don't have to declare them or use an
  976. include file).  They are:
  977.  
  978.  
  979. False    False is an enumeration of the type Boolean, and has the
  980.          value 0.
  981.  
  982. MaxInt   MaxInt is the largest integer that can be stored in the
  983.          32-bit Integer type.  It is: 2,147,483,647, which is
  984.          $7FFFFFFF in hex.  Thus you can say that the range of an
  985.          Integer variable is +MaxInt to -MaxInt.
  986.  
  987. MaxShort MaxShort is the largest number that can be stored in the
  988.          16-bit Short type.  It turns out to be 32,767, or $7FFF
  989.          in hex.  Just as with MaxInt, you can say that the range
  990.          of a Short variable is +MaxShort to -MaxShort (to be
  991.          precise, the range is actually +MaxShort to
  992.          -(MaxShort+1), and MaxInt is analogous).
  993.  
  994. Nil      Nil is a constant of type Address.  It is defined as
  995.          something like:
  996.  
  997.                 Nil = Address(0);
  998.  
  999.          In Standard Pascal, "Nil" is a reserved word.  In PCQ
  1000.          Pascal it isn't reserved, for the simple reason that it
  1001.          doesn't have to be.
  1002.  
  1003. True     True is an enumeration of the type Boolean, and actually
  1004.          has the value -1.  In some cases, any non-zero number
  1005.          will suffice, but the "not" operator will behave
  1006.          erratically if you use weird values.
  1007.  
  1008.  
  1009.  
  1010.  
  1011.  
  1012.  
  1013. ===================================================================
  1014.  
  1015.                     Variable Declarations
  1016.  
  1017. ===================================================================
  1018.  
  1019.  
  1020. Variable declarations are handled just like standard Pascal:
  1021.  
  1022. <Var Declaration> ::= Var <Var Definitions> ;
  1023.  
  1024. <Var Definitions> ::= <Var Definition> |
  1025.                       <Var Definition> ; <Var Definitions>
  1026.  
  1027. <Var Definition>  ::= <Identifier List> : <Type Specification>
  1028.  
  1029. Global variables, i.e. variables declared at the outer-most level,
  1030. are allocated as static memory.  All variables declared within a
  1031. procedure or function are allocated on the stack, so if you are
  1032. writing re-entrant routines, be sure to avoid writing to global
  1033. variables.
  1034.  
  1035. Variables larger than one byte are always allocated on word
  1036. boundaries (not longword boundaries - you'll have to use AllocMem
  1037. to guarantee that).  That's an option in Turbo Pascal, but the
  1038. 68000 makes it mandatory for Amiga programs.  Note that this
  1039. applies within records and arrays as well, so be careful if you
  1040. make assumptions about variable size and location.
  1041.  
  1042. Keep in mind that local variables (not typed constants) disappear
  1043. when you leave the function, so you shouldn't try to access them
  1044. afterward (with a pointer variable, for example).  It just won't
  1045. work.
  1046.  
  1047.  
  1048.  Standard Variables
  1049. --------------------
  1050.  
  1051. There are several variables built-in to PCQ Pascal.  They are
  1052. always available, and are treated like global variables.  They
  1053. are:
  1054.  
  1055. CommandLine     This is a String variable that points to the
  1056.                 command line the user entered (with the name of
  1057.                 the program and any indirection parameters
  1058.                 stripped off).  If the program was executed from
  1059.                 the Workbench, this value is not defined.  Note
  1060.                 that, to be on the safe side, this variable should
  1061.                 be treated as read-only.  Make a copy of it if you
  1062.                 want to modify it.
  1063.  
  1064. ExitAddr        ExitAddr is the location within your program that
  1065.                 a runtime error occurred.  If no error occurred,
  1066.                 its value is undefined.  See the section called
  1067.                 "Exit Procedures" for more information.
  1068.  
  1069. ExitCode        This is the Integer value that will be returned to
  1070.                 AmigaDOS when your program terminates.  It is only
  1071.                 defined within an exit procedure.
  1072.  
  1073. ExitProc        This is an Address variable that holds the address
  1074.                 of the first procedure that will be executed when
  1075.                 your program terminates.  See the section called
  1076.                 "Exit Procedures" for more information.
  1077.  
  1078. HeapError       HeapError is an Address variable that holds the
  1079.                 address of a function to call when New() or
  1080.                 AllocString() is unable to allocate a block of
  1081.                 memory.  See the section called Memory Management
  1082.                 for more information.
  1083.  
  1084. Input           Input is a Text file type.  It corresponds to the
  1085.                 standard input channel of the program, such as the
  1086.                 CLI from which it was run.  PCQ Pascal programs
  1087.                 always establish some sort of standard Input file
  1088.                 unless you specifically tell it not to.  See the
  1089.                 section called Input/Output for more information.
  1090.  
  1091. Output          Output is a Text file type.  It corresponds to the
  1092.                 standard output channel of the program, which in
  1093.                 most cases is the CLI from which it was run.  PCQ
  1094.                 Pascal programs always establish an output file
  1095.                 unless instructed not to.
  1096.  
  1097.  
  1098.  
  1099. ===================================================================
  1100.  
  1101.                Procedure and Function Declarations
  1102.  
  1103. ===================================================================
  1104.  
  1105. Procedures and functions allow you to define common routines
  1106. within a larger block.  Procedures are executed by procedure
  1107. statements, and function are executed when they are used in
  1108. expressions.  The format for procedure and function definitions is
  1109. as follows:
  1110.  
  1111.  
  1112. <Proc Declaration> ::= Procedure <Identifier> ; <Body> |
  1113.                        Procedure <Identifier>
  1114.                                 ( <Formal Params> ); <Body>
  1115.  
  1116. <Body> ::= <Block> | External | Forward
  1117.  
  1118. <Formal Params> ::= <Identifier List> : <Type Specification> |
  1119.                     var <Identifier List> : <Type Specification>
  1120.  
  1121. <Func Declaration> ::= Function <Identifier> :
  1122.                                    <Type Specification> ; <Body> |
  1123.                        Function <Identifier> ( <Formal Params> ) :
  1124.                                    <Type Specification> ; <Body>
  1125.  
  1126.  
  1127. At the risk of being repetitive, keep in mind that you can only
  1128. use procedures where the BNF calls for a <Statement>, and you can
  1129. only use functions where the BNF calls for an <Expression>.
  1130.  
  1131.  
  1132.  Parameter Passing
  1133. -------------------
  1134.  
  1135. Pascal provides two different kinds of parameter passing.  The
  1136. first type are called value parameters.  These are the normal
  1137. case.  When you pass a parameter by value, the compiler makes a
  1138. copy of the value, and sends that along.  It's as if someone tells
  1139. you to study the Mona Lisa, providing some photographs for you to
  1140. look at.  You can draw a moustache on the photograph, but it won't
  1141. affect the Mona Lisa, and whatever the procedure or function does
  1142. to the parameter will not affect your original values.  When you
  1143. are calling the procedure, you can use any expression (of the
  1144. correct type, of course) as the actual parameter.
  1145.  
  1146. The other type of parameters are called reference parameters.
  1147. They are specified by preceding the parameter name with the
  1148. reserved word "var" in the procedure or function header.  If you
  1149. use reference parameters, it's as if someone tells you to study
  1150. the Mona Lisa, sends you to the Louvre, and tells you where to
  1151. find the painting.  Thus you are working on the original, and had
  1152. better be careful about it.  Reference parameters must be given as
  1153. variable references - they cannot be full expressions.  Also,
  1154. reference parameters have to pass a stricter type compatibility
  1155. test than value parameters do, since we can't have the procedure
  1156. trying to write a 4-byte Integer into a 1-byte space.
  1157.  
  1158. Normally you should prefer value parameters over reference
  1159. parameters (it tends to cut down on bugs), except in three cases.
  1160. The first is when you actually do want to affect the value of a
  1161. variable.  The second is when the parameter is large.  If you use
  1162. a value parameter, the compiler must make a complete copy of it on
  1163. the stack before it calls the routine, which uses both time and
  1164. stack space.  If you use a reference parameter, the compiler just
  1165. puts the address on the stack.  The third case is when the
  1166. parameter is a file type, in which case it must be passed by
  1167. reference.
  1168.  
  1169. PCQ Pascal pushes arguments on the stack from left-to-right.  C
  1170. compilers, because they have to support variable numbers of
  1171. parameters, push arguments from right-to-left.  Therefore if you
  1172. plan to call C routines, you will have to re-order either the
  1173. order in the call or the order in the routine.
  1174.  
  1175.  
  1176.  Forward Procedures and Functions
  1177. ----------------------------------
  1178.  
  1179. In Pascal, every identifier must be declared before it can be
  1180. used.  This creates problems when procedures or functions are
  1181. mutually dependent, so Pascal allows you to pre-define procedures
  1182. and functions that will be fully defined farther down in the
  1183. source code.
  1184.  
  1185. A forward reference looks just like a normal procedure or function
  1186. declaration, but has the reserved word "Forward" right after the
  1187. header.  The header contains all the information the compiler
  1188. needs to correctly call a routine, so after the forward
  1189. declaration the routine can be used.  When the routine is
  1190. eventually defined, the compiler ensures that it matches up with
  1191. the definition given earlier.  This means that there must be the
  1192. same number of parameters, the parameter types must be the same,
  1193. and if it's a function, the result type must be the same.  Note
  1194. that the actual names of the parameters can be different - only
  1195. their number, order and type are compared.
  1196.  
  1197. A forward reference must be resolved within the same block as it
  1198. was declared, and the same routine cannot be forward-referenced
  1199. more than once.
  1200.  
  1201.  
  1202.  External References
  1203. ---------------------
  1204.  
  1205. External references are very much like forward references - they
  1206. are declarations of routines that aren't actually fully defined.
  1207. The difference is that forward references must be defined later on
  1208. in the same program file, whereas external references are not
  1209. defined in the source file at all.
  1210.  
  1211. The declaration of external references is the same as that of
  1212. forward references, but the reserved word "External" is used in
  1213. place of "Forward".
  1214.  
  1215. External references are used for two main purposes.  First of all,
  1216. they allow you to use procedures and functions defined in External
  1217. files.  All the system routines declared in the include files, for
  1218. example, are actually defined in External files.  They also allow
  1219. you to call routines compiled in a different language, as long as
  1220. you follow some guidelines in parameter passing.  See the section
  1221. called External Files for more information on using external
  1222. routines.
  1223.  
  1224.  
  1225.  Standard Procedures
  1226. ---------------------
  1227.  
  1228. There are several procedures built-in to PCQ Pascal.  They
  1229. include:
  1230.  
  1231.  
  1232.                Close(FileVariable : Any file type)
  1233.  
  1234. The "Close" procedure disassociates the FileVariable from the
  1235. physical disk file, and frees up all the system resources used to
  1236. keep the file open.  See the Input/Output section for more
  1237. information.
  1238.  
  1239.    Dec(V : Any ordinal or pointer) or Dec(V, Amount : Integer)
  1240.  
  1241. Dec (which is short for decrement) subtracts one (or more) from a
  1242. variable.  "Dec(x,n)" is the same as "x := x-n", but slightly more
  1243. efficient.  The variable must be either an ordinal type, like
  1244. Char, Byte, Integer, etc., or a pointer type.  The amount
  1245. parameter, which is optional, must be an integer type - if it is
  1246. not included, the value one is assumed.
  1247.  
  1248. If the variable is an ordinal type, the value is subtracted
  1249. normally.  If the variable is a pointer type, however, Dec()
  1250. multiplies the amount by the size of the type to which the pointer
  1251. refers.  In other words, if you have a pointer p of type ^Integer,
  1252. the statement Dec(p) actually subtracts 4 from the pointer.
  1253.  
  1254.                   Dispose(Variable : ^Anything)
  1255.  
  1256. The "Dispose" procedure frees memory previously allocated with
  1257. "New" (see below).  See the section called Memory Management for
  1258. information on PCQ's memory routines.
  1259.  
  1260.                 Exit or Exit(ReturnCode : Integer)
  1261.  
  1262. Exit, like the AmigaDOS and the C function of the same name,
  1263. terminates the program.  If a return code is specified, it is
  1264. returned to AmigaDOS.  By convention, return codes are normally 5
  1265. for small problems (warnings), 10 for significant problems
  1266. (errors), and 20 when everything goes wrong (failure).  Using Exit
  1267. without a return code is the same as Exit(0), which indicates that
  1268. everything is O.K.
  1269.  
  1270. Exit is the system-safe way to quit a program - you should not
  1271. call AmigaDOS's DOSExit() routine.  When you call Exit, all the
  1272. exit procedures are called in turn.  This includes the standard
  1273. routine that closes all open files and deallocates memory, as well
  1274. as any that you define.
  1275.  
  1276.                Get(var FileVariable : A file type)
  1277.  
  1278. The "Get" procedure moves the file pointer to the next element in
  1279. the file, without actually reading any element in.  The element in
  1280. the file buffer can be accessed through the FileVariable^ syntax.
  1281. See the Input/Output section for details.
  1282.  
  1283.           Inc(VarReference: Ordinal or Pointer type) or
  1284.      Inc(VarReference : Ordinal or Pointer, Amount : Integer)
  1285.  
  1286. The "Inc" command adds an integer Amount to the variable
  1287. VarReference.  If no amount is specified, it is assumed to be 1.
  1288. If the variable is an ordinal type the addition is carried out
  1289. normally, but if it is a pointer type the amount is first
  1290. multiplied by the size of the object to which the pointer refers.
  1291. In other words, Inc(p), where p is a pointer to Integer, actually
  1292. adds 4 (the size of an Integer in bytes) to p.
  1293.  
  1294.                    New(PointerVar : ^Anything)
  1295.  
  1296. The "New" procedure allocates a block of memory equal in size to
  1297. the type to which the variable (which must be a pointer type)
  1298. points.  The address of the newly allocated block will be assigned
  1299. to the variable.  See the section called Memory Management for
  1300. more information.
  1301.  
  1302.                Put(var FileVariable : A file type)
  1303.  
  1304. The "Put" routine advances the file pointer past the current
  1305. element, writing the current element to disk if necessary.  The
  1306. current element can be set through the FileVariable^ syntax.  See
  1307. the section called Input/Output for details.
  1308.  
  1309.  Read(var FileVariable :  Text or File, Variable References....)
  1310.  
  1311. The "Read" procedure inputs information from an AmigaDOS file.
  1312. The FileVariable is optional, and the procedure is one of the very
  1313. few in Pascal that can take a variable number of arguments.  See
  1314. the Input/Output section for more information.
  1315.  
  1316.      Readln(var FileVariable : Text, Variable References....)
  1317.  
  1318. The "Readln" procedure is very similar to "Read", but it can only
  1319. be used on Text files, and after it has read all the arguments it
  1320. requires, it continues to eat characters until it is at the
  1321. beginning of the next line.  See the Input/Output section for more
  1322. information.
  1323.  
  1324.                Reset(var FileVar : File or Text;
  1325.                         FileName : String;
  1326.                       BufferSize : Integer);
  1327.  
  1328. The "Reset" procedure opens a file for reading.  The BufferSize
  1329. parameter is optional.  If you have used the {$I-} directive to
  1330. indicate manual IO checking, you should be sure to check IOResult
  1331. to see if the file opened correctly.  If you are using automatic
  1332. IO checking, the program will terminate with a runtime error if
  1333. the file does not open correctly.  See the Input/Output section
  1334. for more information.
  1335.  
  1336.              Rewrite(var FileVar : File or Text;
  1337.                         FileName : String;
  1338.                       BufferSize : Integer);
  1339.  
  1340. The "Rewrite" procedure opens a file for output, erasing any
  1341. existing file of the same name.  The BufferSize argument is
  1342. optional.  If the file cannot be opened, IOResult will be set to a
  1343. non-zero value.  If you are using automatic IO checking, that will
  1344. cause your program to terminate with a runtime error.  If you are
  1345. using manual IO checking, be sure to look at IOResult to be sure
  1346. the file is open.  See the Input/Output section for more
  1347. information.
  1348.  
  1349.                      Trap(TrapNum : Integer)
  1350.  
  1351. The "Trap" procedure can be used by some debuggers as a sort of
  1352. automatic breakpoint.  If you insert the correct trap, your
  1353. debugger might stop at that location.  Then again it might not.
  1354.  
  1355.        Write(FileVariable : Text or File, Expressions....)
  1356.  
  1357. The "Write" procedure outputs information to an AmigaDOS file.
  1358. The FileVariable is optional, and it can take a variable number of
  1359. arguments.  See the Input/Output section for details.
  1360.  
  1361.           Writeln(FileVariable : Text, Expressions....)
  1362.  
  1363. The "Writeln" procedure is very similar to "Write", but it only
  1364. works on Text files, and it terminates the line after writing all
  1365. of its arguments.  Again, see the Input/Output section for more
  1366. information.
  1367.  
  1368.  
  1369.  Standard Functions
  1370. --------------------
  1371.  
  1372. There are also a bunch of functions built in to the Pascal
  1373. compiler.  They are:
  1374.  
  1375.  
  1376.                 Adr(Variable Reference) : Address
  1377.  
  1378. The Adr() function returns the actual address in memory of the
  1379. parameter.  This is equivalent to Turbo Pascal's Addr() function,
  1380. and as in Turbo Pascal you can also use the @ operator.
  1381.  
  1382.            Abs(numeric expression) : same numeric type
  1383.  
  1384. The function call Abs(n) returns n, if n is positive, and -n if n
  1385. is negative.
  1386.  
  1387.             ArcTan(numeric Expression) : Real radians
  1388.  
  1389. The ArcTan() function returns the approximate arctangent of the
  1390. parameter in radians.
  1391.  
  1392.                   Bit(BitNumber) : Mask Integer
  1393.  
  1394. The Bit() function returns an Integer with just the specified bit
  1395. set.  It is equivalent to (1 shl BitNumber).
  1396.  
  1397.                   Chr(numeric expression) : Char
  1398.  
  1399. The Chr() function transforms any numeric type into its ASCII
  1400. character equivalent.
  1401.  
  1402.                    Ceil(Real expression) : Real
  1403.  
  1404. Ceil() returns the least integer greater than or equal to the
  1405. parameter.
  1406.  
  1407.             Cos(numeric expression in radians) : Real
  1408.  
  1409. The Cos() function returns the cosine of the given angle measured
  1410. in radians.
  1411.  
  1412.                EOF(file or Text variable) : Boolean
  1413.  
  1414. EOF returns True if the file is at the end-of-file position, or
  1415. False otherwise.  The EOF function is only valid for files opened
  1416. for input.  See the section called Input/Output for more
  1417. information.
  1418.  
  1419.                    Exp(numeric expression) : Real
  1420.  
  1421. The function Exp(x) returns e raised to the xth power.  In case
  1422. it slipped your mind, e is about 2.71828....
  1423.  
  1424.                  Float(Integer expression) : Real
  1425.  
  1426. The Float() function converts any Integer type expression to its
  1427. floating point representation.  If the integer is fairly large, it
  1428. might be approximated.  Thus "Trunc(Float(IntVar)) = IntVar" is
  1429. not always true.
  1430.  
  1431.                   Floor(Real expression) : Real
  1432.  
  1433. The Floor() function returns the largest whole number less than or
  1434. equal to the parameter.
  1435.  
  1436.                         IOResult : Integer
  1437.  
  1438. The IOResult() function checks to see if any errors have occurred
  1439. since the last time you checked.  Normally, PCQ Pascal inserts
  1440. statements to check the IOResult automatically, but if you have
  1441. set IO checking off (using the {$I-} directive), you'll have to
  1442. check it explicitly.  The act of checking it erases it, so if you
  1443. need to re-use it you'll have to save it in a variable.  See the
  1444. Input/Output section for more information.
  1445.  
  1446.                   Ln(numeric expression) : Real
  1447.  
  1448. The Ln() function returns the natural logarithm (i.e. the
  1449. logarithm to the base e) of the parameter.
  1450.  
  1451.                  Odd(numeric expression) : Boolean
  1452.  
  1453. The Odd() function returns TRUE if its argument is odd, and FALSE
  1454. otherwise.
  1455.  
  1456.                Open(fname      : String;
  1457.                     var fvar   : file or Text;
  1458.                     BufferSize : Integer) : Boolean;
  1459.  
  1460. Open is the function form of the Rewrite procedure.  It opens a
  1461. file for output, erasing any existing file with the same name.  If
  1462. the file opens correctly, Open returns True.  If not, it returns
  1463. False.  The BufferSize parameter is optional.  See the section
  1464. called Input/Output for more information.
  1465.  
  1466.                 Ord(Ordinal expression) : Integer
  1467.  
  1468. The Ord() function returns the ordinal value of the argument as an
  1469. Integer.  In other words, it can convert Chars, Booleans, and
  1470. enumerated types into their numeric equivalents.  Since it
  1471. actually changes the type of the argument into an Integer it is
  1472. referred to as a transfer function.
  1473.  
  1474.                Pred(Ordinal expression) : same type
  1475.  
  1476. The Pred() function returns the next least ordinal value in the
  1477. same type.  For example, Pred(2) is 1.  If the argument is the
  1478. lowest value within the type (such as Pred(ByteVar) where ByteVar
  1479. is zero), its behavior is undefined.
  1480.  
  1481.              ReOpen(fname      : String;
  1482.                     var fvar   : file or text;
  1483.                     buffersize : Integer) : Boolean
  1484.  
  1485. ReOpen is the function form of Reset.  It opens a file for
  1486. reading, and returns True if everything went O.K.  If for any
  1487. reason the file did not open correctly, ReOpen returns False.  The
  1488. BufferSize parameter is optional, and can be any amount.  See the
  1489. section called Input/Output for more information.
  1490.  
  1491.                  Round(Real expression) : Integer
  1492.  
  1493. The Round() function rounds a real expression to the nearest
  1494. Integer.  It is actually implemented as Trunc(value + 0.5), so it
  1495. takes somewhat longer to execute than the Trunc function.  Also,
  1496. it always rounds 0.5 up.
  1497.  
  1498.             Sin(numeric expression in radians) : Real
  1499.  
  1500. The Sin() function computes the sine for the given angle measured
  1501. in radians.
  1502.  
  1503.                 SizeOf(Type Identifier) : Integer
  1504.  
  1505. The SizeOf() function returns the actual size of the given type.
  1506. Note that the type must be specified as a single identifier.
  1507.  
  1508.                Sqr(numeric expression) : same type
  1509.  
  1510. The function Sqr(x) returns x*x.
  1511.  
  1512.                  Sqrt(numeric expression) : Real
  1513.  
  1514. The function Sqrt(x) returns the square root of x.  In other
  1515. words, Sqrt(x) * Sqrt(x) = x.
  1516.  
  1517.                Succ(Ordinal expression) : same type
  1518.  
  1519. The Succ() function returns the next greater ordinal value within
  1520. the same type.  If that value is not defined (for example, Succ(n)
  1521. where n is the largest enumeration within a type), the function is
  1522. not defined.
  1523.  
  1524.             Tan(numeric expression in radians) : Real
  1525.  
  1526. Returns the tangent of the angle measured in radians.  If the
  1527. parameter is an odd multiple of Pi/2, this function will take on
  1528. meaningless values (the tangent function is undefined at odd
  1529. multiples of Pi/2).
  1530.  
  1531.                  Trunc(real expression) : Integer
  1532.  
  1533. The Trunc() function returns the integer portion of a floating
  1534. point number.  It is the fastest way to convert a real value to an
  1535. Integer value.
  1536.  
  1537.  
  1538.  
  1539.  
  1540.  
  1541. ===================================================================
  1542.  
  1543.                         Label Declarations
  1544.  
  1545. ===================================================================
  1546.  
  1547. Labels must be declared in the declaration section before they can
  1548. be used in the program.  The label declaration section has the
  1549. following form:
  1550.  
  1551. <Label Declarations> ::= Label <Identifiers> ;
  1552.  
  1553. <Identifiers> ::= <Identifier> | <Identifier> , <Identifiers>
  1554.  
  1555. Note that Standard and Turbo Pascal also allow labels to have
  1556. numeric values, but PCQ Pascal only allows normal identifiers to
  1557. be used.  If you run across a program with numeric labels, you can
  1558. just put some letter on the front to make them legal identifiers.
  1559. Perhaps a better solution would be to trash the program.
  1560.  
  1561.  
  1562.  
  1563.  
  1564.  
  1565. ===================================================================
  1566.  
  1567.                            Expressions
  1568.  
  1569. ===================================================================
  1570.  
  1571. PCQ Pascal accepts expressions very similar in form to just about
  1572. all Pascal implementations.  It's probably very familiar to you,
  1573. but just to be on the safe side, we'll define it.  Let's start off
  1574. with the constants accepted by PCQ:
  1575.  
  1576.  
  1577. <digit>         ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
  1578.  
  1579. <digits>        ::= <digit> | <digit> <digits>
  1580.  
  1581. <binary digit>  ::= 0 | 1
  1582.  
  1583. <binary digits> ::= <binary digit> | 
  1584.                     <binary digit> <binary digits>
  1585.  
  1586. <hex digit>     ::= <digit> | a | b | c | d | e | f
  1587.  
  1588. <hex digits>    ::= <hex digit> | <hex digit> <hex digits>
  1589.  
  1590. <Float Const>   ::= <digits> . <digits>
  1591.  
  1592. <Integer Const> ::= <digits> | $ <hex digits> | % <binary digits>
  1593.  
  1594. <Char Value>    ::= <ASCII char> | \ <escape sequence>
  1595.  
  1596. <Char Values>   ::= <Char Value> | <Char Value> <Char Values>
  1597.  
  1598. <Number Const>  ::= <Integer Const> | <Float Const>
  1599.  
  1600. <Char Const>    ::= ' <Char Value> '
  1601.  
  1602. <String Const>  ::= " <Char Values> "
  1603.  
  1604. <Char Array Const> ::= ' <Char Values> '
  1605.  
  1606.  
  1607. That should confuse things a bit.  What it says is that whenever
  1608. the compiler expects an integer, you can use decimal, hexadecimal
  1609. or binary representation.  It also says that floating point
  1610. constants are only recognized in the normal 23.23 form, without
  1611. any trailing exponent.  Finally, it says that you can use C-style
  1612. escape sequences for any text constant - these escape values are
  1613. discussed in the Strings section.
  1614.  
  1615. So how are these things grouped into complete expressions?
  1616. Consider the following definitions:
  1617.  
  1618. <expression> ::= <simple> <rel op> <simple> | <simple>
  1619.  
  1620. <rel op>     ::= = | <> | < | > | <= | >=
  1621.  
  1622. <simple>     ::= <term> <add op> <term> | <term>
  1623.  
  1624. <add op>     ::= + | - | or | xor
  1625.  
  1626. <term>       ::= <factor> <mul op> <factor> | <factor>
  1627.  
  1628. <mul op>     ::= * | / | div | mod | and | shr | shl
  1629.  
  1630. <factor>     ::= <Number Const>         |
  1631.                  <Sign> <Number Const>  |
  1632.                  <Char Const>           |
  1633.                  <String Const>         |
  1634.                  <Char Array Const>     |
  1635.                  <Variable Reference>   |
  1636.                  @ <Variable Reference> |
  1637.                  not <factor>           |
  1638.                  ( <Expression> )       |
  1639.                  <Function call>
  1640.  
  1641.  
  1642. What does all this mean?  It means that expressions are built up
  1643. from factors, the basic blocks of an expression.  A factor can be
  1644. a constant, a variable, a parenthesized expression, and all the
  1645. other things listed.  The following examples are all factors:
  1646.  
  1647.                                 23
  1648.                            (4.0 - 2.3)
  1649.                             %01000001
  1650.                                'a'
  1651.                      RecordPtr^.Field1[45,23]
  1652.                               @Var1
  1653.                             Abs(Var2)
  1654.  
  1655. Factors can have a unary operator (an operator that applies to
  1656. only one value, unlike binary operators that apply to two).  They
  1657. are:
  1658.  
  1659.         @   This operator is the address-of operator.  The returns
  1660.             the address of the variable reference immediately
  1661.             following.  It is equivalent to the Adr() function.
  1662.         -   Sign negation.  Takes the negation of the factor
  1663.             following it.
  1664.         +   Sign identity.  It is accepted, but has no affect.
  1665.        not  Boolean or bitwise negation.  If the factor is a
  1666.             Boolean value, this returns the opposite.  If it is an
  1667.             integer type, it returns the bitwise compliment.
  1668.  
  1669. These factors are built into terms.  Terms are either the same as
  1670. factors, or two factors with a multiplicative operator between
  1671. them.  The multiplicative operations are the following:
  1672.  
  1673.         *   Multiplication
  1674.         /   Floating point division.  Both arguments to this
  1675.             operator are converted to floating point before the
  1676.             operation takes place.
  1677.        div  Integer division.  Both arguments to this operator
  1678.             are converted to integer forms before the operation
  1679.             takes place.
  1680.        mod  The remainder operation.  Both arguments are
  1681.             converted to integers if necessary.
  1682.        and  Logical AND function.  If both arguments are Boolean
  1683.             values and the left factor evaluates to FALSE, this
  1684.             operation will "short-circuit".  Any Real factors are
  1685.             converted to Integers.
  1686.        shl  Shift left.  Shifts the bits in the left operand the
  1687.             number of positions given by the right operand.  Both
  1688.             arguments are converted to Integers if necessary.
  1689.        shr  Shift right.  Shifts the bits in the right operand
  1690.             the number of positions given by the right operand.
  1691.             This is a logical shift, not arithmetic, so the
  1692.             left-most bit is assigned 0.  Thus if you shift a
  1693.             negative number in order to do division, you will get
  1694.             nonsense results (use div instead - it will use shifts
  1695.             when possible).  Both arguments are converted to
  1696.             Integers.
  1697.  
  1698. Terms, in turn, are built into simple expressions.  Simple
  1699. expressions are either the same thing as terms, or two terms
  1700. grouped by an addition operator.  The addition operators are:
  1701.  
  1702.         +   Adds the two operands.
  1703.         -   Subtracts the second operand from the first.
  1704.         or  Logical OR.  If both operands are Boolean values and
  1705.             the left operand evaluates to TRUE, the right operand
  1706.             is not evaluated.  Both arguments are converted to
  1707.             Integers if necessary.
  1708.        xor  Exclusive OR.  Generates the left term exclusive ORed
  1709.             with the right term.  This never short circuits.  If
  1710.             either argument is a Real value, it is converted to an
  1711.             Integer.
  1712.  
  1713. These simple expressions are built into complete expressions.
  1714. Expressions are either the same thing as simple expressions, or
  1715. two simple expressions grouped by a relative operator.  These
  1716. operators produce Boolean results, and are defined as:
  1717.  
  1718.         =   Returns TRUE iff the two arguments are equal.
  1719.         <>  Returns TRUE iff the two arguments are not equal.
  1720.         >   Returns TRUE iff the left argument is greater than the
  1721.             right argument.
  1722.         <   Returns TRUE iff the left argument is less than the
  1723.             right argument.
  1724.         >=  Returns TRUE iff the left argument is either greater than
  1725.             or equal to the right argument (that's only takes one
  1726.             comparison, by the way).
  1727.         <=  Returns TRUE iff the left argument is either less than
  1728.             or equal to the right argument.
  1729.  
  1730.         (iff is shorthand for "if and only if")
  1731.  
  1732.  
  1733.  Evaluation Order & Short Circuits
  1734. --------------------------------------------------
  1735.  
  1736. The normal rules of math are built-in to the grammar for
  1737. expressions.  The unary operators are evaluated first, then all
  1738. the multiplicative operations, the additive operations, and
  1739. finally the relative operations.  Thus the precedence looks like
  1740. this:
  1741.  
  1742.         Operator              Precedence
  1743.       -------------------------------------
  1744.         @,not,unary +/-     First (highest)
  1745.  
  1746.         *,/,div,mod,
  1747.         and,shr,shl         Second
  1748.  
  1749.         +,-,or,xor          Third
  1750.  
  1751.         =,<>,<,>,>=,<=      Fourth (lowest)
  1752.  
  1753. All expressions in parentheses are, of course, evaluated first.
  1754. Also, keep in mind that all of these operators are left
  1755. associative - in other words, a factor between two operators of
  1756. equal precedence is bound to the one on the left (e.g.  "x+y+z" is
  1757. treated as "(x+y)+z").
  1758.  
  1759. You should not make any conclusions about the order in which the
  1760. two operands to a binary operator are evaluated.  If you have the
  1761. expression "function1 + function2" in your program, for example,
  1762. there is no telling which function would be evaluated first.
  1763.  
  1764. The exception to that rule is for Boolean equations, but only if
  1765. you are using short-circuit evaluations (the default).  What is a
  1766. short circuit?  Imagine you have the expression "A or B" in your
  1767. program.  If the program evaluates A and finds that it is True, it
  1768. already knows the final value of the entire expression.  Therefore
  1769. there's no point in evaluating B.  The analogous case for "A and
  1770. B" occurs when A evaluates to False.  You can be sure, in a
  1771. Boolean expression, that the operands of "and" and "or" will be
  1772. evaluated left-to-right.
  1773.  
  1774. Short-circuit evaluations are often faster than normal ones, but
  1775. they have the added benefit of protecting the programmer.  For
  1776. example, the statement:
  1777.  
  1778.         if OpenMyWindow(w) and (w^.Width = whatever) then ....
  1779.  
  1780. ... would be a problem without short-circuit evaluations because,
  1781. for example, the variable w might not be defined if the function
  1782. call fails.  The value of the function would not change, but if
  1783. w pointed to an odd address it could cause a guru.  With
  1784. short-circuit evaluations, the second factor would not be
  1785. evaluated unless the first returned True.
  1786.  
  1787.  
  1788.  Constant Expressions
  1789. ----------------------
  1790.  
  1791. Constant expressions are the same as normal expressions, but must
  1792. be completely evaluated at compile time.  Thus they can't use any
  1793. external functions or variable references, but can use all the
  1794. same operators and the standard functions (i.e. the ones built-in
  1795. to the compiler).
  1796.  
  1797.  
  1798.  Variable References
  1799. ---------------------
  1800.  
  1801. Variable references can get awfully complex, what with pointers
  1802. and records and arrays and so forth.  The basic syntax is as
  1803. follows:
  1804.  
  1805. <Variable Reference> ::= <Variable Mark> |
  1806.                          <Variable Mark> <Selectors>
  1807.  
  1808. <Variable Mark> ::= <Variable ID> |
  1809.                     <Type ID> ( <Variable Reference> )
  1810.  
  1811. <Selectors>  ::= <Selector> | <Selector> <Selectors>
  1812.  
  1813. <Selector>   ::= ^ | .<Field Id> | [ <Index Expressions> ]
  1814.  
  1815.  
  1816. Generally speaking, a variable reference will consist of the
  1817. identifier of a global or local variable, followed by any number
  1818. of selectors in any combination.  The other possibility, which is
  1819. somewhat different as of version 1.2 of the compiler, is that you
  1820. can place a type cast somewhere in the middle of all this.  The
  1821. following are all examples of variable references:
  1822.  
  1823.         Var1
  1824.         Var1^
  1825.         Var1^.Field1[34,56]
  1826.         Type2(Var1)^.Field2^^[23]
  1827.  
  1828. If you start writing code that looks like the last example, you
  1829. should get some rest.
  1830.  
  1831.  
  1832.  
  1833.  
  1834. ===================================================================
  1835.  
  1836.                           Statements
  1837.  
  1838. ===================================================================
  1839.  
  1840. Statements are the meat and potatoes of programs - they are what
  1841. goes between begin and end.  They have the following form:
  1842.  
  1843. <Statement>   ::= <If Statement>         |
  1844.                   <While Statement>      |
  1845.                   <Repeat Statement>     |
  1846.                   <For Statement>        |
  1847.                   <Case Statement>       |
  1848.                   <With Statement>       |
  1849.                   <Compound Statement>   |
  1850.                   <Assignment Statement> |
  1851.                   <Procedure Call>       |
  1852.                   <Return Statement>     |
  1853.                   <Goto Statement>
  1854.  
  1855.  
  1856.  If Statements
  1857. ---------------
  1858.  
  1859. The if statement allows you to test alternatives.  It has the
  1860. following form:
  1861.  
  1862. <If Statement> ::= if <Boolean Expr> then <Statement> |
  1863.                    if <Boolean Expr> then <Statement>
  1864.                                      else <Statement>
  1865.  
  1866. If the Boolean expression evaluates to True, the statement
  1867. following the word "then" is executed.  If the Boolean expression
  1868. evaluates to False, the statement in the else clause, if one
  1869. exists, is evaluated.  If no else clause exists, execution
  1870. continues with the statement following the "if" statement.
  1871.  
  1872. There is an ambiguity here - consider the following fragment:
  1873.  
  1874.         if Expr then if Expr then Statement1 else Statement2
  1875.  
  1876. To which "if" test does the else clause apply?  PCQ, like most
  1877. implementations, always attaches the else part to the most recent
  1878. "if".
  1879.  
  1880.  
  1881.  While Statements
  1882. ------------------
  1883.  
  1884. The "while" statement is one of several that allow you to loop.
  1885. It has the following form:
  1886.  
  1887. <While Statement> ::= while <Boolean Expr> do <Statement>
  1888.  
  1889. At the beginning of the loop, the Boolean expression is evaluated.
  1890. If it evaluates to True, the statement part is executed.  When
  1891. that finishes, the expression is re-evaluated, and the process
  1892. continues until the expression evaluates to False.  Once that
  1893. happens, execution continues with the statement following the
  1894. while statement.
  1895.  
  1896.  
  1897.  Repeat Statements
  1898. -------------------
  1899.  
  1900. The "repeat" statement provides a slightly different form of
  1901. looping.  It has the following form:
  1902.  
  1903. <Repeat Statement> ::= repeat <Statements> until <Boolean Expr>
  1904.  
  1905. <Statements> ::= <Statement> | <Statement> ; <Statements>
  1906.  
  1907. When the repeat statement is encountered, the statement part is
  1908. executed, then the Boolean expression is evaluated.  If the
  1909. expression evaluates to False, the statement part is executed
  1910. again.  If the expression evaluates to True, execution continues
  1911. at the following statement.  Note that "repeat" loops always
  1912. execute at least once, whereas "while" loops might not execute at
  1913. all.  Also note that the <Statements> part can actually be empty.
  1914.  
  1915.  
  1916.  For Statements
  1917. ----------------
  1918.  
  1919. The "for" statement provides a third type of looping, for
  1920. occasions when you know exactly how many iterations of the loop
  1921. you want to execute.  It has the following form:
  1922.  
  1923. <For Statement> ::= for <Variable Reference> :=
  1924.                         <Expression> <Direction>
  1925.                         <Expression> do <Statement>
  1926. <Direction> ::= to | downto
  1927.  
  1928. Note that this is different from the PCQ version 1.1.  When a
  1929. "for" loop is encountered, the first expression (the initial
  1930. value) is evaluated, and its value is stored in the variable
  1931. reference (called the index).  Then the index is compared to the
  1932. second expression (the final value).  If the direction is "to",
  1933. and the index is less than or equal to the final value, the
  1934. statement part is executed.  At the end of that, the index is
  1935. incremented by one and again tested against the final value.  This
  1936. goes on until the index is greater than the final value, at which
  1937. time execution moves on to the next statement.
  1938.  
  1939. If the direction is "downto", the same thing happens, except the
  1940. index is decremented at each pass, and looping continues until the
  1941. index is less than the final value.
  1942.  
  1943. Note that the "for" loop might not execute at all, if the initial
  1944. value is larger than the final value (for "to" loops, or vice
  1945. versa for "downto" loops).  Also note that the final value is
  1946. fully evaluated each time through the loop, so if it's a complex
  1947. expression you might want to store it in a variable before the
  1948. "for" statement.
  1949.  
  1950. You can always use a "while" or "repeat" loop in place of a "for"
  1951. loop, and in fact the "for" loop is least often used.  Niklaus
  1952. Wirth, the guy who designed Pascal and Modula-2, actually left the
  1953. statement out of his latest language (Oberon).
  1954.  
  1955. It is considered an error to modify the index variable within the
  1956. loop, but PCQ Pascal doesn't enforce it.  That doesn't make it a
  1957. good idea, of course.
  1958.  
  1959.  
  1960.  Case Statements
  1961. -----------------
  1962.  
  1963. The Case statement is used to test a value against a series of
  1964. alternatives, and process instructions accordingly.  It has the
  1965. following form:
  1966.  
  1967. <Case Statement> ::= case <Expression> of <Alternatives> end |
  1968.                      case <Expression> of <Alternatives>
  1969.                                        else <Statement> end
  1970.  
  1971. <Alternatives> ::= <Alternative> | <Alternative> ; <Alternatives>
  1972.  
  1973. <Alternative> ::= <Case Vals> : <Statement>
  1974.  
  1975. <Case Vals> ::= <Case Val> | <Case Val> , <Case Vals>
  1976.  
  1977. <Case Val>  ::= <Const Expr> | <Const Expr> .. <Const Expr>
  1978.  
  1979. When the case statement is executed, the expression is evaluated.
  1980. It is then compared against all of the cases and ranges until it
  1981. matches one, at which point the associated statement is executed.
  1982. If none of the alternatives match, the else statement is executed,
  1983. if there is one.  If not, execution just continues with the
  1984. statement following the case statement.
  1985.  
  1986. Note that the expression is only evaluated once, so a case
  1987. statement can be more efficient than an equivalent series of "if"
  1988. statements.  Also note that one statement (at most) from the case
  1989. statement is executed - it's not like C, where execution falls
  1990. through until you tell it to knock it off.
  1991.  
  1992.  
  1993.  With Statements
  1994. -----------------
  1995.  
  1996. The With statement allows to specify a record variable to which a
  1997. statement will apply.  Within the statement you can abbreviate
  1998. references to the record's fields by specifying just the field
  1999. name.  That saves you some typing, and the compiler generates
  2000. somewhat more efficient code.  It serves no functional purpose.
  2001. The format of a With statement is as follows:
  2002.  
  2003. <With Statement> ::= with <Expressions> do <Statement>
  2004.  
  2005. <Expressions> ::= <Expression> | <Expression> , <Expressions>
  2006.  
  2007. If you specify more than one record (separated by commas), the
  2008. compiler treats it like nested with statements, with the first
  2009. record listed at the outermost scope and the last one at the
  2010. innermost.
  2011.  
  2012. In the statement, any references to fields will be considered to
  2013. apply to the innermost record to which it applies.  Ambiguities
  2014. can be cleared up by using the full record specification.
  2015.  
  2016. With statements are especially handy when the record reference is
  2017. long and convoluted - it will only be executed once, which
  2018. increases efficiency.  The other time it comes in especially handy
  2019. is filling in values in a record.  It doesn't always improve the
  2020. program's efficiency, but it saves a lot of typing.
  2021.  
  2022. If you are executing under a with statement of the form "with p^
  2023. do ...", it is considered an error to alter the value of p.  For
  2024. example, it is an error to free the memory of a record in a "with"
  2025. statement referencing the record.  This error is not detected by
  2026. PCQ Pascal, but it's a good idea to avoid it.
  2027.  
  2028.  
  2029.  Compound Statements
  2030. ---------------------
  2031.  
  2032. The compound statement allow you to use a series of statements in
  2033. any situation that calls for at least one statement.  It has the
  2034. following form:
  2035.  
  2036. <Compound Statement> ::= begin <Statements> end
  2037.  
  2038. A compound statement can in fact be used wherever a statement is
  2039. allowed, and the compound statement by itself generates no extra
  2040. code.  In other words, surrounding a group of expressions with
  2041. "begin" and "end" will not change the code the compiler produces -
  2042. it just clarifies your purpose.
  2043.  
  2044.  
  2045.  Assignment Statements
  2046. -----------------------
  2047.  
  2048. Assignment statements are used to set the value of variables.
  2049. They have the following form:
  2050.  
  2051. <Assignment Statement> ::= <Variable Reference> := <Expression>
  2052.  
  2053. Remember that the type of the variable must match the type of the
  2054. expression identically (see the section called Type Declarations
  2055. for the specific rules).
  2056.  
  2057.  
  2058.  Procedure Calls
  2059. -----------------
  2060.  
  2061. Procedure calls transfer execution to a pre-defined routine,
  2062. passing parameters as required.  They have the following form:
  2063.  
  2064. <Procedure Call> ::= <Identifier> |
  2065.                      <Identifier> ( <Actual Params> )
  2066.  
  2067. <Actual Params> ::= <Actual Param> |
  2068.                     <Actual Param> ; <Actual Params>
  2069.  
  2070. <Actual Param> ::= <Expression>
  2071.  
  2072. Procedures are different from functions in that functions return a
  2073. value, and are callable only from expressions.  Procedures do not
  2074. return a value, and are callable only from statements.
  2075.  
  2076. When a procedure statement is executed, each actual parameter is
  2077. evaluated and pushed on the stack, in left to right order.
  2078. Because C uses variable numbers of parameters, it pushes actual
  2079. parameters on the stack in right to left order.  Therefore if you
  2080. plan to call a C routine you will need to reverse the order of the
  2081. parameters.
  2082.  
  2083.  
  2084.  Return Statements
  2085. -------------------
  2086.  
  2087. Normally, execution of a procedure continues until the end of the
  2088. procedure, when execution returns to the caller.  The "return"
  2089. statement allows you to escape the current procedure immediately.
  2090. It has the following very simple form:
  2091.  
  2092.     <Return Statement> ::= return
  2093.  
  2094. The "return" statement is only valid within procedures.  It is not
  2095. valid within functions because they must return a value - the
  2096. analogous statement in a function is an assignment to the function
  2097. identifier, which causes the function to return immediately.  The
  2098. "return" statement is also not valid in the main body of the
  2099. program, because it would cause the program to terminate.  Instead
  2100. you must explicitly terminate the program with the Exit statement.
  2101.  
  2102.  
  2103.  
  2104.  Goto Statements
  2105. -----------------
  2106.  
  2107. The "goto" statement immediately transfers execution to a defined
  2108. label.  It should be used with extreme care, and if possible
  2109. avoided.  Its form is:
  2110.  
  2111. <Goto Statement> ::= goto <Identifier>
  2112.  
  2113. Standard Pascal requires that a goto label should be a series of
  2114. digits, and Turbo Pascal extends that definition to allow
  2115. identifiers to be used as labels.  PCQ Pascal takes the next
  2116. logical step by requiring that labels be identifiers, not numbers.
  2117.  
  2118. Most programmers will tell you that the "goto" statement is simply
  2119. bad programming practice, because it makes programs difficult to
  2120. understand and debug.  There are, however, other problems.  For
  2121. instance, if you "goto" from inside a "for" loop to outside of the
  2122. loop, you will confuse your program's stack (until you leave the
  2123. routine).  Similar things happen for the "with" statement.  I
  2124. won't even bother to tell you the havoc that would ensue if you
  2125. jumped into a "for" loop from outside.
  2126.  
  2127. The moral of the story is: try to avoid them.
  2128.  
  2129.  
  2130.  
  2131.  
  2132.  
  2133.  
  2134.  
  2135. ===================================================================
  2136.  
  2137.                       Input/Output
  2138.  
  2139. ===================================================================
  2140.  
  2141.  
  2142.  Pascal IO
  2143. -----------
  2144.  
  2145. You can think of the Pascal IO routines as an interface to the
  2146. AmigaDOS routines.  The Pascal IO routines all use AmigaDOS for
  2147. the actual reading and writing, so if you felt like it you could
  2148. just use an AmigaDOS file instead.
  2149.  
  2150. Pascal IO does have several advantages, however.  First of all,
  2151. all PCQ Pascal files are buffered, which means that reads and
  2152. writes do not necessarily have to access AmigaDOS each time.  That
  2153. speeds things up a bit.
  2154.  
  2155. The other advantage you get is the use of the Pascal Read, ReadLn,
  2156. Write and Writeln routines, which can be awfully handy.
  2157.  
  2158. When you declare a file in your program, as either a "File of Some
  2159. Type" or as "Text", you are in effect allocating a record.  That
  2160. record, if its fields were accessible, would look like:
  2161.  
  2162.      PCQFile = record
  2163.          Handle      : An AmigaDOS file handle
  2164.          Next        : A pointer to the next open Pascal file
  2165.          Buffer      : The address of the file's buffer
  2166.          Current     : The position in the buffer at which the
  2167.                        next read or write will take place.
  2168.          Last        : The Last position of a read
  2169.          Max         : The address of the end of the buffer+1
  2170.          RecSize     : The size of the file elements
  2171.          Interactive : A Boolean value - True means the file
  2172.                        is attached to a CLI window.
  2173.          EOF         : A Boolean value
  2174.          Access      : A Short value, either MODE_NEWFILE or
  2175.                        MODE_OLDFILE
  2176.      end;
  2177.  
  2178.  
  2179.  
  2180.  Text and Typed Files
  2181. ----------------------
  2182.  
  2183. Pascal has two very different types of files.  The normal kind of
  2184. file is called a typed file, and is declared with a type
  2185. specification of the form:
  2186.  
  2187.                   FileVar : File of ElementType
  2188.  
  2189. Typed files are essentially unlimited sequences of elements of
  2190. that one element type.  The Write command can be used to write
  2191. individual elements to the end of the file, and the Read command
  2192. can be used to input the current element and move the file pointer
  2193. to the next one.  You can only write one type of element to each
  2194. typed file.
  2195.  
  2196. Typed files store their elements in exactly the same format that
  2197. they appear in memory, so they are often unreadable.  A file of
  2198. character elements is readable, but a file of integer elements
  2199. would be incomprehensible.  Since typed files always store
  2200. complete elements, each element is necessarily a fixed size.
  2201.  
  2202. You don't actually need anything but typed files - anything you
  2203. can do with Pascal files can be done with them.  For the sake of
  2204. convenience, however, Pascal also uses the Text file type.  The
  2205. Text file is a special kind of "File of Char", but is not
  2206. compatible with it.  Text files are made up of ASCII characters
  2207. broken up into variable length lines.  Each line is terminated by
  2208. a special newline character, which on the Amiga is the line feed
  2209. character (ASCII 10.  On MS-DOS machines, the newline character is
  2210. the carriage return/line feed sequence).
  2211.  
  2212. Since Text files (like this documentation, and all the source
  2213. files) are so common, Pascal has a variety of routines built-in to
  2214. read and write values to and from them.  Most of the standard
  2215. types, for example, have a special routine for converting them
  2216. into ASCII characters and writing them to a file.  These routines
  2217. are called automatically by the compiler to write each expression
  2218. in a Write procedure to a Text file.  Similar routines exist for
  2219. reading the same types.  The descriptions of the Read and Write
  2220. procedures below described exactly how this conversion takes
  2221. place.
  2222.  
  2223. There is even a special form of the Read and Write procedures
  2224. designed to work only with Text files - the ReadLn and WriteLn
  2225. commands.  They are explained below, but note that since typed
  2226. files have no lines, these two routines are used only for Text
  2227. files.
  2228.  
  2229.  
  2230.  Opening Files
  2231. ---------------
  2232.  
  2233. There are several closely related routines for opening Pascal
  2234. files.  For opening input files, which are existing files that
  2235. will be opened for reading, you can use either the ReOpen()
  2236. function or the Reset() procedure.  They are defined as follows:
  2237.  
  2238.  
  2239.  
  2240.                Reset(var FileVar : File or Text;
  2241.                         FileName : String;
  2242.                       BufferSize : Integer);
  2243.  
  2244. The "Reset" procedure opens a file for reading.  The FileVar
  2245. parameter specifies the Pascal file variable that should be
  2246. associated with this AmigaDOS file.  The FileName is the file
  2247. name, with a complete path if necessary.  Since this can be any
  2248. valid AmigaDOS filename, it can actually refer to the printer, a
  2249. console window, or all sorts of other things.
  2250.  
  2251. The BufferSize parameter specifies the size of the buffer you
  2252. want, in bytes.  When PCQ tries to open your file, it will try to
  2253. allocate this much memory as a buffer.  If it can't, it sets
  2254. IOResult and fails.  Actually, PCQ tries to allocate a buffer that
  2255. is an even multiple of the file element size, not larger than
  2256. BufferSize, but at least one element long (the element size for
  2257. Text files is one character).  The BufferSize parameter is
  2258. entirely optional - if it's not included, a default value of 128
  2259. is used.
  2260.  
  2261. If you are using automatic IO checking, your program will abort
  2262. with a runtime error if the file cannot be opened.  If you are
  2263. checking manually, it will just set IOResult.
  2264.  
  2265. The variable FileVar should not refer to an file that's already
  2266. open.  Either the file should be closed first, or you should use a
  2267. different file variable.
  2268.  
  2269.  
  2270.  
  2271.              ReOpen(fname      : String;
  2272.                     var fvar   : file or text;
  2273.                     buffersize : Integer) : Boolean
  2274.  
  2275. ReOpen is the function form of Reset.  It attempts to open a file
  2276. in the same way as Reset, and if everything goes O.K. it returns
  2277. True.  If there was a problem, it returns False.
  2278.  
  2279. ReOpen never sets IOResult, so if you are using automatic IO
  2280. checking a call to ReOpen will not abort the program.  As in the
  2281. Reset procedure, the BufferSize parameter is optional.
  2282.  
  2283.  
  2284.  
  2285. If you need to open a file for writing (which deletes any existing
  2286. file of the same name!), you can use the Rewrite procedure or the
  2287. Open() function.  They are defined as:
  2288.  
  2289.  
  2290.  
  2291.              Rewrite(var FileVar : File or Text;
  2292.                         FileName : String;
  2293.                       BufferSize : Integer);
  2294.  
  2295. Rewrite opens an AmigaDOS file for writing, erasing any existing
  2296. file with the same name.  The parameters are just like the Reset
  2297. command, and the BufferSize is still optional.
  2298.  
  2299. Rewrite sets IOResult, so if your program is using automatic IO
  2300. checking it will abort if the file cannot be opened.  Programs
  2301. handling their own IO checks should be sure to look at IOResult.
  2302.  
  2303. As with all the file opening routines, you should not use a file
  2304. variable that already refers to an open file.
  2305.  
  2306.  
  2307.  
  2308.                Open(fname      : String;
  2309.                     var fvar   : file or text;
  2310.                     buffersize : Integer) : Boolean
  2311.  
  2312. Open is equivalent to Rewrite, but in function form.  It attempts
  2313. to open the file for writing, and if everything goes O.K.  it
  2314. returns True.  If there is any problem, it returns false.
  2315. Remember that opening a file for output means that any existing
  2316. file with the same name gets erased.
  2317.  
  2318. Open does not set IOResult, so programs using automatic IO
  2319. checking can use it without aborting.  The BufferSize parameter,
  2320. just as in the rest of the file opening routines, is optional.
  2321.  
  2322.  
  2323.  
  2324.  Writing to Files
  2325. ------------------
  2326.  
  2327. Output in Pascal is handled by the Write and Writeln procedures.
  2328. Unlike most Pascal procedures, these routines will accept an
  2329. unlimited number of parameters.  If you are writing to a Text
  2330. file, the parameters can be a variety of types.  The Write
  2331. procedure has the following basic form:
  2332.  
  2333.  
  2334.      Write(var FileVar : Text or Typed File, Expressions...)
  2335.  
  2336. The FileVar is optional.  If it is not included, the standard Text
  2337. file Output is used in its place.  If the FileVar is a typed file,
  2338. each expression must be of the element type.  They will be written
  2339. to the file with no space in between them, formatted just as they
  2340. are in memory.
  2341.  
  2342. If you are writing to a text file, it's a different story
  2343. entirely.  First of all, each expression can take the form "e:m:n"
  2344. where e is the expression itself and m and n are constant
  2345. integers.  m specifies the minimum field width - if the item to be
  2346. written would take up fewer than m characters, spaces are written
  2347. to fill out the field.  n is only allowed if e is an expression of
  2348. type Real, and it specifies how many digits to the right of the
  2349. decimal point will be written out.  The default values for m and n
  2350. are 1 and 2, respectively.  Specifically what gets written out
  2351. depends on the type, according to the following:
  2352.  
  2353. Integer
  2354. Short
  2355. Byte     These three types are all written as sequences of ASCII
  2356.          digits, as expected.  They are not preceded by any spaces,
  2357.          but Short and Integer types might lead off with a minus
  2358.          sign if appropriate.  There will be no trailing spaces.
  2359.  
  2360. Real     The entire integer part (the part to the left of the
  2361.          decimal point) is written out.  If n is not zero, a
  2362.          decimal point followed by n fractional digits are written
  2363.          out.  Note that for Real numbers, m indicates the number
  2364.          of digits to the left of the decimal point that should be
  2365.          written, not the full field width (this will probably
  2366.          change in the next version).
  2367.  
  2368. Char     A character is written out as just the single character,
  2369.          unchanged.
  2370.  
  2371. Array of Char
  2372.          The entire array, for its whole declared length, is
  2373.          written out character by character.
  2374.  
  2375. String   The entire string up to, but not including, the
  2376.          terminating null character is written.
  2377.  
  2378. Boolean  Either the word TRUE or the word FALSE is written, with
  2379.          no leading or trailing spaces.
  2380.  
  2381.  
  2382.  
  2383.            WriteLn(var FileVar : Text; Expressions...)
  2384.  
  2385. Writeln is exactly the same as Write, but after is has written out
  2386. each of the expressions according to the rules above, it also
  2387. writes out a newline character.  WriteLn can only be used on Text
  2388. files.
  2389.  
  2390.  
  2391.  Reading from Files
  2392. --------------------
  2393.  
  2394. Input in Pascal is handled by the Read procedure.  Like the Write
  2395. procedures, Read accepts any number of parameters, and many types
  2396. of parameters if you are reading from a Text file.  The format is
  2397. as follows:
  2398.  
  2399.    Read(var FVar : Text or Typed File; Variable References....)
  2400.  
  2401. The FVar parameter is optional.  If it is omitted, the standard
  2402. Text file "Input" is used in its place.
  2403.  
  2404. If FVar refers to a typed file, each variable reference is filled
  2405. with the subsequent file elements, unless EOF is reached or some
  2406. other error occurs first.  Reading from a Text file is a somewhat
  2407. more flexible job.  Just as with the Write statements, what
  2408. happens depends on the type being read, according to the
  2409. following:
  2410.  
  2411. Integer
  2412. Short
  2413. Byte     All white space, which is defined as any character whose
  2414.          ASCII value is less than or equal to 32 (the space
  2415.          character) is skipped.  If the first non-white space
  2416.          character is not a digit or the EOF is reached, an IO
  2417.          error is raised (see Exit Procedures for more
  2418.          information).  If not, digits are read until the first
  2419.          non-digit.  The resulting number is returned, and the
  2420.          file pointer rests on that non-digit.
  2421.  
  2422. Real     First, an integer is read exactly as above.  If the next
  2423.          character is a period, digits are again read in as
  2424.          fractional digits until the first non-digit.  The pointer
  2425.          rests on that first non-digit.  A Real value does not
  2426.          need a fractional part, nor does it require a decimal 
  2427.          point.
  2428.  
  2429. Char     Reads the next single character.  Standard Pascal
  2430.          translates end-of-line characters into spaces, but PCQ
  2431.          Pascal, like Turbo Pascal, allows them to come through as
  2432.          ASCII linefeeds.
  2433.  
  2434. Array of Char
  2435.          Reads characters into the array until either the array is
  2436.          full, or the end-of-line is reached.  If the end-of-line
  2437.          is reached, the rest of the array is padded with spaces
  2438.          and the file pointer is left pointing at the end-of-line
  2439.          character - you'll need to call Readln to get rid of it.
  2440.  
  2441. String   Reads characters into the String buffer until the
  2442.          end-of-line is reached.  At that point the string is
  2443.          terminated by a zero byte, and the file pointer is left
  2444.          pointing to the end-of-line character.  Note that this
  2445.          routine does not check for length, so you need to be sure
  2446.          to provide a large enough string for the file you are
  2447.          reading.
  2448.  
  2449. Boolean  Can't be done.
  2450.  
  2451.  
  2452. A series of variable references in a Read procedure acts exactly
  2453. like each of the references in individual Read procedures.  Thus:
  2454.  
  2455.                      Read(Input, Var1, Var2);
  2456.  
  2457. is equivalent to:
  2458.  
  2459.               Read(Input, Var1); Read(Input, Var2);
  2460.  
  2461. which is also equivalent to:
  2462.  
  2463.                      Read(Var1); Read(Var2);
  2464.  
  2465.  
  2466.  
  2467.          ReadLn(var FVar : Text; Variable References...)
  2468.  
  2469. Readln is exactly like Read, but after all the specified variables
  2470. have been read, this command eats characters until it finds the
  2471. next end-of-line, and it eats that too.  This command can only be
  2472. used on Text files.
  2473.  
  2474.  
  2475.  File Buffers
  2476. --------------
  2477.  
  2478. Like Standard Pascal, but unlike Turbo Pascal, PCQ allows you to
  2479. access the file buffer directly.  The syntax of the reference
  2480. looks like:
  2481.  
  2482.                    <File Variable Reference> ^
  2483.                           e.g. FileVar^
  2484.  
  2485. That expression has the same type as the elements of the file
  2486. itself (Text files have Char elements).  With input files, this
  2487. syntax looks at the next element that will be input by the Read()
  2488. procedure, like a look-ahead.  If EOF(FileVar) is True, then
  2489. FileVar^ is invalid.
  2490.  
  2491. For output files, the file buffer reference shows you the output
  2492. buffer.  This is not the value that will be written out with the
  2493. Write() procedure - see the description of Put() below for more
  2494. information.
  2495.  
  2496. Logically, the file buffer you access through this syntax is only
  2497. as long as one element, but the actual buffer in memory can be of
  2498. virtually any size.  See the file opening commands for information
  2499. on setting the buffer size.
  2500.  
  2501. Using this syntax in PCQ is actually considered an IO operation,
  2502. in the sense that it can set IOResult.  This only occurs when the
  2503. file is interactive, because the buffers of interactive files are
  2504. not kept full.
  2505.  
  2506. If you are making use of the file buffer, you will probably use on
  2507. or both of the following routines:
  2508.  
  2509.  
  2510.               Get(var FileVar : Text or Typed File)
  2511.  
  2512. Get just moves the file pointer from the current element to the
  2513. next one.  That may involve calling DOS to refill the buffer, but
  2514. normally it's just a matter of adjusting a field in the file
  2515. variable itself.  It is an error to call this routine on a file
  2516. for which EOF(FileVar) is True.
  2517.  
  2518. Every read from a typed file of the form "Read(FVar,Element)" can
  2519. be thought of as:
  2520.  
  2521.         Element := FVar^; { To assign the current value }
  2522.         Get(FVar);        { To advance the file pointer }
  2523.  
  2524.  
  2525.               Put(var FileVar : Text or Typed File)
  2526.  
  2527. Put moves the file pointer past the current element in an output
  2528. file, writing the buffer to disk if necessary.  Every statement of
  2529. the form "Write(FVar,Expr)", where FVar is a typed file, could be
  2530. implemented as:
  2531.  
  2532.         FVar^ := Expr; { Set the buffer value }
  2533.         Put(FVar);     { Commit the buffer    }
  2534.  
  2535. Note that until the Put procedure is called, any assignments to
  2536. the file buffer will write over each other.
  2537.  
  2538.  
  2539.  IO Checking
  2540. -------------
  2541.  
  2542. Input & Output can cause more unforeseen errors than virtually any
  2543. other area of programming.  PCQ Pascal catches IO errors in one of
  2544. two ways.  The first is called automatic IO checking - PCQ checks
  2545. for errors after each and every IO operation.  If there is an
  2546. error, the program aborts with a runtime error.  Believe it or
  2547. not, that's the default behavior.
  2548.  
  2549. If you turn off automatic checking using the {$I-} compiler
  2550. directive, you become responsible for checking for errors.  You do
  2551. this by calling the IOResult function, which returns 0 if
  2552. everything is O.K., or some other number if there was a problem.
  2553. When you call IOResult, you automatically clear its value, so if
  2554. you are going to use the error code later on you need to save it
  2555. in a variable.
  2556.  
  2557. IOResult is set by every IO routine.  No IO routines will function
  2558. if IOResult is not zero, so you should check for errors whenever
  2559. possible to avoid skipping reads and writes.
  2560.  
  2561. The values returned by IOResult are the same as the runtime
  2562. errors - possible values are listed in the section called Exit
  2563. Procedures.
  2564.  
  2565.  
  2566.  Standard IO
  2567. -------------
  2568.  
  2569. One of the tricky parts of programming on the Amiga is that a
  2570. program can be launched from two very different environments.  The
  2571. CLI invokes a program in much the same way as MS-DOS does - the
  2572. program has obvious input and output channels.  The Workbench, on
  2573. the other hand, offers nothing of the sort.  A program that needs
  2574. input and output channels must establish them explicitly.
  2575.  
  2576. All PCQ Programs establish some sort of standard input and output
  2577. channels, which are accessed through the Text files Input and
  2578. Output.  What those files represent depends, naturally, on the
  2579. environment from which the program was executed.
  2580.  
  2581. Let's take the simple case first.  If you run a program from the
  2582. CLI, Input and Output will refer to the CLI window itself.  Unless
  2583. you use indirection, that is, in which case Input and Output will
  2584. refer to the channels specified on the command line (see an
  2585. AmigaDOS manual for more information).  Maybe that wasn't so
  2586. simple after all.
  2587.  
  2588. If the program was launched from the Workbench, the startup code
  2589. goes through several steps to establish Input and Output.  First
  2590. of all, it looks at the value of the standard String typed
  2591. constant StdInName.  If StdInName is Nil, no file is opened and
  2592. referring to Input will cause grave problems.  If not, the startup
  2593. code attempts to open the file.  If it can't do it, it terminates
  2594. with run-time error 53.  If all went well, Input is established.
  2595.  
  2596. Next the startup code looks at StdOutName.  If it's Nil, Output is
  2597. not established, so any Write procedures had better use an
  2598. explicit file.  If StdOutName refers to the same string as
  2599. StdInName (not two strings with the same contents - it actually
  2600. has to point to the same memory), and if the file associated with
  2601. Input is interactive (i.e.  attached to a console window), then
  2602. Output is associated with the same file handle as Input.  The
  2603. default values of StdInName and StdOutName have this property.  If
  2604. either of those tests fail, the startup code tries to open a file
  2605. according to StdOutName, and if it works, then Output is set up
  2606. accordingly.  Otherwise, the program will terminate with runtime
  2607. error 57.
  2608.  
  2609. The default values for the two channels are defined in PCQ.lib as
  2610. follows:
  2611.  
  2612.         CONST
  2613.             StdInName  : String = "CON:0/0/640/200/";
  2614.             StdOutName : String = StdInName;
  2615.  
  2616. According to the rules specified above, this would normally result
  2617. in one full-screen console window being opened, with input coming
  2618. from it and output going to it.
  2619.  
  2620. Note that StdInName and StdOutName are defined as typed constants.
  2621. They can't be variables, because they are opened before any of
  2622. your code executes.  If that's a major problem, you can define
  2623. them both as Nil, and from inside your program you can open Input
  2624. and Output as anything you like.  You should probably re-use Input
  2625. and Output only when your program was run from the Workbench (you
  2626. can check if you were run from the Workbench by calling
  2627. GetStartupMsg from "Utils/Parameters.i").
  2628.  
  2629. If you compiled your program using the "-s" small initialization
  2630. code switch, all bets are off:  Input and Output are not
  2631. established, and in fact none of the other IO routines are
  2632. initialized either.  See the section called Small Initialization
  2633. Code for more information.
  2634.  
  2635.  
  2636.  
  2637.  
  2638.  
  2639. ===================================================================
  2640.  
  2641.                            Strings
  2642.  
  2643. ===================================================================
  2644.  
  2645. PCQ Pascal strings are similar to C strings, and nothing at all
  2646. like Turbo Pascal strings.  That's too bad, because Turbo Pascal
  2647. strings are a lot easier to work with.  Eventually, PCQ Pascal
  2648. strings will be the same as Turbo Pascal strings, but that day has
  2649. yet to come.
  2650.  
  2651. The string type can be thought of as simply "^Char".  Thus all
  2652. string variables take up exactly 4 bytes, and they store the
  2653. address of the actual text.  The text can be of any length, and
  2654. is terminated by the character Chr(0).  A statement like:
  2655.  
  2656.         StringVar := "A String"
  2657.  
  2658. ... actually stores the address of the constant string in the
  2659. string variable, rather than copying the string itself into some
  2660. existing space.
  2661.  
  2662. String constants in the Pascal text are delimited by double quote
  2663. characters, as opposed to the single quote characters of character
  2664. array constants.  Thus "A String" is considered a constant of type
  2665. String, whereas 'not a string' is considered a constant of type
  2666. "Array [0..11] of Char".
  2667.  
  2668. Strings are defined as simple pointers, so the reference
  2669. "StringVar^" is valid, and is of type Char.  It actually points to
  2670. the first byte within the string buffer.  But unlike normal
  2671. pointers, the individual characters in a string can also be
  2672. accessed through subscript notation.  For example, to get the
  2673. fourth character in a string, you could use "StringVar[3]".
  2674. Remember that "StringVar[0]" is the first element.
  2675.  
  2676.  
  2677.  Allocating String Space
  2678. -------------------------
  2679.  
  2680. Since the actual String variables only store an address, you need
  2681. to allocate some space for the actual text.  C allows you define
  2682. that space when you declare the string type, but PCQ Pascal
  2683. doesn't even offer that much.  In PCQ Pascal, you have to
  2684. explicitly allocate the memory from the system, or assign the
  2685. address of a buffer variable to the string.  There are several
  2686. functions, all defined in the include file StringLib.i, that
  2687. allocate space for strings.  They are:
  2688.  
  2689.                AllocString(Size : Integer) : String
  2690.  
  2691. AllocString simply returns an uninitialized memory area that is at
  2692. least Size bytes long.  This memory is considered PCQ memory, so
  2693. it is returned to the system after its use (see the section called
  2694. Memory Management for more information).
  2695.  
  2696.                 strdup(InString : String) : String
  2697.  
  2698. The strdup (string duplicate) function is equivalent to the
  2699. following:
  2700.                 temp := AllocString(strlen(InString));
  2701.                 strcpy(temp,InString);
  2702.                 strdup := temp;
  2703.  
  2704. In other words, it allocates just enough memory to hold the input
  2705. string, then makes a copy of the input string in the new buffer.
  2706. This memory is also considered PCQ memory, so it will be returned
  2707. to the system when the program terminates.
  2708.  
  2709. The other way to set up a string buffer is to assign the string
  2710. variable the address of an array declared elsewhere.  Thus the
  2711. following:
  2712.  
  2713.         Var
  2714.             String1 : String;
  2715.             Buffer1 : Array [0..127] of Char;
  2716.         begin
  2717.             String1 := Adr(Buffer1);
  2718.  
  2719. ... sets up a 128-character buffer for String1.  If you try to
  2720. store a 129-character string in that buffer, all sorts of problems
  2721. will result, so take care.
  2722.  
  2723.  
  2724.  Using Escape Characters
  2725. -------------------------
  2726.  
  2727. There are, of course, lots of useful characters that can't easily
  2728. be written into a program source file.  The end-of-line character,
  2729. for example, is always considered the end of a line, rather than
  2730. taken as a constant.  If you need to include this sort of
  2731. character in any text constant (a Char, Array of Char, or String),
  2732. you use the C escape convention, in which a backslash "\" is
  2733. followed by a special character.  The escape sequences supported
  2734. by PCQ are:
  2735.  
  2736.            \n   Line Feed, chr(10)
  2737.            \t   Tab, chr(9)
  2738.            \0   Null, chr(0)
  2739.            \b   Backspace, chr(8)
  2740.            \e   ESC, chr(27)
  2741.            \c   CSI (Control Sequence Introducer), chr($9B)
  2742.            \a   Attention, chr(7)
  2743.            \f   Form Feed, chr(12)
  2744.            \r   Carriage Return, chr(13)
  2745.            \v   Vertical Tab, chr(11)
  2746.  
  2747. Every other character passes through unchanged, so the following
  2748. definitions also hold:
  2749.  
  2750.            \\   Just a single backslash
  2751.            \'   A single quote, even in a single-quote-delimited
  2752.                 constant
  2753.            \"   A double quote, even in a String constant
  2754.  
  2755. Thus a string like "A\tboy\nand\\his \"dog." becomes:
  2756.  
  2757.         |A      boy
  2758.         |and\his "dog
  2759.  
  2760. ... where the vertical bar | represents the left margin.
  2761.  
  2762.  
  2763.  StringLib
  2764. -----------
  2765.  
  2766. StringLib.i is an include file in the Utils directory that defines
  2767. a bunch of C-style functions for use on strings.  Those functions
  2768. are explained in the include file itself.  The source for these
  2769. routines is in the runtime library source, which is available in
  2770. the registered version.
  2771.  
  2772.  
  2773.  
  2774.  
  2775. ===================================================================
  2776.  
  2777.                         Memory Management
  2778.  
  2779. ===================================================================
  2780.  
  2781. One of the problems with Amiga programming is that there is no
  2782. resource tracking.  In an MS-DOS program, you can open files and
  2783. allocate memory like crazy, then just quit the program and
  2784. everything's O.K.  On the Amiga, all those files would stay open
  2785. and the memory would stay allocated.  You are expected to clean up
  2786. after yourself.
  2787.  
  2788. To help you do that, PCQ Pascal uses a special memory allocation
  2789. scheme that uses the Intuition AllocRemember routine to keep track
  2790. of all your memory allocations.  When your program terminates, any
  2791. memory you haven't deallocated is automatically freed by an exit
  2792. procedure.
  2793.  
  2794. This only works for memory allocated through one of the special
  2795. PCQ routines New, AllocString (from Utils/StringLib.i) or GetMem
  2796. (from Utils/PCQMemory.i).  Memory allocated through one of these
  2797. routines is called PCQ memory, but of course it's no different
  2798. from normal system memory except that it will be returned.
  2799.  
  2800. Even though it will be automatically freed, you should deallocate
  2801. memory as soon as you are through with it.  There might be other
  2802. programs running that can use it.  If you do free PCQ memory, you
  2803. need to use Dispose, FreeString or FreePCQMem to do it.  If you
  2804. don't, the memory will be returned to the system, but the PCQ
  2805. memory routines won't know about it.  They will, therefore, try to
  2806. free it again when the program terminates.  Guru.
  2807.  
  2808. PCQ memory is always allocated with the flags MEMF_PUBLIC and
  2809. MEMF_CLEAR.  If you need chip memory, therefore, you should use
  2810. the normal Exec function AllocMem (from Exec/Memory.i).
  2811.  
  2812.  
  2813.  HeapError
  2814. -----------
  2815.  
  2816. So what happens when the PCQ memory routines are unable to
  2817. allocate some memory a user has called for?  That depends on the
  2818. value of HeapError, a standard Address variable.  HeapError
  2819. contains the address of a function that has a header with the
  2820. following form:
  2821.  
  2822.            Function HeapFunc(Size : Integer) : Integer;
  2823.  
  2824. The Size parameter is the amount of memory the allocator was
  2825. trying to get, and the integer returned determines how the
  2826. allocator will respond to the problem.  If it returns 0, the
  2827. allocator will abort the program with runtime error 54.  If it
  2828. returns 1, the allocator will return the value Nil, so you'll have
  2829. to check after each call to New, AllocString or GetMem for a Nil
  2830. value.  If the HeapError function returns 2, the allocator tries
  2831. the allocation again.  This gives you a chance to free up some
  2832. memory, if possible.  If that allocation fails, the HeapError
  2833. function will get called again.
  2834.  
  2835. To install a function as the HeapError function, you would use
  2836. something like the following:
  2837.  
  2838.                      HeapError := @HeapFunc;
  2839.  
  2840. ... where HeapFunc is defined as above.
  2841.  
  2842.  
  2843.  
  2844.  
  2845. ===================================================================
  2846.  
  2847.                          Exit Procedures
  2848.  
  2849. ===================================================================
  2850.  
  2851. Exit procedures are routines that you set up to run after the main
  2852. routine is finished, or if there is a run-time error.  They are
  2853. used to return resources to the system, or to exit gracefully or
  2854. even recover from run-time errors.
  2855.  
  2856. How it works is:  when a program terminates, for whatever reason,
  2857. PCQ examines the value of ExitProc, a standard Address variable.
  2858. If it is non-nil, PCQ sets ExitProc to Nil and calls the procedure
  2859. it pointed to.  When the procedure returns, PCQ checks ExitProc
  2860. again, and continues calling exit procedures until ExitProc is
  2861. Nil.  The normal PCQ initialization code sets up an exit procedure
  2862. that frees all memory allocated through New or AllocString, and
  2863. closes any Pascal files that remain open.  Normal programs,
  2864. therefore, have at least one exit procedure.
  2865.  
  2866. To make a procedure an exit procedure, first define a routine with
  2867. no parameters.  Then you set the ExitProc standard variable to the
  2868. address of your routine.  In most cases you'll want to save the
  2869. previous value of ExitProc so all the other exit procedures can
  2870. run as well.  Within the exit procedure itself, you should reset
  2871. ExitProc to point to the previous routine.
  2872.  
  2873. There are two additional variables associated with exit procedures
  2874. that are only valid while the procedure is actually running as an
  2875. exit procedure.  They always exist, but their value is only set
  2876. when the program terminates.  They are:
  2877.  
  2878. ExitCode     ExitCode contains the value of any runtime error that
  2879.              caused the program termination.  This is either a
  2880.              value you supplied through the Exit() routine, or a
  2881.              runtime error code.
  2882.  
  2883. ExitAddr     ExitAddr is the address where a runtime error
  2884.              occurred.  It is only valid when ExitCode is non-zero.
  2885.              It can (in theory) be used to recover from a runtime
  2886.              error, but you'd have to be awfully familiar with the
  2887.              actual runtime code to get it to work.  The runtime
  2888.              source code comes with the registered version of PCQ
  2889.              Pascal.
  2890.  
  2891.  
  2892.  Runtime Errors
  2893. ----------------
  2894.  
  2895. There are several errors that will cause a PCQ program to
  2896. immediately terminate.  When that happens, ExitCode will be set to
  2897. a specific value, which will eventually be returned to AmigaDOS.
  2898. AmigaDOS, in turn, will normally ignore it, so you'll never see
  2899. it.  The two ways I know of the see the return value (if it is
  2900. non-zero) are to run the program in a script, or to run the
  2901. program using AmigaDOS's Run command.  In either case, if the
  2902. program has a non-zero return code AmigaDOS will write out
  2903. "ProgramName failed returncode #".
  2904.  
  2905. The runtime errors generated by PCQ programs are as follows:
  2906.  
  2907.  
  2908.             Code       Description
  2909.           ----------------------------------------------
  2910.              50    No memory for IO buffer (1)
  2911.              51    Read past EOF (1)
  2912.              52    Input file not open (2)
  2913.              53    Could not open StdInName (3)
  2914.              54    New() failed (4)
  2915.              55    Integer divide by zero
  2916.              56    Output file not open (2)
  2917.              57    Could not open StdOutName (3)
  2918.              58    Found EOF before first digit while
  2919.                    reading an integer (1)
  2920.              59    No digits found in reading an integer (1)
  2921.              60    Range error (5)
  2922.  
  2923.         The following AmigaDOS error codes can result from a call
  2924.         to Open, ReOpen, Write, Read, etc:  (1)
  2925.  
  2926.             103    Insufficient free store
  2927.             202    Object in use
  2928.             203    Object already exists
  2929.             204    Directory not found
  2930.             205    Object not found
  2931.             206    Invalid window specification
  2932.             210    Invalid component name
  2933.             212    Object wrong type
  2934.             213    Disk not validated
  2935.             214    Disk write protected
  2936.             218    Device not mounted
  2937.             221    Disk full
  2938.             223    File is write protected
  2939.             224    File is read protected
  2940.             225    Not a DOS disk
  2941.             226    No disk in drive
  2942.  
  2943.         (1)  These errors only cause runtime errors when automatic
  2944.              IO error checking is enabled (it's the default).  If
  2945.              you have used the {$I-} directive to indicate that
  2946.              you'll check IOResult explicitly, the program will
  2947.              not automatically terminate.
  2948.         (2)  PCQ cannot always determine when the file is not
  2949.              open.  If it can, it issues this error.  If it can't,
  2950.              the machine will crash.
  2951.         (3)  These errors occur in the initialization code, before
  2952.              any exit procedures are established.
  2953.         (4)  See the section called Memory Management to see how
  2954.              keep a runtime error from being issued.
  2955.         (5)  This only occurs if you have turned range checking on
  2956.              with the {$R+} directive.
  2957.  
  2958.  
  2959.  
  2960.  
  2961.  
  2962. ===================================================================
  2963.  
  2964.                        Compiler Directives
  2965.  
  2966. ===================================================================
  2967.  
  2968. There are several options that PCQ Pascal provides that are not
  2969. useful for all programs.  For example, a large application should
  2970. not terminate with a runtime error if it can't open a file.
  2971. Therefore PCQ Pascal allows you to determine several aspects of
  2972. the program generated from your code.
  2973.  
  2974. You control these options by issuing compiler directives.
  2975. Compiler directives are contained in comments, and must begin with
  2976. a dollar sign "$" as the first character in the comment.
  2977. Immediately following the dollar sign is a letter indicating the
  2978. directive, which is then followed by zero or more characters
  2979. giving additional information.
  2980.  
  2981. You can include more than one directive in a single comment by
  2982. separating the directives by commas.  Thus the following
  2983. directives turn IO checking off, and range checking on:
  2984.  
  2985.                              {$I-,R+}
  2986.  
  2987. The following directives are supported:
  2988.  
  2989.              {$A Any number of assembly instructions}
  2990.  
  2991. The $A directive allows you to insert assembly language
  2992. instructions into the source code at the given point.  The text of
  2993. the instructions is passed through to the assembler unchanged, so
  2994. you should include comments and make variable references according
  2995. to assembly language style.
  2996.  
  2997. Since comments are allowed anywhere that white space is allowed,
  2998. you could technically insert some assembly language instructions
  2999. in the middle of an expression.  That could produce unpredictable
  3000. results, however, so you should use assembly language only between
  3001. statements.
  3002.  
  3003.                           {$B+} or {$B-}
  3004.  
  3005. The $B directive turns short-circuit evaluations on and off.  If
  3006. you use the $B+ directive to turn short-circuit evaluations on,
  3007. which is actually the default, PCQ will evaluate Boolean
  3008. expressions normally, but as soon as the final value of the
  3009. expression is known, it will skip any remaining parts of the
  3010. expression.  Thus in a series of "and" clauses, as soon as one of
  3011. them evaluates to False, the rest are not evaluated at all.  In a
  3012. series of "or" clauses, as soon as one of them evaluates to True,
  3013. the rest are skipped.  If you are using short-circuit evaluations
  3014. the expression will always be evaluated from left to right.
  3015. Short-circuits make Boolean evaluation somewhat faster, especially
  3016. in long equations.
  3017.  
  3018. If you turn short-circuit evaluations off using the $B- directive,
  3019. all parts of a Boolean expression will be evaluated even if the
  3020. outcome is not in doubt, and the expression will not necessarily
  3021. be evaluated in left-to-right order.
  3022.  
  3023.                            {$I "fname"}
  3024.  
  3025. This directive inserts the file "fname" into the input stream at
  3026. the current position in the file.  When the included file has been
  3027. fully read, the input is again taken from the original file.  You
  3028. can't use any other directives after this one, but you can include
  3029. any comments you like after the file name.
  3030.  
  3031. In order to keep from including a file more than once, the
  3032. compiler keeps a list of all file name already included.  If the
  3033. file name matches one already on the list, it is not included.
  3034. Note that only the actual file name, not the entire path, is
  3035. compared.  Thus you should be sure that all your include files
  3036. have unique names.
  3037.  
  3038. Almost all the example programs demonstrate the use of include
  3039. files.
  3040.  
  3041.                           {$I+} or {$I-}
  3042.  
  3043. The other form of the $I directive determines your programs
  3044. reaction to Input/Output errors.  The default behavior, which
  3045. corresponds to the {$I+} directive, is to issue a runtime error
  3046. whenever an error is detected in an IO routine.  The other option,
  3047. specified by the {$I-} directive, indicates that the program
  3048. itself will check the IOResult function after IO operations, and
  3049. handle any errors accordingly.  See the Input/Output section for
  3050. more information.
  3051.  
  3052.                  {$SN} or {$SX} or {$SP} or {$SD}
  3053.  
  3054. The $S option controls the storage of global variables and typed
  3055. constants.  The N option (for Normal storage) tells the compiler
  3056. that for all subsequent global variables, the compiler should
  3057. allocate memory in the data segment, and also issue an external
  3058. definition (XDEF in assembly language) for the identifier, so it
  3059. can be used by external routines.  This is the normal storage
  3060. scheme for PCQ programs.
  3061.  
  3062. The X option (for eXternal storage) tells the compiler that all
  3063. subsequent global variables are defined outside of the program.
  3064. Therefore the compiler should not allocate any space for the
  3065. variables, but simply create an external reference (XREF in
  3066. assembly language).  This is the normal storage scheme for
  3067. external files.
  3068.  
  3069. The P option (for Private storage) tells the compiler that it
  3070. should allocate space for global variables, but it should not
  3071. export the identifier itself.  This allows external files to have
  3072. global variables that do not affect the main program.
  3073.  
  3074. The D option (for Default storage) resets the storage to its
  3075. standard value.  In an external program, it acts like {$SX}, and
  3076. in a normal program it acts like {$SN}.
  3077.  
  3078.                           {$O+} or {$O-}
  3079.  
  3080. These options are identical to the {$I+} and {$I-} options.
  3081.  
  3082.                           {$R+} or {$R-}
  3083.  
  3084. The $R directive determines whether the compiler will verify that
  3085. index values are within the specified range of the array.  The
  3086. default behavior is {$R-}, which means that the compiler will not
  3087. generate the extra code.  Specifying {$R+} makes the compiler
  3088. issue a runtime error with error code 60.  Turning this option on
  3089. results in larger and slower programs, so I would recommend only
  3090. using the option while testing.
  3091.  
  3092.  
  3093.  
  3094.  
  3095.  
  3096. ===================================================================
  3097.  
  3098.                             Type Casts
  3099.  
  3100. ===================================================================
  3101.  
  3102. If you are using a strongly typed language like Pascal, you need a
  3103. way to get around the type rules.  PCQ Pascal uses the same method
  3104. as Turbo Pascal and Modula-2 to get around the type checks.  The
  3105. format for a type cast is as follows:
  3106.  
  3107.         <Type ID> ( <Expression or Variable Reference> )
  3108.  
  3109. This looks just like a function, but it is definitely not one.  A
  3110. type cast never generates any code - it just lets the code get by
  3111. the compiler.  Naturally, this can lead to some serious problems.
  3112. For example, a type cast like "Short(EnumeratedVar)" will cause
  3113. problems because enumerated types are normally one byte long.  You
  3114. have told the compiler to consider it a two byte value, but the
  3115. other byte is undefined.  The correct way to handle that call
  3116. would be to use the Ord() function, or at least cast it to a Byte
  3117. instead.
  3118.  
  3119. The difference between Short() and Ord() in this example is that
  3120. Ord() is a type transfer function, whereas Short() is not a
  3121. function at all.  As another example, consider the fragment below:
  3122.  
  3123.         Writeln(Integer(2.0));
  3124.         Writeln(Trunc(2.0));
  3125.  
  3126. Those two lines will not write the same values.  Trunc(), another
  3127. type transfer function, converts the real value 2.0 into the
  3128. integer value 2 before writing it.  The Integer "function" does
  3129. nothing at all, so the program just writes the real value as if it
  3130. were an integer, which is sure to produce some preposterous
  3131. number.
  3132.  
  3133. In general, casting an expression to a larger sized expression is
  3134. a bad idea, and casting a simple expression (an ordinal, real, or
  3135. pointer value) to a complex type (an array or record reference) or
  3136. vice versa will almost always produce nonsense results.
  3137.  
  3138.  
  3139.  
  3140. ===================================================================
  3141.  
  3142.                     Small Initialization Code
  3143.  
  3144. ===================================================================
  3145.  
  3146. You might, sometime, want to create a program that doesn't have
  3147. the overhead of normal PCQ Pascal programs.  For example, if you
  3148. never use Pascal files, there's no point having all the code for
  3149. Writeln() in your program.  If you want to cut the start-up and
  3150. shut-down code that PCQ adds to your program to a minimum, you can
  3151. use the "-s" option (for Small) on the command line.  For example,
  3152. to compile Tiny.p with the small startup code, you would use the
  3153. following line:
  3154.  
  3155.         Pascal Tiny.p Tiny.asm -s
  3156.  
  3157. The overhead you get rid of is not useless fat, however, and one
  3158. of the problems with not having it is that you can't use it.  Put
  3159. another way, if you use the "-s" option on the command line, you
  3160. will not be able to use any Pascal IO routines.  Specifically, the
  3161. procedures and functions that become off limits are:
  3162.  
  3163.     Write, WriteLn, Read, ReadLn, Get,
  3164.     Put, Open, ReOpen, Close, IOResult
  3165.  
  3166. The compiler will flag references to all these identifiers with
  3167. the exception of IOResult, but keep in mind that the compiler will
  3168. never see references in separately compiled files (external file)
  3169. or object code libraries.  The moral of this story is that you
  3170. should exercise extreme care when using this option, or you will
  3171. end up linking both startup routines and crashing the machine
  3172. anyway.
  3173.  
  3174. So what, exactly, is missing?  The normal startup code does the
  3175. following:
  3176.  
  3177.     1. Handles the CommandLine or Workbench message.
  3178.     2. Opens Intuition, DOS, and the MathFFP library.
  3179.     3. Sets up Input and Output, opening a window if
  3180.        necessary.
  3181.     4. Initializes the memory allocation list and the
  3182.        open file list so they can be freed at exit.
  3183.     5. Sets up an exit procedure that will free up the
  3184.        memory and files.
  3185.  
  3186. As you can see, there are several pretty big routines: Open(),
  3187. Close(), setting up Input and Output based on the way the program
  3188. was run and the contents of StdInName and StdOutName, the exit
  3189. procedure that frees everything, etc.  The small initialization
  3190. code does this:
  3191.  
  3192.     1. Handles the CommandLine or Workbench message.
  3193.     2. Opens Intuition, DOS and the MathFFP library.
  3194.     3. Intializes the memory list, and sets up a simple
  3195.        routine to free all the New() memory.
  3196.  
  3197. And that's it.  According to my preliminary results, this program:
  3198. "Program Test; begin end." compiles to about 2.5k normally, and
  3199. less than 700 bytes using the small initialization code.
  3200.  
  3201.  
  3202.  
  3203.  
  3204. ===================================================================
  3205.  
  3206.                           External Files
  3207.  
  3208. ===================================================================
  3209.  
  3210. In developing the compiler I found that writing the entire thing
  3211. in one source file was just too much - the intermediate assembly
  3212. files were huge, and the compile times were ridiculous.  In order
  3213. to split things up a bit I added a method for separate
  3214. compilation, similar in purpose to Turbo Pascal's units, but less
  3215. powerful.
  3216.  
  3217. External files have the following format:
  3218.  
  3219.            <External File> ::= External; <Definitions>
  3220.  
  3221. In other words, an external file starts with the reserved word
  3222. External, a semicolon, then any number of definition blocks.
  3223. These definition blocks, as defined above, can be functions,
  3224. procedures, variables, etc.
  3225.  
  3226. Whenever you define a procedure or function, PCQ Pascal "exports"
  3227. the identifier so it can be used by other files.  These other
  3228. files refer to the routine by including an external reference in
  3229. their code (see External References in the Procedures and
  3230. Functions section).  Thus if you define the procedure DoIt in your
  3231. external file, you would include the following declaration in any
  3232. other file in which you used the routine:
  3233.  
  3234.                         Procedure DoIt;
  3235.                             External;
  3236.  
  3237. That declaration tells the compiler that it should "import" the
  3238. identifier from some other file.
  3239.  
  3240. Defining variables and typed constants at the global level in an
  3241. external file is a bit more complicated.  Suppose, for example,
  3242. that you have a global variable in your main program, but you also
  3243. want to refer to it in your external file.  If you declare it
  3244. normally in the external file, you might expect that PCQ would
  3245. reserve two memory areas for the one variable, one in the main
  3246. program and one in the external file.
  3247.  
  3248. Because of that problem, variables and typed constants at the
  3249. global level (only) are by default assumed to be defined only in
  3250. normal program files.  Thus if you define a global variable in an
  3251. external file, PCQ will assume that the variable should be
  3252. imported from some other file, and will not allocate space.  This
  3253. assumption can be overridden by the $S directive, however.
  3254.  
  3255. If you have used an external file, you need to be sure its
  3256. routines are included in the final executable program.  To do
  3257. that, you have to include the file name in the linker command, as
  3258. follows:
  3259.  
  3260.     Blink Main.o Extern1.o ... to MainProgram Library PCQ.lib
  3261.  
  3262. In other words you include any external object files (the output
  3263. of the assembler) in the linker command after the main file, but
  3264. before the "to" keyword.  They can be in any order.
  3265.  
  3266. Although Pascal is a case-insensitive language, assembly is not.
  3267. Thus when you make external references you must be sure that the
  3268. very first reference in your code - either the variable
  3269. declaration or the actual header for the procedure or function -
  3270. has the same case as the definition in the external file.
  3271. Subsequent uses can have any case - the first one is used to
  3272. generate the reference.
  3273.  
  3274.  
  3275.  
  3276.  
  3277. ===================================================================
  3278.  
  3279.                  Notes to Assembly Programmers
  3280.  
  3281. ===================================================================
  3282.  
  3283. In previous versions of the compiler, the registers from d2 to d7,
  3284. a2 and a3 were all available at any time, and the scratch
  3285. registers were available between statements.  That is no longer
  3286. true, so some assembly routines might have to be rewritten.
  3287.  
  3288. Version 1.2 of PCQ now uses registers much more efficiently, which
  3289. means that all of the data registers can be put to use.  PCQ
  3290. allocates registers from d7 down to hold subexpression results, so
  3291. the availability of registers within expressions depends on the
  3292. Pascal code.  Between statements, all data registers are once
  3293. again available.
  3294.  
  3295. Address registers are used as before: a7 is the stack pointer, a6
  3296. is used to point to the library base, a5 points to the stack
  3297. frame, and a4 is used to point to previous frames.  The compiler
  3298. can use a3 and a2 during expressions to hold intermediate address
  3299. values.
  3300.  
  3301. The system routines consider d0,d1,a0 and a1 as scratch, but
  3302. preserve all other registers.
  3303.  
  3304.  
  3305.  
  3306.  
  3307.  
  3308. ===================================================================
  3309.  
  3310.                               Errors
  3311.  
  3312. ===================================================================
  3313.  
  3314. When the compiler runs across some sort of error in your program,
  3315. it prints out the current and previous lines, with the general
  3316. area of the error highlighted.  On the next line, it tells you the
  3317. line number and current procedure or function being defined, plus
  3318. some (hopefully) descriptive text.
  3319.  
  3320. The first error is normally fairly accurate.  After that, however,
  3321. the compiler might start coming up with a lot of spurious
  3322. complaints that are best ignored.  For this reason, PCQ Pascal
  3323. automatically aborts after four errors (I used to use five, but
  3324. apparently the first error was scrolling off of normal screens).
  3325.  
  3326. If you specified the "-q" Quiet command line option, the error
  3327. reports will have a much more regular form, which is:
  3328.  
  3329. "source file name" At ##,## : Error Text
  3330.  
  3331. The quotes, colon, and the word "At" are all literal.  The first
  3332. ## is the line, and the second is the column.  This format is
  3333. designed to make automated compilation routines easier to develop.
  3334.  
  3335.  
  3336.  
  3337.  
  3338.  
  3339. ===================================================================
  3340.  
  3341.                              Sources
  3342.  
  3343. ===================================================================
  3344.  
  3345. I wrote PCQ Pascal as a learning experience, and it case you're
  3346. wondering I sure learned a lot.  Where did I go for information?
  3347. First, let's look at information specifically about the Amiga.
  3348.  
  3349. Amiga 1.3 Native Developer's Update.  This is a package of four
  3350. disks distributed by Commodore (CATS, specifically).  It has the
  3351. complete C and assembly language include libraries, Amiga.lib,
  3352. ALink, and all sorts of other things.  Perhaps more importantly,
  3353. it also has the Amiga Autodocs, a set of documentation files that
  3354. explain each and every function available in the standard Amiga
  3355. libraries and devices.  It explains each one individually,
  3356. however, so you still need a more general source.  For $20 U.S.,
  3357. however, these disks are a bargain.  The 2.0 update should be out
  3358. eventually, but as I write this it's still unavailable, so you
  3359. should send $20 and ask for the 1.3 update from:
  3360.  
  3361.         C.A.T.S
  3362.         1200 Wilson Drive
  3363.         West Chester, PA 19380
  3364.  
  3365.  
  3366. Amiga ROM Kernel Manuals.  This is the official set of books for
  3367. Amiga programming, and if you don't have them you are handicapped.
  3368. The last version I have is from AmigaOS version 1.1 so I'm not
  3369. sure how they are organized these days, but you should definitely
  3370. get the one that explains Intuition, and if you can still afford
  3371. it, the one that explains Libraries and Devices.  They are big and
  3372. very expensive, but it's hard to get by without them.  Some folks,
  3373. by the way, will also tell you that they are mistake-ridden and
  3374. difficult to understand, but I found them to be very accurate and
  3375. clear.  I think some programmers like to blame their lack of
  3376. understanding on others....
  3377.  
  3378. Anders Bjerin's C manual.  I've never looked at this, so I have no
  3379. idea of what it covers.  It covers lots of Intuition and Graphics
  3380. topics, and the C slant shouldn't be too much of a problem.  It's
  3381. available on Fred Fish disks 456 & 457, and unpacks to four full
  3382. disks of documentation.
  3383.  
  3384.  
  3385. As far as information about compilers in particular, I referred to
  3386. the following sources:
  3387.  
  3388. PDC, a freely distributable C compiler supported by Jeff Lydiatt.
  3389. This is a very good program, although it has been eclipsed
  3390. recently by DICE, GCC, and other really good C compilers.  I
  3391. learned, and used, a lot about activation frames from PDC's
  3392. output, although PDC's source code remains a mystery.
  3393.  
  3394. Pascal-S source code.  This is a small demonstration of a Pascal
  3395. p-code compiler produced years ago at Wirth's place, ETH Zurich.
  3396. It can answer some questions, but isn't a really good example of
  3397. programming style.
  3398.  
  3399. Small-C source code.  Small-C is another freely distributable C
  3400. compiler, originally described in Dr. Dobb's Journal years ago.
  3401. It is not very powerful, but the simplicity of the source code
  3402. makes it a very practical reference.  It is one of the compilers
  3403. used to bootstrap PCQ.
  3404.  
  3405. Brinch Hansen on Pascal Compilers, by Per Brinch Hansen.  This
  3406. book was of some use, which is more than I can say about the other
  3407. half dozen I read while writing this.  From this book I mainly
  3408. learned about all the things I was doing wrong.  Great.
  3409.  
  3410. The Toy Compiler series in Amiga Transactor, written by Chris
  3411. Gray.  This series is very informative, and is written by the
  3412. author of Draco.  Gray also writes compilers for a living, so he
  3413. actually knows what he's talking about.  Unfortunately this series
  3414. is hard to find, because the Transactor is out of business.  Ask
  3415. around, though - it's worth it.
  3416.  
  3417. Compilers: Principles, Techniques and Tools, by Aho, Sethi and
  3418. Ullman.  This is the big book, the so-called Dragon book, the last
  3419. word on compiler writing.  If you want to know about it, it's in
  3420. there, but you had better have a pretty decent math background.
  3421. Although it was a textbook for a class I took, I have never read
  3422. more than a few pages of it.
  3423.  
  3424.  
  3425.  
  3426. ===================================================================
  3427.  
  3428.                     Improvements On The Burner
  3429.  
  3430. ===================================================================
  3431.  
  3432. I've been using 1.2 for several months before I issued it, so I'm
  3433. relatively confident of its quality.  Nonetheless, it's such a
  3434. major change that I expect there will be problems.  Therefore my
  3435. first priority, as always, will be bug fixes.
  3436.  
  3437. Next comes optional C calling conventions, integrated peephole
  3438. optimizing, and possibly IEEE single precision reals.  That's all
  3439. easy enough.
  3440.  
  3441. Version 1.3 will be a compatibility release.  It will include
  3442. Turbo-style strings, function return values, double precision
  3443. reals, and Turbo types: Word, LongInt, ShortInt, etc.  Address
  3444. will become Pointer, Integer will become LongInt, Short will
  3445. become Integer, Exit will become Halt, etc.  I may even implement
  3446. Unit syntax.
  3447.  
  3448. The other area I'd like to explore is debuggers, preferably source
  3449. level.  I've been looking for the source code to one of those
  3450. monitor programs, but have yet to find it.
  3451.  
  3452.  
  3453. ===================================================================
  3454.  
  3455.                           Update History
  3456.  
  3457. ===================================================================
  3458.  
  3459. Version 1.2b (March 15, 1992)
  3460.  
  3461.   o   Fixed Write() and Read() of real values, which had
  3462.       somehow broken yet again.
  3463.  
  3464. Version 1.2b (February 15, 1992)
  3465.  
  3466.   o   Fixed the DateTools.i routines
  3467.   o   Fixed a problem with range types with a lower bound in
  3468.       1..255.
  3469.   o   Comparisons of structured types didn't used to work.
  3470.       They do now.
  3471.   o   Fixed a problem with the iff.library GetColorTable glue code.
  3472.  
  3473. Version 1.2b (September 8, 1991)
  3474.  
  3475.   o   Fixed another problem with array indexing, this time with
  3476.       multi-dimensional arrays.
  3477.   o   Fixed a mistake in the Exec/ExecBase.i file.
  3478.  
  3479. Version 1.2b (August 13, 1991)
  3480.  
  3481.   o   Fixed a problem with array indexing.
  3482.   o   Compiler now accepts empty REPEAT/UNTIL loops again.
  3483.   o   Removed unmatched { in Intuition/IntuitionBase.i
  3484.   o   Modified Ord() to automatically promote single byte
  3485.       values to the Short type.
  3486.  
  3487. Version 1.2b (June 22, 1991)
  3488.  
  3489.   o   The compiler would ignore function or procedure parameters
  3490.       following negative constants.
  3491.   o   The compiler now ensures that each element of an array is
  3492.       word-aligned, if the element is larger than one byte.
  3493.   o   Fixed the looping problem with REPEAT/UNTIL.
  3494.   o   The $A didn't work between the routine header and the code
  3495.       area.
  3496.  
  3497. Version 1.2a (June 8, 1991)
  3498.  
  3499. Fixed several bugs:
  3500.   o   The XOR operator would produce illegal assembly commands.
  3501.   o   Some floating point comparisons would produce incorrect
  3502.       results.
  3503.   o   The $A assembly directive now works anywhere in the code,
  3504.       not just in procedures and functions.
  3505.   o   The compiler used to accept unknown identifiers in typed
  3506.       constants (as operands of the @ operator).
  3507.   o   The INC and DEC statements were not handling Inc(var1,var2)
  3508.       forms correctly.
  3509.  
  3510. Version 1.2 (April 18, 1991)
  3511.  
  3512.     Fixed strlen and CreateTask() to work with 32-bit memory.
  3513.     Re-wrote the expression parsing and code generating routines
  3514. completely.  The routines now use registers much more effectively,
  3515. and provide a good base for the separate peephole optimizer.
  3516.     Added a few Turbo Pascal features:  you can now use typecasts
  3517. anywhere, even in address calculations.  Thus you can now write
  3518. something like RecordType(Pointer^).Field, which in version 1.1
  3519. was illegal.
  3520.     Changed the FOR statement significantly in order to make it
  3521. more efficient, and more like Turbo.  It boils down to two
  3522. differences:  FOR loops no longer run a minimum of once (e.g for i
  3523. := 1 to 0 do ...  will execute zero times), and the BY clause is
  3524. gone.
  3525.     Added short circuit evaluations, automatic floating point
  3526. conversions, Heap functions, Reset and Rewrite.
  3527.     You can now use any standard functions or operators in
  3528. constant expressions.
  3529.     Changed the Read routines to comply with Standard Pascal and
  3530. Turbo, in that any white space is skipped before reading integers
  3531. and reals.  It used to stop at EOLNs.
  3532.  
  3533.  
  3534. Version 1.1d, May 6, 1990:
  3535.  
  3536.     I've begun accumulating small changes under a new version
  3537. number purely for aesthetics.  The first difference is that the
  3538. compiler now creates a SECTION for data only if it has to.  That
  3539. sounds like an efficiency issue, but actually it wasn't creating a
  3540. SECTION at all if it was compiling an External unit.
  3541.     When StdOut is a file, the compiler no longer writes the line
  3542. numbers and all that stuff.  I have also made what I hope is the
  3543. last fix to the real number reading routines.
  3544.     The routines that compares include file names to the list of
  3545. previously included files is now case-insensitive.  I can't
  3546. imagine why it wasn't before.
  3547.  
  3548. Version 1.1c, April 6, 1990:
  3549.  
  3550.     I should have guessed that the problem recognizing the sign of
  3551. small real numbers on output would have a symmetric problem for
  3552. input.  It did, and now it doesn't.  I also fixed the problem with
  3553. signs on real constants.  I also added the exp() and ln()
  3554. functions recently sent to me by Martin Combs.  To avoid inflation
  3555. of version numbers, I've changed the date but kept the same
  3556. version.
  3557.     I've been thinking about adding peephole optimization to the
  3558. process, and rather than doing it the right way I've been playing
  3559. with a separate program.  To make that easier, I've removed short
  3560. branches from the code generated.  A68k adds them where necessary
  3561. anyway.
  3562.  
  3563. Version 1.1c, March 3, 1990:
  3564.  
  3565.     The only changes to the compiler are the new standard
  3566. functions.  The more significant changes were in the runtime
  3567. library.  First, I replaced the sin() and cos() functions based on
  3568. suggestions by Martin Combs - the result is that the results are
  3569. accurate to about 3 digits, and only slightly slower.  Martin was
  3570. kind enough to send along a very useful set of routines, which
  3571. also included the tan() and arctan() functions.  I also fixed the
  3572. routine that writes real numbers, so values between -1.0 and 0.0
  3573. now include the minus sign.
  3574.  
  3575. Version 1.1b, February 6, 1990:
  3576.  
  3577.     This program is over a year old.
  3578.     Added the Sqr() function.  Sqr(n) is the same as n * n, but
  3579. marginally faster and smaller.  Also, the compiler used to
  3580. generate lots of errors when an include file was missing.  Now it
  3581. skips the rest of the comment, like it should.
  3582.     Apparently floating point constants didn't used to work.  Why
  3583. am I always the last to know?  I also added the Sin() and Cos()
  3584. functions, based on an aside during a lecture on an entirely
  3585. different topic.
  3586.     Later I added the sqrt() function, using Newton's method.
  3587.  
  3588. Version 1.1a, January 20, 1990:
  3589.  
  3590.     Fixed a bug in the WriteArb routine that manifested itself
  3591. whenever you wrote to a 'File of Something'.
  3592.     Fixed a bug left in the floating point math library.  It seems
  3593. that it had not been updated for the all the 1.1 changes, so
  3594. during linking it required objects that aren't around anymore.
  3595. Since floating point math is now handled by the compiler, I hadn't
  3596. noticed it before.
  3597.  
  3598. Version 1.1, December 1, 1989:
  3599.  
  3600.     This version is completely re-written, and has far too many
  3601. changes to list them individually here.  The main changes are the
  3602. with statement, the new IO system, a completely redesigned symbol
  3603. table, nested procedures, and several new arithmetic operators.
  3604. In order to help port programs from Turbo Pascal and C, I added
  3605. typed constants, the Goto statement, and the normal syntax for
  3606. multi- dimensional arrays.
  3607.  
  3608. Version 1.0c, May 21, 1989:
  3609.  
  3610.     I changed the input routines around a bit, using DOS files
  3611. rather than PCQ files.  I buffered the input, and made the
  3612. structure more flexible so I could nest includes.  Rather than
  3613. make up some IfNDef directive, I decided to keep track of the file
  3614. names included and skip the ones already done.  Buffering the
  3615. input cut compile times in half.  I would not have guessed
  3616. buffering would be that significant, and I suppose I should
  3617. rethink PCQ input/output in light of this.
  3618.     I added code to check for the CTRL-C, so you can break out
  3619. early but cleanly.  The Ports.i include file had a couple of
  3620. errors, which I fixed, and I also fixed the routine that opens a
  3621. console for programs that need one.  It used to have problems when
  3622. there were several arguments in the first write().
  3623.     I added the SizeOf() function, floating point math, and the
  3624. standard functions related to floating point math.
  3625.     There were several minor problems in the include files which I
  3626. found when I got the 1.3 includes, the first official set I've had
  3627. since 1.0.
  3628.     I relaxed the AND, OR and NOT syntax to allow any ordinal
  3629. type.  This allows you to get bitwise operations on integers and
  3630. whatever.  I also added a standard function called Bit(),
  3631. described above.  These are all temporary until I can get sets
  3632. into the language.
  3633.     I finally added string indexing.  In doing so I found a bug in
  3634. the addressing routine selector(), so I rewrote it to be more
  3635. sensible.  I think it also produces larger code, but I'm not too
  3636. worried because I'm going to add expression trees soon anyway.
  3637.  
  3638. Version 1.0b, April 17, 1989:
  3639.  
  3640.     I fixed a bug in the way complex structures were compared.  It
  3641. seems that one too many bytes were considered, so quite often the
  3642. comparison would fail.
  3643.  
  3644. Version 1.0a, April 8, 1989:
  3645.  
  3646.     This version added 32 bit math, and fixed the case statement.
  3647. The math part was just a matter of getting the proper assembly
  3648. source, but I changed the case statement completely.  Version 1.0
  3649. of the compiler produced a table that was searched sequentially
  3650. for the appropriate value, which if found was matched up with an
  3651. address.  I thought all compilers did this, but when debugging a
  3652. Turbo Pascal program at work I found that it just did a bunch of
  3653. comparisons before each statement, as if it were doing a series of
  3654. optimized if statements.  I had thought of this and rejected it as
  3655. being too simplistic, but if it's good enough for Turbo it's good
  3656. enough for me.
  3657.     The next thing I changed in this release was the startup code.
  3658. You can now run PCQ Pascal programs from the Workbench.  This was
  3659. just a matter of taking care of the Workbench message, but I also
  3660. fooled around with standard input and output.  If you try to read
  3661. or write to standard in or out from a program launched from the
  3662. Workbench, the run time code will open a window for you.
  3663.     I also fixed one bug that I found:  an array index that was
  3664. not a numeric type had its type confused.  Nevermore.
  3665.  
  3666. Version 1.0, February 1, 1989
  3667.  
  3668.     Original release.
  3669.  
  3670.  
  3671.  
  3672. ===================================================================
  3673.  
  3674.                Other Notes, Copyright & My Address
  3675.  
  3676. ===================================================================
  3677.  
  3678. This documentation, the source code for the compiler, the compiler
  3679. itself, the source code for the run time library, and the run time
  3680. library itself, are all (ahem):
  3681.  
  3682.                 Copyright (c) 1989 Patrick Quaid.
  3683.  
  3684. I will allow this version of the package to be freely distributed,
  3685. as long as all the files in the archive, with the possible
  3686. exception of the assembler and linker (please include them if at
  3687. all possible), are included and unchanged.  Of course no one can
  3688. make any real money for distributing this program.  It may only be
  3689. distributed on disk collections where a reasonable fee is charged
  3690. for the disk itself.  A reasonable fee is defined here as the
  3691. greater of $10 per disk, or whatever Fred Fish is currently
  3692. charging (about six dollars as I write this).
  3693.  
  3694. Version 1.2b of PCQ Pascal is "freeware", which means that it can
  3695. be freely distributed, and no fee is required.  Future versions,
  3696. including the current 1.2c, are now sent only to registered users,
  3697. and may not be distributed.  The registration fee for PCQ Pascal
  3698. is $25 US, for which you get the following:
  3699.  
  3700.    o  The latest version of the compiler, which now supports
  3701.       variant records, (* and *) delimited comments, CHIP and
  3702.       FAST keywords for global variables and typed constants,
  3703.       standard Pascal pointer declarations, an execution
  3704.       profiler, support for mathtrans.library, and much more.
  3705.    o  PCQ, an extrememly flexible and customizable make utility
  3706.       that lets you compile, assemble and link single programs
  3707.       and complex projects with a single command.
  3708.    o  PCQ.lib.DOC, which describes every routine internal to
  3709.       PCQ Pascal or defined in Include:Utils.  Well over 100
  3710.       routines are covered in a format similar to the AutoDocs,
  3711.       and compatible with DME's REF feature.
  3712.    o  Include files and a runtime library compatible with
  3713.       AmigaDOS 2.0, when they become available.
  3714.  
  3715. For an additional $15 (which just covers printing costs,
  3716. incidentally), I'll send you a printed, bound User's Guide, based
  3717. on Pascal.DOC, and Reference Guide, based on PCQ.lib.DOC.  They
  3718. are completely reformatted, and even have full indexes.
  3719.  
  3720. You can still get the latest version of the freeware compiler from
  3721. me by sending a disk, mailer and postage.  It will only be updated
  3722. to fix bugs, however, so new versions will not come out very
  3723. frequently.
  3724.  
  3725. Any questions, comments, or whatever can be addressed to:
  3726.  
  3727.       Pat Quaid
  3728.       2250 Clarendon Blvd, Apt #1209
  3729.       Arlington, VA 22201
  3730.       USA
  3731.  
  3732.       Telephone: (703) 524-8945
  3733.  
  3734. You are much more likely to be able to contact me by mail than by
  3735. phone, but I certainly don't mind if you try.  Enjoy the compiler.
  3736.