From 724cc003460ec67eda269911da85c9f9e40aa6cf Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Fri, 30 Sep 2016 16:57:23 +0200 Subject: Add extracted sources from floppy disk images Some files have no textual representation (yet) and were added as raw dataspaces. --- doc/programming/programmierhandbuch.2b | 1395 ++++++++++++++++++++++++++++++++ 1 file changed, 1395 insertions(+) create mode 100644 doc/programming/programmierhandbuch.2b (limited to 'doc/programming/programmierhandbuch.2b') diff --git a/doc/programming/programmierhandbuch.2b b/doc/programming/programmierhandbuch.2b new file mode 100644 index 0000000..c2103ba --- /dev/null +++ b/doc/programming/programmierhandbuch.2b @@ -0,0 +1,1395 @@ +#headandbottom("52","EUMEL-Benutzerhandbuch","TEIL 2 : ELAN","2")# +#pagenr ("%", 52)##setcount(1)##block##pageblock# +#headeven# +#center#EUMEL-Benutzerhandbuch +#center#____________________________________________________________ + +#end# +#headodd# +#center#TEIL 2 : ELAN +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +2 - % #right#GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #right#2 - % +#end# + + +2.5 Programmstruktur + +Ein ELAN-Programm kann aus mehreren Moduln (Bausteinen) aufgebaut sein, die in +ELAN PACKETs genannt werden. Das letzte PACKET wird "main packet" genannt, +weil in diesem das eigentliche Benutzerprogramm (Hauptprogramm) enthalten ist. +Dies soll eine Empfehlung sein, in welcher Reihenfolge die Elemente eines PACKETs +geschrieben werden sollen: + +Ein "main packet" kann aus folgenden Elementen bestehen: + +a) Deklarationen und Anweisungen. Diese müssen nicht in einer bestimmten Reihen­ + folge im Programm erscheinen, sondern es ist möglich, erst in dem Augenblick zu + deklarieren, wenn z.B. eine neue Variable benötigt wird. Es ist jedoch gute Pro­ + grammierpraxis, die meisten Deklarationen an den Anfang eines Programms oder + Programmteils (Refinement, Prozedur) zu plazieren. + + ; + + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR erste zahl, zweite zahl; + + page; + put ("erste Zahl = "); get (erste zahl); + put ("zweite Zahl ="); get (zweite zahl) + +____________________________________________________________________________ + + +b) Deklarationen, Refinements und Anweisungen. In diesem Fall ist es notwendig, die + Refinements hintereinander zu plazieren. Refinement-Aufrufe und/oder + Anweisungen sollten textuell vorher erscheinen. + + ; + . + + + Innerhalb der Refinements sind Anweisungen und/oder Deklarationen möglich. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR erste zahl, zweite zahl; + + loesche bildschirm; + lies zwei zahlen ein. + + loesche bildschirm: + page. + + lies zwei zahlen ein: + put ("erste Zahl = "); get (erste zahl); + put ("zweite Zahl ="); get (zweite zahl). + +____________________________________________________________________________ + + +c) Deklarationen, Prozeduren und Anweisungen. Werden Prozeduren vereinbart, + sollte man sie nach den Deklarationen plazieren. Danach sollten die Anweisungen + folgen: + + ; + ; + + + Mehrere Prozeduren werden durch ";" voneinander getrennt. In diesem Fall sind + die Datenobjekte aus den Deklarationen außerhalb von Prozeduren statisch, d.h. + während der gesamten Laufzeit des Programm vorhanden. Solche Datenobjekte + werden auch PACKET-Daten genannt. Im Gegensatz dazu sind die Datenobjekte + aus Deklarationen in Prozeduren dynamische Datenobjekte, die nur während der + Bearbeitungszeit der Prozedur existieren. Innerhalb einer Prozedur dürfen wieder­ + um Refinements verwendet werden. Ein Prozedur-Rumpf hat also den formalen + Aufbau wie unter a) oder b) geschildert. + + Die Refinements und Datenobjekte, die innerhalb einer Prozedur deklariert wurden, + sind lokal zu dieser Prozedur, d.h. können von außerhalb nicht angesprochen + werden. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR erste zahl, zweite zahl; + + PROC vertausche (INT VAR a, b): + INT VAR x; + + x := a; + a := b; + b := x + END PROC vertausche; + + put ("erste Zahl = "); get (erste zahl); + put ("zweite Zahl ="); get (zweite zahl); + IF erste zahl > zweite zahl + THEN vertausche (erste zahl, zweite zahl) + FI + +____________________________________________________________________________ + + +d) Deklarationen, Prozeduren, Anweisungen und PACKET-Refinements. Zusätzlich + zu der Möglichkeit c) ist es erlaubt, neben den Anweisungen außerhalb einer + Prozedur auch Refinements zu verwenden: + + ; + ; + . + + + Diese Refinements können nun in Anweisungen außerhalb der Prozeduren benutzt + werden oder auch durch die Prozeduren (im letzteren Fall spricht man analog zu + globalen PACKET-Daten auch von PACKET-Refinements oder globalen Refine­ + ments). In PACKET-Refinements dürfen natürlich keine Datenobjekte verwandt + werden, die lokal zu einer Prozedur sind. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR erste zahl, zweite zahl; + + PROC vertausche (INT VAR a, b): + INT VAR x; + + x := a; + a := b; + b := x + END PROC vertausche; + + loesche bildschirm; + lies zwei zahlen ein; + ordne die zahlen. + + loesche bildschirm: + page. + + lies zwei zahlen ein: + put ("erste Zahl = "); get (erste zahl); + put ("zweite Zahl ="); get (zweite zahl). + + ordne die zahlen: + IF erste zahl > zweite zahl + THEN vertausche (erste zahl, zweite zahl) + FI + +____________________________________________________________________________ +#page# + +2.6 Zusammengesetzte Datentypen + +In ELAN gibt es die Möglichkeit, gleichartige oder ungleichartige Datenobjekte zu +einem Objekt zusammenzufassen. + + +2.6.1 Reihung + +Die Zusammenfassung gleichartiger Datenobjekte, wird in ELAN eine Reihung (ROW) +genannt. Die einzelnen Objekte einer Reihung werden Elemente genannt. + +Eine Reihung wird folgendermaßen deklariert: + +- Schlüsselwort #on("i")##on("b")#ROW#off("i")##off("b")# +- Anzahl der zusammengefaßten Elemente + (INT-Denoter oder durch LET definierter Name) +- Datentyp der Elemente +- Zugriffsrecht ( #on("i")##on("b")#VAR#off("i")##off("b")# oder #on("i")##on("b")#CONST#off("i")##off("b")# ) +- Name der Reihung. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + ROW 10 INT VAR feld + +____________________________________________________________________________ + + +Im obigen Beispiel wird eine Reihung von 10 INT-Elementen deklariert. ROW 10 INT +ist ein (neuer, von den elementaren unterschiedlicher) Datentyp, für den keine Opera­ +tionen definiert sind, außer der Zuweisung. Das Accessrecht (VAR im obigen Bei­ +spiel) und der Name ('feld') gilt - wie bei den elementaren Datentypen - für diesen +neuen Datentyp, also für alle 10 Elemente. + +Warum gibt es keine Operationen außer der Zuweisung? Das wird sehr schnell +einsichtig, wenn man bedenkt, daß es ja sehr viele Datentypen (zusätzlich zu den +elementaren) gibt, weil Reihungen von jedem Datentyp gebildet werden können: + + +ROW 1 INT ROW 1 REAL +ROW 2 INT ROW 2 REAL + : : +ROW maxint INT ROW maxint REAL + +ROW 1 TEXT ROW 1 BOOL +ROW 2 TEXT ROW 2 BOOL + : : +ROW maxint TEXT ROW maxint BOOL + + +Für die elementaren INT-, REAL-, BOOL- und TEXT-Datentypen sind unter­ +schiedliche Operationen definiert. Man müßte nun für jeden dieser zusammengesetz­ +ten Datentypen z.B. auch 'get'- und 'put'-Prozeduren schreiben, was allein vom +Schreibaufwand sehr aufwendig wäre. Das ist der Grund dafür, daß es keine vorgege­ +bene Operationen auf zusammengesetzte Datentypen gibt. + +Zugegebenermaßen könnte man mit solchen Datentypen, die nur über eine Operation +verfügen (Zuweisung), nicht sehr viel anfangen, wenn es nicht eine weitere vorgege­ +bene Operation gäbe, die Subskription. Sie erlaubt es, auf die Elemente einer Reih­ +ung zuzugreifen und den Datentyp der Elemente "aufzudecken". + +Form: + +Rowname #on("i")##on("b")#[#off("i")##off("b")# Indexwert #on("i")##on("b")#]#off("i")##off("b")# + +Beispiel: + + +feld [3] + + +bezieht sich auf das dritte Element der Reihung 'feld' und hat den Datentyp INT. Für +INT-Objekte haben wir aber einige Operationen, mit denen wir arbeiten können. + +____________________________________________________________________________ + ........................... Beispiele: ........................ + feld [3] := 7; + feld [4] := feld [3] + 4; + +____________________________________________________________________________ + + +Eine Subskription "schält" also vom Datentyp ein ROW ab und liefert ein Element der +Reihung. Die Angabe der Nummer des Elements in der Reihung nennt man Subskript +oder Index (in obigem Beispiel '3'). Der Subskript wird in ELAN in eckigen Klammern +angegeben, um eine bessere Unterscheidung zu den runden Klammern in Ausdrücken +zu erreichen. Ein subskribiertes ROW-Datenobjekt kann also überall da verwendet +werden, wo ein entsprechender Datentyp benötigt wird (Ausnahme: nicht als Schlei­ +fenvariable). + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PROC get (ROW 10 INT VAR feld): + INT VAR i; + FOR i FROM 1 UPTO 10 REP + put (i); put ("tes Element bitte:"); + get (feld [i]); + line + END REP + END PROC get; + + PROC put (ROW 10 INT CONST feld): + INT VAR i; + FOR i FROM 1 UPTO 10 REP + put (i); put ("tes Element ist:"); + put (feld [i]); + line + END REP + END PROC put + +____________________________________________________________________________ + + +In diesen Beispielen werden Reihungen als Parameter benutzt. + +Diese beiden Prozeduren werden im folgenden Beispiel benutzt um 10 Werte einzu­ +lesen und die Summe zu berechnen: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + ROW 10 INT VAR werte; + lies werte ein; + summiere sie; + drucke die summe und einzelwerte. + + lies werte ein: + get (werte). + + summiere sie: + INT VAR summe :: 0, i; + FOR i FROM 1 UPTO 10 REP + summe INCR werte [i] + END REP. + + drucke die summe und einzelwerte: + put (werte); + line; + put ("Summe:"); put (summe). + +____________________________________________________________________________ + + +Da es möglich ist, von jedem Datentyp eine Reihung zu bilden, kann man natürlich +auch von einer Reihung eine Reihung bilden: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + ROW 5 ROW 10 INT VAR matrix + +____________________________________________________________________________ + + +Für eine "doppelte" Reihung gilt das für "einfache" Reihungen gesagte. Wiederum +existieren keine Operationen für dieses Datenobjekt (außer der Zuweisung), jedoch ist +es durch Subskription möglich, auf die Elemente zuzugreifen: + + +matrix [3] + + +liefert ein Datenobjekt mit dem Datentyp ROW 10 INT. + +Subskribiert man jedoch 'matrix' nochmals, so erhält man ein INT: + + +matrix [2] [8] + + +(jede Subskription "schält" von Außen ein ROW vom Datentyp ab). +#page# + +2.6.2 Struktur + +Strukturen sind Datenverbunde wie Reihungen, aber die Komponenten können unglei­ +chartige Datentypen haben. Die Komponenten von Strukturen heißen Felder (Reihun­ +gen: Elemente) und der Zugriff auf ein Feld Selektion (Reihungen: Subskription). Eine +Struktur ist - genauso wie bei Reihungen - ein eigener Datentyp, der in einer +Deklaration angegeben werden muß. + +Die Deklaration einer Struktur sieht folgendermaßen aus: + +- Schlüsselwort #schl ("STRUCT#off("i")##off("b")# +- unterschiedliche Datenobjekte in Klammern. Die Datenobjekte werden mit Datentyp und Namen angegeben +- Zugriffsrecht ( #on("i")##on("b")#VAR#off("i")##off("b")# oder #on("i")##on("b")#CONST#off("i")##off("b")# ) +- Name der Struktur. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + STRUCT (TEXT name, INT alter) VAR ich + +____________________________________________________________________________ + + +Wiederum existieren keine Operationen auf Strukturen außer der Zuweisung und der +Selektion, die es erlaubt, Komponenten aus einer Struktur herauszulösen. + +Die Selektion hat folgende Form: + +Objektname #on("i")##on("b")#.#off("i")##off("b")# Feldname + +Beispiele: + + +ich . name +ich . alter + + +Die erste Selektion liefert einen TEXT-, die zweite ein INT-Datenobjekt. Mit diesen +(selektierten) Datenobjekten kann - wie gewohnt - gearbeitet werden (Ausnahme: +nicht als Schleifenvariable). + +Zum Datentyp einer Struktur gehören auch die Feldnamen: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + STRUCT (TEXT produkt name, INT artikel nr) VAR erzeugnis + +____________________________________________________________________________ + + +Die obige Struktur ist ein anderer Datentyp als im ersten Beispiel dieses Abschnitts, +da die Namen der Felder zur Unterscheidung hinzugezogen werden. Für Strukturen - +genauso wie bei Reihungen - kann man sich neue Operationen definieren. + +Im folgenden Programm werden eine Struktur, die Personen beschreibt, die Prozedu­ +ren 'put', 'get' und der dyadische Operator HEIRATET definiert. Anschließend werden +drei Paare verHEIRATET. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PROC get (STRUCT (TEXT name, vorname, INT alter) VAR p): + put ("bitte Nachname:"); get ( p.name); + put ("bitte Vorname:"); get ( p.vorname); + put ("bitte Alter:"); get ( p.alter); + line + END PROC get; + + PROC put (STRUCT (TEXT name, vorname, INT alter) CONST p): + put (p.vorname); put (p.name); + put ("ist"); + put (p.alter); + put ("Jahre alt"); + line + END PROC put; + + OP HEIRATET + (STRUCT (TEXT name, vorname, INT alter) VAR w, + STRUCT (TEXT name, vorname, INT alter) CONST m): + w.name := m.name + END OP HEIRATET; + +____________________________________________________________________________ + + +____________________________________________________________________________ + ........................... Beispiel: ......................... + ROW 3 STRUCT (TEXT name, vorname, INT alter) VAR frau, + mann; + + personendaten einlesen; + heiraten lassen; + paardaten ausgeben. + + personendaten einlesen: + INT VAR i; + FOR i FROM 1 UPTO 3 REP + get (frau [i]); + get (mann [i]) + END REP. + + heiraten lassen: + FOR i FROM 1 UPTO 3 REP + frau [i] HEIRATET mann [i] + END REP. + + paardaten ausgeben: + FOR i FROM 1 UPTO 3 REP + put (frau [i]); + put ("hat geheiratet:"); line; + put (mann [i]); line + END REP. + +____________________________________________________________________________ + + +Reihungen und Strukturen dürfen miteinander kombiniert werden, d.h. es darf eine +Reihung in einer Struktur erscheinen oder es darf eine Reihung von einer Struktur +vorgenommen werden. Selektion und Subskription sind in diesen Fällen in der Reihen­ +folge vorzunehmen, wie die Datentypen aufgebaut wurden (von außen nach innen). +#page# + +2.6.3 LET-Konstrukt für zusammengesetzte Datentypen + + +Die Verwendung von Strukturen oder auch Reihungen kann manchmal schreibauf­ +wendig sein. Mit dem LET-Konstrukt darf man Datentypen einen Namen geben. +Dieser Name steht als Abkürzung und verringert so die Schreibarbeit. Zusätzlich wird +durch die Namensgebung die Lesbarkeit des Programms erhöht. + +Form: + +#on("i")##on("b")#LET#off("i")##off("b")# Name #on("i")##on("b")#=#off("i")##off("b")# Datentyp + +Der Name darf nur aus Großbuchstaben (ohne Blanks) bestehen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + LET PERSON = STRUCT (TEXT name, vorname, INT alter); + + PROC get (PERSON VAR p): + put ("bitte Nachname:"); get ( p.name); + put ("bitte Vorname:"); get ( p.vorname); + put ("bitte Alter:"); get ( p.alter); + line + END PROC get; + + PROC put (PERSON CONST p): + put (p.vorname); put (p.name); put ("ist"); + put (p.alter); put ("Jahre alt"); line + END PROC put; + + OP HEIRATET (PERSON VAR f, PERSON CONST m): + f.name := m.name + END OP HEIRATET; + + ROW 3 PERSON VAR mann, frau; + +____________________________________________________________________________ + + +Überall, wo der abzukürzende Datentyp verwandt wird, kann stattdessen der Name +PERSON benutzt werden. Wohlgemerkt: PERSON ist kein neuer Datentyp, sondern +nur ein Name, der für STRUCT (....) steht. Der Zugriff auf die Komponenten des +abgekürzten Datentyps bleibt erhalten (was bei abstrakten Datentypen, die später +erklärt werden, nicht mehr der Fall ist). + +Neben der Funktion der Abkürzung von Datentypen kann das LET-Konstrukt auch +zur Namensgebung für Denoter verwandt werden (siehe 2.3.1.2). + + + +2.6.4 Denoter für zusammengesetzte + Datentypen (Konstruktor) + + +Oft ist es notwendig, Datenverbunden Werte zuzuweisen (z.B.: bei der Initialisierung). +Dies kann durch normale Zuweisungen erfolgen: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + LET PERSON = STRUCT (TEXT name, vorname, INT alter); + + PERSON VAR mann; + + mann.name := "meier"; + mann.vorname := "egon"; + mann.alter := 27 + +____________________________________________________________________________ + + +Eine andere Möglichkeit für die Wertbesetzung von Datenverbunden ist der Konstruk­ +tor: + +Form: + +Datentyp #on("i")##on("b")#:#off("i")##off("b")# #on("i")##on("b")#(#off("i")##off("b")# Wertliste #on("i")##on("b")#)#off("i")##off("b")# + +In der Wertliste wird für jede Komponente des Datentyps, durch Kommata getrennt, +ein Wert aufgeführt. Besteht eine der Komponenten wiederum aus einem Datenver­ +bund, muß innerhalb des Konstruktors wiederum ein Konstruktor eingesetzt werden. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + LET PERSON = STRUCT (TEXT name, vorname, INT alter); + + PERSON VAR mann, frau; + + frau := PERSON : ( "niemeyer", "einfalt", 65); + frau HEIRATET PERSON : ( "meier", "egon", 27) + +____________________________________________________________________________ + + +Ein Konstruktor ist also ein Mechanismus, um ein Datenobjekt eines Datenverbundes +in einem Programm zu notieren. + +Konstruktoren sind natürlich für Reihungen auch möglich: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + ROW 7 INT VAR feld; + feld := ROW 7 INT : ( 1, 2, 3, 4, 5, 6, 7); +____________________________________________________________________________ +#page# + +2.7 Abstrakte Datentypen + + +2.7.1 Definition neuer Datentypen + +Im Gegensatz zur LET-Vereinbarung für Datentypen, bei der lediglich ein neuer +Name für einen bereits vorhandenen Datentyp eingeführt wird und bei der somit auch +keine neuen Operationen definiert werden müssen (weil die Operationen für den +abzukürzenden Datentyp verwandt werden können), wird durch eine TYPE-Verein­ +barung ein gänzlich neuer Datentyp eingeführt. + +Form: + +#on("i")##on("b")#TYPE#off("i")##off("b")# Name #on("i")##on("b")#=#off("i")##off("b")# Feinstruktur + +Der Name darf nur aus Großbuchstaben (ohne Blanks) bestehen. Die Feinstruktur +(konkreter Typ, Realisierung des Datentyps) kann jeder bereits definierte Datentyp +sein. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + TYPE PERSON = STRUCT (TEXT name, vorname, INT alter) + +____________________________________________________________________________ + + +Der neudefinierte Datentyp wird abstrakter Datentyp genannt. Im Gegensatz zu +Strukturen und Reihungen stehen für solche Datentypen noch nicht einmal die Zuwei­ +sung zur Verfügung. Ein solcher Datentyp kann genau wie alle anderen Datentypen +verwendet werden (Deklarationen, Parameter, wertliefernde Prozeduren, als Kompo­ +nenten in Reihungen und Strukturen usw.). + +Wird der Datentyp über die Schnittstelle des PACKETs anderen Programmteilen zur +Verfügung gestellt, so müssen Operatoren und/oder Prozeduren für den Datentyp +ebenfalls "herausgereicht" werden. Da dann der neudefinierte Datentyp genauso wie +alle anderen Datentypen verwandt werden kann, aber die Komponenten (Feinstruktur) +nicht zugänglich sind, spricht man von abstrakten Datentypen. + +Welche Operationen sollten für einen abstrakten Datentyp zur Verfügung stehen? +Obwohl das vom Einzelfall abhängt, werden meistens folgende Operationen und +Prozeduren definiert: + +- 'get'- und 'put'-Prozeduren. +- Zuweisung (auch für die Initialisierung notwendig). +- Denotierungs-Prozedur (weil kein Konstruktor für den abstrakten Datentyp außer­ + halb des definierenden PACKETs zur Verfügung steht) + + + +2.7.2 Konkretisierung + +Um neue Operatoren und/oder Prozeduren für einen abstrakten Datentyp zu schrei­ +ben, ist es möglich, auf die Komponenten des Datentyps (also auf die Feinstruktur) +mit Hilfe des Konkretisierers zuzugreifen. Der Konkretisierer arbeitet ähnlich wie die +Subskription oder Selektion: er ermöglicht eine typmäßige Umbetrachtung vom ab­ +strakten Typ zum Datentyp der Feinstruktur. + +Form: + +#on("i")##on("b")#CONCR#off("i")##off("b")# #on("i")##on("b")#(#off("i")##off("b")# Ausdruck #on("i")##on("b")#)#off("i")##off("b")# + +____________________________________________________________________________ + ........................... Beispiel: ......................... + TYPE MONAT = INT; + + PROC put (MONAT CONST m): + put ( CONCR (m)) + END PROC put; + +____________________________________________________________________________ + + +Der Konkretisierer ist bei Feinstrukturen notwendig, die von elementarem Datentyp +sind. Besteht dagegen die Feinstruktur aus Reihungen oder Strukturen, dann wird +durch eine Selektion oder Subskription eine implizite Konkretisierung vorgenommen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + TYPE LISTE = ROW 100 INT; + + LISTE VAR personal nummer; + ... + personal nummer [3] := ... + (* das gleiche wie *) + CONCR (personal nummer) [3] := ... + +____________________________________________________________________________ + + +2.7.3 Denoter für abstrakte + Datentypen (Konstruktor) + + +Denoter für neudefinierte Datentypen werden mit Hilfe des Konstruktors gebildet: + +Form: + +Datentyp #on("i")##on("b")#:#off("i")##off("b")# #on("i")##on("b")#(#off("i")##off("b")# Wertliste #on("i")##on("b")#)#off("i")##off("b")# + +In der Wertliste wird für jede Komponente des Datentyps, durch Kommata getrennt, +ein Wert aufgeführt. Besteht eine der Komponenten wiederum aus einem Datenver­ +bund, muß innerhalb des Konstruktors wiederum ein Konstruktor eingesetzt werden. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + TYPE GEHALT = INT; + + GEHALT VAR meins :: GEHALT : (10000); + +____________________________________________________________________________ + + +Besteht die Feinstruktur aus einem Datenverbund, muß der Konstruktor u.U. mehrfach +geschachtelt angewandt werden: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + TYPE KOMPLEX = ROW 2 REAL; + + KOMPLEX CONST x :: KOMPLEX : ( ROW 2 REAL : ( 1.0, 2.0)); + +____________________________________________________________________________ + + +Auf die Feinstruktur über den Konkretisierer eines neudefinierten Datentyps darf nur in +dem PACKET zugegriffen werden, in dem der Datentyp definiert wurde. Der Konstruk­ +tor kann ebenfalls nur in dem typdefinierenden PACKET verwandt werden. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PACKET widerstaende DEFINES WIDERSTAND, REIHE, PARALLEL, + :=, get, put: + + TYPE WIDERSTAND = INT; + + OP := (WIDERSTAND VAR l, WIDERSTAND CONST r): + CONCR (l) := CONCR (r) + END OP :=; + + PROC get (WIDERSTAND VAR w): + INT VAR i; + get (i); + w := WIDERSTAND : (i) + END PROC get; + + PROC put (WIDERSTAND CONST w): + put (CONCR (w)) + END PROC put; + + WIDERSTAND OP REIHE (WIDERSTAND CONST l, r): + WIDERSTAND : ( CONCR (l) + CONCR (r)) + END OP REIHE; + + WIDERSTAND OP PARALLEL (WIDERSTAND CONST l, r): + WIDERSTAND : + ((CONCR (l) * CONCR (r)) DIV (CONCR (l) + CONCR (r))) + END OP PARALLEL + + END PACKET widerstaende + +____________________________________________________________________________ + + +Dieses Programm realisiert den Datentyp WIDERSTAND und mit den Operationen +eine Fachsprache, mit dem man nun leicht WIDERSTANDs-Netzwerke berechnen +kann, wie z.B. folgendes: + + + + +---R4---+ + | | + +---R1---+ +---R5---+ + | | | | + ---+ +---R3---+ +--- + | | | | + +---R2---+ +---R6---+ + | | + +---R7---+ + + +Zur Berechnung des Gesamtwiderstandes kann nun folgendes Programm geschrieben +werden: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + ROW 7 WIDERSTAND VAR r; + widerstaende einlesen; + gesamtwiderstand berechnen; + ergebnis ausgeben. + + widerstaende einlesen: + INT VAR i; + FOR i FROM 1 UPTO 7 REP + put ("bitte widerstand R"); put (i); put (":"); + get (r [i]); + END REP. + + gesamtwiderstand berechnen: + WIDERSTAND CONST rgesamt :: (r [1] PARALLEL r [2]) REIHE + r [3] REIHE (r [4] PARALLEL r [5] PARALLEL r [6] + PARALLEL r [7]). + + ergebnis ausgeben: + line; + put (rgesamt). +____________________________________________________________________________ +#page# + +2.8 Dateien + +Dateien werden benötigt, wenn + +- Daten über die Abarbeitungszeit eines Programms aufbewahrt werden sollen; +- der Zeitpunkt oder Ort der Datenerfassung nicht mit dem Zeitpunkt oder Ort der + Datenverarbeitung übereinstimmt; +- die gesamte Datenmenge nicht auf einmal in den Zentralspeicher eines Rechners + paßt; +- die Anzahl und/oder Art der Daten nicht von vornherein bekannt sind. + +Eine Datei ("file") ist eine Zusammenfassung von Daten, die auf Massenspeichern +aufbewahrt wird. Dateien sind in bestimmten Informationsmengen, den Sätzen ("re­ +cords") organisiert. + + + +2.8.1 Datentypen FILE und DIRFILE + +In ELAN gibt es zwei Arten von Dateien. Sie werden durch die Datentypen FILE +und DIRFILE realisiert: + + + +FILE: +sequentielle Dateien. Die Sätze können nur sequentiell gelesen bzw. geschrieben +werden. Eine Positionierung ist nur zum nächsten Satz möglich. + + +DIRFILE: +indexsequentielle Dateien. Die Positionierung erfolgt direkt mit Hilfe eines Schlüssels +("key") oder Index, kann aber auch sequentiell vorgenommen werden. + +#on("b")#Wichtig: #off("b")# +DIRFILEs sind auf dem EUMEL-System standardmäßig nicht implementiert! Deswe­ +gen wird auf diesen Dateityp hier nicht weiter eingegangen. +#page# + +2.8.2 Deklaration und Assoziierung + +Dateien müssen in einem ELAN-Programm - wie alle anderen Objekte auch - +deklariert werden. + +Form: + +#on("i")##on("b")#FILE#off("i")##off("b")# #on("i")##on("b")#VAR#off("i")##off("b")# interner Dateibezeichner + +____________________________________________________________________________ + ........................... Beispiel: ......................... + FILE VAR f + +____________________________________________________________________________ + + +Dabei ist zu beachten, daß im EUMEL-System alle FILEs als VAR deklariert werden +müssen, denn jede Lese/Schreib-Operation verändert einen FILE. + +Dateien werden normalerweise vom Betriebsystem eines Rechners aufbewahrt und +verwaltet. Somit ist eine Verbindung von einem ELAN-Programm, in dem eine Datei +unter einem Namen - wie jedes andere Datenobjekt auch - angesprochen werden +soll, und dem Betriebssystem notwendig. Dies erfolgt durch die sogenannte Assozi­ +ierungsprozedur. Die Assoziierungsprozedur 'sequential file' hat die Aufgabe, eine in +einem Programm deklarierte FILE VAR mit einer bereits vorhandenen oder noch +einzurichtenden Datei des EUMEL-Systems zu koppeln. + +Form: + +#on("i")##on("b")#sequential file#off("i")##off("b")# #on("i")##on("b")#(#off("i")##off("b")# Betriebsrichtung, Dateiname #on("i")##on("b")#)#off("i")##off("b")# + +Es gibt folgende Betriebsrichtungen (TRANSPUTDIRECTIONs): + + +input: +Die Datei kann vom Programm nur gelesen werden. Durch 'input' wird bei der Asso­ +ziierung automatisch auf den ersten Satz der Datei positioniert. Ist die zu lesende +Datei nicht vorhanden, wird ein Fehler gemeldet. + + +output: +Die Datei kann vom Programm nur beschrieben werden. Durch 'output' wird bei der +Assoziierung automatisch hinter den letzten Satz der Datei positioniert (bei einer +leeren Datei also auf den ersten Satz). Ist die Datei vor der Assoziierung nicht vor­ +handen, wird sie automatisch eingerichtet. + + +modify: +Im EUMEL-System gibt es noch die Betriebsrichtung 'modify'. +Die Datei kann vom Programm in beliebiger Weise gelesen und beschrieben werden. +Im Gegensatz zu den Betriebsrichtungen 'input' und 'output', bei denen ausschließlich +ein rein sequentielles Lesen oder Schreiben erlaubt ist, kann bei 'modify' beliebig +positioniert, gelöscht, eingefügt und neu geschrieben werden. + +Nach erfolgter Assoziiierung ist auf den zuletzt bearbeiteten Satz positioniert. Die +Datei wird automatisch eingerichtet, wenn sie vor der Assoziierung nicht vorhanden +war. + +Der zweite Parameter der Assoziierungsprozedur gibt an, unter welchem Namen die +Datei in der Task existiert oder eingerichtet werden soll. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + FILE VAR meine datei :: sequential file (output, "xyz"); + +____________________________________________________________________________ + + +Folgendes Beispiel zeigt ein Programm, welches eine Datei liest und auf dem Ausga­ +bemedium ausgibt: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + FILE VAR f :: sequential file (input, "datei1"); + TEXT VAR satz; + WHILE NOT eof (f) REP + getline (f, satz); + putline (satz); + END REP. + +____________________________________________________________________________ + + +Eine genau Übersicht der für Dateien existierende Operatoren und Prozeduren finden +Sie im Teil 5.3. +#page# + +2.9 Abstrakte Datentypen + im EUMEL-System + + + +2.9.1 Datentyp TASK + +Tasks müssen im Rechnersystem eindeutig identifiziert werden; sogar im EUMEL- +Rechner-Netz sind Tasks eindeutig identifizierbar. Dazu wird der spezielle Datentyp +'TASK' benutzt, denn die Identifizierung einer Task über den Namen ist nicht eindeu­ +tig. Der Benutzer kann ja einen Tasknamen ändern, eine Task löschen und eine +neue Task mit gleichem Namen einrichten, die jedoch nicht gleich reagiert. Somit +werden Tasks eindeutig über Variablen vom Datentyp TASK identifiziert. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + TASK VAR plotter := task ("PLOTTER 1") + +____________________________________________________________________________ + + +Die Taskvariable 'plotter' bezeichnet jetzt die Task im System, die augenblicklich den +Namen "PLOTTER 1" hat. Die Prozedur 'task' liefert den systeminternen Taskbe­ +zeichner. + +Nun sind Taskvariablen auch unter Berücksichtigung der Zeit und nicht nur im aktuel­ +len Systemzustand eindeutig. Der Programmierer braucht sich also keine Sorgen +darüber zu machen, daß seine Taskvariable irgendwann einmal eine "falsche" Task +(nach Löschen von "PLOTTER 1" neu eingerichtete gleichen oder anderen Namens) +identifiziert. Wenn die Task "PLOTTER 1" gelöscht worden ist, bezeichnet 'plotter' +keine gültige Task mehr. + +Unbenannte Tasks haben alle den Pseudonamen "-". Sie können nur über Taskvari­ +ablen angesprochen werden. + + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PROC generate shutup manager: + TASK VAR son; + begin ("shutup", PROC shutup manager, son) + END PROC generate shutup manager; + + PROC shutup manager: + disable stop; + command dialogue (TRUE); + REP + break; + line; + IF yes ("shutup") + THEN clear error; + shutup + FI + PER + END PROC shutup manager + +____________________________________________________________________________ + + +Ein Taskvariable wird zum Beispiel als Parameter für die Prozedur 'begin' benötigt. + +begin + #on("b")#PROC begin (TEXT CONST son name, PROC start, + TASK VAR new task)#off("b")# + Die Prozedur richtet eine Sohntask mit Namen 'son name' (im Beispiel: shutup) + ein, die mit der Prozedur 'start' (im Beispiel: shutup manager) gestartet wird. 'new + task' (im Beispiel: son) identifiziert den Sohn, falls die Sohntask korrekt eingerich­ + tet wurde. +#page# + +2.9.2 Datentyp THESAURUS + +Ein Thesaurus ist ein Namensverzeichnis, das bis zu 200 Namen beinhalten kann. +Dabei muß jeder Name mindestens ein Zeichen und höchstens 100 Zeichen lang sein. +Steuerzeichen (code < 32) werden im Namen folgendermaßen umgesetzt: + +#on("i")##on("b")#steuerzeichen#off("b")##off("i")# wird umgesetzt in #on("i")##on("b")#"""" + code(steuerzeichen) + """"#off("b")##off("i")# + +Ein Thesaurus ordnet jedem eingetragenen Namen einen Index zwischen 1 und 200 +(einschließlich) zu. Diese Indizes bieten dem Anwender die Möglichkeit, Thesauri zur +Verwaltung benannter Objekte zu verwenden. (Der Zugriff erfolgt dann über den Index +eines Namens in einem Thesaurus). So werden Thesauri u.a. von der Dateiverwaltung +benutzt. Sie bilden die Grundlage der ALL- und SOME-Operatoren. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + initialisiere; + arbeite thesaurus ab. + + initialisiere: + THESAURUS VAR eine auswahl :: SOME (myself); + TEXT VAR thesaurus element; + INT VAR index :: 0. + + arbeite thesaurus ab: + REPEAT + get (eine auswahl, thesaurus element, index); + IF thesaurus element = "" + THEN LEAVE arbeite thesaurus ab + FI; + fuehre aktionen durch + PER. + + fuehre aktionen durch: + edit (thesaurus element); + lineform (thesaurus element); + pageform (thesaurus element); + print (thesaurus element). + +____________________________________________________________________________ + + +Dieses Beispiel führt für eine Auswahl der in der Task befindlichen Dateien nachein­ +ander die Kommandos 'edit', 'lineform', 'pageform' und 'print' aus. + +Die benutzten Operatoren und Prozeduren leisten folgendes: + +#ix("SOME")# + #on("b")#THESAURUS OP SOME (TASK CONST task) #off("b")# + Der Operator bietet das Verzeichnis der in der angegeben Task befindlichen + Dateien zum Editieren an. Namen, die nicht gewünscht sind, müssen aus dem + Verzeichnis gelöscht werden. + + +#ix("get")# + #on("b")#PROC get (THESAURUS CONST t, TEXT VAR name, INT VAR index) + #off("b")# Die Prozedur liefert den nächsten Eintrag aus dem angegebenen Thesaurus 't'. + 'Nächster' heißt hier, der kleinste vorhandene mit einem Index größer als 'index'. + Dabei wird in 'name'der Name und in 'index'der Index des Eintrags geliefert. +#page# + +2.9.3 Datenräume + +Datenräume sind die Grundlage von Dateien im EUMEL-System. Einen Datenraum +kann man sich als eine Sammlung von Daten vorstellen (u.U. leer). Man kann einem +Datenraum durch ein Programm einen Datentyp "aufprägen". Nach einem solchen +"Aufpräge"-Vorgang kann der Datenraum wie ein "normaler" Datentyp behandelt +werden. + +Standarddateien (FILEs) sind eine besondere Form von Datenräumen. Sie können nur +Texte aufnehmen, da sie ja hauptsächlich für die Kommunikation mit dem Menschen +(vorwiegend mit Hilfe des Editors bzw. Ein-/ Ausgabe) gedacht sind. Will man Zahlen +in einen FILE ausgeben, so müssen diese zuvor in Texte umgewandelt werden. Hier­ +für stehen Standardprozeduren zur Verfügung (z.B. 'put (f, 17)'). + +Will man aber Dateien zur Kommunikation zwischen Programmen verwenden, die +große Zahlenmengen austauschen, verursachen die Umwandlungen von Zahlen in +TEXTe und umgekehrt unnötigen Rechenaufwand. Zu diesem Zweck werden im +EUMEL-System Datenräume eingesetzt, die es gestatten, beliebige Strukturen +(Typen) in Dateien zu speichern. Solche Datenräume kann man weder mit dem Editor +noch mit dem Standarddruckprogramm (print) bearbeiten, da diese ja den Typ des in +dem Datenraum gespeicherten Objektes nicht kennen. + + + +2.9.3.1 Datentyp DATASPACE + +Datenräume können als eigener Datentyp (DATASPACE) in einem Programm behan­ +delt werden. Somit können Datenräume (als Ganzes) ohne Kenntnis eines eventuell +(vorher oder später) aufgeprägten Typs benutzt werden. + +Als Operationen auf DATASPACE-Objekte sind nur Transporte, Löschen und Zuwei­ +sung zugelassen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + DATASPACE VAR ds + +____________________________________________________________________________ + + +Für Datenräume ist die Zuweisung definiert. Der Zuweisungsoperator (':=') bewirkt +eine Kopie des Datenraums vom rechten auf den linken Operanden. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + DATASPACE VAR datenraum :: nilspace; + +____________________________________________________________________________ + + +Die Prozedur 'nilspace' liefert einen leeren Datenraum. Der Datenraum 'datenraum' ist +also eine Kopie des leeren Datenraums. + +Die Prozeduren und Operatoren für Datenräume werden im Teil 5.4.7 beschrieben. +#page# + +2.9.3.2 BOUND-Objekte + +Wie bereits erwähnt, kann man einem Datenraum einen Datentyp aufprägen. Dazu +werden #ib#BOUND#ie#-Objekte benutzt. Mit dem Schlüsselwort #on("i")##on("b")#BOUND#off("i")##off("b")#, welches in der +Deklaration vor den Datentyp gestellt wird, teilt man dem ELAN-Compiler mit, daß +die Werte eines Datentyps in einem Datenraum gespeichert sind bzw. gespeichert +werden sollen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + BOUND ROW 1000 REAL VAR liste + +____________________________________________________________________________ + + +Die Ankopplung des BOUND-Objekts an eine Datei erfolgt mit dem Operator #on("i")##on("b")#:=#off("i")##off("b")#. + +Form: + +BOUND-Objekt #on("i")##on("b")#:=#off("i")##off("b")# Datenraum + +____________________________________________________________________________ + ........................... Beispiel: ......................... + BOUND ROW 1000 REAL VAR gehaltsliste := new ("Gehälter") + +____________________________________________________________________________ + + +Die Prozedur 'new' kreiert dabei einen leeren Datenraum (hier mit dem Namen 'Ge­ +hälter'), der mit Hilfe der Zuweisung (hier: Initialisierung) an die Variable 'gehaltsliste' +gekoppelt wird. + +Nun kann man mit der 'gehaltsliste' arbeiten wie mit allen anderen Feldern auch. Die +Daten, die in 'gehaltsliste' gespeichert, werden eigentlich im Datenraum 'Gehälter' +abgelegt. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + gehaltsliste [5] := 10 000.0; (* Traumgehalt *) + gehaltsliste [index] INCR 200.0; (* usw. *) + +____________________________________________________________________________ + + +Man kann auch Prozeduren schreiben, die auf der Gehaltsliste arbeiten. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PROC sort (ROW 1000 REAL VAR liste): + ... + END PROC sort; + ... + sort (CONCR (gehaltsliste)); + ... + +____________________________________________________________________________ + + +Man beachte, daß der formale Parameter der Prozedur 'sort' nicht mit BOUND spezi­ +fiziert werden darf (BOUND wird nur bei der Deklaration des Objekts angegeben). Das +ist übrigens ein weiterer wichtiger Vorteil von BOUND-Objekten: man kann alle +Prozeduren des EUMEL-Systems auch für BOUND-Objekte verwenden, nur die +Datentypen müssen natürlich übereinstimmen. + + +Häufige Fehler bei der Benutzung von Datenräumen + +- Wenn man an ein DATASPACE-Objekt zuweist (z.B.: DATASPACE VAR ds := + new ("mein datenraum")), so erhält man, wie bereits erwähnt, eine Kopie des + Datenraums in 'ds'. Koppelt man jetzt 'ds' an ein BOUND-Objekt an und führt + Änderungen durch, so wirken diese nur auf die Kopie und nicht auf die Quelle. + Für Änderungen in der Quelle, also in der vom Datei-Manager verwalteten Datei, + ist stets direkt anzukoppeln. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + BOUND ROW 10 INT VAR reihe; + INT VAR i; + + PROC zeige dsinhalt (TEXT CONST datenraum): + BOUND ROW 10 INT VAR inhalt := old (datenraum); + INT VAR j; + line; + putline ("Inhalt:" + datenraum); + FOR j FROM 1 UPTO 10 REP + put (inhalt (j)) + PER + END PROC zeige dsinhalt; + + (* falsch: es wird auf der Kopie gearbeitet: *) + DATASPACE VAR ds := new ("Gegenbeispiel: Zahlen 1 bis 10"); + reihe := ds; + besetze reihe; + zeige dsinhalt ("Gegenbeispiel: Zahlen 1 bis 10"); + + (* richtig: es wird auf dem Datenraum gearbeitet: *) + reihe := new ("Beispiel: Zahlen 1 bis 10"); + besetze reihe; + zeige dsinhalt ("Beispiel: Zahlen 1 bis 10"). + + besetze reihe: + FOR i FROM 1 UPTO 10 REP + reihe (i) := i + PER. + +____________________________________________________________________________ + + + Der Datenraum 'Gegenbeispiel: Zahlen 1 bis 10' wird nicht mit Werten besetzt, + sondern die Kopie dieses Datenraums, der unbenannte Datenraum 'ds'. Auf dem + direkt angekoppelten Datenraum 'Beispiel: Zahlen 1 bis 10' werden die Werte + gespeichert. + + +- Wenn man ein DATASPACE-Objekt benutzt, ohne den Datei-Manager zu + verwenden, so muß man selbst dafür sorgen, daß dieses Objekt nach seiner + Benutzung wieder gelöscht wird. Das Löschen geschieht durch die Prozedur + 'forget'. Ein automatisches Löschen von DATASPACE-Objekten erfolgt nicht bei + Programmende (sonst könnten sie ihre Funktion als Datei nicht erfüllen). Nur + durch 'forget' oder beim Löschen einer Task werden alle ihr gehörenden + DATASPACE-Objekte gelöscht und der belegte Speicherplatz freigegeben. + + +- Ferner ist zu beachten, daß vor der Ankopplung an ein BOUND-Objekt das + DATASPACE-Objekt initialisiert wird (im Normalfall mit 'nilspace'). + +____________________________________________________________________________ + ........................... Beispiel: ......................... + DATASPACE VAR ds := nilspace; + BOUND ROW 1000 REAL VAR real feld := ds; + .... + real feld [index] := wert; + .... + forget (ds) (* Datenraum löschen, + damit der Platz wieder verwendet wird *) + +____________________________________________________________________________ + + +- Will man auf die Feinstruktur eines BOUND-Objekts zugreifen, so muß man + strenggenommen den Konkretisierer benutzen: + + Form: + + #on("i")##on("b")#CONCR#off("i")##off("b")# #on("i")##on("b")#(#off("i")##off("b")# Ausdruck #on("i")##on("b")#)#off("i")##off("b")# + + Der Konkretisierer ermöglicht eine typmäßige Umbetrachtung vom BOUND-Objekt + zum Datentyp der Feinstruktur. Ist der Zugriff jedoch eindeutig, so wird 'CONCR' + automatisch vom Compiler ergänzt. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + BOUND INT VAR i := old ("i-Wert"); + INT VAR x; + x := wert. + + wert: + IF x < 0 + THEN 0 + ELSE CONCR (i) + FI. + +____________________________________________________________________________ + + +In diesem Beispiel muß der Konkretisierer benutzt werden, da sonst der Resultattyp +des Refinements nicht eindeutig ist (BOUND oder INT?). + + + +2.9.3.3 Definition neuer Dateitypen + +Durch die Datenräume und die Datentyp-Definition von ELAN ist es für Programmie­ +rer relativ einfach, neue Datei-Datentypen zu definieren. In der Regel reicht der +Datentyp FILE für "normale" Anwendungen aus, jedoch kann es manchmal sinnvoll +und notwendig sein, neue Datei-Typen für spezielle Aufgaben zu definieren. + +In diesem Abschnitt soll an dem Beispiel DIRFILE (welcher zwar im ELAN-Standard +definiert, aber nicht im EUMEL-System realisiert ist) gezeigt werden, wie ein neuer +Datei-Datentyp definiert wird: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PACKET dirfiles DEFINES DIRFILE, :=, dirfile, getline, ...: + + LET maxsize = 1000; + + TYPE DIRFILE = BOUND ROW maxsize TEXT; + (* DIRFILE besteht aus TEXTen; Zugriff erfolgt ueber einen + Schluessel, der den Index auf die Reihung darstellt *) + + OP := (DIRFILE VAR dest, DATASPACE CONST space): + CONCR (dest) := space + END OP :=; + + DATASPACE PROC dirfile (TEXT CONST name): + IF exists (name) + THEN old (name) + ELSE new (name) + FI + END PROC dirfile; + + PROC getline (DIRFILE CONST df, INT CONST index, + TEXT VAR record): + IF index <= 0 + THEN errorstop ("access before first record") + ELIF index > maxsize + THEN errorstop ("access after last record") + ELSE record := df [index] + FI + END PROC getline; + + PROC putline (DIRFILE CONST df, INT CONST index, + TEXT VAR record): + ... + END PROC putline; + + ... + END PACKET dirfiles; + +____________________________________________________________________________ + + +Die Prozedur 'dirfile' ist die Assoziierungsprozedur für DIRFILEs (analog 'sequential +file' bei FILEs). 'dirfile' liefert entweder einen bereits vorhandenen Datenraum oder +richtet einen neuen ein. Um eine Initialisierung mit der 'dirfile'-Prozedur vorneh­ +men zu können, braucht man auch einen Zuweisungsoperator, der den Datenraum an +den DIRFILE-Datentyp koppelt. + +Zugriffe auf einen DIRFILE sind nun relativ einfach zu schreiben. Im obigen Beispiel +wird nur die Prozedur 'getline' gezeigt. + +Nun ist es möglich, Programme zu schreiben, die den DIRFILE-Datentyp benut­ +zen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + DIRFILE VAR laeufer :: dirfile ("Nacht von Borgholzhausen"); + INT VAR nummer; + TEXT VAR name; + + REP + put ("Startnummer bitte:"); + get (nummer); + line; + put ("Name des Laeufers:"); + get (name); + putline (laeufer, nummer, name); + line + UNTIL no ("weiter") END REP; + ... + +____________________________________________________________________________ +#page# + +2.9.4 Datentyp INITFLAG + +Im Multi-User-System ist es oft notwendig, Pakete beim Einrichten einer neuen +Task in dieser neu zu initialisieren. Das muß z.B. bei der Dateiverwaltung gemacht +werden, da die neue Task ja nicht die Dateien des Vaters erbt. Mit Hilfe von +INITFLAG-Objekten kann man zu diesem Zweck feststellen, ob ein Paket in dieser +Task schon initialisiert wurde. + + +INITFLAG + #on("b")#TYPE INITFLAG #off("b")# + Erlaubt die Deklaration entsprechender Flaggen. + +:= + #on("b")#OP := (INITFLAG VAR flag, BOOL CONST flagtrue) #off("b")# + Erlaubt die Initialisierung von INITFLAGs + +initialized + #on("b")#BOOL PROC initialized (INITFLAG VAR flag) #off("b")# + Wenn die Flagge in der Task A auf TRUE oder FALSE gesetzt wurde, dann liefert + sie beim ersten Aufruf den entsprechenden Wert, danach immer TRUE (in der + Task A!). + + Beim Einrichten von Söhnen wird die Flagge in den Sohntasks automatisch auf + FALSE gesetzt. So wird erreicht, daß diese Prozedur in den neu eingerichteten + Söhnen und Enkeltasks genau beim ersten Aufruf FALSE liefert. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PACKET stack DEFINES push, pop: + + INITFLAG VAR in this task := FALSE ; + INT VAR stack pointer ; + ROW 1000 INT VAR stack ; + + PROC push (INT CONST value) : + + initialize stack if necessary ; + .... + + END PROC push ; + + PROC pop (INT VAR value) : + + initialize stack if necessary ; + .... + + END PROC pop ;. + + initialize stack if necessary : + IF NOT initialized (in this task) + THEN stack pointer := 0 + + FI . + + END PACKET stack +____________________________________________________________________________ + -- cgit v1.2.3