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. | ||
|
||
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. | ||
|
||
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. | ||
|
||
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. | ||
|
||
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). | ||
|
||
Now, let's try to build the (very simple) GUI application basicpm.pas. The screenshot shows the output of the compiler and linker. | ||
|
||
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. | ||
|
||
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. | ||
|
||
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). | ||
|
||
The screenshot below shows the successful build of the sample GUI application basicpm.pas in fp. | ||
|
||
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. | ||
|
||
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 |
||
|
||
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. | ||
|
||
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):
|
||
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. | ||
|
If you find this text helpful, please, support me and this website by signing my guestbook.