Go to the first, previous, next, last section, table of contents.


From Borland Pascal to GNU Pascal

This chapter is intended to be a QuickStart guide for programmers who are familiar with Borland Pascal, version 7 for DOS protected mode. Other versions don't differ too much but this one was the very last DOS version Borland has published.

Borland compatibility

GNU Pascal (GPC) is compatible to version 7 of Borland Pascal (BP) to a large extent and comes with portable replacements of the Borland standard units.

However, BP is a 16-bit compiler while GPC is a 32/64-bit compiler which, unlike other free compilers, does not intend to emulate BP in all respects. The size of the `Integer' type, for instance, is 16 bits in BP but at least 32 bits in GPC. If a BP program has been designed with portability in mind from the ground up, it may work with GPC without any change. Programs which rely on byte order, on the internals or sizes of data types or which use unportable things like interrupts and assembler code, will need to be changed. The GPC Run Time System (RTS) is fairly complete, and you can use all libraries written for GNU C from GNU Pascal, so there is much less need to use unportable constructs than there was in BP. (For example, BP's Turbo Vision library uses assembler to call a local procedure through a pointer. With GPC you can do this in Pascal just as with global procedures.) Please do not throw away the advantage of full portability by sticking to those workarounds.

We have successfully ported real-world projects (with several 10000s of lines) from BP to GPC, so this is possible for you, too.

IDE versus command line

On the DOS (DJGPP) and Linux platforms, you can use the RHIDE for GNU Pascal; check the subdirectories of your DJGPP distribution.

Unfortunately, there is no IDE which would run on all platforms. We are working on it, but this will take some time. Please be patient--or offer your help!

Without an IDE, the GNU Pascal Compiler, GPC, is called about like the command-line version of the Borland Pascal Compiler, BPC. Edit your source file(s) with your favorite ASCII editor, then call GNU Pascal with a command line like

  C:\GNU-PAS> gpc hello.pas -o hello.exe

on your DOS or OS/2 box or

  myhost/home/joe/gnu-pascal> gpc hello.pas -o hello

on your Unix (or Unix-compatible) system. Don't omit the suffix `.pas': GPC is a common interface for a Pascal compiler, a C, ObjC and C++ compiler, an assembler, a linker, and perhaps an Ada and a FORTRAN compiler. From the extension of your source file GPC figures out which compiler to run.

The -o is a command line option which tells GPC how the executable has to be named. If not given, the executable will be called `a.out' (Unix) or `a.exe' (Dos).

Note that GPC is case-sensitive concerning file names and options, so it will not work if you type

  C:\GNU-PAS> GPC HELLO.PAS -O HELLO.EXE

GPC is a very quiet compiler and doesn't print anything on the screen unless you request it or there is an error. If you want to see what is going on, invoke GPC with additional options:

  -Q            "don't be quiet"  (or: Quassel-Modus in German)

