Orphus system

Cheb's Home Page

Home
Cheb's Game Engine Quake II facelift
Штошник на ушах
 

 

What is Pascal?

Unless we delve into archeology (as some sources in the Internet do), or refer to obscure dialects, Pascal at its core is a simplified C++.

Granted, the syntax is painfully different and each language does have features that are a pain to implement when you are porting a program (e.g. multiple inheritance of C++ vs Pascal's enumerated types fluff). But where it matters, and especially compared to other languages of 2010s, Pascal and C++ are basically the same. Tools optimized for creating native code.

Of course, being much rarer Pascal does have problems with availability of libraries in source code form. But ultimately it allows you do the same things as C/C++. There was even a successful effort of porting Quake 2 to Delphi just to prove that.

There are two kinds of modern Pascal worth mentioning: Free Pascal and Delphi.

Delphi

Modern Pascal as a language was born in 1996 with Delphi 2. Don't get me wrong, there was a Delphi 1 before that, but it was 16-bit and so is not worth mentioning (grr-grr, hate the 64-kilobyte segments, stomp on their grave). Pascal as a full-fledged 32-bit compiler began with Delphi 2.

Evolving, Delphi shaped Pascal, saved it from obscurity and made it into what it is today. But ultimately, Delphi is an expensive professional tool for working with databases. It had suffered its share of downs and changed owners a couple times.

I am a staunch proponent of free software, so I have to stop here: after I grew out of being a university student, I stopped using pirated software. Thus I am not familiar with Delphi. The last pirated version I used was Delphi 4, it's ancient history now. Later, I was using the only free version ever, Turbo Delphi Explorer, for a while. But it was obsolete even for 2006, and then I had lost the license key file for it. So my knowledge of Delphi is outdated by almost 10 years.

More on Wikipedia

Free Pascal

Now, we are talking. GNU GPL, bitches! Hell yeah!

Versions 1.x are not worth mentioning since they were not feature-complete. Free Pascal as a usable language begins with 2.0 in 2005 (or 1.9 in 2003 if you consider its early betas).

What are the key points of Free Pascal?

Firstly, Compatibility Is Sacred. Plain and simple. The language began as a free replacement for Turbo Pascal aeons ago, and it *still* emulates Turbo Pascal by default unless you turn modern features on explicitly with {$mode delphi} or {$mode objfpc}{$longstrings on}. I mean, these modes are a de facto standard of the last frakking fifteen years. And yet they are not enabled by default.

Because if a program was compiling once, it should be compiling forever unless some fundamental change makes it impossible.

And I respect the dev team greatly for this.

Secondly, Write once, compile everywhere. It's the official motto. In any Linux distro, launch Synaptic and enter “fpc”. It will be there. x86, x86-64, arm... For a language mantained by a relatively small dev team its proliferation rate is impressive. I can't say for such exotics as Game Boy Advance or Nintendo Wii, but Linux and Windows support is rock solid.

Free Pascal is FreeBSD of programming languages

It's slow to catch on new platforms, yes. But it also keeps supporting platforms of yore. For all eternity.

There are no flashy applications written in it. But there are thousands of down-to-earth grim and gritty programs no one has heard of. All around Mother Russia they work like morlocks: unseen, untouched by the light of day, keeping ancient databases and cash registers running.

So, got vintage hardware? Want a specific application written for it? Look no further than Free Pascal.

Compile a program for Win32 without deliberately using modern Windows API functions. If you try to run it in Windows 98? It runs. Try it in Wine? it runs. I fear that had I have a genuine Windows 95 and tried to run a program (or compiler itself) there, it'd run. But that's not all. It's 2013 out there, soon to be 2014. Download the latest version of FPC for the DOS platform (yes, that DOS). Run it in DosBox. It works. On 16 megabytes of RAM. The program compiled by it works too. In both DosBox and Windows 7 console. It's scary that way.

Pascal is a Grammar Nazi

So, you are used to languages with C-like syntax? And worse, to weakly typed languages? Have to write a few lines in Pascal?

Prepare for lots of fun. And I mean the Dwarf Fortress definition of “fun”.

First, our basic template:
{$mode objfpc}
{$longstrings on}
{$ifdef windows}{$apptype console}{$endif}
program test;
var s: string;
begin
ReadLn(s);
WriteLn('Halo!');
end.

For brevity, I'll be showing only the line 8.

So, you need to find if the string contains a substring? Easily. if (strstr(s,'a')) ... in C++, or if (strpos(s, 'a') !== false) ... in php. There's such a function in Pascal too. pos('a', s) returns an integer. So we boldly go on...

if (pos('a', s)) WriteLn('Halo!');

test.pp(8,19) Fatal: Syntax error, "THEN" expected but "identifier WRITELN" found

Oh yes, the syntax is not C-compatible. Fun.

if pos('a', s) then WriteLn('Halo!');

test.pp(8,5) Error: Boolean expression expected, but got "LongInt"

Fun! In Pascal, the if operator only accepts values of type boolean. This is an enumerated type consisting of two constants: false and true. Being an enumerated type, it is incompatible with anything but itself. Cannot be substituted with integers, strings or pointers. The only way to get a boolean type is by using a comparison operator. Or a dumb type-cast which is a bad practice

Yes, Pascal can allow you to shoot yourself in the foot. You just have to state it explicitly “I want to shoot myself in the foot”, then everything is possible: pointer arithmetic, buffer overflows — anything. But you have to ask for it. In this case you'd have to write
if boolean(pos('a', s)) then WriteLn('Halo!');
and it'd work. Because internally, boolean is the same good old zero/non-zero stuff, for the sake of binary compatibility with code compiled in C.

But we won't go there, as we have just remembered that 'a' could be the first character of the string! So,

if pos('a', s) > -1 then WriteLn('Halo!'); //this should work, right?

And lo, it compiles!

>klmn
Halo!

Fun.

Well, due to historical reasons strings in Pascal begin at position 1, not 0. Sooo, the function pos() simply returns zero when the substring is not found. Finally
if pos('a', s) > 0 then WriteLn('Halo!');
And it works as intended.

Continuing. What if we need to compare two substrings?

if pos('a', s) > 0 || pos('bc', s) > 0 then WriteLn('Halo!');

test.pp(8,21) Fatal: illegal character "'|'" ($7C)

Yes, yes, non-C syntax.

if pos('a', s) > 0 or pos('bc', s) > 0 then WriteLn('Halo!');

test.pp(8,17) Error: Incompatible types: got "Boolean" expected "LongInt"

It's time to start banging your head against nearest suitable wall, isn't it?

The fun comes from the fact that unlike C, with its separate bitwise | and logical || operators, Pascal's or can be either bitwise or logical depending on the type of operands (you can also define your own or operator for your custom types like classes or vectors but that's a story for another time). Basically, Pascal gets confused with the order of operands in your expression. First it applies bitwise or between 0 and pos('bc', s), getting an integer. Then it applies the second comparison > 0 and gets a boolean. Then it finally comes to the left comparison... and finds an integer to the left of > and something that computes to a boolean to the right of it. Something is not right, thinks the compiler.

Sooo, an important lesson: always use the frakkin' parentheses in logical expressions or Pascall will go Grammar Nazi on yor ass! Because bitwise operators have higher priority than logical ones. And here you have been thinking that Pascal's ifs are all parenthesis-less like? Wrong.

if (pos('a', s) > 0) or (pos('bc', s) > 0) then WriteLn('Halo!');

Victory!

There are many more fun sides of Pascal, like division operator / always returning a floating-point value so that you need the specific div operator to perform integer division. Or how APIENTRY is stdcall. But that's a story for another time.