Computing: Free Pascal Programming

Installing Free Pascal on OS/2.


There is an OS/2 download page at the Free Pascal website; however, the link to the ZIP archive is dead. An older version of fpc (version 3.0.4) can be found at the Free Pascal page of OS/2 Site - OS/2 software and information (I successfully installed it on OS/2 Warp 3 Connect, Red Spine); on this page, you also find the fpc documentation (as PDF documents). Finally, the best place to find the latest fpc binaries for OS/2 is the OS/2 download page at Sourceforge. The latest version (July 2023) is Free Pascal 3.2.2. I successfully installed it on OS/2 Warp 3 Connect, Blue Spine. That's what this tutorial is about. I suppose that the installation on OS/2 1 and 2 would fail, as I suppose that it will probably succeed on OS/2 Warp 4.
You can download the full version of Free Pascal 3.2.2 form Sourceforge; the download is a ZIP archive called os2322full.zip.
The simplest way to transfer the files to your OS/2 virtual machine (or, maybe, your "physical" OS/2 machine) is to extract them on the host machine and burn them onto a CDROM (resp. create an ISO). On your OS/2 machine, browse to the extracted files in File Manager and launch setup by double-clicking the program install.exe.
The installation is wizard-based and should succeed without any issues. In the General tab of the Free Pascal Installer window (screenshot on the left), you can choose the installation directory (default: C:\pp) and if or if not you want to create fpc.cfg. You can have a look at the content of the other tabs and adapt the installation if you want so. Normally, you should let all as is. In fact, all components (except for those not included, as, for example, the documentation in PDF, HTML, CHM and TXT format, or the Pascal to Javascript converter) will be installed by default. The screenshot on the right shows the components listed on the OS/2 tab.
Installing Free Pascal on OS/2: Choosing the installation directory
Installing Free Pascal on OS/2: Selecting components to be installed
To start installation, push the Continue button on the General tab. The installation files are extracted and copied to the install directory on your harddisk. When done, the Installation successful window is displayed. You are told, what modifications you'll have to make to the config.sys file and how to do to compile a program.
Installing Free Pascal on OS/2: Successful installation
To modify the environment variables, open CONFIG:SYS with the OS/2 system editor. Add "C:\pp\bin\os2" to the PATH variable and add "C:\pp\dll" to the LIBPATH variable (without the quotes and separating the new value from the preceding one by a semicolon). When you choose to save the file, a dialog box pops up telling you that there is no file type associated with this file. Push the Save as... button to save the file.
Installing Free Pascal on OS/2: Saving config.sys after modifying PATH and LIBPATH [1]
Note: As you can see on the screenshot, I also set BREAK=ON. This did however not work as I expected: even with this setting, it is not possible to terminate a Free Pascal executable using CTRL+C.
After pushing Save As, the Save As dialog box is displayed. Be sure that the filename is well config.sys and that the directory where to save the file is well C:\. Push the Save button to save the file with the new settings (screenshot). As config.sys already exists, you'll have to confirm to overwrite it. And in order to reload config.sys with the new settings, you'll have to reboot your computer.
Installing Free Pascal on OS/2: Saving config.sys after modifying PATH and LIBPATH [2]
Running fpc in the command line.
The Free Pascal for OS/2 installation includes several example programs and we will now try to build a command line program and a GUI application using the fpc compiler. I created a directory \Programming\fpc (on the screenshots, the D: drive is shown; that is because they have been taken on my OS/2 Warp 3 Red Spine system) and copied the files hello.pp and basicpm.pas from \pp\demo\text resp. \pp\demo\os2 to there. Note, that the demo sources use .pp as extension for command line programs, .pas for GUI application, what, of course, is not mandatory.
The screenshots below show the build of hello.pp and the files hello.o and hello.exe created (on the left) and the execution of the resulting binaries (on the right).
Building a Free Pascal program on OS/2 (command line): Build and files created
Building a Free Pascal program on OS/2 (command line): Program execution
Now, let's try to build the (very simple) GUI application basicpm.pas. The screenshot shows the output of the compiler and linker.
Building a Free Pascal GUI application in the OS/2 command line
The application sample is really rudimentary: Not more and not less than the display of a dialog box, that you can close by pushing the "OK" button.
Execution of a very simple Free Pascal GUI application on OS/2
Using the Free Pascal IDE.
The IDE for Free Pascal is called fp.exe; it is very similar to the one shipped with Turbo Pascal. You should start it from command line with the actual directory being the one with your Free Pascal source files. This will create a new fpc.cfg file in this directory and you can be sure to have the settings defined in this file when you build a program or application using the IDE. The screenshot shows the first start of fp, with the possibility to create a new configuration file (screenshot). When you choose to do so, you are asked if you want to copy the actual settings, or create a new file from scratch. Push the Copy existing button to do so.
Free Pascal on OS/2: First execution of the 'fp' IDE
Starting the IDE from the directory with your source files has the benefit that the Open command in the File menu directly shows this folder's content. Use the TAB key to navigate to the Files list, where using the up and down arrow keys, you can select the file that you want to open; hit ENTER to open the file in fp (you can use the mouse instead of the keyboard, if you prefer).
Free Pascal on OS/2: Opening a source file in the 'fp' IDE
The screenshot below shows the successful build of the sample GUI application basicpm.pas in fp.
Free Pascal on OS/2: Successful build of a GUI application in the 'fp' IDE
If you have a look at the files created, you'll notice that the executable is rather huge; 351,319 bytes in my case. A first thing that we can to to reduce the file size is changing the build mode from "debug" to "release". This is done using the menu command Options > Mode > Release (screenshot on the left). This reduced the size of my basicpm.exe to 349,899 bytes. A really significant size reduction is obtained by removing all debug information. Choose Options > Debugger from the menu and then check the Strip all debug symbols from the executable (screenshot on the right). In my case, this resulted in a file size of 184,324 bytes, that's over 50% smaller than during the first build.
Free Pascal on OS/2: 'fp' IDE - Changing the build mode to 'release'
Free Pascal on OS/2: 'fp' IDE - Choosing to strip all debug symbols from the executable
OS/2 Crt unit problems.
After having done some changes to my "equlin" command line program (as on DOS, fpc for OS/2 does not support the <operator>= operators), I tried to built this program (that uses the Crt unit for screen and end-of-line clearing, colored output and output at a given screen position). The build failed with the error message Fatal: Can't find unit Crt used by ....
The reason is simple: The Crt unit is not located in one of the directories that are by default searched for units, and thus we'll have to indicate a supplementary search path for units when wanting to build a program that uses Crt. To do this in fp, choose Options > Directories from the menu and in the Units tab enter the following path:
    C:\pp\units\os2\rtl-console
