#pagenr("%",1)##setcount(1)##block##pageblock# #headeven# #center#EUMEL-Benutzerhandbuch #center#____________________________________________________________ #end# #headodd# #center#TEIL 5 : Programmierung #center#____________________________________________________________ #end# #bottomeven# #center#____________________________________________________________ 5 - % #right#GMD #end# #bottomodd# #center#____________________________________________________________ GMD #right#5 - % #end# TEIL 5: Programmierung 5.1 Der ELAN-Compiler Der ELAN-Compiler des EUMEL-Systems dient zweierlei Aufgaben: zum einen der Übersetzung von ELAN-Programmen, zum anderen der Verwaltung der taskeigenen Modulbibliothek. Diese Moduln, in ELAN Pakete (siehe 2.4.3.4ff.) genannt, stellen als vorübersetzte, und damit abrufbereite#u#1)#e# Prozeduren den Kommandovorrat einer Task dar. Der Codebereich einer Task liegt in ihrem Standarddatenraum (ds4). Die Größe dieses Codebereiches beträgt 256K. Der Inhalt besteht zunächst aus den von der Vatertask ererbten (durch Kopie des ds4 dieser Task) Moduln, im weiteren allen in dieser Task neu hinzu insertierten Packeten. #on("b")# ACHTUNG: Durch ständiges Neuinsertieren eines Packets kann der Codebereich der betroffenen Task zum Überlaufen gebracht werden! #foot# 1) Die von anderen Systemen her gewohnten Phasen 'Binden' und 'Laden' sind durch das EUMEL-ELAN-Compiler-Konzept unnötig. #end# Jedes Kommando im EUMEL-System ist der Aufruf einer, in der Schnittstelle eines bereits insertierten Packetes stehenden, Prozedur. Kommandos für den ELAN-Compiler: - Übersetzen : do , insert , run , runagain - Protokollieren : check , checkon/off , prot , protoff , warnings on/off #page# 'do' #on("b")#PROC do (TEXT CONST program)#off("b")# Übersetzen und Ausführen von 'program' von einem Programm aus. 'program' muß ein ausführbares ELAN Programm sein. ____________________________________________________________________________ ........................... Beispiel .......................... PACKET reo DEFINES reorganize all: PROC reorganize all(THESAURUS CONST thes): do (PROC (TEXT CONST) reorganize ,thes) (* Die Prozedur 'reorganize' (siehe 5-52), die einen*) (* Dateinamen als Parameter verlangt, wird auf alle *) (* Dateien des Thesaurus 'thes' angewandt. *) END PROC reorganize all; END PACKET reo; ____________________________________________________________________________ 'insert' #on("b")#PROC insert (TEXT CONST dateiname) #off("b")# Insertieren eines oder mehrerer PACKETs aus der Datei 'dateiname'. Der Pro­ grammtext muß sich in #on("u")#einer#off("u")# Datei befinden. #on("b")#PROC insert #off("b")# Insertieren eines oder mehrerer PACKETs. Der Dateiname ist der zuletzt benutzte Dateiname. #on("b")#PROC insert (THESAURUS CONST t) #off("b")# Insertieren aller PACKETs, die in den Dateien des Thesaurus 't' enthalten sind. #page# 'run' #on("b")#PROC run #off("b")# Übersetzen und Ausführen eines ELAN-Programms. Der Programmtext muß sich in einer Datei befinden. Der Dateiname ist der zuletzt benutzte Dateiname. #on("b")#PROC run (TEXT CONST dateiname) #off("b")# Wie oben. Der Programmtext wird aus der Datei mit dem Namen 'dateiname' geholt. 'runagain' #on("b")#PROC runagain #off("b")# Nochmaliges Ausführen des zuletzt mit 'run' übersetzten ELAN-Programms. Wurde in der letzten Übersetzung ein Fehler gefunden, erfolgt die Meldung: FEHLER : "run again nicht möglich" #page# 'check' #on("b")#BOOL PROC check #off("b")# Informationsprozedur, die TRUE liefert, wenn 'check' eingeschaltet ist. #on("b")#PROC check on #off("b")# Einschalten der Generierung von Zeilennummern durch den ELAN-Compiler. Der bei der Übersetzung erzeugte Code wird ca. 25% umfangreicher! Voreinstellung im 'PUBLIC'- Zweig: 'check on'. #on("b")#PROC check off #off("b")# Ausschalten der Generierung von Zeilennummern durch den ELAN-Compiler. Voreinstellung im 'SYSUR' - Zweig: 'check off. 'prot' #on("b")#BOOL PROC prot #off("b")# Informationsprozedur, die TRUE liefert, gdw. 'prot' eingeschaltet ist. #on("b")#PROC prot (TEXT CONST dateiname) #off("b")# Einschalten des Compilerlistings auf dem Bildschirm. Das Listing wird gleichzeitig in die Datei 'dateiname' geschrieben. #on("b")#PROC prot off #off("b")# Ausschalten des Listings. 'warnings' #on("b")#BOOL PROC warnings #off("b")# Informationsprozedur, die TRUE liefert gdw. 'warnings' eingeschaltet ist. #on("b")#PROC warnings on #off("b")# Warnungen werden wie Fehlermeldungen ins Notizbuch ausgegeben. #on("b")#PROC warnings off#off("b")# Warnungen werden nicht mit in das Notizbuch ausgegeben. #page# 5.1.1 Fehlermeldungen des ELAN-Compilers erfolgen stets in der Form: #ib#COMPILER ERROR#ie#: wobei folgende Werte annehmen kann: #on("bold")# Bedeutung und eventuelle Abhilfe#off ("bold")#: 101 Überlauf der Namenstabelle Die Anzahl der Namen aller sichtbaren Pakete ist zu groß oder es wurden die Anführungstriche eines TEXT-Denoters vergessen. => Keine Abhilfe. 102 Überlauf der Symboltabelle Die Anzahl der deklarierten Objekte ist zu groß. => Programm in Pakete unterteilen. 103 Überlauf des Zwischencodebereiches => Programm in Pakete unterteilen. 104 Überlauf der Permanenttabelle Zu viele Pakete insertiert. => Keine (neue Task beginnen). 106 Paketdatenadresse zu groß Im Paket wird zuviel Platz ( > 64K ) von globalen Datenobjekten und Denotern eingenommen. => Keine Abhilfe. 107 Lokale Datenadresse zu groß Im Paket wird zuviel Platz ( > 32K ) von lokalen Datenobjekten belegt. => Keine Abhilfe. #page# 204 Überlauf des Compilerstack => Keine Abhilfe. 301 Modulnummern-Überlauf Zu viele sichtbare Pakete, Prozeduren und Operatoren ( > 2048 ). => Keine Abhilfe. 303 siehe 304 304 Zu viele Ansprungadressen In dem gerade übersetzten Modul (Prozedur, Operator oder Paketrumpf) werden vom Compiler zu viele Marken benötigt (mehr als 2000). Marken werden z.B. für die Codegenerierung von Auswahl (IF ...) und Wieder­ holung (REP ...) gebraucht. Insbesondere bei SELECT-Anweisungen werden 'casemax - casemin + 2' Marken benötigt, wobei 'casemax' der INT-Wert des maximalen, 'casemin' der des minimalen CASE-Wertes ist. Dieser Fehler ist somit fast immer auf zu viele und/oder zu weit ge­ spannte SELECT-Anweisungen zurückzuführen. => SELECT-Anweisungen über mehrere Prozeduren verteilen oder Spannweiten verringern. 305 Codeüberlauf Der insgesamt erzeugte sichtbare Code ist zu umfangreich ( > 256K ). => Keine Abhilfe. 306 Paketdatenadresse zu groß Insgesamt zu viele Datenobjekte in den Paketen ( > 128K ). => Keine Abhilfe. 307 Temporäre Datenadresse zu groß Zu viele (lokale) Datenobjekte in einer Prozedur ( > 32K ). => Prozedur in mehrere unterteilen, so daß die Datenobjekte sich über mehrere Prozeduren verteilen. 308 Modulcode-Überlauf Ein Modul (Prozedur, Operator oder Paket-Initialisierungsteil) ist zu groß ( > 7.5 KB Code). => In mehrere Prozeduren oder Pakete zerlegen. 309 Zuviele Paketdaten (Insgesamt mehr als 128K Paketdaten) => Keine Abhilfe #page# 5.2 Standardtypen 5.2.1 Bool Der Wertebereich für Datenobjekte vom Typ BOOL besteht aus den Werten TRUE und FALSE. 'AND' #on("b")#BOOL OP AND (BOOL CONST a, b) #off("b")# Logisches UND, liefert TRUE gdw. a und b TRUE sind. 'CAND' #on("b")#BOOL OP CAND #off("b")# Bedingtes logisches UND, entspricht: 'IF a THEN b ELSE false FI'. Der zweite Operand wird nicht ausgewertet, falls er für das Ergebnis nicht relevant ist. 'COR' #on("b")#BOOL OP COR #off("b")# Bedingtes logisches ODER, entspricht: 'IF a THEN true ELSE b FI'. Der zweite Operand wird nicht ausgewertet, falls er für das Ergebnis nicht relevant ist. 'false' #on("b")#BOOL CONST false #off("b")# 'NOT' #on("b")#BOOL OP NOT (BOOL CONST a) #off("b")# Logische Negation. 'OR' #on("b")#BOOL OP OR (BOOL CONST a, b) #off("b")# Logisches ODER, liefert TRUE gdw. a und/oder b TRUE ist. 'true' #on("b")#BOOL CONST true #off("b")# 'XOR' #on("b")#BOOL OP XOR (BOOL CONST a, b) #off("b")# Exklusives ODER, liefert TRUE gdw. entweder a oder b TRUE ist. #page# 5.2.2 Integer-Arithmetik Ein Datenobjekt vom Typ INT belegt im Speicher 2 Bytes. Zulässige INT - Werte sind die ganzen Zahlen von -32768 bis +32767 einschließlich. Falls größere ganze Zahlen benötigt werden, muß das Packet 'LONGINT', welches sich auf dem Archive 'std.zusatz' befindet, nachinsertiert werden (siehe 6.1.2). Operationen für Integers: - Vergleich : = , <> , < , <= , > , >= - Verknüpfung : + , - , * , ** , DECR , DIV , INCR - Sonstiges : abs , ABS , initialize random , max , maxint , min , minint , MOD , random , sign , SIGN , text #page# ':=' #on("b")#INT OP := (INT VAR a, INT CONST b) #off("b")# Zuweisung. '=' #on("b")#BOOL OP = (INT CONST a, b) #off("b")# Vergleich. '<>' #on("b")#BOOL OP <> (INT CONST a, b) #off("b")# Vergleich auf Ungleichheit. '<' #on("b")#BOOL OP < (INT CONST a, b) #off("b")# Vergleich auf kleiner. '<=' #on("b")#BOOL OP <= (INT CONST a, b) #off("b")# Vergleich auf kleiner gleich. '>' #on("b")#BOOL OP > (INT CONST a, b) #off("b")# Vergleich auf größer. '>=' #on("b")#BOOL OP >= (INT CONST a, b) #off("b")# Vergleich auf größer gleich. #page# '+' #on("b")#INT OP + (INT CONST a) #off("b")# Monadischer Operator (Vorzeichen, ohne Wirkung). #on("b")#INT OP + (INT CONST a, b) #off("b")# Addition. '-' #on("b")#INT OP - (INT CONST a) #off("b")# Vorzeichen-Umkehrung. #on("b")#INT OP - (INT CONST a, b) #off("b")# Subtraktion. '*' #on("b")#INT OP * (INT CONST a, b) #off("b")# Multiplikation. '**' #on("b")#INT OP ** (INT CONST arg, exp) #off("b")# Exponentiation mit 'exp' >= 0 'DECR' #on("b")#OP DECR (INT VAR links, INT CONST rechts) #off("b")# Wirkt wie links := links - rechts 'DIV' #on("b")#INT OP DIV (INT CONST a, b) #off("b")# INT-Division. FEHLER : - DIV durch 0 'INCR' #on("b")#OP INCR (INT VAR links, INT CONST rechts) #off("b")# Wirkt wie links := links + rechts #page# 'abs' #on("b")#INT PROC abs (INT CONST argument) #off("b")# Absolutbetrag eines INT-Wertes. #on("b")#INT OP ABS (INT CONST argument) #off("b")# Absolutbetrag eines INT-Wertes. 'initialize random' #on("b")#PROC initialize random (INT CONST wert) #off("b")# Initialisieren der 'random'-Prozedur, um nicht reproduzierbare Zufallszahlen zu bekommen. Diese 'initialize random'-Prozedur gilt für den "INT-Random Gene­ rator". 'max' #on("b")#INT PROC max (INT CONST links, rechts) #off("b")# Liefert den Größten der beiden INT-Werte. 'maxint' #on("b")#INT CONST maxint #off("b")# Größter INT-Wert im EUMEL-System (32 767). 'min' #on("b")#INT PROC min (INT CONST links, rechts) #off("b")# Liefert den Kleinsten der beiden INT-Werte. min ( 3.0, 2.0) ==> 2.0 min (-2.0, 3.0) ==> -2.0 'minint' #on("b")#INT CONST minint #off("b")# Kleinster INT-Wert im EUMEL-System (-32768). 'MOD' #on("b")#INT OP MOD (INT CONST links, rechts) #off("b")# Liefert den Rest einer INT-Division. 3 MOD 2 ==> 1 -3 MOD 2 ==> 1 FEHLER : - DIV durch 0 'random' #on("b")#INT PROC random (INT CONST lower bound, upper bound) #off("b")# Pseudo-Zufallszahlen-Generator im Intervall 'upper bound' und 'lower bound' einschließlich. Es handelt sich hier um den "INT Random Generator". 'real' #on("b")#REAL PROC real (INT CONST a) #off("b")# Konvertierungsprozedur. #page# 'sign' #on("b")#INT PROC sign (INT CONST argument) #off("b")# Feststellen des Vorzeichens eines INT-Wertes. Folgende Werte werden geliefert: argument > 0 ==> 1 argument = 0 ==> 0 argument < 0 ==> -1 #on("b")#INT OP SIGN (INT CONST argument) #off("b")# Feststellen des Vorzeichens eines INT-Wertes. 'text' #on("b")#TEXT PROC text (INT CONST zahl) #off("b")# Konvertierung des INT Wertes 'zahl' in den kürzest möglichen Text. Das Vorzei­ chen bleibt erhalten. #on("b")#TEXT PROC text (INT CONST zahl, länge) #off("b")# Konvertierung des INT Wertes 'zahl' in einen Text der Länge 'länge'. Das Vorzeichen bleibt erhalten. Falls der Text kürzer als 'länge' ist, wird er links (vorne) mit Leerzeichen aufgefüllt, falls er länder ist wird 'länge' mal "*" ausgegeben. ____________________________________________________________________________ out ("X:"); out(text(12345,7)) ; line; out ("Y:"); out(text(12345,3)) ; (* ergibt *) X: 12345 Y:*** ____________________________________________________________________________ #page# 5.2.3 Real-Arithmetik Für den Datentyp REAL gibt es außer den üblichen Verknüpfungs- und Vergleichs­ operationen noch eine Anzahl mathematischer Prozeduren und Operationen. Teilweise stehen diese in mehr als einer Version zur Verfügung. Jedes Datenobjekt vom Typ REAL belegt im Speicher 8 Byte. REALs haben eine 13-stellige #ib#Mantisse#ie#, die im Rechner dezimal geführt wird. (Das heißt, bei Konversionen zwischen interner und TEXT-Darstellung treten keine Run­ dungsfehler auf.) Der Wertebereich wird durch folgende Eckwerte abgegrenzt: #dpos(0.5,".")##lpos(4.5)# #table# 9.999999999999e+126 größter REAL-Wert 0.000000000001 kleinster positiver REAL-Wert mit x + 1.0 > 1.0 9.999999999999e-126 kleinster positiver REAL-Wert > 0.0 -9.999999999999e-126 größter negativer REAL-Wert -9.999999999999e+126 kleinster REAL-Wert #clearpos# #tableend# - Vergleiche : = , <> , < , <= , > , >= - Verknüpfungen : + , - , * , / , ** , DECR , INCR - Diverse : abs , arctan , arctand , cos , cosd , decimal exponent , e , exp , floor , frac , initialize random , int , ln , log2 , log10 , max , maxreal , min , MOD , pi , random , round , sign , SIGN , sin , sind , smallreal , sqrt , tan , tand , text #page# ':=' #on("b")#REAL OP := (REAL VAR a, REAL CONST b) #off("b")# Zuweisung. '=' #on("b")#BOOL OP = (REAL CONST a, b) #off("b")# Vergleich. '<>' #on("b")#BOOL OP <> (REAL CONST a, b) #off("b")# Vergleich auf Ungleichheit. '<' #on("b")#BOOL OP < (REAL CONST a, b) #off("b")# Vergleich auf kleiner. '<=' #on("b")#BOOL OP <= (REAL CONST a, b) #off("b")# Vergleich auf kleiner gleich. '>' #on("b")#BOOL OP > (REAL CONST a, b) #off("b")# Vergleich auf größer. '>=' #on("b")#BOOL OP >= (REAL CONST a, b) #off("b")# Vergleich auf größer gleich. #page# '+' #on("b")#REAL OP + (REAL CONST a) #off("b")# Monadischer Operator (Vorzeichen, ohne Wirkung). #on("b")#REAL OP + (REAL CONST a, b) #off("b")# Addition. '-' #on("b")#REAL OP - (REAL CONST a) #off("b")# Vorzeichen-Umkehrung. #on("b")#REAL OP - (REAL CONST a, b) #off("b")# Subtraktion. '*' #on("b")#REAL OP * (REAL CONST a, b) #off("b")# Multiplikation. '/' #on("b")#REAL OP / (REAL CONST a, b) #off("b")# Division. FEHLER : - Division durch 0 '**' #on("b")#REAL OP ** (REAL CONST arg, exp) #off("b")# Exponentiation. #on("b")#REAL OP ** (REAL CONST arg, INT CONST exp) #off("b")# Exponentiation. 'DECR' #on("b")#OP DECR (REAL VAR links, REAL CONST rechts) #off("b")# Wirkt wie links := links - rechts 'INCR' #on("b")#OP INCR (REAL VAR links, REAL CONST rechts) #off("b")# Wirkt wie links := links + rechts #page# 'abs' #on("b")#REAL PROC abs (REAL CONST wert) #off("b")# Absolutbetrag eines REAL-Wertes. #on("b")#REAL OP ABS (REAL CONST wert) #off("b")# Absolutbetrag eines REAL-Wertes. 'arctan' #on("b")#REAL PROC arctan (REAL CONST x) #off("b")# Arcus Tangens-Funktion. Liefert einen Wert in Radiant. 'arctand' #on("b")#REAL PROC arctand (REAL CONST x) #off("b")# Arcus Tangens-Funktion. Liefert einen Wert in Grad. 'cos' #on("b")#REAL PROC cos (REAL CONST x) #off("b")# Cosinus-Funktion. 'x' muß in Radiant angegeben werden. 'cosd' #on("b")#REAL PROC cosd (REAL CONST x) #off("b")# Cosinus-Funktion. 'x' muß in Winkelgrad angegeben werden. 'decimal exponent' #on("b")#INT PROC decimal exponent (REAL CONST mantisse) #off("b")# Liefert aus einem REAL-Wert den dezimalen Exponenten als INT-Wert. 'e' #on("b")#REAL PROC e #off("b")# Eulersche Zahl (2.718282). 'exp' #on("b")#REAL PROC exp (REAL CONST z) #off("b")# Exponentialfunktion. 'floor' #on("b")#REAL PROC floor (REAL CONST real) #off("b")# Schneidet die Nachkommastellen des REAL-Wertes 'real' ab. 'frac' #on("b")#REAL PROC frac (REAL CONST z) #off("b")# Liefert die Stellen eines REAL-Wertes hinter dem Dezimalpunkt. 'initialize random' #on("b")#PROC initialize random (REAL CONST z) #off("b")# Initialisieren der 'random'-Prozedur mit verschiedenen Werten für 'z', um nicht reproduzierbare Zufallszahlen zu bekommen. Diese Prozedur gilt für den 'REAL-Random Generator'. 'int' #on("b")#INT PROC int (REAL CONST a) #off("b")# Konvertierungsprozedur. Die Nachkommastellen werden abgeschnitten. Bsp: int (3.9) => 3 'ln' #on("b")#REAL PROC ln (REAL CONST x) #off("b")# Natürlicher Logarithmus. FEHLER : - ln mit negativer Zahl Nur echt positive Argumente sind zulässig. 'log2' #on("b")#REAL PROC log2 (REAL CONST z) #off("b")# Logarithmus zur Basis 2. FEHLER : - log2 mit negativer zahl Nur echt positive Argumente sind zulässig. 'log10' #on("b")#REAL PROC log10 (REAL CONST x) #off("b")# Logarithmus zur Basis 10. FEHLER : - log10 mit negativer zahl Nur echt positive Argumente sind zulässig. 'max' #on("b")#REAL PROC max (REAL CONST links, rechts) #off("b")# Liefert den Größten der beiden REAL-Werte. 'maxreal' #on("b")#REAL CONST maxreal #off("b")# Größter REAL-Wert im EUMEL-System (9.999999999999e126). 'min' #on("b")#REAL PROC min (REAL CONST links, rechts) #off("b")# Liefert den Kleinsten der beiden REAL-Werte. 'MOD' #on("b")#REAL OP MOD (REAL CONST links, rechts) #off("b")# Modulo-Funktion für REALs (liefert den Rest). Beispiele: 5.0 MOD 2.0 ==> 1.0 4.5 MOD 4.0 ==> 0.5 'pi' #on("b")#REAL CONST pi #off("b")# Die Zahl pi (3.141593). 'random' #on("b")#REAL PROC random #off("b")# Pseudo-Zufallszahlen-Generator im Intervall 0 und 1. Es handelt sich hier um den "REAL Random Generator". 'round' #on("b")#REAL PROC round (REAL CONST real, INT CONST digits) #off("b")# Runden eines REAL-Wertes auf 'digits' Stellen. Für positive Werte wird auf Nachkommastellen gerundet. Beispiel: round (3.14159, 3) liefert '3.142'. Für negative 'digits'-Werte wird auf Vorkommastellen gerundet. round (123.456, -2) liefert '100.0'. Abweichung vom Standard: Es wird mit 'digits'-Ziffern gerundet. 'sign' #on("b")#INT PROC sign (REAL CONST argument) #off("b")# Feststellen des Vorzeichens eines REAL-Wertes. #on("b")#INT OP SIGN (REAL CONST argument) #off("b")# Feststellen des Vorzeichens eines REAL-Wertes. 'sin' #on("b")#REAL PROC sin (REAL CONST x) #off("b")# Sinus-Funktion. 'x' muß in Radiant (Bogenmaß) angegeben werden. 'sind' #on("b")#REAL PROC sind (REAL CONST x) #off("b")# Sinus-Funktion. 'x' muß im Winkelgrad angegeben werden. 'smallreal' #on("b")#REAL PROC smallreal #off("b")# Kleinster darstellbarer REAL-Wert im EUMEL-System für den 1.0 - smallreal <> 1.0 1.0 + smallreal <> 1.0 gilt (1.0E-12). 'sqrt' #on("b")#REAL PROC sqrt (REAL CONST z) #off("b")# Wurzel-Funktion. FEHLER : - sqrt von negativer Zahl Das Argument muß größer gleich 0.0 sein. 'tan' #on("b")#REAL PROC tan (REAL CONST x) #off("b")# Tangens-Funktion. 'x' muß in Radiant angegeben werden. 'tand' #on("b")#REAL PROC tand (REAL CONST x) #off("b")# Tangens-Funktion. 'x' muß in Winkelgrad angegeben werden. 'text' #on("b")#TEXT PROC text (REAL CONST real) #off("b")# Konvertierung eines REAL-Wertes in einen TEXT. Ggf. wird der TEXT in Expo­ nenten-Darstellung geliefert. #on("b")#TEXT PROC text (REAL CONST real, laenge) #off("b")# Konvertierung eines REAL-Wertes in einen TEXT. Der TEXT wird in Exponen­ ten-Darstellung geliefert. Um diese Darstellung zu ermöglichen ist der Wert 'laenge' größer oder gleich 8 anzugeben. #on("b")#TEXT PROC text (REAL CONST real, INT CONST laenge, fracs)#off("b")# Konvertierung eines REAL-Wertes in einen TEXT. Dabei gibt 'laenge' die Länge des Resultats einschließlich des Dezimalpunktes und 'fracs' die Anzahl der Dezi­ malstellen an. Kann der REAL-Wert nicht wie gewünscht dargestellt werden, wird laenge * "*" geliefert. #page# 5.2.4 Text Jedes Datenobjekt vom Typ TEXT besteht aus einem festen Teil von 16 Bytes und möglicherweise aus einem flexiblen Teil auf dem #on("i")##on("b")#Heap#off("i")##off("b")#. Im festen Teil werden Texte bis zur Länge von 13 Zeichen untergebracht. Wenn eine TEXT-Variable einen Wert mit mehr als 13 Zeichen Länge annimmt, werden alle Zeichen auf dem Heap unterge­ bracht. Genauer ergibt sich folgendes Bild: kurzer Text (Länge <= 13): Heap-Link 2 Bytes Textlänge 1 Byte Text 13 Bytes langer Text (Länge > 13): Heap-Link 2 Bytes 255 1 Byte Länge 2 Bytes ungenutzt 11 Bytes Wenn eine Variable einmal Platz auf dem Heap bekommen hat, behält sie diesen vorbeugend auch dann, wenn sie wieder einen kurzen Text als Wert erhält. So muß wahrscheinlich kein neuer Platz auf dem Heap zugewiesen werden, wenn sie wieder länger wird. Das gilt allerdings nur bis zur nächsten #ib#Garbage Collection#ie# auf den TEXT-Heap, denn dabei werden alle Heap-Container minimal gemacht bzw. ge­ löscht, wenn sie nicht mehr benötigt werden. Der Platz auf dem Heap wird in Vielfa­ chen von 16 Bytes vergeben. In Fremddatenräumen wird in jedem #ib#Container#ie# neben dem eigentlichen Text auch die Containerlänge untergebracht. #page# Beispiele: TEXT-Länge Speicherbedarf (Byte) 0 16 13 16 14 32 15 48 30 48 31 64 46 64 47 80 62 80 Die Heapgröße eines Fremddatenraums berechnet sich als: 1024 * 1024 = 1048056 - stat Bytes 'stat' ist dabei die statische Größe der Datenstruktur, die dem Datenraum aufgeprägt wurde. Bei einem BOUND ROW 1000 TEXT ergibt sich also eine Heapgröße von 1048056 - (1000 * 16) = 1032056 Bytes. 'heap size' #on("b")#INT PROC heap size #off("b")# Informationsprozedur für die Größe (in KB) des TEXT-Heaps. #page# TEXT- Operationen: - Vergleich : = , <> , < , <= , > , >= LEXEQUAL , LEXGREATER , LEXGREATEREQUAL - Verkettung : + , * , CAT - Veränderung : change , change all , code , compress , delete char , insert char , length , LENGTH , max text length , pos , real , replace , SUB , subtext , text #page# Der EUMEL-Zeichensatz #goalpage("codetab")# Das EUMEL System definiert einen Zeichensatz, der gewährleistet, daß gleiche Text­ zeichen auf allen Maschinen gleich codiert werden. Die interne Darstellung wird durch die folgende EUMEL-Codetabelle beschrieben. Der Zeichensatz beruht auf dem ASCII-Zeichensatz mit Erweiterungen. Der in der Tabelle freie Bereich (z.B code(127) bis code(213)) ist nicht einheitlich verfügbar und wird deshalb nicht beschrieben. Die Codierung bildet mithin auch Grundlage für Vergleiche und Sortierungen. Die Korrekte Darstellung dieser Zeichen auf Bildschirm, Drucker etc. setzt natürlich eine korrekte Konfiguration der Geräte voraus. Die Anpassung eines Geräts an diesen Zeichensatz ist im EUMEL-Systemhandbuch in Teil 2 beschrieben. I 0 1 2 3 4 5 6 7 8 9 ---+-------------------------------------- 3 I SP ! " \# $ % & ' I 4 I ( ) * + , - . / 0 1 I 5 I 2 3 4 5 6 7 8 9 : ; I 6 I < = > ? § A B C D E I 7 I F G H I J K L M N O I 8 I P Q R S T U V W X Y I 9 I Z [ \ ] ^ _ ` a b c I 10 I d e f g h i j k l m I 11 I n o p q r s t u v w I 12 I x y z { | } ~ I 13 I . I . I . I 20 I I 21 I Ä Ö Ü ä ö ü I 22 I k ­ \# SP I 23 I I 24 I I 25 I ß #page# ':=' #on("b")#TEXT OP := (TEXT VAR a, TEXT CONST b) #off("b")# Zuweisung. '=' #on("b")#BOOL OP = (TEXT CONST links, rechts) #off("b")# Vergleich von zwei Texten auf Gleichheit (Texte mit ungleichen Längen sind immer ungleich). '<>' #on("b")#BOOL OP <> (TEXT CONST links, rechts) #off("b")# Vergleich von zwei Texten auf Ungleichheit (Texte mit ungleichen Längen sind stets ungleich). '<' #on("b")#BOOL OP < (TEXT CONST links, rechts) #off("b")# Vergleich zweier Texte auf kleiner ('links' kommt lexikographisch vor 'rechts'). '<=' #on("b")#BOOL OP <= (TEXT CONST links, rechts) #off("b")# Vergleich von zwei Texten auf kleiner gleich ('links' kommt lexikographisch vor oder ist gleich 'rechts'). '>' #on("b")#BOOL OP > (TEXT CONST links, rechts) #off("b")# Vergleich zweier Texte auf größer ('links' kommt lexikographisch nach 'rechts'). '>=' #on("b")#BOOL OP >= (TEXT CONST links, rechts) #off("b")# Vergleich zweier Texte auf größer gleich ('links' kommt lexikographisch nach oder ist gleich 'rechts'). #page# 'LEXEQUAL' #on("b")#BOOL OP LEXEQUAL (TEXT CONST links, rechts) #off("b")# Prüfung auf lexikalische Gleichheit. 'LEXGREATER' #on("b")#BOOL OP LEXGREATER (TEXT CONST links, rechts) #off("b")# Prüfung ob der Text 'links' lexikalisch größer als 'rechts' ist. 'LEXGREATEREQUAL' #on("b")#BOOL OP LEXGREATEREQUAL (TEXT CONST links, rechts) #off("b")# Prüfung ob der Text 'links' lexikalisch größer oder gleich dem Text 'rechts' ist. Die drei Operatoren prüfen nach folgenden Regeln: - Buchstaben haben die aufsteigende Reihenfolge 'A' bis 'Z'. Dabei werden kleine und große Buchstaben gleich behandelt. - Umlaute werden wie üblich ausgeschrieben. (Ä = Ae usw.) (ß = ss) - Alle Sonderzeichen (auch Ziffern) außer ' '(Leerzeichen) und '-' werden igno­ riert, diese beiden Zeichen werden gleich behandelt. #page# '+' #on("b")#TEXT OP + (TEXT CONST links, rechts) #off("b")# Verkettung der Texte 'links' und 'rechts' in dieser Reihenfolge. Die Länge des Resultats ergibt sich aus der Addition der Längen der Operanden. '*' #on("b")#TEXT OP * (INT CONST faktor, TEXT CONST quelle) #off("b")# 'faktor' fache Erstellung von 'quelle' und Verkettung. Dabei muß times >= 0 sein, sonst wird 'niltext' geliefert. 'CAT' #on("b")#OP CAT (TEXT VAR links, TEXT CONST rechts) #off("b")# hat die gleiche Wirkung wie links := links + rechts Hinweis: Der Operator 'CAT' hat eine geringere Heap-Belastung als die Opera­ tion mit expliziter Zuweisung. #page# 'change' #on("b")#PROC change (TEXT VAR senke, TEXT CONST alt, neu) #off("b")# Ersetzung des (Teil-) TEXTes 'alt' in 'senke' durch 'neu' bei dem erstmaligen Auftreten. Ist 'alt' nicht in 'senke' vorhanden, so wird keine Meldung abgesetzt (Abweichung vom Standard). Die Länge von 'senke' kann sich dabei verändern. Beispiel: TEXT VAR mein text :: "EUMEL-Benutzerhandbuch"; change (mein text, "Ben", "N"); (* EUMEL-Nutzerhandbuch *) #on("b")#PROC change (TEXT VAR senke, INT CONST von, bis, TEXT CONST neu) #off("b")# Der TEXT 'neu' wird in den TEXT 'senke' anstatt des TEXTes, der zwischen 'von' und 'bis' steht, eingesetzt. Die Länge von 'senke' kann sich dabei verändern. Beispiel: TEXT VAR mein text :: "EUMEL-Benutzerhandbuch"; change (mein text, 7, 9, "N"); (* wie oben *) 'change all' #on("b")#PROC change all (TEXT VAR senke, TEXT CONST alt, neu) #off("b")# Der Teiltext 'alt' wird durch 'neu' in 'senke' ersetzt. Im Unterschied zur 'chan­ ge'-Prozedur findet die Ersetzung nicht nur bei dem erstmaligen Auftreten von 'alt' statt, sondern so oft, wie 'alt' in 'senke' vorhanden ist. Beispiel: TEXT VAR x :: "Das ist ein Satz"; change all (x, " ", ""); (* DasisteinSatz *) #page# 'code' #on("b")#TEXT PROC code (INT CONST code) #off("b")# Wandelt einen INT-Wert 'code' in ein Zeichen um. 'code' muß 0 <= code <= 255 sein. #on("b")#INT PROC code (TEXT CONST text) #off("b")# Wandelt ein Zeichen 'text' in einen INT-Wert um. Ist LENGTH text <> 1 dann wird der Wert -1 geliefert (also bei mehr als ein Zeichen oder niltext). (Codetabelle auf Seite 5- #topage("codetab")#) 'compress' #on("b")#TEXT PROC compress (TEXT CONST text) #off("b")# Liefert den TEXT 'text' ohne führende und nachfolgende Leerzeichen. 'delete char' #on("b")#PROC delete char (TEXT VAR string, INT CONST delete pos)#off("b")# Löscht ein Zeichen aus dem Text 'string' an der Position 'delete pos'. Für delete pos <= 0 oder delete pos > LENGTH string wird keine Aktion vorgenommen. #page# 'insert char' #on("b")#PROC insert char (TEXT VAR string, TEXT CONST char,INT CONST insert pos)#off("b")# Fügt ein Zeichen 'char' in den Text 'string' an der Position 'insert pos' ein. Für insert pos > LENGTH string + 1 wird keine Aktion vorgenommen. Daher ist es möglich, mit dieser Prozedur auch am Ende eines Textes (Position: LENGTH string + 1) ein Zeichen anzufügen. 'length' #on("b")#INT PROC length (TEXT CONST text) #off("b")# Anzahl von Zeichen ("Länge") von 'text' einschließlich Leerzeichen. 'LENGTH' #on("b")#INT OP LENGTH (TEXT CONST text) #off("b")# Anzahl von Zeichen ("Länge") von 'text' einschließlich Leerzeichen. 'max text length' #on("b")#INT CONST max text length #off("b")# Maximale Anzahl von Zeichen in einem TEXT (32 000). #page# 'pos' #on("b")#INT PROC pos (TEXT CONST quelle, pattern) #off("b")# Liefert die erste Position des ersten Zeichens von 'pattern' in 'quelle', falls 'pat­ tern' gefunden wird. Wird 'pattern' nicht gefunden oder ist 'pattern' niltext, so wird der Wert '0' geliefert. Beispiel: TEXT VAR t1 :: "abcdefghijk...xyz", t2 :: "cd"; ... pos (t1, t2) ... (* liefert 3 *) ... pos (t2, t1) ... (* liefert 0 *) #on("b")#INT PROC pos (TEXT CONST quelle, pattern, INT CONST von)#off("b")# Wie obige Prozedur, jedoch wird erst ab der Position 'von' ab gesucht. Dabei gilt folgende Einschränkung: length (pattern) < 255 #on("b")#INT PROC pos (TEXT CONST quelle, low char, high char, INT CONST von#off("b")# Liefert die Position des ersten Zeichens 'x' in 'quelle' ab der Position 'von', so daß low char <= x <= high char 'low char' und 'high char' müssen TEXTe der Länge 1 sein. Wird kein Zeichen in 'quelle' in dem Bereich zwischen 'low char' und 'high char' gefunden, wird der Wert '0' geliefert. Beispiel: ____________________________________________________________________________ (*Suche nach dem ersten Zeichen <> blank nach einer Leerspalte*) TEXT VAR zeile :: "BlaBla Hier gehts weiter"; INT VAR pos erstes blank :: pos (zeile, " "), ende leerspalte :: pos (zeile, ""33"",""254"", pos erstes blank); ____________________________________________________________________________ #page# 'real' #on("b")#REAL PROC real (TEXT CONST text) #off("b")# Konvertierung eines TEXTes 'text' in einen REAL-Wert. Achtung: Zur Zeit werden keine Überprüfungen vorgenommen, d.h. in dem TEXT muß ein REAL-Wert stehen. 'replace' #on("b")#PROC replace (TEXT VAR senke, INT CONST position, TEXT CONST quelle)#off("b")# Ersetzung eines Teiltextes in 'senke' durch 'quelle' an der Position 'position' in 'senke'. Es muß gelten 1 <= position <= LENGTH senke d.h. 'position' muß innerhalb von 'senke' liegen und 'quelle' muß von der Posi­ tion 'position' ab in 'senke' einsetzbar sein. Dabei bleibt die Länge von 'senke' unverändert. 'SUB' #on("b")#TEXT OP SUB (TEXT CONST text, INT CONST pos) #off("b")# Liefert ein Zeichen aus 'text' an der Position 'pos'. Entspricht subtext (text, pos, pos) Anmerkung: Effizienter als obiger Prozedur-Aufruf. Für pos <= 0 pos > LENGTH text wird niltext geliefert. #page# 'subtext' #on("b")#TEXT PROC subtext (TEXT CONST quelle, INT CONST von) #off("b")# Teiltext von 'quelle', der bei der Position 'von' anfängt. Die Länge des Resultats ergibt sich also zu LENGTH quelle - von + 1 d.h. von der Position 'von' bis zum Ende von 'quelle'. 'von' muß innerhalb von 'quelle' liegen. Ist von < 1, dann wird 'quelle' geliefert. Falls von > LENGTH quelle ist, wird niltext geliefert. #on("b")#TEXT PROC subtext (TEXT CONST quelle, INT CONST von, bis)#off("b")# Teiltext von 'quelle' von der Position 'von' bis einschließlich der Position 'bis'. Die Länge des Resultats ist also bis - von + 1 Dabei muß gelten 1 <= von <= bis <= LENGTH quelle d.h. die Positionen 'von' und 'bis' müssen in dieser Reihenfolge innerhalb von 'quelle' liegen. Ist bis >= LENGTH quelle wird 'subtext (quelle, von)' ausgeführt. Für die Bedingungen für 'von' siehe vor­ stehende Beschreibung von 'subtext'. 'text' #on("b")#TEXT PROC text (TEXT CONST quelle, INT CONST laenge) #off("b")# Teiltext aus 'quelle' mit der Länge 'laenge', beginnend bei der Position 1 von 'quelle'. Es muß gelten 1 <= laenge <= LENGTH quelle d.h. der gewünschte Teiltext muß aus 'quelle' ausblendbar sein. Wenn gilt: laenge > LENGTH quelle wird der zu liefernde TEXT mit der an 'laenge' fehlenden Zeichen mit Leerzeichen aufgefüllt. #on("b")#TEXT PROC text (TEXT CONST quelle, INT CONST laenge, von)#off("b")# Teiltext aus 'quelle' mit der Länge 'laenge', beginnend an der Position 'von' in dem TEXT 'quelle'. Entspricht text (subtext (quelle, von, LENGTH quelle),laenge) Es muß laenge >= 0 1 <= von <= LENGTH quelle gelten, d.h. 'von' muß eine Position angeben, die innerhalb von 'quelle' liegt. Für laenge > LENGTH quelle - von + 1 also wenn die angegebene Länge 'laenge' größer ist als der auszublendende Text, wird das Resultat rechts mit Leerzeichen aufgefüllt. Wenn laenge < LENGTH quelle - von + 1 d.h. wenn die angegebene Länge kleiner ist als der Teiltext von 'von' bis zum letzten Zeichen von 'quelle', wird das Resultat mit der Länge LENGTH quelle - von + 1 geliefert.