{ ----------------------------------------------------------------------------- NOTICE: THESE MATERIALS are UNSUPPORTED by OSS! If you do not understand how to use them do not contact OSS for help! We will not teach you how to program in Pascal. If you find an error in these materials, feel free to SEND US A LETTER explaining the error, and how to fix it. THE BOTTOM LINE: Use it, enjoy it, but you are on your own when using these materials! DISCLAIMER: OSS makes no representations or warranties with respect to the contents hereof and specifically disclaim all warranties of merchantability or fitness for any particular purpose. This document is subject to change without notice. OSS provides these materials for use with Personal Pascal. Use them in any way you wish. -------------------------------------------------------------------------- } PERFORMING MODULAR COMPILATION WITH PERSONAL PASCAL --------------------------------------------------- One of the failings of standard Pascal is its lack of the ability to break a large program into smaller units which can be compiled separately. Personal Pascal solves this deficiency by providing a rudimentary, yet powerful method of performing "modular compilation." In this file, we will provide a simple example of using modules, as well as some guidelines and hints. First, the example: Consider the following simple program: 1 PROGRAM simple; 2 VAR i: integer; 3 BEGIN 4 FOR i := 1 TO 10 DO writeln( i ); 5 END. Just for the purposes of this example, lets say we want to call a routine "print_message" instead of "writeln" in line 4. We also want to put that routine into a different file so we can compile them separately. We need to create two files, one of which will be our "module." First, here is the "main file", which we will assume is called EXAMPLE.PAS: PROGRAM main_file; VAR i: integer; { The next declaration tells the Pascal compiler that the "print_message" routine will be inserted at link time. That is, the EXTERNAL declaration just tells Pascal what the routine looks like, but does not produce any code just yet. } PROCEDURE print_message( n: integer ); EXTERNAL; { Then the main routine is just like before: } BEGIN FOR i := 1 TO 10 DO print_message( i ); { But we call print_message instead of writeln } END. Before we go on to the module, lets look at a few things. 1. The modular compilation flag (M+) didn't appear anywhere in this file! Why? You use the M+ flag in each "module" file EXCEPT the one holding your main routine. Otherwise, you'll get link errors. 2. We declared print_message just as we would have if we were going to code it in this file, but instead of the body of the procedure, we just have the directive EXTERNAL. Now we want to compile this main file to produce a file EXAMPLE.O, the "object" file. But first, we must turn OFF the "Chain to linker" flag in the compiler options dialog box. Also set the compiler to compile for TOS, since we're just using "writeln" to print to the screen. Assuming that EXAMPLE compiled successfully, lets move on to the "module" file, which we'll call MODULE.PAS: {$M+,E+} { This is a module, and we want its procedures to be visible } PROGRAM module; PROCEDURE print_message( n: integer ); BEGIN writeln( 'In the module with parameter ', n ); END; BEGIN END. { This main routine MUST be empty! } If you type this in and compile it (again with "Chain to linker" OFF!), you will get a file MODULE.O. Now we want to link both EXAMPLE.O and MODULE.O together with the Pascal libraries to produce a final program file. Put the name "module.o" in the "Additional link files" fields of the linker options dialog box. Then choose "Link file..." from the File menu, and select the file EXAMPLE.O. The linker will first go to "example.o", then "module.o", then the libraries, in order to produce a final object file EXAMPLE.TOS, which you can run to see the results of our simple example. A NOTE ON GLOBAL VARIABLES -------------------------- In our sample module, we did not declare any global variables. If we wanted to access the global variables that were declared in the main program (just the integer i, in this case), we would have had to declare ALL the global variables THE SAME WAY AND IN THE SAME ORDER AS THE MAIN PROGRAM. In order to make this simpler, put all your global declarations into a file, then use the include directive to insert these into all your files (the main routine, too). COMMENTARY ---------- As you can tell, our example did not demonstrate any advantage of using modular compilation. In fact, we went to more work that we would have by having just one source file! In general, if your program if fairly small, you will not benefit from breaking your program up. On the other hand, if your program is quite large, you can save a lot of compile time by splitting it up into several parts. If possible, you should form the modules so that routines with similar functions are in the same module. The Personal Pascal compiler was generated in this way. It is formed of six modules, which together total to over 130K of program. When you use modular compilation, keep the following points in mind: -- be sure to turn OFF "Chain to linker" -- Use the M+,E+ directives ONLY in modules, NOT in your main program -- The main program segment in a module MUST be emtpy: BEGIN END. -- If you want to access any global variables from modules, all global VAR declarations must also be in the module. We suggest putting your global CONST, TYPE, and VAR declarations into a separate files, and just include it in all modules AND in your main program.