Free Pascal on OS/2: 'fp' IDE - Adding the location of Crt to the units search paths
Note: The directory <fpc-installation-directory>\units\os2\rtl-console contains the units Crt, Keyboard, Mouse and Video.
Now my "equlin" program built successfully, but when running the executable, it did not exit a repeat loop that reads a variable from the keyboard until the value of this variable is '1', '2' or '3'. The screenshot below shows the execution of equlin.exe, where keyboard input is asked for again and again, independently of what value you enter.
Free Pascal on OS/2: Infinetly looping program due to Readln problem (Crt unit)
It didn't take me long to figure out that the problem was due to the fact that reading keyboard input using Readln always results in getting an empty variable, where "always" means independently of what value you enter. Testing the Readln function without using the Crt unit, on the other hand works fine. Conclusion: the problem is due to a bug of the Readln function, that returns an empty input if the Crt unit is used.
I suppose that people running Free Pascal on OS/2 are rare, and among those who do so, only a small number works with command line programs that use the Crt unit. I say this, because I didn't find a single site on the Internet, where the Crt unit problem was discussed. I could (or even should) have made a post in the Free Pascal forum. But first, I think to remember that when I tried to create an account at this forum for some other question, the account creation failed. And second, my experiences with forums are, except for some really great ones, rather bad. So, I decided to solve the problem myself, replacing the Readln function by custom input procedures based on the ReadKey function.
Use the following link to download my ReadCon unit. It contains the 3 following procedures to read from console (= to read keyboard input):
  • ReadString: Read a string variable from console.
  • ReadReal: Read a Real variable from console.
  • ReadInteger: Read an Integer variable from console.