(with capital `Q'!) means that GPC prints out the names of procedures and functions it processes, and

  --verbose

or abbreviated

  -v

means that GPC informs you about the stages of compilation, i.e. preprocessing, compiling, assembling, and linking.

One example (this time for OS/2):

  [C:\GNU-Pascal] gpc --verbose -Q hello.pas

Throughout this chapter, we will tell you about a lot of command-line switches. They are all invoked this way.

After compilation, there will be an executable hello file in the current directory. (hello.exe with DOS and OS/2.) Just run it and enjoy. If you're new to Unix, please note that the current directory is not on the PATH in most installations, so you might have to run your program as `./hello'. This also helps to avoid name conflicts with other programs. Such conflicts are especially common with the program name `test' which happens to be a standard utility under Unix that does not print any output. If you call your program `test.pas', compile it, and then invoke `test', you will usually not run your program, but the utility which leads to mysterious problems. So, invoke your program as `./test' or, better yet, avoid the name `test' for your programs.

If there are compilation errors, GNU Pascal will not stop compilation after the first one--as Borland Pascal does--but try to catch them all in one compilation. If you get more error messages than your screen can hold, you can catch them in a file (e.g. gpc.out) or pipe them to a program like `more' in the following way:

  gpc hello.pas 2>gpc.out

This works with OS/2 and any bash-like shell under Unix; for DOS you must get a replacement for command.com which supports this kind of redirection, or use the `redir' utility (see also the DJGPP FAQ):

  C:\GNU-PAS> redir -eo gpc hello.pas -o hello.exe | more

You can also use Borland's IDE for GNU Pascal on the DOS platform: Install the GNU Pascal Compiler in the Tools menu (via Options/Tools).

  Name:       GNU Pascal
  Path:       gpc
  Arguments:  $SAVE ALL --verbose -Q $NAME($EDNAME).pas
  HotKey:     Shift+F9

Note once more that GPC is case-sensitive, so it is important to specify .pas instead of the .PAS Borland Pascal would append otherwise!

You can include more command-line arguments to GNU Pascal (e.g. `--automake'; see below) as you will learn more about them.

Since Borland Pascal will try to recompile your program if you use its run menu function, you will need another "tool" to run your program:

  Name:       run program
  Path:       command.com
  Arguments:  /c $NAME($EDNAME)
  HotKey:     Shift+F10

Comments and compiler directives

According to the ISO 7185 and ISO 10206 standards, GNU Pascal can recognize comments opened with (* and closed with }. With Borland Pascal, both types of comments can be nested, so you will probably have sources where passages containing comments are "commented out". GPC's default behavior is to allow nested comments, so you don't need to worry about this. However you can switch it off either by a command-line option, or by a compiler directive:

  --no-nested-comments     {$N-}    (*$N-*)

The $N directive also exists in BP but has another meaning. The same holds for most of GPC's other compiler directives (also corresponding to command-line options in most cases):

  --short-circuit     $B+ $B-  like in Borland Pascal:
                               $B- means short-circuit Boolean
                               operators; $B+ complete evaluation

  --c-numbers         $C+ $C-  enable/disable C-style octal 0177
                               and hexadecial 0xFF numbers

  --char-escapes      $E+ $E-  enable/disable C-style character
                               escape sequences in strings

  --io-checking       $I+ $I-  like in Borland Pascal:
                               enable/disable I/O checking

  --nested-comments   $N+ $N-  enable/disable nested comments
                               (see above)

  --pedantic          $P+ $P-  give/don't give portability warnings

                      $W+ $W-  enable/disable warnings

                      $X+ $X-  mostly like in Borland Pascal:
                               enable/disable extended syntax
                               (ignore function return values,
                               operator definitions, "PChars",
                               pointer arithmetics, ...)

  --borland-pascal             disable or warn about GPC features
                               not supported by Borland Pascal;
                               do not warn about "dangerous" BP
                               features

  {$I FileName }               like in Borland Pascal:
                               include filename.pas or
                               filename.p (make it lowercase)

  {$include "filename.pas"}    include (case-sensitive)

  {$include <filename.pas>}    the same, but don't search in the
                               current directory

  {$M Hello!}                  write message "Hello!" to error
                               device during compilation

  {$define FOO}                like in Borland Pascal:
  {$D FOO}                     define FOO (for conditional compilation)
                               Unlike BP, GPC treats FOO case-sensitively
  @cindex foo

  -D FOO                       the same in command line

  {$D loop while true do}      define "loop" to be "while true do"
                               as a macro like in C.
                               The name of the macro is case-sensitive.

  {$undef FOO}                 like in Borland Pascal: undefine FOO

  {$ifdef FOO}                 conditional compilation
    ...                        (like in Borland Pascal).
  {$else}                      GPC predefines the symbol
    ...                        __GPC__ (with two leading
  {$endif}                     and trailing underscores).

You also can use C-style preprocessor directives, e.g. `#include.', but this is deprecated, e.g. because of possible conflicts with Borland Pascal style `#42' character constants.

As in Borland Pascal, {$...} and (*$...*) are equivalent.

Units, GPI files and AutoMake

You can use units in the same way as in Borland Pascal. However, there are some additional features.

Concerning the syntax of a unit, you can, if you want, use Extended Pascal syntax to specify a unit initializer, i.e., instead of writing

  begin
    ...
  end.

at the end of the unit, you can get the same result with

  to begin do
    begin
      ...
    end (* to begin *);

and there also exists

  to end do
    begin
      ...
    end (* to end *);

which specifies a finalization routine. You can use this instead of Borland Pascal's exit procedures, but for compatibility, the included `System' unit also provides the `ExitProc' variable. The `to begin do' and/or `to end do' parts must be followed by the final `end.'. In section GNU Pascal extensions and section About Pascal and Extended Pascal languages, you can find information about Extended Pascal Modules, an alternative to units.

At the moment, there are no qualified identifiers, so take care about name clashes between different units.

When GPC compiles a unit, it produces two files: an .o object file (compatible with other GNU compilers such as GNU C) plus a precompiled Interface which resides in a .gpi file.

(See section GPI files--GNU Pascal Interfaces for GPI file internals.)

If you want to compile a program that uses units, you must "make" the project. (This is the command-line switch `-M' or the IDE keystroke `F9' in BP.) For this purpose, GPC provides the command-line switch `--automake':

  gpc --automake hello.pas

If you want to force everything to be rebuilt rather than only recompile changed files (`-B' or "build" in BP), use `--autobuild' instead of `--automake':

  gpc --autobuild hello.pas

For more information about the AutoMake mechanism, see section GPC's AutoMake Mechanism--How it Works.

If you do not want to use the AutoMake mechanism for whatever reason, you can also compile every unit manually and then link everything together.

GPC does not automatically recognize that something is a unit and cannot be linked; you have to tell this by a command line switch:

  -c            only compile, don't link.

(If you omit this switch when compiling a unit, you get a linker error message `undefined reference to `main''. Nothing serious.)

For example, to compile two units, use:

  gpc -c myunit1.pas myunit2.pas

When you have all units compiled, you can compile a program that uses them without using `--automake':

  gpc hello.pas

