G
NU Pascal Coding Standards
Copyright (C) 2001-2002 Frank Heckenbach frank(at)pascal.gnu.de
,
Peter Gerwinski peter(at)gerwinski.de
,
Nicola Girardi nicola(at)g-n-u.de
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by the copyright holders.
Verändert 10. Mai 2002. Basierend auf der englischen Version 10. Mai 2002.
Vorwort des Übersetzers: Dieses Dokument enthält die Übersetzung der "GNU Pascal Coding Standards". Einige Worte werden so beibehalten, wie sie im Englischen geschrieben wurden, weil es meiner Meinung nach die Lesbarkeit des Textes fördert. Für Fehler in der Übersetzung bin ich verantwortlich, nicht die ursprünglichen Autoren. Für Rückfragen zur Übersetzung bin ich erreichbar unter: Eike Lange eike@g-n-u.de. Mein besonderer Dank gilt Roland Goretzki für seine unermüdliche Arbeit, dieses Dokument vom Fehlerteufel zu befreien.
Trotz aller Sorgfalt lassen sich Fehler in der Übersetzung nicht ganz ausschließen. In Konfliktfällen gilt stets das englische Original. Bitte teilen sie uns eventuelle Diskrepanzen mit, damit wir sie beheben können.
Die GNU Pascal Coding Standards wurden von einer Gruppe freiwilliger Helfer des GNU Pascal Projektes entwickelt. Das Ziel dieses Dokumentes ist es, die GNU Coding Standards um spezifische Informationen für Pascal-Programmierer zu ergänzen. Die Informationen in den GNU Coding Standard beziehen sich zu großen Teilen auf die Programmiersprache C. Gleichsam erklären sie jedoch viele der Regeln und Prinzipien, die zum Schreiben portabler, robuster und zuverlässiger Programme nützlich sind. Die meisten dieser Regeln können mit wenigen Anmerkungen versehen aus dem Dokument übernommen werden, weswegen sich Referenzen zu den GNU Coding Standards in diesem Dokument befinden.
Letzte Aktualisierung dieses Dokuments (original): 10. Mai 2002.
Die GNU Pascal Coding Standards sind als Teil der GPC-Distributionen erhältlich - in Binärdistributionen als Info-Dateien, in Quelltext-Distributions auch als Texinfo-Dateien, aus denen sich weitere Formate wie HTML, PostScript und PDF erzeugen lassen. Eine HTML-Version befindet sich auch auf der Homepage von GPC, http://www.gnu-pascal.de.
Berichtigungen oder Vorschläge zu diesem Dokument können Sie direkt beim Autor einreichen: eike@g-n-u.de. Für das englischsprachige Original wenden Sie sich bitte an die Dokumentations-Mailingliste des GNU Pascal Compilers, gpc-doc@gnu.de. Da unsere Zeit begrenzt ist, sollten Ihre Vorschläge den geänderten Text enthalten. Ein "context diff" der Quelldatei im Texinfo-Format ist sehr willkommen, wobei wir einer einfachen Mail auch nicht abgeneigt sind.
Die folgenden Leute sind die Tyrannen, die ihre Art der
Programmierung anderen auferlegen:
Peter Gerwinski peter(at)gerwinski.de
, Frank
Heckenbach frank(at)pascal.gnu.de
, Markus Gerwinski
markus(at)gerwinski.de
, Dominik Freche
dominik.freche(at)gmx.net
, Nicola Girardi
nicola(at)g-n-u.de
.
Dieses Kapitel der GNU Coding Standards beschreibt unter anderem, wie man sich versichert, daß GNU Software rechtliche Schwierigkeiten vermeidet. SieheIntellectual Property.
Dieses Kapitel beschäftigt sich mit einigen grundlegenden Themen zur Gestaltung eines Programmes.
Wir unterstützen die Idee, daß die Vielfalt der Programmiersprachen etwas Gutes ist. Verschiedene Programmiersprachen sind nützlich für verschiedene Aufgaben. Anders als die GNU Coding Standards (sieheSource Language) wollen wir Sie nicht davon überzeugen, daß Sie C oder Pascal oder eine andere einzelne Programmiersprache für alles nutzen sollten.
Wenn Sie das lesen, dann haben Sie sich möglicherweise schon bei einigen Projekten für Pascal entschieden oder ziehen dies in Erwägung. Dieses Dokument will Ihnen Vorschläge unterbreiten, wie Sie ihren Quellcode formatieren, wenn Sie in GNU Pascal programmieren.
Sie können eine C-Bibliothek oder eine C-Objektcode-Datei mit Ihrem Pascal-Programm oder ihrer Unit verlinken. Bitte beachten Sie die Hinweise im GPC-Handbuch bzgl. der Einzelheiten (sieheOther Languages).
Wir empfehlen die Verwendung von in C geschriebenen
"Wrapper-Funktionen" zum Zugriff auf C-Bibliotheken, also kleinen
Funktionen, die i.w. nichts anderes machen, als die Funktionen der
C-Bilbiothek aufzurufen. Der Grund dafür ist die Portabilität. Eines
Tages könnte es Änderungen an der zu linkenden Bibliothek geben, die
direkte external
-Deklarationen gefährden. Sie sollten dann
die Wrapper anpassen, so daß Pascal Programme mit jeder Version
dieser Bibliothek zusammenarbeiten.
Bei der Arbeit mit großen Paketen kann es passieren, daß die Kompatibilität zwischen Versionen einer Library und dem Programm nicht einfach aufrechterhalten werden kann. In diesem Fall kann man direkt zur Bibliothek linken, mit der man arbeiten möchte, und bindet ebenso eine ergänzende Datei hinzu, die ausschließlich der Versionskontrolle dient. Hier ein Beispiel:
#include <foo.h> #if FOO_MAJOR != 1 || FOO_MINOR != 2 #error The GPC interface for libfoo was only written for libfoo-1.2. #error Please get libfoo-1.2 or check for a version of the GPC interface #error matching your version of libfoo. #endif
Beachten Sie die Benutzung von !=
anstelle von <
oder
>
, um eine sehr präzise Versionskontrolle zu erhalten. Bitte
beachten Sie auch, daß dieses Verfahren nur dann anwendbar ist, wenn
es nur eine einzige Implementation dieser Bibliothek gibt, d.h. es
läßt sich mit einer Bibliothek wie GTK, aber nicht mit libc, libm,
curses etc. anwenden.
Ein automatischer Header-Übersetzer ist geplant. Dieses Werkzeug würde das Schreiben von Wrapperfunktionen überflüssig machen. Das Schreiben eines solchen Programmes ist eine schwierige Aufgabe, und niemand ist sich wirklich sicher, ob sie überhaupt durchführbar ist. Wann ein solches Programm verfügbar sein wird, ist ungewiß.
Sie können annehmen, daß der GNU C Compiler benutzt wird, um die Wrapper,
und, allgemein, jedes bißchen C-Code zu übersetzen, das Sie Ihrem
Programm hinzufügen.
Der Grund für diese Annahme ist, daß nur der GNU C Compiler
garantiert, daß alle Konventionen kompatibel zum GNU Pascal Compiler
sind, und das auf jeder Plattform! Der GNU C Compiler und der GNU
Pascal Compiler teilen sich dasselbe Backend. Außerdem wird der GNU
C Compiler immer zusammen mit dem GNU Pascal Compiler erzeugt. Damit
ist gcc
überall dort vorhanden, wo auch gpc
installiert ist.
GNU Pascal hat viele Möglichkeiten, die Standard Pascal nicht bietet. Ob diese Möglichkeiten in einem Programm genutzt werden sollen, ist eine zu häufig diskutierte Frage.
Auf der einen Seite kann das Benutzen dieser Möglichkeiten zu effizienteren oder übersichtlicheren Programmen führen. Auf der anderen Seite ist dadurch nur der GNU Pascal Compiler in der Lage, diesen Quelltext zu bearbeiten. Dadurch wird das Kompilieren des Programmes auf Systemen unmöglich, auf denen dieser Compiler nicht vorhanden ist.
Im allgemeinen ist es das beste, Kompatibilität zu anderen Compilern
oder zum Sprachstandard beizubehalten, wenn diese
Kompatibilität einfach zu erhalten ist. Leider ist dies jedoch
oftmals mit erheblichen Nachteilen verbunden. Als Beispiel dienen
viele eingefügte {$ifdef}
s, um alle nicht-Standard-Compiler
zu versorgen, was den Code schwerer zu lesen, schreiben, testen und
warten macht. Außerdem sind {$ifdef}
s selbst nicht
standardisiert. Sie gewinnen also nicht viel.
Daher schlagen wir vor, sich nicht zu sehr an Fragen der
Kompatibilität stören. Alles am GNU Pascal Compiler ist offen
(Compiler und Laufzeit-System). Das bedeutet, daß das gesamte
Interface bei Bedarf für andere Compiler verfügbar gemacht werden
kann. Dazu können sogar einfach die Quelltexte übernommen werden,
solange die Lizenzvereinbarung erhalten bleibt. Hier erfahren Sie
mehr über die GNU General Public License:
http://www.gnu.org/copyleft/gpl.html. Das ist sinnvoller als
eine Zerstückelung des Codes. Ein (begrenztes) Beispiel dieser
Strategie kann in der gpc-bp
-Unit (für Borland Pascal)
gefunden werden. Schauen Sie einfach in das Interface. Es ist
meistens einfach, diese Unit um zusätzliche Features zu erweitern.
Bitte benutzen Sie die folgenden Features nicht, speziell solche nicht, die lediglich aus Gründen der Rückwärtskompatibilität eingeführt wurden:
(* *)
für alte Terminals, wo es die
Zeichen {
und }
nicht gab.
#
-Direktiven und //
-Kommentare, wie in C/Delphi.
Wenn eine Datei auch in C genutzt werden muß, so darf sie die
#
-Direktiven, die C-Syntax in Conditionalen sowie
//
-Kommentare enthalten.
Gegenwärtig gibt es dazu folgende Beispiele (das kann sich in Zukunft
ändern): p/rts/constants.h
in den GNU Pascal Compiler Quellen
und der untere Teil von crt.inc
, welcher automatisch in
crt.h
kopiert wird.
^A
. Benutzen Sie bitte #1
oder Chr (1)
stattdessen.
CString
s (außer natürlich für C-Schnittstellen)
WriteStr
:
Str (Foo, s); s := 'Hallo ' + s;
FillChar
und Move
, außer für
Low-Level-Programmierung und wenn es sich auf Zeichen innerhalb
eines Strings bezieht. Das Benutzen von
FillChar (s, SizeOf (s), 0);
, um einen String zu leeren ist falsch in GNU Pascal und außerdem ineffizient, sogar in Borland Pascal. Bitte benutzen Sie folgendes:
s := '';
Dieses Beispiel ändert lediglich das Längenfeld des Strings
s
, und leert ihn schon dadurch.
GetMem
und FreeMem
, die
normalerweise ein Work-Around für fehlende Schemata in anderen
Compilern sind.
GPC
-Unit, um einen portablen Weg
einzuschlagen.)
{$ifdef}
(z.B. für den Prozessortyp) eingekapselt
werden. Unterstützen Sie in einem solchen Fall auch bitte
eine reine Pascal-Version dieser Routinen innerhalb des
{$else}
-Teiles. Testen Sie diese Routinen.
System
-Unit erfordert.
_
)
beginnen oder enden.
CRT
und Printer
hingegen dienen sowohl der Kompatibilität
zu Borland Pascal als auch dem allgemeinen Nutzen.
Die GNU Coding Standards haben interessante Anmerkungen zu diesem Thema. SieheUsing Extensions.
Dieses Kapitel der GNU Coding Standards beschreibt Konventionen zum Schreiben stabiler Programme. Außerdem gibt es Richtlinien zur Ausgabe von Fehlermeldungen, zum Kommandozeilen-Interface und dazu, wie sich Bibliotheken verhalten sollten. Bitte lesen Sie auch den entsprechenden Abschnitt der GNU Coding Standards. SieheProgram Behavior.
Einige Hinweise zur Pascal Programmierung:
Die in den GNU Coding Standards besprochene Auswahl wurde bereits im Run Time System getroffen, so daß Sie sich nicht mehr darum kümmern müssen.
Ein weiterer Unterschied zu den GNU Coding Standards ist das Verhalten bei Fehlerabfragen, die einen "unmöglichen" Zustand entdecken. Wir empfehlen, das Programm nicht einfach abzubrechen. Dies würde implizieren, daß der Anwender ein Programmierer ist, der den Fehler schon irgendwie findet. Diese Annahme ist nicht realistisch! Unser Vorschlag ist es deswegen, eine Fehlermeldung herauszugeben, die es dem Anwender ermöglicht, eine Fehlerbeschreibung an die Programmierer zu senden.
Die GNU Coding Standards schlagen außerdem vor, jeden
Funktionsaufruf auf Fehlerrückgaben zu überprüfen. Dieser
Vorschlag paßt durchaus zu C, jedoch nicht unbedingt zu Pascal.
In Pascal wird das Abfangen von Fehlern oftmals automatisch
durchgeführt, somit brauchen Sie sich in vielen Fällen nicht
darum zu kümmern. Viele I/O-Routinen geben Ihnen nicht einmal einen
Rückgabewert (beispielsweise Reset
). Diejenigen
Fehlerwerte, die zurückgegeben werden, sollten aber auch
überprüft werden.
Sie können die automatischen Fehlerabfragen ausschalten und sich
selber darum kümmern. Tatsächlich ist es so, daß manche Fehler das
Programm mit einer Nachricht abbrechen lassen. Speziell in Units
oder Modulen wollen Sie stattdessen vielleicht den Benutzern eine
Möglichkeit einräumen, die Ursache des Fehlers zu beheben. Um das zu
tun, benutzen Sie bitte den Compiler-Switch {$I-}
und
testen Sie den Wert der Funktion IOResult
(sieheIOResult) oder der globalen Fehlervariablen wie InOutRes
(sieheInOutRes). Beachten Sie bitte, daß I/O-Routinen
sofort zurückkehren, während InOutRes
gesetzt ist, so daß es
nicht notwendig ist, nach jeder Operation diesen Wert abzufragen.
Folgendes wird dadurch möglich:
{$local I-} Rewrite (f, 'bla'); WriteLn (f, 'foo'); WriteLn (f, 'bar'); WriteLn (f, 'baz'); Close (f); {$endlocal} if InOutRes <> 0 then begin WriteLn (StdErr, GetIOErrorMessage); ... end;
Es kann jedoch nützlich sein, nach Rewrite
und anderen
Aufrufe zum Öffnen auf Fehler zu testen, denn dort treten die
meisten Fehler auf, und ein Test macht andere, nachgestellte
Aufrufe oftmals unnötig.
Die GPC-Unit enthält eine Menge Routinen für den Umgang mit Temporärdateien, Konfigurationsdateien und vielen anderen dateinamenbezogenen Aufgaben. Der Vorteil beim Gebrauch dieser Routinen liegt darin, daß sie unter verschiedenen Betriebssystemen laufen (zum Beispiel Dos und Unix) und daß evtl. dateinamenbezogene Probleme an einer zentralen Stelle (dem Run Time System) behoben werden können. Das ist besser, als verschiedene Stellen im Code entsprechend anzupassen.
Soweit es die Bibliotheken betrifft, raten wir davon ab, jede einzelne
Routine in einer einzigen Datei unterzubringen. Wir hoffen, daß der GNU
Pascal Compiler das eines Tages auf der Ebene des Linkers selber macht.
Gegenwärtig, so glauben wir, ist Programmiererfreundlichkeit sinnvoller
als die Größe der ausführbaren Datei. Außerdem empfehlen wir, auf
Namens-Präfixe zu verzichten. In Zukunft werden Namenskonflikte durch
qualifizierte Bezeichner (UnitName.RoutinenName
) gelöst.
Bitte benutzen Sie bis dahin bei Namenskonflikten vorübergehend
Work-Arounds.
Dieses Kapitel gibt Ihnen Ratschläge, wie Sie Ihre Quelltexte gestalten
sollten. Diese Regeln gelten eigentlich nur für veröffentlichten
Code.
Wenn Sie als Beispiel Kommentare in der alten Form (* this one *)
schreiben möchten, so geht das natürlich vorübergehend, bei der
Veröffentlichung sollten Sie dann allerdings unsere diesbezüglichen
Ratschläge beherzigen. Da man aber niemals wissen kann, ob und wann man
den Code veröffentlicht, ist es vorzuziehen, sich von vornherein an
diese Ratschläge zu halten.
MemoryMap
benutzen
Pascal Quelldateien sollten die Endung .pas
haben.
Der Dateiname ohne diese Endung sollte der Name des Programmes,
der Unit oder des Modules sein, aber kleingeschrieben. Es sollte nur
eine einzige Unit, ein einziges Programm oder Modul pro Datei geben.
Zwar erlaubt der GNU Pascal Compiler mehrere Units etc. pro Datei,
doch wird diese Möglichkeit in Zukunft möglicherweise verworfen.
Der Code sollte mit der Option -Wall
, sowohl mit als auch
ohne -O2
kompilierbar sein und in keinem Fall irgendwelche
Warnungen ergeben. (Siehe: SieheCompiler-Direktiven, um einzelne
Warnungen gezielt abzuschalten, wenn es gar nicht anders geht.)
Bitte benutzen Sie nicht die automatische Result
-Variable in
Funktionen. Wenn Sie sie haben wollen, so sollten Sie diese auch
deklarieren:
function Foo (...) = Bar: Integer;
Benutzen Sie die Art der Deklaration mit =
, nicht die ohne
Gleichheitszeichen, es sei denn, Sie wollen PXSC-kompatibel sein.
Wenn eine Funktion einen Boolean
-Wert liefert, um den
Erfolg einer Operation anzuzeigen, so sollte True
den
Erfolg melden und False
das Fehlschlagen.
Beachten Sie, daß dieses Vorgehen anders ist als in C, wo
0
oftmals den Erfolg meldet.
Vermeiden Sie goto
und ähnliche Statements, wie Exit
,
Return
, Break
und Continue
. Vermeiden Sie
goto
um jeden Preis (außer möglicherweise ein
nicht-lokales goto
, um aus einer sehr tief
geschachtelten rekursiven Funktion im Falle eines Fehlers
herauszukommen). Vermeiden Sie die anderen Statements, wenn dies
mit vertretbarem Aufwand möglich ist. Wenn Sie aber dafür eine
weitere Boolean
-Variable einführen müssten, so darf dies als
Entschuldigung für das Benutzen dieser Statements gelten.
Beachten Sie, daß Code oftmals einfacher wird, wenn Sie auf
Break
verzichten und stattdessen eine bessere
Abbruchbedingung oder eine andere Sorte Schleife benutzen.
Niemals sollten Sie die for
-Zählvariable verändern oder dem
Wert der Variablen nach dem Durchlaufen dieser Schleife vertrauen.
(Das ist nicht nur eine Art, seinen Quelltext zu gestalten, sondern
mehr noch eine Definition von Pascal. Solche Dinge ergeben
undefinierte Ergebnisse.)
Vertrauen Sie niemals undefiniertem Verhalten. Als Beispiele dienen
globale Variablen, die zu Beginn des Programmes mit 0
initialisiert zu sein scheinen, angeforderter Speicher, der
initialisiert zu sein scheint, ein freigegebener Speicherbereich,
dessen Inhalt immer noch gültig zu sein scheint oder die oben
besprochenen for
-Zählvariablen. Nichts von all dem ist
garantiert und kann mit jeder Compilerversion oder Plattform
geändert werden. Undefiniert ist eben undefiniert. Und der
Eindruck, daß solche Dinge bei 42 anderen Compilern zu
funktionieren scheinen, ist dabei völlig belanglos!
Bei Vergleichen sollte die sich häufiger ändernde Variable auf der linken Seite stehen.
for i := 1 to 10 do if a[i] = Foo then for j := 1 to 10 do if b[j] = a[i] then ...
In diesem Beispiel ändert sich a[i]
häufiger als Foo
und b[j]
ändert sich häufiger als a[i]
(da j
sich häufiger als i
ändert).
Wir nehmen bei diesem Beispiel an, daß Foo
konstant ist. Wenn
Foo
ebenfalls von i
abhängt, so kann es angebracht
sein, Foo
auf die linke Seite zu stellen. Dies sollte dann
aber durch einen Kommentar erläutert werden.
Vermeiden Sie es, Code doppelt zu schreiben. Es ist zwar so einfach, den Code an eine andere Stelle zu kopieren, aber es wird ein Alptraum sein, diesen dann zu pflegen. Benutzen Sie stattdessen Routinen oder Subroutinen, Units oder Module. Planen Sie Ihren Code so, daß er erweitert werden kann. Packen Sie schlaue Tricks nicht an Stellen, die Sie später ändern wollen.
Umfassen Sie einzelne Statements nicht mit begin
und end
,
es sei denn, Sie wollen das "dangling else" - Problem vermeiden oder
diese Zeile ist der gesamte Rumpf einer Prozedur bzw. Funktion!
Siehe folgende Beispiele:
if foo then begin if bar then baz end { Vermeiden des ``dangling else'' - Problems. } else qux { Einzeiliges Statement. }
Schreiben Sie keine leere Unit-Initialisierung. Folgendes sollten Sie nicht tun:
... procedure Foo; begin ... end; begin end.
Stattdessen schreiben Sie einfach:
... procedure Foo; begin ... end; end.
Schreiben Sie keine ungenutzten Deklarationen, außer in Interfaces, wo diese vom importierenden Code genutzt werden können.
Denken Sie daran: Boolean
-Werte sind Boolean
-Werte!
Bitte schreiben Sie if Foo then
statt
if Foo = True then
, und if not Foo then
statt
if Foo = False then
.
Benutzen Sie auch until False
statt until 1 = 0
,
das sieht auch hübscher aus. Ein anderes Beispiel ist
Foo := Expression
statt if
Expression then Foo := True else Foo := False
.
Vermeiden Sie doppelte globale Bezeichner, überladen Sie eingebaute Bezeichner nicht, obwohl es der GNU Pascal Compiler verschmerzen würde. Benutzen Sie dieselben globalen Bezeichner auch nicht in verschiedenen Units oder Modulen. (Diese Technik wird Ihnen in einer zukünftigen Version des GNU Pascal Compilers zur Verfügung gestellt werden und heißt "qualifizierte Bezeichner", aber auch dann raten wir von der Verwendung ab.)
Wir raten davon ab, globale Variablen für nicht-globale Zwecke
einzusetzen, z.B. eine globale Variable Counter
als Zähler in
diversen lokalen Routinen zu verwenden. Deklarieren Sie stattdessen
eine lokale Variable in jeder Routine, die eine benötigt. Dies
ermöglicht i.a. auch eine bessere Optimierung des erzeugten Codes.
Wenn Sie eine unendliche Schleife schreiben (auch wenn diese
möglicherweise durch Break
verlassen wird), empfehlen wir die
Verwendung der repeat
und nicht der while
Schleife,
weil dadurch der Code weniger weit nach rechts eingerückt wird
(jedenfalls, sofern die Schleife mehr als eine Anweisung enthält).
Also:
repeat ... until False
Und nicht:
while True do begin ... end
Als erstes: Vermeiden Sie unnötige Leerzeichen am Ende einer Zeile.
Vergewissern Sie sich außerdem, daß Sie den Quelltext nicht mit
Tabulatorzeichen speichern. Verschiedene Editoren oder auch verschiedene
Konfigurationen eines Editors interpretieren diese Zeichen
mit einer unterschiedlichen Anzahl Leerzeichen.
Dies gefährdet Ihre mühsam erarbeitete Einrückung.
(Wenn Sie GNU Emacs benutzen, so ist die Funktion untabify
sehr nützlich; wenn sie VIM benutzen, die Umgebungsoption
expandtab
(:set et
); in PENG kann die Option
Expand tabs
verwendet werden.)
Bitte vermeiden Sie es, in Ihren Quelltext Steuerzeichen einzufügen
(außer NewLine, selbstverständlich). Bitte auch keine Form-Feeds
(#12
), wenngleich sie in den GNU Coding Standards zum
Separieren von logischen Bereichen empfohlen werden. Auch keine
SUB
-Zeichen (#26
), diese werden nämlich unter DOS
als Ende-der-Datei-Zeichen mißbraucht. Ältere DOS-Editoren
fügen dieses Zeichen an das Ende der Datei an, obwohl selbst das
FAT-Dateisystem selbst über das Ende der Datei Bescheid weiß.
Wir empfehlen eine maximale Länge von 68 Zeichen pro Zeile, so daß eine Quelldatei in TeX mit voreingestelltem Font auf A4 gedruckt werden kann. oder 78 Zeichen, geeignet für 80 Zeichen breite Bildschirme. Dies ist keine feste Regel, denn umgebrochene Zeilen verringern nur allzuoft die Lesbarkeit.
Benutzen Sie Leerzeilen zwischen Blöcken. Blöcke sind lange
Kommentare, type
, const
, var
, label
Abschnitte, Routinen-Rümpfe, Unit- oder
Modulinitialisierung/-finalisierung, interface
,
implementation
, module
, export
, uses
,
import
Zeilen, globale Compiler-Direktiven.
Soweit lange Kommentare eine folgende Deklaration betreffen,
bitten wir Sie, nur eine Zeile vor dem Kommentar abzusetzen,
nicht zwischen Kommentar und Deklaration.
Eine besondere Ausnahme ist zwischen den Blöcken innerhalb
derselben Routine. Benutzen Sie hier keine Leerzeilen:
procedure Short; var Foo: Integer; Bar: Char; begin ... end;
Aber benutzen Sie Leerzeilen, um Subroutinen abzusetzen:
procedure Long; const ... var Variablen, die von Sub genutzt werden können ... procedure Sub; var ... begin ... end; var Variablen, die nicht von Sub genutzt werden können ... begin ... end;
Benutzen Sie bitte auch keine Leerzeile nach der Deklaration des Namens der Hauptroutine, es sei denn, eine Subroutine folgt sofort. Andernfalls würde die Deklaration aussehen wie eine Forward-Deklaration.
Beachten Sie bitte, daß wir im obigen Beispiel die lokalen Variablen in Abschnitte vor und nach der Subroutine aufgeteilt haben. Dies ist nicht zwingend.
Alles, was wir über Subroutinen gesagt haben, gilt selbstverständlich auch für Sub-Subroutinen beliebiger Verschachtelungstiefe.
Eine Leerzeile sollte dann zwischen Deklarationen desselben Types stehen, wenn es Sinn macht, um diese logisch zu separieren. Falls vor der Deklaration ein Kommentar steht, so soll die Leerzeile vor dem Kommentar stehen. Anderenfalls soll die Leerzeile vor der Deklaration stehen.
Leerzeilen können in langen Kommentaren Absätze teilen.
Keine Leerzeile am Anfang oder am Ende einer Datei. Lediglich ein
einzelnes Zeilenendzeichen nach dem letzten end.
. Niemals
sollten Sie mehrere Leerzeilen hintereinander schreiben.
Die Kommentare sollten in geschweiften Klammern stehen, wie hier:
{ So ist es gut! }
Altmodische Kommentare zwischen Klammern und Sternchen sollten nicht mehr benutzt werden:
(* Ein häßlicher Kommentar. So etwas braucht man nicht mehr! *)
Auch sollten keine Kommentare mehr geschrieben werden, die mit doppelten Schrägzeichen eingeleitet werden und bis zum Ende der Zeile gehen:
// Machen Sie es nicht.
Obwohl ISO Pascal gemischte Kommentare ausdrücklich erlaubt und
der GNU Pascal Compiler sich mit der Option
{$mixed-comments}
auch nicht darüber beschweren würde,
sollten solche Kommentare nicht benutzt werden:
(* Dieses }
{ und jenes. *)
Vermeiden Sie verschachtelte Kommentare wie
{ { diesen hier } }
. Das ist nur dann in Ordnung,
wenn Sie TeX in einem Kommentar setzen wollen oder ähnlich
exotische Dinge. Was auch immer Sie für Gründe haben mögen, müssen
Sie diese Option dann zunächst mit der Direktive
{$nested-comments}
anschalten. Benutzen Sie bitte nicht die
Kommandozeilenoption --nested-comments
. Packen Sie all
diese Optionen in den Quellcode, damit niemand, der den Quellcode
übersetzen möchte, erst die benötigten Optionen erraten muß, und
auch, weil Kommandozeilenoptionen z.B. bein Kompilieren eines
Projektes mit mehreren Units/Modules alle Dateien betreffen
würden.
Bitte schreiben Sie Kommentare in Englisch! Englisch ist diejenige Sprache, die die meisten Programmierer in allen Ländern lesen können. Wenn Sie sich im Englischen nicht fit genug fühlen, dann bitten Sie jemanden, Ihnen dabei zu helfen. Schreiben Sie so gut, wie Sie können.
Sie sollten sich "French Spacing" angewöhnen, d.h. nur ein
Leerzeichen am Ende eines Satzes. Dabei können Sie in GNU Emacs
M-a
und M-e
nicht benutzen. Wir hoffen, daß Sie das
verschmerzen können. Bitte lassen Sie nur ein Leerzeichen nach der
öffnenden und der schließenden geschweiften Klammer des Kommentares
Platz.
Wenn ein Kommentar sich nur auf eine Zeile Code bezieht, so sollte der Kommentar in derselben Zeile hinter dem Code stehen, soweit das möglich ist. Bitte lassen Sie zwei Leerzeichen Platz. Dies ist ebenfalls für den Interface-Bereich einer Unit und bei globalen Variablen angemessen. Oftmals benötigt man diese Sorte Kommentare neben Record-Feldern. Andernfalls sollten Kommentare in eigenen Zeilen stehen:
{ foo bar baz }
Oder etwas länger:
{ foo bar baz }
Mit Absätzen:
{ foo bar baz qux }
Die Kommentare sollten gewöhnlich vor den Code plaziert werden, auf den sie sich beziehen. Sie erhalten dieselbe Einrückung:
{ Meine Typen. } type ... type { Mein erster Typ. } ... begin { Mein erstes Statement. } Bla; { Anfang der Schleife. } repeat { Schleifenkörper. } ... { Beende das hier mal irgendwann. } until Sometime end;
Beachten Sie bitte besonders den Kommentar vor until
.
Kommentare, die eine globale Deklarationen beschreiben, sollten in eigenen Zeilen direkt vor der Deklaration stehen:
{ Das ist Foo. Foo kann so Manches. } procedure Foo;
Schreiben Sie keine "trivialen" Kommentare wie den obigen. Sie sollten Kommentare dadurch vermeiden, daß Sie durchdachten Code schreiben. Linus Torvalds macht das in seinem Kernel Coding Style deutlich:
Comments are good, but there is also a danger of over-commenting. Never try to explain how your code works in a comment: it's much better to write the code so that the working is obvious, and it's a waste of time to explain badly written code. Generally, you want your comments to tell what your code does, not how.
Übersetzung:
Kommentare sind grundsätzlich sinnvoll, aber es besteht die Gefahr der "Überkommentierung". Niemals sollten Sie im Kommentar erklären, wie der Code arbeitet: Es ist viel besser, offensichtlichen Code zu schreiben, so daß seine Arbeitsweise sich ergibt. Es ist verschwendete Zeit, schlecht geschriebenen Code zu kommentieren. Allgemein sollte man mitteilen, was der Code macht, nicht wie er es macht.
(Beachten Sie, daß wir in anderen Bereichen ziemlich stark von seinem Coding Style abweichen.)
"Trickreicher" Code ist es wert, kommentiert zu werden. Wir definieren den Code als "trickreich", der nicht naheliegende Dinge tut, auf nicht sofort einleuchtenden Annahmen basiert, unerwartete Implikationen beinhaltet, bei dessen Änderung etwas Spezielles beachtet werden muss, der sich nicht so verhält, wie es auf den ersten Eindruck scheint, der Seiteneffekte enthält oder es erfordert, daß andere Teile des Codes an anderer Stelle gleichzeitig mit ihm geändert werden. Trickreicher Code sollte grundsätzlich nur in bescheidenem Maße benutzt werden.
In dem Fall, daß sich ein Kommentar auf eine andere Stelle des Codes bezieht, wobei es egal ist, ob die Referenz in derselben oder einer anderen Datei liegt, beziehen Sie sich bitte auf den Namen der Routine oder einen Kontext. Bitte geben Sie den Bezug nicht in Form von Zeilennummern an (diese ändern sich zu häufig). Lassen Sie in den Kommentaren außerdem beide Stellen aufeinander verweisen, wo es Sinn macht. Diese Art der "Kreuzverweise" erwies sich schon oft als sinnvoll.
Code, der auskommentiert werden soll, sollte mit Hilfe von
{$if False} ... {$endif}
vom Kompilieren
ausgeschlossen werden. Bitte benutzen Sie dazu keine Kommentare.
Um logische Abschnitte innerhalb größerer Module oder Units zu markieren, sollten Sie Kommentare benutzen. Wir schlagen Ihnen folgende leicht zu suchende festgelegte Form vor:
{@section Name des Kapitels} {@subsection Name des Abschnitts}
Beachten Sie, daß in diesem Fall ausnahmsweise keine Leerzeichen neben den geschweiften Klammern eingefügt werden.
Ein Modul, eine Unit oder Library sollte im Interface-Bereich Kommentare haben, so daß dieses Interface zu einer verläßlichen Dokumentationsquelle wird. Es ist freigestellt, solche Kommentare für Routinen zu benutzen, die nur im Implementationsbereich oder in Programmen (im Gegensatz zu Modulen etc.) deklariert werden. Mehrere Konstanten-Deklarationen können sich einen Kommentar teilen.
Es wird ein Utility namens pas2texi
geschrieben, welches
Texinfo-Dateien aus Pascal-Kommentaren erzeugt. Dieses Utility
wird verschiedene Textauszeichnungsmöglichkeiten innerhalb von
Kommentaren erlauben. Diese Textauszeichnungen werden innerhalb
der Dokumentation von pas2texi
oder in späteren
Versionen dieses Dokumentes erläutert werden.
"Fixme"-Kommentare dienen dazu, aufzuzeigen, daß an dieser Stelle
Code etwas zu verändern ist. Den Kommentaren werden mindestens
zwei @
vorangestellt. Fügen Sie soviele @
ein,
wie es der Dringlichkeit der Korrektur entspricht.
Die Kommentare sollten das Wesentliche des Problems enthalten, vor
allem wenn die Wurzel des Übels woanderes liegt. Beispielsweise
erklärt der Kommentar { @@fjf226 }
den folgenden Code als
Work-Around für ein Problem des GNU Pascal Compilers, welches von
einem Test-Programm namens fjf226.pas
verdeutlicht wird.
(Diese Datei können Sie tatsächlich innerhalb des Quellpaketes des
GNU Pascal Compilers finden.)
"Fixme"-Kommentare sollten nicht mit anderen Kommentaren vermischt
werden. Wenn beide Kommentare gebraucht werden, so sollten sie
getrennt, wenn auch direkt hintereinander stehen. Da sie
vorübergehender Natur sind, dürfen solche Kommentare überall stehen,
sogar innerhalb von Anweisungen. Normalerweise stehen sie im Rumpf
einer Routine, solange sie nicht das Interface eines Modules bzw.
einer Unit beeinflussen. Interfaces, die voraussichtlich in der
Zukunft geändert werden, sollten @@
-Kommentare direkt vor
ihren beschreibenden Kommentaren aufweisen.
Jede Datei sollte mit einem Kommentar beginnen, welcher der Reihe nach folgendes beinhaltet:
Allgemein sollte man diese Deklarations-Reihenfolge einhalten:
const
-Deklarationen
type
-Deklarationen
var
-Deklarationen
label
-Deklarationen
Sie können von dieser Reihenfolge abweichen, wenn es notwendig erscheint oder den Code lesbarer gestaltet. Im folgenden sehen Sie ein Beispiel, bei dem diese Reihenfolge nicht eingehalten werden kann:
type TIrgendwas = record Dieses, Jenes: Integer end; const IrgendEineKonstante = SizeOf (TIrgendwas);
Die obigen Regeln gelten selbstverständlich auch für Deklarationsbereiche innerhalb von Routinen.
Wenn Sie mehrere mehr oder weniger unabhängige Bereiche in einer
großen Unit oder einem großen Modul haben, so sollten sie obige
Reihenfolge auf jeden Teilbereich des Modules anwenden. Es sollten
z.B. nicht alle Konstanten aller Bereiche in eine einzelne
const
-Deklaration geschrieben werden, das macht den Code
eher unleserlich.
Variablen, die nur im Hauptprogramm genutzt werden, müssen in
Pascal global deklariert werden, wobei GNU Pascal eine Erweiterung
kennt, um diese Beschränkung zu umgehen und Variablen im
Anweisungsteil zu deklarieren (siehevar). In einem
solchen Fall sollten diese Variablen direkt vor dem begin
des
Hauptprogrammes geschrieben werden, nach allen Routinen etc. Das
gilt besonders dann, wenn das Programm groß ist und viele Variablen
deklariert werden. Dadurch wird der Variablen-Deklarations-Bereich
leichter einsehbar und ist einfacher mit den entsprechenden
Code-Bereichen änderbar. Außerdem vermeidet man so, daß
versehentlich Routinen diese Variablen nutzen.
Wenn Sie einen Typ und seinen zugehörigen Zeiger gleich mit
deklarieren wollen, so deklarieren Sie bitte zuerst den Zeiger.
Dies ist übersichtlicher, besonders wenn der zugehörige Typ eine
größere Struktur (record
oder object
) ist. Auch wird
es damit möglich, rekursive Strukturen aufzubauen (Typdefinitionen,
die Zeiger auf denselben Typ beinhalten). Bitte stellen Sie den
Typen ein T
, und den zugehörigen Zeigern ein P
voran.
Folgendes Beispiel veranschaulicht das:
type PMyInt = ^TMyInt; TMyInt = Integer; PStrList = ^TStrList; TStrList = record Next: PStrList; s: TString end;
Bitte beachten Sie in dem Beispiel, daß das Next
-Feld als
erstes aufgeführt ist. Wir schlagen vor, daß Sie es bei rekursiven
Typen immer so machen, es ermöglicht einige generische
Listenroutinen und ist etwas effizienter, da beim Durchlaufen der
Liste keine Offsets auftauchen.
Nicht verpflichtend ist es, alle Zeigertypen innerhalb einer
type
-Deklaration zuerst aufzuführen, aber wir raten Ihnen
dazu. Hier ist ein Beispiel dazu:
type { Zeigertypen } PFoo = ^TFoo; PBar = ^TBar; PBaz = ^TBaz; { Einige maßgefertigte Integertypen } TFoo = Integer (16); TBar = Cardinal (16); TBaz = Cardinal (32);
Innerhalb von Objekt-Typen gibt es drei Deklarationsbereiche. Drei
reservierte Wörter leiten diese Bereiche ein: public
,
protected
, private
. Innerhalb eines jeden dieser
Bereiche sollte man folgende Reihenfolge einhalten:
Im Implementationsbereich sollte man dieselbe Reihenfolge einhalten wie bei der Deklaration. Dies gilt selbstverständlich ebenso für Units und Module.
Benutzen Sie nie ein ;
am Ende eines Blockes, also vor
end
, until
, usw, außer im Fall von case
.
Der letzte Zweig vor else
(oder der letzte Zweig, wenn es
keinen else
-Zweig gibt) sollte ein abschließendes
;
haben, um Probleme wie diese zu vermeiden:
case ... Foo: if Bar then { später eingefügt } begin ... end { wenn es hier kein Semikolon gibt ... } else { ... dann wird dieseselse
plötzlich demthen
zugerechnet } ...
(Dasselbe gilt auch, wenn es if
schon gibt und das
else
des case
später eingefügt wird.)
In Objekten mag es merkwürdig aussehen, das ;
nach dem
letzten Eintrag (meistens eine Objekt-Methode) wegzulassen.
Deswegen erlauben wir es hier und zur Erhaltung der Konsistenz auch
in Records.
Reservierte Wörter sollten allesamt kleingeschrieben werden,
einschließlich aller Direktiven und Wörter, die nur in manchen
Kontexten reserviert sind (wie protected
). Wenn Sie
Direktiven außerhalb ihres Kontextes als Bezeichner benutzen (was
leicht zu Problemen führen kann), so schreiben Sie diese bitte wie
Bezeichner.
c
und c_language
sind gegenwärtig Direktiven, wobei
sie in naher Zukunft verschwinden. In der Zwischenzeit wird C
auch akzeptiert.
Als besondere Ausnahme darf man File
großschreiben, wenn
dieses als eigener Typ gebraucht wird. Anders ist es
selbstverständlich bei file of Char
. Im Fall von
procedure
als Typ (Borland Pascal) kann man diese Regel
nicht anwenden, denn File
kann ein Typ an sich sein, während
procedure
ein Typ-Konstruktor ist. Beispiel:
procedure Foo (var a: File); { Das geht } procedure Foo (var a: procedure); { Das geht nicht! }
Der nächste Punkt betrifft die Großschreibung von Bezeichnern. Es
gibt hierbei keinen Unterschied zwischen eingebauten und
selbstdefinierten Bezeichnern. Grundsätzlich sollte nur der erste
Buchstabe großgeschrieben werden, außer wenn es sich um
zusammengesetzte Wörter oder Akronyme handelt, dann sollte jeder
Anfangsbuchstabe eines jeden Teilwortes großgeschrieben werden.
Unterstriche sollten vermieden werden. Akronyme, die zu einem Teil
der natürlichen Sprache geworden sind, sollten so geschrieben
werden wie in der Sprache. Beispielsweise Dos
oder DOS
aber immer GPC
und niemals Gpc
!
Hier einige Beispiele von Bezeichnern:
Copy
, Reset
, SubStr
, BlockRead
,
IOResult
, WriteLn
, Sqr
, SqRt
,
EOF
, EOLn
.
Anders als bei C-Makros gelten diese Regeln auch für Konstanten.
Beachten Sie, daß asmname
eine Direktive ist, daher sollte
sie nicht als AsmName
geschrieben werden. Sehr kurze
Bezeichner dürfen kleingschrieben werden, z.B.: i
,
s1
oder xx
. Solche kurzen Bezeichnernamen sollten
nur in lokalen Blöcken auftauchen. Dazu zählen auch Parameter
globaler Routinen, denn der Gültigkeitsbereich solcher Parameter ist
lokal. Der Gebrauch dieser Bezeichner sollte nicht in einem globalen
Kontext erfolgen, besonders nicht in Units oder Modulen. Der Autor
kann ja nie wissen, in welchen Kontexten die Units/Module benutzt
werden.
Bitte bleiben Sie einheitlich, was die Groß- und Kleinschreibung ihrer Bezeichner anbelangt. Wenngleich Pascal Sie auch nicht schlägt, wenn Sie mal die Großschreibung einer Variablen innerhalb eines Blockes ändern: Bitte halten Sie sich an eine Form.
Für Bezeichner für die Werte von Aufzählungstypen und für Gruppen
von Konstanten, d.h. an Stellen, wo viele Bezeichner auf einmal
eingeführt werden, kann es nützlich sein, ein zweibuchstabiges
kleingeschriebenes Präfix zu verwenden, dem im Gegensatz zu obigen
Regeln ein Unterstrich (_
) folgt:
type TFooBar = (fb_Foo, fb_Bar, fb_Baz, fb_Qux);
{ Meine Foos } const mf_Foo = 1; mf_Bar = 3; mf_Baz = 42;
In objektorientiertem Code, meistens in Konstruktoren, hat man den
Fall, daß der Parameter einer Funktion zu einem Feldnamen passen
soll, den dieser Parameter initialisiert. Da beide Namen nicht
übereinstimmen dürfen, sollte das Feld den "natürlichen" Namen
haben, da es an mehreren Stellen verwendet wird, und der
Parametername verändert werden. Wir haben bislang keine einheitliche
Regel für den Namen des Parameters in einem solchen Fall gefunden.
Manche Programmierer verwenden a
als Präfix. Wenn Sie eine
gute Idee haben, so lassen Sie es uns wissen.
Makros sollten nicht genutzt werden! Sie sind die Reinkarnation des Bösen! Wenn Sie es doch tun, so müssen Sie zur Strafe alle Buchstaben groß schreiben und einzelne Teilwörter mit Unterstrichen trennen. Da Makros außerhalb der Pascal-Geltungsbereiche stehen, macht es durchaus Sinn, sie anders zu schreiben als den übrigen Pascal-Code. Das gilt ebenso für Bedingungen im Rahmen der bedingten Kompilierung (Conditionale).
Anmerkung des Übersetzers:
Um der Doppeldeutigkeit von "condition", wie sie in einer
if
-Anweisung vorkommt, und wie sie in der bedingten
Ausführung von Code vorkommt, Herr zu werden, habe ich mich
entschieden, in diesem Abschnitt durchgängig "Conditional" im
letztgenannten Kontext zu verwenden. Der Leser möge mir verzeihen.
Grundsätzlich sollten Sie so wenig Compiler-Direktiven wie nur irgend möglich verwenden, weil sie den Code schwerer lesbar und wartbar machen. So sollten Direktiven aussehen:
{$Ihre-Compiler-Direktive}
und niemals so: (sieheKommentare)
(*$mach-es-nicht-Direktive*)
und auch nicht so, weil dies im Gegensatz zu Pascal, von Zeilenumbrüchen anhängt:
#so-auch-nicht-Direktive
Dasselbe bei Makro-Definitionen:
{$define ...}
Dies spart außerdem den Backslash vor dem Zeilenumbruch, im
Gegensatz zu #define
. Aber Sie wollen ohnehin keine Makros
benutzen, ODER? (sieheGroßschreibung)
Fügen Sie niemals ein Leerzeichen vor der schließenden Klammer ein, denn es darf auch keines nach der öffnenden Klammer kommen. Wenn Sie mehrere Direktiven zusammenfügen, so fügen Sie zwischen zweien kein Leerzeichen ein, ein einfaches Komma genügt.
Es sollten keine Kommentare innerhalb der Direktiven eingefügt werden. Schreiben Sie Kommentare stattdessen separat:
{$X+} { Wir brauchen erweiterte Syntax }
Borland Pascal erlaubt, Kommentare mit Direktiven zu vermischen. Das ist ein Mißbrauch eines solchen Kommentares!
Kurze Formen der Direktiven sind in Ordnung, aber man sollte den langen Formen den Vorzug geben. Die kurzen Formen müssen großgeschrieben werden, während die langen Formen kleingeschrieben werden sollten (ausgenommen Argumente, bei denen es auf die richtige Schreibweise ankommt, wie Fehlermeldungen, Warnungen, Dateinamen - bei letzteren ist auch unter DOS die korrekte Groß- und Kleinschreibung zu verwenden, damit der Code portabel bleibt).
Sie können verschiedene Direktiven kombinieren, dabei auch kurze und lange Formen mischen, wie im folgenden Beispiel:
{$gnu-pascal,I-,X+}
Jede Unit und jedes Modul sollte {$gnu-pascal,I-}
oder
{$gnu-pascal,I+}
nahe am Anfang stehen haben, und zwar
nach dem einleitenden Kommentar mit der Beschreibung und der
Lizenz. {$gnu-pascal}
bewirkt, daß die Unit ohne
Dialekt-Optionen kompiliert wird, selbst wenn das aufrufende
Programm Dialekt-Optionen nutzt. {$I-}
und {$I+}
zeigen dem Nutzer der Unit, daß Ein-/Ausgabe-Fehler von den Routinen
abgefangen werden oder Laufzeitfehler zu erwarten sind. Der erste
Fall ist dem anderen in den meisten Fällen vorzuziehen (Routinen,
die Ein-/Ausgabe-Fehler hervorrufen können, sollten als
iocritical
deklariert werden, sobald dies verfügbar wird).
Für Programme ist dies optional.
{$W-}
(keine Warnungen) sollte nur lokal genutzt werden
und ein "FIXME"-Kommentar (sieheKommentare) haben, denn es
zeigt ein Problem mit dem Code oder dem Compiler. Benutzen Sie
spezielle Direktiven, um Warnungen über Compiler-Probleme bei Bedarf
auszuschalten. Beispielsweise, {$W no-object-directives}
oder {$W no-field-name-problem}
. Die Abschaltung dieser
speziellen Warnungen kann global erfolgen.
Bitte schalten Sie keine Warnungen ab, wenn Sie nur zu faul sind, Code zu schreiben, der keine Warnungen produziert.
Jeder Compiler-Schalter, der nicht global gesetzt wird
(beispielsweise zusammen mit {$gnu-pascal}
, siehe oben),
sollte mit {$local ...}
kombiniert werden. Also nicht
so:
{$I-} Reset (f); {$I+}
Sondern so:
{$local I-} Reset (f); {$endlocal}
Das erste Beispiel ist falsch, wenn vorher schon {$I-}
geschrieben wurde. Selbst wenn ein Programmierer weiß, welches
die aktuellen globalen Einstellungen sind, so können sich diese
eines Tages ändern. Auch dadurch, daß Teile des Codes an
eine andere Stelle kopiert werden.
Das untere der beiden Beispiele ist daher die sichere Form.
Um zu verdeutlichen, was wir meinen, hier noch ein Beispiel:
{$local W-} Foo; {$endlocal} { @ GPC gibt hier eine überflüssige Warnung }
Nochmal: Vermeiden Sie es, lokale Direktiven zu gebrauchen.
{$I-}
kann manchmal nütztlich sein. {$X+}
sollte
nur dann gebraucht werden, wenn es wirklich notwendig ist,
und dann auch bitte so lokal wie nur irgend möglich. Vermeiden Sie
Zeiger-Arithmetik!
Benutzen Sie weder {$X+}
noch
{$ignore-function-results}
, um Funktionswerte zu
überprüfen. Es ist schlicht zu einfach, ein beachtenswertes
Funktionsergebnis zu ignorieren. Manchmal, besonders dann, wenn man
eine C-Bibliothek linkt, hat man es mit Funktionsergebnissen zu tun,
die überflüssig erscheinen, weshalb man sie nicht überprüfen möchte.
Solche Funktionen lassen sich bald mit ignorable
deklarieren,
sobald dieses Feature verfügbar wird, so daß das Funktionsergebnis
ignoriert werden kann. Im Moment sollten Sie noch Dummy-Variablen
benutzen.
Benutzen Sie auch dann Dummy-Variablen, wenn Sie
Funktionsergebnisse von Funktionen, deren Ergebnisse
gemeinhin nicht ignoriert werden sollen, ignorieren wollen.
Überprüfen Sie sehr sorgfältig, ob ein solches Ergebnis wirklich
sicher ignoriert werden kann! Wenn jedoch ein unerwarteter Wert
Sie in eine "unmögliche" Situation bringen würde, so ist es
normalerweise besser, das Funktionsergebnis zu überprüfen
und im unerwarteten Fall eine Warnung auszudrucken oder gar
abzubrechen. Tun Sie das wenigstens dann, wenn DEBUG
gesetzt ist. (sieheCompiler-Direktiven).
Linker-Direktiven, d.h. {$L}
fürBibliotheken und
C-Code-Dateien (oder Dateien anderer Sprachen) sollten nahe am
Anfang des Programmes und nahe am Implementationsanfang von Units
oder Modulen stehen. Mehrere Bibliotheken und C-Quelldateien können
in eine Direktive geschrieben werden, wenn sie logisch
zusammengehören (bspw. eine Bibliothek und ihre zugehörige
Wrapper-Funktion), nicht aber dann, wenn sie nicht zusammengehören.
Diese Direktiven sollten nicht mit anderen Direktiven gemischt
werden (was auch nicht geht, wenn L
zuerst angeführt wird;
anders herum geht es, ist aber nicht ratsam). Die externen
Deklarationen der Bibliothek oder C-Routinen sollten sofort der
zugehörigen Direktive folgen (außer für Units oder Module bei
denjenigen Deklarationen, die in das Interface gehören). Das
Benutzen von {$L}
innerhalb eines Programmes ist
normalerweise keine gute Idee. Da lohnt es sich schon, eine Unit zu
schreiben, welche abstrahiert und wiederverwertet werden kann.
Bedingtes Kompilieren kann manchmal nützlich sein, aber es sollten
sowenige {$ifdef}
s wie nur irgend möglich geschrieben
werden, denn sie vermindern die Lesbarkeit des Codes sehr stark.
Wo Conditionale eingesetzt werden, um verschiedene Systeme zu
unterscheiden, sollten die Fähigkeiten des Systems (bspw.
__BYTES_LITTLE_ENDIAN__
) oder Gruppen von Systemen
(bspw. OS_DOS
) überprüft werden, nicht einzelne Systeme.
Dieses Vorgehen funktioniert dann oftmals auch später noch auf
Systemen, von denen man noch nichts weiß oder die noch nicht
existieren.
Wann immer dies möglich ist, sollte vordefinierten Konstanten der
Vorzug gegenüber define
s gegeben werden (bspw.
BytesBigEndian
, OSDosFlag
). Dies ist im Anweisungsteil
möglich (der "immer false" - Zweig wird schlicht wegoptimiert,
trotzdem wird seine Syntax überprüft). Bei Typen-Deklarationen ist
es normalerweise nicht möglich. Hier muß man define
s
einsetzen. Folgendes ist ein Beispiel aus der CRT-Unit:
TWindowXY = packed record {$ifdef __BYTES_BIG_ENDIAN__} Fill: Integer (BitSizeOf (Word) - 16); Y, X: Word (8) {$else} X, Y: Word (8); Fill: Integer (BitSizeOf (Word) - 16) {$endif} end;
Das DEBUG
-Flag sollte eine Unterstützung beim Debuggen des
Codes sein, also Code, der die Funktionalität beim Debuggen nicht
verändert. Nur dafür sollte er eingesetzt werden. Programme müssen
mit und ohne DEBUG
lauffähig sein. Es kann sein, daß der
Code mit DEBUG
langsamer läuft und eine Vielzahl von
Mitteilungen produziert. Diese Mitteilungen sollten klar als
Debug-Mitteilungen erkennbar sein, bspw. dadurch, daß der Ausgabe
ein DEBUG:
vorangestellt wird. Solcher Code darf auch
einfach abbrechen, wenn fehlerhafte oder merkwürdige Zustände
eintreten.
Conditionale können ebenfalls herangezogen werden, um verschiedene
Versionen ein und desselben Codes anzufertigen. So ist es z.B.
innerhalb eines Mathematik-Programmes möglich, eine eigene
Version mit GMP-Zahlen (GMP ist eine Bibliothek zur
Bearbeitung beliebig großer Zahlen) zu erzeugen und eine
ohne, je nachdem, welches Conditional gesetzt ist. In diesem
Fall sollten die Namen und Bedeutungen aller Conditionale in einem
weit oben im Quelltext stehenden Kommentar erklärt werden. Sehen Sie
sich bitte __BP_TYPE_SIZES__
, __BP_RANDOM__
und
__BP_PARAMSTR_0__
als Beispiele aus der Unit System
an. Der Code sollte mit jeder Kombination dieser Conditionale
kompilierbar sein, was bedeutet, eine exponentielle Menge an
Kombinationen zu testen. Noch ein guter Grund, Conditionale so
selten wie möglich zu benutzen oder gar zu vermeiden.
Eine andere denkbare Benutzung von Conditionalen besteht darin, mit ihrer Hilfe verschiedene Implementationen desselben Codes anzufertigen. Sie sollten diese Strategie nur dann anwenden, wenn alle Implementationen unterstützt werden oder es geplant ist, sie zu unterstützen. Andernfalls sollte die alte Implementation besser ins Museum wandern. Halten Sie den Code in einem solchen Fall besser "sauber". Die Hinweise bzgl. des Testens gelten auch hier.
Wenn Sie es mit komplizierten Conditionalen zu tun haben, so folgen Sie bitte der Pascal-Syntax. Formatieren Sie den Code nach den Regeln von Pascal, nicht nach denen von C. Hier ein dummes Beispiel:
{$if defined (Foo) or False}
Im Gegensatz zu (bitte nicht nachmachen!):
{$if defined (Foo) || 0}
Oder noch schlimmer:
#if defined (Foo) || 0
Eine spezielle Conditionale kann genutzt werden, um Code kurzfristig auszukommentieren. Hier ist die zugehörige Syntax:
{$if False} ... {$endif}
Ein Standard-Conditional sollte in Programmen, Units oder Modulen genutzt werden, wenn Sie sicherstellen wollen, daß die richtige Version des GNU Pascal Compilers verwendet wird. Folgen Sie diesem Beispiel:
{$if __GPC_RELEASE__ < 20011123} {$error This unit requires GPC release 20011123 or newer.} {$endif}
Im allgemeinen sollten nie mehrere Leerzeichen aufeinander folgen, außer für Einrückungen und in speziellen Fällen, die im folgenden Beschrieben werden.
Ein einzelner Blank soll vor und nach Operatoren, Zuweisungen
(:=
) und ..
stehen. In Write
, WriteLn
und WriteStr
sollte ein Blank um das :
angebracht
werden. Ein einzelner Blank soll nach Kommata und anderen :
stehen. Folgendes Beispiel macht es deutlicher:
var Foo: Integer; ... begin Foo := 42; WriteLn (Foo + 3 : 5, ' bar') end;
Kein Leerzeichen sollte hingegen nach dem unären Minuszeichen
-
stehen. Dieses sind die korrekten Formen: x - 1
,
-x
und -1
.
Ein Leerzeichen sollte vor und eines nach den Klammerzeichen
((
) und ()
) stehen, solange diese nicht neben anderen
Klammern, eckigen Klammern, dem Pointer-Symbol (^
), einem
Semikolon oder einem Komma auftreten. Mit anderen Worten: Ein
Leerzeichen sollte zwischen Bezeichnern/Schlüsselwörtern und
der öffnenden Klammern stehen. Beispiel:
Foo (Bar^(Baz[Qux * (i + 2)]), Fred (i) + 3);
Für Arrayindizierung wird kein Leerzeichen verwendet (schreiben Sie
nicht Foo [42]
, sondern Foo[42]
), jedoch schon bei
Arraydeklarationen:
Foo: array [1 .. 42] of Integer;
Bei Mengen-Konstruktoren sollte ggf. ein Blank vor der öffnenden Klammer stehen - diese eckigen Klammern sollten wie normale Klammern behandelt werden:
x := [0, 2 .. n];
Aber:
Foo ([1, 2, 3]);
Kein Leerzeichen bei .
und ^
:
Rec.List^.Next^.Field := Foo
Wie wir schon ausführten, soll je ein Blank nach den öffnenden und vor den schließenden geschweiften Klammern in Kommentaren stehen. Dies gilt jedoch nicht für Compiler-Direktiven. Außerdem sollten vor Kommentaren, die einer Code-Zeile folgen, zwei Leerzeichen stehen:
Inc (x); { Increment x. }
Wenn Sie mögen, so fügen Sie beliebig viele Leerzeichen ein, um "tabellarisch" aussehenden Quellcode zu erzeugen. Unserer Meinung nach erhöht dies die Lesbarkeit des Codes ungemein, weil der menschliche Geist auf solche Strukturen trainiert ist, Unterschiede in Zeilen besser gesehen werden können, und man bei Änderungen im Quellcode verwandte Stellen nicht so leicht übersieht. Eine Anwendung dieser Prinzipien sollte in Interface-Deklarationen zu finden sein (es ist nicht leicht anwendbar, wenn jede Routine durch Kommentare getrennt wird, daher ist in einem solchen Fall möglicherweise ein gemeinsamer Kommentar empfehlenswert):
function Pos (const SubString, s: String): Integer; function LastPos (const SubString, s: String): Integer; function PosCase (const SubString, s: String): Integer; function LastPosCase (const SubString, s: String): Integer; function CharPos (const Chars: CharSet; const s: String): Integer; function LastCharPos (const Chars: CharSet; const s: String): Integer; function PosFrom (const SubString, s: String; From: Integer): Integer; function LastPosTill (const SubString, s: String; Till: Integer): Integer; function PosFromCase (const SubString, s: String; From: Integer): Integer; function LastPosTillCase (const SubString, s: String; Till: Integer): Integer;
Ebenfalls möglich:
procedure Foo; function Bar ...; procedure Baz;
Und natürlich:
const FooBar = 1; Baz = 2; Quux = 3;
Dieselbe "Tabellenanordnung" kann man für Initialisierungen gebrauchen:
const Foo: TBarArray = (('Foo' , 3), ('Bar baz', 42), ('' , -1));
Und in case
-Anweisungen:
case ReadKeyWord of kbLeft : if s[n] > l then Dec (s[n]) else s[n] := m[n]; kbRight : if s[n] < m[n] then Inc (s[n]) else s[n] := l; kbUp : if n > 1 then Dec (n) else n := 5; kbDown : if n < 5 then Inc (n) else n := 1; kbHome : s[n] := l; kbEnd : s[n] := m[n]; kbPgUp, kbCtrlPgUp: n := 1; kbPgDn, kbCtrlPgDn: n := 5; kbCR : Done := True; end
Und auch je nach Geschmack in anderem Code:
WriteCharAt (1, 1, 1, Frame[1], TextAttr); WriteCharAt (2, 1, w - 2, Frame[2], TextAttr); WriteCharAt (w, 1, 1, Frame[3], TextAttr);
Zeilenumbrüche sind nach lokalen const
-, type
-
und var
-Deklarationen freigestellt, wenn sie nur eine
einzige Deklaration beinhalten (Sie können auch mehrere Bezeichner
in einer Zeile deklarieren/definieren):
procedure Baz; var Foo, Bar: Integer; begin ... end;
Das geht auch:
procedure Baz; var Foo, Bar: Integer; begin ... end;
Aber bitte nicht so:
procedure Baz; var Foo, Bar: Integer; Qux: Real; begin ... end;
Wenn Sie viele Deklarationen haben, so können Sie Zeilenumbrüche
auf verschiedene Weisen vornehmen. Folgendes Beispiel ist die
bevorzugte Fassung für var
-Deklarationen:
var Foo, Bar, Baz, Qux, Quux, Corge, Grault, Garply, Waldo, Fred, Plugh, Xyzzy, Thud: Integer;
oder:
var Foo, Bar, Baz, Qux, Quux, Corge, Grault, Garply, Waldo: Integer; Fred, Plugh, Xyzzy, Thud: Integer;
Die folgende Form ist eher bei der Definition von record
-
oder öffentlichen object
-Feldern gebräuchlich, besonders,
wenn jeder Zeile ein Kommentar folgt:
var Foo, Bar, Baz, Qux: Integer;
Kein Zeilenumbruch darf nach var
-Deklarationen
innerhalb von Blöcken erfolgen. Solche Zeilenumbrüche setzen das
falsche Signal, daß hier mehrere Deklarationsgruppen erlaubt wären:
Foo := Bar; var Baz: array [1 .. Foo] of Integer;
Da dieses Statement eine GNU Pascal Erweiterung ist, sollte es selten eingesetzt werden, bei Variablen, deren Größe erst innerhalb der Routine berechnet wird oder für Variablen innerhalb von Modul-/Unit-Initialisierungen beispielsweise, um dafür keine globalen Variablen zu benötigen. Denken Sie bitte bei der Anwendung dieses Features über Unterroutinen nach.
Fügen Sie bitte keinen Zeilenumbruch nach label
durch. Sie
sollten Label folgendermaßen deklarieren:
label Foo, Bar, Baz;
So sollten Sie es auf keinen Fall tun:
label Foo, Bar, Baz;
Verschiedene Deklarationen von Labeln in unterschiedlichen Zeilen funktionieren auch nicht:
label Foo; Bar; Baz;
Hier folgt ein Beispiel, wie man innerhalb eines
case
-Blockes Zeilen umbricht:
case foo: begin ... end; bar, baz .. qux: ... else ... end;
Oder auch "tabellarisch":
case foo: begin ... end; bar, baz .. qux: ... else ... end;
Lange Zeilen sollten immer vor oder immer nach Operatoren, sowie nach Kommata umbrochen werden, wobei die Einrückung die Gruppierungen verdeutlichen sollte:
if (x = y) and (foo or (bar and (baz or qux)) or fred) then
Oder so:
if (x = y) and (foo or (bar and (baz or qux)) or fred) then
Hier sehen Sie, wie Sie Zeilenumbrüche innerhalb von if-then-else
Anweisungen vornehmen können. Diese Art der Einrückung sollte auch
verwendet werden, wenn Sie die case
-Anweisung verwenden
würden, dies aber nicht möglich ist (weil die Typen nicht aufzählbar
sind, oder die Werte nicht konstant sind oder ein Vergleich die
Benutzung einer Funktion wie StrEqualCase
notwendig machen
würde, oder zusätzliche Bedingungen auftauchen):
if ... then a else if ... then b else c
Wenn a
und "nicht a
" die Hauptfälle sind und
b
und c
Unterfälle von "nicht a
", so benutzen
Sie bitte die folgende Form (die Unterscheidung ist manchmal
Geschmackssache):
if ... then a else if ... then b else c
Das folgende (biologisch gesehen ziemlich unvollständige) Beispiel enthält eine Mischung beider Formen, die wir für vernünftig halten:
if Wohnort = 'Wasser' then { Im Wasser lebende Tiere } WriteLn ('Ist es ein Fisch?') else if Wohnort = 'Luft' then { Lufttiere } WriteLn ('Ist es ein Vogel?') else { Landlebewesen } if Beine = 8 then WriteLn ('Ist es eine Spinne?') else WriteLn ('Ist es ein Gnu?')
Die Hauptfälle werden hier durch den Wohnort bestimmt, die Anzahl der Beine bestimmen einige untergeordnete Fälle.
Hier eine kurze Zusammenfassung der normalen Schleifen:
for ... do ...
while ... do ...
repeat ... until ...
Wenn nur eine einzelne Anweisung nach if
oder in einer
do
- oder for
-Schleife bzw. zwischen repeat
und
until
existiert und diese Anweisung kurz genug für eine Zeile
ist, so darf diese Anweisung in eine Zeile wie folgt geschrieben
werden:
if ... then ...
for ... do ...
while ... do ...
repeat ... until ...
Wenn mehrere Anweisungen mit begin
und end
in einen
Block gefaßt werden, sieht es folgendermaßen aus:
if ... then begin ... end
for ... do begin ... end
while ... do begin ... end
Es wird nach folgenden Ausdrücken 2 Leerzeichen eingerückt:
begin
, then
, else
, case
, do
(for
, while
, with
, to begin
,
to end
), repeat
, record
, object
,
type
, const
, var
, label
.
Globale Routinen und ihre lokalen Variablen etc. werden nicht eingerückt, ebenso wie globale Variablen etc. Jede Subroutine (Kopf und Körper sowie ihre lokalen Variablen etc.) soll eingerückt werden.
program Prog; var GlobalVar: Integer; procedure GlobalProc; var LocalVar: Integer; procedure LocalProc; var LocalLocalVar: Integer; begin WriteLn ('Dies ist eine lokale Prozedur.') end; begin WriteLn ('Dies ist eine globale Prozedur.') end; begin WriteLn ('Dies ist das Hautpprogramm.') end.
Variante Records sollten so eingerückt werden:
type Foo = record NonVariant: Foo; case Discriminant: Bar of Val1: (Variant1: Baz; Variant2: Qux); Val2: (Variant3: Fred) end; var Foo: record [ wie oben ] end = [ Initialisierung ]
Größere Einrückung (mehr als zwei Leerzeichen) kann bei Zeilenumbrüchen im Code erfolgen, um einen "tabularen" Code zu erzeugen.
Conditionale ({$ifdef}
) sollten dieselbe Einrückung wie
der zugehörige Code haben:
begin {$ifdef DEBUG} WriteLn ('Debugging-Version'); {$endif} ... end;
Kurze Conditionale, die sich nur auf einen Ausdruck beziehen, dürfen auch in eine Zeile geschrieben werden:
Foo := {$ifdef DEBUG} 'Debugging' {$else} 'Veröffentlichung' {$endif};
Wenn Conditionale beabsichtigterweise entgegen den normalen syntaktischen Regeln genutzt werden, so setzen Sie diese an passende Stellen und schreiben Kommentare dazu:
begin { Führe den Code bedingungslos aus, wenn wir debuggen } {$ifndef DEBUG} if EinigeBedingungen then {$endif} begin ... end end;
Oftmals finden Sie schönere und nicht weniger effiziente Wege, dasselbe zu schreiben. In diesem Fall kann es auch so erfolgen:
begin if {$ifdef DEBUG} True {$else} EinigeBedingungen {$endif} then begin ... end end;
Oder noch besser:
{ global } const DebugFlag = {$ifdef DEBUG} True {$else} False {$endif}; begin if DebugFlag or EinigeBedingungen then begin ... end end;
Die meisten der bisherigen Regeln gelten nicht innerhalb von
Strings. Allgemein sollten Textausgaben innerhalb von Zeichenketten
den GNU Coding Standards folgen. Beispielsweise sollten zitierte
Namen von `
und '
begrenzt werden. In Pascal bedeutet
das, daß Sie doppelte '
benutzen müssen. Mehr Informationen:
SieheErrors.
Normalerweise sollten Strings in einfachen Anführungszeichen
so wie 'dieser schöne Satz, den Sie lesen'
eingeschlossen
sein. Mit doppelten Anführungszeichen sollen nur Zeichenketten
umfaßt werden, die C-Escape-Sequenzen beinhalten, wie
"\t"
. Beachten Sie bitte, daß NewLine
("\n"
)
vordefiniert ist. Geben Sie daher NewLine
den Vorzug, wenn
Sie nicht gerade C-Strings für andere Zwecke benötigen.
Mehrzeilige Strings können folgendermaßen genutzt werden:
WriteLn ('Hallo Welt!')
Oder (diese Form ist vor allem dann vorzuziehen, wenn der String selbst Einrückungen und/oder Absätze enthält):
WriteLn ( 'Hallo Welt!')
Folgendes ist auch möglich:
WriteLn ('Hallo' + NewLine + 'Welt!')
(Beachten Sie, daß obiger Code nicht ohne die Unit GPC
kompiliert werden kann.)
Oder natürlich:
WriteLn ('Hallo'); WriteLn ('Welt!')
Wenn Sie testen möchten, ob ein String leer ist, benutzen Sie folgende Syntax:
if s = '' then ...
Der GNU Pascal Compiler optimiert dies automatisch zu folgendem schnelleren Test. Daher können Sie den vorhergehende, kürzere Schreibweise ohne Bedenken verwenden:
if Length (s) = 0 then ...
Dasselbe gilt natürlich auch für <>
und sogar für
Zuweisungen, bei denen s := ''
die empfohlene Form ist,
welche von GPC intern zu SetLength (s, 0)
optimiert wird.
SieheConcepts, für allgemeine Informationen bzgl. Internationalisierung und Lokalisierung.
Ein Tool zur Internationalisierung, welches ähnlich wie
xgettext
arbeitet und pas2po
heißt, wird Ihnen unter
folgender URL angeboten:
http://www.gnu-pascal.de/contrib/eike/
In diesem Zusammenhang möchten wir Sie auch auf die
inter
-Unit hinweisen, welche Sie an selbiger Stelle finden
können. Sie benötigen sowohl pas2po
als auch die Unit, um
Ihr Programm zu internationalisieren. Bitte lesen Sie die den
Paketen beigefügten Informationen.
Dieser Abschnitt der GNU Coding Standards kann so, wie er ist,
auf GNU Pascal übertragen werden.
Beachten Sie, daß mmap
hier MemoryMap
bedeutet.
SieheMmap.
Wir empfehlen Ihnen, das entsprechende Kapitel der GNU Coding Standards zu lesen SieheDocumentation, die dortigen Informationen gelten auch für GNU Pascal. Einige Anmerkungen haben wir aber trotzdem.
Es wäre schön, eine Man-Page für jedes Programm zu haben. Diese
Man-Page sollte auf eine Info-Dokumentation verweisen. Es
existiert ein GNU Programm namens help2man
, welches Man-Pages
aus der Ausgabe der --help
-Option Ihres Programmes generiert.
Es funktioniert gut, bis auf die Tatsache, daß es FSF
an den
Anfang der Man-Page schreibt, was nicht für jedes mit dem GNU Pascal
Compiler erzeugte Programm richtig ist. Dies kann selbstverständlich
entweder im Quelltext oder mit der Hand oder automatisch mit
einem Programm wie sed
geändert werden.
Geben Sie sich mit den Man-Pages nicht zuviel Mühe. Sie gleichzeitig mit der Texinfo-Dokumentation auf dem neusten Stand zu halten, bedeutet eine Menge Arbeit und ist möglicherweise sehr fehlerträchtig. Wenn Sie die Man-Page nicht auf dem neuesten Stand halten, so schafft sie mehr Verwirrung als Nutzen.
Auf der einen Seite fehlen wichtige Informationen, wenn Man-Pages zu knapp ausfallen, auf der anderen Seite werden längere Man-Pages sehr unübersichtlich.
Mit anderen Worten: Schreiben Sie Info- (bzw. Texinfo-)Dokumentation!
Bitte lesen Sie das entsprechende Kapitel der GNU Coding
Standards. Beachten Sie, daß der ganze Aufwand mit den auto-Tools
(autoconf
, automake
, ...) im Rahmen von GNU
Pascal normalerweise nicht gebraucht werden. Außerdem sind Makefiles
in GNU Pascal Programmen nicht immer notwendig.
SieheManaging Releases.
Für Ihre Pascal-Projekte benötigen Sie keine großen Makefile
s
und Sie brauchen sich ebenfalls nicht in autoconf
und
automake
einzuarbeiten. Sie brauchen nur die
Kommandozeilenoption --automake
. Alles Weitere erledigt GNU
Pascal für Sie! (Zum Zeitpunkt des Schreibens hat GNU Pascal
einige kleinere Bugs im Zusammenhang mit der
automake
-Option. Diese Fehler werden aber nachgebessert.
Außerdem wird gerade an einem Utility namens gp
gearbeitet,
welches Ihnen noch mehr Arbeit beim Kompilieren abnimmt.)
Ein einfaches Makefile wie das folgende mag angebracht sein:
GPC_FLAGS=-O2 all: foo foo: foo.pas unit1.pas gpc --automake $(GPC_FLAGS) foo.pas mostlyclean: -rm -f *.o *.gpi *.gpm core clean: mostlyclean -rm -f foo distclean: clean extraclean: distclean -rm -f *~* maintainer-clean: extraclean
Sie wollen vielleicht dem Makefile
noch weitere Regeln
hinzufügen, sei es zur Erstellung der Dokumentation, Datendateien,
Paketen zur Veröffentlichung oder zu was auch immer. Diese Dinge
liegen außerhalb des Rahmens dieses Textes. Die Kompilierung eines
GNU Pascal Programmes erfolgt normalerweise mit
gpc --automake
.
Routinen sind Prozeduren (procedure
), Funktionen
(function
), Objeckt-Konstruktoren (constructor
) und
-Destruktoren (destructor
) sowie (selbstdefinierte)
Operatoren.
Deklarationen sind diejenigen Bereiche des Programmes, die die Eigenschaften irgendwelcher Objekte "erklären", wie Konstanten, Typen, Variablen, Units, Module, und selbstverständlich das Programm.
Anweisungen bzw. Statements sind solche Teile des Programmes, die
irgendetwas "veranlassen". Eine einzelne Anweisung ist eine
Zuweisung (assignment), der Aufruf einer Prozedur (procedure call),
ein Sprungbefehl (goto
, Exit
, Return
,
Break
, Continue
), eine Assembler-Anweisung oder
eine zusammengesetzte Anweisung (begin
... end
,
if
, case
, repeat
, while
, for
,
with
), die ihrerseits wieder verschiedene Anweisungen
enthalten dürfen.
Bezeichner (identifiers) sind Sprachelemente, die Objekten
(Routinen, Konstanten, Variablen, Typen, Units oder Modulen) ihre
Namen geben. Sie können lokal umdefiniert werden, anders als
Schlüsselwörter (keywords), die Teil einer festen Syntax sind
(beispielsweise if
... then
... else
)
und nicht umdefiniert werden können. Makros sind keine
Sprachelemente, da sie niemals vom Compiler verarbeitet werden,
sondern von einem Präprozessor.
Endianess ist ein Begriff, der sich auf die Reihenfolge der Anordnung der höher- und niederwertigen Bytes bezieht. Diese Reihenfolge ist auf manchen Systeme anders als auf anderen. Schauen Sie sich bitte die Erklärung dazu im GPC-Info Dokument an (sieheEndianness).
Hinweis: Andere Begriffe können hier eingefügt werden, sobald es sinnvoll erscheint. Wenn Sie die Definition eines Ausdruckes wissen möchten, so teilen Sie es uns bitte mit.
gettext
: Internationalisierung
MemoryMap
: MemoryMap