The disadvantage of these procedures in comparison with Readln is that only one single variable can be read. A disadvantage that, in my eyes, is not significant, as reading several variables with one Readln statement is rare (I myself always read my variables one by one). The advantages are (beside that they work correctly on OS/2) that entering non-numeric characters when reading a number, or entering a decimal value when reading an Integer, will not make the program abort (as with Readln), but instead returns an error message. Also, entering nothing at all (just hitting ENTER), when a number is read, is permitted. This will set a return flag that may for example be used to set the variable to a default value if the user doesn't input any value. And, last but not least, the ReadCon procedures react on the ESC key being pushed by canceling the program. This may be useful for example if you notice that you entered bad data (remember that on OS/2, CTRL+C does not work, even if BREAK=On is set in config.sys).
Here the Free Pascal code of the ReadCon unit:
    {*** Read from console unit ***}

    unit ReadCon;

    {$mode objfpc}{$H+}

    interface

    uses
        Crt;
    const
        Key_NULL = #0;
        Key_BS = #8;
        Key_ENTER = #13;
        Key_ESC = #27;
    procedure ReadString(out S: string);
    procedure ReadReal(out R: Real; out Empty: Boolean; out Err: string);
    procedure ReadInteger(out I: Integer; out Empty: Boolean; out Err: string);

    implementation

    const
        ErrMess: array[0..1] of string = (
            'Invalid number', 'Invalid integer'
        );

    {* Read string from console *}

    procedure ReadString(out S: string);

    // The procedure reads a string terminated by ENTER (as with Readln, the cursor passes to column 1 of the next line).
    // Characters accepted are ASCII 32 to 126. They are displayed with current text attributes at the current cursor position.
    // The BACKSPACE key may be used to clear the last character entered. The ESCAPE key may be used to abort the program.

    var
        Count: Integer;
        Key: Char;

    begin
        S := ''; Count := 0;
        repeat
            // Do this until the ENTER key (or the ESCAPE key) has been pressed
            Key := #255;
            if KeyPressed then begin
                // Do this if a key has been pressed on the keyboard
                Key := ReadKey;
                if Key = Key_NULL then
                    Key := ReadKey
                else begin
                    // Do this for regular (non control keys)
                    if Ord(Key) in [32..126] then begin
                        // Key is a (printable) character: Print it out and add it to the input string
                        Write(Key);
                        S := S + Key;
                        Inc(Count);
                    end
                    else if Key = Key_ENTER then begin
                        // Key is ENTER: Move the cursor to column 1 of next line (this will also terminate input)
                        Writeln;
                    end
                    else if Key = Key_BS then begin
                        // Key is BACKSPACE: Clear last character entered
                        if Count > 0 then begin
                            // This may only be done if there has been some character(s) entered
                            GotoXY(WhereX - 1, WhereY);
                            Write(' ');
                            GotoXY(WhereX - 1, WhereY);
                            Delete(S, Length(S), 1);
                            Dec(Count);
                        end;
                    end
                    else if Key = Key_ESC then begin
                        // Key is ESCAPE: Abort the program (may be used instead of CTRL+BREAK)
                        Halt;
                    end;
                end;
            end;
        until Key = Key_Enter;
    end;

    {* Read real number from console *}

    procedure ReadReal(out R: Real; out Empty: Boolean; out Err: string);

    // The procedure calls ReadString to read a string terminated by ENTER (the ESCAPE key terminating the program).
    // If the string is empty (ENTER has been pressed without entering any character), the boolean "Empty" is set to True.
    // This allows to use the procedure with no value entered (for example to use a default value in this case).
    // The procedure then checks if the input is a number; if not the error message variable "Err" is set.

    var
        E: Integer;
        S: string;

    begin
        R := 0; Empty := False; Err := '';
        // Read input as a string
        ReadString(S);
        // Check if input string is empty (ENTER pressed without entering any character)
        if S = '' then begin
            // Empty string: Set "Empty" variable to True
            Empty := True;
        end
        // Check if input string is numeric (is a real number)
        else begin
            Val(S, R, E);
            if E <> 0 then begin
                // Non-numeric string: Set error message variable
                Err := ErrMess[0];
            end;
        end;
    end;

    {* Read integer number from console *}

    procedure ReadInteger(out I: Integer; out Empty: Boolean; out Err: string);

    // The procedure calls ReadReal to read a real number terminated by ENTER (the ESCAPE key terminating the program).
    // If nothing has been entered, the boolean "Empty" has been set to True, if the input isn't a number the error
    // message variable "Err" has been set. If neither of these is the case, the procedure checks
    // if the number entered is well an integer. If yes, it is returned; if not, "Err" is set.

    var
        R: Real;

    begin
        I := 0; Empty := False; Err := '';
        // Read input as a real number
        ReadReal(R, Empty, Err);
        if (Err = '') and (not Empty) then begin
            // If the input is neither empty, nor a non-nueric value, check if the number is an integer
            if R = Int(R) then begin
                // Input number is an integer: return it
                I := Round(R);
            end
            else begin
                // Input number isn't an integer: Set error message variable
                Err := ErrMess[1];
            end;
        end;
    end;

    end.
To terminate the tutorial, a screenshot of my (modified) "equcub.pas" program, running on OS/2 Warp 3.
Free Pascal on OS/2: Successful execution of a program with Crt unit


If you find this text helpful, please, support me and this website by signing my guestbook.