However, using `--automake' is recommended, since it will recompile units that were modified.

You could also specify the program and the units in one command line:

  gpc hello.pas myunit1.pas myunit2.pas

One of the purposes of writing units is to compile them separately. However, GNU Pascal allows you to have one or more units in the same source file (producing only one .o file but separate .gpi files). You even can have a Program and units in one and the same source file; in this case, no .o file is produced at all.

Optimization

GNU Pascal is a 32/64 bit compiler with excellent optimization algorithms (which are identically the same as those of GNU C). There are six optimization levels, specified by the command line options `-O', `-O2', ..., `-O6'.

One example:

  Program Test;

  Procedure Foo;
  Var
    A, B: Integer;
  begin
    A:= 3;
    B:= 4;
    writeln ( A + B );
  end;

  begin
    Foo
  end.

When GNU Pascal compiles this program with optimization, it recognizes that the argument of writeln is the constant 7--and optimizes away the variables A and B. If the variables were global, they would not be optimized away because they might be accessed from other places, but the constant 7 would still be optimized.

For more about optimization, see the GNU C documentation.

Debugging

The command line option `-g' specifies generation of debugging information for GDB, the GNU debugger. GDB comes with its own documentation. Currently, GDB does not understand Pascal syntax, so you should be familiar with C expressions if you want to use it.

See also "Notes for debugging" in the "Bugs" chapter; see section Known bugs and inconveniences; how to report bugs.

Sometimes it is nice to have a look at the assembler output of the compiler. When you specify the -S command line option, GPC produces an .s file instead of an .o file. The .s file contains assembler source for your program. More about this in the next section.

GPC Inline Assembler

GNU Pascal has an inline assembler, but it is quite different from Borland's one: It supports a large variety of processors and works together with GPC's optimization.

A tutorial for use of the GPC inline assembler is available from the same place where you got GPC itself in a subdirectory `contrib', file `gpcasm.zip'.

Since many things you usually do with assembler in BP are provided by GPC's Run Time System (RTS), you will not need the inline assembler as often as in BP. (See section Portability hints.)

