Kylix Newsletter #2
INDEX
1. A FEW WORDS FROM THE EDITOR
2. FREE PASCAL AND LAZARUS
3. INTRODUCTION TO BORLAND OBJECT PASCAL (I)
4. PORTING ISSUES: ASSEMBLER IN DELPHI
5. LINKS
6. WHAT'S NEXT?
________________________________________________________________________
1. A FEW WORDS FROM THE EDITOR
A couple of weeks ago we had a great success when we started our Kylix
Newsletter, but to keep it going and growing in contents we need your
support to make it grow in audience. This newsletter is copyrighted, but
please forward it to friends, acquaintances and colleagues that you know
might be interested in this publication as long as you send it in full
and without modifications.
Last week we repeated the success when we launched in advance the first
issue of our Delphi Newsletter, two weeks before planned.
We have been suggested to merge our Kylix and Delphi newsletters into a
bigger and more generic Pascal Newsletter that would also give coverage
to Free Pascal, Lazarus and other projects. We believe the proposal
could be of interest to our subscribers, so we are considering it and we
would like to hear your opinions about it.
Your contributions, comments, critics and questions are welcome. Please
stay in touch!
Regards,
Ernesto De Spirito
eds2008 @ latiumsoftware.com
________________________________________________________________________
JfControls Library. Multi-language. Multi-appearance. Skins. Privileges.
More than 40 integrated and customizable components. Impressive GUI.
Centralized resources administration. Multiple programming problems
solved. For Delphi 3-6 and C++ Builder 3-5. http://www.jfactivesoft.com/
________________________________________________________________________
2. FREE PASCAL AND LAZARUS
FREE PASCAL
-----------
Free Pascal (formerly called FPK-Pascal) is an open-source 32-bit
Borland-compatible Pascal compiler distributed under a modified version
of the GNU General Public License.
Free Pascal is under development and currently there are only evaluation
versions available, but they seem to be working fine. The latest
releases are 0.99.14 (1.0 beta 4) for the Intel chip and 0.99.5d for the
Motorola processor, and there is also a development version available
and daily-released development snapshots. Hopefully, version 1.0 will
see the light this year.
The compiler is written in Pascal and is able to compile its own sources
(which are surprisingly small BTW: about 4 Mb), and it has the following
minimum system requirements:
- Intel 80386 25 Mhz or Motorola 68020 processor. Work is in progress
to port it to the Alpha chip.
- Linux, DOS, Atari, AmigaOS, OS/2 or Win32 operating systems. Work is
being done to port it to other platforms (like FreeBSD).
- 2 Mb RAM (16+ Mb recommended to remake the compiler) for the DOS
version, and 8 Mb RAM for the Linux version.
Apart from the compiler itself there are many tools available:
* Command-line tools (like a source formatter, a makefile generator, a
C header translator, a unit dependency lister, TP lex and yacc).
* The FCL (Free Component Library), which is a free and portable
alternative to Delphi's VCL (Visual Component Library). It is a low-
level library (it doesn't include GUI components) meant to provide
people that implement a GUI with basic routines such as string lists,
streaming, XML routines, Database access and many more things.
It tries to provide as many Delphi-compatible components as possible,
to ease porting, but it also presents alternative components that
offer different functionality, not found in the Delphi components.
* Packages: mainly import units for important libraries, or some tools
that have been developed by the Free Pascal team. There are many such
packages, ranging from GUI packages (such as GTK and OpenGL) to
database packages (such as Interbase and MySQL).
* The IDE is in early beta, but there are IDEs provided by third
parties like Bloodshed Dev-Pas.
* Documentation. It is excellent!
The language syntax is compatible with Borland Turbo Pascal 7.0 and also
supports some extensions used by Delphi 2 and 3 like classes, RTTI,
exceptions and ANSI strings, as well as function overloading and other
such features, although full compatibility with Delphi 4 has not yet
been attained.
The official site is http://www.freepascal.org and there are many
mirrors (be aware that not all of them are up to date). Among other
things, there you will find more information about Free Pascal, a
comparison between Free Pascal and GNU Pascal, the latests news, a
mailing list and a newsletter. And the downloads, of course! Very
complete.
LAZARUS
-------
Lazarus is a set of class libraries for Free Pascal that emulate Delphi.
The idea is to allow programmers to develop Delphi-like programs in all
the platforms supported by Free Pascal without having to do any recoding
to produce identical products for different platforms.
While the FCL (Free Pascal's Free Component Library) is mainly made up
of nonvisual components, the LCL (Lazarus Class Library) focuses on
those classes and components that are visual, and they are totally and
completely API independent, meaning you can link your code against the
API widget set of your choice (Windows, GTK+, GNOME or any other
available). In the future, the LCL will be added to the FCL.
The Lazarus project also involves the creation of an IDE for Free
Pascal, aiming at becoming a RAD tool like Delphi, but truth is current
version is 0.5, if you know what it means...
The official web site is http://www.lazarus.freepascal.org The site is
well designed and there you will find it all: news, information, a
mailing list, documentation, downloads, etc., and they even have a gift
shop. I need one of those coffee mugs!
CONCLUSION
----------
In my personal opinion, the combination Free Pascal + Lazarus is highly
recommendable for academic purposes, since it is a free compatible
alternative to this great professional tool that is Delphi, plus it runs
in various OSs, including Linux (which is free and slowly becoming
popular among students) and the hardware requirements are quite modest.
Also, it could be worth the try if you are interested in a multi-
platform OOP language with a big component library, since Free Pascal
and Lazarus are suitable from system to database programming and are
free even for commercial use (of course, if you modify the compiler or
the units of the FCL or the LCL, you will have to make those changes
publicly available under the GPL).
However, you will have to wait for that, since they are still in a
development stage. Project Lazarus has yet a long way to go, but you can
start trying the compiler. It's a good option for the typical command-
line programs for edcucational purposes. Or maybe you would like to try
it to begin learning Pascal while you wait for Kylix.
________________________________________________________________________
3. INTRODUCTION TO BORLAND OBJECT PASCAL (I)
This is the first of a series of articles intended to give a quick
introduction to the Pascal syntax to those programmers not familiar with
this language. This articles will not teach you Pascal and will not be a
full reference either, just a fast introduction. In this article we will
try to cover the very basics of Pascal and we will leave OOP for the
next issue of this newsletter.
General notes
-------------
* Pascal uses "begin" and "end" to enclose sentences in blocks, instead
of braces ("{}") like C or Java.
* Braces ("{}") enclose comments. Comments are also enclosed between
"(*" and "*)" (without the quotes!). You can also comment till the end
of the line with "//" like in C or Java.
* The semicolon is a statement separator, not a statement terminator
like in C, so it is not necessary before an "end".
* You can split one statement in multiple lines like in C or Java since
line breaks are not separators (semicolons are).
* Comments that start with "$" are compiler directives.
* Hexadecimal numeric values are preceded with a "$".
* A "#" preceding a numeric value denotes a character value, being that
character the corresponding to that numeric value.
* Characters are assignment compatible with strings: they are treated as
one-character strings.
* Variables are not initialized.
* Assignment statements use ":=", while "=" is a comparison operator (In
C and Java, "=" is the assignment operator and "==" is the comparison
operator).
* The C-like syntax a := b := c := 0; is not supported.
* The And, Or, Not operators have a higher precedence than the
comparison operators, so comparisons should usually be parenthesized
(unless you use And, Or, Not as bitwise operators instead of boolean
operators).
* Identifiers are not case sensitive.
* Strings and single characters are delimited by single quotes.
Structure of an application source code
---------------------------------------
Normally an application is made up of a program file (.dpr) and many
"unit" files (.pas). These units are modules like .c files.
The minimum program file starts with the word "program" followed by the
internal name of the program, and the code is enclosed in a begin..end
block, that would be equivalent to the braces in C. For example:
program program1;
begin
WriteLn('Hello world!');
end.
WriteLn is a procedure that writes a string to the system's standard
output device (normally the console).
A program can declare constants, types, variables, procedures and
functions. The following program does nothing useful but it serves as an
example:
program program2;
const
MIN: integer = 1;
MAX: integer = 20;
type
ValueRange = 1..20;
ValueArray = array[ValueRange] of integer;
var
Value: integer;
Values: ValueArray;
function IsInRange(n: integer): boolean;
begin
if (n >= MIN) and (n <= MAX) then
Result := True
else
IsInRange := False;
end;
procedure InputValues();
procedure InitValues();
var i: ValueRange;
begin
for i := MIN to MAX do Values[i] := 0;
end;
begin
InitValues;
repeat
WriteLn('Enter a value between 1 and 20 (0 to exit): ');
ReadLn(value);
if value <> 0 then
if IsInRange(Value) then
Inc(Values[Value])
else
WriteLn('Invalid value. Please try again');
until value = 0;
end;
function MaxValue(): ValueRange;
var
i: ValueRange;
begin
Result := MIN;
for i := MIN + 1 to MAX do
if Values[i] > Values[Result] then
Result := i;
end;
begin
InputValues;
WriteLn('Most typed value is: ', MaxValue());
end.
The word "const" precedes the declaration of constants. In the example,
two constants of integer type are declared, named "MIN" and "MAX",
representing the values 1 and 20 respectively.
The word "type" precedes the declaration of user-defined types. In the
example we declare a range of integer values and an array of 20 integers
indexed from 1 to 20.
The word "var" precedes the declaration of variables. In the example we
declare an integer variable and array variable (an array of 20 integers
indexed from 1 to 20).
Function declarations are preceded by the word "function". Functions
have a name, parameters (optional) and a return type. For example, the
function "IsInRange" takes one integer argument and returns a boolean
value. To return a value, it should be assigned to the implicit variable
"Result" or to the implicit variable named as the function, so
"Result := ..." or "IsInRange := ..." will have the same effect.
Procedure declarations are preceded by the word "procedure" instead of
function, and they don't have a return type since procedures do not
return values.
To call a procedure or a function, just type its name (followed by the
actual parameters enclosed in parenthesis if the procedure or function
takes parameters). For example, "IsInRange(Value)" calls the IsInRange
function passing the variable "Value" as the argument. "InputValues" in
the main block calls the InputValues procedure. "Inc(Values[Value])" (in
C or Java you would write "Values[Value]++" instead) calls a built-in
procedure that increments its argument. Actually it is not really a
procedure since the compiler will generate an INC machine opcode...
Procedures and functions can have local constants, types, variables and
also procedures and functions. They are declared in the same way as
their program-level counterparts, except the declarations are placed
between the procedure or function header and the "begin" of its code
block. For example, function MaxValue declares a local variable named
"i" and the procedure "InputValues" declares a local procedure
"InitValues" which in turn declares a local variable "i".
The advantage of local functions and procedures is that they can access
the local variables and parameters of the enclosing functions or
procedures, so they do not need to be passed as arguments, allowing
clear and efficient coding.
The procedures we used so far (ReadLn, that reads from the standard
input, WriteLn and Inc) are declared in the System unit which is
"included" by the compiler by default, so we do not need to tell it to
do it. The System unit contains many useful constants, types, variables,
procedures and functions, but there are many more available to us in
other units that come with Delphi. For example, most of the elements to
work with files come in the SysUtils unit, and most Windows API calls
come in the Windows unit. To "include" these unit in our program, we use
a "uses" clause. For example:
program program3;
uses
SysUtils, Windows;
.
.
.
And of course, we can make our own units. Units start with the word
"unit" instead of "program" and have four sections:
* interface
The interface section contains all the public declarations (i.e.
constants, types, variables, procedures and functions that will be
available to programs and other units)
* implementation
The implementation section contains all the module (unit-level)
declarations and the definitions of the procedures and functions
declared in the interface section.
* initialization
Code to initialize public and module variables.
* finalization
Code to free resources allocated by the unit.
For example:
unit Unit1;
interface
var globalvar: integer;
procedure IncGlobalVar;
implementation
procedure IncGlobalVar;
begin
Inc(globalvar);
end;
initialization
globalvar := 10;
end.
This unit declares a public variable named globalvar and a public
procedure named IncGlobalVar. In the implementation section this
procedure is defined and the initialization section sets the initial
value of the variable. There is no finalization section because there
are no resources to free.
This program uses the unit declared above:
program program4;
uses
Unit1 in 'Unit1.pas';
begin // Unit is initialized here
WriteLn(globalvar); // 10
IncGlobalVar;
WriteLn(globalvar); // 11
end.
Flow control statements
-----------------------
The "if" statement:
if <condition> then <statement>;
if <condition> then
<statement1>
else
<statement2>;
if <condition> then begin
<statement1>;
<statement2>;
<statement3>[;]
end else
<statement4>;
if <condition> then begin
<statement1>;
<statement2>;
<statement3>[;]
end else begin
<statement4>;
<statement5>[;]
end;
Notice there is no semicolon before an "else". You need to use a
"begin...end" when the statements within the structure are more than
just one. <condition> is a boolean expression (it must evaluate to
True or False).
The "case" statement:
case <selector> of
<caselist1>: <statement1>;
...
<caselistN>: <statementN>;
[else
<statement>;]
end;
<selector> must be an ordinal expression (it cannot be a string for
instance). The case lists are lists of values separated by commas. Valid
case lists could be for example:
1:
5..10:
20, 30..40, 50..60, 67:
When more than one statement is needed in a case, they must be enclosed
in a begin...end block.
The "for" statement:
for <variable> := <start> to/downto <end> do <statement>;
If you use "to" the increment (or "step") is 1, and if you use downto,
the increment is -1. If you need many statements inside the for loop,
they must be enclosed in a begin...end block. Be careful: upon exit of
the for loop, the value of the control variable is undefined!
The "while" statement:
while <condition> do <statement>;
<condition> is a boolean expression and if you need many statements
inside the while loop, you know: use begin...end.
The "repeat...until" statement:
repeat
<statement1>;
<statement2>;
...
<statementN>[;]
until <condition>;
The statements are repeated while the condition is NOT satisfied. The
condition is evaluated at the end, so the inside statements are executed
at least once. No begin...end necessary.
The goto statement:
Its use is discouraged in structured programming. However it is useful
to exit loops. Before using goto, first you have to declare a label and
precede the sentence where you want to jump to by this label followed by
a colon, as in the following example:
function IsCharInString(char c, string s): boolean;
var i, n: Integer;
label CharFound;
begin
n := Length(s);
for i := 1 to n do
if s[i] = c then goto CharFound;
Result := False;
Exit; // Ends a procedure or function
CharFound:
Result := True;
end;
Never use goto to jump into a loop or other structured statement, since
this can have unpredictable effects. Jumps form the inside to the
outside or from the outside to the inside of try...except and try...
finally blocks are not allowed. Jumps from or to another procedure or
function are not allowed either.
Always try to use a structured alternative, or at least use the Break
procedure:
function IsCharInString(char c, string s): boolean;
var i, n: Integer;
begin
Result := False;
n := Length(s);
for i := 1 to n do
if s[i] = c then begin
Result := True;
break; // Exits from the innermost loop
end;
end;
Basic types
-----------
Object Pascal data types can be categorized in the following hierarchy:
simple
ordinal
integer
Shortint -128..127 signed 8-bit
Smallint -32768..32767 signed 16-bit
Longint -2147483648..2147483647 signed 32-bit
Integer -2147483648..2147483647 signed 32-bit
Int64 -2^63..2^63-1 signed 64-bit
Byte 0..255 unsigned 8-bit
Word 0..65535 unsigned 16-bit
Longword 0..4294967295 unsigned 32-bit
Cardinal 0..4294967295 unsigned 32-bit
character
AnsiChar 1-byte ANSI char
WideChar 2-byte UNICODE
Char AnsiChar
boolean
Boolean 1-byte (8 bits) boolean value
ByteBool 1-byte (8 bits) boolean value
WordBool 2-byte (16 bits) boolean value
LongBool 4-byte (32 bits) boolean value
enumerated
type <typeName> = (val1, ..., valn);
Example: type Suit = (Club, Diamond, Heart, Spade);
subrange
type <typeName> = val1..val2;
Example: type ExceptClub = Diamond..Spade;
Capitals = 'A'..'Z';
Hours = 0..23;
real
Real48 2.9x10^-39..1.7x10^38 11-12 digits 6 bytes
Single 1.5x10^-45..3.4x10^38 7-8 digits 4 bytes
Double 5.0x10^-324..1.7x10^308 15-16 digits 8 bytes
Extended 3.6x10^-4951..1.1x10^4932 19-20 digits 10 bytes
Comp -2^63+1..2^63 -1 19-20 digits 8 bytes
Currency -922337203685477.5808
.. 922337203685477.5807 19-20 digits 8 bytes
Real Double
string
ShortString 255 characters backward compatibility
AnsiString ~2^31 characters 8-bit (ANSI) characters
WideString ~2^30 characters Unicode characters
String AnsiString
structured
set
type <typeName> = set of <ordinal-type>;
array
static
type <typeName> = array [<ordinal-type>] of <basetype>;
type <typeName> = array [<ordinal-type1>,
<ordinal-type2>,...] of <basetype>;
dynamic
type <typeName> = array of <basetype>;
record
type <typeName> = record
<fieldList1>: <type1>;
...
<fieldListn>: <typen>;
end;
file
type <typeName> = file of <basetype>;
type <typeName> = file; // Untyped file
class
// We leave it for the next issue of this newsletter
class reference
type <typeName> = class of <class-type>;
interface
// We leave it for the next issue of this newsletter
pointer
type <typeName> = ^<type>;
procedural
type <typeName> = <function or proc declaration>;
type <typeName> = procedure(<parameters>) of object;
Examples: type TIntegerFunction = function: Integer;
TProcedure = procedure;
TStrProc = procedure(const S: string);
TMathFunc = function(X: Double): Double;
TMethod = procedure of object;
TNotifyEvent = procedure(Sender: TObject)
of object;
variant
Variant variables can hold a value of any type, except structured
types, pointers and Int64. However they can hold dynamic arrays and
a special kind of static array called a variant array. They can also
hold COM and CORBA objects.
This would be it for now. In the next issue we would be talking a bit
about classes and objects.
________________________________________________________________________
4. PORTING ISSUES: ASSEMBLER IN DELPHI
This article should only concern you if you coded in Assembler for
Windows and then try to port that code to Linux. Part of the information
shown in this article has been extracted from
http://community.borland.com/article/0,1410,21301,00.html
The bad news is that TASM (Borland's Turbo Assembler) will not be
available with Kylix, so if you need an external assembler because you
wrote .ASM files, then you will have to consider one of these
alternatives to keep a certain degree of portability:
* Rewrite your modules in a higher level language like Pascal or C. This
way you can achieve maximum portability and easiness of maintenance.
Leave assembler (inline) only for the critical code where assembler is
really worth it.
* Migrate the external .ASM code into Object Pascal inline assembler
code blocks. The disadvantage is that you will lose all macros and
other TASM shortcuts you used, but at least it is not a complete
rewrite.
* Use NASM (Netwide Assembler). NASM uses the Intel syntax (like TASM)
and has limited macro support, but this support includes a subset of
MASM. If you wrote your .ASM files in TASM mode, you will have to
convert your code to MASM mode. You will have to do without MASM
features not supported by NASM.
An important issue when writing assembler code for Linux is Position
Independent Code (PIC) required by Linux shared object libraries (DLL
equivalents), meaning that your code should be relocateable in memory
without modification.
In the PIC scheme, the EBX register contains a pointer to the base
address of the current module (Global Offset Table, or GOT in Linux
jargon) and you should always preserve this register across calls into
your assembler code. Also, you should restore the EBX register before
making calls to external functions.
All assembler code that refers to global variables should be changed to
use indirect addressing via the EBX register. For example, if your code
is
MOV EAX, GlobalVar
you would change it for
MOV EAX, [EBX].GlobalVar
This undoubtedly means a loss in performance (and bigger code), so
Borland is using a PIC symbol in the RTL (Run-Time Library) which is
defined when the code should conform to PIC rules (Linux shared
objects), allowing conditional compilation, and it would be wise you do
the same thing.
________________________________________________________________________
5. LINKS
Here is an excellent site dedicated to Delphi. We recommend you download
the program that downloads and updates the Delphi tips and tricks in
your PC: http://www.q3.nu
________________________________________________________________________
6. WHAT'S NEXT?
In the next issue, we will continue the introduction to Object Pascal
and we will keep discussing porting issues. See you then!
________________________________________________________________________
YOU CAN HELP US
We need your help to keep this newsletter going and growing. You can
help by referring the newsletter to your colleagues:
http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php
Or you can help by voting for us in some or all of these rankings to
give more visibility to our web site and thus increase the number of
subscriptions to this newsletter:
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
It's just a few seconds for you that REALLY mean a lot to us.
________________________________________________________________________
This newsletter is provided "AS IS" without warranty of any kind. Its
use implies the acceptance of our licensing terms and disclaimer of
warranty you can read at http://www.latiumsoftware.com/en/legal.php
where you will also find a note about legal trademarks. Articles are
copyright of their respective authors and they are reproduced here with
their permission. You can redistribute this newsletter as long as you do
it in full (including copyright notices), without changes, and gratis.
________________________________________________________________________
Main page: http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php
Group home page: http://groups.yahoo.com/group/pascal-newsletter/
Subscribe/join: pascal-newsletter-subscribe@yahoogroups.com
Unsubscribe/leave: pascal-newsletter-unsubscribe@yahoogroups.com
Problems with your subscription? eds2008 @ latiumsoftware.com
________________________________________________________________________
Latium Software http://www.latiumsoftware.com/en/index.php
Copyright (c) 2000 by Ernesto De Spirito. All rights reserved.
________________________________________________________________________
|