Objects

Objects in the Borland Pascal 7.0 notation are implemented into GNU Pascal with the following differences:

Strings

Strings are "Schema types" in GNU Pascal which is something more advanced than Borland-style strings. For variables, you cannot specify just String as a type like in Borland Pascal; for parameters and pointer types you can. There is no 255 characters length limit. According to Extended Pascal, the maximum string length must be in (parantheses); GNU Pascal accepts [brackets], too, however.

For more about Strings and Schema types see section GNU Pascal extensions and section About Pascal and Extended Pascal languages.

GPC supports Borland Pascal's String-handling functions and some more (see section GNU Pascal extensions):

  Borland Pascal       GNU Pascal

  Length               Length
  Pos                  Pos, Index (1)
  Str                  Str, WriteStr (1) (2)
  Val                  Val, ReadStr (2)
  Copy                 Copy, SubStr, MyStr [ 2 .. 7 ] (3)
  MyStr [ 0 ]:= #7;    SetLength
    -                  Trim
  =, <>, <, <=, >, >=  =, <>, <, <=, >, >= (4)
                       EQ, NE, LT, LE, GT, GE
  Insert               Insert
  Delete               Delete

(1) The order of parameters of the Extended Pascal routines (`Index', `WriteStr') is different from the Borland Pascal routines.

(2) `ReadStr' and `WriteStr' allow an arbitrary number of arguments, and the arguments are not limited to numbers. `WriteStr' also allows comfortable formatting like `Writeln' does, e.g. `WriteStr (Dest, Foo : 20, Bar, 1/3 : 10 : 2)'.

(3) `SubStr' reports a runtime error if the requested substring does not fit in the given string, `Copy' does not.

(4) By default, the string operators behave like in BP. However, if you use the option `--no-exact-compare-strings', they ignore differences of trailing blanks, so e.g. `'foo'' and `'foo '' are considered equal. The corresponding functions (`EQ', ...) always do exact comparisons.

Typed Constants

GNU Pascal supports Borland Pascal's "typed constants" but also Extended Pascal's initialized variables:

  Var
    x: Integer value 7;

or

  Var
    x: Integer = 7;

When a typed constant is misused as an initialized variable, a warning is given unless you specify `--borland-pascal'.

When you initialize a record, you may omit the field names. When you initialize an array, you may provide indices with a :. However, this additional information is ignored completely, so perhaps it's best for the moment to only provide the values ...

When you want a local variable to preserve its value, define it as `static' instead of using a typed constant. Typed constants also become static automatically for Borland Pascal compatibility, but it's better not to rely on this "feature" in new programs. Initialized variables do not become static automatically.

  Procedure Foo;

  Var
    x: static Real;

  begin (* Foo *)
    (* x keeps its value between two calls to this Procedure *)
  end (* Foo *);

Bit, Byte and Memory Manipulation

The bitwise operators `shl', `shr', `and', `or', `xor' work in GNU Pascal like in Borland Pascal. As an extension, you can use them as "procedures", for example

  and ( x, $0000FFFF );

as an alternative to

  x:= x and $0000FFFF;

GPC accepts the Borland-specific notation `$ABCD' for hexadecimal numbers, but you also can use Extended Pascal notation:

   2#11111111   for a binary,
   8#177        for an octal,
  16#FF         for a hexadecimal number,

and so on up to a basis of 36.

`Inc' and `Dec' are implemented like in Borland Pascal; `Pred' and `Succ' are generalized according to Extended Pascal and can have a second (optional) parameter:

  a:= Succ ( a, 5 );

`Absolute' variables work in the context of overloading other variables as well as in the context of specifying an absolute address, but the latter is highly unportable and not very useful even in DOS protected mode.

The `Mem' and `Port' arrays don't exist in GNU Pascal. As a replacement for `Port', you can use the routines provided in the `Ports' unit.

GNU Pascal knows Borland Pascal's procedures FillChar and Move. However, their use can be dangerous because it often makes implicit unportable assumptions about type sizes, endianness, internal structures or similar things. Therefore, avoid them whenever possible. E.g., if you want to clear an array of strings, don't `FillChar' the whole array with zeros (this would overwrite the Schema discriminants, see section Strings), but rather use a `for' loop to assign the empty string to each string. This is even more efficient than `FillChar', since it only has to set the length field of each string to zero.

User-defined operators in GPC

GNU Pascal allows the user to define operators according to the Pascal-SC syntax:

  Type
    Point = record
      x, y: Real;
    end (* Point *);

  Operator + ( a, b: Point ) c: Point;

  begin (* Point + Point *)
    c.x:= a.x + b.x;
    c.y:= a.y + b.y;
  end (* Point + Point *);

The Pascal-SC operators `+>', `+<', etc. for exact numerical calculations are not implemented, but you can define them. If you write a module which really implements these operators, please send it to us, so we can include it into the next distribution.

(And if you know more about modules in Pascal-SC than just their existence, please contact us as well! We could probably easily implement them if we knew how they look like. Something quite close to Pascal-SC modules already is implemented as "GNU specific modules".)

Data Types in BP and GPC

Files

Built-in constants

Built-in operators in BP and GPC

Besides the operators found in Borland Pascal, GNU Pascal supports the following operators:

Built-in Procedures and Functions

Parameters

Miscellaneous

Portability hints

GPC offers you the possibility to make your code fully portable to each of the many platforms supported by GPC. It would be a pity not to make use of this.

This section lists some known pitfalls that often hinder otherwise well-written programs to take full advantage of GPC. If you have never used any compiler but Borland Pascal and similar compilers, some of the advices might look strange to you. But this is just the same level of strangeness that your old programs will have for you once you have understood the principles of cross-platform portability. Remember that many tricks you have always been applying almost automatically in Borland Pascal were necessary to overcome certain limitations of the MS-DOS platform and to compensate for the compiler's missing optimization. Programming with an optimizing compiler like GPC for platforms without a 64 kB limit is a completely new experience--and perhaps it is among the reasons why you are now working with GPC in the first place?

Portability--why?

Okay--but why should I bother and make my program portable? I know that all who want to use my program are running WXYZ-OS anyway.

Yes, but that's the result of a self-fulfilling prophecy. It depends on you whether it will always remain like this or not. Consider a program ABC written for a single platform, WXYZ-OS. Naturally, only WXYZ-OS-users get interested in ABC. The author gets feedback only from WXYZ-OS users and does not see any reason to make the program cross-platform. Then people realize that if they want to run ABC they must move to WXYZ-OS. The author concludes that people only want WXYZ-OS programs, and so on.

To break out, just create a portable version of your program now. Then all OSes have equal chances to show their abilities when running your program, and your customers can choose their OS. Then, maybe, they decide to use your program just for the reason that they can be sure that it will run on all present and future platforms and not only on a specific one--who knows?

My program is a tool specifically designed to make the best of the STUV feature of WXYZ-OS. There is no point in making it portable.

How much do you know about non-WXYZ-OSes? Just ask an expert how the STUV feature is named elsewhere. Be sure, if it is of value, it exists almost everywhere.

Low-level features

I am using a lot of low-level stuff in my programs, so they cannot be portable.

You do not use those low-level routines directly in your high-level routines, do you? There should always be a layer "in-between" that encapsulates the low-level routines and present an API to your program that exactly reflects the needs of your application. This "API in between" is the point where you can exchange the low-level routines by portable calls to the run time system.

If you do not have such a layer in-between, then the API of the low-level routines you call are your first approximation for such a layer. If you have ever thought "it would be great if that API function had that additional parameter", then your own extended version of that API function that has that parameter can become part of your "API in between". But then don't stop here: Certainly the API of the OS is not ideal for your program's needs. Just create more routines that encapsulate all OS-specific stuff ...

When the low-level stuff in question consists of interrupts, assembler and similar things, then the first thing you need is a portable replacement of the functionality. Fortunately, GPC covers many things already in Pascal that require assembler in Borland Pascal:


Go to the first, previous, next, last section, table of contents.