diff options
Diffstat (limited to 'doc')
49 files changed, 50974 insertions, 0 deletions
diff --git a/doc/porting-8086/8/doc/Port.8086 b/doc/porting-8086/8/doc/Port.8086 new file mode 100644 index 0000000..a709a2a --- /dev/null +++ b/doc/porting-8086/8/doc/Port.8086 @@ -0,0 +1,2483 @@ +#type ("trium6")##limit (12.)# +#limit (30.0)# +#type ("trium8")##limit (12.0)# +#start(1.5,1.5)# +#type("triumb36")# +#free(4.0)# + EUMEL + Portierungshand + buch + 8086 / 8088 +#type("triumb18")# +#free(1.5)# + Version 8 +#page(1)# +#type ("trium8")##limit (12.0)# +#block# +#pagelength(19.5)# +#head# +#center#- % - + + +#end# +#type("triumb12")#Inhalt + +#a# +Teil 1: Einführung #topage("ein")# +#free(0.3)# + Zweck dieses Handbuchs #topage("zweck")# + Referenzliteratur #topage("reflit")# + Minimale Hardwarevoraussetzungen #topage("hardw")# + Systemdurchsatz #topage("durchsatz")# + Softwarekomponenten des EUMEL-Systems #topage("kompo")# + Anlieferung des 8086/8088-EUMEL-Systems #topage("anlief")# + +Teil 2: Allgemeine Strukturen #topage("allgem")# +#free(0.3)# + Hintergrund #topage("hg")# + Archiv #topage("arch")# + Hauptspeicher #topage("speicher")# + +Teil 3: SHard-Interface Spezifikation #topage("shardifc")# +#free(0.3)# + 0. Vorbemerkungen #topage("vor")# + Zur Notation #topage("not")# + Link-Leisten #topage("leist")# + Allgemeine Link-Bedingungen #topage("link")# + Interrupts #topage("intr")# + 1. System laden #topage("laden")# + 2. Systemstart und -ende #topage("start")# + 3. Speicherverwaltung #topage("spver")# + Hauptspeicher #topage("haupt")# + Speicherfehler #topage("memerr")# + 4. Zeitgeber #topage("zeit")# + 5. Kanäle #topage("channel")# + 5.1 Stream-IO #topage("stream")# + Terminals #topage("term")# + Drucker, Plotter #topage("druck")# + Exoten #topage("exot")# + 5.2 Block-IO #topage("block")# + Block-IO bei Hintergrund und Archiv #topage("bhgarch")# + Block-IO zur MS-DOS-Partition #topage("bmsdosp")# + 5.3 IO-Steuerung #topage("iocontrol")# + Einstellung serieller Schnittstellen #topage("v24")# + Flußkontrolle #topage("fluss")# + Kalender #topage("kalender")# + 6. SHard-Interface Version #topage("shdver")# + 7. ID-Konstanten #topage("ID")# + 8. Zusätzliche Leistungen #topage("shdelan")# + 9. Spezialroutinen #topage("ke")# + +Teil 4: Tips zur Portierung #topage("tips")# + 0-Version des SHards #topage("0ver")# + Effizienzprobleme #topage("eff")# + Typische Fehler #topage("fehler")# + +Anhang A: EUMEL-Debugger "Info" #topage("info")# +#free(0.3)# + Aufruf des Infos #topage("aufrinf")# + Info-Format #topage("forminf")# + Info-Kommandos #topage("cmdinf")# + Einige Systemadressen #topage("sysaddr")# + Leitblock #topage("pcb")# +#page# +#cc("Teil 1: ","Einführung")# +#goalpage("ein")# + + +#b("Zweck dieses Handbuchs")# +#goalpage("zweck")# + +Dieses Portierungshandbuch wendet sich an diejenigen, die das EUMEL-System auf einem +neuen Rechnertyp implementieren wollen. Es ist Teil einer Serie von Portierungshandbüchern +für verschiedene Prozessortypen. Dieses bezieht sich auf Rechner mit 8086/ 8088-Prozes +soren. + +Zum Betrieb eines EUMEL-Systems wird dieses Handbuch nicht benötigt! + + + +#b("Referenzliteratur")# +#goalpage("reflit")# + + + "EUMEL Benutzerhandbuch" + + "EUMEL Systemhandbuch" + + "EUMEL Quellcode der insertieren ELAN-Pakete" + + "iAPX 86,88-Users Manual" + intel, 1981 + + + +#b("Minimale Hardwarevoraussetzungen")# +#goalpage("hardw")# + +Um das EUMEL-System effizient einsetzen zu können, sollte die Hardware mindestens +folgenden Kriterien genügen: + + #ib#CPU#ie# Die 8086-CPU sollte mit mindestens 2.5 MHz (8088: 4.0 MHz) + arbeiten. Falls die Buszugriffe durch einen CRTC o.ä. ver + langsamt werden, sollte die echte 8086/ 8088-Leistung + durchschnittlich mindestens einem ungebremsten 2.5 MHz (4.0 + MHz) System entsprechen. + Seltene Verlangsamungen (z.B. nur bei I/O-Operationen) + spielen bei diesen Überlegungen keine Rolle. + + RAM Das System sollte über mindestens 80 K Byte #ib#Hauptspeicher#ie# + verfügen, besser sind 128 K als Anfangsausrüstung. + + #ib#Hintergrund#ie# Als Hintergrundmedium sind #ib#Floppy#ie#, #ib#Harddisk#ie# und RAM bzw. + ROM denkbar. + + Kapazität: > 300 K, besser > 400 K (Single-User) + > 750 K, besser > 1000 K (Multi-User) + + Zugriff: < 500 ms (Single-User) + < 200 ms (Multi-User) *) +#foot# +#f# +*) Hier ist die durchschnittliche Zugriffszeit auf einen 512 Byte großen Block gemeint. Für Platten und Floppies kann man +sie als Summe der Positionierzeit über die halbe Platte und der Zeit einer halben Umdrehung berechnen.#a##end# + + #ib#Archiv#ie# Als Archivgerät wird meistens eine Floppy eingesetzt. Aber + auch Band oder Kassettenrecorder sind denkbar. Die Anfor + derungen an Kapazität und Geschwindigkeit sind anwen + dungsspezifisch. + + #ib#Bildschirm#ie# Angestrebt werden sollte ein Bildschirm mit 24 Zeilen mit je 80 + Zeichen (oder größer). Kleinere Bildschirme sind anschließbar, + aber mit 40 Zeichen pro Zeile läßt sich nicht mehr komfortabel + arbeiten. + Rollup und freie Cursorpositionierung sind notwendige Vor + aussetzungen, invers-video ist erwünscht, aber nicht not + wendig. Weiterhin werden 'Löschen bis Zeilenende' und 'Lö + schen bis Schirmende' benötigt. Lokale Editierfunktionen sind + überflüssig. + + #ib#Tastatur#ie# An Steuertasten sollten mindestens ESC und die vier Cur + sortasten vorhanden sein. Dabei ist es günstig, wenn die + Cursortasten ergonomisch als Block bzw. Kreuz angeordnet + sind. EUMEL benötigt weitere Steuertasten für HOP, RUBIN, + RUBOUT und MARK. Dafür können beliebige Tasten der + Tastatur gewählt werden. + + + +#b("Systemdurchsatz")# +#goalpage("durchsatz")# + +Da das EUMEL-System auf dem Prinzip des Demand Paging aufbaut, hängt der System +durchsatz von + + - CPU Leistung + - Speichergröße (RAM) + - Geschwindigkeit beim Hintergrundzugriff (Floppy, Harddisk) + +ab. Mit zunehmender Benutzerzahl steigen in der Regel die Anforderungen an das Paging +(Hintergrund-Zugriff) schneller als an die CPU. In diesem Bereich kann man die System +leistung dann durch mehr Speicher und/oder eine schnellere Platte in größerem Umfang +steigern. Dabei läßt sich eine langsame Platte teilweise durch mehr RAM und umgekehrt +wenig RAM durch eine schnelle Platte ausgleichen. + + + +#b("Softwarekomponenten des EUMEL-Systems")# +#goalpage("kompo")# + +Das EUMEL-System besteht aus mehreren Schichten: + + + + EUMEL 2: Standardpakete, Editor, ... + + EUMEL 1: ELAN Compiler + + EUMEL 0: Basismaschine + + EUMEL -1: SHard + + H a r d w a r e + + +Dieses #ib#Schichtenmodell#ie# ist nach oben offen und kann deshalb um beliebig viele (höhere) +Schichten erweitert werden. + +EUMEL > 0 Die Standardsoftware der Schichten > 0 ist in der Sprache ELAN geschrie + ben (siehe "EUMEL Quellcode"). Dementsprechend sind alle Schichten ober + halb der EUMEL-0-Maschine prozessor- und rechnerunabhängig, d.h. + Anpassungen an einen neuen Rechnertyp sind nicht erforderlich. + +#ib#EUMEL 0#ie# Die sogenannte "EUMEL-0-Maschine" enthält alle Basisoperationen und + hängt davon ab, welchen Prozessortyp der Rechner als CPU verwendet. Sie + existiert für verschiedene Prozessortypen. Hier wird nur auf den Typ 8086/ + 8088 Bezug genommen. Bei der Portierung auf einen 8086/8088-Rechner + wird die 8086/8088-EUMEL-0-Maschine ohne Anpassungen (!) übernom + men. + +EUMEL -1 Diese Schicht stellt das Interface zwischen der EUMEL-0-Maschine und der + eigentlichen Hardware (vom Prozessor abgesehen) dar. Insbesondere umfaßt + sie alle Routinen zur Ansteuerung peripherer Geräte (Gerätetreiber). + Diese Schicht wird "SHard" genannt ("S"oftware-"Hard"ware Interface). + +Der SHard ist der einzige Teil des Systems, der bei der Portierung auf einen 8086/8088- +Rechner angepaßt bzw. neu geschrieben werden muß. Deshalb besteht der größte Teil dieses +Handbuchs aus der Spezifikation des 8086/8088-SHards. + + + +#b("Anlieferung des 8086/8088-EUMEL-Systems")# +#goalpage("anlief")# + +Der Implementierer erhält die EUMEL-Software auf Disketten. Dabei stehen folgende +Standardformate zur Wahl: + + 8", 1D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte + + 5", 2D, 40 Spuren, 9 Sektoren (\#1...\#9) � 512 Byte *) +#foot# +#f# +*) 48 tpi#a##end# + + +Die Diskettenlieferung enthält + + - Single-User Hintergrund + - Multi-User Hintergrund + - Standardarchive + - Archive mit weiterer Anwendersoftware + +Dabei enthält der Hintergrund auch die EUMEL-0-Software (oft auch als "Urlader" be +zeichnet). + +#on("i")#Bitte gehen Sie vorsichtig mit diesen Mutterdisketten um. Verwenden Sie sie nur als Quelle +beim Kopieren. Sie sollten nur auf Kopien davon arbeiten!#off("i")# +#page# +#cc("Teil 2: ","Allgemeine Strukturen")# +#goalpage("allgem")# + + +#b("Hintergrund")# +#goalpage("hg")# + +Der Hintergrund ist in 512 Bytes große Blöcke unterteilt. Sie werden durch Blocknummern (0, +1, 2, ...) adressiert. Die physische Ablage der Blöcke auf dem Hintergrundmedium bleibt dem +SHard überlassen. Er kann sie z.B. linear oder versetzt anordnen. Man sollte darauf achten, +daß Positionierungen auf logisch "nahe" Blöcke möglichst schnell gehen sollten. Deshalb ist +in der Regel zylinderorientierte Anordnung der oberflächenorientierten vorzuziehen. + +Falls auf dem Hintergrundgerät spezielle Blöcke z.B. für Boot und SHard freigehalten werden +sollen, muß das bei der Abbildung der Hintergrundblocknummern auf die Sektoren der Floppy +bzw. der Harddisk berücksichtigt werden. + +Aufbau des Hintergrundes: + + Block 0 Systemetikett + + Block 10...10+k-1 EUMEL-0-Software (Urlader) + + Block 1...9, 10+k ... Paging-Bereich + + +Aufbau des #ib#Systemetikett#ie#s (#ib#Block 0#ie#): + + Byte Wert/Aufgabe + + 0...5 "EUMEL-"; Kennzeichen für EUMEL-Hintergrund. + 6...11 Versionsnummer in druckbaren Zeichen. Sie stellt sicher, daß Urlader und + Hintergrund kompatibel sind. + 12 FFh ; zur Zeit ohne Bedeutung + 13 enthält Wert 0 , wenn System im Shutupzustand ist. + 14..15 Systemlaufzähler (14=low, 15=high). Wird bei jedem Systemstart um 1 + erhöht. + 16..35 Reserviert; zur Zeit ohne Bedeutung + 36..37 Aus historischen Gründen für interne Zwecke belegt. + 38 .. 69 Hier kann eine Installationsnummer geführt werden. + 70 .. 79 Info-Paßwort + 80...255 Reserviert. + 256..511 Kann von SHard beliebig verwendet werden. + + + +#b("Archiv")# +#goalpage("arch")# + +Wie der Hintergrund sind die Archive in 512 Bytes große Blöcke unterteilt. Bisher gibt es +folgende #dx("Standardformate")#: + + + 8", 1D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte + 8", 2D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte + + Block Seite Spur Sektor + + 0 0 0 0 + 16 0 1 0 + 77*16 1 0 0 + + n n DIV (77*16) n MOD (77*16) DIV 16 n MOD 16 + + + 5", 2D, 40 Spuren, 9 Sektoren (\#1...\#9) � 512 Byte + + Block Seite Spur Sektor + + 0 0 0 1 + 9 0 1 1 + 40*9 1 0 1 + + n n DIV (40*9) n MOD (40*9) DIV 9 n MOD 9 + 1 + + + 5", 2D, 80 Spuren, 9 Sektoren (\#1...\#9) � 512 Byte + + Block Seite Spur Sektor + + 0 0 0 1 + 9 0 1 1 + 80*9 1 0 1 + + n n DIV (80*9) n MOD (80*9) DIV 9 n MOD 9 + 1 + + + 5", HD, 80 Spuren, 15 Sektoren (\#1...\#15) � 512 Byte + + Block Seite Spur Sektor + + 0 0 0 1 + 15 0 1 1 + 80*15 1 0 1 + + n n DIV (80*15) n MOD (80*15) DIV 15 n MOD 15 + 1 + + +Selbstverständlich können auch andere #ib#Archivformate#ie# implementiert werden, falls das aus +Hardwaregründen notwendig ist oder sich dadurch wesentliche Verbesserungen (z.B. in der +Kapazität) ergeben. + +Wenn irgend möglich sollte aber mindestens eines der oben aufgeführten Standardformate +unterstützt werden - evtl. als zusätzliches Format -, um den Austausch zwischen verschie +denen Rechnertypen zu vereinfachen. + +#on("i")#Hinweis: Um den Datenaustausch zwischen verschiedenen Rechnertypen zu vereinfa + chen, sollten möglichst alle der hardwaremäßig möglichen Standardformate (min + destens lesend) unterstützt werden. Dabei sollte SHard sich automatisch auf das + Format der jeweils eingelegten Floppy einstellen:#off("i")# + + + Laufwerkstyp Diskettentyp(en) + + 8" 1D 8" 1D + 8" 2D 8" 2D, 1D + + 5" 2D-40 5" 2D-40 + 5" 2D-80 5" 2D-80, 2D-40 *), + 5" HD-80 5" HD-80, 2D-80, 2D-40 *) +#foot# +#f# +*) Bei der Behandlung von 40-Spur-Disketten auf 80-Spur-Laufwerken gelten meistens folgende Regeln: + a) Lesen funktioniert sicher. + b) Schreiben ist unsicher, funktioniert aber häufig. + c) Formatieren funktioniert fast nie. +#a# +#end# + + + +#b("Hauptspeicher")# +#goalpage("speicher")# + +Der #ib#Speicher#ie# wird EUMEL-0 vom SHard in maximal vier Speicherbereichen (M0...M3) +zugewiesen. M0 muß immer vorhanden sein, M1, M2 und M3 nur in speziellen Betriebsarten: + + #dx("M0")# #on("b")#allgemeines #ib#RAM#ie(1,", allgemeines")##off("b")# + Dieser Bereich muß immer vorhanden sein. Bei den meisten Rechnern liegt der + Urlader nicht in einem ROM, sondern wird von SHard in das RAM geladen. Das + geschieht dann an den Anfang von M0. Der Rest wird für Tabellen und als Pa + gingbereich benutzt. M0 umfaßt deshalb meistens allen verfügbaren Speicher, bis + auf den Platz für SHard, Boot-ROM und Bildwiederholspeicher. + + #dx("M1")# #on("b")#Urlader-#ib#ROM#ie(1,", Urlader")##off("b")# + Gibt es nur bei Rechnern, die den Urlader in einem ROM haben. (M0 wird dann + nur für Tabellen und als Pagingspeicher eingesetzt.) + + #dx("M2")# #on("b")#Hintergrund-#ib#ROM#ie(1,", Hintergrund")##off("b")# + Gibt es nur bei Rechnern, die nicht Floppy oder Festplatte sondern ROM und + RAM als Hintergrundspeicher verwenden. + + #dx("M3")# #on("b")#Hintergrund-#ib#RAM#ie(1,", Hintergrund")##off("b")# + Gibt es nur bei Rechnern, die nicht Floppy oder Festplatte sondern ROM und + RAM oder RAM allein als Hintergrundspeicherverwenden. + +Damit sind drei verschiedene Betriebsarten des EUMEL-Systems möglich: + + #dx("Normalbetrieb")#: M0 (> 80 K) + Hintergrundgerät (Festplatte oder Floppy) + Archivgerät (Floppy) + + Im Normalbetrieb befindet sich der Hintergrund auf einer Festplatte oder Floppy. + RAM wird für den Urlader und zum Paging eingesetzt. Alle mittleren und grö + ßeren Systeme verwenden den Normalbetrieb. + + + #dx("Minibetrieb")#: M0 (> 80 K) + M3 (mindestens 300 K) + Archivgerät (Floppy) + + Im Minibetrieb wird RAM als Hintergrundspeicher eingesetzt. Dieser wird beim + Einschalten über das Archivgerät geladen und beim Abschalten ('shutup') wieder + zurückgeschrieben. + + + #dx("ROM-Betrieb")#: M0 (> 24 K) + M1 (> 45 K) + M2 (> 170 K) + M3 (> 60 K) + Archivgerät (Kassettenrecorder oder Floppy) + + Im ROM-Betrieb stehen Urlader und Standardteil des Hintergrundes im ROM. + Der übrige Hintergrund befindet sich im RAM. + +#page# +#cc("Teil 3: SHard ","Interface Spezifikation")# +#goalpage("shardifc")# + + +#bb("0. ","Vorbemerkungen")# +#goalpage("vor")# + + +#b("Zur Notation")# +#goalpage("not")# + +Im folgenden wird zwischen #dx("0-Routinen")#, die dem SHard vom EUMEL-0-System zur +Verfügung gestellt werden, und #dx("SHard-Routinen")# unterschieden, die der SHard implemen +tieren muß. Damit dieser Unterschied bei der Spezifikation deutlich wird, werden 0-Routinen +folgendermaßen aufgeführt: + + name (0-Routine) + +Zusätzlich werden 0-Routinen grundsätzlich klein und SHard-Routinen groß geschrieben. + +8086/8088-Befehle werden wie in "iAPX 86,88 Users Manual" (intel, 1981) notiert: + + mov al,27 + add ab,bl + +Hexadezimale Zahlen werden durch ein nachgestelltes 'h' gekennzeichnet: + + 12h = 18 + 1Fh = 31 + FFFFh = 65535 + + +#b("Link-Leisten")# +#goalpage("leist")# + +Die Verbindung zwischen SHard und Urlader (EUMEL-0) erfolgt über zwei Tabellen. In der +"0-Leiste" stellt EUMEL-0 dem SHard verschiedene 0-Routinen zur Verfügung. Diese +Leiste beginnt an der Adresse M0:0 (im Normal- oder Minimodus) bzw. M1:0 (im ROM- +Modus): + + Adresse + + 00h eumel0id db 'EUMEL ' + db 10 dup (?) + 10h eumel0blocks dw + 12h hgver dw + 14h cputype dw 3 ; für 8086 oder kompatible CPU + 16h urver dw + 18h dw + 1Ah shdvermin dw + 1Ch shdvermax dw + 1E dw + 20h systemstart dd + 24h inputinterrupt dd + 28h timerinterrupt dd + 2Ch warte dd + 30h grab dd + 34h free dd + 38h shutup dd + 3Ch info dd + +Hinweis: Die Segmentteile der 'dd'-Addressen in dieser Link-Leiste sind natürlich unde + finiert. Deshalb muß SHard diese auf M0 bzw. M1 setzen. Dazu ist es mindestens + beim ROM-Urlader erforderlich, die 0-Leiste in einen von SHard verwalteten + RAM-Bereich zu kopieren. + + +Für die Gegenrichtung muß SHard der 0-Maschine die "SHard-Leiste" zur Verfügung stel +len: + + Adresse + + 00h SHDID db 'SHARD ' + db 10 dup (?) + 10h SHDVER dw 8 + 12h MODE dw + 14h ID4 dw + 16h ID5 dw + 18h ID6 dw + 1Ah ID7 dw + db 4 dup (?) + 20h OUTPUT dd + 24h BLOCKIN dd + 28h BLOCKOUT dd + 2Ch IOCONTROL dd + 30h SYSEND dd + db 12 dup (?) + 40h M0START dw + 42h M0SIZE dw + 44h M1START dw + 46h M1SIZE dw + 48h M2START dw + 4Ah M2SIZE dw + 4Ch M3START dw + 4Eh M3SIZE dw + + +Dabei ist als 'MxSTART' eine Paragraphenadresse (d.h. Adresse DIV 16) und entsprechend +als 'MxSIZE' die Länge des Bereichs als Bytelänge DIV 16 anzugeben. + + + + +#b("Allgemeine Link-Bedingungen")# +#goalpage("link")# + +In der Regel sind sowohl 0-Routinen als auch SHard-Routinen durch 'call' aufzurufen: + + call dword ptr <routine> + +Ausnahmen von dieser Regel sind im folgenden stets besonders vermerkt. + +Generelle Link-Bedingung (für SHard- und 0-Routinen) ist: + + Alle Register - bis auf die jeweils spezifizierten Ausgangsparameter und das F-Re + gister *) - bleiben unverändert. +#foot# +#f# +*) Flags sind i.a. nach dem Aufruf einer Routine undefiniert. Ausnahmen sind natürlich die Flags, die als Ausgangspara +meter in manchen Fällen definiert sind.#a##end# + +Jede SHard-Routine muß also alle Register (bis auf F), die sie verändert und die keine +Ausgangsparameter sind, retten und wiederherstellen. Im Gegenzug braucht SHard beim +Aufruf von 0-Routinen selbst keine Register zu retten. +Das schließt auch die Segmentregister mit ein. Um SHard-eigene Daten über DS zu adres +sieren, muß SHard also DS sichern, neu laden und zum Schluß wiederherstellen. Entspre +chendes gilt für ES. SS darf nicht verändert werden. + + +#b("Interrupts")# +#goalpage("intr")# + +Zwei externe Ereignisse (Zeitgeber und Eingabe, siehe S.#topage("zeit")# und S.#topage("inp")#) werden von +EUMEL-0 behandelt. Die entsprechenden Interrupts muß SHard per 'call' an 0-Routinen +weiterleiten. +Die Register (bis auf AX und F) werden von den aufzurufenden 0-Routinen selbst gesi +chert. Auch die Segmentregister DS und ES werden von EUMEL-0 geladen. (CS wird +automatisch durch den "far call" gesetzt, SS darf sowieso nicht verändert werden.) Die +normale Interrupt-Sequenz im SHard sieht dann folgendermaßen aus: + + intadr: push ax + mov al,<parameter> + call dword ptr <routine> + ; interrupt level freigeben + pop ax + iret + + + +#bb("1. System ","laden")# +#goalpage("laden")# + +SHard muß die EUMEL-0-Software vor dem eigentlichen Start an den Anfang der Spei +cherregion M0 laden. EUMEL-0 befindet sich normalerweise auf dem Hintergrund von Block +10 ab. Der erste Block (10) enthält am Anfang die 0-Leiste. Dort steht an der Stelle 10h die +Größe 'eumel0blocks'. Sie gibt an, wieviel Blöcke konsekutiv geladen werden müssen. Hat +sie beispielsweise den Wert 80, müssen die Blöcke 10 bis 89 geladen werden. + + Achtung: Zu diesem Zeitpunkt kann SHard die oben aufgeführten 0-Routinen na + türlich noch nicht benutzen. Insbesondere dürfen die Laderoutinen nicht + 'warte' aufrufen. Das wird hier besonders betont, weil der Hintergrundzugriff + beim eigentlichen Systemlauf in der Regel 'warte' verwenden wird. + + Hinweis: Der erste Block der EUMEL-0-Software (Block 10) enthält in den ersten + fünf Bytes den Text "EUMEL", um eine Identifikation durch den SHard- + Lader zu ermöglichen. + +Es wird empfohlen, nach folgendem Verfahren zu laden: + + IF archivgeraet enthaelt diskette AND eumel 0 auf archiv + THEN lade eumel 0 vom archiv + ELIF eumel 0 auf hintergrund + THEN lade eumel 0 vom hintergrund + ELSE laden unmoeglich + FI . + +So kann man auch bei einem frisch formatierten Hintergrundmedium einen neuen Hinter +grund (mit EUMEL-0-Urlader) einspielen, indem man ein Hintergrundarchiv vor dem +Systemstart in das Archivgerät legt. Dann wird EUMEL-0 von dort geladen, so daß man den +Hintergrund dann wie im Systemhandbuch beschrieben vom Archiv auf das Hintergrundme +dium kopieren kann.*) +#foot# +#f# +*) Kopiervorgänge (Archiv -> Hintergrund) werden vom EUMEL-0-Urlader erledigt, so daß SHard keine derartigen +Routinen enthalten muß.#a##end# + + + +#bb("2. System","start und -ende")# +#goalpage("start")# + +SHard muß alle für den Rechner notwendigen (Hardware-) Initialisierungen durchführen und +erst danach die EUMEL-0-Maschine starten ('systemstart'). + + #dx("systemstart")# (0-Routine) + + Eingang: DS:BX Adresse der SHard-Leiste + Interrupts disabled + + Aufruf: jmp dword ptr systemstart + + Zweck: Die EUMEL-0-Maschine wird gestartet. Alle notwendigen + Hardwareinitialisierungen (z.B. der Peripheriebausteine) + müssen vorher schon geschehen sein. + + Hinweis: Der Stackpointer und die Segmentregister brauchen nicht + definiert zu sein, da beim Ansprung alle Interrupts maskiert + sein sollten und somit keine Interrupts auftreten können. + EUMEL-0 lädt beim Start CS, SS, SP, DS, ES und läßt In + terrupts zu (STI). Falls jedoch in dieser Zeit ein "Non Maskable + Interrupt" auftreten kann, muß SHard SS und SP "vorläufig" + laden. + + MODE: Über das MODE-Wort in der SHard-Leiste können Optionen + gesetzt werden: + + Bit 0 = 0 EUMEL-0 ist auf dem Hintergrund abge + speichert. Der entsprechende Bereich bleibt + geschützt. (Standard) + + Bit 0 = 1 EUMEL-0 befindet sich nicht auf dem Hin + tergrund. Der entsprechende Bereich steht zur + freien Verfügung für andere EUMEL-Daten. + (Da die EUMEL-0-Software nur beim + Systemstart geladen wird (read only!), kann es + bei Geräten mit kleinem Hintergrund inter + essant sein, diese Blöcke auf dem Hinter + grund anderweitig zu nutzen. Das Systemla + den kann dann z.B. mit Hilfe einer speziellen + Urladediskette vom Archivgerät aus erfolgen.) + + Bit 8 = 0 Beim Systemstart wird der Speicher überprüft. + (Standard) + + Bit 8 = 1 Der Speichertest beim Systemstart unterbleibt. + Man sollte nur bei Rechnern, die beim Ein + schalten schon eigene Speichertests durch + führen, auf den Speichertest des EUMEL + verzichten. + + Bit 9 = 0 Beim Systemstart wird die Vortest-Tapete + ausgegeben und man kann durch Eingabe + eines Zeichens die Vortestmenüs aktivieren (s. + Systemhandbuch). (Standard) + + Bit 9 = 1 Die Vortest-tapete wird unterdrückt. Es gibt + auch keine Möglichkeit, die Vortestfunktionen + aufzurufen. Der Speichertest unterbleibt + ebenfalls. + + + + #d("SYSEND")# + + Parameter: - + + Zweck: Hiermit wird SHard das Ende eines Systemlaufs mitgeteilt. + Somit können evtl. notwendige Abschlußbehandlungen durch + geführt werden. SHard kann mit 'ret' zu EUMEL-0 zurück + kehren, muß aber nicht. Diese Routine kann z.B. dazu benutzt + werden, die Hardware auszuschalten oder in ein umgebendes + System zurückzukehren (EUMEL als Subsystem). In den mei + sten Fällen wird die Routine leer implementiert werden, d.h. + nur aus 'ret' bestehen. + + +#bb("3. ","Speicherverwaltung")# +#goalpage("spver")# + + +#b("Hauptspeicher")# +#goalpage("haupt")# + +Der Hauptspeicher umfaßt die Teile des 8086/8088-Speichers, die EUMEL-0 verwalten +darf, nämlich die Bereiche M0, M1, M2 und M3 (siehe S.#topage("speicher")#). M1, M2 und M3 sind dabei nur +bei speziellen Betriebsarten nötig. Jeder der vier Bereiche wird in der SHard-Leiste durch +die Anfagsadresse MxSTART und seine Länge MxSIZE beschrieben: + + MxSTART Anfang des Bereichs als Paragraphenadresse (Byteadresse DIV + 16) + MxSIZE Größe des Bereichs in Paragraphen (Bytegröße DIV 16) + +Nicht vorhandenen Bereiche werden durch MxSIZE = MxSTART = 0 gekennzeichnet. + + + + + +#b("Speicherfehler")# +#goalpage("memerr")# + +Falls die Hardware Speicherfehler aufgrund von Paritybits, ECC oder ähnlichem feststellen +und an SHard melden kann, sollte das zur Erhöhung der Systemsicherheit genutzt werden. + +Wenn SHard (z.B. über Interrupt) einen Speicherfehler mitgeteilt bekommt, sollte er wenn +möglich eine entsprechende Meldung ausgeben und das System brutal anhalten: + + rien ne vas plus: jmp rien ne vas plus + + +Wenn Speicherfehler mit Sicherheit bemerkt werden, verhindert diese Reaktion, daß die +Fehler auf dem Hintergrund festgeschrieben werden und evtl. später zu Systemfehlern füh +ren. + +Der Anwender kann dann durch Hardware-Reset auf den letzten Fixpunkt des EUMEL- +Systems zurücksetzen. So verliert er zwar evtl. die letzten Minuten seiner Arbeit, behält aber +auf alle Fälle ein konsistentes System. + + + + +#bb("4. ","Zeitgeber")# +#goalpage("zeit")# + +SHard muß einen Zeitgeberinterrupt erzeugen, der ca. 10 bis 100 mal pro Sekunde auftritt. +Dabei ist die 0-Routine 'timerinterrupt' aufzurufen. Ohne diesen Interrupt wird die Uhr nicht +geführt, und die Zeitscheibenlogik für das Timesharing fällt aus. + + #dx("timerinterrupt")# (0-Routine) + + Eingang: AL seit letztem Zeitgeberinterrupt vergangene Zeit (in ms) + + Zweck: Wird von EUMEL-0 für interne Uhren und für das Schedu + ling (Zeitscheibenlogik) verwendet. Es werden keine hohen + Genauigkeitsanforderungen an die Zeitangaben bei #on("i")#einzel + nen#off("i")# Interrupts gestellt. Um EUMEL-0 eine genaue Real + zeituhr zu ermöglichen, sollte die so erzeugte Zeitangabe #on("i")#im + Mittel#off("i")# aber möglichst genau sein, d.h. die Summe der in + nerhalb einer Minute so übergebenen Werte sollte zwischen + 59995 und 60005 liegen. + + + +#bb("5. ","Kanäle")# +#goalpage("channel")# + +Einiges zum Kanalkonzept: + +Das System kennt die Kanäle 0..32. + + Kanal 0 ist der Systemhintergrund. + Die Kanäle 1..15 sind für Stream-IO (Terminals, Drucker, ...) vorgesehen. + Kanal 31 ist der Standard-Archivkanal. + Kanal 32 ist der Parameterkanal. + +Die Kanäle 2.. 30 können installationsabhängig verfügbar sein oder auch nicht. Deren Funk +tion ist dann Absprachesache zwischen Installation und SHard. + +Kanäle können über Block-IO (BLOCKOUT, BLOCKIN) oder Stream-IO (OUTPUT,..) +angesprochen werden. Das System erfährt über IOCONTROL, welche Betriebsart des Kanals +sinnvoll ist. + +#on("i")##on("b")#Achtung: Alle Kanaloperationen müssen grundsätzlich für alle Kanäle (0...32) aufgerufen + werden können. Dabei können Operationen auf nicht vorhandenen Kanälen und + unsinnige Operationen (z.B. Stream-IO auf Kanal 0) leer implementiert wer + den.#off("b")# (Dafür werden im folgenden bei jeder SHard-Routine Vorschläge gemacht.)#off("i")# + + + +#bb("5.1 ","Stream-IO")# +#goalpage("stream")# + +Über Stream-IO wickelt das System die übliche zeichenorientierte Ein-/Ausgabe auf Ter +minals, Druckern, Plottern usw. ab. Stream-IO wird nur für die Kanäle 1...15 gemacht. + + #dx("inputinterrupt")# (0-Routine)#goalpage("inp")# + + Eingang: AL Kanalnummer (1...15) + CH eingegebenes Zeichen + CL Fehlerbits: + Bit 0 = 1 Mindestens ein Zeichen konnte auf + diesem Kanal nicht empfangen + werden (z.B. weil Interrupts gesperrt + waren). + Bit 1 = 1 Es wurde ein BREAK erkannt (bei + V24). Dieses Ereignis kann nicht + durch ein Sonderzeichen gemeldet + werden, da bei einer 8-bit-Über + tragung schon alle Zeichen vergeben + sind. Daher wird BREAK hier aufge + nommen, obwohl es im eigentlichen + Sinne kein Fehler sein muß. + Bit 2 = 1 Das übergebene Zeichen ist verfälscht + (z.B. Parität falsch). + + Ausgang: AL Zahl der noch freien Bytes im Eingabepuffer von + EUMEL-0. Die Angabe gilt für den Puffer dieses + Kanals nach Eintrag des übergebenen Zeichens. + + Zweck: SHard muß EUMEL-0 durch Aufruf dieser Routine mitteilen, + daß eine Eingabe vorliegt. + + Hinweise: EUMEL-0 puffert die Zeichen. Falls 0 geliefert wird, ist der + Puffer voll und EUMEL-0 ignoriert weitere Eingaben, bis + wieder Platz im Puffer vorhanden ist. (siehe IOCONTROL + "weiter", S.#topage("weiter")#) + + Bei Kanalnummern <1 oder >15 wird der Aufruf von + EUMEL-0 ignoriert. + + Falls die Hardware keine Inputinterrupts zur Verfügung stellt, + sollte ein Timer benutzt werden, um alle möglichen Input + quellen regelmäßig abzufragen. Dabei muß man allerdings den + goldenen Mittelweg zwischen zu häufiger (Systemdurchsatz + sinkt) und zu seltener Abfrage (Zeichen gehen verloren) such + en. Man sollte dabei nicht nur an die menschliche Tippge + schwindigkeit sondern auch an die höchste Baudrate denken, + die man für Rechnerkopplungen noch unterstützen will. *) + + Falls SHard Flußkontrolle für den Kanal + ausüben soll, muß er die Rückmeldung in AL + auswerten. Dabei ist mit einem geeigneten + Schwellwert zu arbeiten, da in der Regel die + sendende Gegenstelle einer Sendeunterbrechung + nicht sofort Folge leistet. + +#foot# +#f# +*) Eine weitere Möglichkeit, auf manchen Kanälen ohne Interrupts auszukommen, wird bei der IOCONTROL-Funktion +"weiter" beschrieben (siehe S.#topage("weiter")#).#a##end# + + Achtung: #on("i")#Keinesfalls darf 'inputinterrupt' rekursiv aufgerufen werden. + Normalerweise wird das automatisch verhindert, wenn man den + zugehörigen Hardwareinterrupt erst nach der 0-Routine + wieder freigibt. Falls das nicht möglich ist und unter bestimm + ten Umständen das nächste Zeichen abgeholt werden muß, + bevor die 0-Routine beendet ist, muß SHard einen eigenen + Puffer implementieren:#off("i")# + + hardwareinterrupt: + IF input interrupt aktiv + THEN trage zeichen in shard puffer ein ; + gib hardware interrupt frei + ELSE input interrupt aktiv := true ; + gib hardware interrupt frei ; + input interrupt ; + disable interrupt ; + WHILE shard puffer enthält noch + zeichen REP + nimm zeichen aus shard puffer ; + enable interrupt ; + input interrupt ; + disable interrupt + PER ; + input interrupt := false ; + enable interrupt + FI . + + + + #d("OUTPUT")# + + Eingang: AL Kanalnummer (1...15) + CX Anzahl auszugebender Zeichen + DS:BX Adresse der Zeichenkette + Ausgang: CX Anzahl der übernommenen Zeichen + C-Flag gesetzt <=> alle Zeichen übernommen + + Zweck: Ausgabe einer Zeichenkette. Diese ist (möglichst ganz) zwi + schenzupuffern, denn die Ausführung von OUTPUT sollte kein + Warten auf IO enthalten. Der Ausgabepuffer muß mindestens + 50, besser 100 Zeichen fassen können. Durch eine Interrupt + logik oder etwas Äquivalentes ist sicherzustellen, daß dieser + Puffer parallel zur normalen Verarbeitung ausgegeben wird. + Wenn die auszugebende Zeichenkette nicht vollständig in den + Puffer paßt, sollten trotzdem so viele Zeichen wie möglich + übernommen werden. Im weiteren Verlauf ruft EUMEL-0 dann + wieder OUTPUT mit dem Rest der Zeichenkette auf. + + Hinweis: OUTPUT kann mit CX=0 aufgerufen werden. Auch diese leere + Operation muß mit gesetztem C-Flag quittiert werden. + + Achtung: #on("i")#Keinesfalls darf innerhalb von OUTPUT die 0-Routine 'warte' + aufgerufen werden.#off("i")# + + Vorschlag: Falls der Kanal nicht existiert bzw. OUTPUT darauf unsinnig + ist, sollte vorgegaukelt werden, alle Zeichen seien ausgege + ben (CX unverändert und C-Flag gesetzt). + + + +#b("Terminals")# +#goalpage("term")# + +"Normale" #ib#Terminal#ie(1,", normales")#s können ohne weitere Unterstützung des SHards angeschlossen wer +den. Die zur Anpassung an den EUMEL-Zeichensatz *) notwendigen #ib#Umcodierungen#ie# +werden von den höheren Ebenen aus eingestellt. Da diese Umsetztabellen vom SHard +unabhängig sind, stehen automatisch alle so angepaßten Terminaltypen allen EUMEL- +Anwendern zur Verfügung! +#foot# +#f# +*) Siehe "EUMEL Benutzerhandbuch, Teil 3: Editor, 5. Zeichencode"#a##end# + +Für den Anschluß eines #on("b")##on("i")#integrierten #ib#Terminal#ie(1,", integriertes")#s#off("i")##off("b")#, in dessen Bildwiederholspeicher direkt gear +beitet wird, kann man häufig den Terminaltyp 'psi' verwenden (siehe auch "Exoten"). + +Näheres zu Terminaltypen und -anschlüssen findet man im "EUMEL Systemhandbuch" unter +den Stichwörtern #on("i")#Konfiguration#off("i")# und #on("i")#Konfigurierung#off("i")#. + + + +#bb("Drucker, ","Plotter")# +#goalpage("druck")# + +#ib#Drucker#ie# und Plotter werden vom EUMEL-System wie Terminals angesehen. Da in der Regel +der Rechner aber schneller Zeichen senden als der Drucker drucken kann, müssen solche +Geräte in der Regel mit Flußkontrolle angeschlossen werden (siehe S.#topage("fluss")#). + +Wenn Drucker oder Plotter über eine Parallelschnittstelle angeschlossen werden, kann man +auf diesem Kanal möglicherweise auf einen Ausgabepuffer verzichten. Voraussetzung ist +dabei, daß + + a) der Drucker einen eigenen Puffer hat und + b) der Puffer "schnell" gefüllt werden kann (< 0.1 ms/Zeichen). + +Dann kann man auf den bei der SHard-Routine OUTPUT geforderten Puffer verzichten und +die Zeichenkette direkt über die Parallelschnittstelle an den Drucker übergeben. Wenn der +Drucker 'Puffer voll' signalisiert, sollte die Zeichenübernahme bei OUTPUT abgebrochen +werden. *) #on("i")#Auf keinen Fall darf CPU-intensiv auf Freiwerden des Puffers gewartet werden!#off("i")# +#foot# +#f# +*) siehe auch IOCONTROL "frout", S.#topage("frout")##a##end# + + + +#b("Exoten")# +#goalpage("exot")# + +Exotische #ib#Terminal#ie(1," exotisches")#s (im Sinne dieser Beschreibung) sind solche, für die eine Umsetztabelle +im System (siehe Konfiguratorbeschreibung) nicht ausreicht bzw. nicht nötig ist (Beispiele: +Terminals, in deren Bildwiederholspeicher direkt gearbeitet wird; Terminals, die soweit pro +grammierbar sind, daß sie den EUMEL-Zeichencode können). + +Für solche Terminals muß in der Konfiguration der Terminaltyp '#ib#psi#ie#' eingestellt werden. +Dieser wirkt ohne Umcodierungen, d.h. die EUMEL-Codes (siehe Benutzerhandbuch 1.7 +Seite 106) werden direkt dem SHard zugestellt (wie bei 'transparent'), jedoch mit folgenden +Besonderheiten: + +Eingabeseitig werden zusätzlich folgende Codezuordnungen getroffen: + + Code Funktion + + 7 SV (Aktivierung: 'gib supervisor kommando:') + 17 STOP (Ausgabe auf diesen Kanal wird gestoppt) + 23 WEITER (Ausgabe läuft wieder weiter) + 4 INFO (System geht in Debugger, falls Debugoption) + + + +#bb("5.2 ","Block-IO")# +#goalpage("block")# + +Über Block-IO wickelt das System die Zugriffe zum Pagingmedium und zum Archiv ab. +Ferner ist daran gedacht, auch auf V.24-Schnittstellen Block-IO z.B. für Rechnerkopp +lung zuzulassen. Die Kanalnummer in Reg. AL unterscheidet diese Fälle. Außer beim Paging +(AL=0) wird ein Block-IO durch die ELAN-Prozeduren 'blockin' und blockout' induziert. + +Bei Block-IO wird immer ein 512 Byte großer Hauptspeicherbereich mit übergeben. Dieser +kann (im Gegensatz zu OUTPUT) direkt benutzt werden, d.h. es muß keine Umpufferung +erfolgen. + +Dieser Hauptspeicherbereich darf nur bei BLOCKIN verändert werden. + +SHard darf (anders als bei OUTPUT) erst dann zur Aufrufstelle zurückgeben, wenn die ver +langte Operation abgeschlossen ist. Treten während der Operation Wartezeiten auf, so muß +SHard die 0-Routine 'warte' aufrufen, damit das System andere Prozesse weiterlaufen +lassen kann. + +EUMEL-0 definiert bestimmte Funktionen für Hintergrund (Kanal 0) und Archiv (Kanal 31). +Operationen auf anderen Kanälen kann SHard nach Belieben implementieren und deren +Leistung seinen Installationen über ELAN-Pakete zur Verfügung stellen. Das System vergibt +auch in Zukunft für den Parameter in Register CX nur positive Werte (Bit 7 von CH = 0). +Der SHard kann selbst negative Codes einführen. + + + #d("BLOCKIN")# + + Eingang: AL Kanalnummer (0...32) + CX Parameter 1 + DX Parameter 2 + DS:BX Adresse des Hauptspeicherbereichs + Ausgang: AL undefiniert (darf also verändert werden) + CX Rückmeldecode + DS:BX darf verändert werden + + Der Inhalt des Hauptspeicherbereichs (<DS:BX>... <DS: + BX> +511) darf verändert sein. + + Zweck: "Einlesen" von Blöcken. Die genaue Wirkung hängt vom + Parameter und dem Kanal ab. + + Vorschlag: Falls der Kanal nicht existiert bzw. BLOCKIN darauf unsinnig + ist, sollte die Rückmeldung -1 in CX geliefert werden. + + + #d("BLOCKOUT")# + + Eingang: AL Kanalnummer (0...32) + CX Parameter 1 + DX Parameter 2 + DS:BX Adresse des Hauptspeicherbereichs + Ausgang: AL undefiniert (darf also verändert werden) + CX Rückmeldecode + DS:BX darf verändert werden + + Der Inhalt des Hauptspeicherbereichs darf #on("i")#nicht#off("i")# verändert + werden! + + Zweck: "Ausgeben" von Blöcken. Die genaue Wirkung hängt vom + Parameter und dem Kanal ab. + + Vorschlag: Falls der Kanal nicht existiert bzw. BLOCKOUT darauf un + sinnig ist, sollte die Rückmeldung -1 in CX geliefert wer + den. + + + #dx("warte")# (0-Routine) + + Ausgang: Alle Register undefiniert! + + Zweck: Diese Routine ist bei 'blockin' oder 'blockout' dann aufzu + rufen, wenn SHard im Augenblick nichts zu tun hat. Durch den + Aufruf von 'warte' erhalten andere Systemteile die Möglichkeit, + weiter zu arbeiten. Ein 'warte' kann bis zu ca. 1/4 Sekunde + Zeit aufnehmen. 'warte' darf nicht in Interruptroutinen und + Stream-IO verwendet werden! 'warte' zerstört alle Register, + bis auf die Segmentregister CS und SS! SHard muß davon + ausgehen, daß 'warte' seinerseits andere SHard-Kompo + nenten aufruft. + + +Die Verwendung der 0-Routine 'warte' soll hier an einigen Beispielen verdeutlicht wer +den: + + + blockout auf platte : + WHILE platte noch nicht frei REP + warte + ENDREP ; + uebertrage schreibbefehl an controller ; + uebertrage daten an controller . + + blockin von platte : + WHILE platte noch nicht frei REP + warte + ENDREP ; + uebertrage lesebefehl an controller ; + WHILE daten noch nicht gelesen REP + warte + ENDREP ; + hole daten vom controller . + + + blockout auf floppy : + seekbefehl an controller ; + WHILE seek noch nicht fertig REP + warte + ENDREP ; + setze dma auf schreiben block zur floppy ; + schreibbefehl an controller ; + WHILE schreiben noch nicht fertig REP + warte + ENDREP . + + blockin von floppy : + seekbefehl an controller ; + WHILE seek noch nicht fertig REP + warte + ENDREP ; + setze dma auf lesen block von floppy ; + lesebefehl an controller ; + WHILE lesen noch nicht fertig REP + warte + ENDREP . + + + +#b("Block-IO bei Hintergrund und Archiv")# +#goalpage("bhgarch")# + +#ib#Hintergrund#ie# (Kanal 0) und #ib#Archiv#ie# (Kanal 31) unterscheiden sich in den Link-Bedingungen +nur in der Kanalnummer. Die Aufrufe von BLOCKIN und BLOCKOUT werden mit folgenden +Eingangsparametern versorgt: + + #on("b")#BLOCKIN#off("b")# AL 0 bzw. 31 + CH 0 + CL Blocknummer DIV 65536 + DX Blocknummer MOD 65536 + DS:BX Hauptspeicheradresse + + Der angegebene 512-Byte-Block ist in den Hauptspeicher + ab <DS:BX> einzulesen. + + #on("b")#BLOCKOUT#off("b")# AL 0 bzw. 31 + CH 0 + CL Blocknummer DIV 65536 + DX Blocknummer MOD 65536 + DS:BX Hauptspeicheradresse + + Der Hauptspeicherbereich (<DS:BX>... <DS:BX>+511) ist + auf den angegebenen Block zu schreiben. + +Als Rückmeldungen sind zu liefern:#goalpage("errcod")# + + 0 Operation korrekt ausgeführt. + 1 Manuell behebbarer Fehler (z.B. Laufwerktür offen) + 2 Permanenter Fehler (z.B. Daten nicht lesbar) + 3 Versorgungsfehler (zu hohe Blocknummer) + +Zusätzlich zu der Rückmeldung muß bei CX <> 0 in DS:BX die Adresse eines Fehlerstrings +(Längenbyte + Fehlertext) geliefert werden. *) +#foot# +#f# +*) Diese Zusatzrückmeldung ist nur für die BLOCKIN/OUT Aufrufe auf Kanal 0/31 von Bedeutung. Sie wird nur von +EUMEL-0 beim Paging und im Hardwaretest ausgewertet.#a##end# + +#dx("Fehlerwiederholungen")#: Das EUMEL-System führt von sich aus Fehlerwiederholungen + beim Hintergrund- und beim Archivzugriff durch. SHard sollte + deshalb im Fehlerfall die Operation nicht selbst wiederholen, + sondern einen Lese/ Schreibfehler zurückmelden. So werden + dem EUMEL-System auch Soft-Errors gemeldet. In manchen + Fällen soll vor einem erneuten Lese- oder Schreibversuch der + Arm auf Spur 0 positioniert werden o.ä. Um das zu erreichen, + sollte SHard diese "Reparaturaktion" direkt im Anschluß an den + fehlerhaften Versuch durchführen. + +#dx("Kontrollesen")#: Falls Kontrollesen (nach jedem Schreibzugriff) notwendig ist, muß + das allerdings vom SHard durchgeführt werden. In der Regel + reicht es dazu, den geschriebenen Block "ohne Datentrans + port" zu lesen, so daß nur CRC überprüft wird. + +Will SHard weitere Archivlaufwerke zur Verfügung stellen, so kann er dafür Kanalnummern +(30,29..) vergeben. Auf ELAN-Ebene kann die archivierende Task durch 'continue (x)' das +Laufwerk 'x' ansteuern. + +Hinweis: Das System versucht Hintergrund und Archiv parallel zu betreiben, d.h. wenn + SHard bei der Hintergrundbehandlung das UP 'warte' aufruft, kann 'warte' sei + nerseits die Archivbehandlung des SHards aufrufen. Wenn beides z.B. denselben + Floppykontroller benutzt, muß SHard sicherstellen, daß das gut geht (z.B. durch + Semaphoren). + + +Sollen auch #on("b")#Disketten nach #ib#DIN 66 239#ie##off("b")# auf dem Archivkanal gelesen und geschrieben +werden können, müssen auf Kanal 31 zusätzlich Blöcke mit 'deleted data mark' gelesen und +geschrieben werden können. Dafür kann BLOCKIN (beim Lesen einer Diskette) als weitere +Rückmeldung liefern: + + 4 'Deleted data mark' gelesen. + +Ausgabeseitig wird ein entsprechendes BLOCKOUT benötigt: + + #on("b")#BLOCKOUT#off("b")# AL 31 + CH 40h + CL Blocknummer DIV 65536 + DX Blocknummer MOD 65536 + DS:BX Hauptspeicheradresse + + Der Hauptspeicherbereich (<DS:BX>... <DS:BX>+511) ist + mit der Kennung 'deleted data mark' auf den angegebenen + Block zu schreiben. + +Anmerkung: Diese Funktion muß nur implementiert werden, wenn Disketten nach DIN 66 239 + beschrieben können werden sollen. + + + +#b("Block-IO zur MS-DOS-Partition")# +#goalpage("bmsdosp")# + +Auf EUMEL-Rechnern, die mit einer Festplatte ausgerüstet sind, kann man einen Teil der +Platte als MS-DOS-Partition und einen anderen als EUMEL-Partition reservieren. Für den +Datenaustausch auf Dateiebene existiert EUMEL-Software, die über den Kanal 29 auf die +MS-DOS-Partition zugreift. Falls SHard dieses unterstützen will, muß er entsprechende +BLOCKIN/OUT-Operationen zur Verfügung stellen. Diese entsprechen den Operationen auf +Kanal 0: + + #on("b")#BLOCKIN#off("b")# AL 29 + CH 0 + CL Blocknummer DIV 65536 + DX Blocknummer MOD 65536 + DS:BX Hauptspeicheradresse + + Der angegebene 512-Byte-Block ist in den Hauptspeicher + ab <DS:BX> einzulesen. Hier bezieht sich die Blocknummer + auf die MS-DOS-Partition. Dabei muß Block 0 derjenige + sein, der den Urladesektor der MS-DOS-Partition enthält. + (Hier steht der Bios-Parameterblock.) Die weiteren Blöcke + werden genauso wie in der von MS-DOS verwendeten + Numerierung relativ zu diesem Urladesektor adressiert. + + #on("b")#BLOCKOUT#off("b")# AL 29 + CH 0 + CL Blocknummer DIV 65536 + DX Blocknummer MOD 65536 + DS:BX Hauptspeicheradresse + + Der Hauptspeicherbereich (<DS:BX>... <DS:BX>+511) ist + auf den angegebenen Block zu schreiben. Für die Blocknu + merierung gilt das oben beschreibenen. + +Als Rückmeldungen sind zu liefern: + + 0 Operation korrekt ausgeführt. + 1 Manuell behebbarer Fehler (z.B. Laufwerktür offen) + 2 Permanenter Fehler (z.B. Daten nicht lesbar) + 3 Versorgungsfehler (zu hohe Blocknummer) + + Wichtig: Wird ein Block angesprochen, der nicht zur MS-DOS-Parti + tion gehört, so muß 'Versorgungsfehler' (3) gemeldet werden. + + +Anmerkung: Diese Funktionen müssen nur implementiert werden, wenn Datenaustausch + mit MS-DOS-Partitionen auf Plattenmaschinen unterstützt werden soll. + + +#bb("5.3 ","IO-Steuerung")# +#goalpage("iocontrol")# + +Die IO-Steuerung erlaubt Steuerung und Zustandsabfragen der Kanäle. IO-Steuerung wird +(außer bei Kanal 0) auch durch 'control' in ELAN induziert. + +Der Funktionscode in CX unterliegt denselben Konventionen wie bei Block-IO, d.h. das +System verwendet nur positive Codes. Der SHard-Schreiber kann auch negative Codes für +Sonderzwecke vorsehen. + + + #d("IOCONTROL")# + + Eingang: AL Kanalnummer (0...32) + CX Funktionscode 1 + DX Funktionscode 2 + BX Funktionscode 3 + Ausgang: CX Rückmeldung + AL darf verändert werden, in einigen Fällen zusätzliche + Rückmeldung + C-Flag (in einigen Fällen zusätzliche Meldung) + + Zweck: abhängig von 'Funktionscode 1' (s.u.) + +Das System verlangt folgende Informations- und Steuerleistungen über IOCONTROL: + + #d("IOCONTROL ""typ""")# + + Eingang: AL Kanalnummer (0...31) + CX 1 + Ausgang: CX Kanaltyp + + Zweck: Informiert EUMEL-0, welche IO für den angegebenen Kanal + sinnvoll ist. Die Rückmeldung in CX wird bitweise interpre + tiert: + + Bit 0 gesetzt <=> 'inputinterrupt' kann kommen. + Bit 1 gesetzt <=> OUTPUT ist sinnvoll. + Bit 2 gesetzt <=> BLOCKIN ist sinnvoll. + Bit 3 gesetzt <=> BLOCKOUT ist sinnvol. + Bit 4 gesetzt <=> IOCONTROL "format" ist sinn + voll. + + Hinweis: #on("i")#Trotz dieser Informationsmöglichkeit wird nicht garantiert, daß + nur sinnvolle Operationen für den Kanal aufgerufen werden.#off("i")# + + + #d("IOCONTROL ""frout""")# + #goalpage("frout")# + + Eingang: AL Kanalnummer (1...15) + CX 2 + Ausgang: CX Anzahl Zeichen, die nächster OUTPUT übernimmt + C-Flag gesetzt <=> Puffer leer + + Zweck: Liefert Information über die Belegung des Puffers. Diese + Information wird von EUMEL-0 zum Scheduling benutzt. + + Achtung: #on("i")#Wenn EUMEL-0 längere Zeit kein OUTPUT gemacht hat, + muß irgendwann CX > 49 gemeldet werden.#off("i")# + + Hinweis: Unter Berücksichtigung des oben Gesagten darf "gelogen" + werden. Man kann z.B. immer 50 in CX zurückmelden, muß + dann aber schlechtere Nutzung der CPU bei Multi-User- + Systemen in Kauf nehmen. + + Falls auf dem angegebenen Kanal ein Drucker mit eigenem + Puffer über Parallelschnittstelle angeschlossen ist (siehe S.#topage("druck")# + ) und man auf einen SHard-internen Puffer verzichtet hat, + sollte bei 'Druckerpuffer voll' 0 in CX und 'NC' zurückge + meldet werden. Wenn aber Zeichen übernommen werden + können, sollte 50 in CX und 'C-Flag gesetzt' gemeldet wer + den. + + Vorschlag: Falls der Kanal nicht existiert oder nicht für Stream-IO zur + Verfügung steht, sollten 200 in CX und C-Flag gesetzt zu + rückgemeldet werden. + + + #d("IOCONTROL ""weiter""")# + #goalpage("weiter")# + + Eingang: AL Kanalnummer (1...15) + CX 4 + Ausgang: - + + Zweck: Das System ruft "weiter" für den in AL angegebenen Kanal + auf, wenn es wieder Eingabezeichen puffern kann. (siehe + auch: Flußkontrolle S.#topage("fluss")#) + + Hinweis: "weiter" wird von EUMEL-0 auch immer dann aufgerufen, + wenn ein Prozeß auf dem angegebenen Kanal auf Eingabe + wartet und keine Zeichen mehr gepuffert sind. Wenn der be + troffene Kanal von sich aus keine Interrupts erzeugt, kann + SHard dies benutzen, um durch Aufruf von 'inputinterrupt' ein + Eingabezeichen zuzustellen. + #on("i")#Diese Betriebsart sollte nicht für normale Terminalkanäle + eingesetzt werden. Denn dann wird die SV-Taste nur an + EUMEL-0 zugestellt, wenn ein Prozeß auf diesem Kanal auf + Eingabe wartet. Somit sind in dieser Betriebsart CPU-inten + sive Endlosschleifen nicht normal abbrechbar!#off("i")# + + + #d("IOCONTROL ""size""")# + + Eingang: AL Kanalnummer (0...31) + CX 5 + DX Schlüssel + Ausgang: CX Anzahl Blöcke MOD 65536 + AL Anzahl Blöcke DIV 65536 + + Zweck: EUMEL-0 ruft 'size' auf, um die Anzahl Blöcke zu erfahren, + die ein Block-IO-Kanal verkraften kann (Größe von Hin + tergrund und Archiven). Bei Archivlaufwerken, die mehrere + Formate bearbeiten können, dient dieser Aufruf auch zum + Einstellen des Formats für die folgenden blockin/blockout- + Operationen anhand des Schlüssels. + + Schlüssel: 0 Wenn möglich 'erkennend', sonst 'standard'. Im ersten + Fall erkennt SHard das Format der eingelegten Diskette + und stellt dieses ein. + + Die weiteren Schlüssel sind stets definierend. Dabei gibt es die + EUMEL-Standardformate: + + 1 5" 2D-40, Sektor 1..9, 512 Bytes + 2 5" 2D-80, Sektor 1..9, 512 Bytes + 3 5" HD-80, Sektor 1..15, 512 Bytes + 10 8" 1D-77, Sektor 0..15, 512 Bytes + 11 8" 2D-77, Sektor 0..15, 512 Bytes + + Zusätzlich kann man sämtliche Spezialformate angeben: + + 8192 * laufwerkstyp 1: 8" + 2: 5" + 3: 3" + + + 4096 * seiten 0: einseitig + 1: doppelseitig + + + 1024 * dichte 0: single + 1: double + 2: high + + + 256 * spuren 0: 35 + 1: 40 + 2: 77 + 3: 80 + + + 64 * sektorbytes 0: 128 + 1: 256 + 2: 512 + + + 32 * erster sektor 0: \#0 + 1: \#1 + + + sektoren pro spur 0 ... 31 + + So bezeichnet '8762' das Format 8" 1S-77 Sektor 1..26 a + 128 Bytes. + + Anmerkung: SHard sollte alle physisch möglichen EUMEL-Standard + formate unterstützen. Von den Spezialformaten sollten die für + den Datenaustausch wichtigen Formate berücksichtigt werden. + Die EUMEL-Standardformate (1,2,3,10,11) sollten auch über + die entsprechenden analytischen Codes erreicht werden. (Z.B. + bezeichnen 1 und 21929 dasselbe Format.) Die Numerierung + der Blöcke ist in jedem Fall seitenorientiert, d.h. entsprechend + den Standardformaten (siehe S.#topage("arch")#). + + Hinweis: Bei Archiven wird 'size' aufgerufen, nachdem der Archivträ + ger eingelegt wurde. D.h. SHard hat die Gelegenheit, die + Größe anhand des eingelegten Archivträgers zu bestimmen + (z.B. ob single- oder doublesided). + + Vorschlag: Diese Funktion sollte auf nicht vorhandenen und den + Stream-IO-Kanälen 0 liefern. Sie muß aber mindestens auf + Kanal 0 (Hintergrund) und Kanal 31 (Archiv) "echte" Werte + liefern. + + Achtung: #on("i")#Ausnahmsweise darf bei dieser IOCONTROL-Funktion die + 0-Routine 'warte' aufgerufen werden.#off("i")# + + + #d("IOCONTROL ""format""")# + + Eingang: AL Kanalnummer (0...31) + CX 7 + DX Schlüssel + Ausgang: CX Fehlercode wie bei Archiv-BLOCKOUT (siehe S.#topage("errcod")#) + + Zweck: Dient zum Formatieren einen Mediums. Diese Funktion kann + für jeden Kanal leer implementiert sein ('ret'). Sie sollte aber + "formatierend" (z.B. auf Kanal 31) arbeiten, falls auf diesem + Kanal die "typ"-Abfrage "Formatieren sinnvoll" liefert. Falls + (bei Diskettenlaufwerken) mehrere Formate möglich sind, + bestimmt der Schlüssel das gewünschte Format. + + Schlüssel: wie bei IOCONTROL "size" + + Achtung: #on("i")#Ausnahmsweise darf bei dieser IOCONTROL-Funktion die + 0-Routine 'warte' aufgerufen werden.#off("i")# + + + +#b("Konfigurierung serieller Schnittstellen")# +#goalpage("v24")# + +Bei Kanälen, die hardwaremäßig auf #ib#serielle Schnittstellen#ie# (#ib#V.24#ie#) zurückgeführt werden, sind +in der Regel die Größen + + - #ib#Baudrate#ie# (..., 2400, 4800, 9600, ...) + - #ib#Zeichenlänge#ie# (7 Bits, 8 Bits) + - #ib#Parität#ie# (keine, gerade, ungerade) + +einstellbar. Dafür muß SHard die IOCONTROL-Funktionen "baud" und "bits" zur Verfü +gung stellen. Diese werden in zwei Modi benutzt: + + a) #on("b")#einstellend#off("b")# + Läuft der aufrufende EUMEL-Prozeß auf dem privilegierten Steuerkanal (AL = 32), + wird der als Parameter mit übergebene #on("i")#adressierte Kanal#off("i")# auf die geforderten Werte + eingestellt, sofern das möglich ist. + + b) #on("b")#abfragend#off("b")# + Läuft der aufrufende EUMEL-Prozeß nicht auf Kanal 32 (AL <> 32), wird le + diglich abgefragt, ob der #on("i")#adressierte Kanal#off("i")# auf die übergebenen Werte eingestellt + werden könnte. + +Aufgrund des zweiten Modus können die höheren EUMEL-Ebenen dem Anwender bei der +Konfigurierung mitteilen, welche Werte sich auf dem jeweiligen Kanal einstellen lassen. Das +nutzt z.B. das Standard-Konfigurationsprogramm aus. + +Hinweis: Bei einigen Kanälen (z.B. bei einem integrierten Terminal oder einer Parallel + schnittstelle) sind Baudrateneinstellungen sinnlos. Bei anderen können sie nur + hardwaremäßig vorgenommen werden (Jumper, Dip Switches). In allen diesen + Fällen muß SHard bei allen Einstellungen 'unmöglich' melden. (Standardmäßig + wird der Anwender bei der Einstellung seiner Konfiguration dann auch nicht + danach gefragt.) + + + #d("IOCONTROL ""baud""")# + + Eingang: AL eigener Kanal (1...15 / 32) + CX 8 + DX adressierter Kanal + BX Schlüssel + Ausgang: CX Rückmeldung (0 = ok, 1 = nicht möglich) + + Zweck: Wird diese Routine auf dem Steuerkanal (AL=32) aufgeru + fen, wird die angegebene Baudrate für den durch Register DX + adressierten Kanal eingestellt, falls das möglich ist. + Wird diese Routine auf einem anderen Kanal als 32 aufge + rufen, informiert sie den Aufrufer lediglich, ob eine derartige + Einstellung des adressierten Kanals möglich wäre. + + Schlüssel: 1 50 Baud + 2 75 Baud + 3 110 Baud + 4 134.5 Baud + 5 150 Baud + 6 300 Baud + 7 600 Baud + 8 1200 Baud + 9 1800 Baud + 10 2400 Baud + 11 3600 Baud + 12 4800 Baud + 13 7200 Baud + 14 9600 Baud + 15 19200 Baud + 16 38400 Baud + + Anmerkung: In der Regel werden nicht alle Baudraten vom SHard unter + stützt werden. Bei V.24 Schnittstellen sollten aber minde + stens 2400, 4800 und 9600 Baud zur Verfügung stehen, + besser auch 300, 600, 1200 und 19200 Baud. + + Hinweis: Falls SHard-spezifisch weitere Baudraten implementiert + werden sollen, darf SHard hierfür negative Schlüsselwerte + (Register BX) vergeben. + + + #d("IOCONTROL ""bits""")# + + Eingang: AL eigener Kanal (1...15 / 32) + CX 9 + DX adressierter Kanal + BX Schlüssel + Ausgang: CX Rückmeldung (0 = ok, 1 = nicht möglich) + + Zweck: Wird diese Routine auf dem Steuerkanal (AL=32) aufgeru + fen, wird die angegebene Zeichenlänge (Bits pro Zeichen) und + Parität für den durch Register DX adressierten Kanal einge + stellt, falls das möglich ist. + Wird diese Routine auf einem anderen Kanal als 32 aufge + rufen, informiert sie den Aufrufer lediglich, ob eine derartige + Einstellung des adressierten Kanals möglich wäre. + + + Schlüssel: stop * 32 + par * 8 + (bit - 1) + + stop: 0 1 Stopbit + 1 1.5 Stopbits + 2 2 Stopbits + + par: 0 keine Parität + 1 ungerade Parität + 2 gerade Parität + + bit: 1...8 Bits pro Zeichen + + + Anmerkung: In der Regel werden nicht alle Kombinationen vom SHard + unterstützt werden. Bei V.24 Schnittstellen sollten aber mög + lichst 1 Stopbit, 7 und 8 Bits pro Zeichen und alle drei Pari + tätseinstellungen zur Verfügung stehen. + + Hinweis: Falls SHard-spezifisch weitere Einstellungen implementiert + werden sollen, darf SHard hierfür negative Schlüsselwerte + (Register BX) vergeben. + + + + +#b("Flußkontrolle")# +#goalpage("fluss")# + +Die stromorientierten Kanäle (1...15) werden nicht nur zum Anschluß schneller Geräte (wie +Terminals) verwendet, sondern auch, um langsame Geräte (wie Drucker) anzuschließen, die +die Daten u.U. nicht so schnell übernehmen können, wie sie der Rechner schickt. Dabei ist +auf eine geeignete Flußkontrolle zu achten (nicht schneller senden, als der Andere emp +fangen kann). Dieses Problem stellt sich auch bei einer Rechner-Rechner-Kopplung. Hier +ist in der Regel sogar zweiseitige Flußkontrolle notwendig. + +Als Flußkontrolle ist die #ib#REQUEST TO SEND/CLEAR TO SEND#ie# Logik der V.24-Schnitt +stelle oder das #ib#XON/XOFF#ie#-Protokoll zu verwenden. Das letztere kann auch bei Parallel +schnittstellen eingesetzt werden. + +Zur eingabeseitigen Flußkontrollsteuerung kann SHard die Rückmeldung der 0-Routine +'inputinterrupt' (siehe S.#topage("inp")#), die "stop" signalisieren kann, und die IOCONTROL-Funktion +"weiter" (siehe S.#topage("weiter")#)verwenden: + +Allerspätestens bei der 'inputinterrupt'-Rückmeldung AL=0 muß SHard +auf der V.24-Schnittstelle das Signal 'REQUEST TO SEND' wegnehmen bzw. XON senden +(oder +weiter einlaufenden Input selbst zwischenpuffern). Dadurch wird bei den meisten Fremd +rechnern ein weiteres Senden unterbrochen, sofern (im ersten Fall) das Signal 'REQUEST +TO SEND' dort mit dem V.24-Eingang 'CLEAR TO SEND' verbunden ist. Wird von +EUMEL-0 "weiter" aufgerufen, so kann auf dem ensprechenden Kanal wieder empfangen +werden (RTS setzen bzw. XON senden). In der Regel wird SHard schon reagieren müssen, +bevor der EUMEL-Puffer gänzlich gefüllt ist, da die Sendehardware nicht schnell genug +reagieren kann bzw. da noch sich noch Zeichen in Hardwarepuffern befinden können. + +Für die ausgabeseitige Flußkontrolle muß rechnerseitig ebenfalls das Signal 'CLEAR TO +SEND' bzw. der Empfang von XOFF/XON berücksichtigt werden. Wenn an der Schnittstelle +das 'CLEAR TO SEND' weggenommen wird, darf SHard keinen weiteren Output auf dieser +Schnittstelle machen, bis 'CLEAR TO SEND' wieder anliegt. Entsprechend muß der Empfang +von XOFF die Ausagbe anhalten und XON sie wieder starten. + +Bemerkung: Die meisten Systeme enthalten die CTS-Funktion schon in ihrer Hardware, so + daß im SHard dafür keine Vorkehrungen getroffen werden müssen. + + +Zur Einstellung der gewünschten Flußkontrolle eines Kanals dient die IOCONTROL-Funk +tion "flow". Ähnlich wie "baud" und "bits" wirkt auch "flow" nur auf Kanal 32 #on("i")#einstellend#off("i")# und +auf allen anderen Kanälen lediglich #on("i")#abfragend#off("i")#. + + + #d("IOCONTROL ""flow""")# + + Eingang: AL eigener Kanal (1...15 / 32) + CX 6 + DX adressierter Kanal + BX Modus + Ausgang: CX Rückmeldung (0 = ok, 1 = nicht möglich) + + Zweck: Wird diese Routine auf dem Steuerkanal (AL=32) aufgeru + fen, muß sie den gewünschten Flußkontrollmodus für den + adressierten Kanal einstellen. + Dabei sind folgende Modi festgelegt: + + BX= 0 Keine Flußkontrolle + BX= 1 XON/XOFF (in beide Richtungen) + BX= 2 RTS/CTS (in beide Richtungen) + BX= 5 XON/XOFF (nur ausgabeseitig) + BX= 6 RTS/CTS (nur ausgabeseitig) + BX= 9 XON/XOFF (nur eingabesetig) + BX=10 RTS/CTS (nur eingabeseitig) + + SHard wird hierdurch informiert, wie er auf "Puffer voll" und + "weiter" reagieren soll. Wenn keine Flußkontrolle gewünscht + wird (BX=0), muß SHard "stop" und "weiter" ignorieren; bei + BX=1 oder BX=9 muß bei "stop" XOFF und bei "weiter" XON + geschickt werden; bei BX=2 oder BX=10 muß bei "stop" das + Signal RTS auf low und bei "weiter" wieder auf high gesetzt + werden. Mit + "stop" ist hierbei das Unterschreiten des + Schwellwertes bei der Rückmeldung von + "inputinterrupt" gemeint. + + Bei BX=1 oder BX=5 müssen empfangene XON/XOFF-Zei + chen, bei BX=2 oder BX=6 das Signal CTS beachtet wer + den. + + Wird diese Routine auf einem anderen Kanal als 32 aufge + rufen, informiert sie den Aufrufer lediglich, ob der geforderte + Flußkontrollmodus auf dem adressierten Kanal einstellbar + wäre. + + Hinweis: Falls SHard-spezifisch weitere Flußkontrollmodi implemen + tiert werden sollen, darf SHard hierfür negative Moduswerte + (Register BX) vergeben. + + "weiter" wird von EUMEL-0 sehr oft aufgerufen. Es + ist daher nicht sinnvoll, jedesmal XON zu senden, da dies die Gegenstelle + damit überfluten würde. SHard muß sich + merken, ob der Kanal im XOFF-Zustand ist und + nur dann bei "weiter" ein XON senden. + + +#b("Kalender")# +#goalpage("kalender")# + +Die Datums- und Uhrzeitabfrage ist bei Rechnern mit eingebauter Uhr unnötig. EUMEL holt +sich Datum und Uhrzeit dann von SHard. + + #d("IOCONTROL ""calendar""")# + + Eingang: CX 10 + DX (1=Minute, 2=Stunde, 3=Tag, 4=Monat, 5=Jahr) + gewünscht + Ausgang: CX Rückmeldung + + Zweck: Erfragen von Datum und Uhrzeit. Falls keine Uhr vorhanden + ist, muß bei jedem Aufruf -1 zurückgemeldet werden, bei + eingebauter Uhr jeweils das Gewünschte (Minute: 0..59, + Stunde: 0..23, Tag: 1..7, Monat: 1..12, Jahr: 0..99). Die + Rückmeldung muß als BCD-Zahl erfolgen. + + Hinweis: Die Uhr darf zwischen zwei Aufrufen umspringen. Die daraus + resultierende Probleme werden auf höheren Ebenen abge + handelt. + + + + +#bb("6. SHard-","Interface Version")# +#goalpage("shdver")# + +Die #ib#Versionsnummer#ie# der Interface-Spezifikation, auf der SHard aufbaut, muß als 2-By +te-Konstante #ib#SHDVER#ie# in der SHard-Leiste stehen. Für das hier beschriebene Interface +muß sie den Wert 8 haben. + +So sind spätere Erweiterungen des SHard-Interfaces möglich, ohne daß alle SHard-Mo +duln geändert werden müssen. + + + +#bb("7. ","ID-Konstanten")# +#goalpage("ID")# + +SHard muß direkt hinter SHDVER vier 2-Byte-Konstanten ablegen. Diese können von den +höheren Ebenen durch die ELAN-Prozedur + + INT PROC #ib#id#ie# (INT CONST no) + +abgefragt werden. Dabei werden id(0) bis id(3) von EUMEL-0 geliefert, während SHard in +der Leiste die Werte für id(4) bis id(7) zur Verfügung stellen muß: + + ID4 #ib#Lizenznummer#ie# des SHards *) +#foot# +#f# +*) Dieser Wert muß mit der Nummer des Lizenzvertrags zwischen Implementierer und GMD übereinstimmen!#a##end# + + ID5 #ib#Installationsnummer#ie# des EUMEL-Anwenders **) +#foot# +#f# +**) Diese Nummer vergibt der Lizenznehmer an die von ihm belieferten Anwender.#a##end# + + ID6 zur freien Verfügung + + ID7 zur freien Verfügung + + + + +#bb("8. ","Zusätzliche Leistungen")# +#goalpage("shdelan")# + +Will der SHard-Implementierer zusätzliche Leistungen anbieten, die mit den Standardope +rationen nicht möglich sind, kann er weitere Codes für BLOCKIN, BLOCKOUT und +IOCONTROL zur Verfügung stellen. Um Überdeckungen mit Codes zu vermeiden, die von +EUMEL-0 intern verwendet oder erst später eingeführt werden, darf SHard für zusätzli +che Leistungen nur negative Werte als 'Funktionscode 1' verwenden. + + +Zum Ansprechen der neuen Leistungen stehen die ELAN-Prozeduren #on("i")#'#ib# blockout#ie#', '#ib#blockin#ie#'#off("i")# +und #on("i")#'#ib#control#ie#'#off("i")# zur Verfügung. + +Ferner steht dem SHard ein Parameterkanal (32) zur Verfügung. Funktionen, die (im Mul +ti-User) nicht jeder Task zur Verfügung stehen dürfen, müssen über diesen Kanal 32 abge +wickelt werden und dürfen nur dort wirken. + + + PROC blockout (ROW 256 INT CONST para, (* --> DS:BX *) + INT CONST funktion1, (* --> CX *) + funktion2, (* --> DX *) + INT VAR antwort) (* <-- CX *) + + PROC blockin (ROW 256 INT VAR para, (* --> DS:BX *) + INT CONST funktion1, (* --> CX *) + funktion2, (* --> DX *) + INT VAR antwort) (* <-- CX *) + + PROC control (INT CONST funktion1, (* --> CX *) + funktion2, (* --> DX *) + funktion3, (* --> BX *) + INT VAR antwort) (* <-- CX *) + +Hinweis: Der SHard darf für 'funktion 1' (CX) zusätzlich zu den hier beschriebenen Stan + dardcodes nur negative Codes vereinbaren. + + +Beispiel: + + Gibt eine Task, die durch 'continue (x)' an Kanal 'x' hängt, den Befehl + + control (-7,1200,13,antwort), + + so wird IOCONTROL mit (AL='x', CX=-7, BX=13, DX=1200) aufgerufen. Verläßt + SHard 'control' mit CX = 1, so enthält 'antwort' anschließend eine 1. + + +Hinweis: Um die zusätzlichen Leistungen dem Anwender einfach (und abgesichert) zur + Verfügung zu stellen, sollte man sie in ein ELAN-Paket einbetten und dieses + ebenfalls an die Anwender ausliefern. + + Beispiel: PACKET zusatz DEFINES fanfare, ... : + + PROC fanfare (INT CONST tonhoehe, dauer) : + + IF dauer < 0 + THEN errorstop ("negative dauer") + ELIF tonhoehe < 16 + THEN errorstop ("infraschall") + ELIF tonhoehe > 20000 + THEN errorstop ("ultraschall") + ELSE control (-37, 20000 DIV tonhoehe, dauer) + FI + + ENDPROC fanfare ; + + . . . + + + + +#bb("9. ","Spezialroutinen")# +#goalpage("ke")# + +Als Testhilfe und zur Fehlerdiagnose kann SHard in seine Routinen Kontrollereignisse ein +bauen. Das geschieht durch Aufruf der 0-Routine 'info'. Dieser EUMEL-Debugger wird im +Anhang A (siehe S.#topage("info")#) beschreiben. + + #dx("info")# (0-Routine) + + Aufruf: call dword ptr info + jr weiter + db ' text' + weiter: + + Zweck: Info wird aufgerufen. Dabei wird 'text' zur Identifikation des + Kontrollereignisses ausgegeben. Der übergebene Text darf + nicht mit 0h beginnen. + + Hinweis: Bei Systemen "ohne Info" (nur solche dürfen an Anwender + ausgeliefert werden) wird nur der Info-Text ausgegeben und + EUMEL-0 angehalten. + + Achtung: Da der Info selbst die hier beschriebenen Stream-IO-Routi + nen benutzt, darf man ihn von diesen Routinen aus (inputin + terrupt, OUTPUT, IOCONTROL "frout", IOCONTROL "weiter") + nicht aufrufen. Wenn die Ein-/Ausgabe auf Terminal 1 inter + ruptgetrieben läuft, dürfen die Interrupts beim Info-Aufruf + natürlich nicht gesperrt sein. + + +Falls SHard für bestimmte Aktionen, die selten durchgeführt werden (z.B. Formatieren), viel +Speicher benötigt, kann er diesen dynamisch anfordern und später wieder freigeben. + + #dx("grab")# (0-Routine) + + Eingang: BX Anfangsadresse des zu reservierenden Bereichs im + Datensegment von EUMEL-0, muß auf 512 Byte + ausgerichtet sein. + CX Länge des zu reservierenden Bereichs in 512-Byte- + Kacheln + Ausgang: CX Rückmeldecode + + Zweck: Wenn möglich wird der zu verlangte Bereich von EUMEL-0 + "leergekämpft" und SHard zur Verfügung gestellt. + Rückmeldecode: 0 ok, Speicher steht zur Verfügung + 1 grundsätzlich nicht möglich + 2 augenblicklich nicht möglich + + Achtung: Der Aufruf von 'grab' wird in der Regel 'warte' und Block-IO + auf Kanal 0 induzieren. + + Hinweis: Es wird empfohlen, Speicher ab 3800h anzufordern, da diese + Adresse stets im frei einplanbaren Paging-Bereich liegt. + + + #dx("free")# (0-Routine) + + Eingang: BX Anfangsadresse des freizugebenden Bereichs im Da + tensegment von EUMEL-0, muß auf 512 Byte ausge + richtet sein. + CX Länge des zu freizugebenden Bereichs als 'Bytes DIV + 512' + + Zweck: Der entsprechende Bereich muß vorher mit 'grab' beschafft + worden sein. Hiermit wird er wieder EUMEL-0 zur freien + Verfügung gestellt. + + +Für spezielle Fehlersituationen steht die 0-Routine 'shutup' zur Verfügung. Damit kann +SHard z.B. bei Netzausfall ein kontrolliertes Systemende erzwingen. Das ist allerdings nur +sinnvoll, wenn durch Batteriepufferung oder Ähnliches sichergestellt ist, daß noch genügend +Zeit bleibt, um alle Seiten auf den Hintergrund zurückzuschreiben. + + #dx("shutup")# (0-Routine) + + Zweck: Erzwingt Rückschreiben aller Seiten und Systemende, d.h. + entspricht der ELAN-Prozedur 'shutup'. + + Achtung: Der Aufruf von 'shutup' wird in der Regel 'warte' und + Block-IO auf Kanal 0 induzieren, abschließend wird 'sysend' + aufgerufen. +#page# +#cc("Teil 4: ","Tips zur Portierung")# +#goalpage("tips")# + + +#b("0-Version des SHards")# +#goalpage("0ver")# + + +Es wird empfohlen, zuerst eine "0-Version" des SHard zu entwickeln, die möglichst einfach +aufgebaut und nicht auf Effizienz und vollständige Ausnutzung der Betriebsmittel ausge +richtet sein sollte. Damit kann man rasch praktische Erfahrung gewinnen, die dann den +Entwurf und die Implementation des eigentlichen SHard erleichtert. Die 0-Version soll +te + + - nur die Kanäle 0 (Hintergrund), 1 (Terminal) und 31 (Archiv) behandeln, + + - keine Baudraten-, Zeichenlängen-, Paritäts- und Flußkontrolleinstellungen un + terstützen (immer 'nicht möglich' melden), + + - vorhandene (ROM-) Routinen möglichst nutzen, ohne sich um Unschönes wie "busy + wait" beim Floppy- bzw. Plattenzugriff zu grämen. + +Mit dieser 0-Version sollte man dann versuchen, EUMEL zu starten. Da der Hintergrund +beim ersten Mal noch leer ist, muß man das Hintergrund-Archiv (Archivfloppy mit +EUMEL-0 und höheren Ebenen) in das Archivlaufwerk einlegen und von dort laden. Der +Vortest sollte sich direkt nach dem Start folgendermaßen auf Terminal 1 melden: + + E U M E L - Vortest + + Terminals: 1, + RAM-Groesse (gesamt): ? kB + Pufferbereich: ? kB + Hintergrund-Speicher: ? kB + + Speichertest: ************ + +Man sollte während der ****-Ausgabe des Speichertests irgendein Zeichen eingeben. Das +EUMEL-System muß dann in das ausführliche Start-Menü überwechseln. (Andernfalls +funktioniert die Eingabe nicht richtig!) + +Als nächstes sollte man versuchen, den Hintergrund vom Archiv aus zu laden. (Diese Mög +lichkeit wird im Start-Menü angeboten.) Nach dem Ende dieser Operation wird der +EUMEL-Lauf automatisch beendet. Jetzt kann man das HG-Archiv aus dem Archivlauf +werk entfernen und das System neu starten. Dann sollte EUMEL-0 vom Hintergrund gela +den werden. + +Bei Problemen kann der "Info" (siehe S.#topage("info")#) hilfreich sein. Voraussetzung für seine Ver +wendung ist aber, daß die Terminal Ein-/Ausgabe schon funktioniert. + +Beim Start des EUMEL-Systems kann (wie im Systemhandbuch beschrieben) durch den +Konfigurationsdialog der Terminaltyp von Kanal 1 eingestellt werden. Falls das verwendete +Terminal in dieser Liste nicht aufgeführt wird und auch keinem der aufgeführten (in Bezug +auf die Steuercodes) gleicht, kann man z.B. + + - den neuen Terminaltyp an einem anderen EUMEL-Rechner verfügbar machen + (Umsetztabellen definieren) und per Archiv zum neuen Rechner tragen, + + - die notwendigen Umcodierungen per SHard durchführen. + +Diese Problematik entsteht bei Rechnern mit integriertem Terminal in der Regel nicht, weil +Steuerzeichen dort sowieso algorithmisch interpretiert werden müssen. In diesem Fall wird +man direkt die EUMEL-Codes als Grundlage wählen, so daß keine Umsetzungen erfor +derlich sind. + +Bei einer provisorischen Anpassung kann man auf Invers-Video ohne weiteres verzichten. + + +Im Gegensatz zu der 0-Version sollte man bei der eigentlichen SHard-Implementierung +darauf achten, die Möglichkeiten der Hardware effizient zu nutzen. Der Testverlauf entspricht +dann wieder im wesentlichen dem oben beschriebenen Vorgang. + + + +#b("Typische Fehler")# +#goalpage("fehler")# + + + a) SHard-Routinen zerstören Registerinhalte bzw. sichern sie beim Interrupt nicht + vollständig. Hierbei sollte man auch an die Segmentregister denken. + + b) 'call' bzw. 'ret' verändern den Stackpointer. + + c) Fehler bei der Interruptbehandlung führen zu Blockaden ("hängende Interrupts"). + + d) Cursorpositionierung außerhalb des Bildschirms bei einem internen Terminal + (Bildwiederholspeicher im Rechner) wird nicht abgefangen. Das führt dann zu + wildem Schreiben in den Hauptspeicher. + + e) 'warte' wird unerlaubt aufgerufen. ('warte' darf nur von BLOCKIN, BLOCKOUT, + IOCONTROL "size" und IOCONTROL "format" aus aufgerufen werden. Ferner + kann man 'warte' noch nicht beim Systemladen aufrufen!) + + f) OUTPUT-Verhaspler oder -Blockaden entstehen durch Fehlsynchronisation + zwischen dem Füllen des Ausgabepuffers durch die Routine OUTPUT und der + Interruptroutine, die den Puffer leert und ausgibt. + + g) IOCONTROL "frout" meldet in gewissen Situationen nie "mindestens 50 Zeichen + im Puffer frei" und "Puffer leer". Das kann schon im Vortest zu Output-Blok + kaden führen. + + h) Obwohl "frout" einen Wert größer als x meldet, nimmt "output" nicht alle x Zei + chen an. + + i) IOCONTROL "size" meldet falsche Werte. + + j) IOCONTROL verkraftet keine beliebigen (auch unsinnige) Werte. + + k) BLOCKIN bzw. BLOCKOUT geben die Kontrolle an das System zurück, bevor alle + Daten übertragen sind. (Sofort nach der Rückgabe geht EUMEL-0 davon aus, + daß der Puffer frei ist und anderweitig benutzt werden kann!) + + l) Fälschlicherweise wird davon ausgegangen, daß DS oder ES konstant bleiben. + + m) Die Stepping-Rate eines Festplattencontrollers wird falsch eingestellt, bezie + hungsweise die Platte wird nicht im 'buffered step mode' betrieben, obwohl + beschleunigend positionieren kann. Dadurch werden die Zugriffszeiten auf dem + Hintergrund unnötig verlangsamt. Man bedenke, daß man so einen Fehler leicht + übersieht, weil sich das System nicht fehlerhaft, sondern nur langsamer verhält. + Außerdem macht sich die Verlangsamung erst bemerkbar, wenn größere Teile des + Hintergrundes benutzt werden. + + n) Bei schnellem Zeichenempfang treten "Dreher" auf. Das deutet meistens auf + einen rekursiven Aufruf der 0-Routine 'inputinterrupt' hin. Dabei überholt dann + das zweite Zeichen das erste. + + o) Bei schnellem Zeichenempfang, speziell bei gleichzeitiger Ausgabe, gehen Ein + gabezeichen verloren oder werden verfälscht. In der Regel ist das auf Timing + probleme bei der Interruptbehandlung zurückzuführen. Interrupts gehen verloren + bzw. die Zeichen werden nicht schnell genug abgeholt. + + + +#b("Effizienzprobleme")# +#goalpage("eff")# + + a) Bei #on("i")##on("b")#V.24- und Parallelschnittstellen#off("i")##off("b")# ist schlechter Durchsatz in der Regel auf + Fehlverhalten von "frout" zurückzuführen. Auch kostet es in Multi-User- + Systemen sehr viel, wenn OUTPUT immer nur ein Zeichen übernimmt. (Dann läuft + der ganze Apparat der EUMEL-0-Maschine für jedes Zeichen wieder an.) + + Besonders bei der Parallelschnittstelle achte man darauf, daß nicht durch ung + lückliches Timing häufig Blockaden auftreten. So kann zu kurzes 'busy wait' auf + Freiwerden der Parallelschnittstelle dazu führen, daß jedes zweite Zeichen abge + lehnt wird, so daß OUTPUT faktisch zeichenweise arbeitet. Andererseits darf + natürlich 'busy wait' auch nicht auf Millisekunden ausgedehnt werden. + + + b) Wenn #on("i")##on("b")#Floppies ohne DMA#off("i")##off("b")# angeschlossen werden, kann man bei Single-User- + Systemen ohne weiteres 'busy wait' einsetzen, um nach dem Seek-Vorgang auf + den Block zu warten. Im Multi-User sollte das aber wenn irgend möglich um + gangen werden, da eine halbe Umdrehung immerhin ca. 100 ms kostet. + Falls nur ein Endeinterrupt nach jeder Floppyoperation zur Verfügung steht, kann + folgendes Verfahren günstig sein: + + seek befehl an controller ; + warten auf endeinterrupt ; + lesebefehl ohne datentransport auf sektor davor ; + warten auf endeinterrupt ; + lese oder schreib befehl auf adressierten sektor ; + cpu intensives warten und datentransport . + + Die Dummyoperation auf den Sektor vor dem adressierten dient dabei nur dazu, + ohne CPU-Belastung einen Zeitpunkt zu finden, wo man dem eigentlichen + Sektor möglichst nahe ist. Die Zeit, in der die CPU benötigt wird, sinkt damit auf + ca. 25 ms. Die Implementation dieses Algorithmus' ist aber nicht ganz einfach, da + die 0-Routine 'warte' wegen der verlangten kurzen Reaktionszeiten nicht ver + wendet werden kann. Alle 'warte auf ...' müssen also durch Interrupts realisiert + werden: + + setze interrupt auf lesen davor ; + stosse seek an ; + REP + warte + UNTIL komplette operation beendet ENDREP . + + lesen davor : + setze interrupt auf eigentliche operation ; + stosse lesen davor an . + + eigentliche operation : + ignoriere fehler beim datentransport ; + stosse lesen oder schreiben an ; + REP + REP UNTIL bereit ENDREP ; + uebertrage ein byte + UNTIL alles uebertragen ENDREP ; + melde komplette operation beendet . + + Hinweis: Solche Systeme sind über V.24 nicht netzfähig, da sie Eingabezeichen + verlieren werden. + + + c) Bei der Ansteuerung von #on("i")##on("b")#Harddisks#off("b")##off("i")# sollte man darauf achten, daß die 0-Rou + tine 'warte' nicht öfter als notwendig aufgerufen wird. Sonst wird das Paging + zugunsten der CPU-intensiven Prozesse zu stark verlangsamt. Z.B. kann man + bei vielen Plattencontrollern auf eine eigene Seek-Phase verzichten: + + beginne seek ; beginne seek und lesen ; + REP REP + warte warte + UNTIL fertig PER ; UNTIL fertig PER + beginne lesen ; + REP + warte + UNTIL fertig PER + + Hier braucht die linke Fassung immer mindestens ein 'warte' mehr als die rechte. + Bei starker CPU Belastung wird sie deshalb bis zu 100 ms länger für das Einlesen + eines Blocks benötigen. + + Eine ähnliche Situation kann auftreten, wenn die Platte in 256-Byte-Sektoren + unterteilt ist, so daß zu jedem EUMEL-Block zwei Sektoren gehören. Wenn + möglich sollte dann zwischen diesen beiden Sektoren kein 'warte' aufgerufen + werden. Andererseits darf natürlich auch nicht längere Zeit CPU-intensiv gewar + tet werden. Evtl. lohnt es sich in solchem Fall, mit der Sektorverschränkung zu + experimentieren. + +#page# +#cc("Anhang A: EUMEL-","Debugger ""Info""")# +#goalpage("info")# + + +Für interne Testzwecke gibt es den "Info". Systeme "mit Info" und "ohne Info" unterschei +den sich nur im EUMEL-0-Teil (Urlader). Der SHard-Implementierer erhält zum Test +Hintergründe "mit Info" und zur Auslieferung solche "ohne Info". Infofähige Systeme dürfen +nur von den SHard-Implementierern verwendet werden. + + #on("i")##on("b")#Achtung: Infofähige Systeme dürfen auf keinen Fall an Anwender ausgeliefert werden, + da vermittels Info alle Systemsicherungs- und Datenschutzmaßnahmen un + terlaufen werden können.#off("i")##off("b")# *) +#foot# +#f# +*) Ausnahmen von dieser Regel bedürfen der expliziten Zustimmung der EUMEL-Systemgruppe (GMD bzw. HRZ Bie +lefeld) und des jeweiligen Anwenders. Solche System müssen immer durch spezielle Schlüsselworte abgesichert werden.#a##end# + + +#b("Aufruf des Info")# +#goalpage("aufrinf")# + +Zum Aufruf des Infos gibt es drei Möglichkeiten: + + a) Beim Start des EUMEL-Systems geht man durch Eingabe eines beliebigen Zei + chens während des Vortests in den ausführlichen Start-Dialog. Durch Eingabe von + 'I' gelangt man dann in den Info-Modus. #on("i")#(Diese Möglichkeit wird in dem Startmenü + nicht aufgeführt.)#off("i")# + + b) Man kann den Info durch die ELAN-Prozedur 'ke' aufrufen. D.h. wenn das System + gestartet wurde und sich eine Task am Terminal mit "gib kommando" gemeldet hat, + kann man durch 'ke *return*' in den Info-Modus gelangen. + + c) Wenn sich am Terminal keine Task befindet, die auf Eingabe wartet, gelangt man + durch die Tastenfolge 'i *info*' (*info* meist = CTL d, zur Tastendefinition siehe + "Systemhandbuch, Konfigurierung") in den Info-Modus. + +Alle diese Möglichkeiten funktionieren nur bei infofähigen Systemen. + +Bei schweren Systemfehlern, die eine Weitermeldung an die höheren Ebenen des +EUMEL-Systems unmöglich machen, wird soweit möglich ebenfalls der Info aufgerufen. Bei +Systemen "ohne Info" wird lediglich eine Meldung auf Kanal 1 ausgegeben und das System +angehalten. + +Bevor das System Infokommandos annimmt, muß mit dem Kommando 'P' ein Paßwort +eingegeben werden. Lediglich dieses Kommando und das Kommando 'g' werden immer +angenommen. Das Paßwort kann mit dem Kommando 'yP' eingestellt werden. + +#b("Info-Format")# +#goalpage("forminf")# + +Der Info ist bildschirmorientiert. Beim Aufruf des Infos und nach den meisten Info-Kom +mandos werden die drei obersten Zeilen wie folgt aufgebaut: *) +#foot# +#f# +*) Bildschirmgetreues Verhalten kann der Info allerdings erst nach der Konfigurierung des Kanals zeigen. Vorher (d.h. +insbesondere beim Aufruf aus dem Vortest heraus) werden Cursorpositionierungen in der Regel nicht korrekt durchgeführt. #a##end# + +#limit(14.0)# +XYY TEXT +F AL AH CL CH DL DH BL BH SI DI SP BP PC DS ES +xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx + +#limit(12.0)# + +wobei + + X den Miniprozeß bezeichnet, der den Übergang in den Info veranlaßt hat (A=Archiv, + E=Elan, L=Lader, M=Müllabfuhr), + + YY den Maxiprozeß (Task) bezeichnet, der gerade durch den Elan-Prozessor bear + beitet wird (YY ist die hexadezimale Tasknummer), + + TEXT den Grund für den Info-Modus anzeigt, + +Die zweite und dritte Zeile zeigen die Inhalte der 8086/8088-Register an. In der untersten +Zeile erscheint die Eingabeaufforderung 'info:'. + + +#b("Info-Kommandos")# +#goalpage("cmdinf")# + +Info-Kommandos können in der 'info:'-Zeile mit dem Format + + [<zahl>]<buchstabe> + +gegeben werden oder, wenn der Cursor sich im Dump befindet, mit dem Format + + <buchstabe> + +wobei dann für <zahl> die der Cursorposition entsprechende Dumpadresse (modulo 2**16) +gesetzt wird (siehe '*cup*'). + +<zahl> ist immer in Hexaform einzugeben. + +'g' Der Info-Modus wird wieder verlassen. Dies ist allerdings bei harten Fehlern ge + sperrt. + +'z' Der Leitblock des angezeigten Maxiprozesses wird dargestellt, falls <zahl> = 0 ist, + sonst der Leitblock der Task mit der Nummer <zahl>. (Nur im ELAN-Miniprozeß). + +'q' Die Task mit der Nummer <zahl> wird nach dem nächsten 'g'-Kommando in den + Info überführt. Dies ist nötig, wenn man sich die Datenräume dieser Task anschauen + will ('s'). + +'s' Dumps werden auf den Datenraum <zahl> eingestellt. (s:=<zahl>) + Auch der Realspeicher kann hiermit in verschiedenen Modi eingestellt werden: + FF absolute Adressierung + 0 CS-relativ + 1 DS-relativ + 2 ES-relativ + 3 SS-relativ + +'l' Dumps werden auf die Länge <zahl> eingestellt. Desungeachtet kann man einen + versehentlich zu langen Dump durch eine beliebige Eingabe abbrechen. Dann wird + allerdings '*cup*' gesperrt (siehe unten). + +'p' Dumps werden auf die Byteadresse <zahl> eingestellt (p:= <zahl>; wmodus:= + FALSE). + +'w' Dumps werden auf die Wortadresse <zahl> eingestellt. Die vor jeder Dumpzeile + ausgegebene Adresse ist dann auch eine Wortadresse. Ein Wort = 2 Bytes. (p:=2* + <zahl>; wmodus: =TRUE) + +'k' Block <zahl> laden und per Dump anzeigen. Es erfolgt dabei eine Umstellung auf + den Realdatenraum (s=1). + +'P' Paßworteingabe: P<text>*return* + Erst nach diesem Kommando sind die übrigen Kommandos ausführbar. + +'x' Suchen nach Bytekette: + +--> xc text +--> xh xx xx ... +--> x + + Es wird nach 'text' bzw. Hexafolge 'xx xx ...' bzw. nach der durch das letzte 'x'- + Kommando eingestellten Bytekette gesucht. + Das Kommando ist durch *return* abzuschließen. + Die Suche beginnt ab Position 'p' und ist auf die Länge <zahl> Seiten (512 + Byte-Einheiten) begrenzt (0=unendlich). + Eine beliebige Eingabe bricht die Suche vorzeitig ab. + +'*return*' + Es wird der eingestellte Dump ausgegeben (siehe 's','l','p','w'). Bei wmodus (siehe + 'p', 'w') werden Wortadressen ausgegeben. + +'o' Wie '*return*', jedoch wird zuvor p := p+l gesetzt (zum Weiterblättern). + +'r' Freigabe der anderen Miniprozesse. + + Zunächst werden bei Übergang in den Info alle Miniprozesse gesperrt, um eine Ver + fälschung der Fehlersituation zu vermeiden. Bei manchen Kommandos an den Info + müssen aber andere Miniprozesse u.U. aktiv werden (z.B. beim 'k' der Lader). Wenn + dies erforderlich ist, meldet der Info: + 'paging erforderlich'. Man kann dann 'r' geben und das letzte Infokommando wie + derholen, oder mit anderen Kommandos fortfahren, falls man den Fehlerzustand noch + so beibehalten will. + +'y' Zweitfunktion ausführen. + +--> 'yP<text>*return*' + Neues Paßwort einstellen (max. 9 Zeichen). Dieses wird bei 'shutup' (erst + dann!) in Block 0 eingetragen. + +--> 'yt' Block <zahl> von Archiv lesen. Dient zum Test des Archivs. + Es wird eine Kachel freigemacht und der Block mit der Nummer <zahl> + eingelesen. Der Inhalt wird sofort angezeigt (wie Kommando 'k'). + +--> 'yb' Breakpoint an die Adresse <zahl> setzen. Es wird ein INT3 (für Aufruf von + Info) abgesetzt. Info verwaltet gleichzeitig bis zu 10 gesetzte Breakpoints. Die + Breakpointnummer kann man aus der nach jedem Setzen (und Löschen) + angezeigten Breakpoint-Tabelle entnehmen. Breakpoints sind nur im Real + speicher sinnvoll. Ein Aufruf meldet sich mit TEXT= 'break z--xxxx:yyyy' (z + = Breakpointnummer, xxxx = CS, yyyy = PC beim Aufruf des Breakpoints). + Wird Info mit 'g' verlassen, so stellt er zuvor die alten 8086/8088-Befehle + wieder her und führt sie an ihrem originalen Ort aus. Direkt danach wird der + Breakpoint wieder hergestellt. + +--> 'yc' Löscht den Breakpoint an der Adresse <zahl> und stellt die ursprüngli + chen Befehle wieder her. In der Breakpoint-Tabelle muß ein Breakpoint an + dieser Adresse vermerkt sein. + +--> 'yw' Zu anderen Miniprozeß wechseln. Nur sinnvoll, wenn ein anderer Mini unter + 'vor info' aufgeführt ist. + +--> 'yl' Lernmodus ein (wie beim Editor). + +--> 'ye' Ende Lernmodus. + +--> 'ya' Ausführen. Die zwischen 'yl' und 'ye' eingegebenen Zeichen werden dem Info + so vorgesetzt, als kämen sie von der Tastatur. + + Achtung: Rekursion ('ya' im Lernmodus) wird nicht abgefangen. Das Ge + lernte wird nach jedem Kommando, das die ersten drei Zeilen + wiederaufbaut (z.B. *return*), in der Zeile vier angezeigt, wobei + für Steuerzeichen eine Ersatzdarstellung erscheint (%x mit + x=code (code (zeichen) +code ("A")), also z.B. %M für *re + turn*). + +--> 'y *return*' + Wie *return*, jedoch wird der Dump auch beim Ausführen (ya) ausgegeben. + (Ein gelerntes *return* führt im Ausführmodus nicht zum Dump). + +'*cup*' *) (Cursor up). Umschaltung in den Modus zum Ändern in Dumps. +#foot# +#f# +*) Falls der Kanal noch nicht konfiguriert ist, muß man natürlich eine Taste betätigen, die den EUMEL-Code für Cursor +Up erzeugt. In der Regel ist das CTL c. Falls das Terminal ohne Konfigurierung keine Cursorpositionierungen durchführt, ist +dieser Modus nicht sehr gut benutzbar.#a##end# + Der Cursor fährt in den Dump und kann mit den Cursortasten dort bewegt + werden. Wird eine Hexazahl jetzt eingegeben, so wird diese als Inhalt des + Bytes eingetragen, auf dem der Cursor gerade steht. Dies funktioniert auch + auf beliebigen Datenräumen. Info beantragt dann bei der Speicherverwal + tung einen Schreibzugriff für die entsprechende Datenraumseite, so daß + Änderungen mit der Copy-on-Write-Logik erfolgen, also nur taskspezi + fisch sind (durch 'q' eingestellt). Für diese Task sind die Änderungen aller + dings dann permanent, da sie auch auf den Hintergrund wirken. + + Hinweis: Dumpt man mit 'k' einen Block und ändert dann darin, so sind + diese Änderungen u.U. nur temporär, da der Info kein Rückschrei + ben des Blockes veranlaßt. + + Achtung: Jede Eingabe, die kein Positionierzeichen und kein gültiges Zahl + zeichen ist, beendet diesen Modus. Das neue Zeichen wird als + Info-Kommando aufgefaßt, wobei <zahl> auf die aktuelle + Adresse gesetzt wird. + (Für 'yc' / 'yb' sinnvoll: Man setzt den Cursor auf die Stelle, an der + ein Break ausgelöst werden soll und gibt 'yc'/'yb'). + Somit wird dieser Änderungsmodus üblicherweise durch *return* + beendet. + +#b("Einige Systemadressen")# +#goalpage("sysaddr")# + +Der Info nützt nur wenig, wenn man nicht weiß, was man sich anschauen soll. Wesentliche +Angaben über die Systemstruktur enthält das 'Brikett' (interne Systemdokumentation für +Projekt Mikros der GMD). Da diese etwas allgemeiner gehalten ist, geht sie nicht auf imple +mentationsabhängige Konstanten ein. Diese sind hier aufgeführt. + +Ab 1s100h liegt die 'ktab'. Sie enthält Informationen, welche Blöcke an welcher Stelle des +Arbeitsspeicher liegen: In der Kachel mit der Adresse 512*i befindet sich der Inhalt des +Blockes, dessen Nummer in ktab+i, ktab+100h+i steht. Ferner enthält die Tabelle, zu +welchem Datenraum (drid) und welcher Seite des Datenraums der Inhalt gehört. (Nur rele +vant, wenn die Prozeßnummer <> 255 ist). + +Steuerbits: 2**0 : Inhalt wird gerade transportiert (zum HG oder Archiv). + 2**1 : Inhalt ist identisch mit Inhalt auf HG. Wird beim Schreiben auf die + Kachel (per Software) zurückgesetzt. + 2**2 : Schreiberlaubnis (siehe Brikett). + 2**3 : Inhalt wurde kürzlich benutzt. Solche Kacheln werden 'weniger stark' + verdrängt. + + + ktab frei niederwertige Blocknummer + + +80h frei frei Steuerbits + + +100h frei höherwertige Blocknummer + + +180h frei frei Prozeßnummer + + +200h frei frei drid (prozeßspezifisch) + + +280h frei frei Seitennummer (höherw.) + + +300h frei frei Seitennummer (niederw.) + + ^ ^ + -- unbenutzt -- -- Beginn echter Kacheln + -- Beginn der Anforderungen + + +Der 'Beginn echter Kacheln' hängt von der Größe der 8086/8088-Teile ('urlader') ab (i.A. +30h < i < 40h). + +'Beginn der Anforderungen' liegt bei i=2. Es handelt sich um Blocknummern von zu laden +den Blöcken. Ist der höherwertige Teil der Blocknummer gleich FDh, so ist dies keine Anfor +derung. + +Blocknummern > FF00h stehen für Blöcke mit dem Inhalt 512 FFh's und werden nie auf +dem Hintergrundmedium gespeichert. + + + +1sA00h enthält den DR-Eintrag des drdr (siehe Brikett). + + +'musta': Das System fordert Checkpoints und Müllabfuhren über die Zelle 'musta' an. Diese + findet man mit dem Info durch + + xc musta + + (hierfür ist der Text 'musta:' vor der Zelle abgesetzt). + + Die Zelle selbst enthält + + FFh : Keine Müllabfuhr oder Checkpoint + 01h : Müllabfuhr + 02h : Checkpoint + 03h : beides + 04h : Systemendecheckpoint + 0Bh : System auf Archiv schreiben ('save system') + F0h : Müllabfuhr und Checkpoint sind geperrt (nur durch Setzen im Info + möglich) + + Durch Einsetzen der Werte mit dem Info kann die entsprechende Operation ver + anlaßt werden. Beim Einsetzen darf der Info nicht im 'r'-Zustand (siehe Eingabe + 'r') stehen; zum Ausführen der Operation muß 'r' (man bleibt im Info) oder 'g' (Info + verlassen) gegeben werden. + + +1s480h-4FFh: + enthält die Aktivierungstabelle. Ist (480h+i)=01h, so ist die Task i aktiv. Hin + weis: 4FFh enthält immer 01h, ohne daß dieser Zelle eine Task zugeordnet ist. + + +#b("Leitblock")# +#goalpage("pcb")# + +Mit dem 'z'-Kommando wird der Leitblock einer Task dargestellt. Es werden Hexapaare, +gefolgt von einer Bezeichnung, ausgegeben. In der folgenden Beschreibung werden die +Hexapaare durch a,b,c dargestellt. + + a b c icount Der virtuelle Befehlszähler der Task steht auf (cMOD4)* + 10000h+b*100h+a = <ic> im Datenraum 4 dieser Task. + Durch die Eingabefolge: + 4s<ic>w*return* + kann man sich den Code, der ausgeführt werden soll, ansehen. + + Bit 2**7 von c zeigt den Fehlerzustand an. + Bit 2**6 von c zeigt 'disable stop' (siehe Benutzerhandbuch) + an. + Bit 2**4 zeigt vorzeichenlose Arithmetik an (Compilierung). + + a b lbas Die lokale Basis steht auf 10000h+b* 100h+c = <lb> im + Datenraum 4 (Wortadresse). + + a b hptop Der Arbeitsheap geht von 30000h (Byteadr.) bis (aMOD16)* + 10000h+b* 100h+(aDIV16)*10h (Byteadr!). + + a b channel Die Task hängt an Kanal 100h*b+a (Terminalnummer). 0 = + kein Terminal angekoppelt. + + a b taskid Die Tasknummer der betrachteten Task ist a. (b ist die Ver + sionsnummer zum Abdichten von 'send'/ 'wait'). + +Um den Code, auf den der 'icount' zeigt, zu interpretieren, ziehe man das Brikett zu Rate. + + +Hinweis: Wenn der Info einen internen Fehler anzeigt, und auch bei 'ke', ist der durch 'z' + angezeigte Leitblock u.U. nicht aktualisiert. Man kann dies durch die Eingaben 'r', + 'g' erzwingen. (Der Info stellt wegen 'r' dem Interpreter einen Restart zu, der dann + beim 'g' den Leitblock aktualisiert und den Befehl erneut aufsetzt). Tritt dabei der + Fehler nicht wieder auf, handelte es sich um einen transienten Fehler (z.B. der + Codeblock war noch im Einlesen und ist jetzt voll da). So etwas kann z.B. passie + ren, wenn der SHard den Abschluß einer Leseoperation zu früh meldet. + + + + + + + + + + + + diff --git a/doc/porting-8086/8/source-disk b/doc/porting-8086/8/source-disk new file mode 100644 index 0000000..8aeb5a2 --- /dev/null +++ b/doc/porting-8086/8/source-disk @@ -0,0 +1 @@ +porting/portdoc-x86-8.img diff --git a/doc/porting-mc68k/1985.11.26/doc/Port.68000 b/doc/porting-mc68k/1985.11.26/doc/Port.68000 new file mode 100644 index 0000000..0ca6840 --- /dev/null +++ b/doc/porting-mc68k/1985.11.26/doc/Port.68000 @@ -0,0 +1,2173 @@ +#type ("trium8")##limit (12.0)# +#start(2.0,1.5)# +#type("triumb36")# +#free(4.0)# + EUMEL + Portierungs + handbuch + MC68000 +#type("triumb18")# +#free(1.5)# + Stand 26.11.85 +#page(1)# +#type ("trium8")##limit (12.0)# +#block# +#pagelength(18.4)# +#head# +#center#- % - + + +#end# +#type("triumb12")#Inhalt#a# + + + +Teil 1: Einführung #topage("ein")# +#free(0.3)# + Zweck dieses Handbuchs #topage("zweck")# + Referenzliteratur #topage("reflit")# + Minimale Hardwarevoraussetzungen #topage("hardw")# + Systemdurchsatz #topage("durchsatz")# + Softwarekomponenten des EUMEL-Systems #topage("kompo")# + Anlieferung des MC68000-EUMEL-Systems #topage("anlief")# + +Teil 2: Allgemeine Strukturen #topage("allgem")# +#free(0.3)# + Hintergrund #topage("hg")# + Archiv #topage("arch")# + Hauptspeicher #topage("speicher")# + +Teil 3: SHard-Interface Spezifikation #topage("shardifc")# +#free(0.3)# + 0. Vorbemerkungen #topage("vor")# + Zur Notation #topage("not")# + Link-Leisten #topage("leist")# + Allgemeine Link-Bedingungen #topage("link")# + Interrupts #topage("intr")# + 1. System laden #topage("laden")# + 2. Systemstart und -ende #topage("start")# + 3. Speicherverwaltung #topage("spver")# + Hauptspeicher #topage("haupt")# + Speicherfehler #topage("memerr")# + 4. Zeitgeber #topage("zeit")# + 5. Kanäle #topage("channel")# + 5.1 Stream-IO #topage("stream")# + Terminals #topage("term")# + Drucker, Plotter #topage("druck")# + Exoten #topage("exot")# + 5.2 Block-IO #topage("block")# + Block-IO bei Hintergrund und Archiv #topage("bhgarch")# + 5.3 I/O-Steuerung #topage("iocontrol")# + Konfigurierung serieller Schnittstellen #topage("v24")# + Flußkontrolle #topage("fluss")# + Kalender #topage("kalender")# + 6. SHard-Interface Version #topage("shdver")# + 7. ID-Konstanten #topage("ID")# + 8. Zusätzliche Leistungen #topage("shdelan")# + 9. Spezialroutinen #topage("ke")# + +Teil 4: Tips zur Portierung #topage("tips")# +#free(0.3)# + Nullversion des SHards #topage("0ver")# + Typische Fehler #topage("fehler")# + Effizienzprobleme #topage("eff")# + +Anhang A: EUMEL-Debugger "Info" #topage("info")# +#free(0.3)# + Aufruf des Infos #topage("aufrinf")# + Info-Format #topage("forminf")# + Info-Kommandos #topage("cmdinf")# + Einige Systemadressen #topage("sysaddr")# + Leitblock #topage("pcb")# + +Anhang B: Einige EUMEL-Begriffe #topage("glossar")# +#page# +#cc("Teil 1: ","Einführung")##goalpage("ein")# + + +#b("Zweck dieses Handbuchs")##goalpage("zweck")# + +Dieses Portierungshandbuch wendet sich an diejenigen, die das EUMEL-System auf +einem neuen Rechnertyp implementieren wollen. Es ist Teil einer Serie von Portierungs +handbüchern für verschiedene Prozessortypen. Dieses bezieht sich auf Rechner mit +MC68000-Prozessoren. + +Zum Betrieb eines EUMEL-Systems wird dieses Handbuch nicht benötigt! + + + +#b("Referenzliteratur")##goalpage("reflit")# + + + "EUMEL Benutzerhandbuch" + + "EUMEL Systemhandbuch" + + "EUMEL Quellcode der insertierten ELAN-Pakete" + + "MC68000 16-bit microprocessor - Users Manual" + Motorola, 1982 + + "68000 Assembler Reference" + XENIX Group, Microsoft Corp., 1982 + + "Anhang zu '68000 Assembler Reference'" + TA Nürnberg, 1984 + + +Siehe auch die Vorbemerkungen zur Notation in Teil 3 (S. #topage("not")#), sowie die Begriffserklä +rungen im Anhang B (S. #topage("glossar")#). + + +#b("Minimale Hardwarevoraussetzungen")##goalpage("hardw")# + +Um das EUMEL-System effizient einsetzen zu können, sollte die Hardware mindestens +folgenden Kriterien genügen: + + #ib#CPU#ie# Die MC68000-CPU sollte mit mindestens 8.0 MHz arbeiten. Falls die + Buszugriffe durch einen CRTC o.ä. verlangsamt werden, sollte die + echte MC68000-Leistung durchschnittlich mindestens einem unge + bremsten 8.0 MHz System entsprechen. + Seltene Verlangsamungen (z.B. nur bei I/O-Operationen) spielen bei + diesen Überlegungen keine Rolle. + + RAM Das System sollte über mindestens 256 KByte #ib#Hauptspeicher#ie# verfü + gen. + + #ib#Hintergrund#ie# Als Hintergrundmedium sind #ib#Diskette#ie#, #ib#Platte#ie# und RAM bzw. ROM + denkbar. + + Kapazität: + > 300 K, besser > 400 K (Single-User) + > 750 K, besser > 1000 K (Multi-User) + + Zugriff: *) +#foot# +#f#*) Hier ist die durchschnittliche Zugriffszeit auf einen 512 Byte großen Block gemeint. Für Platten und Disketten kann +man sie als Summe der Positionierzeit über die halbe Anzahl der Spuren und der Zeit einer halben Umdrehung be +rechnen. +#a# +#end# + < 500 ms (Single-User) + < 200 ms (Multi-User) + + #ib#Archiv#ie# Als Archiv wird meistens eine Diskette eingesetzt. Aber auch Band + oder Kassette sind denkbar. Die Anforderungen an Kapazität und + Geschwindigkeit sind anwendungsspezifisch. + + #ib#Bildschirm#ie# Angestrebt werden sollte ein Bildschirm mit 24 Zeilen zu je 80 Zeichen + (oder größer). Kleinere Bildschirme sind anschließbar, aber mit 40 Zei + chen pro Zeile läßt sich nicht mehr komfortabel arbeiten. + Rollup und freie Cursorpositionierung sind notwendige Voraussetzun + gen, invers-video ist erwünscht, aber nicht notwendig. Weiterhin + werden die Funktionen 'Löschen bis Zeilenende' und 'Löschen bis + Schirmende' benötigt. + + #ib#Tastatur#ie# An Steuertasten sollten mindestens ESC und die vier Cursortasten + vorhanden sein. Dabei ist es günstig, wenn die Cursortasten ergono + misch als Block bzw. Kreuz angeordnet sind. EUMEL benötigt weitere + Steuertasten für HOP, RUBIN, RUBOUT und MARK. Dafür können + beliebige, anderweitig nicht benötigte Tasten der Tastatur gewählt + werden. + + + +#b("Systemdurchsatz")##goalpage("durchsatz")# + +Da das EUMEL-System auf dem Prinzip des Demand Paging aufbaut, hängt der System +durchsatz von + + - CPU Leistung + - Speichergröße (RAM) + - Geschwindigkeit beim Hintergrundzugriff (Diskette, Platte) + +ab. Mit zunehmender Benutzerzahl steigen in der Regel die Anforderungen an das Paging +(Hintergrund-Zugriff) schneller als an die CPU. In diesem Bereich kann man die System +leistung dann durch mehr Speicher und/oder eine schnellere Platte in größerem Umfang +steigern. Dabei läßt sich eine langsame Platte teilweise durch mehr RAM und umgekehrt +wenig RAM durch eine schnelle Platte ausgleichen. + + + +#b("Softwarekomponenten des EUMEL-Systems")##goalpage("kompo")# + +Das EUMEL-System besteht aus mehreren Schichten: + + + EUMEL 2: Standardpakete, Editor, ... + + EUMEL 1: ELAN Compiler + + EUMEL 0: Systemkern (EUMEL-0-Maschine, EUMEL-0) + + EUMEL -1: SHard + + H a r d w a r e + + +Dieses #ib#Schichtenmodell#ie# ist nach oben offen und kann deshalb um beliebig viele (höhere) +Schichten erweitert werden. + +EUMEL > 0 Die Standardsoftware der Schichten > 0 ist in der Sprache ELAN ge + schrieben (siehe "EUMEL Quellcode"). Dementsprechend sind alle Schich + ten oberhalb der EUMEL-0-Maschine prozessor- und rechnerunabhän + gig, d.h. Anpassungen an einen neuen Rechnertyp sind nicht erforderlich. + +EUMEL 0 Die sogenannte "EUMEL-0-Maschine" enthält alle Basisoperationen und + hängt davon ab, welchen Prozessortyp der Rechner als CPU verwendet. Sie + existiert für verschiedene Prozessortypen. Hier wird nur auf den Typ + MC68000 Bezug genommen. Bei der Portierung auf einen MC68000- + Rechner wird die MC68000-EUMEL-0-Maschine ohne Anpassungen (!) + übernommen. + +EUMEL -1 Diese Schicht stellt das Interface zwischen der EUMEL-0-Maschine und + der eigentlichen Hardware (vom Prozessor abgesehen) dar. Insbesondere + umfaßt sie alle Routinen zur Ansteuerung peripherer Geräte (Gerätetreiber). + Diese Schicht wird "SHard" genannt ("S"oftware-"Hard"ware Interface). + +Der SHard ist der einzige Teil des Systems, der bei der Portierung auf einen MC68000- +Rechner angepaßt bzw. neu geschrieben werden muß. Deshalb besteht der größte Teil +dieses Handbuchs aus der Spezifikation des MC68000-SHards. + + + +#b("Anlieferung des MC68000-EUMEL-Systems")##goalpage("anlief")# + +Der Implementierer erhält die EUMEL-Software auf Disketten. Dabei stehen folgende +Standardformate zur Wahl: + + Diskette 200 (8"), 1D, 77 Spuren, 16 Sektoren (\#0...\#15) zu 512 Byte + + Diskette 130 (5.25"), 2D, 40 Spuren, 9 Sektoren (\#1...\#9) zu 512 Byte *) +#foot# +#f#*) 48 tpi +#a# +#end# + + +Die Diskettenlieferung **) enthält +#foot# +#f#**) Zu Inhalt und Zweck der angelieferten Disketten siehe EUMEL Systemhandbuch, Teil 1: System einrichten. +#a# +#end# + + - Single-User Hintergrund + - Multi-User Hintergrund + - Standardarchive + - ggfs. Archive mit weiterer Anwendersoftware (installationsspezifisch) + +Dabei enthält der Hintergrund auch die EUMEL-0-Maschine (oft auch als "Urlader" +bezeichnet). + +#on("i")#Bitte gehen Sie vorsichtig mit diesen Mutterdisketten um. Verwenden Sie sie nur als +Quelle beim Kopieren. Sie sollten nur auf Kopien davon arbeiten!#off("i")# +#page# +#cc("Teil 2: ","Allgemeine Strukturen")##goalpage("allgem")# + + +#b("Hintergrund")##goalpage("hg")# + +Der Hintergrund ist in 512 Bytes große Blöcke unterteilt. Sie werden durch Blocknummern +(0, 1, 2, ...) adressiert. Die physische Ablage der Blöcke auf dem Hintergrundmedium +bleibt dem SHard überlassen. Er kann sie z.B. linear oder versetzt anordnen. Man sollte +darauf achten, daß Positionierungen auf logisch "nahe" Blöcke möglichst schnell gehen +sollten. Deshalb ist in der Regel zylinderorientierte Anordnung der oberflächenorientierten +vorzuziehen. + +Falls auf dem Hintergrundmedium spezielle Blöcke z.B. für Bootstrap und SHard freige +halten werden sollen, muß das bei der Abbildung der Hintergrundblocknummern auf die +Sektoren der Diskette bzw. der Platte berücksichtigt werden. + +Aufbau des Hintergrundes: + + Block 0 Systemetikett + + Block 10...10+k-1 EUMEL-0-Maschine (z.Zt. ist k=200; dieser Wert ist nur + für EUMEL-0 von Bedeutung) + + Block 1...9, 10+k ... Paging-Bereich + + +Aufbau des #ib#Systemetikett#ie#s (#ib#Block 0#ie#): + + Byte Wert/Aufgabe + + 0...5 "EUMEL-"; Kennzeichen für EUMEL-Hintergrund. + 6...11 Versionsnummer in druckbaren Zeichen. Sie stellt sicher, daß System- + kern und Hintergrund kompatibel sind. + 12 zur Zeit ohne Bedeutung + 13 enthält Wert 0 , wenn System im Shutupzustand ist. + 14..15 Systemlaufzähler (14=low, 15=high). Wird bei jedem Systemstart um 1 + erhöht. + 16..35 Reserviert; zur Zeit ohne Bedeutung + 36..37 Aus historischen Gründen für interne Zwecke belegt. + 38..69 Hier kann eine Installationsnummer geführt werden. + 70..79 Info-Paßwort + 80 =0 Normalzustand + =1 Kompresslauf erforderlich (System frisch von Archiv geladen) + 81...255 Reserviert. + 256..511 Kann von SHard beliebig verwendet werden. + + + +#b("Archiv")##goalpage("arch")# + +Wie der Hintergrund, sind die Archive in 512 Bytes große Blöcke unterteilt *). Bisher gibt +es folgende #d("Standardformate")#: +#foot# +#f#*) Der genaue Aufbau der Archivblöcke ist weder für den SHard-Implementierer, noch für den Benutzer von Be +deutung. SHard hantiert nur mit Blöcken aufgrund von Blocknummern, unabhängig vom Inhalt der Blöcke. Der Benut +zer "sieht" nur Datenräume bzw. Dateien, unabhängig von ihrem Format auf dem Archiv. +#a# +#end# + + + Diskette 200 (8"), 1D, 77 Spuren, 16 Sektoren (\#0...\#15) zu 512 Byte + Diskette 200 (8"), 2D, 77 Spuren, 16 Sektoren (\#0...\#15) zu 512 Byte + + Block Seite Spur Sektor + + 0 0 0 0 + 16 0 1 0 + 77*16 1 0 0 + + n n DIV (77*16) n MOD (77*16) DIV 16 n MOD 16 + + + Diskette 130 (5.25"), 2D, 40 Spuren, 9 Sektoren (\#1...\#9) zu 512 Byte + + Block Seite Spur Sektor + + 0 0 0 1 + 9 0 1 1 + 40*9 1 0 1 + + n n DIV (40*9) n MOD (40*9) DIV 9 n MOD 9 + 1 + + + Diskette 130 (5.25"), 2D, 80 Spuren, 9 Sektoren (\#1...\#9) zu 512 Byte + + Block Seite Spur Sektor + + 0 0 0 1 + 9 0 1 1 + 80*9 1 0 1 + + n n DIV (80*9) n MOD (80*9) DIV 9 n MOD 9 + 1 + + + Diskette 130 (5.25"), HD, 80 Spuren, 15 Sektoren (\#1...\#15) zu 512 Byte + + Block Seite Spur Sektor + + 0 0 0 1 + 15 0 1 1 + 80*15 1 0 1 + + n n DIV (80*15) n MOD (80*15) DIV 15 n MOD 15 + 1 + + +Selbstverständlich können auch andere #ib#Archivformate#ie# implementiert werden, falls das aus +Hardwaregründen notwendig ist oder sich dadurch wesentliche Verbesserungen (z.B. in +der Kapazität) ergeben. + +Wenn irgend möglich sollte aber mindestens eines der oben aufgeführten Standardformate +unterstützt werden - evtl. als zusätzliches Format -, um den Austausch zwischen ver +schiedenen Rechnertypen zu vereinfachen. + +#on("i")#Hinweis: Um den Datenaustausch zwischen verschiedenen Rechnertypen zu vereinfa + chen, sollten möglichst alle hardwaremäßig möglichen Standardformate (min + destens lesend) unterstützt werden. Dabei sollte SHard sich automatisch auf + das Format der jeweils eingelegten Diskette einstellen:#off("i")# + + + Laufwerkstyp Diskettentyp(en) + + 8" 1D 8" 1D + 8" 2D 8" 2D, 1D + + 5" 2D-40 5" 2D-40 + 5" 2D-80 5" 2D-80, 2D-40 *) + 5" HD-80 5" HD-80, 2D-80, 2D-40 *) + +#foot# +#f#*) Bei der Behandlung von 40-Spur-Disketten auf 80-Spur-Laufwerken gelten meistens folgende Regeln: + a) Lesen funktioniert sicher. + b) Schreiben ist unsicher, funktioniert aber häufig. + c) Formatieren funktioniert fast nie. +#a# +#end# + + + +#b("Hauptspeicher")##goalpage("speicher")# + +Der #ib#Speicher#ie# wird EUMEL-0 vom SHard in maximal vier Speicherbereichen (M0...M3) +zugewiesen. Die Anfangsadresse eines solchen Bereiches muß ein Vielfaches von 512B +sein. M0 muß immer vorhanden sein, M1, M2 und M3 nur in speziellen Betriebsarten: + + #d("M0")# #on("b")#allgemeines #ib#RAM#ie(1,", allgemeines")##off("b")# + Dieser Bereich muß immer vorhanden sein. Bei den meisten Rechnern liegt der + Systemkern nicht in einem ROM, sondern wird von SHard in das RAM geladen. + Das geschieht dann an den Anfang von M0. Der Rest wird für Tabellen und als + Pagingbereich benutzt. M0 umfaßt deshalb meistens allen verfügbaren Spei + cher, bis auf den Platz für SHard, Boot-ROM und Bildwiederholspeicher. **) +#foot# +#f#**) Der im Tabellenspeicher liegende 'ktab' ist für die Verwaltung von max. 2048 Kacheln (=1MB) ausgelegt. Der +Speicherbedarf des Systemkerns liegt bei 80KB, für Tabellen werden 40KB benötigt. Dies sollte man bei der Angabe +von M0SIZE berücksichtigen. +#a# +#end# + + #d("M1")# #on("b")#Systemkern-#ib#ROM#ie(1,", Systemkern")##off("b")# + Gibt es nur bei Rechnern, die den Systemkern in einem ROM haben. (M0 wird + dann nur für Tabellen und als Pagingspeicher eingesetzt.) + + #d("M2")# #on("b")#Hintergrund-#ib#ROM#ie(1,",Hintergrund")##off("b")# + Gibt es nur bei Rechnern, die nicht Diskette oder Platte sondern ROM und + RAM als Hintergrundspeicher verwenden. + + #d("M3")# #on("b")#Hintergrund-#ib#RAM#ie(1,",Hintergrund")##off("b")# + Gibt es nur bei Rechnern, die nicht Diskette oder Platte sondern ROM und + RAM oder RAM allein als Hintergrundspeicher verwenden. + +Damit sind drei verschiedene Betriebsarten des EUMEL-Systems möglich: + + #d("Normalbetrieb")#: M0 (> 256 KB) + Hintergrundgerät (Platte oder Diskette) + Archivgerät (Diskette) + + Im Normalbetrieb befindet sich der Hintergrund auf einer Platte oder Diskette + RAM wird für den Systemkern und zum Paging eingesetzt. Alle mittleren und + größeren Systeme verwenden den Normalbetrieb. + + + #d("Minibetrieb")#: M0 (> 256 KB) + M3 (mindestens 300 KB) + Archivgerät (Diskette) + + Im Minibetrieb wird RAM als Hintergrundspeicher eingesetzt. Dieser wird beim + Einschalten über das Archivgerät geladen und beim Abschalten ('shutup') + wieder zurückgeschrieben. + + + #d("ROM-Betrieb")#: M0 (>40 KB) + M1 (>60 KB) + M2 (>170 KB) + M3 (>60 KB) + Archivgerät (Kassettenrecorder oder Diskettenlaufwerk) + + Im ROM-Betrieb stehen Systemkern und Standardteil des Hintergrundes im + ROM. Der übrige Hintergrund befindet sich im RAM. *) +#foot# +#f#*) Für ROM-Betrieb benötigt man eine Spezialversion des Systemkerns. +#a# +#end# + +#page# +#cc("Teil 3: SHard ","Interface Spezifikation")##goalpage("shardifc")# + + +#bb("0. ","Vorbemerkungen")##goalpage("vor")# + + +#b("Zur Notation")##goalpage("not")# + +Im folgenden wird zwischen #d("0-Routinen")#, die dem SHard vom EUMEL-0-System zur +Verfügung gestellt werden, und +#d("SHard-Routinen")# unterschieden, die der SHard implementieren muß. Damit dieser Unter +schied bei der Spezifikation deutlich wird, werden 0-Routinen folgendermaßen aufgeführt: + + name (0-Routine) + +Zusätzlich werden 0-Routinen grundsätzlich klein und SHard-Routinen groß geschrie +ben. + +MC68000-Befehle werden wie im "Anhang zu '68000 Assembler Reference'", (TA, 1984) +notiert: + + moveq \#27,d0 + addw d3,d1 + + +Hexadezimale Zahlen werden durch ein vorangestelltes '/' gekennzeichnet: + + /12 = 18 + /1f = 31 + /ffff = 65535 + + +Achtung: Die Übergabe von Integer-Parametern zwischen SHard und EUMEL-0 erfolgt + grundsätzlich in den niederwertigen 16 Bits des jeweils angegebenen Daten + registers. + +#b("Link-Leisten")##goalpage("leist")# + +Die Verbindung zwischen SHard und EUMEL-0 erfolgt über zwei Tabellen. In der +"0-Leiste" stellt EUMEL-0 dem SHard verschiedene 0-Routinen zur Verfügung. Diese +Leiste beginnt an der Adresse M0 (im Normal- oder Minimodus) bzw. M1 (im ROM- +Modus): + + Adresse Assemblerbefehl + + M0 + 0 eumel0id: .ascii "EUMEL jj-mm-tt " !Kennung mit Datum + +16 eumel0blocks: .word ... !Anzahl EUMEL0-Bloecke auf HG + +18 hgver: .word 173 !HG-Versionsnummer + +20 cputype: .word 4 !MC68000 oder kompat. CPU + +22 eumel0ver: .word mmmtt !EUMEL0-Version (mmm=1 --> Jan.84) + +24 shdvermin: .word 8 !Minimum bzw. Maximum fuer die + +26 shdvermax: .word 8 ! SHard-Versionsnummer + +28 systemstart: jmp ... !Ab hier stehen Sprungbefehle zu + +34 inputinterrupt: jmp ... ! den entsprechenden 0-Routinen + +40 timerinterrupt: jmp ... + +46 warte: jmp ... + +52 shutup: jmp ... + +58 info: jmp ... + + +Für die Gegenrichtung muß SHard der 0-Maschine die "SHard-Leiste" zur Verfügung +stellen: + + Adresse Assemblerbefehl + +SHDID+ 0 SHDID: .ascii "SHARD jj-mm-tt " !Kennung mit Datum + +16 SHDVER: .word 8 !Versionsnummer d. SHard-Schnittstelle + +18 MODE: .word !Modusbits: + BITEUDEL = 0 ! EUMEL-0-Bloecke auf HG freigeben + BITNORMAL = 1 ! Normalbetrieb + BITMINI = 2 ! Minibetrieb + BITROM = 3 ! ROM-Betrieb + +20 ID4: .word !ID-Konstanten (s.S. #topage("ID")#) + +22 ID5: .word ! dito + +24 ID6: .word ! dito + +26 ID7: .word ! dito + +28 OUTCHAR: jmp !Ab hier stehen Sprungbefehle in die + +34 OUTPUT: jmp ! entsprechenden SHard-Routinen + +40 BLOCKIN: jmp + +46 BLOCKOUT: jmp + +52 IOCONTROL: jmp + +58 SYSEND: jmp + +64 SYSABORT: jmp + +70 M0START: .long !Startadr bzw. + +74 M0SIZE: .long ! Länge (in Bytes) des Bereiches M0 + +78 M1START: .long ! dito f. M1 + +82 M1SIZE: .long + +86 M2START: .long ! dito f. M2 + +90 M2SIZE: .long + +94 M3START: .long ! dito f. M3 + +98 M3SIZE: .long + + + +#b("Allgemeine Link-Bedingungen")##goalpage("link")# + +In der Regel sind sowohl 0-Routinen als auch SHard-Routinen durch 'jbsr' aufzurufen: + + jbsr <routine> + +Ausnahmen von dieser Regel sind im folgenden stets besonders vermerkt. + +Generelle Link-Bedingung (für SHard- und 0-Routinen) ist: + + Alle Register - bis auf die jeweils spezifizierten Ausgangsparameter und die 'condi + tion code'-Flags im Status Register *) - bleiben unverändert. +#foot# +#f#*) Condition-Code-Flags sind i.a. nach dem Aufruf einer Routine undefiniert. Ausnahmen sind natürlich die Flags, +die als Ausgangsparameter in manchen Fällen definiert sind. +#a# +#end# + +Jede SHard-Routine muß also alle Register, die sie verändert und die keine Ausgangs +parameter sind, retten und wiederherstellen. Im Gegenzug braucht SHard beim Aufruf von +0-Routinen selbst keine Register zu retten. + + + +#b("Interrupts")##goalpage("intr")# + +Zwei externe Ereignisse (Zeitgeber und Eingabe, siehe S.#topage("zeit")# und S.#topage("inp")#) werden von +EUMEL-0 behandelt. Die entsprechenden Interrupts muß SHard per 'jbsr' an 0-Routinen +weiterleiten. +Die Register (bis auf die Parameterregister) werden von den aufzurufenden 0-Routinen +selbst gesichert. Die normale Interrupt-Sequenz im SHard sieht dann folgendermaßen +aus: + + intadr: movl d0,(sp)- + movw <parameter>,d0 + jbsr <routine> + andw \#/fcff,sr ! interrupt level freigeben + movl (sp)+,d0 + rti + +Achtung: SHard muß die Interrupt-Routinen im 'disable-int'-Modus anspringen, d.h. im + Status Register muß der korrekte Interrupt-Level gesetzt sein. (MC68000 setzt + beim Interrupt schon automatisch die Interrupt-Level-Flags.) + + + + + +#bb("1. System ","laden")##goalpage("laden")# + +SHard muß die EUMEL-0-Software vor dem eigentlichen Start an den Anfang des Spei +cherbereiches M0 laden. EUMEL-0 befindet sich auf dem Hintergrund von Block 10 ab. +Der erste Block von EUMEL-0 enthält am Anfang die 0-Leiste. Dort steht an der +Byteadresse 16 die Größe 'eumel0blocks'. Sie gibt an, wieviel Blöcke konsekutiv geladen +werden müssen. Hat sie beispielsweise den Wert 80, müssen die Blöcke 10 bis 89 gela +den werden. + + Achtung: Zu diesem Zeitpunkt kann SHard die oben aufgeführten 0-Routinen natür + lich noch nicht benutzen. Insbesondere dürfen die Laderoutinen nicht + 'warte' aufrufen. Das wird hier besonders betont, weil der Hintergrundzugriff + beim eigentlichen Systemlauf in der Regel 'warte' verwenden wird. + + Hinweis: Der erste Block von EUMEL-0 enthält in den ersten fünf Bytes den Text + "EUMEL", um eine Identifikation durch den SHard-Lader zu ermöglichen. + +Es wird empfohlen, nach folgendem Verfahren zu laden: + + IF archivgeraet enthaelt diskette AND eumel 0 auf archiv + THEN lade eumel 0 vom archiv + ELIF eumel 0 auf hintergrund + THEN lade eumel 0 vom hintergrund + ELSE laden unmoeglich + FI . + +So kann man auch bei einem frisch formatierten Hintergrundmedium einen neuen Hinter +grund (mit EUMEL-0) einspielen, indem man ein Hintergrundarchiv vor dem Systemstart +in das Archivgerät legt. Dann wird EUMEL-0 von dort geladen, so daß man den Hinter +grund dann wie im Systemhandbuch beschrieben vom Archiv auf das Hintergrundmedium +kopieren kann.*) +#foot# +#f#*) Kopiervorgänge (Archiv -> Hintergrund) werden von EUMEL-0 erledigt, so daß SHard keine derartigen Routinen +enthalten muß. +#a# +#end# + + + + +#bb("2. System","start und -ende")##goalpage("start")# + +SHard muß alle für den Rechner notwendigen (Hardware-) Initialisierungen durchführen +und erst danach die EUMEL-0-Maschine starten ('systemstart'). + + #d("systemstart")# (0-Routine) + + Eingang: a0 = Adresse der SHard-Leiste + + Aufruf: jmp systemstart + + Zweck: Die EUMEL-0-Maschine wird gestartet. Alle notwendigen Hard + wareinitialisierungen (z.B. der Peripheriebausteine) müssen vorher + schon geschehen sein. + + Hinweis: SHard muß den Stackpointer (a7) "vorläufig" definieren (etwa 100 + Langworte reichen dafür aus), da beim Sprung in EUMEL-0 Inter + rupts auftreten können. + + + + #d("SYSEND")# + + Parameter: - + + Zweck: Hiermit wird SHard das Ende eines Systemlaufs mitgeteilt. Somit + können evtl. notwendige Abschlußbehandlungen durchgeführt + werden. SHard kann mit 'rts' zu EUMEL-0 zurückkehren, muß + aber nicht. Diese Routine kann z.B. dazu benutzt werden, die + Hardware auszuschalten oder in ein umgebendes System zurück + zukehren (EUMEL als Subsystem). In den meisten Fällen wird die + Routine leer implementiert werden, d.h. nur aus 'rts' bestehen. + + + + +#bb("3. ","Speicherverwaltung")##goalpage("spver")# + + +#b("Hauptspeicher")##goalpage("haupt")# + +Der Hauptspeicher umfaßt die Teile des MC68000-Speichers, die EUMEL-0 verwalten +darf. + + + +#b("Speicherfehler")##goalpage("memerr")# + +Falls die Hardware Speicherfehler aufgrund von Paritybits, ECC oder ähnlichem feststellen +und an SHard melden kann, sollte das zur Erhöhung der Systemsicherheit genutzt wer +den. + +Wenn SHard (z.B. über Interrupt) einen Speicherfehler mitgeteilt bekommt, sollte er, wenn +möglich, eine entsprechende Meldung ausgeben und das System anhalten: + + basta: jra basta + + +Wenn Speicherfehler mit Sicherheit bemerkt werden, verhindert diese Reaktion, daß die +Fehler auf dem Hintergrund festgeschrieben werden und evtl. später zu Systemfehlern +führen. + +Der Anwender kann dann durch Hardware-Reset auf den letzten Fixpunkt des EUMEL- +Systems zurücksetzen. So verliert er zwar evtl. die letzten Minuten seiner Arbeit, behält +aber auf alle Fälle ein konsistentes System. + + + + +#bb("4. ","Zeitgeber")##goalpage("zeit")# + +SHard muß einen Zeitgeberinterrupt erzeugen, der ca. 10 bis 100 mal pro Sekunde auftritt. +Dabei ist die 0-Routine 'timerinterrupt' aufzurufen. Ohne diesen Interrupt wird die Uhr +nicht geführt, und die Zeitscheibenlogik für das Timesharing fällt aus. + + #d("timerinterrupt")# (0-Routine) + + Eingang: d0 = seit letztem Zeitgeberinterrupt vergangene Zeit (in ms) + + Zweck: Wird von EUMEL-0 für interne Uhren und für das Scheduling + (Zeitscheibenlogik) verwendet. Es werden keine hohen Genauig + keitsanforderungen an die Zeitangaben bei #on("i")#einzelnen#off("i")# Interrupts + gestellt. Um EUMEL-0 eine genaue Realzeituhr zu ermöglichen, + sollte die so erzeugte Zeitangabe #on("i")#im Mittel#off("i")# aber möglichst genau + sein, d.h. die Summe der innerhalb einer Minute so übergebenen + Werte sollte zwischen 59995 und 60005 liegen. + + + + +#bb("5. ","Kanäle")##goalpage("channel")# + +Einiges zum Kanalkonzept: + +Das System kennt die Kanäle 0..32. + + Kanal 0 ist der Systemhintergrund. + Kanäle 1..15 sind für Stream-IO (Terminals, Drucker, ...) vorgesehen. + Kanal 31 ist der Standard-Archivkanal. + Kanal 32 ist der Parameterkanal. + +Die Kanäle 2..30 können installationsabhängig verfügbar sein oder auch nicht. Deren +Funktion ist dann Absprachesache zwischen Installation und SHard. + +Kanäle können über Block-IO (BLOCKOUT, BLOCKIN) oder Stream-IO (OUTPUT,..) +angesprochen werden. Das System erfährt über IOCONTROL, welche Betriebsart des +Kanals sinnvoll ist. + +#on("i")##on("b")#Achtung: Alle Kanaloperationen müssen grundsätzlich für alle Kanäle (0...32) aufgerufen + werden können. Dabei können Operationen auf nicht vorhandenen Kanälen und + unsinnige Operationen (z.B. Stream-IO auf Kanal 0) leer implementiert werden.#off("b")# + (Dafür werden im folgenden bei jeder SHard-Routine Vorschläge gemacht.)#off("i")# + + + +#bb("5.1 ","Stream-IO")##goalpage("stream")# + +Über Stream-IO wickelt das System die übliche zeichenorientierte Ein-/Ausgabe auf Ter +minals, Druckern, Plottern usw. ab. Stream-IO wird nur für die Kanäle 1...15 gemacht. + + #d("inputinterrupt")# (0-Routine)#goalpage("inp")# + + Aufruf: movl kanalnummer,(sp)- !1...15 + movl zeichen,(sp)- !rechtsbündig + jbsr inputinterrupt + lea 8(sp),sp !restore stackpointer + + Zweck: SHard muß EUMEL-0 durch Aufruf dieser Routine mitteilen, daß + eine Eingabe vorliegt. + + Hinweise: EUMEL-0 puffert die Zeichen. EUMEL-0 signalisiert den Zustand + "Puffer voll" durch IOCONTROL "stop" und ignoriert weitere + Eingaben, bis wieder Platz im Puffer vorhanden ist. (siehe + IOCONTROL "stop" und "weiter", S.#topage("weiter")#) + + Bei Kanalnummern <1 oder >15 wird der Aufruf von EUMEL-0 + ignoriert. + + Falls die Hardware keine Inputinterrupts zur Verfügung stellt, sollte + ein Timer benutzt werden, um alle möglichen Inputquellen regel + mäßig abzufragen. Dabei muß man allerdings den goldenen Mittel + weg zwischen zu häufiger (Systemdurchsatz sinkt) und zu seltener + Abfrage (Zeichen gehen verloren) suchen. Man sollte dabei nicht + nur an die menschliche Tippgeschwindigkeit sondern auch an die + höchste Baudrate denken, die man für Rechnerkopplungen noch + unterstützen will. *) + +#foot# +#f#*) Eine weitere Möglichkeit, auf manchen Kanälen ohne Interrupts auszukommen, wird bei der IOCONTROL-Funk +tion "weiter" beschrieben (siehe S.#topage("weiter")#). +#a# +#end# + +Achtung: #on("i")#Keinesfalls darf 'inputinterrupt' rekursiv aufgerufen werden. Nor + malerweise wird das automatisch verhindert, wenn man den + zugehörigen Hardwareinterrupt erst nach der 0-Routine wieder + freigibt. Falls das nicht möglich ist und unter bestimmten Umstän + den das nächste Zeichen abgeholt werden muß, bevor die + 0-Routine beendet ist, muß SHard einen eigenen Puffer imple + mentieren:#off("i")# + + hardwareinterrupt: + IF input interrupt aktiv + THEN trage zeichen in shard puffer ein; + gib hardware interrupt frei + ELSE input interrupt aktiv := true; + gib hardware interrupt frei; + input interrupt; + disable interrupt; + WHILE shard puffer enthaelt noch zeichen + REP nimm zeichen aus shard puffer; + enable interrupt; + input interrupt; + disable interrupt + PER; + input interrupt := false; + enable interrupt + FI. + + + #d("OUTPUT")# + + Eingang: d0 = Kanalnummer (1...15) + d2 = Anzahl auszugebender Zeichen + a0 = Adresse der Zeichenkette + Ausgang: d2 = Anzahl der übernommenen Zeichen + + Zweck: Ausgabe einer Zeichenkette. Diese ist (möglichst ganz) zwischen + zupuffern, denn die Ausführung von OUTPUT sollte kein Warten + auf IO enthalten. Der Ausgabepuffer muß mindestens 50 Zeichen + fassen können. Durch eine Interruptlogik oder etwas Äquivalentes + ist sicherzustellen, daß dieser Puffer parallel zur normalen Verar + beitung ausgegeben wird. Wenn die auszugebende Zeichenkette + nicht vollständig in den Puffer paßt, sollten trotzdem so viele + Zeichen wie möglich übernommen werden. Im weiteren Verlauf ruft + EUMEL-0 dann wieder OUTPUT mit dem Rest der Zeichenkette + auf. + + + Achtung: #on("i")#Keinesfalls darf innerhalb von OUTPUT die 0-Routine 'warte' auf + gerufen werden.#off("i")# + + Vorschlag: Falls der Kanal nicht existiert bzw. OUTPUT darauf unsinnig ist, + sollte vorgegaukelt werden, alle Zeichen seien ausgegeben (d2 + unverändert). + + + + #d("OUTCHAR")# + + Eingang: d0 = Kanalnummer (1...15) + d1 = auszugebendes Zeichen + + Zweck: Ausgabe eines Zeichens. + + Hinweis: Ob das Zeichen übernommen wird, kann vorher durch einen Aufruf + IOCONTROL "frout" erfragt werden, s. S. #topage("frout")#. + + + +#b("Terminals")##goalpage("term")# + +"Normale" #ib#Terminal#ie(1,", normales")#s können ohne weitere Unterstützung des SHards angeschlossen +werden. Die zur Anpassung an den EUMEL-Zeichensatz *) notwendigen #ib#Umcodierungen#ie# +werden von den höheren Ebenen aus eingestellt. Da diese Umsetztabellen vom SHard +unabhängig sind, stehen automatisch alle so angepaßten Terminaltypen allen EUMEL- +Anwendern zur Verfügung! +#foot# +#f#*) Siehe "EUMEL Benutzerhandbuch, Teil 3: Editor, 5. Zeichencode" +#a# +#end# + +Für den Anschluß eines #on("b")##on("i")#integrierten #ib#Terminal#ie(1,", integriertes")#s#off("i")##off("b")#, in dessen Bildwiederholspeicher direkt +gearbeitet wird, kann man häufig den Terminaltyp 'psi' verwenden (siehe auch "Exoten"). + +Näheres zu Terminaltypen und -anschlüssen findet man im "EUMEL Systemhandbuch" +unter den Stichwörtern #on("i")#Konfiguration#off("i")# und #on("i")#Konfigurierung#off("i")#. + + + +#bb("Drucker, ","Plotter")##goalpage("druck")# + +#ib#Drucker#ie# und Plotter werden vom EUMEL-System wie Terminals angesehen. Da in der +Regel der Rechner aber schneller Zeichen senden als der Drucker drucken kann, müssen +solche Geräte in der Regel mit Flußkontrolle angeschlossen werden (siehe S.#topage("fluss")#). + +Wenn Drucker oder Plotter über eine Parallelschnittstelle angeschlossen werden, kann man +auf diesem Kanal möglicherweise auf einen Ausgabepuffer verzichten. Voraussetzung ist +dabei, daß + + a) der Drucker einen eigenen Puffer hat und + b) der Puffer "schnell" gefüllt werden kann (<0.1 ms je Zeichen). + +Dann kann man auf den bei der SHard-Routine OUTPUT geforderten Puffer verzichten +und die Zeichenkette direkt über die Parallelschnittstelle an den Drucker übergeben. Wenn +der Drucker 'Puffer voll' signalisiert, sollte die Zeichenübernahme bei OUTPUT abgebro +chen werden. **) #on("i")#Auf keinen Fall darf CPU-intensiv auf Freiwerden des Puffers gewartet +werden!#off("i")# +#foot# +#f#**) siehe auch IOCONTROL "frout", S.#topage("frout")# +#a# +#end# + + + +#b("Exoten")##goalpage("exot")# + +Exotische #ib#Terminal#ie(1," exotisches")#s (im Sinne dieser Beschreibung) sind solche, für die eine Umsetz +tabelle im System (siehe Konfiguratorbeschreibung) nicht ausreicht bzw. nicht nötig ist +(Beispiele: Terminals, in deren Bildwiederholspeicher direkt gearbeitet wird; Terminals, die +soweit programmierbar sind, daß sie den EUMEL-Zeichencode können). + +Für solche Terminals muß in der Konfiguration der Terminaltyp '#ib#psi#ie#' eingestellt werden. +Dieser wirkt ohne Umcodierungen, d.h. die EUMEL-Codes (siehe Benutzerhandbuch 1.7 +Seite 106) werden direkt dem SHard zugestellt (wie bei 'transparent'), jedoch mit folgenden +Besonderheiten: + +Eingabeseitig werden zusätzlich folgende Codezuordnungen getroffen: + + Code Funktion + + 7 SV (Aktivierung: 'gib supervisor kommando:') + 17 STOP (Ausgabe auf diesen Kanal wird gestoppt) + 23 WEITER (Ausgabe läuft wieder weiter) + 4 INFO (System geht in Debugger, falls Debugoption) + + + +#bb("5.2 ","Block-IO")##goalpage("block")# + +Über Block-IO wickelt das System die Zugriffe zum Hintergrund und zum Archiv ab. +Ferner ist daran gedacht, auch auf V.24-Schnittstellen Block-IO z.B. für Rechnerkopp +lung zuzulassen. Die Kanalnummer in Reg. d0 unterscheidet diese Fälle. Außer beim +Paging (d0=0) wird ein Block-IO durch die ELAN-Prozeduren 'blockin' und blockout' +induziert. + +Bei Block-IO wird immer ein 512 Byte großer Hauptspeicherbereich mit übergeben. +Dieser kann (im Gegensatz zu OUTPUT) direkt benutzt werden, d.h. es muß keine Um +pufferung erfolgen. + +Dieser Hauptspeicherbereich darf nur bei BLOCKIN verändert werden. + +SHard darf (anders als bei OUTPUT) erst dann zur Aufrufstelle zurückgeben, wenn die +verlangte Operation abgeschlossen ist. Treten während der Operation Wartezeiten auf, so +muß SHard die 0-Routine 'warte' aufrufen, damit das System andere Prozesse weiter +laufen lassen kann. + +EUMEL-0 definiert bestimmte Funktionen für Hintergrund (Kanal 0) und Archiv (Kanal 31). +Operationen auf anderen Kanälen kann SHard nach Belieben implementieren und deren +Leistung seinen Installationen über ELAN-Pakete zur Verfügung stellen. Das System +vergibt auch in Zukunft für den #ib##on("i")#Funktionscode#ie##off("i")# in Register d1 nur positive Werte (Bit 15 +von d1 = 0). Der SHard kann selbst negative Codes einführen. + + + #d("BLOCKIN")# + + Eingang: d0 = Kanalnummer (0...32) + d1 = Funktionscode 1 + d2 = Funktionscode 2 + a0 = Adresse des Hauptspeicherbereichs + Ausgang: d0 = undefiniert (darf also verändert werden) + d1 = Rückmeldecode + a0 = darf verändert werden + + Der Inhalt des Hauptspeicherbereichs (<a0>... <a0>+511) darf + verändert sein. + + Zweck: "Einlesen" von Blöcken. Die genaue Wirkung hängt vom Funk + tionscode und dem Kanal ab. + + Vorschlag: Falls der Kanal nicht existiert bzw. BLOCKIN darauf unsinnig ist, + sollte die Rückmeldung -1 in d1 geliefert werden. + + + #d("BLOCKOUT")# + + Eingang: d0 = Kanalnummer (0...32) + d1 = Funktionscode 1 + d2 = Funktionscode 2 + a0 = Adresse des Hauptspeicherbereichs + Ausgang: d0 = undefiniert (darf also verändert werden) + d1 = Rückmeldecode + a0 = darf verändert werden + + Der Inhalt des Hauptspeicherbereichs darf #on("i")#nicht#off("i")# verändert werden! + + Zweck: "Ausgeben" von Blöcken. Die genaue Wirkung hängt vom Funk + tionscode und dem Kanal ab. + + Vorschlag: Falls der Kanal nicht existiert bzw. BLOCKOUT darauf unsinnig ist, + sollte die Rückmeldung -1 in d1 geliefert werden. + + + #d("warte")# (0-Routine) + + Ausgang: Alle Register undefiniert! + + Zweck: Diese Routine ist bei 'blockin' oder 'blockout' dann aufzurufen, + wenn SHard im Augenblick nichts zu tun hat. Durch den Aufruf von + 'warte' erhalten andere Systemteile die Möglichkeit, weiter zu ar + beiten. Ein 'warte' kann bis zu ca. 1/4 Sekunde Zeit aufnehmen. + 'warte' darf nicht in Interruptroutinen und Stream-IO verwendet + werden! 'warte' zerstört alle Register! SHard muß davon ausgehen, + daß 'warte' seinerseits andere SHard-Komponenten aufruft. + + +Die Verwendung der 0-Routine 'warte' soll hier an einigen Beispielen verdeutlicht wer +den: + + + blockout auf platte : + WHILE platte noch nicht frei REP + warte + ENDREP ; + uebertrage schreibbefehl an controller ; + uebertrage daten an controller . + + blockin von platte : + WHILE platte noch nicht frei REP + warte + ENDREP ; + uebertrage lesebefehl an controller ; + WHILE daten noch nicht gelesen REP + warte + ENDREP ; + hole daten vom controller . + + + blockout auf floppy : + seekbefehl an controller ; + WHILE seek noch nicht fertig REP + warte + ENDREP ; + setze dma auf schreiben block zur floppy ; + schreibbefehl an controller ; + WHILE schreiben noch nicht fertig REP + warte + ENDREP . + + blockin von floppy : + seekbefehl an controller ; + WHILE seek noch nicht fertig REP + warte + ENDREP ; + setze dma auf lesen block von floppy ; + lesebefehl an controller ; + WHILE lesen noch nicht fertig REP + warte + ENDREP . + + + +#b("Block-IO bei Hintergrund und Archiv")##goalpage("bhgarch")# + +#ib#Hintergrund#ie# (Kanal 0) und #ib#Archiv#ie# (Kanal 31) unterscheiden sich in den Link-Bedingungen +nur in der Kanalnummer. Die Aufrufe von BLOCKIN und BLOCKOUT werden mit folgenden +Eingangsparametern versorgt: + + #on("b")#BLOCKIN#off("b")# d0 = 0 bzw. 31 + d1 = 0 + d2 = Blocknummer + a0 = Hauptspeicheradresse + + Der angegebene 512-Byte-Block ist in den Hauptspeicher ab + <a0> einzulesen. + + #on("b")#BLOCKOUT#off("b")# d0 = 0 bzw. 31 + d1 = 0 + d2 = Blocknummer + a0 = Hauptspeicheradresse + + Der Hauptspeicherbereich (<a0>... <a0>+511) ist auf den + angegebenen Block zu schreiben. + +Als Rückmeldungen sind zu liefern:#goalpage("errcod")# + + 0 Operation korrekt ausgeführt. + 1 Manuell behebbarer Fehler (z.B. Laufwerktür offen) + 2 Permanenter Fehler (z.B. Daten nicht lesbar) + 3 Versorgungsfehler (zu hohe Blocknummer) + + +#d("Fehlerwiederholung")#: Das EUMEL-System führt von sich aus Fehlerwiederholungen beim + Hintergrund- und beim Archivzugriff durch. SHard sollte deshalb + im Fehlerfall die Operation nicht selbst wiederholen, sondern einen + Lese/ Schreibfehler zurückmelden. So werden dem EUMEL-Sy + stem auch Soft-Errors gemeldet. In manchen Fällen soll vor + einem erneuten Lese- oder Schreibversuch der Arm auf Spur 0 + positioniert werden o.ä. Um das zu erreichen, sollte SHard diese + "Reparaturaktion" direkt im Anschluß an den fehlerhaften Versuch + durchführen. + +#d("Kontrollesen")#: Falls Kontrollesen (nach jedem Schreibzugriff) notwendig ist, muß das + allerdings vom SHard durchgeführt werden. In der Regel reicht es + dazu, den geschriebenen Block "ohne Datentransport" zu lesen, + + + + + + + + + + + + + + + + + + + + + +System verwendet nur positive Codes. Der SHard-Schreiber kann auch negative Codes +für Sonderzwecke vorsehen. + + + #d("IOCONTROL")# + + Eingang: d0 = Kanalnummer (0...32) + d1 = Funktionscode 1 + d2 = Funktionscode 2 + d3 = Funktionscode 3 + Ausgang: d1 = Rückmeldung + + Zweck: abhängig von 'Funktionscode 1' (s.u.) + +Das System verlangt folgende Informations- und Steuerleistungen über IOCONTROL: + + + #d("IOCONTROL ""typ""")# + + Eingang: d0 = Kanalnummer (0...31) + d1 = 1 + Ausgang: d1 = Kanaltyp + + Zweck: Informiert EUMEL-0, welche IO für den angegebenen Kanal + sinnvoll ist. Die Rückmeldung in d1 wird bitweise interpretiert: + + Bit 0 gesetzt <=> 'inputinterrupt' kann kommen. + Bit 1 gesetzt <=> OUTPUT ist sinnvoll. + Bit 2 gesetzt <=> BLOCKIN ist sinnvoll. + Bit 3 gesetzt <=> BLOCKOUT ist sinnvoll. + Bit 4 gesetzt <=> IOCONTROL "format" ist sinnvoll. + + Hinweis: #on("i")#Trotz dieser Informationsmöglichkeit wird nicht garantiert, daß nur + sinnvolle Operationen für den Kanal aufgerufen werden.#off("i")# + + + #d("IOCONTROL ""frout""")##goalpage("frout")# + + Eingang: d0 = Kanalnummer (1...15) + d1 = 2 + Ausgang: d1 = Anzahl Zeichen, die nächster OUTPUT übernimmt, bzw. + Anzahl der OUTCHAR-Aufrufe, deren Zeichen übernommen + wird. + + Zweck: Liefert Information über die Belegung des Puffers. Diese Informa + tion wird von EUMEL-0 zum Scheduling benutzt. + + Achtung: #on("i")#Wenn EUMEL-0 längere Zeit kein OUTPUT gemacht hat, muß + irgendwann d1 > 49 gemeldet werden.#off("i")# + + Hinweis: Unter Berücksichtigung des oben Gesagten darf "gelogen" werden. + Man kann z.B. immer 50 in d1 zurückmelden, muß dann aber + schlechtere Nutzung der CPU bei Multi-User-Systemen in Kauf + nehmen. + + Falls auf dem angegebenen Kanal ein Drucker mit eigenem Puffer + über Parallelschnittstelle angeschlossen ist (siehe S.#topage("druck")# ) und man + auf einen SHard-internen Puffer verzichtet hat, sollte bei 'Druk + kerpuffer voll' 0 in d1 zurückgemeldet werden. Wenn aber Zeichen + übernommen werden können, sollte 50 in d1 gemeldet werden + + Vorschlag: Falls der Kanal nicht existiert oder nicht für Stream-IO zur Verfü + gung steht, sollten 200 in d1 zurückgemeldet werden. + + + #d("IOCONTROL ""weiter""")##goalpage("weiter")# + + Eingang: d0 = Kanalnummer (1...15) + d1 = 4 + Ausgang: - + + Zweck: Das System ruft "weiter" für den in d0 angegebenen Kanal auf, + wenn es wieder Eingabezeichen puffern kann. (siehe auch: Fluß + kontrolle S.#topage("fluss")#) + + Hinweis: "weiter" wird von EUMEL-0 auch immer dann aufgerufen, wenn + ein Prozeß auf dem angegebenen Kanal auf Eingabe wartet und + keine Zeichen mehr gepuffert sind. Wenn der betroffene Kanal von + sich aus keine Interrupts erzeugt, kann SHard diesen Aufruf dazu + benutzen, den Kanal auf mögliche Eingabe abzufragen und ggfs. + das Eingabezeichen durch Aufruf von 'inputinterrupt' EUMEL-0 + zuzustellen. + #on("i")#Diese Betriebsart sollte nicht für normale Terminalkanäle eingesetzt + werden, weil sie die SV-Taste nur dann an EUMEL-0 zustellt, + wenn ein Prozeß auf diesem Kanal auf Eingabe wartet. Dadurch + wären aber CPU-intensive Endlosschleifen nicht normal abbrech + bar! #off("i")# + + + #d("IOCONTROL ""size""")# + + Eingang: d0 = Kanalnummer (0...31) + d1 = 5 + d2 = Schlüssel + Ausgang: d1 = Anzahl Blöcke + + Zweck: EUMEL-0 ruft 'size' auf, um die Anzahl Blöcke zu erfahren, die + ein Block-IO-Kanal verkraften kann (Größe von Hintergrund und + Archiven). Bei Archivlaufwerken, die meherere Formate bearbeiten + können, dient dieser Aufruf auch zum Einstellen des Formats für + die folgenden blockin/blockout-Operationen anhand des Schlüs + sels. + + Schlüssel: 0 Wenn möglich 'erkennend', sonst 'standard'. Im ersten Fall + erkennt SHard das Format der eingelegten Diskette und stellt + dieses ein. + + Die weiteren Schlüssel sind stets definierend: + + 1 5.25" 2D-40, Sektor 1..9, 512 Bytes + 2 5.25" 2D-80, Sektor 1..9, 512 Bytes + 3 5.25" HD-80, Sektor 1..15, 512 Bytes + 4 5.25" 1D-80, Sektor 1..9, 512 Bytes + 10 8" 1D-77, Sektor 0..15, 512 Bytes + 11 8" 2D-77, Sektor 0..15, 512 Bytes + 12 8" 1S-77, Sektor 1..26, 128 Bytes + 13 8" 1D-77, Sektor 1..26, 256 Bytes + 14 8" 2D-77, Sektor 1..16, 256 Bytes + + Hinweis: Bei Archiven wird 'size' aufgerufen, nachdem der Archivträger ein + gelegt wurde. D.h. SHard hat die Gelegenheit, die Größe anhand + des eingelegten Archivträgers zu bestimmen (z.B. ob single- oder + doublesided). + + Vorschlag: Diese Funktion sollte auf nicht vorhandenen und den Stream-IO- + Kanälen 0 liefern. Sie muß aber mindestens auf Kanal 0 (Hinter + grund) und Kanal 31 (Archiv) "echte" Werte liefern. + + Achtung: #on("i")#Ausnahmsweise darf bei dieser IOCONTROL-Funktion die + 0-Routine 'warte' aufgerufen werden.#off("i")# + + + #d("IOCONTROL ""format""")# + + Eingang: d0 = Kanalnummer (0...31) + d1 = 7 + d2 = Schlüssel + Ausgang: d1 = Fehlercode wie bei Archiv-BLOCKOUT (siehe S.#topage("errcod")#) + + Zweck: Dient zum Formatieren eines Mediums. Diese Funktion kann für + jeden Kanal leer implementiert sein ('rts'). Sie sollte aber "forma + tierend" (z.B. auf Kanal 31) arbeiten, falls auf diesem Kanal die + "typ"-Abfrage "Formatieren sinnvoll" liefert. Falls (bei Disketten + laufwerken) mehrere Formate möglich sind, bestimmt der Schlüssel + das gewünschte Format. + + Schlüssel: 0 Standardformat dieses Rechners + 1 5.25" 2D-40, Sektor 1..9, 512 Bytes + 2 5.25" 2D-80, Sektor 1..9, 512 Bytes + 3 5.25" HD-80, Sektor 1..15, 512 Bytes + 4 5.25" 1D-80, Sektor 1..9, 512 Bytes + 10 8" 1D-77, Sektor 0..15, 512 Bytes + 11 8" 2D-77, Sektor 0..15, 512 Bytes + 12 8" 1S-77, Sektor 1..26, 128 Bytes + 13 8" 1D-77, Sektor 1..26, 256 Bytes + 14 8" 2D-77, Sektor 1..16, 256 Bytes + + Hinweis: Falls für das Formatieren ein großer Speicherbereich benötigt wird, + sollte das Formatieren von Disketten besser in einem Boot-Dialog + vor dem Start von EUMEL-0 angeboten werden. Denn sonst + müßte der Pagingbereich unnötig eingeschränkt werden. + Man kann das Formatieren #on("i")#einer Spur#off("i")# CPU-intensiv implementie + ren (d.h. ohne DMA im Interrupts-Disabled-Modus), wenn man in + Kauf nimmt, daß alle anderen Tasks des EUMEL-Systems in + dieser Zeit "stehen". Dann sollte man aber nach jeder Spur + mehrmals die 0-Routine 'warte' aufrufen. + + Achtung: #on("i")#Ausnahmsweise darf bei dieser IOCONTROL-Funktion die + 0-Routine 'warte' aufgerufen werden.#off("i")# + + + +#b("Konfigurierung serieller Schnittstellen")##goalpage("v24")# + +Bei Kanälen, die hardwaremäßig auf #ib#serielle Schnittstellen#ie# (#ib# V.24#ie#) zurückgeführt werden, +sind in der Regel die Größen + + - #ib#Baudrate#ie# (..., 2400, 4800, 9600, ...) + - #ib#Zeichenlänge#ie# (7 Bits, 8 Bits) + - #ib#Parität#ie# (keine, gerade, ungerade) + +einstellbar. Dafür muß SHard die IOCONTROL-Funktionen "baud" und "bits" zur Verfü +gung stellen. Diese werden in zwei Modi benutzt: + + a) #on("b")#einstellend#off("b")# + Läuft der aufrufende EUMEL-Prozeß auf dem privilegierten Steuerkanal (d0 = 32), + wird der als Parameter mit übergebene #on("i")#adressierte Kanal#off("i")# auf die geforderten Werte + eingestellt, sofern das möglich ist. + + b) #on("b")#abfragend#off("b")# + Läuft der aufrufende EUMEL-Prozeß nicht auf Kanal 32 (d0 <> 32), wird lediglich + abgefragt, ob der #on("i")#adressierte Kanal#off("i")# auf die übergebenen Werte eingestellt werden + könnte. + +Aufgrund des zweiten Modus können die höheren EUMEL-Ebenen dem Anwender bei der +Konfigurierung mitteilen, welche Werte sich auf dem jeweiligen Kanal einstellen lassen. Das +nutzt z.B. das Standard-Konfigurationsprogramm aus. + +Hinweis: Bei einigen Kanälen (z.B. bei einem integrierten Terminal oder einer Parallel + schnittstelle) sind Baudrateneinstellungen sinnlos. Bei anderen können sie nur + hardwaremäßig vorgenommen werden (Jumper, Dip Switches). In allen diesen + Fällen muß SHard bei allen Einstellungen 'unmöglich' melden. (Standardmäßig + wird der Anwender bei der Einstellung seiner Konfiguration dann auch nicht + danach gefragt.) + + + #d("IOCONTROL ""baud""")# + + Eingang: d0 = eigener Kanal (1...15 / 32) + d1 = 8 + d2 = 0 + d3 = Schlüssel * 256 + adressierter Kanal + Ausgang: d1 = Rückmeldung (0 = ok, 1 = nicht möglich) + + Zweck: Wird diese Routine auf dem Steuerkanal (d0=32) aufgerufen, wird + die angegebene Baudrate für den durch Register d3(0..7) adres + sierten Kanal eingestellt, falls das möglich ist. Wird diese Routine + auf einem anderen Kanal als 32 aufgerufen, informiert sie den + Aufrufer lediglich, ob eine derartige Einstellung des adressierten + Kanals möglich wäre. + + Schlüssel: 1 50 Baud + 2 75 Baud + 3 110 Baud + 4 134.5 Baud + 5 150 Baud + 6 300 Baud + 7 600 Baud + 8 1200 Baud + 9 1800 Baud + 10 2400 Baud + 11 3600 Baud + 12 4800 Baud + 13 7200 Baud + 14 9600 Baud + 15 19200 Baud + 16 38400 Baud + + Anmerkung: In der Regel werden nicht alle Baudraten vom SHard unterstützt + werden. Bei V.24 Schnittstellen sollten aber mindestens 2400, + 4800 und 9600 Baud zur Verfügung stehen, besser auch 300, 600, + 1200 und 19200 Baud. + + Hinweis: Falls SHard-spezifisch weitere Baudraten implementiert werden + sollen, darf SHard hierfür negative Schlüsselwerte in d3(8..15) ver + geben. + + + #d("IOCONTROL ""bits""")# + + Eingang: d0 = eigener Kanal (1...15 / 32) + d1 = 9 + d2 = 0 + d3 = Schlüssel * 256 + adressierter Kanal + Ausgang: d1 = Rückmeldung (0 = ok, 1 = nicht möglich) + + Zweck: Wird diese Routine auf dem Steuerkanal (d0=32) aufgerufen, wird + die angegebene Zeichenlänge (Bits pro Zeichen) und Parität für + den durch Register d3(0..7) adressierten Kanal eingestellt, falls das + möglich ist. + Wird diese Routine auf einem anderen Kanal als 32 aufgerufen, + informiert sie den Aufrufer lediglich, ob eine derartige Einstellung + des adressierten Kanals möglich wäre. + + + Schlüssel: stop * 32 + par * 8 + (bit - 1) + + stop: 0 1 Stopbit + 1 1.5 Stopbits + 2 2 Stopbits + + par: 0 keine Parität + 1 ungerade Parität + 2 gerade Parität + + bit: 1...8 Bits pro Zeichen + + + Anmerkung: In der Regel werden nicht alle Kombinationen vom SHard unter + stützt werden. Bei V.24 Schnittstellen sollten aber möglichst 1 + Stopbit, 7 und 8 Bits pro Zeichen und alle drei Paritätseinstellun + gen zur Verfügung stehen. + + Hinweis: Falls SHard-spezifisch weitere Einstellungen implementiert werden + sollen, darf SHard hierfür negative Schlüsselwerte in d3(8..15) ver + geben. + + + +#b("Flußkontrolle")##goalpage("fluss")# + +Die stromorientierten Kanäle (1...15) werden nicht nur zum Anschluß schneller Geräte (wie +Terminals) verwendet, sondern auch, um langsame Geräte (wie Drucker) anzuschließen, die +die Daten u.U. nicht so schnell übernehmen können, wie sie der Rechner schickt. Dabei +ist auf eine geeignete Flußkontrolle zu achten (nicht schneller senden, als der Andere +empfangen kann). Dieses Problem stellt sich auch bei einer Rechner-Rechner-Kopplung. +Hier ist in der Regel sogar zweiseitige Flußkontrolle notwendig. + +Als Flußkontrolle ist die #ib#REQUEST TO SEND/CLEAR TO SEND#ie# Logik der V.24-Schnitt +stelle oder das #ib#XON/XOFF#ie#-Protokoll zu verwenden. Das Letztere kann auch bei Parallel +schnittstellen eingesetzt werden. + +Zur eingabeseitigen Flußkontrollsteuerung kann SHard die IOCONTROL-Funktionen +"stop" und "weiter" (siehe S.#topage("weiter")#) verwenden: + +Nach "stop" muß SHard weiter einlaufenden Input selbst zwischenpuffern oder auf der +V.24-Schnittstelle das Signal 'REQUEST TO SEND' wegnehmen bzw. XON senden. +Dadurch wird bei den meisten Fremdrechnern ein weiteres Senden unterbrochen, sofern +(im ersten Fall) das Signal 'REQUEST TO SEND' dort mit dem V.24-Eingang 'CLEAR TO +SEND' verbunden ist. Wird von EUMEL-0 "weiter" aufgerufen, so kann auf dem ent +sprechenden Kanal wieder empfangen werden (RTS setzen bzw. XON senden). + +Für die ausgabeseitige Flußkontrolle muß rechnerseitig ebenfalls das Signal 'CLEAR TO +SEND' bzw. der Empfang von XOFF berücksichtigt werden. Wenn an der Schnittstelle das +'CLEAR TO SEND' weggenommen wird, darf SHard keinen weiteren Output auf dieser +Schnittstelle machen, bis 'CLEAR TO SEND' wieder anliegt. Entsprechend muß der +Empfang von XOFF die Ausgabe anhalten und XON sie wieder starten. + +Bemerkung: Die meisten Systeme enthalten diese CTS-Funktion schon in ihrer Hard + ware, so daß im SHard dafür keine Vorkehrungen getroffen werden müs + sen. + + +Zur Einstellung der gewünschten Flußkontrolle eines Kanals dient die IOCONTROL- +Funktion "flow". Ähnlich wie "baud" und "bits" wirkt auch "flow" nur auf Kanal 32 #on("i")#ein +stellend#off("i")# und auf allen anderen Kanälen lediglich #on("i")#abfragend#off("i")#. + + + #d("IOCONTROL ""flow""")# + + Eingang: d0 = eigener Kanal (1...15 / 32) + d1 = 6 + d2 = 0 + d3 = Modus * 256 + adressierter Kanal + Ausgang: d1 = Rückmeldung (0 = ok, 1 = nicht möglich) + + Zweck: Wird diese Routine auf dem Steuerkanal (d0=32) aufgerufen, muß + sie den gewünschten Flußkontrollmodus für den adressierten Kanal + einstellen. + Dabei sind folgende Modi festgelegt: + + Modus = 0 Keine Flußkontrolle + Modus = 1 XON/XOFF (in beiden Richtungen) + Modus = 2 RTS/CTS (in beiden Richtungen) + Modus = 5 XON/XOFF (nur ausgabeseitig) + Modus = 6 RTS/CTS (nur ausgabeseitig) + Modus = 9 XON/XOFF (nur eingabeseitig) + Modus = 10 RTS/CTS (nur eingabeseitig) + + SHard wird hierdurch informiert, wie er auf "stop" und "weiter" + reagieren soll. Wenn keine Flußkontrolle gewünscht wird + (Modus=0), muß SHard "stop" und "weiter" ignorieren; bei + Modus=1 oder Modus=9 muß bei "stop" XOFF und bei "weiter" + XON geschickt werden; bei Modus=2 oder Modus=10 muß bei + "stop" das Signal RTS auf low und bei "weiter" wieder auf high + gesetzt werden. Mit "stop" ist hierbei das Unterschreiten des + Schwellwertes bei der Rückmeldung von + "inputinterrupt" gemeint. + + Bei Modus=1 oder Modus=5 müssen empfangene XON/XOFF + -Zeichen, bei Modus=2 oder Modus=6 das Signal CTS beachtet + werden. + + Wird diese Routine auf einem anderen Kanal als 32 aufgerufen, + informiert sie den Aufrufer lediglich, ob der geforderte Flußkontroll + modus auf dem adressierten Kanal einstellbar wäre. + + Hinweis: Falls SHard-spezifisch weitere Flußkontrollmodi implementiert + werden sollen, darf SHard hierfür negative Moduswerte in d3(8..15) + vergeben. + + "weiter" wird von EUMEL-0 sehr oft aufgerufen. Es + ist daher nicht sinnvoll, jedesmal XON zu senden, da dies die Gegenstelle + damit überfluten würde. SHard muß sich + merken, ob der Kanal im XOFF-Zustand ist und + nur dann bei "weiter" ein XON senden. + +#b("Kalender")##goalpage("kalender")# + +Die Datums- und Uhrzeitabfrage ist bei Rechnern mit eingebauter Uhr unnötig. EUMEL +holt sich Datum und Uhrzeit dann von SHard. + + #d("IOCONTROL ""calendar""")# + + Eingang: d1 = 10 + d2 = gewünschte Einheit (1=Minute, 2=Stunde, 3=Tag, + 4=Monat, 5=Jahr) + Ausgang: d1 = Rückmeldung + + Zweck: Erfragen von Datum und Uhrzeit. Falls keine Uhr vorhanden ist, + muß bei jedem Aufruf -1 zurückgemeldet werden, bei eingebauter + Uhr jeweils das Gewünschte (Minute: 0..59, Stunde: 0..23, Tag: + 1..31, Monat: 1..12, Jahr: 0..99). + + Hinweis: Die Uhr darf zwischen zwei Aufrufen umspringen. Die daraus re + sultierenden Probleme werden auf höheren Ebenen abgehandelt. + + + +#bb("6. SHard-","Interface Version")##goalpage("shdver")# + +Die #ib#Versionsnummer#ie# der Interface-Spezifikation, auf der SHard aufbaut, muß als +2-Byte-Konstante #ib#SHDVER#ie# in der SHard-Leiste stehen. Für das hier beschriebene +Interface muß sie den Wert 8 haben. + +So sind spätere Erweiterungen des SHard-Interfaces möglich, ohne daß alle SHard- +Moduln geändert werden müssen. + + + + +#bb("7. ","ID-Konstanten")##goalpage("ID")# + +SHard muß in der Leiste vier 2-Byte-Konstanten ablegen. Diese können von den höhe +ren Ebenen durch die ELAN-Prozedur + + INT PROC #ib#id#ie# (INT CONST no) + +abgefragt werden. Dabei werden id(0) bis id(3) von EUMEL-0 geliefert, während SHard in +der Leiste die Werte für id(4) bis id(7) zur Verfügung stellen muß: + + ID4 #ib#Lizenznummer#ie# des SHards *) +#foot# +#f#*) Dieser Wert muß mit der Nummer des Lizenzvertrags zwischen Implementierer und GMD übereinstimmen! +#a# +#end# + + ID5 #ib#Installationsnummer#ie# des EUMEL-Anwenders **) +#foot# +#f#**) Diese Nummer vergibt der Lizenznehmer an die von ihm belieferten Anwender. +#a# +#end# + + ID6 zur freien Verfügung + + ID7 zur freien Verfügung + + + + +#bb("8. ","Zusätzliche Leistungen")##goalpage("shdelan")# + +Will der SHard-Implementierer zusätzliche Leistungen anbieten, die mit den Standardope +rationen nicht möglich sind, kann er weitere Codes für BLOCKIN, BLOCKOUT und +IOCONTROL zur Verfügung stellen. Um Überdeckungen mit Codes zu vermeiden, die von +EUMEL-0 intern verwendet oder erst später eingeführt werden, darf SHard für zusätzliche +Leistungen nur negative Werte als 'Funktionscode 1' verwenden. + + +Zum Ansprechen der neuen Leistungen stehen die ELAN-Prozeduren #on("i")#'#ib#blockout#ie#', '#ib#blockin#ie#'#off("i")# +und #on("i")#'#ib#control#ie#'#off("i")# zur Verfügung. + +Ferner steht dem SHard ein Parameterkanal (32) zur Verfügung. Funktionen, die (im Multi +-User) nicht jeder Task zur Verfügung stehen dürfen, müssen über diesen Kanal 32 +abgewickelt werden und dürfen nur dort wirken. + + + PROC blockout (ROW 256 INT CONST para, (* --> a0 *) + INT CONST funktion1, (* --> d1 *) + funktion2, (* --> d2 *) + INT VAR antwort) (* <-- d1 *) + + PROC blockin (ROW 256 INT VAR para, (* --> a0 *) + INT CONST funktion1, (* --> d1 *) + funktion2, (* --> d2 *) + INT VAR antwort) (* <-- d1 *) + + PROC control (INT CONST funktion1, (* --> d1 *) + funktion2, (* --> d2 *) + funktion3, (* --> d3 *) + INT VAR antwort) (* <-- d1 *) + +Hinweis: Der SHard darf für 'funktion 1' (d1) zusätzlich zu den hier beschriebenen + Standardcodes nur negative Codes vereinbaren. + + +Beispiel: Gibt eine Task, die durch 'continue (x)' an Kanal 'x' hängt, den Befehl + + control (-7,1200,13,antwort), + + so wird IOCONTROL mit (d0='x', d1=-7, d2=1200, d3=13) aufgerufen. + Verläßt SHard 'control' mit d1 = 1, so enthält 'antwort' anschließend eine 1. + + +Hinweis: Um die zusätzlichen Leistungen dem Anwender einfach (und abgesichert) zur + Verfügung zu stellen, sollte man sie in ein ELAN-Paket einbetten und dieses + ebenfalls an die Anwender ausliefern. + + Beispiel: PACKET zusatz DEFINES fanfare, ... : + + PROC fanfare (INT CONST tonhoehe, dauer): + + IF dauer < 0 + THEN errorstop ("negative dauer") + ELIF tonhoehe < 16 + THEN errorstop ("infraschall") + ELIF tonhoehe > 20000 + THEN errorstop ("ultraschall") + ELSE control (-37, 20000 DIV tonhoehe, + dauer) + FI + + ENDPROC fanfare ; + + . . . + + + + +#bb("9. ","Spezialroutinen")##goalpage("ke")# + +Als Testhilfe und zur Fehlerdiagnose kann SHard in seine Routinen Kontrollereignisse ein +bauen. Das geschieht durch Aufruf der 0-Routine 'info'. Dieser EUMEL-Debugger wird +im Anhang A (siehe S.#topage("info")#) beschreiben. + + + #d("info")# (0-Routine) + + Aufruf: movl \#infomsg,(sp)- + jbsr info + lea 4(sp),sp ! restore stackpointer + . + . + infomsg: .asciz "text" + + Zweck: Info wird aufgerufen. Dabei wird 'text' zur Identifikation des Kon + trollereignisses ausgegeben. #on("i")#Hinter dem übergebenen Text muß + ein Byte /00 stehen (durch '.asciz' sichergestellt)!#off("i")# + + Hinweis: Bei Systemen "ohne Info" (nur solche dürfen an Anwender aus + geliefert werden) wird nur der Info-Text ausgegeben und + EUMEL-0 angehalten. + + Achtung: Da der Info selbst die hier beschriebenen Stream-IO-Routinen + benutzt, darf man ihn von diesen Routinen aus (inputinterrupt, + OUTPUT, OUTCHAR, IOCONTROL "frout", IOCONTROL "stop", + IOCONTROL "weiter") nicht aufrufen. Wenn die Ein-/Ausgabe auf + Terminal 1 interruptgetrieben läuft, dürfen die Interrupts beim Info + -Aufruf natürlich nicht gesperrt sein. + +#page# +#cc("Teil 4: ","Tips zur Portierung")##goalpage("tips")# + + +#b("Nullversion des SHards")##goalpage("0ver")# + + +Es wird empfohlen, zuerst eine "Nullversion" des SHard zu entwickeln, die möglichst +einfach aufgebaut und nicht auf Effizienz und vollständige Ausnutzung der Betriebsmittel +ausgerichtet sein sollte. Damit kann man rasch praktische Erfahrung gewinnen, die dann +den Entwurf und die Implementation des eigentlichen SHard erleichtert. Die Nullversion +sollte + + - nur die Kanäle 0 (Hintergrund), 1 (Terminal) und 31 (Archiv) behandeln, + + - keine Baudraten-, Zeichenlängen-, Paritäts- und Flußkontrolleinstellungen un + terstützen (immer 'nicht möglich' melden), + + - vorhandene (ROM-) Routinen möglichst nutzen, ohne sich um Unschönes wie + "busy wait" beim Disketten- bzw. Plattenzugriff zu grämen. + +Mit dieser Nullversion sollte man dann versuchen, EUMEL zu starten. Da der Hintergrund + keitsanforderungen an die Zeitangaben bei #on("i")#einzelnen#off("i")# Interrupts +höheren Ebenen) in das Archivlaufwerk einlegen und von dort laden. Der Vortest sollte +sich direkt nach dem Start folgendermaßen auf Terminal 1 melden: + + E U M E L - Vortest + + Terminals: 1, + RAM-Groesse (gesamt): ... KB + Pufferbereich: ... KB + Hintergrund-Speicher: ... KB + + Speichertest: ************ + +Man sollte während der ****-Ausgabe des Speichertests irgendein Zeichen eingeben. +Das EUMEL-System muß dann in das ausführliche Start-Menü überwechseln. (Andern +falls funktioniert die Eingabe nicht richtig!) + +Als nächstes sollte man versuchen, den Hintergrund vom Archiv aus zu laden. (Diese +Möglichkeit wird im Start-Menü angeboten.) Nach dem Ende dieser Operation wird der +EUMEL-Lauf automatisch beendet. Jetzt kann man das HG-Archiv aus dem Archivlauf +werk entfernen und das System neu starten. Dann sollte EUMEL-0 vom Hintergrund +geladen werden. + +Bei Problemen kann der "Info" (siehe S.#topage("info")#) hilfreich sein. Voraussetzung für seine +Verwendung ist aber, daß die Terminal-Ein-/Ausgabe schon funktioniert. + +Beim Start des EUMEL-Systems kann (wie im Systemhandbuch beschrieben) durch den +Konfigurationsdialog der Terminaltyp von Kanal 1 eingestellt werden. Falls das verwendete +Terminal in dieser Liste nicht aufgeführt wird und auch keinem der aufgeführten (in Bezug +auf die Steuercodes) gleicht, kann man z.B. + + - den neuen Terminaltyp an einem anderen EUMEL-Rechner verfügbar machen + (Umsetztabellen definieren) und per Archiv zum neuen Rechner tragen, + + - die notwendigen Umcodierungen per SHard durchführen. + +Diese Problematik entsteht bei Rechnern mit integriertem Terminal in der Regel nicht, weil +Steuerzeichen dort sowieso algorithmisch interpretiert werden müssen. In diesem Fall wird +man direkt die EUMEL-Codes als Grundlage wählen, so daß keine Umsetzungen erfor +derlich sind. + +Bei einer provisorischen Anpassung kann man auf Invers-Video ohne weiteres verzich +ten. + + +Im Gegensatz zu der Nullversion sollte man bei der eigentlichen SHard-Implementierung +darauf achten, die Möglichkeiten der Hardware effizient zu nutzen. Der Testverlauf ent +spricht dann wieder im wesentlichen dem oben beschriebenen Vorgang. + + + +#b("Typische Fehler")##goalpage("fehler")# + + + a) SHard-Routinen zerstören Registerinhalte bzw. sichern sie beim Interrupt nicht + vollständig. + + b) 'jbsr' bzw. 'rts' verändern den Stackpointer. + + c) Fehler bei der Interruptbehandlung führen zu Blockaden ("hängende Inter + rupts"). + + d) Cursorpositionierung außerhalb des Bildschirms bei einem internen Terminal + (Bildwiederholspeicher im Rechner) wird nicht abgefangen. Das führt dann zu + wildem Schreiben in den Hauptspeicher. + + e) 'warte' wird unerlaubt aufgerufen. ('warte' darf nur von BLOCKIN, BLOCKOUT, + IOCONTROL "size" und IOCONTROL "format" aus aufgerufen werden. Ferner + kann man 'warte' noch nicht beim Systemladen aufrufen!) + + f) OUTPUT-Verhaspler oder -Blockaden entstehen durch Fehlsynchronisation + zwischen dem Füllen des Ausgabepuffers durch die Routine OUTPUT und der + Interruptroutine, die den Puffer leert und ausgibt. + + g) IOCONTROL "frout" meldet in gewissen Situationen nie "mindestens 50 Zeichen + im Puffer frei" und "Puffer leer". Das kann schon im Vortest zu Output-Blok + kaden führen. + + h) Obwohl "frout" einen Wert größer als x meldet, nimmt "output" nicht alle x + Zeichen an. + + i) IOCONTROL "size" meldet falsche Werte. + + j) IOCONTROL verkraftet keine beliebigen (auch unsinnige) Werte. + + k) BLOCKIN bzw. BLOCKOUT geben die Kontrolle an das System zurück, bevor + alle Daten übertragen sind. (Sofort nach der Rückgabe geht EUMEL-0 davon + aus, daß der Puffer frei ist und anderweitig benutzt werden kann!) + + l) Die Stepping-Rate eines Plattencontrollers wird falsch eingestellt, beziehungs + weise die Platte wird nicht im 'buffered step mode' betrieben, obwohl sie be + schleunigend positionieren kann. Dadurch werden die Zugriffszeiten auf dem + Hintergrund unnötig verlangsamt. Man bedenke, daß man so einen Fehler leicht + übersieht, weil sich das System nicht fehlerhaft, sondern nur langsamer verhält. + Außerdem macht sich die Verlangsamung erst bemerkbar, wenn größere Teile + des Hintergrundes benutzt werden. + + m) Bei schnellem Zeichenempfang treten "Dreher" auf. Das deutet meistens auf + einen rekursiven Aufruf der 0-Routine 'inputinterrupt' hin. Dabei überholt dann + das zweite Zeichen das erste. + + n) Bei schnellem Zeichenempfang, speziell bei gleichzeitiger Ausgabe, gehen + Eingabezeichen verloren oder werden verfälscht. In der Regel ist das auf + Timingprobleme bei der Interruptbehandlung zurückzuführen. Interrupts gehen + verloren bzw. die Zeichen werden nicht schnell genug abgeholt. + + + + +#b("Effizienzprobleme")##goalpage("eff")# + + a) Bei #on("i")##on("b")#V.24- und Parallelschnittstellen#off("i")##off("b")# ist schlechter Durchsatz in der Regel auf + Fehlverhalten von "frout" zurückzuführen. Auch kostet es in Multi-User- + Systemen sehr viel, wenn OUTPUT immer nur ein Zeichen übernimmt. (Dann + läuft der ganze Apparat der EUMEL-0-Maschine für jedes Zeichen wieder an.) + + Besonders bei der Parallelschnittstelle achte man darauf, daß nicht durch un + glückliches Timing häufig Blockaden auftreten. So kann zu kurzes 'busy wait' auf + Freiwerden der Parallelschnittstelle dazu führen, daß jedes zweite Zeichen abge + lehnt wird, so daß OUTPUT faktisch zeichenweise arbeitet. Andererseits darf na + türlich 'busy wait' auch nicht auf Millisekunden ausgedehnt werden. + + + b) Wenn #on("i")##on("b")#Disketten ohne DMA#off("i")##off("b")# angeschlossen werden, kann man bei Single- + User-Systemen ohne weiteres 'busy wait' einsetzen, um nach dem Seek- + Vorgang auf den Block zu warten. Im Multi-User sollte das aber wenn irgend + möglich umgangen werden, da eine halbe Umdrehung immerhin ca. 100 ms + kostet. + Falls nur ein Endeinterrupt nach jeder Diskettenoperation zur Verfügung steht, + kann folgendes Verfahren günstig sein: + + seek befehl an controller ; + warten auf endeinterrupt ; + lesebefehl ohne datentransport auf sektor davor ; + warten auf endeinterrupt ; + lese oder schreib befehl auf adressierten sektor ; + cpu intensives warten und datentransport . + + Die Dummyoperation auf den Sektor vor dem adressierten dient dabei nur dazu, + ohne CPU-Belastung einen Zeitpunkt zu finden, wo man dem eigentlichen + Sektor möglichst nahe ist. Die Zeit, in der die CPU benötigt wird, sinkt damit auf + ca. 25 ms. Die Implementation dieses Algorithmus' ist aber nicht ganz einfach, + da die 0-Routine 'warte' wegen der verlangten kurzen Reaktionszeiten nicht + verwendet werden kann. Alle 'warte auf ...' müssen also durch Interrupts reali + siert werden: + + setze interrupt auf lesen davor ; + stosse seek an ; + REP + warte + UNTIL komplette operation beendet ENDREP . + + lesen davor : + setze interrupt auf eigentliche operation ; + stosse lesen davor an . + + eigentliche operation : + ignoriere fehler beim datentransport ; + stosse lesen oder schreiben an ; + REP + REP UNTIL bereit ENDREP ; + uebertrage ein byte + UNTIL alles uebertragen ENDREP ; + melde komplette operation beendet . + + + c) Bei der Ansteuerung von #on("i")##on("b")#Platten#off("b")##off("i")# sollte man darauf achten, daß die 0-Routi + ne 'warte' nicht öfter als notwendig aufgerufen wird. Sonst wird das Paging + zugunsten der CPU-intensiven Prozesse zu stark verlangsamt. Z.B. kann man + bei vielen Plattencontrollern auf eine eigene Seek-Phase verzichten: + + beginne seek ; beginne seek und lesen ; + REP REP + warte warte + UNTIL fertig PER ; UNTIL fertig PER + beginne lesen ; + REP + warte + UNTIL fertig PER + + Hier braucht die linke Fassung immer mindestens ein 'warte' mehr als die + rechte. Bei starker CPU Belastung wird sie deshalb bis zu 100 ms länger für das + Einlesen eines Blocks benötigen. + + Eine ähnliche Situation kann auftreten, wenn die Platte in 256-Byte-Sektoren + unterteilt ist, so daß zu jedem EUMEL-Block zwei Sektoren gehören. Wenn + möglich sollte dann zwischen diesen beiden Sektoren kein 'warte' aufgerufen + werden. Andererseits darf natürlich auch nicht längere Zeit CPU-intensiv ge + wartet werden. Evtl. lohnt es sich in solchem Fall, mit der Sektorverschränkung + zu experimentieren. + +#page# +#cc("Anhang A: EUMEL-","Debugger ""Info""")##goalpage("info")# + + +Für interne Testzwecke gibt es den "Info". Systeme "mit Info" und "ohne Info" unter +scheiden sich nur im EUMEL-0-Teil (Systemkern). Der SHard-Implementierer erhält +zum Test Hintergründe "mit Info" und zur Auslieferung solche "ohne Info". Infofähige +Systeme dürfen nur von den SHard-Implementierern verwendet werden. + + #on("i")##on("b")#Achtung: Infofähige Systeme dürfen auf keinen Fall an Anwender ausgeliefert werden, + da vermittels Info alle Systemsicherungs- und Datenschutzmaßnahmen un + terlaufen werden können.#off("i")##off("b")# *) +#foot# +#f#*) Ausnahmen von dieser Regel bedürfen der expliziten Zustimmung der EUMEL-Systemgruppe (GMD bzw. HRZ +Bielefeld) und des jeweiligen Anwenders. Solche System müssen immer durch spezielle Schlüsselworte abgesichert +werden. +#a# +#end# + + + +#b("Aufruf des Info")##goalpage("aufrinf")# + +Zum Aufruf des Infos gibt es drei Möglichkeiten: + + a) Beim Start des EUMEL-Systems geht man durch Eingabe eines beliebigen Zei + chens während des Vortests in den ausführlichen Start-Dialog. Durch Eingabe + von 'I' gelangt man dann in den Info-Modus. #on("i")#(Diese Möglichkeit wird in dem + Startmenü nicht aufgeführt.)#off("i")# + + b) Man kann den Info durch die ELAN-Prozedur 'ke' aufrufen. D.h. wenn das + System gestartet wurde und sich eine Task am Terminal mit "gib kommando" + gemeldet hat, kann man durch 'ke *return*' in den Info-Modus gelangen. + + c) Wenn sich am Terminal keine Task befindet, die auf Eingabe wartet, gelangt man + durch die Tastenfolge 'i *info*' (*info* meist = CTL d, zur Tastendefinition siehe + "Systemhandbuch, Konfigurierung") in den Info-Modus. + +Alle diese Möglichkeiten funktionieren nur bei infofähigen Systemen. + +Bei schweren Systemfehlern, die eine Weitermeldung an die höheren Ebenen des +EUMEL-Systems unmöglich machen, wird soweit möglich ebenfalls der Info aufgerufen. +Bei Systemen "ohne Info" wird lediglich eine Meldung auf Kanal 1 ausgegeben und das +System angehalten. + + + +#b("Info-Format")##goalpage("forminf")# + +Der Info ist bildschirmorientiert. Beim Aufruf des Infos und nach den meisten Info-Kom +mandos werden die zwei obersten Zeilen wie folgt aufgebaut: *) +#foot# +#f#*) Bildschirmgetreues Verhalten kann der Info allerdings erst nach der Konfigurierung des Kanals zeigen. Vorher (d.h. +insbesondere beim Aufruf aus dem Vortest heraus) werden Cursorpositionierungen in der Regel nicht korrekt durchge +führt. +#a# +#end# + +Mini: nnnn text eeee +Maxi: xxxx + + +wobei + + #on("b")#nnnn#off("b")# den Miniprozeß bezeichnet, der den Übergang in den Info veranlaßt hat: INTER + (Interpreter), LADER, MUELL (Müllabfuhr) oder ARCHIV, + + #on("b")#xxxx#off("b")# den Maxiprozeß (Task) bezeichnet, der gerade durch den Elan-Prozessor + bearbeitet wird (xxxx ist code (tasknummer + code ("0"))), + + #on("b")#text#off("b")# den Grund für den Info-Modus anzeigt und + + #on("b")#eeee#off("b")# eine interne, nur den EUMEL-0-Entwickler interessierende Fehlernummer + ist. + +In der untersten Zeile erscheint (hinter der Angabe des evtl. angezeigten Datenraumes, der +Adresse und der Länge) die Eingabeaufforderung 'info:'. + + + +#b("Info-Kommandos")##goalpage("cmdinf")# + +Info-Kommandos können in der 'info:'-Zeile mit dem Format + + [<zahl>]<buchstabe> + +gegeben werden oder, wenn der Cursor sich im Dump befindet, mit dem Format + + <buchstabe> + +wobei dann für <zahl> die der Cursorposition entsprechende Dumpadresse (modulo +2**16) gesetzt wird (siehe '*cup*'). + +<zahl> ist immer in Hexaform einzugeben. + +'g' Der Info-Modus wird wieder verlassen. Dies ist allerdings bei harten Fehlern ge + sperrt. + +'z' Der Leitblock des angezeigten Maxiprozesses wird dargestellt. (Nur im Miniprozeß + INTER.) + +'s' Dumps werden auf den Datenraum <zahl> eingestellt (s:=<zahl>). Auch der + Realspeicher kann hiermit in verschiedenen Modi eingestellt werden: + + 1s Programmspeicher (absolute Adressen) + ffs Tabellenspeicher (relativ zum Tabellenanfang) + +'l' Dumps werden auf die Länge <zahl> eingestellt. Desungeachtet kann man einen + versehentlich zu langen Dump durch eine beliebige Eingabe abbrechen. Dann wird + allerdings '*cup*' gesperrt (siehe unten). + +'p' Dumps werden auf die Byteadresse <zahl> eingestellt (p:= <zahl>; wmodus:= + FALSE). + +'w' Dumps werden auf die Wortadresse <zahl> eingestellt. Die vor jeder Dumpzeile + ausgegebene Adresse ist dann auch eine Wortadresse. Ein Wort = 2 Bytes + (p:=2*<zahl>; wmodus:=TRUE). + +'k' Block <zahl> laden und per Dump anzeigen. Es erfolgt dabei eine Umstellung auf + den Realdatenraum (s:=/ff). + +'x' Suchen nach Bytekette: + +--> xctext +--> xhxx xx ... +--> x + + Es wird nach 'text' bzw. Hexafolge 'xx xx ...' bzw. nach der durch das letzte + 'x'-Kommando eingestellten Bytekette gesucht. + Das Kommando ist durch *return* abzuschließen. + Die Suche beginnt ab Position 'p' und ist auf die Länge <zahl> Seiten (512 + Byte-Einheiten) begrenzt (0=unendlich). + Eine beliebige Eingabe bricht die Suche vorzeitig ab. + +'*return*' + Es wird der eingestellte Dump ausgegeben (siehe 's', 'l', 'p', 'w'). Bei wmodus + (siehe 'p', 'w') werden Wortadressen ausgegeben. + +'o' Wie '*return*', jedoch wird zuvor p := p+l gesetzt (zum Weiterblättern). + + +'*cup*' *) (Cursor up). Umschaltung in den Modus zum Ändern in Dumps. +#foot# +#f#*) Falls der Kanal noch nicht konfiguriert ist, muß man natürlich eine Taste betätigen, die den EUMEL-Code für +Cursor Up erzeugt. In der Regel ist das CTL c. Falls das Terminal ohne Konfigurierung keine Cursorpositionierungen +durchführt, ist dieser Modus nicht sehr gut benutzbar. +#a# +#end# + Der Cursor fährt in den Dump und kann mit den Cursortasten dort bewegt werden. + Wird eine Hexazahl jetzt eingegeben, so wird diese als Inhalt des Bytes eingetra + gen, auf dem der Cursor gerade steht. Dies funktioniert auch auf beliebigen Da + tenräumen. Info beantragt dann bei der Speicherverwaltung einen Schreibzugriff für + die entsprechende Datenraumseite, so daß Änderungen mit der Copy-on- + Write-Logik erfolgen, also nur taskspezifisch sind. Für diese Task sind die Ände + rungen allerdings dann permanent, da sie auch auf den Hintergrund wirken. + + Hinweis: Dumpt man mit 'k' einen Block und ändert dann darin, so sind diese + Änderungen u.U. nur temporär, da der Info kein Rückschreiben des + Blockes veranlaßt. + + Achtung: Jede Eingabe, die kein Positionierzeichen und kein gültiges Zahlzeichen + ist, beendet diesen Modus. Das neue Zeichen wird als Info-Komman + do aufgefaßt, wobei <zahl> auf die aktuelle Adresse gesetzt wird. + Somit wird dieser Änderungsmodus üblicherweise durch *return* been + det. + + + +#b("Einige Systemadressen")##goalpage("sysaddr")# + +Der Info nützt nur wenig, wenn man nicht weiß, was man sich anschauen soll. Wesentliche +Angaben über die Systemstruktur enthält das 'Brikett' (interne Systemdokumentation für +Projekt Mikros der GMD). Da diese etwas allgemeiner gehalten ist, geht sie nicht auf +implementationsabhängige Konstanten ein. Diese sind hier aufgeführt. + +Der Tabellenspeicher der EUMEL-0-Maschine wird relativ zu M0START angelegt. Im Info +kann der Tabellenspeicher durch die Datenraumangabe ffs adressiert werden, z.B. wird +durch das Kommando ffs1000p der Anfang der 'ktab' gezeigt. + +Ab /1000 liegt die 'ktab'. Sie enthält Informationen, welche Blöcke an welcher Stelle des +Arbeitsspeichers liegen: In der Kachel mit der Adresse /a000+/200*i befindet sich der +Inhalt des Blockes, dessen Nummer in <ktab+2*i> steht. Ferner enthält die Tabelle, zu +welchem Datenraum (drid) und welcher Seite des Datenraums der Inhalt gehört. (Nur +relevant, wenn die Prozeßnummer <> /ff ist). + + ktab: + + /1000 Blocknummern (je 2 Bytes) + /2000 Prozeßnummern (je 1 Byte) + /2800 drid's (prozeßspezifisch, je 1 Byte) + /3000 Seitennummern (je 2 Bytes) + /4000 Steuerbits (je 1 Byte): + + 2**0: Inhalt wird gerade transportiert (zum HG oder Archiv). + 2**1: Inhalt ist identisch mit Inhalt auf HG. Wird beim Schreiben auf die + Kachel (per Software) zurückgesetzt. + 2**2: Schreiberlaubnis (siehe Brikett). + 2**3: Inhalt wurde kürzlich benutzt. Solche Kacheln werden 'weniger + stark' verdrängt. + + + +/5d50 enthält den 'Laderpool'. Es handelt sich um Blocknummern von zu ladenden + Blöcken. Ist der höherwertige Teil der Blocknummer gleich /fd, so ist dies keine + Anforderung. + + Blocknummern > /ff00 stehen für Blöcke mit dem Inhalt 512mal /ff und werden + nie auf dem Hintergrundmedium gespeichert. + + + +/0 enthält den DR-Eintrag des drdr (siehe Brikett). + + + + +/5c00.../5cff: + enthält die Aktivierungstabelle. Ist (/5c00+i)=/01, so ist die Task i aktiv. Hin + weis: /5cff enthält immer /01, ohne daß dieser Zelle eine Task zugeordnet ist. + + + +#b("Leitblock")##goalpage("pcb")# + +Mit dem 'z'-Kommando wird der Leitblock einer Task dargestellt. Die einzelnen Einträge, +die voneinander durch je 2 Blanks getrennt sind, haben die Form + Bezeichnung=Wert +wobei Wert in hexadezimaler Form angegeben ist. In der folgenden Beschreibung steht x, +y und z für irgendeine Hexadezimalziffer. + + ic=0xxxxx Der virtuelle Befehlszähler der Task zeigt auf /xxxxx im Datenraum 4 + dieser Task. Durch die Eingabefolge: + 4s<xxxxx>w*return* + kann man sich den Code, der ausgeführt werden soll, ansehen. + + flags=xxyy Bit /80 von yy zeigt den Fehlerzustand an. + Bit /40 von yy zeigt 'disable stop' (siehe Benutzerhandbuch) an. + Bit /10 von yy zeigt vorzeichenlose Arithmetik an (Compilierung). + + lbas=xxxx Die lokale Basis steht auf /1xxxx im Datenraum 4 (Wortadresse). + + pbas=xx Die Paketbasis steht auf /xx00 im Datenraum 4 (Wortadresse). + + hptop=xyz3 Der Arbeitsheap geht von /30000 (Byteadresse!) bis /3xyz0 (Byte + adresse!). + + chan=xx Die Task hängt an Kanal /xx (Terminalnummer). + 0 <==> kein Terminal angekoppelt. + + task=xxyy,zzzz Die Tasknummer der betrachteten Task ist /yy. /xx ist die Stations + nummer im EUMEL-Netz, /zzzz ist die Versionsnummer zum + Abdichten von 'send'/ 'wait'. + +Um den Code, auf den der 'ic' zeigt, zu interpretieren, ziehe man das Brikett zu Rate. +#page# +#cc("Anhang B: Einige ","EUMEL-Begriffe")##goalpage("glossar")# + + +#on("bold")#Archiv:#off("bold")# + + Medium (z.B. Diskette, Band, Kassette) zur Speicherung von Datenräumen (Pro + grammen, Daten und Dateien) einer oder mehrerer Tasks außerhalb eines + EUMEL-Systems zum Zwecke der Aufbewahrung oder des Datenaustauschs. + + Auch ein ganzer EUMEL-Hintergrund kann (durch 'save system') auf Archiv (z.B. auf + eine oder mehrere Disketten) geschrieben werden. Ein solches "Hintergrundarchiv" + kann dann zur Erzeugung eines EUMEL-Hintergrundes (im Vortest) dienen. + + +#on("bold")#Archivsystem:#off("bold")# + + Programmsystem zur Übertragung von Datenräumen zwischen Archiv und Hinter + grund. + + +#on("bold")#EUMEL-0 (EUMEL-0-Maschine, Systemkern):#off("bold")# + + Softwareschicht, aufbauend auf die hardwareabhängige Schicht SHard. EUMEL-0 ist + nur vom Prozessor, nicht aber von der jeweiligen Rechnerkonfiguration abhängig. Die + durch EUMEL-0 definierte Schnittstelle zu höheren (in ELAN implementierten) + Schichten ist auf allen EUMEL-Systemen identisch. EUMEL-0 wird auf dem + EUMEL-Hintergrundarchiv angeliefert. + + +#on("bold")#Hintergrund (EUMEL-Hintergrund, HG):#off("bold")# + + 1. Medium (z.B. Platte, Diskette, RAM) zur Speicherung von Datenräumen (Pro + grammen, Daten und Dateien) aller Tasks eines EUMEL-Systems; + 2. Die Gesamtheit der auf diesem Medium gespeicherten Information. + + Die Bezeichnung "Hintergrund" ist im Zusammenhang mit dem Konzept des im + EUMEL realisierten Virtuellen Speichers zu sehen. Der Datentransfer zwischen Hin + tergrund und Arbeitsspeicher (RAM) erfolgt ohne Zutun oder Wissen des EUMEL- + Benutzers bzw. der Task, der die Daten gehören. + diff --git a/doc/porting-mc68k/1985.11.26/source-disk b/doc/porting-mc68k/1985.11.26/source-disk new file mode 100644 index 0000000..bf86ccf --- /dev/null +++ b/doc/porting-mc68k/1985.11.26/source-disk @@ -0,0 +1 @@ +porting/portdoc-m68k_eumel-netz-1985-11-26.img diff --git a/doc/porting-z80/8/doc/Port.Z80 b/doc/porting-z80/8/doc/Port.Z80 new file mode 100644 index 0000000..ed3c80a --- /dev/null +++ b/doc/porting-z80/8/doc/Port.Z80 @@ -0,0 +1,2484 @@ +#type ("trium8")##limit (12.0)# +#pagelength(19.5)# +#start(1.5,1.5)# +#type("triumb36")# +#free(4.0)# + EUMEL + Portierungshandbuch + Z 80 +#type("triumb18")# +#free(1.5)# + Version 8 #page(1)# +#type ("trium8")##limit (12.0)# +#block# +#pagelength(19.5)# +#head# +#center#- % - + + +#end# +#type("triumb14")#Inhalt#a# + +Teil 1: Einführung #topage("ein")# +#free(0.3)# + Zweck dieses Handbuchs #topage("zweck")# + Referenzliteratur #topage("reflit")# + Minimale Hardwarevoraussetzungen #topage("hardw")# + Systemdurchsatz #topage("durchsatz")# + Softwarekomponenten des EUMEL-Systems #topage("kompo")# + Anlieferung des Z80-EUMEL-Systems #topage("anlief")# + +Teil 2: Allgemeine Strukturen #topage("allgem")# +#free(0.3)# + Hintergrund #topage("hg")# + Archiv #topage("arch")# + Hauptspeicher #topage("speicher")# + +Teil 3: SHard-Interface Spezifikation #topage("shardifc")# +#free(0.3)# + 0. Vorbemerkungen #topage("vor")# + Zur Notation #topage("not")# + Link-Leisten #topage("leist")# + Allgemeine Link-Bedingungen #topage("link")# + Interrupts #topage("intr")# + 1. System laden #topage("laden")# + 2. Systemstart und -ende #topage("start")# + 3. Speicherverwaltung #topage("spver")# + Hauptspeicher #topage("haupt")# + Schattenspeicher #topage("schatt")# + Blocktransfer im Speicher #topage("ldir")# + Speicherfehler #topage("memerr")# + 4. Zeitgeber #topage("zeit")# + 5. Kanäle #topage("channel")# + 5.1 Stream-IO #topage("stream")# + Terminals #topage("term")# + Drucker, Plotter #topage("druck")# + Exoten #topage("exot")# + 5.2 Block-IO #topage("block")# + Block-IO bei Hintergrund und Archiv #topage("bhgarch")# + 5.3 IO-Steuerung #topage("iocontrol")# + Einstellung serieller Schnittstellen #topage("v24")# + Flußkontrolle #topage("fluss")# + Kalender #topage("kalender")# + 6. SHard-Interface Version #topage("shdver")# + 7. ID-Konstanten #topage("ID")# + 8. Zusätzliche Leistungen #topage("shdelan")# + 9. Spezialroutinen #topage("ke")# + +Teil 4: Tips zur Portierung #topage("tips")# + 0-Version des SHards #topage("0ver")# + Effizienzprobleme #topage("eff")# + Typische Fehler #topage("fehler")# + +Anhang A: EUMEL-Debugger "Info" #topage("info")# +#free(0.3)# + Aufruf des Infos #topage("aufrinf")# + Info-Format #topage("forminf")# + Info-Kommandos #topage("cmdinf")# + Einige Systemadressen #topage("sysaddr")# + Leitblock #topage("pcb")# +#page# +#cc("Teil 1: ","Einführung")# +#goalpage("ein")# + + +#b("Zweck dieses Handbuchs")# +#goalpage("zweck")# + +Dieses Portierungshandbuch wendet sich an diejenigen, die das EUMEL-System auf einem +neuen Rechnertyp implementieren wollen. Es ist Teil einer Serie von Portierungshandbüchern +für verschiedene Prozessortypen. Dieses bezieht sich auf Rechner mit Z80-Prozessoren. + +Zum Betrieb eines EUMEL-Systems wird dieses Handbuch nicht benötigt! + + + +#b("Referenzliteratur")# +#goalpage("reflit")# + + + "EUMEL Benutzerhandbuch" + + "EUMEL Systemhandbuch" + + "EUMEL Quellcode der insertieren ELAN-Pakete" + + "Z80-Assembly Language Programming Manual" + Zilog, 1977 + + + +#b("Minimale Hardwarevoraussetzungen")# +#goalpage("hardw")# + +Um das EUMEL-System effizient einsetzen zu können, sollte die Hardware mindestens +folgenden Kriterien genügen: + + #ib#CPU#ie# Die Z80-CPU sollte mit mindestens 2.5 MHz arbeiten. Falls + die Buszugriffe durch einen CRTC o.ä. verlangsamt werden, + sollte die echte Z80-Leistung durchschnittlich mindestens + einem ungebremsten 2.5 MHz System entsprechen. + Seltene Verlangsamungen (z.B. nur bei I/O-Operationen) + spielen bei diesen Überlegungen keine Rolle. + + RAM Das System sollte über mindestens 64 K Byte #ib#Hauptspeicher#ie# + verfügen, besser sind 128 K als Anfangsausrüstung. + + #ib#Hintergrund#ie# Als Hintergrundmedium sind #ib#Floppy#ie#, #ib#Harddisk#ie# und RAM bzw. + ROM denkbar. + + Kapazität: > 300 K, besser > 400 K (Single-User) + > 750 K, besser > 1000 K (Multi-User) + + Zugriff: < 500 ms (Single-User) + < 200 ms (Multi-User) *) +#foot# +#f#*) Hier ist die durchschnittliche Zugriffszeit auf einen 512 Byte großen Block gemeint. Für Platten und Floppies kann man +sie als Summe der Positionierzeit über die halbe Platte und der Zeit einer halben Umdrehung berechnen.#a# +#end# + + #ib#Archiv#ie# Als Archivgerät wird meistens eine Floppy eingesetzt. Aber + auch Band oder Kassettenrecorder sind denkbar. Die An + forderungen an Kapazität und Geschwindigkeit sind anwen + dungsspezifisch. + + #ib#Bildschirm#ie# Angestrebt werden sollte ein Bildschirm mit 24 Zeilen mit je + 80 Zeichen (oder größer). Kleinere Bildschirme sind anschließ + bar, aber mit 40 Zeichen pro Zeile läßt sich nicht mehr kom + fortabel arbeiten. + Rollup und freie Cursorpositionierung sind notwendige Vor + aussetzungen, invers-video ist erwünscht, aber nicht not + wendig. Weiterhin werden 'Löschen bis Zeilenende' und + 'Löschen bis Schirmende' benötigt. Lokale Editierfunktionen + sind überflüssig. + + #ib#Tastatur#ie# An Steuertasten sollten mindestens ESC und die vier Cursor + tasten vorhanden sein. Dabei ist es günstig, wenn die Cursor + tasten ergonomisch als Block bzw. Kreuz angeordnet sind. + EUMEL benötigt weitere Steuertasten für HOP, RUBIN, + RUBOUT und MARK. Dafür können beliebige Tasten der + Tastatur gewählt werden. + + + +#b("Systemdurchsatz")# +#goalpage("durchsatz")# + +Da das EUMEL-System auf dem Prinzip des Demand Paging aufbaut, hängt der System +durchsatz von + + - CPU Leistung + - Speichergröße (RAM) + - Geschwindigkeit beim Hintergrundzugriff (Floppy, Harddisk) + +ab. Mit zunehmender Benutzerzahl steigen in der Regel die Anforderungen an das Paging +(Hintergrund-Zugriff) schneller als an die CPU. In diesem Bereich kann man die System +leistung dann durch mehr Speicher und/oder eine schnellere Platte in größerem Umfang +steigern. Dabei läßt sich eine langsame Platte teilweise durch mehr RAM und umgekehrt +wenig RAM durch eine schnelle Platte ausgleichen. + + + +#b("Softwarekomponenten des EUMEL-Systems")# +#goalpage("kompo")# + +Das EUMEL-System besteht aus mehreren Schichten: + + + + EUMEL 2: Standardpakete, Editor, ... + + EUMEL 1: ELAN Compiler + + EUMEL 0: Basismaschine + + EUMEL -1: SHard + + H a r d w a r e + + +Dieses #ib#Schichtenmodell#ie# ist nach oben offen und kann deshalb um beliebig viele (höhere) +Schichten erweitert werden. + +EUMEL > 0 Die Standardsoftware der Schichten > 0 ist in der Sprache ELAN geschrie + ben (siehe "EUMEL Quellcode"). Dementsprechend sind alle Schichten ober + halb der EUMEL-0-Maschine prozessor- und rechnerunabhängig, d.h. + Anpassungen an einen neuen Rechnertyp sind nicht erforderlich. + +#ib#EUMEL 0#ie# Die sogenannte "EUMEL-0-Maschine" enthält alle Basisoperationen und + hängt davon ab, welchen Prozessortyp der Rechner als CPU verwendet. Sie + existiert für verschiedene Prozessortypen. Hier wird nur auf den Typ Z80 + Bezug genommen. Bei der Portierung auf einen Z80-Rechner wird die + Z80-EUMEL-0-Maschine ohne Anpassungen (!) übernommen. + +EUMEL -1 Diese Schicht stellt das Interface zwischen der EUMEL-0-Maschine und der + eigentlichen Hardware (vom Prozessor abgesehen) dar. Insbesondere umfaßt + sie alle Routinen zur Ansteuerung peripherer Geräte (Gerätetreiber). + Diese Schicht wird "SHard" genannt ("S"oftware-"Hard"ware Interface). + +Der SHard ist der einzige Teil des Systems, der bei der Portierung auf einen Z80-Rech +ner angepaßt bzw. neu geschrieben werden muß. Deshalb besteht der größte Teil dieses +Handbuchs aus der Spezifikation des Z80-SHards. + + + +#b("Anlieferung des Z80-EUMEL-Systems")# +#goalpage("anlief")# + +Der Implementierer erhält die EUMEL-Software auf Disketten. Dabei stehen folgende Stan +dardformate zur Wahl: + + 8", 1D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte + + 8", 2D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte + + 5", 2D, 40 Spuren, 9 Sektoren (\#1...\#9) � 512 Byte *) +#foot# +#f#*) 48 tpi#a# +#end# + + +Die Diskettenlieferung enthält + + - Single-User Hintergrund + - Multi-User Hintergrund + - Standardarchive + - Archive mit weiterer Anwendersoftware + +Dabei enthält der Hintergrund auch die EUMEL-0-Software (oft auch als "Urlader" be +zeichnet). + +#on("i")#Bitte gehen Sie vorsichtig mit diesen Mutterdisketten um. Verwenden Sie sie nur als Quelle +beim Kopieren. Sie sollten nur auf Kopien davon arbeiten!#off("i")# +#page# +#cc("Teil 2: ","Allgemeine Strukturen")# +#goalpage("allgem")# + + +#b("Hintergrund")# +#goalpage("hg")# + +Der Hintergrund ist in 512 Bytes große Blöcke unterteilt. Sie werden durch Blocknummern (0, +1, 2, ...) adressiert. Die physische Ablage der Blöcke auf dem Hintergrundmedium bleibt dem +SHard überlassen. Er kann sie z.B. linear oder versetzt anordnen. Man sollte darauf achten, +daß Positionierungen auf logisch "nahe" Blöcke möglichst schnell gehen sollten. Deshalb ist +in der Regel zylinderorientierte Anordnung der oberflächenorientierten vorzuziehen. + +Falls auf dem Hintergrundgerät spezielle Blöcke z.B. für Boot und SHard freigehalten werden +sollen, muß das bei der Abbildung der Hintergrundblocknummern auf die Sektoren der Floppy +bzw. der Harddisk berücksichtigt werden. + +Aufbau des Hintergrundes: + + Block 0 Systemetikett + + Block 10...10+k-1 EUMEL-0-Software (Urlader) + + Block 1...9, 10+k ... Paging-Bereich + + +Aufbau des #ib#Systemetikett#ie#s (#ib#Block 0#ie#): + + Byte Wert/Aufgabe + + 0...5 "EUMEL-"; Kennzeichen für EUMEL-Hintergrund. + 6...11 Versionsnummer in druckbaren Zeichen. Sie stellt sicher, daß Urlader und + Hintergrund kompatibel sind. + 12 FFh ; zur Zeit ohne Bedeutung + 13 enthält Wert 0 , wenn System im Shutupzustand ist. + 14..15 Systemlaufzähler (14=low, 15=high). Wird bei jedem Systemstart um 1 + erhöht. + 16..35 Reserviert; zur Zeit ohne Bedeutung + 36..37 Aus historischen Gründen für interne Zwecke belegt. + 38 .. 69 Hier kann eine Installationsnummer geführt werden. + 70 .. 79 Info-Paßwort + 80 =0 Normalzustand + =1 Kompresslauf erforderlich (System frisch von Archiv geladen) + 81...255 Reserviert. + 256..511 Kann von SHard beliebig verwendet werden. + + + +#b("Archiv")# +#goalpage("arch")# + +Wie der Hintergrund sind die Archive in 512 Bytes große Blöcke unterteilt. Bisher gibt es +folgende #dx("Standardformate")#: + + + 8", 1D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte + 8", 2D, 77 Spuren, 16 Sektoren (\#0...\#15) � 512 Byte + + Block Seite Spur Sektor + + 0 0 0 0 + 16 0 1 0 + 77*16 1 0 0 + + n n DIV (77*16) n MOD (77*16) DIV 16 n MOD 16 + + + 5", 2D, 40 Spuren, 9 Sektoren (\#1...\#9) � 512 Byte + + Block Seite Spur Sektor + + 0 0 0 1 + 9 0 1 1 + 40*9 1 0 1 + + n n DIV (40*9) n MOD (40*9) DIV 9 n MOD 9 + 1 + + + 5", 2D, 80 Spuren, 9 Sektoren (\#1...\#9) � 512 Byte + + Block Seite Spur Sektor + + 0 0 0 1 + 9 0 1 1 + 80*9 1 0 1 + + n n DIV (80*9) n MOD (80*9) DIV 9 n MOD 9 + 1 + + + 5", HD, 80 Spuren, 15 Sektoren (\#1...\#15) � 512 Byte + + Block Seite Spur Sektor + + 0 0 0 1 + 15 0 1 1 + 80*15 1 0 1 + + n n DIV (80*15) n MOD (80*15) DIV 15 n MOD 15 + 1 + + +Selbstverständlich können auch andere #ib#Archivformate#ie# implementiert werden, falls das aus +Hardwaregründen notwendig ist oder sich dadurch wesentliche Verbesserungen (z.B. in der +Kapazität) ergeben. + +Wenn irgend möglich sollte aber mindestens eines der oben aufgeführten Standardformate +unterstützt werden - evtl. als zusätzliches Format -, um den Austausch zwischen verschie +denen Rechnertypen zu vereinfachen. + +#on("i")#Hinweis: Um den Datenaustausch zwischen verschiedenen Rechnertypen zu vereinfachen, + sollten möglichst alle der hardwaremäßig möglichen Standardformate (mindestens + lesend) unterstützt werden. Dabei sollte SHard sich automatisch auf das Format + der jeweils eingelegten Floppy einstellen:#off("i")# + + + Laufwerkstyp Diskettentyp(en) + + 8" 1D 8" 1D + 8" 2D 8" 2D, 1D + + 5" 2D-40 5" 2D-40 + 5" 2D-80 5" 2D-80, 2D-40 *) + 5" HD-80 5" HD-80, 2D-80, 2D-40 *) +#foot# +#f#*) Bei der Behandlung von 40-Spur-Disketten auf 80-Spur-Laufwerken gelten meistens folgende Regeln: + a) Lesen funktioniert sicher. + b) Schreiben ist unsicher, funktioniert aber häufig. + c) Formatieren funktioniert fast nie. +#a# +#end# + + + +#b("Hauptspeicher")# +#goalpage("speicher")# + +Die 64 K des direkt vom Z80 adressierbaren #ib#Speicher#ie#s sind folgendermaßen aufgeteilt: + + FFFFh #corner1("-5.0")# + Platz für SHard + yyyyh #box3("T","3","75.0")# + #corner1("-5.0")# + Pagingbereich + + xxxxh #box3("T","3","75.0")# + #corner1("-5.0")# + EUMEL 0 + + 1400h #box3("T","3","75.0")# + #corner1("-5.0")# + Platz für SHard + 0000h #box3("T","3","75.0")# + +Möglichst große Teile des SHards (am besten alle) sollten im unteren Adreßbereich (bis +13FFh) liegen, damit dem Paging viel Speicher zur Verfügung steht. + +Der nicht direkt (aber durch Banking oder DMA) erreichbare Teil des #ib#RAM#ie#s wird Schatten +speicher (siehe S.#topage("schatt")#) genannt. + + +Hinweis: Falls ein Teil des Hauptspeicher-Adreßraums fest (d.h. auch nach dem Boot + loading nicht ausblendbar) durch ROM belegt ist, muß dieses in einem der beiden + SHard-Bereichen liegen. + +#page# +#cc("Teil 3: SHard ","Interface Spezifikation")# +#goalpage("shardifc")# + + +#bb("0. ","Vorbemerkungen")# +#goalpage("vor")# + + +#b("Zur Notation")# +#goalpage("not")# + +Im folgenden wird zwischen #dx("0-Routinen")#, die dem SHard vom EUMEL-0-System zur +Verfügung gestellt werden, und #dx("SHard-Routinen")# unterschieden, die der SHard implementie +ren muß. Damit dieser Unterschied bei der Spezifikation deutlich wird, werden 0-Routinen +folgendermaßen aufgeführt: + + name (0-Routine) + +Zusätzlich werden 0-Routinen grundsätzlich klein und SHard-Routinen groß geschrieben. + +Z80-Befehle werden wie in "Z80-Assembly Language Programming Manual" (Zilog, 1977) +notiert: + + ld a,27 + add a,l + +Hexadezimale Zahlen werden durch ein nachgestelltes 'h' gekennzeichnet: + + 12h = 18 + 1Fh = 31 + FFFFh = 65535 + + +#b("Link-Leisten")# +#goalpage("leist")# + +Die Verbindung zwischen SHard und Urlader (EUMEL-0) erfolgt über zwei Tabellen. In der +"0-Leiste" stellt EUMEL-0 dem SHard verschiedene 0-Routinen zur Verfügung. Diese +Leiste beginnt an der Adresse 1400h: + + 1400h defm 'EUMEL ' + 1410h defw eumel0blocks + 1412h defw hgversion + 1414h defw 1 ; Kennzeichen für Z80-Urlader + 1416h defw urladerversion + 1418h defw 0 ; reserviert + 141ah defw ; kleinste unterstützte SHardversion + 141ch defw ; größte ... + 141eh jp systemstart + jp inputinterrupt + jp timerinterrupt + jp warte + jp grab + jp free + jp shutup + jp info + +Diese Leiste wird vom Urlader nach dem Systemstart überschrieben. Der SHard muß daher, +bevor er nach systemstart springt, die für ihn relevanten Teile (mindestens die Sprungbefehle) +in einen eigenen Bereich kopieren: + + #ib#eusystemstart#ie#: jp 0 + #ib#euinputinterrupt#ie#: jp 0 + #ib#eutimerinterrupt#ie#: jp 0 + #ib#euwarte#ie#: jp 0 + #ib#eugrab#ie#: jp 0 + #ib#eufree#ie#: jp 0 + #ib#eushutup#ie#: jp 0 + #ib#euinfo#ie# jp 0 + +So kann SHard die entsprechenden 0-Routinen vermittels der obigen Vereinbarungen aufru +fen: + + jp eusystemstart + ... + call euwarte + +Für die Gegenrichtung muß SHard der 0-Maschine die "SHard-Leiste" zur Verfügung +stellen, deren Adresse beim Sprung nach 'systemstart' in HL stehen muß. Die 0-Maschine +kopiert diese Leiste. SHard darf daher anschliessend den Bereich anderweitig (z.B. +EA-Puffer) verwenden: + + + #ib#SHDID#ie#: defm 'SHARD ' ; 16 Byte + #ib#SHDVER#ie#: defw 8 + #ib#MODE#ie#: defw + #ib#ID4#ie#: defw + #ib#ID5#ie#: defw + #ib#ID6#ie#: defw + #ib#ID7#ie#: defw + defw + defw + #ib#OUTPUT#ie#: jp shout + #ib#BLOCKIN#ie#: jp shbin + #ib#BLOCKOUT#ie#: jp shbout + #ib#IOCONTROL#ie#: jp shiocnt + #ib#SYSEND#ie#: jp shend + #ib#SCHINF#ie#: jp shsinf + #ib#SCHACC#ie#: jp shsacc + defw + #ib#LIMIT#ie#: defw + + +#b("Allgemeine Link-Bedingungen")# +#goalpage("link")# + +In der Regel sind sowohl 0-Routinen als auch SHard-Routinen durch 'call' aufzurufen: + + call <routine> + +Ausnahmen von dieser Regel sind im folgenden stets besonders vermerkt. + +Generelle Link-Bedingung (für SHard- und 0-Routinen) ist: + + Alle Register - bis auf die jeweils spezifizierten Ausgangsparameter und das F-Regi + ster *) - bleiben unverändert. +#foot# +#f#*) Flags sind i.a. nach dem Aufruf einer Routine undefiniert. Ausnahmen sind natürlich die Flags, die als Ausgangs +parameter in manchen Fällen definiert sind.#a# +#end# + +Jede SHard-Routine muß also alle Register (bis auf F), die sie verändert und die keine +Ausgangsparameter sind, retten und wiederherstellen. Im Gegenzug braucht SHard beim +Aufruf von 0-Routinen selbst keine Register zu retten. + + +#b("Interrupts")# +#goalpage("intr")# + +Zwei externe Ereignisse (Zeitgeber und Eingabe, siehe S.#topage("zeit")# und S.#topage("inp")#) werden von +EUMEL-0 behandelt. Die entsprechenden Interrupts muß SHard per 'call' an 0-Routinen +weiterleiten. Außerhalb des Moduls SHard wird der 'reti'-Befehl nicht verwendet, damit der +SHard die Kontrolle über die Interruptlevel behält. Die Register (bis auf die Eingangsparame +ter) werden von den aufzurufenden 0-Routinen selbst gesichert. Die normale Interrupt- +Sequenz im SHard sieht dann folgendermaßen aus: + + intadr: push af + ld a,<parameter> + call <routine> + pop af + reti + +Achtung: SHard muß die Interrupt-Routinen im 'disable-int'-Modus anspringen. Dies ist + normalerweise schon durch die Hardware gegeben. + +Die 0-Routinen geben von sich aus den 'ei'-Befehl. Dies erfolgt im allgemeinen sehr +frühzeitig (innerhalb der ersten 30 Befehle), um einen interruptgetriebenen Floppytreiber +zulassen zu können. + + + + +#bb("1. System ","laden")# +#goalpage("laden")# + +SHard muß die EUMEL-0-Software vor dem eigentlichen Start laden. EUMEL-0 befindet +sich normalerweise auf dem Hintergrund. Es müssen von Block 10 an eumel-0-blocks +(siehe 0-Leiste) Blöcke in den Speicher von der Adresse 1400h an aufsteigend geladen +werden. + + Achtung: Zu diesem Zeitpunkt kann SHard die oben aufgeführten 0-Routinen natür + lich noch nicht benutzen. Insbesondere dürfen die Laderoutinen nicht 'warte' + aufrufen. Das wird hier besonders betont, weil der Hintergrundzugriff beim + eigentlichen Systemlauf in der Regel 'warte' verwenden wird. + + Hinweis: Der erste Block der EUMEL-0-Software (Block 10) enthält in den ersten + fünf Bytes den Text "EUMEL", um eine Identifikation durch den SHard- + Lader zu ermöglichen. + +Es wird empfohlen, nach folgendem Verfahren zu laden: + + IF archivgeraet enthaelt diskette AND eumel 0 auf archiv + THEN lade eumel 0 vom archiv + ELIF eumel 0 auf hintergrund + THEN lade eumel 0 vom hintergrund + ELSE laden unmoeglich + FI . + +So kann man auch bei einem frisch formatierten Hintergrundmedium einen neuen Hinter +grund (mit EUMEL-0-Urlader) einspielen, indem man ein Hintergrundarchiv vor dem +Systemstart in das Archivgerät legt. Dann wird EUMEL-0 von dort geladen, so daß man den +Hintergrund dann wie im Systemhandbuch beschrieben vom Archiv auf das Hintergrund +medium kopieren kann.*) +#foot# +#f#*) Kopiervorgänge (Archiv -> Hintergrund) werden vom EUMEL-0-Urlader erledigt, so daß SHard keine derartigen +Routinen enthalten muß.#a# +#end# + + + +#bb("2. System","start und -ende")# +#goalpage("start")# + +SHard muß alle für den Rechner notwendigen (Hardware-) Initialisierungen durchführen und +erst danach die EUMEL-0-Maschine starten ('systemstart'). + + #dx("systemstart")# (0-Routine) + + Eingang: HL = Adresse der SHard-Leiste + Interrupts disabled + + Aufruf: jp systemstart + + Zweck: Die EUMEL-0-Maschine wird gestartet. Alle notwendigen + Hardwareinitialisierungen (Interrupt Modus des Z80 und Ini + tialisierungen der Peripheriebausteine) müssen vorher schon + geschehen sein. + + Hinweis: Der Stackpointer braucht nicht definiert zu sein, da beim + Ansprung DI-Zustand herrschen sollte und somit keine + Interrupts auftreten können. EUMEL-0 lädt beim Start das + SP-Register und läßt Interrupts zu (EI). Falls jedoch in dieser + Zeit ein "Non Maskable Interrupt" auftreten kann, muß SHard + SP "vorläufig" laden. + + MODE: Über das MODE-Wort in der SHard-Leiste können Op + tionen gesetzt werden: + + Bit 0 = 0 EUMEL-0 ist auf dem Hintergrund abge + speichert. Der entsprechende Bereich bleibt + geschützt. (Standard) + + Bit 0 = 1 EUMEL-0 befindet sich nicht auf dem Hin + tergrund. Der entsprechende Bereich steht + zur freien Verfügung für andere EUMEL- + Daten. + (Da die EUMEL-0-Software nur beim + Systemstart geladen wird (read only!), kann + es bei Geräten mit kleinem Hintergrund + interessant sein, diese Blöcke auf dem + Hintergrund anderweitig zu nutzen. Das + Systemladen kann dann z.B. mit Hilfe einer + speziellen Urladediskette vom Archivgerät + aus erfolgen.) + + Bit 8 = 0 Beim Systemstart wird der Speicher über + prüft. (Standard) + + Bit 8 = 1 Der Speichertest beim Systemstart unter + bleibt. Man sollte nur bei Rechnern, die + beim Einschalten schon eigene Speicher + tests durchführen, auf den Speichertest des + EUMEL verzichten. + + Bit 9 = 0 Beim Systemstart wird die Vortest-Tapete + ausgegeben und man kann durch Eingabe + eines Zeichens die Vortestmenüs aktivieren + (s. Systemhandbuch). (Standard) + + Bit 9 = 1 Die Vortest-tapete wird unterdrückt. Es gibt + auch keine Möglichkeit, die Vortestfunk + tionen aufzurufen. Der Speichertest unter + bleibt ebenfalls. + + + #dx("SYSEND")# + + Parameter: - + + Zweck: Hiermit wird SHard das Ende eines Systemlaufs mitgeteilt. + Somit können evtl. notwendige Abschlußbehandlungen durch + geführt werden. SHard kann mit 'ret' zu EUMEL-0 zurück + kehren, muß aber nicht. Diese Routine kann z.B. dazu benutzt + werden, die Hardware auszuschalten oder in ein umgebendes + System zurückzukehren (EUMEL als Subsystem). In den + meisten Fällen wird die Routine leer implementiert werden, + d.h. nur aus 'ret' bestehen. + + +#bb("3. ","Speicherverwaltung")# +#goalpage("spver")# + + +#b("Hauptspeicher")# +#goalpage("haupt")# + +Der Hauptspeicher (#ib#RAM#ie#) umfaßt die direkt adressierbaren 64 K des Z80. Da die Anfangs +adresse des für EUMEL-0 und Paging verfügbaren Bereichs fest ist (1400h), muß SHard nur +über die Obergrenze des verfügbaren Bereichs informieren. + + #dx("LIMIT")# + + Über das LIMIT-Wort in der SHard-Leiste kann sich SHard + noch Bereiche vor dem Speicherende (z.B. für CP/M BIOS) + freihalten. Auf jeden Fall muß CFFFh <= LIMIT gewährleistet + sein, d.h. der Bereich bis CFFFh gehört zum Pagingbereich. + Im Normalfall wird FFFFh geliefert werden. + + + +#b("Schattenspeicher")# +#goalpage("schatt")# + +Das EUMEL-System ist in der Lage, trotz der durch die 16-Bit Adressen gegebenen Ein +schränkung auf 64 kB, weiteren Speicher anzuschließen. Dieser wird Schattenspeicher +genannt. + +Der Schattenspeicher (#ib#RAM#ie#) sollte so angeschlossen sein, daß über ein nicht zu großes #ib##on("italic")# +Fenster#ie##off("italic")# des normalen Adressraumes ( < 4 kB) auf diesen zugegriffen werden kann. Welcher +Bereich des Schattenspeichers dabei gemeint ist, wird durch die SHard-Routine SCHACC +mitgeteilt (s.u.). Diese Art des Zugriffs wird Fenstermodus genannt. Das Restsystem nutzt das +Fenster echt (d.h. ohne den Inhalt in andere Bereiche des normalen Adressraumes zu trans +portieren). + +Ist ein so kleines Fenster in der Hardware nicht vorgesehen (z.B. 48 kB Bänke bzw. nur +DMA-Zugriff), so kann auch solcher Schattenspeicher benutzt werden (Transportmodus). +Wichtig ist dabei, daß EUMEL-0 die oben erwähnten echten Fensterzugriffe unterläßt. +(Simulation im Transportmodus wäre erheblich zu teuer.) Daher muß EUMEL-0 wissen, in +welchem Modus der Schattenspeicher ansprechbar ist (SCHINF). + +Hinweis: Wenn möglich sollte der Fenstermodus implementiert werden, da er im Multi- + User-Betrieb (ab ca. 3 Teilnehmern) deutliche Effizienzvorteile bietet. + + +Das Schattenspeicherinterface gibt es in 2 Modi: + + - Fenstermodus (Bit 2**15 von BC gesetzt bei SCHINF) + - Transportmodus (Bit 2**14 von BC gesetzt bei SCHINF) + + +#d("Fenstermodus")# + + #dx("SCHINF")# (im Fenstermodus) + + Ausgang: BC 2**15 + Schattenspeichergröße (in K) + + Zweck: EUMEL-0 kann so die Größe des Schattenspeichers und den + gewünschten Modus (hier: Fenstermodus) erfragen. Falls kein + Schattenspeicher vorhanden ist, muß 0 als Größe geliefert + werden. Das Resultat von SCHINF darf sich innerhalb eines + Systemlaufs nicht ändern. + + + #dx("SCHACC")# (im Fenstermodus) + + Eingang: HL Nummer der 1/2K-Seite, die in das Fenster zu schal + ten ist. + Ausgang: HL Anfangsadresse (im Normaladreßraum) des aktuellen + Fensters + + Zweck: Dient zum Zugriff auf den Schattenspeicher über das Fen + ster. Man beachte, daß mehrere Fenster möglich sind, aber + alle im Adreßbereich des SHards liegen müssen! Die Num + mern der 1/2K-Seiten des Schattenspeichers liegen immer + im Bereich von 0 bis 2n-1, wobei n die von SCHINF geliefer + te Größe des Schattenspeichers ist. Daraus folgt, daß + SCHACC nicht aufgerufen wird, falls kein Schattenspeicher + vorhanden ist. + +#d("Transportmodus")# + + #dx("SCHINF")# (im Transportmodus) + + Ausgang: BC 2**14 + Schattenspeichergröße (in K) + + Zweck: EUMEL-0 kann so die Größe des Schattenspeichers und den + gewünschten Modus (hier: Transportmodus) erfragen. Falls + kein Schattenspeicher vorhanden ist, muß 0 als Größe gelie + fert werden. Das Resultat von SCHINF darf sich innerhalb + eines Systemlaufs nicht ändern. + + + #dx("SCHACC")# (im Transportmodus) + + Eingang: A = 1 Transport in den Schattenspeicher + A = 2 Transport aus dem Schattenspeicher + DE Nummer der 1/2K Seite im Schattenspeicher + HL Adresse im normalen Hauptspeicherbereich + + Zweck: Es werden jeweils 512 Bytes aus dem Normal- in den + Schattenspeicher (A=1) bzw. aus dem Schattenspeicher in + den normalen Hauptspeicher (A=2) kopiert. + Die Nummern der 1/2K-Seiten des Schattenspeichers liegen + immer im Bereich von 0 bis 2n-1, wobei n die von SCHINF + gelieferte Größe des Schattenspeichers ist. Daraus folgt, daß + SCHACC nicht aufgerufen wird, falls kein Schattenspeicher + vorhanden ist. + + Eingang: A = 3 + E Index (immer geradzahlig: 0,2,4,...254) + Ausgang: BC Bereichslänge DIV 3 + HL Bereichsadresse + + Zweck: Für den angegebenen Index ist die Adresse eines Haupt + speicherbereichs und 1/3 der Länge dieses Bereichs zu + rückzumelden (Anzahl Einträge � 3 Bytes) Es sind also 128 + solcher Bereiche zur Verfügung zu stellen. Bei n K Schat + tenspeicher sollte jeder Bereich größer als 6*n/128 Bytes sein. + Alle Bereiche müssen gleich groß sein. + + Beispiel: Bei bis zu 256 K sollten 16-Byte-Bereiche + benutzt werden: + + shacc3: ld l,e + ld h,0 + add hl,hl + add hl,hl + add hl,hl + ld bc,schtab + add hl,bc ; <e> DIV 2 * 16 + schtab + ld bc,5 ; 16 DIV 3 + ret + + schtab: defs 128*16 + + + + +#b("Blocktransfer im Speicher")# +#goalpage("ldir")# + + + +#b("Speicherfehler")# +#goalpage("memerr")# + +Falls die Hardware Speicherfehler aufgrund von Paritybits, ECC oder ähnlichem feststellen +und an SHard melden kann, sollte das zur Erhöhung der Systemsicherheit genutzt werden. + +Wenn SHard (z.B. über Interrupt) einen Speicherfehler mitgeteilt bekommt, sollte er wenn +möglich eine entsprechende Meldung ausgeben und das System brutal anhalten: + + rien#ub# #ue#ne#ub# #ue#vas#ub# #ue#plus: jr rien#ub# #ue#ne#ub# #ue#vas#ub# #ue#plus + + +Wenn Speicherfehler mit Sicherheit bemerkt werden, verhindert diese Reaktion, daß die +Fehler auf dem Hintergrund festgeschrieben werden und evtl. später zu Systemfehlern führen. + +Der Anwender kann dann durch Hardware-Reset auf den letzten Fixpunkt des EUMEL- +Systems zurücksetzen. So verliert er zwar evtl. die letzten Minuten seiner Arbeit, behält aber +auf alle Fälle ein konsistentes System. + + + + +#bb("4. ","Zeitgeber")# +#goalpage("zeit")# + +SHard muß einen Zeitgeberinterrupt erzeugen, der ca. 10 bis 100 mal pro Sekunde auftritt. +Dabei ist die 0-Routine 'timerinterrupt' aufzurufen. Ohne diesen Interrupt wird die Uhr nicht +geführt, und die Zeitscheibenlogik für das Timesharing fällt aus. + + #dx("timerinterrupt")# (0-Routine) + + Eingang: A seit letztem Zeitgeberinterrupt vergangene Zeit (in ms) + + Zweck: Wird von EUMEL-0 für interne Uhren und für das Schedu + ling (Zeitscheibenlogik) verwendet. Es werden keine hohen + Genauigkeitsanforderungen an die Zeitangaben bei #on("i")#einzel + nen#off("i")# Interrupts gestellt. Um EUMEL-0 eine genaue Real + zeituhr zu ermöglichen, sollte die so erzeugte Zeitangabe #on("i")#im + Mittel#off("i")# aber möglichst genau sein, d.h. die Summe der inner + halb einer Minute so übergebenen Werte sollte zwischen + 59995 und 60005 liegen. + + + +#bb("5. ","Kanäle")# +#goalpage("channel")# + +Einiges zum Kanalkonzept: + +Das System kennt die Kanäle 0..32. + + Kanal 0 ist der Systemhintergrund. + Die Kanäle 1..15 sind für Stream-IO (Terminals, Drucker, ...) vorgesehen. + Kanal 31 ist der Standard-Archivkanal. + Kanal 32 ist der Parameterkanal. + +Die Kanäle 2.. 30 können installationsabhängig verfügbar sein oder auch nicht. Deren Funk +tion ist dann Absprachesache zwischen Installation und SHard. + +Kanäle können über Block-IO (BLOCKOUT, BLOCKIN) oder Stream-IO (OUTPUT,..) ange +sprochen werden. Das System erfährt über IOCONTROL, welche Betriebsart des Kanals +sinnvoll ist. + +#on("i")##on("b")#Achtung: Alle Kanaloperationen müssen grundsätzlich für alle Kanäle (0...32) aufgerufen + werden können. Dabei können Operationen auf nicht vorhandenen Kanälen und + unsinnige Operationen (z.B. Stream-IO auf Kanal 0) leer implementiert wer + den.#off("b")# (Dafür werden im folgenden bei jeder SHard-Routine Vorschläge gemacht.)#off("i")# + + + +#bb("5.1 ","Stream-IO")# +#goalpage("stream")# + +Über Stream-IO wickelt das System die übliche zeichenorientierte Ein-/Ausgabe auf Termi +nals, Druckern, Plottern usw. ab. Stream-IO wird nur für die Kanäle 1...15 gemacht. + + #dx("inputinterrupt")# (0-Routine)#goalpage("inp")# + + Eingang: A Kanalnummer (1...15) + B eingegebenes Zeichen + C Fehlerbits: + Bit 0 = 1 Mindestens ein Zeichen ging + verloren. + Bit 1 = 1 Es wurde der BREAK-Zustand + (bei V24) erkannt. + Bit 2 = 1 Das Zeichen ist u.U. falsch + (Paritätsfehler). + + Ausgang: A Anzahl Zeichen, die noch übernommen werden kön + nen. + + Zweck: SHard muß EUMEL-0 durch Aufruf dieser Routine mitteilen, + daß eine Eingabe vorliegt. + + Hinweise: EUMEL-0 puffert die Zeichen. Siehe auch IOCONTROL: + "weiter". + + Bei Kanalnummern <1 oder >15 wird der Aufruf von + EUMEL-0 ignoriert. + + Falls die Hardware keine Inputinterrupts zur Verfügung stellt, + sollte ein Timer benutzt werden, um alle möglichen Input + quellen regelmäßig abzufragen. Dabei muß man allerdings den + goldenen Mittelweg zwischen zu häufiger (Systemdurchsatz + sinkt) und zu seltener Abfrage (Zeichen gehen verloren) + suchen. Man sollte dabei nicht nur an die menschliche Tipp + geschwindigkeit sondern auch an die höchste Baudrate + denken, die man für Rechnerkopplungen noch unterstützen + will. *) +#foot# +#f#*) Eine weitere Möglichkeit, auf manchen Kanälen ohne Interrupts auszukommen, wird bei der IOCONTROL-Funktion +"weiter" beschrieben (siehe S.#topage("weiter")#).#a# +#end# + + Falls SHard Flußkontrolle für den Kanal ausüben soll, muß er + die Rückmeldung in A auswerten. Dabei ist mit einem geeig + neten Schwellwert zu arbeiten, da in der Regel die sendende + Gegenstelle einer Sendeunterbrechung nicht sofort Folge + leistet. + + Achtung: #on("i")#Keinesfalls darf 'inputinterrupt' rekursiv aufgerufen werden. + Normalerweise wird das automatisch verhindert, wenn man + den zugehörigen Hardwareinterrupt erst nach der 0-Routine + wieder freigibt. Falls das nicht möglich ist und unter bestimm + ten Umständen das nächste Zeichen abgeholt werden muß, + bevor die 0-Routine beendet ist, muß SHard einen eigenen + Puffer implementieren:#off("i")# + + hardwareinterrupt: + IF input interrupt aktiv + THEN trage zeichen in shard puffer ein ; + gib hardware interrupt frei + ELSE input interrupt aktiv := true ; + gib hardware interrupt frei ; + input interrupt ; + disable interrupt ; + WHILE shard puffer enthaelt noch zeichen REP + nimm zeichen aus shard puffer ; + enable interrupt ; + input interrupt ; + disable interrupt + PER ; + input interrupt := false ; + enable interrupt + FI . + + + #d("OUTPUT")# + + Eingang: A Kanalnummer (1...15) + BC Anzahl auszugebender Zeichen + HL Adresse der Zeichenkette + Ausgang: BC Anzahl der übernommenen Zeichen + C-Flag gesetzt <=> alle Zeichen übernommen + + Zweck: Ausgabe einer Zeichenkette. Diese ist (möglichst ganz) zwi + schenzupuffern, denn die Ausführung von OUTPUT sollte kein + Warten auf IO enthalten. Der Ausgabepuffer muß mindestens + 50, besser 100 Zeichen fassen können. Durch eine Inter + ruptlogik oder etwas Äquivalentes ist sicherzustellen, daß + dieser Puffer parallel zur normalen Verarbeitung ausgegeben + wird. Wenn die auszugebende Zeichenkette nicht vollstän + dig in den Puffer paßt, sollten trotzdem so viele Zeichen wie + möglich übernommen werden. Im weiteren Verlauf ruft + EUMEL-0 dann wieder OUTPUT mit dem Rest der Zei + chenkette auf. + + Hinweis: OUTPUT kann mit BC=0 aufgerufen werden. Auch diese + leere Operation muß mit gesetztem C-Flag quittiert wer + den. + + Achtung: #on("i")#Keinesfalls darf innerhalb von OUTPUT die 0-Routine 'warte' + aufgerufen werden.#off("i")# + + Vorschlag: Falls der Kanal nicht existiert bzw. OUTPUT darauf unsinnig + ist, sollte vorgegaukelt werden, alle Zeichen seien ausge + geben (BC unverändert und C-Flag gesetzt). + + + +#b("Terminals")# +#goalpage("term")# + +"Normale" #ib#Terminal#ie(1,", normales")#s können ohne weitere Unterstützung des SHards angeschlossen wer +den. Die zur Anpassung an den EUMEL-Zeichensatz *) notwendigen #ib#Umcodierungen#ie# werden +von den höheren Ebenen aus eingestellt. Da diese Umsetztabellen vom SHard unabhängig +sind, stehen automatisch alle so angepaßten Terminaltypen allen EUMEL-Anwendern zur +Verfügung! +#foot# +#f#*) Siehe "EUMEL Benutzerhandbuch"#a# +#end# + +Für den Anschluß eines #on("b")##on("i")#integrierten #ib#Terminal#ie(1,", integriertes")#s#off("i")##off("b")#, in dessen Bildwiederholspeicher direkt gear +beitet wird, kann man häufig den Terminaltyp 'psi' verwenden (siehe auch "Exoten"). + +Näheres zu Terminaltypen und -anschlüssen findet man im "EUMEL Systemhandbuch" +unter den Stichwörtern #on("i")#Konfiguration#off("i")# und #on("i")#Konfigurierung#off("i")#. + + + +#bb("Drucker, ","Plotter")# +#goalpage("druck")# + +#ib#Drucker#ie# und Plotter werden vom EUMEL-System wie Terminals angesehen. Da in der Regel +der Rechner aber schneller Zeichen senden als der Drucker drucken kann, müssen solche +Geräte in der Regel mit Flußkontrolle angeschlossen werden (siehe S.#topage("fluss")#). + +Wenn Drucker oder Plotter über eine Parallelschnittstelle angeschlossen werden, kann man +auf diesem Kanal möglicherweise auf einen Ausgabepuffer verzichten. Voraussetzung ist +dabei, daß + + a) der Drucker einen eigenen Puffer hat und + b) der Puffer "schnell" gefüllt werden kann (< 0.1 ms/Zeichen). + +Dann kann man auf den bei der SHard-Routine OUTPUT geforderten Puffer verzichten und +die Zeichenkette direkt über die Parallelschnittstelle an den Drucker übergeben. Wenn der +Drucker 'Puffer voll' signalisiert, sollte die Zeichenübernahme bei OUTPUT abgebrochen +werden. *) #on("i")#Auf keinen Fall darf CPU-intensiv auf Freiwerden des Puffers gewartet werden!#off("i")# +#foot# +#f#*) siehe auch IOCONTROL "frout", S.#topage("frout")##a# +#end# + + + +#b("Exoten")# +#goalpage("exot")# + +Exotische #ib#Terminal#ie(1," exotisches")#s (im Sinne dieser Beschreibung) sind solche, für die eine Umsetztabelle +im System (siehe Konfiguratorbeschreibung) nicht ausreicht bzw. nicht nötig ist (Beispiele: +Terminals, in deren Bildwiederholspeicher direkt gearbeitet wird; Terminals, die soweit +programmierbar sind, daß sie den EUMEL-Zeichencode können). + +Für solche Terminals muß in der Konfiguration der Terminaltyp '#ib#psi#ie#' eingestellt werden. Dieser +wirkt ohne Umcodierungen, d.h. die EUMEL-Codes (siehe Benutzerhandbuch) werden direkt +dem SHard zugestellt (wie bei 'transparent'), jedoch mit folgenden Besonderheiten: + +Eingabeseitig werden zusätzlich folgende Codezuordnungen getroffen: + + Code Funktion + + 7 SV (Aktivierung: 'gib supervisor kommando:') + 17 STOP (Ausgabe auf diesen Kanal wird gestoppt) + 23 WEITER (Ausgabe läuft wieder weiter) + 4 INFO (System geht in Debugger, falls Debugoption) + + + +#bb("5.2 ","Block-IO")# +#goalpage("block")# + +Über Block-IO wickelt das System die Zugriffe zum Pagingmedium und zum Archiv ab. +Ferner ist daran gedacht, auch auf V.24-Schnittstellen Block-IO z.B. für Rechnerkopplung +zuzulassen. Die Kanalnummer in Reg. A unterscheidet diese Fälle. Außer beim Paging (A=0) +wird ein Block-IO durch die ELAN-Prozeduren 'blockin' und blockout' induziert. + +Bei Block-IO wird immer ein 512 Byte großer Hauptspeicherbereich mit übergeben. Dieser +kann (im Gegensatz zu OUTPUT) direkt benutzt werden, d.h. es muß keine Umpufferung +erfolgen. + +Dieser Hauptspeicherbereich darf nur bei BLOCKIN verändert werden. + +SHard darf (anders als bei OUTPUT) erst dann zur Aufrufstelle zurückgeben, wenn die +verlangte Operation abgeschlossen ist. Treten während der Operation Wartezeiten auf, so muß +SHard die 0-Routine 'warte' aufrufen, damit das System andere Prozesse weiterlaufen +lassen kann. + +EUMEL-0 definiert bestimmte Funktionen für Hintergrund (Kanal 0) und Archiv (Kanal 31). +Operationen auf anderen Kanälen kann SHard nach Belieben implementieren und deren +Leistung seinen Installationen über ELAN-Pakete zur Verfügung stellen. Das System vergibt +auch in Zukunft für den #ib##on("italic")#Funktionscode#ie##off("italic")# in Register BC nur positive Werte (Bit 7 von B = 0). +Der SHard kann selbst negative Codes einführen. + + + #d("BLOCKIN")# + + Eingang: A Kanalnummer (0...32) + BC Funktionscode 1 + DE Funktionscode 2 + HL Adresse des Hauptspeicherbereichs + Ausgang: A undefiniert (darf also verändert werden) + BC Rückmeldecode + HL darf verändert werden + + Der Inhalt des Hauptspeicherbereichs (<HL>... <HL> + +511) darf verändert sein. + + Zweck: "Einlesen" von Blöcken. Die genaue Wirkung hängt vom + Funktionscode und dem Kanal ab. + + Vorschlag: Falls der Kanal nicht existiert bzw. BLOCKIN darauf unsinnig + ist, sollte die Rückmeldung -1 in BC geliefert werden. + + + #d("BLOCKOUT")# + + Eingang: A Kanalnummer (0...32) + BC Funktionscode 1 + DE Funktionscode 2 + HL Adresse des Hauptspeicherbereichs + Ausgang: A undefiniert (darf also verändert werden) + BC Rückmeldecode + HL darf verändert werden + + Der Inhalt des Hauptspeicherbereichs darf #on("i")#nicht#off("i")# verändert + werden! + + Zweck: "Ausgeben" von Blöcken. Die genaue Wirkung hängt vom + Funktionscode und dem Kanal ab. + + Vorschlag: Falls der Kanal nicht existiert bzw. BLOCKOUT darauf un + sinnig ist, sollte die Rückmeldung -1 in BC geliefert wer + den. + + + #dx("warte")# (0-Routine) + + Ausgang: Alle Register undefiniert! + + Zweck: Diese Routine ist bei 'blockin' oder 'blockout' dann aufzu + rufen, wenn SHard im Augenblick nichts zu tun hat. Durch + den Aufruf von 'warte' erhalten andere Systemteile die + Möglichkeit, weiterzuarbeiten. Ein 'warte' kann bis zu ca. 1/4 + Sekunde Zeit aufnehmen. 'warte' darf nicht in Interrupt + routinen und Stream-IO verwendet werden! 'warte' zerstört + alle Register! SHard muß davon ausgehen, daß 'warte' sei + nerseits andere SHard-Komponenten aufruft. + + +Die Verwendung der 0-Routine 'warte' soll hier an einigen Beispielen verdeutlicht werden: + + + blockout auf platte : + WHILE platte noch nicht frei REP + warte + ENDREP ; + uebertrage schreibbefehl an controller ; + uebertrage daten an controller . + + blockin von platte : + WHILE platte noch nicht frei REP + warte + ENDREP ; + uebertrage lesebefehl an controller ; + WHILE daten noch nicht gelesen REP + warte + ENDREP ; + hole daten vom controller . + + + blockout auf floppy : + seekbefehl an controller ; + WHILE seek noch nicht fertig REP + warte + ENDREP ; + setze dma auf schreiben block zur floppy ; + schreibbefehl an controller ; + WHILE schreiben noch nicht fertig REP + warte + ENDREP . + + blockin von floppy : + seekbefehl an controller ; + WHILE seek noch nicht fertig REP + warte + ENDREP ; + setze dma auf lesen block von floppy ; + lesebefehl an controller ; + WHILE lesen noch nicht fertig REP + warte + ENDREP . + + + +#b("Block-IO bei Hintergrund und Archiv")# +#goalpage("bhgarch")# + +#ib#Hintergrund#ie# (Kanal 0) und #ib#Archiv#ie# (Kanal 31) unterscheiden sich in den Link-Bedingungen nur +in der Kanalnummer. Die Aufrufe von BLOCKIN und BLOCKOUT werden mit folgenden +Eingangsparametern versorgt: + + #on("b")#BLOCKIN#off("b")# A 0 bzw. 31 + B 0 + C Blocknummer DIV 65536 + DE Blocknummer MOD 65536 + HL Hauptspeicheradresse + + Der angegebene 512-Byte-Block ist in den Hauptspeicher + ab <HL> einzulesen. + + #on("b")#BLOCKOUT#off("b")# A 0 bzw. 31 + B 0 + C Blocknummer DIV 65536 + DE Blocknummer MOD 65536 + HL Hauptspeicheradresse + + Der Hauptspeicherbereich (<HL>...<HL>+511) ist auf den + angegebenen Block zu schreiben. + +Als Rückmeldungen sind zu liefern:#goalpage("errcod")# + + 0 Operation korrekt ausgeführt. + 1 Manuell behebbarer Fehler (z.B. Laufwerktür offen) + 2 Permanenter Fehler (z.B. Daten nicht lesbar) + 3 Versorgungsfehler (zu hohe Blocknummer) + +Zusätzlich zu der Rückmeldung muß bei BC <> 0 in HL die Adresse eines Fehlerstrings +(Längenbyte + Fehlertext) geliefert werden. *) +#foot# +#f#*) Diese Zusatzrückmeldung ist nur für die BLOCKIN/OUT Aufrufe auf Kanal 0/31 von Bedeutung. Sie wird nur von +EUMEL-0 beim Paging und im Hardwaretest ausgewertet.#a# +#end# + +#dx("Fehlerwiederholungen")#: Das EUMEL-System führt von sich aus Fehlerwiederho + lungen beim Hintergrund- und beim Archivzugriff + durch. SHard sollte deshalb im Fehlerfall die Opera + tion nicht selbst wiederholen, sondern einen Lese/ + Schreibfehler zurückmelden. So werden dem + EUMEL-System auch Soft-Errors gemeldet. In + manchen Fällen soll vor einem erneuten Lese- oder + Schreibversuch der Arm auf Spur 0 positioniert + werden o.ä. Um das zu erreichen, sollte SHard diese + "Reparaturaktion" direkt im Anschluß an den fehler + haften Versuch durchführen. + +#dx("Kontrollesen")#: Falls Kontrollesen (nach jedem Schreibzugriff) notwendig ist, + muß das allerdings vom SHard durchgeführt werden. + In der Regel reicht es dazu, den geschriebenen + Block "ohne Datentransport" zu lesen, so daß nur + CRC überprüft wird. + +Will SHard weitere Archivlaufwerke zur Verfügung stellen, so kann er dafür Kanalnummern +(30,29..) vergeben. Auf ELAN-Ebene kann die archivierende Task durch 'continue (x)' das +Laufwerk 'x' ansteuern. + +Hinweis: Das System versucht Hintergrund und Archiv parallel zu betreiben, d.h. wenn + SHard bei der Hintergrundbehandlung das UP 'warte' aufruft, kann 'warte' seiner + seits die Archivbehandlung des SHards aufrufen. Wenn beides z.B. denselben + Floppykontroller benutzt, muß SHard sicherstellen, daß das gut geht (z.B. durch + Semaphoren). + + + + +#bb("5.3 ","IO-Steuerung")# +#goalpage("iocontrol")# + +Die IO-Steuerung erlaubt Steuerung und Zustandsabfragen der Kanäle. IO-Steuerung wird +(außer bei Kanal 0) auch durch 'control' in ELAN induziert. + +Der Funktionscode in BC unterliegt denselben Konventionen wie bei Block-IO, d.h. das +System verwendet nur positive Codes. Der SHard-Schreiber kann auch negative Codes für +Sonderzwecke vorsehen. + + + #d("IOCONTROL")# + + Eingang: A Kanalnummer (0...32) + BC Funktionscode 1 + DE Funktionscode 2 + HL Funktionscode 3 + Ausgang: BC Rückmeldung + A darf verändert werden, in einigen Fällen zusätzliche + Rückmeldung + C-Flag (in einigen Fällen zusätzliche Meldung) + + Zweck: abhängig von 'Funktionscode 1' (s.u.) + +Das System verlangt folgende Informations- und Steuerleistungen über IOCONTROL: + + #d("IOCONTROL ""typ""")# + + Eingang: A Kanalnummer (0...31) + BC 1 + Ausgang: BC Kanaltyp + + Zweck: Informiert EUMEL-0, welche IO für den angegebenen Kanal + sinnvoll ist. Die Rückmeldung in BC wird bitweise interpre + tiert: + + Bit 0 gesetzt <=> 'inputinterrupt' kann kommen. + Bit 1 gesetzt <=> OUTPUT ist sinnvoll. + Bit 2 gesetzt <=> BLOCKIN ist sinnvoll. + Bit 3 gesetzt <=> BLOCKOUT ist sinnvol. + Bit 4 gesetzt <=> IOCONTROL "format" ist sinn + voll. + + Hinweis: #on("i")#Trotz dieser Informationsmöglichkeit wird nicht garantiert, daß + nur sinnvolle Operationen für den Kanal aufgerufen werden.#off("i")# + + + #dx("IOCONTROL ""frout""")##goalpage("frout")# + + Eingang: A Kanalnummer (1...15) + BC 2 + Ausgang: BC Anzahl Zeichen, die nächster OUTPUT übernimmt + C-Flag gesetzt <=> Puffer leer + + Zweck: Liefert Information über die Belegung des Puffers. Diese + Information wird von EUMEL-0 zum Scheduling benutzt. + + Achtung: #on("i")#Wenn EUMEL-0 längere Zeit kein OUTPUT gemacht hat, + muß irgendwann BC > 49 gemeldet werden.#off("i")# + + Hinweis: Unter Berücksichtigung des oben Gesagten darf "gelogen" + werden. Man kann z.B. immer 50 in BC zurückmelden, muß + dann aber schlechtere Nutzung der CPU bei Multi-User- + Systemen in Kauf nehmen. + + Falls auf dem angegebenen Kanal ein Drucker mit eigenem + Puffer über Parallelschnittstelle angeschlossen ist (siehe + S.#topage("druck")#) und man auf einen SHard-internen Puffer verzichtet hat, + sollte bei 'Druckerpuffer voll' 0 in BC und 'NC' zurückge + meldet werden. Wenn aber Zeichen übernommen werden + können, sollte 50 in BC und 'C-Flag gesetzt' gemeldet + werden. + + Vorschlag: Falls der Kanal nicht existiert oder nicht für Stream-IO zur + Verfügung steht, sollten 200 in BC und C-Flag gesetzt + zurückgemeldet werden. + + + + + #dx("IOCONTROL ""weiter""")##goalpage("weiter")# + + Eingang: A Kanalnummer (1...15) + BC 4 + Ausgang: - + + Zweck: Das System ruft "weiter" für den in A angegebenen Kanal + auf, wenn es wieder Eingabezeichen puffern kann. + + Hinweis: "weiter" wird von EUMEL-0 auch immer dann aufgerufen, + wenn ein Prozeß auf dem angegebenen Kanal auf Eingabe + wartet und keine Zeichen mehr gepuffert sind. Wenn der + betroffene Kanal von sich aus keine Interrupts erzeugt, kann + SHard dies benutzen, um durch Aufruf von 'inputinterrupt' ein + Eingabezeichen zuzustellen. + #on("i")#Diese Betriebsart sollte nicht für normale Terminalkanäle + eingesetzt werden. Denn dann wird die SV-Taste nur an + EUMEL-0 zugestellt, wenn ein Prozeß auf diesem Kanal auf + Eingabe wartet. Somit sind in dieser Betriebsart CPU-inten + sive Endlosschleifen nicht normal abbrechbar!#off("i")# + + + #d("IOCONTROL ""size""")# + + Eingang: AL Kanalnummer (0...31) + CX 5 + DX Schlüssel + Ausgang: CX Anzahl Blöcke MOD 65536 + AL Anzahl Blöcke DIV 65536 + + Zweck: EUMEL-0 ruft 'size' auf, um die Anzahl Blöcke zu erfahren, + die ein Block-IO-Kanal verkraften kann (Größe von Hin + tergrund und Archiven). Bei Archivlaufwerken, die mehrere + Formate bearbeiten können, dient dieser Aufruf auch zum + Einstellen des Formats für die folgenden blockin/blockout- + Operationen anhand des Schlüssels. + + Schlüssel: 0 Wenn möglich 'erkennend', sonst 'standard'. Im ersten + Fall erkennt SHard das Format der eingelegten Disket + te und stellt dieses ein. + + Die weiteren Schlüssel sind stets definierend. Dabei gibt es + die EUMEL-Standardformate: + + 1 5" 2D-40, Sektor 1..9, 512 Bytes + 2 5" 2D-80, Sektor 1..9, 512 Bytes + 3 5" HD-80, Sektor 1..15, 512 Bytes + 10 8" 1D-77, Sektor 0..15, 512 Bytes + 11 8" 2D-77, Sektor 0..15, 512 Bytes + + Zusätzlich kann man sämtliche Spezialformate angeben: + + 8192 * laufwerkstyp 1: 8" + 2: 5" + 3: 3" + + + 4096 * seiten 0: einseitig + 1: doppelseitig + + + 1024 * dichte 0: single + 1: double + 2: high + + + 256 * spuren 0: 35 + 1: 40 + 2: 77 + 3: 80 + + + 64 * sektorbytes 0: 128 + 1: 256 + 2: 512 + + + 32 * erster sektor 0: \#0 + 1: \#1 + + + sektoren pro spur 0 ... 31 + + So bezeichnet '8762' das Format 8" 1S-77 Sektor 1..26 a + 128 Bytes. + + Anmerkung: SHard sollte alle physisch möglichen EUMEL-Standard + formate unterstützen. Von den Spezialformaten sollten die für + den Datenaustausch wichtigen Formate berücksichtigt werden. + Die EUMEL-Standardformate (1,2,3,10,11) sollten auch über + die entsprechenden analytischen Codes erreicht werden. (Z.B. + bezeichnen 1 und 21929 dasselbe Format.) Die Numerierung + der Blöcke ist in jedem Fall seitenorientiert, d.h. entsprechend + den Standardformaten (siehe S.#topage("arch")#). + + Hinweis: Bei Archiven wird 'size' aufgerufen, nachdem der Archivträ + ger eingelegt wurde. D.h. SHard hat die Gelegenheit, die + Größe anhand des eingelegten Archivträgers zu bestimmen + (z.B. ob single- oder doublesided). + + Vorschlag: Diese Funktion sollte auf nicht vorhandenen und den + Stream-IO-Kanälen 0 liefern. Sie muß aber mindestens auf + Kanal 0 (Hintergrund) und Kanal 31 (Archiv) "echte" Werte + liefern. + + Achtung: #on("i")#Ausnahmsweise darf bei dieser IOCONTROL-Funktion die + 0-Routine 'warte' aufgerufen werden.#off("i")# + + + #d("IOCONTROL ""format""")# + + Eingang: A Kanalnummer (0...31) + BC 7 + Ausgang: BC Fehlercode wie bei Archiv-BLOCKOUT (siehe S.#topage("errcod")#) + + Zweck: Dient zum Formatieren eines Mediums. Diese Funktion kann + für jeden Kanal leer implementiert sein ('ret'). Sie sollte aber + "formatierend" (z.B. auf Kanal 31) arbeiten, falls auf diesem + Kanal die "typ"-Abfrage "Formatieren sinnvoll" liefert. Falls + (bei Diskettenlaufwerken) mehrere Formate möglich sind, + bestimmt der Schlüssel das gewünschte Format. + + Schlüssel: wie bei IOCONTROL "size" + + Hinweis: Falls für das Formatieren ein großer Speicherbereich benö + tigt wird, sollte das Formatieren von Disketten besser in + einem Boot-Dialog vor dem Start von EUMEL-0 angebo + ten werden. Denn sonst müßte der Pagingbereich unnötig + eingeschränkt werden. + Man kann das Formatieren einer Spur CPU-intensiv im + plementieren (d.h. ohne DMA im DI-Modus), wenn man in + Kauf nimmt, daß alle anderen Tasks des EUMEL-Systems in + dieser Zeit "stehen". Dann sollte man aber nach jeder Spur + mehrmals die 0-Routine 'warte' aufrufen. + + Achtung: #on("i")#Ausnahmsweise darf bei dieser IOCONTROL-Funktion die + 0-Routine 'warte' aufgerufen werden.#off("i")# + + + +#b("Konfigurierung serieller Schnittstellen")# +#goalpage("v24")# + +Bei Kanälen, die hardwaremäßig auf #ib#serielle Schnittstellen#ie# (#ib#V.24#ie#) zurückgeführt werden, sind +in der Regel die Größen + + - #ib#Baudrate#ie# (..., 2400, 4800, 9600, ...) + - #ib#Zeichenlänge#ie# (7 Bits, 8 Bits) + - #ib#Parität#ie# (keine, gerade, ungerade) + +einstellbar. Dafür muß SHard die IOCONTROL-Funktionen "baud" und "bits" zur Verfü +gung stellen. Diese werden in zwei Modi benutzt: + + a) #on("b")#einstellend#off("b")# + Läuft der aufrufende EUMEL-Prozeß auf dem privilegierten Steuerkanal (A = 32), + wird der als Parameter mit übergebene #on("i")#adressierte Kanal#off("i")# auf die geforderten Werte + eingestellt, sofern das möglich ist. + + b) #on("b")#abfragend#off("b")# + Läuft der aufrufende EUMEL-Prozeß nicht auf Kanal 32 (A <> 32), wird lediglich + abgefragt, ob der #on("i")#adressierte Kanal#off("i")# auf die übergebenen Werte eingestellt werden + könnte. + +Aufgrund des zweiten Modus können die höheren EUMEL-Ebenen dem Anwender bei der +Konfigurierung mitteilen, welche Werte sich auf dem jeweiligen Kanal einstellen lassen. Das +nutzt z.B. das Standard-Konfigurationsprogramm aus. + +Hinweis: Bei einigen Kanälen (z.B. bei einem integrierten Terminal oder einer Parallel + schnittstelle) sind Baudrateneinstellungen sinnlos. Bei anderen können sie nur + hardwaremäßig vorgenommen werden (Jumper, Dip Switches). In allen diesen + Fällen muß SHard bei allen Einstellungen 'unmöglich' melden. (Standardmäßig + wird der Anwender bei der Einstellung seiner Konfiguration dann auch nicht + danach gefragt.) + + + #d("IOCONTROL ""baud""")# + + Eingang: A eigener Kanal (1...15 / 32) + BC 8 + DE adressierter Kanal + HL Schlüssel + Ausgang: BC Rückmeldung (0 = ok, 1 = nicht möglich) + + Zweck: Wird diese Routine auf dem Steuerkanal (A=32) aufgerufen, + wird die angegebene Baudrate für den durch Register DE + adressierten Kanal eingestellt, falls das möglich ist. + Wird diese Routine auf einem anderen Kanal als 32 aufge + rufen, informiert sie den Aufrufer lediglich, ob eine derartige + Einstellung des adressierten Kanals möglich wäre. + + Schlüssel: 1 50 Baud + 2 75 Baud + 3 110 Baud + 4 134.5 Baud + 5 150 Baud + 6 300 Baud + 7 600 Baud + 8 1200 Baud + 9 1800 Baud + 10 2400 Baud + 11 3600 Baud + 12 4800 Baud + 13 7200 Baud + 14 9600 Baud + 15 19200 Baud + 16 38400 Baud + + Anmerkung: In der Regel werden nicht alle Baudraten vom SHard un + terstützt werden. Bei V.24 Schnittstellen sollten aber min + destens 2400, 4800 und 9600 Baud zur Verfügung stehen, + besser auch 300, 600, 1200 und 19200 Baud. + + Hinweis: Falls SHard-spezifisch weitere Baudraten implementiert + werden sollen, darf SHard hierfür negative Schlüsselwerte + (Register HL) vergeben. + + + #d("IOCONTROL ""bits""")# + + Eingang: A eigener Kanal (1...15 / 32) + BC 9 + DE adressierter Kanal + HL Schlüssel + Ausgang: BC Rückmeldung (0 = ok, 1 = nicht möglich) + + Zweck: Wird diese Routine auf dem Steuerkanal (A=32) aufgerufen, + wird die angegebene Zeichenlänge (Bits pro Zeichen) und + Parität für den durch Register DE adressierten Kanal einge + stellt, falls das möglich ist. + Wird diese Routine auf einem anderen Kanal als 32 aufge + rufen, informiert sie den Aufrufer lediglich, ob eine derartige + Einstellung des adressierten Kanals möglich wäre. + + + Schlüssel: stop * 32 + par * 8 + (bit - 1) + + stop: 0 1 Stopbit + 1 1.5 Stopbits + 2 2 Stopbits + + par: 0 keine Parität + 1 ungerade Parität + 2 gerade Parität + + bit: 1...8 Bits pro Zeichen + + + Anmerkung: In der Regel werden nicht alle Kombinationen vom SHard + unterstützt werden. Bei V.24 Schnittstellen sollten aber + möglichst 1 Stopbit, 7 und 8 Bits pro Zeichen und alle drei + Paritätseinstellungen zur Verfügung stehen. + + Hinweis: Falls SHard-spezifisch weitere Einstellungen implementiert + werden sollen, darf SHard hierfür negative Schlüsselwerte + (Register HL) vergeben. + + + + +#b("Flußkontrolle")# +#goalpage("fluss")# + +Die stromorientierten Kanäle (1...15) werden nicht nur zum Anschluß schneller Geräte (wie +Terminals) verwendet, sondern auch, um langsame Geräte (wie Drucker) anzuschließen, die +die Daten u.U. nicht so schnell übernehmen können, wie sie der Rechner schickt. Dabei ist +auf eine geeignete Flußkontrolle zu achten (nicht schneller senden, als der Andere emp +fangen kann). Dieses Problem stellt sich auch bei einer Rechner-Rechner-Kopplung. Hier +ist in der Regel sogar zweiseitige Flußkontrolle notwendig. + +Als Flußkontrolle ist die #ib#REQUEST TO SEND/CLEAR TO SEND#ie# Logik der V.24-Schnitt +stelle oder das #ib#XON/XOFF#ie#-Protokoll zu verwenden. Das letztere kann auch bei Parallel +schnittstellen eingesetzt werden. + +Zur eingabeseitigen Flußkontrollsteuerung kann SHard die Rückmeldung der 0-Routine +'inputinterrupt' (siehe S.#topage("inp")#) und die IOCONTROL-Funktion "weiter" (siehe S.#topage("weiter")#) verwen +den: + +Unterschreitet die Rückmeldung einen von SHard zu bestimmenden Schwellwert, muß SHard +auf der V.24-Schnittstelle das Signal 'REQUEST TO SEND' wegnehmen bzw. XOFF senden. +Dadurch wird bei den meisten Fremdrechnern ein weiteres Senden unterbrochen, sofern (im +ersten Fall) das Signal 'REQUEST TO SEND' dort mit dem V.24-Eingang 'CLEAR TO +SEND' verbunden ist. Wird von EUMEL-0 "weiter" aufgerufen, so kann auf dem enspre +chenden Kanal wieder empfangen werden (RTS setzen bzw. XON senden). + +Für die ausgabeseitige Flußkontrolle muß rechnerseitig ebenfalls das Signal 'CLEAR TO +SEND' bzw. der Empfang von XOFF/XON berücksichtigt werden. Wenn an der Schnittstelle +das 'CLEAR TO SEND' weggenommen wird, darf SHard keinen weiteren Output auf dieser +Schnittstelle machen, bis 'CLEAR TO SEND' wieder anliegt. Entsprechend muß der Empfang +von XOFF die Ausagbe anhalten und XON sie wieder starten. + +Bemerkung: Die meisten Systeme enthalten die CTS-Funktion schon in ihrer Hardware, + so daß im SHard dafür keine Vorkehrungen getroffen werden müssen. + + +Zur Einstellung der gewünschten Flußkontrolle eines Kanals dient die IOCONTROL-Funk +tion "flow". Ähnlich wie "baud" und "bits" wirkt auch "flow" nur auf Kanal 32 #on("i")#einstellend#off("i")# +und auf allen anderen Kanälen lediglich #on("i")#abfragend#off("i")#. + + + #d("IOCONTROL ""flow""")# + + Eingang: A eigener Kanal (1...15 / 32) + BC 6 + DE adressierter Kanal + HL Modus + Ausgang: BC Rückmeldung (0 = ok, 1 = nicht möglich) + + Zweck: Wird diese Routine auf dem Steuerkanal (A=32) aufgeru + fen, muß sie den gewünschten Flußkontrollmodus für den + adressierten Kanal einstellen. + Dabei sind folgende Modi festgelegt: + + HL= 0 Keine Flußkontrolle + HL= 1 XON/XOFF (in beide Richtungen) + HL= 2 RTS/CTS (in beide Richtungen) + HL= 5 XON/XOFF (nur ausgabeseitig) + HL= 6 RTS/CTS (nur ausgabeseitig) + HL= 9 XON/XOFF (nur eingabesetig) + HL=10 RTS/CTS (nur eingabeseitig) + + Wenn keine Flußkontrolle gewünscht wird (HL=0), muß SHard + "weiter" ignorieren; bei HL=1 oder HL=9 muß bei "stop" + XOFF und bei "weiter", sofern zuletzt XOFF geschickt wurde, + XON geschickt werden; bei HL=2 oder HL=10 muß bei + "stop" das Signal RTS auf low und bei "weiter" wieder auf + high gesetzt werden. Mit "stop" ist hierbei das Unterschreiten + des Schwellwertes bei der Rückmeldung von "inputinterrupt" + gemeint. + Bei HL=1 oder HL=5 müssen empfangene XON/XOFF-Zei + chen, bei HL=2 oder HL=6 das Signal CTS beachtet wer + den. + + Wird diese Routine auf einem anderen Kanal als 32 aufge + rufen, informiert sie den Aufrufer lediglich, ob der geforderte + Flußkontrollmodus auf dem adressierten Kanal einstellbar + wäre. + + Hinweis: Falls SHard-spezifisch weitere Flußkontrollmodi implemen + tiert werden sollen, darf SHard hierfür negative Moduswerte + (Register HL) vergeben. + + "weiter" wird von EUMEL-0 sehr oft aufgerufen. Es ist daher + nicht sinnvoll, jedesmal XON zu senden, da dies die Gegen + stelle damit überfluten würde. SHard muß sich merken, ob der + Kanal im XOFF-Zustand ist und nur dann bei "weiter" ein + XON senden. + +#b("Kalender")# +#goalpage("kalender")# + +Die Datums- und Uhrzeitabfrage ist bei Rechnern mit eingebauter Uhr unnötig. EUMEL holt +sich Datum und Uhrzeit dann von SHard. + + #d("IOCONTROL ""calendar""")# + + Eingang: CX 10 + DX (1=Minute, 2=Stunde, 3=Tag, 4=Monat, 5=Jahr) + gewünscht + Ausgang: CX Rückmeldung + + Zweck: Erfragen von Datum und Uhrzeit. Falls keine Uhr vorhanden + ist, muß bei jedem Aufruf -1 zurückgemeldet werden, bei + eingebauter Uhr jeweils das Gewünschte (Minute: 0..59, + Stunde: 0..23, Tag: 1..7, Monat: 1..12, Jahr: 0..99). Die Rück + meldung muß als BCD-Zahl erfolgen. + + Hinweis: Die Uhr darf zwischen zwei Aufrufen umspringen. Die daraus + resultierende Probleme werden auf höheren Ebenen abgehan + delt. + + + + +#bb("6. SHard-","Interface Version")# +#goalpage("shdver")# + +Die #ib#Versionsnummer#ie# der Interface-Spezifikation, auf der SHard aufbaut, muß als 1-Byte- +Konstante #ib#SHDVER#ie# in der SHard-Leiste stehen. Für das hier beschriebene Interface muß sie +den Wert 8 haben. + +So sind spätere Erweiterungen des SHard-Interfaces möglich, ohne daß alle SHard- +Moduln geändert werden müssen. + + + +#bb("7. ","ID-Konstanten")# +#goalpage("ID")# + +SHard muß direkt hinter SHDVER vier 2-Byte-Konstanten ablegen. Diese können von den +höheren Ebenen durch die ELAN-Prozedur + + INT PROC #ib#id#ie# (INT CONST no) + +abgefragt werden. Dabei werden id(0) bis id(3) von EUMEL-0 geliefert, während SHard in der +Leiste die Werte für id(4) bis id(7) zur Verfügung stellen muß: + + ID4 #ib#Lizenznummer#ie# des SHards *) +#foot# +#f#*) Dieser Wert muß mit der Nummer des Lizenzvertrags zwischen Implementierer und GMD übereinstimmen!#a# +#end# + + ID5 #ib#Installationsnummer#ie# des EUMEL-Anwenders **) +#foot# +#f#**) Diese Nummer vergibt der Lizenznehmer an die von ihm belieferten Anwender.#a# +#end# + + ID6 zur freien Verfügung + + ID7 zur freien Verfügung + + + + +#bb("8. ","Zusätzliche Leistungen")# +#goalpage("shdelan")# + +Will der SHard-Implementierer zusätzliche Leistungen anbieten, die mit den Standardopera +tionen nicht möglich sind, kann er weitere Codes für BLOCKIN, BLOCKOUT und +IOCONTROL zur Verfügung stellen. Um Überdeckungen mit Codes zu vermeiden, die von +EUMEL-0 intern verwendet oder erst später eingeführt werden, darf SHard für zusätzliche +Leistungen nur negative Werte als 'Funktionscode 1' verwenden. + + +Zum Ansprechen der neuen Leistungen stehen die ELAN-Prozeduren #on("i")#'#ib#blockout#ie#', '#ib#blockin#ie#'#off("i")# +und #on("i")#'#ib#control#ie#'#off("i")# zur Verfügung. + +Ferner steht dem SHard ein Parameterkanal (32) zur Verfügung. Funktionen, die (im Multi- +User) nicht jeder Task zur Verfügung stehen dürfen, müssen über diesen Kanal 32 abge +wickelt werden und dürfen nur dort wirken. + + + PROC blockout (ROW 256 INT CONST para, (* --> HL *) + INT CONST funktion1, (* --> BC *) + funktion2, (* --> DE *) + INT VAR antwort) (* <-- BC *) + + PROC blockin (ROW 256 INT VAR para, (* --> HL *) + INT CONST funktion1, (* --> BC *) + funktion2, (* --> DE *) + INT VAR antwort) (* <-- BC *) + + PROC control (INT CONST funktion1, (* --> BC *) + funktion2, (* --> DE *) + funktion3, (* --> HL *) + INT VAR antwort) (* <-- BC *) + +Hinweis: Der SHard darf für 'funktion 1' (BC) zusätzlich zu den hier beschriebenen Stan + dardcodes nur negative Codes vereinbaren. + + +Beispiel: + + Gibt eine Task, die durch 'continue (x)' an Kanal 'x' hängt, den Befehl + + control (-7,1200,13,antwort), + + so wird IOCONTROL mit (A='x', BC=-7, HL=13, DE=1200) aufgerufen. Verläßt + SHard 'control' mit BC = 1, so enthält 'antwort' anschließend eine 1. + + +Hinweis: Um die zusätzlichen Leistungen dem Anwender einfach (und abgesichert) zur + Verfügung zu stellen, sollte man sie in ein ELAN-Paket einbetten und dieses + ebenfalls an die Anwender ausliefern. + + Beispiel: PACKET zusatz DEFINES fanfare, ... : + + PROC fanfare (INT CONST tonhoehe, dauer) : + + IF dauer < 0 + THEN errorstop ("negative dauer") + ELIF tonhoehe < 16 + THEN errorstop ("infraschall") + ELIF tonhoehe > 20000 + THEN errorstop ("ultraschall") + ELSE control (-37, 20000 DIV tonhoehe, dauer) + FI + + ENDPROC fanfare ; + + . . . + + + + +#bb("9. ","Spezialroutinen")# +#goalpage("ke")# + +Als Testhilfe und zur Fehlerdiagnose kann SHard in seine Routinen Kontrollereignisse einbau +en. Das geschieht durch Aufruf der 0-Routine 'info'. Dieser EUMEL-Debugger wird im +Anhang A (siehe S.#topage("info")#) beschreiben. + + #dx("info")# (0-Routine) + + Aufruf: call info + jr weiter + defm ' text' + weiter: + + Zweck: Info wird aufgerufen. Dabei wird 'text' zur Identifikation des + Kontrollereignisses ausgegeben. #on("i")#Der übergebene Text muß + mit einem Blank beginnen!#off("i")# + + Hinweis: Bei Systemen "ohne Info" (nur solche dürfen an Anwender + ausgeliefert werden) wird nur der Info-Text ausgegeben und + EUMEL-0 angehalten. + + Achtung: Da der Info selbst die hier beschriebenen Stream-IO-Rou + tinen benutzt, darf man ihn von diesen Routinen aus (input + interrupt, OUTPUT, IOCONTROL "frout", IOCONTROL + "weiter") nicht aufrufen. Wenn die Ein-/Ausgabe auf Termi + nal 1 interruptgetrieben läuft, dürfen die Interrupts beim + Info-Aufruf natürlich nicht gesperrt sein. + + +Falls SHard für bestimmte Aktionen, die selten durchgeführt werden (z.B. Formatieren), viel +Speicher benötigt, kann er diesen dynamisch anfordern und später wieder freigeben. + + #dx("grab")# (0-Routine) + + Eingang: HL Anfangsadresse des zu reservierenden Bereichs im + Datensegment von EUMEL-0, muß auf 512 Byte + ausgerichtet sein. + BC Länge des zu reservierenden Bereichs in 512-Byte- + Kacheln + Ausgang: BC Rückmeldecode + + Zweck: Wenn möglich wird der zu verlangte Bereich von EUMEL-0 + "leergekämpft" und SHard zur Verfügung gestellt. + Rückmeldecode: 0 ok, Speicher steht zur Verfügung + 1 augenblicklich nicht möglich + 3 grundsätzlich nicht möglich + + Achtung: Der Aufruf von 'grab' wird in der Regel 'warte' und Block-IO + auf Kanal 0 induzieren. + + Hinweis: Es wird empfohlen, Speicher ab A000h anzufordern, da diese + Adresse stets im frei einplanbaren Paging-Bereich liegt. + + + #dx("free")# (0-Routine) + + Eingang: HL Anfangsadresse des freizugebenden Bereichs im + Datensegment von EUMEL-0, muß auf 512 Byte + ausgerichtet sein. + BC Länge des zu freizugebenden Bereichs in 512-Byte- + Kacheln + + Zweck: Der entsprechende Bereich muß vorher mit 'grab' beschafft + worden sein. Hiermit wird er wieder EUMEL-0 zur freien + Verfügung gestellt. + + +Für spezielle Fehlersituationen steht die 0-Routine 'shutup' zur Verfügung. Damit kann +SHard z.B. bei Netzausfall ein kontrolliertes Systemende erzwingen. Das ist allerdings nur +sinnvoll, wenn durch Batteriepufferung oder Ähnliches sichergestellt ist, daß noch genügend +Zeit bleibt, um alle Seiten auf den Hintergrund zurückzuschreiben. + + #dx("shutup")# (0-Routine) + + Zweck: Erzwingt Rückschreiben aller Seiten und Systemende, d.h. + entspricht der ELAN-Prozedur 'shutup'. + + Achtung: Der Aufruf von 'shutup' wird in der Regel 'warte' und Block- + IO auf Kanal 0 induzieren. +#page# +#cc("Teil 4: ","Tips zur Portierung")# +#goalpage("tips")# + + +#b("0-Version des SHards")# +#goalpage("0ver")# + + +Es wird empfohlen, zuerst eine "0-Version" des SHard zu entwickeln, die möglichst einfach +aufgebaut und nicht auf Effizienz und vollständige Ausnutzung der Betriebsmittel ausge +richtet sein sollte. Damit kann man rasch praktische Erfahrung gewinnen, die dann den +Entwurf und die Implementation des eigentlichen SHard erleichtert. Die 0-Version sollte + + - keinen Schattenspeicher kennen (SCHINF meldet 0), + + - nur die Kanäle 0 (Hintergrund), 1 (Terminal) und 31 (Archiv) behandeln, + + - keine Baudraten-, Zeichenlängen-, Paritäts- und Flußkontrolleinstellungen unter + stützen (immer 'nicht möglich' melden), + + - vorhandene (ROM-) Routinen möglichst nutzen, ohne sich um Unschönes wie + "busy wait" beim Floppy- bzw. Plattenzugriff zu grämen. + +Mit dieser 0-Version sollte man dann versuchen, EUMEL zu starten. Da der Hintergrund +beim ersten Mal noch leer ist, muß man das HG-Archiv (Archivfloppy mit EUMEL-0 und +höheren Ebenen) in das Archivlaufwerk einlegen und von dort laden. Der Vortest sollte sich +direkt nach dem Start folgendermaßen auf Terminal 1 melden: + + E U M E L - Vortest + + Terminals: 1, + RAM-Groesse (gesamt): 64 kB + Pufferbereich: ? kB + Hintergrund-Speicher: ? kB + + Speichertest: ************ + +Man sollte während der ****-Ausgabe des Speichertests irgendein Zeichen eingeben. Das +EUMEL-System muß dann in das ausführliche Start-Menü überwechseln. (Andernfalls +funktioniert die Eingabe nicht richtig!) + +Als nächstes sollte man versuchen, den Hintergrund vom Archiv aus zu laden. (Diese Mög +lichkeit wird im Start-Menü angeboten.) Nach dem Ende dieser Operation wird der +EUMEL-Lauf automatisch beendet. Jetzt kann man das HG-Archiv aus dem Archivlauf +werk entfernen und das System neu starten. Dann sollte EUMEL-0 vom Hintergrund geladen +werden. + +Bei Problemen kann der "Info" (siehe S.#topage("info")#) hilfreich sein. Voraussetzung für seine Ver +wendung ist aber, daß die Terminal Ein-/Ausgabe schon funktioniert. + +Beim Start des EUMEL-Systems kann (wie im Systemhandbuch beschrieben) durch den +Konfigurationsdialog der Terminaltyp von Kanal 1 eingestellt werden. Falls das verwendete +Terminal in dieser Liste nicht aufgeführt wird und auch keinem der aufgeführten (in Bezug auf +die Steuercodes) gleicht, kann man z.B. + + - den neuen Terminaltyp an einem anderen EUMEL-Rechner verfügbar machen + (Umsetztabellen definieren) und per Archiv zum neuen Rechner tragen, + + - die notwendigen Umcodierungen per SHard durchführen. + +Diese Problematik entsteht bei Rechnern mit integriertem Terminal in der Regel nicht, weil +Steuerzeichen dort sowieso algorithmisch interpretiert werden müssen. In diesem Fall wird +man direkt die EUMEL-Codes als Grundlage wählen, so daß keine Umsetzungen erfor +derlich sind. + +Bei einer provisorischen Anpassung kann man auf Invers-Video ohne weiteres verzichten. + + +Im Gegensatz zu der 0-Version sollte man bei der eigentlichen SHard-Implementierung +darauf achten, die Möglichkeiten der Hardware effizient zu nutzen. Der Testverlauf entspricht +dann wieder im wesentlichen dem oben beschriebenen Vorgang. + + + +#b("Typische Fehler")# +#goalpage("fehler")# + + + a) SHard-Routinen zerstören Registerinhalte bzw. sichern sie beim Interrupt nicht + vollständig. Hierbei sollte man auch an den zweiten Registersatz des Z80-Pro + zessors und an die Register IX und IY denken. + + b) 'call' bzw. 'ret' verändern den Stackpointer. + + c) Fehler bei der Interruptbehandlung führen zu Blockaden ("hängende Interrupts"). + + d) Cursorpositionierung außerhalb des Bildschirms bei einem internen Terminal + (Bildwiederholspeicher im Rechner) wird nicht abgefangen. Das führt dann zu + wildem Schreiben in den Hauptspeicher. + + e) 'warte' wird unerlaubt aufgerufen. ('warte' darf nur von BLOCKIN, BLOCKOUT, + IOCONTROL "size" und IOCONTROL "format" aus aufgerufen werden. Ferner + kann man 'warte' noch nicht beim Systemladen aufrufen!) + + f) OUTPUT-Verhaspler oder -Blockaden entstehen durch Fehlsynchronisation + zwischen dem Füllen des Ausgabepuffers durch die Routine OUTPUT und der + Interruptroutine, die den Puffer leert und ausgibt. + + g) IOCONTROL "frout" meldet in gewissen Situationen nie "mindestens 50 Zei + chen im Puffer frei" und "Puffer leer". Das kann schon im Vortest zu Output- + Blockaden führen. + + h) Obwohl "frout" einen Wert größer als x meldet, nimmt "output" nicht alle x + Zeichen an. + + i) IOCONTROL "size" meldet falsche Werte. + + j) IOCONTROL verkraftet keine beliebigen (auch unsinnige) Werte. + + k) BLOCKIN bzw. BLOCKOUT geben die Kontrolle an das System zurück, bevor alle + Daten übertragen sind. (Sofort nach der Rückgabe geht EUMEL-0 davon aus, + daß der Puffer frei ist und anderweitig benutzt werden kann!) + + l) Einem SIO-Baustein wird nach Ausgabe des letzten Zeichens oder nach Ände + rung des externen Status nicht mitgeteilt, daß keine Interrupts mehr erzeugt + werden sollen. (SIOs wiederholen Interrupts so lange, bis man es ihnen explizit + verbietet!) + + m) Die Stepping-Rate eines Festplattencontrollers wird falsch eingestellt, bezie + hungsweise die Platte wird nicht im 'buffered step mode' betrieben, obwohl sie + beschleunigend positionieren kann. Dadurch werden die Zugriffszeiten auf dem + Hintergrund unnötig verlangsamt. Man bedenke, daß man so einen Fehler leicht + übersieht, weil sich das System nicht fehlerhaft, sondern nur langsamer verhält. + Außerdem macht sich die Verlangsamung erst bemerkbar, wenn größere Teile des + Hintergrundes benutzt werden. + + n) Bei schnellem Zeichenempfang treten "Dreher" auf. Das deutet meistens auf + einen rekursiven Aufruf der 0-Routine 'inputinterrupt' hin. Dabei überholt dann + das zweite Zeichen das erste. + + o) Bei schnellem Zeichenempfang, speziell bei gleichzeitiger Ausgabe, gehen Einga + bezeichen verloren oder werden verfälscht. In der Regel ist das auf Timingpro + bleme bei der Interruptbehandlung zurückzuführen. Interrupts gehen verloren bzw. + die Zeichen werden nicht schnell genug abgeholt. + + +#b("Effizienzprobleme")# +#goalpage("eff")# + + a) Bei #on("i")##on("b")#V.24- und Parallelschnittstellen#off("i")##off("b")# ist schlechter Durchsatz in der Regel auf + Fehlverhalten von "frout" zurückzuführen. Auch kostet es in Multi-User-Sy + stemen sehr viel, wenn OUTPUT immer nur ein Zeichen übernimmt. (Dann läuft + der ganze Apparat der EUMEL-0-Maschine für jedes Zeichen wieder an.) + + Besonders bei der Parallelschnittstelle achte man darauf, daß nicht durch un + glückliches Timing häufig Blockaden auftreten. So kann zu kurzes 'busy wait' auf + Freiwerden der Parallelschnittstelle dazu führen, daß jedes zweite Zeichen + abgelehnt wird, so daß OUTPUT faktisch zeichenweise arbeitet. Andererseits darf + natürlich 'busy wait' auch nicht auf Millisekunden ausgedehnt werden. + + + b) Wenn #on("i")##on("b")#Floppies ohne DMA#off("i")##off("b")# angeschlossen werden, kann man bei Single- + User-Systemen ohne weiteres 'busy wait' einsetzen, um nach dem Seek- + Vorgang auf den Block zu warten. Im Multi-User sollte das aber wenn irgend + möglich umgangen werden, da eine halbe Umdrehung immerhin ca. 100 ms + kostet. + Falls nur ein Endeinterrupt nach jeder Floppyoperation zur Verfügung steht, kann + folgendes Verfahren günstig sein: + + seek befehl an controller ; + warten auf endeinterrupt ; + lesebefehl ohne datentransport auf sektor davor ; + warten auf endeinterrupt ; + lese oder schreib befehl auf adressierten sektor ; + cpu intensives warten und datentransport . + + Die Dummyoperation auf den Sektor vor dem adressierten dient dabei nur dazu, + ohne CPU-Belastung einen Zeitpunkt zu finden, wo man dem eigentlichen Sektor + möglichst nahe ist. Die Zeit, in der die CPU benötigt wird, sinkt damit auf ca. 25 + ms. Die Implementation dieses Algorithmus' ist aber nicht ganz einfach, da die + 0-Routine 'warte' wegen der verlangten kurzen Reaktionszeiten nicht verwendet + werden kann. Alle 'warte auf ...' müssen also durch Interrupts realisiert werden: + + setze interrupt auf lesen davor ; + stosse seek an ; + REP + warte + UNTIL komplette operation beendet ENDREP . + + lesen davor : + setze interrupt auf eigentliche operation ; + stosse lesen davor an . + + eigentliche operation : + ignoriere fehler beim datentransport ; + stosse lesen oder schreiben an ; + REP + REP UNTIL bereit ENDREP ; + uebertrage ein byte + UNTIL alles uebertragen ENDREP ; + melde komplette operation beendet . + + + c) Bei der Ansteuerung von #on("i")##on("b")#Harddisks#off("b")##off("i")# sollte man darauf achten, daß die 0-Rou + tine 'warte' nicht öfter als notwendig aufgerufen wird. Sonst wird das Paging zu + gunsten der CPU-intensiven Prozesse zu stark verlangsamt. Z.B. kann man bei + vielen Plattencontrollern auf eine eigene Seek-Phase verzichten: + + beginne seek ; beginne seek und lesen ; + REP REP + warte warte + UNTIL fertig PER ; UNTIL fertig PER + beginne lesen ; + REP + warte + UNTIL fertig PER + + Hier braucht die linke Fassung immer mindestens ein 'warte' mehr als die rechte. + Bei starker CPU Belastung wird sie deshalb bis zu 100 ms länger für das Einle + sen eines Blocks benötigen. + + Eine ähnliche Situation kann auftreten, wenn die Platte in 256-Byte-Sektoren + unterteilt ist, so daß zu jedem EUMEL-Block zwei Sektoren gehören. Wenn + möglich sollte dann zwischen diesen beiden Sektoren kein 'warte' aufgerufen + werden. Andererseits darf natürlich auch nicht längere Zeit CPU-intensiv gewar + tet werden. Evtl. lohnt es sich in solchem Fall, mit der Sektorverschränkung zu + experimentieren. + +#page# +#cc("Anhang A: EUMEL-","Debugger ""Info""")# +#goalpage("info")# + + +Für interne Testzwecke gibt es den "Info". Systeme "mit Info" und "ohne Info" unterschei +den sich nur im EUMEL-0-Teil (Urlader). Der SHard-Implementierer erhält zum Test +Hintergründe "mit Info" und zur Auslieferung solche "ohne Info". Infofähige Systeme dürfen +nur von den SHard-Implementierern verwendet werden. + + #on("i")##on("b")#Achtung: Infofähige Systeme dürfen auf keinen Fall an Anwender ausgeliefert wer + den, da vermittels Info alle Systemsicherungs- und Datenschutzmaßnah + men unterlaufen werden können.#off("i")##off("b")# *) +#foot# +#f#*) Ausnahmen von dieser Regel bedürfen der expliziten Zustimmung der EUMEL-Systemgruppe (GMD bzw. HRZ +Bielefeld) und des jeweiligen Anwenders. Solche System müssen immer durch spezielle Schlüsselworte abgesichert werden.#a# +#end# + + +#b("Aufruf des Info")# +#goalpage("aufrinf")# + +Zum Aufruf des Infos gibt es drei Möglichkeiten: + + a) Beim Start des EUMEL-Systems geht man durch Eingabe eines beliebigen Zei + chens während des Vortests in den ausführlichen Start-Dialog. Durch Eingabe von + 'I' gelangt man dann in den Info-Modus. #on("i")#(Diese Möglichkeit wird in dem Start + menü nicht aufgeführt.)#off("i")# + + b) Man kann den Info durch die ELAN-Prozedur 'ke' aufrufen. D.h. wenn das System + gestartet wurde und sich eine Task am Terminal mit "gib kommando" gemeldet + hat, kann man durch 'ke *return*' in den Info-Modus gelangen. + + c) Wenn sich am Terminal keine Task befindet, die auf Eingabe wartet, gelangt man + durch die Tastenfolge 'i *info*' (*info* meist = CTL d, zur Tastendefinition siehe + "Systemhandbuch, Konfigurierung") in den Info-Modus. + +Alle diese Möglichkeiten funktionieren nur bei infofähigen Systemen. + +Bei schweren Systemfehlern, die eine Weitermeldung an die höheren Ebenen des EUMEL- +Systems unmöglich machen, wird soweit möglich ebenfalls der Info aufgerufen. Bei Systemen +"ohne Info" wird lediglich eine Meldung auf Kanal 1 ausgegeben und das System angehalten. + +Bevor das System Infokommandos annimmt, muß mit dem Kommando 'P' ein Paßwort einge +geben werden. Lediglich dieses Kommando und das Kommando 'g' werden immer angenom +men. Das Paßwort kann mit dem Kommando 'yP' oder mit der ELAN-Prozedur "info +password" eingestellt werden. + +#b("Info-Format")# +#goalpage("forminf")# + +Der Info ist bildschirmorientiert. Beim Aufruf des Infos und nach den meisten Info-Kom +mandos werden die drei obersten Zeilen wie folgt aufgebaut: *) +#foot# +#f#*) Bildschirmgetreues Verhalten kann der Info allerdings erst nach der Konfigurierung des Kanals zeigen. Vorher (d.h. +insbesondere beim Aufruf aus dem Vortest heraus) werden Cursorpositionierungen in der Regel nicht korrekt durchgeführt.#a# + +#end# + +#limit(14.0)# +XY TEXT +F A C B E D L H F A C B E D L H IX SP IY PC +xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx +#limit(12.0)# + +wobei + + X den Miniprozeß bezeichnet, der den Übergang in den Info veranlaßt hat (A=Archiv, + E=Elan, L=Lader, M=Müllabfuhr), + + Y den Maxiprozeß (Task) bezeichnet, der gerade durch den Elan-Prozessor bear + beitet wird (Y ist code (tasknummer + code ("0"))), + + TEXT den Grund für den Info-Modus anzeigt, + +Die zweite und dritte Zeile zeigen die Inhalte der Z80-Register an (beide Registersätze). +In der untersten Zeile erscheint die Eingabeaufforderung 'info:'. + + +#b("Info-Kommandos")# +#goalpage("cmdinf")# + +Info-Kommandos können in der 'info:'-Zeile mit dem Format + + [<zahl>]<buchstabe> + +gegeben werden oder, wenn der Cursor sich im Dump befindet, mit dem Format + + <buchstabe> + +wobei dann für <zahl> die der Cursorposition entsprechende Dumpadresse (modulo 2**16) +gesetzt wird (siehe '*cup*'). + +<zahl> ist immer in Hexaform einzugeben. + +'g' Der Info-Modus wird wieder verlassen. Dies ist allerdings bei harten Fehlern ge + sperrt. + +'z' Der Leitblock des angezeigten Maxiprozesses wird dargestellt, falls <zahl> = 0 ist, + sonst der Leitblock der Task mit der Nummer <zahl>. (Nur im ELAN-Miniprozeß). + +'q' Die Task mit der Nummer <zahl> wird nach dem nächsten 'g'-Kommando in den + Info überführt. Dies ist nötig, wenn man sich die Datenräume dieser Task anschauen + will ('s'). + +'s' Dumps werden auf den Datenraum <zahl> eingestellt. Ist <zahl>=FF, so wird der + Realspeicher eingestellt. (s:=<zahl>) + +'l' Dumps werden auf die Länge <zahl> eingestellt. Desungeachtet kann man einen + versehentlich zu langen Dump durch eine beliebige Eingabe abbrechen. Dann wird + allerdings '*cup*' gesperrt (siehe unten). + +'p' Dumps werden auf die Byteadresse <zahl> eingestellt (p:=<zahl>; wmodus:= + FALSE). + +'w' Dumps werden auf die Wortadresse <zahl> eingestellt. Die vor jeder Dumpzeile + ausgegebene Adresse ist dann auch eine Wortadresse. Ein Wort = 2 Bytes. (p:=2* + <zahl>; wmodus:=TRUE) + +'k' Block <zahl> laden und per Dump anzeigen. Es erfolgt dabei eine Umstellung auf + den Realdatenraum (s=FF). + +'P' Paßworteingabe: P<text>*return* + Erst nach diesem Kommando sind die übrigen Kommandos ausführbar. + +'x' Suchen nach Bytekette: + +--> xc text +--> xh xx xx ... +--> x + + Es wird nach 'text' bzw. Hexafolge 'xx xx ...' bzw. nach der durch das letzte + 'x'-Kommando eingestellten Bytekette gesucht. + Das Kommando ist durch *return* abzuschließen. + Die Suche beginnt ab Position 'p' und ist auf die Länge <zahl> Seiten (512 Byte- + Einheiten) begrenzt (0=unendlich). + Eine beliebige Eingabe bricht die Suche vorzeitig ab. + +'*return*' + Es wird der eingestellte Dump ausgegeben (siehe 's','l','p','w'). Bei wmodus (siehe + 'p', 'w') werden Wortadressen ausgegeben. + +'o' Wie '*return*', jedoch wird zuvor p := p+l gesetzt (zum Weiterblättern). + +'r' Freigabe der anderen Miniprozesse. + + Zunächst werden bei Übergang in den Info alle Miniprozesse gesperrt, um eine + Verfälschung der Fehlersituation zu vermeiden. Bei manchen Kommandos an den Info + müssen aber andere Miniprozesse u.U. aktiv werden (z.B. beim 'k' der Lader). Wenn + dies erforderlich ist, meldet der Info: + 'paging erforderlich'. Man kann dann 'r' geben und das letzte Infokommando wieder + holen, oder mit anderen Kommandos fortfahren, falls man den Fehlerzustand noch so + beibehalten will. + +'y' Zweitfunktion ausführen. + +--> 'yP<text>*return*' + Neues Paßwort einstellen (max. 9 Zeichen). Dieses bleibt auch nach 'shutup' + gültig. + +--> 'yt' Block <zahl> von Archiv lesen. Dient zum Test des Archivs. + Es wird eine Kachel freigemacht und der Block mit der Nummer <zahl> + eingelesen. Der Inhalt wird sofort angezeigt (wie Kommando 'k'). + +--> 'yb' Breakpoint an die Adresse <zahl> setzen. Es wird ein Aufruf an den Info + abgesetzt. Nur im Realspeicher sinnvoll. Dieser Aufruf meldet sich mit + TEXT= 'test'. Wird er mit 'g' verlassen, so stellt Info zuvor die alten + Z80-Befehle wieder her und führt sie an ihrem originalen Ort aus. + +--> 'yc' wie 'yb', jedoch werden die originalen Z80-Befehle an einem anderen Ort + (im Info) ausgeführt. Sie dürfen daher z.B. keinen Relativsprung enthalten + und keine 'push'/'pop'-Befehle. Dafür bleibt dieser Breakpoint auch nach + dem zugehörigen 'g' im Code erhalten. Dieser Breakpoint meldet sich mit + TEXT='test 2'. 'yc' darf nicht gegeben werden, wenn der Info im 'test 2' + steht (Umhängen verboten). + + #on("i")#Achtung: Die Verwendung von 'yb' und 'yc' ist sehr kritisch durchzuführen. + Zu beachten ist, daß der in den Code eingesetzte Sprung (Z80 jp) + 3 Byte belegt.#off("i")# + + +--> 'yl' Lernmodus ein (wie beim Editor). + +--> 'ye' Ende Lernmodus. + +--> 'ya' Ausführen. Die zwischen 'yl' und 'ye' eingegebenen Zeichen werden dem + Info so vorgesetzt, als kämen sie von der Tastatur. + + Achtung: Rekursion ('ya' im Lernmodus) wird nicht abgefangen. Das Gelern + te wird nach jedem Kommando, das die ersten drei Zeilen + wiederaufbaut (z.B. *return*), in der Zeile vier angezeigt, wobei + für Steuerzeichen eine Ersatzdarstellung erscheint (%x mit + x=code (code (zeichen) +code ("A")), also z.B. %M für + *return*). + +--> 'y *return*' + Wie *return*, jedoch wird der Dump auch beim Ausführen (ya) ausgege + ben. (Ein gelerntes *return* führt im Ausführmodus nicht zum Dump). + +'*cup*' *) (Cursor up). Umschaltung in den Modus zum Ändern in Dumps. +#foot# +#f#*) Falls der Kanal noch nicht konfiguriert ist, muß man natürlich eine Taste betätigen, die den EUMEL-Code für Cursor +Up erzeugt. In der Regel ist das CTL c. Falls das Terminal ohne Konfigurierung keine Cursorpositionierungen durchführt, ist +dieser Modus nicht sehr gut benutzbar.#a# +#end# + Der Cursor fährt in den Dump und kann mit den Cursortasten dort bewegt + werden. Wird eine Hexazahl jetzt eingegeben, so wird diese als Inhalt des + Bytes eingetragen, auf dem der Cursor gerade steht. Dies funktioniert auch + auf beliebigen Datenräumen. Info beantragt dann bei der Speicherverwal + tung einen Schreibzugriff für die entsprechende Datenraumseite, so daß + Änderungen mit der Copy-on-Write-Logik erfolgen, also nur taskspezi + fisch sind (durch 'q' eingestellt). Für diese Task sind die Änderungen al + lerdings dann permanent, da sie auch auf den Hintergrund wirken. + + Hinweis: Dumpt man mit 'k' einen Block und ändert dann darin, so sind + diese Änderungen u.U. nur temporär, da der Info kein Rückschrei + ben des Blockes veranlaßt. + + Achtung: Jede Eingabe, die kein Positionierzeichen und kein gültiges + Zahlzeichen ist, beendet diesen Modus. Das neue Zeichen wird als + Info-Kommando aufgefaßt, wobei <zahl> auf die aktuelle Adres + se gesetzt wird. + (Für 'yc' / 'yb' sinnvoll: Man setzt den Cursor auf die Stelle, an + der ein Break ausgelöst werden soll und gibt 'yc'/'yb'). + Somit wird dieser Änderungsmodus üblicherweise durch *return* + beendet. + +#b("Einige Systemadressen")# +#goalpage("sysaddr")# + +Der Info nützt nur wenig, wenn man nicht weiß, was man sich anschauen soll. Wesentliche +Angaben über die Systemstruktur enthält das 'Brikett' (interne Systemdokumentation für +Projekt Mikros der GMD). Da diese etwas allgemeiner gehalten ist, geht sie nicht auf imple +mentationsabhängige Konstanten ein. Diese sind hier aufgeführt. + +Ab 1500h liegt die 'ktab'. Sie enthält Informationen, welche Blöcke an welcher Stelle des +Arbeitsspeicher liegen: In der Kachel mit der Adresse 512*i befindet sich der Inhalt des +Blockes, dessen Nummer in ktab+i, ktab+100h+i steht. Ferner enthält die Tabelle, zu +welchem Datenraum (drid) und welcher Seite des Datenraums der Inhalt gehört. (Nur rele +vant, wenn die Prozeßnummer <> 255 ist). + +Steuerbits: 2**0 : Inhalt wird gerade transportiert (zum HG oder Archiv). + 2**1 : Inhalt ist identisch mit Inhalt auf HG. Wird beim Schreiben auf die + Kachel (per Software) zurückgesetzt. + 2**2 : Schreiberlaubnis (siehe Brikett). + 2**3 : Inhalt wurde kürzlich benutzt. Solche Kacheln werden 'weniger + stark' verdrängt. + + + ktab frei niederwertige Blocknummer + + +80h frei frei Steuerbits + + +100h frei höherwertige Blocknummer + + +180h frei frei Prozeßnummer + + +200h frei frei drid (prozeßspezifisch) + + +280h frei frei Seitennummer (höherw.) + + +300h frei frei Seitennummer (niederw.) + + ^ ^ + <-- unbenutzt --> ! +-- Beginn echter Kacheln + +-- Beginn der Anforderungen + + +Der 'Beginn echter Kacheln' hängt von der Größe der Z80-Teile ('urlader') ab (i.A. +30h < i < 40h). + +'Beginn der Anforderungen' liegt bei i=1Fh. Es handelt sich um Blocknummern von zu +ladenden Blöcken. Ist der höherwertige Teil der Blocknummer gleich FDh, so ist dies keine +Anforderung. + +Blocknummern > FF00h stehen für Blöcke mit dem Inhalt 512 FFh's und werden nie auf dem +Hintergrundmedium gespeichert. + + + +1E2Bh enthält den DR-Eintrag des drdr (siehe Brikett). + + +'musta': Das System fordert Checkpoints und Müllabfuhren über die Zelle 'musta' an. Diese + findet man mit dem Info durch + + xc musta + + (hierfür ist der Text 'musta' vor der Zelle abgesetzt). + + Die Zelle selbst enthält + + FFh : Keine Müllabfuhr oder Checkpoint + 01h : Müllabfuhr + 02h : Checkpoint + 03h : beides + 04h : Systemendecheckpoint + 0Bh : System auf Archiv schreiben ('save system') + F0h : Müllabfuhr und Checkpoint sind geperrt (nur durch Setzen im Info + möglich) + + Durch Einsetzen der Werte mit dem Info kann die entsprechende Operation veran + laßt werden. Beim Einsetzen darf der Info nicht im 'r'-Zustand (siehe Eingabe 'r') + stehen; zum Ausführen der Operation muß 'r' (man bleibt im Info) oder 'g' (Info + verlassen) gegeben werden. + + +1880h-18FFh: + enthält die Aktivierungstabelle. Ist (1880h+i)=01h, so ist die Task i aktiv. Hin + weis: 18FFh enthält immer 01h, ohne daß dieser Zelle eine Task zugeordnet ist. + + +#b("Leitblock")# +#goalpage("pcb")# + +Mit dem 'z'-Kommando wird der Leitblock einer Task dargestellt. Es werden Hexapaare, +gefolgt von einer Bezeichnung, ausgegeben. In der folgenden Beschreibung werden die +Hexapaare durch a,b,c dargestellt. + + a b c icount Der virtuelle Befehlszähler der Task steht auf (cMOD4)* + 10000h+b*100h+a = <ic> im Datenraum 4 dieser Task. + Durch die Eingabefolge: + 4s<ic>w*return* + kann man sich den Code, der ausgeführt werden soll, anse + hen. + + Bit 2**7 von c zeigt den Fehlerzustand an. + Bit 2**6 von c zeigt 'disable stop' (siehe Benutzerhandbuch) + an. + Bit 2**4 zeigt vorzeichenlose Arithmetik an (Compilierung). + + a b lbas Die lokale Basis steht auf 10000h+b*100h+c = <lb> im + Datenraum 4 (Wortadresse). + + a b hptop Der Arbeitsheap geht von 30000h (Byteadr.) bis (aMOD16)* + 10000h+b*100h+(aDIV16)*10h (Byteadr!). + + a b channel Die Task hängt an Kanal 100h*b+a (Terminalnummer). 0 = + kein Terminal angekoppelt. + + a b taskid Die Tasknummer der betrachteten Task ist a. (b ist die + Versionsnummer zum Abdichten von 'send'/ 'wait'). + +Um den Code, auf den der 'icount' zeigt, zu interpretieren, ziehe man das Brikett zu Rate. + + +Hinweis: Wenn der Info einen internen Fehler anzeigt, und auch bei 'ke', ist der durch 'z' + angezeigte Leitblock u.U. nicht aktualisiert. Man kann dies durch die Eingaben 'r', + 'g' erzwingen. (Der Info stellt wegen 'r' dem Interpreter einen Restart zu, der dann + beim 'g' den Leitblock aktualisiert und den Befehl erneut aufsetzt). Tritt dabei der + Fehler nicht wieder auf, handelte es sich um einen transienten Fehler (z.B. der + Codeblock war noch im Einlesen und ist jetzt voll da). So etwas kann z.B. passie + ren, wenn der SHard den Abschluß einer Leseoperation zu früh meldet. + diff --git a/doc/porting-z80/8/source-disk b/doc/porting-z80/8/source-disk new file mode 100644 index 0000000..ff072f3 --- /dev/null +++ b/doc/porting-z80/8/source-disk @@ -0,0 +1 @@ +porting/portdoc-z80-8.img diff --git a/doc/programmer-manual/1.8.7/doc/programmierhandbuch.1 b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.1 new file mode 100644 index 0000000..24f2b03 --- /dev/null +++ b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.1 @@ -0,0 +1,650 @@ +#headandbottom("1","EUMEL-Benutzerhandbuch","TEIL 1 : Einleitung","1")# +#pagenr("%",1)##setcount(1)##block##pageblock# +#headeven# +#center#EUMEL-Benutzerhandbuch +#center#____________________________________________________________ + +#end# +#headodd# +#center#TEIL 1 : Einleitung +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +1 - % #right#GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #rigth#1 - % +#end# + +TEIL 1 : Einleitung + + +1.1 Allgemeines über EUMEL + +Dieses Buch bietet eine Übersicht über die Standardprozeduren des Betriebssystem +EUMEL. Es bietet damit sowohl Hilfestellung für die Benutzung der standardmäßig +vorhandenen Kommandos als auch für die Programmierung, also die Erweiterung +dieses Kommandovorrats. Es ist jedoch kein Lehrbuch der Programmierung! + +In den ersten drei Kapiteln dieses Programmierhandbuches werden einige Grund +begriffe des Systems, die grundlegende Programmiersprache (ELAN) und der +EUMEL-Editor erläutert. + +Das vierte Kapitel bietet eine Übersicht über diejenigen Prozeduren und Operatoren, +die eher der 'Job-Control-Language' zugerechnet werden können, also häufig im +Kommandodialog benutzt werden. + +Im fünften Teil sind diejenigen Operationen beschrieben, die meistenteils für die +Programmierung benutzt werden. (Compiler, Operationen auf den elementaren Daten +typen, Dateien, Ein- und Ausgabe usw.). + +Diese Trennung ist jedoch recht willkürlich, es ist ja gerade eine der wichtigen Eigen +schaften dieses Betriebssystems, daß es keine Trennung zwischen der Kommando +sprache des Betriebssystems und Programmmiersprache für das System gibt. Jedes +Systemkommando ist Aufruf einer ELAN Prozedur, jede neue Prozedur stellt eine +Erweiterung des Kommandovorrats des Systems dar. + +Aus Gründen der Übersichtlichkeit der Zusammenstellung ist dieses Buch nicht frei +von Vorwärtsverweisen! + +#page# + +1.2 Struktur des Betriebssystems EUMEL + +Grundlegend für das Verständnis des Betriebssystems EUMEL ist der Begriff der +#on("b")#Task#off("b")#. Eine Task kann als theoretisch unendliche Wiederholung eines Systempro +gramms der Form: + + 'nimm Kommando entgegen' + 'verarbeite Kommando' + +aufgefaßt werden. Einige Tasks existieren bereits als Grundstock des Systems, +weitere werden von Benutzern des Systems erschaffen und dienen als persönliche +Arbeitsumgebung für den 'Eigentümer'. Eine Task kann als benutzereigener, unab +hängiger Computer im Computer betrachtet werden, denn sie kann Kommandos +entgegennehmen und ausführen und Daten verwalten und aufbewahren. + +Eine Task kann neu erzeugt werden, an einen Bildschirm gekoppelt werden und +beendet werden. + +Das Tasksystem ist in einer baumartigen Struktur angeordnet. Außer der Wurzel 'UR' +hat jede Task einen Vorgänger ('Vater-Task') und möglicherweise Nachfolger +('Sohn-Tasks'). + +#on("u")##ib#Task-Organisation#ie##off("u")# + + + SUPERVISOR + - + SYSUR + ARCHIVE + configurator + OPERATOR + shutup + + UR + PUBLIC + Benutzertask1 + Benutzertask2 + Benutzertask3 + ..... + + + +Jeder Benutzer arbeitet innerhalb eines EUMEL-Systems, indem er eine Task an +sein Terminal koppelt und dort Programme aufruft. + +Dateien sind grundsätzlich Eigentum einer Task. Es ist grundlegend für das Verständ +nis des Betriebssystems EUMEL, die Beziehung zwischen Tasks und Dateien zu +erkennen. + +Eine Task ist ein Prozeß, der gegebenenfalls Dateien besitzt. Dateien können nur in +einer Task existieren. Um eine Datei einer anderen Task zur Verfügung zu stellen, +wird eine Kopie der Datei an die andere Task geschickt, die sendende Task ist da +nach Eigentümer des 'Originals', die empfangende Task Eigentümer der 'Kopie'. + +Soll eine Hierarchie von Dateien aufgebaut werden, so ist sie über eine Hierarchie +von Tasks zu realisieren, da in einer Task alle Dateien gleichberechtigt sind. + +Bis zu dieser Stelle war stets von Dateien die Rede. Dateien sind jedoch ein Spezial +fall der grundlegenderen Struktur des Datenraumes. + +Ein #ib#Datenraum#ie# ist ein allgemeiner Datenbehälter. Ein Datenraum kann beliebige +Daten aufnehmen und erlaubt direkten Zugriff auf diese Daten. Die Struktur der Daten +im Datenraum unterscheidet sich nicht von der Struktur der Programmdaten. Der +'innere Datentyp' eines Datenraums wird vom Programmierer festgelegt. + +Vorgeprägt vom System gibt es Textdateien, jeder andere Datentyp muß vom Pro +grammierer geprägt werden, um so Dateien erzeugen zu können, die Objekte eben +dieses neuen Typs enthalten. +#page# + + +1.3 Eigenschaften des Betriebssystems + +Der erste Entwurf des Mikroprozessor-Betriebssystems EUMEL (#on("b")#E#off("b")#xtendable multi +#on("b")#U#off("b")#ser #on("b")#M#off("b")#icroprozessor #on("b")#EL#off("b")#AN system) entstand 1979 mit dem Anspruch, auf Mikrocom +putern den Anwendern Hilfsmittel und Unterstützungen zu bieten, wie sie sonst nur +auf Großrechnern zur Verfügung gestellt werden. + +Aspekte, die EUMEL von anderen Betriebssystemen für Mikrocomputer unterscheiden, +sind: + +- Hardwareunabhängigkeit +- Multitaskingkonzept +- Multiuserbetrieb +- Erweiterbarkeit +- virtuelle Speicherverwaltung +- Datensicherheit + + + +#on("u")##on("b")#Das EUMEL-Schichtenmodell#off("b")##off("u")# + +Die Hardwareunabhängigkeit des Betriebssystems EUMEL begründet sich in seinem +Aufbau aus Schichten (sogenannten virtuellen Maschinen), die einen klar definierten +Leistungsumfang haben. + +#center#beliebige Anwendungen +#center#Textverarbeitung, Datenbanken etc. + +#center#Systemdienste: Monitor, Dateiverwaltung, Editor +#center#Task-System +#center#Standardpakete (BOOL, INT, REAL, TEXT) +#center#ELAN-Compiler + +#center#EUMEL0 +#center#(virtueller Prozessor mit eigenem Befehlssatz) + +#center#SHard (Gerätetreiber) + +#center#Hardware + + +Jede Schicht erwartet und erhält von ihren Nachbarn wohldefinierte Eingaben und gibt +wohldefinierte Ausgaben weiter. Änderungen in einer Schicht müssen also in den +angrenzenden Schichten beachtet werden, aber nicht in allen Teilen des Systems. + +Um EUMEL auf Rechner mit einem neuen Prozessortyp zu portieren, wird zunächst +eine auf die Eigenheiten des Prozessors abgestimmte EUMEL0-Maschine entworfen +und eine Hardwareanpassung (#ib#SHard#ie# : Software/Hardware-Interface) für einen +Rechner mit diesem Prozessor hergestellt. Alle höheren Schichten des Systems +bleiben unberührt. Weitere mit diesem Prozessortyp ausgestattete Rechner können mit +EUMEL betrieben werden, indem ein SHard für dieses Rechnermodell geschrieben +wird. + +Aus Benutzersicht ist wichtig, daß dadurch jegliche Software, die auf irgendeinem +Rechner unter EUMEL verfügbar ist, auf jedem anderen Rechner, für den eine +EUMEL Portierung existiert, lauffähig ist und gleiches Verhalten zeigt. Eine Vernet +zung beliebiger Rechner, auf die EUMEL portiert ist, ist problemlos möglich. + +Desweiteren ist für den Benutzer des Systems von Bedeutung, daß er von der hard +warenahen Schicht entfernt ist. Weder die Programmiersprache noch irgendwelche +speziellen Systemfunktionen gewähren direkten Zugriff auf den Speicher oder Regi +sterinhalte. Diese Tatsache hat weitreichende Folgen in Hinsicht auf Datenschutz und +Systemsicherheit. + + + + +Multi-Tasking-/Multi-User-Betrieb +Wie einleitend dargestellt, besteht ein EUMEL-System aus diversen Tasks. Durch +eine Aufteilung der Prozessorzeit in Zeitscheiben ist eine (quasi) parallele Bedienung +mehrerer Tasks möglich. + +Die multi-user-Fähigkeit des Betriebssystems wird durch den Anschluß mehrerer +Bildschirmarbeitsplätze (Terminals) an V.24 Schnittstellen des Rechners erreicht. +Dabei wird jeder Schnittstelle eine sogenannte Kanalnummer zugeordnet. Jeder +Benutzer kann seine Task dann an einen Kanal (=Terminal) koppeln und an diesem +Terminal gleichzeitig mit anderen Benutzern arbeiten. + + + + +Prozeßkommunikation und Netzwerkfähigkeit +Grundlage der Kommunikation ist die 'Manager-Eigenschaft' von Tasks. Eine Task +ist 'Manager', wenn sie Aufträge anderer Tasks annehmen und ausführen kann. +Insbesondere kann ein Manager veranlaßt werden, eine an ihn geschickte Datei anzu +nehmen, bzw. eine ihm gehörende Datei an die fordernde Task zu schicken. + +Derartige Kommunikationslinien verlaufen normalerweise in der Baumstruktur des +Systems: z.B. ist die Task 'PUBLIC' (vergl. Seite 2) grundsätzlich Manager-Task. +Eine unterhalb von PUBLIC liegende Task kann eine Datei an PUBLIC senden, bzw. +von PUBLIC holen. + +Es ist auch möglich, eine Task für den Zugriff beliebiger anderer Tasks zu öffnen und +somit beliebige Kommunikationspfade aufzubauen. Prinzipiell ist damit auch schon der +Aufbau eines Netzwerkes beschrieben, denn sendende und empfangende Tasks +können sich auf verschiedenen Rechnern befinden. + +Durch selbst erstellte Programme kann der Eigentümer einer 'Manager-Task' die +Reaktion dieser Task auf einen Auftrag von außen bestimmen. Beispielsweise kann +ein Manager derart programmiert werden, daß er nur Dateien empfängt und ausdruckt, +aber niemals Dateien verschickt (Spool-Task). + + + +Erweiterbarkeit +Die Programmiersprache ELAN ist im EUMEL-System gleichzeitig Programmier- +und System-Kommandosprache (JCL), denn jedes Kommando ist Aufruf einer +ELAN-Prozedur und jede vom Benutzer geschriebene ELAN-Prozedur erweitert +den Kommandovorrat des Systems. + +Da alle EUMEL-Werkzeuge (einschließlich Editor) selbst ELAN-Programme sind, +kann das System vom Benutzer selbst durch Hinzufügen eigener ELAN-Programme +oder Programmpakete beliebig erweitert werden. Dabei können die bereits implemen +tierten Systemteile (z.B. die Fenstertechnik des Editors) genutzt werden. + +Ein Benutzer muß, um alle Möglichkeiten vom EUMEL zu nutzen, nur eine Sprache +lernen und nicht - wie bei anderen Betriebssystemen - zwei unterschiedliche, eine +Kommando- und eine Programmiersprache. + +ELAN selbst ist eine PASCAL-ähnliche Programmiersprache, die mit Hilfe der +schrittweisen Verfeinerung (Refinement-Konzept) die Top-Down-Programmierung +unterstützt. Das Paketkonzept, das der Modularisierung dient, und die freie Wahl von +Bezeichnernamen sind Voraussetzung für übersichtliche und effiziente Programmie +rung. + + + + +Virtuelle Speicherverwaltung +Im EUMEL-System wird der Hauptspeicherplatz nach dem #on("b")#Demand-Paging-Prinzip#off("b")# +verwaltet. Daten und Programme werden dazu in Seiten von 512 Byte aufgeteilt. Nur +diejenigen Seiten, die wirklich benötigt werden, werden vom Hintergrundspeicher +(Platte) in den Hauptspeicher geholt. Damit ist für den Benutzer bezüglich seiner +Programm- bzw. Dateigrößen nicht mehr der Hauptspeicher, sondern die Hinter +grundkapazität von Bedeutung. Die Durchsatzgeschwindigkeit (Performance) ist +abhängig von der Größe des RAM-Speichers und der Zugriffsgeschwindigkeit des +Hintergrundmediums. Das Demand-Paging-Verfahren ist Grundlage für den +Multi-User-Betrieb, wobei der Hauptspeicherplatz möglichst effizient zu nutzen und +kein Benutzer zu benachteiligen ist. + +Beim Duplizieren eines Datenraumes wird im EUMEL-System lediglich eine logische, +keine physische Kopie erzeugt. Zwei Seiten (zweier Datenräume) heißen dann gekop +pelt (geshared), wenn beide Seiten physisch demselben Block zugeordnet sind. Erst +bei einem Schreibzugriff werden die Seiten entkoppelt (entshared) und tatsächlich +physisch kopiert. Daher der Name "#on("b")#copy-on-write#off("b")#". + +Dieses Prinzip wird natürlich auch systemintern angewandt. Beispielsweise erbt eine +Sohn-Task den Kommandovorrat der Vater-Task, indem der Standard-Datenraum, +der die vorübersetzten ELAN-Prozeduren enthält, in der beschriebenen Weise kopiert +wird. Prozeduren, die später hinzugefügt werden, werden natürlich nicht vererbt, da +die Standard-Datenräume dann entkoppelt werden. + + + + +Datensicherheit +Störungen (inklusive Stromausfall) werden systemseitig durch eine automatische +#on("b")#Fixpoint-Rerun-Logik#off("b")# aufgefangen, indem zum Zeitpunkt eines Fixpunkts der Inhalt +des RAM Speichers, der seit dem letzten #ib#Fixpunkt#ie# verändert wurde auf den +permanenten Speicher (Festplatte) geschrieben wird. Somit kann nach einer Störung +immer auf den Systemzustand des letzten Fixpunktes aufgesetzt werden und die +Datenverluste halten sich in erträglichen Grenzen. + +Der Zeitraum zwischen zwei Fixpunkten beträgt standardmäßig 15 Minuten, kann aber +vom Benutzer anders eingestellt werden. + +Auch bei dieser Sicherung wird das Copy-on-write-Prinzip angewendet, so daß +Platz- und Zeitaufwand gering sind und den normalen Ablauf nicht stören. + +#page# + +1.4 Wichtige Begriffe + +- #on("b")##ib#archive#ie##off("b")#. Spezielle Task zur Verwaltung des Diskettenlaufwerks. Da für die + längerfristige Datenhaltung und zur zusätzlichen Datensicherung Dateien auf + Disketten geschrieben werden, besitzt das EUMEL-System für diese Aufgabe + eine besondere Task, die die Bedienung vereinfacht und exklusiven Zugriff auf das + Laufwerk garantiert. + +- #on("b")##ib#configurator#ie##off("b")#. Besondere Task im Systemzweig des EUMEL-Systems. In + dieser Task ist die #ib#Konfiguration#ie# von Kanälen möglich, d.h. Kanal und + angeschlossenenes Gerät werden aufeinander abgestimmt. + +- #on("b")##ib#editor#ie##off("b")#. Programm zur Dateibearbeitung am Bildschirm. Das Programm wird + durch das ( Monitor- ) Kommando 'edit' und die Eingabe des Namens der ge + wünschten Datei als Parameter gestartet. + + Da ein Bildschirm normalerweise auf 80 Zeichen Zeilenbreite und 24 Zeilen be + schränkt ist, kann der Editor als Fenster betrachtet werden, das über die mögli + cherweise weitaus größere Datei bewegt wird und durch das der betrachtete Aus + schnitt der Datei bearbeitet werden kann. + +- #on("b")##ib#manager task#ie##off("b")#. Task, die Aufträge von anderen Tasks entgegennehmen und + ausführen #on("u")#kann#off("u")#. Beispielsweise ist die Verwaltung von Dateien, die mehreren + Benutzern (= anderen Tasks) zugänglich sein sollen, eine typische Aufgabe für + einen Manager. + +- #on("b")##ib#Monitor#ie##off("b")#. Der Empfänger von Kommandos innerhalb einer Task ist der Monitor. Der + Monitor ist sichtbar durch eine Zeile, in der 'gib kommando' steht. In diese Zeile + werden #ib#Kommando#ie#s und erforderliche Parameter eingegeben. + +- #on("b")##ib#Supervisor#ie##off("b")#. Spezielle Task zur Überwachung eines EUMEL-Systems. Ein + Benutzer kann durch die Supervisor-Kommandos Leistungen von dieser Task + fordern: neue Task einrichten, Task wiederaufnehmen und diverse Informationen. + +- #on("b")##ib#Task#ie##off("b")#. Beliebig langlebiger Prozeß im EUMEL-System, der die Arbeits + umgebung für Benutzer bildet. Jede Task besitzt einen #ib#Standard-Datenraum#ie#, der + Code und Compilertabellen der Task enthält und kann weitere Datenräume + (Dateien) besitzen. + +#page# + +1.5 Die Notation in diesem Buch + +Beachten Sie bitte folgende Regeln der Aufschreibung: + +- Funktionstasten werden ebenso wie besondere Tastenkombinationen explizit als + Tasten dargestellt: + + <SV> <ESC> <e> + + +- Alles, was Sie am Bildschirm Ihres Rechners schreiben oder lesen sollen, ist in + Textbereiche, die einen Bildschirm darstellen, eingefaßt. + + Beispiel: + +____________________________________________________________________________ + gib kommando: + edit ("mein programm") + +____________________________________________________________________________ + + +- Innerhalb des Handbuchs sind in der Aufschreibung die Konventionen der Pro + grammiersprache ELAN berücksichtigt. Dabei sind folgende Besonderheiten zu + beachten: + + 1) Kommandos werden grundsätzlich klein geschrieben. + + 2) Dateinamen u.ä. sind Textdenoter und werden somit in Klammern und Anfüh + rungsstriche gesetzt. In diesem Buch steht an den Stellen, wo ein Dateiname + auftaucht #on("i")# 'dateiname' #off("i")#; den Namen, den Sie tatsächlich verwenden, können + Sie frei wählen. + + 3) Falls besondere Begriffe oder Beispiele innerhalb eines normalen Textes + auftreten, werden sie in einfache Anführungsstriche gesetzt. + + +#page# + +1.6 Die Funktionstasten des EUMEL-Systems + +Die Lage der EUMEL-Funktionstasten entnehmen Sie bitte der speziellen Installa +tionsanleitung zu dem von Ihnen benutzten Gerät. #l pos (0.0)##l pos(4.0)# + + +<v> <^> <>> <<> Positionierungstasten +#table# + +<SHIFT> Umschalttaste + +<CR> Eingabe-/ Absatztaste + +<ESC> Kommandotaste + +<SV> Supervisortaste + +<HOP> Verstärkertaste + +<RUBOUT> Löschtaste + +<RUBIN> Einfügetaste + +<TAB> Tabulatortaste + +<MARK> Markiertaste + +<STOP> Stoptaste + +<WEITER> Weitertaste +#tableend##clear pos# + +Weitere Informationen hierzu finden Sie in der Installationsanleitung zu dem von Ihnen +benutzten Rechner oder Terminal. +#page# + +1.7 Eine Beispielsitzung + +Im Folgenden wird eine Beispielsitzung skizziert, in der ein ELAN-Programm erstellt +und getestet wird. + + <SV> SUPERVISOR aufrufen + + + +____________________________________________________________________________ + + Terminal 2 + + + EUMEL Version 1.8/M + + + gib supervisor kommando: + begin("meine erste Task") + + + + ESC ? --> help + ESC b --> begin("") ESC h --> halt + ESC c --> continue("") ESC s --> storage info + ESC q --> break ESC t --> task info + +____________________________________________________________________________ + + + + +Durch das Kommando 'begin ("meine erste Task")', welches durch <CR> abgeschlos +sen werden muß, wird eine Task mit dem Namen 'meine erste Task' im Benutzer +zweig, also unterhalb von 'PUBLIC' angelegt. Würde diese Task bereits existieren, so +könnten Sie sie mit 'continue ("meine erste Task")' an das Terminal holen. + +____________________________________________________________________________ + + gib kommando : + edit ("mein erstes Programm") + +____________________________________________________________________________ + + +In der Task eröffnen Sie eine Datei mit dem Kommando 'edit ("dateiname")'. + + +____________________________________________________________________________ + + gib kommando : + edit ("mein erstes Programm") + "mein erstes Programm" neu einrichten (j/n) ? j + +____________________________________________________________________________ + + +Falls diese Datei neu ist, erfolgt eine Kontrollfrage (zur Kontrolle der gewünschten +Schreibweise des Dateinamens), die Sie durch <j> bejahen. + + +____________________________________________________________________________ + ............ mein erstes Programm ............... Zeile 1 #markon# +_ +____________________________________________________________________________ + + + + + + +In die noch leere Datei tippen Sie nun den Programmtext ein. + + +____________________________________________________________________________ + ............ mein erstes Programm ............... Zeile 1 + _INT PROC ggt (INT CONST a, b): + INT VAR b kopie :: abs (b), a kopie :: abs (a); + WHILE b kopie <> 0 REPEAT + INT VAR rest := a kopie MOD b kopie; + a kopie := b kopie; + b kopie := rest + END REPEAT; + a kopie + END PROC gt; + + REP + lies 2 zahlen ein; + gib groessten gemeinsamen teiler aus + UNTIL no ("weitertesten") PER. + + lies 2 zahlen ein: + line; put ("2 Zahlen eingeben:"); + INT VAR a, b; + get (a); get (b). + + gib groessten gemeinsamen teiler aus: + put ("der größte gemeinsame Teiler von"); + put (a); put ("und"); put (b); put ("ist"); put (ggt (a,b)); + line. + +____________________________________________________________________________ + + +In dem Programmbeispiel wird ein Prozedur 'ggt' definiert, die den größten gemein +samen Teiler zweier Zahlen bestimmt. Die Prozedur soll für verschiedene Beispiele +getestet werden; dies geschieht in dem Hauptprogramm, das solange Zahlen einliest +und den größten gemeinsamen Teiler ausgibt, bis der Benutzer auf die Frage 'weiter +testen (j/n) ?' mit <n> antwortet. + +Haben Sie das Programm eingegeben, so können Sie die Bearbeitung dieser Pro +grammdatei durch Drücken der Tasten <ESC> <q> (nacheinander!) beenden. + + +____________________________________________________________________________ + + gib kommando : + run ("mein erstes Programm") + +____________________________________________________________________________ + + +Um Ihr Programm zu übersetzen und auszuführen, geben Sie das Kommando +'run ("dateiname")'. + +Der Verlauf der Übersetzung, die zwei Läufe über das Programm erfordert, ist am +Zähler, der an der linken Seite des Bildschirms ausgegeben wird, zu erkennen. + +Werden beim Übersetzen des Programms Fehler entdeckt, so werden diese im 'note +book' parallel zur Programmdatei gezeigt. In dem Beispielprogramm wurde ein +Schreibfehler in Zeile 9 gemacht. + + +____________________________________________________________________________ + ............ mein erstes Programm ............... Zeile 1 + _INT PROC ggt (INT CONST a, b): + INT VAR b kopie :: abs (b), a kopie :: abs (a); + WHILE b kopie <> 0 REPEAT + INT VAR rest := a kopie MOD b kopie; + a kopie := b kopie; + b kopie := rest + END REPEAT; + a kopie + END PROC gt; + + REP + .................. notebook ..................... Zeile 1 #markon# + Zeile 9 FEHLER bei >> gt << + ist nicht der PROC Name + + +____________________________________________________________________________ + + + +Diesen Fehler müssen Sie nun verbessern. + +____________________________________________________________________________ + ............ mein erstes Programm ............... Zeile 9 + INT PROC ggt (INT CONST a, b): + INT VAR b kopie :: abs (b), a kopie :: abs (a); + WHILE b kopie <> 0 REPEAT + INT VAR rest := a kopie MOD b kopie; + a kopie := b kopie; + b kopie := rest + END REPEAT; + a kopie + END PROC ggt;_ + + REP + .................. notebook ..................... Zeile 1 + Zeile 9 FEHLER bei >> gt << + ist nicht der PROC Name + +____________________________________________________________________________ + + + + +Haben Sie das Programm korrigiert, so können Sie die Datei durch Drücken der +Tasten <ESC> <q> (nacheinander!) wieder verlassen. + + +____________________________________________________________________________ + + gib kommando : + run ("mein erstes Programm") + +____________________________________________________________________________ + + +Nach Eingabe von <R> wird das Programm erneut übersetzt. + + +____________________________________________________________________________ + + Keine Fehler gefunden, 136 B Code, 82 B Paketdaten generiert + + + ******* ENDE DER UEBERSETZUNG ******* + + + 2 Zahlen eingeben: _ + +____________________________________________________________________________ + + +Das Programm war jetzt fehlerfrei. Nach der Übersetzung wurde die Ausführung +gestartet. Nun können Beispiele getestet werden. + +____________________________________________________________________________ + + 2 Zahlen eingeben: 125 250 + der größte gemeinsame Teiler von 125 und 225 ist 25 + weitertesten (j/n) ? + +____________________________________________________________________________ + + +Beantwortet man die Frage mit <n>, so wird die Ausführung des Programms beendet. + + +____________________________________________________________________________ + + gib kommando : + +____________________________________________________________________________ + + +Um die Arbeit in der Task zu beenden, geben Sie auch an dieser Stelle <ESC> <q> +(nacheinander!) ein. + +Nach Verlassen der Task ist wiederum die EUMEL-Tapete auf dem Bildschirm. Jede +weitere Aktion wird wiederum von hier aus durch <SV> begonnen. Insbesondere vor +dem #ib#Ausschalten des Geräts#ie# muß nach <SV> eine Task des priviliegierten System +zweigs (oft: '#ib#shutup#ie#') mit <ESC> <c> an das Terminal gekoppelt werden, in der das +Kommando 'shutup' gegeben wird. + diff --git a/doc/programmer-manual/1.8.7/doc/programmierhandbuch.2a b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.2a new file mode 100644 index 0000000..a204091 --- /dev/null +++ b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.2a @@ -0,0 +1,1845 @@ +#headandbottom("1","EUMEL-Benutzerhandbuch","TEIL 2 : ELAN","2")# +#pagenr("%",1)##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# + +TEIL 2: ELAN + +2.1 Besondere Eigenschaften von ELAN + +Kerneigenschaften von ELAN sind das #ib#Paketkonzept#ie# und die Methode des +#ib#Refinements#ie#. + +#on("b")#Paketkonzept:#off("b")# +ELAN bietet die Möglichkeit, neue Datentypen sowie Prozeduren und Operatoren auf +diesen Datentypen zu definieren. Eine solche Definition von Algorithmen und Daten +typen kann zu einer logischen Einheit, einem Paket, zusammengefaßt werden. Pakete +können in einer Task vorübersetzt werden und erweitern damit automatisch den +Sprachumfang. + +#on("b")#Methode des Refinements:#off("b")# +Die Methode des Refinements erlaubt das schrittweise Herleiten von Problemlösungen +von der jeweils geeigneten Terminologie herunter zu den von ELAN standardmäßig +angebotenen Sprachelementen. Durch diese Vorgehensweise wird in äußerst starkem +Maße ein strukturierter Programmentwurf gemäß dem Top-Down-Prinzip gefördert. + +Die Programmiersprache ELAN wird im EUMEL-System zu folgenden Zwecken +eingesetzt: + +- Systemimplementationssprache +- Kommandosprache +- Anwenderprogrammiersprache +#page# + +2.2 Lexikalische Elemente + +Unter lexikalischen Elementen einer Programmiersprache versteht man die Elemente, +in denen ein Programm notiert wird. + +In ELAN sind dies: + +- Schlüsselwörter +- Bezeichner +- Sonderzeichen +- Kommentare + + + + +2.2.1 Schlüsselwörter + +Einige Wörter haben in ELAN eine feste Bedeutung und können somit nicht frei +gewählt werden. Solche Wörter werden im EUMEL-System in Großbuchstaben +geschrieben, Leerzeichen dürfen nicht enthalten sein. + +Beispiele: + + +VAR +INT +WHILE + + +Wie später beschrieben wird, gibt es in ELAN auch die Möglichkeit, neue Schlüssel +wörter einzuführen. + + +#page# + +2.2.2 Bezeichner + +Bezeichner oder Namen werden benutzt, um Objekte in einem Programmtext zu +benennen und zu identifizieren (z.B: Variablennamen, Prozedurnamen). + +Namen werden in ELAN folgendermaßen formuliert: + +Das erste Zeichen eines Namens muß immer ein Kleinbuchstabe sein. Danach dürfen +bis zu 254 Kleinbuchstaben, aber auch Ziffern folgen. Zur besseren Lesbarkeit können +Leerzeichen in einem Namen erscheinen, die aber nicht zum Namen zählen. Sonder +zeichen sind in Namen nicht erlaubt. + +Beispiele für #on("b")#korrekte#off("b")# Bezeichner: + + +das ist ein langer name +x koordinate +nr 1 + + + +Beispiele für #on("b")#falsche#off("b")# Bezeichner: + + +x*1 +1 exemplar +Nr 1 +#page# + +2.2.3 Sonderzeichen + +Sonderzeichen sind Zeichen, die weder Klein- oder Großbuchstaben, noch Ziffern +sind. Sie werden in ELAN als Trennzeichen oder als Operatoren benutzt. + +In ELAN gibt es folgende Trennungszeichen: + +- das Semikolon (';') trennt Anweisungen +- der Doppelpunkt (':') trennt Definiertes und Definition +- der Punkt ('.') wird als Endezeichen für bestimmte Programmabschnitte, als Dezi + malpunkt und als Selektor-Zeichen für Datenstrukturen benutzt +- das Komma (',') trennt Parameter +- Klammernpaare ('(', ')') werden zum Einklammern von Parameterlisten oder Teil + ausdrücken benutzt +- mit Anführungszeichen ('"') werden Text-Denoter umrahmt +- eckige Klammernpaare ('[', ']') werden zur Subskription benutzt. + + +Als Operatornamen sind folgende Sonderzeichen erlaubt: + +- ein Sonderzeichen, sofern es nicht als Trennzeichen benutzt wird: + ! $ % & ' * + - / < = > ? § ^ ' ~ +- eine Kombination von zwei Sonderzeichen. Diese Kombination muß jedoch bereits + in ELAN existieren: + := <= >= <> ** + +#page# + +2.2.4 Kommentare + +Kommentare dienen ausschließlich der Dokumentation eines Programms. Sie werden +vom Compiler überlesen und haben somit keinen Einfluß auf die Ausführung eines +Programms. Sie dürfen an beliebigen Stellen eines Programmtextes geschrieben +werden, jedoch nicht innerhalb von Schlüsselwörtern und Namen. Ein Kommentar darf +über mehrere Zeilen gehen. In ELAN sind Kommentare nur in wenigen Fällen notwen +dig, da Programme durch andere Mittel gut lesbar geschrieben werden können. + +Ein Kommentar in ELAN wird durch Kommentarklammern eingeschlossen. Es gibt +folgende Formen von Kommentarklammern: + +(* Kommentar *) +{ Kommentar } +\#( Kommentar )# + +Die letzte Version '\#( Kommentar )\#' wird im EUMEL-System nicht +unterstützt; statt dessen gibt es noch folgende Möglichkeit: + +\# Kommentar \# + +Da bei der Kommentarkennzeichnung mit \# für Kommentaranfang und -ende das +gleiche Zeichen benutzt wird, ist eine Schachtelung hier nicht möglich. +#page# + +2.3 Datenobjekte + +Eine Klasse von Objekten mit gleichen Eigenschaften wird in Programmiersprachen +Datentyp genannt. Dabei hat ein Datentyp immer einen Namen, der die Klasse von +Objekten sinnvoll kennzeichnet. Als ein Datenobjekt wird ein Exemplar eines Daten +typs (also ein spezielles Objekt einer Klasse) bezeichnet. + +Datentypen sind in ELAN ein zentrales Konzept. Jedes der in einem ELAN- +Programm verwandten Datenobjekte hat einen Datentyp; somit kann man Datentypen +auch als Eigenschaften von Datenobjekten ansehen. Für jeden Datentyp sind nur +spezielle Operationen sinnvoll. Man kann nun Compilern die Aufgabe überlassen zu +überprüfen, ob stets die richtige Operation auf einen Datentyp angewandt wird. + + + +2.3.1 Elementare Datentypen + +Einige Datentypen spielen bei der Programmierung eine besondere Rolle, weil sie +häufig benötigt werden. + +In ELAN sind das die Datentypen für + +- ganze Zahlen (INT) +- reelle Zahlen (REAL) +- Zeichen und Zeichenfolgen (TEXT) +- Wahrheitswerte (BOOL). + +Diese Datentypen sind von der Sprache ELAN vorgegeben und werden elementare +Datentypen genannt. Für effiziente Rechnungen mit elementaren Datentypen gibt es +in den meisten Rechnern spezielle Schaltungen, so daß die Hervorhebung und be +sondere Rolle, die sie in Programmiersprachen spielen, gerechtfertigt ist. Zudem hat +man Werte-Darstellungen (Denoter) innerhalb von Programmen für die elementaren +Datentypen vorgesehen. + + + +2.3.1.1 Denoter für elementare Datentypen + +Die Darstellung eines Werts in einem Rechner zur Laufzeit eines Programms wird +Repräsentation genannt. Wenn es eindeutig ist, daß es sich nur um die Repräsenta +tion im Rechner handelt, spricht man kurz von Werten. Um mit Objekten elementarer +Datentypen arbeiten zu können, muß es in einem Programm die Möglichkeit geben, +Werte eines Datentyps zu bezeichnen (denotieren). Die Werte-Darstellungen, die in +ELAN Denoter genannt werden, sind für jeden Datentyp unterschiedlich. Wie bereits +erwähnt, haben alle Datenobjekte in ELAN (also auch Denoter) nur einen - vom +Compiler feststellbaren - Datentyp. Aus der Form eines Denoters ist also der Daten +typ erkennbar: + + + +INT-Denoter: +Sie bestehen aus einer Aneinanderreihung von Ziffern. + +Beispiele: + + +17 +007 +32767 +0 + + +Führende Nullen spielen bei der Bildung des Wertes keine Rolle (sie werden vom +ELAN-Compiler überlesen). Negative INT-Denoter gibt es nicht. Negative Werte +werden durch eine Aufeinanderfolge des monadischen Operators '-' (siehe 2.4.1.1) +und eines INT- Denoters realisiert. + + +REAL-Denoter: +Hier gibt es zwei Formen: +Die erste besteht aus zwei INT-Denotern, die durch einen Dezimalpunkt getrennt +werden. + +Beispiele: + + +0.314159 +17.28 + + +Der Dezimalpunkt wird wie ein Komma in der deutschen Schreibweise benutzt. Nega +tive REAL-Denoter gibt es wiederum nicht. + +Die zweite Form wird als "wissenschaftliche Notation" bezeichnet. Sie findet dann +Verwendung, wenn sehr große Zahlen oder Zahlen, die nahe bei Null liegen, darge +stellt werden müssen. + +Beispiele: + + +3.0 e5 +3.0e-5 + + +Der INT-Denoter hinter dem Buchstaben #on("b")#e#off("b")# gibt an, wie viele Stellen der Dezimal +punkt nach rechts (positive Werte) bzw. nach links (negative Werte) zu verschieben +ist. Dieser Wert wird Exponent und der Teil vor dem Buchstaben #on("b")#e#off("b")# Mantisse genannt. + + +TEXT-Denoter: +Sie werden in Anführungszeichen eingeschlossen. + +Beispiele: + + +"Das ist ein TEXT-Denoter" +"Jetzt ein TEXT-Denoter ohne ein Zeichen: ein leerer Text" +"" + + +Zu beachten ist, daß das Leerzeichen ebenfalls ein Zeichen ist. Soll ein Anführungs +zeichen in einem TEXT erscheinen (also gerade das Zeichen, welches einen Denoter +beendet), so muß es doppelt geschrieben werden. + +Beispiele: + + +"Ein TEXT mit dem ""-Zeichen" +"Ein TEXT-Denoter nur mit dem ""-Zeichen:" +"""" + + +Manchmal sollen Zeichen in einem TEXT-Denoter enthalten sein, die auf dem +Eingabegerät nicht zur Verfügung stehen. In diesem Fall kann der Code-Wert des +Zeichens angegeben werden. + +Beispiel: + + +"da"251"" + + +ist gleichbedeutend mit "daß". Der Code-Wert eines Zeichens ergibt sich aus der +EUMEL-Code-Tabelle (siehe 5.2.4.1), in der jedem Zeichen eine ganze Zahl zuge +ordnet ist. + + +BOOL-Denoter: +Es gibt nur zwei BOOL-Denoter: +TRUE für "wahr" und FALSE für "falsch". + + + +2.3.1.2 LET-Konstrukt für Denoter + +Neben der Funktion der Abkürzung von Datentypen (siehe 2.6.3) kann das LET- +Konstrukt auch für die Namensgebung für Denoter verwandt werden. + +Die LET-Vereinbarung sieht folgendermaßen aus: + + +#on("i")##on("b")#LET#off("i")##off("b")# Name #on("i")##on("b")#=#off("i")##off("b")# Denoter + + +Mehrere Namensgebungen können durch Komma getrennt werden. + + +____________________________________________________________________________ + .......................... Beispiele: ......................... + LET anzahl = 27; + LET pi = 3.14159, + blank = " "; +____________________________________________________________________________ + + +Der Einsatz von LET-Namen für Denoter hat zwei Vorteile: + +- feste Werte im Programm sind leicht zu ändern, da nur an einer Stelle des Pro + gramms der Denoter geändert werden muß + (z.B.: In Vereinbarungen von Reihungen (siehe 2.6.1) können LET-Denoter, im + Gegensatz zu Konstanten, als Obergrenze angegeben werden. Dieser + Wert kann dann auch an anderen Stellen des Programms, z.B. in Schlei + fen (siehe 2.4.2.5), benutzt werden. Bei Änderung der Reihungsgröße + braucht dann nur an einer Stelle des Programms der Wert geändert zu + werden.) +- der Name gibt zusätzliche Information über die Bedeutung des Denoters. + + + +2.3.2 Zugriffsrecht + +Von manchen Datenobjekten weiß man, daß sie nur einmal einen Wert erhalten +sollen. Sie sollen also nicht verändert werden. Oder man weiß, daß in einem Pro +grammbereich ein Datenobjekt nicht verändert werden soll. Um ein unbeabsichtigtes +Verändern zu verhindern, wird in ELAN dem Datenobjekt ein zusätzlicher Schutz +mitgegeben: das Zugriffsrecht oder Accessrecht. + +In der Deklaration eines Datenobjekts können folgende Accessattribute angegeben +werden: + +- #on("i")##on("b")#VAR #off("i")##off("b")# für lesenden und schreibenden (verändernden) Zugriff + +- #on("i")##on("b")#CONST#off("i")##off("b")# für nur lesenden Zugriff. + + + +2.3.3 Deklaration + +Damit man Datenobjekte in einem Programm ansprechen kann, gibt man einem +Datenobjekt einen Namen (wie z.B. einen Personennamen, unter der sich eine wirk +liche Person "verbirgt"). Will man ein Datenobjekt in einem Programm verwenden, so +muß man dem Compiler mitteilen, welchen Datentyp und welches Accessrecht das +Objekt haben soll. Das dient u.a. dazu, nicht vereinbarte Namen (z.B. verschriebene) +vom Compiler entdecken zu lassen. Weiterhin ist aus dem bei der Deklaration ange +gebenen Datentyp zu entnehmen, wieviel Speicherplatz für das Objekt zur Laufzeit zu +reservieren ist. + +Eine Deklaration oder Vereinbarung besteht aus der Angabe von + +- Datentyp +- Zugriffsrecht ( #on("i")##on("b")#VAR#off("i")##off("b")# oder #on("i")##on("b")#CONST#off("i")##off("b")#) +- Name des Datenobjekts. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR mein datenobjekt; + +____________________________________________________________________________ + + +Verschiedene Datenobjekte mit gleichem Datentyp und Accessrecht dürfen in einer +Deklaration angegeben werden; sie werden durch Kommata getrennt. Mehrere Dekla +rationen werden - genauso wie Anweisungen - durch das Trennzeichen Semikolon +voneinander getrennt. + +____________________________________________________________________________ + .......................... Beispiele: ......................... + INT VAR mein wert, dein wert, unser wert; + BOOL VAR listen ende; + TEXT VAR zeile, wort; + +____________________________________________________________________________ + + +2.3.4 Initialisierung + +Um mit den vereinbarten Datenobjekten arbeiten zu können, muß man ihnen einen +Wert geben. Hat ein Datenobjekt noch keinen Wert erhalten, so sagt man, sein Wert +sei undefiniert. Das versehentliche Arbeiten mit undefinierten Werten ist eine beliebte +Fehlerquelle. Deshalb wird von Programmierern streng darauf geachtet, diese Fehler +kuelle zu vermeiden. Eine Wertgebung an ein Datenobjekt kann (muß aber nicht) +bereits bei der Deklaration erfolgen. In ELAN wird dies Initialisierung genannt. Für mit +CONST vereinbarte Datenobjekte ist die Initialisierung die einzige Möglichkeit, ihnen +einen Wert zu geben. Die Initialisierung von Konstanten ist zwingend vorgeschrieben +und wird vom Compiler überprüft. + +Die Initialisierung besteht aus der Angabe von + +- Datentyp +- Zugriffsrecht ( #on("i")##on("b")#VAR#off("i")##off("b")# oder #on("i")##on("b")#CONST#off("i")##off("b")#) +- Name des Datenobjekts +- Operator #on("i")##on("b")#::#off("i")##off("b")# oder #on("i")##on("b")#:=#off("i")##off("b")# +- Wert, den das Datenobjekt erhalten soll (Denoter, Ausdruck). + +____________________________________________________________________________ + .......................... Beispiele: ......................... + INT CONST gewuenschtes gehalt :: 12 000; + TEXT VAR zeile :: ""; + REAL CONST pi :: 3.14159, zwei pi := 2.0 * pi; + BOOL VAR bereits sortiert :: TRUE; +____________________________________________________________________________ +#page# + +2.4 Programmeinheiten + +Neben Deklarationen (Vereinbarungen) sind Programmeinheiten die Grundbestandteile +von ELAN. + + +Programmeinheiten können sein: + +#on("b")#- elementare Programmeinheiten #off("b")# + - Ausdruck + - Zuweisung + - Refinementanwendung + - Prozeduraufruf + +#on("b")#- zusammengesetzte Programmeinheiten #off("b")# + - Folge + - Abfrage + - Auswahl + - Wiederholung + +#on("b")#- abstrahierende Programmeinheiten #off("b")# + - Refinementbvereinbarung + - Prozedurvereinbarung + - Operatorvereinbarung + - Paketvereinbarung. +#page# + +2.4.1 Elementare Programmeinheiten + + +2.4.1.1 Ausdruck + +Ausdrücke sind eine Zusammenstellung von Datenobjekten (Denoter, VAR- oder +CONST-Objekte) und Operatoren. Jeder korrekte Ausdruck liefert einen Wert. Der +Typ des Ausdrucks wird bestimmt durch den Typ des Wertes, den der Ausdruck +liefert. + + +Operatoren + +Operatoren werden in ELAN durch ein oder zwei Sonderzeichen oder durch Groß +buchstaben als Schlüsselwort dargestellt (siehe 2.4.3.3). + +Als Operanden (also die Datenobjekte, auf die ein Operator "wirken" soll) dürfen +VAR- und CONST-Datenobjekte, Denoter oder Ausdrücke verwendet werden. Typ +der Operanden und des Resultats eines Operators werden in der Operatorvereinba +rung festgelegt (siehe 2.4.3.3). + +Man unterscheidet zwei Arten von Operatoren: + +#on("b")#- monadische Operatoren #off("b")# + Monadischen Operatoren haben nur einen Operanden, der rechts vom Operator + zeichen geschrieben werden muß. + + Beispiel: + + + - a + NOT x + + + Der '-' - Operator liefert den Wert von a mit umgekehrten Vorzeichen. a muß + dabei vom Datentyp INT oder REAL sein. + Der Operator 'NOT' realisiert die logische Negation. y muß vom Datentyp BOOL + sein. + + +#on("b")#- dyadische Operatoren #off("b")# + Dyadische Operatoren haben zwei Operanden. Das Operatorzeichen steht zwi + schen den beiden Operanden. + + Beispiele: + + + a + b + a - b + a * b + a DIV b + a ** b + x < y + x <> y + x AND y + x OR y + + + In den ersten fünf Beispielen werden jeweils die Werte von zwei INT-Objekten a + und b addiert (Operatorzeichen: '+'), subtrahiert ('-'), multipliziert ('*'), dividiert + (ganzzahlige Division ohne Rest: 'DIV') und potenziert ('**'). + Im sechsten und siebten Beispiel werden zwei BOOL-Werte x und y verglichen + und im achten und neunten Beispiel die logische Operation 'und' (Operator 'AND') + bzw. 'oder' (Operator 'OR') durchgeführt. + + +Priorität von Operatoren + +Es ist erlaubt, einen Ausdruck wiederum als Operanden zu verwenden. Praktisch +bedeutet dies, daß mehrere Operatoren und Datenobjekte zusammen in einem Aus +druck geschrieben werden dürfen. + +Beispiele: + + +a + 3 - b * c +- a * b + + +Die Reihenfolge der Auswertung kann man durch Angabe von Klammern steuern. + +Beispiel: + + +(a + b) * (a + b) + + +Es wird jeweils erst 'a + b' ausgewertet und dann erst die Multiplikation durchge +führt. In ELAN ist es erlaubt, beliebig viel Klammernpaare zu verwenden (Regel: die +innerste Klammer wird zuerst ausgeführt). Es ist sogar zulässig, Klammern zu ver +wenden, wo keine notwendig sind, denn überflüssige Klammernpaare werden überle +sen. Man muß jedoch beachten, daß Ausdrücke, und damit auch z.B. #on("b")#(a)#off("b")#, immer +Accessrecht CONST haben. + +Beispiel: + + +((a - b)) * 3 * ((c + d) * (c - d)) + + +Somit können beliebig komplizierte Ausdrücke formuliert werden. + +Um solche Ausdrücke einfacher zu behandeln und sie so ähnlich schreiben zu kön +nen, wie man es in der Mathematik gewohnt ist, wird in Programmiersprachen die +Reihenfolge der Auswertung von Operatoren festgelegt. In ELAN wurden neun Ebe +nen, Prioritäten genannt, festgelegt: + + +#on("bold")#Priorität Operatoren +#off("bold")# + + 9 alle monadischen Operatoren + 8 ** + 7 *, /, DIV, MOD + 6 +, - + 5 =, <>, <, <=, >, >= + 4 AND + 3 OR + 2 alle übrigen, nicht in dieser Tabelle aufgeführten + dyadischen Operatoren + 1 := + +(Die erwähnten Operatoren in der Tabelle werden in der Beschreibung der Standard +prozeduren und -Operatoren besprochen). + +Operatoren mit der höchsten Priorität werden zuerst ausgeführt, dann die mit der +nächst niedrigeren Priorität usw.. Operatoren mit gleicher Priorität werden von links +nach rechts ausgeführt. Dadurch ergibt sich die gewohnte Abarbeitungsfolge wie beim +Rechnen. + +Beispiel: + + +-2 + 3 * 2 ** 3 + +a) -2 +b) 2 ** 3 +c) 3 * (2 ** 3) +d) ((-2)) + (3 * (2 ** 3)) + + +Wie bereits erwähnt, ist es immer erlaubt, Klammern zu setzen. Ist man sich also +über die genaue Abarbeitungsfolge nicht im Klaren, so kann man Klammern verwen +den. + + + +2.4.1.2 Zuweisung + +Ein spezieller Operator ist die Zuweisung. + +Form: + + +Variable #on("i")##on("b")#:=#off("i")##off("b")# Wert + + +Dieser Operator hat immer die geringste Priorität, wird also immer als letzter einer +Anweisung ausgeführt. Die Zuweisung wird verwendet, um einer Variablen einen +neuen Wert zu geben. Der Operator ':=' liefert kein Resultat (man sagt auch, er +liefert keinen Wert) und verlangt als linken Operanden ein VAR-Datenobjekt, an den +der Wert des rechten Operanden zugewiesen werden soll). Der Wert des linken Oper +anden wird also verändert. Der rechte Operand wird nur gelesen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + a := b; + +____________________________________________________________________________ + + +Hier wird der Wert von 'b' der Variablen 'a' zugewiesen. Der vorher vorhandene Wert +von 'a' geht dabei verloren. Man sagt auch, der Wert wird überschrieben. + +Als rechter Operand des ':='-Operators darf auch ein Ausdruck stehen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + a := b + c; + +____________________________________________________________________________ + + +Hier wird das Resultat von 'b + c' an die Variable 'a' zugewiesen. Man beachte +dabei die Prioritäten der Operatoren '+' (Priorität 6) und ':=' (Priorität 1): die Addition +wird vor der Zuweisung ausgeführt. Die Auswertung von Zuweisungen mit Ausdrücken +muß immer so verlaufen, da die Zuweisung stets die niedrigste Priorität aller Operato +ren hat. + +Oft kommt es vor, daß ein Objekt auf der linken und rechten Seite des Zuweisungs +operators erscheint, z.B. wenn ein Wert erhöht werden soll. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + a := a + 1; + +____________________________________________________________________________ + + +Hier wird der "alte", aktuelle Wert von 'a' genommen, um '1' erhöht und dem Objekt +'a' zugewiesen. Man beachte, daß hier in einer Anweisung ein Datenobjekt unter +schiedliche Werte zu unterschiedlichen Zeitpunkten haben kann. + + + +2.4.1.3 Refinementanwendung + +In ELAN ist es möglich, Namen für Ausdrücke oder eine bzw. mehrere Anweisungen +zu vergeben. Das Sprachelement, das diese Namensgebung ermöglicht, heißt Refi +nement. Die Ausführung eines solchen Namens heißt Refinementanwendung, die +Namensgebung heißt Refinementvereinbarung (siehe 2.4.3.1). Die Ausdrücke oder +Anweisungen bilden den Refinementrumpf. Ein Refinement kann man in einem Pro +gramm unter dem Refinementnamen ansprechen. Man kann sich die Ausführung so +vorstellen, als würden der Refinementrumpf immer dort eingesetzt, wo der Name des +Refinements als Operation benutzt wird. + + + +2.4.1.4 Prozeduraufruf + +Eine Prozedur ist eine Sammlung von Anweisungen und Daten, die zur Lösung einer +bestimmten Aufgabe benötigt werden. Eine Prozedur wird in einer Prozedurvereinba +rung definiert (siehe 2.4.3.2). Eine solche Prozedur kann man in einem Programm +unter einem Namen (eventuell unter Angabe von Parametern) ansprechen. Man +spricht dann vom Aufruf einer Prozedur oder einer Prozeduranweisung. + +Formen des Prozeduraufrufs: + +- #on("b")#Prozeduren ohne Parameter#off("b")# werden durch den Prozedurnamen angesprochen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + pause; + +____________________________________________________________________________ + + + (Die Prozedur 'pause' wartet bis ein Zeichen eingegeben wird) + + +- #on("b")#Prozeduren mit Parameter#off("b")# werden durch + + + Prozedurnamen #on("i")##on("b")#(#off("i")##off("b")# aktuelle Parameterliste #on("i")##on("b")#)#off("i")##off("b")# + + + aufgerufen. Eine Parameterliste ist entweder ein Datenobjekt oder mehrere durch + Kommata getrennte Datenobjekte. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + pause (10); + +____________________________________________________________________________ + + + (Mit der Prozedur 'pause (INT CONST zeitgrenze)' kann für eine Zeitdauer von + 'zeitgrenze' in Zehntel-Sekunden gewartet werden. Die Wartezeit wird durch + Erreichen der Zeitgrenze oder durch Eingabe eines Zeichens abgebrochen) + + + Bei den aktuellen Parametern ist folgendes zu beachten: + + a) Wird ein VAR-Parameter in der Definition der Prozedur vorgeschrieben, darf + kein Ausdruck als aktueller Parameter "übergeben" werden, weil an einen + Ausdruck nichts zugewiesen werden kann. Ausdrücke haben - wie bereits + erwähnt - das Accessrecht CONST. + +____________________________________________________________________________ + ........................ Gegenbeispiel: ....................... + TEXT VAR text1, text2; + text1 := "Dieses Beispiel "; + text2 := "Fehlermeldung"; + insert char (text1 + text2, "liefert eine", 17); + +____________________________________________________________________________ + + + (Die Prozedur 'insert char (TEXT VAR string, TEXT CONST char, INT CONST + pos)' fügt das Zeichen 'char' in den Text 'string' an der Position 'pos' ein) + + b) Wird ein CONST-Parameter verlangt, dann darf in diesem Fall ein Ausdruck + als aktueller Parameter geschrieben werden. Aber auch ein VAR-Datenobjekt + darf angegeben werden. In diesem Fall wird eine Wandlung des Accessrechts + (CONSTing) vorgenommen: der aktuelle Parameter erhält sozusagen für die + Zeit der Abarbeitung der Prozedur das Accessrecht CONST. + + + In ELAN sind auch Prozeduren als Parameter erlaubt. Die Prozedur als aktueller + Parameter wird in der Parameterliste folgendermaßen angegeben: + + + Resultattyp #on("i")##on("b")#PROC#off("i")##off("b")# #on("i")##on("b")#(#off("i")##off("b")# virtuelle Parameterliste #on("i")##on("b")#)#off("i")##off("b")# Procname + + + Die Angabe des Resultattyps entfällt, wenn es sich nicht um eine wertliefernde + Prozedur handelt. Die virtuelle Parameterliste inklusive der Klammern entfällt, falls + die Prozedur keine Parameter hat. Die virtuelle Parameterliste beschreibt die + Parameter der Parameterprozedur. Es werden Datentyp und Zugriffsrecht eines + jeden Parameters angegeben, jedoch ohne Namen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + wertetabelle (REAL PROC (REAL CONST) sin, + untergrenze, obergrenze, schrittweite); + + + (Die Prozedur 'sin' wird an die Prozedur 'wertetabelle' übergeben) + +____________________________________________________________________________ + + +2.4.2 Zusammengesetzte Programmeinheiten + + +2.4.2.1 Folge + +Mehrere in einer bestimmten Reihenfolge auszuführende Anweisungen werden als +Folge bezeichnet. In ELAN kann man eine oder mehrere Anweisungen in eine Pro +grammzeile schreiben oder eine Anweisung über mehrere Zeilen. Das setzt jedoch +voraus, daß die Anweisungen voneinander getrennt werden. Die Trennung von Anwei +sungen erfolgt in ELAN durch das Trennsymbol Semikolon. Es bedeutet soviel wie: +"führe die nächste Anweisung aus". + +____________________________________________________________________________ + ........................... Beispiel: ......................... + put ("mein"); + put (1); + put (". Programm") + +____________________________________________________________________________ + + +(Die Prozedur 'put' gibt den als Parameter angegebenen Wert auf dem Ausgabegerät +aus) + + + +2.4.2.2 Abfrage + +Mit Abfragen steuert man die bedingte Ausführung von Anweisungen. Abhängig von +einer Bedingung wird in zwei verschiedene Programmabschnitte verzweigt. + +Der formale Aufbau einer Abfrage sieht folgendermaßen aus: + + +#on("i")##on("b")#IF#off("i")##off("b")# Bedingung + #on("i")##on("b")#THEN#off("i")##off("b")# Abschnitt + #on("i")##on("b")#ELSE#off("i")##off("b")# Abschnitt +#on("i")##on("b")#END IF#off("i")##off("b")# + + +Der ELSE-Teil darf dabei auch fehlen. Anstelle von #on("i")##on("b")#END IF#off("i")##off("b")# darf auch die Abkürzung #on("i")##on("b")#FI#off("i")##off("b")# (IF von hinten gelesen) benutzt werden. + +In folgenden Beispielen wird der Absolutbetrag von 'a' ausgegeben: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR a; + get (a); + IF a < 0 + THEN a := -a + END IF; + put (a) + +____________________________________________________________________________ + + +Die Umkehrung des Vorzeichens von a im THEN-Teil wird nur durchgeführt, wenn +der BOOLesche Ausdruck ('a < 0') den Wert TRUE liefert. Liefert er den Wert +FALSE, wird die Anweisung, die der bedingten Anweisung folgt (nach END IF), ausge +führt. Das obige Programm kann auch anders geschrieben werden: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR a; + get (a); + IF a < 0 + THEN put (-a) + ELSE put (a) + END IF + +____________________________________________________________________________ + + +Der THEN-Teil wird wiederum ausgeführt, wenn die BOOLesche Bedingung erfüllt +ist. Liefert sie dagegen FALSE, wird der ELSE-Teil ausgeführt. + +Die bedingte Anweisung ermöglicht es, abhängig von einer Bedingung eine oder +mehrere Anweisungen ausführen zu lassen. Dabei können im THEN- bzw. ELSE- +Teil wiederum bedingte Anweisungen enthalten sein. + + +Abfragekette +Bei Abfrageketten kann das ELIF-Konstrukt eingesetzt werden. (ELIF ist eine Zu +sammenziehung der Worte ELSE und IF). + +Anstatt + +____________________________________________________________________________ + ........................... Beispiel: ......................... + IF bedingung1 + THEN aktion1 + ELSE IF bedingung2 + THEN aktion2 + ELSE aktion3 + END IF + END IF; + +____________________________________________________________________________ + + +kann man besser + +____________________________________________________________________________ + ........................... Beispiel: ......................... + IF bedingung1 + THEN aktion1 + ELIF bedingung2 + THEN aktion2 + ELSE aktion3 + END IF; + +____________________________________________________________________________ + + +schreiben. + + + +2.4.2.3 Auswahl + +Die Auswahl wird benutzt, wenn alternative Anwendungen in Abhängikeit von Werten +eines Datenobjekts ausgeführt werden sollen. + +Der formale Aufbau der Auswahl sieht folgendermaßen aus: + + +#on("i")##on("b")#SELECT#off("i")##off("b")# INT-Ausdruck #on("i")##on("b")#OF#off("i")##off("b")# + #on("i")##on("b")#CASE#off("i")##off("b")# 1. Liste von INT-Denotern #on("i")##on("b")#:#off("i")##off("b")# Abschnitt + #on("i")##on("b")#CASE#off("i")##off("b")# 2. Liste von INT-Denotern #on("i")##on("b")#:#off("i")##off("b")# Abschnitt + . + . + . + #on("i")##on("b")#CASE#off("i")##off("b")# n. Liste von INT-Denotern #on("i")##on("b")#:#off("i")##off("b")# Abschnitt + #on("i")##on("b")#OTHERWISE#off("i")##off("b")# Abschnitt +#on("i")##on("b")#END SELECT#off("i")##off("b")# + + +Eine Liste von INT-Denotern besteht aus einem oder mehreren durch Kommata ge +trennten INT-Denotern. Der OTHERWISE-Teil darf auch fehlen. Man sollte ihn +jedoch verwenden, um Fehlerfälle abzufangen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + SELECT monat OF + CASE 2: IF schaltjahr + THEN tage := 29 + ELSE tage := 28 + END IF + CASE 4, 6, 9, 11: tage := 30 + CASE 1, 3, 5, 7, 8, 10 ,12: tage := 31 + OTHERWISE kein monat + END SELECT; + +____________________________________________________________________________ + + +(In diesem Programmausschnitt werden die Tage eines Monats bestimmt) + + + +2.4.2.4 Wertliefernde Abfrage und + wertliefernde Auswahl + + +Soll eine Abfrage oder eine Auswahl einen Wert liefern, dann darf der ELSE- bzw. +der OTHERWISE-Teil nicht fehlen und alle Zweige müssen einen Wert liefern. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + SELECT monat OF + CASE 2: IF schaltjahr + THEN 29 + ELSE 28 + END IF + CASE 4, 6, 9, 11: 30 + CASE 1, 3, 5, 7, 8, 10 ,12: 31 + OTHERWISE kein monat; 0 + END SELECT; + +____________________________________________________________________________ + + +2.4.2.5 Wiederholung + +Die Wiederholung dient zur mehrfachen Ausführung von Anweisungen, meist in Ab +hängigkeit von einer Bedingung. Darum wird die Wiederholungsanweisung oft auch +Schleife genannt und die in ihr enthaltenen Anweisungen Schleifenrumpf. + +Es gibt verschiedene Schleifentypen: + +- Endlosschleife +- abweisende Schleife +- nicht abweisende Schleife +- Zählschleife. + + +Endlosschleife +Bei der Endlosschleife wird nicht spezifiziert, wann die Schleife beendet werden soll. + +Form: + + +#on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#END REPEAT#off("i")##off("b")# + + +Anstelle von #on("i")##on("b")#REPEAT#off("i")##off("b")# darf die Abkürzung #on("i")##on("b")#REP#off("i")##off("b")# und anstelle von #on("i")##on("b")#END REPEAT#off("i")##off("b")# +das Schlüsselwort #on("i")##on("b")#PER#off("i")##off("b")# (REP von hinten gelesen) +benutzt werden. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + break; + REPEAT + fixpoint; + pause (18000) + END REPEAT + +____________________________________________________________________________ + + +Wird dieses Programm in einer Task im SYSUR-Zweig ausgeführt, so führt diese +Task Fixpunkte im Abstand von 30 Minuten durch. + + + +Abweisende Schleife +Bei der abweisenden Schleife wird die Abbruchbedingung an den Anfang der Schleife +geschrieben. + +Form: + + +#on("i")##on("b")#WHILE#off("i")##off("b")# Bedingung #on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#END REPEAT#off("i")##off("b")# + + +Bei jedem erneuten Durchlauf der Schleife wird überprüft, ob der BOOLesche Aus +druck den Wert TRUE liefert. Ist das nicht der Fall, wird die Bearbeitung mit der +Anweisung fortgesetzt, die auf das Schleifenende folgt. Die Schleife wird abweisende +Schleife genannt, weil der Schleifenrumpf nicht ausgeführt wird, wenn die Bedingung +vor Eintritt in die Schleife bereits FALSE liefert. + + +Nicht abweisende Schleife +Anders verhält es sich bei der nicht abweisenden Schleife. Bei der nicht abweisenden +Schleife wird die Abbruchbedingung an das Ende der Schleife geschrieben. + +Form: + + +#on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#UNTIL#off("i")##off("b")# Bedingung #on("i")##on("b")#END REPEAT#off("i")##off("b")# + + +Hier wird der Schleifenrumpf auf jeden Fall einmal bearbeitet. Am Ende des Rumpfes +wird die BOOLesche Bedingung abgefragt. Liefert sie den Wert FALSE, wird die +Schleife erneut abgearbeitet. Liefert die Bedingung den Wert TRUE, wird die Schleife +abgebrochen und mit der ersten Anweisung hinter der Schleife in der Bearbeitung +fortgefahren. + +Bei den beiden letztgenannten Arten der Wiederholungsanweisung ist es wichtig, daß +Elemente der BOOLeschen Bedingung in der Schleife verändert werden, damit das +Programm terminieren kann, d.h. die Schleife abgebrochen wird. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + TEXT VAR wort, satz :: ""; + REPEAT + get (wort); + satz CAT wort; + satz CAT " " + UNTIL wort = "." PER; + +____________________________________________________________________________ + + +Dises Programm liest solange Wörter ein und verbindet diese zu einem Satz, bis ein +Punkt eingegeben wurde. + + + +Zählschleife +Zählschleifen werden eingesetzt, wenn die genaue Anzahl der Schleifendurchläufe +bekannt ist. + +Form: + + +#on("i")##on("b")#FOR#off("i")##off("b")# Laufvariable #on("i")##on("b")#FROM#off("i")##off("b")# Anfangswert #on("i")##on("b")#UPTO#off("i")##off("b")# Endwert #on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#END REPEAT#off("i")##off("b")# + + +Bei Zählschleifen wird eine Laufvariable verwendet, die die INT-Werte von 'Anfangs +wert' bis 'Endwert' in Schritten von 1 durchläuft. 'Anfangswert' und 'Endwert' können +beliebige INT-Ausdrücke sein. Diese Schleife zählt "aufwärts". Wird anstatt #on("i")##on("b")#UPTO#off("i")##off("b")# +das Schlüsselwort #on("i")##on("b")#DOWNTO#off("i")##off("b")# verwendet, wird mit Schritten von 1 "abwärts" gezählt. + +Form: + + +#on("i")##on("b")#FOR#off("i")##off("b")# Laufvariable #on("i")##on("b")#FROM#off("i")##off("b")# Endwert #on("i")##on("b")#DOWNTO#off("i")##off("b")# Anfangswert #on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#END REPEAT#off("i")##off("b")# + + +Die Laufvariable darf in der Schleife nicht verändert werden. Nach dem normalen +Schleifenende ist der Wert der Laufvariablen nicht definiert. + + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR summe :: 0, i; + FOR i FROM 1 UPTO 100 REPEAT + summe INCR i + END REPEAT + +____________________________________________________________________________ + + +Dieses Programm berechnet die Summe der natürlichen Zahlen von 1 bis 100. + + +Die verschiedenen Schleifenarten können kombiniert werden: + + +#on("i")##on("b")#FOR#off("i")##off("b")# Laufvariable #on("i")##on("b")#FROM#off("i")##off("b")# Anfangswert #on("i")##on("b")#UPTO#off("i")##off("b")# Endwert +#on("i")##on("b")#WHILE#off("i")##off("b")# Bedingung #on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#END REPEAT#off("i")##off("b")# + + + +#on("i")##on("b")#FOR#off("i")##off("b")# Laufvariable #on("i")##on("b")#FROM#off("i")##off("b")# Anfangswert #on("i")##on("b")#UPTO#off("i")##off("b")# Endwert #on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#UNTIL#off("i")##off("b")# Bedingung #on("i")##on("b")#END REPEAT#off("i")##off("b")# + + + + + +#on("i")##on("b")#WHILE#off("i")##off("b")# Bedingung #on("i")##on("b")#REPEAT#off("i")##off("b")# + Abschnitt +#on("i")##on("b")#UNTIL#off("i")##off("b")# Bedingung #on("i")##on("b")#END REPEAT#off("i")##off("b")# + +#page# + +2.4.3 Abstrahierende Programmeinheiten + + +2.4.3.1 Refinementvereinbarung + +In ELAN ist es möglich, Namen für Ausdrücke oder eine bzw. mehrere Anweisungen +zu vergeben. Das Sprachelement, das diese Namensgebung ermöglicht, heißt Refi +nement. Die Ausführung eines solchen Namens heißt Refinementanwendung (siehe +2.4.1.3), die Namensgebung heißt Refinementvereinbarung. Die Ausdrücke oder +Anweisungen bilden den Refinementrumpf. + +Werden in einem Programm Refinements benutzt, dann wird der Programmteil bis +zum ersten Refinement durch einen Punkt abgeschlossen. Die Refinementvereinba +rung sieht folgendermaßen aus: + + +Name #on("i")##on("b")#:#off("i")##off("b")# + Abschnitt #on("i")##on("b")#.#off("i")##off("b")# + + + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR a, b, x; + einlesen von a und b; + vertauschen von a und b; + vertauschte werte ausgeben. + + einlesen von a und b: + get (a); + get (b). + + vertauschen von a und b: + x := a; + a := b; + b := x. + + vertauschte werte ausgeben: + put (a); + put (b). + +____________________________________________________________________________ + + +Für den Namen 'einlesen von a und b' werden die Anweisungen 'get (a); get (b)' vom +ELAN-Compiler eingesetzt. Man kann also die ersten vier Zeilen des Programms als +eigentliches Programm ansehen, wobei die Namen durch die betreffenden Anwei +sungen ersetzt werden. Ein Refinement hat also keinen eigenen Datenbereich, d.h. +Vereinbarungen, die in Refinements gemacht werden, gelten auch außerhalb des +Refinements. + + + +Vorteile der Refinementanwendung +Durch die sinnvolle Verwendung von Refinements wird ein Programm im Programm +und nicht in einer separaten Beschreibung dokumentiert. Weiterhin kann ein Pro +gramm "von oben nach unten" ("top down") entwickelt werden: Das obige - zuge +geben einfache - Beispielprogramm wurde in drei Teile zerlegt und diese durch +Namen beschrieben. Bei der Beschreibung von Aktionen durch Namen wird gesagt +was gemacht werden soll. Es wird noch nicht beschrieben wie, denn auf dieser Stufe +der Programmentwicklung braucht man sich um die Realisierung der Refinements +(noch) keine Sorgen zu machen. Das erfolgt erst, wenn das Refinement programmiert +werden muß. Dabei können wiederum Refinements verwendet werden usw., bis man +auf eine Ebene "heruntergestiegen" ist, bei der eine (jetzt: Teil-) Problemlösung sehr +einfach ist und man sie direkt hinschreiben kann. Man beschäftigt sich also an jedem +Punkt der Problemlösung nur mit einem Teilaspekt des gesamten Problems. Zudem +sieht man - wenn die Refinements einigermaßen vernünftig verwendet werden - +dem Programm an, wie die Problemlösung entstanden ist. + +Die Verwendung von Refinements hat also eine Anzahl von Vorteilen. +Refinements ermöglichen: + +- "top down" - Programmierung +- Strukturierung von Programmen und damit effiziente Fehlersuche und gute Wart + barkeit +- Dokumentation im Programmtext. + + +Wertliefernde Refinements +Refinements können auch dort verwendet werden, wo ein Wert erwartet wird, z.B. in +einem Ausdruck oder einer 'put'-Anweisung. In diesem Fall muß die letzte Anwei +sung des Refinements einen Wert liefert. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT VAR a :: 1, b :: 2, c :: 3; + put (resultat). + + resultat: + (a * b + c) ** 3. + +____________________________________________________________________________ + + +Man kann auch ein wertlieferndes Refinement mit mehreren Anweisungen schrei +ben. + +Allgemeine Regel: +Die letzte Anweisung eines Refinements bestimmt, ob es einen Wert liefert - und +wenn ja, von welchen Datentyp. + + + +2.4.3.2 Prozedurvereinbarung + +Eine Prozedur ist eine Sammlung von Anweisungen und Daten, die zur Lösung einer +bestimmten Aufgabe benötigt werden. + +Der formale Aufbau einer Prozedur sieht folgendermaßen aus: + + +#on("i")##on("b")#PROC#off("i")##off("b")# Prozedurname #on("i")##on("b")#:#off("i")##off("b")# + Prozedurrumpf +#on("i")##on("b")#END PROC#off("i")##off("b")# Prozedurname + + +Der Prozedurrumpf kann Deklarationen, Anweisungen und Refinements enthalten. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PROC loesche bildschirm ab aktueller cursorposition: + out (""4"") + END PROC loesche bildschirm ab aktueller cursorposition + +____________________________________________________________________________ + + +Verwendung von Prozeduren +Prozeduren werden verwendet, wenn + +- Anweisungen und Datenobjekte unter einem Namen zusammengefaßt werden + sollen ("Abstraktion") +- gleiche Anweisungen von mehreren Stellen eines Programms verwandt werden + sollen (Codereduktion), u.U. mit verschieden Datenobjekten (Parameter) +- Datenobjekte nur innerhalb eines Programmteils benötigt werden und diese nicht + von dem gesamten Programm angesprochen werden sollen. + +In den folgenden Programmfragmenten werden zwei Werte vertauscht. In der ersten +Lösung wird ein Refinement, in der zweiten eine Prozedur verwandt. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + IF a > b + THEN vertausche a und b + END IF; + put (a); + put (b); + vertausche a und b. + + vertausche a und b: + INT CONST x :: a; + a := b; + b := x. + +____________________________________________________________________________ + + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PROC vertausche a und b: + INT CONST x :: a; + a := b; + b := x + END PROC vertausche a und b; + + IF a > b + THEN vertausche a und b + END IF; + put (a); + put (b); + vertausche a und b; + +____________________________________________________________________________ + + +Beim ersten Hinsehen leisten beide Programme das Gleiche. Es gibt jedoch drei +wichtige Unterschiede: + +1) Das Refinement 'vertausche a und b' wird zweimal (vom ELAN-Compiler) ein + gesetzt, d.h. der Code ist zweimal vorhanden. Die Prozedur dagegen ist vom Code + nur einmal vorhanden, wird aber zweimal - durch das Aufführen des Prozedur + namens - aufgerufen. + +2) Die Variable 'x' ist in der ersten Programmversion während des gesamten Ablauf + des Programms vorhanden, d.h. ihr Speicherplatz ist während dieser Zeit belegt. + Solche Datenobjekte nennt man statische Datenobjekte oder auch (aus Gründen, + die erst etwas später offensichtlich werden) Paket-Objekte. Das Datenobjekt 'x' + der rechten Version dagegen ist nur während der Bearbeitung der Prozedur vor + handen, sein Speicherplatz wird danach freigegeben. Solche Datenobjekte, die nur + kurzfristig Speicher belegen, werden dynamische Datenobjekte genannt. + + Prozeduren sind also ein Mittel, um die Speicherbelegung zu beeinflussen. + +3) Da Refinements keinen eigenen Datenbereich haben, kann die Variable 'x' in der + ersten Programmversion - obwohl sie in einem Refinement deklariert wurde - + von jeder Stelle des Programms angesprochen werden. Solche Datenobjekte + werden globale Datenobjekte genannt. Das Datenobjekt 'x' der Prozedur dagegen + kann nur innerhalb der Prozedur angesprochen werden, es ist also ein lokales + Datenobjekt der Prozedur. Innerhalb der Prozedur dürfen globale Datenobjekte + (also Objekte, die außerhalb von Prozeduren deklariert wurden) auch angespro + chen werden. + + Eine Prozedur in ELAN bildet im Gegensatz zu Refinements einen eigenen Gültig + keitsbereich hinsichtlich Datenobjekten und Refinements, die innerhalb der Pro + zedur deklariert werden. Prozeduren sind somit ein Mittel, um die in ihr dekla + rierten Datenobjekte hinsichtlich der Ansprechbarkeit nach Außen "abzuschotten". + + + +Prozeduren mit Parametern +Prozeduren mit Parametern erlauben es, gleiche Anweisungen mit unterschiedlichen +Datenobjekten auszuführen. + +Form: + + +#on("i")##on("b")#PROC#off("i")##off("b")# Prozedurname #on("i")##on("b")#(#off("i")##off("b")# formale Parameterliste #on("i")##on("b")#)#off("i")##off("b")# #on("i")##on("b")#:#off("i")##off("b")# + Prozedurrumpf +#on("i")##on("b")#END PROC#off("i")##off("b")# Prozedurnamen + + +Die Parameterliste besteht aus einem oder mehreren durch Kommata getrennten Para +metern. Ein Parameter wird mit Datentyp, Accessrecht und Namen angegeben. +Ähnlich wie bei der Datendeklaration braucht man für aufeinanderfolgende Parameter +mit gleichem Datentyp und gleichem Accessrecht die Attribute nur einmal anzugeben. +Parameter mit Accessrecht #on("i")##on("b")#CONST#off("i")##off("b")# sind Eingabeparameter, Parameter mit Access +recht #on("i")##on("b")#VAR#off("i")##off("b")# realisieren Ein-/Ausgabeparameter. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PROC vertausche (INT VAR a, b): + INT VAR x :: a; + a := b; + b := x + END PROC vertausche; + + INT VAR eins :: 1, + zwei :: 2, + drei :: 3; + vertausche (eins, zwei); + vertausche (zwei, drei); + vertausche (eins, zwei); + put (eins); put (zwei); put (drei) + +____________________________________________________________________________ + + +Die Datenobjekte 'a' und 'b' der Prozedur 'vertausche' werden formale Parameter +genannt. Sie stehen als Platzhalter für die bei einem Prozeduraufruf einzusetzenden +aktuellen Parameter (in obigen Beispiel die Datenobjekte 'eins', 'zwei' und 'drei'). + + + +Prozeduren als Parameter +Es ist auch möglich, Prozeduren als Parameter zu definieren. + +Eine Prozedur als Parameter wird folgendermaßen in der Parameterliste spezifiziert: + +Resultattyp #on("i")##on("b")#PROC#off("i")##off("b")# #on("i")##on("b")#(#off("i")##off("b")# virtuelle Parameterliste #on("i")##on("b")#)#off("i")##off("b")# Prozedurname + + +Die Angabe des Resultattyps entfällt, wenn es sich nicht um eine wertliefernde Proze +dur handelt. Die virtuelle Parameterliste inklusive der Klammern entfällt, falls die +Prozedur keine Parameter hat. Die virtuelle Parameterliste beschreibt die Parame +ter der Parameterprozedur. Es werden Datentyp und Zugriffsrecht eines jeden Para +meters angegeben, jedoch ohne Namen. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + PROC wertetabelle (REAL PROC (REAL CONST) funktion, + REAL CONST untergrenze, obergrenze, + schrittweite): + + REAL VAR wert; + putline ("W E R T E T A B E L L E"); + putline ("-----------------------"); + wert := untergrenze; + REPEAT + put (text (wert, 10, 5)); + put (text (funktion (wert), 10, 5)); + line; + wert INCR schrittweite + UNTIL wert > obergrenze PER + + END PROC wertetabelle; + + (* Prozeduraufruf: *) + wertetabelle (REAL PROC (REAL CONST) sin, 0.0, pi, 0.2) + +____________________________________________________________________________ + + +Wertliefernde Prozeduren +Eine wertliefernde Prozedur sieht folgendermaßen aus: + + +Resultattyp #on("i")##on("b")#PROC#off("i")##off("b")# Prozedurname #on("i")##on("b")#(#off("i")##off("b")# formale Parameterliste #on("i")##on("b")#)#off("i")##off("b")# #on("i")##on("b")#:#off("i")##off("b")# + wertliefernder Prozedurrumpf +#on("i")##on("b")#END PROC#off("i")##off("b")# Prozedurnamen + + + +Die Parameterliste inklusive Klammerung kann fehlen. Der Prozedurrumpf muß einen +Wert mit dem in Resultattyp angegeben Datentyp liefern. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT PROC max (INT CONST a, b): + IF a > b + THEN a + ELSE b + END IF + END PROC max; + + put (max (3, 4)) + +____________________________________________________________________________ + + +(In diesem Beispiel wird das Maximum von 'a' und 'b' ermittelt und ausgegeben) + +#page# + +2.4.3.3 Operatorvereinbarung + +Operatoren können in ELAN ähnlich wie Prozeduren definiert werden. Operatoren +müssen einen und können maximal zwei Operatoren besitzen (monadische und dyadi +sche Operatoren). + +Form: + + +Resultattyp #on("i")##on("b")#OP#off("i")##off("b")# Opname #on("i")##on("b")#(#off("i")##off("b")# ein oder zwei Parameter #on("i")##on("b")#)#off("i")##off("b")# #on("i")##on("b")#:#off("i")##off("b")# + Operatorrumpf +#on("i")##on("b")#END OP#off("i")##off("b")# Opname + + +Der Resultattyp wird nur bei wertliefernden Operatoren angegeben. + +Als Operatornamen sind erlaubt: + +- ein Sonderzeichen, sofern es nicht als Trennzeichen benutzt wird: + ! $ % & ' * + - / < = > ? § ^ ' ~ +- eine Kombination von zwei Sonderzeichen. Diese Kombination muß jedoch bereits + in ELAN existieren: + := <= >= <> ** +- ein Schlüsselwort (siehe 2.2.1). + + + +Vereinbarung eines monadischen Operators +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT OP SIGN (REAL CONST argument): + IF argument < 0.0 THEN -1 + ELIF argument = 0.0 THEN 0 + ELSE 1 + FI + END OP SIGN + +____________________________________________________________________________ + + +(Der Operator 'SIGN' liefert abhängig vom Vorzeichen des übergebenen Wertes den +INT-Wert -1, 0 oder 1) + + + +Vereinbarung eines dyadischen Operators +____________________________________________________________________________ + ........................... Beispiel: ......................... + TEXT OP * (INT CONST anzahl, TEXT CONST t): + INT VAR zaehler :: anzahl; + TEXT VAR ergebnis :: ""; + WHILE zaehler > 0 REP + ergebnis := ergebnis + t; + zaehler := zaehler - 1 + END REP; + ergebnis + END OP *; + +____________________________________________________________________________ + + +(Der Operator '*' verkettet 'anzahl'- mal den Text 't') + + + +2.4.3.4 Paketvereinbarung + +Pakete sind in ELAN eine Zusammenfassung von Datenobjekten, Prozeduren, Opera +toren und Datentypen. Diese bilden den Paketrumpf. Elemente eines Pakets (Prozedu +ren, Operatoren, Datentypen) können außerhalb des Pakets nur angesprochen werden, +wenn sie in der Schnittstelle des Pakets, die auch "interface" genannt wird, aufge +führt werden. Mit anderen Worten: es können alle Elemente eines Pakets von außen +nicht angesprochen werden, sofern sie nicht über die Schnittstelle "nach außen ge +reicht" werden. Pakete können separat übersetzt werden, so daß der "Zusammen +bau" eines umfangreichen Programms aus mehreren Paketen möglich ist. + +Der formale Aufbau eines Pakets sieht folgendermaßen aus: + + +#on("i")##on("b")#PACKET#off("i")##off("b")# Paketname #on("i")##on("b")#DEFINES#off("i")##off("b")# Schnittstelle #on("i")##on("b")#:#off("i")##off("b")# + Paketrumpf +#on("i")##on("b")#END PACKET#off("i")##off("b")# Paketname + + +In der Schnittstelle werden Prozeduren und Operatoren nur mit ihrem Namen, durch +Kommata getrennt, angegeben. Weiterhin können Datentypen und mit CONST verein +barte Datenobjekte in der Schnittstelle aufgeführt werden, aber keine VAR-Datenob +jekte, weil diese sonst über Paket-Grenzen hinweg verändert werden könnten. + +Im Gegensatz zu einer Prozedur kann ein PACKET nicht aufgerufen werden (nur die +Elemente der Schnittstelle können benutzt werden). + +Pakete werden zu folgenden Zwecken eingesetzt: + +- Spracherweiterung +- Schutz vor fehlerhaftem Zugriff auf Datenobjekte +- Realisierung von abstrakten Datentypen. + + + +Spracherweiterung +____________________________________________________________________________ + ........................... Beispiel: ......................... + PACKET fuer eine prozedur DEFINES swap: + + PROC swap (INT VAR a, b): + INT CONST x :: a; + b := a; + a := x + END PROC swap + + END PACKET fuer eine prozedur + +____________________________________________________________________________ + + +Dies ist ein Paket, das eine Tausch-Prozedur für INT-Datenobjekte bereitstellt. Das +PACKET kann übersetzt und dem ELAN-Compiler bekannt gemacht werden +(EUMEL: "insertieren"). Ist das geschehen, kann man 'swap' wie alle anderen Proze +duren (z.B. 'put', 'get') in einem Programm verwenden. Tatsächlich werden die mei +sten Prozeduren und Operatoren (aber auch einige Datentypen), die in ELAN zur +Verfügung stehen, nicht durch den ELAN-Compiler realisiert, sondern durch solche +PACKETs. Um solche Objekte einigermaßen zu standardisieren, wurde in der +ELAN-Sprachbeschreibung festgelegt, welche Datentypen, Prozeduren und Operato +ren in jedem ELAN-System vorhanden sein müssen. Solche Pakete werden Stan +dard-Pakete genannt. Jeder Installation - aber auch jedem Benutzer - steht es +jedoch frei, zu den Standard-Paketen zusätzliche Pakete dem Compiler bekannzu +geben, und damit den ELAN-Sprachumfang zu erweitern. + + + +Schutz vor fehlerhaftem Zugriff auf Datenobjekte +____________________________________________________________________________ + ........................... Beispiel: ......................... + PACKET stack handling DEFINES push, pop, init stack: + + LET max = 1000; + ROW max INT VAR stack; (* siehe Kapitel Reihung, 2.6.1. *) + INT VAR stack pointer; + + PROC init stack: + stack pointer := 0 + END PROC init stack; + + PROC push (INT CONST dazu wert): + stack pointer INCR 1; + IF stack pointer > max + THEN errorstop ("stack overflow") + ELSE stack [stack pointer] := dazu wert + END IF + END PROC push; + + PROC pop (INT VAR von wert): + IF stack pointer = 0 + THEN errorstop ("stack empty") + ELSE von wert := stack [stack pointer]; + stack pointer DECR 1 + END IF + END PROC pop + + END PACKET stack handling; + +____________________________________________________________________________ + + +Dieses Packet realisiert einen Stack. Den Stack kann man über die Prozeduren 'init +stack', 'push' und 'pop' benutzen. +#page# +____________________________________________________________________________ + ........................... Beispiel: ......................... + init stack; + werte einlesen und pushen; + werte poppen und ausgeben. + + werte einlesen und pushen: + INT VAR anzahl :: 0, wert; + REP + get (wert); + push (wert); + anzahl INCR 1 + UNTIL ende kriterium END REP. + + werte poppen und ausgeben: + INT VAR i; + FOR i FROM 1 UPTO anzahl REP + pop (wert); + put (wert) + END REP. + +____________________________________________________________________________ + + +Die Datenobjekte 'stack' und 'stack pointer' haben nur Gültigkeit innerhalb des +PACKETs 'stack handling'. + +Anweisungen wie z.B. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + put (stack [3]); + stack [27] := 5 + +____________________________________________________________________________ + + + +außerhalb des PACKETs 'stack handling' sind also verboten und werden vom +ELAN-Compiler entdeckt. + +Ein PACKET bietet also auch einen gewissen Schutz vor fehlerhafter Verwendung von +Programmen und Datenobjekten. Wichtig ist weiterhin, daß die Realisierung des +Stacks ohne weiteres geändert werden kann, ohne daß Benutzerprogramme im 'main +packet' geändert werden müssen, sofern die Schnittstelle nicht verändert wird. Bei +spielsweise kann man sich entschließen, den Stack nicht durch eine Reihung, son +dern durch eine Struktur zu realisieren. Davon bleibt ein Benutzerprogramm unbe +rührt. + + + +Realisierung von abstrakten Datentypen +Der Vollständigkeit halber wird folgendes Beispiel hier gezeigt. Wie neue Datentypen +definiert werden, wird in Kapitel 2.7.1. erklärt. + +____________________________________________________________________________ + ........................... 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. + + + +2.4.4 Terminatoren für Refinements, + Prozeduren und Operatoren + + +Das LEAVE-Konstrukt wird verwendet, um eine benannte Anweisung (Refinement, +Prozedur oder Operator) vorzeitig zu verlassen. Es ist auch möglich, geschachtelte +Refinements zu verlassen. + +Form: + +#on("i")##on("b")#LEAVE#off("i")##off("b")# Name + + +Durch eine (optionale) WITH-Angabe kann auch eine wertliefernde benannte Anwei +sung verlassen werden. + +Form: + +#on("i")##on("b")#LEAVE#off("i")##off("b")# Name #on("i")##on("b")#WITH#off("i")##off("b")# Ausdruck + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT OP ** (INT CONST basis, exp): + IF exp = 0 + THEN LEAVE ** WITH 1 + ELIF exp < 0 + THEN LEAVE ** WITH 0 + FI; + + INT VAR zaehler, ergebnis; + ergebnis := basis; + FOR zaehler FROM 2 UPTO exp REP + ergebnis := ergebnis * basis + PER; + ergebnis + END OP ** + +____________________________________________________________________________ + + +(Diese Operation realisiert die Exponentiation für INT-Werte) + + + +2.4.5 Generizität von Prozeduren + und Operatoren + + +In ELAN ist es möglich, unterschiedlichen Prozeduren bzw. Operatoren gleiche +Namen zu geben. Solche Prozeduren (Operatoren) werden generische Prozeduren +(Operatoren) genannt. Die Identifizierung erfolgt durch Anzahl, Reihenfolge und Daten +typ der Parameter (Operanden). + +Deshalb werden Prozeduren und Operatoren unter Angabe des Prozedur- bzw. des +Operatorkopfes dokumentiert. + +Beispiele: + + +INT OP MOD (INT CONST l, r) +REAL OP MOD (REAL CONST l, r) + + +Der MOD-Operator liefert den Rest einer Division. Er ist sowohl für INT- wie auch +für REAL-Datenobjekte definiert. + + + +PROC put (INT CONST wert) +PROC put (REAL CONST wert) +PROC put (TEXT CONST wert) + + +Die put-Prozedur ist für INT-, REAL- und TEXT-Datenobjekte definiert. + + + +Priorität von generischen Operatoren +Bei der Neudefinition von Operatoren kann man bereits benutzte Sonderzeichen oder +Schlüsselwörter benutzen. In diesem Fall bekommt der neudefinierte Operator die +gleiche Priorität wie der bereits vorhandene Operator. + + + +2.4.6 Rekursive Prozeduren + und Operatoren + + +Alle Prozeduren und Operatoren dürfen in ELAN rekursiv sein. + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT PROC fakultaet (INT CONST n): + IF n > 0 + THEN fakultaet (n-1) * n + ELSE 1 + END IF + END PROC fakultaet + +____________________________________________________________________________ + + +Die Fakultätsfunktion ist kein gutes Beispiel für eine Rekursion, denn das Programm +kann leicht in eine iterative Version umgewandelt werden: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT PROC fakultaet (INT CONST n): + INT VAR prod :: 1, i; + FOR i FROM 2 UPTO n REP + prod := prod * i + END REP; + prod + END PROC fakultaet + +____________________________________________________________________________ + + +Die Umwandlung von einem rekursiven Programm in ein iteratives ist übrigens immer +möglich, jedoch oft nicht so einfach, wie in dem Beispiel der Ackermann-Funktion: + +____________________________________________________________________________ + ........................... Beispiel: ......................... + INT PROC acker (INT CONST m, n): + IF m = 0 + THEN n + 1 + ELIF n = 0 + THEN acker (m-1, 0) + ELSE acker (m - 1, acker (m, n - 1)) + ENDIF + END PROC acker + +____________________________________________________________________________ + + +Das eigentliche Einsatzgebiet von rekursiven Algorithmen liegt aber bei den 'back +track'-Verfahren. Diese werden eingesetzt, wenn eine exakte algorithmische Lösung +nicht bekannt ist oder nicht gefunden werden kann und man verschiedene Versuche +machen muß, um zu einem Ziel (oder Lösung) zu gelangen. + diff --git a/doc/programmer-manual/1.8.7/doc/programmierhandbuch.2b b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.2b new file mode 100644 index 0000000..c2103ba --- /dev/null +++ b/doc/programmer-manual/1.8.7/doc/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. + + <Deklarationen> ; + <Anweisungen> + +____________________________________________________________________________ + ........................... 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. + + <Deklarationen> ; + <Refinement-Aufrufe und/oder Anweisungen> . + <Refinements> + + 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: + + <Deklarationen> ; + <Prozeduren> ; + <Anweisungen> + + 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: + + <Deklarationen> ; + <Prozeduren> ; + <Anweisungen> . + <Refinements> + + 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 +____________________________________________________________________________ + diff --git a/doc/programmer-manual/1.8.7/doc/programmierhandbuch.3 b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.3 new file mode 100644 index 0000000..eade335 --- /dev/null +++ b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.3 @@ -0,0 +1,728 @@ +#headandbottom("1","EUMEL-Benutzerhandbuch","TEIL 3 : Editor","3")# +#pagenr("%",1)##setcount##block##pageblock# +#headeven# +#center#EUMEL-Benutzerhandbuch +#center#____________________________________________________________ + +#end# +#headodd# +#center#TEIL 3 : Editor +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +3 - % #right#GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #right#3 - % +#end# + +TEIL 3: Der Editor + +Mit dem #ib#EUMEL-Editor#ie# steht für den Teil der Programmierung, der aus der Eingabe +von Programmtext besteht, dasselbe komfortable Werkzeug zur Verfügung, wie für die +Textverarbeitung. Merkmale des EUMEL-Editors sind die einfache Fenstertechnik +und die übersichtliche Bedienung durch wenige Funktionstasten. + +Eine mit dem Editor erzeugte Textdatei ist maximal 4075 Zeilen lang, die maximale +Breite einer Zeile beträgt 16000 Zeichen. + + + +3.1 Ein- und Ausschalten des Editors + +Der Editor wird eingeschaltet durch Eingabe von: + +____________________________________________________________________________ + gib kommando : + #ib#edit#ie# ("dateiname") + +____________________________________________________________________________ + + +Falls eine Datei unter dem eingegebenen Namen existiert, wird ein Fenster auf dieser +Datei an der Stelle geöffnet, an der zuletzt ein Zugriff auf diese Datei stattfand. + +Existiert noch keine Datei unter dem angegebenen Namen in der Task, folgt eine +Anfrage, ob eine Datei unter dem eingegebenen Namen neu eingerichtet werden soll: + +____________________________________________________________________________ + gib kommando : + edit("dateiname") + "dateiname" neu einrichten (j/n) ? + +____________________________________________________________________________ + + +Die Abfrage dient der Kontrolle der Schreibweise. Man kann ggf. das Einrichten der +Datei ablehnen, den Dateinamen verbessern und das Kommando erneut geben. + +Bei korrekter Schreibweise bejahen Sie die Kontrollfrage#u# 1)#e#mit + +#center#<j> <J> <y> oder <Y> + + +Es erscheint ein leerer Editorbildschirm. Die oberste Zeile des Bildschirms ist die +#ib#Titelzeile#ie#. In ihr kann nicht geschrieben werden. Sie zeigt jedoch verschiedene nütz +liche Dinge an: den Namen der Datei, die Nummer der aktuellen Zeile, in der gerade +geschrieben wird, Tabulatormarken, Einfügemodus, Lernmodus usw. + +____________________________________________________________________________ + #mark on# ............... dateiname ....................#mark off# Zeile 1 #mark on# #mark off# + _ + +____________________________________________________________________________ + + + +Wollen Sie die #ib#Schreibarbeit beenden#ie# und den #ib#Editor ausschalten#ie#, so drücken Sie die +beiden Tasten + +<ESC> <q> + +nacheinander. Sie haben damit den #ib#Editor verlassen#ie# und befinden sich wieder auf +Monitor-Ebene. +#page# + +3.2 Die Funktionstasten + +Die Funktionstasten realisieren diejenigen Fähigkeiten des Editor, die über die reine +Zeicheneingabe hinausgehen. Wo die Tasten auf Ihrem Gerät liegen, hängt von dem +jeweiligen Gerätetyp ab. Die Wirkung der Tasten ist im Weiteren erläutert. + +#l pos (0.0)##l pos(4.0)# +#table# +#free(0.5)# +#taste1(" SHIFT ")# Umschalttaste +#tableend# +#free(0.5)# +<v> <^> <>> <<> Positionierungstasten +#table# +#free(0.5)# +<CR> Eingabe-/ Absatztaste +#free(0.5)# +<ESC> Kommandotaste +#free(0.5)# +<HOP> Verstärkertaste +#free(0.5)# +<TAB> Tabulatortaste +#free(0.5)# +<MARK> Markiertaste +#free(0.5)# +<RUBOUT> Löschtaste +#free(0.5)# +<RUBIN> Einfügetaste +#free(0.5)# +<SV> Supervisortaste +#free(0.5)# +<STOP> Stoptaste +#free(0.5)# +<WEITER> Weitertaste +#tableend##clear pos# +#free(0.5)# +Es kann sein, daß Tasten nicht richtig beschriftet sind. Die Installations-anleitung +muß dann die Entsprechungen beschreiben. Natürlich können sich weitere Funktions +tasten außer den im folgenden beschriebenen auf Ihrer Tastatur befinden. Diese +haben standardmäßig jedoch keine besondere Bedeutung für den Editor. + +#page# + +3.3 Die Wirkung der Funktionstasten + +<SHIFT> + +#ib#Umschalttaste#ie# + +Wird diese Taste gleichzeitig mit einer anderen betätigt, so wird ein Buchstabe in +Großschreibung, bei den übrigen Tasten das obere Zeichen, ausgegeben. So wird z.B. +anstelle der "9" das Zeichen ")" ausgegeben. +#free(0.5)# +<>> <<> + +<v> <^> + +Positionierungstasten + +#ib#Positionierung des Cursors#ie# um eine Spalten-/Zeilenposition in die jeweilige Richtung. +#free(0.5)# +<CR> + +#ib#Eingabetaste / Absatztaste#ie#, Carriage Return, kurz: 'CR' + +Diese Taste schließt die aktuelle Zeile explizit ab und es wird an den Beginn der +nächsten Zeile positioniert. Einrückungen werden beibehalten. + +Der EUMEL-Editor ist auf automatischen Wortumbruch voreingestellt, d.h. ein Wort, +das über das 77. Zeichen der aktuellen Zeile herausreichen würde, wird automatisch +in die nächste Zeile gerückt (siehe 'word wrap' 4.2.5). Die Absatztaste wird also +benötigt, um explizite Zeilenwechsel und Einrückungen bei der Textformatierung zu +erhalten. Eine Absatzmarke wird durch ein 'blank' hinter dem letzten Zeichen der +Zeile erzeugt und ist im Editor an der Inversmarkierung am rechten Bildschirmrand zu +erkennen. + +Im EUMEL-System werden Kommandos auf einer Kommandozeile, auf der alle +Editorfunktionen zur Verfügung stehen, eingegeben. Auf dieser Ebene beendet die +Taste also ausdrücklich die Kommandoeingabe, das gegebene Kommando wird an +schließend analysiert und ausgeführt. + +<HOP> + +"#ib#Verstärkertaste#ie#"; wird als Vorschalttaste bedient. + +In Kombination mit anderen Funktionstasten wird deren Wirkung verstärkt. + + +<HOP> <v> + +Steht der Cursor nicht am unteren Bildrand, so wird er dorthin positioniert. Steht er +am unteren Bildrand, so wird um einen Bildschirminhalt "weitergeblättert". + +Entsprechend werden auch die Tasten : <^> <>> <<> mit der HOP-Taste verstärkt. + +#page# +<HOP> <RUBIN> + +#ib#Einfügen von Textpassagen#ie#. Die HOP-Taste in Verbindung mit RUBIN und RUBOUT +wird zum 'verstärkten' Löschen und Einfügen verwendet. + +Ab der aktuellen Position des Cursors 'verschwindet' der restliche Text. Es kann wie +bei der anfänglichen Texteingabe fortgefahren werden. Die Anzeige '#ib#REST#ie#' in der +Titelzeile erinnert daran, daß noch ein Resttext existiert. Dieser erscheint nach einem +neuerlichen Betätigen der beiden Tasten HOP RUBIN wieder auf dem Bildschirm (die +Anzeige 'REST' verschwindet dann wieder). + +____________________________________________________________________________ + ................ dateiname ..................... Zeile 4 + In diesem Text soll vor dem zweiten Satz + etwas eingefügt werden. Hierzu wird der + Cursor an die Position geführt, an der + ein beliebiger Text eingefügt werden soll.#absatz# + +____________________________________________________________________________ + + +Nach Betätigen der Taste #on("i")##on("b")#HOP#off("i")##off("b")# und #on("i")##on("b")#RUBIN#off("i")##off("b")#sieht der Bildschirm wie folgt aus: + +____________________________________________________________________________ + .............. dateiname ........REST.......... Zeile 4 + In diesem Text soll vor dem zweiten Satz + etwas eingefügt werden. + + +____________________________________________________________________________ + + + +Nun kann beliebig viel Text eingefügt werden. Nochmaliges Betätigen von HOP und +RUBIN führt den Text-Rest wieder bündig heran. + +#page# +<HOP> <RUBOUT> + +Löscht die Zeile ab Cursor-Position bis Zeilenende. + +____________________________________________________________________________ + ................ dateiname ..................... Zeile 4 + Soll eine ganze Zeile oder ein Textrest + gelöscht werden, so positioniert man an die + Stelle, ab der gelöscht werden soll. Rest löschen.... + Nach HOP RUBOUT ist der Zeilenrest gelöscht.#absatz# + +____________________________________________________________________________ + + + +Nach Betätigen der Tasten #on("i")##on("b")#HOP#off("i")##off("b")# und #on("i")##on("b")#RUBOUT#off("i")##off("b")# sieht der Bildschirm wie folgt aus. + +____________________________________________________________________________ + ............... dateiname .................... Zeile 4 + Soll eine ganze Zeile oder ein Textrest + gelöscht werden, so positioniert man an die + Stelle, ab der gelöscht werden soll. + Nach HOP RUBOUT ist der Zeilenrest gelöscht.#absatz# + +____________________________________________________________________________ + + + +Steht der Cursor am Zeilenanfang, wird nach HOP RUBOUT dementsprechend die +ganze Zeile gelöscht und die Lücke durch Nachrücken der Folgezeilen geschlossen +(HOP RUBOUT betätigen). +#page# +<TAB> + +#ib#Tabulatortaste#ie# + +Mit der Tabulatortaste werden die eingestellten Tabulatorpositionen angesprungen. +Jeder Tastendruck läßt den Cursor auf die nächste eingestellte Tabulatorposition +springen. + +#on("i")#Voreingestellte#off("i")# Tabulatorpositionen sind die beiden Schreibgrenzen, Textanfang in der +Zeile und Ende der Zeile. + +Weitere Tabulatorpositionen können durch Positionierung auf die gewünschte Spalte +und #on("i")##on("b")#HOP#off("i")##off("b")# #on("i")##on("b")#TAB#off("i")##off("b")# gesetzt werden. Sie können gelöscht werden, indem sie mit #on("i")##on("b")#TAB#off("i")##off("b")# +angesprungen und mit #on("i")##on("b")#HOP#off("i")##off("b")# #on("i")##on("b")#TAB#off("i")##off("b")# +ausgeschaltet werden. + +Die gesamte eingestellte Tabulalation kann durch #on("i")##on("b")#ESC#off("i")##off("b")# #on("i")##on("b")#TAB#off("i")##off("b")# ein-/ und ausge +schaltet werden. + +Die eingestellten Tabulatorpositionen erkennen Sie an den Tabulatorzeichen (Dachzei +chen) in der obersten Bildschirmzeile. +#page# +<MARK> + +#ib#Ein- bzw. Ausschalten der Markierung#ie#. + +Bei Betätigung dieser Taste wird in einen speziellen #ib#Markierzustand#ie# geschaltet. Alles, +was Sie jetzt schreiben bzw. durch Bewegen des Cursors in Richtung Dateiende +kennzeichnen, steht als #on("i")#markierter#off("i")# Bereich für die Bearbeitung zur Verfügung. Zur +besseren Sichtbarkeit wird der markierte Bereich invers zum übrigen Text dargestellt. + +Wird der Cursor in eine Richtung bewegt, wird das gesamte Textstück zwischen +Einschaltpunkt der Markierung und aktueller Cursorposition markiert. Rückwärtsbewe +gungen des Cursors verkürzen den markierten Bereich wieder. + +Durch erneutes Betätigen der MARK-Taste schalten Sie den Markier-Zustand +wieder aus. + +Mit weiteren Kommandos kann der Bereich nun bearbeitet werden: + +<ESC> <d> Markierten Abschnitt in 'Scratch'-Datei kopieren. + +<ESC> <p> Markierten Abschnitt herauskopieren. + +<ESC> <RUBOUT> Markierten Abschnitt löschen. + + +Der mit #on("i")##on("b")#ESC#off("i")##off("b")# #on("i")##on("b")#p#off("i")##off("b")# oder#on("i")##on("b")#d#off("i")##off("b")# kopierte Bereich kann beliebig oft in derselben oder einer +anderen Datei ein/angefügt werden. + +Der mit #on("i")##on("b")#ESC#off("i")##off("b")# #on("i")##on("b")#RUBOUT#off("i")##off("b")# gelöschte Abschnitt kann genau einmal durch #on("i")##on("b")#ESC#off("i")##off("b")# #on("i")##on("b")#RUBOUT#off("i")##off("b")# +an anderer Stelle derselben Datei eingefügt werden. + +(vgl. ESC-Taste, Operationen auf Markierungen, 3-#topage("ESC")#) +#page# +<RUBIN> + +#ib#Ein- bzw. Ausschalten des Einfügemodus.#ie# + +Das Betätigen der Taste schaltet in den Einfügemodus. Der Zustand wird durch das +Wort "RUBIN" im linken Drittel der Titelzeile der Datei angezeigt. Vor dem Zeichen, +auf dem der Cursor steht, wird eingefügt. Nochmaliges Betätigen der Taste schaltet +den Einfügemodus aus. +#free(1.0)# +<RUBOUT> + +#ib#Löschtaste#ie# + +Das Zeichen, auf dem der Cursor steht, wird gelöscht. Wenn der Cursor, wie bei +fortlaufender Eingabe üblich, hinter dem letzten Zeichen einer Zeile steht, wird das +letzte Zeichen gelöscht. + +#page# + +3.4 ESC Kommandos + +<ESC> + +#ib#Kommandotaste#ie# + +Mit der ESC-Taste in Kombination mit einer Folgetaste werden vordefinierte Aktionen +ausgelöst. Es gibt Aktionen, die vorprogrammiert zur Verfügung stehen, und Sie selbst +können weitere hinzufügen. + +Der Kommandodialog wird eingeschaltet durch: + +<ESC> <ESC> + + +____________________________________________________________________________ + ............... Beispiel ..................... Zeile 4 + + gib kommando: + +____________________________________________________________________________ + + +Der Kommandodialog ermöglicht die Eingabe von beliebigen Kommandos ohne den +Editor verlassen zu müssen. Insbesondere Such- und Kopieroperationen stellen auch +für den Programmierer nützliches Werkzeug dar (siehe 3.5). + +Auf der Kommandozeile kann jedes Kommando gegeben werden. Die Kommandozeile +kann wie eine normale Textzeile editiert werden. Nach #on("i")##on("b")#CR#off("i")##off("b")# verschwindet die Kom +mandozeile und das Kommando wird ausgeführt. + +Falls ein Fehler auftritt erfolgt eine entsprechende Fehlermeldung in der Kopfzeile und +die Kommandozeile erscheint erneut. + +Um ein weiteres Editor-Fenster zu 'öffnen', betätigt man im Editor + +<ESC> <e> + +Betätigt man ESC e ungefähr in der Mitte des Bildschirms, hat man das Fenster auf +die neue Datei in der unteren Hälfte des Bildschirms und die 'alte' Datei in der +oberen Bildschirmhälfte. Zunächst wird der Dateiname erfragt. Nach dessen Eingabe +und #on("i")##on("b")#CR#off("i")##off("b")# wird ein Fenster auf eröffnet. Die obere linke Ecke des Fensters befindet +sich an der aktuellen Cursor-Position. Dabei darf sich der Cursor nicht zu sehr am +rechten oder unteren Rand befinden, weil das Fenster sonst zu klein würde. In diesem +'Fenster' kann man dann genauso arbeiten wie im 'normalen' Editor. + +Mit der Tastenfolge + +<ESC> <w> + +wechselt man von einem Fenster (zyklisch) in das benachbarte. Es gibt eine Hier +archie zwischen den Fenstern in der Reihenfolge, in der eines im anderen einge +richtet worden ist. Gibt man + +<ESC> <q> + +in einem Fenster, so verschwindet dieses und alle darin eingeschachtelten Fenster, +und man befindet sich im übergeordneten Fenster. + +Durch + +<ESC> <p> oder <ESC> <d> + +schreibt man einen markierten Teil in eine 'Scratch'-Datei (nicht editierbarer +Zwischenspeicher); durch ESC p wird ein markierter Text aus der Ursprungsdatei +entfernt und in die 'Scratch'-Datei geschrieben. Im Gegensatz dazu wird er durch +ESC d kopiert. Durch + +<ESC> <g> + +fügt man ihn in eine andere (oder dieselbe) Datei ein. Im Unterschied zu ESC RUBIN +wird die temporäre Datei dadurch nicht entleert. + +Die für ESC p, bzw. ESC d benutzte #ib#'Scratch'-Datei#ie#, die nicht editierbar ist, ist nicht +mit dem sogenannten Notizbuch zu verwechseln. Das Notizbuch ist eine Datei, in der +alle Editorfunktionen benutzt werden können, auf die jedoch ohne Angabe eines +Dateinamens durch + +<ESC> <n> + +ab der aktuellen Cursorposition ein Fenster eröffnet wird. Das Notizbuch nimmt +insbesondere Fehlermeldungen und Meldungen bei der Übersetzung von Programmen +auf. + +<ESC> <v> + +erlaubt vom äußeren Fenster aus alle eingeschachtelten Fenster zu verlassen. +#page# + +Vorbelegte Tasten + +#ib#ESC q#ie# Verlassen des Editors bzw. der eingeschachtelten Fenster. + +#ib#ESC e#ie# Weiteres Editorfenster einschalten. + +#ib#ESC n#ie# Notizbuch 'anzeigen'. + +#ib#ESC v#ie# Dateifenster auf ganzen Bildschirm vergrößern + bzw. Bildschirm rekonstruieren (eingeschachteltes Fenster verlas + sen). + +#ib#ESC w#ie# Dateiwechsel beim Fenstereditor. + +#ib#ESC f#ie# Nochmalige Ausführung des letzten Kommandos. + +#ib#ESC b#ie# Das Fenster wird auf den linken Rand der aktuellen (ggf. verscho + benen) Zeile gesetzt. + +ESC > Zum nächsten Wortanfang. + +ESC < Zum vorherigen Wortanfang. + +#ib#ESC 1#ie# Zum Anfang der Datei. + +#ib#ESC 9#ie# Zum Ende der Datei. +#page# + +Operationen auf Markierungen + + +#goalpage("ESC")# +#ib#ESC RUBOUT#ie# Markiertes "vorsichtig" löschen. + +#ib#ESC RUBIN#ie# Mit ESC RUBOUT vorsichtig Gelöschtes einfügen. + +#ib#ESC p#ie# Markiertes löschen und in die Notiz-Datei schreiben. Kann mit ESC + g an anderer Stelle reproduziert werden. + +#ib#ESC d#ie# Duplizieren: + Markiertes in die Notiz-Datei kopieren, anschließend die + Markierung abschalten. Kann mit ESC g beliebig oft reproduziert + werden. + +#ib#ESC g#ie# Mit ESC p gelöschten oder mit ESC d duplizierten Text an aktuelle + Cursor-Stelle schreiben, d.h. Notiz-Datei an aktueller Stelle einfü + gen. +#page# + +Zeichen schreiben +Diese Tasten sind standardmäßig so vorbelegt wie hier aufgeführt, sie können aber +von Benutzern und in Anwenderprogrammen geändert werden. + +#ib#ESC a#ie# Schreibt ein ä. +#ib#ESC A#ie# Schreibt ein Ä. +#ib#ESC o#ie# Schreibt ein ö. +#ib#ESC O#ie# Schreibt ein Ö. +#ib#ESC u#ie# Schreibt ein ü. +#ib#ESC U#ie# Schreibt ein Ü. +#ib#ESC s#ie# Schreibt ein ß. +#ib#ESC (#ie# Schreibt eine [. +#ib#ESC )#ie# Schreibt eine ]. +#ib#ESC <#ie# Schreibt eine {. +#ib#ESC >#ie# Schreibt eine }. +#ib#ESC \##ie# Schreibt ein \#, das auch gedruckt werden kann. +#ib#ESC #ie# Schreibt einen (geschützten) Trennstrich, siehe Textverarbeitung. +#ib#ESC k#ie# Schreibt ein (geschütztes) "k", siehe Textverarbeitung. +#ib#ESC blank#ie# Schreibt ein (geschütztes) Leerzeichen, siehe Textverarbeitung. +#free(0.7)# + +Kommando auf Taste legen + +#ib#ESC ESC#ie# Kommandodialog einschalten + +#ib#ESC ! taste#ie# Im Kommandodialog: + Geschriebenes Kommando auf Taste legen. + +#ib#ESC ? taste#ie# Im Kommandodialog: + Auf 'taste' gelegtes Kommando zum Editieren anzeigen. + +#ib#ESC k#ie# Im Kommandodialog: + Das zuletzt editierte Kommando (einzeilige ELAN-Programm) + anzeigen. + + +Der Lernmodus +Der Lernmodus ermöglicht beliebige Tastensequenzen zu speichern und auf eine +Taste 't' zu legen. Durch #on("i")##on("b")#ESC#off("i")##off("b")# #on("i")##on("b")#t#off("i")##off("b")# wird die gesamte Sequenz ausgeführt. + +Nicht belegt werden können die vom System vorbelegten Tasten (3-14). + +Beispielsweise könnte es für einen Programmierer sinnvoll sein die Tastenfolge +'THEN' 'CR' '>' '>' '>' '>' auf die Taste #on("i")##on("b")#T#off("i")##off("b")# zu legen. Durch #on("i")##on("b")#ESC#off("i")##off("b")# #on("i")##on("b")#T#off("i")##off("b")# wird 'THEN' in +die aktuelle Zeile geschrieben und der Cursor mit passender Einrückung in die +Einrückung in die Folgezeile gesetzt. + + +#ib#ESC HOP#ie# #ib#Lernen einschalten#ie#. + +#ib#ESC HOP taste#ie# #ib#Lernen ausschalten#ie# und Lernsequenz auf 'taste'legen. + +#ib#ESC HOP HOP#ie# #ib#Gelerntes vergessen#ie#. Bedingung ist, daß man die Lernsequenz in + der Task löscht, in der man sie hat lernen lassen. + + +#on("b")# +#center#A C H T U N G : +Der Lernmodus bleibt eingeschaltet, auch wenn der Editor beendet wird. Dann werden +die folgenden Monitor-Kommandos usw. usf. 'gelernt'. Durch unsinniges 'Lernen' +lassen sich schlimmstenfalls beliebige Verwüstungen anrichten. + +Der Lernmodus wird in der Editor-Kopfzeile angezeigt. Falls der Editor beendet wird, +ohne den Lernmodus auszuschalten, erfolgt eine Warnung auf Monitor-Ebene. + +Um den Lernmodus zu beenden drücken Sie: + +<ESC> <HOP> <HOP> + +Dadurch wird der Lernmodus ausgeschaltet und nichts gelernt, die Gefahr ist gebannt.#off("b")# + +#page# +<SV> + +#ib#SUPERVISOR-Taste#ie# + +Betätigen Sie diese Taste im Editor, dann unterbrechen Sie Ihre Editierarbeit und +erhalten die Meldung + +____________________________________________________________________________ + + Terminal 2 + + + EUMEL Version 1.8/M + + + gib supervisor kommando: + + + + + ESC ? --> help + ESC b --> begin("") ESC h --> halt + ESC c --> continue("") ESC s --> storage info + ESC q --> break ESC t --> task info + +____________________________________________________________________________ + + + +Wollen Sie nun im Editor fortfahren bzw. haben Sie irrtümlich die SV-Taste betätigt, +dann geben Sie das Kommando + +____________________________________________________________________________ + + gib supervisor kommmando : + continue ("meine task") + +____________________________________________________________________________ + + + +(falls Ihre Task, in der Sie arbeiteten, wirklich "meine task" hieß!) + +Um Ihren in Bearbeitung befindlichen Text wieder vollständig auf dem Bildschirm zu +sehen, betätigen die die Tasten + +<ESC> <b> + +Sie sind wieder an der Stelle, an der Sie den Text mit der SV-Taste verlassen ha +ben, und können normal weiterarbeiten. + +#on("u")#Achtung:#off("u")# Die SV-Taste kann, je nach Terminal, durch das Betätigen von zwei +Tasten gleichzeitig realisiert sein (oft 'CTRL b'). Beachten Sie die Beschreibung Ihrer +Tastatur! + + + +#on("b")# +Für die Programmierung ist die Tastenfolge <SV> <ESC> <h> von Bedeutung, da hier +durch der Fehler 'halt vom Terminal' erzeugt wird. Dadurch können unerwünscht +laufende Programme abgebrochen werden. +#off("b")# +#page# +<STOP> + +#ib#Unterbrechen einer Ausgabe#ie# (oft auch als CTRL a realisiert). + +Haben Sie diese Taste aus Versehen betätigt, erkennen Sie dies daran, daß der +Editor nicht "reagiert". Betätigen Sie die WEITER-Taste (oft auch CTRL c). +#free(1.0)# +<WEITER> + +Unterbrochene Ausgabe fortsetzen. + +Ein mit der STOP-Taste angehaltene Ausgabe können Sie durch Betätigen der +#ib#WEITER-Taste#ie# fortsetzen. + + +#on("u")#VORSICHT:#off("u")# Die STOP-Taste unterbricht nur die Ausgabe auf den Bildschirm. Zei + chen, die während des STOP eingegeben werden, werden gespeichert + und nach 'WEITER' ausgegeben! + + +#page# + +3.5 Positionieren, Suchen, Ersetzen + im Kommandodialog + + +Um das Editorfenster auf eine bestimmte Zeile zu positionieren wird einfach diese +Zeilennummer angegeben. + +____________________________________________________________________________ + ............... Beispiel ..................... Zeile 4 + + gib kommando: 123 + +____________________________________________________________________________ + + + +Falls die Zeilenzahl der Datei geringer als die angegebene Zeilennummer ist, wird auf +die letzte Zeile positioniert. + + +Um das Editorfenster auf ein bestimmtes Textstück zu positionieren, wird der gesuch +te Text, ggf. mit Suchrichtung angegeben. + +____________________________________________________________________________ + ............... Beispiel ..................... Zeile 4 + + gib kommando: "END PROC" + +____________________________________________________________________________ + + +Die Suchrichtung kann durch 'D' (down) oder 'U' (up) zusätzlich spezifiziert werden. + +____________________________________________________________________________ + ............... Beispiel ..................... Zeile 4 + + gib kommando: U "INT VAR schleifenzaehler" + +____________________________________________________________________________ + + + +Um beliebige Texte durch andere zu ersetzen, dienen die Operatoren 'C' (change) +bzw. 'CA' (change all). + +Bei Ausführung dieses Kommandos wird zunächst nach #on("u")#unten#off("u")# in der editierten Datei +nach dem zu ersetzenden Text gesucht. Wenn der Text gefunden wird, wird er durch +den hinter dem Operator stehenden Text ersetzt. + +____________________________________________________________________________ + ............... Beispiel ..................... Zeile 4 + + gib kommando: "lb" C "lange bezeichnung" + +____________________________________________________________________________ + + + +Bei Anwendung von 'CA' wird jedes Auftreten des gesuchten Textes ab der +Cursorposition durch den Ersatztext ersetzt, bis das Dateiende errreicht ist. + +Weitere Erklärungen zum Suchen und Ersetzen in 5.5. +#page# + +Weitere Hilfen + + +Textabschnitt an anderer Stelle der Datei einsetzen: + +- Abschnitt markieren und mit #on("i")##on("b")#ESC#off("i")##off("b")# #on("i")##on("b")#d#off("i")##off("b")# zwischenspeichern. + +- Zweites Editorfenster auf die Datei mit #on("i")##on("b")#ESC#off("i")##off("b")# #on("i")##on("b")#e#off("i")##off("b")# öffnen. + +- Nach #on("i")##on("b")#ESC#off("i")##off("b")# #on("i")##on("b")#ESC#off("i")##off("b")# Zeilennummer oder Suchbegriff angeben und mit #on("i")##on("b")#ESC#off("i")##off("b")# #on("i")##on("b")#g#off("i")##off("b")# Abschnitt an der gewünschte Stelle einsetzen. + + + +Textabschnitt schnell herauskopieren und sichern: + +- Gewünschten Abschnitt markieren + +- #on("i")##on("b")#ESC#off("i")##off("b")# #on("i")##on("b")#ESC#off("i")##off("b")# PUT("dateiname") #on("i")##on("b")#CR#off("i")##off("b")# + Der Abschnitt wird in die Datei 'dateiname' geschrieben. Falls die Frage 'dateina + me' löschen (j/n) verneint wird, wird der Abschnitt, an das Ende der Datei angefügt. + Dadurch können Textabschnitte schnell gesammelt werden. + + +Komplette Datei in die editierte Datei einfügen: + +- #on("i")##on("b")#ESC#off("i")##off("b")# #on("i")##on("b")#ESC#off("i")##off("b")# GET("dateiname") #on("i")##on("b")#CR#off("i")##off("b")# + Der komplette Inhalt von 'dateiname' wird an die aktuelle Position geschrieben. + + +Breitere Zeile erzeugen: + +- #on("i")##on("b")#ESC#off("i")##off("b")# #on("i")##on("b")#ESC#off("i")##off("b")# limit(123) #on("i")##on("b")#CR#off("i")##off("b")# + Die Zeilenbreite wird auf 123 Zeichen geändert. Der maximal zulässige Wert ist + 16000. Dieser Wert bezieht sich auf den Zeilenumbruch. Bei Zeilenbreite > 77 wird + nur die aktuelle Zeile verschoben. Um für den ganzen Bildschirm die rechte Seite + der Datei zu sehen, kann die linken Spalte des Bildschirmfenster neu gesetzt wer + den: + + #on("i")##on("b")#ESC#off("i")##off("b")# #on("i")##on("b")#ESC#off("i")##off("b")# margin(60) #on("i")##on("b")#CR#off("i")##off("b")# + + Die Normaleinstellung wird durch 'limit(77)' und 'margin(1)' wiederhergestellt. + diff --git a/doc/programmer-manual/1.8.7/doc/programmierhandbuch.4 b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.4 new file mode 100644 index 0000000..650d945 --- /dev/null +++ b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.4 @@ -0,0 +1,1692 @@ +#headandbottom("1","EUMEL-Benutzerhandbuch","TEIL 4 : Kommandosprache","4")# +#pagenr("%",1)##setcount(1)##block##pageblock# +#headeven# +#center#EUMEL-Benutzerhandbuch +#center#____________________________________________________________ + +#end# +#headodd# +#center#TEIL 4 : Kommandosprache +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +4 - % #right#GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #right#4 - % +#end# +TEIL 4: Kommandosprache + +In Teil 4 sind diejenigen Kommandos beschrieben, die erfahrungsgemäß eher der +Handhabung der Arbeitsumgebung zuzurechnen sind. Es ist den Verfassern bewußt, +daß Auswahl und Zusammenstellung recht willkürlich sind, weil eine klare Abgrenzung +zum Teil 5, welcher die Kommandos, die dem Thema: 'Programmierung' zugeordnet +werden, nicht möglich ist. + +Der Teil 4 ist in die Themen: + +- 4.1. Supervisor-Kommandos + +- 4.2.1 Hilfs- und Informationsprozeduren + +- 4.2.2 Thesaurus + +- 4.2.3 Tasks + +- 4.2.4 Handhabung von Dateien + +- 4.2.5 Editor + +- 4.2.6 Dateitransfer + +- 4.2.7 Passwortschutz + +- 4.2.8 Archiv + +gegliedert. Insbesondere zu 4.2.4 ist anzumerken, daß nur Kommandos, die ganze +Dateien betreffen hier erläutert sind. Kommandos, die Dateiinhalte betreffen (Suchen, +Ersetzen etc.) sind in 3.5, bzw. 5.3 beschrieben. +#page# + +4.1 Supervisor + +Es gibt genau sieben vom Supervisor akzeptierte Kommandos. Diese Kommandos +können gegeben werden wenn nach dem Einschalten des Geräts oder dem Abkoppeln +einer Task die SV-Taste gedrückt wurde und die sogenannte EUMEL-Tapete +erscheint. + +____________________________________________________________________________ + + Terminal 2 + + + EUMEL Version 1.8.1/M + + + gib supervisor kommando: + + + + + ESC ? --> help + ESC b --> begin("") ESC h --> halt + ESC c --> continue("") ESC s --> storage info + ESC q --> break ESC t --> task info + +____________________________________________________________________________ + + + + +Desweiteren kann <SV> in einer Task gedrückt werden, um durch <ESC> <h> einen +Programmabbruch einzuleiten. + +Im Gegensatz zu den im weiteren beschriebenen, durch ELAN Prozeduren realisierten +Kommandos, sind diese Supervisor-Kommandos nicht als Prozeduren im System und +mithin nicht durch 'help (...)' anzeigbar. +#page# +'begin' + #on("b")#PROC begin (TEXT CONST taskname) #off("b")# + Richtet eine neue Task als Sohn von PUBLIC ein. + + + #on("b")#PROC begin (TEXT CONST taskname, vatertask) #off("b")# + Richtet eine neue Task als Sohn der Task 'vatertask' ein, falls die Vater-Task + eine Manager-Task ist. Falls diese Task keinen Managerstatus besitzt, passiert + nichts! In diesem Falle muß das Kommando durch <SV> abgebrochen werden. + + + FEHLER : "taskname" existiert bereits + "vatertask" gibt es nicht + + + + +'continue' + #on("b")#PROC continue (TEXT CONST taskname) #off("b")# + Eine existierende Task wird an das Terminal des Benutzers angekoppelt. + + FEHLER : "taskname" gibt es nicht + + + Falls 'begin' oder 'continue' trotz korrekter Voraussetzungen kein Resultat zeigen, + 'hängt' die betroffene Task. Beim 'begin' Kommando kann das der Fall sein, falls + die Vater-Task nicht durch 'break' abgekoppelt wurde, sondern mit < SV > verlas + sen wurde. In diesem Fall muß das Kommando durch <SV> abgebrochen werden, + die Vater-Task angekoppelt und mit <ESC> <q> korrekt abgekoppelt werden. +#page# +'break' + #on("b")#PROC break #off("b")# + Das Terminal wird vom Rechner abgekoppelt. + + + +'halt' + #on("b")#PROC halt #off("b")# + Das laufende Programm der dem Terminal aktuell zugeordneten Task wird abge + brochen. + + Falls in der an das Terminal gekoppelten Task ein laufendes Programm abgebro + chen werden soll, muß zunächst durch <SV> der Supervisor aufgerufen werden. + Durch das Supervisor-Kommando 'halt' wird der Fehler 'halt from terminal' + induziert. Das Programm wird wie durch jeden anderen Fehler abgebrochen, falls + nicht 'disable stop' gesetzt wurde! + + + +#page# +'storage info' + #on("b")#PROC storage info #off("b")# + Informationsprozedur über den belegten und den verfügbaren Hintergrund-Spei + cher des gesamten Systems in KByte#u#1)#e#. + +#foot# + + 1) Bei der derzeit aktuellen '+' Version EUMEL 1.8.1/M+ sind die beiden Anga + ben mit 4 zu multiplizieren ! +#end# + Das Terminal wird unmittelbar abgekoppelt! + + + +'task info' + #on("b")#PROC task info #off("b")# + Informiert über alle Tasknamen im System unter gleichzeitiger Angabe der Vater/ + Sohn-Beziehungen durch Einrückungen. + + + + +'help' + #on("b")#PROC help #off("b")# + Kurzbeschreibung der SV-Kommandos. +#page# + +4.2 Monitor + +Unter dem Stichwort Monitor-Kommandos sind an dieser Stelle Kommandos be +schrieben, die ständig zur Handhabung der Arbeitsumgebung benutzt werden. +Gleichwohl sei sofort darauf hingewiesen, daß jedes ELAN Programm dem Monitor zur +Ausführung übergeben werden kann. Es gibt also keine speziellen Monitor- +Kommandos, sondern nur eine Reihe von Prozeduren (=Kommandos), die in dieser +Umgebung erfahrungsgemäß besonders häufig benutzt werden. + + +#on("u")#4.2.1 Hilfs- und Informationsprozeduren#off("u")# + +- Pakete, Prozeduren : packets, bulletin , help + Parameter + +- Tasksystem zeigen : task info , task status + +- Speicherplatz zeigen : storage , storage info + + +#on("u")#4.2.2 Thesaurus #off("u")# + +- besondere Thesauri : ALL , all , SOME , remainder + +- Verknüpfung : + , - , / + + +#on("u")#4.2.3 Taskoperationen#off("u")# + +- besondere Tasknamen : archive , brother , father , myself + printer , public , son , supervisor +- Terminal abkoppeln : break +- Task löschen : end +- Manager-Task : global manager , free global manager +- Umbenennen der Task : rename myself + +#page# +#on("u")#4.2.4 Handhabung von Dateien #off("u")# + + : copy , edit , forget , list , rename , show + + +#on("u")#4.2.5 Editor #off("u")# + +- Editieren : edit , editget , show +- Tastenbelegung : kommando auf taste (legen) , + lernsequenz auf taste (legen) , + std tastenbelegung , + taste enthält kommando , + word wrap + + +#on("u")#4.2.6 Transfer #off("u")# + +- Datei holen : fetch , fetchall +- Datei senden : save , saveall +- Drucken : print +- Datei löschen : erase + + +#on("u")#4.2.7 Passwortschutz #off("u")# + +- 'begin' absichern : begin password +- 'continue' absichern : task password +- Dateien absichern : enter password +- Systemzweig sichern : family password + + +#on("u")#4.2.8 Das Archiv #off("u")# + +- Reservieren/freigeben : archive , release +- Formatieren : format +- Löschen : clear +- Kontrollesen : check + + +#page# + +4.2.1 Hilfsprozeduren + +Die drei Prozeduren listen ihre Ausgabe jeweils in eine temporäre Datei, die mit +'show' (s. 4.2.5) gezeigt wird. + + +'packets' + #on("b")#PROC packets #off("b")# + Auflisten der Namen aller insertierten Pakete in der Task. + + + + + + +'bulletin' + #on("b")#PROC bulletin (TEXT CONST paket name) #off("b")# + Listen aller in der DEFINES-Liste des Pakets mit dem Namen "paket name" + enthaltenen Prozeduren. + + FEHLER : ... ist kein Paketname + + + #on("b")#PROC bulletin #off("b")# + Es wird eine Liste aller bisher insertierten Objekte erstellt. Diese Liste ist paket + weise sortiert. 'bulletin' zeigt also eine Liste #on("u")#aller#off("u")# Prozeduren an, die in der Task + benutzt werden können. +#page# +'help' + #on("b")#PROC help (TEXT CONST name) #off("b")# + Listen aller Prozeduren / Operatoren mit dem Namen "name". Der Name des + Packets in dessen Schnittstelle die Prozedur steht wird mit ausgegeben. + + Falls es kein Objekt des erfragten Namens gibt, erfolgt die Ausgabe: + + unbekannt "name". + + Beispiel: +____________________________________________________________________________ + + gib kommando : + help("save") + +____________________________________________________________________________ + + + liefert: + +____________________________________________________________________________ + +PACKET nameset: + + save........... (THESAURUS CONST, TASK CONST) + save........... (THESAURUS CONST) + +PACKET globalmanager: + + save........... (DATASPACE CONST, TEXT CONST, TASK CONST) + save........... (TEXT CONST, TASK CONST) + save........... (TEXT CONST) + save........... + +____________________________________________________________________________ + + + + Desweiteren kann auch nach Prozedurnamen gesucht werden, die nur annähernd + bekannt sind, indem ein Suchmuster spezifiziert wird. Das Suchmuster besteht aus + dem bekannten Teil des Namens und dem Operator '*', der vor und/oder nach + dem Suchbegriff gesetzt werden kann. '*' bezeichnet eine beliebige (auch leere) + Zeichenkette. + + Beispiel: Gesucht werden die verschiedenen 'info' Prozeduren: + +____________________________________________________________________________ + gib kommando : + help("*info*") + +____________________________________________________________________________ + + + +____________________________________________________________________________ + + taskinfo....... (INT CONST, INT CONST) + taskinfo....... (INT CONST, FILE VAR) + taskinfo....... (INT CONST) + taskinfo....... + editinfo....... (FILE VAR, INT CONST) + editinfo....... (FILE CONST) --> INT + storageinfo.... + +____________________________________________________________________________ + + + + Dieser Stern darf nicht mit dem 'joker' des 'Pattern Matching' verwechselt werden. + In der 'help' Prozedur darf '*' #on("u")#nicht#off("u")# in den Suchbegriff eingesetzt werden, sondern + nur an Wortanfang und -Ende gesetzt werden. + + +#page# + +Informationsprozeduren + +'storage' + #on("b")#INT PROC storage (TASK CONST task) #off("b")# + Informationsprozedur über den logisch belegten Hintergrund-Speicher der Task. + (Angabe in KByte, bzw. 4KB Einheiten bei der '+'-Version) + + +____________________________________________________________________________ + + gib kommando : + put(storage(myself)) + 1234 + + gib kommando : + +____________________________________________________________________________ + + +'storage info' + #on("b")#PROC storage info #off("b")# + Informationsprozedur über den belegten und den verfügbaren Hintergrund-Spei + cher des gesamten Systems. Die Ausgabe erfolgt in KByte, bei der aktuellen + '+'-Version in 4 KByte Einheiten. + + +____________________________________________________________________________ + + gib kommando : + storage info + 1234K von 12000K + + gib kommando : +____________________________________________________________________________ +#page# + +'task info' + #on("b")#PROC task info #off("b")# + Informiert über alle Tasknamen im System unter gleichzeitiger Angabe der Vater/ + Sohn-Beziehungen (Angabe durch Einrückungen). + + + #on("b")#PROC task info (INT CONST art) #off("b")# + Informiert über alle Tasks im System. Mit 'art' kann man die Art der Zusatz- + Information auswählen. + + art=1: entspricht 'task info' ohne Parameter, d.h. es gibt nur die Tasknamen + unter Angabe der Vater/Sohn-Beziehungen aus. + + art=2: gibt die Tasknamen aus. Zusätzlich erhalten Sie Informationen über die + verbrauchte CPU-Zeit der Task, die Priorität, den Kanal, an dem die + Task angekoppelt ist, und den eigentlichen Taskstatus. Hierbei bedeuten: + + 0 -busy- Task ist aktiv. + 1 i/o Task wartet auf Beendigung des Outputs oder auf + Eingabe. + 2 wait Task wartet auf Sendung von einer anderen Task. + 4 busy-blocked Task ist rechenwillig, aber blockiert#u#1)#e#. + 5 i/o -blocked Task wartet auf I/O, ist aber blockiert. + 6 wait-blocked Task wartet auf Sendung, ist aber blockiert. Ach + tung: Die Task wird beim Eintreffen einer Sendung + automatisch entblockiert. + > 6 dead + + art=3: wie 2, aber zusätzlich wird der belegte Speicher angezeigt. (Achtung: + Prozedur ist zeitaufwendig!). + +#foot# + +1) Eine Blockierung kann von 'Scheduler' veranlaßt werden + (siehe Systemhandbuch) +#end# + +#page# +____________________________________________________________________________ + + gib kommando : + task info(2) + +____________________________________________________________________________ + + + + liefert: + +____________________________________________________________________________ + + ............................ ............................... + 15.05.87 10:39 CPU PRIO CHAN STATUS + SUPERVISOR.......................... 0000:19:47 0 - wait + -................................ 0000:07:54 0 - wait + SYSUR............................ 0000:34:02 0 - wait + shutup dialog................ 0000:05:26 0 - i/o + configurator................. 0000:04:17 0 - wait + OPERATOR..................... 0000:00:14 0 - i/o + ARCHIVE...................... 0000:10:33 0 31 wait + net.......................... 0006:41:56 0 - wait + net timer................ 0000:02:48 2 - i/o + net port................. 0000:40:23 0 7 wait + PRINTER...................... 0000:05:59 0 - wait + -........................ 0000:00:11 0 - wait + UR.................................. 0000:02:11 0 - wait + PUBLIC........................... 0002:02:03 0 - wait + task1........................ 0000:41:50 0 - -busy- + task2........................ 0000:03:10 0 - i/o + task3........................ 0000:57:28 0 1 -busy- + +____________________________________________________________________________ + + +#page# + + + #on("b")#PROC task info (INT CONST art, FILE VAR infodatei) #off("b")# + Wie oben, die Ausgabe wird jedoch in die Datei 'infodatei' geschrieben. + +____________________________________________________________________________ + + FILE VAR info := sequential file(output,"infodatei") ; + taskinfo(3, info); + +____________________________________________________________________________ + + + #on("b")#PROC task info ( INT CONST art, stationsnr) #off("b")# + Ermöglicht im Netzbetrieb 'task info' über die Station mit der Nummer 'stationsnr'. + +____________________________________________________________________________ + + gib kommando : + taskinfo(1,12) ; + +____________________________________________________________________________ +#page# +'task status' + + #on("b")#PROC task status #off("b")# + Informationsprozedur über den Zustand der eigenen Task. Informiert über + - Name der Task, Datum und Uhrzeit; + - verbrauchte CPU-Zeit; + - belegten Speicherplatz; + - Kanal, an den die Task angekoppelt ist; + - Zustand der Task (rechnend u.a.m.); + - Priorität. + + #on("b")#PROC task status (TASK CONST t) #off("b")# + Wie obige Prozedur, aber über die Task mit dem internen Tasknamen 't'. + + +____________________________________________________________________________ + + gib kommando : + task status (public) + + 15.05.87 10:30 TASK: PUBLIC + + Speicher: 1234K + CPU Zeit: 0011.12:23 + Zustand : wait, (Prio 0), Kanal - + +____________________________________________________________________________ +#page# + +4.2.2 Thesaurus + +Ein #ib#Thesaurus#ie# ist ein #ib#Namensverzeichnis#ie#, das bis zu 200 Namen beinhalten kann. +Dabei muß jeder Namen mindestens ein Zeichen und darf höchstens 100 Zeichen +lang sein. Steuerzeichen (code < 32) in Namen werden umgesetzt (siehe 2.9.2). + +Thesauri werden unter anderem von der Dateiverwaltung benutzt, um das Dateiver +zeichnis einer Task zu führen. + +Man kann einen Thesaurus selbst erstellen, indem eine Datei z.B. mit Namen von +Dateien gefüllt wird. Diese Datei kann dann als Thesaurus für weitere Aktionen die +nen. + + + +- Thesaurus liefern : ALL , all , SOME , remainder +- Auswählen : LIKE +- Verknüpfen : + , - , / + + + +#on("b")#ACHTUNG#off("b")# : Bei der Verwendung von Thesaurus Operationen in Verbindung mit +'fetch', 'save' etc. ist zu beachten, daß mit 'SOME', 'ALL' und 'all' zunächst nur eine +Auswahl aus einer Liste getroffen wird. Zusätzlich muß das Ziel oder die Quelle des +Dateitransfers vereinbart werden. + +Ein beliebter Fehler ist z.B.: 'fetch (ALL archive)'. + +Hier ist nicht weiter spezifiziert, von wo Dateien geholt werden sollen - also werden +sie von 'father' geholt! (s. 4.2.5) + +Falls die Dateien vom Archiv geholt werden sollen, ist das Archiv als Quelle zu be +nennen: + +Also : 'fetch (ALL archive, archive)' = Hole alle Dateien, die in dem Thesaurus von + 'archive' sind von der Task 'archive'. +#page# +'ALL' + THESAURUS OP ALL (TASK CONST task) + Liefert einen Thesaurus, der alle Dateinamen der angegebenen Task enthält. + + + + #on("b")#THESAURUS OP ALL (TEXT CONST dateiname) #off("b")# + Liefert einen Thesaurus, der die in der angegebenen Datei vorhandenen Namen + (jede Zeile ein Name) enthält. + + + + +'all' + #on("b")#THESAURUS PROC all #off("b")# + Liefert einen Thesaurus, der alle Dateinamen der eigenen Task enthält. Entspricht + 'ALL myself'. + + + + +'SOME' + #on("b")#THESAURUS OP SOME (THESAURUS CONST thesaurus) #off("b")# + Bietet den angegebenen Thesaurus zum editieren an. Dort können nicht erwünsch + te Namen gestrichen werden. + + + + #on("b")#THESAURUS OP SOME (TASK CONST task) #off("b")# + Aufruf von: SOME ALL task. + + + #on("b")#THESAURUS OP SOME (TEXT CONST dateiname) #off("b")# + Aufruf von: SOME ALL dateiname. + +#page# +'remainder' + #on("b")#PROC remainder #off("b")# + Liefert nach einem 'errorstop' die noch nicht bearbeiteten Dateien. + +____________________________________________________________________________ + + gib kommando : + save all (archive) + + '"....." kann nicht geschrieben werden (Archiv voll)' + +____________________________________________________________________________ + + + + Nachdem man eine neue Floppy ins Archivlaufwerk gelegt hat, kann man mit + + +____________________________________________________________________________ + gib kommando : + save (remainder, archive) + +____________________________________________________________________________ + + den Rest der Dateien auf die nächste Floppy sichern. +#page# +'LIKE' + #on("b")#THESAURUS OP LIKE (THESAURUS CONST thesaurus, TEXT CONST muster) #off("b")# + Alle im Thesaurus enthaltenen Dateien, die dem 'muster' entsprechen sind im + Ergebnisthesaurus enthalten. + + (Die Syntax von 'muster' ist bei der Beschreibung des Pattern-Matching (5.4) + beschrieben) + + +____________________________________________________________________________ + + gib kommando : + print (all LIKE "*.p") + +____________________________________________________________________________ + + + Alle Dateien, deren Name mit '.p' endet, werden gedruckt. + +#page# +'+' + #on("b")#THESAURUS OP + (THESAURUS CONST links, rechts) #off("b")# + Liefert die Vereinigungsmenge von 'links' und 'rechts'. + Achtung: Die Vereinigungsmenge enthält keine Namen mehrfach. + + #on("b")#THESAURUS OP + (THESAURUS CONST links, TEXT CONST rechts)#off("b")# + Fügt dem Thesaurus 'rechts' zu, wenn 'rechts' noch nicht im Thesaurus enthal + ten ist. + + + + +'-' + #on("b")#THESAURUS OP - (THESAURUS CONST links, rechts) #off("b")# + Liefert die Differenzmenge. Achtung: Die Differenzmenge enthält keine Namen + mehrfach. + + #on("b")#THESAURUS OP - (THESAURUS CONST links, TEXT CONST rechts)#off("b")# + Nimmt den Namen 'rechts' aus dem Thesaurus. + +____________________________________________________________________________ + + gib kommando : + fetch(ALL father - ALL myself) + +____________________________________________________________________________ + + +'/' + #on("b")#THESAURUS OP / (THESAURUS CONST links, rechts) #off("b")# + Liefert die Schnittmenge + Achtung: Die Schnittmenge enthält keine Namen mehrfach. + + +#page# + +4.2.3 Tasks + +Zur Identifizierung von Tasks dienen sogenannte 'interne Taskbezeichner'. Ein solcher +Taskbezeichner wird beim Einrichten einer neuen Task vergeben. Interne Taskbe +zeichner sind auch unter Berücksichtigung der Zeit eindeutig. + +Der Zugriff auf interne Taskbezeichner erfolgt über Prozeduren und Operatoren, die +auf Objekte des Datentyps TASK (siehe 2.9.1) angewandt werden. + +Zusätzlich zum internen Tasknamen, der nicht auszugeben ist, haben Tasks meistens +einen Namen#u#1) #e#. +#foot# + +1) Unbenannte Tasks haben den Pseudonamen "-". +#end# + +Aus Benutzersicht können benannte Tasks innerhalb eines Rechners vollständig und +eindeutig über ihren Namen identifiziert werden. + + +- Task liefern : / , task , niltask + +- Verwandtschaften : brother , father , myself , son + +- Ausgezeichnete Tasks : archive , printer , public , supervisor + +- Namen liefern : name + +- Tasknamen ändern : rename myself + +- Reservieren bes. Tasks : reserve + +#page# +'/' + #on("b")#TASK OP / (TEXT CONST taskname) #off("b")# + Liefert die Task des angegebenen Namens, falls sie existiert. Der eigene Katal + og wird automatisch aktualisiert + + (identisch mit der PROC task (TEXT CONST taskname). + + FEHLER : "taskname" gibt es nicht + + + #on("b")#TASK OP / (INT CONST station number, TEXT CONST name) #off("b")# + Liefert im Netzbetrieb die Task des angegebenen Namen von der Station mit der + angegebenen Nummer. + + + +'niltask' + #on("b")#TASK CONST niltask #off("b")# + Bezeichner für "keine Task". So liefern die Prozeduren 'son', 'brother' und 'father' + als Resultat 'niltask', wenn keine Sohn-, Bruder- oder Vatertask existiert. + + + +'task' + #on("b")#TASK PROC task (TEXT CONST taskname) #off("b")# + Liefert die Task des angegebenen Namens, falls sie existiert. Der eigene Katal + og wird automatisch aktualisiert. + + FEHLER : "taskname" gibt es nicht + + + #on("b")#TASK PROC task (INT CONST channel number) #off("b")# + Liefert den Namen der Task, die an dem angegebenen Kanal hängt. +#page# +'brother' + #on("b")#TASK PROC brother (TASK CONST task) #off("b")# + Liefert den nächsten Bruder von 'task'. Falls kein Bruder existiert, wird 'niltask' + geliefert. Aktualisiert den eigenen Katalog nicht automatisch! + + + +'father' + #on("b")#TASK PROC father #off("b")# + Liefert die eigene Vatertask. + + + #on("b")#TASK PROC father (TASK CONST task) #off("b")# + Liefert den Vater von 'task'. Existiert kein Vater (z.B. bei UR), wird niltask gelie + fert. Aktualisiert den eigenen Katalog nicht automatisch! + + + +'myself' + #on("b")#TASK PROC myself #off("b")# + Liefert eigenen Task-Bezeichner. + + + +'son' + #on("b")#TASK PROC son (TASK CONST task) #off("b")# + Liefert den ersten Sohn von 'task'. Falls keiner im Katalog vermerkt ist, wird + 'niltask' geliefert. Aktualisiert den eigenen Katalog nicht automatisch! + + +#page# +'archive' + #on("b")#TASK PROC archive #off("b")# + Liefert den internen Taskbezeichner der aktuellen Task mit Namen ARCHIVE. + Diese Prozedur dient zum schnellen und bequemen Ansprechen der Archivtask. + + + +'printer' + #on("b")#TASK PROC printer #off("b")# + Liefert den internen Taskbezeichner der aktuellen Task mit Namen #ib#PRINTER#ie#. + Diese Prozedur dient zum schnellen und bequemen Ansprechen des Druckspoo + lers. + + +'public' + #on("b")#TASK PROC public #off("b")# + Liefert den internen Taskbezeichner der Task #ib#PUBLIC#ie#. + + + + +'supervisor' + #on("b")#TASK PROC supervisor #off("b")# + Liefert den internen Taskbezeichner des Supervisors. + + +#page# +'name' + #on("b")#TEXT PROC name (TASK CONST task) #off("b")# + Liefert den Namen von 'task'. Die Task muß noch im System existieren, sonst ist + der Name nicht mehr bekannt. Falls die 'task' noch nicht im eigenen Katalog + enthalten ist, wird er aktualisiert. + + + +'rename myself' + #on("b")#PROC rename myself (TEXT CONST neuer name) #off("b")# + Name der eigenen Task wird in 'neuer name' geändert. Wirkt wie Löschung und + Wiedereinrichten der Task in Bezug auf alle TASK VAR's die sich auf diese Task + beziehen. + + FEHLER : Task existiert bereits + Name unzulässig + => anderen Namen wählen + + + +'reserve' + #on("b")#PROC reserve (TASK CONST task) #off("b")# + Reservieren einer Task für den ausschließlichen Dialog mit der Task, in der das + Kommando gegeben wurde. + + #on("b")#PROC reserve (TEXT CONST message, TASK CONST task) #off("b")# + Wie 'reserve (TASK CONST task)' mit Übergabe einer 'message'. + + + Die reservierte Task muß ein spezieller Manager, (z.B. /"DOS" aus dem Werkzeug + MS-DOS-DAT) sein ! +#page# + +4.2.4 Handhabung von Dateien + +'copy' + #on("b")#PROC copy (TEXT CONST quelle, ziel) #off("b")# + Kopiert die Datei 'quelle' in eine neue Datei mit dem Namen 'ziel' in der Benut + zer-Task. + + FEHLER : "ziel" existiert bereits + "quelle" gibt es nicht + zu viele Dateien + + + +'forget' + #on("b")#PROC forget (TEXT CONST dateiname) #off("b")# + Löschen einer Datei mit dem Namen 'dateiname' in der Benutzer-Task. + + FEHLER : "datei" gibt es nicht + + + #on("b")#PROC forget (THESAURUS CONST thesaurus) #off("b")# + Löscht die im 'thesaurus' enthaltenen Dateien in der Benutzer-Task. + + Im Dialog erfolgt vor dem Löschen einer Datei standardmäßig die Abfrage: + + +____________________________________________________________________________ + + gib kommando : + forget("einedatei") + "einedatei" löschen(j/n) ? + +____________________________________________________________________________ + +#page# +'list' + #on("b")#PROC list #off("b")# + Listet alle Dateien der Benutzer-Task mit Namen und Datum des letzten Zugriffs + auf dem Terminal auf. + + + #on("b")#PROC list (TASK CONST task) #off("b")# + Listet alle Dateien der angegebenen 'task' mit Namen und Datum der letzten + Änderung auf dem Terminal auf. Die Task muß Manager sein. + + + #on("b")#PROC list (FILE VAR liste) #off("b")# + Listet alle Dateinamen in die Datei 'liste', die mit 'output'(s. 5.3.5) assoziiert sein + muß. + + + #on("b")#PROC list (FILE VAR liste, TASK CONST manager) #off("b")# + Listet alle Dateien der Task 'manager' mit Namen und Datum der letzten Ände + rung in die Datei 'liste'. + + +____________________________________________________________________________ + + gib kommando : + FILE VAR f:= sequential file (output,"list");list(f,archive) + +____________________________________________________________________________ + +#page# +'rename' + #on("b")#PROC rename (TEXT CONST altername, neuername) #off("b")# + Umbenennen einer Datei von 'altername' in 'neuername'. + + + + FEHLER : "neuername" gibt es bereits + "altername" gibt es nicht +#page# + +4.2.5 Editor-Prozeduren + +'edit' + #on("b")#PROC edit (TEXT CONST dateiname) #off("b")# + Ruft den Editor mit 'dateiname' auf. + + + #on("b")#PROC edit #off("b")# + a) Im Monitor: + Ruft den Editor mit den zuletzt verwandten Dateinamen auf. + + b) Im Editor: + Der Dateiname wird erfragt. + + Für jedes 'edit' gilt: + Wurde 'edit' zum ersten Mal aufgerufen, nimmt das Fenster den gesamten Bild + schirm ein. Bei erneutem 'edit'-Aufruf wird ein Fenster nach rechts unten ab der + aktuellen Cursor-Position eröffnet. + + + #on("b")#PROC edit (THESAURUS CONST t) #off("b")# + Editieren aller in dem Thesaurus 't' enthaltenen Dateien nacheinander. + + + Weitere 'edit-Prozeduren', die z.B. Variation der Fenstergröße etc. zulassen, sind + in 5.4.6 beschrieben. + +#page# +'editget' + #on("b")#PROC editget (TEXT VAR editsatz) #off("b")# + Ausgabe einer (Kommando)zeile, in der Editorfunktionen zur Verfügung + stehen siehe Teil 5.5.1.4. + + + +'show' + #on("b")#PROC show (TEXT CONST dateiname) #off("b")# + Die Datei wird am Bildschirm gezeigt. Positionierung und Suchen funktionieren wie + in 'edit', Aktionen die Änderungen in der Datei bewirken würden, werden nicht + angenommen. + + + + #on("b")#PROC show #off("b")# + 'show' auf der zuletzt bearbeiteten Datei. + +#page# +'kommando auf taste legen' + #on("b")#PROC kommando auf taste legen (TEXT CONST taste, elan programm)#off("b")# + Die Taste 'taste' wird mit dem angegebenen ELAN-Programm belegt. Durch <ESC> + <taste> wird das Programm direkt ausgeführt. + +____________________________________________________________________________ + + gib kommando : + kommando auf taste legen ("a","fetch (SOME archive,archive)") + +____________________________________________________________________________ + + + +'kommando auf taste' + #on("b")#TEXT PROC kommando auf taste (TEXT CONST taste)#off("b")# + Falls 'taste' mit einem ELAN-Programm belegt ist, liefert die Prozedur den + Programmtext, andernfalls den leeren Text niltext. + +____________________________________________________________________________ + + gib kommando : + put (kommando auf taste("f")) + +____________________________________________________________________________ + + + +'taste enthaelt kommando' + #on("b")#BOOL PROC taste enthaelt kommando (TEXT CONST taste)#off("b")# + Liefert TRUE falls 'taste' mit einem ELAN-Programm belegt ist. + + +'lernsequenz auf taste legen' + #on("b")#PROC lernsequenz auf taste legen (TEXT CONST taste, sequenz)#off("b")# + 'taste' wird mit der Zeichenfolge 'sequenz' belegt. Durch <ESC> <taste> wird die + Zeichenfolge an der aktuellen Position ausgegeben. + + Als Zeichenfolge sind natürlich auch einzelne Zeichen und EUMEL-Codes zuläs + sig. + + Die vom System vorbelegten Tasten sind in 3.4 'Zeichen schreiben' aufgelistet. + +____________________________________________________________________________ + + gib kommando : + lernsequenz auf taste legen ("x","gib kommando :"13""2""2"") + +____________________________________________________________________________ + + + +'lernsequenz auf taste' + #on("b")#TEXT PROC lernsequenz auf taste (TEXT CONST taste) #off("b")# + Liefert die auf 'taste' gelegte Zeichenfolge. + + +'std tastenbelegung' + #on("b")#PROC std tastenbelegung #off("b")# + Die Standard-Tastenbelegung (s.3.4) wird (wieder) hergestellt. + + +'word wrap' + #on("b")#PROC word wrap (BOOL CONST b) #off("b")# + Der automatische Zeilenumbruch wird durch 'word wrap (FALSE)' aus- und durch + 'word wrap (TRUE)' eingeschaltet. Wird diese Prozedur während des Editierens + aufgerufen, gilt die Einstellung für die aktuelle Textdatei. Wird die Prozedur als + Monitor-Kommando gegeben, so gilt die Eingabe als Voreinstellung für neue + Dateien. +#page# + +4.2.6 Dateitransfer + +Unter diesem Abschnitt sind diejenigen Prozeduren beschrieben, die der simplen +Kommunikation mit Manager-Tasks dienen: Holen oder Senden einer Dateikopie, +Löschen in der Manager-Task. + +#on("b")#ACHTUNG : Für alle Prozeduren gilt: falls die Manager-Task nicht existiert, wird eine +Fehlermeldung erzeugt, existiert eine Task des angegebenen Namens, die aber nicht +Managertask ist, so terminieren die Prozeduren nicht! +#off("b")# + + +'fetch' + #on("b")#PROC fetch (TEXT CONST dateiname, TASK CONST manager) #off("b")# + Kopiert die Datei 'dateiname' aus der Task 'manager' + + + #on("b")#PROC fetch (THESAURUS CONST th, TASK CONST manager) #off("b")# + Kopiert alle Dateien, deren Namen im Thesaurus th enthalten sind, aus der Task + 'manager'. + + +____________________________________________________________________________ + + gib kommando : + fetch(ALL(12/"PUBLIC"), 12/"PUBLIC") + +____________________________________________________________________________ + + + + Mit diesem Kommando werden (in einem EUMEL Netz) alle Dateien der Task + 'PUBLIC' des Rechners mit der Stationsnummer 12 in diesem Netz kopiert. + +#page# +____________________________________________________________________________ + + gib kommando : + fetch(SOME archive , archive) + +____________________________________________________________________________ + + + + Bietet den Thesaurus von 'ARCHIVE' an, nach Auswahl werden alle Dateien deren + Namen nicht gelöscht wurden, von der Diskette kopiert. + + + #on("b")#PROC fetch (TEXT CONST dateiname) #off("b")# + Kopiert die Datei 'dateiname' aus der Task 'father' + + + #on("b")#PROC fetch (THESAURUS CONST th) #off("b")# + Kopiert alle Dateien, deren Namen in 'th' sind aus der Task 'father'. + + + +'fetchall' + + #on("b")#PROC fetchall #off("b")# + entspricht: fetch (ALL father, father) + + + #on("b")#PROC fetchall (TASK CONST manager)#off("b")# + entspricht: fetch(ALL manager, manager) + +#page# +'save' + #on("b")#PROC save (TEXT CONST dateiname, TASK CONST manager) #off("b")# + Kopiert die Datei 'dateiname' in die Task 'manager' + + + #on("b")#PROC save (THESAURUS CONST th, TASK CONST manager) #off("b")# + Kopiert alle Dateien, deren Namen im Thesaurus th enthalten sind, in die Task + 'manager'. + +____________________________________________________________________________ + + gib kommando : + save(all, (12/"PUBLIC")) + +____________________________________________________________________________ + + + Mit diesem Kommando werden (in einem EUMEL Netz) alle Dateien der eigenen + Task in die Task 'PUBLIC' des Rechners mit der Stationsnummer 12 in diesem + Netz kopiert. + +____________________________________________________________________________ + + gib kommando : + save(SOME myself, manager) + +____________________________________________________________________________ + + + Bietet den eigenen Thesaurus an, nach Auswahl werden alle Dateien deren + Namen nicht gelöscht wurden, zur Task 'manager' kopiert. + + + #on("b")#PROC save (TEXT CONST dateiname) #off("b")# + Kopiert die Datei 'dateiname' in die Task 'father' + + + #on("b")#PROC save (THESAURUS CONST th) #off("b")# + Kopiert alle Dateien, deren Namen in 'th' enthalten sind, in die Task 'father'. + + + #on("b")#PROC save #off("b")# + Kopiert die zuletzt bearbeitete Datei in die Task 'father' + + + + +'saveall' + #on("b")#PROC saveall #off("b")# + entspricht: save (all, father) + + + #on("b")#PROC saveall (TASK CONST manager) #off("b")# + entspricht: save (ALL myself, manager) + +#page# +'erase' + #on("b")#PROC erase (TEXT CONST dateiname, TASK CONST manager) #off("b")# + Löscht die Datei 'dateiname' aus der Task 'manager' + + + #on("b")#PROC erase (THESAURUS CONST th, TASK CONST manager) #off("b")# + Löscht alle Dateien, deren Namen im Thesaurus th enthalten sind, aus der Task + 'manager'. + + + #on("b")#PROC erase (TEXT CONST dateiname) #off("b")# + Löscht die Datei 'dateiname' aus der Task 'father' + + + #on("b")#PROC erase (THESAURUS CONST th) #off("b")# + Löscht alle Dateien, deren Namen in 'th' sind, aus der Task 'father' + + + #on("b")#PROC erase #off("b")# + Löscht die zuletzt bearbeitete Datei aus der Task 'father' + + +#page# +'print' + Das Kommando 'print' beinhaltet den Auftrag an die Task 'PRINTER' die enthal + tene(n) Datei(en) auszudrucken. + + Voraussetzung ist natürlich, daß die Druckersoftware ordnungsgemäß benutzt + wurde, um 'PRINTER' einzurichten. Siehe dazu Systemhandbuch Teil 6. + + + #on("b")#PROC print (TEXT CONST dateiname) #off("b")# + Kopiert die Datei 'dateiname' in die Task 'PRINTER'. + + + #on("b")#PROC print (THESAURUS CONST th) #off("b")# + Kopiert alle Dateien, deren Namen im Thesaurus 'th' enthalten sind, in die Task + 'PRINTER'. + + + #on("b")#PROC print #off("b")# + Kopiert die zuletzt bearbeitete Datei in die Task 'PRINTER'. + + +#page# + +4.2.7 Passwortschutz + +Der Passwortschutz im EUMEL-System ist in verschiedener Ausprägung möglich. +Einfachste Möglichkeit ist der Schutz einer Task durch ein Passwort. Falls diese Task +nicht Manager ist, können alle Daten und Programme, die nur in dieser Task zur +Verfügung stehen, auch nur vom Besitzer der Task benutzt werden. + +Ähnlich kann auch von einer Manager-Task aus der gesamte Zweig unterhalb dieser +Task mit einem Passwort geschützt werden: beispielsweise kann es empfehlenswert +sein, den Systemzweig komplett zu schützen, indem in SYSUR ein entsprechendes +Passwort vereinbart wird. + +Ein Umgehen des Passwortschutzes bei Manager-Tasks (durch Einrichten einer +Sohn-Task und 'fetchall') wird durch ein 'begin password' verhindert. + +Auch einzelne Dateien lassen sich schützen, indem Lese/Schreibpasswörter für den +Dateitransfer vereinbart werden. + +Generell gilt für die Verwendung von Passworten: + +- Passworte, die zu naheliegend gewählt sind (Vorname des Lebenspartners o.ä.) + sind meistens sinnlos, falls wirklich Datenschutz bezweckt ist. + +- Passworte, die so raffiniert sind, daß sogar ihr Schöpfer sie vergißt, führen zu + 100%igem Datenverlust, da die betroffene Task oder Datei nur noch gelöscht + werden kann. + +- Die Vereinbarung von "-" als Passwort bewirkt, daß die entsprechende Aktion + nicht mehr durchgeführt werden kann. Wird z.B. '-' als 'task password' + eingegeben, so kann die Task nie wieder an ein Terminal gekoppelt werden. + +- Passwörter können geändert werden, indem das entsprechende Kommando noch + einmal mit dem neuen Passwort gegeben wird. + +#page# +'begin password' + + #on("b")#PROC begin password (TEXT CONST passwort) #off("b")# + + Auf Supervisor-Ebene wird vor Einrichten einer neuen Task als Sohn der Task in + der das 'begin password' gegeben wurde, dieses erfragt. + + Das Password vererbt sich auf die hinzukommenden Sohn-Tasks. + +____________________________________________________________________________ + + #on("b")#SYSUR#off("b")# + maintenance : + begin password ("alles dicht") + +____________________________________________________________________________ + + +bewirkt: + +____________________________________________________________________________ + + Terminal 2 + + + EUMEL Version 1.8.1/M + + + gib supervisor kommando: + begin ("sabotage","SYSUR") + Passwort: + + + ESC ? --> help + ESC b --> begin("") ESC h --> halt + ESC c --> continue("") ESC s --> storage info + ESC q --> break ESC t --> task info + + +____________________________________________________________________________ + + +#page# +'enter password' + #on("b")#PROC enter password (TEXT CONST datei, schreibpass, lesepass) + #off("b")# + Hiermit können ausgewählte Dateien einer Manager-Task geschützt werden. Die + angegebene Datei wird mit Schreib- und Lesepassword versehen. Die Pass + wörter werden in der eigenen Task nicht berücksichtigt. + + Bei einem lesenden Zugriff (fetch) von irgendeiner Task aus auf die entsprechende + Datei in der Manager-Task muß das Lesepasswort, bei schreibendem Zugriff + (save/erase) das Schreibpasswort vereinbart sein. + + +____________________________________________________________________________ + + maintenance : + enter password ("wichtige datei","sicher","heit") + +____________________________________________________________________________ + + + + + #on("b")#PROC enter password (TEXT CONST password) #off("b")# + Passwort für den Dateitransfer einstellen. Falls zwei verschiedene Passwörter für + Lesen und Schreiben vereinbart werden sollen, so sind sie als ein Text durch "/" + getrennt einzugeben. + +____________________________________________________________________________ + + gib kommando : + enter password ("sicher/heit") + + gib kommando : + save(SOME all) + +____________________________________________________________________________ +#page# +'family password' + #on("b")#PROC family password (TEXT CONST geheim) #off("b")# + Einstellen eines Passworts für den Zweig des Systems , der unterhalb der (Mana + ger) Task liegt, in der das 'family password' eingegeben wurde. Dabei erhalten + alle Tasks, die kein Password oder dasselbe wie diese Manager-Task haben, das + 'family password'. Tasks in dem Zweig, die ein eigenes anderes besitzen, behal + ten dieses. + +____________________________________________________________________________ + + PUBLIC + + Task1 "" + + Task2 family password("fingerweg") + Task21 geheim + Task22 "" + + Task3 "" + Task31 "" + +____________________________________________________________________________ + + + + +bewirkt: + +____________________________________________________________________________ + PUBLIC + + Task1 "" + + Task2 fingerweg + Task21 geheim + Task22 fingerweg + + Task3 "" + Task31 "" + +____________________________________________________________________________ + + +#page# + +'task password' + + #on("b")#PROC task password (TEXT CONST geheim) #off("b")# + Einstellen eines Passworts für die Task in der es gegeben wird. Ist eine Task mit + einem Passwort geschützt, so wird durch den Supervisor nach dem 'continue'- + Kommando das Passwort angefragt (Entsprechend dem 'begin password'). Nur + nach Eingabe des richtigen Passworts gelangt man in die gewünschte Task. Das + Passwort kann durch nochmaligen Aufruf von 'task password' geändert werden, + z.B. wenn es in regelmäßigen Abständen geändert werden muß, um personenbe + zogene Daten zu schützen. + +#page# + +4.2.8 Das Archiv + +Mit dem Terminus 'Archiv' wird beim EUMEL-System ein Diskettenlaufwerk bezeich +net, das nur Datensicherungsaufgaben dient. Falls ein Rechner eins von zwei vorhan +denen Diskettenlaufwerk als Arbeitsspeicher benutzt, so wird dieses als Hintergrund +bezeichnet. Falls Sie einen derartigen Rechner benutzen, können Sie der Installa +tionsanleitung entnehmen, welches Laufwerk welcher Aufgabe zugeordnet ist. + +Das #ib#Archiv#ie# übernimmt im EUMEL-System die Verwaltung der langfristigen Daten +haltung. Das Archiv sollen Sie benutzen, um: + +- Sicherungskopien wichtiger Dateien außerhalb des Rechners zu besitzen; + +- nicht benötigte Dateien außerhalb einer Task zu halten (Speicherplatzersparnis!); + +- Dateien auf andere Rechner zu übertragen. + +Das Archiv wird im EUMEL-System durch die Task 'ARCHIVE', die das Disketten +laufwerk des Rechners verwaltet, realisiert. + +- reservieren : archive + +- freigeben : release + +- löschen : clear , format + +- prüfen : check + +#page# +'archive' + #on("b")#PROC archive (TEXT CONST archivname) #off("b")# + Reservierung der Task ARCHIVE für den exklusiven Dialog mit der aufrufenden + Task. 'archivname' wird bei allen folgenden Archivoperationen mit dem der Disket + te zugewiesenen (und hoffentlich auf dem Aufkleber vermerkten) Namen abgegli + chen. + + + +'release' + #on("b")#PROC release (TASK CONST archive) #off("b")# + Nach diesem Kommando kann die Task 'ARCHIVE' mit ihren Leistungen von einer + anderen Task in Anspruch genommen werden. Falls dieses Kommando nicht + gegeben wird, aber seit 5 Minuten kein Dialog mit 'archive' stattfand, kann eine + andere Task durch die Anforderung 'archive("diskettenname")' das Archiv reser + vieren. Durch diese Maßnahme wird verhindert, daß ein vergeßlicher Benutzer bei + einem System mit mehreren Benutzern das Archiv blockiert. + +#page# + +'clear' + #on("b")#PROC clear (TASK CONST archive) #off("b")# + Löschen des Disketten-Inhaltsverzeichnisses und Zuweisung des in der Reservie + rung eingegebenen Namens. + +____________________________________________________________________________ + + gib kommando : + archive("name"); #ib#clear#ie# (archive) + +____________________________________________________________________________ + + + Durch die Ausführung des Kommandos erhält die eingelegte Diskette den in der + Reservierung angegebenen Namen. #on("b")#Das Inhaltsverzeichnis, das sich auf der + Diskette befindet, wird gelöscht. Damit sind die Daten, die sich eventuell auf + dieser Diskette befanden, nicht mehr auffindbar#off("b")#. Die Diskette entspricht einer neu + formatierten Diskette#u#1)#e#. + + Man kann also eine beschriebene Diskette nicht umbenennen, ohne die darauf + befindlichen Daten zu löschen. + + #foot# + + #u#1)#e# Das Kommando 'format' enthält implizit 'clear'. +#end# + + Eine Neuformatierung ist demnach bei Wiederverwendung der Diskette nicht + notwendig. + +#page# +'format' + #on("b")#PROC format (TASK CONST archive) #off("b")# + Formatieren einer Diskette. Vor der erstmaligen Benutzung einer Archivdiskette + muß diese formatiert, d.h. in Spuren und Sektoren für die Positionierung des + Schreib-/Lesekopfes des Diskettenlaufwerks eingeteilt werden, um überhaupt ein + Beschreiben der Diskette zu ermöglichen. Die Einteilung ist geräteabhängig, häufi + ge Formate sind: + + 40 Spuren zu je 9 Sektoren (360 K) + 80 Spuren zu je 9 Sektoren (720 K). + + Die #on("b")#Erst#off("b")#benutzung einer #ib#Archivdiskette#ie# erfordert nach der Reservierung des Ar + chivs das Kommando: + +____________________________________________________________________________ + + gib kommando : + archive("diskname"); + + gib kommando : + format (archive); + +____________________________________________________________________________ + + +Erst nach einer Kontrollabfrage: + +____________________________________________________________________________ + + gib kommando: + format (archive) + + Archiv "diskname" formatieren ? (j/n) + +____________________________________________________________________________ + + + + wird tatsächlich formatiert und die Diskette steht mit dem Namen "diskname" für + Archivoperationen zur Verfügung. + +#page# + + #on("b")#PROC format (INT CONST code, TASK CONST archive) #off("b")# + Bei einigen Rechnern ist es möglich, die Formatierung zu variieren. Falls beim + Formatieren auf einem solchen Rechner ein anderes als das Standardformat + erzeugt werden soll, so ist die Codierung des gewünschten Formats mitanzuge + ben. + + + Beispiel: Für ein Gerät mit 5,25 Zoll Disketten wäre z.B. einstellbar: + code 0 : Standardformat + code 1 : 2D , 40 Spuren , 9 Sektoren + code 2 : 2D , 80 Spuren , 9 Sektoren + code 3 : HD , 80 Spuren ,15 Sektoren + + 'format (archive)' erzeugt ebenso wie 'format (0,archive)' eine + standardformatierte Diskette, 'format (3,archive)' erzeugt eine High + Density Formatierung (HD Floppy benutzen!). + +#on("b")# + ACHTUNG: Wird eine bereits beschriebene Diskette noch einmal formatiert, so + sind alle Daten, die auf der Diskette waren, verloren. + + Die Umformatierung einer Diskette (z.B. von 720K auf 360K) auf + unterschiedlichen Laufwerken kann zu Problemen führen. +#off("b")# +#page# +'check' + #on("b")#PROC check (TEXT CONST dateiname, TASK CONST task) #off("b")# + Überprüft, ob die Datei 'dateiname' auf dem Archiv lesbar ist. + + + #on("b")#PROC check (THESAURUS CONST t, TASK CONST task) #off("b")# + Überprüft, ob die in dem Thesaurus 't' enthaltenen Dateien auf dem Archiv lesbar + sind. + + + Mit diesem Kommando kann nach dem Beschreiben einer Diskette überprüft wer + den, ob die Datei(en) lesbar sind. Hierdurch können also verschmutzte oder + beschädigte Disketten erkannt werden. + + +____________________________________________________________________________ + + gib kommando : + save (all , archive) + + gib kommando : + check (ALL archive, archive) + +____________________________________________________________________________ + +#page# + +Beispiel: + + +____________________________________________________________________________ + + gib kommando : + archive ("neu") + + gib kommando : + format (archive) + +____________________________________________________________________________ + + +liefert zunächst die Kontollfrage: + +____________________________________________________________________________ + + gib kommando : + format (archive) + + Archiv "neu" formatieren ? (j/n) + +____________________________________________________________________________ + + +Nach Eingabe 'j' + +____________________________________________________________________________ + + gib kommando : + saveall (archive) + + gib kommando : + archive("alt") (* nächste Diskette *) + + gib kommando : + fetch(SOME archive ,archive) + +____________________________________________________________________________ + + +Der Thesaurus des Archivs wird angezeigt: +#page# +____________________________________________________________________________ + + .................alt (100 K belegt von 720 K)............... + + 01.02.87 25 K "handbuch teil 1" + 01.03.87 23 K "handbuch teil 2" + 01.04.87 20 K "handbuch teil 3" + 01.05.87 32 K "handbuch teil 4" + +____________________________________________________________________________ + + + + + +Zum Abschluß Archiv freigeben! +____________________________________________________________________________ + + gib kommando : + release(archive) + +____________________________________________________________________________ +#page# + +Fehlermeldungen des Archivs +Versucht man, eine Datei vom Archiv zu holen, kann es vorkommen, daß das Ar +chiv-System + +____________________________________________________________________________ + + gib kommando : + fetch ("datei", archive) + #ib#Lese-Fehler (Archiv)#ie# + +____________________________________________________________________________ + + + +meldet und den Lese-Vorgang abbricht. Dies kann auftreten, wenn die Floppy +beschädigt oder aus anderen Gründen nicht lesbar ist (z.B. nicht justierte Disket +ten-Geräte). In einem solchen Fall vermerkt das Archiv-System intern, daß die Datei +nicht korrekt gelesen werden kann. Das sieht man z.B. bei 'list (archive)'. Dort ist der +betreffende Datei-Name mit dem Zusatz 'mit Lese-Fehler' gekennzeichnet. Um +diese Datei trotzdem zu lesen, muß man sie unter ihrem Dateinamen mit dem Zusatz +'mit Lese-Fehler' lesen. + +____________________________________________________________________________ + + gib kommando: + fetch ("datei mit Lese-Fehler", archive) + +____________________________________________________________________________ + + + +Die Datei wird in diesem Fall trotz Lese-Fehler (Informationsverlust!) vom Archiv +gelesen. +#page# + +Weitere Fehlermeldungen des Archivs: + + +FEHLER : Lesen unmöglich (Archiv) + Die Archiv-Diskette ist nicht eingelegt oder die Tür des Laufwerks ist nicht + geschlossen. + => Diskette einlegen bzw. Tür schließen. + +FEHLER : Schreiben unmöglich (Archiv) + Die Diskette ist schreibgeschützt. + => falls wirklich gewünscht, Schreibschutz entfernen. + +FEHLER : Archiv nicht angemeldet + Das Archiv wurde nicht angemeldet + => 'archive ("name")' geben. + +FEHLER : Lese-Fehler (Archiv) + Siehe Lesen unmöglich + +FEHLER : Schreibfehler (Archiv) + Die Diskette kann nicht (mehr) beschrieben werden. + => Andere Diskette verwenden. + +FEHLER : Speicherengpass + Im System ist nicht mehr genügend Platz, um eine Datei vom Archiv zu + laden. + => ggf. Dateien löschen. + +FEHLER : RERUN bei Archiv-Zugriff Das System wurde bei einer Archiv-Operation + durch Ausschalten bzw. Reset unterbrochen. + +FEHLER : "dateiname" gibt es nicht + Die Datei "dateiname" gibt es nicht auf dem Archiv. + => mit 'list(archive)' Archiv prüfen. + +FEHLER : Archiv heißt ... + Die eingelegte Diskette hat einen anderen als den eingegebenen Archivna + men. + => Kommando 'archive' mit korrektem Namen geben. + +FEHLER : Archiv wird von Task ... benutzt + Das Archiv wurde von einem anderen Benutzer reserviert. + => Abwarten. + +FEHLER : "dateiname" kann nicht geschrieben werden (Archiv voll) + Die Datei ist zu groß für die eingelegte Diskette. + => Andere Diskette für diese Datei nehmen. + +FEHLER : Archiv inkonsistent + Die eingelegte Diskette hat nicht die Struktur einer Archiv-Diskette. + => 'format (archive)' vergessen. + +FEHLER : save/erase wegen Lese-Fehler verboten + Bei Archiven mit Lese-Fehler sind Schreiboperationen verboten, weil ein + Erfolg nicht garantiert werden kann. + diff --git a/doc/programmer-manual/1.8.7/doc/programmierhandbuch.5 b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.5 new file mode 100644 index 0000000..a921572 --- /dev/null +++ b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.5 @@ -0,0 +1,1329 @@ +#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#: <zahl> + +wobei <zahl> folgende Werte annehmen kann: + +#on("bold")#<zahl> 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. + diff --git a/doc/programmer-manual/1.8.7/doc/programmierhandbuch.5b b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.5b new file mode 100644 index 0000000..d91bcc9 --- /dev/null +++ b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.5b @@ -0,0 +1,1481 @@ +#pagenr("%",40)##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# + +5.3 Der Datentyp FILE (Textdateien) + +Der Datentyp FILE definiert Dateien von sequentieller Struktur, die Texte enthalten. +Ein Objekt vom Datentyp FILE ist charakterisiert durch: + +1) seine Betriebsrichtung : input = nur lesender Zugriff + (TRANSPUTDIRECTION) output= nur schreibender Zugriff + modify= lesender und schreibender Zugriff. +2) seinen Namen. + +Betriebsrichtung und Name werden in der Assoziierungsprozedur 'sequential file' +(siehe Kap 2.8.2) festgelegt. + + +____________________________________________________________________________ + + ........................... Beispiel .......................... + TEXT VAR name := ausgabe ; + + FILE VAR f := sequential file(output,name) ; + + +____________________________________________________________________________ + + + +Das Festlegen einer Betriebsrichtung impliziert eine Kontrolle der Benutzung der +betreffenden Datei, hilft somit Programmierfehler zu vermeiden. + +ACHTUNG : #on("b")##on("u")#Alle#off("b")##off("u")# Prozeduren, die auf FILEs zugreifen, verlangen Objekte vom Typ + FILE VAR, da die Lese/Schreiboperationen als ändernd betrachtet wer + den (müssen). + +#page# + +5.3.1 Assoziierung + +'sequential file' + #on("b")#FILE PROC sequential file (TRANSPUTDIRECTION CONST mode, DATASPACE VAR ds) #off("b")# + Assoziierung einer sequentiellen Datei mit dem Dataspace 'ds' und der Betriebs + richtung 'mode' (vergl. 'modify', 'input' bzw. 'output'). Diese Prozedur dient zur + Assoziierung eines temporären Datenraums in der Benutzer-Task, der nach der + Beendigung des Programmlaufs nicht mehr zugriffsfähig ist (weil der Name des + Datenraums nicht mehr ansprechbar ist). Somit muß der Datenraum explizit vom + Programm gelöscht werden. + + + #on("b")#FILE PROC sequential file (TRANSPUTDIRECTION CONST mode,TEXT CONST name)#off("b")# + Assoziierung einer sequentiellen Datei mit dem Namen 'name' und der Betriebs + richtung 'mode' (vergl. 'input' bzw. 'output'). Existiert der FILE bereits, dann wird + mit 'input' auf den Anfang des FILEs, bei 'output' hinter den letzten Satz der datei + positioniert. Existiert dagagen der FILE noch nicht und ist die + TRANSPUTDIRECTION 'output' oder 'modify', wird ein neuer FILE eingerich + tet. + + FEHLER : "name" gibt es nicht" + Es wurde versucht, einen nicht vorhandenen FILE mit 'input' zu asso + ziieren. + +#page# + +'input' + #on("b")#PROC input (FILE VAR f) #off("b")# + Ändern der Verarbeitungsart von 'modify' oder 'output' in 'input'. Dabei wird auf + den ersten Satz der Datei positioniert. + + #on("b")#TRANSPUTDIRECTION CONST input #off("b")# + Assoziierung in Zusammenhang mit der Prozedur 'sequential file' einer sequentiel + len Datei mit der 'TRANSPUTDIRECTION' 'input' (nur lesen). + + +'output' + #on("b")#PROC output (FILE VAR file) #off("b")# + Ändern der Verarbeitungsart von 'input' oder 'modify' in 'output'. Dabei wird hinter + den letzten Satz der Datei positioniert. + + #on("b")#TRANSPUTDIRECTION CONST output #off("b")# + In Verbindung mit der Prozedur 'sequential file' kann eine Datei assoziiert werden + mit der Betriebsrichtung 'output' (nur schreiben). + + +'modify' + #on("b")#PROC modify (FILE VAR f) #off("b")# + Ändern der Betriebsrichtung von 'input' oder 'output' in die Betriebsrichtung 'mo + dify'. + + #on("b")#TRANSPUTDIRECTION CONST modify #off("b")# + Diese Betriebsrichtung erlaubt das Vorwärts- und Rückwärts-Positionieren und + das beliebige Einfügen und Löschen von Sätzen. 'modify' wird für die Assoziie + rungsprozedur 'sequential file' benötigt. + + + +#page# + +5.3.2 Informationsprozeduren + +'eof' + #on("b")#BOOL PROC eof (FILE CONST file) #off("b")# + Informationsprozedur auf das Ende eines FILEs. Liefert den Wert TRUE, sofern + hinter den letzten Satz eines FILEs positioniert wurde. + + +'line no' + #on("b")#INT PROC line no (FILE CONST file) #off("b")# + Liefert die aktuelle Zeilennummer. + + +'lines' + #on("b")#PROC lines (FILE VAR f) #off("b")# + Liefert die Anzahl der Zeilen der Datei 'f'. + + +'headline' + #on("b")#TEXT PROC headline (FILE CONST f) #off("b")# + Liefert den Inhalt der Kopfzeile der Datei 'f'. + + #on("b")#PROC headline (FILE VAR f, TEXT CONST ueberschrift) #off("b")# + Setzt #ib#'ueberschrift' in die Kopfzeile#ie# der Datei 'f'. +#page# + +5.3.3 Betriebsrichtung INPUT + +In der Betriebsrichtung 'input' sind nur Leseoperationen auf der Datei zugelassen. Die +Assoziierungsprozedur 'sequential file' bewirkt: + +1) Falls die Eingabedatei noch nicht existiert, wird eine Fehlermeldung ausgegeben. + +2) Falls es eine Datei des Namens gibt, wird auf das erste Zeichen des ersten + Satzes positioniert. + + + +'get' + #on("b")#PROC get (FILE VAR f, INT VAR number) #off("b")# + Lesen des nächsten Wortes aus der Datei 'f' und Konvertierung des Wortes zu + einem Integer-Objekt. + + #on("b")#PROC get (FILE VAR f, REAL VAR number) #off("b")# + Lesen des nächsten Wortes aus der Datei 'f' und Konvertierung des Wortes zu + einem Real-Objekt. + + + #on("b")#PROC get (FILE VAR f, TEXT VAR text) #off("b")# + Lesen des nächsten Wortes aus der Datei 'f'. + + #on("b")#PROC get (FILE VAR f, TEXT VAR text, TEXT CONST delimiter)#off("b")# + Lesen eines TEXT-Wertes 'text' von der Datei 'f', bis das Zeichen 'delimiter' + angetroffen wird. Ein eventueller Zeilenwechsel in der Datei wird dabei übergan + gen. + + #on("b")#PROC get (FILE VAR f, TEXT VAR text, INT CONST maxlength)#off("b")# + Lesen eines TEXT-Wertes 'text' von der Datei 'f' mit 'maxlength' Zeichen. Ein + eventueller Zeilenwechsel in der Datei wird dabei nicht übergangen. + + + +'getline' + #on("b")#PROC get line (FILE VAR file, TEXT VAR record) #off("b")# + Lesen der nächsten Zeile aus der sequentiellen Datei 'file'. + Mögliche Fehler bei Betriebsrichtung 'input': + + "Datei zu" + Die Datei 'file' ist gegenwärtig nicht assoziiert. + + "Leseversuch nach Dateiende" + Es wurde versucht, über die letzte Zeile einer Datei zu lesen. + + "Leseversuch auf output file" + Es wurde versucht, von einem mit 'output' assoziierten FILE zu lesen. + + "Unzulässiger Zugriff auf modify-FILE" + +#page# + +5.3.4 Betriebsrichtung OUTPUT + +In der Betriebsrichtung 'output' sind nur Schreiboperationen auf der Datei zugelassen. +Die Assoziierungsprozedur 'sequential file' bewirkt: + +1) Falls die Ausgabedatei noch nicht existiert, wird sie angelegt und auf den ersten + Satz positioniert. + +2) Falls es bereits eine Datei des Namens gibt, wird hinter den letzten Satz positio + niert, die Datei wird also fortgeschrieben. + + +'put' + #on("b")#PROC put (FILE VAR f, INT CONST number) #off("b")# + Ausgabe eines INT-Wertes 'number' in die Datei 'f'. Dabei wird ein Leerzeichen + an die Ausgabe angefügt. + + #on("b")#PROC put (FILE VAR f, REAL CONST number) #off("b")# + Ausgabe eines REAL-Wertes 'number' in die Datei 'f'. Dabei wird ein Leerzei + chen an die Ausgabe angefügt. + + #on("b")#PROC put (FILE VAR f, TEXT CONST text) #off("b")# + Ausgabe eines TEXT-Wertes 'text' in die Datei 'f'. Dabei wird ein Leerzeichen an + die Ausgabe angefügt. + + + +'putline' + #on("b")#PROC putline (FILE VAR file, TEXT CONST record) #off("b")# + Ausgabe eines TEXTes 'record' in die Datei 'file'. Danach wird auf die nächste + Zeile positioniert. 'file' muß mit 'output' assoziiert sein. + + +'write' + #on("b")#PROC write (FILE VAR f, TEXT CONST text) #off("b")# + Schreibt 'text' in die Datei 'f' (analog 'put (f, text)'), aber ohne Trennblank. + + +'line' + #on("b")#PROC line (FILE VAR file) #off("b")# + Positionierung auf die nächste Zeile der Datei 'file'. Wird versucht, über das Ende + eines mit 'input' assoziierten FILEs zu positionieren, wird keine Aktion vorgenom + men. + + #on("b")#PROC line (FILE VAR file, INT CONST lines) #off("b")# + Positionierung mit 'lines' Zeilen Vorschub in der Datei 'file'. + + + FEHLER: "Datei zu!" + Die Datei 'file' ist gegenwärtig nicht assoziiert. + + "Schreibversuch auf input-File" + Es wurde versucht, auf einen mit 'input' assoziierten FILE zu + schreiben. + + + Bei Textdateien, die mit dem Editor weiterbearbeitet werden sollen, ist also zu + beachten: ine Ausgabe mit 'put' setzt ein 'blank' hinter die Ausgabe. Falls dieses + Leerzeichen das letzte Zeichen in der Zeile ist, wird eine Absatzmarke in der Zeile + gesetzt. Wird mit 'write' oder 'putline' ausgegeben, steht kein Leerzeichen und + somit keine Absatzmarke am Zeilenende. +#page# + +5.3.5 Betriebsrichtung MODIFY + +In der Betriebsrichtung 'modify' sind Lese- und Schreiboperationen auf der Datei +zugelassen. Desweiteren ist beliebiges Positionieren in der Datei erlaubt. Neue Sätze +können an beliebiger Stelle in die Datei eingefügt werden, die sequentielle Struktur +der Datei bleibt erhalten. Die Assoziierungsprozedur 'sequential file' bewirkt: + +1) Falls die Ausgabedatei noch nicht existiert, wird sie angelegt. + +2) Falls es bereits eine Datei des Namens gibt, ist undefiniert wo positioniert ist. Die + erste Positionierung muß explizit vorgenommen werden! + + + +'col' + #on("b")#PROC col (FILE VAR f, INT CONST position) #off("b")# + Positionierung auf die Spalte 'position' innerhalb der aktuellen Zeile. + + #on("b")#INT PROC col (FILE CONST f) #off("b")# + Liefert die aktuelle Position innerhalb der aktuellen Zeile. + + +'down' + #on("b")#PROC down (FILE VAR f) #off("b")# + Positionieren um eine Zeile vorwärts. + + #on("b")#PROC down (FILE VAR f, INT CONST number) #off("b")# + Positionieren um 'number' Zeilen vorwärts. + + +'to line' + #on("b")#PROC to line (FILE VAR f, INT CONST number) #off("b")# + Positionierung auf die Zeile 'number'. + + +'up' + #on("b")#PROC up (FILE VAR f) #off("b")# + Positionieren um eine Zeile rückwärts. + + #on("b")#PROC up (FILE VAR f, INT CONST number) #off("b")# + Positionieren um 'number' Zeilen rückwärts. + +#page# +'delete record' + #on("b")#PROC delete record (FILE VAR file) #off("b")# + Der aktuelle Satz der Datei 'file' wird gelöscht. Der folgende Satz wird der aktuelle + Satz. + + +'insert record' + #on("b'PROC insert record (FILE VAR file) #off("b")# + Es wird ein leerer Satz in die Datei 'file' vor die aktuelle Position eingefügt. Dieser + Satz kann anschließend mit 'write record' beschrieben werden (d.h. der neue Satz + ist jetzt der aktuelle Satz). + + + +'read record' + #on("b")#PROC read record (FILE CONST file, TEXT VAR record) #off("b")# + Liest den aktuellen Satz der Datei 'file' in den TEXT 'record'. Die Position wird + dabei nicht verändert. + + + +'write record' + #on("b")#PROC write record (FILE VAR file, TEXT CONST record) #off("b")# + Schreibt einen Satz in die Datei 'file' an die aktuelle Position. Dieser Satz muß + bereits vorhanden sein, d.h. mit 'write record' kann keine leere Datei beschrieben + werden, sondern es wird der Satz an der aktuellen Position überschrieben. Die + Position in der Datei wird nicht verändert. + + +#page# + +5.3.6 FILE -Ausschnitte + +Ähnlich den Editorfunktionen 'ESC RUBOUT' und 'ESC RUBIN', die erlauben ganze +Abschnitte einer Datei zu löschen und das Gelöschte an anderer Stelle wiedereinzu +fügen, gibt es die Möglichkeit per Programm solche Segmente +eines 'modify-FILEs' zu verschieben. + + +'clear removed' + #on("b")#PROC clear removed (FILE VAR f) #off("b")# + Das mit 'remove' entfernte Segment wird gelöscht und nicht an anderer Stelle + eingefügt. + + +'reinsert' + #on("b")#PROC reinsert (FILE VAR f) #off("b")# + Das mit 'remove' entfernte Segment wird vor die aktuelle Zeile wiedereingefügt. + + +'remove' + #on("b")#PROC remove (FILE VAR f, INT CONST size) #off("b")# + Löscht 'size' Zeilen vor der aktuellen Position aus 'f'. Das Segment wird in einen + internen Puffer geschrieben. + + +'reorganize' + #on("b")#PROC reorganize (TEXT CONST datei)#off("b")# + Reorganisation von 'datei'. Die durch Löschen und Einfügen aus vielen + Segmenten bestehende Datei wird zu einem Segment zusammengefügt, die + aktuelle Position ist danach das erste Zeichen der ersten Zeile. + + Durch diese Prozedur kann ggf. Speicherplatz gespart werden. + + #on("b")#PROC reorganize#off("b")# + Reorganisation der zuletzt bearbeiteten Datei. + + +'segments' + #on("b")#PROC segments (FILE VAR f) #off("b")# + Liefert die Anzahl der Segmente von 'f'. Eine große Anzahl von Segmenten kann + langsamere Zugriffe zur Folge haben. + +#page# + +5.4 Suchen und Ersetzen in Textdateien + +Such- und Ersetzungsprozeduren können sowohl interaktiv beim Editieren (siehe +dazu 3.3), als auch in Prozeduren, die auf FILEs (siehe 5.3) arbeiten, angewandt +werden. + +Die dazu dienenden Prozeduren sind im Paket 'pattern match' enthalten. Mit 'Pattern +Matching' (Muster treffen) wird ein Verfahren bezeichnet Gleichheit von Objekten +anhand von Regeln, denen diese Objekte genügen, zu überprüfen. + +Da oft nach Texten gesucht werden muß, deren genaue Ausprägung nicht bekannt ist, +oder deren Auftreten nur in einem bestimmten Zusammenhang interessiert, gibt es die +Möglichkeit feststehende Textelemente mit Elementen ungewisser Ausprägung zu +kombinieren, also Textmuster zu erzeugen. + +Um einen Text zu suchen, muß die Suchrichtung und der gesuchte Text oder ein +Muster, welches diesen Text beschreibt, angegeben werden. + +- Aufbauen von Textmustern : + , - , OR , any , bound , notion + +- Suchen nach Textmustern : down , downety , up , uppety + +- Treffer registrieren : LIKE , UNLIKE , at , pattern found + +- Treffer herausnehmen : ** , match , matchend , matchpos , + somefix , word + +- Ändern in Dateien : change + + +Nach einem erfolgreichen Suchvorgang ist stets auf das erste Zeichen der zu such +enden Zeichenkette positioniert. + + +Eine besondere Funktion kommt dem 'joker' zu: Dieses Symbol (Defaultwert: '*') steht +für eine beliebige Zeichenkette beliebiger Länge. Insbesondere bei Ersetzungsaktionen +in denen dieses Zeichen zur Musterbeschreibung verwendet wird, ist daher Vorsicht +geboten und sorgfältig zu testen. + +#page# + +5.4.1 Aufbau von Textmustern + +'+' + #on("b")#TEXT OP + (TEXT CONST links, rechts) #off("b")# + Verkettung der Texte 'links' und 'rechts' zu 'linksrechts'. Falls das Ergebnis länger + als die maximal zulässige Textlänge ist, ist es undefiniert. + + Wenn 'muster1' einen beliebigen Text finden sollte, ( Siehe: PROC any) wird das + Ende des von 'muster1' erkannten Textes durch den Anfang des von 'muster2' + erkannten Textes im Nachhinein definiert. + + + +'-' + #on("b")#TEXT OP - (TEXT CONST alphabet) #off("b")# + Der Operator liefert das zu 'alphabet' komplementäre Alphabet, also alle Zeichen + gemäß der EUMEL Codetabelle (5.2.4), die nicht in 'alphabet' enthalten sind. + Sinnvoll im Zusammenhang mit der Textprozedur 'any'. + + +'OR' + #on("b")#TEXT OP OR (TEXT CONST links, rechts) #off("b")# + Liefert die Alternative von 'links' und 'rechts'. Die Reihenfolge spielt beim Suchen + keine Rolle. + + + +'any' + Die Textprozedur 'any' liefert einen unbekannten Text unbestimmter Länge. + Dieser Text sollte entweder durch festen Text sinnvoll eingegrenzt werden, oder + direkt eingeschränkt werden. + + + #on("b")#TEXT PROC any #off("b")# + Beschreibt einen beliebigen Text. + + #on("b")#TEXT PROC any (INT CONST laenge) #off("b")# + Beschreibt einen beliebigen Text der angebenen Länge. + + + #on("b")#TEXT PROC any (TEXT CONST alphabet) #off("b")# + Beschreibt einen beliebigen Text, der nur aus Zeichen besteht, die in 'alphabet' + enthalten sind. + + + #on("b")#TEXT PROC any (INT CONST laenge, TEXT CONST alphabet) #off("b")# + Beschreibt einen Text der vorgegebenen Länge, der nur aus den in 'alphabet' + vorgegebenen Zeichen besteht. + + +____________________________________________________________________________ + + ........................... Beispiel .......................... + Die Textprozedur 'any' liefert einen unbekannten Text unbe + stimmter Länge. Dieser Text sollte entweder durch festen Text + sinnvoll eingegrenzt werden, oder direkt eingeschränkt werden. +gib kommando: D("D" OR "d" + any (2,"aeirs") + Sucht nach bestimmten Artikeln: 'der', 'die', 'das' etc. + +____________________________________________________________________________ + + + +'bound' + #on("b")#TEXT PROC bound #off("b")# + Bezeichnet ein Muster der Länge null, das nur am Zeilenanfang oder am Zeilenen + de gefunden wird. Ein Präfix 'bound' fordert, daß das gesuchte Muster in der + ersten Spalte beginnen muß, ein Postfix 'bound' fordert, daß das Muster mit dem + Zeilenende abschließt. + +____________________________________________________________________________ + + ........................... Beispiel .......................... + Die Textprozedur 'any' liefert einen unbekannten Text unbe + stimmter Länge. Dieser Text sollte entweder durch festen + Textsinnvoll eingegrenzt werden, oder direkt eingeschränkt + werden. +gib kommando: U(bound + any (" ")) + +____________________________________________________________________________ + + + + liefert Treffer bei eingerückten Zeilen. + + + +'notion' + #on("b")#PROC notion (TEXT CONST suchwort) #off("b")# + Mit dieser Prozedur kann ein #on("u")#Wort#off("u")# spezifiziert werden, nach dem gesucht werden + soll. Bei der Suche nach 'suchwort' wird nur dann ein Treffer geliefert, wenn + 'suchwort' als Wort, also begrenzt von ' ' (blank), '.' , ',' oder anderen Sonderzei + chen ist. + + #on("b")#PROC notion (TEXT CONST suchwort, INT CONST reg) #off("b")# + Wie oben, der Treffer wird im Register 'reg' gespeichert. + +#page# + +5.4.2 Suche nach Textmustern + +'down' + #on("b")#PROC down (FILE VAR f, TEXT CONST muster) #off("b")# + Suche nach 'muster' in der Datei 'f' in Richtung Dateiende. Wird 'muster' gefun + den, ist die Position das erste Zeichen von 'muster'. Andernfalls steht man hinter + dem letzten Zeichen der Datei. + + Achtung: 'down' sucht vom nächsten Zeichen rechts ab, so daß wiederholtes + Suchen keine Endlosschleife ergibt. + + + #on("b")#PROC down (FILE VAR f, TEXT CONST muster, INT CONST number)#off("b")# + Wie obiges 'down', es wird aber maximal nur 'number'-Zeilen weit nach 'muster' + gesucht. + + + +'downety' + #on("b")#PROC downety (FILE VAR f, TEXT CONST muster) #off("b")# + Suche nach 'muster' in der Datei 'f' in Richtung Dateiende. Wird 'muster' gefun + den, ist die Position das erste Zeichen von 'muster'. Andernfalls steht man auf + dem letzten Zeichen der Datei. + + Achtung: 'downety' sucht (im Gegensatz zu 'down') vom aktuellen Zeichen an. + Daher muß explizit vorwärts positioniert werden. + + + #on("b")#PROC downety (FILE VAR f, TEXT CONST muster, INT CONST number) #off("b")# + Wie obiges 'downety', aber maximal nur 'number'-Zeilen weit. +#page# +'up' + #on("b")#PROC up (FILE VAR f, TEXT CONST muster) #off("b")# + Suche nach 'muster' in der Datei 'f' in Richtung Dateianfang. Wird 'muster' + gefunden, ist die Position das erste Zeichen von 'muster'. Andernfalls steht man + auf dem ersten Zeichen der Datei. + + Achtung: 'up' sucht vom nächsten Zeichen links ab, so daß wiederholtes Suchen + keine Endlosschleife ergibt. + + + #on("b")#PROC up (FILE VAR f, TEXT CONST muster, INT CONST number)#off("b")# + Wie obiges 'up', aber maximal nur 'number'-Zeilen weit. + + + +'uppety' + #on("b")#PROC uppety (FILE VAR f, TEXT CONST muster) #off("b")# + Suche nach 'muster' in der Datei 'f' in Richtung Dateianfang. Wird 'muster' + gefunden, ist die Position das erste Zeichen von 'muster'. Andernfalls steht man + auf dem ersten Zeichen der Datei. + + Achtung: 'uppety' sucht (im Gegensatz zu 'up') vom aktuellen Zeichen. + + + #on("b")#PROC uppety (FILE VAR f, TEXT CONST muster, INT CONST number)#off("b")# + Wie obiges 'uppety', aber maximal nur 'number'-Zeilen weit. + +#page# + +5.4.3 Treffer registrieren + +'LIKE' + #on("b")#BOOL OP LIKE (TEXT CONST text , muster) #off("b")# + Liefert TRUE, falls der Text 'text' 'muster' entspricht. In 'muster' kann das + Spezialzeichen '*' verwandt werden, das abkürzend für die Konkatenation mit + 'any' steht. + + Daraus folgt, daß das Suchen oder Ersetzen des Zeichens '*' nur durch + any (1,"*") zu bewerkstelligen ist. + + +____________________________________________________________________________ + + ........................... Beispiel .......................... + \#Druckdateien aus Thesaurus löschen\# + gib kommando:"*.p" C "" + 16.04.87 "Handbuch teil1" + 04.05.87 "Handbuch teil1.p" + 16.04.87 "Handbuch teil2" + 06.05.87 "Handbuch teil2.p" + +____________________________________________________________________________ + + + + aber: + +____________________________________________________________________________ + + ........................... Beispiel .......................... + \#Vordere Kommentarklammern löschen \# + gib kommando:"(" + any(1,"*") C "" + lernsequenz auf taste legen("a" , "archive") ; + (* lernsequenz auf taste legen("(" , ""91"") ; *) + (* lernsequenz auf taste legen(")" , ""93"") ; *) + kommando auf taste legen("P" , "print("""")"8""8""11"") . + +____________________________________________________________________________ + + + +'UNLIKE' + #on("b")#BOOL OP UNLIKE (TEXT CONST text , muster) #off("b")# + Wirkt wie: '(NOT text LIKE muster)' +#page# + +5.4.4 Treffer herausnehmen + +Mit Hilfe der 'Register' ist es möglich identifizierte Texte zwischenzuspeichern und in +weiteren Aktionen weiterzuverwenden. + + +'**' + #on("b")#TEXT OP ** (TEXT CONST muster, INT CONST register)#off("b")# + Der als 'muster' erkannte Text wird einem 'Register' mit der Nummer 'register' + zugeordnet. Es können 256 Register (1 bis 256) benutzt werden. + + +'match' + #on("b")#TEXT PROC match (INT CONST nr) #off("b")# + Liefert den Text der dem Register 'nr' zuletzt zugeordnet wurde. + + +'matchpos' + #on("b")#INT PROC matchpos (INT CONST nummer) #off("b")# + Liefert die Spaltennummer, auf der das dem Register 'nummer' zugeordnete Mu + ster in der Zeile beginnt. + +____________________________________________________________________________ + + ........................... Beispiel .......................... + + gib kommando:D("file"+any+"("+(any ** (1)... + +____________________________________________________________________________ +#page# + +5.4.5 Ändern in Dateien + +'change' + #on("b")#PROC change (FILE VAR datei, INT CONST von, bis , TEXT CONST neuertext)#off("b")# + In der Datei wird in der aktuellen Zeile in den Ausschnitt zwischen 'von' und 'bis' + der Text 'neuertext' eingesetzt. + + entspricht: + + +____________________________________________________________________________ + + ........................... Beispiel .......................... + FILE VAR file := sequential file (modify, name) + TEXT VAR zeile; + . + . + read record (file ,zeile); + change (zeile, von, bis ,"neuertext"); + write record (file, zeile); + . + +____________________________________________________________________________ + +#page# + +5.4.6 Editor-Prozeduren + +'edit' + #on("b")#edit (TEXT CONST datei)#off("b")# + Editieren der Datei 'datei'. Das Editorfenster ist maximal groß (von 1,1 bis + max,max). Der Standard-Kommandointerpreter ist gültig, so daß Eingaben, die + mit #schl("ESC")# beginnen, interpretiert werden, wie in 3.4 'Vorbelegte Tasten' beschrie + ben. + + #on("b")#edit#off("b")# + Wie oben, editiert wird die Datei mit dem zuletzt benutzten Namen. + + #on("b")#edit (THESAURUS CONST thes)#off("b")# + Wie oben, editiert werden alle Dateien, deren Namen im Thesaurus 'thes' enthal + ten sind. + + #on("b")#edit (TEXT CONST datei, INT CONST von x, von y, bis x, bis y)#off("b")# + Editieren der Datei 'datei'. Das Editorfenster hat die linke obere Ecke bei 'von x, + von y' und die rechte untere Ecke bei 'bis x, bis y'. + + #on("b")#edit (FILE VAR f)#off("b")# + Editieren der als 'sequential file' assoziierten Textdatei 'f'. + + #on("b")#edit (FILE VAR, INT CONST von x, von y, bis x, bis y)#off("b")# + Editieren der als 'sequential file' assoziierten Textdatei in einem Fenster mit der + linken, oberen Ecke 'von x, von y' und der rechten, unteren Ecke 'bis x, bis y'. + + #on("b")#edit (FILE VAR f, TEXT CONST res, + PROC (TEXT CONST) kdo interpreter)#off("b")# + Editieren der als 'sequential file' assoziierten Textdatei 'f'. In 'res' werden reser + vierte Zeichen übergeben, die von der Prozedur 'kdo interpreter' als Kommandos + interpretiert werden, wenn sie als ESC-Sequenz eingegeben werden. + Beispiel : #schl("ESC ")# #schl("e")# + +#page# +'editget' + #on("b")#editget (TEXT VAR ausgabe) #off("b")# + Aufruf des Zeileneditor. An der aktuellen Cursorposition wird eine Zeile ausgegeben in + der 'ausgabe' steht. Für diese Zeile stehen alle Editiermöglichkeiten zur + Verfügung, 'ausgabe' kann also beliebig überschrieben, ergänzt etc. werden. Die + Eingabe wird durch #schl("CR")# abgeschlossen. Im Gegensatz zur Prozedur 'get' ist auch + eine leere Eingabe möglich. + + #on("b")#editget (TEXT VAR ausgabe, INT CONST zeile, INT CONST scroll, + TEXT CONST sep, TEXT CONST res, TEXT VAR exit) #off("b")# + Wie oben, die Zeilenlänge ist jedoch auf 'zeile' Zeichen begrenzt. Die Eingabe + wird durch #schl("CR")# oder durch eine Cursorbewegung über die Position 'zeile' hinaus + abgeschlossen. + + Die Angabe 'scroll' setzt die Breite des Zeilenfensters fest, wird diese Breite + überschritten, so wird 'ausgabe' gerollt. + + In 'sep' (Separator) können Zeichen festgesetzt werden, mit denen die Eingabe + beendet wird (zusätzlich zu CR !). + + In 'res' (reservierte Tasten) können Tasten festgelegt werden, die in Verbindung + mit <ESC> die Eingabe beenden. + + Wurde der Zeileneditor durch einen Separator verlassen, so steht in 'exit' dieses + Zeichen. Falls der Zeileneditor durch eine reservierte Taste verlassen, so enthält + 'exit' 'ESC' und die Taste. + + #on("b")#editget (TEXT VAR ausgabe, INT CONST zeile, INT CONST scroll)#off("b")# + Bedeutung der Parameter siehe oben. + + #on("b")#editget (TEXT VAR ausgabe, TEXT CONST sep, TEXT CONST res, + TEXT VAR exit) #off("b")# + Bedeutung der Parameter siehe oben. + + #on("b")#editget (TEXT VAR ausgabe, INT CONST zeile, TEXT VAR exit) #off("b")# + Bedeutung der Parameter siehe oben. +#page# + +5.4.7 Sortierung von Textdateien + +Für die Sortierung von Textdateien gibt es zwei Sortierprogramme: + +- Sortierung nach ASCII : sort + +- Sortierung nach + deutschem Alphabet : lexsort + + +'sort' + #on("b")#PROC sort (TEXT CONST datei) #off("b")# + Diese Prozedur sortiert die Datei 'datei' zeilenweise gemäß der von der EUMEL + Codetabelle (siehe 5.2.4) vorgegebenen Reihenfolge. Zur Sortierung werden die + Zeilen vom ersten Zeichen der Zeile beginnend, zeichenweise verglichen und + dementsprechend sortiert. + + #on("b")#PROC sort (TEXT CONST datei, INT CONST position) #off("b")# + Sortierkriterien wie oben, jedoch wird bei Vergleich und Sortierung der Satz erst + ab der Position 'position' beachtet. Sortiert wird der ganze Satz! + + +'lex sort' + #on("b")#PROC lex sort (TEXT CONST datei) #off("b")# + Zeilenweise Sortierung nach lexikographischer Reihenfolge gemäß DIN 5007. Zu + den Vergleichen werden die Operatoren LEXEQUAL, LEXGRATER, + LEXGRATEREQUAL benutzt (siehe 5.2.4). + + #on("b")#PROC lex sort (TEXT CONST datei, INT CONST position) #off("b")# + Lexikalische Sortierung durch Vergleich ab Position 'position'. + +#page# + +5.4.8 Prozeduren auf Datenräumen + +Neben den Textdateien gibt es im EUMEL-System den Typ Datenraum, der Objekte +jeglichen Typs aufnehmen kann und direkten Zugriff auf die Objekte gewährt (siehe +2.9.2). + +Für Objekte von Type Datenraum (nicht für die in Datenräumen enthaltenen Objekte!) +existieren folgende Standardprozeduren: + + +':=' + #on("b")#OP := ( DATASPACE VAR ds1, DATASPACE CONST ds2)#off("b")# + Der Datenraum 'ds1' wird als Kopie von 'ds2' angelegt. Es handelt sich zunächst + um eine logische Kopie, eine physische Kopie wird erst nach einem Schreibzugriff + auf 'ds1' oder 'ds2' nötig. + + +'new' + #on("b")#DATASPACE PROC new (TEXT CONST dsname) #off("b")# + Liefert einen neuen Datenraum namens 'dsname'. + +____________________________________________________________________________ + + DATASPACE VAR ds := new ("datenraum") + (* ergibt zwei Datenräume 'ds' und 'datenraum'! *) + +____________________________________________________________________________ + + + +'nilspace' + #on("b")#DATASPACE PROC nilspace#off("b")# + Der 'nilspace' ist ein leerer Datenraum, der ausschließlich als Quelle zum Kopie + ren bei der Initialisierung Verwendung finden darf. + + +'old' + #on("b")#DATASPACE PROC old (TEXT CONST dsname) #off("b")# + Liefert einen bereits existierenden Datenraum (oder auch eine Datei) mit dem + Namen 'dsname'. + + FEHLER : "dsname" gibt es nicht + + +'type' + #on("b")#PROC type (DATASPACE CONST ds, INT CONST typ)#off("b")# + Der Datenraum 'ds' erhält den frei wählbaren Schlüssel 'typ'. Es muß eine positive + Zahl gewählt werden. Der Datenraum muß zum Zeitpunkt der Typzuweisung an + ein BOUND Objekt gekoppelt (gewesen) sein. + + #on("b")#INT PROC type (DATASPACE CONST ds)#off("b")# + Liefert den Schlüssel des Datenraums 'ds'. Falls 'ds' nie an ein BOUND Objekt + gekoppelt war, liefert die Prozedur einen Wert < 0, sonst 0 (keine Zuweisung + erfolgt) oder die zugewiesene Typnummer. + + +'dataspaces' + #on("b")#INT PROC dataspaces (TASK CONST task) #off("b")# + Liefert die Anzahl der Datenräume der Task 'task'. + + #on("b")#INT PROC dataspaces #off("b")# + Anzahl der Datenräume von 'myself'. + + +'ds pages' + #on("b")#INT PROC ds pages (DATASPACE CONST ds)#off("b")# + Liefert die Anzahl der durch 'ds' belegten Seiten (je 512 Byte). + + +'storage' + #on("b")#INT PROC storage (DATASPACE CONST ds)#off("b")# + Liefert den von 'ds' belegten Speicherplatz in KB. + +#page# +'copy' + #on("b")#PROC copy (DATASPACE CONST ds, TEXT CONST datei) #off("b")# + Eine neue Datei mit dem Namen 'datei' wird angelegt. Der Inhalt der Datei ist eine + Kopie des Inhalts des Datenraumes 'ds'. + + +'forget' + #on("b")#PROC forget (DATASPACE CONST ds)#off("b")# + Der Datenraum 'ds' wird gelöscht#u#1)#e#. + +#foot# + + 1) Durch diese Prozedur steht nicht unmittelbar mehr freier Speicherplatz zur + Verfügung. Die physische Räumung von Speicherplatz erfolgt durch die + 'Müllabfuhr' bei einem Fixpunkt. +#end# + +'fetch' + #on("b")#PROC fetch (DATASPACE CONST ziel, TEXT CONST datei, + TASK CONST manager) #off("b")# + Aus der Task 'manager' wird der Datenraum der Datei 'datei' in den eigenen + Datenraum 'ziel' kopiert. + + +'save' + #on("b")#PROC save (DATASPACE CONST quelle, TEXT CONST datei, + TASK CONST manager) #off("b")# + Der eigene Datenraum 'quelle' wird in die Datei 'datei' in der Task 'manager' + kopiert. +#page# + +5.5 Eingabe/Ausgabe + +- Eingabesteuerzeichen : HOP , � � � � , TAB , RUBIN , RUBOUT + CR , MARK , ESC + +- Ausgabesteuerzeichen : HOME , � � � � , CL EOP , CL EOL + CPOS , BELL , CR , ENDMARK , BEGINMARK + +- Positionierung : cursor , get cursor , line , page + +- Eingabe : get , getline , inchar , incharety + +- Ausgabe : cout , out , out subtext , put , putline , + TIMESOUT , write + +- Kontrolle : online , pause , sysin , sysout + +- Zeitmessung : clock , date , day , hour , pause , time + time of day + +#page# + +5.5.1 E/A auf Bildschirm + +Steuerzeichen und Standardprozeduren zur Ein- Ausgabe am Bildschirm werden +zur Steuerung des Dialogverhaltens von Prozeduren benutzt. + + +5.5.1.1 Eingabesteuerzeichen +Eingabesteuerzeichen werden durch die Funktionstasten (s. 3.2) erzeugt. Die Wirkung +der Tasten ist ebenfalls an dieser Stelle beschrieben. + +Durch die Tasten werden folgende Codes an Programme gegeben: + +Codierung I Bezeichnung +-----------+-------------- +HOP I 1 +RECHTS I 2 +OBEN I 3 +LINKS I 8 +TAB I 9 +UNTEN I 10 +RUBIN I 11 +RUBOUT I 12 +CR I 13 +MARK I 16 +ESC I 27 + + +#page# + +5.5.1.2 Ausgabesteuerzeichen + +Die Ausgabe dieser Zeichen bewirkt folgendes Verhalten der Bildschirmausgabe. + +Code I Name I Wirkung +-----+-------------+------------------------------------------------------- + 0 I NUL I keine Wirkung + 1 I HOME I Cursor in die linke obere Ecke setzen (Position 0,0!) + 2 I RECHTS I Cursor eine Stelle nach rechts setzen + 3 I OBEN I Cursor eine Zeile höher setzen + 4 I CL EOP I Rest der Seite löschen + 5 I CL EOL I Rest der Zeile löschen + 6 I CPOS I Cursor setzen, nächstes Ausgabezeichen bestimmt die + I I y-Position, das darauf folgende die x-Position. + 7 I BELL I akustisches Signal + 8 I LINKS I Cursor eine Stelle nach links setzen +10 I UNTEN I Cursor eine Stelle nach unten setzen +13 I CR I Cursor an den Anfang der nächsten Zeile setzen +14 I ENDMARK I Ende des markierten Bereichs +15 I BEGINMARK I Anfang des markierten Bereichs + + + + +____________________________________________________________________________ + + ........................... Beispiel .......................... + TEXT VAR ausgabe := (""7""15"V O R S I C H T"14"7""); + out(ausgabe); + +____________________________________________________________________________ + +#page# + +5.5.1.3 Positionierung + +'cursor' + #on("b")#PROC cursor (INT CONST column, row) #off("b")# + Positioniert den Cursor auf dem Bildschirm, wobei 'column' die Spalte und 'row' + die Zeile angibt. Die zulässigen Bereiche von 'column' und 'row' sind geräteab + hängig. + + + +'get cursor' + #on("b")#PROC get cursor (INT VAR x, y) #off("b")# + Erfragung der aktuellen Cursor-Position. Die Koordinaten des Cursors werden in + 'x' und 'y' geliefert. Die aktuelle Cursor-Position ist nach Ausgabe von 'HOME' + (Code = 1) oder einer Positionierung des Cursors mit der Prozedur 'cursor' stets + definiert. Die Prozedur 'get cursor' liefert jedoch undefinierte Werte, wenn über + den rechten Rand einer Zeile hinausgeschrieben wurde (die Wirkung einer solchen + Operation hängt von der Hardware eines Terminals ab). + + +'line' + #on("b")#PROC line #off("b")# + Es wird zum Anfang einer neuen Zeile positioniert. + + #on("b")#PROC line (INT CONST number) #off("b")# + Es werden 'number' Zeilenwechsel vorgenommen. + + +'page' + #on("b")#PROC page #off("b")# + Es wird zum Anfang einer neuen Seite positioniert (hier: linke obere Ecke (Position + 1,1 !) des Bildschirms, wobei der Bildschirm gelöscht wird). + +#page# + +5.5.1.4 Eingabe + + +Grundlegende Prozeduren +Die folgenden Prozeduren dienen ausschließlich der Eingabe vom Terminal. + +'editget' + Siehe 5.4.6 + + +'getchar' + #on("b")#PROC getchar (TEXT VAR zeichen)#off("b")# + Liest genau ein Zeichen von der Tastatur und schreibt es in die Variable 'zeichen'. + + +'inchar' + #on("b")#PROC inchar (TEXT VAR character) #off("b")# + Wartet solange, bis ein Zeichen von der Tastatur eingegeben wird, und schreibt + dieses Zeichen in die Variable 'character'. + + +'incharety' + #on("b")#TEXT PROC incharety #off("b")# + Versucht, ein Zeichen von der Tastatur zu lesen. Wurde kein Zeichen eingegeben, + wird niltext geliefert. + + #on("b")#TEXT PROC incharety (INT CONST time limit) #off("b")# + Versucht, ein Zeichen vom Bildschirm zu lesen. Dabei wird maximal eine 'time + limit' lange Zeit auf das Zeichen gewartet (gemessen in Zehntel-Sekunden). + +#page# + +Umleitbare Eingabeprozeduren +Die folgenden Eingabeprozeduren lesen ebenfalls vom Terminal, die Eingabequelle +kann jedoch durch die Prozedur 'sysin' umgestellt werden. Falls in 'sysin' eine Datei +angegeben wird wird die Eingabe statt vom Terminal aus dieser Datei gelesen. + + +'sysin' + #on("b")#PROC sysin (TEXT CONST file name) #off("b")# + Eingabe-Routinen lesen nicht mehr vom Benutzer-Terminal, sondern aus der + Datei 'file name'. + + #on("b")#TEXT PROC sysin #off("b")# + Liefert den Namen der eingestellten 'sysin'-Datei. "" bezeichnet das Benutzer- + Terminal. + + +'get' + #on("b")#PROC get (INT VAR number) #off("b")# + Einlesen eines INT-Wertes vom Bildschirm. Der einzulesende INT-Wert kann + bei der Eingabe vom Terminal editiert werden. + + #on("b")#PROC get (REAL VAR value) #off("b")# + Einlesen eines REAL-Wertes vom Bildschirm. Der einzulesende REAL-Wert + kann bei der Eingabe vom Terminal editiert werden. + + #on("b")#PROC get (TEXT VAR word) #off("b")# + Liest einen Text in die Variable 'word' mit maximal 255 Zeichen. Es werden + solange Zeichen vom Terminal gelesen, bis ein Leerzeichen oder #schl("CR")# eingegeben + wird. Dabei werden führende Leerzeichen übergeben. Der einzulesende Text + kann bei der Eingabe editiert werden. Eine leere Eingabe ist nicht erlaubt. + + #on("b")#PROC get (TEXT VAR word, INT CONST laenge) #off("b")# + Liest einen Text vom Bildschirm mit der Länge 'laenge' oder bis #schl("CR")# eingegeben + wird. Der einzulesende Wert kann bei der Eingabe editiert werden. + + #on("b")#PROC get (TEXT VAR word, TEXT CONST separator) #off("b")# + Liest einen Text vom Bildschirm, bis ein Zeichen 'separator' angetroffen oder #schl("CR")# + eingegeben wird. Der einzulesende Text kann bei der Eingabe editiert werden. + + +'getline' + #on("b")#PROC get line (TEXT VAR line) #off("b")# + Das System wartet auf eine Zeile vom Bildschirm (max. 255 Zeichen). #schl("CR")# been + det die Eingabe. + +#page# + +5.5.1.5 Ausgabe + + +Grundlegende Prozeduren +Die folgenden Prozeduren dienen ausschließlich der Ausgabe auf das Terminal. + + +'cout' + #on("b")#PROC cout (INT CONST number) #off("b")# + Schreibt 'number' an die aktuelle Cursor-Position auf den Bildschirm. Anschlie + ßend wird an diese Position wieder zurück positioniert. 'number' muß > 0 sein. + Paßt 'number' nicht mehr auf die Zeile, so ist die Wirkung von 'cout' nicht de + finiert. 'cout' gibt den Wert von 'number' nur aus, wenn genügend freie Kanal- + Kapazität für diese Ausgabe vorhanden ist. Das hat zur Folge, daß Programme + nicht auf die Beendigung einer Ausgabe von 'number' warten müssen und ggf. + Ausgaben überschlagen werden. + + +'out' + #on("b")#PROC out (TEXT CONST text) #off("b")# + Ausgabe eines Textes auf dem Bildschirm. Im Unterschied zu 'put' wird kein + Blank an den ausgegebenen Text angefügt. + + + +'out subtext' + #on("b")#PROC out subtext (TEXT CONST source, INT CONST from) #off("b")# + Ausgabe eines Teiltextes von 'source' von der Position 'from' bis Textende. Es + wird keine Aktion vorgenommen für + + + from > LENGTH source + + + #on("b")#PROC out subtext (TEXT CONST source, INT CONST from, to)#off("b")# + Ausgabe eines Teiltextes von 'source' von der Position 'from' bis zur Position 'to'. + Für + + + to > LENGTH source + + + wird out subtext (source, from) ausgeführt. + + #on("b")#PROC out text (TEXT CONST source, INT CONST from, to) #off("b")# + Ausgabe eines Teiltextes von 'source' von der Position 'from' bis zur Position 'to'. + Für + + + to > LENGTH source + + + wird für die fehlenden Zeichen Blanks ausgegeben. + + + +'TIMESOUT' + #on("b")#OP TIMESOUT (INT CONST times, TEXT CONST text) #off("b")# + Ausgabe eines TEXTes 'text' 'times'mal. An die Ausgabe wird im Gegensatz zu + 'put' kein Leerzeichen angefügt. Es wird kein Text ausgegeben für + + + times < 1 + + +#page# + +Umleitbare Ausgabeprozeduren +Die folgenden Ausgabeprozeduren schreiben ebenfalls auf das Terminal, die Ausgabe +kann jedoch durch die Prozedur 'sysout' umgeleitet werden. Falls in 'sysout' eine +Datei angegeben wird wird die Ausgabe statt zum +Terminal in die angegebene Datei geleitet. + + +'sysout' + #on("b")#PROC sysout (TEXT CONST file name) #off("b")# + Ausgabe-Routinen gehen nicht mehr zum Benutzer-Terminal, sondern in die + Datei 'file name'. + + #on("b")#TEXT PROC sysout #off("b")# + Liefert den Namen der eingestellten 'sysout'-Datei. "" bezeichnet das Benut + zer-Terminal. + + +'line' + #on("b")#line#off("b")# + Positionierung auf den Anfang einer neuen Ausgabezeile. + + #on("b")#line (INT CONST faktor)#off("b")# + Nächste Ausgabezeile um 'faktor' Zeilen weiter positionieren. + + +'put' + #on("b")#PROC put (INT CONST number) #off("b")# + Ausgabe eines INT-Wertes auf dem Bildschirm. Anschließend wird ein Leer + zeichen ausgegeben. + + #on("b")#PROC put (REAL CONST real) #off("b")# + Ausgabe eines REAL-Wertes auf dem Bildschirm. Anschließend wird ein Leer + zeichen ausgegeben. + + #on("b")#PROC put (TEXT CONST text) #off("b")# + Ausgabe eines Textes auf dem Bildschirm. Nach der Ausgabe von 'text' wird ein + Blank ausgegeben, um nachfolgenden Ausgaben auf der gleichen Zeile voneinan + der zu trennen. Hardwareabhängig sind die Aktionen, wenn eine Ausgabe über + eine Zeilengrenze (hier: Bildschirmzeile) vorgenommen wird. Meist wird die Ausga + be auf der nächsten Zeile fortgesetzt. + + +'putline' + #on("b")#PROC putline (TEXT CONST text) #off("b")# + Ausgabe von 'text' auf dem Bildschirm. Nach der Ausgabe wird auf den Anfang + der nächsten Zeile positioniert. Gibt man TEXTe nur mit 'putline' aus, so ist + gesichert, daß jede Ausgabe auf einer neuen Zeile beginnt. Hardwareabhängig + sind die Aktionen, wenn eine Ausgabe über eine Zeilengrenze (hier: Bildschirm + zeile) vorgenommen wird. Meist wird die Ausgabe auf der nächsten Zeile fort + gesetzt. + + +'write' + #on("b")#PROC write (TEXT CONST text) #off("b")# + Gibt 'text' ohne Trennblank aus ('put' mit Trennblank). + +#page# + +5.5.1.6 Kontrolle + +'online' + #on("b")#BOOL PROC online #off("b")# + Liefert TRUE, wenn die Task mit einem Terminal gekoppelt ist. + + +'pause' + #on("b")#PROC pause (INT CONST time limit) #off("b")# + Wartet 'time limit' in Zehntel-Sekunden. Bei negativen Werten ist die Wirkung + nicht definiert. Die Wartezeit wird nicht nur durch das Erreichen der Grenze ab + gebrochen, sondern auch durch die Eingabe eines beliebigen Zeichens. + + #on("b")#PROC pause#off("b")# + Wartet bis zur Eingabe eines beliebigen Zeichens. + + +#page# + +5.5.2 Zeitmessung + +'clock' + #on("b")#REAL PROC clock (INT CONST index) #off("b")# + Datum und Uhrzeit werden vom EUMEL-System für alle Tasks geführt. Neben + einer Uhr ('Realzeituhr'), die das Datum und die aktuelle Uhrzeit enthält, wird eine + Uhr für die von der Task verbrauchte CPU-Zeit geführt ('CPU-Zeituhr'). Beide + Zeiten werden vom System als REALs realisiert. Die Prozedur 'clock' liefert die + aktuellen Werte dieser Uhren. Bei 'index = 0' wird die akkumulierte CPU-Zeit + der Task, bei 'index = 1' der Wert der Realzeituhr geliefert. + + Mit den REAL-Werten der Uhren kann ohne weiteres gerechnet werden, jedoch + sind nur Werte > 0 definiert. Die REAL-Werte der Realzeituhr beginnen beim + 1.1.1900 um 0 Uhr. Es sind nur Werte für dieses Jahrhundert zugelassen. Werte + der Realzeituhr in lesbarer Form kann man durch die Konvertierungsprozeduren + 'date' (vergl. 5- #topage("date")# ) (für den aktuellen Tag) und 'time of day' (Uhrzeit, vergl. + 5-#topage("time")#) erhalten. + + Um die benötigte CPU-Zeit eines Programms zu berechnen, muß man die + CPU-Zeituhr zweimal abfragen. Um solche Zeiten in lesbarer Form zu erhalten, + kann man die Konvertierungsprozedur 'time' (vergl. 5- #topage("time")#) verwenden. Beispiel: + +____________________________________________________________________________ + + ........................... Beispiel .......................... + REAL CONST anfang :: clock (0); + berechnungen; + REAL CONST ende :: clock (0); + put ("benoetigte CPU-Zeit in Sek:"); + put (time (ende - anfang)) + +____________________________________________________________________________ +#page# +'date' +#goalpage("date")# + #on("b")#TEXT PROC date (REAL CONST time) #off("b")# + Konvertierungsprozedur für das Datum, welches sich aus dem Aufruf der Prozedur + 'clock (1)' ergibt. Das Datum wird in der Form 'tt.mm.jj' geliefert. Beispiel: + +____________________________________________________________________________ + + put (date (clock (1))) (* z.B.: 24.12.87 *) + +____________________________________________________________________________ + + + #on("b")#REAL PROC date (TEXT CONST datum) #off("b")# + Konvertierungsprozedur für ein Datum in der Form 'tt.mm.jj'. Liefert einen + REAL-Wert, wie ihn die Prozedur 'clock (1)' liefern würde. Beispiel: + +____________________________________________________________________________ + + put (date ("24.12.87")) (* 6.273539e10 *) + +____________________________________________________________________________ + + + #on("b")#TEXT PROC date#off("b")# + Liefert das Tagesdatum. Wirkt wie 'date (clock (1))', ist jedoch erheblich schneller. + + + +'day' + #on("b")#REAL CONST day #off("b")# + Liefert die Anzahl der Sekunden eines Tages (86 400.0). + + + +'hour' + #on("b")#REAL CONST hour #off("b")# + Liefert die Anzahl der Sekunden einer Stunde (3600.0). + + + +'pause' + #on("b")#PROC pause (INT CONST time limit) #off("b")# + Wartet 'time limit' in Zehntel-Sekunden. Bei negativen Werten ist die Wirkung + nicht definiert. Die Wartezeit wird nicht nur durch das Erreichen der Grenze ab + gebrochen, sondern auch durch die Eingabe eines beliebigen Zeichens. + + + +'time' +#goalpage("time")# + #on("b")#TEXT PROC time (REAL CONST time) #off("b")# + Konvertierungsprozedur für die Zeiten der CPU-Zeituhr. Liefert die Zeiten in der + Form 'hh:mm:ss.s'. Vergl. dazu 'clock'. + + #on("b")#TEXT PROC time (REAL CONST value, INT CONST laenge) #off("b")# + Konvertiert die Zeit in externe Darstellung. Für die 'laenge'-Werte ergibt sich: + + + laenge = 10 (* hh:mm:ss.s *) + laenge = 12 (* hhhh:mm:ss.s *) + + + + #on("b")#REAL PROC time (TEXT CONST time) #off("b")# + Konvertierungsprozedur für Texte der CPU-Zeituhr in REAL-Werte. + + + +'time of day' + #on("b")#TEXT PROC time of day (REAL CONST time) #off("b")# + Konvertierungsprozedur für REALs, wie sie die Realzeituhr + liefert. Es wird die Tageszeit in der Form 'hh:mm' geliefert. Beispiel: + +____________________________________________________________________________ + + put (time of day (clock (1))) (* z.B.: 17:25 *) + +____________________________________________________________________________ + + + #on("b")#TEXT PROC time of day #off("b")# + Liefert die aktuelle Tageszeit. Entspricht + +____________________________________________________________________________ + + time of day (clock (1)) + +____________________________________________________________________________ +#page# + +5.6 Scanner + +Der Scanner kann benutzt werden, um festzustellen, welche Art von Symbolen in +einem TEXT enthalten sind. Die Repräsentation der Symbole müssen dabei der +ELAN-Syntax entsprechen. Folgende #ib#Symbole#ie# kann der Scanner erkennen: + + - "tags", d.h. Namen, + - "bolds", d.h. Schlüsselworte, + - "number", d.h. INT oder REAL Zahlen, + - Operatoren, + - "delimiter", d.h. Begrenzer wie z.B. ";", + - und das Ende des Scan-Textes. + + +Der Scanner überliest Kommentare und Leerzeichen zwischen den Symbolen. Der +(erste) zu verarbeitende Text muß mit der Prozedur + + + #ib#scan#ie# + + +in den Scanner "hineingesteckt" werden. Mit der Prozedur + + + #ib#next symbol#ie# + + +wird das jeweils nächste Symbol des TEXTes geholt. Am Ende wird "end of scan" +und als Symbol 'niltext' geliefert. Falls innerhalb eines TEXT-Denoters oder eines +Kommentars "end of scan" auftritt, wird "within text" bzw. "within comment" gemel +det. Der Scan-Prozeß kann dann mit dem nächsten zu scannenden TEXT (der +nächsten Zeile) fortgesetzt werden. Dafür wird nicht die Prozedur 'scan', sondern + + + #ib#continue scan#ie# + + +verwandt. Sie setzt im letzten Scan-Zustand (z.B. Kommentar oder TEXT-Deno +ter) wieder auf, so daß auch Folgen von TEXTen (Zeilen) wie z.B. Dateien leicht +gescannt werden können. + +Mit den Prozeduren + + + scan (* meldet eine Datei zum scannen an *) + next symbol (* holt die Symbole *) + + +kann man auch eine Datei nach ELAN-Symbolen untersuchen. + +____________________________________________________________________________ + + FILE VAR f :: ... + ... + scan (f); (* beginnt das Scanning in + der nächsten Zeile *) + TEXT VAR symbol; + INT VAR type; + REP + next symbol (f, symbol, type); + verarbeite symbol + UNTIL type >= 7 END REP. + +____________________________________________________________________________ + +#page# + +Scanner-Kommandos + + +'continue scan' + #on("b")#PROC continue scan (TEXT CONST scan text) #off("b")# + Das Scanning soll mit 'scan text' fortgesetzt werden. Falls der Scan-Vorgang + beim vorigen 'scan text' innerhalb eines TEXT-Denoters oder eines Kommentars + abgebrochen wurde, wird er jetzt entsprechend mit dem nächsten 'next symbol' + fortgesetzt. Der erste Teil-Scan einer Folge muß aber stets mit 'scan' eingeleitet + werden! + +'next symbol' + #on("b")#PROC next symbol (TEXT VAR symbol, INT VAR type) #off("b")# + Holt das nächste Symbol. In "symbol" steht der TEXT des Symbols, so z.B. die + Ziffern eines INT-Denoters. Bei TEXT-Denotern werden die führenden und + abschließenden Anführungsstriche abgeschnitten. Leerzeichen oder Kommentare + spielen in "tags" oder "numbers" keine Rolle. Zwischen Symbolen spielen Leer + zeichen oder Kommentare keine Rolle. In "type" steht eine Kennzeichung für den + Typ des Symbols: + + tag = 1 , + bold = 2 , + number = 3 , + text = 4 , + operator = 5 , + delimiter = 6 , + end of file = 7 , + within comment = 8 , + within text = 9 . + + Wird Scan-Ende innerhalb eines Kommentars gefunden, so wird 'niltext' und + 'within comment' geliefert. Wird Scan-Ende innerhalb eines TEXT-Denoters + gefunden, so wird der schon analysierte Teil des Denoters und 'within text' gelie + fert. + + #on("b")#PROC next symbol (TEXT VAR symbol) #off("b")# + s.o. Es wird aber nur der Text des Symbols (ohne Typ) geliefert. + + #on("b")#PROC next symbol (FILE VAR f, TEXT CONST symbol) #off("b")# + Arbeitet wie obige Prozeduren, jedoch auf einen FILE. + + #on("b")#PROC next symbol (FILE VAR f, TEXT CONST symbol, INT VAR type)#off("b")# + Arbeitet wie obige Prozeduren, jedoch auf einen FILE. + + +'scan' + #on("b")#PROC scan (TEXT CONST scan text) #off("b")# + Meldet einen 'scan text' für den Scanner zur Verarbeitung an. Die Prozedur 'scan' + muß vor dem ersten Aufruf von 'next symbol' gegeben werden. Im Gegensatz zu + 'continue scan' normiert 'scan' den inneren Zustand des Scanners, d.h. vorherige + Scan-Vorgänge haben keinen Einfluß mehr auf das Scanning. + + #on("b")#PROC scan (FILE VAR f) #off("b")# + Wie obige Prozedur, jedoch auf einen FILE. Die zu scannende Zeile ist die näch + ste Zeile im FILE 'f' ('scan' macht zuerst ein 'getline'). + diff --git a/doc/programmer-manual/1.8.7/doc/programmierhandbuch.6 b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.6 new file mode 100644 index 0000000..ce11f6f --- /dev/null +++ b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.6 @@ -0,0 +1,1441 @@ +#pagenr("%",1)##setcount(1)##block##pageblock# +#headeven# +#center#EUMEL-Benutzerhandbuch +#center#____________________________________________________________ + +#end# +#headodd# +#center#TEIL 6 : Das Archiv 'std.zusatz' +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +6 - % #right#GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #right#6 - % +#end# + +TEIL 6: Das Archiv 'std.zusatz' + +Das Archiv 'std.zusatz' enthält Pakete, die nur bei Bedarf insertiert werden sollen. +Eine Einbindung in das EUMEL Grundsystem würde dieses ungebührlich unfangreich +machen. + +Das Archiv enthält zusätzliche Software für: + +- mathematische Operationen : complex , longint , vector , matrix + +- Analyse : reporter , referencer + +- Taschenrechnerfunktion + zur Editor-Erweiterung : TeCal , TeCal Auskunft + + +#page# + +6.1. Erweiterungen um + Mathematische Operationen + + +6.1.1 COMPLEX + +Das Packet COMPLEX erweitert das System um den Datentyp COMPLEX (komplexe +Zahlen) und Operationen auf komplexen Zahlen. Folgende Operationen stehen für +COMPLEX zur Verfügung: + +- Einfache Operatoren : := , = , <> , + ,- , * + +- Eingabe/Ausgabe : get , put + +- Denotierungsprozedur : complex , complex i , complex one , com + plex zero + +- Komponenten : real part , imag part + +- bes. Funktionen : ABS , CONJ , phi , dphi , sqrt + +#page# + +COMPLEX Operationen + + +'TYPE COMPLEX' + Komplexe Zahl, bestehend aud Realteil 're' und Imaginärteil 'im'. + + +':=' + #on("b")#OP := (COMPLEX VAR a, COMPLEX CONST b) #off("b")# + Zuweisung. + + +'=' + #on("b")#BOOL OP = (COMPLEX CONST a, b) #off("b")# + Vergleich von 'a' und 'b' auf Gleichheit. + + +'<>' + #on("b")#BOOL OP <> (COMPLEX CONST a, b) #off("b")# + Vergleich von 'a' und 'b' auf Ungleichheit. + + +'+' + #on("b")#COMPLEX OP + (COMPLEX CONST a, b) #off("b")# + Summe von 'a' und 'b'. + + +'-' + #on("b")#COMPLEX OP - (COMPLEX CONST a, b) #off("b")# + Differenz von 'a' und 'b'. + + +'*' + #on("b")#COMPLEX OP * (COMPLEX CONST a, b) #off("b")# + Multiplikation von 'a' mit 'b'. + + +'/' + #on("b")#COMPLEX OP / (COMPLEX CONST a, b) #off("b")# + Division von 'a' mit 'b'. + +#page# +'get' + #on("b")#PROC get (COMPLEX VAR a) #off("b")# + Einlesen eines komplexen Wertes vom Bildschirm in der Form zweier REAL-De + noter. Die Eingabe kann editiert werden. + + +'put' + #on("b")#PROC put (COMPLEX CONST a) #off("b")# + Ausgabe eines komplexen Wertes auf dem Bildschirm in Form zweier REAL- + Werte. Hinter jedem REAL-Wert wird ein Leerzeichen angefügt. + + +'complex' + #on("b")#COMPLEX PROC complex (REAL CONST re, im) #off("b")# + Denotierungsprozedur. Angabe in kartesischen Koordinaten. + + +'complex i' + #on("b")#COMPLEX PROC complex i #off("b")# + Denotierungsprozedur für den komplexen Wert '0.0 + i 1.0'. + + +'complex one' + #on("b")#COMPLEX PROC complex one #off("b")# + Denotierungsprozedur für den komplexen Wert '1.0 + i 0.0'. + + +'complex zero' + #on("b")#COMPLEX PROC complex zero #off("b")# + Denotierungsprozedur für den komplexen Wert '0.0 + i 0.0'. + + +'imag part' + #on("b")#REAL PROC imag part (COMPLEX CONST number) #off("b")# + Liefert den Imaginärteil des komplexen Wertes 'number'. + + +'real part' + #on("b")#REAL PROC real part (COMPLEX CONST number) #off("b")# + Liefert den Real-Teil des komplexen Wertes 'number'. + + +'ABS' + #on("b")#REAL OP ABS (COMPLEX CONST x) #off("b")# + REAL-Betrag von 'x'. + + +'CONJ' + #on("b")#COMPLEX OP CONJ (COMPLEX CONST number) #off("b")# + Liefert den konjugiert komplexen Wert von 'number'. + + +'dphi' + #on("b")#REAL PROC dphi (COMPLEX CONST x) #off("b")# + Winkel von 'x' (Polardarstellung). + + +'phi' + #on("b")#REAL PROC phi (COMPLEX CONST x) #off("b")# + Winkel von 'x' (Polardarstellung) in Radiant. + + +'sqrt' + #on("b")#COMPLEX PROC sqrt (COMPLEX CONST x) #off("b")# + Wurzelfunktion für komplexe Werte. + +#page# + +6.1.2 LONGINT + +LONGINT ist ein Datentyp, für den (fast) alle Prozeduren und Operatoren des Daten +typs INT implementiert wurden. LONGINT unterscheidet sich von INT dadurch, daß +erheblich größere Werte darstellbar sind. + +Für den Datentyp LONGINT stehen folgende Operationen zur Verfügung: + +- Operatoren : := , = , <> , < , <= ,> , >= , + , - , * , + ** , + ABS , DECR , DIV , INCR , MOD , SIGN + +- Eingabe/Ausgabe : get , put + + +- Math. Prozeduren : abs , int , longint , max , max logint , min , + random , sign , text , zero + + + +LONGINT-Operationen + + +'TYPE LONGINT' + Datentyp + + +':=' + #on("b")#OP := (LONGINT VAR links, LONGINT CONST rechts) : #off("b")# + Zuweisungsoperator + + +'= ' + #on("b")#BOOL OP = (LONGINT CONST links, rechts) #off("b")# + Vergleichen zweier LONGINTs auf Gleichheit. + + +'<>' + #on("b")#BOOL OP <> (LONGINT CONST links, rechts) #off("b")# + Vergleichen zweier LONGINTs auf Ungleichheit. + + +'< ' + #on("b")#BOOL OP < (LONGINT CONST links, rechts) #off("b")# + Vergleichen zweier LONGINTs auf kleiner. + + +'<=' + #on("b")#BOOL OP <= (LONGINT CONST links, rechts) #off("b")# + Vergleichen zweier LONGINTs auf kleiner gleich. + + +'> ' + #on("b")#BOOL OP > (LONGINT CONST links, rechts) #off("b")# + Vergleichen zweier LONGINTs auf größer. + + +'>=' + #on("b")#BOOL OP >= (LONGINT CONST links, rechts) #off("b")# + Vergleichen zweier LONGINTs auf größer gleich. + + +'+ ' + #on("b")#LONGINT OP + (LONGINT CONST argument) #off("b")# + Monadischer Operator. Ohne Wirkung. + + #on("b")#LONGINT OP + (LONGINT CONST links, rechts) #off("b")# + Addition zweier LONGINTs. + + +'- ' + #on("b")#LONGINT OP - (LONGINT CONST argument) #off("b")# + Vorzeichenumkehrung. + + #on("b")#LONGINT OP - (LONGINT CONST links, rechts) #off("b")# + Subtraktion zweier LONGINTs. + + +'* ' + #on("b")#LONGINT OP * (LONGINT CONST links, rechts) #off("b")# + Multiplikation von zwei LONGINTs. + + +'**' + #on("b")#LONGINT OP ** (LONGINT CONST argument, exponent) #off("b")# + Exponentiation zweier LONGINTs mit positivem Exponenten. + + FEHLER : + LONGINT OP ** : negative exponent + Der 'exponent' muß >= 0 sein. + 0 ** 0 is not defined + 'argument' und 'exponent' dürfen nicht gleich 0 sein. + + + #on("b")#LONGINT OP ** (LONGINT CONST argument, INT CONST exponent)#off("b")# + Exponentiation eines LONGINT mit positiven INT Exponenten. + + FEHLER : + LONGINT OP ** : negative exponent + Der 'exponent' muß >= 0 sein. + 0 ** 0 is not defined + 'argument' und 'exponent' dürfen nicht gleich 0 sein. + +'ABS' + #on("b")#LONGINT OP ABS (LONGINT CONST argument) #off("b")# + Absolutbetrag eines LONGINT. + + +'DECR' + #on("b")#OP DECR (LONGINT VAR resultat, LONGINT CONST ab) #off("b")# + resultat := resultat - ab + + +'DIV' + #on("b")#LONGINT OP DIV (LONGINT CONST links, rechts) #off("b")# + Division zweier LONGINTs. + + FEHLER : + Division durch 0 + 'rechts' muß <> 0 sein. + + +'INCR' + #on("b")#LONGINT OP INCR (LONGINT VAR resultat, LONGINT CONST dazu)#off("b")# + resultat := resultat + dazu + + + +'MOD' + #on("b")#LONGINT OP MOD (LONGINT CONST links, rechts) #off("b")# + Modulo-Funktion für LONGINTs. Der Rest einer LONGINT-Division wird ermit + telt. + + FEHLER : + text (links) + 'MOD 0' + 'rechts' muß ungleich null sein. + + +'SIGN' + #on("b")#INT OP SIGN (LONGINT CONST longint) #off("b")# + Feststellen des Vorzeichens von 'longint'. Liefert: + + + 0 wenn 'longint' = 0, + 1 wenn 'longint' > 0, + -1 wenn 'longint' < 0. + + +#page# +'get' + #on("b")#PROC get (LONGINT VAR zahl) #off("b")# + Eingabe eines LONGINTs vom Terminal. + + #on("b")#PROC get (FILE VAR file, LONGINT VAR zahl) #off("b")# + Einlesen von 'zahl' aus der sequentiellen Datei 'file'. Die Datei muß mit 'input' + assoziiert sein (vergl. 'sequential file'). + + FEHLER : + Datei zu + Leseversuch nach Daateiende + Leseversuch auf output-FILE + + +'put' + #on("b")#PROC put (LONGINT CONST longint) #off("b")# + Ausgabe eines LONGINTs auf dem Bildschirm. Anschließend wird ein Leerzeichen + ausgegeben. Hardwareabhängig sind die Aktionen, wenn eine Ausgabe über die + Bildschirmzeilengrenze vorgenommen wird. Meist wird jedoch die Ausgabe auf der + nächsten Zeile fortgesetzt. + + #on("b")#PROC put (FILE VAR file, LONGINT CONST zahl) #off("b")# + Ausgabe von 'zahl' in die sequentielle Datei 'file'. 'file' muß mit 'output' assoziiert + sein. + + FEHLER : + Datei zu + Schreibversuch auf input-FILE +#page# +'abs' + #on("b")#LONGINT PROC abs (LONGINT CONST argument) #off("b")# + Absolutbetrag eines LONGINT. + + +'int' + #on("b")#INT PROC int (LONGINT CONST longint) #off("b")# + Konvertierung von LONGINT nach INT. + + FEHLER : + integer overflow + 'longint' ist größer als 'maxint'. + + +'longint' + #on("b")#LONGINT PROC longint (INT CONST int) #off("b")# + Konvertierung von 'int' nach LONGINT. + + #on("b")#LONGINT PROC longint (TEXT CONST text) #off("b")# + Konvertierung von 'text' nach LONGINT. + + +'max' + #on("b")#LONGINT PROC max (LONGINT CONST links, rechts) #off("b")# + Liefert das Maximum zweier LONGINTs. + + +'maxlongint' + #on("b")#LONGINT PROC max longint #off("b")# + Liefert größten LONGINT Wert. + + +'min' + #on("b")#LONGINT PROC min (LONGINT CONST links, rechts) #off("b")# + Liefert das Minimum zweier LONGINTs. + + +'random' + #on("b")#LONGINT PROC random (LONGINT CONST lower bound, upper bound)#off("b")# + Pseudo-Zufallszahlen-Generator im Intervall 'lower bound' und 'upper bound' + einschließlich. Es handelt sich hier um den 'LONGINT Random Generator'. + + +'sign' + #on("b")#INT PROC sign (LONGINT CONST longint) #off("b")# + Feststellen des Vorzeichens von 'longint'. Liefert: + + + 0 wenn 'longint' = 0, + 1 wenn 'longint' > 0, + -1 wenn 'longint' < 0. + + + +'text' + #on("b")#TEXT PROC text (LONGINT CONST longint) #off("b")# + Konvertierung von 'longint' nach TEXT. + + #on("b")#TEXT PROC text (LONGINT CONST longint, INT CONST laenge) #off("b")# + Konvertierung von 'longint' nach TEXT. Die Anzahl der Zeichen soll 'laenge' + betragen. Für + + + LENGTH (text (longint)) < laenge + + + werden die Zeichen rechtsbündig in einen Text mit der Länge 'laenge' eingetra + gen. Ist der daraus entstehende TEXT kleiner als 'laenge', werden die an 'laenge' + fehlenden Zeichen im TEXT mit Leerzeichen aufgefüllt. Für + + + LENGTH (text (longint)) > laenge + + + wird ein Text mit der Länge 'laenge' geliefert, der mit '*'-Zeichen gefüllt ist. + + +'zero' + #on("b")#LONGINT PROC zero #off("b")# + Liefert LONGINT Wert Null. + + +#page# + +6.1.3 VECTOR + +Der Datentyp VECTOR erlaubt Operationen auf Vektoren aus Elementen vom Typ +REAL. Im Gegensatz zur Struktur 'ROW m REAL' muß die Anzahl der Elemente nicht +zur Übersetzungszeit deklariert werden, sondern kann zur Laufzeit festgelegt werden. +Somit kann eine zur Übersetzungszeit unbekannte Anzahl von REALs bearbeitet +werden, wobei nur soviel Speicherplatz wie nötig verwendet wird. Die maximale Größe +eines VECTOR beträgt 4000 Elemente. + +Der in den Operationen ':=', 'idn' und 'vector' benutzte Datentyp INITVECTOR wird +nur intern gehalten. Er dient der Speicherplatzersparnis bei der Initialisierung. + + +- Operatoren : := , = , <> , + , - , * , / + LENGTH , SUB + +- Eingabe/Ausgabe : get , put + +- Besondere Vector- : length , nilvector , norm , vector , replace + Operationen + +#page# +':=' + #on("b")#OP := (VECTOR VAR ziel, VECTOR CONST quelle) #off("b")# + Zuweisung. Nach der Zuweisung gilt auch + + + length (quelle) = length (ziel) + + + d.h. der linke Operand besitzt nach der Zuweisung genauso viele Elemente wie + 'quelle', unabhängig davon, ob 'ziel' vor der Zuweisung mehr oder weniger Ele + mente als 'quelle' besaß. Beispiel: + + + VECTOR VAR y :: vector (10, 1.0), + z :: vector (15, 2.0); + ... + y := z; (* length (y) liefert nun 15 ! *) + + + #on("b")#OP := (VECTOR VAR ziel, INITVECTOR CONST quelle) #off("b")# + Dient zur Initialisierung eines VECTORs. Beispiel: + + + VECTOR VAR x :: vector (17); + + + 'vector' erzeugt ein Objekt vom Datentyp INITVECTOR. Dieses Objekt braucht + nicht soviel Speicherplatz wie ein VECTOR-Objekt. Dadurch wird vermieden, daß + nach erfolgter Zuweisung nicht ein durch 'vector' erzeugtes Objekt auf dem Heap + unnötig Speicherplatz verbraucht. + + +'=' + #on("b")#BOOL OP = (VECTOR CONST a, b) #off("b")# + Vergleich zweier Vektoren. Der Operator liefert FALSE, wenn die Anzahl der + Elemente von 'a' und 'b' ungleich ist oder wenn zwei Elemente mit gleichem + Index ungleich sind. Beispiel: + + + VECTOR VAR x :: vector (10, 1.0), + y :: vector (15, 2.0), + z :: vector (10, 1.0); + ... x = y ... (* FALSE *) + ... x = z ... (* TRUE *) + + +'<>' + #on("b")#BOOL OP <> (VECTOR CONST a, b) #off("b")# + Vergleich zweier Vektoren auf Ungleichheit (NOT (a = b)). + + +'+' + #on("b")#VECTOR OP + (VECTOR CONST a) #off("b")# + Monadisches '+' für VECTOR. Keine Auswirkung. + + #on("b")#VECTOR OP + (VECTOR CONST a, b) #off("b")# + Elementweise Addition der Vektoren 'a' und 'b'. Beispiel: + + + VECTOR VAR x, (* 'x' hat undefinierte Länge *) + a :: vector (10, 1.0), + b :: vector (10, 2.0); + ... + x := a + b; (* 'x' hat nun 10 Elemente mit Werten'3.0' + *) + + FEHLER : + VECTOR OP + : LENGTH a <> LENGTH b + 'a' und 'b' haben nicht die gleiche Anzahl von Elementen. + + +'-' + #on("b")#VECTOR OP - (VECTOR CONST a) #off("b")# + Monadisches '-'. + + #on("b")#VECTOR OP - (VECTOR CONST a, b) #off("b")# + Elementweise Subtraktion der Vektoren 'a' und 'b'. + + FEHLER : + VECTOR OP - : LENGTH a <> LENGTH b + 'a' und 'b' haben nicht die gleiche Anzahl von Elementen. + +'*' + #on("b")#REAL OP * (VECTOR CONST a, b) #off("b")# + Skalarprodukt zweier Vektoren. Liefert die Summe der elementweisen Multiplika + tion der Vektoren 'a' und 'b'. Beachte eventuelle Rundungsfehler! Beispiel: + + + REAL VAR a; + VECTOR VAR b :: vector (10, 2.0), + c :: vector (10, 2.0); + ... + a := b * c; (* 40.0 *) + + FEHLER : + REAL OP * : LENGTH a <> LENGTH b + 'a' und 'b' haben nicht die gleiche Anzahl von Elementen. + + #on("b")#VECTOR OP * (VECTOR CONST a, REAL CONST s) #off("b")# + Multiplikation des Vektors 'a' mit dem Skalar 's'. + + #on("b")#VECTOR OP * (REAL CONST s, VECTOR CONST a) #off("b")# + Multiplikation des Skalars 's' mit dem Vektor 'a'. + + +'/' + #on("b")#VECTOR OP / (VECTOR CONST a, REAL CONST s) #off("b")# + Division des Vektors 'a' durch den Skalar 's'. Beispiel: + + + VECTOR VAR a, (* 'a' hat undefinierte Laenge *) + b :: vector (10, 4.0); + ... + a := b / 2.0; + (* 'a' hat nun 10 Elemente mit Werten '2.0' *) + + + +'LENGTH' + #on("b")#INT OP LENGTH (VECTOR CONST a) #off("b")# + Liefert die Anzahl der Elemente von 'a'. + + +'SUB' + #on("b")#REAL OP SUB (VECTOR CONST v, INT CONST i) #off("b")# + Liefert das 'i'-te Element von 'v'. + + FEHLER : + OP SUB : subscript overflow + Der Index 'i' liegt außerhalb des Vektors (i > LENGTH v). + OP SUB : subscript underflow + Der Index 'i' liegt außerhalb des Vektors (i < 1). + +#page# +'get' + #on("b")#PROC get (VECTOR VAR a, INT CONST l) #off("b")# + Einlesen der Elemente von 'a' vom Terminal, wobei 'l' die Anzahl der Elemente + angibt. + + FEHLER : + PROC get : size <= 0 + Die angeforderte Elementanzahl 'l' muß > 0 sein. + + +'put' + #on("b")#PROC put (VECTOR CONST v) #off("b")# + Ausgabe der Werte der Elemente von 'v' auf dem Terminal. + + +#page# +'length' + #on("b")#INT PROC length (VECTOR CONST a) #off("b")# + Liefert die Anzahl der Elemente von 'a'. Beispiel: + + + VECTOR VAR a :: vector (10, 1.0), + b :: vector (15, 2.0); + ... + ... length (a) ... (* 10 *) + ... length (b) ... (* 15 *) + + + +'nilvector' + #on("b")#INITVECTOR PROC nilvector #off("b")# + Erzeugen eines Vektors mit einem Element mit dem Wert '0.0'. + + +'norm' + #on("b")#REAL PROC norm (VECTOR CONST v) #off("b")# + Euklidische Norm (Wurzel aus der Summe der Quadrate der Elemente). + + + +'replace' + #on("b")#PROC replace (VECTOR VAR v, INT CONST i, REAL CONST r)#off("b")# + Zuweisung des i-ten Elementes von 'v' mit dem Wert von 'r'. Beispiel: + + + VECTOR VAR v :: ...; + ... + replace (v, 13, 3.14); + (* Das 13. Element von 'v' bekommt den Wert '3.14' *) + + FEHLER : + PROC replace : subscript overflow + Der Index 'i' liegt außerhalb des Vektors (i > LENGTH v). + PROC replace : subscript underflow + Der Index 'i' liegt außerhalb des Vektors (i < 1). + + +'vector' + #on("b")#INITVECTOR PROC vector (INT CONST l) #off("b")# + Erzeugen eines Vektors mit 'l' Elementen. Ein INITVECTOR-Objekt benötigt nicht + soviel Speicherplatz wie ein VECTOR-Objekt. Die Elemente werden mit dem + Wert '0.0' initialisiert. + + FEHLER : + PROC vector : size <= 0 + Die angeforderte Elementanzahl 'l' muß > 0 sein. + + #on("b")#INITVECTOR PROC vector (INT CONST l, REAL CONST value)#off("b")# + Erzeugen eines Vektors mit 'l' Elementen. Ein INITVECTOR-Objekt benötigt nicht + soviel Speicherplatz wie ein VECTOR-Objekt. Die Elemente werden mit dem + Wert 'value' initialisiert. Beispiel: + + + VECTOR VAR v := vector (17, 3.14159); + (* 'v' hat 17 Elemente mit den Wert '3.14159' *) + + FEHLER : + PROC vector : size <= 0 + Die angeforderte Elementanzahl 'l' muß > 0 sein. + +#page# + +6.1.4 MATRIX + +Der Datentyp MATRIX erlaubt Operationen auf m x n Matrizen. Im Gegensatz zur +Struktur 'ROW m ROW n REAL' muß die Anzahl der Elemente nicht zur Überset +zungszeit deklariert werden, sondern kann zur Laufzeit festgelegt werden. Somit kann +eine zur Übersetzungszeit unbekannte Anzahl von REALs bearbeitet werden, wobei +nur soviel Speicherplatz wie nötig verwendet wird. Die maximale Größe einer MATRIX +beträgt 4000 Elemente. + +Der in den Operationen ':=', 'idn' und 'matrix' benutzte Datentyp INITMATRIX wird +nur intern gehalten. Er dient der Speicherplatzersparnis bei der Initialisierung. + + +- Operatoren : := , = , <> , + , - , * + COLUMNS , DET , INV , ROWS , TRANSP , + +- Eingabe/Ausgabe : get , put + +- Besondere Matrix- : column , idn , matrix , row , sub + Operationen transp , + replace column , replace element , + replace row + + + +#page# +':=' + #on("b")#OP := (MATRIX VAR l, MATRIX CONST r) #off("b")# + Zuweisung von 'r' auf 'l'. Die MATRIX 'l' bekommt u.U. eine neue Anzahl von + Elementen. Beispiel: + + + MATRIX VAR a :: matrix (3, 4, 0.0), + b :: matrix (5, 5, 3.0); + ... + a := b; (* 'a' hat jetzt 5 x 5 Elemente *) + + + #on("b")#OP := (MATRIX VAR l, INITMATRIX CONST r) #off("b")# + Dient zur Initialisierung einer Matrix. Beispiel: + + + MATRIX VAR x :: matrix (17, 4); + + + 'matrix' erzeugt ein Objekt vom Datentyp INITMATRIX. Dieses Objekt braucht + nicht soviel Speicherplatz wie ein MATRIX-Objekt. Dadurch wird vermieden, daß + nach erfolgter Zuweisung nicht ein durch 'matrix' erzeugtes Objekt auf dem Heap + unnötig Speicherplatz verbraucht. + +'=' + #on("b")#BOOL OP = (MATRIX CONST l, r) #off("b")# + Vergleich zweier Matrizen. Der Operator '=' liefert FALSE, wenn die Anzahl + Spalten oder Reihen der Matrizen 'l' und 'r' ungleich ist und wenn mindestens ein + Element mit gleichen Indizes der zwei Matrizen ungleiche Werte haben. Beispiel: + + + MATRIX VAR a :: matrix (3, 3), + b :: matrix (3, 3, 1.0), + c :: matrix (4, 4); + ... a = b ... + (* FALSE wegen ungleicher Werte *) + ... a = c ... + (* FALSE wegen ungleicher Groesse *) + ... b = c ... + (* FALSE wegen ungleicher Groesse *) + + + +'<>' + #on("b")#BOOL OP <> (MATRIX CONST l, r) #off("b")# + Vergleich der Matrizen 'l' und 'r' auf Ungleichheit. + + +'+' + #on("b")#MATRIX OP + (MATRIX CONST m) #off("b")# + Monadisches '+'. Keine Auswirkungen. + + #on("b")#MATRIX OP + (MATRIX CONST l, r) #off("b")# + Addition zweier Matrizen. Die Anzahl der Reihen und der Spalten muß gleich sein. + Beispiel: + + MATRIX VAR a :: matrix (3, 43, 1.0), + b :: matrix (3, 43, 2.0), + summe; + summe := a + b; + (* Alle Elemente haben den Wert '3.0' *) + + + FEHLER: + MATRIX OP + : COLUMNS l <> COLUMNS r + Die Anzahl der Spalten von 'l' und 'r' sind nicht gleich. + MATRIX OP + : ROWS l <> ROWS r + Die Anzahl der Zeilen von 'l' und 'r' sind nicht gleich. + + +'-' + #on("b")#MATRIX OP - (MATRIX CONST m) #off("b")# + Monadisches Minus. Beispiel: + + + MATRIX VAR a :: matrix (3, 4, 10.0) + a := - a; (* Alle Elemente haben den Wert '- 10.0' *) + + + #on("b")#MATRIX OP - (MATRIX CONST l, r) #off("b")# + Subtraktion zweier Matrizen. Die Anzahl der Reihen und Spalten muß gleich sein. + + FEHLER: + MATRIX OP - : COLUMNS l <> COLUMNS r + Die Anzahl der Spalten von 'l' und 'r' sind nicht gleich. + MATRIX OP - : ROWS l <> ROWS r + Die Anzahl der Zeilen von 'l' und 'r' sind nicht gleich. + +'*' + #on("b")#MATRIX OP * (REAL CONST r, MATRIX CONST m) #off("b")# + Multiplikation einer Matrix 'm' mit einem Skalar 'r'. Beispiel: + + + MATRIX VAR a :: matrix (3, 4, 2.0); + ... + a := 3 * a; (* Alle Elemente haben den Wert '6.0' *) + + + #on("b")#MATRIX OP * (MATRIX CONST m, REAL CONST r) #off("b")# + Multiplikation einer Matrix 'm' mit einem Skalar 'r'. + + #on("b")#MATRIX OP * (MATRIX CONST l, r) #off("b")# + Multiplikation zweier Matrizen. Die Anzahl der Spalten von 'l' und die Anzahl der + Zeilen von 'r' müssen gleich sein. Beispiel: + + + MATRIX VAR a :: matrix (3, 4, 2.0), + b :: matrix (4, 2, 3.0), + produkt; + produkt := a * b; + (* Alle Elemente haben den Wert '24.0' *) + + + FEHLER : + MATRIX OP * : COLUMNS l <> ROWS r + Die Anzahl der Spalten von 'l' muß mit der Anzahl der Zeilen von 'r' + übereinstimmen. + + #on("b")#VECTOR OP * (VECTOR CONST v, MATRIX CONST m) #off("b")# + Multiplikation des Vektors 'v' mit der Matrix 'm'. + + FEHLER : + VECTOR OP * : LENGTH v <> ROWS m + Die Anzahl der Elemente von 'v' stimmt nicht mit den Anzahl der Zeilen + von 'm' überein. + + #on("b")#VECTOR OP * (MATRIX CONST m, VECTOR CONST v) #off("b")# + Multiplikation der Matrix 'm' mit dem Vektor 'v'. + + FEHLER : + VECTOR OP * : COLUMNS m <> LENGTH v + Die Anzahl der Spalten von 'm' stimmt nicht mit der Anzahl der Ele + menten von 'v' überein. + + +'COLUMNS' + #on("b")#INT OP COLUMNS (MATRIX CONST m) #off("b")# + Liefert die Anzahl der Spalten von 'm'. Beispiel: + + + MATRIX VAR a :: matrix (3, 4), + b :: matrix (7, 10); + put (COLUMNS a); (* 4 *) + put (COLUMNS b); (* 10 *) + + + +'DET' + #on("b")#REAL OP DET (MATRIX CONST m) #off("b")# + Es wird der Wert der Determinanten von 'm' geliefert. + + FEHLER : + OP DET : no square matrix + Die Matrix ist nicht quadratisch, d.h. ROWS m <> COLUMNS m + + +'INV' + #on("b")#MATRIX OP INV (MATRIX CONST m) #off("b")# + Liefert als Ergebnis die Inverse von 'm' (Achtung: starke Rundungsfehler möglich). + + FEHLER: + OP INV : no square matrix + Die Matrix 'm' ist nicht quadratisch, + d.h. ROWS m <> COLUMNS m + OP INV : singular matrix + Die Matrix ist singulär. + + +'ROWS' + #on("b")#INT OP ROWS (MATRIX CONST m) #off("b")# + Liefert die Anzahl der Zeilen von 'm'. Beispiel: + + + MATRIX VAR a :: matrix (3, 4), + b :: matrix (7, 10); + ... + put (ROWS a); (* 3 *) + put (ROWS b); (* 7 *) + + + +'TRANSP' + #on("b")#MATRIX OP TRANSP (MATRIX CONST m) #off("b")# + Liefert als Ergebnis die transponierte Matrix 'm'. + +#page# +'get' + #on("b")#PROC get (MATRIX VAR m, INT CONST rows, columns) #off("b")# + Einlesen von Werten für die Matrix 'm' vom Terminal mit 'rows'-Zeilen und + 'columns'-Spalten. + + +'put' + #on("b")#PROC put (MATRIX CONST m) #off("b")# + Ausgabe der Werte einer Matrix auf dem Terminal. +#page# +'column' + #on("b")#VECTOR PROC column (MATRIX CONST m, INT CONST i) #off("b")# + Die 'i'-te Spalte von 'm' wird als VECTOR mit 'ROWS m' Elementen geliefert. + Beispiel: + + + MATRIX CONST a :: matrix (3, 4); + VECTOR VAR b :: column (a, 1); + (* 'b' hat drei Elemente mit den Werten '0.0' *) + + FEHLER: + PROC column : subscript overflow + Der Index 'i' liegt außerhalb der Matrix 'm' (i > COLUMNS m). + PROC column : subscript underflow + Der Index 'i' liegt außerhalb der Matrix 'm' (i < 1). + +'idn' + #on("b")#INITMATRIX PROC idn (INT CONST size) #off("b")# + Erzeugen einer Einheitsmatrix vom Datentyp INITMATRIX. Beispiel: + + + MATRIX VAR a :: idn (10); + (* Erzeugt eine Matrix mit 10 x 10 Elementen, deren + Werte '0.0' sind, mit der Ausnahme der Diagonalele + mente, die den Wert '1.0' haben.*) + + FEHLER : + PROC idn : size <= 0 + Die angeforderte 'size' Anzahl Spalten oder Zeilen muß > 0 sein. + + +'matrix' + #on("b")#INITMATRIX PROC matrix (INT CONST rows, columns) #off("b")# + Erzeugen eines Datenobjekts vom Datentyp INITMATRIX mit 'rows' Zeilen und + 'columns' Spalten. Alle Elemente werden mit dem Wert '0.0' initialisiert. Beispiel: + + + MATRIX CONST :: matrix (3, 3); + + FEHLER: + PROC matrix : rows <= 0 + Die angeforderte Zeilenanzahl 'rows' muß > 0 sein. + PROC matrix : columns <= 0 + Die angeforderte Spaltenanzahl 'columns' muß > 0 sein. + + #on("b")#INITMATRIX PROC matrix (INT CONST rows, columns, REAL CONST value)#off("b")# + Erzeugen eines Datenobjekts vom Datentyp MATRIX mit 'rows' Zeilen und 'co + lumns' Spalten. Alle Elemente der erzeugten MATRIX werden mit dem Wert + 'value' initialisiert. Beispiel: + + + MATRIX CONST :: matrix (3, 3, 3.14); + + FEHLER: + PROC matrix : rows <= 0 + Die angeforderte Zeilenanzahl 'rows' muß > 0 sein. + PROC matrix : columns <= 0 + Die angeforderte Spaltenanzahl 'columns' muß > 0 sein. + + +'row' + #on("b")#VECTOR PROC row (MATRIX CONST m, INT CONST i) #off("b")# + Die 'i'-te Reihe von 'm' wird als VECTOR mit 'COLUMNS m' Elementen gelie + fert. Beispiel: + + + MATRIX CONST a :: matrix (3, 4); + VECTOR VAR b :: row (a, 1); + (* 'b' hat vier Elemente mit den Werten '0.0'*) + + FEHLER: + PROC row : subscript overflow + Der Index 'i' liegt außerhalb der Matrix 'm' (i > ROWS m). + PROC row : subscript underflow + Der Index 'i' liegt außerhalb der Matrix 'm' (i < 1). + + +'sub' + #on("b")#REAL PROC sub (MATRIX CONST m, INT CONST row, column) #off("b")# + Liefert den Wert eines Elementes von 'm', welches durch die Indizes 'row' und + 'column' bestimmt wird. Beispiel: + + + MATRIX VAR m :: matrix (5, 10, 1.0); + put (sub (m, 3, 7)); + + FEHLER: + PROC sub : row subscript overflow + Der Index 'row' liegt außerhalb von 'm' (row > ROWS m). + PROC sub : row subscript underflow + Der Index 'row' liegt außerhalb von 'm' (row < 1). + PROC sub : column subscript overflow + Der Index 'column' liegt außerhalb von 'm' (column > ROWS m). + PROC sub : row subscript underflow + Der Index 'column' liegt außerhalb von 'm' (column < 1). + + +'transp' + #on("b")#PROC transp (MATRIX VAR m) #off("b")# + Transponieren der Matrix 'm', wobei kaum zusätzlicher Speicherplatz benötigt + wird. + +#page# +'replace column' + #on("b")#PROC replace column (MATRIX VAR m, INT CONST column index, VECTOR + CONST column value) #off("b")# + Ersetzung der durch 'column index' definierten Spalte in der MATRIX 'm' durch + den VECTOR 'column value'. Beispiel: + + + MATRIX VAR a :: matrix (3, 5, 1.0); + VECTOR VAR b :: vector (3, 2.0); + ... + replace column (a, 2, b); + (* Die zweite Spalte von 'a' wird durch die Werte von + 'b' ersetzt *) + + FEHLER: + PROC replace column : LENGTH columnvalue <> ROWS m + Die Anzahl der Zeilen der MATRIX 'm' stimmt nicht mit der Anzahl der + Elemente von 'columnvalue' überein. + PROC replace column : column subscript overflow + Der Index 'columnindex' liegt außerhalb von 'm' + (columnindex > COLUMNS m). + PROC sub : column subscript underflow + Der Index 'columnindex' liegt außerhalb von 'm' (columnindex < 1). + + +'replace element' + #on("b")#PROC replace element (MATRIX VAR m , INT CONST row, column, + REAL CONST value) #off("b")# + Ersetzung eines Elementes von 'm' in der 'row'-ten Zeile und 'column'-ten + Spalte durch den Wert 'value'. Beispiel: + + + MATRIX VAR a :: matrix (5, 5); + ... + replace element (1, 1, 3.14159); + + FEHLER: + PROC replace element : row subscript overflow + Der Index 'row' liegt außerhalb von 'm' (row > ROWS m). + PROC replace element : row subscript underflow + Der Index 'row' liegt außerhalb von 'm' (row < 1). + PROC replace element : column subscript overflow + Der Index 'column' liegt außerhalb von 'm' (column > COLUMNS m). + PROC replace element : row subscript underflow + Der Index 'column' liegt außerhalb von 'm' (column < 1). + + +'replace row' + #on("b")#PROC replace row (MATRIX VAR m, INT CONST rowindex, + VECTOR CONST rowvalue) #off("b")# + Ersetzung der Reihe 'rowindex' in der MATRIX 'm' durch den VECTOR 'rowvalue'. + Beispiel: + + + MATRIX VAR a :: matrix (3, 5, 1.0); + VECTOR VAR b :: vector (5, 2.0); + ... + replace row (a, 2, b); + (* Die 2. Reihe von 'a' wird durch Werte von 'b'ersetzt *) + + FEHLER: + PROC replace row : LENGTH rowvalue <> COLUMNS m + Die Anzahl der Spalten der MATRIX 'm' stimmt nicht mit der Anzahl der + Elemente von 'rowvalue' überein. + PROC replace row : row subscript overflow + Der Index 'rowindex' liegt außerhalb von 'm' + (rowindex > ROWS m). + PROC sub : row subscript underflow + Der Index 'rowindex' liegt außerhalb von 'm' (rowindex < 1). + +6.2 Programmanalyse + +Das Packet 'reporter' ermöglicht: + +a) Ablaufinformationen ("trace"); +b) #ib#Häufigkeitszählung#ie# ("frequency count"); +c) Programmunterbrechung bei Nichterfüllung einer Bedingung ("#ib#assertion#ie#"). + + +'Installation' +Das Programm befindet sich in der Datei 'reporter' und kann wie üblich insertiert +werden. Jedoch muß es mit 'check off' übersetzt werden, damit keine Zeilennummern +für 'reporter' generiert werden. Dies ist notwendig, damit die Zeilennummern des zu +testenden Programms nicht mit den Zeilennummern des Programms 'reporter' ver +wechselt werden können. Beispiel: + + + check off; insert ("reporter"); check on + + +Mit dem Kommando + + + #ib#generate reports#ie# ("testdatei") + + +werden die oben erwähnten Prozeduraufrufe ('#ib#report#ie#') in das zu testende Programm, +welches in der Datei 'testdatei' steht, geschrieben. Die Prozeduraufrufe werden nach +jedem Prozedur-, Operator- oder Refinement-Kopf eingefügt und erhalten den +entsprechenden Namen als Parameter. Diese Prozeduraufrufe werden gekennzeichnet, +damit sie von der Prozedur + + + eliminate reports ("testdatei") + + +automatisch wieder entfernt werden können. Beispiel (für die eingefügten Prozedurauf +rufe): + + + ... + PROC beispiel (INT CONST mist): + \#\#report ("PROC beispiel");\#\# + ... + + + +'Automatische Ablaufinformation' +Ist ein Programm mit 'generate reports' mit 'report'-Aufrufen versehen worden, kann +es wie gewohnt übersetzt werden. Wird das Programm vom ELAN-Compiler kor +rekt übersetzt und dann gestartet, wird bei jedem Antreffen eines 'report'-Aufrufs der +Parameter (Name der Prozedur, Operator oder Refinement) in eine Datei, die +TRACE-Datei geschrieben. Die TRACE-Datei wird beim Programmlauf automatisch +von 'reporter' unter dem Namen 'TRACE' eingerichtet. + +Mit Hilfe dieser Datei kann der Programmablauf verfolgt werden. Es ist damit auch +möglich festzustellen, wo eine "Endlos-Rekursion" auftritt. Die Ablaufinformationen +bestehen nur aus den Namen der angetroffenen Prozeduren und Refinements. Trotz +dem können die Anzahl der Informationen sehr umfangreich werden. Deshalb gibt es +die Möglichkeit, die Erzeugung der Ablaufinformationen ab- bzw. wieder anzuschal +ten. Dazu gibt es die Möglichkeit, in das zu testende Programm die Prozeduren + + + #ib#report on#ie# + #ib#report off#ie# + + +einzufügen und das zu testende Programm mit diesen Prozeduraufrufen (erneut) zu +übersetzen. + + +'Benutzereigene Ablaufinformation' +Zusätzlich zu den von 'generate reports' eingefügten 'report'-Aufrufen kann ein +Benutzer eigene Aufrufe an geeigneten Stellen in ein Programm schreiben. Dafür +werden weitere 'report'-Prozeduren zur Verfügung gestellt, die als ersten Parameter +ein TEXT-Objekt (meist Name des Objekts oder der Ausdruck selbst) und als zwei +ten ein INT/REAL/TEXT/ BOOL-Objekt (der zu überprüfende Wert oder Ausdruck) +enthalten. Beispiel: + + + ... + PROC beispiel (INT CONST mist): + \#\#report ("beispiel");\#\# (* automatisch eingefuegte *) + INT VAR mist :: ...; ... + \#\#report ("mist:", mist);\#\# (* vom Benutzer per Hand einge + fuegt *) + ... + + +Folgende 'report'-Routinen stehen zur Verfügung, damit man sie "von Hand" in ein +zu testendes Programm einfügen kann: + + + PROC report on + PROC report off + PROC report (TEXT CONST message) + PROC report (TEXT CONST message, INT CONST value) + PROC report (TEXT CONST message, REAL CONST value) + PROC report (TEXT CONST message, TEXT CONST value) + PROC report (TEXT CONST message, BOOL CONST value) + + +Wichtig: Hier - wie bei allen anderen "von Hand eingefügten" Aufrufen - sollte +ein Nutzer sich an die Konvention halten, diese in "\#\#" einzuklammern. Mit 'eliminate +reports' werden diese Einfügungen automatisch entfernt. Sollen diese Aufrufe aber +immer im Programm erhalten bleiben (jedoch nicht wirksam sein), sollten sie + +a) vor 'generate reports'-Aufruf mit jeweils '\#\#\#' eingefaßt werden. Beispiel: + \#\#\# report ("...") \#\#\# + So steht das 'report'-Statement in einem Kommentar. 'generate reports' wandelt + '\#\#\#' --> '\#\#\#\#' um, so daß ein solches Statement wirksam wird. 'eliminate + reports' wandelt ein '\#\#\#\#' --> '\#\#\#' zurück. + +b) nach 'generate reports' in '\#\#\#\#' eingefaßt werden. + + +'Häufigkeitszählung' +Eine Häufigkeitszählung erhält man, in dem man in das zu testende Programm die +Aufrufe + + + count on + count off + + +einfügt. Ist die Häufigkeitszählung eingeschaltet, merkt sich 'reporter' die Anzahl der +Durchläufe für jede Prozedur bzw. Refinement. Mit der Prozedur + + + #ib#generate counts#ie# ("zu testende datei") + + +werden die vermerkten Häufigkeiten in das zu testende Programm direkt eingefügt. +Die Häufigkeiten werden wie oben beschrieben gekennzeichnet, so daß sie mit 'elimi +nate reports' entfernt werden können. + + +'Assertions' +Zusätzlich zu den oben erwähnten Möglichkeiten bietet 'reporter' noch die Prozedur + + + #ib#assert#ie# + + +an. Diese Prozedur kann von einem Programmierer an einer Stelle in das zu testende +Programm eingefügt werden, an der bestimmte Bedingungen erfüllt sein müssen. Die +Prozedur 'assert' steht in zwei Formen zur Verfügung: + + + PROC #ib#assert#ie# (BOOL CONST zusicherung) + PROC assert (TEXT CONST message, BOOL CONST zusicherung) + + +Ist der Wert von 'zusicherung' nicht TRUE, wird der Programmlauf abgebrochen. + + + +reporter - Kommandos + + +'count on' + #on("b")#PROC count on #off("b")# + Schaltet die Häufigkeitszählung ein. + +'count off' + #on("b")#PROC count off #off("b")# + Schaltet die Häufigkeitszählung aus. + +'eliminate reports' + #on("b")#PROC eliminate reports (TEXT CONST datei) #off("b")# + Entfernt gekennzeichnete 'report'-Aufrufe aus der Datei 'datei'. + +'generate reports' + #on("b")#PROC generate reports (TEXT CONST datei) #off("b")# + Fügt 'report'-Aufrufe in die Datei 'datei' ein und kennzeichnet diese mit '\#\#'. + +'report on' + #on("b")#PROC report on #off("b")# + Schaltet die Ablaufinformationen in die Datei 'TRACE' ein. + +'report off' + #on("b")#PROC report off #off("b")# + Schaltet die Ablaufinformationen wieder aus. + +'generate counts' + #on("b")#PROC generate counts (TEXT CONST datei) #off("b")# + Bringt die Häufigkeitszählung (wie oft eine Prozedur oder Refinement durchlaufen + wurde) in die Programmdatei 'datei'. Mit 'eliminate reports' werden diese wieder + automatisch entfernt. + +'assert' + #on("b")#PROC assert (TEXT CONST message, BOOL CONST value) #off("b")# + Schreibt 'message' und den Wert von 'value' in die TRACE-Datei. Ist 'value' + FALSE, wird angefragt, ob das Programm fortgesetzt werden soll. +#page# + +Referencer + + +'referencer' wird durch + + + referencer ("ref datei", "referenz liste") + + +aufgerufen, wobei die Datei 'referenz liste' nicht existieren darf. 'referenz liste' enthält +nach Ablauf des Programms die gewünschte Liste, die sogenannte #ib# Referenzliste#ie#. + +#ub#Achtung#ue#: 'referencer' arbeitet ausschließlich mit Namen und verarbeitet nur wenige +syntaktische Konstrukte. Darum ist es nur erlaubt, ein PACKET auf einmal von 'refe +rencer' verarbeiten zu lassen. Verarbeitet man mehrere PACKETs auf einmal, kann es +geschehen, daß gleichnamige Objekte in unterschiedlichen Paketen zu Warnungen +(vergl. die unten beschriebenen Überprüfungen) führen. + +In der Referenzliste sind + +- alle Objekte mit ihrem Namen (in der Reihenfolge ihres Auftretens im Programm) + +- alle Zeilennummern, in der das Objekt angesprochen wird + +- die Zeilennummern, in der das Objekt deklariert wurde ('L' für ein lokales und 'G' + für ein globales Objekt, 'R' für ein Refinement) + +verzeichnet. + +Die Referenzliste kann u.a. dazu dienen, zu kontrollieren, ob und wie (bzw. wo) ein +Objekt angesprochen wird. Dies lohnt sich selbstverständlich nur bei etwas umfan +greicheren Programmen (bei "Mini"-Programmen kann man dies sofort sehen). + +Bei der Erstellung der Referenzliste nimmt das Programm 'referencer' gleichzeitig +einige Überprüfungen vor, die helfen können, ein Programm zu verbessern: + +1. Warnung bei mehrzeiligen Kommentaren. + +2. Überdeckungsfehler. Wird ein Objekt global (auf PACKET-Ebene) und nochmals + lokal in einer Prozedur deklariert, ist das globale Objekt nicht mehr ansprechbar. + Überdeckungen sind nach der gültigen Sprachdefinition z.Zt. noch erlaubt, werden + aber bei einer Revision des Sprachstandards verboten sein. + +3. Mehrmaliges Einsetzen von Refinements. Wird ein Refinement mehrmals einge + setzt (das ist völlig legal), sollte man überlegen, ob sich dieses Refinement nicht + zu einer Prozedur umgestalten läßt. + +4. Nicht angewandte Refinements. Wird ein Refinement zwar deklariert, aber nicht + "aufgerufen", erfolgt eine Warnung. + +5. Nicht angesprochene Daten-Objekte. Werden Daten-Objekte zwar deklariert, + aber im folgenden nicht angesprochen, wird eine Warnung ausgegeben. Hinweis: + Alle Objekte, die nur wenig angesprochen werden, also nur wenige Zeilennum + mern in der Referenzliste besitzen, sind verdächtig (Ausnahmen: importierte + Prozeduren, LET-Objekte u.a.m.). + + + +referencer - Kommandos + + +'referencer' + #on("b")#PROC referencer (TEXT CONST check file, dump file) #off("b")# + Überprüft 'check file'. In 'dump file' steht nach Abschluß die Referenzliste. + +#page# + +6.3 Rechnen im Editor + +Das Programm TeCal ermöglicht einfache Rechnungen (ähnlich wie mit einem Ta +schenrechner) unter der Benutzung des Editors. Gleichzeitig stehen dem Benutzer +aber alle Fähigkeiten des Editors zur Verfügung. TeCal ermöglicht Rechnungen auf +einfache Weise zu erstellen oder Tabellenspalten zu berechnen. Zur Benutzung +müssen 'TeCal' und 'TeCal Auskunft' insertiert werden. + +TeCal wird aus dem Editor heraus durch 'ESC t' oder durch das Editor-Kommando + + + tecal + + +aktiviert. Dadurch wird in der untersten Zeile des Bildschirms eine Informationszeile +aufgebaut, in der die (Zwischen-) Ergebnisse einer Rechnung zur Kontrolle fest +gehalten werden. + + + +Arbeitsweise + + +Wenn TeCal insertiert ist, kann die Taschenrechnerfunktion jederzeit durch <ESC> <t> +aufgerufen werden. Aus der editierten Datei werden Werte mit <ESC> <L> gelesen, +durch <ESC> <+> (bzw. -,*,/) verknüpft und mit <ESC> <S> an die aktuelle Cursor +position geschrieben werden. + +Der von TeCal errechnete Wert wird durch <ESC> <S> derart ausgegeben, daß an der +Stelle an der der Cursor steht die letzte Stelle vor dem Dezimalpunkt geschrieben +wird. + +Die Eingabe von Klammern geschieht durch <ESC> <(> <ESC> <)>. + +Durch die Hilfsfunktion <ESC> <?> lassen sich die TeCal Funktionen auflisten. + +Der Prozentoperator <ESC> <%> erlaubt einfache Rechnungen der Form: 'zahl' <ESC> <+> +<ESC> <%> <ESC> <=> . + +Derartige Folgen können natürlich mit der bekannten Editor-Lernfunktion auch ge +lernt werden, so daß sich z.B. die Mehrwertsteuerberechnung auf wenige Tasten +reduziert. + +Spalten können summiert werden, indem auf der #on("u")#untersten#off("u")# Zahl einer Spalte <ESC> <V> +eingegeben wird. Daraufhin werden alle darüberliegende Zahlen addiert, bis ein +Zeichen auftritt, das nicht in einer Zahl auftritt (Leerzeichen stören nicht!). + +____________________________________________________________________________ + ............ + 55.00 + 66.99 + 123.45 + + 99.99 + + 9876.54 + ........... + + Anzeige: 0.00 14.00% Memory: 0.00 + +____________________________________________________________________________ + + +TeCal Prozeduren + + +'evaluate' + #on("b")#evaluate (TEXT CONST zeile, INT CONST von) #off("b")# + Ausdruck 'zeile' ab der Stelle 'von' berechnen. + + #on("b")#evaluate (TEXT CONST zeile) #off("b")# + Ausdruck 'zeile' ab Stelle 1 berechnen. + + +'kommastellen' + #on("b")#kommastellen (INT CONST stellen) #off("b")# + Berechnungen auf 'stellen' Zahlen hinter dem Komma einstellen. + + +'merke' + #on("b")#PROC merke (INT CONST zahl)#off("b")# + Integer 'zahl' im Merkregister abspeichern. + + #on("b")#PROC merke (REAL CONST zahl)#off("b")# + Real 'zahl' im Merkregister abspeichern. + +'prozentsatz' + #on("b")#PROC prozentsatz (INT CONST zahl) #off("b")# + Prozentsatz von 'zahl' Prozent einstellen. Der Wert wird automatisch konvertiert. + + #on("b")#PROC prozentsatz (REAL CONST zahl) #off("b")# + Prozentsatz von 'zahl' Prozent einstellen. + + +'tecal' + #on("b")#PROC tecal (FILE VAR f) #off("b")# + Datei 'f', die mit 'sequential file' assoziiert ist, mit TeCal editieren. + + #on("b")#PROC tecal (TEXT VAR datei) #off("b")# + 'datei' mit TeCal editieren. + + #on("b")#PROC tecal #off("b")# + Zuletzt editierte Datei mit TeCal editieren. + + +'tecalauskunft' + #on("b")#PROC tecalauskunft #off("b")# + Auskunft zeigen. + + #on("b")#PROC tecalauskunft (TEXT CONST zeichen) #off("b")# + Auskunft zu 'zeichen' zeigen. + diff --git a/doc/programmer-manual/1.8.7/doc/programmierhandbuch.index b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.index new file mode 100644 index 0000000..f3f4ede --- /dev/null +++ b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.index @@ -0,0 +1,449 @@ +#pagenr("%",1)##block##pageblock# +#headandbottom("1","EUMEL-Benutzerhandbuch","INDEX","Index")# +#headeven# +#center#EUMEL-Benutzerhandbuch +#center#____________________________________________________________ + +#end# +#headodd# +#center#INDEX +#center#____________________________________________________________ + +#end# +#bottomeven# +#center#____________________________________________________________ +Index - % #right#GMD +#end# +#bottomodd# +#center#____________________________________________________________ +GMD #right#Index - % +#end# +#lpos(0.2)##lpos(6.2)# + +INDEX + +#table# +* 5-11, 5-18, 5-32, 6-19, 6-27, 6-4, 6-9 +** 5-11, 5-19, 5-60, 6-10 ++ 4-20, 5-11, 5-18, 5-32, 5-54, 6-18, 6-26, 6-3, 6-9 +- 4-20, 5-11, 5-18, 5-54, 6-18, 6-26, 6-3, 6-9 +/ 4-20, 4-22, 5-18, 6-19, 6-4 +:= 2-91, 5-10, 5-17, 5-30, 5-65, 6-17, 6-25, 6-3, 6-8 +< 5-10, 5-17, 5-30, 6-8 +<= 5-10, 5-17, 5-30, 6-8 +<> 5-10, 5-17, 5-30, 6-18, 6-26, 6-3, 6-8 += 5-10, 5-17, 5-30, 6-17, 6-25, 6-3, 6-8 +> 5-10, 5-17, 5-30, 6-9 +>= 5-10, 5-17, 5-30, 6-9 + +Abfragekette 2-25 +ABS 6-10, 6-6 +abs 5-13, 5-20, 6-13 +Abweisende Schleife 2-29 +ALL 4-17 +all 4-17 +AND 5-7 +any 5-54 +Archiv 4-44 +Archivdiskette 4-47 +archive 1-9, 4-24, 4-45 +arctan 5-20 +arctand 5-20 +assert 6-39 +assertion 6-36 +Assertions 6-39 +Ausgabesteuerzeichen 5-70 +Ausschalten des Geräts 1-17 +Automatische Ablaufinformation 6-37 + +begin 2-78, 4-3 +begin password 4-40 +Benutzereigene Ablaufinformation 6-37 +BOOL-Denoter: 2-9 +BOUND 2-83 +bound 5-56 +break 4-4 +brother 4-23 +bulletin 4-8 + +CAND 5-7 +CAT 5-32 +change 5-33 +change 5-61 +change all 5-33 +check 4-49, 5-4 +clear 4-46 +clear removed 5-51 +clock 5-80 +code 5-34 +col 5-48 +column 6-31 +COLUMNS 6-28 +COMPILER ERROR 5-5 +complex 6-5 +complex i 6-5 +complex one 6-5 +complex zero 6-5 +compress 5-34 +configurator 1-9 +CONJ 6-6 +Container 5-26 +continue 4-3 +continue scan 5-83 +copy 4-26, 5-67 +COR 5-7 +cos 5-20 +cosd 5-20 +count off 6-39 +count on 6-39 +cout 5-75 +cursor 5-71 + +dataspaces 5-66 +date 5-81 +Datenraum 1-3 +Datensicherheit 1-8 +day 5-81 +decimal exponent 5-20 +DECR 5-12, 5-19, 6-10 +delete char 5-34 +delete record 5-50 +Der EUMEL-Zeichensatz 5-29 +Der Lernmodus 3-17 +DET 6-28 +DIRFILE 2-73 +DIV 5-12, 6-11 +do 5-2 +down 5-48, 5-57 +downety 5-57 +dphi 6-6 +ds pages 5-66 + +e 5-21 +edit 3-1, 4-29, 5-62 +editget 4-30, 5-63, 5-72 +editor 1-9 +Editor verlassen 3-2 +Ein- bzw. Ausschalten der Markierung 3-9 +Ein- bzw. Ausschalten des Einfügemodus 3-10 +Einfügen von Textpassagen 3-6 +Eingabesteuerzeichen 5-69 +Eingabetaste / Absatztaste 3-4 +eliminate reports 6-39 +Endlosschleife 2-28 +enter password 4-41 +eof 5-43 +erase 4-37 +Erweiterbarkeit 1-6 + +ESC ) 3-16 +ESC ( 3-16 +ESC > 3-16 +ESC < 3-16 +ESC 9 3-14 +ESC 1 3-14 +ESC a 3-16 +ESC A 3-16 +ESC b 3-14 +ESC blank 3-16 +ESC d 3-15 +ESC e 3-14 +ESC ESC 3-16 +ESC f 3-14 +ESC g 3-15 +ESC HOP 3-17 +ESC HOP HOP 3-17 +ESC HOP taste 3-17 +ESC k 3-16 +ESC n 3-14 +ESC O 3-16 +ESC o 3-16 +ESC p 3-15 +ESC q 3-14 +ESC RUBIN 3-15 +ESC RUBOUT 3-15 +ESC s 3-16 +ESC ? taste 3-16 +ESC ! taste 3-16 +ESC U 3-16 +ESC u 3-16 +ESC v 3-14 +ESC w 3-14 +ESC k 3-16 +ESC 3-16 + +EUMEL-Editor 3-1 +evaluate 6-44 +exp 5-21 + +false 5-7 +family password 4-42 +father 4-23 +Fehlermeldungen des Archivs 4-52 +fetch 4-33, 5-67 +fetchall 4-34 +FILE 2-73 +Fixpunkt 1-8 +floor 5-21 +forget 4-26, 4-47, 5-67 +frac 5-21 + +Garbage Collection 5-26 +Gelerntes vergessen 3-17 +generate counts 6-40 +generate reports 6-40 +get 2-80, 5-44, 5-73, 6-5, 6-12, 6-21, 6-30 +getchar 5-72 +get cursor 5-71 +getline 5-45, 5-74 + +Häufige Fehler bei der Benutzung von Datenräumen 2-85 +Häufigkeitszählung 6-36 +halt 4-4 +headline 5-43 +heap size 5-27 +help 4-5, 4-9 +hour 5-81 + +idn 6-31 +imag part 6-6 +inchar 5-72 +incharety 5-72 +INCR 5-12, 5-19, 6-11 +INITFLAG 2-91 +initialized 2-91 +initialize random 5-13, 5-21 +input 2-75, 5-42 +insert 5-2 +insert char 5-35 +insert record 5-50 +Installation 6-36 +int 5-21 +int 6-13 +INT-Denoter: 2-7 +INV 6-28 + +Kommando 1-9 +kommando auf taste 4-31 +kommando auf taste legen 4-31 +Kommando auf Taste legen 3-16 +Kommandotaste 3-11 +kommastellen 6-44 +Konfiguration 1-9 + +length 5-35, 6-22 +LENGTH 5-35, 6-19 +Lernen ausschalten 3-17 +Lernen einschalten 3-17 +lernsequenz auf taste 4-32 +lernsequenz auf taste legen 4-32 +Lese-Fehler (Archiv) 4-52 +LEXEQUAL 5-31 +LEXGREATER 5-31 +LEXGREATEREQUAL 5-31 +lex sort 5-64 +LIKE 4-19, 5-59 +line 5-47, 5-71, 5-77 +line no 5-43 +lines 5-43 +list 4-27 +ln 5-22 +Löschtaste 3-10 +log10 5-22 +log2 5-22 +longint 6-13 + +manager task 1-9 +Mantisse 5-16 +Markierzustand 3-9 +match 5-60 +matchpos 5-60 +matrix 6-32 +max 5-13, 5-22, 6-13 +maxint 5-13 +maxlongint 6-13 +maxreal 5-22 +max text length 5-35 +merke 6-45 +min 5-13, 5-23, 6-14 +minint 5-14 +MOD 5-14, 5-23, 6-11 +modify 2-75, 5-42 +Monitor 1-9 +Multi-Tasking-/Multi-User-Betrieb 1-5 +myself 4-23 + +name 4-25 +Namensverzeichnis 4-16 +Netzwerkfähigkeit 1-6 +new 5-65 +next symbol 5-83 +next symbol 5-85 +Nicht abweisende Schleife 2-29 +nilspace 5-65 +niltask 4-22 +nilvector 6-22 +norm 6-22 +NOT 5-8 +notion 5-56 + +old 5-66 +online 5-79 +Operationen auf Markierungen 3-15 +Operatoren 2-14 +OR 5-8 +OR 5-54 +out 5-75 +output 2-75, 5-42 +out subtext 5-76 + +packets 4-8 +page 5-71 +Paketkonzept 2-1 +pause 5-79, 5-82 +phi 6-6 +pi 5-23 +pos 5-36 +Positionierung 5-71 +Positionierung des Cursors 3-4 +print 4-38 +PRINTER 4-24 +printer 4-24 +Priorität von generischen Operatoren 2-49 +Priorität von Operatoren 2-16 +prot 5-4 +Prozeduren als Parameter 2-39 +Prozeduren mit Parametern 2-38 +prozentsatz 6-45 +Prozeßkommunikation 1-6 +PUBLIC 4-24 +public 4-24 +put 5-46, 5-78, 6-12, 6-21, 6-30, 6-5 +putline 5-46, 5-78 + +random 5-14, 5-23, 6-14 +read record 5-50 +real 5-14, 5-37 +REAL-Denoter: 2-8 +Realisierung von abstrakten Datentypen 2-47 +real part 6-6 +referencer 6-42 +Referenzliste 6-41 +Refinements 2-1 +reinsert 5-51 +release 4-45 +remainder 4-18 +remove 5-51 +rename 4-28 +rename myself 4-25 +reorganize 5-52 +replace 5-37, 6-22 +replace column 6-34 +replace element 6-34 +replace row 6-35 +report 6-36 +report off 6-40 +report on 6-40 +reserve 4-25 +REST 3-6 +round 5-23 +row 6-32 +ROWS 6-29 +run 5-3 +runagain 5-3 + +save 4-35, 5-67 +saveall 4-36 +scan 5-86 +Schreibarbeit beenden 3-2 +Schutz vor fehlerhaftem Zugriff auf Datenobjekte 2-45 +Scratch-Datei 3-13 +segments 5-52 +sequential file 5-41 +SHard 1-5 +show 4-30 +shutup 1-17 +sign 5-15, 5-24, 6-14 +SIGN 6-11 +sin 5-24 +sind 5-24 +smallreal 5-24 +SOME 2-80, 4-17 +son 4-23 +sort 5-64 +Spracherweiterung 2-44 +sqrt 5-24, 6-6 +Standard-Datenraum 1-9 +std tastenbelegung 4-32 +STOP-Taste 3-20 +storage 4-11, 5-66 +storage info 4-5, 4-11 +sub 6-33 +SUB 5-37, 6-20 +subtext 5-38 +supervisor 4-24 +Supervisor 1-9 +SUPERVISOR-Taste 3-18 +Symbole 5-83 +sysin 5-73 +sysout 5-77 + +Tabulatortaste 3-8 +tan 5-25 +tand 5-25 +task 4-22 +Task 1-9 +task info 4-5, 4-12 +Task-Organisation 1-2 +task password 4-43 +task status 4-15 +taste enthaelt kommando 4-31 +tecal 6-45 +tecalauskunft 6-45 +text 5-15, 5-25, 5-39, 6-15 +TEXT-Denoter: 2-9 +Thesaurus 4-16 +time 5-82 +time of day 5-82 +TIMESOUT 5-76 +Titelzeile 3-2 +to line 5-48 +transp 6-33 +TRANSP 6-29 +true 5-8 +type 5-66 +TYPE COMPLEX 6-3 +TYPE LONGINT 6-8 + +Überschrift in die Kopfzeile 5-43 +Umschalttaste 3-4 +UNLIKE 5-59 +Unterbrechen einer Ausgabe 3-20 +up 5-49 +up 5-58 +uppety 5-58 + +vector 6-23 +Vereinbarung eines dyadischen Operators 2-42 +Vereinbarung eines monadischen Operators 2-42 +Verstärkertaste 3-5 +Verwendung von Prozeduren 2-35 +Virtuelle Speicherverwaltung 1-7 +Vorbelegte Tasten 3-17 + +warnings 5-4 +WEITER-Taste 3-20 +Wertliefernde Prozeduren 2-40 +Wertliefernde Refinements 2-34 +word wrap 4-32 +write 5-78 +write 5-47 +write record 5-50 + +XOR 5-8 + +Zählschleife 2-30 +Zeichen schreiben 3-16 +zero 6-15 +#tableend# + diff --git a/doc/programmer-manual/1.8.7/doc/programmierhandbuch.inhalt b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.inhalt new file mode 100644 index 0000000..45b3f1f --- /dev/null +++ b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.inhalt @@ -0,0 +1,249 @@ +#setcount (1)# +#block##pageblock# +#pagenr ("%", 1)# +#headeven# +#center#EUMEL-Benutzerhandbuch +#center#____________________________________________________________ + +#end# +#headodd# +#center#Inhalt +#center#____________________________________________________________ + +#end# +#bottomeven# + +#center#____________________________________________________________ +I - % #right#GMD +#end# +#bottomodd# + +#center#____________________________________________________________ +GMD #right# I - % +#end# + +#lpos(0.2)##lpos(1.8)##lpos(9.0)# + +TEIL 1 : Einleitung +#table# +1.1 Allgemeines über EUMEL 1 +1.2 Struktur des Betriebssystems EUMEL 2 +1.3 Eigenschaften des Betriebssystems 4 + Multi-Tasking-/Multi-User-Betrieb 5 + Prozeßkommunikation und Netzwerkfähigkeit 6 + Erweiterbarkeit 6 + Virtuelle Speicherverwaltung 7 + Datensicherheit 8 +1.4 Wichtige Begriffe 9 +1.5 Die Notation in diesem Buch 10 +1.6 Die Funktionstasten des EUMEL-Systems 11 +1.7 Eine Beispielsitzung 12 +#tableend# + + + + +TEIL 2 : ELAN +#table# +2.1 Besondere Eigenschaften von ELAN 1 +2.2 Lexikalische Elemente 2 +2.2.1 Schlüsselwörter 2 +2.2.2 Bezeichner 3 +2.2.3 Sonderzeichen 4 +2.2.4 Kommentare 5 +2.3 Datenobjekte 6 +2.3.1 Elementare Datentypen 6 +2.3.1.1 Denoter für elementare Datentypen 7 + INT-Denoter: 7 + REAL-Denoter: 8 + TEXT-Denoter: 9 + BOOL-Denoter: 9 +2.3.1.2 LET-Konstrukt für Denoter 10 +2.3.2 Zugriffsrecht 11 +2.3.3 Deklaration 11 +2.3.4 Initialisierung 12 +2.4 Programmeinheiten 13 +2.4.1 Elementare Programmeinheiten 14 +2.4.1.1 Ausdruck 14 + Operatoren 14 + Priorität von Operatoren 16 +2.4.1.2 Zuweisung 18 +2.4.1.3 Refinementanwendung 19 +2.4.1.4 Prozeduraufruf 20 +2.4.2 Zusammengesetzte Programmeinheiten 22 +2.4.2.1 Folge 22 +2.4.2.2 Abfrage 23 +2.4.2.3 Auswahl 26 +2.4.2.4 Wertliefernde Abfrage + und wertliefernde Auswahl 27 +2.4.2.5 Wiederholung 27 + Abfragekette 25 + Endlosschleife 28 + Abweisende Schleife 29 + Nicht abweisende Schleife 29 + Zählschleife 30 +2.4.3 Abstrahierende Programmeinheiten 32 +2.4.3.1 Refinementvereinbarung 32 + Vorteile der Refinementanwendung 33 + Wertliefernde Refinements 34 +2.4.3.2 Prozedurvereinbarung 35 +2.4.3.3 Operatorvereinbarung 41 + Verwendung von Prozeduren 35 + Prozeduren mit Parametern 38 + Prozeduren als Parameter 39 + Wertliefernde Prozeduren 40 + Vereinbarung eines monadischen Operators 42 + Vereinbarung eines dyadischen Operators 42 +2.4.3.4 Paketvereinbarung 43 + Spracherweiterung 44 + Schutz vor fehlerhaftem Zugriff + auf Datenobjekte 45 + Realisierung von abstrakten Datentypen 47 +2.4.4 Terminatoren für Refinements, + Prozeduren und Operatoren 48 +2.4.5 Generizität von Prozeduren und Operatoren 49 + Priorität von generischen Operatoren 49 +2.4.6 Rekursive Prozeduren und Operatoren 50 +2.5 Programmstruktur 52 +2.6 Zusammengesetzte Datentypen 56 +2.6.1 Reihung 56 +2.6.2 Struktur 61 +2.6.3 LET-Konstrukt für + zusammengesetzte Datentypen 64 +2.6.4 Denoter für zusammengesetzte + Datentypen (Konstruktor) 65 +2.7 Abstrakte Datentypen 67 +2.7.1 Definition neuer Datentypen 67 +2.7.2 Konkretisierung 69 +2.7.3 Denoter für abstrakte Datentypen (Konstruktor) 70 +2.8 Dateien 73 +2.8.1 Datentypen FILE und DIRFILE 73 + FILE: 73 + DIRFILE: 73 +2.8.2 Deklaration und Assoziierung 74 + input: 75 + output: 75 + modify: 75 +2.9 Abstrakte Datentypen im EUMEL-System 77 +2.9.1 Datentyp TASK 77 +2.9.2 Datentyp THESAURUS 79 +2.9.3 Datenräume 81 +2.9.3.1 Datentyp DATASPACE 82 +2.9.3.2 BOUND-Objekte 83 + Häufige Fehler bei der Benutzung von Datenräume 85 +2.9.3.3 Definition neuer Dateitypen 88 +2.9.4 Datentyp INITFLAG 91 +#tableend# + + + + +TEIL 3 : Der Editor +#table# +3.1 Ein- und Ausschalten des Editors 1 +3.2 Die Funktionstasten 3 +3.3 Die Wirkung der Funktionstasten 4 +3.4 ESC Kommandos 11 + Operationen auf Markierungen 15 + Zeichen schreiben 16 + Kommando auf Taste legen 16 + Vorbelegte Tasten 17 + Der Lernmodus 17 +3.5 Positionieren, Suchen, Ersetzen + im Kommandodialog 21 + Weitere Hilfen 23 +#tableend# + + + + +TEIL 4 : Kommandosprache +#table# +4.1 Supervisor 2 +4.2 Monitor 6 +4.2.1 Hilfsprozeduren 8 + Informationsprozeduren 11 +4.2.2 Thesaurus 16 +4.2.3 Tasks 21 +4.2.4 Handhabung von Dateien 26 +4.2.5 Editor-Prozeduren 29 +4.2.6 Dateitransfer 33 +4.2.7 Passwortschutz 39 +4.2.8 Das Archiv 44 + Fehlermeldungen des Archivs 52 +#tableend# + + + + +TEIL 5 : Programmierung +#table# +5.1 Der ELAN-Compiler 1 +5.1.1 Fehlermeldungen des ELAN-Compilers 5 +5.2 Standardtypen 7 +5.2.1 Bool 7 +5.2.2 Integer-Arithmetik 9 +5.2.3 Real-Arithmetik 16 +5.2.4 Text 26 + Der EUMEL-Zeichensatz 29 +5.3.1 Assoziierung 41 +5.3.2 Informationsprozeduren 43 +5.3.3 Betriebsrichtung INPUT 44 +5.3.4 Betriebsrichtung OUTPUT 46 +5.3.5 Betriebsrichtung MODIFY 48 +5.3.6 FILE -Ausschnitte 51 +5.4 Suchen und Ersetzen in Textdateien 53 +5.4.1 Aufbau von Textmustern 54 +5.4.2 Suche nach Textmustern 57 +5.4.3 Treffer registrieren 59 +5.4.4 Treffer herausnehmen 60 +5.4.5 Ändern in Dateien 61 +5.4.6 Editor-Prozeduren 62 +5.4.7 Sortierung von Textdateien 64 +5.4.8 Prozeduren auf Datenräumen 65 +5.5 Eingabe/Ausgabe 68 +5.5.1 E/A auf Bildschirm 69 +5.5.1.1 Eingabesteuerzeichen 69 +5.5.1.2 Ausgabesteuerzeichen 70 +5.5.1.3 Positionierung 71 + Grundlegende Prozeduren 72 + Umleitbare Eingabeprozeduren 73 + Grundlegende Prozeduren 75 + Umleitbare Ausgabeprozeduren 77 +5.5.1.4 Eingabe 72 +5.5.1.5 Ausgabe 75 +5.5.1.6 Kontrolle 79 +5.5.2 Zeitmessung 80 +5.6 Scanner 83 + Scanner-Kommandos 85 +#tableend# + + + + +TEIL 6 : Das Archiv 'std zusatz' +#table# +6.1 Erweiterungen um Mathematische Operationen 2 +6.1.1 COMPLEX 2 +6.1.2 LONGINT 7 +6.1.3 VECTOR 16 +6.1.4 MATRIX 24 +6.2 Programmanalyse 36 + reporter - Kommandos 39 + Referencer 41 + referencer - Kommandos 42 +6.3 Rechnen im Editor 43 + Arbeitsweise 43 + TeCal Prozeduren 44 +#tableend# + + + + +Anhang : ELAN-Syntaxdiagramme + + + + +INDEX + diff --git a/doc/programmer-manual/1.8.7/doc/programmierhandbuch.titel b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.titel new file mode 100644 index 0000000..79b09b0 --- /dev/null +++ b/doc/programmer-manual/1.8.7/doc/programmierhandbuch.titel @@ -0,0 +1,52 @@ +____________________________________________________________________________ + + +#on("b")##on ("u")# +#center#Betriebssystem E U M E L +#off ("u")# + + +#center#Programmierhandbuch + + + + +#off("b")# +#center#Lizenzfreie Software der +#on ("b")# + +#center#Gesellschaft für Mathematik und Datenverarbeitung mbH, +#center#5205 Sankt Augustin + + +#off("b")# +#center#Die Nutzung der Software ist nur im Schul- und Hochschulbereich für +#center#nichtkommerzielle Zwecke gestattet. + +#center#Gewährleistung und Haftung werden ausgeschlossen + + +____________________________________________________________________________ +#page# +#block##pageblock# +#start(5.0,1.5)# + +#lpos(3.0)# +#table# + + + + + + +Benutzerhandbuch + +Programmierung + + + +Stand: 1.7.87 + +#tableend##page# + + diff --git a/doc/programmer-manual/1.8.7/source-disk b/doc/programmer-manual/1.8.7/source-disk new file mode 100644 index 0000000..13e2021 --- /dev/null +++ b/doc/programmer-manual/1.8.7/source-disk @@ -0,0 +1 @@ +grundpaket/10_handbuecher.2.img diff --git a/doc/system-manual/1.8.7/doc/systemhandbuch.1 b/doc/system-manual/1.8.7/doc/systemhandbuch.1 new file mode 100644 index 0000000..a8f53bb --- /dev/null +++ b/doc/system-manual/1.8.7/doc/systemhandbuch.1 @@ -0,0 +1,1685 @@ +____________________________________________________________________________ + + +#on("b")##on ("u")# +#center#Betriebssystem E U M E L +#off ("u")# + + +#center#Systemhandbuch + + + + +#off("b")# +#center#Lizenzfreie Software der +#on ("b")# + +#center#Gesellschaft für Mathematik und Datenverarbeitung mbH, +#center#5205 Sankt Augustin + + +#off("b")# +#center#Die Nutzung der Software ist nur im Schul- und Hochschulbereich für +#center#nichtkommerzielle Zwecke gestattet. + +#center#Gewährleistung und Haftung werden ausgeschlossen + + +____________________________________________________________________________ +#page# +#start(5.1,1.5)# +#free(4.0)# +#center#EUMEL + + +#center#Systemhandbuch + + + + + + + + + +#center#copyright ERGOS GmbH, 1990 + + +#page# +#block# + +Copyright: ERGOS GmbH April 1990 + + Alle Rechte vorbehalten. Insbesondere ist die Überführung in + maschinenlesbare Form sowie das Speichern in Informations + systemen, auch auszugsweise, nur mit schriftlicher Einwilligung + der ERGOS GmbH gestattet. + + + +-----------------------------------------------------+ + + + + + + + +Autoren : Jochen Liedtke + Dietmar Heinrichs + Rainer Hahn + Christian Szymanski + Thomas Müller + +Texterstellung : Dieser Text wurde mit der ERGOS-EUMEL Textverarbeitung erstellt + und aufbereitet und auf einem Kyocera Laserdrucker ge + druckt. +#page# + + + + + + + + +----------------------------------------------+ + + + + +#page# + +#start(2.5,1.5)# +#pageblock# +#block# +#headeven# + +%#center#EUMEL-Systemhandbuch + + +#end# +#headodd# + +#center#Einführung#right#% + + +#end# + +#ib(9)#Einführung#ie(9)# + +Der größte Teil dieses Systemhandbuchs ist für Anwender geschrieben, die tiefer in +das EUMEL-System einsteigen und evtl. Systemergänzungen oder Systemänderun +gen programmieren wollen. Der erste Teil ist allerdings für alle interessant, die ein +EUMEL-System verwenden, selbst für Anfänger, die ihr System zum ersten Mal in +Betrieb nehmen wollen. Entsprechend der verschiedenen Adressatenkreise unter +scheiden sich die einzelnen Kapitel stark in der Beschreibungsart. Deshalb: + +#on("b")##on("i")#Sind Sie EUMEL-Neuling?#off("b")##off("i")# + + Dann sollten Sie #on("b")##on("i")#vor#off("b")##off("i")# dem Einschalten Ihres Systems die Einführung des Kapi + tels "System einrichten" lesen. Dort werden keine weiteren Kenntnisse voraus + gesetzt. Danach sollten Sie erst einmal durch praktisches Arbeiten mit Hilfe des + Benutzerhandbuchs etwas mit dem System vertraut werden. + + +#on("b")##on("i")#Haben Sie schon einige Zeit mit dem EUMEL gearbeitet?#off("b")##off("i")# +#on("b")##on("i")#Sind Sie mit dem System einigermaßen vertraut?#off("b")##off("i")# + + Dann lesen Sie den kompletten Teil 1 ("System einrichten") dieses Systemhand + buchs. + Das Lesen der folgenden Kapitel ist für den einfachen Betrieb des EUMEL- + Systems nicht erforderlich. Sie setzen auch intime Kenntnis des Systems auf + dem Niveau des Benutzerhandbuchs voraus und würden Anfänger leicht verwir + ren. + + +#on("b")##on("i")#Haben Sie Probleme mit Ihrer Hardware?#off("b")##off("i")# + + #on("i")#Wenn Sie nichts von Hardware verstehen, wenden Sie sich an einen Fachmann!#off("i")# + + Wenn Sie ein gewisses Grundwissen über Hardware haben, dann lesen Sie Teil 2 + ("Hardware und ihre Steuerung"). In diesem Kapitel sollten Sie "3. Kanä + le und Konfigurierung" erst einmal auslassen. + + +#on("b")##on("i")#Wollen Sie tiefer in das Betriebssystem einsteigen?#off("b")##off("i")# +#on("b")##on("i")#Haben Sie EUMEL-Erfahrung?#off("b")##off("i")# +#on("b")##on("i")#Haben Sie Programmiererfahrung?#off("b")##off("i")# + + Dann lesen Sie im Systemhandbuch alles, was Ihnen interessant erscheint. +#page# +#headeven# + +%#center#EUMEL-Systemhandbuch + + +#end# +#headodd# + +#center#1. System einrichten#right#% + + +#end# + +#ib(9)#1. #ib#System einrichten#ie##ie(9)# + +#ib(9)#1.1. Einführung#ie(9)# + +#ib(9)#Wie Ihr System aufgebaut ist#ie(9)# + +Der kleinstmögliche EUMEL-Rechner besteht aus einem #ib#Rechnerkern#ie# und einem Ter +minal: + + + Rechnerkern Terminal 1 + + + #on("i")#Anmerkung: In manchen Fällen ist das Terminal hardwaremäßig in den Rechner + integriert. Trotzdem fassen wir diese physische Einheit dann als + zwei logisch getrennte Komponenten auf, nämlich Rechnerkern + und Terminal!#off("i")# + +Wie man sieht, hat das #ib#Terminal#ie# die Nummer 1. Das bedeutet, daß es über Kanal 1 mit +dem Rechnerkern verbunden ist. Das EUMEL-System kennt 16 solche #ib#Kanäle#ie#, wobei es +von der konkreten Hardware abhängt, welche Kanäle wirklich vorhanden sind und +welche Geräte man daran anschließen kann. (Allerdings ist der Kanal 1 als Verbindung +zum Terminal 1 immer vorhanden.) + +In den meisten Fällen wird auch ein #ib#Drucker#ie# angeschlossen sein. Die genaue An +schlußart ist wieder von der konkret verwendeten Hardware abhängig. Nehmen wir an, +er sei an Kanal 4 angeschlossen: + + + + Rechnerkern Terminal 1 + + Drucker (Kanal 4) + + + +Man sieht also, daß Lücken bei der Verwendung der Kanäle auftreten dürfen. Bei +Multi-User-Systemen können, sofern die entsprechenden Schnittstellen vorhanden +sind, weitere Terminals und andere Geräte (z.B. #ib#Plotter#ie#) angeschlossen werden: + + + + Rechnerkern Terminal 1 + + Terminal 2 + + Plotter (Kanal 3) + + Drucker (Kanal 4) + + Terminal 5 + + Terminal 6 + + + + + +#ib(9)#1.2. Wie Sie die EUMEL-Software erhalten und + installieren#ie(9)# + + + +Betriebssystem : EUMEL (Version 1.8) +Hardware : IBM-PC/AT, IBM-PC/XT und Kompatible +SHard-Version : 4.9 und 5.0 + +Erforderliche Disketten + + - EUMEL-Generierungsdiskette : "SETUP-EUMEL AT" (bzw. "SETUP- + EUMEL XT") + - EUMEL-Systemdisketten : "HG0" und "HG1" (EUMEL0-Maschine + und Hintergrund) evtl. auch nur eine 1,2 + MB Hintergrunddiskette + +Die Diskette "SETUP-EUMEL" ist ein kleines EUMEL-System zur Installation des Be +triebssystems EUMEL auf einem AT/XT kompatiblen Rechner. Auf diesem System +laufen Programme ab, die im Dialog mit dem Benutzer das Einrichten einer oder +mehrerer EUMEL-Partitionen ermöglichen. +#on("b")#Diese Diskette darf nicht schreibgeschützt sein!#off("b")# + +Beim Einrichten einer EUMEL-Partition wird nach Prüfung der Festplatte durch +"SETUP-EUMEL" der hardwarenahe Teil des EUMEL-Systems, 'SHard' (Software/ +Hardware-Interface), auf die Festplatte geschrieben. + +Die Hintergrunddisketten beinhalten das eigentliche Betriebssystem EUMEL (den +Systemkern (EUMEL-0-Maschine)) und die darauf aufbauenden Systemteile (Hinter +grund)). + + +Leistungen des SETUP EUMEL + +Wenn Sie bereits ein Betriebssystem auf Ihrer Festplatte installiert haben, müssen Sie +darauf achten, daß noch ausreichend Platz für ein EUMEL-System übrig ist. Die Min +destgröße einer Partition für ein EUMEL-System beträgt ca. 1MB, die maximale Größe +ist vom benutzten Systemkern abhängig: der in der Version 1.8.6 M+ verwendete +Systemkern u186+ \#1523 erlaubt eine maximale Größe von 128 MB. Andere, ältere +EUMEL Versionen erlauben nur eine Partitionsgröße von 16 MB. Aus Kompatibilitäts +gründen stellt das Installationsprogramm eine Kontrollfrage bei Überschreiten der 16 +MB Grenze. + +Soll neben EUMEL auch eine MS-DOS Partition auf der Festplatte sein, muß, da +MS-DOS standardmäßig die gesamte Festplatte belegt, dieses System gesichert, mit +dem MS-DOS-Kommando 'fdisk' (o.ä.) die Partition gelöscht und entsprechend kleiner +neu eingerichtet werden. Sie können auch bei der EUMEL-Installation alle bereits +bestehenden Systeme löschen; dazu bietet Ihnen der SETUP-EUMEL die Option +'Löschen der gesamten Partitionstabelle' an. Dabei gehen jedoch alle Daten auf der +Festplatte verloren. Achten Sie also darauf, daß sie alle Daten vorher gesichert haben! + +Um nun die Partitionierung für Ihr EUMEL-System vorzunehmen, legen Sie die Diskette +"SETUP-EUMEL" ohne Schreibschutzmarke in das Start-Laufwerk. Sollten Sie ein Gerät +mit zwei Laufwerken besitzen, dann ist es das Laufwerk A:. (Bei Unklarheiten im Benut +zerhandbuch des Herstellers nachsehen.) + +Schalten Sie nun den Rechner ein bzw. betätigen Sie den Tastatur-RESET, wenn Ihr +Gerät bereits eingeschaltet ist (meistens mit dem gleichzeitigen Druck der Tasten +CTRL, ALT und DEL). + +Der SETUP-EUMEL gibt zunächst folgende SHard-Meldung aus: + ++--------------------------------------------+ +i i +i Setup-SHard für EUMEL auf IBM PC/AT, V 4.8 i +i Copyright (C) 1989 ERGOS GmbH, Siegburg i +i i ++--------------------------------------------+ + +Warten Sie beim Hochfahren des SETUP-EUMELs, bis Ihnen nach einem Zwischen +bildschirm ("SETUP-EUMEL für Modul-SHard") eine Partitionstabelle angezeigt wird. +Dieser können Sie entnehmen, ob bereits Partitionen auf der Festplatte eingerichtet +und wie diese spezifiziert sind. + +Angezeigt werden neben Größe, Start- und Endspur der einzelnen Partitionen auch +eine Typ-Nummer. Für EUMEL-Partitionen werden in aufsteigender Reihenfolge die +Typ-Nummern 69 bis 72, für MS-DOS je nach Größe der eingerichteten Partition die +Nummern 1 oder 4 vergeben. Außerdem wird die gerade aktive Partition durch einen +entsprechenden Eintrag in der Tabelle kenntlich gemacht. "Aktiv" ist die Partition, die +nach dem nächsten Einschalten des Rechners bzw. nach dem nächsten Tastatur- +RESET gestartet würde. + + +Sie sehen zusätzlich ein Menü mit folgenden zur Auswahl stehenden Funktionen: + ++------------------------------------------------------------+ +i i +i - EUMEL-Partition einrichten 1 i +i - erneuern (Neuer SHard) 2 i +i - aktivieren 3 i +i - löschen 4 i +i - Partitionstabelle löschen 5 i +i - SHard-Konfiguration anzeigen 6 i +i - SHard konfigurieren 7 i +i - SHardmodule laden oder löschen 8 i +i - SETUP-EUMEL beenden 0 i +i i ++------------------------------------------------------------+ + +#on("i")##on("u")#EUMEL - Partition einrichten #off("u")##off("i")# + +Eine neue EUMEL-Partition wird gemäß den im weiteren erfragten Angaben eingerich +tet. In die Partition wird ein SHard geschrieben, dessen Konfiguration die gelieferte +Grundkonfiguration oder die von Ihnen eingestellte ist (s. Partitionieren der Festplatte, +Seite 3). + + +#on("i")##on("u")#EUMEL - Partition erneuern (Neuer SHARD)#off("u")##off("i")# + +In eine bereits vorhandene Partition wird ein SHard in der eingestellten Konfiguration +geschrieben. Der bis dahin vorhandene SHard wird überschrieben. Die Möglichkeit +besteht jedoch nur, wenn die Partition mit einem SETUP-EUMEL eingerichtet worden +ist. + +Erneuern bedeutet, nur den SHard #on("u")#auszutauschen#off("u")# auf einer Partition, die schon einen +fertigen EUMEL enthält, ohne daß man dabei den EUMEL löscht. Das ist dann sinnvoll, +wenn man eine neue Version des SHard benutzen möchte oder den SHard aus ir +gendwelchen Gründen (z.B. Streamer gekauft) um einen oder mehrere Module erwei +tern will. + +Diese Aktion kann nur durchgeführt werden, wenn bereits ein SHard mit der Versions +nummer 4.x in dieser Partion vorhanden ist. Ältere (Version 2.7, 2.8 etc.) können #on("u")#nicht#off("u")# +ersetzt werden. + + +#on("i")##on("u")#EUMEL - Partition aktivieren#off("u")##off("i")# + +Eine Partition wird ausgewählt und aktiv gesetzt, d.h. beim nächsten Start des Re +chners wird das System, das auf dieser Partition steht, hochgefahren. + + +#on("i")##on("u")#EUMEL - Partition löschen #off("u")##off("i")# + +Hierbei wird ein Eintrag aus der Partitionstabelle entfernt. Die EUMEL-Partition wird +nicht wirklich gelöscht, d.h. wenn man nach dem Löschen den Plattenbereich noch +nicht anderweitig verwendet hat, kann das EUMEL-System auf dieser Partition durch +ein "EUMEL-Partition einrichten" auf genau demselben Plattenbereich (Start-/Endzy +linder) wieder hergestellt werden. + + +#on("i")##on("u")#Partitionstabelle löschen#off("u")##off("i")# + +Dies ist eine sehr gefährliche Option ! +Es werden hiermit #on("u")##on("b")#alle#off("b")##off("u")# Partitionen auf der Platte gelöscht (nicht nur die von EUMEL). +Auch hier gilt zwar, daß die Partitionen selbst an sich unangetastet bleiben und wie +derhergestellt werden könnten, aber dies ist bei anderen Betriebssystemen oft nicht +möglich. Also #on("u")#VORSICHT#off("u")#. + + +#on("i")##on("u")#SHard-Konfiguration anzeigen #off("u")##off("i")# + +Die Module des SHard, der bereitgestellt ist, um auf die Platte geschrieben zu werden, +werden angezeigt. Es werden alle definierten Kanäle angezeigt und zu jeder Kanal +nummer der assoziierte Modulname. Aufgelistet ist die zuletzt mit dem SETUP-EUMEL +zusammengestellte Konfiguration. + + +#on("i")##on("u")#SHard konfigurieren #off("i")##off("u")# + +Zusammenstellen von einer SHardbasis und SHardmodulen zu einem neuen SHard, +um eine neue Partition einzurichten oder den SHard einer bestehenden Partition zu +ersetzen. +ACHTUNG: Bitte diesen Menuepunkt nicht experimentell benutzen! Eine Anleitung + zum Thema Module etc. wird separat erscheinen. +#page# +#on("i")##on("u")#SHardmodule laden oder löschen #off("u")##off("i")# + +Hiermit können neue Module oder neue Versionen von Modulen in den SETUP-EUMEL +geladen werden oder nicht mehr benötigte Module gelöscht werden. Die neuen Modu +le werden von einer EUMEL-Archivdiskette gelesen, deren Name zuvor eingegeben +werden muß. +ACHTUNG: Bitte diesen Menüpunkt nicht experimentell benutzen! Eine Anleitung + zum Thema Module etc. wird separat erscheinen. + + +#on("i")##on("u")#SETUP-EUMEL beenden #off("u")##off("i")# + +SETUP-Programm ordnungsgemäß beenden. +ENDE-Meldung abwarten! + + + + +Die eigentliche Partitionierung beginnt nun, indem Sie Menü-Punkt 1 "EUMEL-Partition +einrichten" anwählen. (Punkt 1 wird Ihnen nur dann #on("b")#nicht#off("b")# angeboten, wenn die Fest +platte bereits vollständig belegt ist. Sichern Sie dann das alte System und löschen eine +oder alle Partitionen.) Die Kontrollabfrage "Neue EUMEL-Partition einrichten? (j/n)" +beantworten Sie entsprechend mit "j". + +Beim Generieren einer EUMEL-Partition werden Angaben zu Größe und Startzylinder +abgefragt. Dafür werden Vorgaben gemacht, die Sie bestätigen, indem Sie die +<RETURN>-Taste betätigen, oder die Sie überschreiben können. Die abschließende +Abfrage "Sind die Partitionsangaben korrekt?" fordert Sie zur Überprüfung Ihrer Einga +ben auf. + +Nach der Eingabe und der Überprüfung der Sektoren erscheint eine Meldung wie z.B.: + ++--------------------------------------------------+ +i i +i Ich habe keine schlechten Sektoren gefunden i +i SHard wird auf die Partition geschrieben i +i Bitte betätigen Sie eine Taste! i +i i ++--------------------------------------------------+ + +oder + ++--------------------------------------------------+ +i i +i Ich habe 2 schlechte Sektoren gefunden i +i SHard wird auf die Partition geschrieben i +i Bitte betätigen Sie eine Taste! i +i i ++--------------------------------------------------+ + +Danach gelangen Sie wieder in das Generierungsmenü. Wählen Sie "0" für "SETUP- +EUMEL beenden". Über eine Sicherheitsfrage verlassen Sie nun den ersten Teil der +Installation. Warten Sie #on("b")#unbedingt#off("b")#, bis auf dem Bildschirm die Meldung "ENDE" er +scheint, bevor Sie die Diskette "SETUP EUMEL" aus dem Laufwerk nehmen. + + + +Installieren eines EUMEL-Hintergrundes + +Im nächsten Schritt wird auf ihrer Festplatte das vollständige EUMEL-System instal +liert. + +Bitte betätigen Sie den Tastatur-Reset an Ihrem Rechner (oder die Tasten CTRL, ALT +und DEL oder den AUS-/EIN-Schalter). + +Auf dem Bildschirm erscheint die folgende Meldung: + ++--------------------------------------------------------------------------+ +i i +i SHard für EUMEL auf IBM PC,AT,XT, V 4.7 i +i Copyright (c) 1985, 86, 87, 88, 89 Martin Schönbeck Beratungen GmbH, i +i Spenge i +i Ladevorgang kann durch Tastendruck unterbrochen werden i +i Habe leider keine EUMEL-0-Maschine gefunden i +i Ladevorgang unterbrochen, drücken Sie eine Taste um fortzufahren. i +i i ++--------------------------------------------------------------------------+ + +Legen Sie nun die erste Hintergrunddiskette (HG0) in das Laufwerk ein und betätigen +Sie eine Taste. Der Systemkern wird geladen und es erscheinen Angaben zu HG-, +RAM-, und Pufferkapazität sowie zu den angeschlossenen Kanälen, diesmal jedoch +bezogen auf die Festplatten-Partition. Warten Sie nun, bis die Meldung "HG ungültig" +kommt. Drücken Sie anschließend eine beliebige Taste. +Falls Sie in ein bereits bestehendes EUMEL-System einen neuen Urlader einspielen +wollen, lesen Sie bitte den Abschnitt "Installation eines neuen Urladers". + +#page# +#free(1.0)# +Ein Menü bietet Ihnen dann folgende Auswahl: + ++-----------------------------------------+ +i i +i (1) Systemstart i +i (2) Hintergrund vom Archiv laden i +i (3) Hardwaretest i +i (4) neuen Urlader vom Archiv laden i +i i ++-----------------------------------------+ + +Wählen Sie Menü-Punkt (2) "Hintergrund vom Archiv laden" und bestätigen Sie die +Abfrage "Alten HG überschreiben?" mit "j". + +Das Laden des Hintergrundes kann einige Minuten in Anspruch nehmen. Sie werden +mit der Meldung "Nächstes HG-Archiv eingelegt? (j/n)" zum Einlegen der Folgedisket +te(n) aufgefordert, was Sie anschließend mit der Eingabe von "j" quittieren. + +Es können bei beschädigten Disketten Lesefehler auftreten; dann gibt das System eine +der Meldungen 'Harter Lesefehler' bzw. 'Softerror' aus. Bei letzterem könnte der ent +sprechende Sektor nach mehrmaligem Versuch noch gelesen werden. Bei einem +harten Lesefehler können Sie die Diskette nicht verwenden. Bitte benachrichtigen Sie +die Firma, von der Sie die Disketten erhalten haben. + +Wenn der Hintergrund eingelesen ist, erscheint die Aufforderung 'fertig, bitte RESET'. +#on("b")#Vergessen Sie nicht#off("b")#, vor der Betätigung des Tastatur-RESET die Hintergrunddiskette +aus dem Diskettenlaufwerk zu entfernen. + +Wenn Sie während des Hochfahrens keine Taste drücken, dann startet der Lader durch +und das EUMEL-System meldet sich mit einer Tabelle von Geräteanpassungen: + ++--------------------------------------------------------------------------+ +i i +i psi transparent pc.1.25 pc.2.25 i +i pc.3.25 pc.1.24 pc.2.24 pc.3.24 i +i psi25 tandberg.2244s DEC.VT100.ascii DEC.VT100 i +i DEC.VT220.ascii DEC.VT220.german FT10/20.german FT10/20.ascii i +i ampex210.ascii ampex210.german ampex220.german ampex232 i +i Wyse.WY50.ascii Wyse.WY50.german Wyse.WY60.german i +i Wyse.WY120.german i +i i +i Kanal 1 (j/n) i +i i ++--------------------------------------------------------------------------+ + +Da unterschiedliche Tastaturen auch unterschiedliche Tastenbelegungen haben, ist es +notwendig, mit Hilfe der Konfigurationstabelle Ihre Tastatur und Ihren Bildschirm an +das EUMEL-System anzupassen. Dafür bietet Ihnen das System "Kanäle" an. #on("u")#Kanal 1#off("u")# +entspricht dem Haupt-Terminal des Rechners, #on("u")#muß also auf jeden Fall konfiguriert +werden#off("u")#. Beantworten Sie also die Frage "Kanal 1 (j/n)" mit "j". +Das EUMEL-System funktioniert auch, wenn Sie zunächst nur Kanal 1 mit der Anpas +sung konfigurieren, die Ihrem Gerätetyp entspricht. Wenn Ihr Rechner eine AT-Tastatur +hat, ist die korrekte Konfiguration "pc.1"; die Konfigurationen "pc.2" und "pc.3" decken +die meisten der Rechner ab, deren Tastenbelegung von der Standard-AT Tastatur +geringfügig abweicht. Die Erweiterung ".24" bzw. ".25" gibt die Anzahl der Bildschirm +zeilen wieder. Standardmäßig sind im SHard 24 Zeilen eingestellt. + +Weitere Kanäle zum Anschluß von Druckern oder weiteren Terminals können jederzeit +bei Bedarf vorgenommen werden (EUMEL Systemhandbuch Teil 1). +Die Anfrage nach der Konfiguration weiterer Kanäle kann deshalb verneint werden. Die +Abfrage 'koennen unbenutzte Geraetetypen geloescht werden (j/n)' beantworten Sie +einstweilen mit 'n'. Anschließend werden noch Datum und Uhrzeit abgefragt. Damit ist +das Erstinstallationsprogramm abgeschlossen und es erscheint die Meldung 'mainten +ance :'. Geben Sie an dieser Stelle <ESC> <q> (nacheinander) ein. Sie haben damit +die Task 'configurator' ordnungsgemäß verlassen. Erst damit ist sichergestellt, daß die +eingestellte Konfiguration wirksam wird. + + +Installation eines neuen Urladers + +Wenn Sie den alten Urlader mit einem neuen (z.B. protected mode) überschreiben +wollen, starten Sie das EUMEL-System zunächst neu. Sobald die Meldung + + #on("b")#Ladevorgang kann durch Tastendruck unterbrochen werden#off("b")# + +erscheint, drücken Sie eine beliebige Taste (z.B. ENTER). Auf dem Bildschirm er +scheint nun zusätzlich die Meldung + + #on("b")#Ladevorgang unterbrochen, drücken Sie eine Taste um fortzufahren#off("b")# +#page# +Legen Sie nun die Diskette mit dem neuen Urlader in das Bootlaufwerk und drücken +Sie wieder eine beliebige Taste. Danach werden folgende Meldungen auf dem Bild +schirm ausgegeben: + ++-----------------------------------------------------+ +i i +i EUMEL wird von Diskette geladen i +i i +i i +i E U M E L - Vortest i +i i +i Terminals: 1 .... i +i RAM-Groesse (gesamt): .... kB i +i Pufferbereich: .... kB i +i Hintergrund-Speicher .... kB i +i i +i Speichertest: ********** i +i i ++-----------------------------------------------------+ + +In der Zeit, in der die Sternchen des Speichertests erscheinen, drücken Sie bitte wieder +die ENTER-Taste. Nach dem Speichertest erscheint dann folgendes Menü: + ++-----------------------------------------------------+ +i i +i (1) Systemstart i +i (2) neuen Hintergrund vom Archiv laden i +i (3) Hardwaretest i +i (4) neuen Urlader vom Archiv laden i +i i ++-----------------------------------------------------+ + +Wählen Sie Menüpunkt 4 und auf dem Bildschirm erscheinen die folgenden Zeilen: + +#box("-0.1","0.0","8.0","1.0")# + \# xxx + fertig, bitte RESET + +wobei hinter dem \#-Zeichen die übertragenen Blöcke des neuen Urladers gezählt +werden. + +Anschließend entfernen Sie bitte die Urladerdiskette aus dem Laufwerk und drücken +den RESET-Schalter Ihres Rechners. Das EUMEL-Betriebssystem wird nun mit dem +neuen Urlader gestartet. + + +Tastenbelegung: + +EUMEL-Zeichen: Taste auf dem IBM-PC/AT + + MARK : +--------+ + i bild i (oder Pfeil nach oben) + +--------+ + + RUBIN : +--------+ + i Einfüg i + +--------+ + + RUBOUT : +--------+ + i Lösch i + +--------+ + + TAB : +--------+ + i <= => i + +--------+ + + HOP : +--------+ + i Pos 1 i + +--------+ + + ESC : +------------+ + i Eing Lösch i + +------------+ + + SV : +------------+ +-------+ + i CTRL g i oder i F1 i + +------------+ +-------+ + +Bemerkung: Die CTRL-Taste kann auch mit STRG bezeichnet sein. + +Sollte die Tastaturbelegung noch nicht die EUMEL-spezifischen Tasten (HOP, MARK, +SV, RUBIN, RUBOUT) an den entsprechenden Orten anbieten, können Sie durch +Ankoppeln der Task "configurator" und Absetzen des Befehls "configurate" die Tastatu +ren (auch für zusätzlich angeschlossene Terminals) kanalweise umkonfigurieren. Nähe +res entnehmen Sie bitte dem Systemhandbuch, S.6ff. + + +Zusatzprogramme + +Nachdem das System vollständig installiert ist, kann noch typspezifische Software +eingespielt werden. Diese befindet sich auf der Diskette 'EUMEL-Archiv "AT" (bzw. +"XT")'. Der folgende Ablauf skizziert schon das Prinzip jeder Arbeit in einem EUMEL- +System: Task ankoppeln mit 'continue("taskname")' bzw. 'begin("taskname")', Eingabe +von Kommandos wie 'edit', 'run' oder 'generate shutup dialog manager', abschließend +Task abkoppeln durch <ESC> <q>. Eine ausführliche Beschreibung finden Sie in +den EUMEL-Handbüchern. +#page# +Wenn Sie nach Einstellen des Kanals 1 die Task 'configurator' verlassen haben, befin +den Sie Sich auf Supervisor-Ebene. Um die auf der Diskette befindlichen Programme +an der richtigen Stelle zu übersetzen, sind folgende Schritte notwendig: + +Drücken Sie die <SV>-Taste (F1). Damit landen Sie im Supervisor-Menü, dem +Systemverteiler. Mit <ESC> <c> und Eingabe des Tasknamens 'SYSUR' (auf Groß +schreibung achten!) holen Sie die Task 'SYSUR' an das Terminal. Diese Task meldet +sich mit 'maintenance:'. Da Sie mit einem Mehrbenutzersystem arbeiten, müssen Sie +das Diskettenlaufwerk zunächst für sich reservieren: 'archive("AT")'. Erst dann können +Sie Dateien von der Diskette holen: 'fetch("AT install",archive)' und das Installations +programm ausführen: 'run'. Der weitere Ablauf erfordert keine Eingriffe. + +Nach Ablauf der Programme sollten Sie schließlich eine besondere Task zum Abschal +ten einrichten. Dazu müssen Sie nocheinmal die Task 'SYSUR' an den Bildschirm +holen und dort das durch die Zusatzsoftware (u.a.) neu hinzugewonnene Kommando +'generate shutup dialog manager' geben. Nach Absetzen des Kommandos können Sie +'SYSUR' durch <ESC> <q> wieder verlassen. + +Um menügesteuert das Betriebssystem abzuschalten oder einen Partitionswechsel +vorzunehmen, steht Ihnen die Task 'shutup dialog' zur Verfügung. Bei Ausführung des +Supervisor-Kommandos 'continue("shutup dialog")' wird Ihnen die aktuelle Partitions +tabelle angezeigt, so wie Sie diese bereits bei der Generierung kennengelernt haben, +d.h. mit Angabe von Größe, Start- und Endzylinder der eingerichteten Partitionen. Sie +können dann eine beliebige Partition menugesteuert auswählen und starten oder das +Betriebssystem kontrolliert abschalten (sog. 'shutup'). Dabei wird der aktuelle System +zustand automatisch gesichert. + + +Archivformate bei ATs und Kompatiblen mit zwei Diskettenlauf +werken: + +Standardmäßig ist der Archivkanal 31 an das Laufwerk 'A:' gebunden, das eine Kapazi +tät von 1,2 Megabyte besitzt. Ist jedoch bei Ihrem Gerät ein zweites Diskettenlaufwerk, +z.B. mit einer Kapazität von 360 Kilobyte eingebaut, dann können Sie auf dieses Lauf +werk über den Kanal 30 zugreifen. + +Dazu richten Sie unter 'SYSUR' eine Task ein, die Sie z.B. 'ARCHIVE 360' benennen. +Geben Sie in dieser Task das Kommando 'archive manager (30)'; dann können Sie von +jeder Benutzertask das Archiv mit dem Kommando 'archive ("Archivname",/ "ARCHIVE +360")' anmelden. Der Zugriff auf eine Diskette in diesem Laufwerk geschieht z.B. über +'list(/"ARCHIVE 360")' oder 'save ("Dateiname",/"ARCHIVE 360")'. Eine andere Möglich +keit ist ein 3,5" Laufwerk. + + + +Die einzelnen Schritte der Installation im Überblick: + + + 1. Die Diskette 'SETUP-EUMEL' in das Laufwerk stecken. + + 2. Rechner einschalten oder Tastatur-RESET + + 3. EUMEL-Partition einrichten. + + 4. Generierung beenden und auf 'ENDE'-Meldung warten. + + 5. Diskette 'SETUP-EUMEL AT (XT)' entnehmen. + + 6. Tastatur-RESET. + + 7. Die Meldung 'Leider keine EUMEL-0-Maschine gefunden' abwarten. + + 8. Hintergrunddiskette ('HG0') einlegen und Taste drücken. + + 9. Nach der Meldung 'HG-ungültig' eine Taste betätigen, um in den Startdialog zu + gelangen. + + 10. Menupunkt 2 anwählen: Neuen Hintergrund vom Archiv laden. Hintergrunddis + kette einlegen und 'Alten HG überschreiben?' mit "j" quittieren. Folgedisketten + einlegen, sobald entsprechende Meldung ("weiterer Archivträger eingelegt?") + erscheint, und "j" eingeben. + + 11. Hintergrunddiskette entnehmen und anschließend Tastatur-RESET ausführen. + + 12. Kanal 1 konfigurieren. + + + +#ib(9)#1.3. Ausführliche Beschreibung#ie(9)# + + +#ib##ib(9)#System laden#ie##ie(9)# + + +Wie Sie in der Installationsanleitung lesen konnten, geht man beim Systemstart durch +Eingabe eines Zeichens während des Vortests in das Startmenü und wählt dort "Hin +tergrund vom Archiv laden" an. Falls der zu ladende Hintergrund sich über mehrere +Archiv-Disketten erstreckt, werden die folgenden sukzessive angefordert. + + + + +#ib##ib(9)#System sichern#ie##ie(9)# + + +Der aktuelle eigene Hintergrund läßt sich (mit allen Tasks und allen Dateien) durch das +Kommando + + #ib#save system#ie# + +auf Archivdisketten sichern. Dabei wird der Systemzustand zunächst über einen Fix +punkt gesichert. Anschließend werden #on("b")##on("i")#formatierte#off("i")##off("b")# Disketten angefordert. Der Hinter +grund wird komprimiert gesichert, d.h. nur die belegten Blöcke werden auf das Archiv +geschrieben. + +#on("i")#Anmerkung: Diese Prozedur kann nur von privilegierten Tasks (Nachfahren von + "SYSUR"), wie dem OPERATOR, aufgerufen werden. + Vor dem Aufruf von 'save system' sollten Sie genügend Disketten for + matiert haben (Überprüfen Sie mit 'storage info', wieviele Disketten Sie + benötigen, um den gesammten Hintergrund darauf zu schreiben). #off("i")# + + + + +#ib(9)#System gegen Unbefugte schützen#ie(9)# + + +Falls der Benutzerkreis eines Multi-User-Systems nicht "gutartig" ist, sollte man verhin +dern, daß jeder Benutzer des Systems Zugang zu #ib#privilegierten Operationen#ie# hat, wie +Löschen anderer Tasks, Konfiguration ändern und System sichern. + +Dies erreichen Sie dadurch, daß Sie #on("b")#alle#off("b")# privilegierten Tasks, das sind 'SYSUR' und alle +Söhne, Enkel usw. von 'SYSUR', durch #ib#Paßworte#ie# schützen. Damit wird der Zugang zu +diesen Tasks nur möglich, wenn man das entsprechende Paßwort eingibt. Man de +finiert solche #on("i")##on("b")##ib#Task-Paßworte#ie##off("i")##off("b")#, indem man die zu schützende Task mit Hilfe des Super +visor-Kommandos "continue" an ein Terminal holt und dann das Kommando + + #ib#task password#ie# ("simsalabim") + +gibt. Dabei ist "simsalabim" nur ein Beispiel. Bitte verwenden Sie ein anderes Paß +wort! Da die Eigenschaft, privilegiert zu sein, nur davon abhängt, im "SYSUR"-Zweig +(und nicht im normalen "UR"-Zweig) des Systems zu sein, könnte sich ein gewitzter +Anwender die Privilegierung einfach erschleichen, indem er eine neue Sohntask von +"SYSUR" einrichtet. Um auch diese Möglichkeit zu unterbinden, sollte man in #on("b")#jeder#off("b")# +Task des SYSUR-Zweiges ebenfalls ein #on("i")##on("b")#"begin"-Paßwort#off("i")##off("b")# definieren. Das geschieht mit +dem Kommando + + #ib#begin password#ie# ("simsalabim") + +Bei der Wahl der Paßworte sollte man folgendes bedenken: + + - Ein zu kurzes oder offensichtliches Paßwort (beispielsweise der Name des + Systemverwalters) wird von "Hackern" schnell herausgefunden. + + - Oft werden Paßworte bekannt, weil irgendwo ein Zettel mit den Paßworten + herumliegt. + + - Der Paßwortschutz ist hart. Wenn man sein Paßwort vergessen hat, gibt es + keinen Zugang mehr zu der geschützten Task. + + + +Beschreibung der Paßwortprozeduren: + +#ib#task password#ie# + PROC task password (TEXT CONST password) + Zweck: Einstellen eines Paßwortes für eine Task im Monitor. + +#ib#begin password#ie# + PROC begin password (TEXT CONST password) + Zweck: Verhindert das unberechtigte Einrichten einer Sohn-Task. + Anmerkung: Das 'begin password' vererbt sich auf die später erzeugten Sohn- + Tasks. + +#ib#family password#ie# + PROC family password (TEXT CONST password) + Zweck: Setzt oder ändert das Paßwort derjenigen Familienmitglieder, die kein + Paßwort oder das gleiche Paßwort wie die aufrufende Task haben. + Zu einer Familie gehören die Task in der man sich befindet und die ihr + untergeordneten Tasks. + Bsp.: Das Kommando 'family password ("EUMEL")' wird in SYSUR + gegeben. Dadurch wird das SYSUR-Paßwort und die Paßworte + der entsprechenden Tasks unter SYSUR auf "EUMEL" gesetzt. + + + +#ib##ib(9)#Konfiguration#ie##ie(9)# + +Die #ib#Konfiguration#ie# läuft über die Task "#ib#configurator#ie#" ab. Diese Task müssen Sie also für +die hier aufgeführten Operationen durch das Supervisor-Kommando "continue" an +koppeln (Dabei wird das Paßwort überprüft, falls die Task geschützt wurde). + +#on("i")#Anmerkung: Man kann die Task "configurator" löschen und dann neu (als Sohn, En + kel,... von SYSUR) wieder einrichten. Danach holt man die Konfigura + tionsdatei (z.B. von std.devices) und gibt das Kommando "#ib#configuration + manager#ie#".#off("i")# + + +Der in der Einführung unter "Wie Sie die Konfiguration einstellen" beschriebene Konfi +gurationsdialog läßt sich vermittels des Kommandos + + #ib#configurate#ie# + +aufrufen. Dabei wird für jeden angewählten Kanal die bis jetzt gültige Einstellung als +Vorschlag mit ausgegeben. Die Einstellung aller Kanäle, die nicht angesprochen wer +den, bleibt unverändert. + +Im Menü werden die Namen aller Dateien mit #ib#Gerätetabellen#ie# aufgeführt, die in der +Task enthalten sind. Daraus folgt, daß nur noch die bei der letzten Konfigurierung +benutzten Typen aufgeführt werden, wenn vorher auf die Frage "Koennen unbenutzte +Geraetetypen geloescht werden (j/n)?" mit "j" geantwortet wurde. Löschen Sie also +nicht alle unbenutzten Gerätetypen, wenn Sie sie später evtl. nochmal bruachen (siehe +auch "Teil 2, 3. Kanäle und Konfigurierung"). + +Im Konfigurationsdialog kann folgendes eingestellt werden: + + #ib#Typ#ie# Es werden alle vorhandenen Gerätetabellen durchgegangen, bis + eine davon ausgewählt wurde. Diese manchmal etwas langwierige + Arbeit kann man durch Eingabe des Zeichens ESC abkürzen: + Danach kann man den Typnamen direkt eingeben. #on("i")#Das funktioniert + aber nur vernünftig, wenn das eigene Arbeitsterminal bereits richtig + konfiguriert worden ist!#off("i")# + + #ib#Baudrate#ie# (nur für V.24-Kanäle von Bedeutung) Es werden alle einstellbaren + Baudraten durchgegangen, bis eine davon ausgewählt wurde. Das + sind die Werte 50, 75, 110, 134.5, 150, 300, 600, 1200, 1800, 2400, + 3600, 4800, 7200, 9600, 19200, 38400 Baud. + + #ib#Bits#ie# (nur für V.24-Kanäle von Bedeutung) Es werden die einstellbaren + Zeichengrößen durchgegangen, d.h. 7 oder 8 Bit pro Zeichen. + + #ib#Parität#ie# (nur für V.24-Kanäle von Bedeutung) Möglich sind die Einstellun + gen 'no', 'even' und 'odd'. + + #ib#Stopbits#ie# (nur für V.24-Kanäle von Bedeutung) Stopbits geben die Pause + zwischen zwei aufeinanderfolgenden Zeichen an. Möglich sind 1 + oder 2 Stopbits. + + + #ib#Protokoll#ie# Terminals u.ä. werden üblicherweise ohne Protokoll angeschlossen. + Bei langsamen Geräten wie Druckern bzw. Plottern oder aber bei + Rechnerkopplungen bzw. Netzen kann der Empfänger nicht immer + so schnell Zeichen annehmen wie sie von der Gegenstation gesen + det werden. In diesem Fall kann man das #ib#XON/XOFF-#ie# oder das + #ib#RTS/CTS-Protokoll#ie# einstellen. + #on("b")#BEACHTE: Sender und Empfänger müssen auf das gleiche Proto + koll eingestellt sein.#off("b")# + + Manchmal müssen auch Terminals mit Protokoll angeschlossen + werden. Üblicherweise wählt man dann aber ein rein ausgabe + seitiges Protokoll, damit SV den EUMEL auf jeden Fall erreicht. + Es gibt folgende Protokolle: + + #ib#XON/XOFF-Protokoll#ie#: + Rechner und Gerät steuern die Sendungen jeweils über + XON/XOFF-Zeichen. + #ib#RTS/CTS-Protokoll#ie#: + Rechner und Gerät steuern ihre Sendungen jeweils über + RTS/CTS- Leitungen. + #ib#XON/XOFF-ausgabeseitig#ie#: + Das angeschlossene Gerät steuert die Ausgabe über + XON/XOFF.Eingaben zum Rechner unterliegen keinem + Protokoll. + #ib#RTS/CTS-ausgabeseitig#ie#: + Das angeschlossene Gerät steuert die Ausgabe über + RTS/CTS. Eingaben zum Rechner unterliegen keinem + Protokoll. + #ib#XON/XOFF-eingabeseitig#ie#: + Der EUMEL-Rechner steuert die angeschlossenen + Geräte durch XON/XOFF. Die Ausgaben zum Gerät + unterliegen keinem Protokoll. + #ib#RTS/CTS-eingabeseitig#ie#: + Der EUMEL-Rechner steuert die angeschlossenen + Geräte durch RTS/CTS. Die Ausgaben zum Gerät unter + liegen keinem Protokoll. + + #ib#Puffer#ie# Terminals und alle Ausgabegeräte (Drucker u.ä.) haben standard + mäßig die normalen "kleinen" Eingabepuffer im System zugeord + net. Bei Rechner-Rechner-Kopplungen, DFÜ oder Netzen kann ein + "großer" #ib#Eingabepuffer#ie# von 512 Byte notwendig werden. Dement + sprechend sind #ib#Großpuffer#ie# nur beim Schnittstellentyp 'transparent' + möglich. + +Im #ib#Konfigurationsdialog#ie# werden bei jedem Kanal nur die dort vorhandenen Möglich +keiten angeboten. Dabei wird die vorherige Einstellung immer als erste angeboten. So +kann man sich verhältnismäßig einfach "durchtasten". + +Die Fragen des #ib#Konfigurationsdialog#ie#s werden nach folgendem Schema gestellt: + +#linefeed(1.18)# + erfrage ("Kanal") ; + erfrage ("Typ") ; + IF dieses ist ein v24 kanal + THEN IF baudrate einstellbar + THEN erfrage ("Baudrate") + FI ; + IF zeichengroesse einstellbar + THEN erfrage ("Bits") + FI ; + IF parität einstellbar + THEN erfrage ("Parität") + FI ; + IF stopbits einstellbar + THEN erfrage ("Stopbits") + FI ; + FI ; + erfrage ("Protokoll") ; + IF typ ist tranparent + THEN erfrage ("Puffer") + FI. + +#linefeed(1.0)# +Will man seine eingestellte #ib#Konfiguration sichern#ie#, reicht es, alle Dateien der Task +"#ib#configurator#ie#" auf ein Archiv zu schreiben. Diese Konfiguration kann man dann bei +einem neuen Hintergrund einfach vom Archiv laden. Um die Konfigurierung dann auch +auszuführen, gibt man das Kommando "setup". + + + + +#ib##ib(9)#Druckersoftware einrichten#ie##ie(9)# + + + +Das Standardarchive "std.printer" enthält einige Druckeranpassungen für die Ansteu +erung diverser Druckertypen. Soll einer dieser Druckertypen an das EUMEL-System +angeschlossen werden, so muß zuerst eine Task "#ib#PRINTER#ie#" (als Sohntask von +"SYSUR" mit dem Supervisorkommando) vorhanden sein bzw. durch + + + begin ("PRINTER", "SYSUR") + + +eingerichtet werden. In dieser Task müssen dann die folgenden Schritte vollzogen +werden: + +- Anmelden des Archivs: + + archive ("std.printer") + + +- Holen der Druckeranpassung vom Archiv: + + fetch ("druckertyp.inserter", archive) + + +- Insertieren der Druckeranpassung: + + insert ("druckertyp.inserter") + + + +Beispiel: + archive ("std.printer") + fetch ("laser.inserter", archive); + check off; + insert ("laser.inserter") + + +Nach Beendigung der Kompilierung finden Sie sich in einem Menü wieder, daß Ihnen +die Auswahl Ihres Drucker-Herstellers durch die Eingabe der vor dem Firmennamen +stehenden Zahl erlaubt. Diese Eingabe schicken Sie mit RETURN ab. Da Hersteller +mitunter verschiedene Modelle mit verschiedenen Funktionen anbieten, ist es nötig, +daß Sie Ihr Modell auswählen. Auch diese Eingabe wird durch RETURN abgeschickt. +Nachdem Sie die Nummer des gewünschten Druckers eingegeben haben, erfolgt noch +einmal eine Sicherheitsabfrage, ob dieser Drucker installiert werden soll. + +Neben den speziell zu dem gewählten Drucker passenden Fragen (z.B. NLQ-Modus +standardmäßig) ist es erforderlich, den Kanal einzugeben, an dem der Drucker ange +schlossen ist (z.B. Kanal 15 für eine parallele Schnittstelle). + +Wenn die Generierung beendet ist, muß in allen bestehenden Tasks - insbesondere in +der Task 'PUBLIC' - die Fonttabelle mit dem fonttable-Kommando eingestellt werden. +Mit dem Kommando + + + print ("dateiname") + + +wird dann eine Datei ausgedruckt. + +Befindet sich keine passende Druckeranpassung für den anzuschließenden Drucker +typ auf dem Standardarchiv "std.printer", so sollte die Druckeranpassung "printer.std" +benutzt werden. Diese Druckeranpassung ist eine universelle Druckeranpassung für +alle Drucker, die mit ASCII-Code 13 ein 'Carriage Return' (d.h. Bewegung des Druck +kopfes an den linken Rand) und mit ASCII-Code 10 eine Zeilenschaltung von 1/6 Zoll +vornehmen. Mit ihr kann dann in einem Schrifttyp (entweder 10 oder 12 Zeichen pro +Zoll, je nachdem welche Fonttabelle eingestellt ist) gedruckt werden. So erhält man +wenigstens eine Minimalansteuerung des Druckers. Für eine bessere Ansteuerung des +Drucker muß ein Programm geschrieben werden, das das Druckertreiber-Interface +erfüllt (siehe Teil 6 "Der EUMEL-Drucker") und eine Fonttabelle erstellt (siehe Teil 7 "Der +Fontspeicher") werden. +#page# +#headeven# + +%#center#EUMEL-Systemhandbuch + + +#end# +#headodd# + +#center#2. Hardware und ihre Steuerung#right#% + + +#end# + + +#ib(9)#2. Hardware und ihre Steuerung#ie(9)# + + + + +#ib(9)#2.1. Vorwort#ie(9)# + + +Die #ib#Hardware#ie# eines jeden EUMEL-Systems läßt sich in #ib#Rechnerkern#ie# und Peripherie +einteilen. + + +a) Der #ib#Rechnerkern#ie# + + +In der Regel wird der Rechnerkern aus folgenden Komponenten bestehen: + + - #ib#CPU#ie# + - #ib#Vordergrundspeicher#ie# (oft als RAM bezeichnet) + - #ib#Hintergrundspeicher#ie# (Floppy, Harddisk, oder auch RAM/ROM) + +Alle Daten, Dateien und Programme werden auf dem Hintergrundspeicher abgelegt. +Der benötigte Platz wird dabei dynamisch nach Bedarf zugewiesen. Jeder Zugriff auf +Daten, die sich auf dem Hintergrundspeicher befinden, muß über den Vordergrund +speicher erfolgen. Zu diesem Zweck verlagert das EUMEL-System automatisch alle +aktuell benötigten Daten in den Vordergrundspeicher. Das erfolgt nach dem Prinzip +des #ib#Demand-Paging#ie# (s. Benutzerhandbuch Kap. 1). Die CPU führt die aktiven Pro +gramme (unter Benutzung des Speichers) aus. Dabei bearbeitet sie reihum alle re +chenwilligen Prozesse. +Die drei Komponenten des Rechnerkerns werden vollständig vom EUMEL-Betriebs +system verwaltet und miteinander verknüpft, so daß der Anwender sich in der Regel +darum weder kümmern muß noch kann. Ausgenommen davon sind allerdings die +Diagnose von Hardwarefehlern und Überlegungen zur Systemleistung. + + +b) Die #ib#Peripherie#ie# + + +Alle anderen Geräte oder Gerätekomponenten gehören aus der Sicht des EUMEL- +Systems zur Peripherie. Wesentliches Kennzeichen ist, daß sie über Kanäle mit dem +Rechnerkern verbunden sind und von dort aus durch System- und Anwender +programm gesteuert werden können. Angeschlossen werden können u.a. + + - #ib#Terminal#ie#s + - #ib#Drucker#ie# und #ib#Plotter#ie# + - andere #ib#Rechner#ie# bzw. #ib#Rechnernetze#ie# + - #ib#Archivgerät#ie#e (z.B. Floppy-Laufwerke) + +In der Regel hat jedes EUMEL-System mindestens ein #ib#Terminal#ie# und #ib#Archivlaufwerk#ie#. +Auch wenn dieses "Terminal 1" und das Floppy-Laufwerk baulich in den Rechner +integiert sind, gehören sie logisch zur Peripherie. Die entsprechenden Kanäle sind +dann allerdings Teil des Rechners und brauchen den Anwender nicht zu interessie +ren. Die beiden wesentlichen anderen Kanaltypen sind: + + - #ib#serielle Schnittstelle#ie#n (#ib#V.24#ie#) + - #ib#Parallelschnittstellen#ie# + +Beide führen "echt" aus dem Rechner heraus und sind u.U. hardwaremäßig für den +Anwender von Bedeutung. Normalerweise sollte zwar der Lieferant der EUMEL- +Hardware für die Verkabelung und den Anschluß peripherer Geräte sorgen, aber +Kenntnisse können in Fehlersituationen (z.B. Kabelbruch), bei Umkonfigurierungen +und bei Kombinationen verschiedener Geräte helfen. + + + + +#ib(9)#2.2. #ib#Hardware-Test#ie##ie(9)# + + + +Der EUMEL-Hardware-Test ist ein rechnerunabhängiger Test und kann demzufolge +nicht so viel überprüfen wie Testprogramme, die genau auf eine entsprechende Hard +ware zugeschnitten sind. Trotzdem sollten die meisten Hardware-Fehler schon mit +dem EUMEL-#ib#Hardware-Test#ie# gefunden werden. + +Bei jedem Systemstart wird der "#ib#Vortest#ie#" durchgeführt. Nachdem er Terminals, Spei +cher und Hintergrund angezeigt hat, testet er einmal den Hauptspeicher. Danach wird +das eigentliche EUMEL-System gestartet. + + +Durch Eingabe eines beliebigen Zeichens während des Vortests (Speichertest: +*********) kommt man in den ausführlichen #ib#Start-Dialog#ie#. Dort wird u.a. auch die +Möglichkeit "Hardware-Test" angeboten. Wählt man diese an, werden die verfügbaren +Tests als Menü aufgelistet. Bei jedem EUMEL-System stehen folgende Testmöglichkei +ten zur Verfügung: + + (1) #ib#Speichertest#ie# + (2) #ib#Kanaltest#ie# + (3) #ib#Hintergrundtest#ie# + (4) #ib#Archivtest#ie# + +Alle Tests sind dabei Dauertests, d.h. sie beginnen nach jedem Durchlauf von neu +em, können aber durch <ESC> abgebrochen werden. + + + + + +#ib##ib(9)#Speichertest#ie##ie(9)# + + +Der #ib#Speichertest#ie# soll den Vordergrundspeicher (#ib#RAM#ie#) des Rechners untersuchen. +Gerade #ib#Speicherfehler#ie# tendieren aber dazu, nur sporadisch aufzutreten oder wär +meabhängig zu sein. Deshalb sollte der Test bei Verdacht auf Speicherfehler längere +Zeit (einige Stunden) laufen. Leider können auch dann nicht alle Fehler aufgedeckt +werden, z.B. nicht solche, die nur in ganz speziellen Situationen entstehen, wie Spei +cherzugriff mit gleichzeitig anlaufendem Floppymotor und Zeichenausgabe. Generell +gilt hier (wie für jeden Test), daß das Nichtvorhandensein von Fehlern nie Vollkommen +sicher nachgewiesen werden kann. + +Der Speichertest teilt den Speicher in drei verschiedene Bereiche auf: + + 0 : adresse MOD 3 = 0 + 1 : adresse MOD 3 = 1 + 2 : adresse MOD 3 = 2 + +Der freie Speicher wird nach folgendem Algorithmus geprüft: + + schreibe (1, OLOLOLOL) ; out ("*") ; + schreibe (2, OLOLOLOL) ; out ("*") ; + schreibe (0, LOLOLOLO) ; out ("*") ; + pruefe (1, OLOLOLOL) ; out ("*") ; + schreibe (1, LOLOLOLO) ; out ("*") ; + pruefe (2, OLOLOLOL) ; out ("*") ; + pruefe (0, LOLOLOLO) ; out ("*") ; + pruefe (1, LOLOLOLO) ; out ("*") ; + schreibe (0, OLOLOLOL) ; out ("*") ; + pruefe (0, OLOLOLOL) ; out ("*") ; + schreibe (2, LOLOLOLO) ; out ("*") ; + pruefe (2, LOLOLOLO) ; out ("*") . + + +Dabei werden durch 'PROC schreibe (INT CONST bereich, BYTE CONST muster)' alle +Bytes des entsprechenden Bereichs mit dem angegebenen Muster geladen. 'PROC +pruefe (INT CONST bereich, BYTE CONST soll)' überprüft entsprechend alle Bytes des +Bereichs darauf, ob sie das Sollmuster enthalten. + +Findet der Speichertest Fehler, können u.a. folgende Ursachen vorliegen: + + - Ein Speicherchip ist defekt. + + - Die Versorgungsspannung für den Speicher (meistens +5V) ist zu niedrig, + d.h. das Netzteil ist nicht richtig eingestellt bzw. defekt. (Das kann insbeson + dere dann entstehen, wenn ein Rechner so "hochgerüstet" wurde, daß das + Netzteil nachgeregelt werden müßte.) + + - Die Kontakte der Speicherkarten sind locker oder oxidiert. + + - Die Speicheransteuerung ist defekt. + + + + + +#ib##ib(9)#Kanaltest#ie##ie(9)# + + +Beim #ib#Kanaltest#ie# werden fortlaufend auf allen #ib#Terminalkanälen#ie# (außer auf Terminal 1) +die jeweiligen Kanalnummern in der Form "Kanal: n" ausgegeben. Jedes Eingabe +zeichen wird in dezimaler Verschlüssung unter Angabe der Kanalnummer auf dem +Terminal 1 gemeldet. + +Mit Hilfe dieses Tests können u.a. Kabel und Geräteeinstellungen überprüft werden. +Mögliche Fehlerursachen: + + - falsche #ib#Baudrate#ie# eingestellt + + Symptome: Bei Aus- und Eingabe werden vollkommen unsinnige Zeichen + angeliefert. + Abhilfe: Baudrate am Endgerät oder am Rechner richtig einstellen. + + - falsche #ib#Parität#ie# eingestellt + + Symptome: Einige Zeichen werden richtig übertragen, andere verfälscht. In + einigen Fällen können auch alle Zeichen falsch übertragen wer + den. + Abhilfe: Parität am Endgerät oder am Rechner richtig einstellen. + + - falsches #ib#Kabel#ie# (z.B. Sende- und Empfangsleitungen fälschlich gekreuzt bzw. + nicht gekreuzt, Kabel ohne Flußkontrolle an Schnittstelle mit + Flußkontrolle, V.24-Kabel an Parallelschnittstelle oder umge + kehrt): + + Symptome: Keine Ausgabe, keine Eingabe oder andauernder Strom von + "Schrottzeichen". + Abhilfe: richtiges Kabel nehmen oder Kabel korrigieren. + + - defektes Kabel (Kabelbruch, defekter Stecker o.ä.) + + Symptome: beliebig. + Testmöglichkeit: Kabel wechseln. + + - defektes #ib#Endgerät#ie# + + Symptome: beliebig. + Testmöglichkeit: Anderes Gerät mit gleicher Einstellung (Baudrate, Parität + usw.) anschließen. + + - defekte #ib#Schnittstelle#ie# im Rechner + + Symptome: beliebig + Testmöglichkeit: Endgerät mit gleichem Kabel an eine andere Schnittstelle + am Rechner anschließen (dazu evtl. die Geräteparameter + wie Baudrate anpassen). + + + + + +#ib##ib(9)#Hintergrundtest#ie(9)##ie# + + +Zur Überprüfung des #ib#Hintergrund#ie#es werden drei Tests angeboten: + + (1) #ib#Lesetest#ie# + (2) #ib#Lese-/Schreibtest#ie# + (3) #ib#Positioniertest#ie# + + +Der #ib##on("i")##on("b")#Lesetest#off("i")##off("b")##ie# prüft, ob alle für EUMEL verfügbaren Blöcke auf der Platte bzw. Floppy +lesbar sind. Dabei wird der Blockinhalt nicht inspiziert. Sowohl behebbare (soft) als +auch harte #ib#Lesefehler#ie# werden gemeldet. Der Bediener kann einen Korrekturversuch +durch Rückschreiben veranlassen. Bei einem #ib#Soft-Error#ie# (Block konnte nach mehreren +Versuchen doch gelesen werden) wird der gelesene Block neu geschrieben. Der Fehler +kann jetzt ohne negative Folgen behoben sein, bei defekter Hardware aber auch zu +Folgefehlern führen. +Als Korrekturversuch bei harten Fehlern wird ein mit 'FFFD' gefüllter Block geschrie +ben. Wird ein solcher Block später vom EUMEL gelesen und als Code angesehen, führt +das zur Fehlermeldung "#ib#code block unreadable#ie#". Wird FFFD als INT angesehen, liefert +es den Wert -3, bei REAL oder TEXT können keine Vorhersagen gemacht werden. + + +Bei dem #ib##on("i")##on("b")#Schreib-/Lesetest#off("i")##off("b")##ie# wird jeder Block mit mehreren Bitmustern beschrieben und +zur Kontrolle wieder gelesen. Der alte Inhalt wird vor dem Test gesichert und nachher +wieder in den Block geschrieben. + + #on("b")#Achtung: Normalerweise zerstört der Test den EUMEL-Hintergrund nicht. Bei + defekter Platte können allerdings Blöcke durch mißlungenes Rück + schreiben zerstört werden. #off("b")# + + +Der #ib##on("i")##on("b")#Positioniertest#off("i")##off("b")##ie# arbeitet ähnlich wie die Leseprüfung. Allerdings wird in der Reihen +folge 0, 1, 0, 2, 0, 3, ... gelesen, so daß die Platte für jeden Lesevorgang positionieren +muß. + + #on("b")#Achtung: Wegen der harten Plattenbelastung sollte dieser Test nicht zu lange + laufen.#off("b")# + + + + + +#ib##ib(9)#Archivtest#ie##ie(9)# + + +Der Archivtest arbeitet ähnlich wie der Hintergrundtest - allerdings auf dem Archiv. Er +kann sowohl zur Überprüfung von Archiv-Datenträgern (#ib#Lesetest#ie#) als auch zum Test +des #ib#Archivlaufwerks#ie# benutzt werden. + + + + + +#ib(9)#2.3. #ib#Serielle Geräteschnittstelle#ie##ie(9)# + + +#ib##ib(9)#Pinbelegung und Kabel#ie(9)##ie# + + +#on("b")##on("i")#Anmerkung: Dieses Kapitel ist nur für solche Anwender von Bedeutung, die sich selbst + mit der Verkabelung ihrer Geräte befassen.#off("i")##off("b")# + +Im folgenden werden die wichtigsten Leitungen der offiziellen #ib#V.24-Schnittstelle#ie# (#ib#seriel +le Schnittstelle#ie# zum Anschluß von Terminals, Druckern, Fremdrechnern u.ä.) beschrie +ben: + + Pin Betriebsrichtung Bedeutung + + 2 out Sendedaten + 3 in Empfangsdaten + + 4 out Sendeaufforderung (RTS) + 5 in Empfangsbereitschaft (CTS) + + 7 Signalerde + + 8 in Gegenstation bereit (DCD) + + 20 out eigene Station bereit (DTR) + + +Dabei dient das Paar (2,3) zur Übertragung der Daten, mit Hilfe von (4,5) ist #ib#Flußkon +trolle#ie# möglich (z.B. kann ein Drucker damit Sendungen vom Rechner "verlangsamen"). +Das Paar (8,20) wird bei manchen Geräten und Rechnern benutzt, um festzustellen, ob +die Gegenstation eingeschaltet ist. + + +Die meisten Rechner haben die gleiche #ib#Pinbelegung#ie# wie oben aufgeführt. Die Kabel +müssen dann die folgenden #ib#Pin#ie#s verbinden: + + +Rechner 2 3 4 5 7 8 20 Vollständige Verbindung mit Flußkontrolle. + +Gerät 2 3 4 5 7 8 20 + + +Rechner 2 3 4 5 7 Reicht für die meisten Anschlüsse mit Flußkontrol + le, z.B. Rechnerkopplung. +Gerät 2 3 4 5 7 + + +Rechner 2 3 5 7 Reicht für die meisten Drucker, Flußkontrolle nur + einseitig vom Drucker zum Rechner. +Gerät 2 3 4 7 + + +Rechner 2 3 7 Reicht meistens für Terminals, Flußkontrolle ist + dabei überflüssig. +Gerät 2 3 7 + + +Rechner 2 3 4 5 7 Manchmal für Terminals. Rechnerseitig wird Fluß + kontrolle durch die Brücke 4-5 simuliert. +Gerät 2 3 7 + + +Bei manchen Rechnern werden die notwendigen paarweisen Vertauschungen schon +im Rechner durchgeführt. Es ergibt sich entsprechend: + + +Rechner 2 3 4 5 7 8 20 Vollständige Verbindung mit Flußkontrolle. + +Gerät 2 3 4 5 7 8 20 + + +Rechner 2 3 4 5 7 Einfacher Anschluß mit Flußkontrolle. + +Gerät 2 3 4 5 7 + + +Rechner 2 3 4 7 Drucker, einseitige Flußkontrolle. + +Gerät 2 3 4 7 + + +Rechner 2 3 7 Terminal. + +Gerät 2 3 7 + + +Rechner 2 3 4 5 7 Terminal mit simulierter Flußkontrolle. + +Gerät 2 3 7 + + + + + + + +#ib(9)#2.4. #ib#Kanäle#ie# und #ib#Konfigurierung#ie##ie(9)# + + + +Im EUMEL-System dienen #ib#Kanäle#ie# zur Kommunikation mit der Außenwelt, d.h. Kanäle +sind Verbindungen vom Rechner zu peripheren Geräten wie Terminals, Drucker, Plotter +und Archiv. Kanäle können für zeichen- und #ib#blockorientierte Ein-/Ausgabe#ie# verwendet +werden. Ein Kanal heißt #ub##ib#privilegiert#ie(1,"er Kanal")##ue#, wenn er nur von privilegierten Systemtasks (Nach +kommen des Supervisors) benutzt werden kann. + +#ib#Kanalaufteilung#ie#: + + Kanal Bedeutung + + 1 zeichenorientiert, blockorientiert + Dieser Kanal muß mit einem Terminal verbunden sein, da + über ihn der Systemstart erfolgt. + 2-16 zeichenorientiert, blockorientiert + Diese Kanäle werden für weitere Terminals, Drucker, Plot + ter, Rechnerkopplung usw. verwandt. + + 15-23 blockorientiert + + 24-30 blockorientiert, privilegiert + + 31 blockorientiert, privilegiert + Dieser Kanal ist der #ib#Standardkanal des Archivsystems#ie#, d.h. + üblicherweise wird darüber die Archivfloppy angesprochen. + + 32 blockorientiert, privilegiert + Dieses ist ein #ib#interner Kanal#ie#, an den kein externes Gerät + angeschlossen werden kann. Er wird zur Konfigurierung + der anderen Kanäle benutzt. + +Der Supervisor des EUMEL-Systems verwaltet die Kanäle. Jeder Task ist dabei kein +oder genau ein Kanal zugeordnet. Entsprechend ist jedem Kanal keine oder genau +eine Task zugeordnet. Solche Zuordnungen können von außen durch den Benutzer +(nur bei interaktiven Kanälen) über die SV-Kommandos bzw. Prozeduraufrufe 'conti +nue' und 'break' (s. Kap. 5) verändert werden. In jedem Fall überprüft der Supervisor +die Zugriffsberechtigung. + + + + + +#ib##ib(9)#Zeichenorientierte Ein-/Ausgabe#ie##ie(9)# + + +Zeichenorientierte Ein-/Ausgabe kann auf den Kanälen 1 bis 16 benutzt werden. Dafür +stehen die Basisoperationen + + PROC #ib#out#ie# (TEXT CONST text) + PROC #ib#outsubtext#ie# (TEXT CONST source, + INT CNST from) + PROC outsubtext (TEXT CONST source, + INT CONST from, to)9 + PROC #ib#cursor#ie# (INT CONST x, y) + PROC #ib#inchar#ie# (TEXT VAR char) + TEXT PROC #ib#incharety#ie# + TEXT PROC incharety (INT CONST time limit) + PROC #ib#get cursor#ie# (INT VAR x, y) + +und alle darauf aufbauenden Operationen (wie 'put', 'get', 'putline', 'getline' usw.) zur +Verfügung. Diese Kanäle sind 'konfigurierbar' (s.u.) und erlauben den Anruf des +Systems durch den Benutzer von außen (SV-Taste). In der Regel werden die Kanäle 1 +bis 16 für Terminals, Drucker, Plotter und andere zeichenorientierte Anschlüsse be +nutzt. +Wenn ein Kanal zum Anschluß eines Terminals verwendet wird, müssen die #ib#Standard- +Steuerzeichen#ie# des EUMEL-Systems (s. Benutzerhandbuch Programmierung, Kap. 3 +"Der Editor", "5.2.4. Der EUMEL-Zeichensatz") auf jedem Terminal die gleiche Semantik +haben. Das heißt beispielsweise, daß der Code ""2"" auf jedem Terminal bei Ausgabe +den Cursor um eine Stelle nach rechts verschiebt. Da Datenendgeräte in dieser Hin +sicht aber faktisch keiner Norm gehorchen, müssen die EUMEL-Codes in der Regel in +#ib#terminalspezifische Codes#ie# umgesetzt werden. Diese Umsetzregeln kann man bei der +Konfigurierung (s.u.) festlegen. Für die meisten Terminaltypen werden allerdings +fertige Konfigurationssätze mit dem EUMEL-System zusammen ausgeliefert, die man +bei der Einrichtung des Systems (s. Kap. 1 Installationsanleitung) interaktiv anwählen +kann. + + + + +#ib##ib(9)#Blockorientierte Ein-/Ausgabe#ie##ie(9)# + + +Blockorientiere Ein-/Ausgabe kann auf den Kanälen 1 bis 32 benutzt werden. Dafür +stehen die Operationen + + PROC #ib#control#ie# (INT CONST code1, code2, code3, + INT VAR return code) + PROC #ib#blockout#ie# (DATASPACE CONST ds, + INT CONST page nr, code1, code2, INT VAR return code) + PROC #ib#blockout#ie# (ROW 256 INT CONST block, + INT CONST code1, code2, INT VAR return code) + PROC #ib#blockin#ie# (DATASPACE VAR ds, + INT CONST page nr, code1, code2, INT VAR return code) + PROC #ib#blockin#ie# (ROW 256 INT VAR block, + INT CONST code1, code2, INT VAR return code) + +zur Verfügung. Näheres findet man in Kap. 4.5 dieses Systemhandbuchs. + + + + + +#ib##ib(9)#Konfigurierung von Kanal 1 bis 15#ie(9)##ie# + + + +Alle #ib#zeichenorientierten Kanäle#ie# können (mittels Block I/O auf Kanal 32) konfiguriert +werden. Dabei werden im wesentlichen #ib#Umsetzregeln#ie# für Ein- und Ausgabe definiert, +die den Zweck haben, + + - bei der Ausgabe den EUMEL Zeichensatz auf den Zeichensatz des ange + schlossenen Geräts abzubilden und + + - bei der Eingabe die gerätespezifischen Zeichen auf den EUMEL Zeichensatz + abzubilden. + +So ist eine geräteunabhängige Programmierung möglich. + +Mit Hilfe der Prozedur '#ib#link#ie#' kann man einen der Kanäle 1 bis 16 auf einen bestimm +ten Typ setzen. Immer vorhanden sind die Typen: + +"#ib#transparent#ie#": Keine Codeumsetzungen (für Drucker usw.) und +"#ib#psi#ie#" : Keine Codeumsetzungen, jedoch folgende Sonderfunktionen: +#free(1.0)# + Code Funktion + 7 (CTLg) SV + 17 (CTLq) Stop + 23 (CTLw) Weiter + +Weitere Typen müssen in Form eines DATASPACE, die nach den Gerätetypen benannt +sind, in der Task vorliegen, in der das Kommando 'link' gegeben wird. + +Neue Terminaltypen können mit den Prozeduren 'new type', 'enter outcode', 'enter +incode' usw. definiert werden. Im einzelnen stehen folgende Prozeduren zur Verfü +gung: + + +#ib#link#ie# + PROC link (INT CONST channel, TEXT CONST type) + Zweck: Der angegebene Kanal (1 bis 16) wird auf den angegebenen Typ konfi + guriert. + Hinweis: Die Prozedur 'link' hat die angegebene Wirkung nur, wenn + die Task an Kanal 32 hängt, der nur für Söhne des + SUPERVISOR zugänglich ist ('continue (32)'). + +#ib#y size#ie# + PROC y size (INT CONST channel, new size, INT VAR old size) + Zweck: Einstellmöglichkeiten für verschiedene Bildschirmgrößen. Diese Proze + dur wirkt nur auf Kanal 32. 'channel' gibt dabei den zu konfigurierenden + Kanal an. + +#ib#new type#ie# + PROC new type (TEXT CONST typ) + Zweck: Eröffnet einen neuen Kanaltyp mit dem Namen 'typ'. Die folgenden + Aufrufe von 'enter outcode', 'enter incode' usw. beziehen sich dann auf + diesen Typ. + +#ib#enter outcode#ie# + PROC enter outcode (INT CONST eumelcode, zielcode) + Zweck: Legt fest, daß der Code 'eumelcode' bei Ausgabe auf dem Terminaltyp + in 'zielcode' gewandelt werden soll. + + PROC enter outcode (INT CONST eumelcode, TEXT CONST zeichen) + Zweck: Wirkt wie 'enter outcode (eumelcode, code (zeichen))'. + + PROC enter outcode (INT CONST eumelcode, zeit, TEXT CONST seq) + Zweck: Hiermit wird festgelegt, daß der Code 'eumelcode' als Mehrzeichenfolge + 'seq' ausgegeben werden soll. Jedesmal, wenn diese Folge ausgegeben + wurde, verzögert das System die Ausgabe des nächsten Zeichens um + mindestens 'zeit' Millisekunden. Dies wird z.B. von den meisten Termi + nals gefordert, wenn sie die Funktion 'Löschen Bildschirm' ausführen + sollen. + +#ib#enter incode#ie# + PROC enter incode (INT CONST eumelcode, TEXT CONST seq) + Zweck: Es wird festgelegt, daß eine Eingabezeichenfolge 'seq' an das System + als ein (!) Zeichen mit dem Code 'eumelcode' weitergegeben werden + soll. Die ganze Sequenz muß dabei innerhalb von ca. 40 Millisekunden + eintreffen, andernfalls werden die Zeichen einzeln gemeldet. Diese + Logik ist erforderlich, um auch Terminals anzuschließen, die z.B. Cursor + tasten als ESC-Sequenzen melden. Ohne die Zeitüberwachung würde + das Betätigen der ESC-Taste sonst die Eingabe blockieren, bis die Folge + 'seq' vollständig ist. + Folgende Eumelcodes sind für die Sondertasten (SV usw.) anzugeben: + + 17 : STOP + 23 : WEITER + 7 : SV + + Weitere Codes ('HOP',...) sind im Benutzerhandbuch Programmierung + (5 - 29, Der EUMEL-Zeichensatz) angegeben. + + #on("i")#Hinweis: Liefert die SV-Taste eines Terminals von sich aus schon Code + 7, so ist dennoch 'enter incode (7, ""7"")' anzugeben. Entspre + chendes gilt für die zwei anderen "Ereignistasten" STOP und + WEITER. Bei allen anderen Tasten brauchen jedoch nur echte + Umcodierungen vermerkt zu werden.#off("i")# + + +#ib#cursor logic#ie# + PROC cursor logic (INT CONST offset, modus, TEXT CONST pre, mid, post) + Zweck: Es wird festgelegt, daß der EUMEL-Code 6 (Cursorposition) mit den + folgenden beiden Zeichen, deren Codes y und x seien, + + bei modus = 255 als + pre + code (offset+y) + mid + code (offset+x) + post + und bei modus = 1 als + pre + text (offset+y) + mid + text (offset+x) + post + + ausgegeben wird. + Hinweis: 'offset' ist üblicherweise 32 (manchmal 0) und + mid = post = "". + +#ib#cursor logic#ie# + PROC cursor logic (INT CONST dist, TEXT CONST pre, mid, post) + Zweck: Diese Prozedur wird von den Konfigurationsdateien alter Versionen + benutzt. + +#ib#ansi cursor#ie# + PROC ansi cursor (TEXT CONST pre, mid, post) + Zweck: Diese Prozedur ist anstelle von 'cursor logic' zu verwenden, wenn die + Cursor-Positionierungen bei dem Terminal so erfolgt, wie im Ansi- + Standard definiert wird. + +#ib#elbit cursor#ie# + PROC elbit cursor + Zweck: Diese Prozedur ist bei Elbit-Terminals anstelle von 'cursor logic' zu + verwenden. + + + + + + +#ib##ib(9)#Konfigurations-Manager#ie##ie(9)# + + +Wenn das System gestartet wird, weiß der Urlader noch nicht, welche #ib#Terminaltypen#ie# +an welchen Kanälen hängen. (Der Vortest kann deshalb auch nicht bildschirmorien +tiert arbeiten). + +Falls eine Task 'configurator' im System ist, schickt der SUPERVISOR dieser eine Start +sendung zu. Diese Task kann daraufhin die nötigen Konfigurierkommandos ('link',...) +ausführen. + +Ansonsten ist 'configurator' ein normaler Fontmanager, der die Fonttabellen verwaltet +(siehe Kap. 7). Deshalb sollte im System immer eine Task 'configurator' existieren und +nach Möglichkeit immer im 'wait' stehen. Man kann ihn also auch mit 'continue' an ein +Terminal holen und dann wie üblich Kommandos geben. + +#ib#configurate#ie# + PROC configurate + Zweck: Führt den Konfigurationsdialog und anschließendes 'setup' durch. + +#ib#setup#ie# + PROC setup + Zweck: Alle Kanäle werden gemäß der im letzten Konfigurationsdialog bestimm + ten Werte konfiguriert (wird automatisch bei jedem Systemstart durch + geführt). + +#ib#configuration manager#ie# + PROC configuration manager + Zweck: Durch Aufruf dieser Prozedur wird die Task zu einem Konfigurations + manager. Man kann also die Task "configurator" löschen, neu als + Systemtask einrichten und mit diesem Kommando wieder etablieren. + BEACHTE: - Die Task muß 'configurator' heißen. + - Alle Terminalanpassungen gehen beim Löschen verloren, d.h. + man sollte sie vorher sichern! + + +#on("i")#Hinweis: Es passieren, daß eine Task schon Ausgaben macht, bevor der Kanal + konfiguriert ist (z.B. wenn ein 'shutup' bei aktiver Netz-Kommunikation + durchgeführt wurde).#off("i")# + diff --git a/doc/system-manual/1.8.7/doc/systemhandbuch.2 b/doc/system-manual/1.8.7/doc/systemhandbuch.2 new file mode 100644 index 0000000..c4772f0 --- /dev/null +++ b/doc/system-manual/1.8.7/doc/systemhandbuch.2 @@ -0,0 +1,1351 @@ +#start(2.5,1.5)# +#pageblock# +#block# +#page (35)# +#headeven# + +%#center#EUMEL-Systemhandbuch + + +#end# +#headodd# + +#center#3. ELAN-Programme#right#% + + +#end# + + +#ib(9)#3. #ib#ELAN-Programme#ie##ie(9)# + + + + +#ib(9)#3.1. #ib#Wertebereich#ie#e und #ib#Speicherbedarf#ie##ie(9)# + + +#ib#INT-Objekte#ie# + + +Jedes #ib#Datenobjekt#ie# vom Typ INT belegt im Speicher 2 Bytes. Mögliche INT-Werte sind +die ganzen Zahlen von -32768 bis +32767 einschließlich. + + + + +#ib#REAL-Objekte#ie# + + +Jedes Datenobjekt vom Typ REAL belegt im Speicher 8 Bytes. + +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 abgelegt: + + 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 + + + + + +#ib#BOOL-Objekte#ie# + + +Jedes Datenobjekt vom Typ BOOL belegt im Speicher 2 Bytes. + + + + + +#ib#TEXT-Objekte#ie# + + +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")##ib#Heap#ie##off("i")##off("b")#. Im festen Teil werden #ib#Texte bis +zur Länge von 13 Zeichen#ie# 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 (LENGTH <= 13): + + Heap-Link 2 Bytes + Textlänge 1 Byte + Text 13 Bytes + + langer Text (LENGTH > 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. gelöscht, +wenn sie nicht mehr benötigt werden. Der Platz auf dem Heap wird in Vielfachen von +16 Bytes vergeben. In Fremddatenräumen wird in jedem #ib#Container#ie# neben dem eigent +lichen Text auch die Containerlänge untergebracht. + +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 - 520 = 1048056 - stat Bytes + +'stat' ist dabei die statistische 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. + + + + + + +#ib#ROW- und STRUCT-Objekte#ie# + + +Bei der Berechnung des Speicherbedarfs von #ib#STRUCT#ie#s und #ib#ROW#ie#s muß man beden +ken, daß längere Datenobjekte ausgerichtet werden. Und zwar werden alle Objekte, die +mindestens die Länge eines REAL-Objektes haben, auf durch 8 teilbare Speichera +dressen ausgerichtet. Man bedenke, daß bei ROWs alle Elemente entsprechend ihres +Elementtyps ausgerichtet sind. + +Beispiele: Länge (Byte) + + ROW 2 BOOL 4 + ROW 4 INT 8 + ROW 5 INT 16 + ROW 2 STRUCT (INT, BOOL) 4 + ROW 100 STRUCT (INT,INT) 400 + ROW 100 STRUCT (INT,REAL) 1600 + ROW 100 STRUCT (INT,INT,INT,INT,REAL) 1600 + ROW 100 STRUCT (REAL, REAL) 1600 + ROW 100 STRUCT (INT,TEXT) 2400 + ROW 100 STRUCT (INT,INT,INT,INT,TEXT) 2400 + ROW 100 STRUCT (INT,TEXT,INT,TEXT) 4800 + ROW 100 STRUCT (INT,INT,TEXT,TEXT) 4000 + ROW 100 ROW 3 INT 600 + ROW 100 ROW 4 INT 800 + ROW 100 ROW 5 INT 1600 +aber: + ROW 500 INT 1000 + +#on("i")#Anmerkung: Bei der #ib#Speichervergabe#ie# der einfachen Variablen und Konstanten eines + Programms spielen Verluste aufgrund von Ausrichtungen in der Regel + keine Rolle. Der ELAN-Compiler optimiert dabei soweit möglich.#off("i")# +#page# +#headeven# + +%#center#EUMEL-Systemhandbuch + + +#end# +#headodd# + +#center#4. Standardpakete für Systemprogrammierer#right#% + + +#end# + + +#ib(9)#4. #ib#Standardpakete für + Systemprogrammierer#ie(9)##ie# + + +#ib(9)#4.1. #ib#Fehlerbehandlung#ie##ie(9)# + + +Übersicht + + +#on("italics")# + Fehler treten auf, wenn ein Programm eine gewünschte Leistung + nicht erbringen kann. Solche Situationen müssen von System- + Programmen kontrolliert behandelt werden. Die folgenden Aus + führungen sind somit nur für diejenigen interessant, die "Sy + stem"-Programme schreiben wollen.#off("italics")# + +#ib#Fehler#ie# treten in Operationen auf, wenn diese eine geforderte Leistung nicht erbringen +können (z.B. das Drucken einer nicht vorhandenen Datei). Da folgende Anweisungen +aber davon ausgehen, daß die gewünschten Leistungen erbracht wurden, ist es nicht +sinnvoll, die Operation weiter auszuführen. Wir sprechen vom #ib#Abbruch einer Operation#ie#, +wenn nach einem Fehler keine Anweisungen mehr ausgeführt werden, sondern die +Operation verlassen wird. Im EUMEL-System kann durch folgende drei Maßnahmen +ein Abbruch verursacht werden: + +- Aufruf der Prozedur '#ib#errorstop#ie#': + Die Operation wird mit einer Fehlermeldung abgebrochen, die man dem Aufruf von + 'errorstop' als Parameter beifügt werden kann. + +- Aufruf der Prozedur '#ib#stop#ie#': + Die Operation wird abgebrochen. Wirkt wie 'errorstop' mit der Meldung "stop". + +- Umschalten in den Supervisor: + Durch Betätigen der Taste SV und Eingabe des Kommandos '#ib#halt#ie#'. Die laufende + Operation wird abgebrochen. Wirkt wie ein 'errorstop', der von "außen" in das + Programm induziert wird. + +Da alle drei Maßnahmen zum Abbruch führen können und somit eine anormale (vor +zeitige) Beendigung eines Programms bewirken, werden sie im folgenden zusammen +fassend als #ib#Fehler#ie# bezeichnet. + +Für solche Fehler bietet das EUMEL-System die Möglichkeit, den Abbruch zu unter +drücken. Dies kann notwendig werden, wenn + +a) bestimmte Fehlerfälle vom aufrufenden Programm selbst behandelt werden sollen. + Beispiel: + + Der EUMEL-Editor wird aufgerufen, um eine Datei zu bearbeiten. Er versucht als + erstes, die Datei zu assoziieren. Existiert die Datei nicht, wird die Prozedur + (z.B. 'old'), mit der die Datei angemeldet werden soll, normalerweise mit der Feh + lermeldung ' "datei" gibt es nicht' abgebrochen. Diesen Fehlerzustand fängt der + Editor jedoch ab und versucht, eine neue Datei einzurichten (Anmerkung: In Wirk + lichkeit fragt der Editor natürlich vor der Assoziierung mit 'exists' ab, ob die Datei + existiert). + +b) eine Operation die Kontrolle auf jeden Fall behalten soll. + + Dies ist z.B. beim Monitor notwendig. Gleich welche Fehler vom Monitor gerufene + Programme produzieren, der Monitor muß in der Lage sein, die weitere Bearbei + tung zu ermöglichen. + +c) eine Operation nicht unterbrechbar sein darf. + + Beispielsweise dürfen Programm(teil)e, die Daten transportieren, nicht unterbro + chen werden, da sonst ein Verlust dieser Daten eintreten könnte. + + + +#ib(9)##ib#Fehlerbehandlung#ie# und #ib#Fängerebenen#ie##ie(9)# + + +Der Aufruf einer der Prozeduren + + #ib#errorstop#ie# + #ib#stop#ie# + #ib#halt#ie# + +(wobei letztere vom Supervisor gegeben werden muß) werden zusammenfassend als +#ib#Fehler#ie# bezeichnet. Bei einem Fehler wird ein #ib#Fehlerzustand#ie# gesetzt. Im Fehlerzustand +merkt sich das EUMEL-System, daß ein Fehler vorliegt. Die Prozeduren + + #ib#enable stop#ie# + #ib#disable stop#ie# + +bestimmen, ob Operationen im Fehlerzustand weiter bearbeitet oder abgebrochen +werden. Beispiel: + + + INT VAR x; + get (x); + ... + disable stop; + x := x * x; + ... + + +Hier wird mit 'disable stop' verhindert, daß ein Abbruch beispielsweise durch 'INT- +Ueberlauf' auftreten kann. Die Anweisungen nach 'x * x' werden also weiter bearbei +tet. + +Welchen Wert hat aber nun die Variable 'x', nachdem der Fehler auftrat? Offensicht +lich war die den Fehler auslösende Operation '*' nicht in der Lage, den richtigen Wert +zu errechnen. #ib#Abgebrochene Operationen#ie# liefern in der Regel keinen Wert. Dadurch ist +der Wert von 'x' in unserem Beispiel nach einem Fehler bei '*' undefiniert. Es ist nun +ersichtlich, daß mit der Anwendung der 'disable stop'-Prozedur äußerst vorsichtig zu +verfahren ist, weil u.U. Werte verloren gehen können bzw. mit unerwarteten Werten +weitergerechnet wird. + +Damit Programmierer erfahren können, ob ein Fehler aufgetreten ist, gibt es die Infor +mations-Prozedur + + #ib#is error#ie# + +über den Fehlerzustand. Die Prozedur liefert den Wert TRUE, wenn ein Fehler vorliegt, +andernfalls FALSE. Die Prozedur + + #ib#clear error#ie# + +"löscht" den Fehlerzustand, d.h. anschließende Abfragen mit 'is error' liefern FALSE. +(Die "richtige" Reaktion auf den Fehler muß ein Programmierer natürlich selbst be +stimmen). + +Beispiel: + + + INT VAR x; + get (x); + ... + disable stop; + x := x * x; + IF is error + THEN put ("'x'-Wert zu groß"); + x := 0; + clear error + FI; + ... + + +Leider würden jetzt aber auch alle folgenden Anweisungen bei eventuellen Fehlern +nicht abgebrochen, also auch in Situationen, in denen ein Abbruch erwünscht ist, um +#ib#Programmierfehler#ie# zu erkennen. Deshalb können durch + + #ib#enable stop#ie# + +Abbrüche wieder zugelassen werden. Wenn wir jetzt also schreiben: + + + INT VAR x; + get (x); + ... + disable stop; + x := x * x; + IF is error + THEN put ("'x'-wert zu gross"); + x := 0; + clear error + FI; + enable stop; + ... + + +dann würden - wie gewünscht - eventuelle Fehler in den Anweisungen nach 'enable +stop' zu einem Abbruch führen. + +Nicht mit '#ib#clear error#ie#' gelöschte Fehler führen bei '#ib#enable stop#ie#' ebenfalls zu einem +Abbruch. In dem Programmteil + + + ... + disable stop; + x := x * x; + enable stop; + ... + + +würde der eventuell auftretender Fehler 'INT Ueberlauf' nicht abgefangen, sondern nur +verzögert wirksam, weil er nicht mit 'clear error' gelöscht wurde. + +Für die Behandlung von Fehlern durch Benutzer gibt es Prozeduren, die eine adäquate +Reaktion auf den Fehler erlauben. Mit + + #ib#error message#ie# + +können Sie auf die erste Fehlermeldung (eines 'error stop') nach dem letzen 'clear +error' zugreifen (d.h. Folgefehler verändern nicht die Originalmeldung). Die Prozedur + + #ib#error code#ie# + +liefert den #ib#Fehlercode#ie#, der bei der Prozedur 'errorstop' zusätzlich zum #ib#Fehlertext#ie# +angegeben werden kann. + + #ib#error line#ie# + +liefert die Zeilennummer des zuletzt aufgetretenen Fehlers. Mit + + #ib#put error#ie# + +kann eine noch anstehende Fehlermeldung ausgegeben werden. Beispiel: + + + INT VAR x; + get (x); + ... + disable stop; + x := x * x; + IF is error + THEN IF error message = "INT-Ueberlauf" + THEN put ("'x'-wert zu gross"); + ELSE put error + FI; + clear error + FI; + enable stop; + ... + + +Tritt ein Fehler auf, so wird die den Fehler auslösende Operation entweder abgebro +chen oder "normal" weiter bearbeitet, je nachdem, ob 'enable stop' oder 'disable stop' +gesetzt ist. Auf jeden Fall wird der #ib#Fehlerzustand#ie# an die aufrufende Operation weiter +gemeldet, die wiederum abgebrochen oder weiterbearbeitet werden kann usw. Die +#ib#Weitermeldung#ie# eines Fehlers kann auch über mehrere Stufen erfolgen, solange bis der +Fehler gelöscht wird. Andererseits gilt 'enable/ disable stop' nicht nur für die aktuelle +Operation, sondern auch für gerufene Operationen ("Vererbung"). Die gerufenen Ope +rationen können allerdings 'enable/disable stop' neu festlegen. Beispiel: + + + PROC a: PROC b: PROC c: + ... ... ROW 10 INT VAR x; + disable stop; enable stop; ... + b; ... INT VAR i :: 4711; + IF is error c; x [i] := ...; + THEN ... ... ... + clear error END PROC b END PROC c + FI; + enable stop + END PROC a; + + +In der Prozedur 'a' wird die Prozedur 'b' aufgerufen. Diese ruft wiederum eine Prozedur +'c' auf. Für die Prozedur 'c' gilt nun der Zustand 'enable stop' der Prozedur 'b' (#ib#Verer +bung von 'enable stop'#ie#). Tritt jetzt in 'c' der Subskriptions-Fehler auf, wird 'c' abgebro +chen. Die Wirkung der fehlerauslösenden Operation ist nicht definiert. + +Da aber auch die Prozedur 'b' im 'enable stop' Zustand ist, wird auch die Prozedur 'b' +abgebrochen. Der Fehler bleibt jedoch erhalten, wird also weitergemeldet. Dies wirkt +sich so aus, daß die Anweisung 'c' nicht ausgeführt wird. Da die Prozedur 'a' 'disable +stop' gesetzt hat, werden die auf den Aufruf von 'b' folgenden Anweisungen durchlau +fen und somit durch 'clear error' der Fehler gelöscht. In diesem Beispiel "fängt" die +Prozedur 'a' Fehler auf, die in den Prozeduren 'b' und 'c' entstehen können. + +Ein solcher #ib#Fänger#ie# wird durch zwei Prozeduren konstruiert. Der eigentliche Fänger +(hier: Prozedur 'a') ruft eine ausführende Prozedur (hier: 'b') im 'disable stop'-Zustand +auf. Die gerufene Prozedur setzt sofort 'enable stop' und führt dann die eigentlichen +Aktionen aus. So wird die gerufene Prozedur abgebrochen (kann also im Fehlerfall +nicht zuviel Schaden anrichten). Der Abbruch führt bis zur Fängerprozedur ('a') hinter +den Aufruf der gerufenen Prozedur ('b'). Nach Löschung eventuell auftretender Fehler +ist somit sichergestellt, daß der Fänger immer weiterarbeiten kann. + + + +#ib(9)#Wichtiger Hinweis#ie(9)# + + + + 1. #on("italics")##on("bold")#Da im 'disable stop'-Zustand kein Fehler zum Abbruch führt, kann + eine Operation in diesem Zustand auch nicht durch 'halt' abge + brochen werden. Einerseits ist das für manche Systemteile wün + schenswert, andererseits können Operationen, die auf Grund von + Programmierfehlern nicht terminieren (Endlosschleifen), nicht + unter Kontrolle gebracht werden. Also Vorsicht! (Letztes Mittel: + Task löschen)#off("italics")##off("bold")# + + 2. #on("i")##on("b")#Es ist nicht (!) garantiert, daß im Fehlerzustand aufgerufene + Prozeduren ihre normale Wirkung haben. Garantiert ist dies je + doch für alle Prozeduren und Operatoren, die in diesem Kapi + tel aufgeführt werden.#off("i")##off("b")# + +#on("italics")##on("bold")#Merke: Fehler sind im EUMEL-System Aufrufe der Prozeduren 'errorstop', + 'stop' oder das Betätigen der SV Taste und dem Supervisor- + Kommando 'halt'. Ein Fehler gilt solange, bis er mit Hilfe der + Prozedur 'clear error' gelöscht wurde. Die Prozeduren 'enable/ + disable stop' steuern die Abarbeitung der Operationen im Fehler + fall. Gilt für eine Operation 'enable stop', wird die Operation + abgebrochen, d.h. die restlichen Anweisungen der Operation + nach der Fehler auslösenden Anweisung werden nicht durchlau + fen. Ist 'disable stop' gesetzt, werden die restlichen Operationen + weiterhin abgearbeitet. 'enable/disable stop' gilt für alle - auch + indirekt - aufgerufenen Operationen ("Vererbung"), es sei denn, in + den gerufenen Operationen wird ein erneutes 'enable/disable + stop' gesetzt. Über die Aufrufkette werden ggf. auch die Fehler + zurück gemeldet.#off("italics")##off("bold")# + + + #on("italics")##on("bold")#Eine Fänger-Ebene ist eine Prozedur, die 'disable stop' setzt und + dann andere Operationen aufruft. Nach jedem dieser Aufrufe + kann eine Fehlerbehandlung mit 'clear error' durchgeführt wer + den. Damit ist gewährleistet, daß Fehler immer von der Fänger- + Ebene "aufgefangen" und entsprechend behandelt werden.#off("italics")##off("bold")# + + + +#ib(9)##ib#Prozeduren zur Fehlerbehandlung#ie##ie(9)# + + +#ib#clear error#ie# + PROC clear error + Zweck: Löscht den Fehlerzustand. 'is error' liefert anschließend wieder FALSE. + 'error message', 'error code' und 'error line' werden nicht gelöscht. + +#ib#disable stop#ie# + PROC disable stop + Zweck: Unterbindet den Abbruch in aufgerufenen Operationen. 'disable stop' + gilt für die Prozedur, in der sie aufgerufen wird und in allen folgenden + gerufenen Prozeduren, es sei denn, sie wird durch 'enable stop' außer + Kraft gesetzt. Wird die Operation verlassen, in der 'disable stop' aufge + rufen wurde, wird der "alte" Zustand wiederhergestellt, der vor dem + Aufruf der Operation galt. 'disable stop' kann weiterhin in einer aufge + rufenen Operation durch den Aufruf von 'enable stop' in dieser und den + folgenden Operationen außer Kraft gesetzt werden. + +#ib#enable stop#ie# + PROC enable stop + Zweck: Setzt die Wirkung eines Aufrufs von 'disable stop' zurück. Fehler ('error + stop', 'stop' oder 'halt') in der aktuellen Operation oder den folgenden + aufgerufenen Operationen führen zum Abbruch. Bisher nicht gelöschte + Fehler (siehe 'clear error') führen sofort zum Abbruch. + +#ib#error code#ie##--goalpage ("fehlercodes")# + INT PROC error code + Zweck: Liefert den durch 'errorstop' gesetzten #ib#Fehlercode#ie#. Beispiel: + + PROC test: + enable stop; + error stop (110, "Dies ist mein Abbruch!"); + END PROC test; + + ... + disable stop; + test; + put (error code); (* liefert 110 *) + clear error; + enable stop + + +#ib#error line#ie# + INT PROC error line + Zweck: Liefert die Zeilennummmer des Fehlers (Voraussetzung : Die Überset + zung erfolgt im 'checkon-Modus). + +#ib#error message#ie# + TEXT PROC error message + Zweck: Liefert die Fehlermeldung als Text. Anhand dieser Meldung kann ent + schieden werden, welcher Fehler vorliegt. + Hinweis: Eine Fehlermeldung "" (also: 'error stop ("")') führt zum Fehlerabbruch + mit der Bedeutung "Fehlermeldung wurde bereits ausgegeben". Dem + entsprechend erfolgt bei der Fehlermeldung 'niltext' keine Reaktion bei + 'put error'. + +#ib#errorstop#ie# + PROC error stop (TEXT CONST message) + Zweck: Bricht ab und setzt die Zeilennummer (wenn man sich im 'checkon'- + Modus befindet), in der der Fehler aufgetreten ist, sowie den Text 'mes + sage'. Der Abbruch kann mit 'disable stop' unterbunden werden. 'error + stop' hat keine Wirkung, wenn ein noch nicht gelöschter Fehler vorliegt. + Zu einer Fehlermeldung "" siehe auch die Prozedur 'error message'. Als + 'error-code' wird 0 gesetzt. + + + PROC error stop (INT CONST code, TEXT CONST message) + Zweck: Analog obiger 'errorstop'-Prozedur, aber mit Angabe des Fehlercodes, + der durch die Prozedur 'error code' in einer Fängerebene erfragt wer + den kann. + +#ib#is error#ie# + BOOL PROC is error + Zweck: Informationsprozedur auf das Vorhandensein eines Fehlers. + +#ib#put error#ie# + PROC put error + Zweck: Gibt die durch 'errorstop' gesetzte Fehlermeldung aus, falls ein Fehler + noch nicht gelöscht ist (siehe auch: 'error message'). + + + + +#ib##ib(9)#Fehlercode#ie#s#ie(9)# + + +Einige Fehlercodes sind bereits belegt: + + 0 kein Fehlercode spezifiziert (Standardwert) + 1 'halt' vom Terminal + 2 Stack-Ueberlauf + 3 Heap-Ueberlauf + 4 INT-Ueberlauf + 5 DIV durch 0 + 6 REAL-Ueberlauf + 7 TEXT-Ueberlauf + 8 zu viele DATASPACEs + 9 Ueberlauf bei Subskription + 10 Unterlauf bei Subskription + 11 falscher DATASPACE-Zugriff + 12 INT nicht initialisiert + 13 REAL nicht initialisiert + 14 TEXT nicht initialisiert + 15 nicht implementiert + 16 Block unlesbar + 17 Codefehler + 100 Syntax-Fehler beim Übersetzen + + + + + +#ib(9)#4.2. #ib#THESAURUS#ie##ie(9)# + + + +Ein #ib#Thesaurus#ie# ist ein #ib#Namensverzeichnis#ie#, das bis zu 200 Namen beinhalten kann. +Dabei muß jeder Namen mindestens ein Zeichen und darf höchstens 100 Zeichen lang +sein. Steuerzeichen (code < 32) sind in Namen nicht erlaubt. + +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. + + + + +#ib(9)#Grundoperationen#ie(9)# + + +#ib#CONTAINS#ie# + BOOL OP CONTAINS (THESAURUS CONST t, TEXT CONST name) + Zweck: Liefert genau dann TRUE, wenn 't' den Namen 'name' enthält. Falls + 'name=""' oder 'LENGTH name > 100', wird FALSE geliefert. + +#ib#delete#ie# + PROC delete (THESAURUS VAR t, TEXT CONST name, INT VAR index) + Zweck: Falls der Name 'name' im Thesaurus 't' enthalten ist, wird er dort ge + löscht. In 'index' wird dann sein alter Index geliefert, unter dem er im + Thesaurus eingetragen war. Ist der Name nicht im Thesaurus enthalten, + wird 0 als Index geliefert. + + PROC delete (THESAURUS VAR t, INT CONST index) + Zweck: Der Eintrag mit dem angegebenen Index wird aus dem Thesaurus 't' + gelöscht. + +#ib#empty thesaurus#ie# + THESAURUS PROC empty thesaurus + Zweck: Für Initialisierungszwecke wird ein leerer Thesaurus geliefert. + +#ib#get#ie# + PROC get (THESAURUS CONST t, TEXT VAR name, INT VAR index) + Zweck: Liefert den "nächsten" Eintrag aus dem 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. + D.h. 'index' wird automatisch weitergeschaltet. Den ersten Eintrag erhält + man entsprechend durch Aufruf mit 'index=0'. Nach dem letzten Ein + trag wird 'name=""' und 'index=0' geliefert. Beispiel: + + + TEXT VAR name; + INT VAR index := 0 ; + get (thesaurus, name, index) ; + WHILE index > 0 REP + putline (name) ; + get (thesaurus, name, index) + PER + + +#ib#highest entry#ie# + INT PROC highest entry (THESAURUS CONST t) + Zweck: Liefert den höchsten belegten Index des Thesaurus 't'. + Achtung: Das ist nicht die Anzahl der vorhandenen Namen, da durch + Löschungen Lücken entstanden sein können. + +#ib#insert#ie# + PROC insert (THESAURUS VAR t, TEXT CONST name, INT VAR index) + Zweck: Der Name 'name' wird als zusätzlicher Eintrag in den Thesaurus 't' + eingetragen und der dafür vergebene Index geliefert. Falls der Thesau + rus schon voll ist und der Name nicht mehr eingetragen werden kann, + wird 0 als Index geliefert. + Achtung: Mehrfacheintragungen sind möglich. Wenn man diese verhin + dern will, muß man entsprechend vermittels + + + IF NOT t CONTAINS name + THEN insert (t, name, index) + FI + + + eintragen. + Fehlerfall: + * Name unzulaessig + + PROC insert (THESAURUS VAR t, TEXT CONST name) + Zweck: s.o. Allerdings wird der Index des Namens nicht geliefert. Ein Thesau + rusüberlauf wird entsprechend als 'errorstop' gemeldet. + Fehlerfälle: + * Name unzulaessig + * THESAURUS-Ueberlauf + +#ib#link#ie# + INT PROC link (THESAURUS CONST t, TEXT CONST name) + Zweck: Liefert den Index des Namens 'name' im Thesaurus 't'. Falls der Name + nicht enthalten ist, wird 0 geliefert. Ist der Name mehrfach im Thesau + rus enthalten, ist nicht definiert, welcher der möglichen Indizes geliefert + wird. + +#ib#name#ie# + TEXT PROC name (THESAURUS CONST t, INT CONST index) + Zweck: Liefert den Namen des Eintrags mit dem Index 'index' aus dem The + saurus 't'. Falls kein solcher Eintrag im Thesaurus enthalten ist, wird + Niltext geliefert. + +#ib#rename#ie# + PROC rename (THESAURUS VAR t, TEXT CONST old, new) + Zweck: Ändert im Thesaurus 't' einen Eintrag mit dem alten Namen 'old' in 'new' + um. Falls 'old' nicht im Thesaurus enthalten ist, wird keine Leistung + erbracht. Falls 'old' mehrfach in 't' enthalten ist, ist nicht definiert, wel + cher der möglichen Einträge geändert wird. + Fehlerfall: + * Name unzulaessig + + PROC rename (THESAURUS VAR t, INT CONST index, TEXT CONST new) + Zweck: Ändert im Thesaurus 't' den Namen des durch 'index' identifizierten + Eintrags in 'new'. + Fehlerfall: + * Name unzulaessig + +#ib#THESAURUS#ie# + TYPE THESAURUS + Zweck: Bezeichnet Thesaurus-Datenobjekte + +:= + OP := (THESAURUS VAR dest, THESAURUS CONST source) + Zweck: Zuweisung + + + + + + +#ib(9)#Verknüpfungsoperationen#ie(9)# + +Das Paket '#ib#nameset#ie#' bietet die Möglichkeit, Operationen nicht nur auf einzelnen Datei +en, sondern auf (geordneten) Mengen ablaufen zu lassen: + +#ib#ALL#ie# + THESAURUS OP ALL (TASK CONST task) + Zweck: Liefert einen Thesaurus, der alle Dateinamen der angegebenen Task + enthält. + + THESAURUS OP ALL (TEXT CONST file name) + Zweck: Liefert einen Thesaurus, der die in der angegebenen Datei vorhande + nen Namen (jede Zeile ein Name) enthält. + +#ib#all#ie# + THESAURUS PROC all + Zweck: Liefert einen Thesaurus, der alle Dateinamen der eigenen Task enthält. + Entspricht 'ALL myself'. + +#ib#LIKE#ie# + THESAURUS OP LIKE (THESAURUS CONST thesaurus, TEXT CONST muster) + Zweck: Alle im Thesaurus enthaltenen Dateien, die dem 'muster' entsprechen + sind im Ergebnisthesaurus enthalten. + (Die Syntax von 'muster' findet man bei der Beschreibung des Pattern- + Matching) + +#ib#SOME#ie# + THESAURUS OP SOME (THESAURUS CONST thesaurus) + Zweck: Bietet den angegebenen Thesaurus im EUMEL-Editor zum Ändern an. + Es können nicht erwünschte Namen gestrichen werden. + + THESAURUS OP SOME (TASK CONST task) + Zweck: Aufruf von: SOME ALL task. + + THESAURUS OP SOME (TEXT CONST file name) + Zweck: Aufruf von: SOME ALL filename. + +#ib#FILLBY#ie# + OP FILLBY (THESAURUS VAR thesaurus, FILE VAR file) + Zweck: Schreibt 'file' in den Thesaurus. Dabei werden Zeilen, die schon im + Thesaurus sind, nicht mehr in den Thesaurus geschrieben. Jede Zeile + kommt im Thesaurus also nur einmal vor. + + OP FILLBY (FILE VAR file, THESAURUS CONST thesaurus) + Zweck: Schreibt den Thesaurus in die Datei 'file'. + + OP FILLBY (TEXT CONST filename, + THESAURUS CONST thesaurus) + Zweck: Richtet eine Datei mit dem Namen 'filename' ein und schreibt den The + saurus in die Datei. + ++ + THESAURUS OP + (THESAURUS CONST left, right) + Zweck: Liefert die Vereinigungsmenge von 'left' und 'right'. + Achtung: Die Vereinigungsmenge enthält keine Namen mehrfach. + + THESAURUS OP + (THESAURUS CONST left, TEXT CONST right) + Zweck: Fügt dem Thesaurus 'right' zu, wenn 'right' noch nicht im Thesaurus + enthalten ist. + +- + THESAURUS OP - (THESAURUS CONST left, right) + Zweck: Liefert die Differenzmenge. Achtung: Die Differenzmenge enthält keine + Namen mehrfach. + + THESAURUS OP - (THESAURUS CONST left, TEXT CONST right) + Zweck: Nimmt den Namen 'right' aus dem Thesaurus. + +/ + THESAURUS OP / (THESAURUS CONST left, right) + Zweck: Liefert die Schnittmenge + Achtung: Die Schnittmenge enthält keine Namen mehrfach. + +#ib#do#ie# + PROC do (PROC (TEXT CONST) operate, THESAURUS CONST thesaurus) + Zweck: Ruft 'operate' nacheinander mit allen im Thesaurus enthaltenen Namen + auf. + + PROC do (PROC (TEXT CONST, TASK CONST) operate, + THESAURUS CONST thesaurus, TASK CONST task) + Zweck: s.o. + +#ib#erase#ie# + PROC erase (THESAURUS CONST thesaurus) + Zweck: Löscht alle aufgeführten Dateien in der Vater-Task. + + PROC erase (THESAURUS CONST thesaurus, TASK CONST manager) + Zweck: Löscht alle aufgeführten Dateien in der Task 'manager'. + +#ib#fetch#ie# + PROC fetch (THESAURUS CONST thesaurus) + Zweck: Holt alle aufgeführten Dateien vom Vater. + + PROC fetch (THESAURUS CONST thesaurus, TASK CONST manager) + Zweck: Holt alle aufgeführten Dateien vom 'manager'. + +#ib#fetch all#ie# + PROC fetch all (TASK CONST manager) + Zweck: Holt alle Dateien vom 'manager'. Diese Prozedur entspricht dem Aufruf + der Prozedur 'fetch (ALL manager, manager)'. + + PROC fetch all + Zweck: Aufruf der Prozedur 'fetch all (father)'. + +#ib#forget#ie# + PROC forget (THESAURUS CONST thesaurus) + Zweck: Löscht alle aufgeführten Dateien in der Benutzer-Task. + +#ib#insert#ie# + PROC insert (THESAURUS CONST thesaurus) + Zweck: Insertiert alle aufgeführten Dateien in der Benutzer-Task. + +#ib#remainder#ie# + PROC remainder + Zweck: Liefert nach einem 'errorstop' die noch nicht bearbeiteten Dateien. + Beispiel: + 'save all (archive)' + kann dazu führen, daß nicht alle Dateien auf das Archiv geschrie + ben werden können. Fehlermeldung: + '"....." kann nicht geschrieben werden (Archiv voll)' + Nachdem man eine neue Floppy ins Archivlaufwerk gelegt hat, + kann man mit + 'save (remainder, archive)' + den Rest der Dateien auf der Floppy sichern. + +#ib#save#ie# + PROC save (THESAURUS CONST thesaurus) + Zweck: Schickt alle aufgeführten Dateien zur Vater-Task. + + PROC save (THESAURUS CONST thesaurus, TASK CONST manager) + Zweck: s.o. + +#ib#save all#ie# + PROC save all (TASK CONST manager) + Zweck: Schickt alle eigenen Dateien zum 'manager'. Diese Prozedur entspricht + dem Aufruf der Prozedur 'save (ALL myself, manager)'. + + PROC save all + Zweck: Aufruf der Prozedur 'save all (father)'. + + +Beispiele: + + save (ALL myself) + forget (ALL myself) + forget (all) + fetch (SOME father) + fetch (ALL father - ALL myself) + insert (ALL "gen datei") + save (ALL myself - ALL archive, archive) + + + + +#ib(9)#4.3. #ib#Kommandos und Dialog#ie(9)##ie# + + + +#ib##ib(9)#Kommandodialog#ie##ie(9)# + + +Das Paket "#ib#command dialogue#ie#" dient zur zentralen Steuerung und einfachen Durch +führung von #ib#Kommando-Dialog#ie#en wie + + "datei" loeschen (j/n)? + +Er wird von allen Systemteilen verwandt, die einen Kommandodialog mit dem Benut +zer aufnehmen. Anwenderprozeduren mit ähnlichen Problemen sollten genauso damit +arbeiten. + +Der Kommandodialog kann zentral aus- und eingeschaltet werden. + + + +#ib#command dialogue#ie# + BOOL PROC command dialogue + Zweck: Liefert den aktuellen Zustand des Kommandodialogs: + TRUE - Dialog soll geführt werden! + FALSE - Dialog soll nicht geführt werden! + + PROC command dialogue (BOOL CONST status) + Zweck: Schaltet den Kommandodialog ein ('status' = TRUE) oder aus ('status' + = FALSE). Der alte Zustand wird überschrieben. Soll später wieder in + den alten Zustand zurückgeschaltet werden, muß er vorher erfragt und + gesichert werden. + +#ib#yes#ie# + BOOL PROC yes (TEXT CONST question) + Zweck: a) Kommandodialog soll geführt werden (command dialogue = TRUE) + Der übergebene Fragetext wird durch " (j/n)?" ergänzt auf dem Ter + minal ausgegeben. Als Antwort wird eine der Tasten <j>, <J>, + <y>, <Y>, <n>, <N> akzeptiert; jede andere Eingabe führt zu + einem akustischen Signal und der Fragewiederholung. Das Resultat + der Prozedur ist + TRUE bei bejahender Antwort (j,J,y,Y) + FALSE bei verneinender Antwort (n,N) + b) Kommandodialog soll nicht geführt werden (command dialogue = + FALSE) + Keine Aktion, das Resultat ist TRUE. + +#ib#no#ie# + BOOL PROC no (TEXT CONST question) + Zweck: a) Kommandodialog soll geführt werden (command dialogue = TRUE) + Frage und Antwort wie bei 'yes'. Das Resultat ist + TRUE bei verneinender Antwort (n,N) + FALSE bei bejahender Antwort (j,J,y,Y) + b) Kommandodialog soll nicht geführt werden (command dialogue = + FALSE) + Keine Aktion, das Resultat ist FALSE. + +#ib#say#ie# + PROC say (TEXT CONST message) + Zweck: IF command dialogue THEN out (text) FI + +#ib#last param#ie# + TEXT PROC last param + Zweck: Liefert den zuletzt gesetzten Parameter-Text (siehe folgende Proze + dur). Falls 'command dialogue' = TRUE und die 'param position' > 0 + ist, wird der Parametertext als Standardparameter an der angegebenen + x-Position eine Zeile höher in der Form ("...") ausgegeben. Diese Proze + dur wird von den parameterlosen Kommandos bzw. Prozeduren wie + 'edit', 'run' usw. verwandt, um mit dem Standardparameter weiterzuar + beiten. + + PROC last param (TEXT CONST new) + Zweck: Setzt 'last param' auf 'new'. (Das Setzen muß explizit durchgeführt + werden und geschieht nicht implizit durch den 'command handler'. 'Last + param' wird beispielsweise von den einparametrigen Prozeduren 'edit' + und 'run' gesetzt. + +#ib#param position#ie# + PROC param position (INT CONST x) + Zweck: Setzt die Echoposition für 'last param'. Bei x=0 wird ein Echo unter + drückt. + +#ib#std#ie# + TEXT PROC std + Zweck: Liefert wie 'last param' den zuletzt gesetzten Parameter. Im Gegensatz + dazu wird der Parameter aber nicht ausgegeben. + + + + + +#ib##ib(9)#Kommandoverarbeitung#ie##ie(9)# + + +Das Paket '#ib#command handler#ie#' stellt Prozeduren zur #ib#Kommandoanalyse#ie# und zum +Führen des kompletten Kommandodialogs zur Verfügung. + + +#ib#get command#ie# + PROC get command (TEXT CONST dialogue text, TEXT VAR command line) + Zweck: Falls eine Fehlermeldung aussteht, ('is error' liefert TRUE), wird sie über + 'put error' ausgegeben und der Fehlerzustand zurückgesetzt. Der 'dialo + gue text' wird als Dialogaufforderung ausgegeben und der Benutzer + kann eine Kommandozeile eingeben. Die letzte Kommandozeile wird + ihm dabei automatisch (zum Ändern) angeboten, wenn vorher eine + Fehlermeldung anstand. Der Benutzer kann dies ebenfalls erreichen, + wenn er zu Beginn <ESC k> gibt. Die Kommandozeile wird dem Auf + rufer in der Variablen 'command line' geliefert. + + PROC get command (TEXT CONST dialogue text) + Zweck: s.o. Allerdings wird eine interne Kommandozeile des Pakets 'command + handler' als 'command line' verwandt. Dadurch wird es möglich, alle + Spuren einer Kommandoeingabe durch 'cover tracks' zu beseitigen. + +#ib#analyze command#ie# + PROC analyze command (TEXT CONST command list, command line, + INT CONST permitted type, + INT VAR command index, number of params, + TEXT VAR param 1, param 2) + Zweck: Die übergebene Kommandozeile ('command line') wird anhand der + übergebenen 'command list' analysiert. Sie ist ein TEXT, der aus einer + Folge von Kommandospezifikationen besteht. Jede hat die Form + K:I.P + + K Kommandotext, Prozedurname nach ELAN-Syntax + I Hauptindex, Form eines INT-Denoters + P Parameterspezifikation, eine Folge der Ziffern 0, 1 und 2. + + Beispiele: + - 'edit:15.012' + Das Kommando 'edit' wird in drei verschieden parametrisierten + Formen spezifiziert: + edit mit 0 Parameter erhält Index 15 + edit mit 1 Parameter erhält Index 16 + edit mit 2 Parametern erhält Index 17 + + - 'fetch:18.1' + Das Kommando 'fetch' wird in einer Form spezifiert: + fetch mit 1 Parameter erhält Index 18 + + Die Analyse erfolgt gemäß ELAN-Syntaxregeln. Dabei sind als Para + meter Denoter vom Typ TEXT und vom übergebenen ' permitted type' + zugelassen. Diese Typen werden wie beim Scanner (s. Benutzerhand + buch Programmierung Kap. 5.6) angegeben: + + 1 tag + 2 bold + 3 number + 4 text + 5 operator + 6 delimiter + + Falls das Kommando in der Kommandoliste gefunden wird (und die + Syntax in Ordnung ist), wird der entsprechende 'command index' zu + rückgemeldet. Die Parameter werden (falls vorhanden) in 'param 1' und + 'param 2' abgelegt. Undefinierte oder nicht vorhandene Parameter + werden als Niltext geliefert. Wenn ein Kommando vorhanden ist, die + Anzahl der Parameter aber nicht stimmt, wird der negative Hauptindex + geliefert. Ist es vollkommen unbekannt oder ist die Eingabe zu komplex + (mehrere Kommandos, Ausdrücke oder komplexere ELAN-Statements), + wird 0 geliefert. Der Anwender kann in solchen Fällen die Analyse mit + einer anderen Kommandoliste fortsetzen, das Kommando dem ELAN- + Compiler übergeben oder eine Fehlermeldung auslösen (s. 'command + error'). + + PROC analyze command (TEXT CONST command list, + INT CONST permitted type, + INT VAR command index, number of params, + TEXT VAR param 1, param 2) + Zweck: s.o. Allerdings wird die interne Kommandozeile des Pakets 'command + handler' als 'command line' verwandt. + +#ib#command error#ie# + PROC command error + Zweck: Falls bei der Kommandoanalyse ein Fehler gefunden wurde, führt er + nicht zum 'errorstop', sondern wird nur hinterlegt. (Soll das Kommando + dem Compiler übergeben werden, liegt ja evt. überhaupt kein Fehler + vor.) Diese hinterlegte Meldung kann mit 'command error' als 'errorstop' + gegeben werden. Mögliche Meldungen: + "ungueltiger name" + ") fehlt" + "( fehlt" + "Parameter ist kein TEXT ("fehlt)" + "Kommando zu schwierig" + +#ib#cover tracks#ie# + PROC cover tracks + Zweck: Die Spuren der letzten Kommandoanalyse werden gelöscht. Das dient + u.a. dazu, daß später eingerichtete Sohntasks keine Relikte des Kom + mandos mehr auf dem Textheap vorfinden und evtl. mittels nicht initiali + sierter TEXT VARs herausfinden können. Vollständig können die Spuren + aber nur dann gelöscht werden, wenn für die Kommandoanalyse die + 'get command'- und 'analyze command'-Prozeduren benutzt wurden, + die auf der internen Kommandozeile des Pakets 'command handler' + arbeiten. + +#ib#do command#ie# + PROC do command + Zweck: Die interne Kommandozeile des Pakets 'command handler' wird dem + ELAN-Compiler zur Ausführung übergeben. + + + + + +#ib(9)#Beispiele zur Kommandoverarbeitung#ie(9)# + + +#ib##ub#Kleiner Monitor#ue##ie# + + +LET command list = "otto:1.12emil:3.012hugo:6.0" ; + +LET number = 3 , + text = 4 ; + +INT VAR command index, params ; +TEXT VAR param 1, param 2 ; + +PROC monitor : + + disable stop ; + command dialogue (TRUE) ; + REP get command ("gib kleines kommando:") ; + analyze command (command list, text, + command index, params, + param 1, param 2) ; + execute command + PER + +ENDPROC monitor ; + +PROC execute command : + + enable stop ; + SELECT command index OF + CASE 1 : otto (param 1) + CASE 2 : otto (param 1, param 2) + CASE 3 : emil + CASE 4 : emil (param 1) + CASE 5 : emil (param 1, param 2) + CASE 6 : hugo + OTHERWISE do command line + END SELECT + +ENDPROC execute command ; + + + +#ib(9)##ub#Steuerkommando-Analyse#ue##ie(9)# + + +PROC command (TEXT CONST command text) : + + disable stop ; + command dialoge (FALSE) ; + analyze command (command list, command text, number, + command index, params, param 1, param 2) ; + execute command ; + IF is error + THEN put error ; + clear error + FI + +ENDPROC command ; + +PROC execute command : + + enable stop ; + SELECT command index OF + CASE .... + OTHERWISE IF command index = 0 + THEN errorstop ("unbekanntes Kommando") ELSE command error + FI + END SELECT + +ENDPROC execute command ; + + + + + +#ib(9)#4.4. Verschiedenes#ie(9)# + + +#ib(9)##ib#SESSION#ie(9)##ie# + + +Mit Hilfe von 'session' kann man feststellen, ob das System neu gestartet wurde. Dabei +spielt es keine Rolle, ob es korrekt ('shutup') abgeschaltet wurde, oder ob es sich um +einen "RERUN" handelt. + +#ib#session#ie# + INT PROC session + Zweck: Liefert eine "Sitzungsnummer". Diese wird automatisch bei jedem + Systemstart erhöht. + +Beispiel: + + + REP + INT VAR old session := session ; + WHILE session = old session REP pause (100) PER ; + putline ("Neuer Systemstart") + PER. + + + + +#ib(9)##ib#INITFLAG#ie##ie(9)# + + +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 #on("b")##on("i")#in dieser Task#off("b")##off("i")# schon initialisiert +wurde. + + +#ib#INITFLAG#ie# + TYPE INITFLAG + Zweck: Erlaubt die Deklaration entsprechender Flaggen. + +:= + OP := (INITFLAG VAR flag, BOOL CONST flagtrue) + Zweck: Erlaubt die Initialisierung von INITFLAGs + +#ib#initialized#ie# + BOOL PROC initialized (INITFLAG VAR flag) + Zweck: 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 automa + tisch 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 ; + .... + + ENDPROC push ; + + PROC pop (INT VAR value) : + + initialize stack if necessary ; + .... + + ENDPROC pop ;. + + initialize stack if necessary : + IF NOT initialized (in this task) + THEN stack pointer := 1 + FI . + + ENDPACKET stack + + + + + +#ib(9)##ib#Bit-Handling#ie##ie(9)# + + +Die #ib#Bit-Operationen#ie# arbeiten auf INT-Objekten. Sie können z.B. für die Systempro +grammierung benutzt werden, wenn es um Bitmasken u.ä. geht. + +Ein INT besteht aus 16 Bits. Dabei hat das niederwertigste die Nummer 0, das höch +stwertige die Nummer 15. + + +#ib#AND#ie# + INT OP AND (INT CONST left, right) + Zweck: Bitweise UND-Verknüpfung von 'left' mit 'right'. + +#ib#OR#ie# + INT OP OR (INT CONST left, right) + Zweck: Bitweise ODER-Verknüpfung von 'left' mit 'right'. + +#ib#XOR#ie# + INT OP XOR (INT CONST left, right) + Zweck: Bitweise EXCLUSIV-ODER-Verknüpfung von 'left' mit 'right'. + +#ib#bit#ie# + BOOL PROC bit (INT CONST bits, bit no) + Zweck: Liefert TRUE genau dann, wenn das Bit mit der Nummer 'bit no' in dem + INT 'bits' gesetzt ist. + +#ib#set bit#ie# + PROC set bit (INT VAR bits, INT CONST bit no) + Zweck: Das Bit mit der Nummer 'bit no' wird in 'bits' auf 1 gesetzt. + +#ib#reset bit#ie# + PROC reset bit (INT VAR bits, INT CONST bit no) + Zweck: Das Bit mit der Nummer 'bit no' wird in 'bits' auf 0 gesetzt. + +#ib#rotate#ie# + PROC rotate (INT VAR bits, INT CONST number of bits) + Zweck: Bits können mit dieser Prozedur zyklisch geschiftet werden. + Bsp.: rotate (1,1) ---> 2 + rotate (1,2) ---> 4 + rotate (1,-3) ---> 16384 + rotate (16384,3) ---> 1 + +#ib#lowest set#ie# + INT PROC lowest set (INT CONST bits) + Zweck: Liefert die Nummer des niederwertigsten 1-Bits in 'bits'. Ist kein Bit auf 1 + gesetzt, wird -1 geliefert. + +#ib#lowest reset#ie# + INT PROC lowest reset (INT CONST bits) + Zweck: Liefert die Nummer des niederwertigsten 0-Bits in 'bits'. Ist kein Bit auf 0 + gesetzt, wird -1 geliefert. + + + + + +#ib(9)#4.5. #ib#Blockorientierte Ein-/Ausgabe#ie##ie(9)# + + + +Die blockorientierte Ein-/Ausgabe dient dazu, Datenraumseiten (#ib#Blöcke#ie#) oder Teile +davon über die #ib#Kanäle#ie# zu transferieren. Sie wird vom System u.a. beim Archivzugriff +und bei der Konfigurierung der Kanäle eingesetzt. + +Die Wirkung der blockorientierten Ein-/Ausgabeoperationen kann dabei kanal- und +rechnerspezifisch unterschiedlich sein. +Auf dem Archivkanal (31) und allen anderen Block-IO-Kanälen werden bei +'code 1 = 0' die normalen Blocklese- bzw. -schreiboperationen durchgeführt. 'code 2' +gibt dabei die Blocknummer an. Andere (positive) Werte von 'code 1' sind zur Zeit +nicht offiziell definiert. Negative Werte können vom SHard für Spezialaufgaben verge +ben werden. + + + +#ib#blockin#ie# + PROC blockin (DATASPACE VAR ds, INT CONST page nr, code1, code2, + INT VAR return code) + Zweck: Die Seite 'page nr' des Datenraums 'ds' wird "eingelesen". Die Opera + tion kann durch 'code1' und 'code2' näher gesteuert werden. + + PROC blockin (ROW 256 INT VAR block, INT CONST code1, code2, + INT VAR return code) + Zweck: Wie oben, nur wird der Block direkt als Datenstruktur übergeben. + +#ib#blockout#ie# + PROC blockout (DATASPACE CONST ds, INT CONST page nr, + code1, code2, INT VAR return code) + Zweck: Die Seite 'page nr' des Datenraums 'ds' wird "ausgegeben". Die Opera + tion kann durch 'code1' und 'code2' näher gesteuert werden. + + PROC blockout (ROW 256 INT CONST block, INT CONST code1, code2, + INT VAR return code) + Zweck: Wie oben, nur wird der Block als Datenstruktur übergeben. + +#ib#control#ie# + PROC control (INT CONST code1, code2, code3, INT VAR return code) + Zweck: Diese Prozedur dient zur Kanalsteuerung. + +#ib#ds pages#ie# + INT PROC ds pages (DATASPACE CONST ds) + Zweck: Liefert die Anzahl der belegten Seiten eines Datenraums. (Jede Seite ist + 512 Byte groß.) + +#ib#next ds page#ie# + INT PROC next ds page (DATASPACE CONST ds, INT CONST page nr) + Zweck: Liefert die Nummer der nächsten (von 'page nr' an gerechneten) Seite + des Datenraums. Die erste belegte Seite erhält man durch + + next ds page (ds, -1) + + #on ("b")#Achtung: Die Seitennummern müssen nicht lückenlos sein.#off ("b")# + diff --git a/doc/system-manual/1.8.7/doc/systemhandbuch.3 b/doc/system-manual/1.8.7/doc/systemhandbuch.3 new file mode 100644 index 0000000..3c0a482 --- /dev/null +++ b/doc/system-manual/1.8.7/doc/systemhandbuch.3 @@ -0,0 +1,1366 @@ +#start(2.5,1.5)# +#pageblock# +#block# +#page (63)# +#headeven# + +%#center#EUMEL-Systemhandbuch + + +#end# +#headodd# + +#center#5. Supervisor, Tasks und Systemsteuerung#right#% + + +#end# + +#ib(9)#5. #ib#Supervisor#ie#, #ib#Tasks#ie# und + #ib#Systemsteuerung#ie##ie(9)# + + + +#ib(9)#5.1. #ib#Tasks#ie##ie(9)# + + + +#ib(9)#Der Datentyp #ib#TASK#ie##ie(9)# + + +Benannte Tasks werden innerhalb eines Rechners vollständig und eindeutig über ihren +Namen identifiziert. Eine weitere Möglichkeit der Identifikation besteht in der Verwen +dung von Datenobjekten vom Typ TASK. Beispiel: + + TASK VAR plotter := task ("PLOTTER 1") + +Die Taskvariable 'plotter' bezeichnet jetzt die Task im System, die augenblicklich den +Namen "PLOTTER 1" hat. Nun sind #ib#Taskvariablen#ie# auch unter Berücksichtigung der Zeit +und nicht nur im aktuellen 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 ande +ren Namens) identifiziert. Wenn die Task "PLOTTER 1" gelöscht worden ist, bezeichnet +'plotter' keine gültige Task mehr. + +#ib#Unbenannte Tasks#ie# haben alle den Pseudonamen "-". Sie können nur über Taskvari +ablen angesprochen werden. + +Der #ib#Task-Katalog#ie# wird vom Supervisor geführt; andere Tasks können sich Kopien +dieses Katalogs besorgen. Einige Prozeduren arbeiten auf dieser taskeigenen Kopie, +ohne diese automatisch auf den neuesten Stand zu bringen (Effizienzgründe). Das +muß bei Bedarf explizit geschehen. + + +#ib#TASK#ie# + TYPE TASK + Zweck: Interner Taskbezeichner + +:= + OP := (TASK VAR dest, TASK CONST source) + Zweck: Zuweisung von internen Taskbezeichnern + += + BOOL OP = (TASK CONST left, right) + Zweck: Gleichheitsabfrage + +< + BOOL OP < (TASK CONST left, right) + Zweck: Überprüft, ob die Task 'left' ein Sohn, Enkel, Urenkel, ... der Task 'right' + ist. + +/ + TASK OP / (TEXT CONST task name) + Zweck: Liefert die Task des angegebenen Namens, falls sie existiert. Der eigene + Katalog wird automatisch aktualisiert (identisch mit der + PROC task (TEXT CONST task name). + Fehlerfall: + * ... gibt es nicht + + TASK OP / (INT CONST station number, TEXT CONST name) + Zweck: Liefert die Task des angegebenen Namen von der Station mit der ange + gebenen Nummer. + +#ib#access#ie# + PROC access (TASK CONST task) + Zweck: Aktualisiert den eigenen Taskkatalog, falls 'task' nicht darin enthalten ist. + +#ib#access catalogue#ie# + PROC access catalogue + Zweck: Aktualisiert den eigenen Taskkatalog, indem die neueste Fassung vom + Supervisor geholt wird. Die Prozeduren 'father', 'son', 'brother' arbeiten + dann auf dieser neuen Fassung. + +#ib#archive#ie# + TASK PROC archive + Zweck: Liefert den internen Taskbezeichner der aktuellen Task mit Namen + "ARCHIVE". Diese Prozedur dient zum schnellen und bequemen An + sprechen der Archivtask. + +#ib#brother#ie# + TASK PROC brother (TASK CONST task) + Zweck: Liefert den nächsten Bruder von 'task'. Falls kein Bruder existiert, wird + 'niltask' geliefert. Aktualisiert den eigenen Katalog nicht automatisch! + +#ib#canal#ie# + TASK PROC canal (INT CONST channel number) + Zweck: Diese Prozedur zeigt an, welche Command-Analyser-Task an einem + bestimmten Kanal hängt. + +#ib#exists#ie# + BOOL PROC exists (TASK CONST task) + Zweck: Falls 'task' auf der eigenen Station liegt, informiert diese Prozedur, ob + die angegebene 'task' noch existiert. Der eigene Taskkatalog wird dabei + aktualisiert. + Wenn abgefragt werden soll, ob 'task' auf einer anderen Station liegt, + muß die Prozedur 'name (task) <> "" ' verwendet werden. + Achtung: Diese Prozedur taugt nicht dazu, zu erfragen, ob eine Task + mit bestimmtem Namen im System exisiert. + + exists (task ("hugo")) + + Falls die Task "hugo" nicht existiert, führt schon der Aufruf + 'task ("hugo")' zum 'errorstop (""hugo" gibt es nicht")'. + +#ib#exists task#ie# + BOOL PROC exists task (TEXT CONST name) + Zweck: Wenn auf der eigenen Station eine Task mit dem Namen 'name' exi + stiert, liefert diese Prozedur 'TRUE'. + +#ib#father#ie# + TASK PROC father + Zweck: Liefert die eigene Vatertask. + + TASK PROC father (TASK CONST task) + Zweck: Liefert den Vater von 'task'. Existiert kein Vater (z.B. bei UR), wird niltask + geliefert. Aktualisiert den eigenen Katalog nicht automatisch! + +#ib#index#ie# + INT PROC index (TASK CONST task) + Zweck: Liefert einen INT-Wert von 1 bis 125, der 'task' unter allen gleichzeitig (!) + existierenden Tasks eindeutig identifiziert. + +#ib#is niltask#ie# + BOOL PROC is niltask (TASK CONST task) + Zweck: task = niltask + +#ib#myself#ie# + TASK PROC myself + Zweck: Liefert eigenen Task-Bezeichner. + +#ib#name#ie# + TEXT PROC name (TASK CONST task) + Zweck: Liefert den Namen von 'task'. Die Task muß noch im System existieren, + sonst ist der Name nicht mehr bekannt. Falls die 'task' noch nicht im + eigenen Katalog enthalten ist, wird er aktualisiert. + +#ib#niltask#ie# + TASK CONST niltask + Zweck: Bezeichner für "keine Task". So liefern die Prozeduren 'son', 'brother' + und 'father' als Resultat 'niltask', wenn keine Sohn-, Bruder- oder Vater + task existiert. + +#ib#printer#ie# + TASK PROC printer + Zweck: Liefert den internen Taskbezeichner der aktuellen Task mit Namen + #ib#PRINTER#ie#. Diese Prozedur dient zum schnellen und bequemen Anspre + chen des Druckspoolers. + +#ib#public#ie# + TASK PROC public + Zweck: Liefert den internen Taskbezeichner der Task #ib#PUBLIC#ie#. + +#ib#reserve#ie# + PROC reserve (TASK CONST task) + Zweck: Reservieren einer Task für den ausschließlichen Dialog mit der Task, in + der das Kommando gegeben wurde. + PROC reserve (TEXT CONST message, TASK CONST task) + Zweck: Wie 'reserve (TASK CONST task)' mit Übergabe einer 'message'. + +#ib#son#ie# + TASK PROC son (TASK CONST task) + Zweck: Liefert den ersten Sohn von 'task'. Falls keiner im Katalog vermerkt ist, + wird 'niltask' geliefert. Aktualisiert den eigenen Katalog nicht automa + tisch! + +#ib#supervisor#ie# + TASK PROC supervisor + Zweck: Liefert den internen Taskbezeichner des Supervisors. + +#ib#task#ie# + TASK PROC task (TEXT CONST task name) + Zweck: Liefert die Task des angegebenen Namens, falls sie existiert. Der eigene + Katalog wird automatisch aktualisiert. + Fehlerfall: + * ... gibt es nicht + + TASK PROC task (INT CONST channel number) + Zweck: Liefert den Namen der Task, die an dem angegebenen Kanal hängt. + + + +#ib##ib(9)#Inter-Task-Kommunikation#ie##ie(9)# + + +Die #ib#Task-Kommunikation#ie# im EUMEL System ist strikt botschaftsorientiert. Eine #ib#Bot +schaft#ie# bzw. "#ib#Sendung#ie#" besteht immer aus einem #ib#Sendungscode#ie# (INT) und einem +Datenraum (DATASPACE). Damit kann eine Botschaft bis zu 1 Mbyte umfassen! + +Kommunikation zwischen zwei Tasks ist nur dann möglich, wenn #ib#Sender#ie# und #ib#Empfän +ger#ie# dazu bereit sind. Eine Sendung kann also nur dann korrekt transferiert werden, +wenn der Empfänger existiert und empfangsbereit ist. Diese Art der Kommunikation +wurde gewählt, um + + - eine möglichst einfache und effiziente Implementation zu ermöglichen und + - mit den vorhandenen Primitiva möglichst flexibel bei der Implementation + "höherer" Kommunikationsmethoden (z.B. Warteschlangen) zu sein. + + +#ib#call#ie# + PROC call (TASK CONST destination, INT CONST send code, + DATASPACE VAR message ds, INT VAR reply code) + Zweck: Die eigene Task wartet, bis die Zieltask 'destination' empfangsbereit ist. + Dann wird die Sendung ('send code' und 'message ds') transferiert. + Anschließend wartet die Sendertask auf eine Antwort von 'destination'. + Für Sendungen anderer Tasks ist sie dabei nicht (!) empfangsbereit, nur + die Zieltask kann eine Antwortsendung schicken. Nachdem eine solche + Antwort eingetroffen ist, wird sie in 'message ds' und 'reply code' gelie + fert und die eigene Task fortgesetzt. Wenn die angesprochene Zieltask + nicht existiert, wird -1 als 'reply code' geliefert. 'message ds' ist in + diesem Fall unverändert. + 'call' hat Ähnlichkeiten mit einem Prozeduraufruf, nur ist es hier der + Aufruf einer anderen Task. Störungen können hierbei nicht auftreten, da + der Zustand der Zieltask keine Rolle spielt (es wird auf Empfangsbereit + schaft gewartet) und beim Warten auf Antwort auch keine "Querschlä + gersendungen" von anderen Tasks dazwischenfunken können. + +#ib#pingpong#ie# + PROC pingpong (TASK CONST destination, INT CONST send code, + DATASPACE VAR message ds, INT VAR reply code) + Zweck: Diese Prozedur wirkt wie die entsprechende 'call'-Prozedur, wartet aber + nicht (!), bis die Zieltask empfangsbereit ist. Wenn die Zieltask existiert, + aber nicht empfangsbereit ist, wird -2 als 'reply code' geliefert. Der + 'message ds' ist dann nicht verändert. + +#ib#send#ie# + PROC send (TASK VAR destination, INT CONST send code, + DATASPACE VAR message ds, INT VAR receipt) + Zweck: Wenn die Zieltask existiert und empfangsbereit ist, wird die Sendung + ('send code' und 'message ds') transferiert und die Zieltask aktiviert. Als + 'receipt' wird 0 (=ack) gemeldet. Diese positive Quittung kommt nicht + von der Zieltask, sondern bestätigt nur, daß die Sendung ordnungsge + mäß übertragen wurde. Der Datenraum gehört dann nicht mehr der + Sender-, sondern der Zieltask, d.h. die Variable 'message ds' bezeichnet + keinen gültigen Datenraum mehr. + Im Gegensatz zu 'call' und 'pingpong' läuft die Sendertask ohne Halt + weiter und wartet nicht auf eine Antwort von der Zieltask. + Falls die Zieltask nicht existiert, wird -1, falls sie nicht empfangsbereit ist, + -2 als 'receipt' geliefert. Bei diesen negativen Quittungen bleibt der + Datenraum Eigentum der Absendertask, d.h. die Variable 'message ds' + bezeichnet immer noch einen gültigen Datenraum. + + PROC send (TASK VAR destination, INT CONST send code, + DATASPACE VAR message ds) + Zweck: s.o. Negative Quittungen (-1 oder -2) werden jedoch ignoriert. Der Da + tenraum wird entweder transferiert oder gelöscht ('forget'), steht also in + keinem Fall mehr zur Verfügung. Die Prozedur sollte nur verwendet + werden, wenn der Sender sicher ist, daß die Sendung transferiert wer + den kann, bzw. daß sie im Fehlerfall nicht transferiert zu werden braucht. + +#ib#wait#ie# + PROC wait (DATASPACE VAR message ds, INT VAR message code, + TASK VAR source task) + Zweck: Die eigene Task geht in den #ub##ib#offenen Wartezustand#ie##ue# über. Sie ist jetzt + gegenüber allen anderen Tasks empfangsbereit. Sie wird erst fortge + setzt, wenn eine Sendung eintrifft. Diese wird in 'message ds' und 'mes + sage code', die Absendertask in 'source task' geliefert. + +Der #ub##ib#Sendungscode#ue##ie# muß zwischen den Beteiligten abgesprochen sein und ist also frei +wählbar. Allerdings sind negative Werte nicht erlaubt, sondern für bestimmte "Pseudo +antworten" vom Betriebssystem reserviert: + + -1 "Zieltask existiert nicht" + + -2 "Zieltask ist nicht empfangsbereit" + + -4 "Eingabe vom Kanal" Diese Meldung kann nur (!) beim offenen War + ten ('wait') auftreten, und auch dann nur, wenn die Task gleichzeitig + an einen Kanal angekoppelt ist. Auf diese Weise wird mitgeteilt, daß + mindestens ein Zeichen vorliegt. Dieses kann im folgenden mit 'in + char', 'incharety', 'blockin' oder darauf aufbauenden Prozeduren + gelesen werden. + +Weitere Codes werden in Systemroutinen standardmäßig verwandt und sollten auch +von Anwenderroutinen genauso interpretiert werden: + + 0 "#ib#ack#ie#" positive Quittung + + 1 "#ib#nak#ie#" negative Quittung + + 2 "#ib#error nak#ie#" negative Quittung mit Fehlermeldung. + Der gelieferte Datenraum sollte die Struktur eines + BOUND TEXTs haben und die Fehlermeldung in + diesem TEXT beinhalten. + + +Beispiel: #ub#Kommunikation mit einem Manager#ue# + + + Auftraggeber Manager + + + call (....) REP + wait (ds, order, order task) ; + execute order ; + send (order task, reply, ds) + PER + +Da der Auftraggeber 'call' verwendet, wartet er automatisch so lange, bis der Manager +für ihn empfangsbereit wird. Dann schickt er die Sendung und geht gleichzeitig (!) in +den geschlossenen "auf Antwort warten" - Zustand über. Der Manager kann daher +unbesorgt mit dem "unsicheren" 'send' antworten, da die Empfangsbereitschaft des +Auftraggebers nur durch Katastrophen wie Löschung der Task oder "halt from terminal" +gestört werden kann. (In diesen Fällen kann die Antwort ruhig ins Leere gehen.) + +Hier sieht man auch den Unterschied zwischen + + call (...) und send (....); wait (....) . + +Bei der zweiten Alternative können drei Störfälle eintreten: + + + a) Der Manager ist nicht empfangsbereit. 'send' versagt, 'wait' wartet ewig. + + b) Da über die zeitlichen Rahmenbedingungen nichts ausgesagt werden kann, + ist es möglich, daß der Manager die Antwort schickt, bevor die 'wait'-Opera + tion beim Auftraggeber ausgeführt werden konnte. In unserem Beispiel + würde das den Verlust der Rückmeldung und ewiges Warten seitens des + Auftraggebers auslösen. + + c) Beim 'wait' kann eine Störsendung einer anderen Task eintreffen. + + + + + + + +#ib(9)#5.2. #ib#Supervisor#ie##ie(9)# + + + +#ib(9)##ib#Verbindung zum Supervisor#ie##ie(9)# + + +#ib#begin#ie# + PROC begin (PROC start, TASK VAR new task) + Zweck: Es wird eine #ib#unbenannte Task#ie# (Pseudoname "-") als neuer Sohn der + aufrufenden eingerichtet und mit der Prozedur 'start' gestartet. Namens + kollision ist nicht möglich, die erzeugte Task kann aber auch nicht na + mensmäßig angesprochen werden. 'new task' identifiziert den neuen + Sohn, falls kein Fehler auftrat. + Fehlerfälle : + * zu viele Tasks + + PROC begin (TEXT CONST son name, PROC start, TASK VAR new task) + Zweck: Es wird eine Task mit Namen 'son name' als Sohn der aufgerufenen + eingerichtet und mit der Prozedur 'start' gestartet. 'new task' identifi + ziert den neuen Sohn, falls kein Fehler auftrat. + Fehlerfälle : + * zu viele Tasks + * Name unzulaessig (* "" oder LENGTH > 100 *) + * ... existiert bereits + +#ib#begin password#ie# + PROC begin password (TEXT CONST password) + Zweck: Bei normalen 'global manager'-Tasks kann man mit dieser Operation + das weitere Kreieren von Sohntasks unter Paßwortkontrolle stellen. + Wenn dieses Kommando in der Manager-Task gegeben worden ist, wird + bei folgenden SV-begin-Kommandos interaktiv das Paßwort verlangt. + Dabei gelten die üblichen Paßwort-Konventionen: + + a) "" (Niltext) bedeutet #on("i")#kein Paßwort#off("i")#. Damit kann man durch + 'begin password ("")' das Paßwort wieder ausschalten. + b) "-" bedeutet #on("i")#jedes eingegebene Paßwort ist ungültig#off("i")#. Damit + kann man durch 'begin password ("-")' das Einrichten von + Sohntasks von außen (durch SV-Kommando) abschalten. + +#ib#break#ie# + PROC break + Zweck: Die Task koppelt sich von einem evtl. angekoppelten Terminal ab. Bei + der Abkopplung wird auf dem Terminal die "Tapete" ("Terminal n... + EUMEL Version ..../M...") ausgegeben. + + PROC break (QUIET CONST quiet) + Zweck: Die Task koppelt sich von einem evtl. angekoppelten Terminal ab. Dabei + wird aber keine "Tapete" ausgegeben. + +#ib#channel#ie# + INT PROC channel + Zweck: Liefert die #ib#Kanalnummer#ie# der eigenen Task. Falls kein Kanal (Terminal) + zugeordnet ist, wird 0 geliefert. + + INT PROC channel (TASK CONST task) + Zweck: Liefert die Kanalnummer der angegebenen Task. Ist kein Kanal zuge + ordnet, wird 0 geliefert. + +#ib#clock#ie# + REAL PROC clock (INT CONST index) + Zweck: Liefert die über Index spezifizierte #ib#Systemuhr#ie#. Die Zeiteinheit ist 1 sec, + die Meßgenauigkeit 0.1 sec. + clock (0) : CPU-Zeit der eigenen Task + clock (1) : Realzeit des Systems + + REAL PROC clock (TASK CONST task) + Zweck: Liefert die CPU-Zeit der angegebenen Task. + + Hinweis: Die CPU-Zeit beginnt mit der Taskkreation zu laufen. Sie gibt also + jeweils die gesamte bisher verbrauchte CPU-Zeit an. Die Zeitdauer + bestimmter Operationen kann als Differenz zweier 'clock'-Aufrufe + gemessen werden. Beim Ende einer Task wird ihr CPU-Zeitverbrauch + dem Vater zugeschlagen, um Abrechnungen zu ermöglichen. + +#ib#continue#ie# + PROC continue (INT CONST channel nr) + Zweck: Die Task versucht, sich an den vorgegebenen Kanal anzukoppeln. Falls + sie vorher schon an ein Terminal gekoppelt war, wird implizit 'break' + durchgeführt, falls die Aktion erfolgreich durchgeführt werden konnte. + Ein erfolgreiches 'continue' beinhaltet implizit 'reset autonom'. + Anmerkung: Normale Tasks können auf die Kanäle 1-24 zugreifen, + Systemtasks dürfen sich auch an die privilegierten Kanäle + 25-32 ankoppeln. + Fehlerfälle: + * ungueltiger Kanal + * Kanal belegt + +#ib#end#ie# + PROC end + Zweck: Löscht die eigene Task und alle Söhne. Wenn die Task an ein Terminal + angekoppelt ist, wird vorher angefragt, ob wirklich gelöscht werden soll. + Anschließend wird die Standard-"Tapete" auf dem Bildschirm ausge + geben. + + PROC end (TASK CONST task) + Zweck: Löscht die angegebene 'task'. 'task' muß allerdings die eigene oder eine + Sohn- bzw. Enkel-Task der eigenen sein (siehe auch: 'Privilegierte Ope + rationen'). Im Unterschied zur oben aufgeführten parameterlosen Proze + dur 'end' wird nicht angefragt und auch keine "Tapete" ausgegeben. + Wenn also die eigene Task ohne Reaktion auf dem Terminal beendet + werden soll, kann dies mit 'end (myself)' geschehen. + Fehlerfall: + * 'end' unzulaessig + +#ib#family password#ie# + PROC family password (TEXT CONST password) + Zweck: Diese Prozedur setzt oder ändert das Paßwort derjenigen Familien + mitglieder, die kein Paßwort oder das gleiche Paßwort wie die aufrufen + de Task haben. + Zu einer Familie gehören die Task, in der man sich befindet, und die ihr + untergeordneten Tasks. + Natürlich gelten auch hier die allgemeinen Paßwortbedingungen (siehe + dazu: 'task password'). + Beispiel: Das Kommando 'family password ("EUMEL")' wird in SYSUR + gegeben. Dadurch wird das SYSURPaßwort und die Paß + worte der entsprechenden Tasks unter SYSUR auf "EUMEL" + gesetzt. + + +#ib#next active#ie# + PROC next active (TASK VAR task) + Zweck: 'task' wird auf die nächste aktive Task gesetzt. Aktiv sind alle Tasks, die + sich im Zustand 'busy' befinden oder auf Ein/Ausgabe warten (i/o) und + an einen Kanal angekoppelt sind. Beispiel: + + + TASK VAR actual task := myself; + REP + ... ; + next active (actual task) + UNTIL actual task = myself PER. + + + Hier werden alle aktiven Tasks durchgemustert (z.B. für Scheduling- + Anwendungen). Dieses Verfahren ist sehr viel weniger aufwendig als + eine Durchmusterung des ganzen Taskbaumes, liefert aber nur die + gerade aktiven Tasks. + +#ib#rename myself#ie# + PROC rename myself (TEXT CONST new task name) + Zweck: Die eigene Task erhält als neuen Tasknamen 'new task name'. Damit + kann auch aus einer benannten eine unbenannte Task mit dem Pseu + donamen "-" werden. Umbenennung in die andere Richtung ist eben + falls möglich. + Achtung: Durch das Umbenennen der Task werden alle Taskvariablen, + die sich auf diese Task beziehen, ungültig (als wäre die Task + gelöscht und dann neu eingerichtet). + Fehlerfälle: + * ... existiert bereits + * Name unzulaessig + +#ib#reset autonom#ie# + PROC reset autonom + Zweck: Die eigene Task deklariert sich beim Supervisor als nicht autonom + (Normalzustand). Das bedeutet, 'continue'-Aufforderungen über ein + 'Supervisor-Kommando' vom Terminal werden vom System ohne Be + nachrichtigung der Task durchgeführt. + +#ib#set autonom#ie# + PROC set autonom + Zweck: Die eigene Task deklariert sich beim Supervisor als #ib#autonom#ie# (üblich für + Manager-Tasks). Wenn jetzt ein 'continue'-Supervisor-Kommando auf + diese Task von einem Terminal aus gegeben wird, wird der Task über + 'send' eine Nachricht zugestellt. + Achtung: Im autonomen Zustand ist der Programmierer selbst für die + Reaktion der Task verantwortlich. Man kann sie von außen auf + keine Weise gewaltsam an ein Terminal koppeln (ermög + licht Paßalgorithmen / Datenschutz). + Um die Programmierung etwas zu entschärfen, wird eine + Task automatisch aus dem autonomen in den Normalzustand + überführt, wenn sie selbst ein 'continue' gibt. + +#ib#status#ie# + INT PROC status (TASK CONST task) + Zweck: Liefert den Status der angegebenen Task: + + 0 -busy- Task ist aktiv. + 1 i/o Task wartet auf Beendigung des Outputs oder + auf Eingabe. + 2 wait Task wartet auf Sendung von einer anderen Task. + 4 busy-blocked Task ist rechenwillig, ist aber blockiert. + 5 i/o -blocked Task wartet auf I/O, ist aber blockiert. + 6 wait-blocked Task wartet auf Sendung, ist aber blockiert. + Achtung: Die Task wird beim Eintreffen einer + Sendung automatisch entblockiert. + +#ib#storage#ie# + PROC storage (INT VAR size, used) + Zweck: Informiert über den physisch verfügbaren ('size') und belegten ('used') + Speicher des Gesamtsystems. Die Einheit ist KByte. + Achtung: 'size' gibt den Speicher an, der benutzt werden kann, ohne in + eine Engpaßsituation zu kommen. Tatsächlich wird auf dem + Hintergrundmedium noch eine gewisse Reserve freigehalten. + Wenn diese angebrochen wird, befindet sich das System im + #ib#Speicherengpaß#ie#. Dieser Zustand kann mit 'used > size' + abgefragt werden. + + INT PROC storage (TASK CONST task) + Zweck: Liefert die Größe des Speicherbereichs in KByte, den die angegebene + Task augenblicklich belegt. + Dabei werden durch Sharing mögliche Optimierungen nicht berücksich + tigt. D.h. eine Task kann physisch erheblich weniger Speicher als logisch + belegen. Entsprechend kann die Speichersumme aller Tasks den phy + sisch belegten Speicherbereich des Gesamtsystems beträchtlich über + schreiten. + +#ib#task password#ie# + PROC task password (TEXT CONST password) + Zweck: Das angegebene Paßwort wird beim Supervisor hinterlegt. Bei folgen + den SV-Kommandos 'continue...' auf diese Task wird interaktiv das + Paßwort abgefragt. Dabei gelten die üblichen Paßwort-Konventionen: + + a) "" (Niltext) bedeutet #on("i")#kein Paßwort#off("i")#. Damit kann man durch + 'task password ("")' das Paßwort wieder ausschalten. + + b) "-" bedeutet #on("i")#jedes eingegebene Paßwort ist ungültig#off("i")#. Damit + kann man durch 'task password ("-")' das Ankoppeln an ein + Terminal von außen (durch SV-Kommando) unterbinden. + + + + +#ib##ib(9)#Privilegierte Operationen#ie(9)##ie# + + +Die im folgenden aufgeführten privilegierten Operationen können #ub#nur#ue# von #ib#System +tasks#ie# - das sind direkte oder indirekte Söhne des Supervisors - ausgeführt werden. Um +Mißbrauch unmöglich zu machen, sollte der Supervisor nach der Einrichtung der +gewünschten Systemtasks bzgl. der Einrichtung neuer Söhne gesperrt und alle Sy +stemtasks durch Paßworte geschützt werden. + + +#ib#block#ie# + PROC block (TASK CONST task) + Zweck: Die angegebene #ib#Task wird blockiert#ie#, d.h. so lange von der Verarbeitung + suspendiert, bis die Blockade durch 'unblock' wieder aufgehoben wird. + Diese Operation wird vom Scheduler benutzt. Falls das Packet 'schedu + ler' insertiert ist, sollten andere Tasks die Prozedur 'block' nicht anwen + den, um dem Scheduling nicht entgegenzuwirken. + +#ib#collect garbage blocks#ie# + PROC collect garbage blocks + Zweck: Es wird eine außerplanmäßige Gesamtmüllabfuhr durchgeführt. Plan + mäßig (d.h. ohne Aufruf dieser Prozedur) wird sie alle 15 Minuten und in + Engpaßsituationen durchgeführt. Nach Aufruf dieser Prozedur wird der + automatische Fixpunkt/ Müllabfuhr-Rhythmus ca. 1 Stunde lang ge + sperrt. Somit kann man z.B. in der Task "scheduler" einen eigenen + Fixpunkt/Müllabfuhr-Rhythmus implementieren. + Achtung: Diese Operation erfordert starkes Paging und dauert dement + sprechend lange. + +#ib#end#ie# + PROC end (TASK CONST task) + Zweck: Die angegebene Task und alle Söhne, Enkel etc. werden gelöscht. + Systemtasks (direkte und indirekte Nachkommen des SUPERVISORs) + können beliebige andere Tasks (nicht nur eigene Söhne) löschen. + +#ib#fixpoint#ie# + PROC fixpoint + Zweck: Für das Gesamtsystem wird ein außerplanmäßiger #ib#Fixpunkt#ie# geschrie + ben. Planmäßige Fixpunkte (d.h. ohne Aufruf dieser Prozedur) werden + alle 15 Minuten geschrieben. Nach Aufruf dieser Prozedur wird der + automatische Fixpunkt/Müllabfuhr-Rhythmus ca. 1 Stunde lang ge + sperrt. Somit kann man z.B. in der Task "scheduler" einen eigenen + Fixpunkt/Müllabfuhr-Rhythmus implementieren. + Achtung: Diese Operation verursacht starkes Paging (Rückschreiben + aller veränderten Seiten auf das Hintergrundmedium) und + dauert dementsprechend lange. + +#ib#prio#ie# + INT PROC prio (TASK CONST task) + Zweck: Liefert die augenblickliche #ib#Priorität#ie# der angegebenen Task. + + PROC prio (TASK CONST task, INT CONST new prio) + Zweck: Setzt die Priorität der Task. + + Hinweis: 0 ist die höchste, 15 die niedrigste Priorität. Die Prioritäten 0 bis 2 + werden von EUMEL 0 (fine scheduling) verwaltet. Die restlichen Priori + täten können für 'rough scheduling' (siehe auch im Kapitel Scheduler) + eingesetzt werden. + Durch 'continue ("name")' wird die Priorität wieder auf 0 gesetzet. + +#ib#set date#ie# + PROC set date + Zweck: #ib#Datum#ie# und #ib#Uhrzeit#ie# können im Dialog gesetzt werden (Form wie beim + Start des Systems). Dabei wird gegebenenfalls die HardwareUhr gele + sen. + Sollte der SHard ein falsches Datum liefern, so muß das Datum mit + set clock (date("tt.mm.jj") + time ("hh:mm:ss")) + gesetzt werden. + +#ib#save system#ie# + PROC save system + Zweck: Der gesamte Systemhintergrund wird auf Archivdisketten gesichert. Zu + diesem Zweck wird das System wie bei 'shutup' heruntergefahren. + +#ib#shutup#ie# + PROC shutup + Zweck: #ib#Kontrolliertes Herunterfahren des Systems#ie#. Beim nächsten Systemstart + wird automatisch Datum und Uhrzeit erfragt, wenn der Kommandodial + og eingeschaltet ('command dialogue (TRUE)') und keine Hardwareuhr + vorhanden ist. Falls diese Prozedur nicht vor dem Abschalten aufgerufen + wurde, findet beim Neustart ein Aufsetzen auf dem letzten Fixpunkt statt + (RERUN). + +#ib#unblock#ie# + PROC unblock (TASK CONST task) + Zweck: Eine vorherige Blockierung der Task wird aufgehoben. Ist die Task nicht + blockiert, bewirkt 'unblock' nichts. Diese Operation wird vom Scheduler + benutzt. Andere Tasks sollten sie normalerweise nicht anwenden, um + dem Scheduling nicht entgegenzuwirken. + + + + + +#ib(9)#5.3. #ib#ID Konstanten#ie##ie(9)# + + +Die Informationsprozedur + + INT PROC id (INT CONST no) + +liefert folgende Informationen über die Soft und Hardware des Rechners: + + Von EUMEL 0 werden geliefert: + id (0) --> EUMELVersion + id (1) --> Prozessortyp (1: Z80, + 2: Z8001, + 3: 8086 und kompatible, + 4: 68000 + 5: 80286) + id (2) --> UrladerVersion + id (3) --> reserviert + + Vom SHard werden geliefert: + id (4) --> Lizenznummer des SHards + id (5) --> Installationsnummer des EUMELAnwenders + id (6) --> SHardspezifisch + id (7) --> SHardspezifisch + + + + + +#ib(9)#5.4. #ib#Systemverwaltung#ie##ie(9)# + + +#on("i")#Achtung#off("i")#: Dieser Teil des Systemhandbuchs ist nur für solche Multi-User-Installationen + von Bedeutung, die erweiterte Systemverwaltungsfunktionen generieren + bzw. modifizieren wollen. + + #on("i")#Das EUMEL-System ist in der ausgelieferten minimalen Standardform (ohne + die Features) ohne weiteres benutzbar#off("i")#. + + + + + +#ib(9)#Der Systemmanager #ib#SYSUR#ie##ie(9)# + + +Der Systemmanager verhält sich im wesentlichen wie ein normaler Manager, allerdings +mit folgender Erweiterung: + + - Die Operationen 'list' und 'fetch' können von allen Tasks des Systems und + nicht nur von Söhnen durchgeführt werden. Damit kann man Systemverwal + tungsdateien (z.B. "#ib#logbuch#ie#") von allen Tasks aus lesen. 'erase' und 'save' sind + jedoch nur von Söhnen bzw. Enkeln - d.h. von privilegierten Systemtasks - aus + zulässig. + +Das Paket stellt folgende Operationen zusätzlich zur Verfügung: + +#ib#generate shutup manager#ie# + PROC generate shutup manager + Zweck: Es wird eine Sohntask mit Namen "shutup" kreiert. Diese Task ist nicht + (!) paßwortgeschützt, läßt aber keine normalen Kommandos zu, son + dern fragt nur + + shutup (j/n) ? + + So kann jeder das System kontrolliert abschalten und die privilegierten + Operationen des OPERATORs wie 'end' sind dennoch geschützt. + +#ib#put log#ie# + PROC put log (TEXT CONST log record) + Zweck: Der angegebene 'log record' wird mit vorangestelltem Tasknamen des + Absenders, Datums- und Uhrzeitangabe in die Logbuchdatei "logbuch" + in der Task "SYSUR" geschrieben. Der neue Satz wird an die Datei ange + fügt. ("logbuch" wird z.B. vom EUMELmeter verwandt.) + + Hinweis: Bei Verwendung des Logbuchs darf die zwar große, aber doch end + liche Dateikapazität nicht vergessen werden. Nachdem das Logbuch + mit 4073 Sätzen voll ist, werden weitere 'put log' Operationen igno + riert. Die Datei "logbuch" sollte deshalb - wenn sie beispielsweise vom + EUMELmeter verwandt wird - von Zeit zu Zeit gelöscht werden ('erase' + bzw. 'forget')! + + + + +#ib(9)##ib#Scheduler#ie##ie(9)# + + +Der Scheduler dient zur Verwaltung der rechenwilligen #ib#Hintergrundtask#ie#s. Will man den +Scheduler (eventuell abgeändert) insertieren, muß man die Task "scheduler" als Sohn +von SYSUR einrichten. Dann holt man die Datei "scheduler" vom Archiv und insertiert +sie. "scheduler" beinhaltet "#ib#eumelmeter#ie#". Es wird beim Start erfragt, ob die Meßrouti +nen aktiviert werden sollen oder nicht. + + + + +#ib##ib(9)#Funktionsweise des Schedulers#ie(9)##ie# + + +Der Scheduler sammelt in bestimmten Zeitintervallen alle aktiven (rechnenden) Tasks +ab, die an kein Terminal angekoppelt sind und auch keine Manager sind. Diese Tasks +werden blockiert und in die Warteschlange der #ib#Standardklasse#ie# eingefügt. + +Die Klassen des Schedulers werden durch die #ib#Taskpriorität#ie#en 5 bis 9 definiert. Die +Standardklasse entspricht der Priorität 7. Die Klassenzugehörigkeit einer Task kann von +einer Systemtask aus (z.B. von "OPERATOR") mit der Prozedur '#ib#prio#ie#' verändert werden. + +Der Scheduler geht nach folgender Strategie vor: + + Anhand der Vordergrund/Hintergrundlast des Systems wird entschieden, ob + überhaupt Hintergrundtasks aktiv sein dürfen, welche Klassen aktiv sein dürfen + und wieviel #ib#Hintergrundtask#ie#s gleichzeitig rechnen dürfen. + + Die wartenden #ib#Hintergrundtask#ie#s werden im #ib#Round-Robin-Verfahren#ie# aktiviert. + Dabei kommt die Klasse n+1 erst dann zum Zug, wenn die Warteschlange der + Klasse n leer ist oder weniger Tasks enthält, als gleichzeitig aktiviert werden + sollen. + +Die implementierte Standardstrategie hat als oberste Maxime, den Vordergrund auf +keinen Fall zu stören. Dementsprechend wird der Hintergrund nur aktiviert, wenn eine +der folgenden Bedingungen erfüllt ist: + + - Die Vordergrundlast des Systems liegt unter 3% . + + - Es ist keine normale #ib#Vordergrundtask#ie# (Nachfahre von "UR") an einen Kanal + angekoppelt. Man beachte, daß Systemtasks hierbei nicht berücksichtigt + werden. Ein aktiver Drucker blockiert die Hintergrundtasks also nicht. + + + + +EUMELmeter (Systemstatistik) + + +Die #ib#Meßsoftware#ie# zum #ib#Protokollieren der Systembelastung#ie# befindet sich auf dem Archiv +'std.zusatz'. + +Falls das System keinen #ib#Scheduler#ie# benutzt, muß eine Meßtask als Sohn von "SYSUR" +eingerichtet werden. In diese Task muß dann die Datei "#ib#eumelmeter#ie#" vom Archiv geholt +und übersetzt werden. + +Falls das System einen Scheduler beinhalten soll, muß bei der Generierung des Sche +dulers lediglich auf die Frage "mit eumelmeter (j/n) ?" mit "j" geantwortet werden. + + + +#ib##ib(9)#EUMELmeter#ie(9)##ie# + + +Das EUMELmeter protokolliert die #ib#Systemlast#ie# in ca. 10 minütigen Abständen in der +Datei "#ib#logbuch#ie#" in "SYSUR". Für jedes Meßintervall wird eine Zeile angefügt. Die Zeilen +sind folgendermaßen aufgebaut: + +tt.mm.jj hh:mm hg uf ub pw pb cpuf cpub cpus last nutz + + +tt.mm.jj hh:mm Datum und Uhrzeit des Eintrags + +hg Größe des aktuell belegten Hintergrundspeichers + (in KB) + +uf Anzahl der aktiven Vordergrundtasks + +ub Anzahl der aktiven Hintergrundtasks + +pw #ib#Paginglast#ie# bei wartender CPU (#ib#Paging/Wait#ie#) + +pb Paginglast bei aktiver CPU (#ib#Paging/Busy#ie#) + +cpuf #ib#CPU-Auslastung#ie# durch Vordergrundtasks + +cpub CPU-Auslastung durch Hintergrundtasks + +cpus #ib#CPU-Systemlast#ie# + +last #ib#Gesamtlast des Systems#ie#: + pw + pb + cpuf + cpub+ cpus + (Achtung: kann 100% übersteigen, da Platte und CPU über + lappt arbeiten können.) + +nutz #ib#Nutzgüte#ie# im Meßintervall: 100% - pw - cpus + Die Nutzgüte gibt an, welcher Anteil der Systemarbeit für echte + Nutzarbeit verfügbar war. Sie ist die Summe aus der echten + Nutzlast 'cpuf+cpub' und der Leerzeit, die ja theoretisch auch + für Nutzarbeit hätte verwandt werden können. Sie läßt sich, wie + oben angegeben, auch berechnen, indem man den idealerweise + überflüssigen Overhead 'cpus' und 'pw' von 100% abzieht. +#page# + +#count per page# +#headeven# +%#center#EUMEL-Systemhandbuch + + +#end# +#headodd# +#center#6. Der EUMEL-Drucker#right#% + + +#end# + +#ib(9)#6. Der #ib#EUMEL-Drucker#ie##ie(9)# + + + +#ib(9)#6.1. Allgemeine Einführung#ie(9)# + + +Die Ansteuerung eines #ib#Druckers#ie# durch das EUMEL-System geschieht durch zwei +aufeinanderbauende Komponenten. Die eine Komponete ist der hardwareunabhängi +ge #ib#EUMEL-Drucker#ie#, der die #ib#Textverarbeitungsanweisungen#ie# umsetzt und die Druck +seite entsprechend aufbereitet, so daß sie im Blocksatz, in Tabellenform oder in Spal +ten gedruckt werden kann. Die andere Komponente ist der hardwareabhängige #ib#Druk +kertreiber#ie#, der durch ein einfaches Interface zum EUMEL-Drucker, wie z.B. Textausge +ben, Positionieren oder Schrifttypen und Modifikationen an- und ausschalten, den +eigentlichen Druck vornimmt. +Die hardwareunabhängige Komponente, der EUMEL-Drucker, befindet sich bei den +ausgelieferten Systemen im priviligierten Ast des Taskbaums, so daß beim Anschluß +eines Druckers nur noch der hardwareabhängige Druckertreiber insertiert werden muß. +Auf dem PRINTER-Archiv befinden sich schon einige Druckeranpassungen für diverse +Druckertypen. + +- Implementierung des Druckertreiber-Interface + Das Paket mit dem Druckertreiber muß in einer Task "PRINTER" insertiert und + ein Spool eingerichtet werden. + +- Erstellen einer Fonttabelle für den anzuschießenden Drucker + Eine vorhandene Fonttabelle wird dabei in die Task "configurator" gebracht + werden. Die Fonttabelle sollte in allen bestehenden Tasks - insbesondere in + der Task "PUBLIC" und der Task "PRINTER" - mit dem #on("i")##on("b")#fonttable#off("i")##off("b")#-Kommando + eingestellt werden. + + + + +#ib(9)#6.2. Das #ib#Druckertreiber-Interface#ie##ie(9)# + + +Da der EUMEL-Drucker vor dem Druckertreiber insertiert ist, aber auf dem Drucker +treiber aufbaut, müssen beim Aufruf der 'print'-Prozedur des EUMEL-Druckers die +Prozeduren des Druckertreibers mit übergeben werden. Aus progammtechnischen +Gründen sollte ihre Anzahl möglichst gering gehalten werden. Deshalb gibt es die +folgende drei Prozeduren, die mit einem 'op code' parametrisiert werden. Die Bedeu +tung der weiteren Parameter der Interfaceprozeduren hängen von diesem 'op code' ab. +Die folgende Beschreibung der Prozeduren gibt einen Programmrahmen vor, in dem +die Parameter durch Refinements entsprechend ihrer Bedeutung umdefiniert sind. + + + +PROC open (INT CONST op code, INT VAR param 1, param 2) : + + LET document code = 1 , + page code = 2 ; + + SELECT op code OF + CASE document code : open document + CASE page code : open page + END SELECT. + + + x steps : param1 . + y steps : param2 . + + #ib#open document#ie# : + + Zweck: Die Prozedur wird vom EUMEL-Drucker zur Einleitung jedes Ausdrucks + aufgerufen. Hier können notwendige Initialisierungen der Hardware + durchgeführt werden. In 'x steps' und 'y steps' muß die Breite bzw. + Höhe der bedruckbaren Fläche des Papieres in Mikroschritten des + Druckers angegeben werden.#u##count#)#e# +#foot# + +#value#) Zur Definition der Mikroschritte siehe Bemerkung 2. +#end# + + + + x start : param1 . + y start : param2 . + + #ib#open page#ie# : + + Zweck: Hiermit wird dem Hardware-Interface der Beginn einer neuen Seite + mitgeteilt. Die Parameter 'x start' und 'y start' liefern die gewünschte + Position der linken oberen Ecke des Schreibfeldes. Das Hardware-In + terface muß in diesen Parametern seine augenblickliche Position auf + dem Papier zurückmelden, wobei die Position (0,0) die linke obere + Ecke des Papieres ist. + Vor der Rückmeldung kann aber auch auf die angegebene Startpo + sition positioniert und diese zurückgemeldet werden. Es ist jedoch + darauf zu achten, daß die zurückgemeldete Position den internen + Nullpunkt für die Absolutkoordinaten im EUMEL-Drucker definiert. + Deswegen muß das Hardware-Interface sicherstellen, daß bei einem + "Zeilenrücklauf" die zurückgemeldete Position 'x start' erreicht wird. + (Siehe 'carriage return' in der Prozedur 'execute'). Auch gibt es Fälle, + bei denen links von der gemeldeten 'x start'-Position positioniert wird. + Bei #ib#Druckern mit Einzelblatteinzug#ie#, bei denen das Papier gleich auf die + zweite oder dritte Zeile positioniert wird, sollte, um ein korrektes Druck + bild zu erreichen, diese Postion in 'y start' zurückgemeldet werden. + + +END PROC open; + + +PROC close (INT CONST op code, INT CONST param 1) : + + LET document code = 1 , + page code = 2 ; + + SELECT op code OF + CASE document code : close document + CASE page code : close page + END SELECT. + + + #ib#close document#ie# : + + Zweck: Hiermit wird dem Hardware-Interface das Ende eines Druckvorgangs + mitgeteilt. + + + + remaining y steps : param 1 . + + #ib#close page#ie# : + + Zweck: Hiermit wird dem Hardware-Interface mitgeteilt, daß der Druck der + aktuellen Seite abgeschlossen ist. + 'remaining y steps' gibt an, wieviel Mikroschritte das vertikale Papier + ende noch von der aktuellen Druckposition entfernt ist. Die x-Position + des Druckers ist bei Aufruf dieser Prozedur immer der linke Rand + 'x start'. + + +END PROC close; + + +PROC execute (INT CONST op code, TEXT CONST string, + INT CONST param1, param2) : + + LET write text code = 1 , + write cmd code = 2 , + carriage return code = 3 , + move code = 4 , + draw code = 5 , + on code = 6 , + off code = 7 , + type code = 8 ; + + SELECT op code OF + CASE write text code : write text + CASE write cmd code : write cmd + CASE carriage return code : carriage return + CASE move code : move + CASE draw code : draw + CASE on code : on + CASE off code : off + CASE type code : type + END SELECT . + + + from : param1 . + to : param2 . + + #ib#write text#ie# : + + Zweck: Der übergebene Text 'string' muß von der Zeichenposition 'from' bis + 'to' (einschließlich) auf dem Drucker ausgegeben werden. Die Über + schreitung der Papierbreite braucht nicht überprüft zu werden. + + + + #ib#write cmd#ie# : + + Zweck: Der übergebene Text 'string' enthält zwischen den Positionen 'from' + und 'to' ein direkt angegebenes #ib#Druckerkommando#ie# (\#"..."\#). Wenn + direkte Druckerkommandos erlaubt sein sollen, müssen sie ausgege + ben werden. + + + + x steps to left margin : param 1 . + + #ib#carriage return#ie# : + + Zweck: Der Druckkopf muß (ohne Zeilenvorschub) an den linken Rand be + wegt werden, d.h. an die bei 'open page' vom Druckertreiber gemel + dete Position 'x start'. 'x steps to left margin' gibt an, wieviel Minimal + schritte die augenblickliche Position vom linken Rand entfernt ist. + + + + x steps : param 1 . + y steps : param 2 . + + #ib#move#ie# : + + Zweck: Die Schreibposition muß um 'x steps' Mikroschritte nach rechts und um + 'y steps' Mikroschritte nach unten verschoben werden. Negative + Schrittwerte bedeuten dabei die jeweils andere Richtung. Das Über + schreiten des Papiers braucht nicht überprüft zu werden. Bei einer + horizontalen Bewegung nach rechts ('x steps' > 0) müssen die einge + schalteten Modifikationen beachtet werden. Wenn z.B. 'underline' + eingeschaltet ist, muß die Strecke unterstrichen werden. + Kann eine Leistung (z.B. Bewegung nach links) nicht erbracht wer + den, muß ein 'errorstop' ausgelöst werden. Im Fehlerfall bei einer + Horizontalbewegung versucht der EUMEL-Drucker nach einem Zei + lenrücklauf nochmals die angestrebte x-Position zu erreichen. Somit + brauchen horizontale Bewegungen nach links ('x steps' < 0) nicht + unbedingt implementiert zu werden, sondern können mit einem 'error + stop' beantwortet werden. Im Fehlerfall bei einer vertikalen Bewegung + wird an der alten Position weitergeschrieben. + + + + #ib#draw#ie# : + Zweck: Von der aktuellen Schreibposition an (linke untere Ecke der Zeichenposition) + soll eine gerade Linie zum Zielpunkt ('x steps' weiter rechts, 'y steps' weiter + unten) gezogen werden. Kann eine Leistung (z.B. schräge Linie, Linie nach + oben o.ä.) nicht erbracht werden, muß ein 'errorstop' ausgelöst werden. + Dieser Fehlerfall wird vom EUMEL-Drucker ignoriert. Das Überschreiten + des Schreibfeldes braucht nicht überprüft zu werden. + + + + modification : param 1 . + + #ib#on#ie# : + + Zweck: Die #ib#Modifikation#ie# der Nummer 'modification' soll eingeschaltet wer + den, sofern die Hardware es erlaubt. Augenblicklich gibt es folgende + Modifikationen: + + 1 underline + 2 bold + 4 italics + 8 reverse + + Die in der Fonttabelle spezifizierte Befehlssequenz, um die entspre + chende Modifikation anzuschalten, kann mit der Prozedur #on("i")#on string + (modification)#off("i")# abgefragt werden. + Kann eine Leistung nicht erbracht werden, muß ein 'errorstop' aus + gelöst werden. Im Fehlerfall der Modifikation 'underline' versucht der + neue EUMEL-Drucker die Zeile mit Hilfe von 'draw' zu unterstreichen. + Im Fehlerfall der Modifikation 'bold' wird die Zeile nochmals, um den in + der Fonttabelle spezifizierten 'bold offset' verschoben, ausgegeben. + Bei den restlichen beiden Modifkationen wird der Fehlerfall ignoriert. + + + + #ib#off#ie# : + + Zweck: Die angegebene #ib#Modifikation#ie# 'modification' soll ausgeschaltet wer + den. Die in der Fonttabelle spezifizierte Befehlssequenz, um die ent + sprechende Modifikation auszuschalten, kann mit der Prozedur #on("i")#off + string (modification)#off("i")# abgefragt werden. Ein Fehlerfall wird hier igno + riert. + + + + font nr : param 1 . + + #ibie# : + + Zweck: Die Druckausgabe soll auf den #ib#Schrifttyp#ie# mit der angegebenen Font + nummer 'font nr' umgeschaltet werden. Diese Nummer bezieht sich auf + die eingestellte Fonttabelle. Mit den Prozeduren des Fontspeichers + können anhand dieser Nummer die nötigen Informationen beschafft + werden. So liefert z.B. die Prozedur #on("i")#font string (font nr)#off("i")# die in der Font + tabelle spezifizierte Befehlssequenz oder die Prozedur #on("i")#font (font nr)#off("i")# + den Namen des Fonts. Die Breite des Leerzeichens kann mit #on("i")#char pitch + (font nr, " ")#off("i")# bestimmt werden. + + +END PROC execute; + + + + + +#ib(9)#6.3. Prozedur-Schnittstelle des EUMEL- + Druckers#ie(9)# + + + +#ib#print#ie# + PROC print (PROC (TEXT VAR) next line, BOOL PROC eof, + PROC (INT CONST, INT VAR, INT VAR) open, + PROC (INT CONST, INT CONST) close, + PROC (INT CONST, TEXT CONST, + INT CONST, INT CONST) execute, + BOOL CONST elan listing, TEXT CONST file name) + Zweck: Solange die Prozedur 'eof' FALSE liefert wird mit der Prozedur 'next + line' eine Zeile eingelesen. Dieser Eingabestrom wird für den Druck + aufbereitet. Ist die Konstante 'elan listing' auf FALSE gesetzt, so wird + der Eingabestrom als Textdatei mit Textkosmetik-Anweisungen aus + gedruckt. Andernfalls wird der Eingabestrom wie ein ELAN-Listing + behandelt. In der Textkonstanten 'file name' muß dann der Dateiname + der Programmdatei enthalten sein. + + + PROC print (FILE VAR file, + PROC (INT CONST, INT VAR, INT VAR) open + PROC (INT CONST, INT CONST) close + PROC (INT CONST, TEXT CONST, + INT CONST, INT CONST) execute) + Zweck: Der Eingabestrom kommt aus der angegebenen Datei. Anhand vorge + gebener Kriterien wird entschieden, ob diese Datei als Textdatei oder + als ELAN-Listing ausgedruckt wird. + +#ib#with elan listings#ie# + PROC with elan listings (BOOL CONST flag) + Zweck: Mit dieser Prozedur kann bei der vorangegangenen 'print'-Prozedur + gesteuert werden, ob überhaupt irgendwelche Dateien als ELAN-Lis + tings gedruckt werden sollen. Wird damit FALSE eingestellt, so wer + den alle Dateien als Textdateien gedruckt. + + BOOL PROC with elan listings + Zweck: Liefert die aktuelle Einstellung. + + +#ib#is elan source#ie# + PROC is elan source (FILE VAR file) + Zweck: Entscheidet nach vorgebenen Kriterien, ob die angegebene Datei ein + ELAN-Listing ist. + + +#ib#bottom label for elan listings#ie# + PROC bottom label for elan listings (TEXT CONST label) + Zweck: Bei ELAN-Listings wird in der Fußzeile ein Text eingestellt, der durch + Schägstrich getrennt vor die Seitennummer geschrieben wird. (z.B. zur + Durchnumerierung der Pakete im Quellcode) + + TEXT PROC bottom label for elan listings + Zweck: Liefert die aktuelle Einstellung. + + +#ib#material#ie# + TEXT PROC material + Zweck: Hier kann das Hardware-Interface jeder Zeit den aktuellen Material + wert abfragen, der vom Benutzer mit der 'material'-Anweisung einge + stellt ist. + + +#ib#x pos#ie# + INT PROC x pos + Zweck: Wird in der Prozedur 'execute' die Funktion 'move' oder 'draw' ange + steuert, so liefert diese Prozedur die absolute Zielposition in x-Rich + tung, wo bei der Nullpunkt durch das zurückgelieferte 'x start' bei 'open + page' definiert ist. Diese Prozedur dient zur Unterstützung von Druk + kern, die eine absolute Positionierung in horizontaler Richtung benöti + gen. + + +#ib#y pos#ie# + INT PROC y pos + Zweck: Wird in der Prozedur 'execute' die Funktion 'move' oder 'draw' an + gesteuert, so liefert diese Prozedur die absolute Zielposition in y-Rich + tung, wo bei der Nullpunkt durch das zurückgelieferte 'y start' bei 'open + page' definiert ist. Diese Prozedur dient zur Unterstützung von Druk + kern, die eine absolute Positionierung in vertikaler Richtung benötigen. + + +#ibie# + INT PROC linetype + Zweck: Wird in der Prozedur 'execute' die Funktion 'draw' angesteuert, so gibt + diese Prozedur den gewünschten Linientyp an. Bisher ist nur definiert: + 1 underline + + Anmerkung: Bis jetzt benutzt der EUMEL-Druckers die Funktion 'draw' lediglich + zum Unterstreichen in Fehlerfall der Modifikation 'underline', d.h. + zeichnen mit 'y steps = 0' und 'x steps >= 0' mit 'line type = 1' + reicht aus. + + +#ib#y offset index#ie# + INT PROC y offset index + Zweck: Wurde der Font mit 'y offsets' definiert, so kann hiermit in der bei der + Funktion 'write text' in der Prozedur 'execute' der jeweilige Offset-In + dex für den auszugebenden Text abgefragt werden. Der Offset-Index + sagt aus, die wievielte Verschiebung nun ausgegeben wird. Dabei + werden die Verschiebungen in der Reihenfolge durchnummeriert, in + der sie in der Fonttabelle angegeben wurden. Anhand dieses Offset-In + dex muß das Hardware-Interface entscheiden, welche Bitmuster aus + gegeben werden müssen. + + +#ib#pages printed#ie# + INT PROC pages printed + Zweck: Gibt nach dem Ausdruck an, wieviel Seiten gedruckt wurden. + + + + +#ib(9)#6.4. Bemerkungen und Ratschläge#ie(9)# + + + +1) Für ein Paket, das dieses Interface implementiert, sind folgende Punkte wichtig: + + - Man braucht sich keine Zustände (aktuelle Position o.ä.) zu merken. + + - Rückmeldungen über die Leistungsfähigkeit eines Druckers bzw. seiner An + passung erfolgen über 'errorstop'. Der #ib#EUMEL-Drucker#ie# stellt fest, ob bestimm + te Leistungen (Einschalten der Attribute und Bewegungen des Druckers) + verfügbar sind, indem er sie versuchsweise ausführen läßt. Bei den Prozedu + ren 'open', 'close' und den Funktionen 'write text', 'write cmd', 'carriage return' + und 'type' der Prozedur 'execute' führt ein 'errorstop' jedoch zum Abbruch des + Drucks. + +2) Die #on("i")##on("b")##ib#Mikroschritte#ie##off("i")##off("b")# sollten die kleinsten durchführbaren horizontalen bzw. vertikalen + Bewegungen des Druckers sein. Oft gibt aber das Handbuch des Druckers keine + eindeutige Angabe über die Mikroschritte in horizontaler Richtung, sondern sagt + nur, daß es gewisse Schriften mit einer bestimmten Anzahl von Zeichen pro Zoll + gibt.#u##count#)#e# Dann ergibt sich die Anzahl von Mikroschritten pro Zoll aus dem kleinsten#foot# + +#value#) 1 Zoll = 1 Inch = 2.54 cm + +#end# + gemeinsamen Vielfachen der Anzahl Zeichen pro Zoll aller Schriften. + + Beispiel: + Der Olivetti Drucker PR1470 hat drei Schriften mit 10, 12, und 16.6 Zeichen pro + Zoll. Das kleinste gemeinsame Vielfache ist 300. Ein Mikroschritt bei dem Druk + ker PR1470 entspricht also einem 300stel Zoll. Die Breite der einzelnen Schrif + ten läßt sich nun aus der folgenden Tabelle ablesen. + + Anzahl Zeichen pro Zoll Breite in 1/300 Zoll + 10 30 + 12 25 + 16.6 18 + + Wenn der Drucker in diesen theoretischen Mikroschritten nicht positionieren kann, + so muß er bei einem #on("i")#move#off("i")#-Befehl so genau wie möglich positionieren. Der Rest + sollte abgespeichert und beim nächsten #on("i")#move#off("i")#-Befehl hinzuaddiert werden. + +3) Um ein optimales Druckbild zu bekommen, müssen alle Breiten und Höhenanga + ben der Zeichen genau angegeben werden. + +4) Die Fonttabelle bietet eine einfache Möglichkeit, Zeichen mit Hilfe der #ib#Ersatzdar + stellung#ie#en umzucodieren. Deshalb sollte der Druckerkanal auch mit der Konfigu + rationstabelle 'transparent' konfiguriert werden. + +5) Um den Schrifttyp festzulegen, mit dem #ib#ELAN-Listing#ie#s gedruckt werden sollen, + kann in der Fonttabelle einem Font der Name #on("i")##on("b")#"#ib#elanlist#ie#"#off("i")##off("b")# zugeordnet werden, denn + der ELAN-Lister versucht auf einen Schrifttyp mit diesem Namen zuschalten. Wenn + kein Schrifttyp "elanlist" existiert, dann wird für ELAN-Listings der erste Schrifttyp + der Fonttabelle genommen. + +6) Nach der Installation des #ib#Druckertreiber#ie#s ist darauf zu achten, daß in der Task + "PRINTER" eine Fonttabelle des Druckers eingestellt ist. + +7) Der #ib#Druckertreiber#ie# sollte eventuell noch ein Prozedur bereitstellen, mit der die + Papierbreite bzw. -höhe eingestellt werden kann, die bei 'open document' dem + EUMEL-Drucker gemeldet wird. + + + + +#ib(9)#6.5. Arbeitsweise des EUMEL-Druckers#ie(9)# + + + +Der EUMEL-Drucker arbeitet mit der folgenden Strategie: + +Die Datei wird zeilenweise analysiert. Bei der Analyse werden einzelne #ib#Token#ie# be +stimmt. Ein Token ist ein Textteil, der zusammenhängend gedruckt werden kann, ohne +daß es zu Typumschaltungen, Modifkationsänderungen oder Positionierungen in x- +bzw. y-Richtung kommt. So ist bei einfachem Zeilendruck jede Zeile ein Token, wäh +rend im Blocksatz jedes Wort ein Token ist. Ein Token hat also immer + + - einen Text, + - die Länge des Textes bei der Ausgabe, + - eine absolute x- und y- Position auf dem Papier, + - einen Schrifttyp, + - Modifikationen für den Text, + - Modifikationen für den Zwischenraum vom letzten Token zu diesem Token. + +Sind alle Token einer Zeile bestimmt, so werden sie in eine Liste aller bisher erzeug +ten, aber noch nicht gedruckten Token der absoluten y-Position nach einsortiert. Diese +Tokenliste wird erst dann ausgedruckt, wenn sichergestellt ist, daß im weiteren Verlauf +der Datei kein Token vor das letzte Token der sortierten Liste kommt. Beim Zeilendruck +ist dies nach jeder Zeile der Fall. Bei Spaltendruck kann jedoch erst dann ausgedruckt +werden, wenn sich die Analyse in der letzten Spalte befindet. Spätestens bei einem +Seitenwechsel muß die Tokenliste ausgegeben werden. + +Durch diese Strategie lassen sich Spaltendruck oder Indizes und Exponenten sehr +leicht für alle Drucker implementieren, ohne daß ein Drucker in vertikaler Richtung +rückwärts positionieren muß. + +Bei der Ausgabe der Tokenliste wird jeweils auf die nächst größere y-Position posi +tioniert und dort werden alle Token zu dieser y-Position ausgegeben. Die Ausgabe +eines Tokens erfolgt in der folgenden Reihenfolge: + + - der Schrifttyp wird eingeschaltet, + - die Modifikationen für den Zwischenraum werden eingeschaltet, + - der Positionsbefehl für horizontale Bewegungen wird gegeben, + - die Modifikationen für den Text werden eingeschaltet, + - der Text wird ausgegeben. + +Die ersten vier Punkte werden nur dann ausgeführt, wenn sie notwendig sind. Über +schreitet der Text die Papierbreite, so zeigen Punkte am Ende der Zeile dies an. + diff --git a/doc/system-manual/1.8.7/doc/systemhandbuch.4 b/doc/system-manual/1.8.7/doc/systemhandbuch.4 new file mode 100644 index 0000000..e511eb5 --- /dev/null +++ b/doc/system-manual/1.8.7/doc/systemhandbuch.4 @@ -0,0 +1,1185 @@ +#start(2.5,1.5)# +#pageblock# +#block# +#page (91)# +#headeven# +%#center#EUMEL-Systemhandbuch + + +#end# +#headodd# +#center#7. Der Fontspeicher#right#% + + +#end# + +#ib(9)#7. Der #ib#Fontspeicher#ie##ie(9)# + + + +#ib(9)#7.1. #ib#Fonttabellen#ie##ie(9)# + + +Damit die Textverarbeitung Dokumente formatieren kann, muß sie über Breiten und +Höhen der einzelnen Schrifttypen (auch "#ib#Fonts#ie#" genannt) des Druckers, auf dem das +Dokument gedruckt wird, Bescheid wissen. Auch bei dem Ausdruck des Dokuments +wird diese Information benötigt. Im EUMEL-System stellt der #ib#Fontspeicher#ie# diese Infor +mation den #ib#Formatierprogramm#ie#en (#on("i")#lineform#off("i")# und #on("i")#pageform#off("i")#) und dem #ib#EUMEL-Drucker#ie# +zur Verfügung. + +Da nun der Drucker Angaben zur Positionierung in seinen #ib#Mikroschritten#ie# (kleinste +Schrittweite in horizontaler oder vertikalter Richtung) benötigt, liefert die Fonttabelle +die Breiten- und Höhenangaben in Mikroschritten und eine Umrechnungseinheit von +Schritten in Zentimeter oder umgekehrt. So braucht der EUMEL-Drucker bei Positionie +rungen keine Umrechnung vorzunehmen. Allerdings müssen die Formatierprogramme +auch in Mikroschritten des jeweiligen Druckers rechnen. Dadurch werden jedoch +Unterschiede durch Rundungsfehler zwischen dem EUMEL-Drucker und den Forma +tierprogrammen vermieden. + +Bei diesem Konzept können Fonts von verschiedenen Druckern nicht in einer Fontta +belle verwaltet werden, denn unterschiedliche Drucker haben meist verschiedene +Mikroschritte. Somit muß es für jeden Drucker mindestens eine Fonttabelle geben. + +Es gibt aber auch Fälle, in denen Fonts auf einem Drucker nicht mit anderen Fonts des +Druckers zusammengedruckt werden können. Solche Fälle liegen z.B. bei Typenrad +druckern vor, die immer nur mit einem Typenrad drucken können und dessen Zei +chenbreite hardwaremäßig eingestellt werden muß (z.B. beim Olivetti PR320), bei +Druckern, die verschiedene Fonts für Längs- und Querformat haben (z.B. beim Agfa +P400), oder bei Druckern, deren Fonts geladen werden (z.B. beim HP 2686). Eine +#on("b")##ib#Fonttabelle#ie##off("b")# enthält also alle die Fonts eines Druckers, #on("b")#die auf dem Drucker kompati +bel sind#off("b")#. Es kann mehrere Fonttabellen zu einem Drucker geben. + +Die verschiedenen Fonttabellen werden von im Multi-User Betrieb von der Task "#ib#confi +gurator#ie#" verwaltet. Sie enthält alle Fonttabellen, die auf dem Rechner zur Verfügung +stehen. Mit dem Kommando + + + #ib#fonttable#ie# ("Name der Fonttabelle") + + +wird in einer Task die gewünschte Fonttabelle eingestellt. Danach stehen die Fonts +dieser Tabelle in der Task zur Verfügung. Die Einstellung der Fonttabelle vererbt sich +auf die Sohntasks, d.h. wird eine Sohntask begonnen, so ist dort die Fonttabelle des +Vaters eingestellt. + +Dazu das folgenden Beispiel: + + Für den Agfa-Drucker P400 gibt es die Fonttabellen "agfa" und "agfaquer", in + denen die Fonts für Längsdruck bzw. Querdruck enthalten sind. In der Task + #on("i")#PUBLIC#off("i")# wird mit dem Kommando #on("i")#fonttable ("agfa")#off("i")# die Fonttabelle "agfa" ein + gestellt. Alle neuen Sohntasks können sofort ohne weitere Einstellung mit der + Textformatierung im Längsformat beginnen. Will nun jemand im Querformat + drucken, so muß er in seiner Task mit dem Kommando #on("i")#fonttable ("agfaquer")#off("i")# den + Fontspeicher auf die Fonts zum Querdruck umstellen. + +Das Kommando + + + #ib#list fonts#ie# + + +listet die Fonts der eingestellten Fontabelle ins #on("i")#notebook#off("i")# und das Kommando + + + #ib#list fonttables#ie# + + +informiert über die verfügbaren Fonttabellen. + + + + +#ib(9)#7.2. Erstellen einer #ib#Fonttabelle#ie##ie(9)# + + +Die Fonttabelle ist ein Datenraum mit einer eigenen Struktur. Somit kann sie nicht +mehr mit dem Editor, sondern nur mit einem entsprechenden Programm bearbeitet +werden. Solch ein Programm befindet sich in der Datei "#ib#font convertor#ie#" auf dem Stan +dardarchiv 'std.zusatz'. Diese Datei sollte in einer Systemtask (Sohntask von "SYSUR") +insertiert werden. Danach stehen entsprechende Kommandos zur Bearbeitung einer +Fonttabelle zur Verfügung. + +Um eine Fonttabelle zu bekommen, muß zuerst eine #on("b")##ib#Fontdatei#ie##off("b")# (d.h. eine editierbare +Datei mit dem unten beschriebenen Aufbau) angelegt werden. Mit dem Kommando + + + #ib#create fonttable#ie# ("Name der Fontdatei") + + +werden alle in der Fontdatei spezifizierten Fonttabellen erstellt. Sie liegen als benannte +Datenräume in der Task vor und können mit dem Kommando #on("i")#save#off("i")# von einer System +task an die Task "configurator" gesendet werden. Danach sind diese Fonttabellen in +allen Task auf dem Rechner verfügbar und können mit dem #on("i")#fonttable#off("i")# - Kommando +eingestellt werden. + +Soll dagegen eine bestehende Fonttabelle geändert werden, so erstellt das Komman +do + + + #ib#create fontfile#ie# ("Name der Fonttabelle", "Name der Fontdatei") + + +aus der angegebenen Fonttabelle eine Fontdatei. Die Fonttabelle muß dazu in der Task +als benannter Datenraum vorliegen (d.h. sie muß eventuell mit #on("i")#fetch#off("i")# von der Task +"configurator" geholt werden). In der so erstellten Fontdatei können die Änderungen +mit dem Editor vorgenommen, mit #on("i")#create fonttable#off("i")# die geänderte Fonttabelle erstellt +und diese wiederum mit #on("i")#save#off("i")# an die Task "configurator" gesendet werden. Mit dem +#on("i")#fonttable#off("i")#-Kommando kann dann in den bestehenden Tasks die geänderte Fonttabelle +eingestellt werden. Alle neuen Tasks erhalten automatisch die geänderte Fonttabelle. + + + +#ib(9)#Prozedurbeschreibung der Umwand +lungsKommandos#ie(9)# + + +Nach der Insertierung der Datei "font convertor" stehen die folgenden Kommandos zur +Umwandlung einer Fontdatei in eine Fonttabelle oder umgekehrt zur Verfügung. + +#ib#create fontfile#ie# + PROC create fontfile (TEXT CONST fonttable name, fontfile name) + Zweck: Aus Fonttabelle 'fonttable name' wird eine Fontdatei mit dem ange + gebenen Name erstellt. Die Fonttabelle muß dabei in der eigenen Task + als benannter Datenraum vorliegen. + +#ib#create fonttable#ie# + PROC create fonttable (TEXT CONST fontfile name) + Zweck: Es werden alle Fonttabellen erzeugt, die in der Fontdatei 'fontfile name' + angegeben sind. Die Fonttabellen liegen dann als benannte Datenräu + me in der Task vor. + + PROC create fonttable + Zweck: Es werden alle Fonttabellen erzeugt, die in der zuletzt bearbeiteten + Datei angegeben sind. + + + + +#ib(9)#7.3. Aufbau der #ib#Fontdatei#ie##ie(9)# + + +In der Fontdatei können drei Strukturen stehen und zwar Kennungen, Identifkationen +und Zeichenspezifikationen.#u##count#)#e# +#foot# + +#value#) Beim formalen Aufbau bedeuten eckige Klammern, daß diese Angaben optional sind. + +#end# + + + +#ib(9)##ib#Kennungen#ie##ie(9)# + + + Formaler Aufbau: <#on("i")#Kennung#off("i")#> : Name 1 [, Name 2] [ ... ] ; + + Eine Kennung leitet eine Definition ein. Für die Namen der Namensliste gelten die + folgenden Konventionen: + + - der Name muß als TEXT-Denoter angegeben werden, + - der Name muß ungleich #on("i")#niltext#off("i")# sein, + - Leerzeichen sind im Namen nicht signifikant (d.h. "agfa quer" wird zu "agfa + quer"). + + Eine Kennung kann die folgenden Werte annehmen: + + <#on("i")#Kennung#off("i")#> { FONTTABLE, FONT } + + - #on("b")##ib#FONTTABLE#ie##off("b")# + Hiermit wird eine Definition einer Fonttabelle eingeleitet. Es wird nur der erste + Name der Namensliste ausgewertet, da die Fonttabelle eindeutig identifiziert + sein muß. Alle folgenden Angaben werden dieser Fonttabelle zugeordnet, bis + eine neue Kennung FONTTABLE folgt. + + - #on("b")##ib#FONT#ie##off("b")# + Hiermit wird eine Definition eines Schrifttyps eingeleitet. Ein Schrifttyp kann + mehrere Namen haben. Jedoch darf in einer Fonttabelle jeder Fontname nur + einem Font zugeordnet werden. + + + +#ib(9)##ib#Identifikation#ie#en#ie(9)# + + + Formaler Aufbau: [ <#on("i")#Identifikation#off("i")#> = <Wert der Identifikation> ; ] + + Mit den Identifikationen werden bestimmte Angaben zu den Kennungen gemacht. + Sie müssen unmittelbar nach der entsprechenden Kennung folgen, brauchen aber + nur angegeben werden, wenn sie von den Standardwerten abweichen. + + + +#ib(9)#Identifikationen nach der Kennung #ib#FONTTABLE#ie##ie(9)# + + + <#on("i")#Identifikation#off("i")#> { x unit, y unit, on string, off string } + + - #on("b")##ib#x unit#ie##off("b")# + Hiermit wird die Anzahl der Mikroschritte des Druckers pro Zentimeter in + horizontaler (x-) Richtung spezifiziert. Die Einheit muß als REAL-Denoter + angegeben werden. Alle weiteren Breitenangaben zu den Fonts dieses Druk + kers beziehen sich auf diese Einheit. + + STD-Wert: 10.0 / 2.54 = 3.937008 + + - #on("b")##ib#y unit#ie##off("b")# + Hiermit wird die Anzahl der Mikroschritte des Druckers pro Zentimeter in + vertikaler (y-) Richtung spezifiziert. Die Einheit muß als REAL-Denoter ange + geben werden. Alle weiteren Höhenangaben zu den Fonts dieses Druckers + beziehen sich auf diese Einheit. + + STD-Wert: 6.0 / 2.54 = 2.362205 + + - #on("b")##ib#on string#ie##off("b")# + Hier müssen vier Textdenoter, durch Komma getrennt, angegeben werden. + Die Textdenoter enthalten die Befehlssequenzen, um beim Drucker die Mo + difikationen anzuschalten. Dabei ist die Reihenfolge der Modifikationen + underline, bold, italics, reverse. + Liegt für eine der Modifikationen keine Befehlssequenz vor, so muß #on("i")#niltext#off("i")# + angegeben werden. Die Befehlssequenzen können vom Druckertreiber ab + gefragt werden. + + STD-Wert: #on("i")#niltext#off("i")# für alle Modifikationen + + - #on("b")##ib#off string#ie##off("b")# + Hier müssen vier Textdenoter, durch Komma getrennt, angegeben werden. + Die Textdenoter enthalten die Befehlssequenzen, um beim Drucker die Mo + difikationen auszuschalten. Dabei ist die Reihenfolge der Modifikationen + underline, bold, italics, reverse. + Liegt für eine der Modifikationen keine Befehlssequenz vor, so muß #on("i")#niltext#off("i")# + angegeben werden. Die Befehlssequenzen können vom Druckertreiber ab + gefragt werden. + + STD-Wert: #on("i")#niltext#off("i")# für alle Modifikationen + + + +#ib(9)#Identifikationen nach der Kennung #ib#FONT#ie##ie(9)# + + + <#on("i")#Identifikation#off("i")#> { font lead, font height, font depth, indentation pitch, + next larger font, next smaller font, + font string, y offsets, bold offset } + + - #on("b")##ib#font lead#ie##off("b")##u##count#)#e# + Der Durchschuß eines Fonts gibt den Zwischenraum in vertikaler Richtung + zwischen den Zeilen bei einfachem Zeilenvorschub an. Er muß in Mikroschrit + ten der y-Richtung als INT-Denoter angegeben werden. + + STD-Wert: 0 +#foot# + +#value#) Für spätere Erweiterungen des EUMEL-Druckers wurde die bisherige Fonthöhe in Durchschuß, Fonthöhe + und Fonttiefe aufgespalten. Für alle bis jetzt definierten Leistungen braucht nur wie bisher die Fonthöhe + angegeben zu werden. Der Durchschuß und die Fonttiefe werden dann auf Null gesetzt. +#end# + + - #on("b")##ib#font height#ie##off("b")##u##value#)#e# + Die Fonthöhe ist die Distanz von der Basislinie bis zur Oberkante des höch + sten Zeichens. Sie muß in Mikroschritten der y-Richtung als INT-Denoter + angegeben werden. + + STD-Wert: 6 Zeilen pro Inch entsprechend der definierten #on("i")#y unit#off("i")# + + - #on("b")##ib#font depth#ie##off("b")##u##value#)#e# + Die Fonttiefe ist die Distanz von der Basislinie bis zur Unterkante des tief + sten Zeichens. Sie muß in Mikroschritten der y-Richtung als INT-Denoter + angegeben werden. + + STD-Wert: 0 + + - #on("b")##ib#indentation pitch#ie##off("b")# + Einrückungen oder Aufzählungen werden äquidistant berechnet, d.h. Anzahl + der Zeichen mal einer festen Breite. Diese Einrückbreite sollte ein Mittel al + ler Zeichenbreiten sein und braucht nicht der Breite des Leerzeichens zu + entsprechen. Sie muß in Mikroschritten der x-Richtung als INT-Denoter an + gegeben werden. + + STD-Wert: 10 Zeichen pro Inch entsprechend der definierten #on("i")#x unit#off("i")# + + - #on("b")##ib#next larger font#ie##off("b")# + Hier muß der Name des nächst größeren Fonts als TEXT-Denoter aufgeführt + werden. Gibt es keinen nächst größeren Font, so ist #on("i")#niltext#off("i")# anzugeben. + + STD-Wert: #on("i")#niltext#off("i")# + + - #on("b")##ib#next smaller font#ie##off("b")# + Hier muß der Name des nächst kleineren Fonts als TEXT-Denoter aufge + führt werden. Gibt es keinen nächst kleineren Font, so ist #on("i")#niltext#off("i")# anzugeben. + Bei Indizes oder Exponenten wird automatisch auf diesen nächst kleineren + Font umgeschaltet. + + STD-Wert: #on("i")#niltext#off("i")# + + + - #on("b")##ib#font string#ie##off("b")# + Hier kann als TEXT-Denoter eine Befehlssequenz angegeben werden, die + den Drucker auf diesen Font umschaltet. Diese Befehlssequenz kann vom + Druckertreiber abgefragt werden. Dadurch ist es nicht nötig, daß er die Na + men der Fonts kennt. + + STD-Wert: #on("i")#niltext#off("i")# + + - #on("b")##ib#y offsets#ie##off("b")# + Um bei Matrixdruckern Schriften zu erzeugen, die höher als eine Nadelreihe + sind, müssen entsprechende Bitmuster des Textes an verschiedenen y-Po + sitionen ausgegeben werden. Um diese Anforderung durch den EUMEL- + Drucker zu unterstützen, kann hier eine Liste von Verschiebungen von der + Basislinie angegeben werden, an denen der Text ein weiteres Mal ausgege + ben wird. Dabei bedeuten negative Werte eine Verschiebung oberhalb und + positive Werte eine Verschiebung unterhalb der Basislinie. Ist der Wert Null, + so wird der Text auf der Basislinie ausgegeben. Die Modifikation #on("i")#underline#off("i")# + wird bei der Ausgabe des Textes nur an der ersten Verschiebung angestellt. + Die Werte für die Verschiebungen müssen in Mikroschritten der y-Richtung + als INT-Denoter angegeben und durch Komma getrennt werden. + + STD-Wert: 0 + + - #on("b")##ib#bold offset#ie##off("b")# + Falls der Drucker die Modifikation #on("i")#bold#off("i")# nicht beherrscht, versucht der + EUMEL-Drucker sie durch Doppeldruck zu simulieren. Der 'bold offset' gibt + an, ob und wieviel der zweite Durchgang in x-Richtung verschoben werden + soll. Dies ergibt insbesondere bei Laserdruckern, die nicht für alle Schriftty + pen einen Bold-Typ haben, einen recht guten Fettdruck. Der Wert muß in + Mikroschritten der x-Richtung als INT-Denoter angegeben werden. + + STD-Wert: 0 + + + +#ib(9)##ib#Zeichenspezifikationen#ie##ie(9)# + + + + Formaler Aufbau: [ <Zeichen> [, <Breite des Zeichens>] + [, <Ersatzdarstellung des Zeichens>] ; ] + + + Nachdem die Identifikationen zu einer Kennung angegeben wurden, können Zei + chenspezifikationen folgen, d.h. zu einem Zeichen kann die Breite und/oder eine + Ersatzdarstellung spezifiziert werden. Dazu muß zuerst das Zeichen selber als + TEXT-Denoter angegeben werden. + + - #on("b")##ib#Breite des Zeichens#ie##off("b")# + Die Zeichenbreite muß als INT-Denoter in Mikroschritten angegeben werden. + Alle Zeichenbreiten werden mit der Einrückbreite vorbesetzt, so daß nur sol + che Zeichen angegeben werden müssen, deren Breite von der Einrückbreite + abweichen. Negative Zeichenbreiten sind nicht erlaubt. Die Angabe von Zei + chenbreiten nach der Kennung FONTTABLE wird ignoriert. + + - #on("b")##ib#Ersatzdarstellung des Zeichens#ie##off("b")# + Die Ersatzdarstellung wird statt des Zeichens ausgedruckt. Sie muß als + TEXT-Denoter angegeben werden. Werden Ersatzdarstellungen nach der + Kennung FONTTABLE angegeben, so gelten sie global für alle Fonts dieser + Fonttabelle. Sie können jedoch bei der Fontangabe lokal wieder überschrie + ben werden. Eine Ersatzdarstellung darf höchsten 255 Zeichen lang sein. Alle + Ersatzdarstellungen eines Fonts dürfen 32767 Zeichen nicht überschreiten. + + + +#ib(9)##ib#Kommentare in der Fontdatei#ie##ie(9)# + + + In der Fontdatei dürfen Kommentare eingefügt werden. Sie müssen den Kommen + taren der ELAN-Syntax entsprechen, d.h. mit '(*' beginnen und mit '*)' enden. + + + +#ib(9)##ib#Deutsche Namen#ie##ie(9)# + + + Kennungen und Identifikationen dürfen in der Fontdatei auch mit folgenden deut + schen Namen angegeben werden. + + FONTABLE : FONTABELLE + FONT : FONT + +#free (0.15)# + x unit : x einheit + y unit : y einheit + on string : on sequenz + off string : off sequenz + indentation pitch : einrueckbreite + font lead : durchschuss + font height : fonthoehe + font depth : fonttiefe + next larger font : groesserer font + next smaller font : kleinerer font + font string : font sequenz + y offsets : y verschiebungen + bold offset : bold verschiebung + + + + +#ib(9)#7.4. Beispiel für eine Fontdatei#ie(9)# + + +In diesem Beispiel einer Fonttdatei sind drei Fonttabellen enthalten, nämlich "agfa" und +"agfaquer" für den Agfa-Drucker und "epson" für einen Epson-Drucker. + + +FONTTABLE : "agfa" ; + x unit = 160.0 ; #right#(* Anzahl der Mikroschritte pro cm *) + y unit = 160.0 ; + on string = "\UL1;", "\BO1;", "\IT1;", "\CFW;\CBB;" ; + off string = "\UL0;", "\BO0;", "\IT0;", "\CFT;\CBT;" ; + +#right#(* globale Ersatzdarstellungen für alle Agfa-Fonts *) + + ""214"" , "\!298;" ; #right#(* AE *) + ""215"" , "\!299;" ; #right#(* OE *) + ""216"" , "\!300;" ; #right#(* UE *) + ""217"" , "\!451;" ; #right#(* ae *) + ""218"" , "\!452;" ; #right#(* oe *) + ""219"" , "\!453;" ; #right#(* ue *) + . + . + . + + FONT : "trium10" ; + indentation pitch = 30 ; + font lead = 7 ; + font heigth = 54 ; + font depth = 15 ; + next larger font = "trium12" ; + next smaller font = "helvetica8" ; + font string = "\FO5;" ; + + " " , 20 ; "!" , 16 ; + """" , 22 ; "\#" , 31 ; + "$" , 31 ; "%" , 55 ; + . + . + . + ""217"" , 31 ; #right#(* ae *) + +#right#(* lokale Ersatzdarstellungen für Font "trium10" *) + + ""244"" , 43 , "\FO23;\!725;\FO5;" ; #right#(* ungleich *) + ""245"" , 31 , "\FO23;\!405;\FO5;" ; #right#(* mal-Zeichen *) + + FONT : "modern12", "elanlist" ; #right#(* Mehrere Namen für einen Font *) + indentation pitch = 33 ; + font lead = 14; + font heigth = 53; + font depth = 13; + next larger font = "" ; + next smaller font = "micro" ; + font string = "\FO11;" + #right#(* Alle Zeichen haben die gleiche Breite *) + + FONT . . . + + +FONTTABLE : "agfaquer" ; + x unit = 160.0 ; + y unit = 160.0 ; + on string = "\UL1;", "\BO1;", "\IT1;", "\CFW;\CBB;" ; + off string = "\UL0;", "\BO0;", "\IT0;", "\CFT;\CBT;" ; + . + . + . + + +FONTTABLE : "epson" ; + x unit = 47.24409 ; #right#(* 120.0 / 2.54 *) + y unit = 85.03937 ; #right#(* 216.0 / 2.54 *) + on string = ""27"-"1"", "", ""27"4", ""; + off string = ""27"-"0"", "", ""27"5", ""; + + ""214"" , ""27"R"2""091""27"R"0"" ; #right#(* AE *) + ""215"" , ""27"R"2""092""27"R"0"" ; #right#(* OE *) + ""216"" , ""27"R"2""093""27"R"0"" ; #right#(* UE *) + ""217"" , ""27"R"2""123""27"R"0"" ; #right#(* ae *) + ""218"" , ""27"R"2""124""27"R"0"" ; #right#(* oe *) + ""219"" , ""27"R"2""125""27"R"0"" ; #right#(* ue *) + ""220"" , "k" ; #right#(* Trenn-k *) + ""221"" , "-" ; #right#(* Trennstrich *) + ""222"" , "\#" ; #right#(* geschütztes Nummernkreuz *) + ""223"" , " " ; #right#(* geschütztes Leerzeichen *) + ""251"" , ""27"R"2""126""27"R"0"" ; #right#(* ss *) + ""252"" , ""27"R"2""064""27"R"0"" ; #right#(* Paragraph *) + + FONT : "12", "elite", "elite12" ; #right#(* Mehrere Namen für einen Font *) + font height = 36 ; + indentation pitch = 10 ; + next smaller font = "12.klein" ; + font string = ""27"!"1""27"p"0""27"T" ; + bold offset = 2 ; + + FONT : "12.klein", "elite.klein", "elanlist" ; + font height = 20 ; + indentation pitch = 10 ; + next smaller font = "12.klein" ; + font string = ""27"!"1""27"p"0""27"S"1"" ; + bold offset = 1 ; + + FONT : "12.hoch" ; + font height = 96 ; + indentation pitch = 10 ; + next smaller font = "12.klein" ; + font string = "" ; + bold offset = 2 ; + y offsets = 12, -12 ;#right#(* der Text wird jeweils 12 Mikroschritte unter- + #right# und überhalb der Basislinie ausgegeben *) + + FONT : "prop10", "prop" ; + font height = 12 ; + indentation pitch = 24 ; + next smaller font = "" ; + font string = ""27"!"0""27"p"1""27"T" ; + bold offset = 2 ; + + "!" , 10 ; + """" , 16 ; + "(" , 12 ; + . . . + + + + + +#ib(9)#7.5. Schnittstelle des #ib#Fontspeicher#ie#s#ie(9)# + + + +Das Paket #on("i")#font store#off("i")# liefert die folgenden Prozeduren: + +#ib#fonttable#ie# + PROC fonttable (TEXT CONST fonttable name) + Zweck: Stellt die angegebene Fonttabelle in der Task ein. Dabei wird zuerst in + der eigenen Task nach der angegebenen Fonttabelle gesucht. Existiert + die Fonttabelle in der eigenen Task nicht, so wird die Fonttabelle von + der Task "configurator" geholt. + Wenn die Fonttabelle eingestellt ist, sind in der Task nur noch die Fonts + dieser Fonttabelle bekannt. Die Einstellung vererbt sich auf die Sohn + tasks. + + TEXT PROC fonttable + Zweck: Liefert den Name der eingestellten Fonttabelle. + +#ib#list fonttables#ie# + PROC list fonttables + Zweck: Zeigt die Liste der verfügbaren Fonttabellen im #on("i")#notebook#off("i")#. + +#ib#list fonts#ie# + PROC list fonts + Zweck: Listet die Fonts der eingestellten Tabelle ins #on("i")#notebook#off("i")#. + + PROC list fonts (TEXT CONST fonttable name) + Zweck: Listet die Fonts der angegebenen Fonttabelle ins #on("i")#notebook#off("i")#. Die vorher + eingestellte Fonttabelle bleibt jedoch weiter eingestellt. + +#ib#x step conversion#ie# + INT PROC x step conversion (REAL CONST cm) + Zweck: Rechnet die in Zentimeter angegebene Länge in Mikroschritte der + x-Richtung um. + + REAL PROC x step conversion (INT CONST steps) + Zweck: Rechnet die in Mikroschritten der x-Richtung angegebene Länge in + Zentimeter um. + +#ib#y step conversion#ie# + INT PROC y step conversion (REAL CONST cm) + Zweck: Rechnet die in Zentimeter angegebene Länge in Mikroschritte der + y-Richtung um. + + REAL PROC y step conversion (INT CONST steps) + Zweck: Rechnet die in Mikroschritten der y-Richtung angegebene Länge in + Zentimeter um. + +#ib#on string#ie# + TEXT PROC on string (INT CONST modification) + Zweck: Liefert die in der Fonttabelle spezifizierte Befehlssequenz, um eine + Modifikation anzuschalten. Es gibt die folgenden Modifikationen + 1 underline + 2 bold + 4 italics + 8 reverse + +#ib#off string#ie# + TEXT PROC off string (INT CONST modification) + Zweck: Liefert die in der Fonttabelle spezifizierte Befehlssequenz, um eine + Modifikation auszuschalten. Es gibt die folgenden Modifikationen + 1 underline + 2 bold + 4 italics + 8 reverse + +#ib#font#ie# + INT PROC font (TEXT CONST font name) + Zweck: Liefert die interne Fontnummer des Fonts. Mit dieser Fontnummer + können die weiteren Informationen über den Font angefordert werden. + Existiert kein Font mit diesem Namen, so wird Null geliefert. + + TEXT PROC font (TEXT CONST font nr) + Zweck: Liefert den Fontnamen des Fonts mit der angegeben Fontnummer. Hat + der Font mehrere Namen, so wird der erste Name der Namensliste aus + der Fontdatei geliefert. Existiert kein Font unter dieser Nummer, so wird + #on("i")#niltext#off("i")# geliefert. + +#ib#font exists#ie# + BOOL PROC font exists (TEXT CONST font name) + Zweck: Informationsprozedur zur Abfrage der Existenz eines Fonts. + +#ib#next smaller font exists#ie# + BOOL PROC next smaller font exists (INT CONST font nr, + INT VAR next smaller font) + Zweck: Informationsprozedur zur Abfrage der Existenz des nächst kleineren + Fonts. Wenn er existiert, wird die Fontnummer dieses Fonts zurück + geliefert. + +#ib#next larger font exists#ie# + BOOL PROC next larger font exists (INT CONST font nr, + INT VAR next larger font) + Zweck: Informationsprozedur zur Abfrage der Existenz des nächst größeren + Fonts. Wenn er existiert, wird die Fontnummer dieses Fonts zurück + geliefert. + +#ib#indentation pitch#ie# + INT PROC indentation pitch (INT CONST font nr) + Zweck: Liefert die Einrückbreite in Mikroschritten der x-Richtung. Sie sollte eine + mittlere Breite der Zeichen sein, denn mit ihr werden die Einrückungen + und Aufzählungen berechnet. + +#ib#font lead#ie# + INT PROC font lead (INT CONST font nr) + Zweck: Liefert den Durchschuss des Fonts in Mikroschritten der y-Richtung. + Der Druchschuß ist der Zwischenraum zwischen den einzelnen Zeilen + bei einfachem Zeilenvorschub. + +#ib#font height#ie# + INT PROC font height (INT CONST font nr) + Zweck: Liefert die Höhe des Fonts in Mikroschritten der y-Richtung. Die Fon + thöhe ist die Distanz von der Basislinie bis zur Oberkante des höchsten + Zeichens. + +#ib#font depth#ie# + INT PROC font depth (INT CONST font nr) + Zweck: Liefert die Tiefe des Fonts in Mikroschritten der y-Richtung. Die Fonttie + fe ist die Distanz von der Basislinie bis zur Unterkante des tiefsten + Zeichens. + +#ib#font string#ie# + TEXT PROC font string (INT CONST font nr) + Zweck: Liefert den Fontstring des Fonts. Der Fontstring enthält die Befehls + sequenz, um den Drucker auf diesen Font umzuschalten. + +#ib#y offsets#ie# + TEXT PROC y offsets (INT CONST font nr) + Zweck: Liefert einen Text mit den y-Verschiebungen von der Basislinie. Die + einzelnen Verschiebungen können mit dem Operator 'ISUB' abgefragt + werden. + +#ib#bold offsets#ie# + INT PROC bold offsets (INT CONST font nr) + Zweck: Liefert die 'bold'-Verschiebung. + +#ib#char pitch#ie# + INT PROC char pitch (INT CONST font nr, TEXT CONST char) + Zweck: Liefert die Breite des Zeichens in Mikroschritten der x-Richtung. + +#ib#replacement#ie# + TEXT PROC replacement (INT CONST font nr, TEXT CONST char) + Zweck: Falls das Zeichen eine Ersatzdarstellung hat, so wird diese geliefert, + anderfalls das Zeichen selbst. + +#ib#get font#ie# + PROC get font (INT CONST font nr, + INT VAR indentation pitch, font lead, font height, font depth, + ROW 256 INT VAR pitch table) + Zweck: Die Variablen liefern die entsprechenden Informantionen über den + Font. Der Eintrag des Codewerts eines Zeichens plus eins in der Brei + tentabelle liefert die Breite dieses Zeichens. + +#ib#get replacements#ie# + PROC get replacements (INT CONST font nr, + TEXT VAR replacements, + ROW 256 INT VAR replacement table) + Zweck: In der Fonttabelle kann für jedes Zeichen eine Ersatzdarstellung an + gegeben werden. Diese Ersatzdarstellungen werden mit dieser Proze + dur geliefert. Dabei stehen in der Textvariablen 'replacement' die ge + samten Ersatzdarstellungen des Fonts. Die Ersatzdarstellungstabelle + enthält Zeiger auf den Text der Ersatzdarstellungen. Die Ersatzdarstel + lung eines Zeichnes bestimmt sich wie folgt: + + + ersatzdarstellung : + INT CONST wert := replacement table (code( zeichen ) + 1); + IF wert > 0 + THEN INT CONST ende := wert + code (replacements SUB wert); + subtext (replacements, wert + 1, ende) + ELSE zeichen + FI. + + +Bei den Prozeduren des Packets #on("i")#font store#off("i")# können die folgenden Fehlerfälle auftreten: + + - Fonttabelle noch nicht eingestellt + Es wurde noch keine Fonttabelle in der Task eingestellt. + + - Fonttabelle "fonttable name" gibt es nicht + Die angegebene Fonttabelle wurde weder in der eigenen Task, noch in der + Task 'configurator' gefunden. + + - Font 'font nr' gibt es nicht + Unter der angegebenen Fontnummer gibt es in der eingestellten Font + tabelle keinen Font. Speziell ist das für 'font nr' = 0 der Fall, falls ein Font + name nicht gefunden wurde. + + - unzulaessige Modifikation + Die angegebene Modifikation ist ungleich 1, 2, 4 oder 8. +#page# + +#headeven# + +%#center#EUMEL-Systemhandbuch + + +#end# +#headodd# + +#center#8. Verschiedenes#right#% + + +#end# + +#ib(9)#8. Verschiedenes#ie(9)# + + + + +#ib(9)#8.1. Der Spoolmanager#ie(9)# + + +Der "#ib#Spoolmanager#ie#" verwaltet eine #ib#Warteschlange von Datenräumen#ie# (Dateien), die von +einem "#ib#Server#ie#" abgearbeitet werden sollen. Dabei puffert der Spoolmanager Dateien, +die von beliebigen Tasks geschickt werden können, in einer Warteschlange und gibt +sie der Reihe nach dem Server zur eigentlichen Verarbeitung. Ein typischer Einsatzfall +(aber nicht der einzige) für ein solches System ist der Druck von Dateien in Multi- +User-Systemen. Unabhängig davon, ob der Drucker gerade aktiv ist und wieviele +Dateien noch auf den Ausdruck warten, kann jeder seine Datei dem Druckerspool (in +der Regel die Task "PRINTER") senden und sofort danach weiterarbeiten. + + + +#ib(9)#Prozeduren des Spoolmanagers#ie(9)# + + +Im privilegierten Ast des Taskbaumes (Söhne von "SYSUR"), stehen die folgenden +Prozeduren zur Einrichtung eines Spoolmanagers zur Verfügung. + +#ib#spool manager#ie# + PROC spool manager (PROC server, BOOL CONST with start) + Zweck: Die Task, in der die Prozedur aufgerufen wird, wird zum Spoolmanager. + Wenn 'with start' auf TRUE gesetzt ist, wird eine Server-Task als unbe + nannter Sohn ("-") eingerichtet und mit der übergebenen 'PROC server' + gestartet. Anderfalls muß der Spool durch den Benutzer mit Hilfe der + Spoolkommandos (siehe dort) gestartet werden. + + PROC spool manager (PROC server) + Zweck: Diese Prozedur ruft die Prozedur 'spool manager' mit 'with start' gleich + TRUE auf. + + +Mit Hilfe der folgenden Prozeduren kann der Spool eingestellt werden. + +#ib#station only#ie# + PROC station only (BOOL CONST flag) + Zweck: Wenn flag auf TRUE gesetzt ist, nimmt der Spooler nur Aufträge von + Tasks der eigenen Station entgegen. + Voreinstellung: 'station only (FALSE)'. + + BOOL PROC station only + Zweck: liefert TRUE, wenn der Spooler nur von der eigenen Station benutzt + werden darf. + +#ib#spool duty#ie# + PROC spool duty (TEXT CONST duty) + Zweck: Mit dieser Prozedur kann ein Text im Spooler eingestellt werden, der die + Aufgabe des Spoolers beschreibt. Dieser wird beim 'list' gemeldet. + + TEXT PROC spool duty + Zweck: Liefert die eingestellte Text-Beschreibung der Aufgabe des Spools. + +#ib#spool control task#ie# + PROC spool control task (TASK CONST task) + Zweck: Diese Prozedur gibt der Task 'task' und ihrer Söhne die Berechtigung + Spoolkommandos (z.B. 'stop' oder 'start') an den Spoolmanager zusen + den. Dabei muß die Task auf derselben Station wie der Spool sein und + in der Task muß die Datei "spool cmd", die sich auf dem Standardar + chiv befindet, insertiert werden. + Wird "SUPERVISOR" als Spoolkontrolltask eingestellt, so können alle + Tasks der Station, in denen die Datei "spool cmd" insertiert ist, die + Spoolkommandos geben. + + TASK PROC spool control task + Zweck: Liefert die Taskidentifikation der Spoolkontrolltask. + +#ib#server channel#ie# + PROC server channel (INT CONST channel) + Zweck: Mit Hilfe dieser Prozedur wird im Spoolmanager eine Kanalnummer + eingestellt, die der Server mit der Prozedur 'server channel' abfragen + kann. + Fehlerfall: + * falsche Kanalangabe + Der angegebene Kanal ist kleiner als 1 oder größerer als 32. + + INT PROC serverchannel + Zweck: Liefert die Nummer des Kanals, der im Spool eingestellt ist. + +#on("b")#Anmerkung:#off("b")# Soll im nicht-privilegierten Ast des Taskbaums (Söhne von "PUBLIC") ein + Spool eingerichtet werden, so muß dort die Datei "spool manager", die + sich auf dem Standardarchiv "std.zusatz" befindet, insertiert werden. + + + + +#ib(9)##ib#Spoolkommandos#ie##ie(9)# + + +Ein Spool kann zur Verwaltung der Warteschlange wie jede andere Task ans Termi +nal gekoppelt werden. Danach stehen die folgenden Spoolkommandos zur Verfügung. +Diese Kommandos sind keine Prozeduren, sondern werden nur interpretiert. Sie dürfen +also nur alleine eingegeben werden. Nach Beendigung der Verwaltungsaufgaben muß +der Spool mit dem Kommando 'break' verlassen werden, da sonst keine weiteren +Aufträge an den Spool gesendet werden können und auch die Warteschlange nicht +weiter abgearbeitet wird. + +#ib#stop#ie# + Zweck: Die Server-Task wird gelöscht und dadurch der Spool deaktiviert. Der + Spool empfängt zwar noch weitere Aufträge und sortiert diese in die + Warteschlange ein. Die Warteschlange wird aber nicht weiterabgearbei + tet. Ein eventuell von der Server-Task belegter Kanal wird freigegeben. + Ist bei einem 'stop' noch ein Auftrag in Bearbeitung, so wird dieser + Auftrag abrupt abgebrochen. Es wird jedoch angefragt, ob der Auftrag + nochmal neu an die erste Stelle in der Warteschlange eingetragen wer + den soll. + Ist ein Spool deaktiviert, so wird dies bei einem 'list' angezeigt, + +#ib#halt#ie# + Zweck: Der Spool deaktiviert sich nach Abarbeitung des Auftrags, der gerade + bearbeitet wird. Bei einem 'list' wird dies vermerkt. + +#ib#start#ie# + Zweck: Der Spool wird aktiviert, indem eine neue Server-Task begonnen wird. Ist + der Spool zuvor nicht gestoppt worden, so wird zuerst ein 'stop' durch + geführt. + Wurde mit der Prozedur 'server channel' kein Kanal eingestellt, so wird + die Warnung + WARNUNG : Serverkanal nicht eingestellt + ausgeben. Der Spool wird trotzdem gestartet. + +start (kanal nummer) + Zweck: Vor dem Start des Spools wird zuerst mit der Prozedur 'server channel' + der angegebene Kanal eingestellt. + +#ib#first#ie# + Zweck: Im Dialog kann ein Auftrag in der Warteschlange auf den ersten Platz + vorgezogen werden. + +#ib#killer#ie# + Zweck: Im Dialog werden alle Aufträge der Warteschlange zum Löschen ange + boten. + +#ib#list spool#ie# + Zweck: Der aktuelle Zustand des Spools und die Warteschlange werden geli + stet. + +Ist nun eine Spoolkontrolltask eingestellt worden (siehe 'spool control task'), so muß in +ihr die Datei "spool cmd" insertiert werden. Danach stehen die folgenden Prozeduren +zur Verfügung. + +#ib#stop#ie# + PROC stop (TASK CONST spool) + Zweck: Dem Spool 'spool' wird ein 'stop' zugestellt, was den Spool deaktiviert. + Wird noch ein Auftrag bearbeitet, so wird angefragt, ob dieser neu + eingetragen werden soll. + +#ib#halt#ie# + PROC halt (TASK CONST spool) + Zweck: Dem Spool 'spool' wird ein 'halt' zugestellt, d.h der Spool deaktiviert + sich nach Beendigung des aktuellen Auftrags. + +#ib#wait for halt#ie# + PROC wait for halt (TASK CONST spool) + Zweck: Dem Spool 'spool' wird ein 'halt' zugestellt. Die Task wartet jedoch auf + eine Rückantwort, die ihr der Spool sendet, wenn er sich nach Been + digung des aktuellen Auftrags deaktiviert hat. + Fehlerfall: + * Task "task name" wartet schon auf halt + Die angegebene Task wartet schon auf eine Rückantwort des Spools + 'spool'. + +#ib#start#ie# + PROC start (TASK CONST spool) + Zweck: Dem Spool 'spool' wird ein 'start' zugestellt, wodurch der Spool sich + aktiviert. War der Spool zuvor nicht deaktiviert, so wird er zuerst ge + stoppt. + +#ib#first#ie# + PROC first (TASK CONST spool) + Zweck: Im Dialog kann einer der Aufträge in der Warteschlange des Spools + 'spool' auf den ersten Platz vorgezogen werden. + +#ib#killer#ie# + PROC killer (TASK CONST spool) + Zweck: Im Dialog werden die Aufträge der Warteschlange des Spools 'spool' + zum Löschen angeboten. + + + +#ib(9)#Arbeitsweise des #ib#Servers#ie##ie(9)# + + +Der Server wird vom Spoolmanager mit einer Prozedur gestartet, die die Abarbeitung +der Warteschlange vornimmt. Dabei muß diese Prozedur zuerst den Datenraum mit +dem 'fetch code' (= 11) holen. Danach kann der Server sich noch mit dem 'fetch +param code' (= 21) die Dateiparameter (Dateiname, Schreib- und Lesepaßwort, Sen +dername und Senderstation) abholen und mit der Bearbeitung des Auftrags beginnen. + +Beispiel: + + +LET fetch code = 11, + param fetch code = 21; +BOUND STRUCT (TEXT name, write pass, read pass, sendername, + INT senderstation ) VAR msg; +DATASPACE VAR ds, param ds; +INT VAR reply; + +spool manager (PROC server); + +PROC server : + disable stop; + continue (server channel); + REP forget (ds); ds := nilspace; + call (father, fetch code, ds, reply); + forget (param ds); param ds := nilspace; + call (father, param fetch code, param ds, reply); + msg := param ds; + execute spool; + IF is error THEN error treatment FI; + PER; +END PROC server; + +PROC execute spool : + enable stop; + ... + + + + + +#ib(9)#Senden eines Auftrags an den Spool#ie(9)# + + +Jede Task kann jedem Spool durch Aufruf von '#ib#save#ie#' eine Datei senden. + +Beispiel: + + + save ("datei name", task ("spool name")) + + +Dieses 'save'-Kommando funktioniert zweiphasig. Dabei wird in der ersten Phase dem +Spool die Dateiparameter zugesendet. In der zweiten Phase folgt dann der Datenraum +selber. Bei Netzübertragung zu einem Spool ist dieses zweiphasige 'save' jedoch +nachteilig. Deshalb können Dateien vom Typ 'FILE' auch mit einem einphasigen 'save' +unter dem 'file save code' (= 22) an den Spool gesendet werden. Die #on("i")#'headline'#off("i")# dieser +Dateien muß jedoch dann auf eine bestimmte Art und Weise aufbereitet werden, so +daß sie die Dateiparameter enthält. Beim Aufbau der #on("i")#'headline'#off("i")# muß eine Information +muß mit dem Code 0 beginnen und dem Code 1 enden. Die Dateiparamter müssen +dann mit der folgenden Reihenfolge in die #on("i")#'headline'#off("i")# eingetragen werden. + + - Dateiname + - Schreibepaßwort + - Lesepaßwort + - Name des Senders + - Station des Senders + +Beispiel: + + +... +LET file save code = 22; +DATASPACE VAR ds := old (file name); +FILE VAR file := sequential file (input, ds); +INT VAR reply; +headline (file, ""0"" + file name + + ""1""0"" + write password + + ""1""0"" + read password + + ""1""0"" + name (myself) + + ""1""0"" + text (station (myself)) + ""1""); +call (spool task, file save code, ds, reply); +... + + +Der Spoolmanager setzt bei Dateien, die mit dem 'file save code' angeliefert werden +die #on("i")#'headline'#off("i")# wieder auf den Dateinamen. + +Den Benutzer stehen neben dem '#ib#save#ie#'-Kommando zur Übertragung einer Datei zum +Spool noch die folgenden Kommandos zur Verfügung. + + + save (ALL myself, task ("spool name")) + save (SOME myself, task ("spool name")) + + übertragung aller bzw. einiger Dateien der eigenen Task zum Spool. + + + #ib#erase#ie# ("datei name", task ("spool name")) + erase (ALL task ("spool name"), task ("spool name")) + + Löschen eines bzw. aller eigenen Aufträge in der Warteschlange des Spools + + + #ib#list#ie# (task ("spool name")) + + Liste des Spools über den aktuellen Zustand und die Warteschlange. + +Existiert ein Spool "PRINTER", so gibt es noch die folgenden Befehle. + + + #ib#print#ie# + print ("datei name") + print (ALL myself) + print (SOME myself) + + Sie entsprechen einem 'save' an die Task "PRINTER" + + + #ib#printer#ie# + + Liefert den internen Taskbezeichner der Task "PRINTER", d.h. diese Proze + dur entspricht dem Aufruf von 'task ("PRINTER")'. + + + + + +#ib(9)#8.2. #ib#Freie Kanäle#ie(9)##ie# + + +Das Paket '#ib#free channel#ie#' ermöglicht in Multi-User-Systemen die Einrichtung freier +Kanäle. Freie Kanäle kann man zusätzlich zu dem Terminalkanal, der einem vom +Supervisor zugeordnet wurde, benutzen. Jeder freie Kanal wird durch eine (benannte) +Task - dem #ib#Kanalmanager#ie# - implementiert. Er wird danach mit dem Tasknamen ange +sprochen und kann von jeder Task belegt und wieder freigegeben werden. Während +einer Belegung können andere Tasks den Kanal nicht benutzen. Der Kanalmanager +koppelt sich für jede Belegung an den physikalischen Kanal an und gibt ihn danach +auch wieder frei. Ein physischer Kanal kann also im Wechsel von mehreren Kanalma +nagern oder einem Kanalmanager und "normalen" Tasks belegt werden. + +Das Paket 'free channel' muß beim Kanalmanager und allen Benutzern des Kanals +bzw. bei einem gemeinsamen Vater insertiert sein. + + +#ib#FCHANNEL#ie# + Zweck: Der Datentyp FCHANNEL spezifiziert einen freien Kanal. Die Assoziie + rung mit einem realen freien Kanal erfolgt mit der Prozedur 'free chan + nel' und der Zuweisung ':=' (ähnlich wie beim Datentyp FILE). + +:= + OP := (FCHANNEL VAR dest, FCHANNEL CONST source) + Zweck: Zuweisung. Wird insbesondere bei der Assoziation (Assoziation: Verbin + dung zwischen FCHANNEL VAR und Kanal) benötigt. + +#ib#close#ie# + PROC close (FCHANNEL VAR f) + Zweck: Der belegte FCHANNEL wird freigeben. + + PROC close (TEXT CONST channel name) + Zweck: Der namentlich spezifizierte Kanal wird freigegeben. + +#ib#dialogue#ie# + PROC dialogue (FCHANNEL CONST f, TEXT CONST end of dialogue char) + Zweck: Der Terminalkanal wird direkt mit dem angegebenen freien Kanal ge + koppelt. (Das Benutzerterminal wird "durchgeschaltet".) Eingaben am + Terminal werden auf 'f' ausgegeben, auf 'f' ankommende Daten werden + auf dem Benutzerterminal ausgegeben. Der Datenverkehr erfolgt im + #ib#Vollduplexmodus#ie#, d.h. der Datenverkehr beider Richtungen läuft unab + hängig voneinander parallel. Hiermit können Terminals dynamisch an + andere Rechner gekoppelt werden. Der Dialogzustand wird durch Ein + gabe des 'end of dialogue char' am Benutzerterminal beendet. + +#ib#fetch#ie# + PROC fetch (FCHANNEL VAR channel, TEXT CONST filename, controlchars) + Zweck: Die angegebene datei wird über den Kanal 'channel' eingelesen. Dabei + besteht 'control chars' aus zwei bis vier Zeichen + (eof + eol + handshake + handshake prompt) + eof: + Dieses Zeichen wird als Dateiabschluß erwartet. + eol: + Dieses Zeichen wird als Zeilenende erwartet. + handshake, handshake prompt: + Falls 'handshake prompt <> "" ' ist, wird bei dem Empfang eines + PromptZeichen eine Quittung (HandshakeZeichen) ausgegeben. + +#ib#free channel#ie# + FCHANNEL PROC free channel (TEXT CONST channel name) + Zweck: Der namentlich spezifizierte Kanal wird belegt und als FCHANNEL + geliefert. + Fehlerfälle: + * task not existing + * channel not free + + PROC free channel (INT CONST physical channel number) + Zweck: Installiert die eigene Task als Kanalmanager für den angegebenen + physikalischen Kanal. + +#ib#in#ie# + PROC in (FCHANNEL CONST f, TEXT VAR response) + Zweck: Es werden die Daten geliefert, die seit dem letzten 'in'Aufruf bzw. seit + der Assoziierung eingetroffenen Daten geliefert. Bei 'niltext' liegen keine + Eingabedaten vor. + +#ib#open#ie# + PROC open (FCHANNEL VAR f) + Zweck: Der Kanal wird neu belegt. Die Assoziation erfolgt mit dem gleichen + Kanal wie bei der letzten Assoziation. + Fehlerfälle: + * "task" gibt es nicht + * Kanal ist nicht frei + +#ib#out#ie# + PROC out (FCHANNEL VAR f, TEXT CONST message) + Zweck: Der übergebene Text wird auf dem Kanal 'f' ausgegeben. + +#ib#save#ie# + PROC save (FCHANNEL VAR f, TEXT CONST name, control chars) + Zweck: Die übergebene Datei muß eine Textdatei sein (Struktur eines FILEs + haben). Sie wird komplett auf dem Kanal 'f' ausgegeben. + Dabei bestehen 'control chars' aus bis zu drei Zeichen: + (eof char + eol char + handshake option) + eof char: + Dieses Zeichen wird als Dateiabschluß geschickt. + eol char: + Dieses zeichen wird als Zeilenabschluß geschickt. + handshake option: + Falls die 'control chars' drei Zeichen umfassen, wird nach jeder + Zeile auf das als drittes definierte HandshakeZeichen gewartet. + +Beispiele: + + + a) FCHANNEL VAR f := free channel ("otto") ; + TEXT VAR antwort ; + out (f, "hallo") ; + in (f, antwort) ; + put (antwort) ; + close (f) ; + + b) open (f) ; + REP + out (f, "hallo ") ; + in (f, antwort) + UNTIL antwort <> "" PER ; + put (antwort) ; + close (f) ; + + c) open (f) ; + dialogue (f, "§") ; + close (f) + diff --git a/doc/system-manual/1.8.7/source-disk b/doc/system-manual/1.8.7/source-disk new file mode 100644 index 0000000..13e2021 --- /dev/null +++ b/doc/system-manual/1.8.7/source-disk @@ -0,0 +1 @@ +grundpaket/10_handbuecher.2.img diff --git a/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil1 b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil1 new file mode 100644 index 0000000..cdeca13 --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil1 @@ -0,0 +1,924 @@ + EUMEL-Benutzerhandbuch + + TEIL 1: Einführung + +Vorwort + +Lieber EUMEL-Nutzer! + +Ihnen liegt hier das EUMEL-Benutzerhandbuch zur Public-Domain-Version 1.7.3 +vor. Es gliedert sich in mehrere Teile. Der erste Teil des Benutzerhandbuchs +soll dem zukünftigen Benutzer den "Einstieg" in das EUMEL-System erleichtern. +Dazu werden die wichtigsten Eigenschaften des EUMEL-Systems vorgestellt. +Danach zeigen wir eine Beispielsitzung. Anschließend werden einige +prinzipielle Konzepte des EUMEL-Systems vermittelt. Den Abschluß bildet ein +kleines EUMEL-Wörterbuch. + +Die übrigen Teile des EUMEL-Benutzerhandbuchs dokumentieren jeweils ein oder +mehrere abgeschlossene Einheiten des Systems. Ein EUMEL-Nutzer braucht so nur +die ihn interessierenden Teile zu lesen. Ein Programmierer z.B. sollte + + Einführung, Supervisor/Monitor, Editor, ELAN-Compiler und Dateien + +durcharbeiten. Für Programmierer, die noch keine Erfahrung mit ELAN besitzen, +ist der Teil "Erste Hilfe" gedacht. Weiterhin werden die Teile über Dateien +und Standardpakete oft benötigt. Ein Nutzer, der vorwiegend an der Textbe- +und verarbeitung interessiert ist, braucht dagegen nur + + Einführung, Supervisor/Monitor, Dateien, Editor und Textkosmetik. + +Der OPERATOR/Spooler-Teil ist nur für diejenigen Programmierer gedacht, die +ein EUMEL-System betreuen. Weitere Informationen finden System-Programmierer +im System-Handbuch bzw. in der Veröffentlichung des Quellcodes. + + +1. Eigenschaften des EUMEL-Betriebssystems + +Das EUMEL-Betriebssystem (Extendable multi User Microprocessor ELANsystem) +ist ein Betriebssystem, das z.Z. für den Einsatz auf Mikroprozessoren vorge- +sehen ist. Es weist u.a. folgende Eigenschaften auf: + +- Das EUMEL-System ist ein "Time sharing"-Betriebssystem, d.h. mehrere Be- + nutzer können gleichzeitig an einem Rechensystem arbeiten (z.B. Programme + übersetzen, bearbetten (rechnen) oder erstellen (edieren)). Dabei wird die + verfügbare Rechen- und Speicherkapazität zwischen den Benutzer-Prozessen + dynamisch aufgeteilt. + +- Jeder Benutzer richtet (mindestens) eine Task ein, in der er sich Programme + und/oder Dateien halten kann, auf die andere Nutzer nicht zugreifen können. + Tasks können von einem Terminal "abgekoppelt" und trotzdem - sofern aus- + reichend freie Rechnerkapazität zur Verfügung steht - als Batch-Auftrag im + Hintergrund weiter bearbeitet werden. + +- Das EUMEL-Betriebssystem ist so konzipiert, daß der Sicherheit des Systems + besondere Beachtung geschenkt wurde. Zu diesem Zweck werden in bestimmten + zeitlichen Abständen sogenannte Restart-Punkte auf dem externen Speicher- + medium gesichert. In diesen Sicherungen wird der augenblickliche System- + Zustand konserviert, so daß bei Netzausfall oder eventuellen System-Zu- + sammenbrüchen der Betrieb übergangslos wieder aufgenommen werden kann, mit + der Ausnahme des Verlustes der Daten, die nach dem letzten Restart-Punkt + aufliefen. + +- "Tasks" und/oder Dateien können vor dem unbefugten Zugriff durch "Pass- + words" geschützt werden. Ein weitergehender Schutz wird durch die Möglich- + keit von Password-Algorithmen vom EUMEL-System angeboten, so daß den Be- + langen des Datenschutzes Rechnung getragen werden kann. + +- Das EUMEL-Betriebssystem ist leicht erweiterbar. Da der Kern des Betriebs- + systems in ELAN geschrieben ist, können Anwender selbst leicht Erweiterun- + gen bzw. lokale Modifikationen in das System ein- bzw. anfügen. Dabei kön- + nen bestimmte Erweiterungen nur bestimmten Benutzern oder Benutzergruppen + zur Verfügung gestellt werden. Da die Programmiersprache ELAN selbst er- + weiterbar ist, ist es möglich, verschiedenen Anwendern oder -gruppen unter- + schiedliche Erweiterungen der Sprache anzubieten. + +- In dem EUMEL-Betriebssystem ist eine implizite Dateihierarchie realisiert. + Dies wird erreicht, indem den Tasks Dateien zugeordnet werden. Man kann + Dateien im Taskbaum von "Vater-Tasks" holen oder zu ihnen schicken. Lokale + Dateien werden mit dem Beenden einer Task automatisch gelöscht, während + Dateien, die längerfristig gehalten werden sollen, bei längerlebenden Tasks + gehalten werden müssen. + +- Die Kommandosprache ("job control language") des EUMEL-Systems entspricht + der ELAN-Syntax (Prozeduraufrufe). Das befreit den Anwender von der + Schwierigkeit, zwei verschiedenartige Sprachen zu erlernen. Darüber hinaus + können eine oder mehrere Anweisungen der Kommandosprache in ELAN-Programmen + enthalten sein. Z.B. ist es möglich, Kommandos vom Editor ausführen zu + lassen oder den Editor von einem Programm aus aufzurufen. + +- Die Dienstprogramme des EUMEL-Systems, wie z.B. der EUMEL-Editor, sind + geräteunabhängig und meist erweiterbar konzipiert. Zudem sind sie auch in + ELAN formuliert, so daß Änderungen und Korrekturen leicht vorgenommen + werden können. + +- Das EUMEL-System verwaltet seinen Hauptspeicher nach dem "demand-paging"- + Prinzip. Daten und/oder Programme werden daher in Seiten von 512 Bytes + aufgeteilt. Nur diejenigen Seiten, die zu einem Zeitpunkt wirklich benötigt + werden, befinden sich im Speicher. Dadurch kann sich das EUMEL-System auf + wechselnde Speicherplatz-Anforderungen optimal einstellen. + +- Für alle Programme wird reentranter Code erzeugt. Somit können mehrere + Benutzer Code gleichzeitig benutzen ("sharable code"), wobei der Code nur + einmal vorhanden sein muß. Dies ist insbesondere für Dienstprogramme wie + z.B. Compiler, Editor usw. wichtig. + +- Dateien können ebenfalls (wie Programme) von mehreren Benutzern gemeinsam + verwendet werden, ohne daß mehrere Kopien davon hergestellt werden müssen + Das System sorgt mit seinen Paging-Fähigkeiten automatisch für das "sharen" + von Dateien. Erfolgt jedoch ein Schreibzugriff, so wird nur für den + schreibenden Benutzer eine Kopie angelegt. + +- Das EUMEL-System bietet gute Textbe- und -verarbeitungsmöglichkeiten. + Grundlage dafür ist der bildschirmorientierte Editor (eine Entwicklung der + GMD). Der Editor erlaubt auch ein "multi window editing" und die Ausführung + von beliebigen Kommandos. Zusätzlich gibt es eine Reihe von Programmen zur + "Textkosmetik", die es erlauben, Texte zeilen- und seitenweise zu forma- + tieren. Dabei ist es möglich, unterschiedliche Schriftarten zu verwenden. + + +2. Eine kleine Beispielsitzung mit EUMEL + +Zum ersten Kennenlernen wird hier ein Beispiel einer EUMEL-Sitzung darge- +stellt. Diese Vorlage kann man am Rechner "nachspielen". Da die Reaktion des +Systems hier auf dem Papier nur unvollkommen wiedergegeben werden kann, ist +diese Beispielsitzung durch "trockenes" Lesen (ohne Rechner) sicherlich etwas +schwieriger zu verstehen als durch Nachspielen. + +Alle Ausgaben des EUMEL werden mit + +----> + +gekennzeichnet, alle Benutzereingaben haben + +<---- + +als Kennzeichen. Spezielle Tasten werden groß geschrieben, z.B. + + RETURN + +als Bezeichnung für die RETURN-Taste. + + +Anfang + +Im Multi-User-System können gleichzeitig mehrere Benutzer aktiv sein. Dabei +braucht jeder ein eigenes "Zimmer" im "EUMEL-Haus", in dem er arbeiten kann, +ohne andere zu stören. Diese "Zimmer" heißen hier "Tasks" und haben Namen. +Zu Beginn muß der Benutzer sich an seinem Bildschirm eine Task erzeugen. Dazu +muß er das Betriebssystem aktivieren: + +<---- SV + +EUMEL meldet sich: EUMEL Version 1.7.3/M + +----> gib supervisor kommando: + +Dann muß der Benutzer sich einen Tasknamen ausdenken (z.B. "ottokar") und +ein Kommando zum Einrichten einer neuen Task geben: + +<---- begin ("ottokar") RETURN + +Daraufhin wird eine neue Task erzeugt, sie meldet sich: + +----> gib kommando: + +Jetzt kann die eigentliche Sitzung beginnen. + + +Programm erstellen + +Wir schreiben ein kleines Programm zur Primzahlberechnung: + +<---- edit ("prim") RETURN + +----> neue datei einrichten (j/n) ? + +<---- j + +Es soll eine neue Datei mit dem Namen 'prim' eingerichtet werden, daher ant- +worten wir mit 'j'. Die Datei ist zu Anfang leer. Der Editor zeigt nur die +Überschrift, der restliche Bildschirm ist leer. Wir können jetzt unser Pro- +gramm eingeben: + + INT VAR zahl := 3 ; + WHILE zahl <= 1000 REP + drucke falls primzahl ; + zahl INCR 2 + PER . + + drucke falls primzahl : + INT VAR teiler := 3 ; + WHILE teiler * teiler <= zahl REP + IF teiler gefunden + THEN LEAVE drucke falls primzahl + FI ; + teiler INCR 2 + PER ; + put (zahl) ; + line . + + teiler gefunden : + zahl MOD teiler = 0 . + +Bei der Eingabe des Programms können wir auch die Funktionstasten benutzen. +Die genauen Funktionen sind in den folgenden Teilen des Benutzerhandbuchs +erklärt. Für den Anfang gilt aber: Probieren geht über Studieren! + +Wir verlassen den Editor: + +<---- ESC q + +----> gib kommando: + + +Programm übersetzen und ausführen + +<---- run RETURN + +----> ("prim") + +Der Dateiname ('prim') wird automatisch ergänzt und das Programm wird vom +ELAN-Compiler übersetzt. Dabei erscheinen die Nummern der gerade übersetzten +Zeilen in der linken unteren Bildecke. Wenn keine Fehler gefunden wurden, +wird das Programm anschließend ausgeführt. Dann sollten die Primzahlen von +3 bis 1000 erscheinen. + + +Ein fehlerhaftes Programm korrigieren + +Falls der ELAN-Compiler Fehler findet, wird das Programm nicht ausgeführt. +Das System geht automatisch in den Editor, der jetzt zwei Dateien "parallel" +auf dem Bildschirm zeigt. Die obere enthält die Fehlermeldungen, die untere +das ELAN-Programm, so daß Korrekturen leicht möglich sind. Dabei kann man gut +folgende Editor-Funktionen benutzen (ausprobieren!): + + ESC ESC n RETURN positioniert auf Zeile n + + HOP UNTEN + zum Blättern + HOP OBEN + + ESC w wechselt zur jeweils anderen Datei (z.B. um in der + Fehlermeldungsdatei weiterzublättern) + +Nach Verlassen des Editors (ESC q) kann das Programm wieder gestartet werden. + + +Ändern des Programms + +<---- edit RETURN + +----> ("prim") + +Auch hier wird der Dateiname zum Kommando 'edit' automatisch ergänzt. Jetzt +kann das Programm mit den üblichen Editor-Möglichkeiten verändert werden. +Vorschläge: + + - Man ändere den Bereich (Vorsicht: maxint ist 32767). + - Man teste die Teiler bis zur Zahl selbst hoch. + - Man benutze REALs anstelle von INTs. + - Man suche Zwillinge. + +An Editor-Möglichkeiten könnte man ausprobieren: + + RUBOUT löscht ein Zeichen. + + RUBIN schaltet den Einfügezustand ein. Das nächste RUBIN + schaltet ihn wieder ab. + + HOP UNTEN zum Anfang des Bildschirms oder "blättern nach oben". + + HOP OBEN zum Ende des Bildschirms oder "blättern nach unten". + + HOP RUBOUT am Zeilenanfang löscht die ganze Zeile. + + HOP RUBIN schaltet "Zeilen einfügen" ein. Das nächste HOP RUBIN + schaltet es wieder aus. + + +Datei löschen + +<---- forget RETURN + +----> ("prim") + +----> löschen (j/n) ? + +<---- j + +----> gib kommando: + + +Ende einer Sitzung + +<---- end RETURN + +----> task loeschen (j/n) ? + +<---- j + +----> EUMEL Version 1.7.3 / M + + + +3. Einige Eigenschaften des EUMEL-Systems + +In diesem Abschnitt werden wir einige Eigenschaften des EUMEL-Systems +schildern, die zum korrekten Arbeiten mit dem System wichtig sind. Um das +Verständnis zu erleichtern, verwenden wir für einige System-Eigenschaften +Modelle, die das Verhalten des Systems an typischen Merkmalen widerspiegeln +spiegeln sollen, die aber - wie bei allen Modellen - kein exaktes Abbild +darstellen. + + +Tasks, Supervisor und Monitor + +Zuerst versuchen wir zu erklären, wie sich ein Benutzer im EUMEL-System +anmeldet und den Mechanismus, wie man bestimmte Leistungen vom System +anfordert (Einige Ideen dieses ersten Abschnittes gehen auf W. Ambros, +Rhein-Sieg Gymnasium, St. Augustin, zurück). + +Stellen wir uns das EUMEL-System als ein riesiges Verwaltungsgebäude vor, +wie es in unseren Städten in den letzten Jahren überall gebaut wurde. Ein +Verwaltungsangestellter beginnt frohgemut seinen ersten Arbeitstag. Da das +Gebäude so riesig ist, kann er sein Zimmer nicht finden. Aber er ist pfiffig: +er fragt einfach den freundlichen Pförtner, der ihn in sein Zimmer führt. + +So ist es im EUMEL-System: +Wenn man eine Arbeit neu beginnen will, muß man sich beim Supervisor (das ist +der Pförtner in unserem Modell) anmelden. Dazu muß man erstmal den Supervisor +"wecken" (wie mit einer Klingel): wir drücken die Supervisor-Taste (im +folgenden mit SV abgekürzt). Der Supervisor meldet sich dann mit + + gib supervisor kommando : + +Nun kann man eine Task anmelden. Das ist ein Zimmer im EUMEL-System, in dem +man arbeiten kann, ohne von den anderen Benutzern gestört zu werden. Ist die +Task noch nicht vorhanden, wird sie eingerichtet. Dann leitet uns der Super- +visor in die angegebene Task. + +Der Verwaltungsangestellte ist nun vom Pförtner zu seinem Büro geleitet +worden. Dort empfängt ihn der Bürovorsteher: "Was möchten Sie arbeiten?" +Unser Angestellter kann nun (z.B.) sagen, daß er etwas schreiben möchte. Der +Bürovorsteher führt ihn in einen speziellen Schreibraum, in dem einige +spezielle Einrichtungen und Geräte für komfortables Schreiben stehen. + +So sieht es im EUMEL-System aus: +Nachdem man eine neue Task eingerichtet hat oder eine bereits vorhandene +fortsetzen will, gelangt man zum Monitor (das ist unser Bürovorsteher), der +sich mit + + gib kommando : + +meldet. Nun kann man verschiedene Arbeiten verrichten, wie z.B. den Editor +rufen, um einen Text oder ein Programm zu schreiben: + + edit ("meine datei") + +In diesem Schreibzimmer kann unser Angestellter irgendetwas schreiben, z.B. +ein Programm, einen Liebesbrief, ein Testament oder ganz etwas anderes. Hat +er eine Frage oder will er eine besondere Leistung, dann kann unser Ange- +stellter den Bürovorsteher aus dem Schreibzimmer rufen. Hat er seine Schreib- +arbeit beendet, geht er aus dem Zimmer und trifft dort wiederum auf den auf- +merksamen Vorsteher. Ihm kann er nun sagen, daß er das Schriftstück (z.B.) +drucken oder von einem Dolmetscher übersetzen lassen will. + +Im EUMEL-System: +Im Editor schreibt man Texte oder Programme. Während man im Editor ist, kann +man besondere Leistungen durch Kommandos anfordern, ohne den Editor zu ver- +lassen, z.B. in einer anderen Datei nachschauen oder einen Teiltext in dem +geschriebenen Schriftstück suchen. Nachdem die Arbeit beendet ist, verläßt +man den Editor (ESC q) und gelangt wiederum in den Monitor. Hier kann man +das Schriftstück drucken oder - im Falle eines Programms - übersetzen lassen: + + print ("meine datei") + run ("meine datei") + +Hat das Programm einen Fehler, eröffnet uns der Monitor ein Fenster auf die +Datei und zeigt uns gleichzeitig die Fehlermeldungen, so daß wir bequem +korrigieren können. + +Nachdem unser Angestellter mit seinen Arbeiten fertig ist, kann er dem Vor- +steher (Monitor) sagen: + + Ich kündige! (will nicht mehr weiterarbeiten) ('end') + Bis Morgen! (will später weiterarbeiten) ('break') + +Merke: Der Supervisor des EUMEL-Systems regelt die Einrichtung, Zugang und + Löschung von Tasks. In einer Task kann ein Benutzer arbeiten, ohne + von anderen gestört zu werden. Spezielle Tasks sind für allgemeine + Aufgaben vorgesehen, wie z.B. das Drucken und Sichern von Dateien. + Durch den Monitor kann man Kommandos innerhalb einer Task geben. + + +Demand Paging + +Nun versuchen wir einen zentralen Begriff des EUMEL-Systems zu erklären, das +"demand paging". Diese Eigenschaft moderner Rechensysteme sorgt dafür, daß +bei (normalerweise immer) beschränkten Speicherkapazitäten eines Rechners +Programme bearbeitbar sind, die in ihrer Gesamtgröße nicht in den Speicher +des Rechners passen würden. + +Nehmen wir wieder den Angestellten, der nun in einem Zimmer (Task) auf einem +Tisch das EUMEL-Benutzerhandbuch durcharbeiten will. Stellen wir uns weiter +vor, daß er das Benutzerhandbuch nicht rein "sequentiell" lesen will, sondern +daß er fortwährend "blättern" muß. Eigentlich muß unser Angestellter mehrere +Seiten des Benutzerhandbuchs gleichzeitig lesen. Deshalb kommt er auf die +listige Idee, die Seiten, die er dringend benötigt, zu photokopieren und auf +seinem Tisch nebeneinander auszubreiten, damit er nicht mehr blättern muß. +Leider ist sein Tisch zu klein, um alle photokopierten Seiten darauf auszu- +breiten. Durch die Sparbemühungen der Regierung ist es auch aussichtslos, +sich um einen größeren Tisch zu bemühen. Aber im Titel für Verbrauchsmaterial +ist genügend Geld vorhanden, so daß Papier für den Photokopierer angeschafft +werden kann. Außerdem geht das Photokopieren sehr schnell, weil er den Photo- +kopierer direkt neben seinen Tisch aufbaut. Darum photokopiert er nur die- +jenigen Seiten, die er gerade benötigt und legt diese auf seinen Tisch. +Braucht er eine neue Seite aus dem Buch und hat diese auf dem Schreibtisch +keinen Platz mehr, so muß er eine auf dem Tisch liegende Seite entfernen. +Geschickt wählt sich unser Angestellter eine Seite aus, von der er annimmt, +daß er diese nicht so schnell wieder benötigt. + +Was macht er nun mit der "alten" Seite? Er könnte die kopierte Seite einfach +in das Benutzerhandbuch einordnen. Aber dazu müßte er erstmal in dem Benut- +zerhandbuch suchen, was ihm zuviel Mühe macht. Deshalb wirft er diese Seite +einfach weg, denn er kann sie ja jederzeit wieder aus dem Handbuch kopieren. + +Gerade will er eine Seite wegwerfen, da fällt ihm auf, daß er das "Wegwerf"- +Verfahren vielleicht nicht immer anwenden sollte. Seine Notizen, die er sich +auf einigen Seiten gemacht hat, würden ja mit weggeworfen und damit ver- +nichtet. Deshalb wirft er Seiten mit Notizen nicht weg, sondern tauscht diese +Seiten mit den ursprünglichen Seiten im Benutzerhandbuch aus. + +Fassen wir zusammen: +Jemand arbeitet ein Buch "durch". Er kopiert sich diejenigen Seiten, die er +jeweils benötigt. Da sein Tisch zu klein ist, um alle Seiten gleichzeitig +auszulegen, kann er immer nur einen Ausschnitt aus dem Buch bearbeiten, was +aber ausreicht. Braucht er eine neue Seite, so muß er eine auf dem Tisch +liegende Seite "verdrängen". Hat er diese Seite nicht verändert, also mit +Notizen versehen, so kann er sie einfach wegwerfen. "Veränderte" Seiten +ersetzt er im Buch und bewahrt sie somit auf. + +Ähnliches erfolgt auch im EUMEL-System: +Der Zentralspeicher (der Tisch in unserem Modell) des Rechners ist meist ge- +genüber dem Massenspeicher, der im EUMEL-System auch als "Hintergrund" be- +zeichnet wird (Floppy oder Magnetplatte; in unserem Modell das Buch) zu +klein, als daß alle Informationen gleichzeitig hineinpassen würden. Darum +werden alle Informationen in sogenannte Seiten ("pages") unterteilt, die +jeweils 512 Byte (ein Byte entspricht einem Zeichen) groß sind. Wird eine +Information benötigt, so wird die betreffende Seite in den Speicher geholt +(daher auch der Begriff "demand paging", etwa: Seitenaustausch auf An- +forderung). Das geht so lange gut bis der gesamte Platz im Zentralspeicher +des Rechners belegt ist. Soll nun eine neue Seite vom Massenspeicher geholt +werden, weil die darin enthaltenen Informationen gebraucht werden, muß eine +Seite im Zentralspeicher ersetzt werden (Fachwort: die Seite muß "verdrängt" +werden). Sie kann überschrieben werden (in unserem Modell wurde sie "wegge- +worfen"), wenn keine Veränderungen vorgenommen wurden, d.h. keine Schreibzu- +griffe, sondern nur Lesezugriffe auf die Seite erfolgten. Wurde die Seite +verändert, so muß sie auf den Hintergrund zurückkopiert werden und dort die +ursprüngliche Seite ersetzen. + + +Merke: Die Vorteile eines "demand paging" Systems sind nun offensichtlich: + Es ist möglich, bei weitem größere Informationsmengen (Daten und/oder + Programme) zu bearbeiten als diejenige, die eigentlich in den vor- + handenen Speicher passen würde, weil tatsächlich immer nur ein Aus- + schnitt der gesamten Informationsmenge zu einem Zeitpunkt bearbeitet + werden muß. Bei traditionellen Systemen ist dagegen die maximale Größe + von Programmen und Daten durch die physikalische Größe des Zentral- + speichers beschränkt. + + +Sharing + +Sharing bezeichnet die gemeinsame Nutzung von Seiten ("pages") durch mehr +als einen Benutzer. + +Zurück zu unserem Angestellten: Dieser ist inzwischen fleißiger geworden und +hat das gleiche Verfahren auf mehrere Bücher ausgedehnt, d.h. er kopiert sich +diejenigen Seiten aus den Büchern, die er gerade benötigt. Bei der Ver- +drängung einer Seite behält er sein altes (nicht sehr umweltfreundliches) +Verfahren bei: nur die veränderten Seiten ersetzen die Original-Seiten in den +Büchern (werden zurückgelegt), die anderen (nicht veränderten) weggeworfen. + +Aber auch andere Angestellte seines Büros haben ihn beobachtet, beneiden ihn +um seine "geschickte" Arbeitstechnik und wollen mitarbeiten. Leider steht +ihnen gemeinsam nur der eine Tisch zur Verfügung, der zudem in der Zwischen- +zeit auch nicht größer geworden ist, weil die Sparmaßnahmen der Regierung +noch immer anhalten. Darum müssen sie sich nun den einzigen Tisch teilen, auf +dem sie ihre kopierten Seiten auslegen können. + +Im Laufe der Arbeit ergibt es sich, daß sie unterschiedliche Seiten der +Bücher durcharbeiten müssen, weil sie verschieden schnell arbeiten, aber auch +andere Arbeitsgebiete haben. + +Durch die unterschiedliche Arbeitsgeschwindigkeit ergibt es sich, daß ein +Angestellter z.B. zu einem Zeitpunkt sich intensiv nur mit einer Seite be- +schäftigt, ein anderer aber mehrere Seiten quasi gleichzeitig braucht. Aber +oft brauchen mehrere Angestellte mehrere Seiten, so daß der verfügbare Platz +auf dem Tisch bald etwas zu eng wird. Natürlich "funktioniert" unser Ver- +fahren immer noch, aber es ist doch etwas langsam geworden, weil unsere +Angestellten mehr mit dem Austausch von Seiten beschäftigt sind, als daß sie +noch zu dem Verarbeiten der gelesenen Informationen kommen. Sie überlegen +also, wie das Verfahren zu verbessern ist und kommen auf folgenden Trick: +kopierte Seiten, die zwei oder mehr Angestellte zur gleichen Zeit bearbeiten +wollen, brauchen nur einmal auf dem Tisch zu liegen (schließlich sind unsere +Angestellten gewöhnt, in Gruppen zu arbeiten). Diese Rationalisierungs-Idee +ist ja offensichtlich, denn schließlich benutzen die Angestellten die Bücher +auch gemeinsam. Aber Vorsicht: wenn einer der Angestellten, die gemeinsam +eine Seite bearbeiten, sich etwas auf dieser Seite notieren will, darf nicht +die gemeinsam auf dem Tisch liegende Seite verwendet werden. In diesem Fall +ist es notwendig, vorher eine erneute Kopie zu machen, weil andere Ange- +stellte seine Notizen nicht unbedingt mitlesen sollen, also die unveränderte +Seite brauchen. + +Und das findet im Rechner statt: +Das "demand paging" Verfahren funktioniert natürlich nicht nur mit einer +Datei und einem Programm, sondern auch mit mehreren Dateien und Programmen, +von denen nur diejenigen Seiten in den Zentralspeicher geholt werden, die zu +einem Zeitpunkt in den Rechner passen. Aber erst mit mehreren Benutzern des +EUMEL-Systems entfaltet das "demand paging" Verfahren seine volle Mächtig- +keit, denn alle Benutzer können Programme und/oder Dateien verarbeiten, die +in der Gesamtheit nicht in den Speicher passen würden. Dabei wird eine Eigen- +schaft des EUMEL-Systems gut genutzt: Alle Programme des EUMEL-Systems (und +übrigens alle Programme, die der ELAN-Compiler übersetzt hat) sind reentrant, +d.h. können von mehreren Benutzern gleichzeitig gelesen werden, aber brauchen +nur einmal im Zentralspeicher vorhanden zu sein. Zwei oder mehr Benutzer +können also eine oder mehrere Seiten gemeinsam verwenden (Fachausdruck: +"sharen"), sowohl im Zentralspeicher wie auch im Massenspeicher ("Hinter- +grund"). Dies gilt nicht nur für Programme, sondern auch für Daten. Erst +wenn ein Benutzer eine Veränderung vornimmt, also schreibend auf die Seite +zugreift, wird diese Seite (nur für diesen Benutzer!) kopiert (EUMEL-Fachaus- +druck: "copy on write"). Alle anderen Benutzer arbeiten mit der unveränderten +Seite weiter. Der große Vorteil dieses Verfahrens: eine redundante +Speicherung von Daten und Programmen wird vermieden. + +Es passiert nun oft, daß ein Benutzer zu einem Zeitpunkt relativ wenig Seiten +benötigt: sei es, daß er Daten mit Hilfe des Editors eingibt oder nachdenkt, +sei es, daß ein Programm wenig Daten verwendet und selbst sehr kurz ist. Mit +anderen Worten: die Anzahl der benötigten Seiten zu einem Zeitpunkt (Fachaus- +druck: "working set") für diesen Benutzer ist klein. Dann ist es möglich, daß +andere Benutzer zu diesem Zeitpunkt mehr Seiten im Zentralspeicher des Rech- +ners haben. Deren "working set" ist also groß. + +Merke: Damit wird ein weiterer Vorteil des "demand paging" Verfahrens klar: + Ein "demand paging" System stellt sich automatisch und dynamisch auf + die Anforderungen von Benutzern ein, indem denjenigen Benutzern mehr + Speicher zugeteilt wird, die mehr benötigen und umgekehrt. Aber auch + ein Nachteil wird sichtbar: Benötigen alle Benutzer des Systems viel + Zentralspeicher, dann kann es zu folgender Situation kommen: Benutzer + A benötigt eine neue Seite. Das System verdrängt für diesen Zweck eine + Seite, die Benutzer B gehört. Nachdem Benutzer B an die Reihe kommt, + benötigt er diese Seite wieder. Das System verdrängt eine Seite des + Benutzers A u.s.f.. Eine solche Situation, in der "pages" ständig in + den Speicher kopiert und aus dem Speicher bei einer Seitenverdrängung + auf den Hintergrund geschrieben werden muß (und somit kaum gerechnet + wird), wird als "thrashing" bezeichnet. "thrashing" oder mit anderen + Worten: sehr geringer Verbrauch an Rechenzeit bei gleichzeitig er- + höhtem "paging"-Aufwand ist ein Anzeichen für zu hohe Anforderungen + an das System (Ausweg: Erweiterung des Hauptspeichers oder Be- + schleunigung des Hintergrundmediums (Platte statt Floppy) oder + Reduktion der Anforderungen). + + +Datenräume + +Datenräume sind die Grundlage für Dateien im EUMEL-System. + +Zurück zu unseren Angestellten: +Nachdem die Verbesserung vorgenommen wurde, daß sich zwei oder mehr Ange- +stellte eine Seite auf dem Tisch "teilen", tritt sofort ein neues Problem +auf. Es kann nun nämlich passieren, daß zwei Angestellte eine Original-Seite +verändern und beide in dem gleichen Buch ersetzt werden müssen. Es befinden +sich somit noch mindestens zwei andere mit Notizen versehene Seiten mit +gleicher Seitennummer in einem Buch. Zu allem Unglück wurde die Original- +Seite ersetzt, so daß andere Angestellte nur die mit Notizen versehene Seiten +erhalten können. Was ist zu tun? Das Verfahren sollte doch beibehalten +werden, denn schließlich ist eine totale Abkehr von Arbeitsvorgängen für +Verwaltungsangestellte nicht denkbar. + +Als erste Idee kommt ihnen in den Sinn, einfach alle Bücher für alle Ange- +stellten zu photokopieren. Dann kann es ja nicht zu einer solchen Kollision +kommen, daß zwei oder mehr Angestellte eine Seite in einem Buch ersetzen +wollen, weil jeder Angestellte seine eigene Kopie besitzt. Um die ver- +schiedenen Kopien eines Buches auseinander zu halten, wird von den Ange- +stellten verlangt, ihre Buch-Kopie mit einem sinnvollen Namen zu versehen. +Dies Verfahren funktioniert auch eine Weile, bis ein strebsamer Angestellter +einen Verbesserungsvorschlag macht, der prompt mit DM 5,- honoriert wird: +wie bereits mit den Seiten auf dem Tisch geschehen, ist es ja nicht not- +wendig, die Bücher zu photokopieren, sondern nur die mit Notizen versehenen +in einen Ordner, der entsprechend einer Buch-Kopie angelegt wird, einzu- +ordnen. Alle anderen, nicht veränderten Seiten können noch immer gemeinsam +benutzt werden. + +Und so funktioniert es nun: +Bei Arbeitsbeginn finden die Angestellten einen Buchbestand vor. Um mit einem +Buch arbeiten zu können, muß ein Angestellter einen Ordner für dieses Buch +anlegen, in den die ggf. veränderten Seiten eingeordnet werden. Zu diesem +Zweck muß jeder Ordner einen sinnvollen Namen erhalten, damit die Angestell- +ten ihre Ordner auch wiederfinden. Am Anfang müssen die Angestellten Seiten +der Original-Bücher kopieren. Wird eine solche Seite mit Notizen versehen, +also verändert, muß sie bei einer Verdrängung in den entsprechenden Ordner +eingefügt werden. Muß ein Angestellter eine neue Seite kopieren, so schaut +er erst in seinem Ordner nach, ob sich die entsprechende Seite dort befindet. +Damit wird garantiert, daß jeder Angestellte auch immer seine, mit Notizen +versehene Seiten erhält. Befindet sich eine gesuchte Seite nicht in dem +Ordner (am Arbeitsbeginn ist ein Ordner natürlich immer leer), so kopiert er +sich eine Seite aus dem entsprechenden Original-Buch. + +In der Zwischenzeit passiert folgendes im Rechner: +Eine Sammlung von Daten und/oder Programmen wird im EUMEL-System ein "Daten- +raum" ("dataspace") genannt. Erhält ein Datenraum einen Namen, so wird +dieser Datenraum eine Datei ("file") genannt. Angenommen, es existiert im +System eine Datei mit dem Namen 'Mist', die ein Angestellter mit dem Namen +'Krümel Monster' erstellt hat. Ein anderer Benutzer mit dem Namen 'Grobi' +will mit dieser Datei arbeiten. Grobi kopiert sich also diese Datei und gibt +ihr den Namen 'Grobis Mist'. Durch diese Kopier-Operation wird ein neuer +Datenraum angelegt, der aber anfänglich nur Verweise auf den Datenraum ent- +hält, der sich unter dem Namen 'Mist' verbirgt. Der Datenraum bzw. die +Seiten, die in Datei 'Mist' enthalten sind, werden also "geshared", d.h. von +mehreren Benutzern gemeinsam verwendet (in unserem Beispiel von Grobi und +Krümel Monster). Es erfolgt also eine logische Kopie, aber keine physika- +lische! + +Will der Angestellte Grobi nun eine Seite der Datei 'Grobis Mist' verwenden, +so erhält er natürlich die entsprechende Seite aus der Datei 'Mist'. Ver- +ändert der Angestellte Grobi nun eine Seite, so wird diese veränderte Seite +in dem Datenraum vermerkt, der unter dem Namen 'Grobis Mist' ansprechbar ist. +Davon merkt der Benutzer 'Krümel Monster' natürlich nichts, denn er arbeitet +mit den Seiten seines Datenraums weiter, die unverändert geblieben sind. Aber +auch Grobi merkt nichts davon, daß Seiten soweit wie möglich gemeinsam be- +nutzt werden. + +Merke: Durch das Konzept der Datenräume und Dateien (die nichts anderes sind + als benannte Datenräume), ist es möglich, auch Daten von verschiedenen + Programmen her gemeinsam zu benutzen und somit eine redundante + Speicherung überflüssig zu machen. Programme sind ebenfalls in Daten- + räumen gespeichert, so daß einer gemeinsamen Benutzung von z.B. + Systemprogrammen durch mehrere Nutzer nichts im Wege steht. + + + +Fixpunkte + +In gewissen Zeitabständen wird der gesamte Systemzustand eines EUMEL-Systems +gespeichert ("Fixpunkt"). Bei eventuell auftretenden Störungen kann dadurch +immer bei dem letzten Fixpunkt mit der Verarbeitung fortgefahren werden. + +Zurück zu unseren Angestellten, die typischerweise dieses komische System +weiter benutzen: Es passiert zum ersten Mal ein entsetzliches Unglück: +während im Sommer mehrere Fenster geöffnet wurden, betritt der "reitende" +Bürobote das Zimmer und alle Seiten werden von den Tischen und aus allen +offenen Ordnern herabgeweht. Da unsere Angestellten - wie man sich leicht +vorstellen kann - etwas vergeßlich sind, können sie nicht mehr rekon- +struieren, welche Seiten auf den Tischen und welche sich in den Büchern bzw. +Ordnern befanden. Die Arbeit von mehreren Monaten ist somit verloren! + +Deshalb werden Sicherheitsmaßnahmen getroffen: +In regelmäßigen Zeitabständen müssen alle Angestellten ihre Arbeit unter- +brechen. Dann wird von einem - extra dazu abgestellten - Angestellten Listen +angelegt, in denen die Seiten auf dem Tisch, den Ordnern und den Büchern +vermerkt wird. Im Falle eines erneuten Unglücks braucht man also nur die +letzte dieser Listen zu konsultieren, um eine gesicherte Arbeitssituation +herzustellen. Allerdings ist in einem solchen Fall diejenige Arbeit verloren, +die in der Zwischenzeit seit der Erstellung der letzten Liste geleistet +wurde. Aber das wird ja gerne in Kauf genommen, weil überhaupt weitergemacht +werden kann und nicht die gesamte Arbeit verloren ist. + +Merke: In gewissen (einstellbaren, typisch: 15 Minuten) Zeitabständen wird + vom EUMEL-System der gesamte Zustand des Systems gesichert. Diese + Sicherung wird "Fixpunkt" genannt. Dazu ist es notwendig, daß die + Verarbeitung der Programme kurz (z.Z. 0.2 Sek.) unterbrochen wird, + was sich jedoch meist nicht besonders störend auswirkt. Damit ist es + aber sichergestellt, daß bei einem Stromausfall, Hardware- oder Soft- + warestörungen immer zu einem Zeitpunkt in der Verarbeitung "aufge- + setzt" werden kann, bei dem nur diejenigen Daten verloren sind, die + seit dem letzten "Fixpunkt" aufliefen. + + + +Archiv + +Ein weiteres Sicherungsmittel im EUMEL-System ist das Archiv, mit welchem +man Dateien (also Daten und/oder Programme) extern zum EUMEL-System +speichern kann. + +Verlassen wir nun lieber unsere Angestellten. Dieses Modell würden wir sonst +übermäßig strapazieren. Wenden wir uns vielmehr einem weiteren Sicherungs- +mittel des EUMEL-Systems zu, dem EUMEL-Archiv. Mit Hilfe des EUMEL-Archivs +ist es möglich, Dateien auf Floppies zu schreiben und somit außerhalb des +EUMEL-Systems aufzubewahren. Es ist nun möglich, mehrere Dateien auf einer +Floppy zu speichern. Bloß wie funktioniert das? + +Ein gutes Modell des EUMEL-Archivs stellt ein Tonband oder eine Musikkassette +dar. Auf diesen werden die Musikstücke (unsere Dateien) nacheinander (Fach- +ausdruck: "sequentiell") aufgezeichnet, d.h. neue Musikstücke (Dateien) +können immer nur angefügt werden. Ist das Tonband oder die Kassette voll +beschrieben, so schaltet das Gerät meist automatisch ab. Im EUMEL-System +gibt's in solchen Fällen eine Fehlermeldung. + +Unterschiedlich zu einem Tonband ist jedoch, daß im EUMEL-System die Namen +der Dateien mit abgespeichert werden und diese Dateien - durch die Angabe +des Dateinamens - gezielt vom Archiv gelesen werden können. Bei einem Ton- +band oder einer Kassette muß man sich erst alle Musikstücke anhören, bis +das Musikstück erreicht ist, welches benötigt wird. Dieses "sequentielle" +Überlesen nicht benötigter Dateien erledigt das EUMEL-System "automatisch". + +Im EUMEL-System gibt es nun nicht nur die Möglichkeit, eine Datei auf ein +Archiv zu schreiben oder von einem Archiv zu lesen, sondern auch mehrere Da- +teien mit einem Kommando zu lesen oder zu schreiben. Zusätzlich ist es mög- +lich, ein Archiv zu löschen (und dann ggf. neu zu beschreiben), wenn die +"archivierten" Dateien nicht mehr benötigt werden. + +Nun passiert es oft, daß eine bereits archivierte Datei verändert wird und +nochmals auf das Archiv geschrieben werden soll. Aber durch eine Veränderung +der Datei hat diese gerade ihren Platzbedarf verändert. Somit könnte die +Datei - sofern sie sich vergrössert hat - eine nachfolgende Datei auf dem +Archiv u.U. teilweise überschreiben. Deshalb wurde im EUMEL-Archiv folgende +Vereinbarung getroffen: Wird eine Datei nochmals auf ein Archiv geschrieben, +so wird die Datei, die sich bereits auf dem Archiv befindet, als "ungültig" +gekennzeichnet und die neue Version an das Ende angefügt. Nur wenn die alte +Datei die letzte auf dem Archiv ist, wird sie von der neuen Version über- +schrieben. + +Merke: Durch dieses Verfahren kann es zu einer kuriosen Situation kommen: + zwei Dateien werden abwechselnd auf ein Archiv in mehreren Versionen + geschrieben. Obwohl beide Dateien zusammengenommen bei weitem nicht + das Archiv auffüllen würden, kommt es zum Überlauf. In einem solchen + Fall muß man das Archiv löschen (wobei vorher die Dateien ggf. in das + System geholt werden müssen) und beide Dateien erneut auf das Archiv + schreiben. + + + +4. Kleines #ib#EUMEL-Wörterbuch + +In diesem Wörterbuch werden einige der Begriffe, die häufig in diesem Be- +nutzer-Handbuch verwendet werden, erläutert. Bezüge auf weitere Begriffe, +die in diesem Wörterbuch stehen, werden mit den Zeichen ">" und "<" ge- +klammert. + +Anweisung: Direktive an die Textkosmetik, welche direkt in einen Text + geschrieben wird. Eine Anweisung muß in "\#" eingefaßt + werden. Beachte den Unterschied zu einem Kommando. + +Archiv: Ein Programmsystem, um Dateien des EUMEL-Systems auf + Floppys außerhalb des Systems zu speichern oder von dort + wieder in das EUMEL-System zu holen. Als Archiv wird auch + noch ein Speichermedium bezeichnet (in der Regel eine + Diskette). + +Benutzer-Task: Im Gegensatz zu einer >System-Task< ist eine Benutzer-Task + eine Task, die von einem Benutzer erzeugt worder ist. Sie + ist entweder an ein Terminal gekoppelt oder kann unab- + hängig von einem Terminal im Hintergrund bearbeitet werden. + +BOUND: Attribut von Variablen, das bei einer Deklaration vor die + Typangabe gesetzt wird. Dient zur Aufprägung eines Daten- + typs auf einen Datenraum. + +DATASPACE: Eine Datei ohne Namen. + +Datenraum: Siehe >DATASPACE<. + +Editor: Programm zur Eingabe und Veränderung von Texten, Daten und + Programmen. + +ELAN: Programmiersprache des EUMEL-Systems ("ELementary + LANguage"). + +ELAN-Compiler: Ein Programm, welches ein korrektes ELAN-Programm in ein + äquivalentes, ablauffähiges Programm (im >EUMEL0-Code<) + übersetzt. + +EUMEL0-Code: Maschinensprache des EUMEL-Systems. + +EUMEL-Drucker: Programm zur Ansteuerung von (unterschiedlichen) Druckern. + Der EUMEL-Drucker wird durch Kommandos gesteuert und er- + laubt es, unterschiedliche Drucker mit verschiedenartigen + Leistungen immer gleich anzusprechen. + +EUMEL-Standard: Objekte (also Datentypen, Prozeduren und/oder Operatoren), + die durch Pakete realisiert werden und standardmässig in + jedem EUMEL-System verfügbar sind. + +Fixpunkt: Speicherung des aktuellen Systemzustandes in regelmäßigen + Abständen. Bei Hardware- oder Softwarestörungen kann immer + bei der letzten Fixpunkt-Sicherung aufgesetzt werden. + +Hintergrund-Task: Eine >Task<, die nicht an ein Terminal angekoppelt ist + (d.h. einem Benutzer nicht direkt zugänglich), aber trotz- + dem vom System bearbeitet wird oder im Wartezustand ist + (warten auf einen Auftrag oder eine Ein/Ausgabe-Operation). + +Kommando: Ein ELAN-Programm, welches in der Regel aus einem + Prozeduraufruf besteht. Ein Kommando kann vom >Monitor< + oder Editor gegeben werden. Kommandos können ebenfalls in + Programmen verwandt werden. + +Lokale Dateien: Dateien einer Benutzer-Task. + +Manager: Eine >Task<, die auf Aufträge wartet. Beispiele sind die + Spool-Task bzw. Datei-Manager. Letzterer wird für die + Haltung längerfristig benötigter Dateien gebraucht. + +Monitor: Der Monitor steuert die Kommunikation zwischen einem + Benutzer am Terminal und dem EUMEL-Betriebssystem, nachdem + der Benutzer sich mit Hilfe des >Supervisors< eine Task + erschaffen hat. Die Monitor-Kommandos beziehen sich immer + auf die angekoppelte Benutzer-Task. + +paging: Benötigte Informationen werden in Einheiten ("pages") in + den Zentralspeicher des Rechners geladen. Somit ist es + möglich, bei weitem größere Informationsmengen zu ver- + arbeiten, als auf einmal in den Speicher des Rechners + passen. + +OPERATOR: >Task<, mit der das EUMEL-System u.a. gestartet, "abge- + schaltet" und gesichert werden kann. + +Scanner: Programm, um aus einem Text lexikalische Elemente ("Le- + xeme") herauszublenden. In dem im >EUMEL-Standard< + implementierten Scanner werden Lexeme nach der ELAN-Syntax + erkannt, redundante Leerzeichen (nicht in Texten) sowie + Kommentare überlesen. + +Sendungs-Vermittlung: Steuerung der Übermittlung von Informationen zwischen + verschiedenen >Tasks<. + +sharing: >Datenräume< und/oder >pages< können von mehreren Benutzern + gleichzeitig benutzt werden. Erst bei einer Schreibopera- + tion eines Benutzers wird nur für diesen Nutzer eine Kopie + der Daten angelegt. ("copy on write"). + +Spooler: Systemprogramm des EUMEL-Systems, welches Druckaufträge + zwischenspeichert, so daß unmittelbar weiter gearbeitet + werden kann. + +Supervisor: Kern des EUMEL-Betriebssystems auf der ELAN-Ebene zum Ver- + walten von Tasks. + +Supervisor-Kommando: Kommando zur Steuerung (An-/Abkoppeln, Erzeugen, + Benutzung) einer >Benutzer-Task<. + +System-Task: Eine >Task<, die für Aufrechterhaltung, Betrieb und Steu- + erung des EUMEL-Systems benötigt und nicht von einem + Benutzer erzeugt wird, sondern "immer" im >Taskbaum< + vorhanden ist. + +Task: Eigenständiger Prozeß (Auftrag) im EUMEL-System. + +Taskbaum: Eine baumförmige Anordnung von >Tasks<, in die jede Task + des EUMEL-Systems eingefügt wird. Dabei hat jede Task + - mit Ausnahme des >Urvaters< - eine >Vater-Task<, und + kann weitere Tasks erzeugen ("Söhne"). + +Textkosmetik: Programme des EUMEL-Systems, die die Gestaltung eines + Textes erlauben. + +Urvater: Wurzel des >Task-Baums< mit dem Namen 'UR'. + +Vater-Dateien: Dateien einer >Vater-Task<. + +Vater-Task: Eine >Task<, die einer Task in direkt aufsteigender Linie + im >Taskbaum< übergeordnet ist. Es wird dabei zwischen + einer "unmittelbaren" (die direkt übergeordnete Vater-Task) + und "mittelbaren" Vater-Tasks (Vater-Tasks, die über die + unmittelbare Vater-Task erreichbar sind) unterschieden. + + + +5. ELAN-Literatur + +Bittner, M., Jäckel, J., Jähnichen, S.: + ELAN - Beispielsammlung. + Institut für angewandte Informatik, + Fachbereich 20, TU Berlin, + Berlin, 1979 + +Hahn, R.: + Höhere Programmiersprachen im Vergleich. + Akademische Verlagsgesellschaft, + Wiesbaden, 1981 + +Hahn, R., Nienaber, B.: + Probleme lösen mit dem Computer. + Teil 1: Einführung in die algorithmische Problemlösung. + Teil 2: Werkzeuge und Methoden. + Neuer Verlag Bernhard Bruscha, + Tübingen, 1978 + +Hahn, R., Stock, P.: + ELAN - Handbuch. + Akademische Verlagsgesellschaft, + Wiesbaden, 1979 + +Hommel, G., Jäckel, J., Jähnichen, S., Kleine, K., Koch, W., Koster, K.: + ELAN - Sprachbeschreibung. + Akademische Verlagsgesellschaft, + Wiesbaden, 1979 + +Hommel, G., Jähnichen, S., Koch, W.: + SLAN - Eine erweiterbare Sprache zur Unterstützung der strukturierten + und modularen Programmierung. + 4. GI Fachtagung Programmiersprachen in Erlangen, + Springer Verlag, 1976 + +Hommel, G., Jähnichen, S., Koster, C.H.A.: + Methodisches Programmieren. + De Gruyter, Berlin, 1983 + +Klingen, L., Liedtke, J: + Programmieren mit ELAN + Teubner, Stuttgart, 1983 + +Liedtke, J.: + EUMEL - Ein ELAN-System für Mikroprozessoren. + GMD-Spiegel, + Bonn, 1979 + +Voila, H.T.: + A new computer routine for the generation of publishable data from + nothing. + Computer Quickies 48, 117 (1984) + + diff --git a/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil10 b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil10 new file mode 100644 index 0000000..0f3b656 --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil10 @@ -0,0 +1,771 @@ + EUMEL-Benutzerhandbuch + + TEIL 10: Graphik + +1. Übersicht + +Dieser Teil des Benutzer-Handbuchs beschreibt die Graphik-Möglichkeiten des +EUMEL-Systems. Die Graphik-Pakete gehören nicht zum EUMEL-Standard, sondern +sind Anwenderpakete, die im Quellcode ausgeliefert und von jeder Instal- +ation in das System aufgenommen werden können. Unter Umständen müssen +Programme erstellt werden, die die Anpassungen für spezielle graphische +Geräte einer Installation vornehmen. + +Das Graphik-System ermöglicht es, durch ELAN-Programme geräteunabhängige +Informationen für Zeichnungen ("Graphiken") zu erstellen. Die Graphik +erzeugenden Programme brauchen dabei keine gerätespezifischen Größen sowie +gerätespezifischen Unterprogramme zu enthalten. Sie befassen sich somit +ausschließlich mit der Erzeugung der problemorientierten Information für die +Konstruktion einer Zeichnung. Nach der geräteunabhängigen Erzeugung einer +Graphik kann diese auf unterschiedlichen Geräten ausgegeben werden (z.B. +erst auf einem Terminal zur Kontrolle und dann auf einem Plotter). + +Die EUMEL-Graphik umfaßt zwei- und dreidimensionale Graphik. Dabei ent- +spricht die Y-Achse bei der zweidimensionalen Graphik der Z-Achse (Höhe) bei +der dreidimensionalen Graphik. Im dreidimensionalen Fall sind perspektivi- +sche, orthografische und schiefwinklige Projektionen mit beliebigen Betrach- +tungswinkeln möglich. + +Bei der EUMEL-Graphik wird streng zwischen Erzeugung und Manipulation von +Graphiken (Bildern) auf der einen und Darstellung der erzeugten Bilder auf +der anderen Seite unterschieden. Für die Erzeugung und Manipulation der +Graphiken existiert der Typ PICTURE, für die Darstellung der Bilder gibt es +den Typ PICFILE. Dabei müssen Ausschnitt, Maßstab, Betrachtungswinkel und +Projektionsart erst bei der Darstellung festgelegt werden. Diese Kon- +struktion des Graphik-Systems hat folgende Vorteile: + +a) Programme, die Graphik-Informationen erzeugen, sind geräteunabhängig. + Das bedeutet, daß Programmierer sich ausschließlich mit einem logischen + Problem zu befassen brauchen und nicht mit gerätespezifischen Besonder- + heiten. + +b) Graphiken können auf mehreren unterschiedlich gearteten Geräten mehrmals + dargestellt werden, ohne daß das erzeugende Programm geändert oder neu + gestartet werden muß. Z.B. kann ein Programmierer eine Graphik erst auf + dem Terminal auf Richtigkeit und Größenverhältnisse überprüfen, bevor er + die Zeichnung auf einem Plotter zeichnen läßt. + +c) Graphiken können leicht geändert (z.B. vergrößert oder in eine Richtung + gestreckt) werden, ohne daß das erzeugende Programm erneut durchlaufen + werden muß. Zudem können Graphiken aneinander oder übereinander gelegt + werden. + +d) Graphiken mit unterschiedlichen Farben, Strichen usw. können leicht er- + zeugt werden. + +e) Der Anschluß von neuen Graphik-Geräten durch Benutzer ist leicht möglich, + ohne daß die Graphik erzeugenden Programme modifiziert werden müssen. + +f) Plotter können wie Drucker an einen SPOOLER gehängt werden. + +g) Bilder können als PICFILEs gespeichert und versandt werden. + + + +Erzeugung von Bildern + +Bilder entstehen in Objekten vom Datentyp + + PICTURE + +Diese müssen mit der Prozedur + + nilpicture + +initialisiert werden. Sie enthalten dann ein leeres Bild, dessen Dimension +noch nicht festgelegt ist. Die Dimension eines PICTUREs wird mit dem ersten +Schreibzugriff ('move' oder 'draw') festgelegt. Ein PICTURE kann immer nur +entweder zwei- oder dreidimensional sein. Außerdem kann einem PICTURE mit +der Prozedur + + pen + +genau ein virtueller Stift zugeordnet oder der aktuelle Stift erfragt werden. + +Die Erzeugung eines Bildes basiert auf dem Modell eines Plotters. Der (vir- +tuelle) Zeichenstift kann mit + + move + +ohne zu zeichnen an beliebige Stellen gefahren werden (reine Positionierung). +Mit + + draw + +wird der Stift veranlaßt, eine Linie von der aktuellen zur angegebenen Ziel- +position zu zeichnen. 'move' löst also Bewegungen mit gehobenem, 'draw' +solche mit gesenktem Stift aus. Um auch 'relatives' Zeichnen zu ermöglichen, +existiert die Prozedur + + where + +die die aktuelle Stiftposition liefert. + + + +Manipulation von Bildern + +Erstellte Bilder können als Ganzes manipuliert werden. Die Prozeduren + + translate (* verschieben *) + stretch (* strecken bzw. stauchen *) + rotate (* drehen *) + reflect (* spiegeln *) + +verändern jeweils das ganze Bild. Es ist aber auch möglich, mehrere Bilder +zusammenzufügen. Mit + + CAT + +kann ein weiteres Bild angefügt werden. Dabei müssen allerdings beide +PICTURE die gleiche Dimension haben. In solchen als ganzes manipulierten +Bildern kann man ohne Einschränkung mit 'draw' und 'move' weiterzeichnen. + + + +Darstellung + +Für die Darstellung der erzeugten Bilder existiert der Typ + + PICFILE + +Dieser besteht aus max. 128 PICTUREs, die mit den Prozeduren + + put + get + +eingegeben bzw. ausgegeben werden können. PICFILE wird durch Datenräume +realisiert, deshalb erfolgt die Assoziation an einen benannten Datenraum +ähnlich wie beim FILE. Dafür wird die Prozedur + + picture file + +verwandt. Ein neuer PICFILE enthält genau ein leeres PICTURE. Die Darstel- +lung der PICFILEs auf Zeichengeräten erfolgt mit der Prozedur + + plot + +Da die Graphiken aber in "Weltkoordinaten" erzeugt werden und die spätere +Darstellung vollkommen unbeachtet bleibt, müssen gewisse Darstellungspara- +meter für die Zeichnung gesetzt werden. Diese Parameter werden im PICFILE +abgelegt und gelten jeweils für den gesamten PICFILE. Dadurch ist es möglich, +einen PICFILE mit spezifizierter Darstellungsart über einen SPOOLER an einen +Plotter zu senden oder die bei der letzten Betrachtung gewählte Darstellung +mit in dem PICFILE gespeichert zu halten. Für die Darstellung können den +virtuellen Stiften mit der Prozedur + + select pen + +reale Stifte zugeordnet werden. Voreingestellt ist für alle virtuellen +Stifte: Standardfarbe, Standardstärke, durchgängige Linie. + +Indem man einigen virtuellen Stiften den leeren Stift als realen Stift zu- +ordnet, kann man einzelne PICTUREs ausblenden. Sowohl bei der Darstellung +von zwei- als auch dreidimensionaler Graphik kann die gewählte Zeichenfläche +auf dem Endgerät mit der Prozedur + + viewport + +festgelegt werden. Voreingestellt ist das Quadrat mit der größtmöglichen +Seitenlänge, d.h. der kürzeren Seite der hardwaremäßigen Zeichenfläche. + + + +Darstellung zweidimensionaler Graphik + +Bei der Darstellung zweidimensionaler Bilder muß der zu zeichnende Ausschnitt +(das 'Fenster') angegeben werden. Mit der Prozedur + + window + +wird durch Angabe der minimalen und maximalen X- bzw. Y-Koordinaten ein +Fenster definiert. Da das so definierte Fenster auf die ganze (mit 'viewport' +definierbare) Zeichenfläche abgebildet wird, ist der Abbildungsmaßstab durch +das Zusammenspiel von 'viewport' und 'window' bestimmt. Da bei 'viewport' +standardmäßig das maximale Zeichenquadrat voreingestellt ist, wird in diesem +Fall durch gleiche X- und Y-Fenstergröße eine winkeltreue Darstellung er- +reicht. + + + +Darstellung dreidimensionaler Graphik + +Im dreidimensionalen Fall wird das Fenster ebenfalls mit + + window + +definiert, wobei dann allerdings auch der Bereich der dritten Dimension +(Z-Koordinaten) zu berücksichtigen ist. Da die dreidimensionale Graphik auf +eine zweidimensionale Fläche projiziert wird, können aber noch weitere Dar- +stellungsparameter angegeben werden. Der Betrachtungswinkel wird mit Hilfe +der Prozedur + + view + +angegeben. Zur Spezifikation der gewünschten Projektionsart gibt es + + orthographic (* orthographische Projektion *) + perspective (* perspektivische Projektion, + der Fluchtpunkt ist frei wählbar *) + oblique (* schiefwinklige Projektion *) + + + +Beispiel (Sinuskurve) + + funktion zeichnen; + bild darstellen . + +funktion zeichen : + PICTURE VAR pic :: nilpicture; + REAL VAR x := -pi; + move (pic, x, sin (x)); + REP x INCR 0.1; + draw (pic, x, sin (x)) + UNTIL x >= pi PER . + +bild darstellen : + PICFILE VAR p :: picture file ("sinus"); + window (p, -pi, pi, -1.0, 1.0); + put (p, pic); + plot (p) . + + + +Beispiel (Würfel) + + wuerfel zeichen; + wuerfel darstellen. + +wuerfel zeichnen : + zeichne vorderseite; + zeichne rueckseite; + zeichne verbindungskanten. + +zeichne vorderseite : + PICTURE VAR vorderseite :: nilpicture; + move (vorderseite, 0.0, 0.0, 0.0); + draw (vorderseite, 1.0, 0.0, 0.0); + draw (vorderseite, 1.0, 0.0, 1.0); + draw (vorderseite, 0.0, 0.0, 1.0); + draw (vorderseite, 0.0, 0.0, 0.0). + +zeichne rueckseite : + PICTURE VAR rueckseite :: translate (vorderseite, 0.0, 1.0, 0.0). + +zeichne verbindungskanten : + PICTURE VAR verbindungskanten :: nilpicture; + move (verbindungskanten, 0.0, 0.0, 0.0); + draw (verbindungskanten, 0.0, 1.0, 0.0); + + move (verbindungskanten, 1.0, 0.0, 0.0); + draw (verbindungskanten, 1.0, 1.0, 0.0); + + move (verbindungskanten, 1.0, 0.0, 1.0); + draw (verbindungskanten, 1.0, 1.0, 1.0); + + move (verbindungskanten, 0.0, 0.0, 1.0); + draw (verbindungskanten, 0.0, 1.0, 1.0). + +wuerfel darstellen : + PICFILE VAR p := picture file ("wuerfel"); + put (p, vorderseite); + put (p, rueckseite); + put (p, verbindungskanten); + window (p, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0); + view (p, 0.0, 40.0, 20.0); + orthographic (p); + plot (p). + + + +Beschreibung der Graphik-Prozeduren + +Zweidimensionale PICTUREs brauchen weniger Speicherplatz als dreidimensio- +nale. Daher werden in einigen Fehlermeldungen unterschiedliche Größen ange- +geben. + +:= + OP := (PICTURE VAR dest, PICTURE CONST source) + Zweck: Zuweisung + + OP := (PICFILE VAR dest, DATASPACE CONST source) + Zweck: Assoziiert die PICFILE Variable 'dest' mit der DATASPACE CONST + 'source' und initialisiert die PICFILE Variable sofern nötig. + Fehlerfall: + * dataspace is no PICFILE + Der anzukoppelnde Datenraum hat einen falschen Typ. + +CAT + OP CAT (PICTURE VAR dest, PICTURE CONST source) + Zweck: Aneinanderfügen von zwei PICTURE's. + Fehlerfälle: + * OP CAT: left dimension <> right dimension + Es können nur PICTUREs mit gleicher Dimension angefügt werden. + * OP CAT: Picture overflow + Die beiden PICTURE überschreiten die maximale Größe eines Pictures. + +act picture + PICTURE PROC act picture (PICFILE VAR p) + Zweck: Liefert das PICTURE des PICFILEs 'p', auf das mit 'backward' o.ä. + positioniert wurde. + +backward + PROC backward (PICFILE VAR p) + Zweck: Positioniert den PICFILE 'p' um ein PICTURE zurück. + Fehlerfall: + * backward at begin of file + Es wurde versucht vor den Anfang des PICFILEs zu positionieren. + +draw + PROC draw (PICTURE VAR pic, REAL CONST x, y) + Zweck: Die Prozedur zeichnet in dem (zweidimensionalen) Bild 'pic' eine + Linie von der aktuellen Position zur Position (x, y). + Fehlerfälle: + * picture overflow + Zu viele Befehle in einem PICTURE (z. Zeit max. 1927) + * picture is three dimensional + Ein PICTURE kann nur entweder zwei- oder dreidimensional sein. + + PROC draw (PICTURE VAR pic, REAL CONST x, y, z) + Zweck: Die Prozedur zeichnet in dem (dreidimensionalen) Bild 'pic' eine + gerade Linie von der aktuellen Position zur Position (x, y, z). + Fehlerfälle: + * picture overflow + Zu viele Befehle in einem PICTURE (z. Zeit max. 1310) + * picture is only two dimensional + Ein PICTURE kann nur entweder zwei- oder dreidimensional sein. + + PROC draw (PICTURE VAR pic, TEXT CONST text) + Zweck: Der angegebene Text wird in das Bild 'pic' eingetragen. Der An- + fang ist dabei die aktuelle Stiftposition. Diese wird nicht ver- + ändert. + Fehlerfall: + * picture overflow + Der Text paßt nicht mehr in das PICTURE. + + PROC draw (PICTURE VAR pic, TEXT CONST text, REAL CONST angle, height) + Zweck: Der angegebene Text wird unter dem Winkel 'angle' gegenüber der + Waagerechten und in der Größe 'height' in das PICTURE 'pic' + eingetragen. Der Anfang ist dabei die aktuelle Stiftposition. + Diese wird nicht verändert. + Fehlerfall: + * picture overflow + Der Text paßt nicht mehr in das PICTURE. + + PROC draw (PICFILE VAR pic, REAL CONST x, y) + Zweck: Die Prozedur zeichnet in dem aktuellen (zweidimensionalen) + PICTURE des PICFILEs 'p' eine gerade Linie. Der (virtuelle) Stift + wird von der aktuellen Position zur Position (x, y) gefahren. + Falls das aktuelle PICTURE zu voll ist, wird automatisch auf das + nächste umgeschaltet. + Fehlerfälle: + * picfile overflow + Das letzte PICTURE ist voll (z. Zeit max. 128 PICTURE) + * picture is threedimensional + Das aktuelle PICTURE ist dreidimensional. + + PROC draw (PICTFILE VAR pic, REAL CONST x, y, z) + Zweck: s. o. + Fehlerfälle: + * picfile overflow + Das letzte PICTURE ist voll (z. Zeit max. 128) + * picfile is only twodimensional + Das aktuelle PICTURE ist zweidimensional. + + PROC draw (PICTFILE VAR pic, TEXT CONST text) + Zweck: Der angegebene Text wird in das aktuelle PICTURE des PICFILEs 'p' + eingetragen. Falls das aktuelle PICTURE zu voll ist, wird auto- + matisch auf das nächste umgeschaltet. Der Anfang ist dabei die + aktuelle Stiftposition. Diese wird nicht verändert. + Fehlerfall: + * picfile overflow + Das letzte PICTURE ist voll (z. Zeit max. 128) + + PROC draw (PICFILE VAR pic, TEXT CONST text, REAL CONST angle, height) + Zweck: Der angegebene Text wird unter dem Winkel 'angle' gegenüber der + Waagerechten und in der Größe 'height' in das aktuelle PICTURE + des PICFILES 'p' eingetragen. Falls das aktuelle PICTURE zu voll + ist, wird automatisch auf das nächste umgeschaltet. Der Anfang ist + dabei die aktuelle Stiftposition. Diese wird nicht verändert. + Fehlerfall: + * picfile overflow + Das letzte PICTURE ist voll (z. Zeit max. 128) + +eof + BOOL PROC eof (PICFILE CONST p) + Zweck: Liefert 'TRUE' wenn hinter das Ende des PICFILEs positioniert + wurde. + +extrema + PROC extrema (PICTURE CONST p, REAL VAR x min, x max, y min, y max) + Zweck: Die Prozedur liefert die größten und kleinsten X- und Y-Koordi- + naten des PICTUREs 'p'. Diese werden in die Parameter 'x min', + 'x max', 'y min' und 'y max' eingetragen. + + PROC extrema (PICTURE CONST p, + REAL VAR x min, x max, y min, y max, z min, z max) + Zweck: s.o. + + PROC extrema (PICFILE VAR p, REAL VAR x min, x max, y min, y max) + Zweck: s.o. + + PROC extrema (PICFILE VAR p, + REAL VAR x min, x max, y min, y max, z min, z max) + Zweck: s.o. + +forward + PROC forward (PICFILE VAR p) + Zweck: Positioniert den PICFILE um ein PICTURE weiter. + Fehlerfall: + * picfile overflow + Es sollte hinter das Ende des PICFILEs positioniert werden. + +get + PROC get (PICFILE VAR p, PICTURE VAR pic) + Zweck: Liest ein PICTURE aus einem PICFILE und positioniert auf das + Nächste. + Fehlerfall: + * input after end of picfile + Es sollte nach dem Ende des Picfiles gelesen werden. + +move + PROC move (PICTURE VAR pic, REAL CONST x, y) + Zweck: Der (virtuelle) Stift wird zur Position (x, y) gefahren. + Fehlerfälle: + * picture overflow + Zu viele Befehle in einem PICTURE (z. Zeit max. 1927 'moves') + * picture is three dimensional + Ein PICTURE kann nur entweder zwei- oder dreidimensional sein. + + PROC move (PICTURE VAR pic, REAL CONST x, y, z) + Zweck: Der (virtuelle) Stift wird zur Position (x, y, z) gefahren. + Fehlerfälle: + * picture overflow + Zu viele Befehle in einem PICTURE (z. Zeit max. 1310) + * picture is only twodimensional + Ein PICTURE kann nur entweder zwei- oder dreidimensional sein. + + PROC move (PICFILE VAR p, REAL CONST x, y) + Zweck: Der (virtuelle) Stift wird zur Position (x, y) gefahren. Falls + das aktuelle PICTURE des PICFILEs 'p' zu voll ist, wird auto- + matisch auf das nächste umgeschaltet. + Fehlerfall: + * picfile overflow + Das letzte PICTURE ist voll (z. Zeit max. 128 PICTUREs) + + PROC move (PICFILE VAR p, REAL CONST x, y, z) + Zweck: Der (virtuelle) Stift wird zur Position (x, y, z) gefahren. Falls + das aktuelle PICTURE des PICFILEs 'p' zu voll ist, wird auto- + matisch auf das nächste umgeschaltet. + Fehlerfall: + * picfile overflow + Das letzte PICTURE ist voll (z. Zeit max. 128 PICTUREs) + +nilpicture + PICTURE PROC nilpicture + Zweck: Die Prozedure liefert ein leeres PICTURE zur Initialisierung. + +oblique + PROC oblique (PICFILE VAR p, REAL CONST a, b) + Zweck: Bei dem (dreidimensionalen!) Bild 'p' wird 'schiefwinklig' als + gewünschte Projektionsart eingestellt. Dabei ist (a, b) der Punkt + in der X-Y-Ebene, auf den der Einheitsvector in Z-Richtung + abgebildet werden soll. + +orthographic + PROC orthographic (PICFILE VAR p) + Zweck: Bei dem (dreidimensionalen!) Bild 'p' wird "orthografisch" als + Projektionsart eingestellt. Bei der orthografischen Projektion + wird ein dreidimensionaler Körper mit parallelen Strahlen senk- + recht auf die Projektionsebene abgebildet. + +pen + INT PROC pen (PICTURE CONST pic) + Zweck: Liefert die Nummer des 'virtuellen Stifts'. + + PICTURE PROC pen (PICTURE CONST pic, INT CONST pen) + Zweck: Liefert ein PICTURE mit dem Inhalt 'pic' und dem 'virtuellen + Stift' mit der Nummer 'pen'. Möglich sind die Nummern 1 - 16. + Fehlerfälle: + * PROC pen: pen [No] < 1 + Der gewünschte Stift ist kleiner als 1. + * PROC pen: pen [No] > 16 + Der gewünschte Stift ist größer als 16. + +perspective + PROC perspective (PICFILE VAR p, REAL CONST cx, cy, cz) + Zweck: Bei den dreidimensionalen PICTUREs des PICFILE's 'p' wird + "perspektivisch" als gewünschte Projektionsart eingestellt. Der + Punkt (cx, cy, cz) ist der Fluchtpunkt der Projektion, d.h. alle + Parallelen zur Blickrichtung schneiden sich in diesem Punkt. + +pic no + INT PROC pic no (PICFILE CONST p) + Zweck: Liefert die Nummer des aktuellen PICTUREs. + +picture file + DATASPACE PROC picture file (TEXT CONST name) + Zweck: Die Prozedur dient zur Assoziation eines benannten Datenraumes + mit einem PICFILE (s. Operator ':='). + +plot + PROC plot (TEXT CONST name) + Zweck: Der PICFILE mit dem Namen 'name' wird entspechend der angege- + benen Darstellungsart gezeichnet. Diese Parameter ('perspective', + 'orthographic', 'oblique', 'view', 'window' etc.) müssen vorher + eingestellt werden. + Fehlerfall: + * FILE does not exist + Es existiert kein PICFILE mit dem Namen 'name' + + PROC plot (PICFILE VAR p) + Zweck: Der PICFILE 'p' wird entspechend der angegebenen Darstellungsart + gezeichnet. Diese Parameter müssen vorher eingestellt werden. + + + Zweidimensional: + + obligat: 'window' (zweidimensional) + optional: 'view' (zweidimensional) + 'select pen' + 'viewport' + + Dreidimensional: + + obligat: 'window' (dreidimensional) + optional: 'view' (dreidimensional) + 'orthographic', 'perspective', 'oblique' + 'viewport' + 'select pen' + +put + PROC put (PICFILE VAR p, PICTURE CONST pic) + Zweck: Schreibt ein PICTURE in einen PICFILE und positioniert um eins + vor. + Fehlerfall: + * picfile overflow + Der PICFILE ist voll. (z. Z. max. 128 PICTURE) + +reset + PROC reset (PICFILE VAR p) + Zweck: Positioniert auf den Anfang eines Picfiles. + +rotate + PICTURE PROC rotate (PICTURE CONST pic, REAL CONST alpha) + Zweck: Das PICTURE 'pic' wird um den Punkt (0, 0) um den Winkel 'alpha' + (im Gradmaß) im mathematisch positiven Sinn gedreht. + + PICTURE PROC rotate (PICTURE CONST pic, REAL CONST alpha, beta, gamma) + Zweck: Das dreidimensionale PICTURE 'pic' wird um den Winkel 'alpha', + 'beta' oder 'gamma' im mathematisch positiven Sinn gedreht. Der + Winkel 'alpha' dreht um die X-Achse, der Winkel 'beta' um die + Y-Achse und 'gamma' um die Z-Achse. Es darf dabei nur jeweils + ein Winkel von 0.0 verschieden sein. Alle Winkel werden im + Gradmaß angegeben. + +select pen + PROC select pen (PICFILE VAR p, + INT CONST pen, colour, thickness, linetype) + Zweck: Für die Darstellung des Bildes 'p' soll dem "virtuellen Stift" + 'pen' ein realer Stift zugeordnet werden, der möglichst die Farbe + 'colour' und die Dicke 'thickness' hat und dabei Linien mit dem + Typ 'line type' zeichnet. Es wird die beste Annäherung für das + Ausgabegerät für diese Parameter genommen. Dabei gelten folgende + Vereinbarungen: + + Farbe: negative Farben setzten den Hintergrund, positive Farben + zeichnen im Vordergrund. + + 0 Löschstift (falls vorhanden) + 1 Standardfarbe des Endgeräts (schwarz oder weiß) + 2 rot + 3 blau + 4 grün + 5 schwarz + 6 weiß > 20 nicht normierte Sonderfarben + + Dicke: 0 + Standardstrichstärke des Endgerätes > 0 + Strichstärke in 1/10 mm + + Typ: + 0 keine sichtbare Linie + 1 durchgängige Linie + 2 gepunktete Linie + 3 kurz gestrichelte Linie + 4 lang gestrichelte Linie + 5 Strichpunktlinie + + Die hier aufgeführten Möglichkeiten müssen nicht an allen + grafischen Endgeräten vorhanden sein. Der geräteabhängige + Graphik-Treiber wählt jeweils die für ihn bestmögliche Annäherung. + + Fehlerfälle: + * pen < 1 + * pen > 16 + +size + INT PROC size (PICFILE CONST p) + Zweck: Liefert die aktuelle Größe eines PICFILEs in Bytes. + +stretch + PICTURE PROC stretch (PICTURE CONST pic, REAL CONST xc, yc) + Zweck: Das PICTURE 'pic' wird in X-Richtung um den Faktor 'xc', in + Y-Richtung um den Faktor 'yc' gestreckt (bzw. gestaucht). Dabei + bewirkt der Faktor + c > 1 eine Streckung + 0 < c < 1 eine Stauchung + c < 0 zusätzlich eine Achsenspiegelung + + PICTURE PROC stretch (PICTURE CONST pic, REAL CONST xc, yc, zc) + Zweck: Das dreidimensionale PICTURE 'pic' wird entsprechend den + angegeben Faktoren 'xc', 'yc' und 'zc' gestreckt. Wirkung s.o. + +translate + PICTURE PROC translate (PICTURE CONST pic, REAL CONST dx, dy) + Zweck: Das PICTURE 'pic' wird um 'dx' und 'dy' verschoben. + Fehlerfall: + * picture is threedimensional + 'pic' ist dreidimensional. + + PICTURE PROC translate (PICTURE CONST pic, REAL CONST dx, dy, dz) + Zweck: Das PICTURE 'pic' wird um 'dx', 'dy' und 'dz' verschoben. + Fehlerfall: + * picture is twodimensional + Das PICTURE 'pic' ist zweidimensional + +two dimensional + PROC two dimensional (PICFILE VAR p) + Zweck: Setzt als Projektionsart zweidimensional. + +view + PROC view (PICFILE VAR p, REAL CONST alpha, phi, theta) + Zweck: Dreidimensionale Bilder werden häufig nicht direkt von vorne + dargestellt, sondern für die Betrachtung gedreht. Mit der Prozedur + 'view' kann diese Betrachtungsrichtung durch die Polarwinkel 'phi' + und 'theta' angegeben werden. Mit dem Winkel 'alpha' kann dann + das Bild um den Mittelpunkt der Zeichenfläche gedreht werden. + Dadurch kann ein Bild auch auf einem Terminal hochkant gestellt + werden. Voreingestellt ist 'phi = 0, theta = 0 und alpha = 0', + d.h. direkt von oben. + + Im Gegensatz zu 'rotate' hat 'view' keine Wirkung auf das eigent- + liche Bild (PICFILE), sondern nur auf die gewählte Darstellung. + So addieren sich zwar aufeinanderfolgende "Rotationen", 'view' + aber geht immer von der Nullstellung aus. Auch kann das Bild + durch eine "Rotation" ganz oder teilweise aus oder in das Dar- + stellungsfenster ('window') gedreht werden. Bei 'view' verändern + sich die Koordinaten der Punkte nicht, d.h. das Fenster wird mit- + gedreht. + +viewport + PROC viewport (PICFILE VAR p, + REAL CONST hormin, hormax, vertmin, vertmax) + Zweck: Die Zeichenfläche auf dem Endgerät, auf dem das Bild dargestellt + werden soll, wird spezifiziert. Dabei wird sowohl die Größe als + auch die relative Lage der Zeichenfläche definiert. Der linke + untere Eckpunkt der physikalischen Zeichenfläche des Gerätes hat + die Koordinaten (0.0, 0.0). Die definierte Zeichenfläche erstreckt + sich + + 'hormin' - 'hormax' in der Horizontalen, + 'vertmin' - 'vertmax' in der Vertikalen. + + So liegt der linke untere Eckpunkt dann bei (hormin, vertmin), der + rechte obere bei (hormax, vertmax). + + Damit sowohl geräteunabhängige als auch maßstabsgerechte + Zeichnungen möglich sind, können die Koordinaten in zwei Arten + spezifiziert werden : + + a) Gerätekoordinaten + Die Koordinaten können Werte von 0.0 bis 2.0 annehmen. Dabei + hat die kürzere Seite der physikalischen Zeichenfläche defini- + tionsgemäß die Länge 1.0. + + b) absolute Koordinaten + Die Werte werden in cm angegeben. Für die Maximalwerte sind + nur Werte größer als 2.0 möglich. + + Voreingestellt ist + + viewport (0.0, 1.0, 0.0, 1.0), + + d.h. das größtmöglichste Quadrat, beginnend in der linken unteren + Ecke der physikalischen Zeichenfläche. In vielen Fällen wird + diese Einstellung ausreichen, so daß der Anwender kein eigenes + 'viewport' definieren muß. + + Der Abbildungsmaßstab wird durch das Zusammenspiel von 'viewport' + und 'window' festgelegt (siehe dort). Dabei ist insbesondere + darauf zu achten, daß winkeltreue Darstellungen nur bei gleichem + X- und Y-Maßstab möglich sind. Da man oft quadratische Fenster + ('window') verwendet, wurde als Standardfall auch ein quadrati- + sches 'viewport' gewählt. + +where + PROC where (PICTURE CONST pic, REAL VAR x, y) + Zweck: Die aktuelle Stiftposition wird in 'x' und 'y' eingetragen. + Fehlerfall: + * picture is threedimensional + Das PICTURE 'pic' ist dreidimensional + + PROC where (PICTURE CONST pic, REAL VAR x, y, z) + Zweck: Die aktuelle Stiftposition wird in 'x', 'y' und 'z' eingetragen. + Fehlerfall: + * picture is twodimensional + Das PICTURE 'pic' ist zweidimensional + +window + PROC window (PICFILE VAR p, REAL CONST x min, x max, y min, y max) + Zweck: Für die Darstellung eines zweidimensionalen Bildes wird das + darzustellende Fenster definiert. Alle Bildpunkte, deren X-Ko- + ordinaten im Intervall [x min, x max] und deren Y-Koordinaten im + Intervall [y min, y max] liegen, gehören zum definierten Fenster. + Vektoren, die über dieses Fenster hinausgehen, werden abge- + schnitten. Dieses Fenster wird auf die spezifizierte Zeichen- + fläche abgebildet. (Das ist standardmäßig das größtmögliche + Quadrat auf dem ausgewählten Gerät). + + Der Darstellungsmaßstab ergibt sich als + + x max - x min + ----------------------------------------- + horizontale Seitenlänge der Zeichenfläche + + y max - y min + ----------------------------------------- + vertikale Seitenlänge der Zeichenfläche + + Für eine winkeltreue Darstellung müssen X- und Y-Maßstab + gleich sein! Einfach können winkeltreue Darstellung erreicht + werden, wenn das Fenster eine quadratische Form hat. Die + Zeichenfläche ('viewport') ist dementsprechend als Quadrat vor- + eingestellt. + + PROC window (PICFILE VAR p, + REAL CONST x min, x max, y min, y max, z min, z max) + Zweck: Für die Darstellung eines dreidimensionalen Bildes wird das darzu- + stellende Fenster definiert. Alle Bildpunkte, deren X-Koordinaten im + Intervall [x min, x max] und deren Y-Koordinaten im Intervall + [y min, y max] und deren Z-Koordinaten im Intervall [z min, z max] + liegen, gehören zum definierten Fenster. Dieses dreidimensionale + Fenster (Quader) wird entsprechend der eingestellten Projektions- + art (orthografisch, perspektivisch oder schiefwinklig) und den + Betrachtungswinkeln (s. 'view') auf die spezifizierte Zeichen- + fläche abgebildet. (Das ist standardmäßig das größtmögliche + Quadrat auf dem ausgewählten Gerät.) Linien, die außerhalb dieses + Quadrates liegen, werden abgeschnitten. + + Anders als im zweidimensionalen Fall ist das Problem der Maßstäbe + nicht mehr nur durch das Zusammenspiel von 'window' und 'view- + port' zu beschreiben. Hier spielen auch Projektionsart und Dar- + stellungswinkel eine Rolle. Falls alle Darstellungswinkel den + Wert 0.0 haben, gilt das für den zweidimensionalen Fall gesagte + für die Ebene (y = 0.0) entsprechend. + +write is possible + BOOL PROC write is possible (PICTURE CONST pic, INT CONST space) + Zweck: Liefert 'TRUE', falls 'space' Bytes Platz in 'pic' vorhanden ist. + diff --git a/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil11 b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil11 new file mode 100644 index 0000000..cae9c50 --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil11 @@ -0,0 +1,1072 @@ + EUMEL-Benutzerhandbuch + + TEIL 11: Utilities + + +In diesem Teil werden einige Dienstprogramme aufgeführt. Diese Programme +sind bei speziellen Anwendungen nützlich. + + + +1. Scanner + +Der Scanner zerlegt einen TEXT in Symbole bzw. "Tokens" entsprechend der +ELAN-Sprachdefinition. + +Der Scanner kann benutzt werden, um festzustellen, welche Art von Symbolen +in einem TEXT enthalten sind. Die Repräsentation der Symbole müssen dabei +der ELAN-Syntax entsprechen. Folgende #ib#Symbole#ie# kann der Scanner +erkennen: + + - "tags", d.h. Namen, + - "bolds", d.h. Schlüsselworte, + - "number", d.h. INT oder REAL Zahlen, + - Operatoren, + - "delimiter", d.h. Begrenzer wie z.B. ";", + - und das Ende des Scan-Textes. + + +Der Scanner überliest Kommentare und Leerzeichen zwischen den Symbolen. +Der (erste) zu verarbeitende Text muß mit der Prozedur + + scan + +in den Scanner "hineingesteckt" werden. Mit der Prozedur + + next symbol + +wird das jeweils nächste Symbol des TEXTes geholt. Am Ende wird "end of scan" +und als Symbol 'niltext' geliefert. Falls innerhalb eines TEXT-Denoters oder +eines Kommentars "end of scan" auftritt, wird "within text" bzw. "within +comment" gemeldet. Der Scan-Prozeß kann dann mit dem nächsten zu scannenden +TEXT (der nächsten Zeile) fortgesetzt werden. Dafür wird nicht die Prozedur +'scan', sondern + + continue scan + +verwandt. Sie setzt im letzten Scan-Zustand (z.B. Kommentar oder TEXT- +Denoter) wieder auf, so daß auch Folgen von TEXTen (Zeilen) wie z.B. Dateien +leicht gescannt werden können. + +Mit den Prozeduren + + scan (* meldet eine Datei zum scannen an *) + next symbol (* holt die Symbole *) + +kann man auch eine Datei nach ELAN-Symbolen untersuchen. Beispiel: + + FILE VAR f :: ... + ... + scan (f); (* beginnt das Scanning in der nächsten Zeile *) + TEXT VAR symbol; + INT VAR type; + REP + next symbol (f, symbol, type); + verarbeite symbol + UNTIL type >= 7 END REP. + +Merke: Mit dem Scanner kann man einen ELAN-Text analysieren. + + + +Scanner-Kommandos + +continue scan + PROC continue scan (TEXT CONST scan text) + Zweck: Das Scanning soll mit 'scan text' fortgesetzt werden. Falls der + Scan-Vorgang beim vorigen 'scan text' innerhalb eines TEXT- + Denoters oder eines Kommentars abgebrochen wurde, wird er jetzt + entsprechend mit dem nächsten 'next symbol' fortgesetzt. Der + erste Teil-Scan einer Folge muß aber stets mit 'scan' einge- + leitet werden! + +next symbol + PROC next symbol (TEXT VAR symbol, INT VAR type) + Zweck: Holt das nächste Symbol. In "symbol" steht der TEXT des Symbols, + so z.B. die Ziffern eines INT-Denoters. Bei TEXT-Denotern + werden die führenden und abschließenden Anführungsstriche ab- + geschnitten. Leerzeichen oder Kommentare spielen in "tags" oder + "numbers" keine Rolle. Zwischen Symbolen spielen Leerzeichen + oder Kommentare keine Rolle. In "type" steht eine Kennzeichung + für den Typ des Symbols: + + tag = 1 , + bold = 2 , + number = 3 , + text = 4 , + operator = 5 , + delimiter = 6 , + end of file = 7 , + within comment = 8 , + within text = 9 . + + Wird Scan-Ende innerhalb eines Kommentars gefunden, so wird + 'niltext' und 'within comment' geliefert. Wird Scan-Ende inner- + halb eines TEXT-Denoters gefunden, so wird der schon analysierte + Teil des Denoters und 'within text' geliefert. + + PROC next symbol (TEXT VAR symbol) + Zweck: s.o. Es wird aber nur der Text des Symbols (ohne Typ) geliefert. + + PROC next symbol (FILE VAR f, TEXT CONST symbol) + Zweck: arbeitet wie obige Prozeduren, jedoch auf einen FILE. + + PROC next symbol (FILE VAR f, TEXT CONST symbol, INT VAR type) + Zweck: arbeitet wie obige Prozeduren, jedoch auf einen FILE. + +scan + PROC scan (TEXT CONST scan text) + Zweck: Meldet einen 'scan text' für den Scanner zur Verarbeitung an. + Die Prozedur 'scan' muß vor dem ersten Aufruf von 'next symbol' + gegeben werden. Im Gegensatz zu 'continue scan' normiert 'scan' + den inneren Zustand des Scanners, d.h. vorherige Scan-Vorgänge + haben keinen Einfluß mehr auf das Scanning. + + PROC scan (FILE VAR f) + Zweck: Wie obige Prozedur, jedoch auf einen FILE. Die zu scannende Zeile + ist die nächste Zeile im FILE 'f' ('scan' macht zuerst ein 'get- + line'). + + + +2. Inspector + +Der Inspector stellt ein Hilfsmittel bei der Programmentwicklung dar. + +Der Inspector informiert über alle + + - insertierten Prozeduren / Operatoren mit dem gleichen Namen + - Prozeduren / Operatoren / Typen, die ein Paket definiert + - bisher insertierten Pakete + - insertierten Prozeduren / Operatoren / Typen. + +Mit dem Aufruf von + + help ("name") + +wird eine Liste aller Prozeduren / Operatoren, die 'name' heißen, auf dem +Bildschirm ausgegeben. Die Liste ist paketweise sortiert unter Angabe des +Paketnamens. Die Ausgabe erfolgt mit der Angabe der Parametertypen. Gibt es +kein Objekt mit dem angegebenen Namen, so erscheint die Ausgabe + + unbekannt: name + +Das Kommando + + bulletin ("paket name") + +informiert über alle Objekte, die in der DEFINES-Liste des Pakets mit dem +Namen "paket name" stehen. Die Ausgabe erfolgt wie beim list-Kommando. + +Eine gesamte Liste aller bisher insertierten Prozeduren/Operatoren/Typen +erhält man mit dem Kommando + + bulletin + +Bei diesen Funktionen ist (noch) zu beachten, daß Typen immer dem textmäßig +vorhergehendem Paket zugeordnet werden. Der Grund hierfür liegt in der +Behandlung abstrakter Datentypen im ELAN-Compiler. Eine Korrektur ist für +spätere Auslieferungen geplant. + +Mit + + packets + +werden die Namen aller bisher insertierten Pakete "gelistet". + +Merke: Mit 'help' kann man sich über verfügbare Prozeduren/Operatoren in- +formieren. + + + +Inspector-Kommandos + +help + PROC help (TEXT CONST name) + Zweck: Listen aller Prozeduren / Operatoren mit dem Namen "name". Die + Ausgabe erfolgt direkt auf den Bildschirm. + +bulletin + PROC bulletin (TEXT CONST paket name) + Zweck: Listen aller in der DEFINES-Liste des Pakets mit dem Namen + "paket name". + + PROC bulletin + Zweck: Es wird eine Liste aller bisher insertierter Objekte erstellt. + Diese Liste ist paketweise sortiert. + +packets + PROC packets + Zweck: Auflisten der Namen aller bisher insertierten Pakete. + + + +3. Lexikographische Vergleiche + +Die üblichen Operatoren für TEXTe arbeiten mit dem der Reihenfolge des EUMEL- +Zeichencodes. Hier wird beschrieben, wie man lexikographische Vergleiche +nach DIN erhält. + +Für TEXT-Vergleiche nach DIN 5007 gibt es die Operatoren + + LEXEQUAL + LEXGREATER + LEXGREATEREQUAL + +Diese Operatoren vergleichen zwei TEXTE nach DIN 5007 mit folgenden +Bedingungen: + +- Die Reihenfolge enspricht 'ABC...Z', wobei große und kleine Buchstaben + gleich behandelt werden. + +- Weitere Entsprechungen: + ö = oe, ä = ae, ü = ue + Ö = Oe, Ü = Ue, Ä = Ae, + Ä = ä, Ü = ü, Ö = ö, + ß = ss + Dadurch ist z.B. + + "muß" LEXGREATER "Muster" --> FALSE + "Goethe" LEXEQUAL "Göthe" --> TRUE + +- Alle Sonderzeichen (außer " " und "-") werden ignoriert. + +- Ein Leerzeichen und ein Bindestrich zwischen Worten werden gleich behan- + delt. Beispiel: + + "EUMEL System" LEXEQUAL "EUMEL-System" --> TRUE + +Anmerkung: Diese drei Operatoren sind - sofern die oben erwähnten Zeichen in +den Operanden vorkommen - langsamer als die "normalen" TEXT-Vergleiche +(=, >, <, usw.). Das liegt daran, daß die Operanden in solchen Fällen +umgewandelt werden. + + + +Lexikographische Operatoren + +LEXEQUAL + BOOL OP LEXEQUAL (TEXT CONST l, r) + Zweck: Lexikographischer Vergleich von 'l' und 'r' auf Gleichheit. + +LEXGREATER + BOOL OP LEXGREATER (TEXT CONST l, r) + Zweck: Lexikographischer Vergleich von 'l' und 'r' auf "Grösser". + +LEXGREATEREQUAL + BOOL OP LEXGREATEREQUAL (TEXT CONST l, r) + Zweck: Lexikographischer Vergleich von 'l' und 'r' auf "Grösser Gleich". + + + +4. Der 'reporter' + +Das Programm 'reporter' dient zur Fehlersuche und/oder Lokalisierung von +besonders häufig durchlaufenen Programmteilen. Zu diesem Zweck werden in ein +Programm Prozeduraufrufe eingefügt, die veranlassen, daß bestimmte Informa- +tionen (normalerweise Ablaufinformationen) in eine Datei (die TRACE-Datei) +geschrieben werden. + +'reporter' ermöglicht + +a) Ablaufinformationen ("trace"); +b) Häufigkeitszählung ("frequency count"); +c) Programmunterbrechung bei Nichterfüllung einer Bedingung ("assertion"). + + + +Installation von 'reporter' + +Das Programm befindet sich in der Datei 'reporter' und kann wie üblich in- +sertiert werden. Jedoch muß es mit 'check off' übersetzt werden, damit keine +Zeilennummern für 'reporter' generiert werden. Dies ist notwendig, damit die +Zeilennummern des zu testenden Programms nicht mit den Zeilennummern des +Programms 'reporter' verwechselt werden können. Beispiel: + + check off; insert ("reporter"); check on + + + +Vorbereitungen + +Mit dem Kommando + + generate reports ("testdatei") + +werden die oben erwähnten Prozeduraufrufe ('report') in das zu testende +Programm, welches in der Datei 'testdatei' steht, geschrieben. Die Prozedur- +aufrufe werden nach jedem Prozedur-, Operator- oder Refinement-Kopf +eingefügt und erhalten den entsprechenden Namen als Parameter. Diese +Prozeduraufrufe werden gekennzeichnet, damit sie von der Prozedur + + eliminate reports ("testdatei") + +automatisch wieder entfernt werden können. Beispiel (für die eingefügten +Prozeduraufrufe): + + ... + PROC beispiel (INT CONST mist): + ##report ("beispiel");## + ... + + + +Automatische Ablaufinformationen + +Ist ein Programm mit 'generate reports' mit 'report'-Aufrufen versehen +worden, kann es wie gewohnt übersetzt werden. Wird das Programm vom ELAN- +Compiler korrekt übersetzt und dann gestartet, wird bei jedem Antreffen +eines 'report'-Aufrufs der Parameter (Name der Prozedur, Operator oder +Refinement) in eine Datei, die TRACE-Datei geschrieben. Die TRACE-Datei wird +beim Programmlauf automatisch von 'reporter' unter dem Namen 'TRACE' einge- +richtet. + +Mit Hilfe dieser Datei kann der Programmablauf verfolgt werden. Es ist damit +auch möglich festzustellen, wo eine "Endlos-Rekursion" auftritt. Die Ablauf- +informationen bestehen nur aus den Namen der angetroffenen Prozeduren und +Refinements. Trotzdem können die Anzahl der Informationen sehr umfangreich +werden. Deshalb gibt es die Möglichkeit, die Erzeugung der Ablaufinforma- +tionen ab- bzw. wieder anzuschalten. Dazu gibt es die Möglichkeit, in das zu +testende Programm die Prozeduren + + report on + report off + +einzufügen und das zu testende Programm mit diesen Prozeduraufrufen (erneut) +zu übersetzen. + + + +Benutzereigene Ablaufinformationen + +Zusätzlich zu den von 'generate reports' eingefügten 'report'-Aufrufen kann +ein Benutzer eigene Aufrufe an geeigneten Stellen in ein Programm schreiben. +Dafür werden weitere 'report'-Prozeduren zur Verfügung gestellt, die als +ersten Parameter ein TEXT-Objekt (meist Name des Objekts oder der Ausdruck +selbst) und als zweiten ein INT/REAL/TEXT/ BOOL-Objekt (der zu überprüfende +Wert oder Ausdruck) enthalten. Beispiel: + + ... + PROC beispiel (INT CONST mist): + ##report ("beispiel");## (* automatisch eingefuegte *) + INT VAR mist :: ...; ... + ##report ("mist:", mist);## (* vom Benutzer per Hand eingefuegt *) + ... + +Folgende 'report'-Routinen stehen zur Verfügung, damit man sie "von Hand" in +ein zu testendes Programm einfügen kann: + + PROC report on + PROC report off + PROC report (TEXT CONST message) + PROC report (TEXT CONST message, INT CONST value) + PROC report (TEXT CONST message, REAL CONST value) + PROC report (TEXT CONST message, TEXT CONST value) + PROC report (TEXT CONST message, BOOL CONST value) + +Wichtig: Hier - wie bei allen anderen "von Hand eingefügten" Aufrufen - +sollte ein Nutzer sich an die Konvention halten, diese in "##" einzuklammern. +Mit 'eliminate reports' werden diese Einfügungen automatisch entfernt. +Sollen diese Aufrufe aber immer im Programm erhalten bleiben (jedoch nicht +wirksam sein), sollten sie + +a) vor 'generate reports'-Aufruf mit jeweils '###' eingefaßt werden. + Beispiel: + ### report ("...") ### + So steht das 'report'-Statement in einem Kommentar. 'generate reports' + wandelt '###' --> '####' um, so daß ein solches Statement wirksam wird. + 'eliminate reports' wandelt ein '####' --> '###' zurück. + +b) nach 'generate reports' in '####' eingefaßt werden. + + + +Häufigkeitszählung + +Eine Häufigkeitszählung erhält man, in dem man in das zu testende Programm +die Aufrufe + + count on + count off + +einfügt. Ist die Häufigkeitszählung eingeschaltet, merkt sich 'reporter' die +Anzahl der Durchläufe für jede Prozedur bzw. Refinement. Mit der Prozedur + + generate counts ("zu testende datei") + +werden die vermerkten Häufigkeiten in das zu testende Programm direkt einge- +fügt. Die Häufigkeiten werden wie oben beschrieben gekennzeichnet, so daß sie +mit 'eliminate reports' entfernt werden können. + + + +Assertions + +Zusätzlich zu den oben erwähnten Möglichkeiten bietet 'reporter' noch die +Prozedur + + assert + +an. Diese Prozedur kann von einem Programmierer an einer Stelle in das zu +testende Programm eingefügt werden, an der bestimmte Bedingungen erfüllt sein +müssen. Die Prozedur 'assert' steht in zwei Formen zur Verfügung: + + PROC assert (BOOL CONST zusicherung) + PROC assert (TEXT CONST message, BOOL CONST zusicherung) + +Ist der Wert von 'zusicherung' nicht TRUE, wird der Programmlauf abgebrochen. + + + +'reporter'-Kommandos + +count on + PROC count on + Zweck: Schaltet die Häufigkeitszählung ein. + +count off + PROC count off + Zweck: Schaltet die Häufigkeitszählung aus. + +eliminate reports + PROC eliminate reports (TEXT CONST datei) + Zweck: Entfernt gekennzeichnete 'report'-Aufrufe aus der Datei 'datei'. + +generate reports + PROC generate reports (TEXT CONST datei) + Zweck: Fügt 'report'-Aufrufe in die Datei 'datei' ein und kennzeichnet + diese mit '##'. + +report on + PROC report on + Zweck: Schaltet die Ablaufinformationen in die Datei 'TRACE' ein. + +report off + PROC report off + Zweck: Schaltet die Ablaufinformationen wieder aus. + +generate counts + PROC generate counts (TEXT CONST datei) + Zweck: Bringt die Häufigkeitszählung (wie oft eine Prozedur oder Refine- + ment durchlaufen wurde) in die Programmdatei 'datei'. Mit + 'eliminate reports' werden diese wieder automatisch entfernt. + +assert + PROC assert (TEXT CONST message, BOOL CONST value) + Zweck: Schreibt 'message' und den Wert von 'value' in die TRACE-Datei. + Ist 'value' FALSE, wird angefragt, ob das Programm fortgesetzt + werden soll. + + + +5. Referencer + +Das Programm 'referencer' erstellt aus einem (syntaktisch korrektem) ELAN- +Programm eine Liste, in der jedes Auftreten eines Objekts mit der betref- +fenden Zeilennummer verzeichnet ist. + + 'referencer' wird durch + + referencer ("ref datei", "referenz liste") + +aufgerufen, wobei die Datei 'referenz liste' nicht existieren darf. +'referenz liste' enthält nach Ablauf des Programms die gewünschte Liste, die +sogenannte Referenzliste. + +Achtung: 'referencer' arbeitet ausschließlich mit Namen und verarbeitet nur +wenige syntaktische Konstrukte. Darum ist es nur erlaubt, ein PACKET auf +einmal von 'referencer' verarbeiten zu lassen. Verarbeitet man mehrere +PACKETs auf einmal, kann es geschehen, daß gleichnamige Objekte in unter- +schiedlichen Paketen zu Warnungen (vergl. die unten beschriebenen Überprü- +fungen) führen. + +In der Referenzliste sind + +- alle Objekte mit ihrem Namen (in der Reihenfolge ihres Auftretens im + Programm) + +- alle Zeilennummern, in der das Objekt angesprochen wird + +- die Zeilennummern, in der das Objekt deklariert wurde ('L' für ein lokales + und 'G' für ein globales Objekt, 'R' für ein Refinement) + +verzeichnet. + +Die Referenzliste kann u.a. dazu dienen, zu kontrollieren, ob und wie (bzw. +wo) ein Objekt angesprochen wird. Dies lohnt sich selbstverständlich nur bei +etwas umfangreicheren Programmen (bei "Mini"-Programmen kann man dies sofort +sehen). + +Bei der Erstellung der Referenzliste nimmt das Programm 'referencer' gleich- +zeitig einige Überprüfungen vor, die helfen können, ein Programm zu ver- +bessern: + +1. Warnung bei mehrzeiligen Kommentaren. + +2. Überdeckungsfehler. Wird ein Objekt global (auf PACKET-Ebene) und noch- + mals lokal in einer Prozedur deklariert, ist das globale Objekt nicht mehr + ansprechbar. Überdeckungen sind nach der gültigen Sprachdefinition z.Zt. + noch erlaubt, werden aber bei einer Revision des Sprachstandards verboten + sein. + +3. Mehrmaliges Einsetzen von Refinements. Wird ein Refinement mehrmals einge- + setzt (das ist völlig legal), sollte man überlegen, ob sich dieses Refine- + ment nicht zu einer Prozedur umgestalten läßt. + +4. Nicht angewandte Refinements. Wird ein Refinement zwar deklariert, aber + nicht "aufgerufen", erfolgt eine Warnung. + +5. Nicht angesprochene Daten-Objekte. Werden Daten-Objekte zwar deklariert, + aber im folgenden nicht angesprochen, wird eine Warnung ausgegeben. + Hinweis: Alle Objekte, die nur wenig angesprochen werden, also nur wenige + Zeilennummern in der Referenzliste besitzen, sind verdächtig (Ausnahmen: + importierte Prozeduren, LET-Objekte u.a.m.). + + + +'referencer'-Kommandos + +referencer + PROC referencer (TEXT CONST check file, dump file) + Zweck: Überprüft 'check file'. In 'dump file' steht nach Abschluß die + Referenzliste. + + + +6. Notizen (Notizbuch, Fehlerprotokoll) + +Das Notizbuch erlaubt es u.a., Fehlermeldungen zwischenzeitig zu speichern +und am Ende einer Verarbeitung die Fehlermeldungen zusammen mit dem bear- +beiteten Text im Paralleleditor anzuzeigen. + +Das Notizbuch wird eingesetzt, wenn Texte bearbeitet werden, die gewissen +Regeln entsprechen müssen (Beispiele: ELAN-Compiler, Textkosmetik usw.). In +solchen Fällen ist es nützlich, die Fehlermeldungen zwischenzeitig zu +speichern und erst am Ende einer Verarbeitung gesammelt dem Benutzer zusam- +men mit dem Quelltext anzuzeigen. Diese Aufgaben übernimmt das Notizbuch. +Mit der Prozedur + + note + +kann eine Meldung im Notizbuch gespeichert werden. Mit + + note line + +wird der Beginn einer neuen Zeile im Notizbuch signalisiert. Das bedeutet, +daß ein Programmierer für alle Zeilenvorschübe in der Fehlermeldungsdatei mit +dieser Prozedur zu sorgen hat. + +Mit der Informationsprozedur + + anything noted + +kann man am Ende einer Verarbeitung abfragen, ob Fehlermeldungen gespeichert +wurden. Ist das der Fall, kann man den Paralleleditor aufrufen: + + note edit + +In der oberen Hälfte werden die Fehlermeldungen dargestellt, in der unteren +den zu bearbeitenden Text. Beispiel: + + PROC verarbeite (TEXT CONST datei): + FILE VAR f :: sequential file (input, datei); + verarbeitung; + ende behandlung. + + verarbeitung: + ... + note (fehlermeldung); + note line. + + ende behandlung: + IF anything noted + THEN note edit (f) + FI + END PROC verarbeite + + + +Notizbuch-Kommandos + +anything noted + BOOL PROC anything noted + Zweck: Informationsprozedur, ob etwas in das Notizbuch geschrieben wurde. + +note edit + PROC note edit + Zweck Bewirkt das Anzeigen des Notizbuchs auf vollem Bildschirm. + + PROC note edit (FILE VAR f) + Zweck: Anzeigen des Notizbuchs und der Datei 'f' durch den Parallel- + editor. + +note file + FILE PROC note file + Zweck: Assoziierungsprozedur. Liefert das Notizbuch. + +note line + PROC note line + Zweck: Zeilenvorschub im Notizbuch. + +note + PROC note (TEXT CONST meldung) + Zweck: Schreibt 'meldung' in das Notizbuch. + + PROC note (INT CONST zahl) + Zweck: Schreibt 'zahl' als TEXT in das Notizbuch (analog 'put'). + + + +7. Sortier-Programme + +Es stehen zwei verschiedene Sortier-Programme zur Verfügung: 'sort' +(Sortierung nach ASCII-Reihenfolge) und 'lex sort' (Sortierung nach +deutschem Alphabet). + +Das Kommando + + sort ("datei") + +sortiert 'datei' zeilenweise. Beispiel: + + Eingabe-Datei: + Berta ist eine Frau. + Adam ist ein Mann. + ... + Sortierte Datei: + Adam ist ein Mann. + Berta ist eine Frau. + ... + +Dabei werden die Zeilen-Anfänge solange zeichenweise miteinander verglichen, +bis ein Unterschied auftritt und dann ggf. umgeordnet. Werden zwei ungleich +lange Zeilen (Anzahl Zeichen/Zeile) miteinander verglichen, dann kann man +sich die kürzere Zeile mit Leerzeichen auf die Länge der längeren Zeile +verlängert denken. + +Die Reihenfolge, in der die Zeilen sortiert werden, erfolgt nach dem ASCII- +Zeichensatz in aufsteigender Reihenfolge (vergl. TEIL 3; EUMEL-Zeichencode): + + Leerzeichen + einige Sonderzeichen + Ziffern + einige Sonderzeichen + Große Buchstaben + einige Sonderzeichen + kleine Buchstaben + einige Sonderzeichen + Umlaute und ß + +Das bedeutet, daß z.B. folgendermaßen sortiert wird: + + Adam + Ball + Zuruf + aber das ist ein Satz + niemals + Überlauf + +Um zu erreichen, daß große und kleine Buchstaben gleichwertig behandelt +werden, kann man das Kommando + + lex sort ("datei") + +geben. In diesem Fall würde die sortierte Datei folgendermaßen aussehen: + + aber das ist ein Satz + Adam + Ball + niemals + Überlauf + Zuruf + +Man beachte, daß der Umlaut 'Ü' wie 'Ue' behandelt wird (für die restlichen +Umlaute gilt eine analoge Behandlung; ebenso wird 'ß' wie 'ss' behandelt). +Weiterhin werden alle Sonderzeichen bei der Sortierreihenfolge ignoriert. + + + +Sortier-Kommandos + +sort + PROC sort (TEXT CONST datei) + Zweck: Die Prozedur 'sort' sortiert die Datei 'datei' zeilenweise. Die + Sortierung erfolgt nach der Ordnung, die der EUMEL-Zeichencode + vorschreibt. Beispielsweise werden Zeilen ("Sätze"), die mit + Ziffern beginnen, vor Sätzen, die mit Buchstaben anfangen, ein- + geordnet. Sätze, die mit großen Buchstaben beginnen, werden vor + Sätzen mit kleinen Buchstaben einsortiert. Weiterhin werden die + Umlaute und das "ß" nach allen anderen Buchstaben eingeordnet. + + PROC sort (TEXT CONST datei, INT CONST anfang) + Zweck: Sortiert eine Datei wie obige Prozedur, jedoch wird bei der + Sortierung nicht der Anfang eines Satzes beachtet, sondern die + Position 'anfang'. + +lex sort + PROC lex sort (TEXT CONST datei) + Zweck: Wie 'sort', jedoch nach (deutscher) lexikographischer Reihen- + folge nach DIN 5007. Bei den Vergleichen werden die Operatoren + LEXEQUAL, LEXGREATER, LEXGREATEREQUAL (vergl. TEIL 11 des + Benutzerhandbuchs) verwandt. Anmerkung: 'lex sort' ist um + einiges langsamer als 'sort'. + + PROC lex sort (TEXT CONST datei, INT CONST anfang) + Zweck: Wie 'lex sort', jedoch wird bei der Sortierung bei 'anfang' + jeder Zeile begonnen. + + + +8. Rechnen im Editor: TeCal + +Das Programm TeCal (Abkürzung für "Text Calculator") ermöglicht das einfache +Rechnen im EUMEL-Editor. + +Das Programm TeCal ermöglicht einfache Rechnungen (ähnlich wie mit einem +Taschenrechner) unter der Benutzung des Editors. Gleichzeitig stehen dem +Benutzer aber alle Fähigkeiten des Editors zur Verfügung. TeCal ermöglicht +Rechnungen auf einfache Weise zu erstellen oder Tabellenspalten zu berechnen. + +TeCal wird aus dem Editor heraus durch 'ESC t' oder durch das Editor- +Kommando + + tecal + +aktiviert. (Anmerkung: TeCal ist nicht standardmäßig insertiert). Dadurch +wird in der untersten Zeile des Bildschirms eine Informationszeile aufgebaut, +in der die (Zwischen-) Ergebnisse einer Rechnung zur Kontrolle festgehalten +werden. + +Merke: TeCal ermöglicht einfache Rechnungen im EUMEL-Editor. + + + +Ein einfaches Beispiel + +Angenommen, Prokurist Meier der Firma 'Software Experts' muß eine Rechnung +schreiben. Er schreibt u.a.: + + ... + Wir berechnen Ihnen + + 1 Manual 'Software Auswahl leicht gemacht' 112.30 DM + 1 Manual 'Ohne Fehler programmieren' 300.- + + Summe + +Nun kann er die TeCal-Funktionen durch + + ESC t + +zuschalten. (Natürlich kann TeCal auch schon während des Schreibens einge- +schaltet sein, das Editorfenster ist dann nur um eine Zeile (nämlich die +TeCal-Informationszeile) kürzer. Zuerst löscht Prokurist Meier eventuell +vorhandene Zwischenergebnisse von TeCal (TeCal vergißt eine angefangene +Rechnung durch Abschalten nicht!) mit + + ESC C + +Das funktioniert wie eine CLEAR-Taste bei einem Taschenrechner, löscht also +ggf. vorhandene Werte. In der Informationszeile (die letzte Zeile des Bild- +schirms) erscheint darum als Wert '0.0'. + +Nun "fährt" er mit dem Cursor auf den ersten Wert ('112.30'). Dabei ist es +belanglos, welche Ziffer er "trifft". Dann betätigt er + + ESC L + +(für Lesen). Damit erscheint dieser Wert in der Informationszeile. Durch +'ESC L' wird versucht, einen Wert von der Stelle aus der Datei zu lesen, die +durch den Cursor angezeigt wird. (Gelingt dies nicht, erfolgt in der +obersten Zeile eine Fehlermeldung). Dann betätigt er + + ESC + + +weil er ja die zwei Werte addieren will. Das Zwischenergebnis in der TeCal- +Informationszeile bleibt dadurch unverändert. Jetzt fährt er auf den zweiten +Wert und betätigt erneut 'ESC L'. Nun erscheint der zweite Wert in der An- +zeige. Um das Ergebnis der Rechnung zu erfahren, betätigt er + + ESC = + +Die Summe der zwei Zahlen erscheint nun in der Informationszeile. Nun fährt +er mit dem Cursor auf die Stelle, an der die Summe stehen soll und betätigt +hier + + ESC S + +(für Schreiben). Damit erscheint die eben errechnete Summe (412.30) an dieser +Stelle der Datei. + +Man bedient TeCal also wie einen Taschenrechner. Man muß allerdings, um die +Rechentasten zu bedienen, ESC zuvor drücken. Dies ist notwendig, um die +"normalen" Tasten von den TeCal-Tasten zu unterscheiden. + +Merke: Mit einigen einfachen Tastendrücken können Berechnungen vorgenommen +werden. 'ESC L' liest einen Wert von der aktuellen Cursor-Position, 'ESC S' +schreibt den angezeigten TeCal-Wert an die aktuelle Cursor-Position. 'ESC C' +löscht alle Werte im TeCal-Rechner. + + + +Einige weitere einfache Rechenoperationen + +In diesem Abschnitt werden weitere einfache Operationen von TeCal be- +schrieben. + +Natürlich kann man mit TeCal nicht nur Addieren. Die folgenden Operationen +laufen analog 'ESC +': + + ESC - (Subtrahieren) + ESC * (Multiplizieren) + ESC / (Dividieren) + +Beispiel: + + ... + Wir berechnen Ihnen + + Artikelbezeichnung Anzahl Einzelpreis Summe + + Schraube, verdreht 27 1.05 28.35 + + Gesamt 28.35 + +Dazu drückt Prokurist Meier folgende Tasten: + + Cursor auf Taste TeCal-Anzeige + + 27 ESC C 0.00 + unverändert ESC L 27.00 + unverändert ESC * 27.00 + 1.05 ESC L 1.05 + unverändert ESC = 28.35 + unter Summe ESC S 28.35 + in Gesamtzeile ESC S 28.35 + +Wie wir sehen, kann Prokurist Meier jederzeit seine Eingaben kontrollieren +mit Hilfe der TeCal-Informationszeile. + +Anmerkung: + +'ESC S' schreibt den aktuellen Wert wie der Dezimal-Tabulator des Editors +(vergleiche Kapitel Editor). Die Stelle, an der der Cursor steht, wird beim +Schreiben die letzte Stelle vor dem Dezimalpunkt. Ziffern vor dem Dezimal- +punkt werden also nach links, Ziffern nach dem Dezimalpunkt nach rechts ge- +schrieben. + +Merke: ESC mit den Tasten '-', '+', '*' und '/' haben die gewohnte Wirkung. + + + +Die Verwendung von Klammern + +TeCal erlaubt bei Rechnungen die Eingabe von Klammern. + +Beispiel (wir haben hier die Taste ESC fortgelassen): + + 2 * (3 + 5) = 16.00 + +Merke: Klammern können bei Rechnungen beliebig verwendet werden. + + + +Der Prozent-Operator + +Angenommen, wir wollen 14 Prozent von 200 DM errechnen. Dann können wir wie +gewohnt verfahren (für bessere Lesbarkeit zeigen wir hier für 'ESC L' den +jeweiligen Wert): + + 200 ESC % ESC = + +Der Prozent-Operator berechnet immer einen eingestellten Prozentsatz von dem +gerade angezeigten Zwischenergebnis. Der eingestellte Prozentsatz wird in der +Informationszeile angezeigt. Er läßt sich mit Hilfe des Kommandos + + prozentsatz ('prozentzahl') + +verändern. + +Was müssen wir machen, um die 14 Prozent von 200 auf den Wert von 200 zu +addieren? Ganz einfach: + + 200 ESC + ESC % ESC = + +Wie wir solche Tastensequenzen einfacher erledigen können, zeigen wir in +einem späteren Abschnitt. + +Merke: Der Prozent-Operator berechnet immer den eingestellten Prozentanteil +vom angezeigten Wert. + + + +Spaltenweise summieren + +Da es beim Schreiben von Rechnungen o.ä. häufig vorkommt, daß eine ganze +Zahlenkolonne addiert werden soll, besitzt TeCal eine Sonderfunktion, die es +dem Benutzer erspart, mit dem Cursor auf jeden einzelnen Wert zu fahren und +'ESC L' sowie 'ESC +' zu drücken. Durch + + ESC V + +addiert TeCal zu der Zahl, auf der der Cursor steht alle, die in gerader +Linie darüberstehen, solange bis eine Zeile gefunden wird, in der Text oder +andere Zeichen stehen, die nicht zu einer Zahl gehören. Leerzeichen führen +also nicht zum Abbruch der Rechnung. Nehmen wir an, Prokurist Meier hätte +seine Rechnung soweit fertig : + + ... + Wir berechnen Ihnen + + Artikelbezeichnung Anzahl Einzelpreis Summe + + Schraube, verdreht 27 1.05 28.35 + Nagel, m. Kopf 33 0.50 16.50 + Hammer, Spezialausführung m. + Eichenholzgriff 1 44.70 44.70 + -------- + +Um nun die Gesamtsumme zu berechnen fährt er einfach mit dem Cursor auf die +unterste Zahl (44.70) und betätigt ESC V. In der Anzeige steht direkt die +Gesamtsumme, die dann mit ESC S unter dem Strich eingetragen werden kann. + +Merke: Zahlenkolonnen können mit ESC V summiert werden. + + + +Direkte Eingabe + +Es kann ein Wert direkt in die Berechnung eingehen, ohne daß er vorher in +der Datei stehen muß. + +Durch das Betätigen von + + ESC E + +erscheint 'gib wert :' in der TeCal-Informationszeile. Nun kann ein Wert +(wie im Editor) eingegeben werden, zugelassen ist auch ein ganzer Ausdruck +wie z.B. + + (3.00 DM + 5.00 DM) * 365 Tage - 2,00 DM * 12 Monate + +Dabei sind auch Buchstaben erlaubt, die aber überlesen werden. Betätigt man +RETURN, wird der Ausdruck ausgewertet und der Wert in die Anzeige über- +nommen. Für das oben gezeigte Beispiel steht die Anzeige also anschließend +auf 2896. Auf diese Weise kann man auch einfach Zwischenrechnungen machen, +ohne daß die verwendeten Zahlen irgendwo in der Datei stehen. Das Ergebnis +kann man dann weiter verrechnen, als wäre es mit ESC L aus der Datei gelesen +worden. Natürlich kann man es auch direkt mit ESC S in die Datei schreiben. + +Merke: Mit ESC E wird ein Wert direkt in TeCal aufgenommen. Durch Eingabe +eines ganzen Rechenausdrucks lassen sich leicht auch Rechnungen durchführen, +ohne daß die Zahlen in einer Datei stehen. + + + +TeCal und Lernen im Editor + +Bei sich wiederholenden Rechnungen ist es sinnvoll, Rechenoperationen "zu +lernen" und auf eine Taste zu legen. + +Angenommen, Prokurist Meier hat häufig Rechnungen zu schreiben und muß des +öfteren die Mehrwertsteuer und Bruttopreis unter die jeweiligen Nettopreise +schreiben. Zu diesem Zweck kann er die "Lern"-Einrichtung des Editors +benutzen (vergl. EUMEL-Benutzerhandbuch: Editor). Beim Lernen "merkt" sich +der Editor jeden Tastendruck (also auch TeCal-Operationen). Die gelernten +Tasten kann man anschließend mit einem Tastendruck abrufen. Meier kann die +Operationen wie folgt vom Editor lernen lassen: + +Er fährt mit dem Cursor zuerst auf den Nettopreis, von der die Mehrwertsteuer +errechnet werden soll. Dann betätigt er ESC HOP (es erscheint LEARN in der +Kopfzeile des Editors). Dann schreibt er die TeCal-Operationen wie oben +gezeigt (in diesem Falle also ESC L ESC + ESC % ; dann steht der Mehrwert- +steuerbetrag in der Anzeige. Er fährt also mit dem Cursor eine Zeile tiefer +und betätigt ESC S, dann geht er noch eine Zeile tiefer und gibt ESC = und +wiederum ESC S um den Bruttobetrag zu berechnen und zu schreiben. Mit dem +abschließenden ESC HOP und einer weiteren Taste (sagen wir mal 'm' als +Abkürzung für Mehrwert) beendet er das Lernen. Nun kann er jederzeit die +Mehrwertsteuer und Bruttobetrag unter einen gegebenen Nettobetrag schreiben, +indem er ESC m betätigt. + +Praktischer Tip: + +Tabulator-Bewegungen kann man ebenfalls lernen. So ist es z.B. möglich, die +Berechnung von Spalten- oder Reihensummen zu erlernen, indem man mit +TAB jeweils zu dem nächsten Wert springt. + +Merke: Es können beliebige Rechnungen erlernt und auf eine Taste gelegt +werden. Die gelernten Rechnungen können mit Hilfe einer Taste abgerufen +werden. + + + +Benutzung des Merkregisters + +Mit + + ESC M + +(für Merken) kann man ein gerade angezeigtes (Zwischen-) Ergebnis im +Speicher aufbewahren, um es später an anderer Stelle wieder in die Rechnung +einzubeziehen. Das geschieht, in dem man dann statt eine Zahl mit ESC L +einzulesen + + ESC K + +(für Konstante) eingibt. Dadurch wird die Zahl aus dem Merkregister wieder +in die Anzeige übertragen, so daß man damit weiterrechnen kann. + +Merke: Man kann Zahlen mit ESC M abspeichern und mit ESC K wiederholen. + + + +Auskunft über TeCal-Funktionen + +Wenn Sie beim Arbeiten mit TeCal noch nicht so sicher sind oder eine Funktion +benutzen möchten, die Sie sonst nur selten verwenden und deren genaue +Wirkung sie vielleicht wieder vergessen haben, so hilft Ihnen + + ESC ? + +weiter. Nach betätigen dieser Tasten meldet sich die TeCal Auskunft mit +Funktionstaste drücken oder <?>. Dann geben Sie das Funktionssymbol ein, das +Sie erklärt bekommen möchten. Geben Sie z.B. ein C ein, wenn Sie die Wirkung +von ESC C wissen möchten. Daraufhin wird ein Text gezeigt, in dem die +entsprechende Auskunft steht. In diesem Text können Sie sich wie im Editor +bewegen. Wenn Sie den Text gelesen haben, können Sie das Fenster wieder mit +ESC Q verlassen. Dadurch wird der alte Zustand vor der Auskunftsfunktion +wiederhergestellt. Durch + + ESC ? ? + +erklärt sich die Auskunft selbst. Sie bekommen dort unter anderem die Liste +aller TeCal-Funktionen gezeigt. + +Merke: Mit ESC ? erhält man Auskünfte über TeCal-Funktionen. + + + +Einstellen von Nachkommastellen + +Durch das Kommando + + kommastellen ('zahl') + +wird die Anzahl der angezeigten Nachkommastellen (0-9) eingestellt. Genau so +viele Nachkommastellen werden auch bei ESC S oder ESC T geschrieben (intern +wird aber jeweils mit höchster Genauigkeit gerechnet). Mit + + ESC R + +kann man ein angezeigtes Zwischenergebnis auch intern auf die angezeigte Zahl +von Nachkommastellen runden. Beispiel: + + ESC ( 1 ESC / 3 ESC ) ESC * 2 ESC= + +führt zur Anzeige von 0.67 (bei zwei eingestellten Nachkommastellen). Gibt +man jetzt (aber nach ESC ) noch ESC R ein, so wird das Zwischenergebnis von +1/3 auf 0.33 gerundet, so daß das Endergebnis 0.66 beträgt. + +Merke: Im Kommandomodus kann man durch das Kommando 'kommastellen' die An- +zahl der Nachkommastellen einstellen. + diff --git a/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil12 b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil12 new file mode 100644 index 0000000..ba5d0c6 --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil12 @@ -0,0 +1,234 @@ + EUMEL-Benutzerhandbuch + + TEIL 12: SPOOLER / OPERATOR + +1. Spooler-Übersicht + +Ein "Spooler" ist eine Warteschlange von Datenräumen#ie# (Dateien) vor einem +"Worker": + + +------------+ +------------+ + -----> | | | | + -----> | spooler | ------------> | worker | + -----> | | | | + +------------+ +------------+ + +Der Spooler puffert Dateien, die von beliebigen Tasks geschickt werden kön- +nen, in seiner Warteschlange und gibt sie der Reihe nach dem Worker zur +eigentlichen Verarbeitung. Ein typischer Einsatzfall (aber nicht der einzige) +für ein solches System ist der EUMEL-Drucker in Multi-User-Systemen. Unab- +hängig davon, ob der Drucker gerade aktiv ist und wieviele Dateien noch auf +den Ausdruck warten, kann man seine Datei dem Druckspooler schicken und +sofort danach weiterarbeiten. + +Da jeder Spooler und auch jeder Worker eine eigene Task ist, können Spooler +nur im Multi-User-Systemen eingesetzt werden. + +Im folgenden wird nur die anwenderseitige Schnittstelle eines Spoolers be- +schrieben. + +Merke: Ein Spooler puffert Dateien für einen Worker. + + + +2. Die Benutzung eines Spoolers + +Jeder Spooler im System ist eine eigene Task und hat dementsprechend einen +Tasknamen, über den er angesprochen werden kann. So heißt der Druckspooler +beispielsweise " PRINTER". + +Jede Task kann jedem Spooler durch Aufruf von 'save' eine Datei schicken. +Beispiel: + + save ("datei name", task ("spooler name")) + +(Vergl. auch TEIL 7). In der Regel ist ein SPOOLER für (mindestens) einen +Drucker in einem EUMEL-System vorhanden. Dieser kann über den internen +Task-Bezeichner 'print' angesprochen werden. Beispiel: + + save ("datei name", printer) + +Eine so übergebene Datei kann man durch + + erase ("datei name", printer) + +aus der Warteschlange löschen. (Natürlich nur solange sie sich noch in dieser +Warteschlange befindet). Dabei kann man nur auf solche Dateien zugreifen, die +aus der eigenen Task stammen. Durch Aufruf von + + list (printer) + +wird die aktuelle Warteschlange des angegebenen Spoolers auf dem Terminal +angezeigt, so daß man sich über die Anzahl der Dateien und die Position der +eigenen Dateien im Spooler informieren kann. + +Aufbauend auf diesen allgemeinen Kommandos können weitere für spezielle +Spooler programmiert werden. So gibt es für den Spooler 'printer' die Proze- +duren + + print und print ("datei name") + +die im wesentlichen auf + + save ("datei name", printer) + +zurückgeführt werden. + +Merke: Einem SPOOLER kann man eine (oder mehrere) Dateien mit 'save' +schicken. Mit 'list' kann man sich über die Dateien im SPOOLER informieren. +Einem Drucker-SPOOLER übergibt man mit 'print' eine Datei. + + + +3. Privilegierte Spooler-Kommandos + +Gewisse Kommandos können einer #ib#Spooler-Task#ie# direkt im Dialog (ähn- +lich wie im 'maintenance'-Zustand eines globalen Datei-Managers) gegeben +werden. Dazu muß der Spooler mit 'continue' an ein Terminal geholt werden. +Ist der SPOOLER durch ein Paßwort, so sind diese privilegierten Kommandos +nicht für jeden Benutzer zugänglich. + +break + PROC break + Zweck: Beendet den Dialogzustand des Spoolers. Der Spooler koppelt sich + vom Terminal ab und geht in seinen normalen Verarbeitungsmodus + über. + +first + PROC first + Zweck: Vorziehen einer Datei in der Warteschlange auf den ersten Platz. + Alle Dateien von der zweiten an werden im Dialog zum Vorziehen + angeboten. + +start + PROC start + Zweck: Die (vorher gestoppte) Worker-Task wird neu kreiert und ge- + startet. + +stop + PROC stop + Zweck: Die Worker-Task wird abgebrochen und gelöscht. Damit wird auch + ein von ihr belegetes Terminal wieder frei. + + +Hinweis: Die Kommandos 'start/stop' sind gut dazu geeignet, die Verarbeitung + einer Datei durch einen Worker (z.B. Druckoutput) abzubrechen, bei + Hardwareeingriffen zu stoppen oder Worker (wie z.B. Drucker) nur + zeitweise zu betreiben. + +Hinweis: Wenn der Worker mit Verzögerung abgebrochen werden soll, kann man + den Spooler an ein Terminal holen und dann so lange mit der Eingabe + von 'stop' warten, bis der Worker mit der gerade bearbeiteten Datei + fertig ist. Der Spooler kann in dieser Zeit nicht von anderen Tasks + oder dem Worker angesprochen werden. + + + +4. Der OPERATOR + +Im folgenden Abschnitt wird die standardmäßig implementierte Task OPERATOR +erläutert. Erweiterungsmöglichkeiten sind im Systemhandbuch beschrieben. Dem +OPERATOR stehen gewisse privilegierte Kommandos zur Verfügung. Diese Kom- +mandos (System abschalten, fremde Tasks löschen u.a) werden vom "normalen" +Benutzer des Multi-User-Systems nicht benötigt. Sie sind nur für den +"Operateur" interessant. Es empfiehlt sich, OPERATOR mit einem Paßwort zu +versehen, damit die priviligierten Kommandos nicht jedem Benutzer zur Ver- +fügung stehen. + + + +Einschalten des EUMEL-Systems + +Wie ein EUMEL-System eingeschaltet wird, kann hier nicht beschrieben werden, +weil dies abhängig von speziellen Rechnern ist (Lage des Ein/Aus-Schalters +u.a.m.). Üblicherweise liefern die Hersteller für diesen Zweck bei der Aus- +lieferung Anweisungen mit. + +Nach Einschalten des Rechnersystems befindet man sich in der Task OPERATOR. +Diese Task dient zum kontrollierten Ein- und Ausschalten des EUMEL-Systems. +Nach dem Einschalten wird man automatisch von der Task OPERATOR nach dem +aktuellen Datum und der Uhrzeit gefragt. Nach Eingabe dieser Werte erfolgt + + gib kommando : + +Der Benutzer befindet sich also in der Monitor-Ebene (vergl. dazu auch +TEIL 2). Um die Task OPERATOR vom Terminal abzukoppeln, gibt man + + break + +Nach Betätigen der SV-Taste erscheint dann + + gib supervisor kommando : + +Nun kann man mit 'begin' oder 'continue' eine neue Task einrichten oder mit +einer alten Task in der Arbeit fortfahren. + +Merke: Nach dem Einschalten gibt man das Datum und die Uhrzeit an. + Dann koppelt man die Task OPERATOR mit 'break' ab. + + + +EUMEL-System ausschalten + +Nachdem die Arbeiten in der Benutzer-Task beendet wurden, koppelt man die +Task mit + + break + +vom Terminal ab oder beendet die Task mit + + end + +Achtung: Bei 'end' werden alle Dateien der Task gelöscht. + +Nach Betätigen der SV-Taste kann nun ein Supervisor-Kommando gegeben +werden. Um das EUMEL-System kontrolliert auszuschalten, muß man die Task +OPERATOR wieder an das Terminal holen. Das erfolgt mit + + continue ("OPERATOR") + +Die OPERATOR-Task meldet sich mit + + gib kommando : + +Nun kann man das Kommando + + shutup + +geben, welches das System kontrolliert abschließt. 'shutup' garantiert, daß +alle Dateien auf dem Hintergrund des EUMEL-Systems gesichert werden. Wird +das EUMEL-System ohne 'shutup' ausgeschaltet (z.B. indem der Rechner einfach +ausgeschaltet wird), können die Informationen, die seit dem letzten Fixpunkt +(üblicherweise 15 Minuten) aufgelaufen sind, verloren sein. + +Merke: In der Task OPERATOR wird mit dem Kommando 'shutup' das EUMEL-System +kontrolliert abgeschaltet. + + + +Übersicht über die #ib#OPERATOR-Kommandos + +end + PROC end (TASK CONST task) + Zweck: Löschen der Task 'task'. Hierbei findet keine Paßwortüberprüfung + statt. Darum sollte die Task OPERATOR auch mit einem Paßwort + versehen sein, weil man vom OPERATOR jede Task löschen kann. + Beispiel: + + end (task ("hugo")) (* oder: *) + end (/"hugo") + +set date + PROC set date + Zweck: Einstellen des Datums und der Uhrzeit. Das Erfragen der Werte + erfolgt interaktiv. + +shutup + PROC shutup + Zweck: Kontrolliertes Herunterfahren des gesamten Systems. Alle Tasks + bleiben mit ihren Daten erhalten. Beim Start des Systems meldet + sich die OPERATOR-Task wieder auf dem gleichen Terminal. Das + Kommando sollte deshalb möglichst nur am Terminal 0 gegeben + werden. Nach dem Start sollte der OPERATOR mit 'break' vom + Terminal abgekoppelt werden. + diff --git a/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil2 b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil2 new file mode 100644 index 0000000..c70ddfc --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil2 @@ -0,0 +1,628 @@ + EUMEL-Benutzerhandbuch + + TEIL 2: Supervisor/Monitor + + +1. Task-Organisation + +In diesem Kapitel wird die Task-Verwaltung und der Task-Baum beschrieben. + +Alle Tasks des EUMEL-Systems werden in einen Task-Baum eingebunden. Das be- +deutet, daß die Task eines Benutzers automatisch einen "Vater" besitzt, aber +auch neue Tasks ("Söhne") erzeugen kann. In einem EUMEL-System gibt es in +der Regel zwei spezielle Tasks (#ib#UR#ie# und #ib#SUPERVISOR#ie#). Alle +anderen Tasks sind Söhne oder Enkel dieser Tasks. Zum Beispiel: + +Die mit großen Buchstaben geschriebenen Tasknamen sind "System"-Tasks; die +mit kleinen Buchstaben geschriebenen Tasknamen sind Benutzer-Tasks (dies +ist nicht zwingend, sondern Konvention). + +- SUPERVISOR: Übernimmt das Einrichten bzw. Löschen von Tasks. + +- OPERATOR: Übernimmt u.a. die Aufgaben für das Ein- bzw. Ausschalten des + EUMEL-Systems. + +- ARCHIVE: Übernimmt die Auslagerung von Dateien auf Archive. + +- UR: Ist der "Urvater" des EUMEL-Systems, enthält u.a. den + ELAN-Compiler. + +- PUBLIC: Enthält Dateien, die längerfristig gehalten werden müssen und + die alle Benutzer des Systems benötigen. + + +Der Task-Baum hat folgende Bedeutung: + +Eine Task, die sich "unter" einer anderen befindet, ist ein "Sohn" dieser +"Vater"-Task. Beispielsweise ist die Task PUBLIC ein Sohn von UR (und UR ist +somit Vater von PUBLIC). + +Die für eine Task zur Verfügung stehenden Datentypen und Operationen (d.h. +die Objekte, die aus insertierten ELAN-Paketen herausgereicht werden), sind +durch die direkte aufsteigende Linie im Task-Baum vorgegeben. Die in "Vater- +Tasks" insertierten und über die Schnittstelle herausgereichten Objekte +stehen in den "Söhnen" automatisch zur Verfügung. Beispielsweise stehen einer +Sohn-Task von 'user 1' alle insertierten Objekte aus der 'user 1'-Task zur +Verfügung (zusätzlich zu denen, die in UR und PUBLIC insertiert wurden). +Somit ist leicht möglich, unterschiedliche Sprachmengen des ELAN-Compilers +zur Verfügung zu stellen. Vergl. dazu auch das Kapitel über den ELAN- +Compiler. +Ähnliches gilt bei Dateien. So ist es erlaubt, Dateien zu direkten Vätern und +Söhnen im Taskbaum zu transportieren, aber nicht unmittelbar in "parallele" +Tasks. Man kann somit in der 'user 1'-Task Dateien von UR oder PUBLIC be- +ziehen, aber nicht von 'user 2' (da diese Task eine "parallele" Task ist). +Soll das trotzdem geschehen, so muß eine Datei erst von 'user 1' zu PUBLIC +geschickt werden und dann von 'user 2' dort abgeholt werden. Genaueres über +solche Operationen findet man im Benutzerhandbuch über die Datenräume. + +Einige Tasks sind speziell dafür eingerichtet, Dateien für mehrere Nutzer +aufzubewahren. So sind UR und PUBLIC Tasks, die Dateien verwalten, die +längerfristig gehalten werden sollen. Solche Tasks werden "Manager"-Tasks +genannt. + + +2. Supervisor und Tasks + +Eine Task ist für einen Benutzer ein "eigener Rechner", in der er Programme +bearbeiten lassen und/oder Daten aufbewahren kann, ohne von anderen Nutzern, +die gleichzeitig im System arbeiten, gestört zu werden. Der Supervisor er- +möglicht u.a. die Einrichtung, Weiterbearbeitung und Beendigung einer Task. + + +Überblick + +Eine Task ist im EUMEL-System ein selbständiger Prozeß. Zu jedem Program- +mierer an einem Terminal gehört eine damit verbundene Task. Für den Benutzer +ist diese Task sozusagen ein "eigener Rechner". In einem EUMEL-System sind +zur gleichen Zeit noch weitere Tasks vorhanden, so z.B. zum Start und Ab- +schalten des Systems (OPERATOR), zur Druckersteuerung (SPOOLER), zur Ver- +waltung längerfristig benötigter Dateien u.a.m.. + +Der Supervisor ist auf der ELAN-Ebene des EUMEL-Systems der Betriebssystem- +kern. Seine Aufgabe ist im wesentlichen die Task-Verwaltung, nämlich die Er- +richtung und das Löschen von Tasks. Im einfachsten Fall kommt ein Benutzer +des EUMEL-Systems mit dem Supervisor also nur bei den Supervisor-Kommandos +in Kontakt, die den Beginn und das Ende einer Task steuern. + +Jede Task wird in einen "Taskbaum" eingeordnet. Jede Benutzer-Task ist +"Sohn" einer bereits vorhandenen "Vater"-Task und "erbt" von dieser vorüber- +setzte Programme. Man kann Dateien zu einer Vater-Task schicken oder von +dieser empfangen. + + +Eine neue Task beginnen + +Mit dem Supervisor-Kommando 'begin' kann eine neue Task eingerichtet werden. + +Soll eine neue Arbeit im EUMEL-System begonnen werden, muß eine neue Task +eingerichtet werden. Dazu muß das Supervisor-Kommando 'begin' gegeben +werden. Jedes Supervisor-Kommando muß durch die Betätigung der SV-Taste +eingeleitet werden. Dadurch meldet sich das EUMEL-System mit + + gib supervisor kommando : + +Jetzt kann eines der Supervisor-Kommandos gegeben werden. In unserem Fall +wollen wir mit dem 'begin'-Kommando eine neue Task einrichten. Beispiel: + + begin ("rainer") + +errichtet eine neue Task in dem EUMEL-System mit dem Namen 'rainer'. Die +Task meldet sich mit + + gib kommando : + +Nun kann ein beliebiges Monitor-Kommando gegeben werden. + +Wird eine Task in der geschilderten Weise eingerichtet, ist diese Task im +Taskbaum automatisch ein "Sohn" der Task 'PUBLIC'. 'PUBLIC' ist in der Lage, +Dateien von der neuen Sohn-Task zu empfangen ('save'-Kommando) oder man kann +Dateien von 'PUBLIC' in die Sohn-Task holen ('fetch'-Kommando). Solche Tasks, +die Dateien verwalten können, werden 'manager' genannt. + +Merke: Nach dem Betätigen der SV-Taste meldet sich der Supervisor. + Mit dem 'begin'-Kommando wird eine neue Task eingerichtet. + + + +Eine Task ab- und ankoppeln + +Mit dem 'break'- und 'continue'-Kommandos können die Arbeiten in einer Task +unterbrochen und später wieder aufgenommen werden. + +Soll die Arbeit in einer Task unterbrochen werden, so kann man das (Monitor-) +Kommando + + break + +geben, welches die Task vom Benutzer-Terminal abkoppelt. Die Task wird dann +vom System als "Hintergrund-Task" geführt, bleibt also weiterhin bestehen. +Mit dem Supervisor-Kommando + + continue ("meine task") + +kann eine solche "abgekoppelte" Task wieder an ein Terminal angekoppelt und +die unterbrochenen Arbeiten weitergeführt werden. + +Mit 'break' wird eine Task unterbrochen, während durch das 'continue'-Kom- +mando die Arbeiten fortgesetzt werden können. + + + +Eine Task beenden + +Mit dem 'end'-Kommando wird eine Task beendet und gelöscht. + +Sind die Arbeiten in einer Task beendet, so sollte sie aus dem System ent- +fernt werden. Dies erfolgt mit dem Kommando + + end + +Nach einer Rückfrage des Systems wird die Task gelöscht. Beachte, daß mit dem +Löschen der Task auch alle in ihr befindlichen Dateien gelöscht werden. + +Merke: Mit dem 'end'-Kommando wird eine Task beendet und alle in ihr befind- +lichen Daten werden gelöscht. + + + +Eine Task als Sohn einer Task einrichten + +Mit dem 'begin'-Kommando ist es auch möglich, eine Task als Sohn einer be- +stimmten Task einzurichten. Damit die Vater-Task auch Dateien der einzu- +richtenden Sohn-Task verwalten kann, muß man sie vorher zu einer 'manager'- +Task machen. + +In der Regel richtet man seine Task als Sohn von PUBLIC ein. Das erfolgt +automatisch, sofern man im 'begin'-Kommando nichts anderes als den neuen +Tasknamen angibt. Manchmal ergibt sich aber die Notwendigkeit, eine Task als +Sohn einer bestimmten Task einzurichten. Gründe können dafür u.a. sein: + +- Man will eine eigene Datei-Hierarchie über mehrere Tasks einrichten. + +- Man will ein Programmsystem anderen Benutzern zur Verfügung stellen. + +Damit eine Task als Vater für andere, noch einzurichtende Task arbeiten kann, +muß man sie zuerst zu einer 'manager'-Task machen. Das erfolgt mit dem +Kommando + + global manager + +Dies Kommando muß in der Task gegeben werden, die eine Vater-Task werden +soll. Damit wird die Task befähigt, Söhne einzurichten und Dateien, die von +einem (oder mehreren) Söhnen geschickt werden, zu verwalten. + +Durch das 'global manager'-Kommando wird implizit ein 'break'-Kommando ge- +geben, so daß der Benutzer in der Supervisor-Ebene landet. Koppelt man nun +zu irgendeinem Zeitpunkt diese (zunächst potentielle) Vater-Task wieder an +('continue'-Kommando), meldet sich die Task nicht wie gewohnt mit 'gib +kommando :', sondern mit + + maintenance : + +um anzudeuten, daß es sich um eine 'manager'-Task handelt. + +Um eine Sohn-Task "unterhalb" der 'manager'-Task einzurichten, gibt man das +'begin'-Kommando, wobei man die Vater-Task mit angibt. Beispiel: + + begin ("rainer", "vatername") + +richtet eine neue Task 'rainer' ein, die als Sohn der Vater-Task 'vatername' +in den Taskbaum eingeordnet wird. + +Merke: Das Kommando 'global manager' macht eine Task zu einer 'manager'-Task. +Mit dem 'begin'-Kommando kann man auch eine Task als Sohn einer bestimmten +Task einrichten. + + + +Ein laufendes Programm unterbrechen + +Mit dem Betätigen der SV-Taste und dem Supervisor-Kommando 'halt' kann ein +Programm abgebrochen werden. + +Soll ein Programm, welches gerade ausgeführt wird, vorzeitig abgebrochen +werden, so betätigt man die SV-Taste und gibt das Supervisor-Kommando + + halt + +Anschließend kann man wieder ein Monitor-Kommando geben, weil man durch das +'halt'-Kommando automatisch wieder in seine Task gelangt. + +Merke: Mit dem 'halt'-Kommando wird ein Programm abgebrochen. + + + +Eine Task mit Paßwort schützen + +Man kann eine Task durch ein Paßwort vor unberechtigtem Zugriff schützen. + +Das Kommando + + task password + +welches nur im Monitor gegeben werden kann, sorgt dafür, daß eine Task fort- +an nur wieder mit einem 'continue'-Kommando 'betreten' werden kann, wenn man +vorher das richtige Paßwort angibt. Beispiel: + + task passwort ("mein geburtstag") + +Versucht nun ein Benutzer, die mit dem Paßwort geschützte Task mit dem +'continue'-Kommando an sein Terminal anzukoppeln, wird er zunächst nach dem +'Paßwort' gefragt. Nur unter Angabe des Paßwortes wird die Task angekoppelt. #count("1")#) + +Man sollte Paßwörter möglichst behalten! Durch Paßwörter geschützte Tasks +kann niemand - außer durch die Angabe des korrekten Paßworts - die Task +wieder ankoppeln. Hat man das Paßwort vergessen, kann man nur noch die Task +löschen. + +Damit ist gewährleistet, daß kein unberechtigter Benutzer an die Dateien und +Programme der Task gelangen kann. Es gibt jedoch noch zwei Situationen, die +einen unberechtigten Zugang zu Dateien erlauben: + +a) Dateien in die Vater-Task schicken: + Transportiert man Dateien in die Vater-Task ('save'-Kommando, vergl. auch + Teil 7: Datei-Verwaltung), können Benutzer auf diese Dateien zugreifen + (sofern sie Zugang zu dieser Task haben). Dies kann man verhindern, in dem + man ein Datei-Paßwort angibt (siehe Teil 7 für die Beschreibung dieser + Paßworte). Man beachte, daß das Paßwort für Dateien und das oben be- + schriebene Paßwort für Tasks nichts miteinander zu tun haben. + +b) Dateien werden in eine Sohn-Task geholt: + Ist die Task als Vater-Task eingerichtet (Kommando 'global manager') dann + ist es möglich, von der Sohn-Task Dateien ('fetch'-Kommando) aus der + Vater-Task zu holen, die mit einem Paßwort geschützt ist. Darum muß man + verhindern, daß Unberechtigte Söhne einer mit Paßwort geschützten Task + einrichten können. Das kann man mit dem Kommando + + begin password ("geheim") + + Wird dieses Kommando gegeben, wird man bei dem Versuch, eine Sohn-Task + einzurichten, nach einem Paßwort gefragt. Beachte, daß das 'begin- + password' nichts mit dem Task-Paßwort und Datei-Paßwort zu tun hat. + +Merke: Mit dem 'task password'-Kommando wird eine Task durch ein Paßwort +geschützt. + + + +Informations-Kommandos + +(Die Informations-Kommandos können auch vom Monitor aus gegeben werden). + +Mit der Informationsprozedur + + task status + +können Sie sich über den Zustand einer Task informieren. Beispiele: + + task status (* informiert über die eigene Task *) + task status (father) (* informiert über die Vater-Task *) + +'task status' informiert u.a. über die verbrauchte CPU-Zeit der Task, den +belegten Speicherplatz (man beachte, daß Dateien mit Vater-Tasks oder Sohn- +Tasks werden), den Kanal, an dem die Task angekoppelt ist und dem Zustand +der Task (vergl. auch 'task info'). + +Mit der Prozedur + + task info + +können Sie eine Übersicht über alle in dem System befindlichen Tasks er- +halten. +Mit dem Kommando + + storage info + +kann man erfahren, wieviel Speicherplatz auf dem EUMEL-Hintergrund (noch) +zur Verfügung steht. + +Durch einige Kommandos, die man nur vom Monitor aus geben kann, kann man +sich den Namen von Tasks liefern lassen. Die Kommandos + + myself + father + +liefern den (internen) Task-Namen. Mit dem Kommando + + name + +bekommt man den internen Tasknamen in einen Text gewandelt. Beispiel: + + put (name (myself)) + put (name (father)) + +Mit dem Kommando + + rename myself + +kann der Task-Name der Benutzer-Task geändert werden. + +Merke: Durch die Informations-Kommandos 'storage info' und 'task info' kann +man erfahren, wieviel Speicherplatz und welche Tasks in dem EUMEL-System +sind. Mit den Kommandos 'myself' und 'father' kann man mehrere Dateien auf +einmal manipulieren (vergl. Teil 7). + + + +Übersicht über Supervisor- und Task-Kommandos + +In diesem Abschnitt werden alle Supervisor- und Task-Kommandos in der ELAN- +Notation dargestellt. + +Die Supervisor-Kommandos entsprechen - wie alle anderen Kommandos im EUMEL- +System - der ELAN-Syntax (Kommando-Namen werden klein geschrieben, Parameter +in Klammern, mehrere Parameter durch Kommata getrennt, TEXT-Parameter in +Anführungstrichen usw.). Dabei ist jedoch zu beachten, daß diese Kommandos +zum Teil nur im Supervisor-Zustand (vorheriges Betätigen der SV-Taste) ge- +geben werden können. Die Kommandos 'break', 'end', 'storage info' und +'task info' können auch im Monitor gegeben werden. +Folgende Supervisor-Kommandos stehen zur Verfügung: + +begin + PROC begin (TEXT CONST task name) + Zweck: Richtet eine neue Task als Sohn von PUBLIC ein. + + PROC begin (TEXT CONST task name, father task name) + Zweck: Richtet eine neue Task als Sohn der 'father task name'-Task ein. + +begin password + PROC begin password (TEXT CONST geheim) + Zweck: Verhindert das unberechtigte Einrichten einer Sohn-Task. + +break + PROC break + Zweck: Die zum Terminal aktuell zugeordnete Task wird abgekoppelt. Sie + wird damit zu einer Hintergrund-Task, d.h. sie wird entweder bis + zu ihrem Ende oder bis zur nächsten angeforderten Terminal-Ein-/ + Ausgabe oder bis zum nächsten 'continue'- Kommando weiter be- + arbeitet. + +continue + PROC continue (TEXT CONST task name) + Zweck: Eine im Hintergrund laufende Task wird an das Terminal des + Benutzers angekoppelt. + +end + PROC end + Zweck: Die zum Terminal aktuell gehörende Task wird abgebrochen und + gelöscht. Das Kommando ist im Monitor verfügbar. + +father + TASK PROC father + Zweck: Liefert den internen Tasknamen. + +global manager + PROC global manager + Zweck: Macht eine Task zur 'manager'-Task. Erst nach Aufruf dieser + Prozedur sind Sohn-Tasks möglich. + +halt + PROC halt + Zweck: Das laufende Programm der dem Terminal aktuell zugeordneten Task + wird abgebrochen. Im Gegensatz zum 'end'-Kommando wird nur das + laufende Programm abgebrochen, aber die Task wird nicht gelöscht. + Genauer: + Es wird der Fehler 'halt from terminal' induziert. Normalerweise + wird das Programm dadurch wie durch jeden anderen Fehler abge- + brochen. Genaueres findet man im Systemhandbuch unter Fehler- + behandlung. + +name + TEXT PROC name (TASK CONST interner name) + Zweck: Wandelt den internen Task-Namen in einen TEXT. + +rename myself + PROC rename myself (TEXT CONST neuer name) + Zweck: Umbenennen einer Benutzer-Task. + +myself + TASK PROC myself + Zweck: Liefert den internen Task-Namen der Benutzer-Task. + +storage info + PROC storage info + Zweck: Informationsprozedur über den verfügbaren Hintergrund-Speicher. + +task info + PROC task info + Zweck: Informiert über alle Tasknamen im System unter gleichzeitiger An- + gabe der Vater/Sohn-Beziehungen (Angabe durch Einrückungen). + + PROC task info (INT CONST art) + Zweck: Informiert über alle Tasks im System. Mit 'art' kann man die Art + der Zusatz-Information auswählen. Für 'art' sind zur Zeit + folgende Werte zugelassen: + + 1: entspricht 'task info' ohne Parameter, d.h. gibt nur die + Tasknamen unter angabe der Vater/Sohn-Beziehungen aus. + + 2: gibt die Tasknamen aus. Zusätzlich erhalten Sie Informationen + über die verbrauchte CPU-Zeit der Task, die Priorität, den + Kanal, an dem die Task angekoppelt ist und den eigentlichen + Taskstatus. Hierbei bedeuten: + + 0 -busy- Task ist aktiv. + 1 i/o Task wartet auf Beendigung des Outputs + oder auf Eingabe. + 2 wait Task wartet auf Sendung von einer anderen + Task. + 4 busy-blocked Task ist rechenwillig, aber blockiert. + 5 i/o -blocked Task wartet auf I/O, ist aber blockiert. + 6 wait-blocked Task wartet auf Sendung, ist aber blockiert. + Achtung: Die Task wird beim Eintreffen einer + Sendung automatisch entblockiert. + + 3: wie 2, aber zusätzlich wird der belegte Speicher angezeigt. + (Achtung: Prozedur ist aufwendig!). Beachten Sie, daß Dateien + mit Väter/Söhnen "geshared" werden. Beispiel: + Mit 'begin ("sohn", "vater")' wird eine neue Task eingerichtet. + Für 'sohn' wird in diesem Zustand der gleiche belegte Speicher + angezeigt wie für 'vater'. Erst wenn (Datei-)Operationen in + der Sohn- oder Vater-Task vorgenommen werden, wird ein unter- + schiedlicher Speicherplatz angezeigt. + +task status + PROC task status + Zweck: Informationsprozedur über den Zustand der eigenen Task. + Informiert u.a. über + - Name der Task, Datum und Uhrzeit; + - verbrauchte CPU-Zeit; + - belegten Speicherplatz; + - Kanal, an den die Task angekoppelt ist; + - Zustand der Task (rechnend u.a.m.); + - Priorität. + + PROC task status (TASK CONST t) + Zweck: Wie obige Prozedur, aber über die Task mit dem internen Task- + namen 't'. Beispiel: task status (father) + +task password + PROC password (TEXT CONST geheim) + Zweck: Einstellen eines Paßworts für eine Task im Monitor. Das Kommando + 'task password' ist ein Monitor-Kommando. Ist eine Task mit einem + Paßwort geschützt, so wird durch den Supervisor nach dem + 'continue'-Kommando das Paßwort angefragt. Nur nach Eingabe des + richtigen Paßworts gelangt man in die gewünschte Task. Das Paß- + wort kann durch nochmaligen Aufruf von 'task password' geändert + werden, z.B., wenn es in regelmäßigen Abständen geändert werden + muß, um personenbezogene Daten zu schützen. + + Es gibt keine Möglichkeit, ein einmal eingestelltes Paßwort in + Erfahrung zu bringen. Sollte das Paßwort vergessen werden, kann + somit die Task nur noch gelöscht werden. + + Wird als Paßwort ein '-'-Zeichen eingegeben, so wird verhindert, + daß die betreffende Task jemals wieder mit dem 'continue'-Kom- + mando angekoppelt werden kann. Dies ist z.B. für Manager-Tasks + sinnvoll. + + + +3. Der Monitor + +Der EUMEL-Monitor führt den Dialog mit dem Benutzer innerhalb einer Task. In +diesem Kapitel werden nur die Ausführung der Kommandos und die Kommando- +Arten beschrieben, während die einzelnen Kommandos selbst in den jeweiligen +Kapiteln des Benutzerhandbuchs erläutert werden. + +Der Monitor ermöglicht es, Leistungen im Dialog mit Hilfe von Kommandos +(ELAN-Prozeduraufrufen) vom EUMEL-Betriebssystem anzufordern. Nach dem +Beginn einer Sitzung meldet sich der Monitor mit + + gib kommando : + +Danach kann der Benutzer Monitor-Kommandos geben. Erfolgt dabei ein Schreib- +fehler, so kann er (wie beim Editor) innerhalb der Zeile positionieren, über- +schreiben, löschen, einfügen u.a.m.. Die Ausführung des/der Kommandos wird +mit der Taste RETURN ausgelöst. Nach Abschluß einer Kommando-Ausführung er- +scheint wieder obige Meldung. Die Tastenfolge ESC k stellt das zuletzt gege- +bene Kommando wieder dar. + +Monitor-Kommandos müssen gemäß der ELAN-Syntax geschrieben werden (Kommando- +Namen werden klein geschrieben, Parameter in Klammern, mehrere Parameter +durch Kommata getrennt, TEXT-Parameter in Anführungstrichen usw.). Beispiele: + + edit ("meine datei") + copy ("meine datei", "Duplikat") + +Bei den meisten Kommandos mit einem TEXT-Parameter kann der Parameter fort- +gelassen werden. Der Monitor versorgt das Kommando immer mit dem zuletzt an- +gegebenen Parameter und zeigt dies auch auf dem Bildschirm des Benutzers an. +Beispiel: + + edit ("Datei vom 17.4.") + +schreibt der Nutzer nun z.B. + + run + +und betätigt RETURN, dann ergänzt der Monitor das Kommando: + + run ("Datei vom 17.4.") + +Monitor-Kommandos sind einzeilige ELAN-Programme, die dem ELAN-Compiler zur +Übersetzung und anschließender Ausführung zugeleitet werden. Darum können +die Monitor-Kommandos auch von Programmen aus verwendet werden. Falsch ge- +schriebene oder nicht vorhandene Kommandos werden vom ELAN-Compiler mit ent- +sprechender Fehlermeldung abgewiesen. Oft benutzte Kommandos werden aus +Effizienzgründen vom Monitor selbst interpretiert und ausgeführt. Durch die +automatische Überleitung von Kommandos zum ELAN-Compiler ist es möglich + +a) einzeilige ELAN-Programme direkt in der Monitor-Ebene ausführen zu + lassen, d.h. ohne das Programm in eine Datei zu schreiben. Beispiel: + + put (sin (0.5)) + +b) mehrere Kommandos (ELAN-Anweisungen), durch ";" getrennt, auf einmal zu + schreiben. Beispiele: + + edit ("datei"); lineform ("datei"); print ("datei") + INT VAR i; FOR i FROM 1 UPTO90 REP print ("x") ENDREP + +c) eine Erweiterung des Kommando-Vorrats jederzeit vorzunehmen, indem man + die gewünschte Prozedur (in einem PACKET "verpackt") 'insertiert'. + +Im folgenden werden die am häufigsten benutzten Kommandos aufgeführt. +Genauere Informationen über die einzelnen Kommandos findet man in den +entsprechenden Kapiteln des Benutzerhandbuchs. + +Informations-Kommandos + + storage info Belegter externer Speicher + task info Zeigt die im System befindlichen Tasks + task status Zustände der im System befindlichen Tasks + + +Verbindung zum Supervisor + + end Task und die in ihr befindlichen Dateien + löschen + break Task abkoppeln + task password ("geheim") Paßwort einstellen + + +Editor-Kommandos + + edit ("datei") Datei editieren + edit ("datei1", "datei2") Parallel-Editor + + +Compiler-Kommandos + + run ("datei") Übersetzen und ausführen eines ELAN-Programms + run again Letztes übersetztes Programm nochmal aus- + führen + insert ("datei") Übersetztes Programm eintragen + + +Datei-Kommandos + + copy ("datei", "duplikat") Datei kopieren + rename ("alt", "neu") Datei umbenennen + reorganize ("datei") Datei "reorganisieren" + fetch ("datei") Datei von Vater-Task holen + save ("datei") Datei zur Vater-Task schicken + erase ("datei") Datei in Vater-Task löschen + forget ("datei") Datei in Benutzer-Task löschen + list Dateien der Benutzer-Task anzeigen + + +Archiv-Kommandos + + archive ("name") Archiv mit einem Namen reservieren + release (archive) Archiv freigeben + clear (archive) Löscht ein Archiv + list (archive) Dateien des Archivs anzeigen + save all (archive) Archiviert alle Dateien einer Task + fetch all (archive) Holt alle Dateien eines Archivs in eine Task + save ("datei", archive) Datei archivieren + fetch ("datei", archive) Datei vom Archiv holen + + +Textkosmetik und Drucker + + lineform ("datei") Zeilenweises Formatieren + pageform ("datei") Seitenweises Formatieren + index ("datei") Stichwort- und Inhaltsverzeichnis + print ("datei.p") Drucken + diff --git a/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil3 b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil3 new file mode 100644 index 0000000..eaf1ed6 --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil3 @@ -0,0 +1,2097 @@ + EUMEL-Benutzerhandbuch + + TEIL 3: Editor + +Vorwort + +Der EUMEL-Editor ist ein Programm zur Bearbeitung von Texten. Er bietet +vielfältige Möglichkeiten, um Autoren oder Programmierer bei dem Erstellen, +Korrigieren und Gestalten von Manuskripten oder Programmen zu unterstützen. +Die größte Hilfe beim Schreiben besteht (durch die Speicherfähigkeit von +Computern) aus dem Zugriff auf einmal geschriebene Informationen. Im Gegen- +satz zu einer Schreibmaschine können durch den EUMEL-Editor (beliebig oft) +Einfügungen vorgenommen, Texte korrigiert, gelöscht und umgeordnet werden. +Somit ist das Schreiben von Texten mittels des EUMEL-Systems besonders dann +vorteilhaft und zeitsparend, wenn Texte häufig geändert werden oder wenn +sie in einer besonders schönen Form gedruckt werden sollen (sofern ein ent- +sprechender Drucker zur Verfügung steht). Weiterhin bietet der Editor Hilfen +zum Schreiben an, wie z.B. automatischen Wortumbruch am Zeilenende, eine +Einrückungsautomatik, "Lernen" von Texten u.a.m.. Zusätzlich kann der Editor +in seinen Fähigkeiten erweitert und somit für spezielle Schreibarbeiten an- +gepaßt werden. Bei der Entwicklung des Editors wurde besonderer Wert auf +einfache Bedienung gelegt: innerhalb von wenigen Minuten kann schon ge- +schrieben werden und auf dem Bildschirm sieht man direkt, was mit dem Text +passiert. Das Schreiben und die Korrektur werden durch einige wenige, aber +leistungsstarke Funktionstasten unterstützt. + +Anfänger sollten zumindest das erste Kapitel lesen, bevor mit dem Schreiben +begonnen wird. Dort wird geschildert, wie auf einfache Weise Texte ge- +schrieben und geändert werden können. Die beschriebenen Tätigkeiten sollte +man an einem kleinen Probetext erst einmal ausprobieren. Lesen und an- +schließendes Ausprobieren eines der hier beschriebenen Vorgänge beschleunigt +stark das Erlernen der Funktionen des Editors. + +Weitere Fähigkeiten des Editors werden in den folgenden Kapiteln erläutert. +Diese Kapitel sollte man lesen, wenn die ersten Texte geschrieben worden +sind. Die dort erklärten Möglichkeiten des Editors kann man dann bei Bedarf +nachlesen, erlernen und einsetzen. Im letzten Kapitel werden Programmierern +Hinweise gegeben, wie sie die Benutzerschnittstelle des Editors an indivi- +duelle Bedürfnisse anpassen können. + +Einige Gestaltungsmöglichkeiten für Texte kann man nicht auf dem Terminal +"sehen", wie z.B. Proportionalschriften, Fettdruck usw.. Solche Leistungen +können durch Anweisungen an die Textkosmetik-Programme und den EUMEL-Drucker +angefordert werden. Diese Anweisungen müssen in den Text eingefügt werden. +Dazu sollte das Kapitel über die Textkosmetik gelesen werden. + +is nämlich alles ohne Radiergummi-Abbildung !!! + + + +1. Einführung in die Benutzung des Editors + +In diesem Kapitel beschreiben wir das Tastenfeld eines EUMEL-Terminals, weil +es hier einige Tasten gibt, die auf einer Schreibmaschine nicht vorhanden +sind. Anschließend erklären wir, wie der Editor ein- und ausgeschaltet wird, +wie Texte geschrieben und auf einfache Weise korrigiert werden können. Eine +kurze Erklärung des Tabulators beendet die Einführung. + + + +Das Tastenfeld + +In diesem Abschnitt wird das Tastenfeld eines EUMEL-Terminals erklärt. Es +wird erläutert, wo sich die Tasten befinden und wie man Umlaute schreibt. + +Das Tastenfeld eines EUMEL-Terminals entspricht weitgehend dem einer +Schreibmaschine. Wir finden also die Buchstaben a-z und die Ziffern 0-9 auf +Tasten. Mit der SHIFT-Taste und gleichzeitigem Drücken einer anderen Taste +können die großen Buchstaben und eine Reihe von speziellen anderen Zeichen, +die Sonderzeichen genannt werden, geschrieben werden. Die "Zwischenraum- +taste" oder Leertaste erzeugt immer ein Leerzeichen. + +Nun gibt es in der Praxis zwei unterschiedliche Tastaturen. Zum einen +existiert die EDV-Tastatur, die zum Schreiben von Programmen benutzt wird. +Sie erkennt man daran, daß keine Umlaute (ä, ü, ö) und kein ß auf den Tasten +eingraviert sind. Dafür gibt es Tasten für eckige und geschweifte Klammern. +Sollen auf einer solchen Tastatur die Umlaute geschrieben werden, muß man +sich eines Tricks bedienen: mit der Taste ESC und nachfolgendem Betätigen +einer anderen Taste erhalten wir den entsprechenden Umlaut. +Diese Tasten sind standardmäßig vorbelegt, können aber von Benutzern und in +Anwenderprogrammen geändert werden. + + ESC a bringt ä, ESC A bringt Ä + ESC u bringt ü, ESC U bringt Ü + ESC o bringt ö, ESC O bringt Ö und + ESC s bringt ß. + +In der Regel kann man die Umlaute auf dem Bildschirm eines solchen EDV- +Terminals nicht sehen, sondern sie erscheinen als a, u, usw.. Beim Druck +eines Textes werden sie aber richtig dargestellt. + +Die andere Tastatur entspricht in der Tastenbelegung weitgehend einer deut- +schen Schreibmaschine und besitzt Tasten für die Umlaute und ß. Sollen vor- +wiegend deutsche Texte geschrieben werden, empfiehlt es sich, solch ein +Terminal zu verwenden. + +Neben diesen "einfachen" Tasten gibt es noch einige wenige Tasten, die zur +Bedienung des Editors (aber auch anderer Programme) notwendig sind. Wo die +Tasten auf Ihrem Gerät liegen, hängt von dem jeweiligen Gerätetyp ab. Die +Wirkung der Tasten erklären wir in den anschließenden Abschnitten. +Es kann sein, daß die Tasten nicht richtig beschriftet sind. Dann sollten Sie +den Betreuer ihrer Installation bitten, diese zu beschriften. Zusätzlich zu +den hier beschriebenen können sich noch weitere Tasten auf ihrem Terminal +befinden, die aber keine besondere Bedeutung für den Editor haben. + +Taste Bedeutung +----------------------------------------------------------------------------- +SHIFT Umschalttaste. + Für Großbuchstaben statt Kleinbuchstaben und Sonderzeichen + statt Ziffern. + +RETURN Beginn einer neuen Zeile (Absatz). + Die RETURN-Taste ist oft mit einem geknicktem Pfeil nach + links gekennzeichnet. Im Kommandomodus (also bei "gib + kommando :") wird ein gegebenes Kommando ausgeführt. + +LINKS Tasten für die Positionierung. +RECHTS +OBEN +UNTEN + Positionierung der Schreibmarke (Cursor) in die jeweilige + Richtung (auf den Tasten oft auch durch Pfeile dargestellt). + +HOP "Verstärkertaste": Wirkt als Vorschalttaste. + +RUBOUT Löschtaste. + +RUBIN Ein- bzw. Ausschalten des Einfügezustandes. + +TAB Tabulatortaste. + +MARK Ein- bzw. Ausschalten der Markierung. + +ESC Kommandotaste. + +Merke: Das Tastenfeld eines EUMEL-Terminals ist in der Regel wie das einer +Schreibmaschine und kann ebenso bedient werden. Umlaute müssen bei EDV- +Tastaturen mit Hilfe der Taste ESC geschrieben werden. Einige Spezialtasten +werden benutzt, um die Textbearbeitung des Editors zu steuern. + +Weitere Kommandotasten: + SV Supervisor-Taste im Mehrbenutzer-Betrieb ("multi-user"). + Diese Taste bewirkt den Aufruf des Supervisors und ist keine + spezielle Editor-Taste. + STOP Anhalten eines Programms. + Wird die Taste aus Versehen betätigt (erkennbar daran, daß + der Editor nicht "reagiert"), muß WEITER betätigt werden. + WEITER Programm soll weiterlaufen. + + + +Speicherung von Texten + +In diesem Abschnitt wird der Begriff "Datei" erklärt und erläutert, wie +unterschiedliche Texte auseinandergehalten werden können. + +Das EUMEL-System speichert einmal geschriebene Texte, bis sie vom Benutzer +gelöscht werden. In der Regel wird nicht nur ein (langer) Text oder ein Pro- +grammtext geschrieben, sondern mehrere und unterschiedliche. Um diese aus- +einanderhalten zu können, versehen wir sie jeweils mit einem Namen, der frei +gewählt werden kann. Beispiele für Namen: + + "Brief vom 1.8.83" + "1. Kapitel meines Buches" + +Eine Sammlung von Zeichen (also im Normalfall unsere geschriebenen Texte), +die mit einem Namen versehen worden ist, nennt man eine 'Datei' ('file'). Der +Editor erstellt also eine Datei, wenn wir einen Text schreiben. Eine Datei +kann bis zu 4 000 Zeilen fassen, wobei eine Zeile bis zu 32 000 Zeichen lang +sein darf. + +Mit Hilfe des (Datei-) Namens kann man den Text (immer) wieder ansprechen, +solange, bis die Datei gelöscht wird. Bei der Bearbeitung einer Datei durch +den Editor wirkt sich jede Änderung des Textes auf dem Bildschirm sofort bis +in die gespeicherte Datei aus. Eine Datei kann durch Kommandos verarbeitet +werden. Eine Auswahl (Vergl. dazu die Beschreibung des Monitors): + +edit (Datei bearbeiten), rename (Datei umbenennen), copy (Duplizieren der +Datei), to archive (Archivieren), lineform bzw. autoform (Zeilen +formatieren), pageform (Seiten formatieren), print (Drucken) usw. + +Merke: Ein Text wird im EUMEL-System in einer Datei gehalten. Eine Datei +faßt bis zu 4000 Zeilen Text. Eine Datei kann über den Dateinamen ange- +sprochen werden, der frei gewählt werden kann. + + + +Ein- und Ausschalten des Editors + +Hier beschreiben wir, wie der Editor ein- und ausgeschaltet wird und wie +der Editor eine Datei einrichtet. Zusätzlich wird das Ausschalten des auto- +matischen Wortumbruchs erklärt. + +Wenn auf dem Bildschirm die Aufforderung + + gib kommando : + +erscheint, befindet man sich in der Monitor-Ebene. Durch + + edit ("dateiname") + +kann der EUMEL-Editor eingeschaltet (programmtechnisch: "aufgerufen") +werden. Ist die Datei noch nicht vorhanden, d.h. kein Text unter dem ange- +gebenen Namen im System gespeichert, folgt eine Anfrage, ob eine neue Datei +eingerichtet werden soll. Dies dient zur Kontrolle von Schreibfehlern, die +besonders bei ähnlichen Dateinamen auftreten. Man kann dann das Einrichten +der Datei ablehnen, den Dateinamen verbessern und das Kommando erneut geben. + +Der Editor zeigt jetzt in der obersten Zeile des Bildschirms die Titelzeile, +die den Dateinamen und die Zeilennummer enthält, die gerade bearbeitet wird. +Im Fall einer bereits beschriebenen Datei zeigt der Editor das zuletzt bear- +beitete Textstück. Bei einer neuen Datei ist der Bildschirm unterhalb der +Titelzeile leer. Dieser Teil dient als "Schreibfläche". Der Cursor, so nennt +man die blinkende Schreibmarke, steht dann direkt unter der Titelzeile. Er +zeigt immer die aktuelle Schreibposition an. Jetzt kann sofort mit dem +Schreiben begonnen werden, ganz wie mit einer normalen Schreibmaschine. + +Beenden der Schreibarbeit und Ausschalten des Editors erfolgt durch Drücken +der beiden Tasten + + ESC q + +nacheinander. Man befindet sich wieder in der alten Kommando-Ebene. + +Es ist aber auch möglich, während der Schreibarbeit (also bei eingeschalte- +tem Editor) durch zweimaliges Drücken von ESC in die (Editor) Kommando- +Ebene zu gelangen. Nach Abarbeitung des Kommandos gelangt man wieder in den +normalen Schreibzustand. + +Der Editor ist auf das Schreiben von "normalen" Texten eingestellt. Bei +"normalen" Texten soll ein Wort, welches über das Ende einer Zeile gehen +würde, automatisch in die nächste Zeile gebracht werden. Dies wird +"Wortumbruch" genannt. + +Ist kein Wortumbruch erwünscht, so gibt man das Kommando + + word wrap (false) + +In diesem Fall schreibt der Editor bis zum Zeilenende und springt dann auto- +matisch (u.U. mitten im Wort) auf die nächste Zeile. Der Wortumbruch kann +durch + + word wrap (true) + +wieder eingeschaltet werden. + +Merke: Der Editor wird durch das Kommando 'edit ("name")' aufgerufen und +und wird durch ESC q wieder verlassen. Der Cursor zeigt die aktuelle +Schreibposition an. Der Editor ist auf automatischen Wortumbruch eingestellt. + + + +Schreiben eines Textes + +In diesem Abschnitt wird erklärt, wie ein Text geschrieben wird und was es +mit Absätzen auf sich hat. + +Nach dieser etwas langen Vorrede können wir endlich losschreiben. Wird ein +Zeichen geschrieben, rückt der Cursor automatisch nach rechts auf die +nächste Schreibstelle. Durch den automatischen Wortumbruch werden ange- +fangene Worte, die über ein Zeilenende hinausgehen würden, ohne Silbentren- +nung in die nächste Zeile gebracht. +Nehmen Sie bitte keine Silbentrennung "per Hand" vor (wie in dieser An- +leitung).Eingebrachte Trennstriche gelten als Bindestrich und bleiben somit +auch bei Umformatierungen erhalten, was unerwünscht ist. Für diese mühevolle +Aufgabe gibt es in der Textkosmetik ein Programm! + +Die RETURN-Taste (bei einer Schreibmaschine bedeutet sie "Wagenrücklauf") +braucht also nur noch betätigt zu werden, wenn eine Zeile vorzeitig beendet +werden soll: also bei einem Absatz oder einer Leerzeile. Der Cursor wird da- +bei an den Anfang der nächsten Zeile positioniert. Gleichzeitig erscheint in +der vorherigen Zeile am rechten Rand des Bildschirms eine Markierung, die +anzeigt, daß hier ein Absatz gemacht wurde. + +Diese Absatzkennzeichnung ist wichtig: Sie bedeutet u.a. eine "Grenze" für +die Textkosmetik-Programme beim (optimalen) Auffüllen von Zeilen. Für den +Drucker bedeutet ein Absatz, keinen rechten Randausgleich (druckertechnisch: +"Blocksatz") in dieser Zeile vorzunehmen. +Die Absatzkennzeichnung besteht aus einem Leerzeichen in der Datei ("blank"; +im Unterschied zur Schreibmaschine ist das Leerzeichen in der EDV auch ein +Zeichen und wird gespeichert). Absatzkennzeichen können gelöscht oder auch +hinzugefügt werden (wie das gemacht wird, erfahren Sie in den nächsten Ab- +schnitten). Ist der Wortumbruch ausgeschaltet, erscheint keine Absatzkenn- +zeichnung beim Betätigen der RETURN-Taste. + +Darum ist das Betätigen der RETURN-Taste bei Tabellenzeilen und Programm- +texten besonders wichtig, denn hier soll ja jede Zeile separat bleiben. + +Ein Bildschirm faßt (neben der Titelzeile) üblicherweise 23 Zeilen, die mit +Text beschrieben werden können. Ist die letzte Zeile voll und muß eine neue +Zeile begonnen werden, "rutscht" der Bildschirminhalt automatisch um eine +Zeile nach oben. Damit ist Platz für eine Leerzeile, die nun ebenfalls be- +schrieben werden kann usw.. Keine Angst: die so verschwundenen Zeilen sind +natürlich nicht "weg". Da ein Bildschirm immer nur eine beschränkte Anzahl +von Zeilen hat, kann der Editor nur einen Ausschnitt aus der Datei zeigen. +In unserem Fall, wo wir zunächst nur am Ende der Datei schreiben, werden +also immer die letzten Zeilen der Datei angezeigt. + +Merke: Ist der Wortumbruch eingeschaltet, wird ein angefangenes Wort, das +über das Zeilenende gehen würden, an den Anfang der neuen Zeile gebracht. +Die RETURN-Taste wird nur bei Absätzen, Tabellenzeilen oder Leerzeilen be- +tätigt. In diesem Fall erscheint eine Absatzkennzeichnung am rechten Rand +des Bildschirms. Ist der Bildschirm vollgeschrieben, werden beim fort- +laufenden Schreiben alle Zeilen um eine Zeile nach oben gerückt. + + + +Einrückungen + +Hier wird die Einrückungsautomatik erklärt. + +Soll ein Text eingerückt werden (wie in den obigen "Merke"-Zeilen) oder bei +Aufzählungen, so wird die in der ersten Zeile geschriebene Einrückung auto- +matisch in den folgenden Zeilen beibehalten, bis sie durch die Posi- +tionierungstasten wieder aufgehoben wird. Es gibt also kein Einrückkommando. +Wie der rechte Rand (also die Zeilenbreite) eingestellt wird, erklären wir +später. +Dies kann für die gesamte Datei (und somit für den gesamten Text) durch ein +ein Kommando erfolgen, mit welchem man den Editor auf diese Zeilenbreite +einstellt. Um den rechten Rand nur für einige Zeilen zu verändern (wie z.B. +bei unseren "Merke"-Zeilen) kann ein 'limit'-Kommando der Textkosmetik +verwandt werden. + +Merke: Einrückungen werden automatisch beibehalten. + + + +Einfaches Positionieren und das Editor-Fenster + +Um Korrekturen (Überschreiben, Löschen oder Einfügen) vorzunehmen, muß der +Cursor, der die aktuelle Schreibposition anzeigt, bewegt werden können. Bei +längeren Texten ist es möglich, den Cursor auch auf Zeilen zu positionieren, +die sich (noch nicht) auf dem Bildschirm befinden. Somit zeigt der Editor +nicht nur immer das Ende einer Datei, sondern einen beliebigen Ausschnitt, +der auf dem Bildschirm im sogenannten Fenster sichtbar ist. + +Ist eine Korrektur notwendig, muß der Cursor (blinkende Schreibmarke) auf die +Stelle positioniert werden, an der die Korrektur vorgenommen werden soll. +Dazu verwenden wir die Positionierungstasten LINKS, RECHTS, OBEN und UNTEN. +LINKS und RECHTS bewegen den Cursor innerhalb einer Zeile. Stößt man mit +RECHTS an das Ende einer Zeile, wird der Cursor an den Anfang der nachfol- +genden Zeile bewegt. (Positionierungen jenseits des linken Randes sind nicht +möglich). + +Ein Zeilenwechsel kann einfacher mit den Tasten OBEN und UNTEN vorgenommen +werden. Die Taste OBEN bewegt den Cursor eine Zeile nach oben, die Taste +UNTEN entsprechend eine Zeile tiefer. + +Was passiert nun, wenn der untere oder der obere Rand des Bildschirms er- +reicht wird und es wird darüber hinaus positioniert? In diesem Fall wird der +Text zeilenweise nach oben oder nach unten verschoben und es erscheint die +gewünschte Zeile, wobei andere am anderen Rand "verschwinden". Wir sehen +also, daß wir mit den Positionierungstasten den Bildschirm als Fenster über +die Datei hinweggleiten lassen können (Fachausdrücke: "roll up" oder "roll +down"). Den Text selbst können wir uns auf einem langen Band geschrieben +vorstellen. Die Zeilennummer, in der der Cursor steht, wird stets in der +Titelzeile angezeigt. + +Innerhalb einer Zeile ist es etwas anders: Positionieren wir bei einer Zeile, +die breiter als der Bildschirm ist, nach rechts, wird das Fenster nur für +diese Zeile verschoben (Fachausdruck: "scrolling"). + +Merke: Mit Hilfe der vier Positionierungstasten kann man den Cursor auf dem +Bildschirm bewegen. Außerdem ist es möglich, das Fenster mittels der +Positionierungstasten über den Text zu bewegen. + + + +Einfache Korrekturen: Zeichen überschreiben, löschen und einfügen + +In diesem Abschnitt wird erklärt, wie einfache Korrekturen durch Über- +schreiben von Zeichen, Löschen von Zeichen und Einfügen von Zeichen vorge- +nommen werden können. + +Es können Korrekturen gleich beim Schreiben vorgenommen werden, indem die +zuletzt geschriebenen Zeichen mit der RUBOUT-Taste gelöscht werden. Häufig +merkt man aber Schreibfehler erst etwas später, so daß man diese Fehler nicht +so leicht korrigieren kann. Für solche Zwecke muß man den Cursor an die Text- +stelle bewegen, an dem korrigiert werden soll. Wie man das macht, haben wir +im letzten Abschnitt geschildert. + +Die einfachste Möglichkeit der Korrektur ist das Überschreiben. Soll z.B. ein +Zeichen durch ein anderes ersetzt werden, so positioniert man den Cursor +genau über dieses und tippt das richtige Zeichen ein.Das kann natürlich auch +mit mehreren Zeichen nacheinander erfolgen. + +Will man ein Zeichen löschen, so positioniert man auch hier den Cursor auf +dieses Zeichen und betätigt die Taste RUBOUT. Das Zeichen verschwindet und +die Restzeile rückt heran. Sollen mehrere Zeichen gelöscht werden, muß die +RUBOUT-Taste entsprechend oft gedrückt werden. + +Steht der Cursor hinter dem letzten Zeichen der Zeile, wird immer das letzte +Zeichen der Zeile gelöscht. Man kann also mit dieser Eigenschaft eine Zeile +"von hinten wegradieren". + +Fehlende Zeichen kann man genauso einfach einfügen. Man bringt den Cursor +auf das Zeichen, vor das eingefügt werden soll. Dann drückt man die Taste +RUBIN. Der Editor gelangt in den Einfüge-Zustand, was in der Titelzeile durch +RUBIN angezeigt wird. Er fügt alle Zeichen ein, die jetzt getippt werden (an- +statt zu überschreiben). Der Teil der Zeile rechts vom Cursor rückt jeweils +um entsprechend viele Stellen nach rechts. + +Wichtig ist, daß im RUBIN-Zustand der Editor genauso funktioniert wie im +Normal-Zustand (natürlich mit der Ausnahme, daß eingefügt statt überschrieben +wird). + +Ein neuerliches Betätigen der RUBIN-Taste beendet den Einfüge-Zustand. Die +RUBIN-Taste wirkt also wie ein Schalter, der den Einfüge-Zustand ein- und +ausschaltet. Allerdings kann man nur so viele Zeichen in eine Zeile einfügen, +bis das letzte Wort der Zeile an das Zeilenende stößt. Das angefangene Wort +wird am Anfang der folgenden Zeile eingefügt, sofern dort noch Platz ist und +es nicht offensichtlich ein Absatzende kennzeichnet. Andernfalls wird auto- +matisch eine neue Zeile für das angefangene Wort eingefügt. + +Im eingeschalteten RUBIN-Zustand können keine Zeichen verloren gehen. Viele +Benutzer lassen darum den RUBIN-Zustand immer eingeschaltet, um sich vor dem +unbeabsichtigten Überschreiben von Texten zu schützen. Es wird korrigiert, +indem man die Verbesserung einfügt und den alten Text löscht. + +Merke: Mit Hilfe der Positionierungstasten LINKS, RECHTS, OBEN und UNTEN +kann eine Stelle in der Datei ausgewählt werden, an der eine Korrektur vor- +genommen werden soll. Die einfachste Korrektur ist das Überschreiben von +fehlerhaften Zeichen. Zeichen löschen erfolgt mit der Taste RUBOUT. Mit +RUBIN kann der Einfüge-Zustand ein- und ausgeschaltet werden. Im Einfüge-Zu- +stand wird nicht überschrieben, sondern es wird vor der Cursor-Position das +getippte Zeichen eingefügt. + + + +Springen, Zeilen einfügen/löschen mittels HOP-Taste + +Bewegungen des Cursors sind mit den Positionierungstasten bei größeren "Ab- +ständen" etwas mühsam, ebenso bei umfangreichen Löschungen und Einfügungen. +Die "Verstärkertaste" HOP ermöglicht es, diese Operationen auf einfache +Weise zu beschleunigen. Mit der HOP-Taste kann man das Fenster über der +Datei nicht nur zeilenweise, sondern auch um jeweils eine Fensterlänge ver- +schieben. Das nennt man Blättern. + +Wird die HOP-Taste vor einer anderen der schon erklärten Funktionstasten +gedrückt, verstärkt sie deren Wirkung. Die HOP-Taste ist eine "Präfix"-Taste: +sie wird vor (und nicht gleichzeitig, wie z.B. die Umschalttaste SHIFT) einer +anderen Taste gedrückt. Zuerst das springende Positionieren: +Weitere wichtige Anwendungen der HOP-Taste beschreiben wir in den nächsten +Abschnitten. + +HOP RECHTS Sprung an das rechte Zeilenende. + Falls die Zeile länger als das Fenster breit ist, wird seitlich + geblättert. + +HOP LINKS Sprung an den Zeilenanfang (ggf. seitlich blätternd). + +HOP OBEN Sprung auf die erste Zeile des Bildschirms. + Nochmaliges Betätigen dieser Tastenkombination positioniert den + Cursor (und damit das Fenster in der Datei) um ein Fenster + zurück. + +HOP UNTEN Sprung auf die letzte Zeile des Bildschirms. + Das Blättern erfolgt analog HOP OBEN. + +HOP RETURN Macht die aktuelle Zeile zur ersten des Fensters. + Die Zeile, in der sich der Cursor befindet, wird die erste + Zeile des Fensters. + +Die HOP-Taste in Verbindung mit RUBIN und RUBOUT wird zum "verstärkten" +Löschen und Einfügen verwandt: + +HOP RUBIN Einfügen von Textpassagen: + Ab der aktuellen Position des Cursors verschwindet der rest- + liche Text. Es kann wie bei der anfänglichen Texteingabe fort- + gefahren werden. Die Anzeige REST in der Titelzeile erinnert + daran, daß noch ein Resttext existiert. Dieser erscheint nach + einem neuerlichen Betätigen der beiden Tasten HOP RUBIN wieder + auf dem Bildschirm (die Anzeige REST verschwindet dann wieder). + +HOP RUBOUT Löscht Zeile ab Cursor-Position bis Zeilenende: + Löscht die Zeile rechts vom Cursor. Steht der Cursor am Zeilen- + anfang, wird dementsprechend die ganze Zeile gelöscht und die + Lücke durch Nachrücken der Folgezeilen geschlossen. + +Merke: Die HOP-Taste dient in Verbindung mit den Positionierungstasten zum +"Springen" oder zum "Blättern" innerhalb der Datei. Vor der Taste RUBOUT ge- +drückt, bewirkt sie die Löschung von Zeilen. Mit HOP RUBIN kann man längere +Texte in einen Text einfügen. + + + +Der Tabulator + +Eine weitere wichtige Positionierungshilfe ist die TAB-Taste. Sie wird zum +Schreiben von Tabellen benötigt. Wie bei einer Schreibmaschine können Ta- +bulatormarken gesetzt bzw. gelöscht werden. + +Der Tabulator hat eine wichtige Funktion für das schnelle Positionieren, auch +wenn keine Marken eingestellt wurden. Voreingestellte Tabulatormarken sind +nämlich der Textanfang einer Zeile (Einrückung; falls vorhanden) und die +Stelle direkt hinter dem letzten Zeichen der Zeile. Betätigt man also die +Taste TAB, dann springt der Cursor an die nächste dieser voreingestellten +Positionen. So kann man schnell an den Anfang oder das Ende einer Zeile mit +dem Cursor gelangen (und z.B. am Zeilenende Zeichen "von hinten" löschen +oder dort weiterschreiben). + +Nun zum Setzen des Tabulators: Er wird gesetzt, indem man den Cursor auf die +Zeilenposition bringt, in der die Marke plaziert werden soll. Hier betätigt +man nun HOP TAB. Die Tabulatorsetzung kann man in der Titelzeile an einer +Markierung ("Dach"-Zeichen) sehen (falls sie im Fensterbereich ist und die +aktuelle Zeile nicht seitlich verschoben ist). Betätigt man nun an irgend- +einer Position innerhalb einer Zeile die TAB-Taste, wird der Cursor auf die +Position der nächsten Tabulatormarkierung (die sich rechts vom Cursor be- +findet) oder eine der voreingestellten Positionen bewegt. + +Gesetzte Tabulatormarken können gelöscht werden, indem man mit der TAB- +Taste die Position der Tabulatormarke einstellt und dann HOP TAB betätigt. +Die Marke ist dann gelöscht (das Dach verschwindet in der Titelzeile). + +Tabulatormarkierungen hinterlassen keine Spuren in der Datei, sondern dienen +nur als Positionierungshilfen. + +Werden Tabulatormarken gesetzt (HOP TAB), gelten die voreingestellten Tabu- +latormarken (Anfang und Ende einer Zeile) nicht mehr. Dies ist z.B. bei dem +Schreiben von Tabellen notwendig. Andererseits möchte man beim Schreiben von +"normalen" Text wieder die voreingestellten Tabulatormarken bedienen können. +Mit den Tasten + + ESC TAB + +kann man die gesetzten Tabulatormarken (erkenntlich an dem "Dach"-Zeichen in +der Kopfzeile) verschwinden lassen. Dann gelten wieder die voreingestellten +Marken. Erneutes ESC TAB stellt die gesetzten Tabulatormarken wieder her +usw. + +Merke: Das Einstellen und Löschen von Tabulatormarken erfolgt mit HOP TAB; +das Positionieren auf diese mit TAB. Voreingestellte Tabulatormarken sind +Zeilenanfang und -ende. ESC TAB wirkt wie ein Umschalter zwischen voreinge- +stellten und gesetzten Tabulatormarken. + + + +2. Beschreibung weiterer Funktionen + +In diesem Kapitel werden weitere Funktionen des Editors beschrieben, die bei +dem Erstellen von Texten und Korrekturen sinnvoll einsetzbar sind. Die +Kenntnis der hier beschriebenen Funktionen sind für erste Arbeiten nicht +notwendig (dafür reicht das erste Kapitel). Man sollte aber dieses Kapitel +zumindest überfliegen, damit bei Bedarf die zusätzlichen Möglichkeiten des +Editors erlernt und angewandt werden können. + + + +Zeilen aufbrechen und Rückumbruch + +Um grössere Textpassagen einzufügen, betätigt man HOP RUBIN nacheinander. +Diese Tastenfolge kann benutzt werden, um eine Zeile zu spalten (Zeile auf- +zubrechen). HOP RUBOUT am Ende einer Zeile macht einen Rückumbruch. + +Wie bereits beschrieben, bewirkt HOP RUBIN in einer Zeile, daß der Zeilenrest +rechts vom Cursor und alle Zeilen unterhalb der aktuellen Zeile scheinbar +verschwinden. REST in der Titelzeile erinnert daran, daß ein Teil der Datei +nicht sichtbar ist. + +Wird unmittelbar nach HOP RUBIN wiederum HOP RUBIN betätigt, wird der vor- +herige Zeilenrest als eigenständige Zeile dargestellt. Es ist damit eine Auf- +spaltung einer Zeile in zwei Zeilen vollzogen. + +Der umgekehrte Fall, nämlich zwei Zeilen zu einer zusammenzufassen (sog. +Rückumbruch), ist durch HOP RUBOUT hinter dem letzten Zeichen einer Zeile +möglich. (Hinter das letzte Zeichen einer Zeile kann einfach mit dem +Tabulator positioniert werden). + +Das Aufbrechen einer Zeile und der Rückumbruch zusammen angewandt stellen +also den ursprünglichen Zustand wieder her. Beispiel: Mit HOP RUBIN bricht +man eine Zeile auf (der Rest der Zeile und nachfolgende Zeilen verschwinden +vom Bildschirm). Erneutes HOP RUBIN stellt den rechten Zeilenteil auf der +nächsten Zeile und die nachfolgenden Zeilen auf dem Bildschirm wieder dar. Da +der Cursor sich noch immer am rechten Rand der aufgebrochenen Zeile befindet, +kann man mit HOP RUBOUT den ursprünglichen rechten Zeilenteil wieder re- +kombinieren. + +Merke: Zweimaliges HOP RUBIN spaltet eine Zeile auf; HOP RUBOUT hinter dem +Ende einer Zeile fügt die nachfolgende Zeile an die aktuelle an (Rück- +umbruch). + + + +Zahlentabellen schreiben: Dezimaltabulator + +Beim Schreiben von Zahlentabellen sollen die Zahlen oft rechtsbündig im Text +erscheinen. Dazu bietet der Editor den Dezimaltabulator an. + +Für jede Zahlenkolonne wird die gewünschte Position der Einerstelle (also der +letzten Stelle) mit Hilfe eines Tabulators eingestellt. Mit TAB wird der +Cursor zur jeweils nächsten Tabulatormarke vorgerückt. Werden nun Ziffern +geschrieben, so schreibt man nicht - wie gewohnt - nach rechts, sondern die +Ziffern werden nach links eingerückt. Etwas genauer: Beim Drücken einer +Zifferntaste wird, solange links vor der Zahl noch ein Blank, eine Zahl, "+", +"-" oder ein Punkt sichtbar ist, diese gelöscht und die hierdurch neu ent- +standene Ziffernfolge rechtsbündig an der Tabulatorposition geschrieben. +Zahlenkolonnen können so leicht und rechtsbündig geschrieben werden. +Wird eine Proportionalschrift (Schrift, bei der die Zeichen unterschiedliche +Breiten haben) verwandt, sollte man zwischen den einzelnen Zahlenkolonnen +mindestens zwei Leerzeichen schreiben. Andernfalls bekommt man - auf Grund +der unterschiedlicher Zeichenbreiten - keine rechtsbündigen Kolonnen ge- +druckt. + + 12 12345,78 + 1 0,23 + 12345 1234,00 + +Merke: Ziffern werden bei Einsatz des Tabulators automatisch rechtsbündig ab +der Tabulatormarke geschrieben. + +Es gibt somit vier nützliche Automatiken: neben dem automatischen Dezimal- +tabulator der Wortumbruch, die Einrückautomatik und die Zeileneinfügeauto- +matik beim einfügenden Schreiben. + + + +Den Editor lernen lassen + +Beliebige Folgen von Tastenbetätigungen können gelernt und Tasten zugeordnet +werden. Das ist sinnvoll, wenn wiederholt immer die gleichen Tastenbe- +tätigungen ausgeführt werden müssen, wie z.B. in Tabellenzeilen etwas ein- +fügen oder wenn des öfteren gleiche Texte geschrieben werden müssen, wie +z.B. ein Absender, Grußformeln usw. + +Der Lernmodus wird durch Betätigen der Tasten ESC HOP eingeschaltet (es +erscheint LEARN als Kontrolle in der Titelzeile). Alle Tastenanschläge (auch +Tastenanschläge wie RETURN: man kann also auch mehrere Zeilen lernen lassen) +werden jetzt gelernt bis zum expliziten Ausschalten des Lernmodus. + +Das Beenden oder Ausschalten des Lernmodus erfolgt durch Drücken der drei +Tasten ESC HOP 'taste'. Dabei wird die gelernte Tastenanschlagsfolge, auch +Lernsequenz genannt, der Taste 'taste' zugeordnet. + +Durch späteres Betätigen der Tastenfolge ESC 'taste' kann der gelernte Text +an jeder Stelle der Datei geschrieben werden. Beispiel: Ein "Schreiberling" +hat jeden Tag 27 mal die Worte 'Hochschulrechenzentrum der Universität +Bielefeld' zu tippen. Er läßt diese Worte den Editor lernen mit + + ESC HOP Hochschulrechenzentrum der Universität Bielefeld + ESC HOP b + +Die Worte liegen jetzt auf der Taste 'b'. Wird 'b' gedrückt, erscheint ein +'b' auf dem Bildschirm. Mit ESC 'b' erscheinen die obigen Worte. ESC ist +also notwendig, um das normale 'b' von der Lernsequenz zu unterscheiden. + +Bei einigen Terminaltypen gibt es Tasten, die vom EUMEL-System nicht benutzt +werden. Bei diesen kann man ESC beim Aufruf der Lernsequenz weglassen. + +Welche Tasten dürfen zum Lernen belegt werden? Alle Tasten, außer + +- vom System benutzte Tasten, wie SV, CTRL; +- vom Editor (je nach Anwendung) vorbelegte Tasten, wie die Tasten q oder + ESC und HOP; +- durch Programmierung (siehe dieses Kapitel) fest belegte Tasten. + +Praktische Tips: Man sollte die Tastatur nicht mit Lernsequenzen überlasten, +weil man sich viele Tasten nicht merken kann. Besser ist es, einige wenige +Tasten fest zu belegen und andere für momentane Aufgaben einzusetzen. + +Der Einsatz von Lernsequenzen ist besonders sinnvoll zum Schreiben von An- +weisungen für die Textkosmetik. Anweisungen wie z.B. 'unterstreichen ein- +schalten', Schrifttyp-Anweisung usw. werden zweckmäßigerweise auf Tasten +gelegt. + +Hat man sich einmal beim Lernen verschrieben, so ist das nicht weiter +schlimm: es kann ohne Bedenken korrigiert werden (z.B. mit der Taste RUBOUT). +Solche Tastenanschläge werden dann allerdings auch gelernt, was man aber +beim Einsetzen der Lernsequenz kaum sieht. + +Merke: Tastenanschläge werden mit ESC HOP gelernt und mit ESC HOP 'taste' +auf eine Taste gelegt. Mit ESC 'taste' kann die Lernsequenz jederzeit abge- +rufen werden. + + + +Mehrere Zeilen auf einmal verarbeiten: Markieren + +Oft ergibt sich die Notwendigkeit, mehrere Zeilen oder ganze Textpassagen zu +löschen oder zu verschieben. Hierbei hilft die Taste MARK, mit der man Texte +markieren (also kennzeichnen) kann. Die so markierten Texte können dann auf +verschiedene Weisen als Ganzes verarbeitet werden. + +Durch Drücken der Taste MARK wird die Markierung eingeschaltet und - bei +erneuter Betätigung - wieder ausgeschaltet. Der Anfang der Markierung wird +"festgehalten" und man kann nun das Markierende durch die Positionierungs- +tasten und die HOP-Taste in Richtung auf das Dateiende verschieben, wobei +die dazwischen liegenden Zeichen markiert (in der Regel "video-invertiert" +dargestellt) werden. Ein so markierter Text kann mit ESC RUBOUT gelöscht +werden. Markieren und löschen mit ESC RUBOUT ist eine bequeme und sichere +Löschmethode, da man genau sieht, was gelöscht wird. + +Der gelöschte Abschnitt ist aber nicht vollständig gelöscht, sondern er kann +an anderer (oder an der gleichen) Stelle im Text durch ESC RUBIN wieder ein- +efügt werden. Dies gilt aber nur für den zuletzt gelöschten Text. Auf diese +Art kann ein Textabschnitt beliebiger Länge an eine andere Stelle des Textes +sicher, schnell und bequem verschoben werden. Zusätzlich ist das nachträg- +liche Korrigieren von fehlerhaften Löschungen leicht möglich, weil der Text +wieder mit ESC RUBIN leicht reproduziert werden kann. + +Mit eingeschalteter Markierung kann auch geschrieben werden. Das markierende +Schreiben ist eine besonders vorsichtige Art der Texterstellung, denn der +Texteinschub bleibt erst durch Ausschalten der Markierung (MARK) wirklich +bestehen. Er kann wieder gelöscht werden (ESC RUBOUT) und an eine andere +Stelle gebracht werden (ESC RUBIN). Beim markierenden Schreiben wirkt +RUBOUT immer auf das zuletzt geschriebene Zeichen. + +Die Markierung kann auch dazu verwendet werden, auf markierte Textabschnitte +eigene Benutzerprogramme anzuwenden. + +Merke: Die Markierung schaltet man durch die Taste MARK ein und aus. Ein +markierter Abschnitt kann gelöscht werden (ESC RUBOUT) und an einer anderen +Stelle wieder eingefügt werden (ESC RUBIN). Mit eingeschalteter Markierung +kann auch geschrieben werden. Die Markierung dient ebenfalls als Parameter +für Textverarbeitungsprogramme. + + + +Zwei einfache Kommandos + +Einige Operationen kann man nur mühselig mit den bis jetzt beschriebenen +Tasten durchführen. Z.B. ist es sehr zeitaufwendig, eine bestimmte Text- +stelle zu finden. Andere Operationen sind mit den im vorigen Kapitel be- +schriebenen Tasten überhaupt nicht möglich, wie etwa die Zeilenbreite ein- +zustellen oder Programme aufzurufen, die die zu editierende Datei ver- +arbeiten. Solche Operationen werden durch Kommandos ermöglicht, die man vom +Editor aus geben kann. + +Durch zweimaliges Betätigen von ESC erfolgt die Aufforderung + + gib kommando : + +Es erscheint auf dem Bildschirm eine Kommandozeile, in der der Benutzer +Kommandos (d.h. ELAN-Programme) schreiben kann. Durch Betätigen der Taste +RETURN wird das Kommando ausgeführt. Beispiel: + + ESC ESC (* es erscheint 'gib kommando :' *) + "diese Zeichen" + RETURN + +Durch die Angabe eines TEXTes in Anführungstrichen wird nach dem einge- +schlossenen TEXT 'diese Zeichen' ab der aktuellen Cursor-Position gesucht. +Wird 'diese Zeichen' gefunden, bleibt der Cursor auf dem gesuchten Text +stehen. Andernfalls steht der Cursor hinter dem Ende der letzten Zeile der +Datei. Weiteres Beispiel: + + ESC ESC + 127 + RETURN + +Durch dieses Kommando wird auf die 127. Zeile positioniert. + +Diese beiden häufig benötigten Kommandos haben eine Sonderstellung und +werden speziell behandelt, weil sie nicht der allgemeinen ELAN-Syntax ent- +sprechen. Darum dürfen sie auch nicht in Verbindung mit anderen Kommandos +verwendet werden (siehe nächsten Abschnitt). Alle anderen Kommandos, die wir +in den nächsten Abschnitten beschreiben, entsprechen der ELAN-Syntax und +sind somit allgemeine Kommandos. + +Merke: Kommandos nach man nach zweimaligen Betätigen der ESC-Taste schreiben. +Mit RETURN wird die Ausführung des Kommandos ausgelöst. Durch Angabe eines +TEXTes wird ab der aktuellen Cursor-Position nach diesem TEXT gesucht. Durch +die Angabe einer ganzen Zahl (INT) wird auf die entsprechende Zeilennummer +in der Datei positioniert. + + + +Beliebige Kommandos + +Beliebige Kommandos (siehe Monitor-Beschreibung) und ELAN-Programme sind +zulässig. + +Die Kommandozeile kann wie eine "normale" Textzeile editiert werden (Posi- +tionieren, Überschreiben, Einfügen, Löschen und Markieren). Erzeugt ein +Programm eine Ausgabe oder rufen fehlerhafte Kommandos Fehlermeldungen +hervor, werden diese in der ersten Zeile des Bildschirms angezeigt. Danach +ist man wieder im Editor und kann wie gewohnt arbeiten. + +Die oben beschriebenen zwei Spezial-Kommandos kann man nicht mit anderen +Kommandos zusammen verbinden (mit ';'). Deshalb gibt es für sie auch eine +ELAN-Form, die es erlaubt, sie mit anderen Kommandos zusammen zu verwenden: + +a) TEXT suchen ab der aktuellen Cursor-Position (D ist eine Abkürzung für + 'DOWN'): + + "diese Zeichen" (* Spezial-Version *) + D "diese Zeichen" (* Allgemeine Version *) + +b) Auf eine Zeile Positionieren (T ist eine Abkürzung für TO LINE): + + 127 (* Spezial-Version *) + T 127 (* Allgemeine Version *) + +Es können mehrere Kommandos in der Kommandozeile angegeben werden. Die ein- +zelnen Kommandos müssen in diesem Fall mit ';' voneinander getrennt werden. +Beispiel: + + ESC ESC + T 1; D "noch Zeichen" RETURN + +Diese zwei Kommandos werden nacheinander ausgeführt. Zuerst wird auf die +erste Zeile positioniert und dann (von der ersten Zeile) nach 'noch Zeichen' +gesucht. Damit ist es möglich, die Datei nicht nur von der aktuellen Zeile zu +durchsuchen, sondern die gesamte Datei. Soll nicht in Richtung auf das Datei- +ende, sondern in Richtung auf den Dateianfang (also nach "oben") gesucht +werden, kann man das U-Kommando (Abkürzung für UP) verwenden: + + ESC ESC + U "noch'n Text" RETURN + +Ein weiteres Kommando ist das C-Kommando (Abkürzung für 'CHANGE'), mit +welchem man einen TEXT sucht und diesen dann ersetzen kann. Beispiel: + + ESC ESC + "alte Zeichen" C "neue Zeichen" RETURN + +Es wird ab der aktuellen Cursor-Position nach 'alte Zeichen' gesucht. Wird +der TEXT gefunden, wird er durch 'neue Zeichen' ersetzt. Der Cursor befindet +sich in diesem Fall nach dem ersetzten TEXT. Wird 'alte Zeichen' dagegen +nicht in der Datei gefunden, befindet sich der Cursor (wie beim erfolglosen +Suchen mit D) am Ende der letzten Zeile der Datei. + +Wie alle andern Kommandos kann auch das C-Kommando mit anderen Kommandos +verbunden werden. Beispiel: + + ESC ESC + T 500; "Schreibfelher" C "Schreibfehler" RETURN + +Hier wird ab der 500. Zeile der Datei nach 'Schreibfelher' gesucht und ggf. +ersetzt. Soll ein TEXT nicht nur einmal, sondern bei jedem Auftreten ersetzt +werden, benutzt man das CA-Kommando (Abkürzung für CHANGEALL): + + ESC ESC + "dieser alte Text" CA "dieser neue Text" RETURN + +Dadurch wird 'dieser alte Text' bei jedem Auftreten ab der aktuellen Cursor- +Position durch 'dieser neue Text' ersetzt. + +Merke: Mehrere Kommandos werden mit ';' verbunden. + + + +Kommandos auf Tasten legen + +Oft benutzte Kommandos können auf Tasten gelegt werden. Damit ist es möglich, +den Editor auf spezielle Bedürfnisse eines Benutzers zu modifizieren. + +Anstatt der Taste RETURN beim Abschluß können oft benutzte Kommandos mit der +Drei-Tastenfolge ESC ! 'taste' auf eine Taste gelegt werden. Beispiel: + + ESC ESC (* es erscheint die Kommandozeile *) + D "Schreibfehler" + ESC ! s (* das Kommando 'DOWN "Schreibfehler"' ist + nun auf die Taste 's' gelegt *) + +Wird nun die Taste 's' gedrückt, erscheint das Zeichen 's' auf dem Bildschirm. +Mit ESC s wird das D-Kommando ausgeführt. Natürlich können auch komplizier- +tere ziertere Kommandos auf Tasten gelegt werden. + +Einige Tasten sind bereits mit Kommandos belegt (man kann sie aber ver- +ändern). Will man ein Kommando, welches auf eine Taste gelegt wurde, ver- +ändern oder löschen, drückt man im Kommandodialog (!) die Drei-Tastenfolge +ESC ? 'taste'. Beispiel: + + ESC ESC (* in den Kommandodialog gehen *) + ESC ? s (* es erscheint nun: 'D "Schreibfehler"' *) + +Dieses Kommando kann nun z.B. verändert und ausgeführt (durch RETURN) oder +wiederum auf die gleiche oder eine andere Taste gelegt werden (durch +ESC ! 'taste'). + +Die Ausführung eines Kommandos kann meist mit ESC abgebrochen werden, +z.B. wenn ein Suchkommando unerwünscht weit reicht. + +Merke: Kommandos können auf Tasten gelegt werden (wie beim Lernen). Das +letzte Kommando kann durch ESC f wiederholt werden. + + + +Die wichtigsten Kommandos zur Textverarbeitung + +Einige Kommandos sind speziell für die Textverarbeitung im Editor program- +miert. Die wichtigsten werden hier vorgestellt. + +Kommando Bedeutung +----------------------------------------------------------------------------- +"text" Text suchen: +D "text" Der zu suchende Text muß in Anführungszeichen geschrieben + werden (damit werden auch Leerzeichen innerhalb des ge- + suchten Textes wichtig). Es wird ab der Stelle in der + Datei in Richtung auf das Dateiende hin gesucht (also + "nach unten"), an der sich der Cursor befindet. Wird der + Text gefunden, positioniert der Editor den Cursor direkt + dahinter. Beispiel: + + D "Autor" + + sucht nach dem ersten Auftreten von 'Autor'. Beachte, daß + bei der Suche nach Zeichen, die man nicht direkt mit der + Tastatur schreiben kann, der Codewert angegeben werden + muß (vergl. dazu die EUMEL-Codetabelle). Beispiel: + + DOWN ""217"" (* sucht ein ä *) + DOWN "Diesen Text mu"251" man finden" + + (Ein Codewert innerhalb eines Textes muß in " einge- + schlossen werden). + Wird nur ein Text gesucht, kann man auch nur diesen + angeben. Beispiel: + + "diesen fehler" + +D nummer (Relatives) Positionieren in Richtung auf das Dateiende. + Beispiel: + + D 75 + + positioniert um 75 Zeilen in Richtung auf das Dateiende. + +U "text" Analog D, aber in Richtung auf den Dateianfang ("nach + oben"). + +U nummer Analog D, aber in Richtung auf den Dateianfang. + +nummer Absolutes Positionieren: +T nummer Durch Angabe einer Zahl, wird auf die entsprechende + Zeile der Datei positioniert. Beispiel: + + T 317 + 317 + + Ist die Datei bereits vor der Zeile '317' zu Ende, wird + auf die letzte Zeile der Datei positioniert. + +"alt" C "neu" Suchen und Ersetzen eines Textes: Sucht nach dem Text + 'alt'. Falls vorhanden, wird 'alt' durch 'neu' ersetzt. + Beispiel: + + "einfach" C "leicht" + + ersetzt 'einfach' durch 'leicht'. + +"alt" CA "neu" Suchen aller 'alt' ab der aktuellen Position bis zum + Dateiende und ersetzen durch 'neu'. + +type ("text") Schreiben eines 'text' durch ein Kommando. Das type-Kom- + mando wird häufig benutzt, um Zeichen zu schreiben, die + nicht auf der Tastatur zu finden sind. In diesem Fall muß + der Codewert des Zeichens angegeben werden (jeweils in + doppelten "). Beispiel (vergl. auch EUMEL-Codetabelle): + + type (""251"") + + schreibt ein ß an die aktuelle Position der Zeile. + +Merke: Durch das D- bzw. U-Kommando kann ein Text in der Datei gesucht +werden. Mit C kann ein Text gesucht und ersetzt werden. "alt" CA "neu" er- +setzt alle 'alt' durch 'neu'. 'type' schreibt ein Zeichen (oder einen Text). +Durch T kann auf eine bestimmte Zeile der Datei positioniert werden. + + + +Texte aus anderen Dateien einfügen oder in andere Dateien schreiben + +Manchmal ist es notwendig, einen Text in eine andere Datei zu schreiben +(z.B. wenn man diesen Text noch einmal verwenden will) oder einen Text einer +anderen Datei in den zu bearbeitenden Text einzufügen. Die GET- und PUT- +Kommandos bieten die Möglichkeit, Texte zwischen Dateien auszutauschen +(vergl. auch Paralleleditor). + +Das Kommando GET 'dateiname' holt den Text der Datei "dateiname" an die +aktuelle Schreibposition. Beispiel: + + GET "absender" + +holt den Text 'absender'. Wenn also des öfteren Briefe geschrieben werden, +braucht man sich den Absender nur einmalig in die Datei 'absender' zu schrei- +ben und kann diesen mit dem Kommando GET (was man auf eine Taste legen kann) +u.U. mehrmals an verschiedenen Stellen in die Datei einfügen. + +Das Kommando PUT (abgekürzt: P) schreibt einen vorher markierten Text in +eine Datei. Beispiel: + + PUT "Tabelle" + +schreibt einen markierten Text in die Datei 'Tabelle'. 'Tabelle' wird ggf. +eingerichtet. Ist die Datei 'Tabelle' bereits vorhanden, so wird erfragt, ob +die Datei gelöscht werden kann, um den markierten Text aufzunehmen (über- +schreiben). Andernfalls wird der markierte Text an den bereits vorhandenen +Text in 'Tabelle' angefügt. Es ist somit durch mehrmaliges markieren und dem +PUT-Kommando möglich, Texte aus einer Datei aufzusammeln und in eine neue +Datei zu geben. + +Merke: Die GET- und PUT-Kommandos schreiben bzw. holen Texte aus Dateien. + + + +Breitere Zeilen bearbeiten + +Der Editor ist auf eine Zeilenbreite von 77 Zeichen eingestellt. Oft ist es +notwendig, mit einer anderen Zeilenbreite zu schreiben, welches man mit dem +LIMIT-Kommando einstellen kann. Aber auch die Positionierung innerhalb einer +Zeile wird dadurch etwas anders, weil bei breiteren Zeilen als die Bild- +schirmbreite die Zeile nicht auf einmal auf den Bildschirm paßt. In diesem +Fall wird gerollt. + +Eine andere Zeilenbreite stellt man durch 'limit' ein. Beachte, daß die somit +eingestellte Zeilenbreite für die gesamte Datei gilt. Beispiel: +(Soll eine veränderte Zeilenbreite nur für einen Abschnitt gelten, muß man +eine Textkosmetik-Anweisung einfügen, welches erst nach Anwendung von +'lineform' wirkt.) + + limit (180) + +Nun kann man wie gewohnt schreiben. Allerdings wird die aktuelle Zeile, in +der man sich befindet, nicht wie gewohnt am Bildschirmende umgebrochen, +sondern erst an der Spalte 180 (sofern sie nicht vorher durch die RETURN- +Taste beendigt wird). Wird über das rechte Bildschirmende hinaus geschrieben, +bleibt die Cursor-Position am Ende des Bildschirms erhalten, aber die Zeile +wird beim weiteren Schreiben nach links verschoben, "rollt" also nach links +(der Anfang der Zeile verschwindet scheinbar nach links). + +Mit der Positionierung verhält es sich ähnlich. Wird über den rechten Bild- +schirmrand mit RECHTS positioniert, wird die Zeile ebenfalls gerollt. HOP +RECHTS dagegen bewirkt ein Blättern nur innerhalb dieser Zeile nach rechts. +Analog verläuft es bei verschobener Zeile, wenn nach links (LINKS bzw. HOP +LINKS) positioniert wird. + +Beim Schreiben von Tabellen kann es sinnvoll sein, das Fenster vorübergehend +auf eine andere Anfangsposition (als 1) einzustellen. Das kann mit dem +'margin'-Kommando erfolgen. Beispiel: + + margin (50) + +Das Fenster des Editors zeigt nun einen Ausschnitt aus der Datei, beginnend +ab Spalte 50. In der Titelzeile wird "M50" angezeigt. + +Merke: Eine veränderte Zeilenbreite wird mit dem limit-Kommando eingestellt. +Wird über den Bildschirmrand positioniert, wird die Zeile gerollt. Mit dem +'margin'-Kommando kann spaltenmäßig ein Anfangspunkt des Fensters einge- +stellt werden. + + + +Paralleles Editieren (Fenstereditor) + +Oft ist notwendig, mit mehreren Dateien gleichzeitig zu arbeiten, z.B. wenn +aus einer Datei etwas in eine andere kopiert werden muß, wenn Fehler durch +die Textkosmetik-Programme oder einen Compiler gefunden werden oder wenn man +kurz etwas in einer andern Datei nachschauen will. Zu diesem Zweck bietet der +Editor die Möglichkeit, zwei (oder mehr) Dateien zur gleichen Zeit zu be- +arbeiten. + +Um ein neues Editor-Fenster einzuschachteln, betätigt man im Editor + + ESC e + +Dies eröffnet ein Fenster auf eine andere Datei, deren Name interaktiv er- +fragt wird. Die obere linke Ecke des Fensters befindet sich an der aktuellen +Cursor-Position. Dabei darf sich der Cursor nicht zu sehr am rechten oder +unteren Rand befinden (weil das Fenster sonst zu klein würde). In diesem +"Fenster" auf eine andere Datei kann man genauso arbeiten, wie im "normalen" +Editor. ESC q verläßt den aktuellen Fenstereditor (und alle darin einge- +schachtelten Fenster). + +Mit der Tastenfolge + + ESC w + +kann man von einem Fenster in das benachbarte wechseln (zyklisch). Insbeson- +dere kann ein markierter Teil einer Datei mit dem Kommando + + ESC p (* oder: PUT "" *) + +in eine temporäre Datei geschrieben und nach ESC w mit + + ESC g (* oder: GET "" *) + +in die andere Datei eingefügt werden. + +Betätigt man ESC e ungefähr in der Mitte des Bildschirms, hat man das Fenster +auf die neue Datei in der unteren Hälfte des Bildschirms und die "alte" Datei +in der oberen Bildschirmhälfte. Dies nennt man "Paralleleditor", weil zwei +Dateien zur gleichen Zeit editiert werden können. Der Paralleleditor wird +auch von anderen Programmen benutzt, wie z.B. dem ELAN-Compiler, um Fehler- +meldungen bequem anzuzeigen. + +Das Notizbuch schlägt man mit + + ESC n + +auf. In diesem Notizbuch werden Informationen durch die Prozedur + + note + +geschrieben. + +Merke: Der Fenstereditor wird durch ESC e aufgerufen und mit ESC q verlassen. +Mit ESC w kann zwischen Dateien umgeschaltet werden. In jeder Datei stehen +die gleichen Funktionen wie im "einfachen" Editor zur Verfügung. Man kann +markierte Texte mit PUT bzw. GET von einer Datei in die andere bringen +(Kopieren). + + + +Arbeiten mit dem Zeileneditor + +Der Zeileneditor erlaubt ein Editieren einer Eingabe mit allen Editor- +Funktionen. + +Der Zeileneditor (auch "Feldeditor" genannt) wird über die Prozedur + + editget + +aufgerufen. Durch diese Prozedur kann eine Zeile vom Terminal wie im Editor +eingegeben werden, d.h. es können u.a. Einfügungen bzw. Löschungen in der +Zeile vorgenommen werden. 'editget' dient darum als Grundlage für alle 'get'- +Prozeduren. Beispiel: + + TEXT VAR eingabe :: ""; + put ("Bitte geben Sie einen Wert ein:"); + editget (eingabe); + line + +'editget' kann aber auch einen Wert ausgeben, den ein Benutzer ggf. +verändern kann. Beispiel: + + TEXT VAR eingabe :: "trium10"); + put ("Bitte Schrifttyp angeben:"); + editget (eingabe); + line + +Hier kann ein Benutzer den TEXT 'trium10' verändern oder nur RETURN betäti- +gen. + +Es gibt noch weitere Versionen von 'editget', bei denen man die Zeilenbreite, +reservierte Tasten u.a.m. angeben kann. + +Merke: 'editget' ist der Zeileneditor. + + + +3. Vorbelegung von Tasten + +Wie schon beschrieben, können Lernsequenzen und Kommandos (d.h. ELAN- +Programme) Tasten zugeordnet werden. Da einige Funktionen häufig benötigt +werden, sind diese standardmäßig bestimmten Tasten zugeordnet. + + + +Kommandodialog + +ESC ESC Kommandodialog einschalten. + +ESC ! taste Im Kommandodialog: geschriebenes Kommando auf Taste legen. + +ESC ? taste Im Kommandodialog: Auf 'taste' gelegtes Kommando anzeigen zum + Editieren. + +ESC k Im Kommandodialog: Das zuletzt editierte ELAN-Programm an- + zeigen. + + + +Lernen + +ESC HOP Lernen einschalten. + +ESC HOP taste Lernsequenz auf 'taste' legen. + + + +Operationen auf Markierungen + +ESC RUBOUT Markiertes "vorsichtig" löschen. + +ESC RUBIN Vorsichtig Gelöschtes einfügen. + +ESC p Markiertes in die Scratch-Datei kopieren (PUT ""), an + schließend löschen (kann mit ESC g an anderer Stelle re- + produziert werden). + +ESC d Duplizieren: Markiertes in die Scratch-Datei kopieren + (PUT ""), anschließend die Markierung abschalten. (Kann mit + ESC g beliebig oft reproduziert werden). + +ESC g MIT ESC p gelöschtes oder mit ESC d dupliziertes an aktuelle + Cursor-Stelle schreiben, d.h. Scratch-Datei an aktueller + Stelle einfügen (GET ""). + + + +Weitere Operationen + +ESC q Verlassen des Editors. + +ESC e Fenstereditor einschalten. + +ESC n Notizbuch "aufschlagen". + +ESC w Dateiwechsel beim Fenstereditor. + +ESC f Nochmalige Ausführung des letzten Kommandos + +ESC b Das Fenster wird auf den linken Rand der aktuellen (ggf. + verschobenen) Zeile gesetzt. + +ESC RECHTS Zum nächsten Wortanfang. + +ESC LINKS Zum vorigen Wortanfang. + +ESC 1 Zum Anfang der Datei. + +ESC 9 Zum Ende der Datei. + + + +Zeichen schreiben + +ESC a Schreibt ein ä. +ESC A Schreibt ein Ä. +ESC o Schreibt ein ö. +ESC O Schreibt ein Ö. +ESC u Schreibt ein ü. +ESC U Schreibt ein Ü. +ESC s Schreibt ein ß. +ESC ( Schreibt eine [. +ESC ) Schreibt eine ]. +ESC < Schreibt eine {. +ESC > Schreibt eine }. +ESC \# Schreibt ein \#, was auch gedruckt werden kann. +ESC blank Schreibt ein (geschütztes) Leerzeichen. + + + +4. Komplexere Kommandos (ELAN-Programme) + +In diesem Kapitel finden Sie (neben den bereits in den vorherigen Kapiteln +beschriebenen) eine Übersicht über die vorgefertigten Kommandos. Weitere +können leicht vom Benutzer und Programmierer selbst erstellt werden. + + + +Wiederholungen schreiben + +In der Programmiersprache ELAN gibt es ein Sprachmittel, um Anweisungen +wiederholen zu lassen. Dieses Sprachmittel nennt man Wiederholungsanweisung +oder Schleife. Durch dieses Sprachmittel ist es leicht möglich, eine oder +mehrere Kommandos mehrmals ausführen zu lassen. + +Eine Wiederholung, meist Schleife genannt, wird durch die Worte REP (steht +für 'REPEAT', was soviel wie 'wiederhole' heißt) und PER (die Umkehrung von +REP) oder END REP gebildet. Alle Anweisungen, die zwischen diesen Worten +stehen, werden wiederholt ausgeführt (bis das Ende der Datei erreicht ist). +Damit kann man einen Text in der gesamten Datei ändern. (In den folgenden +Beispielen schreiben wir die Kommandozeile der besseren Übersichtlichkeit +halber in mehreren Zeilen). Beispiel: + + T 1; + WHILE NOT eof REP + "alter text" C "neuer text" + PER + +Durch die erste Anweisung wird zur ersten Zeile der Datei positioniert. Dann +steht im Programm eine sogenannte "abweisende Schleife", die durch 'WHILE +bedingung' eingeleitet wird (die Schleife wird solange ausgeführt, bis die +Bedingung nicht mehr erfüllt ist). Die Bedingung besteht hier aus einer Ab- +frage auf das Dateiende der bearbeiteten Datei ('eof'). Nach Eintritt in die +Schleife wird nach 'alter text' gesucht. Falls gefunden, wird er durch +'neuer text' ersetzt. Das Suchen und ersetzen wird solange durchgeführt, bis +das Dateiende erreicht wird. Falls 'alter text' nicht gefunden wird, steht +man auf dem letzten Zeichen der letzten Zeile der Datei (wie bei einer er- +folglosen wiederholten letzten Suche), so daß die nächste WHILE-Überprüfung +die Schleife abbricht. + +Die meisten der oben beschriebenen Kommandos gibt es nicht nur als Operato- +ren, sondern auch als Prozeduren. Beispiele: + + T 1 ==> toline (1) + D "text" ==> down ("text") + U "text" ==> up ("text") + D 17 ==> down (17) + U 18 ==> up (18) + "alt" C "neu" ==> change to ("alt", "neu") + "alt" CA "neu" ==> change all ("alt", "neu") + +Man kann also das obige Beispiel auch folgendermaßen programmieren: + + toline (1); + WHILE NOT eof REP + change to ("alter text", "neuer text") + PER + +Durch dieses zusammengesetzte Editor-Kommando können also ein oder mehrere +Worte in der gesamten Datei auf einfache Weise geändert werden. +Natürlich kann man das obige Beispiel einfacher schreiben: + + toline (1); change all ("alter text", "neuer text") + +Was muß man nun programmieren, um eine Ersetzung nur einmal pro Zeile vor- +zunehmen? Erinnern wir uns: nach einer Ersetzung steht der Cursor hinter dem +ersetzten Text. Somit finden wir bei der erneuten Suche unter Umständen den +Text nochmals in der aktuellen Zeile. Wenn wir nach einer Ersetzung aber um +eine Zeile vorwärts positionieren (mit 'down (1)'), kann dies nicht ge- +schehen. Leider wird durch die Vorwärts-Positionierung die Position des +Cursors nicht verändert. Somit kann die erneute Suche einen Text in der +nächsten Zeile verpassen. Man muß also neben der Vorwärts-Positionierung um +eine Zeile zusätzlich auch noch an den Anfang der Zeile gehen. Für die +Positionierung innerhalb einer Zeile gibt es die Prozedur + + col (17) (* Positioniert auf die 17. Spalte + der aktuellen Zeile *) + +Damit können wir nun eine einmalige Ersetzung in einer Zeile programmieren: + + toline (1); + WHILE NOT eof REP + col (1); + change to ("alter text", "neuer text"); + down (1); + PER + +Es wird erst auf die erste Zeile, erste Spalte positioniert. Dann wird 'alter +text' gesucht und ggf. durch 'neuer text' ersetzt. Danach wird eine Zeile +vorwärts positioniert, wiederum auf Spalte 1. Dadurch ist gewährleistet, daß +eine Ersetzung nur einmal pro Zeile vorgenommen wird und immer von der +ersten Spalte einer Zeile aus gesucht wird. Dies geschieht solange, bis das +Ende der Datei erreicht ist. + +Manchmal ergibt sich die Notwendigkeit, in Tabellen in jeder Zeile noch Leer- +spalten einzufügen oder zu entfernen. Auch dies kann mit der Schleife leicht +erledigt werden: + + toline (1); + WHILE NOT eof REP + col (48); + "" C " "; + down (1) + PER + +Hier werden in jeder Zeile an der Spalte 48 drei Leerzeichen eingefügt. In +diesem Fall suchen wir ab der Spaltenposition 48 einen sogenannten "Niltext" +("leerer Text"). Dieser Text wird natürlich immer gefunden. Aber man muß +hier aufpassen, denn der gesuchte Text sollte in dieser Zeile vorhanden sein, +sonst wird in einer der nächsten Zeilen ein TEXT ersetzt, der nicht unbe- +dingt an der Spaltenposition 48 steht! + +Wie bereits angemerkt, sollten in den zu verändernden Zeilen an der Position +48 ein Leerzeichen stehen, sonst wird das C-Kommando fehlerhaft bei dem +nächsten TEXT ausgeführt. Das kann man verhindern, indem man folgendes +programmiert: + + toline (1); + WHILE NOT eof REP + down (" "); (* sucht das naechste Blank ab Spalte 48 *) + IF col = 48 + THEN change to (" ", " "); + FI + END REP + +Die Prozedur 'col' (ohne Parameter) liefert die aktuelle Spaltenposition +innerhalb einer Zeile. + +Manchmal soll eine Änderung nur in einem bestimmten Bereich vorgenommen +werden. Dazu gibt es die Prozedur 'line no', mit der man die aktuelle Zeilen- +nummer erfragen kann. Beispiel: + + toline (50); + WHILE NOT eof REP + aenderungen + UNTIL line no = 100 END REP + +In diesem Beispiel werden 'aenderungen' im Zeilenbereich 50 - 100 vorgenom- +men. 'line no' liefert die aktuelle Zeilennummer des FILEs, welches gerade +vom Editor bearbeitet wird. + +Weitere Beispiele: + + (* suchen in Spalte 17: *) + REP + down ("muster") + UNTIL eof OR col = 17 END REP + + (* in Spalte 1 ersetzen: *) + REP + down ("alt"); + IF col = 1 + THEN "alt" C "neu" + FI + UNTIL eof END REP + +Merke: Eine Wiederholung REP ... PER führt die in ihr enthaltenen An- +weisungen wiederholt aus. Eine Abfrage auf das Dateiende der bearbeiteten +Datei ist durch 'eof' möglich. + + + +Das Notizbuch + +Im Notizbuch kann man sich Notizen über den Ablauf von Kommandos machen. + +Die Prozedur + + note + +schreibt einen INT- oder TEXT-Parameter in eine Zwischendatei. Diese Datei +kann man sich mit + + ESC n + +anschauen. Beispiel: + + (* ersetzen und notieren: *) + REP + "alt" C "neu"; + note (line no) (* Zeilennummer der Ersetzung notieren *) + UNTIL eof END REP + +Merke: Die Prozedur 'note' schreibt in das Notizbuch. Mit ESC n kann man +sich das Notizbuch anschauen. + + + +Neue Editor-Kommandos bereitstellen + +Sollen neue Editor-Kommandos bereitgestellt werden, muß man dem Editor ggf. +mitteilen, ob und wie das Fenster auf die Datei auf dem Bildschirm neu ge- +schrieben werden muß. + +Neue Editor-Kommandos kann man allen Benutzern bereitstellen, in dem ein +Programm geschrieben wird. Beispiel: + + PROC datum schreiben: + type (datum). + + datum: + date (clock (1)). (* Siehe auch TEIL 8: Standardpakete *) + END PROC datum schreiben + +Diese Prozedur (oder mehrere) muß noch in ein PACKET "gekleidet" und dann +insertiert werden. Dann steht 'datum schreiben' allen Benutzern dieser Task +oder dessen Sohn-Task zur Verfügung (siehe dazu auch TEIL 5: ELAN-Compiler). + +Bei etwas komplizierteren Prozeduren sollte man dem Editor mitteilen, ob und +wie er das Fenster auf die Datei auf dem Bildschirm neu schreiben muß. +Normalerweise schreibt der Editor nach einem Kommando den gesamten Bild- +schirm neu. Dies kann man verhindern, indem man die Prozedur + + nichts neu + +aufruft. Sie teilt dem Editor mit, daß das Fenster nicht neu geschrieben +werden muß. Weitere Prozeduren teilen dem Editor mit, daß Teile des Fensters +neu geschrieben werden müssen: + + satznr neu (* Zeilennummer links oben *) + ueberschrift neu + zeile neu + abschnitt neu + bild neu + +Dabei kann man die Prozeduren in beliebiger Reihenfolge aufrufen, wobei +jeweils immer die größte Änderung dominiert. Beispiel: + + nichts neu; + ... + zeile neu; + ... + bild neu; + ... + ueberschrift neu + ... + +'bild neu' dominiert über 'zeile neu', +'zeile neu' dominiert über 'ueberschrift neu'; +'ueberschrift neu' dominiert über 'nichts neu'. + +Im obigen Beispiel 'datum schreiben' würde es also ausreichen, am Anfang der +Prozedur 'nichts neu' und am Ende 'zeile neu' aufzurufen, damit nur die +aktuelle Zeile neu geschrieben wird. + +Manchmal ist es notwendig, dem Benutzer bei einer Kommandoverarbeitung neue +Zustände direkt anzuzeigen. Dafür gibt es die Prozeduren + + satznr zeigen + ueberschrift zeigen + bild zeigen + +Beispiel: + + satznr zeigen (line no) + +zeigt bei einer Kommandoverarbeitung die aktuelle Zeilenummer. + +Merke: Normalerweise baut der Editor nach einer Kommandoausführung das +Fenster auf dem Bildschirm neu auf. Mit 'nichts neu' kann das verhindert +werden. Weitere Prozeduren teilen dem Editor mit, welche Fensterteile neu +geschrieben werden müssen. Das Schreiben von Fensterteilen kann auch direkt +ausgelöst werden. + + + +Die ELAN-Notation + +Kommandos werden in ELAN-Notation beschrieben. Dabei bedeuten: + +OP Operator. + Der Name des Operators muß mit grossen Buchstaben vor oder + zwischen die Operanden geschrieben werden. Beispiele: + OP C (TEXT CONST muster, pattern) + --> "alt" C "neu" + +PROC Prozedur. + Der Name der Prozedur muß klein geschrieben werden. Die + Parameter werden in Klammern angefügt. Beispiele: + PROC getchar (TEXT VAR zeichen) + --> getchar (character) + PROC edit (TEXT CONST datei, + INT CONST x, y, xsize, ysize) + --> edit ("meine datei", 1, 1, 79, 24) + +INT Ganze Zahl ('Integer'). + Der Wert ist eine ganze Zahl (ohne Dezimalpunkt!). + +BOOL Wahrheitswert ('Boolean'). + Hat zwei Werte: TRUE ('Wahr') und FALSE ('Falsch'). + +TEXT Text. + Muß in Anführungszeichen geschrieben werden. Soll das + '"'-Zeichen in einem Text vorkommen, muß es doppelt + geschrieben werden. + +VAR Veränderbarer Wert. + Wert kann von der Prozedur oder dem Operator verändert + werden. + +CONST Unveränderbarer Wert. + Wert kann von der Prozedur oder dem Operator nicht ver- + ändert werden. + + + +Kommando-Übersicht + +In dieser Übersicht werden Editor-Kommandos, die in der Regel nur in Pro- +grammen verwendet werden, mit (P) gekennzeichnet. "Nicht-Programmierer" +brauchen also nur die nicht gekennzeichneten Kommandos zu lesen. Alle hier +aufgeführten Kommandos arbeiten auf die vom Editor bearbeitete Datei +('editfile'). Einige der Prozeduren stehen auch zur allgemeinen Dateiver- +arbeitung zur Verfügung (siehe TEIL 7), allerdings dann mit einem zusätz- +lichen FILE-Parameter. + +abschnitt neu (P) + PROC abschnitt neu (INT CONST von zeile, bis zeile) + Zweck: Mitteilung an den Editor, daß der entsprechende Abschnitt + auf dem Bildschirm neu geschrieben werden muß. + +at (P) + BOOL PROC at (TEXT CONST muster) + Zweck: Feststellen, ob der Editor auf 'muster' steht. Die Cursor- + Position wird dabei nicht verändert. + +bild neu (P) + PROC bild neu + Zweck: Mitteilung an den Editor, daß das Bild nach Kommandover- + arbeitung neu geschrieben werden muß. + +bild zeigen + PROC bild zeigen + Zweck: Mitteilung an den Editor, daß das Bild sofort neu geschrieben + werden muß. + +C + OP C (TEXT CONST muster, pattern) + Zweck: Wie D "muster" mit anschließender Ersetzung desselben durch + 'pattern'. + +change to (P) + PROC change to (TEXT CONST muster, pattern) + Zweck: Analog C. + + PROC change to (TEXT CONST muster, pattern, INT CONST number) + Zweck: Analog C, aber nur 'number' Zeilen weit. + +CA + OP CA (TEXT CONST source, destination) + Zweck: Arbeitet ab der aktuellen Position wie + + WHILE NOT eof REP + "source" C "destination" + END REP + +change all (P) + PROC change all (TEXT CONST source, destination) + Zweck: Analog CA. + +col (P) + PROC col (INT CONST pos) + Zweck: Positioniert auf die Spalte 'pos' der aktuellen Zeile. + Beispiel: + + col (37) + + positioniert auf die 37. Spalte der aktuellen Zeile. + + INT PROC col + Zweck: Liefert die aktuelle Position des Cursors innerhalb einer Zeile. + +D + OP D (INT CONST n) + Zweck: Positioniert das Fenster n Zeilen vorwärts in Richtung auf das + Dateiende. + + OP D (TEXT CONST muster) + Zweck: Sucht 'muster' vorwärts in Richtung auf das Dateiende. Die Suche + beginnt direkt hinter der aktuellen Cursor-Position. Wird 'muster' + nicht gefunden, steht der Cursor hinter dem letzten Zeichen der + Datei. Wird 'muster' gefunden, steht der Cursor direkt auf dem + ersten Zeichen von 'muster'. + +down (P) + PROC down (INT CONST n) + Zweck: Analog D. + + PROC down (TEXT CONST muster) + Zweck: Analog D. + + PROC down (TEXT CONST muster, INT CONST n) + Zweck: Analog D, jedoch geht die Suche nur 'n' Zeilen. + +downety (P) + PROC downety (TEXT CONST muster) + Zweck: Im Gegensatz zu 'down' beginnt die Suche mit dem aktuellen Zeiche + n, d.h. der Aufruf führt zu einer leeren Leistung, wenn der Cursor schon + auf 'muster' steht. Deshalb bei der Programmierung vorsichtig verwenden. + + PROC downety (TEXT CONST muster, INT CONST n) + Zweck: Analog 'downety', jedoch geht die Suche nur 'n' Zeilen und + beginnt bei der aktuellen Cursor-Position (siehe oben). + +editfile (P) + FILE PROC editfile + Zweck: Liefert die aktuell editierte Datei. + +eof + BOOL PROC eof + Zweck: Abfrage auf das Dateiende der zu bearbeitenden Datei. + +GET + OP GET (TEXT CONST dateiname) + Zweck: Kopiert den Inhalt der Datei mit dem angegebenen Namen vor die + aktuelle Cursor-Position. Ist die Quelldatei kopiert, wird nur + der markierte Teil kopiert. + + OP G (TEXT CONST dateiname) + Zweck: Wie GET. + +len (P) + INT PROC len + Zweck: Liefert die Länge der aktuellen Zeile. + +limit + OP limit (INT CONST limit) + Zweck: Setzt die rechte Schreibgrenze auf 'limit'. Beispiel: + + limit (120) + + stellt den Editor auf eine Zeilenlänge von 120 Zeichen. + + INT PROC limit + Zweck: Liefert die eingestellte Zeilenbreite. + +line no (P) + INT PROC line no + Zweck: Liefert die aktuelle Zeilennummer der editierten Datei. + +margin + PROC margin (INT CONST anfang) + Zweck: Alle Zeilen erscheinen erst ab Spalte 'anfang' im Sichtfenster. + Beispiel: + + margin (50) + + legt das Fenster ab Spalte 50 fest. + + INT PROC margin + Zweck: Liefert den eingestellten linken Rand. + +mark (P) + PROC mark (BOOL CONST an) + (Zweck: Schaltet die Markierung an der aktuellen Stelle ein bzw. aus. + Beispiel: + + mark (true) (* schaltet Markierung an *) + mark (false) (* schaltet Markierung aus *) + + BOOL PROC mark + Zweck: Liefert TRUE, sofern die Markierung eingeschaltet ist. + +nichts neu (P) + PROC nichts neu + Zweck: Mitteilung an den Editor, daß nach Kommandoverarbeitung das Bild + nicht neu geschrieben werden muß. + +note (P) + PROC note (INT CONST wert) + Zweck: Schreibt 'wert' in das Notizbuch. + + PROC note (TEXT CONST message) + Zweck: Schreibt 'message' in das Notizbuch. + +pattern found (P) + BOOL PROC pattern found + Zweck: Gibt an, ob der letzte Suchprozeß erfolgreich war. + +PUT + OP PUT (TEXT CONST dateiname) + Zweck: Richtet eine Datei mit dem angegebenen Namen ein, kopiert den + markierten Textabschnitt in diese. + + OP P (TEXT CONST dateiname) + Zweck: Wie PUT. + +satznr neu (P) + PROC satznr zeigen + Zweck: Mitteilung an den Editor, daß nach Kommandoverarbeitung die + Zeilennummer rechts oben neu geschrieben werden muß. + +satznr zeigen (P) + PROC satznr zeigen (INT CONST nr) + Zweck: Mitteilung an den Editor, die Zeilennummer 'nr' sofort neu zu + schreiben. + +T + OP T (INT CONST n) + Zweck: Positioniert auf die Zeile 'n'. + +toline (P) + PROC toline (INT CONST n) + Zweck: Analog T. + +type (P) + PROC type (TEXT CONST t) + Zweck: Trägt 't' in den Eingabestrom ('f kommando') des Editors ein. + Beispiel: + + type (text (sqrt (2.0))) + + fügt an die aktuelle Cursor-Position den Wert 1.41... ein. + Beispiel: + + INT VAR i; + FOR i FROM 1 UPTO 10 REP + type (text (i) + " ") + END REP + (* Ausgabe: 1 2 3 4 5 6 7 8 9 10 *) + +U + OP U (INT CONST n) + Zweck: Positioniert das Fenster n Zeilen rückwärts in Richtung auf den + Dateianfang. + + OP U (TEXT CONST muster) + Zweck: Sucht 'muster' rückwärts in Richtung auf den Dateianfang. Die + Suche beginnt links neben der aktuellen Cursor-Position. Vergl. D + +ueberschrift neu (P) + PROC ueberschrift neu + Zweck: Mitteilung an den Editor, daß nach Kommandoverarbeitung die + Überschriftszeile neu zu schreiben ist. + +ueberschrift zeigen (P) + PROC ueberschrift zeigen + Zweck: Mitteilung an den Editor, daß sofort die Überschriftszeile neu + zu schreiben ist. + +up (P) + PROC up (INT CONST n) + Zweck: Analog U. + + PROC up (TEXT CONST muster) + Zweck: Analog U. + + PROC up (TEXT CONST muster, INT CONST n) + Zweck: Analog U, aber nur 'n' Zeilen weit. + +uppety (P) + PROC uppety (TEXT CONST muster) + Zweck: Im Gegensatz zu 'up' beginnt die Suche direkt auf der aktuellen + Cursor-Position. Vergl. 'down'. + + PROC uppety (TEXT CONST muster, INT CONST n) + Zweck: Analog 'uppety', aber nur 'n' Zeilen weit. + +word (P) + TEXT PROC word + Zweck: Liefert das Wort von der aktuellen Position bis zum nächsten + Blank bzw. Zeilenende. Die Cursor-Position wird nicht verändert. + + TEXT PROC word (TEXT CONST muster) + Zweck: Liefert das Wort von der aktuellen Position bis zum nächsten Auf- + treten von 'muster' (ausschließlich) bzw. Zeilenende. Die Cursor- + Position wird nicht verändert. + + TEXT PROC word (INT CONST laenge) + Zweck: Liefert das Wort von der aktuellen Position in der angegebenen + 'laenge' bzw. bis zum Zeilenende. Die Cursor-Position wird nicht + verändert. + +word wrap + PROC word wrap (BOOL CONST an) + Zweck: Schaltet den automatischen Wortumbruch an (voreingestellt) bzw. + aus. Beispiel: + + word wrap (true) (* angeschaltet *) + word wrap (false) (* ausgeschaltet *) + +zeile neu (P) + PROC zeile neu + Zweck: Mitteilung an den Editor, daß nach Kommandoverarbeitung die + aktuelle Zeile neu zu schreiben ist. + + + +5. EUMEL-Zeichensatz + +Das EUMEL-System definiert einen Zeichensatz, der gewährleistet, daß Zeichen +auf allen Maschinen überall gleich codiert werden. Dadurch ist es z.B. mög- +lich, Dateien und Programme ohne Konvertierungen zwischen EUMEL-Systemen +unterschiedlicher Hersteller zu übertragen. Der EUMEL-Zeichensatz beruht auf +dem ASCII-Zeichensatz (DIN 66 003) mit Erweiterungen. + + + +Darstellbare Zeichen + +Die genaue Darstellung der einzelnen Zeichen hängt vom Endgerät ab. Die hier +aufgeführten Zeichen sind i.A. auf allen Geräten vorhanden. Ein erweiterter +Zeichensatz (mit mathematischen, diakritischen und griechischen Zeichen) ist +nur auf Spezialgeräten verfügbar und wird deshalb hier nicht angegeben. + +Beispiele zum Lesen der Tabelle: + + code (" ") -> 32 + code ("m") -> 109 + + |3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 +-+------------------------------------------------------------------- +0| ( 2 < F P Z d n x k + | +1| ) 3 = G Q [ e o y - ß + | +2|SP * 4 > H R \\ f p z \# + | +3|! + 5 ? I S ] g q { SP + | +4|" , 6 § J T ^ h r | Ä + | +5|\# - 7 A K U _ i s } Ö + | +6|$ . 8 B L V ` j t ~ Ü + | +7|% / 9 C M W a k u ä + | +8|& 0 : D N X b l v ö + | +9|' 1 ; E O Y c m w ü + +Anmerkungen: +1) SP bedeutet Leerzeichen ("blank"). +2) Die Zeichen 'k', '-' und 'SP' mit den Codes 220, 221, 223 werden für die + Zwecke der Textkosmetik benötigt (Trenn 'k' bei der Umwandlung von 'ck' in + 'kk'; Trennzeichen; geschütztes Leerzeichen). +3) Das Zeichen '\#' (Code 222) ist druckbar, während das Zeichen '\#' (Code 35) + nicht druckbar ist (Einleitungszeichen für Anweisungen der Textkosmetik + und Drucker). +4) Das Zeichen SP (Code 223) wird zur besseren Identifizierung als Unter- +streichungsstrich auf dem Terminal dargestellt. Im einem Ausdruck erscheint +es als ein Leerzeichen. + + + +Steuerzeichen und -tasten + +Das EUMEL-System definiert neben den darstellbaren Zeichen auch Steuer- +zeichen, die entsprechend der angeschlossenen Geräte ggf. jeweils umcodiert +werden. + +Das EUMEL-System definiert (Ausgabe-) Steuerzeichen mit ihren (ausgabesei- +tigen) Wirkungen. Diese Steuerzeichen sind geräteunabhängig und werden vom +EUMEL-System automatisch für die jeweiligen Geräte passend umcodiert. Bei +Standard-Geräteschnittstellen ist die Wirkung anderer Steuerzeichen nicht +definiert. Für den Anschluß von Druckern, für Datenfernübertragung u.ä. +können sogenannte "Transparent"-Schnittstellen verwandt werden. Bei diesen +Schnittstellen ist die Wirkung aller Steuerzeichen undefiniert (vom ange- +schlossenen Gerät abhängig); es wird aber garantiert, daß alle Zeichen ohne +Code-Umsetzung direkt ausgegeben werden. + + + +Ausgabesteuerzeichen + +Wert | Bezeichnung | Wirkung +------+--------------+----------------------------------------- + 0 | NUL | keine Wirkung, Füllzeichen + 1 | HOME | Cursor auf linke obere Ecke des Bildschirms + 2 | RECHTS | Cursor eine Stelle nach rechts + 3 | OBEN | Cursor eine Zeile nach oben + 4 | CL EOP | Löschen von Cursor-Position bis Bildschirmende + 5 | CL EOL | Löschen von Cursor-Position bis Zeilenende + 6 | CPOS | Cursor positionieren, nächstes Ausgabezeichen be- + | | stimmt die y-Position (0 <= code (y) <= 23), darauf- + | | folgendes Ausgabezeichen die x-Position + | | (0 <= code (x) <= 78). + 7 | BELL | akustisches Signal + 8 | LINKS | Cursor eine Stelle nach links +10 | UNTEN | Cursor eine Zeile nach unten bzw. 'roll up', falls + | | der Cursor schon in der letzten Zeile stand +13 | RETURN | Cursor an den Anfang der aktuellen Zeile +14 | ENDMARK | Ende des zu markierenden Bereichs +15 | BEGINMARK | Anfang des zu markierenden Bereichs + + + +Eingabe-Steuertasten + +Für die Eingabeseite sind im EUMEL ebenfalls Steuertasten definiert. Diese +Tasten sollten am angeschlossenen Gerät vorhanden sein oder bereitgestellt +werden (z.B. durch Überkleben von Tasten) oder müssen mit Hilfe der +CONTROL-Taste simuliert werden. Das EUMEL-System führt entsprechend der +folgenden Tabelle evtl. notwendige Umcodierungen der Eingabe durch. Weitere +vorhandene Spezialtasten erzeugen gerätespezifische Codes. Bei der "Transpa- +rent"-Schnittstelle werden - symmetrisch zur Ausgabeseite - alle hereinkom- +menden Zeichen ohne Code-Umsetzung weitergereicht. + +Wert | Bezeichnung +------+------------ + 1 | HOP + 2 | RECHTS + 3 | OBEN + 8 | LINKS + 9 | TAB +10 | UNTEN +11 | RUBIN +12 | RUBOUT +13 | RETURN +16 | MARK +27 | ESC + + + +6. Der Editor als Unterprogramm + +Um eine Anpassung der Benutzerschnittstelle an spezielle Bedürfnisse vor- +nehmen zu können, werden einige noch nicht erläuterte ELAN-Prozeduren zur +Verfügung gestellt. Mit diesen kann für jede Anwendung ein Spezialprogramm +zur Verfügung gestellt werden, das den Editor als Unterprogramm aufruft. Für +den "normalen" Editor-Benutzer ist dieses Kapitel somit nicht weiter von +Interesse. + + + +Tastenverwaltung + +kommando auf taste legen + PROC kommando auf taste legen (TEXT CONST taste, elan programm) + Zweck: Belegt die Taste 'taste' mit dem ELAN-Programm 'elan programm'. + Beispiel: + + kommando auf taste legen + ("v", "edit (""meine datei"")") + + belegt die Taste 'v' mit der 'edit'-Prozedur. + +kommando auf taste + TEXT PROC kommando auf taste (TEXT CONST taste) + Zweck: Liefert den Quelltext des auf die Taste 'taste' gelegten ELAN-Pro- + gramms oder niltext, wenn diese nicht entsprechend belegt ist. + +lernsequenz auf taste legen + PROC lernsequenz auf taste legen (TEXT CONST taste, lernsequenz) + Zweck: Belegt die Taste 'taste' mit den Zeichen 'lernsequenz'. Beispiel: + + lernsequenz auf taste legen ("a", ""217"") + + belegt die Taste 'a' mit dem 'ä'. + +lernsequenz auf taste + TEXT PROC lernsequenz auf taste (TEXT CONST taste) + Zweck: Liefert die auf 'taste' gelegte Tastenanschlagsfolge + oder niltext, wenn diese nicht entsprechend belegt ist. + +taste enthaelt kommando + BOOL PROC taste enthaelt kommando (TEXT CONST taste) + Zweck: Liefert TRUE, wenn 'taste' mit einem ELAN-Programm belegt ist. + +std tastenbelegung + PROC std tastenbelegung + Zweck: Belegt die Tasten mit der Standardbelegung. + + + +Aufruf des Editors, Zeilen- und Fenstereditors + +edit + PROC edit + Zweck: a) Im Monitor: + Ruft den Editor mit den zuletzt verwandten Dateinamen auf. + b) Im Editor: + Der Dateiname wird erfragt. + Für jedes 'edit' gilt: + Wurde der 'edit' zum ersten mal aufgerufen, nimmt das Fenster + den gesamten Bildschirm ein. Bei erneuten 'edit'-Aufruf wird + ein Fenster nach rechts unten ab aktuellen Cursor-Punkt eröffnet. + + PROC edit (TEXT CONST datei) + Zweck: Ruft den Editor mit 'datei' auf. + + PROC edit (TEXT CONST datei, x, y, xsize, ysize) + Zweck: Wie obiger 'edit'-Aufruf, jedoch kann das Fenster, in der 'datei' + editierbar ist, gesetzt werden. Die Parameter definieren ein + Editor-Fenster mit der linken oberen Ecke auf den Bildschirmkoor- + dinaten 'x' und 'y' und einer Zeilenbreite 'xsize' und 'ysize' + Zeilen. Wird der Editor mit 'edit ("datei")' aufgerufen, wird + implizit 'edit ("datei", 1, 1, 79, 24)' aufgerufen. + + PROC edit (FILE VAR f) + Zweck: Vergl. obige 'edit'-Prozedur. + + PROC edit (THESAURUS CONST t) + Zweck: Editieren aller in dem Thesaurus 't' enthaltenen Dateien nachein- + ander. Beispiel: + + edit (ALL myself) + + PROC edit (FILE VAR f, INT CONST x, y, xsize, ysize) + Zweck: Vergl. obige 'edit'-Prozedur. + +editget + PROC editget (TEXT VAR editsatz) + Zweck: Eingabe mit Editiermöglichkeit von 'editsatz' vom Terminal an der + aktuellen Bildschirmposition. 'editsatz' wird ausgegeben. Die + Eingabe wird mit RETURN beendet. Im Gegensatz zu 'get' ist hier + auch eine leere Eingabe (RETURN) erlaubt. + + PROC editget (TEXT VAR editsatz, INT CONST editlimit, editlaenge, + TEXT CONST sep, res, TEXT VAR exit char) + Zweck: Wie oben. Dabei bedeuten: + + editsatz: TEXT, der zum Editieren ausgegeben wird. + editlimit: Einstellung des 'limit's der Zeile (max. Anzahl von Zeichen). + Bei obiger 'editget'-Prozedur wird 'editlimit' mit + 'maxtextlength' aufgerufen. + editlaenge: Breite des Zeilenfensters, bevor gerollt wird (bei leerer + Zeile ist dies 77). + sep: Zeichen, bei denen die Eingabe (zusätzlich zu RETURN) + beendet werden soll. + res: Angabe von reservierten Tasten. Wird einer dieser Tasten mit + ESC betätigt, wird die Eingabe beendet. In + exit char: steht dann ESC und das Zeichen, mit dem der Editor verlassen + wurde. + + PROC editget (TEXT VAR editsatz, INT CONST editlimit, + TEXT VAR exit char) + Zweck: Siehe oben. + + PROC editget (TEXT VAR editsatz, TEXT CONST sep, res, + TEXT VAR exit char) + Zweck: Siehe oben. + +show + PROC show (FILE VAR f) + Zweck: Zeigt eine Datei 'f' auf dem Bildschirm. Wie beim Editor kann mit + Hilfe der Positionierungstasten UNTEN bzw. OBEN oder HOP UNTEN bzw. + HOP OBEN oder HOP RETURN "geblättert" werden. Die Datei 'f' muß + deshalb mit der Verarbeitungsart 'modify' assoziiert worden sein. + Soll die Prozedur 'show' verlassen werden, müssen - wie beim Editor + - die zwei Tasten ESC und q betätigt werden. Die Datei kann nicht + schreibend verändert werden. + + PROC show (TEXT CONST filename) + Zweck: Wie obige Prozedur. + + + +Zeichen verarbeiten + +getchar + PROC getchar (TEXT VAR zeichen) + Zweck: Holt das nächste Eingabezeichen von der Tastatur. + +is incharety + BOOL PROC is incharety (TEXT CONST zeichen) + Zweck: Ist das nächste Eingabezeichen der Tastatur 'zeichen', liefert + 'is incharety' TRUE. In diesem Fall wird 'zeichen' von der Eingabe + verschluckt. Ist das nächste Zeichen von der Tastatur nicht 'zei- + chen', liefert 'is incharety' FALSE. Die Eingabe bleibt unver- + ändert. + diff --git a/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil4 b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil4 new file mode 100644 index 0000000..ecca7e6 --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil4 @@ -0,0 +1,2306 @@ + EUMEL-Benutzerhandbuch + + TEIL 4: Textkosmetik und Druck + +TEIL 4: Textkosmetik und Druck + + +Vorwort + +Die Textkosmetik-Programme des EUMEL-Systems bieten eine einfach zu er- +lernende und zu bedienende Möglichkeit, Texte für den endgültigen Druck zu +gestalten (Programmtechnisch: #ib#formatieren#ie#). Die Textkosmetik ermög- +licht zusätzlich, Texte in einer Art und Weise zu manipulieren, die auf +preiswerten Terminals zur Zeit nicht darstellbar ist, wie z.B. verschieden- +artige Schriften. "Nebenbei" erledigt die Textkosmetik aufwendige Routine- +arbeiten, wie z.B. Seitennumerierung und die Plazierung von Fußnoten. + +Die Textkosmetik-Programme bearbeiten Dateien, die durch den EUMEL-Editor +erstellt wurden. Darum sollte man sich zuerst mit dem EUMEL-Editor vertraut +machen. + +Für die meisten Aufgaben ist kein Benutzereingriff erforderlich, darum sind +die Programme so konstruiert, daß sie durch in den Text eingefügte Anweisun- +gen gesteuert werden. Einige Arbeiten erfordern den Benutzereingriff, wie +z.B. die Kontrolle von Silbentrennungen bei fremdsprachigen Texten und die +Plazierungen von Seitenenden. Diese Arbeiten werden auf einfache Weise +interaktiv vorgenommen. Die Form der Anweisung ist für die Textkosmetik und +den EUMEL-Drucker gleich und entspricht der ELAN-Syntax. Man beachte den +Unterschied zwischen einem Kommando und einer Text-Anweisung: während ein +Kommando direkt ausgeführt wird, wird eine im Text eingebettete Text-Anwei- +sung (im weiteren kurz "#ib#Anweisung#ie#" genannt) erst nach dem Aufruf von +Textkosmetik-und Drucker-Programmen wirksam. + +Die Wirkungsweise der Textkosmetik-Anweisungen ist leicht zu erlernen und +kann vor allen Dingen stufenweise erfolgen. Deshalb ein guter Rat für An- +fänger: Lesen Sie diesen Teil des Benutzer-Handbuchs erst oberflächlich, so +daß Sie ungefähr Bescheid wissen, welche Möglichkeiten die Textkosmetik-Pro- +gramme bieten. Dann können Sie diejenigen Teile der Textkosmetik auswählen +und bei Bedarf anwenden, die sie für Ihre spezielle Anwendung benötigen. + +Zum Schluß noch eine Warnung: Die Regeln, Konventionen und Wirkungsweisen +des EUMEL-Systems und der Textkosmetik-Programme muß ein Nutzer beherrschen, +will er das System gut nutzen. Der Lernaufwand erfordert etwas Zeit und Mühe, +der aber bei der Benutzung einer jeden Maschine erforderlich ist. Soll nur +ein kurzer Brief geschrieben werden, ist man mit einer Schreibmaschine +besser bedient. Beherrscht man dagegen die Benutzung des EUMEL-Systems +einigermaßen, so kann auch die Erstellung eines kurzen Briefes schneller +erfolgen als auf einer Schreibmaschine. + + + +1. Einführung in die Benutzung der Textkosmetik + +In diesem Kapitel wird eine Übersicht über die verfügbaren Programme der +Textkosmetik gegeben. + + + +Schreiben, Gestalten und Drucken von Texten + +Im EUMEL-System unterscheiden wir zwischen drei Stufen einer Textbehandlung: +Erstellung, Gestaltung und Druck. Die Trennung in verschiedene Arbeitsstufen +hat den Vorteil, daß man sich zu einem Zeitpunkt nur auf einen Arbeits- +schritt konzentrieren muß. + + +a) Texterstellung bzw. Textbearbeitung + +Das Schreiben von Texten wird mit Hilfe des Editors erledigt. In dieser Stufe +der Texterstellung kann ein Benutzer sich ausschließlich auf das Schreiben +und die inhaltliche Korrektheit seines Textes konzentrieren. Wird ein Text +ohne Anweisungen gedruckt, dann erscheint er so, wie er mit dem Editor ge- +schrieben wurde. Bei der Erstellung des Textes können bereits Textkosmetik- +Anweisungen in den Text eingefügt werden. + +Texte sollten im 'Fließtext'-Modus erstellt werden, d.h. Worte, die über +Zeilengrenzen gehen würden, werden ohne Silbentrennung vom Editor in die +nächste Zeile gebracht. + + +b) Textkosmetik bzw. Textgestaltung + +Nachdem ein Text geschrieben wurde, kann man ihn mit Textkosmetik-Programmen +gestalten, ohne ihn inhaltlich zu verändern. Dies kann auch vor oder nach +eventuellen Korrekturen erfolgen. Die Textkosmetik bietet zur Zeit drei +Programme an, die je nach Bedarf eingesetzt werden können: + +I) 'autoform/lineform' formatiert einen Text zeilenweise und vollzieht + eine Silbentrennung. Weiterhin erlaubt 'autoform/lineform' die Verwen- + dung unterschiedlicher Schrifttypen und Schrifthöhen. + +II) 'pageform' gestattet die Formatierung eines Textes in Seiten (drucktech- + nisch: "Paginieren"). Es ist mit 'pageform' u.a. möglich, die Seiten- + einteilung zu bestimmen, eine Seite in Spalten zu formatiern ("Zeitungs- + format"), Zeilen am Anfang bzw. Ende jeder Seite einfügen zu lassen, + eine Seitennummerierung zu erhalten und Fußnoten zu gestalten. + +III) 'index' erlaubt die Erstellung von Stichwort- und Inhaltsverzeichnissen. + + +c) Drucken + +Zu jedem Zeitpunkt der Textbehandlung kann gedruckt werden. Um Drucker mit +unterschiedlichen Eigenschaften betreiben zu können, wurde der (Fachausdruck: +"virtuelle") EUMEL-Drucker als Schnittstelle zwischen dem EUMEL-System und +(echten) Druckern geschaffen. Der EUMEL-Drucker beachtet die gleichen An- +weisungen wie die Textkosmetik-Programme und noch einige zusätzliche, die +nur für die Druckaufbereitung notwendig sind. Spezielle Druckleistungen, wie +z.B. verschiedenartige Schrifttypen, können nur auf besonderen Druckern er- +zeugt werden. Verfügt ein Drucker nicht über eine bestimmte Hardware-Eigen- +schaft, wird die vom Benutzer geforderte Leistung ignoriert. Somit ist es +möglich, Probedrucke für Korrekturen auch auf preiswerten Druckern herzu- +stellen. + +Merke: Der EUMEL-Editor übernimmt die Texterstellung; 'lineform' formatiert +zeilenweise; 'pageform' formatiert seitenweise; 'index' erstellt Stich- und +Inhaltsverzeichnisse; der EUMEL-Drucker ist eine Software-Anpassung an +unterschiedliche Ausgabe-Geräte. + + + +Anweisungen für die Textkosmetik und den Drucker + +In diesem Abschnitt wird beschrieben, wie Anweisungen für die Textkosmetik- +Programme in einen Text eingefügt werden. + +Die Ausführung von 'lineform', 'pageform', 'index' und EUMEL-Drucker wird +mit Hilfe von Anweisungen gesteuert, die man in den Text an geeigneter +Stelle einfügt. Anweisungen haben die Form + + #kommando# + +Beachte, daß jede Anweisung von #-Zeichen eingeschlossen sein muß, damit +die Anweisung vom eigentlichen Text unterschieden werden kann. Beispiele: + + #page# (* aber auch z.B.: # page # *) + #free (3.0)# + #type ("elitedeutsch")# + +Das "#"-Zeichen darf nur für Anweisungen verwandt werden, also sonst nicht +im Text vorkommen. (Wird das "#"-Zeichen benötigt, muß das Zeichen mit ESC # +geschrieben werden. Vergl. auch die Tastenbelegung in der Editor-Beschrei- +bung). + +Die von '#'-Zeichen eingeschlossenen Anweisungen sind so konstruiert, daß +sie - wie alle anderen Kommandos im EUMEL-System auch - der ELAN-Syntax +entsprechen (u.a. müssen sie klein geschrieben werden; Parameter in runden +Klammern; mehrere Parameter werden durch Kommata getrennt; TEXT-Parameter +in Anführungsstrichen; REAL-Parameter mit Dezimalpunkt usw.). Leerzeichen +spielen (außer in TEXT-Parametern) keine Rolle und können zur besseren Les- +barkeit beliebig verwandt werden. + +Man beachte den Unterschied zwischen einer Anweisung und einem Kommando: +während es nur eine beschränkte Anzahl von Anweisungen gibt, die nur von den +Textkosmetik-Programmen ausgeführt werden (also sonst nicht in Programmen +oder Monitor benutzt werden können), kann ein Benutzer ein Kommando in der +Regel in einem Programm, im Editor oder im Monitor verwenden. Hinzu kommt, +daß neben dem vom EUMEL-System zur Verfügung gestellten Kommandos in der +Regel noch installationsspezifische und/oder benutzereigene Kommandos gibt. + +Anweisungen dürfen im allgemeinen überall auf einer Zeile stehen (wie z.B. +in der nächsten Zeile). #on("underline")#Ausnahmen#off("underline")# werden +bei der Beschreibung der Anweisungen speziell erwähnt. Alle Anweisungen +werden zum frühest möglichen Zeitpunkt ausgeführt, haben also u.U. bereits +Auswirkungen auf die Zeile, in der sie stehen. + +Die Zeichen, aus denen eine Anweisung besteht, werden bei der Formatierung +einer Zeile oder Seite nicht mitgezählt und vom EUMEL-Drucker nicht gedruckt. +Eine Zeile, die nur aus Anweisungen besteht, wird ebenso behandelt. + +Merke: Anweisungen steuern die Verarbeitung der Textkosmetik-Programme. Sie +müssen in '#'-Zeichen eingeschlossen sein und dürfen in der Regel überall +auf einer Zeile stehen. Sie werden an der Stelle ausgeführt, an der sie +stehen. + + + +Aufruf der Textkosmetik-Programme + +In diesem Abschnitt wird beschrieben, wie die Textkosmetik-Programme +aktiviert werden. + +Die Textkosmetik-Programme werden durch Kommandos aktiviert (d.h. in der +'gib kommando:'-Ebene). Die Aktivierung (Fachausdruck: "Aufruf") erfolgt - +ebenso wie beim Editor - durch den Namen des Programms und die Angabe +der Datei. Beispiele: + + autoform ("meine datei") + lineform ("text1"); + pageform ("1. Kapitel") + index ("Buch.p") + +Das Programm 'pageform' erzeugt aus der Eingabedatei eine Druckdatei, die +entsprechend umgeformt wird (Fußnoten werden an die richtige Stelle plaziert, +Seitenummern eingesetzt u.a.m.). Diese Druckdatei bekommt den Namen der +angegebenen Eingabedatei mit dem Zusatz '.p'. Beispiel: 'pageform ("text")' +erzeugt eine Datei 'text.p'. Es ist auch erlaubt, 'pageform' durch die Angabe +eines zweiten Parameters mitzuteilen, wie die Druckdatei heißen soll: + + pageform ("mein text", "erste Druckdatei") + +Ähnlich verhält es sich mit dem Programm 'index', welches bis zu 9 Stichwort- +bzw. Inhaltsverzeichnisse erstellen kann. Da in den Verzeichnissen die +Seitennummern aufgeführt werden, kann 'index' nur Druckdateien bearbeiten. +Beispiel: + + index ("handbuch.p") + +Das Programm 'index' erstellt die angeforderten Verzeichnisse in Dateien, +die mit dem Zusatz '.i<nummer>' gekennzeichnet werden. Beispiele (für den +obigen Aufruf): + + 'Handbuch.i1', 'Handbuch.i2' + +usw.. + +Merke: Die Textkosmetik-Programme werden durch Kommandos aufgerufen mit der +Angabe der Dateinamen als Parameter. + + + +Vorzeitiger Abbruch und Fehlermeldungen + +Alle Textkosmetik-Programme können vorzeitig vom Benutzer abgebrochen werden. +Eventuelle Fehlermeldungen werden durch den Paralleleditor angezeigt. + +Durch die Taste SV und das Supervisor-Kommando 'halt' können die Textkosme- +tik-Programme jederzeit vorzeitig abgebrochen werden. Die Eingabedatei steht +dann unverändert zur Verfügung. Ein vorzeitiger Abbruch kann notwendig sein, +wenn ein Programm mit einer falschen Datei aufgerufen wurde oder zu viele +Fehler gemeldet wurden. + +Alle Textkosmetik-Programme melden Fehler, wenn eine oder mehrere Anweisun- +gen falsch benutzt werden. Die Fehlermeldungen werden auf dem Bildschirm +angezeigt. Bei Beendigung eines Programms wird - falls Fehler entdeckt +wurden - die Fehlermeldungen im oberen Fenster des Paralleleditors angezeigt, +während im unteren Fenster die Eingabedatei zur Korrektur angeboten wird. + +Merke: Vorzeitiger Abbruch eines Programms durch SV und 'halt'. (Die Eingabe- +datei steht unverändert zur Verfügung.) Fehlermeldungen werden im Parallel- +editor angezeigt. + + + +2. Zeilenweises formatieren: 'autoform/lineform' + +Die Programme 'autoform' oder 'lineform' formatieren einen Text zeilenweise +(ggf. mit Silbentrennung), unter Berücksichtigung von Schrifttyp und Zeilen- +breite. + + + +Eine Datei formatieren: 'autoform/lineform'-Kommando + +Die Programme 'lineform/autoform' werden unter Angabe der Datei aufgerufen. +Beispiel: + + lineform ("meine datei") + autoform ("Brief vom 24.12.") + + + +Unterschied von 'autoform' und 'lineform' + +Zur Zeilenformatierung werden zwei Programme angeboten, die sich nur in der +Art der Behandlung von Silbentrennungen unterscheiden: + +a) autoform: + Zeilenformatierung mit automatischer Silbentrennung. 'autoform' sollte + nur bei deutschen Texten eingesetzt werden, weil die Silbentrennung bei + fremdsprachigen Texten nach anderen Regeln erfolgen muß. + +b) lineform: + Zeilenformatierung mit Silbentrennung "per Hand", wobei (nach deutschen + Trennregeln) ein sinnvoller Trennvorschlag gemacht wird. Die Trennstelle + kann interaktiv soweit verschoben werden, wie das zu trennende Wort noch + auf die Zeile paßt. + +Merke: 'autoform' nimmt eine automatische Silbentrennung vor, während +'lineform' die #ib#Silbentrennung "per Hand"#ie# erlaubt. + + + +Übersicht über 'autoform'/'lineform' + +'autoform'/'lineform' formatieren eine Datei zeilenweise. Dabei werden +Zeilen möglichst vollständig aufgefüllt. + +'autoform'/'lineform' haben im wesentlichen vier Aufgaben: + +a) Auffüllen von Zeilen: + 'autoform'/'lineform' können besonders gut nach Korrekturen eingesetzt + werden, bei denen - nach Einfügungen oder Löschungen - nicht vollstän- + dige oder zu lange Zeilen in der Datei stehen bleiben können. + +b) Erstellen von Zeilen mit unterschiedlichen Schrifttypen: + Werden in einer Datei mehrere Schriftarten ('type'-Anweisung) verwandt, + berechnen 'autoform'/'lineform' nach der eingestellten Zeilenbreite die + Anzahl Zeichen, die auf eine Zeile passen. + +c) Erstellen von unterschiedlichen Zeilenlängen: + Manchmal ist es notwendig, die Breite von Zeilen zu verändern ('limit'- + Anweisung). Dies wird von 'autoform'/'lineform' berücksichtigt. + +d) Silbentrennung: + Automatische ('autoform') und interaktive Silbentrennung ('lineform'). + Sofern notwendig, werden Silbentrennungen rückgängig gemacht. + +'autoform'/'lineform' beachten nur wenige Anweisungen: + +Anweisung Zweck + + limit Zeilenbreite einstellen + off Schrifttyp-Modifikation ausstellen + on Schrifttyp-Modifikation einstellen + type Schrifttyp einstellen + + +'autoform'/'lineform' akzeptieren als Eingabe eine Datei und verändern diese. +Dafür wird eine (interne) Zwischendatei benötigt. Deshalb ist darauf zu +achten, daß noch ausreichend Platz auf dem System ist, der jedoch nur +zwischenzeitig für den Formatierungsschritt benötigt wird. + +'autoform'/'lineform' fragen nach ihrem Aufruf an, auf welche Zeilenbreiten +und mit welchem Schrifttyp die Datei formatiert werden soll. Diese Informa- +ionen werden von 'autoform'/'lineform' in Form von 'limit'- und 'type'-An- +weisungen in der Datei vermerkt, so daß die Anfragen bei weiteren Datei- +Bearbeitungen entfallen. + +Bei Zeilen, die länger als die angegebene Zeilenbreite sind, werden die- +jenigen Worte, die über die Zeilenbreite hinausgehen, in die nächste Zeile +umgebrochen. Kürzere Zeilen werden aus der nachfolgenden Zeile bis zur +Zeilenbreite aufgefüllt. Worte werden jedoch nicht über Absatzgrenzen hinweg +verschoben. Deshalb ist vor Anwendung von 'lineform' darauf zu achten, daß +Absätze richtig markiert wurden. Fehlende Markierungen sollte man nachträg- +lich einfügen (RETURN am Ende einer Zeile), andernfalls werden Zeilen über +Absatzgrenzen zusammen gezogen. Dies gilt insbesondere für Tabellenzeilen. + +Einrückungen (Leerzeichen am Anfang einer Zeile) werden von 'autoform'/'line- +form' ebenfalls bei der Formatierung von Zeilen eingehalten. +Dabei behandelt die Prozedur 'autoform'/'lineform' Einrückungen in einem +speziellen Fall nicht so, wie ein Benutzer es erwarten würde. Bei ein- +zeiligen Absätzen wird - falls die Zeile länger als das eingestellte Limit +ist und der "überschüssige" Teil in eine neue Zeile umgebrochen werden muß +- die Einrückung der aktuellen Zeile beibehalten. Das ist meist das +"richtige" Verhalten, während es bei Aufzählungen falsch ist, weil die +zweite Zeile einer Aufzählung oft eingerückt wird. Beispiel: + + - Diese Zeile war zu lang und wurde unter + das "-"-Zeichen umgebrochen. + +Man sollte daher - nach Verarbeitungsende - die Datei nach solchen Fällen +durchsuchen. + +Merke: 'autoform'/'lineform' vervollständigen zu kurze Zeilen oder brechen +zu lange Zeilen um. Dabei werden Absätze beachtet. + + + +Interaktive Silbentrennung mit 'lineform' + +'lineform' trennt Silben interaktiv. 'lineform' sollte deshalb für fremd- +sprachige Texte angewandt werden. + +Paßt ein Wort nicht mehr ganz auf eine Zeile, dann wird dieses Wort inter- +aktiv zur Trennung angeboten. Die Umgebung dieses Wortes wird zur Er- +leichterung des Trennvorgangs mit angezeigt. Das Trennzeichen erscheint an +einer sinnvollen Stelle im zu trennenden Wort. Beispiel: + + Text vor dem Trennwort; das + Trenn-wort steht mit nachfolgendem Text in dieser Zeile + +Der Benutzer hat die Möglichkeit, das Trennzeichen mit Hilfe der Positionie- +rungstasten innerhalb des "Trennbereichs" (das ist der markierte Bereich, der +noch auf die Zeile passen würde), zu verschieben. An der gewünschten Trenn- +position (der Wortteil, der noch auf die Zeile kommen soll, steht links vom +Trennstrich) kann die RETURN-Taste betätigt werden. RETURN zeigt dem Pro- +gramm 'lineform' an, daß an dieser Stelle die Trennung erfolgen soll. 'line- +form' fügt an den ersten Teil des Wortes das "-"-Zeichen an und schreibt den +abgetrennten Wortteil in die nächste Zeile. +Hinweis: Das Trennzeichen "-" hat einen anderen Code als der "normale" +Bindestrich (vergl. dazu die Codetabelle), da Trennungen ggf. bei erneuten +Änderungen wieder rückgängig gemacht werden müssen. + +Es stehen folgende Operationen bei der interaktiven Trennung zur Verfügung: + + Taste Bedeutung + + RETURN Trennen. + LINKS Trennstelle um ein Zeichen nach links verschieben. + RECHTS Trennstelle um ein Zeichen nach rechts verschieben. + HOP LINKS Trennstelle vor das Wort setzen (das Wort wird an dieser + Position nicht getrennt). + HOP RECHTS Trennstelle in die ursprüngliche Position setzen. + BLANK Trennzeichen wird von "-" auf " " umgeschaltet. + Dies kann verwandt werden, um Worte, die nicht zusammen + geschrieben werden sollen, beim Trennvorgang in zwei + Worte aufzuspalten. + - Schaltet das Trennzeichen von Leerzeichen (" ") wieder auf + den Trennstrich ("-") um. + +Zwei Sonderbedingungen sind bei der interaktiven Trennung noch zu beachten: + + - Bei Worten mit Bindestrich wird die Trennstelle hinter dem Bindestrich als + Leerzeichen angezeigt. Die Trennstelle vor dem Bindestrich wird bei + weiterem Positionieren nach links übersprungen. Das verhindert, daß Worte + mit führendem Bindestrich im Text erscheinen. + + - Bei einer Trennposition zwischen den Zeichen "ck" wird das Zeichen "c" in + ein "k" umgewandelt. Beispiel: + + Druk-ker +Hinweis: Das umgewandelte "k" hat einen anderen Code als das "normale" +"k" (vergl. dazu die Codetabelle). Das ist notwendig, um bei späteren +Änderungen solche Trennungen wieder rückgängig machen zu können. + +Sofern für die Zeilenformatierung notwendig, macht die Prozedur 'lineform' +bereits erfolgte Trennungen rückgängig (das Trennzeichen wird entfernt und +die Wortteile wieder zusammengefügt), wenn sich das getrennte Wort nicht mehr +am Zeilenende (etwa durch Korrekturen oder Veränderungen der Zeilenbreite) +befinden sollte. + +Merke: 'lineform' bietet Worte zur Silbentrennung an. Die "Trennstelle" kann +durch den Nutzer verschoben werden. + + + +Automatische Silbentrennung mit 'autoform' + +'autoform' arbeitet wie 'lineform', nur werden die Silbentrennungen auto- +matisch vorgenommen. + +Ist eine Silbentrennung bei der Formatierung notwendig, übernimmt 'autoform' +diese automatisch und gibt diese zur Kontrolle auf dem Bildschirm aus. Die +automatische Silbentrennung arbeitet mit einer hohen Trenngüte; allerdings +nur für deutsche Texte. Trotzdem kann es vorkommen, daß einige Trennungen +(insbesondere bei Fremdworten) falsch vorgenommen werden. In diesem Fall +muß man diese nachträglich mit dem Editor korrigieren. Dabei sollte man das +oben erwähnte Trennzeichen verwenden (ESC -). + + +Wenige oder viele Silbentrennungen: Trennpunkt einstellen + +Viele Silbentrennungen in einem Text erschweren das Lesen. Würde man nun +keine Silbentrennungen vornehmen, wird der rechte Rand stark "ausgefranst" +oder beim Blocksatz ("rechter Randausgleich") müssen viele Zwischenräume +zwischen den Worten eingefügt werden. Durch das Kommando + + hyphenation width (prozentuale angabe) + +kann der Trennpunkt, ab dem die Silbentrennung einsetzen soll, eingestellt +werden. Die Angabe erfolgt in Prozenten der Zeilenbreite. Beispielsweise +stellt 'hyphenation width (5)' den Trennpunkt auf 5% der Zeilenbreite ein +(Voreingestellt ist 7). Bei einer Angabe von 20 werden sehr wenige Worte zur +Silbentrennung angeboten, während bei einer Angabe von '3' ungefähr jede +dritte Zeile eine Silbentrennung versucht wird. Die Einstellung des Trenn- +punktes bestimmt also, ab wann ein Wort zur Silbentrennung untersucht wird. +Andererseits bestimmt die Einstellung auch, wieviel Zwischenraum zwischen +Worten eingefügt werden muß, um einen rechten Randausgleich zu erzielen. + +Merke: 'hyphenation width' bestimmt, an welchem Punkt Worte zur Silbentren- +nung angeboten werden. + + +Mit unterschiedlichen Schriften schreiben: 'type' + +Unterschiedliche Schrifttypen#ie# werden mit der 'type'-Anweisung ange- +fordert. + +Es ist möglich, mit 'lineform' verschiedenartige Schrifttypen (kurz Typen +genannt) verarbeiten zu lassen. Jeder Typ hat - neben dem speziellen Aus- +sehen der Zeichen - die Eigenschaft, daß jedes Zeichen eine bestimmte Breite +und Höhe hat. + +Es gibt zwei Arten von Schriften: bei äquidistanten Schriften sind alle +Zeichen gleich breit (wie bei einer "normalen" Schreibmaschine). Proportio- +nalschrift findet man in gedruckten Büchern. Hier haben unterschiedliche +Zeichen auch unterschiedliche Breiten. Die Zeichen ".", "i", "!" sind z.B. +schmaler als die Zeichen "w", "o", "m" usw. + +Mit der Anweisung + + type ("schriftname") + +kann auf einen anderen Schrifttyp umgeschaltet werden (auch mehrmals inner- +halb einer Zeile). Dieser Typ gilt solange, bis wieder ein neue 'type'-An- +weisung gegeben wird. Beispiel: + + \#type("basker12")\#Jetzt schreiben wir in einer Schrift. Und jetzt + schalten wir um auf\#type ("modern12")\# noch eine andere Schrift. + +Welche Schriftarten zur Verfügung stehen, hängt natürlich von dem verfügbaren +Drucker ab. Sie können die Schrifttypen bei Ihrer EUMEL-Installation er- +fragen. +Schrifttypen können modifiziert gedruckt werden (vergl. dazu den nächsten Ab- +schnitt). Durch die Angabe einer 'type'-Anweisung werden alle Modifikationen +ausgeschaltet. + +Merke: Eine 'type'-Anweisung gibt einen gewünschten Schrifttyp an. + + + +Kursiv, fett, unterstrichen, revers drucken: 'on/off' + +Mit der 'on'- und 'off'-Anweisung ist es möglich, einen Schrifttyp zu modi-f +izieren. Die Schrift wird zwar nicht gewechselt, aber verändert gedruckt. +Zur Zeit ist unterstrichen, fett, kursiv und der Druck von weiß auf schwarz +möglich (abhängig vom eingesetzten Drucker). + +Die 'on'/'off'-Anweisung wirkt wie ein Schalter, der die gewünschte Schrift- +typ-Modifikation ein- bzw. ausschaltet. Beispiel: + +... Das EUMEL-System ermöglicht es, +\#on("italic")\#kursiv\#off("italic")\# +und +\#on("underline")\#unterstrichen\#off("underline")\# +und +\#on("bold")\#fett\#off("bold")\# +und +\#on("revers")\#revers\#off("revers")\# +zu schreiben. + +Die Anweisung 'on' schaltet die Modifikation ein, 'off' schaltet sie aus. +Folgende Modifikationen sind z.Zt. implementiert: + + bold (Fettdruck) + italic (Kursivdruck) + underline (Unterstreichung) + revers (Weiß auf Schwarz) + +Dabei ist folgendes zu beachten: + +a) Ein 'type'-Anweisung schaltet eine Modifikation immer aus. + +b) Eine Modifikation sollte nicht über einen Absatz gehen ('lineform' er- + zeugt eine Warnung). Somit ist es gewährleistet, daß das Ausschalten + einer Modifikation nicht vergessen wird. + +c) Nicht alle Drucker können die hier angegebenen Modifikationen auch + drucken. Bitte erkundigen Sie sich bei Ihrer Installation. + +d) Welche Modifikationen gleichzeitig eingeschaltet werden können, ist + ebenfalls druckerabhängig. + +Merke: Die Anweisungen 'on' und 'off' schalten eine Modifikation an- und aus. + + + +Gesperrt schreiben + +Wird ein Wort g e s p e r r t geschrieben, muß natürlich verhindert werden, +daß dieses Wort beim Formatieren getrennt wird. Andere Worte, wie z.B. in +Formeln, sollten ebenfalls zusammen auf eine Zeile geschrieben werden (z.B. +'sin (x)'). + +Dies kann man erreichen, indem man nicht das Leerzeichen zwischen die Zeichen +schreibt, denn das Leerzeichen bedeutet für 'autoform'/'lineform' immer das +Ende eines Wortes. Man nimmt stattdessen ESC blank. ESC blank erscheint auf +dem Bildschirm zur besseren Identifizierung als Unterstreichungsstrich (oder +invers: ) Beim Drucken wird jedoch wieder ein Leerzeichen produziert. +Beispiel: + + g_e_s_p_e_r_r_t (auf dem Terminal) + g e s p e r r t (auf Papier) + +Wir nennen dieses Leerzeichen auch "geschütztes Leerzeichen". + +Merke: G e s p e r r t wird mit dem geschützten Leerzeichen geschrieben. + + + +Tabellen und Aufzählungen schreiben + +Aufzählungen und Tabellen werden automatisch richtig formatiert und gedruckt, +wenn man sich an einige einfache Regeln hält. + +Verwendet man eine Proportionalschrift beim Tabellenschreiben, so sind die +Spalten in der Regel unterschiedlich breit, selbst wenn eine gleiche Anzahl +Zeichen in jeder Spalte geschrieben wird. Dies kann man durch das Schreiben +von einem "Doppelblank" vermeiden. Beispiel: + + nnnnn | zweite Spalte + mmmmm | steht nicht untereinander + +aber mit Doppelblank: + + nnnn | zweite Spalte + mmmm | stehen jetzt untereinander + +Das Doppelblank dient 'lineform/autoform' und dem Drucker als Zeichen, daß +die Positionen speziell berechnet ('lineform') und beim Druck berücksichtigt +werden müssen. In seltenen Fällen (insbesondere beim Einsatz von Schriftypen, +die in der Größe stark voneinander abweichen) kann es vorkommen, daß diese +Tabellenautomatik nicht funktioniert und Spalten übereinander gedruckt +werden. In solchen Fällen muß man die Anzahl der trennenden Doppelblanks +erhöhen. + +Praktischer Tip: +Beachte, daß für das Funktionieren der "Tabellenautomatik" bei proportionalen +Schriften es erforderlich ist, das jede Tabellenzeile eine Absatzzeile ist. +Man sollte diese Zeilen vor dem Druck daraufhin überprüfen oder durch 'line- +form/autoform' die Datei bearbeiten lassen. Sollte durch die zeilenweise +Formatierung einmal zwei Zeilen zusammengezogen sein (wegen fehlender Absatz- +kennzeichnung), kann man diese leicht mit dem Editor wieder "auseinander- +brechen" (zweimaliges HOP RUBIN). + +Ähnliches gilt bei Aufzählungen. Beispiel: + + 1) Das ist die erste Aufzählung. + Dieser Satz wird bündig gedruckt. + 2) Hier auch. + +Auch in solchen Fällen wird der gedruckte Text in der Regel richtig einge- +rückt. Die Aufzählungsautomatik wirkt nur nach einem Absatz und bei Propor- +tionalschriften. Die Regeln sind etwas kompliziert, so daß sie hier nicht +einzeln aufgeführt werden (siehe S. #topage("block")# unter dem Kommando +'block'). Trifft man auf einen der seltenen Fälle, wo die Einrückungsautoma- +tik nicht funktioniert, kann man immer das Doppelblank der Tabellenautomatik +verwenden. + +Merke: Die Tabellen- und die Aufzählungsautomatik sorgen dafür, daß Tabellen- +spalten und Aufzählungen bündig gedruckt werden. + + + +Zeilenbreite einstellen: 'limit' + +Mit der 'limit'-Anweisung kann die Zeilenbreite eingestellt werden. + +Die 'limit'-Anweisung gibt (in cm) an, wie breit die Zeile sein soll. Be- +achte, daß die Angabe der Zeilenbreite nichts mit dem LIMIT-Kommando des +Editors zu tun hat. Dieses gibt an, wieviel Zeichen einer äquidistanten +Schrift beim Schreiben auf eine Bildschirmzeile passen sollen. + +Die Zeilenbreite wird zusammen mit dem Schrifttyp beim erstmaligen Aufruf von +'autoform'/'lineform' interaktiv erfragt und als 'limit'-Anweisung (zusammen +mit der 'type'-Anweisung) in die erste Zeile der Datei eingetragen. Es kann +in einer Datei mehrmals verändert werden. Die Zeilenbreite gilt immer ab der +Zeile, in der die 'limit'-Anweisung steht. Beispiel: + + \#limit(10.0)\#Mit der 'limit'-Anwei + sung kann man Paragraphen in einem + anderen Format leicht gestalten. + Die rechte Schreibgrenze wird durch + die 'limit'-Anweisung eingestellt, + während der linke Rand durch eine + entsprechende Einrückung gestaltet + wird. \#limit(13.5)\# + +Man beachte, daß als Parameter in der 'limit'-Anweisung eine Zahl mit Dezi- +malpunkt angegeben werden muß. + +Die folgende Tabelle gibt sinnvolle 'limit'-Einstellungen für die am +häufigsten verwandten Papiergrößen an: + + + Format 'limit' Verbleibender + (Zeilenbreite) Rand + + DIN A4 16.0 cm je 2.65 cm + + DIN A5 12.0 cm je 1.42 cm + + DIN A4 quer 25.0 cm je 2.35 cm + +Merke: Die 'limit'-Anweisung stellt die Zeilenbreite in cm ein, während das +'LIMIT'-Kommando des Editors die Zeilenbreite in Anzahl Zeichen angibt. + + + +3. Seitenweises formatieren: 'pageform' + +'pageform' formatiert eine Datei seitenweise, wobei Routinearbeiten, wie +etwa die Plazierung von Fußnoten, Seitennummerierung usw. ebenfalls von +'pageform' erledigt werden. + + + +Eine Datei in Seiten teilen: 'pageform'-Kommando + +Das Programm 'pageform' wird mit dem Kommando + + pageform ("Buch") + +aufgerufen. 'pageform' erzeugt aus der Eingabedatei (hier: 'Buch') eine +Druckdatei, deren Name durch ein angehängtes '.p' gebildet wird (in unserem +Beispiel: 'Buch.p'). + + +Übersicht über die Arbeitsweise von 'pageform' + +'pageform' erzeugt aus einer Eingabedatei eine Druckdatei, wobei z.B. Fuß- +noten und Seitennummern an den richtigen Stellen eingefügt werden. + +'pageform' akzeptiert als Eingabe eine Datei und produziert eine neue Datei, +die "Druckdatei". Die Druckdatei besteht aus der Eingabedatei mit ggf. neu +eingefügten Zeilen. Die eingesetzten Zeilen stammen aus 'head'-, 'bottom' +oder 'footnote'-Anweisungen. Dadurch erhöht sich die Zeilenanzahl der Datei +(bis zu 15%). + +Durch 'pageform' ist es möglich, am Anfang und am Ende jeder Seite Zeilen +einfügen zu lassen. Solche Textzeilen aus Kopf- bzw. Fußbereichen sowie +Zeilen aus Fußnoten werden in der Druckdatei in jede Seite an entsprechender +Stelle eingefügt. + +Es ist möglich, in Kopf- oder Fußzeilen Seitennummern aufzunehmen. Diese Sei- +tennummern werden von 'pageform' bei Seitenwechseln automatisch erhöht und +an eine vom Benutzer gekennzeichnete Stelle eingesetzt. Fußnoten können auch +durch Nummern gekennzeichnet werden. Querverweise sind ebenfalls möglich. + +'pageform' berechnet die Anzahl von Zeilen, die auf eine Seite passen sollen, +aus den Angaben für die Seitenlänge, eingestellten Zeilenvorschub und even- +tuelle Kopf-, Fuß- und Fußnotenzeilen. Bei der Berechnung wird von der je- +weiligen Schrifthöhe des eingestellten Schriftyps ('type'-Anweisung) ausge- +gangen. Dann zeigt 'pageform' das errechnete Seitenende auf dem Bildschirm +an. Das Seitenende kann interaktiv verschoben werden, um es an eine ge- +wünschte Stellen zu plazieren oder es können Leerzeilen eingefügt/gelöscht +werden, um Seiten gleich lang zu machen. Zusätzlich ist es auch möglich, +Seiten in Spalten ("Zeitungsdruck") aufzuteilen und diese interaktiv zu +formatieren. + + Anweisungs-Übersicht + + bottom Fußzeilen *) + bottomeven " *) + bottomodd " *) + columns Spaltenformatieren + columnsend Spalten ausschalten + count Zähler erhöhen und einsetzen + end Beendet 'head', 'bottom' und *) + 'foot'-Bereiche + foot Fußnote *) + free Zeilen freilassen *) + goalpage Seitenverweis (Ziel) + head Kopfzeilen *) + headeven " *) + headodd " *) + linefeed Zeilenabstand *) + page Neue Seite anfangen *) + pagelength Seitenlänge setzen + pagenr Seitennummer bzw. -zeichen + setcount Zähler setzen + topage Seitenverweis (Ursprung) + value Wert des Zählers einsetzen + +*) Diese Anweisungen dürfen nur allein oder als letztes auf einer Zeile stehen. + + +Merke: 'pageform' erlaubt nicht nur eine Seitenformatierung, sondern auch +Spaltenformatierung, Fußnoten-Plazierung, Kopf- und/oder Fußzeilen, Seiten- +numerierung und Querverweise. 'pageform' erzeugt eine neue Datei, die +"Druckdatei" mit dem Namen der Eingabedatei, an den ".p" angefügt wird. + + + +Seitenende interaktiv verschieben#ie# mit 'pageform' + +In diesem Abschnitt wird beschrieben, welche interaktiven Möglichkeiten +'pageform' bietet, um Seiten zu gestalten. + +Auf dem Bildschirm wird das von 'pageform' errechnete jeweilige Seitenende +unter Angabe der aktuellen Seitennummer angezeigt. Das Seitenende erscheint +ungefähr in der Mitte des Bildschirmes und wird durch eine von 'pageform' ge- +kennzeichnete Zeile markiert, die auch - nach erfolgter Seitenformatierung - +in der Druckdatei zu sehen ist. (Der EUMEL-Drucker druckt diese Zeile nicht.) +Beispiel: + +\#page\#\#--------------------- Ende Seite 1 ---\# + +Über der Markierung erscheinen die letzten Zeilen der bereits verarbeiteten +Seite, darunter Zeilen der nächsten Seite. Es ist nun mit Hilfe der Positio- +nierungstasten möglich, die Markierung und damit das Seitenende nach "oben +zu verschieben". Somit kann vermieden werden, daß logisch zusammengehörender +Text auseinandergerissen wird und z.B. "Waisenkinder" entstehen (letzte +Zeile eines Abschnittes kommt noch auf die neue Seite). + +Bei der interaktiven Seitenformatierung kann die Markierung nicht über das +errechnete Ende einer Seite nach "unten" oder über das vorherige, bereits +verarbeitete Seitenende nach "oben" verschoben werden. Die Markierung kann +auch nicht in einen Fußnotenbereich plaziert werden, weil Fußnoten sinn- +vollerweise nicht geteilt werden sollten. + +Entstehen Leerzeilen bei der Seitenformatierung am Anfang einer Seite (z.B. +durch Plazierung des Seitenendes zwischen zwei Absätzen), so werden diese +von 'pageform' automatisch aus der Druckdatei entfernt. Will man Leerzeilen +am Anfang einer Seite#ie#, dann sollte das 'free' in Verbindung mit der +'page'-Anweisung verwandt werden. + +Zusätzlich ist es möglich, Leerzeilen in eine Seite der Druckdatei einzu- +fügen und/oder beliebige Zeilen zu löschen (vergl. b)). + +Folgende Operationen stehen bei der interaktiven Seitenformatierung zur +Verfügung: + +a) Seitenende verschieben: + +'pageform' berechnet das "rechnerische" Seitenende und zeigt dieses auf dem +Bildschirm durch die Markierung an. Die Markierung kann interaktiv verschoben +werden: + + Taste Bedeutung + + RETURN Seitenende an diese Stelle plazieren. + OBEN Seitenende eine Zeile nach oben verschieben. + UNTEN Seitenende eine Zeile nach unten verschieben + (wenn vorher nach "oben" verschoben). + HOP OBEN Seitenende um einen Bildschirm nach oben verschieben. + HOP UNTEN Seitenende um einen Bildschirm nach unten verschieben. + +b) Leerzeilen einfügen und/oder Zeilen löschen + +Ergeben die Berechnungen von 'pageform', daß der bearbeitete Text nicht +richtig auf der Seite plaziert ist, können in die Seite (der Druckdatei!) +Leerzeilen eingefügt und/ oder Zeilen gelöscht werden. Dies kann beispiels- +weise sinnvoll sein, wenn durch die Löschung einer Zeile ein Absatz noch auf +die Seite passen würde oder durch die Einfügung von Leerzeilen ein Absatz +auf der letzten Zeile der Seite endet. Oft ist es auch sinnvoll, daß alle +Seiten gleich lang sind. In diesem Fall sollten vor Kapiteln und Absätzen +Leerzeilen eingefügt oder gelöscht werden. + +Um Leerzeilen einzufügen und/oder Zeilen zu löschen, muß die Markierung (wie +unter a) beschrieben) an die Stelle plaziert werden, an der die Änderung +vorgenommen werden soll. Abschließend berechnet 'pageform' die Seite erneut. + + Taste Bedeutung + + HOP RUBIN Leerzeilen einfügen. + Anstatt der Markierung können durch (u.U. mehrmaliges) + RETURN Leerzeilen eingefügt werden. HOP RUBIN beendet + den Vorgang (wie Zeileneinfügen im Editor). + + HOP RUBOUT Zeile löschen. + Die Zeile unmittelbar oberhalb der Markierung wird + gelöscht. + +'page'-Anweisung bestätigen/löschen + +Wird von der Prozedur 'pageform' eine 'page'-Anweisung angetroffen, so wird +das so gewünschte Seitenende auf dem Bildschirm des Benutzers angezeigt. Die +'page'-Anweisung kann entweder bestätigt oder gelöscht werden. + + Taste Bedeutung + + RETURN Seitenende bestätigen. + + RUBOUT 'page'-Anweisung ignorieren. Die Prozedur 'pageform' + bearbeitet in diesem Fall die Datei weiter, als ob + keine 'page'-Anweisung angetroffen wurde. + +Merke: Ein Seitenende wird von 'pageform' auf dem Bildschirm angezeigt. Dies +kann man mit den Positionierungstasten verschieben. Es können in die Seite +Leerzeilen eingefügt oder Zeilen gelöscht werden. Eine 'page'-Anweisung kann +man bestätigen oder löschen. + + + +Seitenlänge einstellen: 'pagelength' + +'pageform' ist auf eine Seitenlänge von 25.0 cm eingestellt (entspricht +einem DINA4-Schreibfeld). Ist eine andere Seitenlänge erwünscht, muß die +'pagelength'-Anweisung in den Text eingefügt werden. + +Beispiel: + + \#pagelength (20.0)\# + +stellt die Seitenlänge auf 20 cm ein. Man beachte, daß der Dezimalpunkt bei +der Seitenlänge mit angegeben werden muß. + +Die folgende Tabelle gibt die Seitenlänge für die am häufigsten gewählten +Papiergrößen an: + + Format Seitenlänge oberer und + (in cm) unterer Rand + + DIN A4 25.0 je 2.35 cm + + DIN A5 18.0 je 2.15 cm + + DIN A4 quer 18.0 je 2.15 cm + +Merke: Mit der 'pagelength'-Anweisung kann die Seitenlänge (in cm) einge- +tellt werden. + + + +Zeilenabstand einstellen: 'linefeed' + +Die 'linefeed'-Anweisung stellt einen Zeilenvorschub relativ zu der Schrift- +höhe des eingestellten Schrifttyps ein. + +'pageform' berechnet die Anzahl Zeilen/Seite immer in Abhängigkeit vom einge- +stellten Schrifttyp. Hat man z.B. eine Schrift gewählt, die doppelt so hoch +wie z.B. eine Schreibmaschinenschrift ist, bekommt man auch entsprechend +weniger Zeilen auf eine Seite. Um diesen Berechnungsvorgang braucht sich ein +Nutzer in der Regel nicht zu kümmern. + +Anders verhält es sich, wenn ein anderer Zeilenvorschub als der "normale" +Abstand zwischen Zeilen vorgenommen werden soll. In diesem Fall muß man wis- +sen, daß die "Höhe" einer Zeile sich aus der Schrifttypgröße errechnet plus +(ca.) 10%, welches den Abstand zwischen den Zeilen darstellt. + +Soll nun ein anderer Abstand eingestellt werden, wird die 'linefeed'-An- +weisung eingesetzt. Der Parameter gibt an, um wieviel eine Zeilenhöhe erhöht +oder verringert werden soll. Beispiel: + + \#linefeed (2.0)\# + +Nach Antreffen dieser Anweisung wird die Zeilenhöhe durch 2 * eingestellte +Schrifttypgröße errechnet. Es wird also der Zeilenabstand zwischen den Zeilen +entsprechend vergrößert, da die Schriftgröße gleich bleibt. Dies entspricht +dem zweizeiligen Schreiben bei einer Schreibmaschine (wenn man davon absieht, +daß hier auch unterschiedliche Schrifthöhen berücksichtigt werden). Ein +1 1/2 zeiliges Schreiben wäre mit + + \#linefeed (1.5)\# + +einzustellen. + + \#linefeed (0.5)\# + +stellt die Zeilenhöhe = 1/2 * eingestellte Schrifthöhe ein, so daß die Zeilen +teilweise ineinander gedruckt werden. Bei 'linefeed (0.0)' werden Zeilen +übereinander gedruckt (druckerabhängig). + +Man beachte, daß die Angabe in der 'linefeed'-Anweisung relativ erfolgt. Bei +allen anderen Anweisungen der Textkosmetik werden Angabe in Zentimeter ver- +langt. Die 'linefeed'-Anweisung bildet somit eine Ausnahme (von der Regel). + +Merke: Wieviel Zeilen auf eine Seite passen, ist von den Höhen der einge- +stellten Schrifttypen abhängig. Diese Berechnung erfolgt automatisch durch +'pageform'. Die 'linefeed'-Anweisung stellt einen Zeilenvorschub relativ zum +eingestellten Schrifttyp ein. + + + +Platz freihalten: 'free' + +Mit der 'free'-Anweisung kann man einen zusammenhängenden Teil auf einer +Seite freihalten. + +Die 'free'-Anweisung wird an solchen Stellen im Text eingesetzt, an denen - +nach dem Druck - Zeichnungen, Tabellen und ähnliches eingeklebt werden sol- +len. Es wird der in der 'free'-Anweisung angebene Platz freigehalten. Bei- +spiel: + +\#free (2.0)\# +hält zwei Zentimeter frei. Paßt der angeforderte Platz nicht mehr auf die +Seite, so wird der angeforderte Platz auf der nächsten Seite reserviert +('pageform' plaziert das Seitenende vor die 'free'-Anweisung). + +Merke: Die 'free'-Anweisung hält einen Platz auf dem Papier frei (Angabe in +cm). + + + +Neue Seite beginnen: 'page' + +An einigen Stellen im Text, z.B. zu Beginn eines neuen Kapitels, soll unbe- +ingt eine neue Seite angefangen werden. + +Dies erreicht - wie bereits erwähnt - man mit der 'page'-Anweisung. 'page- +form' meldet im diesem Fall, nach wieviel cm auf der Seite die Anweisung an- +getroffen wurde. Man kann nun mit RETURN das Seitenende bestätigen, oder die +Anweisung (in der Druckdatei) löschen. Im letzteren Fall berechnet 'page- +form' die Seite neu (als ob die 'page'-Anweisung nicht dagewesen wäre). + +Gleichzeitig ist es möglich, mit Hilfe der 'page'-Anweisungs eine neue Sei- +tennummer#ie# für die neue Seite einzustellen (vergl. die nächsten Ab- +chnitte). + +Merke: Die 'page'-Anweisung bewirkt eine neue Seite und muß beim Formatieren +bestätigt werden. + + + +Kopf- und Fußzeilen: 'head/bottom' + +Mit den 'head'- und #ib#'bottom'-Anweisung#ie#en ist es möglich, Zeilen am +Anfang und Ende jeder Seite einfügen zu lassen. + +Zeilen am Anfang ("Kopfzeilen") und Ende ("Fußzeilen") jeder Seite werden +nur einmal geschrieben und mit Anweisungen gekennzeichnet. Diese Zeilen fügt +'pageform' dann an den entsprechenden Stellen ein. Beispiel: + +\#head\# + Unser EUMEL-Benutzerhandbuch + +\#end\# + +Diese zwei Zeilen (also die zwischen den 'head'- und 'end'-Anweisungen ein- +geschlossenen Zeilen) werden unverändert von 'pageform' an den Anfang jeder +Seite in die Druckdatei plaziert. Man beachte, daß zweckmäßigerweise (minde- +stens) eine Leerzeile nach einer solchen Kopfzeile in den 'head'-Bereich ein- +gefügt werden sollte, um die Kopfzeile von dem eigentlichen Text der Seite zu +trennen. + +Entsprechendes gilt für Fußzeilen, die zwischen 'bottom' und 'end' einge- +chlossen werden müssen: + +\#bottom\# + Autor: I. Listig +\#end\# + +Praktischer Tip: Man füge nach einer Schriftzeile mindestens eine Leerzeile +ein (in einem 'head') bzw. vor der Schriftzeile (in einem 'bottom'), um den +eigentlichen Text von den Kopf- bzw. Fußzeilen abzuheben. + +'pageform' zählt die Seiten, beginnend mit der Seitennummer '1'. (Wie man +Seitennummern in die Kopf- und Fußzeilen bekommt, verraten wir im nächsten +Abschnitt). Es ist nun möglich, getrennte Kopf- und Fußzeilen für gerade und +ungerade Seiten zu gestalten (wie in diesem Benutzerhandbuch). Dies erfolgt +mit den Anweisungen 'headeven' und 'headodd' für Seiten mit geraden und un- +geraden Seitennummern; ('bottomeven' und 'bottomodd' dito). + +Diese Anweisungen müssen ebenfalls jeweils mit einer 'end'-Anweisung be- +endet werden. + +Es ist möglich, Kopf- und Fußzeilen mehrmals innerhalb einer Datei zu +wechseln, um unterschiedliche Beschriftungen zu erhalten (z.B. kapitelweise). +Dies ist jedoch nur sinnvoll, wenn dies auf einer neuen Seite erfolgt, also +unmittelbar nach einer 'page'-Anweisung in den Text eingefügt wird. Beispiel: + + \#page\# + \#head\# + Neuer Seiten Kopf + + \#end\# + +"Fußzeilen" sollen überall gleiches Aussehen haben, unabhängig davon, welche +Anweisungen im restlichen Text gegeben werden. Darum werden die bei der De- +finition einer Fußzeile aktuellen Werte für + + limit + type + linefeed + +bei dem Einsetzen der Zeilen berücksichtigt. Es ist somit erlaubt, einen +anderen Schrifttyp (z.B. als der restliche Text) für Fußzeilen zu verwenden, +indem die 'type'-Anweisung innerhalb des 'bottom'-Bereiches gegeben wird. +Beachte, daß nach 'head'-, 'bottom' und auch 'foot'-Bereiche die o.a. Kom- +mandos nicht automatisch zurückgestellt werden. Darum sollte vor der 'end'- +Anweisung wieder auf den im übrigen Text verwandten Schrifttyp zurückge- +stellt werden. Gleiches gilt für die 'limit'- und 'linefeed'-Anweisung. +Beispiel: + + \#bottom\# + \#type ("besonders schoen")\# + Autor: I. Listig + + (Schriftyp zurückstellen): \#type ("normal")\# \#end\# + +Merke: Kopf- und Fußzeilen können durch die Anweisungen 'head' bzw. 'bottom' +oder 'headeven', 'headodd' bzw. 'bottomeven', 'bottomodd' definiert werden. +Die Zeilen müssen jeweils durch die 'end'-Anweisung beendet werden. + + + +Seiten numerieren + +In den Kopf- und Fußzeilen steht das '%'-Zeichen für die aktuelle Seiten- +nummer. + +Erscheint das '%'-Zeichen innerhalb eines Kopf- oder Fußbereiches, wird von +'pageform' beim Einsetzen dieser Zeilen auf jeder Seite die aktuelle Seiten- +nummer#ie# eingesetzt (sind mehrere '%'-Zeichen vorhanden, wird die Seiten- +nummer mehrmals eingesetzt). Beispiel: + +\#head\# + Seite: - % - + +\#end\# + +Durch einen Fußbereich kann man die Seitennummern auch am Ende einer Seite +haben. Man beachte, daß sich bei mehrstelligen Seitennummern durch das Ein- +setzen die Zeilenlänge vergrößert. + +Manchmal ist es notwendig und sinnvoll, einen Text in mehreren Dateien zu +halten. Bei einer Folgedatei muß die Seitennummer dann neu gesetzt werden. +Das erfolgt mit der 'page'-Anweisung. Beispiel: + +\#page (4)\# + +vollzieht eine neue Seite. Die Seitennummer der neuen Seite ist '4'. + +Bei einigen Spezialanwendungen benötigt man mehr als eine Seitennummer. +Beispielsweise soll ein Text nicht nur absolut, sondern auch jede Seite in +jedem Kapitel separat durchgezählt werden. Eine andere Anwendung ist die +Benennung einer Folgeseite, wie in diesem Beispiel: + +\#page (4711)\# +\#head\# + Mein Buch Seite: % + +\#end\# +\#pagenr ("$", 4712)\# +\#bottom\# + + Nächste Seite: $ +\#end\# + +Durch die 'pagenr'-Anweisung gibt man ein neues "Seitenzeichen" (hier: '$') +und den Anfangwert für diese Seitennummer (hier: '4712'), der ebenfalls wie +das '%'-Seitenzeichen von 'pageform' bei jeder neuen Seite um '1' erhöht und +ggf. in die Kopf- und Fußzeilen eingesetzt wird. Es sind zwei zusätzliche +Seitenzeichen (neben dem '%') möglich. + +Merke: In den Kopf- und Fußzeilen wird ein '%'-Zeichen von 'pageform' durch +die aktuelle Seitennummer ersetzt. Die Seitennummer kann durch das 'page'- +Anweisung neu gesetzt werden. + + + +Fußnoten schreiben: 'foot' + +Fußnoten werden direkt im Text durch die Anweisungen 'foot' und 'end' ge- +kennzeichnet. Die Fußnoten plaziert 'pageform' an das Ende einer Seite. + +Fußnoten werden vom Benutzer direkt in den Text geschrieben, am besten nach +einem Absatz. Die Fußnote wird von 'pageform' an das Ende einer Seite, ggf. +vor Fußzeilen plaziert. Für die Kennzeichnung von Fußnoten und die ent- +sprechende Markierung im Text ist der Benutzer selbst zuständig. Allerdings +wird von 'pageform' bei dem Einsetzen einer Fußnote am Ende einer Seite +Unterstreichungsstriche vor die Fußnoten eingefügt, damit Fußnoten vom +"normalen" Text abgehoben werden. + +\#foot\# +*) Das ist die erste Anmerkung auf dieser Seite. +\#end\# + +Mehrere Fußnoten innerhalb einer Seite werden von 'pageform' in der Reihen- +folge ihres Auftretens gesammelt und am Ende der Seite plaziert. Für eine +entsprechende Trennung der Fußnoten voneinander (z.B. durch Leerzeilen) hat +der Benutzer selbst zu sorgen. + +Man sollte eine Fußnote unmittelbar hinter den Absatz schreiben, in der die +Markierung für die Fußnote erscheint, denn u.U. paßt die Fußnote nicht mehr +auf die aktuelle Seite und muß somit von 'pageform' auf die nächste Seite +gebracht werden. 'pageform' geht davon aus, daß die Kennzeichnung der Fuß- +note in der Zeile unmittelbar vor der Fußnote steht und bringt diese Zeile +ebenfalls auf die neue Seite. + +Merke: Fußnoten werden direkt hinter einem Absatz in den Text mittels der +Anweisungen 'foot' und 'end' geschrieben, die 'pageform' an das Ende der +Seite einfügt. Die Kennzeichnung der Fußnoten hat der Benutzer selbst vorzu- +nehmen oder man kann sie mit Hilfe von 'count'- und 'value'-Anweisungen +durchnumerieren (siehe nächsten Abschnitt). + + + +Fußnoten numerieren: Zählen lassen + +Bei vielen Fußnoten in einem Text ist es nicht möglich, die Fußnoten beim +Schreiben des Textes entsprechend zu beschriften. Für diesen Fall und um auf +die Fußnote im Text nochmals Bezug nehmen zu können, bietet 'pageform' die +Möglichkeit an, die Fußnoten zu numerieren. + +Durch die 'count'-Anweisung wird 'pageform' veranlaßt, einen internen Zähler +(beginnend bei dem Wert 0) zu erhöhen und diesen Wert anstatt der 'count'- +Anweisungen in den Text einzusetzen. Beispiel: + +\#count\# + +setzt den Wert 1 anstatt der Anweisung ein (Anmerkung: trifft 'lineform' auf +eine 'count'-Anweisung, so wird die Zeile berechnet, als ob drei Ziffern +anstatt der Anweisung ständen). Jede weitere 'count'-Anweisung erhöht den +internen Zähler und der Zählerwert wird wiederum eingesetzt: + +\#count\# + +setzt den Wert 2 ein usw. Dadurch ist es möglich, beliebige Textteile +(Kapitel, mathematische Sätze u.a.m.) fortlaufend zu numerieren, ohne auf +die Numerierung beim Schreiben und Ändern des Textes zu achten. + +Mit der 'value'-Anweisung kann man den letzten erreichten count-Wert noch- +mals einsetzen. Das ist insbesondere für Fußnoten sinnvoll einsetzbar. +Beispiel: + + Bla Bla Bla (\#count\#) + \#foot\# + Eine Fußnote + \#end\# + ... + +Das Resultat würde folgendermaßen aussehen: + + Bla Bla Bla (3) + .... + + _____ + (3) Eine Fußnote + +Man beachte, daß in diesem Fall die 'value'-Anweisung der 'count'-Anweisung +folgen muß, ohne das eine weitere 'count'-Anweisung dazwischen steht. Das +liegt - wie bereits erwähnt - daran, daß die 'value'-Anweisung immer den +letzten 'count' Wert einsetzt. + +Das kann man umgehen, indem die 'count'- und 'value'-Anweisungen mit einem +TEXT-Parameter versehen werden, der als Kennzeichnung dient. Beispiel: + + \#count ("Merk1")\# + +arbeitet ebenso wie 'count' ohne Parameter (setzt also hier den Wert 4 ein), +aber zusätzlich vermerkt 'pageform' den aktuellen Zählerwert neben dem Kenn- +zeichen. Nun ist es mit der 'value'-Anweisung möglich, den vermerkten Zähler- +wert durch Angabe des Kennzeichens an beliebigen Stellen im Text zu reprodu- +zieren (auch wenn der interne Zähler weitergezählt wurde). Beispiel: + + \#count\#\#count\# + \#value("Merk1")\# + +Die ersten zwei 'count'-Anweisungen produzieren - wie beschrieben - die +Werte 5 bzw. 6. Die 'value'-Anweisung dagegen setzt den vermerkten Wert 4 +ein. + +Dies ist insbesondere sinnvoll, wenn man im Text auf eine Fußnote verweisen +will. Beispiel: + + Bla Bla. Siehe auch Anmerkung (\#value ("Waldschrat")\#). Bla + ... + ... + Bla Bla Bla (\#count ("Waldschrat")\#) + \#foot\# + (\#value ("Waldschrat")\#) Waldschrate kommen in vier Farben vor: + Rot, schwarz, grün und blau/gelb. + \#end\# + +Manchmal ist es notwendig (ebenso wie bei der Seitennummer), den internen +Zähler neu zu setzen. Beispiel: + + \#setcount (13)\#\#count ("aha!")\# + +produziert den Wert 13. + +Merke: Die 'count'-Anweisung setzt einen internen Zähler in die Druckdatei +ein. Durch die #ib#'value'-Anweisung#ie# werden gespeicherte Werte einge- +setzt, was man bei Fußnoten ausnutzen kann. + + + +Querverweise mit 'topage'/'goalpage' + +Mit den Anweisungen 'topage' und 'goalpage' sind Querverweise möglich, die +von 'pageform' in die Druckdatei eingefügt werden. + +Mit Hilfe von Querverweisen soll auf andere Stellen im Text verwiesen werden, +was nur bei längeren Texten üblich ist. Um dem Leser die mühselige Suche +nach der Textstelle zu ersparen, gibt man in der Regel die Seitennummer an. +Leider steht die Seitennummer vor der Fertigstellung des Textes meist noch +nicht fest. Auch in diesem Fall kann 'pageform' helfen. Die 'topage'- An- +weisung verweist auf eine andere Seite im Text, an der sich eine Anweisung +'goalpage' befinden muß. Anstatt der Anweisung 'topage' wird die Seitennum- +mer der Seite eingesetzt, auf der sich 'goalpage' befindet. Damit jedes +'topage' auch (sein) entsprechendes 'goalpage' findet, wird bei beiden An- +weisungen ein TEXT-Parameter angegeben. Beispiel: + + Man schreibt: ... siehe auch auf Seite \#topage("verweis1")\# + ... + Auf einer anderen Seite befindet sich \#goalpage("verweis1")\# + +Nach 'Seite' wird die entsprechende Seitennummer eingesetzt. + +Es ist möglich, mehrmals auf die gleiche (Ziel-) Seite zu verweisen, man muß +nur darauf achten, daß immer das gleiche Merkmal (TEXT-Parameter) verwandt +wird. + +Merke: Mit den 'topage'- und 'goalpage'-Anweisungen sind Seitenquerverweise +möglich. Für 'topage' wird die Seitennummer eingesetzt, auf der 'goalpage' +steht. + + + +Formatierung von Spalten: 'columns' + +Mit der 'columns'-Anweisung ist es möglich, einen Text in Spalten zu forma- +tieren ("Zeitungsdruck"). + +Durch die Angabe der 'columns'-Anweisung wird 'pageform' aufgefordert, den +Text in Spalten zu formatieren. Die Spaltenbreite muß der Benutzer mit der +'limit'-Anweisung einstellen. Beispiel: + + \#limit (18.0)\# + ... + \#columns (2, 2.0)\#\#limit (8.0)\# + ... + +Anfangs schreibt der Benutzer mit einer Zeilenbreite von 18 cm. Dann fordert +er mit der 'columns'-Anweisung zweispaltigen Druck an (zwischen den Spalten +soll 2 cm Abstand sein). Somit muß die 'limit'-Anweisung auf 8 cm einge- +stellt werden. + +Die interaktive Spaltenformatierung wird von 'pageform' wie gewohnt vorgenom- +men. Auf dem Bildschirm erscheint nun das Spaltenende, wobei die Nummer der +Spalte angezeigt wird. Fußnoten werden spaltenweise eingeordnet und müssen +somit die gleiche Zeilenbreite haben, wie die restlichen Spalten. + +'pageform' erzeugt in der Druckdatei die Spalten hintereinander. Das folgende +Beispiel zeigt einen Ausschnitt aus der Druckdatei mit Kopf- und Fußzeilen +bei einem zweispaltigen Druck: + + head-Zeilen + xx + xx + xx + bottom-Zeilen + \#page\#\#------- Ende Seite 1 Spalte 1 ----\# + xx + xx + xx + \#page\#\#------- Ende Seite 1 Spalte 2 ----\# + +Die zweite Spalte erscheint also ohne Kopf- und Fußzeilen, die jedoch bei der +Berechnung berücksichtigt werden. Man beachte, daß die Kopf- und Fußzeilen +über die Spalten gehen können. Dies erreicht man durch geeignete 'limit'- +Anweisungen in den genannten Bereichen. Hochwertige Drucker plazieren die +zweite Spalte im Druckbild neben die erste. Bei preiswerteren Druckern muß +man die Spalten nebeneinander kleben. + +Es ist zwar prinzipiell möglich, die Spalten in der Druckdatei nebeneinander +zu schreiben. Jedoch hätte das Druckerprogramm Schwierigkeiten, diese neben- +einander zu drucken, ohne daß z.B. ein Schrifttypwechsel in einer Spalte +Auswirkungen auf eine Benachbarte hat. Praktischer Tip: Bei Druckern mit +"Traktorführung" kann man erst alle ersten Spalten drucken, dann das Papier +"von Hand" zurückdrehen und die zweiten Spalten drucken usw. + +Alle Anweisungen funktionieren beim spaltenweisen Formatieren wie üblich. Die +'free'-Anweisung z.B. hält entsprechenden Platz in einer Spalte frei. Eine +Ausnahme bildet die 'page'-Anweisung. Sie vollzieht hier ein Spaltenende. Die +'page'-Anweisung mit einem Parameter (welcher die Seitennummer der nächsten +Seite angibt), vollzieht dagegen ein Seitenende. + +Die 'columns end'-Anweisung beendet die spaltenweise Formatierung. Es ist +zweckmäßig, unmittelbar vor der 'columns'- und hinter der 'columns end'- +Anweisung eine 'page'-Anweisung zu schreiben. + +Überschriften (bzw. Textblöcke) über mehrere Spalten hinweg sind nur in der +ersten Seite direkt hinter der 'columns'-Anweisung möglich. Beispiel: + + \#page\# + \#limit (18.0)\# + HEAD + Breite Überschrift + \#columns (2, ...)\#\#limit (8.0)\# + XX + XX + XX + Bottom + \#page\#\#------- Ende Seite 1 Spalte 1 ----\# + XX + XX + XX + \#page\#\#------- Ende Seite 1 Spalte 2 ----\# + +Die Zeilen für die zweispaltige Überschrift werden berücksichtigt. Dies gilt +jedoch nur unmittelbar hinter der 'columns'-Anweisung. Will man diesen Effekt +nochmals haben, beendet man mit 'columns end', schreibt die 'page'-Anweisung, +die breite Überschrift und schaltet die 'columns'-Anweisung wieder ein usw. + +Merke: Die Anweisungen 'columns'- und 'columns end' bewirken ein spalten- +weises Formatieren des Textes durch 'pageform'. Die Spaltenbreite ('limit'- +Anweisung) hat der Benutzer selbst einzustellen. + + + +4. Stichwortverzeichnisse erstellen: 'index'-Kommando + +Das Programm 'index' kann Stichwort- und Inhaltsverzeichnisse erstellen. +Stichwortverzeichnisse#ie# können sortiert werden. Mehrere Stichwortver- +zeichnisse können durch 'index merge' zusammengeführt werden. + + + +Übersicht über die Arbeitsweise von 'index' + +Durch den Aufruf von + + index ("datei.p") + +werden durch Indexanweisungen gekennzeichnete Worte in Dateien, den soge- +nannten Indexdateien, gespeichert. + +Anweisung Zweck + + ib Anfang Index + (folgende Worte werden bis zur 'ie'-Anweisung in den + Index übernommen) + ie Ende eines Index + +Solche Verzeichnisse von Worten werden im EUMEL-System allgemein als Index +bezeichnet. Nachdem eine oder mehrere Indexdateien aus einer Druckdatei +erstellt sind, werden die Indexdateien auf Anfrage alphabetisch sortiert. +Bei einem Inhaltsverzeichnis sollte man die Sortierung natürlich ablehnen. + +Nach der Sortierung werden gleiche Einträge automatisch zusammengefaßt und +die entsprechenden Seitennummern nacheinander aufgeführt. + +Praktischer Tip: Will man nur eine Sortierung, aber keine Zusammenfassung +von Einträgen, dann lehnt man die Sortieranfrage ab. Anschließend kann man +die Indexdatei mit 'lex sort ("indexdatei namen")' sortieren. Hierbei +bleiben gleiche Einträge erhalten. + +Das Programm + + index merge ("index.i1", "index.i2") + +erlaubt es, zwei durch 'index' erzeugte Verzeichnisse zusammenzuführen. +'index' kann ebenfalls benutzt werden, um ein Inhaltsverzeichnis und/oder +ein Verzeichnis aller Abbildungen zu erstellen oder Literaturhinweise zu +überprüfen. + +Die Worte, die durch 'index' in einen Index übernommen werden sollen, müssen +in der Eingabedatei (der Druckdatei aus 'pageform') für 'index' durch An- +weisungen gekennzeichnet werden. Die Form der Anweisungen entspricht der +ELAN-Syntax (analog den Anweisungen für 'lineform', 'pageform' und EUMEL- +Drucker). Solche #ib(1,"ff")#Indexanweisungen#ie# werden von den anderen +Textbe- und -verarbeitungs Programmen ('lineform', 'pageform', EUMEL- +Drucker) ignoriert. Man kann also bei dem Schreiben mit dem Editor gleich +festlegen, welche Worte in einen Index aufgenommen werden sollen. + + + +Worte kennzeichnen: 'ib'/'ie' + +Da in einem Index - neben dem eigentlichen Worteintrag - die Seitennummer +enthalten sein soll, arbeitet das Programm 'index' nur mit einer Druckdatei, +d.h. einer Ausgabedatei von 'pageform'. Die Indexworte werden in Indexda- +teien gesammelt. Die Indexdateien erhalten den Namen der zu bearbeitenden +Datei, an den ".i" und die Nummer des Index angefügt wird. Beispiel: + + ... Hier wird eine Eigenschaft des \#ib(1)\#EUMEL-Systems\#ie(1)\# beschrieben. + +(Die durch die Anweisungen 'ib' und 'ie' gekennzeichneten Worte werden mit +der dazugehörigen Seitennummer in die erste Indexdatei geschrieben.) + +Die Einträge in einer Indexdatei werden von den Seitennummern durch min- +destens drei Punkte getrennt. + +Werden diese nicht gewünscht, kann man sie leicht mit dem Editor entfernen. +Beachte, daß man nur bei einer äquidistanten Schrift ein rechtsbündiges +Verzeichnis erhalten kann. + +Es gibt die Möglichkeit, bis zu neun unterschiedliche Indexdateien zu er- +stellen, z.B. durch + + \#ib (1)\# und \#ie (1)\# + +gekennzeichnete Worte gehen in die Indexdatei mit der Nummer 1, durch + + \#ib (9)\# und \#ie (9)\# + +gekennzeichnete Worte gehen in die Indexdatei mit der Nummer 9. Als Erleich- +terung für diejenigen, die nur einen Index erstellen müssen, dürfen die 'ib'- +und 'ie'-Anweisungen ohne Parameter benutzt werden, welches gleichbedeutend +ist mit 'ib(1)' und 'ie(1)'. + +Die durch 'ib'- und 'ie'-Anweisungen gekennzeichneten Worte können auch über +Zeilengrenzen (mit Silbentrennungen) gehen. Beispiel: + + .... \#ib\#schöne Index-An- + weisungen\#ie\# ... + +'index' zieht getrennte Worte zusammen (hier: 'schöne Index-Anweisungen'). +Will man einige Worte in verschiedenen Indexdateien haben, darf man die 'ib'- +und 'ie'-Anweisungen auch "schachteln". Dies kann man besonders bei Kapitel- +überschriften nutzen. Beispiel (vergl. auch die Überschrift dieses Ab- +schnitts): + + \#ib(9)\#Worte kennzeichnen: '\#ib\#ib\#ie\#'/'\#ib\#ie\#ie\#'\#ie(9)\# + +In diesem Beispiel wird das Inhaltsverzeichnis in die Indexdatei '9' ge- +bracht, während der "allgemeine" Index in der Indexdatei '1' gesammelt wird. + + + +Nebeneinträge erzeugen + +Es ist möglich, an die Seitennummer eines Eintrags einen beliebigen Text +anfügen zu lassen. Beispiele: + + EUMEL-System ... 27ff. + Monitor ........ 13(Def.) + EUMEL-Editor ... 2(Kap.4) + +Dies wird durch die generische Form der 'ib'-Anweisung ermöglicht: + + ... der \#ib(1,"(Kap.4)")\#EUMEL-Editor\#ie\# ist gut geeignet, + Texte zu erstellen ... + +(erzeugt den letzten obigen Eintrag). + +An einen Eintrag kann ein weiterer TEXT angefügt werden, um etwa Unterein- +träge zu bilden: + + EUMEL-System .............. 27 + EUMEL-System, kapitales ... 28 + EUMEL-System, schönes ..... 29 + +Das wird ebenfalls durch eine andere Form der 'ie'-Anweisung ermöglicht: + + ... ist das \#ib\#EUMEL-System\#ie(1,", schönes")\# wirklich ein + schönes System ... + +(erzeugt den letzten obigen Eintrag). + +Nach der Erstellung einer Indexdatei können - nach interaktiver Anfrage - die +Einträge sortiert werden. Die Sortierung erfolgt alphabetisch nach DIN 5007, +Abschnitt 1 und 3.2 (Umlaute werden "richtig" eingeordnet). + +Wie bereits erwähnt, kann 'index' vielseitig eingesetzt werden: + +a) Erstellung von Stichwortverzeichnissen: + Wie bereits beschrieben. + +b) Erstellung von Inhaltsverzeichnissen: + Kapitelüberschriften mit eigenen Indexanweisungen klammern und durch + 'index' wie beschrieben verarbeiten. Beispiel: + + \#ib(8)\#9.1.3 Das abenteuerliche Leben von Micky Maus unter + besonderer Berücksichtigung seiner Geburtsstadt Entenhausen\#ie(8)\# + + Dann ist man sicher, daß das Inhaltsverzeichnis bezüglich Seitennummern + und Kapitelüberschriften korrekt ist. + +c) Erstellung von Abbildungsverzeichnissen: + Abbildungsüber- bzw. -unterschriften wie Inhaltsverzeichnisse verarbeiten. + +d) Überprüfung von Literaturhinweisen auf Vollständigkeit: + Man klammert alle Literaturhinweise mit extra Indexanweisungen (Beispiel: + \#ib(9)\#/Meier82/\#ie(9)\#) und überprüft dann mit Hilfe dieser Indexdatei + die Literaturverweise. Dann ist man sicher, daß alle Literaturverweise im + Text auch in der Literaturaufstellung stehen. + + + +Indexdateien zusammenführen: 'index merge' + +Durch das Programm 'index merge' kann eine Indexdatei in eine zweite "einge- +mischt" werden. Es ist somit möglich, einen Index zu erstellen, der sich über +mehrere Dateien erstreckt, indem man 'index' die Druckdateien dieser Dateien +bearbeiten läßt und anschließend die entstandenen Indexdateien mit 'index +merge ' zusammenfaßt. Indexdateien können ggf. mit dem Editor bzw. 'lineform' +und/ oder 'pageform' bearbeitet und anschließend gedruckt werden. Beispiel: + + index merge ("1.kapitel.i1", "2.kapitel.i1") + +Hier wird die Indexdatei des '1.kapitel' in die Indexdatei des '2.kapitel' +eingeordnet und auf Wunsch sortiert. + +Beachte, daß 'index' und 'index merge' Kommandos und keine Anweisungen sind. + +Merke: 'index' verarbeitet eine Druckdatei (Zusatz: ".p") und erzeugt eine +oder mehrere Indexdateien (Zusatz: ".i<nummer>"). Die in einen Index zu +übernehmenden Worte müssen im Text durch die 'ib'- und 'ie'-Anweisungen +eingefaßt sein. + + + +5. Drucken: 'print' + +Der EUMEL-Drucker, der mit dem Kommando 'print' angesprochen wird, ist eine +Software-Schnittstelle zu einem angeschlossenem Drucker. In diesem Kapitel +wird erklärt, wie man mit dem EUMEL-Drucker eine Datei druckt und welche +speziellen Anweisungen den Drucker steuern. + +Jeder Drucker erbringt "hardwaremäßig" unterschiedliche Leistungen (z.B. +Randausgleich, Unterstreichung). Diese Leistungen werden durch Eingabe +spezieller Zeichenfolgen veranlaßt, die zwar genormt sind, aber von den Druk- +kerherstellern nicht eingehalten werden oder unterschiedlich interpretiert +werden. + +Um vom EUMEL-System unterschiedliche Drucker auf gleiche Weise ansprechen +zu können, wurde eine Software-Schnittstelle geschaffen, die EUMEL-Drucker +genannt wird. Der EUMEL-Drucker akzeptiert eine Datei und veranlaßt, daß +diese in geeigneter Weise gedruckt wird. Weiterhin beachtet der EUMEL- +Drucker die Anweisungen der Textkosmetik. Die Form der Anweisungen der +Textkosmetik und des EUMEL-Druckers sind gleich. + + + +Eine Datei drucken: 'print'-Kommando + +Mit dem Kommando + + print + +kann dem EUMEL-Drucker eine Datei zum Drucken übergeben werden. Beispiel: + + print ("Drucker Beschreibung") + +In der Regel ist im EUMEL-System (Multi-User) ein "Spooler" installiert, so +daß sofort mit der Arbeit fortgefahren werden kann. Der EUMEL-Drucker ar- +beitet in diesem Fall parallel zu anderen Arbeiten des Nutzers. + + + +Anweisungen für den EUMEL-Drucker + +Ein Text (eine Datei) kann vom Drucker auch ohne Anweisungen gedruckt +werden, etwa für Probedrucke. Für diesen Fall hat der Drucker vernünftige +Voreinstellungen. Für einen "normalen" Text braucht ein Benutzer keine spe- +ziellen Druckeranweisungen in den zu druckenden Text einzufügen, denn die +Anweisungen für die Textkosmetik reichen zur Druckersteuerung aus. Nur wenn +besondere Leistungen verlangt werden, wie z.B. Blocksatz oder den gedruckten +Text an eine bestimmte Stelle zu plazieren, sind Druckeranweisungen notwen- +dig. + +Werden vom Drucker Leistungen verlangt, die hardwaremäßig nicht vorhanden +sind, so sorgt der EUMEL-Drucker dafür, daß eine möglichst äquivalente +Leistung erbracht wird. Wird beispielsweise ein nicht vorhandener Schrifttyp +angefordert, wird mit dem Standard-Schrifttyp der jeweiligen Installation +gedruckt. + +Damit ist es möglich, einen Text auf einem Drucker zu drucken, der den ge- +forderten Typ nicht kennt und der eigentlich für einen anderen Drucker +bestimmt ist. + +Wie bereits erwähnt, beachtet der EUMEL-Drucker die gleichen Anweisungen wie +die Textkosmetik-Programme. Eine 'type'-Anweisung beispielsweise, welches +einen bestimmten Schrifttyp anfordert, wird also auch vom EUMEL-Drucker als +Befehlsfolge an den angeschlossenen Hardware-Drucker übergeben (sofern der +Schrifttyp auf dem Drucker realisierbar ist). Wie die Anweisungen ge- +schrieben werden müssen, wird in der Beschreibung der Textkosmetik ge- +schildert. + +Anweisungen werden nicht gedruckt. Besteht eine Zeile nur aus Anweisungen, +so wird diese Zeile vom EUMEL-Drucker nicht gedruckt. Im Gegensatz zu den +Programmen der Textkosmetik werden unbekannte oder fehlerhafte Anweisungen +vom EUMEL-Drucker ohne Fehlermeldung "verschluckt". Alle Anweisungen werden +zum frühest möglichen Zeitpunkt ausgeführt, haben also u.U. bereits Aus- +wirkungen auf die Zeile, in der sie stehen. + +Einige Anweisungen sind speziell nur für den EUMEL-Drucker vorhanden. +Diese werden in diesem Kapitel erklärt bzw. werden in der Anweisungs-Über- +sicht mit aufgeführt. + +Neben den "normalen" Anweisungen, die nur in "\#"-Zeichen eingeschlossen +werden, gibt es noch zwei andere Formen: + +a) Kommentar-Anweisungen: + Werden in "\#-" und "\#"-Zeichen eingeschlossen. Solche Anweisungen + werden ignoriert. Beispiel: + + \#---- Ende der Seite 1 ---\# + +b) Spezielle Druckeranweisungen: + Werden in "\#/" und "\#"-Zeichen eingefaßt. Die von diesen Anweisungs- + Zeichen eingeschlossenen Druckerbefehlen werden unverändert (ohne die + "\#/" und "\#"-Zeichen) an den Drucker weitergereicht. Beispiel: + + \#/C05\# (* C05 geht an den Drucker *) + + Solche Anweisungen werden manchmal benötigt, um spezielle Druckereigen- + schaften auszunutzen, die schwer oder garnicht im EUMEL-Drucker reali- + sierbar sind. + +Anmerkung: Diese Anweisungen werden, wie die normalen Anweisungen auch, bei +der Berechnung einer Zeile nicht berücksichtigt und nicht gedruckt. + +Merke: Der EUMEL-Drucker übernimmt die Anpassung an spezielle Hardware- +Drucker. Er beachtet die gleichen Anweisungen wie die Textkosmetik-Programme. +Zusätzlich gibt es noch einige wenige spezielle Druckeranweisungen. + + + +Blocksatz drucken: 'block' + +Die Anweisung 'block' bewirkt einen Blocksatz beim Druck. + +Fügt man in den Text (meist am Anfang einer Datei) die Anweisung + + \#block\# + +ein, druckt der Drucker ab dieser Stelle alle Zeilen, die nicht mit einem +Absatzkennzeichen versehen sind, im Blocksatz. Dies heißt, daß durch Ver- +größern der Wortabstände alle Zeilen an der gleichen Position enden (rechter +Randausgleich). Preiswerte Drucker können dies nur durch Einfügen ganzer +Leerzeichen zwischen den Worten vornehmen, was sich oft beim Lesen störend +bemerkbar macht. Bei qualitativ hochwertigen Druckern wird dagegen der +Blocksatz durch Einfügen kleinerer Abstände zwischen den Worten oder sogar +zwischen den Zeichen erreicht. + +Merke: Die Anweisung 'block' bewirkt den Blocksatz beim Druck. + + +Schreibfeld verschieben: 'start' + +Durch die Anweisung 'start' ist es möglich, das Schreibfeld beim Druck auf +dem Papier an eine andere Stelle zu plazieren. + +Der EUMEL-Drucker plaziert das Schreibfeld auf einem Drucker automatisch der- +art, daß ein genügender Rand verbleibt. Diese Voreinstellung ist natürlich +abhängig vom Drucker und der Installation. Mit der 'start'-Anweisung kann +die automatische Einstellung verändert werden. Beispiel: + + \#start (1.0, 2.0)\# + +legt die linke, obere Ecke des Schreibfeldes fest (vom linken Rand 1 cm, vom +oberen Rand 2 cm). + +Merke: Die 'start'-Anweisung legt den linken oberen Rand des Schreibfeldes +fest. + + + +Zentrieren + +Mit dem '#ib#center#ie#'-Kommando kann man eine Zeile in der Mitte der Zeile +drucken lassen. + +Das 'center'-Kommando zentriert die Schrift einer Zeile. Beispiel: + +\#center\#Diese Zeile ist zentriert + +Dies Kommando ist nur bei Proportionalschriften sinnvoll einzusetzen, da man +bei einer äquidistanten Schrift man direkt auf dem Bildschirm sehen kann, +wie der Text auf einer Zeile plaziert ist. + +Merke: 'center' zentriert eine Zeile beim Drucken. + + + +6. Textkosmetik-Makros + +Makros dienen als Abkürzung für immer wiederkehrende Textteile und/oder +Kommandos. + +Textkosmetik-Makros kommen zum Einsatz bei + +- immer wiederkehrenden Textteilen; + +- immer wiederkehrenden Anweisungssequenzen; + +- bei der Erstellung von Manuskripten, deren endgültige Form man anfänglich + noch nicht weiß oder die man noch ändern will. + +Die Definition von einem oder mehreren Makros wird mit dem Editor vorgenom- +men. Diese Makro-Datei wird dann geladen. Von diesem Augenblick an "kennen" +'lineform'/'autoform' und 'pageform' die Makros (d.h. die Textzeilen und/ +oder Anweisungen, die sich unter dem dem Makronamen "verbergen"). + +'lineform'/'autoform' beachten die Anweisungen, die in den Makros enthalten +sind. Man beachte, daß die Anweisungen und Textzeilen, die in den Makros ent- +halten sind, nicht in der Datei erscheinen. Erst 'pageform' setzt diese in +die Druckdatei ein. + + +Ein Beispiel + +Hier wird ein einfaches Beispiel für einen Briefkopf gezeigt. + +Angenommen, die Firma 'Meier' schreibt mit dem EUMEL-System ihre Geschäfts- +briefe. Sie hat einen Drucker zur Verfügung, mit dem man auch die Briefköpfe +erstellen kann. Für den Briefkopf schreibt die Junior-Chefin ein Makro'kopf' +in eine Datei 'macro definitionen': + + \#*kopf\# + \#type("fett und gross")\# Firma Meier + \#type("fett")\# Gemischtwaren in kleinen Mengen + \#type("klein")\# Straße + Stadt + \#type ("normal")\# + \#*macro end\# + +Der Name des Makros ist 'kopf'. Man beachte, daß eine Makro-Definition mit +dem Namen des Makros beginnen müssen. Der Makroname muß mit einem '*' +gekennzeichnet werden, um ihn von "normalen" Text-Anweisungen unterscheiden +zu können. Jedes Makro wird mit einer 'macro end'-Anweisung beendet +(es dürfen mehrere Makros hintereinander in die Datei geschrieben werden). + +Nun muß die Junior-Chefin das so definierte Makro 'laden': + + load macros ("macro defintionen") + +Zur Kontrolle kann sie sich die "geladenen" Makros in einen Datei ausgeben +lassen: + + list macros ("kontroll datei") + +Nun kann die Junior-Chefin ihrem Sekretär sagen, daß er von jetzt ab ein +neues Kommando zur Verfügung hat, welches einen Briefkopf in jeden Brief +drucken kann (mit dem Namen 'kopf'). Der Sekretär schreibt also nun +folgenden Brief: + +\#kopf\# + +Sehr geehrte Frau .... +usw. + +Nachdem er mit 'lineform' den Brief zeilenweise formatiert hat, kontrolliert +er die formatierte Datei. Hier hat sich noch nichts verändert, die neue An- +weisung 'kopf' steht unverändert in der Datei. ('lineform' beachtet zwar +alle Anweisungen und Textzeilen eines Makros, setzt diese jedoch nicht in +die Datei ein). + +Nun formatiert der Sekretär die Datei, welche den Brief enthält, mit 'page- +form'. In der Druckdatei ist nun die Anweisung 'kopf' verschwunden, dafür +stehen aber nun die Zeilen des Makrorumpfes ('pageform' setzt die Zeilen des +Makros in die Druckdatei ein): + + \#type("fett und gross")\# Firma Meier + \#type("fett")\# Gemischtwaren in kleinen Mengen + \#type("klein")\# Straße + Stadt + \#type ("normal")\# + + + Sehr geehrte Frau ... + usw. + +Merke: Makros sind bei der Verwendung von wenigen Text- und/oder Anweisungs- +folgen nützlich, die immer in der gleichen Form benötigt werden. + + +Ein Beispiel mit Makro-Parametern + +Unsere Junior-Chefin fällt nun auf, daß sie ihr Makro noch etwas verbessern +kann. Sie will noch das Datum mit in den Briefkopf aufnehmen. Somit editiert +sie ihre Makro-Datei folgendermaßen (man beachte die '$'-Zeichen): + + \#*kopf ($1)\# + \#type("fett und gross")\# Firma Meier + \#type("fett")\# Gemischtwaren in kleinen Mengen + \#type("klein")\# Straße + Stadtname + \#type ("normal")\# + + Stadtname, den $1 + \#*macro end\# + +Damit hat sie dem 'kopf'-Makro einem Parameter gegeben ('$1'; die Parameter +werden numeriert. Ein zweiter Parameter würde '$2' heißen usw.). + +Der Sekretär muß nun die Anweisung 'kopf' mit dem jeweiligen Datum in einen +Brief schreiben: + + \#kopf ("9.1.1984")\# + +'pageform' setzt nun das angegebene Datum direkt hinter 'Stadtname, den' in +den Briefkopf ein (in der Druckdatei). Beachte, daß nur TEXT-Denoter als +aktuelle Parameter eines Makros erlaubt sind. + +Merke: Durch die Makro-Parameter ist es also möglich, immer wiederkehrende +Textteile in Schriftstücke einsetzen zu lassen, die sich nur in Kleinigkei- +ten unterscheiden. + + +Ein Beispiel für Manuskripte + +Hier wird gezeigt, wie man mit Makros Anweisungen formulieren kann, die aus- +sagen, um was es sich bei einem Text handelt und nicht, wie es behandelt +werden soll. + +Bei Manuskripten für Artikel, Bücher und Manuals weiß ein Autor oft vorher +nicht, in welchem Format das Manuskript gedruckt werden wird. Zu diesem +Zweck ist es ebenfalls nützlich, die Makros zu verwenden. Beispiel: + + \#*kapitel anfang ($1)\# + \#free (2.0)\# + \#type ("gross und fett")\#\#ib (9)\#$1\#ie (9)\#\#type ("normal")\# + + \#*macro end\# + +In diesem Beispiel wird ein Makro für den Anfang eines Kapitels definiert. +Zwischen zwei Kapiteln soll hier zwei cm Zwischenraum bleiben, die Kapitel- +Überschrift (als Parameter) wird in einer grösseren Schrift gedruckt. Zu- +sätzlich wird die Überschrift in den 9. Index aufgenommen für ein Inhalts- +verzeichnis. Nach der Überschrift wird eine Leerzeile eingeschoben, bevor +der "richtige" Text anfängt. + +Ein(e) Anwender(in) dieses Makros schreibt also z.B. folgende Anweisung: + + \#kapitel anfang ("Ein Beispiel fuer Manuskripte")\# + +(Beachte, daß die Kapitel-Überschrift nicht länger als eine Textzeile sein +darf. Das liegt daran, das 'lineform'/'autoform' zwar die Zeile bearbeitet, +aber nicht in den Text einsetzt. 'pageform' setzt also die unveränderte +- nicht aufgebrochene Textzeile - ein). + +Man kann nun Makros für die meisten Textstrukturen definieren. Schreibkräfte +brauchen dann in der Regel die meisten der Text-Anweisungen nicht zu kennen, +sondern nur noch eine Anzahl von einfachen Makro-Anweisungen. + +Die Makro-Definitionen können jederzeit geändert werden, um wechselnden +Bedürfnissen angepaßt zu werden (z.B. wenn ein Verlag ein bestimmtes +Schreibformat verbindlich vorschreibt). In diesem Fall brauchen nicht alle +Text-Dateien geändert zu werden, sondern nur die Makro-Definitionen. + +Ein weiterer Vorteil einer solchen Vorgehensweise ist, daß die Makro-Anwei- +sungen in diesem Fall angeben, was eine bestimmte Text-Struktur ist, und +nicht, wie die Struktur behandelt werden soll. + +Anmerkung: +In eine Makro-Definition sollte man ggf. 'limit'-, 'type'- und 'linefeed'- +Angaben einsetzen, um die Makros unabhängig von der Aufrufstelle zu machen. +Ggf. sollte man die Datei vorher mit 'lineform' bearbeiten, um Trennungen +vorzunehmen. + +Merke: Makros dienen zur flexiblen Behandlung von Text-Strukturen, indem +Makros definiert werden, die angeben, um was es sich dabei handelt. + + + +Beschreibung der Makro-Kommandos + +Mit dem Kommando + + load macros ("macro datei") + +kann eine Datei, in denen die Makro-Definitionen enthalten sind, in den +Makro-Speicher des Textsystems geladen werden. Ist dies fehlerfrei erfolgt, +kann man 'lineform'/'autoform' Dateien übergeben, die die definierten Makro- +Anweisungen "kennen" und befolgen. 'pageform' setzt bei Antreffen einer +Makro-Anweisung den Makrorumpf in die Ausgabe-Datei ein. + +Die Definition eines Makros erfolgt mit dem Makronamen, der von Anweisungs- +zeichen eingeschlossen ist. Um Makro-Anweisungen von "normalen" Textkosmetik- +Anweisungen zu unterscheiden, müssen diese nach dem ersten Anweisungszeichen +mit einem '*' gekennzeichnet werden. Beispiel: + + \#*macro eins\# + Makrorumpf mit "normalen" Kommandos, wie z.B. + \#type ("x")\# + \#*macro end\# + +Der Aufruf eines Makros, welcher z.B. in einer von 'lineform' zu bearbeiten- +den Datei steht, unterscheidet sich nicht von einer "normalen" Textanweisung. +Beispiel: + + ... \#macro eins\# ... + +Hat das Makro Parameter (bei der Definition mit '$'-Zeichen durchnumeriert), +müssen beim Aufruf TEXT-Parameter eingesetzt werden (also in Anführungs- +strichen). Beispiel: + + \#*macro zwei ($1)\# + ... $1 ... + \#*macro end\# + + (* Aufruf: *) + + \#macro zwei ("ein einzusetzender Text")\# + +Anmerkung: +Bei Makros gibt es keine generischen Anweisungen. Makros, die gleiche Namen +haben, aber sich durch die Anzahl der Parameter unterscheiden, sind also +nicht erlaubt. + +Beachten Sie ferner, daß Makro-Texte so verwendet werden, wie diese mit +'load macros' geladen werden. Beispiel: + + \#*a\# + \#on("underline")\# + \#*macro end\# + + \#*b\# + \#off("underline")\# + \#*macro end\# + +Betätigt man in der Makro-Datei nach jeder Zeile die RETURN-Taste (Absatz), +dann erhält man bei folgender Verwendung Fehlermeldungen von 'lineform': + + ... \#a\#zu unterstreichender Text\#b\# ... + +weil hier Mitten im Satz Absätze erscheinen und 'lineform' bei jedem Absatz +prüft, ob noch Modifikationen "offen" sind. In solchen Anwendungen sollte +man also Makros ohne Absätze speichern. + + + +7. Anweisungs-Übersicht + +* block + Zweck: Blocksatz (rechter Randausgleich). Der Text einer Zeile wird durch + Vergrößern der Wortlücken auf die Zeilenlänge, die durch das + 'limit'-Kommando eingestellt ist, verlängert. Es gelten folgende + Bedingungen: + a) Leerzeichen werden nicht verbreitert bei + - Zeilen mit Absatzzeichen; + - Mehrfache Leerzeichen; + - führende Leerzeichen (Einrückung); + - ein Leerzeichen hinter dem ersten Wort einer Zeile, wenn es auf + die Zeichen "]", ")", ".", "-", ":" endet. + b) Einrückungen werden äquidistant berechnet (Anzahl Zeichen * + Breite eines "Standard-Blanks"). Dies gilt nur für Proportional- + schriften und vor einer Absatzzeile. Es gilt als Einrückung: + - "Spiegelstrich" (Bindestrich und Leerzeichen am Anfang der + Zeile); + - Doppelpunkt als Ende des ersten Wortes (Position < 20); + - Schliessende Klammer oder Punkt als Ende des ersten Wortes, + wenn eine Ziffer davor steht (Position < 7); + c) Tabellen werden auch äquidistant berechnet. Dies gilt ebenfalls + nur für Proportionalschriften und vor einer Absatzzeile. Es gilt + als Teil einer Tabelle: + - Position des letzten Mehrfachblank. + +* bottom + Zweck: Erzeugen von "Fußzeilen" am Ende jeder Seite in der Druckdatei für + Untertitel und Seitennummern. Die Textzeilen zwischen den Anwei- + sungen 'bottom' und 'end' werden von 'pageform' am Ende jeder Seite + eingesetzt. + +* bottom even + Zweck: Definition von Fußzeilen für Seiten mit geraden Seitennummern. Es + gilt das unter 'bottom' gesagte. + +* bottom odd + Zweck: Definition von Fußzeilen für Seiten mit ungeraden Seitennummern. Es + gilt das bei 'bottom' gesagte. + +* center + Zweck: Zentrieren einer Zeile (Absatzzeile). + +* columns (INT CONST anzahl, REAL CONST luecke) + Zweck: Einschalten der Spaltenformatierung. + +* columnsend + Zweck: Ausschalten der Spaltenformatierung. + +* count + Zweck: Erhöhung eines internen Zählers und Einsetzen des Wertes anstatt + der Anweisung in die Druckdatei. + +* count (TEXT CONST merkmal) + Zweck: Wie obiges 'count', jedoch wird der Wert des Zählers vermerkt, so + daß er mit 'value' wieder erfragt werden kann. + +* end + Zweck: Beendet die Defintion von 'head', 'bottom' oder Fußnotenbereichen. + +* foot + Zweck: Definieren von Fußnoten. Es werden die aktuellen Werte von 'limit', + 'linefeed' und 'type' für die Fußnote verwendet (vergl. 'bottom'- + Anweisung). + +* free (REAL CONST freier platz) + Zweck: Es werden 'freier platz' cm freigehalten. + +* goalpage (TEXT CONST merkmal) + Zweck: (Ziel-) Verweis für Seitenquerverweise in Verbindung mit der Anwei- + sung 'topage'. 'merkmal' muß mit dem Parameter des entsprechenden + 'topage' übereinstimmen. + +* head + Zweck: Definieren von Kopfzeilen, die von 'pageform' am Anfang jeder Seite + eingefügt werden. Es gilt das unter 'bottom' gesagte. + +* head even + Zweck: Definieren von Kopfzeilen für Seiten mit geraden Seitennummern. Es + gilt das unter 'bottom' gesagte. + +* head odd + Zweck: Definieren von Kopfzeilen für Seiten mit ungeraden Seitennummern. + Es gilt das unter 'bottom' gesagte. + +* ib + Zweck: Arbeitet wie 'ib (1)', man darf aber den Parameter weglassen. + +* ib (INT CONST index nummer) + Zweck: Indexanfang einer oder mehrerer Indexworte bis zur entsprechenden + 'ie'-Anweisung. Die Worte zwischen 'ib' und 'ie' werden in die + Indexdatei geschrieben. 'index nummer' gibt die Indexdatei an. + +* ib (INT CONST index nummer, TEXT CONST seitennummer zusatz) + Zweck: Indexanfang mit Zusatztext für die Seitennummer. Das oben gesagte + gilt entsprechend. 'seitennummer zusatz' wird unmittelbar hinter + die Seitennummer angefügt. 'seitennummer zusatz' muß in jeder 'ib'- + Anweisung neu gesetzt werden. + +* ie + Zweck: Arbeitet wie 'ie (1)', man darf aber den Parameter weglassen. + +* ie (INT CONST index nummer) + Zweck: Abschluß eines Index. Ein Index darf nicht über Absatz- und Seiten- + grenzen gehen. Ein Index über mehr als zwei Zeilen ist ebenfalls + aus Sicherheitsgründen (vergessene Abschlußanweisung) nicht erlaubt. + +* ie (INT CONST index nummer, TEXT CONST index zusatz) + Zweck: Es wird 'index zusatz' an die durch die Index-Anweisungen einge- + faßten Worte angefügt. Beispiel: + + \#ib (1)\#EUMEL-System\#ie(1, ", kapitales")\# ist + schön. + + Erscheint als 'EUMEL-System, kapitales ... 4' in der Indexdatei. + Diese Anweisung dient also dazu, auch Sub-Indizes zu ermöglichen. + +* limit (REAL CONST wert) + Zweck: Einstellen einer neuen Zeilenbreite in cm. Die Zeilenbreite gilt + solange, bis sie durch ein erneute 'limit'-Anweisung verändert wird. + +* linefeed (REAL CONST wert) + Zweck: Einstellen eines neuen Zeilenvorschubs in Abhängigkeit vom einge- + stellten Schrifttyp. + +* material (TEXT CONST mat) + Zweck: Angabe von installationsspezifischen Merkmalen für den Drucker. + +* off (TEXT CONST modification) + Zweck: Abschalten einer Modifikation. + +* on (TEXT CONST modification) + Zweck: Einschalten einer Modifikation. Folgende Modifikationen sind zur + Zeit möglich: + bold (Fettdruck) + italic (Kursivdruck) + underline (Unterstreichung) + revers (Weiß auf Schwarz) + +* page + Zweck: Anfang einer neuen Seite. 'page' muß als letztes auf einer Zeile + stehen. + +* page (INT CONST nr) + Zweck: Anfang einer neuen Seite mit 'nr' Seitennummer. + +* page length (REAL CONST cm) + Zweck: Einstellen der Seitenlänge in cm. + +* page nr (TEXT CONST seitennr zeichen, start) + Zweck: Einstellen eines neuen Seitennr-Zeichens und Anfangwerts bzw. + setzen der Seitennummer des bereits vorhandenen Seitenzeichens + ("%"). Neben dem vorhandenen "%"-Zeichen können zwei zusätzliche + (beliebige, aber von den "\#"-Zeichen unterschiedliche) Seiten- + zeichen definiert werden. + +* papersize (REAL CONST width, length) + Zweck: Angabe der Papiergröße des Druckers in cm. + +* print (INT CONST von, bis) + Zweck: Teilausdruck einer Datei. Der Drucker verarbeitet die Datei, bis er + an die Seite 'von' angelangt ist. Dann druckt er die Seiten bis + einschließlich 'bis'. Beachte, daß der EUMEL-Drucker die Seiten + immer ab 1 durchzählt (und eine eventuelle Seitennumerierung nicht + beachtet). + +* start (REAL CONST x, y) + Zweck: Legt den linken, oberen Eckpunkt des Schreibfeldes fest. Die + Angaben erfolgen in cm. + +* topage (TEXT CONST merkmal) + Zweck: Verweis auf eine Seite mit der Anweisung 'goalpage' und dem + gleichen 'merkmal'. Für 'topage' wird die Seitennummer von + 'goalpage' eingesetzt. + +* type (TEXT CONST schrifttyp name) + Zweck: Einstellen eines anderen Schrifttyps. Die verfügbaren Schriftarten + und deren Namen sind installationsspezifisch und deshalb hier nicht + beschrieben. + +* value + Zweck: Einsetzen des letzten 'count' Wertes. + +* value (TEXT CONST merkmal) + Zweck: Erfragen des mit 'count' gespeicherten Zählerwertes für 'merkmal' + und Einsetzen dieses Wertes durch 'pageform' in die Druckdatei. + + + +7. Kommando-Übersicht + +autoform + PROC autoform + Zweck: Aufruf von 'autoform' unter Verwendung des letzten eingestellten + Dateinamens. + + PROC autoform (TEXT CONST datei) + Zweck: 'lineform' mit automatischer Silbentrennung. Nur die vorgenomme- + nen Trennungen werden auf dem Bildschirm angezeigt. + + PROC autoform (FILE VAR f, TEXT CONST type name, REAL CONST width) + Zweck: Wie oben, jedoch auf einer Datei. + +index + PROC index (TEXT CONST eingabe datei) + Zweck: Erstellen von Indexdateien aus einer Druckdatei wie beschrieben. + Eine Indexdatei erhält den Namen der zu bearbeitenden Datei mit + dem Zusatz ".i" und der entsprechenden Indexnummer. Hat das + Programm 'index' die Druckdatei bearbeitet, werden die in die + Indexdatei geschriebenen Einträge alphabetisch sortiert (nach + Anfrage). Gleiche Einträge werden zusammengezogen: ein gleich- + lautender Eintrag wird entfernt, seine Seitennummer wird jedoch + an den bereits vorhandenen mit einem Komma aggefügt. + + Die Sortierung entspricht DIN 5007: + - Die Sortierreihenfolge enspricht 'ABC...Z', wobei große und + kleine Buchstaben gleich behandelt werden. + - Weitere Entsprechungen: + ö = oe, ä = ae, ü = ue + Ö = Oe, Ü = Ue, Ä = Ae, Ä = ä, Ü = ü, Ö = ö, ß = ss + Dadurch wird z.B. 'muß' vor 'Muster' einsortiert und 'Goethe' + ist gleich 'Göthe'. + - Alle Sonderzeichen (außer " " und "-") werden ignoriert. + - Ein Leerzeichen und ein Bindestrich zwischen Worten werden + gleich behandelt. Beispiel: + + 'EUMEL System' und 'EUMEL-System' sind also gleich. + + Es sind z.Z. max. neun unterschiedliche Indexdateien vorgesehen. + Der Name einer Indexdatei ergibt sich aus dem Namen der zu bear- + beitenden Druckdatei, wobei '.p' durch '.i' mit der entsprechen- + den Ziffer ersetzt wird. Beispiel (für Indizes mit + 'index nummer' = 1, z.B. \#ib\# ... \#ie\#): + + skript.p --> skript.i1 + +index merge + PROC index merge (TEXT CONST von, hinzu) + Zweck: Einmischen der Indizes der Indexdatei 'von' in die Indexdatei + 'hinzu'. Beide Indexdateien müssen vorhanden sein. Dabei wird + 'von' vor dem ersten Satz von 'hinzu' eingefügt und anschließend + ggf. sortiert. + +list macros + PROC list macros (TEXT CONST datei) + Zweck: Ausgabe der "geladenen" Makros in die Datei 'datei'. 'datei' darf + vorher nicht existieren, wird also von 'list macros' eingerichtet. + Die "geladenen" Makros bleiben unberührt. Man kann die mit 'list + macros' in die Datei 'datei' geschriebenen Makro-Definitionen ggf. + verändern und erneut mit 'load macros' laden. + Fehlerfall: + * file already exists + Ausgabe-Datei 'datei' ist bereits vorhanden. + +lineform + PROC lineform + Zweck: Der zuletzt verwandte Dateiname wird benutzt. Beispiel: + + edit ("test") + ... + lineform (* wird zu 'lineform ("test") *) + + PROC lineform (TEXT CONST dateiname) + Zweck: Formatieren einer Datei zeilenweise. + + PROC lineform (FILE VAR f, TEXT CONST type name, REAL CONST width) + Zweck: Aufruf von 'lineform' von einem Programm. + +load macros + PROC load macros (TEXT CONST datei) + Zweck: Lädt Makro-Definitionen in den Makro-Speicher des Textsystems. Die + Definitionen müssen in der Datei 'datei' enthalten sein (mit dem + Editor erstellen). Es können mehrere Definitionen in der Datei ent- + halten sein. Um den Makro-Speicher zu leeren, übergibt man eine + leere 'datei'. + + Eine Makro-Definition besteht aus einem + - Makro-Kopf: + Muß alleine auf einer Zeile stehen. Der Makro-Kopf fängt mit + '\#*'-Zeichen an und wird mit '\#' beendet. Beispiel: \#*ein macro\# + Der Name eines Macros muß (wie alle andern Anweisungen auch) + mit kleinen Buchstaben geschrieben werden. Leerzeichen spielen + keine Rolle. + Eventuelle Parameter müssen in Klammern (bei mehreren durch + Kommata getrennt) und mit einem $-Zeichen numeriert werden. + Beispiel: + \#*macro1 ($1)\# + \#*macro 2 ($1, $2)\# + + - Makro-Rumpf: + Besteht aus beliebig vielen Text-Zeilen, die Kommandos enthalten + können. Parameter (also das $-Zeichen mit anschließender Nummer) + werden bei Aufruf eines Makros ersetzt. In einem Makro-Rumpf + darf keine Makro-Anweisung erscheinen, die noch nicht definiert + wurde (sog. "Vorwärts-Referenzen"). + + - Makro-Ende: + besteht aus der Anweisung + \#*macro end\# + und muß wie der Makro-Kopf alleine auf einer Zeile stehen. + + Fehlerfälle: + * file does not exists + Die Eingabe-Datei 'datei' ist nicht vorhanden. + * macro store overflow (number lines) + Es passen zur Zeit nicht mehr als 1 000 Zeilen in den Makro-Speicher. + * macro store overflow (number macros) + Es passen zur Zeit nicht mehr als 100 Makro-Defintionen in den + Makro-Speicher. + +pageform + PROC pageform + Zweck: Wie beschrieben, jedoch ohne Parameter. Die zuletzt benutzte + Datei wird bearbeitet. Für die Druckdatei wird dieser Dateiname, + an den ".p" angehängt wird, eingesetzt. Beispiel: + + edit ("test") + ... + pageform (* wird zu 'pageform ("test", "test.p")' + ergaenzt *) + + PROC pageform (TEXT CONST dateiname) + Zweck: Wie beschrieben, wobei der Parameter für die Druckdatei ergänzt + wird (an 'dateiname' wird '.p' angehängt). Beispiel: + + pageform ("test") + (* wird zu 'pageform ("test", "test.p")' ergaenzt *) + + PROC pageform (TEXT CONST dateiname, druckdatei) + Zweck: Wie oben. + +print + PROC print (TEXT CONST datei) + Zweck: Druck der Datei 'datei' unter Berücksichtigung von Anweisungen. + + + diff --git a/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil5 b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil5 new file mode 100644 index 0000000..d59b147 --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil5 @@ -0,0 +1,667 @@ + EUMEL-Benutzerhandbuch + + + TEIL 5: ELAN-Compiler + + +Der ELAN-Compiler im EUMEL-System + +In diesem Kapitel wird die Benutzung des ELAN-Compilers im EUMEL-System be- +schrieben. Es enthält Angaben, welche Einschränkungen bzw. Erweiterungen +gegenüber dem Sprachstandard existieren. Eine Einführung in die Programmier- +sprache ELAN wird hier nicht gegeben. + + + +1. Einführung + +Der im EUMEL-System eingesetzte ELAN-Compiler wurde von J. Liedtke und +U. Bartling am HRZ Bielefeld in den Jahren 1975/76 erstellt und in den +folgenden Jahren erweitert und der Sprachbeschreibung angepaßt. Der gleiche +ELAN-Compiler wird auch auf verschiedenen Großrechnern (TR440, IBM, SIEMENS) +eingesetzt. + +Den ELAN-Compiler kann man sich als aus zwei Teilen bestehend vorstellen. +Einmal gibt es den "eigentlichen" ELAN-Compiler, der ein ELAN-Programm in +eine Maschinensprache (im EUMEL-System der sogenannte EUMEL0-Code) übersetzt. +Zum anderen verwaltet der ELAN-Compiler übersetzte Moduln (in ELAN Packets +genannt). + +In einem Packet können Prozeduren, Datentypen und/oder Operatoren definiert +werden. Ist ein solches Packet vorübersetzt (im EUMEL-System wird dieser +Vorgang 'insertieren' genannt), stehen diese Objekte zur Benutzung zur Ver- +fügung. Durch Packets kann man somit die Sprache ELAN erweitern. + +Weitere Informationen über die Programmiersprache ELAN finden Sie in den +folgenden Büchern: + +Hommel / Jähnichen / Koster: +Methodisches Programmieren +W. de Gruyter, Berlin, 1983 + +Klingen / Liedtke: +Programmieren mit ELAN +Teubner, Stuttgart, 1983 + +In der Regel sind in einem EUMEL-System die Standard-Packets bereits in- +sertiert (Ausnahmen: Datentypen #ib#VECTOR#ie# und #ib#MATRIX#ie#). Zusätz- +lich sind weitere Packets vorübersetzt, die Kommandos zur Verfügung stellen. +Welche weiteren Packets insertiert werden, kann jede EUMEL-Installation und +jeder Nutzer entscheiden. Somit kann man sein System auf spezielle +Anwendungen zuschneiden. + + + +2. Übersetzen mit dem ELAN-Compiler + +In diesem Abschnitt wird erklärt, wie Programme mit dem ELAN-Compiler über- +setzt oder vorübersetzt werden können. + + + +Einfaches Übersetzen: 'run'-Kommando + +Mit dem 'run'-Kommando kann ein ELAN-Programm übersetzt und ausgeführt +werden. + +Das 'run'-Kommando (vergl. auch die Kommandos in der Beschreibung des +Monitors) übersetzt ein in einer Datei befindliches ELAN-Programm. Beispiel: + + run ("mein programm") + +übersetzt das ELAN-Programm, welches in der Datei 'mein programm' enthalten +ist. (Wie man ELAN-Programme schreibt, ist u.a. im Editor-Kapitel beschrie- +ben). + +Der Fortschritt der Übersetzung wird durch laufende Nummern auf dem Bild- +schirm des Benutzers angezeigt, die die gerade verarbeiteten Zeilennummern +anzeigen. Da der ELAN-Compiler ein Zwei-Paß Compiler ist, werden alle +Zeilen (mindestens) zweimal überprüft. + +Ist das Programm syntaktisch korrekt, d.h. hat der ELAN-Compiler keine +Fehler gefunden, wird eine Ende-Meldung abgesetzt, die den Speicherumfang +des übersetzten Programms enthält. Die Ende-Meldung entfällt, wenn die Task +an kein Terminal angekoppelt ist. + +Nach der Ende-Meldung wird das Programm unmittelbar ausgeführt (ein Binder +ist im EUMEL-System nicht notwendig). + +Merke: Das Kommando 'run' übersetzt ein in einer Datei befindliches Programm +und führt fehlerfreie Programme aus. + + + +Korrektur von Fehlern + +In diesem Abschnitt wird beschrieben, wie (syntaktische bzw. semantische) +Fehler korrigiert werden können. + +Entdeckt der ELAN-Compiler Fehler, so meldet er sie dem Benutzer unter An- +Angabe der Zeilennummer. Die zwei Pässe des Compilers sind so konstruiert, +daß sie unterschiedliche Fehler entdecken. Ist bereits im ersten Paß ein +Fehler entdeckt worden, wird der zweite Paß nicht gestartet. Somit kann es +vorkommen, daß man glaubt, alle Fehler beseitigt zu haben und dann werden +wieder (andere) Fehler durch den zweiten Paß gemeldet ... + +Fehlermeldungen und Quelldatei werden nach Abschluß der Übersetzung durch +den Paralleleditor angezeigt. Vergl. dazu auch die Beschreibung des Editors. + +Merke: Eventuelle Fehler und das zu korrigierende Programm werden durch den +Paralleleditor angezeigt. So kann man das fehlerhafte Programm bequem ver- +ändern. + + +Nochmalige Ausführung eines Programms: 'run again' + +Mit 'run again' kann das zuletzt fehlerfrei übersetzte Programm nochmals +ausgeführt werden. + +Ist ein Programm fehlerfrei übersetzt worden, so kann man es mit dem Komman- +do 'run again' (beispielsweise mit anderen Eingabedaten) nochmals ausführen. + +Merke: Das Kommando 'run again' führt das zuletzt übersetzte Programm noch- +mals aus. + + + +Übersetzen von Kommandos + +Auch Kommandos werden in der Regel vom ELAN-Compiler übersetzt. + +Der ELAN-Compiler wird nicht nur für Programme eingesetzt, sondern auch als +Übersetzer für die EUMEL-Kommandosprache (in anderen Systemen "job control +language", abgekürzt JCL genannt) und für Kommandos, die man im Editor geben +kann. Jedes Kommando der EUMEL-Kommandosprache ist ein kleines ELAN-Programm, +welches in der Regel aus einem Prozeduraufruf besteht. Einige häufig be- +nutzte Kommandos werden der Effizienz halber über einen Kommando-Interpreter +abgewickelt. Beispiel: + + edit ("mein erstes Programm") + +Natürlich ist es möglich, mehrere Kommandos oder ein richtiges, einzeiliges +Programm als Kommando zu verwenden. Beispiele: + + put (17 * 4) + + INT VAR i; FOR i FROM 1 UPTO 100 REP put ("i") PER + + edit ("datei"); lineform ("datei"); print ("datei") + + INT VAR i; FOR i FROM 1 UPTO 10 REP print ("d") END REP + +Mit vorübersetzten Prozeduren (siehe auch das Kommando 'insert') ist es +möglich, eine eigene Kommandosprache zusammenzustellen. + +Merke: Der ELAN-Compiler wird auch für die Übersetzung und Ausführung von +Kommandos benutzt. + + + +Vorübersetzen: 'insert' + +Das Kommando 'insert' übersetzt ein in einer Datei befindliches ELAN-Pro- +gramm und trägt dieses in den Tabellenspeicher des Compilers ein. + +Mit dem Kommando 'insert' kann ein ELAN-Programm (d.h. ein Packet oder eine +Packetfolge) in den Tabellenspeicher (eine Art "Compilerdatenbank") des +ELAN-Compilers eingetragen werden. Die in den Packets enthaltenen Objekte +stehen nach Abschluß der Übersetzung zur Verfügung. Beispiel: + +Die Datei 'mein druck' enthalte folgendes Programm: + + PACKET mein druck DEFINES drucke: + + PROC drucke (TEXT CONST datei): + edit (datei); + lineform (datei); + pageform (datei); + print (datei) + END PROC drucke; + + END PACKET drucke; + +Mit dem Kommando + + insert ("mein druck") + +wird das Packet 'drucke' in die Tabellen des ELAN-Compilers aufgenommen. +Nun kann (als Kommando oder in einem Programm) der Prozeduraufruf 'drucke' +verwandt werden. + +Man beachte, daß der Nutzer beim Einrichten seiner Task alle insertierten Ob- +jekte der Vater-Task erhält. Insertiert der Benutzer in seiner Task weitere +Packets, so sind diese nur ihm verfügbar (oder ggf. seinen Sohn-Tasks). Es +ist somit möglich, Tasks mit unterschiedlichem Sprachumfang einzurichten. + +Einmal insertierte Packets können nicht mehr aus den Compilertabellen ent- +fernt werden. Man kann also nur die Task löschen (bitte vorher alle Dateien +archivieren oder bei der Vater-Task aufheben (siehe Kommando: 'save')). + +Das Kommando 'insert' arbeitet auch mit einem Thesaurus (vergl. dazu auch +den Teil über Dateien). Beispiel: + + insert (ALL myself) + +insertiert alle Dateien der Benutzer-Task in Reihenfolge. + +Merke: Das Kommando 'insert' übersetzt die in einer Datei enthaltene Packet- +folge und trägt diese in die Tabellen des Compilers ein. + + + +Programme von einem Programm übersetzen lassen + +Manchmal ist es notwendig, daß ein Programm den ELAN-Compiler zur Über- +setzung und Ausführung eines Programms aufrufen muß. + +Natürlich kann man auch die Kommandos 'run' oder 'insert' von einem Programm +aus aufrufen. Leider müssen die zu übersetzenden Programme in einer Datei +enthalten sein. Will man jedoch nur eine Anweisung übersetzen und ausführen +lassen und nicht den "Umweg" über eine Datei gehen (wie z.B. die Kommandos +im Monitor oder Editor), so kann man die Prozedur '#ib#do#ie#' verwenden. +Beispiel: + + ... + get (eingabe); + do (eingabe); + ... + +Findet der ELAN-Compiler bei der Übersetzung eines Textes der Prozedur 'do' +einen Fehler, so wird dieser Fehler über 'errorstop' gemeldet (vergl. dazu +auch das Kapitel über die Fehlerbehandlung im System-Handbuch) und die Über- +setzung bei der ersten Fehlermeldung abgebrochen. In diesem Fall kann ein +Nutzer den Fehler durch eine #ib#Fängerebene#ie# leicht selbst behandeln. + +Merke: Die Prozedur 'do' übersetzt (kleinere) ELAN-Programme von einem Pro- +gramm aus. + + + +Kommandos zur Steuerung des ELAN-Compilers + +In diesem Abschnitt beschreiben wir die Kommandos für die Steuerung des +ELAN-Compilers#ie#. Ebenso wie die Kommandos zur Übersetzung eines Programms +müssen die Kommandos zur Steuerung des Compilers vom Monitor gegeben werden. + +Mit dem Kommando + + prot ("datei name") + +wird das Listing des ELAN-Compilers eingeschaltet und in die angegebene +Datei ausgegeben. Mit + + prot off + +wird es wieder ausgeschaltet. 'prot off' ist voreingestellt. + +Normalerweise werden Zeilennummern des Quellprogramms im übersetzten Pro- +gramm mitgeführt, so daß bei einem Fehler zusätzlich zur Fehlermeldung auch +die Nummer der Zeile ausgegeben werden kann, in der der Fehler aufgetreten +ist. Mit dem Kommando + + check off + +kann die Generierung von Zeilenummern für das Objektprogramm abgeschaltet +werden. Durch die Angabe dieses Kommandos wird weniger Code für das +Programm erzeugt. Mit + + check on + +wird die Generierung von Zeilennummern durch den Compiler wieder einge- +schaltet. 'check on' ist voreingestellt. Mit der Prozedur + + check + +die ein boolesches Resultat liefert, kann in einem Programm abgefragt werden, +ob der 'check'-Zustand ein- oder ausgeschaltet ist. Beispiel: + + IF check THEN check off FI + +Merke: Die Kommandos 'check on' bzw. 'check off' schalten das Einfügen von +Zeilennummern in den erzeugten Code ein bzw. aus. + + + +3. Abweichungen gegenüber dem Sprachstandard + +Der im HRZ Bielefeld entwickelte ELAN-Compiler weist einige Abweichungen +gegenüber dem Sprachstandard auf, wie er in der Sprachbeschreibung formu- +liert ist. Es existieren einige Einschränkungen, die einen Programmierer +jedoch nicht weiter behindern. Die Spracherweiterungen wurden meist speziell +für das EUMEL-System geschaffen. Weitere Abweichungen gegenüber dem aktuellen +Sprachstandard, die aber in der nächsten Sprachbeschreibung enthalten sein +werden, sind in einem weiteren Abschnitt aufgeführt. + + + +Einschränkungen gegenüber dem Sprachstandard + + * Das "row display" wurde nicht implementiert. Der Grund dafür liegt in + dem unverhältnismäßig hohen Aufwand, dieses Sprachmittel bei der gegen- + wärtigen Compiler-Struktur zu implementieren. Abhilfe: Man verwende den + Konstruktor. Beispiel: + + ROW 5 INT VAR vektor; + vektor := [1, 2, 3, 4, 5]; (* nicht möglich *) + vektor := ROW 5 INT :(1, 2, 3, 4, 5); (* Ersatz: Konstruktor *) + + * Einige alternative Darstellungen von Symbolen können nicht verwendet + werden. Diese sind: + + "&"-Zeichen für "AND", + "/="-Zeichen für "<>", + "%"- und "//"-Zeichen für "DIV". + + * Eine Typ-Definition muß einer Deklaration immer textuell vorangehen. + Beispiel: + + TYPE QUADRAT = ... (* erlaubt *) + QUADRAT VAR rundes quadrat; + ... + PUNKT VAR meiner; (* verboten *) + TYPE PUNKT = ... + + Es ist jedoch erlaubt, einen Typ in einer Typ-Definition zu verwenden, + der textuell erst später definiert wird. Beispiel: + + TYPE PERSON = STRUCT (TEXT name, vorname, ADRESSE wohnort); + TYPE ADRESSE = ... + + Diese Einschränkung ("defined before applied") gilt nur für Typen, + nicht für Datenobjekte u.ä.. Selbstverständlich ist + + otto := 0; + INT VAR otto; + ... + + erlaubt (aber kein besonders schöner Programmierstil)! + + * Die Operatoren AND und OR können nicht redefiniert werden, sofern einer + ihrer Operanden vom Typ BOOL ist. + + + +Implementationsbedingte Einschränkungen + + * Es sind bis zu 32 000 Zeichen in einem TEXT zugelassen. Hat ein TEXT + bis 13 Zeichen, so wird er vollständig auf dem Stack untergebracht. + TEXTe mit mehr als 13 Zeichen werden auf dem Heap gespeichert. Die + Benutzung des Heaps bedeutet unter Umständen eine Verlangsamung eines + Programms. Darum ist + +max text length = 32 000 + + * Die Anzahl der Zeichen in einem TEXT-Denoter (Angabe eines TEXTes in + einem Programm) ist auf 254 Zeichen beschränkt. + + * INT-Werte werden in sechzehn Bit dargestellt (einschließlich Vor- + zeichen). Das bedeutet, daß + + maxint = 32 767 + minint = - 32 768 + + ist. + + * REAL-Werte werden intern mit einer Mantisse von 13 Stellen abgespei- + chert, von denen die ersten sieben Stellen bei der Ausgabe dargestellt + werden. Das bedeutet, daß + + maxreal = 9.999999999999e126 + + ist. + + * Die lexikographische Reihenfolge von Zeichen entspricht dem ASCII-Code + (vergl. dazu die Code-Tabelle). + + * Weiterhin sieht der ASCII-Code noch eine Anzahl von Steuerzeichen vor, + die jedoch von Herstellern leider nicht immer gleich interpretiert + werden. Diese Zeichen sind im EUMEL-System teilweise normiert und + können verwandt werden. Die verfügbaren Steuerzeichen sind ebenfalls im + EUMEL-Taschenbuch aufgeführt. + + * Die Initialisierung von Paketen (genauer: die Initialisierung von + Datenobjekten, die in vorübersetzten PACKETs außerhalb von Prozeduren + deklariert wurden) wird nur einmal, während der Übersetzung, durchge- + führt. Werden mehrere Pakete hintereinander (aus einer Datei) übersetzt, + dürfen die Prozeduren 'run', 'run again', 'insert' und 'do', die wieder + den ELAN-Compiler aufrufen, nur bei der Ausführung des letzten Packets + verwandt werden, weil der ELAN-Compiler nicht rekursiv benutzbar ist. + + + +Erweiterungen gegenüber dem Standard + + * Einem Datenobjekt, das an einen #ib#Datenraum#ie# gebunden werden soll, + wird bei der Deklaration das Schlüsselwort #ib#BOUND#ie# vorangestellt. + Damit wird dem ELAN-Compiler mitgeteilt, daß er für ein solches Objekt + keinen Speicherplatz reservieren muß. Die Assoziation mit einem Daten- + raum erfolgt bei der Deklaration mit Hilfe der Initialisierung. + Beispiel: + + BOUND INT VAR objekt :: old ("hugo"); + (* eine bereits errichtete Datei wird unter dem Namen "hugo" benutzt. + "objekt" ist jetzt an die Datei mit dem Namen "hugo" "gebunden" *) + + + +Vorweggenommene Implementation des nächsten Standards + +In diesem Abschnitt sind Erweiterungen/Einschränkungen des ELAN-Compilers +hinsichtlich der aktuellen ELAN-Sprachbeschreibung aufgeführt, die in der +nächsten Sprachbeschreibung mit aufgenommen werden. + + * ASCII-Zeichen, die nicht unmittelbar dargestellt werden können, können + in TEXT-Denotern angegeben werden, sofern sie in Anführungszeichen + eingeschlossen werden. Beispiele: + + ""13"" + + ist ein TEXT-Denoter, der nur CR (carriage return) enthält. + + "Jetzt erfolgt ein Zeilenwechsel "13""10"" + + Hier wird nach der Ausgabe des Textes ein "Wagenrücklauf" ('CR', + Code = 13) und einen Zeilenvorschub ('LF', Code = 10) erzeugt. + + ""1""4"" + + positioniert in die linke obere Ecke eines Bildschirms (Code = 1) und + löscht den Bildschirm (Code = 4). + + * Im aktuellen Standard wurde die #ib#Reihenfolge der Auswertung von + Operanden#ie# nicht definiert. Nunmehr wird zusätzlich nicht garantiert, + daß alle Operanden ausgewertet werden, wenn dies nicht notwendig ist. + Beispiel: + + IF f (x) > 0 AND x <> 0 THEN ... FI + + Hier muß beispielsweise 'f (x)' nicht ausgewertet werden, wenn 'x = 0' + ist. + + * Die booleschen Operatoren CAND und COR stehen zusätzlich zur Verfügung. + Wirkung: + + a CAND b :<==> IF a THEN b ELSE FALSE FI + + a COR b :<==> IF a THEN TRUE ELSE b FI + + Beispiel: + + IF element vorhanden + THEN verarbeite element + FI. + + element vorhanden: + index > 0 CAND liste (index) > 0. + + * Prozeduren als Parameter. Beispiel: + + (* Deklaration: *) + PROC draw (REAL PROC (REAL CONST) funktion, + REAL CONST von, bis, delta) + (* Aufruf: *) + draw (REAL PROC (REAL CONST) sin, -pi, pi, 0.1) + + Die obige Form von Prozedur-Parametern wird als "Langform" bezeichnet. + Die Langform muß verwandt werden, wenn generische aktuelle Parameter + benutzt werden. Eine "Kurzform" reicht aus, wenn der aktuelle Prozedur- + Parameter keine generischen Prozedur ist, d.h. eindeutig über den + Prozedurnamen (und nicht noch über die Datentypen seiner Parameter) + identifiziert werden kann. Die Kurzform unterscheidet sich von der + Langform nur beim Aufruf, bei dem eventuelle Resultate und die Daten- + typen der Parameter nicht mit angegeben werden müssen. Beispiel: + + (* Aufruf obiger Prozedur bei nichtgenerischer aktueller Prozedur + 'sin' *) + draw (PROC sin, -pi, pi, 0.1) + + * In Paketen sind auch außerhalb von Prozeduren Refinements zugelassen. + In solchen "Paket-Refinements" dürfen nur Paket-Objekte angesprochen + werden. Insbesondere ist es erlaubt, auch im letzten Paket ('main + packet') neben Prozeduren auch Refinements in beliebiger Reihenfolge zu + benutzen. Beispiel: + + PROC kommando erkennung: + ... + END PROC kommando erkennung; + + PROC kommando ausführung: + ... + END PROC kommando ausführung; + + datei assoziieren; + saetze lesen und bearbeiten; + ende behandlung. + + datei assoziieren: + FILE VAR f :: sequential file ...; + ... + saetze lesen und bearbeiten: + ... + ende behandlung: + put ("Ende der Bearbeitung"). + + Dies ist die Schreibweise, die wir empfehlen. Will man aber Refinements + auch zwischen Prozeduren deklarieren, wird es etwas komplizierter. + Beispiel: + + PROC a: + END PROC a; + ref; (* Refinement Aufruf *) + PROC b: + END PROC b; + (* Achtung: Semikolon, Punkt vor dem Refinement *) + .ref: . ; (* Punkt, Semikolon nach dem Refinement *) + PROC c: + END PROC c + + Paket-Refinements dürfen auch von Prozeduren benutzt werden, allerdings + sind dann auch die Sichtbarkeitsregeln zu beachten. D.h. die Paket- + Refinements, die in Prozeduren verwandt werden, dürfen dann auch nur + Paket-Objekte ansprechen. Die Aufnahme eines Refinements in das Inter- + face ist verboten. + + + +4. Interne Fehlermeldungen des Compilers + +Interne Fehlermeldungen des Compilers#ie# erfolgen, wenn der ELAN-Übersetzer +an implementationsbedingte Einschränkungen stößt. + + Interne Fehlermeldungen erfolgen in der Form: + + COMPILER ERROR: <zahl> + +wobei <zahl> folgende Werte annehmen kann: + +<zahl> Bedeutung und eventuelle Abhilfe: + + 101 name table overflow: + Die Anzahl der Namen im Programm ist zu groß oder es wurden die + Anführungstriche eines TEXT-Denoters vergessen. Keine Abhilfe. + + 102 symbol table overflow: + Die Anzahl der deklarierten Objekte ist zu groß. + Abhilfe: Programm in Pakete unterteilen. + + 103 intermediate string overflow: + Abhilfe: Programm in Pakete unterteilen. + + 104 permanent table overflow + Zu viele Pakete insertiert. + Abhilfe: Keine (neue Task beginnen). + + 106 packet address overflow: + Insgesamt zu viele Adressen in Paketen ( > 64K ), d.h. ein Daten- + objekt ist zu groß. + Keine Abhilfe. + + 107 local data overflow: + Ein Datenobjekt in einer Prozedur ist zu groß ( > 32K ). + Abhilfe: + Datenobjekt in mehrere unterteilen. + + 204 compiler stack overflow: + Keine Abhilfe. + + 301 too many modules: + Zu viele Pakete, Prozeduren und Operatoren ( > 2048 ). + Keine Abhilfe. + + 303 applied table overflow: + siehe 304 + + 304 too many labels: + In dem gerade übersetzten Modul (Prozedur, Operator oder Paket- + rumpf) werden vom Compiler zu viele Marken benötigt (mehr als + 2000). Marken werden z.B. für die Codegenerierung von Auswahl + (IF ...) und Wiederholung (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 gespannte SELECT-Anweisungen + zurückzuführen. + Abhilfe: SELECT-Anweisungen über mehrere Prozeduren verteilen oder + Spannweiten verringern. + + 305 code overflow: + Der insgesamt erzeugte Code ist zu umfangreich ( > 256K ). + Keine Abhilfe. + + 306 packet data overflow: + Insgesamt zu viele Datenobjekte in den Paketen ( > 128K ). + Keine Abhilfe. + + 307 local data overflow: + Zu viele (lokale) Datenobjekte in einer Prozedur ( > 32K ). + Abhilfe: Prozedur in mehrere unterteilen, so daß die Datenobjekte + sich über mehrere Prozeduren verteilen. + + 308 module code overflow: + Ein Modul (Prozedur, Operator oder Paket-Initialisierungsteil) ist + zu groß ( > 7.5 KB Code). + Abhilfe: In mehrere Prozeduren oder Pakete zerlegen. + +Anmerkung: Fehlermeldungen, die hier nicht aufgeführt sind, weisen in der +Regel auf ein fehlerhaftes Arbeiten des ELAN-Compilers hin. In diesem Fall +bitten wir um die Einsendung des Programms (Listing, Quelldatei auf Diskette +bei umfangreichen Programmen) und entsprechender Fehlermeldung. + + + +5. Übersicht über die Compiler-Kommandos + +check + BOOL PROC check + Zweck: Informationsprozedur. + + PROC check on + Zweck: Einschalten der Generierung von Zeilennummern durch den + ELAN-Compiler. Voreingestellt ist 'check on'. + + PROC check off + Zweck: Ausschalten der Generierung von Zeilennummern durch den + ELAN-Compiler. + +do + PROC do (TEXT CONST program) + Zweck: Übersetzen und Ausführen von 'program' von einem Programm aus. + +insert + PROC insert + Zweck: Insertieren eines oder mehrerer PACKETs. Der Programmtext muß sich + in einer Datei befinden. Der Dateiname ist der zuletzt benutzte + Dateiname. + + PROC insert (TEXT CONST dateiname) + Zweck: Wie oben. Der Programmtext wird aus der Datei mit dem Namen + 'dateiname' geholt. + + PROC insert (THESAURUS CONST t) + Zweck: Insertieren aller PACKETs, die in den Dateien des Thesaurus 't' + enthalten sind. + +prot + BOOL PROC prot + Zweck: Informationsprozedur, ob 'prot' eingeschaltet ist. + + PROC prot (TEXT CONST dateiname) + Zweck: Einschalten des Compilerlistings auf dem Bildschirm. Das Listing + wird gleichzeitig in die Datei 'dateiname' geschrieben. + +prot off + PROC prot off + Zweck: Ausschalten des Listings. + +run + PROC run + Zweck: Übersetzen und Ausführen eines ELAN-Programms. Der Programmtext + muß sich in einer Datei befinden. Der Dateiname ist der zuletzt + benutzte Dateiname. + + PROC run (TEXT CONST dateiname) + Zweck: Wie oben. Der Programmtext wird aus der Datei mit dem Namen + 'dateiname' geholt. + + + diff --git a/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil6a b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil6a new file mode 100644 index 0000000..1ee80ec --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil6a @@ -0,0 +1,1590 @@ + EUMEL-Benutzerhandbuch + + + TEIL 6: Erste Hilfe in ELAN + + +Vorwort + +Dieser Teil des EUMEL-Handbuchs ist keine "Einführung in die Programmierung +mit ELAN", sondern ist als Begleitmaterial für einen ELAN-Kurs gedacht. +Zudem beschreibt das Skript nicht die vollständige Sprache; dafür ist die +Sprachbeschreibung und das Handbuch vorgesehen. Folgende ELAN-Bücher sind +z.Zt. erhältlich: + +Klingen / Liedtke: +Programmieren mit ELAN +Teubner, Stuttgart, 1982 + +Jähnichen u.a.: +Systematisches Programmieren mit ELAN +W. de Gruyter, 1982 + +Wir haben in dieses Skript auch einige Aufgaben mit aufgenommen, die An- +fänger auf jeden Fall lösen sollten. Die Aufgaben dienen aber nur dazu, das +erlernte Wissen über ELAN zu überprüfen und sind keine eigentlichen Program- +mieraufgaben, die es im begleitenden Kurs geben sollte. Es gibt zwei Arten +von Aufgaben: + +a) HSG (Hätten Sie's gewußt?): Aufgaben, die das bis dahin Gelernte über- + prüfen sollen. +b) TSW (Trau', Schau', wem!): Aufgaben mit Programmen, die Fehler enthalten + können. Alle Programme dieses Skripts sind übrigens von der Art TSW. + +Es ist auch sinnvoll und notwendig, möglichst viele Programme dieses Skripts +direkt auf dem Terminal zu probieren und zu verändern. Auf diese Weise wird +ein Anfänger auch mit den Fehlermeldungen des ELAN-Compilers vertraut. + + + +Das erste Programm + +Gleich am Anfang einer Programmierlaufbahn haben Anfänger eine schwierige +Hürde zu nehmen: das erste Programm "zum Laufen" zu bringen. Das wird einem +Anfänger meist nicht leicht gemacht: schließlich hat er mit dem Betriebs- +system eines Computers zu kämpfen. Ein #ib#Betriebssystem#ie# sorgt u.a. für +die Steuerung so unterschiedlicher Peripheriegeräte wie Drucker, Lochkarten- +leser, Magnetplatten und -bänder usw. Zusätzlich hat es dafür Sorge zu +tragen, daß Informationen sicher gespeichert werden und nicht unbeabsichtigt +verändert werden können. Letztendlich hat ein Betriebsystem die Aufgabe, die +Aufträge von Benutzern ("jobs") - und das können mehrere auf einmal sein - +sicher und effizient bearbeiten zu lassen. Um mit einem Betriebsystem +"sprechen" zu können, ist meist eine eigene Sprache vorhanden, die Kommando- +sprache ("job control language", abgekürzt: JCL). + +Eine Kommandosprache kann - auf Grund der vielfältigen Aufgaben, die mit +ihrer Hilfe formuliert werden müssen - mehr oder weniger kompliziert sein. +Zusätzlich sind Kommandosprachen sehr unterschiedlich: aus leicht einsichti- +gen Gründen wollen sich Hersteller nicht auf eine Kommandosprache einigen. +Deshalb können wir die Anweisungen in einer speziellen Kommandosprache hier +nicht angeben; man erfragt diese am besten. Auf jeden Fall muß etwas getan +werden, um ein Programm auf einem Rechner "zum Laufen" zu bringen. + +Wie bereits erwähnt, beschränken wir uns hier auf die eigentlichen Programme. +Um den Mechanismus mit den Anweisungen an das Betriebsystem von Anfang +an kennen zu lernen, denken wir uns ein sehr einfaches Programm aus, das wir +bearbeiten lassen wollen. + +Programm 1: + + put ("Hallo: mein erstes Programm") + +Dieses Programm muß nun dem Rechner zur Bearbeitung übergeben werden. +Auch hier treffen wir auf Unterschiede bei den verschiedenen Rechensystemen: +bei einigen Rechnern muß ein solches Programm (mit Anweisungen der +Kommandosprache) auf Lochkarten übertragen werden, bei anderen dagegen +tippt man das Programm direkt an einem Sichtgerät ("Terminal") ein. Die +Ausgabe erfolgt dann über einen Schnelldrucker oder auch über das Sichtgerät. +Um von Geräten bestimmter Installationen zu abstrahieren, nennen wir im +folgenden das Eingabemedium #ib#Eingabegerät#ie# und das Gerät, auf dem die +Resultate erscheinen, dementsprechend Ausgabegerät. + +Aufgabe (TSW): + + Versuchen Sie, Programm 1 auf dem Rechner Ihrer Installation zu "rechnen". +Übungsziel: Umgang mit dem Betriebsystem + + +Das Ergebnis unseres ersten Programms ist nun das Erscheinen des Textes: +'Hallo: mein erstes Programm'. Was ist hier passiert? Da ein Rechner ein +ELAN-Programm meist nicht direkt ausführen kann, muß es in eine Form +gebracht werden, die der Rechner "versteht". Diese Form ist wiederum eine +(sehr andersartige und - für Menschen - nicht leicht verständliche) Sprache, +die Maschinensprache. Man muß also ein ELAN-Programm übersetzen. Dies wird +von einem Programm (und nicht etwa einer festverdrahteten Schaltung) vorge- +nommen, einem Übersetzer. Eine bestimmte Art von Übersetzer heißt Compiler; +er übersetzt ein Programm als Ganzes (im Gegensatz zu einem Interpreter, der +nur einzelne Anweisungen übersetzt und anschließend ausführt). Darum sind +bei ELAN-Programmen, die meist durch Compiler übersetzt ("kompiliert") +werden, zwei Phasen zu unterscheiden: + +a) Übersetzungsphase: + + In dieser Phase wird ein ELAN-Programm (man spricht von Quellprogramm + bzw. "source program") in ein äquivalentes Maschinenprogramm (Objektpro- + gramm) transformiert. Dabei überprüft der Übersetzer das Quellprogramm + auf eventuelle Fehler (Anweisungen, die nicht der ELAN-Sprachbeschreibung + entsprechen). Bei solchen Fehlern, die ein Compiler entdecken kann, + spricht man von syntaktischen Fehlern oder von Fehlern zur Übersetzungs- + zeit. + +b) Bearbeitungsphase: + + In dieser Phase ("run time") wird das übersetzte (Maschinen-) Programm + abgearbeitet. Auch hier können Fehler auftreten (z.B. wenn auf einen Wert + vom Programm zugegriffen wird, der noch gar nicht berechnet wurde). + Solche Fehler nennt man Laufzeitfehler. + +Haben wir das erste Programm so geschrieben, wie oben angegeben, dürften +keine Fehler entdeckt werden und das Programm wird (hoffentlich korrekt, d.h. +mit den geforderten Ergebnissen) beendet. Was für ein Programm haben wir nun +geschrieben bzw. was haben wir vom Rechner verlangt? + +Das Wort 'put' bezeichnet eine Prozedur. Eine Prozedur ist ein Algorithmus +(hier mit Parametern): eine bestimmte Sammlung von Anweisungen und unter +Umständen Daten. Eine solche Prozedur können wir in einem Programm unter +einem Namen (nämlich 'put') ansprechen und ausführen lassen. Man spricht +dann von dem Aufruf einer Prozedur, wenn ein Prozedurname geschrieben wird. +Von einer Prozedur brauchen wir nur zu wissen, was die Prozedur macht, aber +gottseidank nicht, wie sie es macht. + +Eine Prozedur wie 'put' ist vorgefertigt und einfach benutzbar, wobei wir +später sehen werden, wie man solche Prozeduren selber schreiben kann. Die +Prozedur 'put' hat einen Parameter, nämlich den in Klammern geschriebenen +Text, der auf dem Ausgabegerät ausgegeben werden soll. Wir können eine +solche Prozedur auch mit anderen Parametern versehen und mehrmals aufrufen: + +Programm 2: + + put ("Programm:"); + put (2) + +Mit dem zweiten Programm ist es uns gelungen, ein Programm mit zwei Anwei- +sungen zu schreiben (dabei ist der Parameter bei dem ersten Aufruf der +'put'-Prozedur ein Text, beim zweiten Parameter eine ganze Zahl). + +ELAN ist eine formatfreie Sprache, d.h. Anweisungen können so auf eine Zeile +verteilt werden, wie es uns gefällt und zweckmäßig erscheint. + +Programm 3: + + put ("mein"); put (3); put (".Programm") + +Man kann also eine oder mehrere Anweisungen auf eine Zeile schreiben oder +eine Anweisung über mehrere Zeilen. Das setzt jedoch voraus, daß die Anwei- +sungen voneinander getrennt werden (schließlich muß der Übersetzer erkennen +können, wo eine Anweisung anfängt und aufhört). Das ist besonders notwendig, +weil man in Namen in ELAN beliebig Leerzeichen zur besseren Lesbarkeit +verwenden kann. + + +Programm 4: + + p u t ( "aha"); + put ("aha") + +Beide Anweisungen bewirken also das Gleiche. + +Die Trennung von Anweisungen erfolgt in ELAN durch das Trennsymbol +Semikolon. Es bedeutet soviel wie: "führe die nächste Anweisung aus". Aus +diesem Grund darf hinter der letzten Anweisung eines Programms kein Semiko- +lon geschrieben werden (es folgt ja auch keine Anweisung mehr). + +Der Aufruf einer Prozedur (wie z.B. 'put') verlangt von unserem Rechner im- +mer eine Leistung. Wollen wir aber in einem Programm eine Bemerkung schrei- +ben (z.B. um uns etwas zu merken), dann können wir einen Kommentar schrei- +ben, der vom Übersetzer überlesen und somit keinen Einfluß auf die Aus- +führung eines Programms hat. Ein Kommentar in ELAN wird durch die Zeichen +(* und *) eingeschlossen und darf über mehrere Zeilen gehen. Kommentare sind +in ELAN aber nur in wenigen Fällen notwendig, weil wir Programme durch +andere Mittel gut lesbar machen können. + + + +Ziel der Programmierung + +Was wollen wir eigentlich mit dem Programmieren von Computern erreichen? +Häufig wiederkehrende und somit oft langweilige Tätigkeiten oder solche, die +besonders schnell erledigt werden müssen, sollen von dem "Werkzeug Computer +erledigt werden. Gehaltsberechnungen, Unterstützung beim Schreiben von +Texten, Katalogsysteme für Bibliotheken, Steuerung von Walzstraßen usw. sind +typische Aufgaben für Computer. + +Bei der Programmierung wird also versucht, Objekte (wie z.B. Geld bei einer +Gehaltsberechnung) und Prozesse (wie z.B. die Simulation von Wirtschaftsab- +läufen) der realen Welt mit Hilfe von Programmen in einem Computer nachzu- +bilden und nach bestimmten Vorstellungen so zu verändern, daß man "brauch- +bare" Ergebnisse erlangt. In einem Programm sind Befehle an einen Rechner +für eine solche Abbildung enthalten. Die Befehle in einem Programm werden +Anweisungen genannt. Ein Programmierer muß also folgendes tun: + +1. Abbilden von Objekten und Prozessen der realen Welt in ein Programm. + Dabei müssen die Bedingungen der Aufgabe beachtet werden. Was das Pro- + gramm Programm leisten soll, wird darum in einer Spezifikation festgelegt. + +2. Einbringen des Programms in einen Rechner und Bearbeitung desselben. Die + Formulierung von Anweisungen in einem Programm erfolgt in einer bestimmten + Sprache, nämlich einer Programmiersprache. + +3. Interpretation der Ergebnisse. + + + +Das Konzept des Datentyps + +Befassen wir uns vorerst nur mit Objekten. Sicherlich gibt es sehr viele Ob- +jekte in unserer Welt. Einige von ihnen haben aber gleiche Eigenschaften: + +- Fahrzeuge (Autos, Mofas, Dreiräder) bringen uns von Ort A nach Ort B. + +- Geld (Münzen, Geldscheine, Murmeln, Franc, DM) erlaubt es, etwas zu kaufen. + +- Schreibgeräte (Bleistift, Kugelschreiber, Schreibmaschine) sind die Werk- + zeuge von Leuten, die etwas zu schreiben haben. + +- ... + +Es ist also möglich, einige Objekte der realen Welt in Klassen zusammenzu- +fassen. Eine solche Zusammenfassung kann hinsichtlich gleicher Eigenschaften +bzw. gleicher Operationen, die für solche Objekte zugelassen sind, erfolgen. +Eine Klasse von Objekten mit gleichen Eigenschaften wird in Programmier- +sprachen Datentyp genannt. Dabei hat ein Datentyp immer einen Namen, der die +Klasse von Objekten sinnvoll kennzeichnet. Als ein Datenobjekt wird ein +Exemplar eines Datentyps (also ein spez. Objekt einer Klasse) bezeichnet. + +Datentypen sind in ELAN ein zentrales Konzept. Jedes der in einem ELAN- +Programm verwandten Datenobjekte hat einen Datentyp; somit kann man Daten- +typen auch als Eigenschaften von Datenobjekten ansehen. Für jeden Datentyp +sind nur spezielle Operationen sinnvoll. Z.B. sind für einen Datentyp +"UBoot" die Operationen "erstellen", "tauchen", "auftauchen", "versenken" +und "lieber nicht verwenden" sinnvoll, aber nicht die Operation "+" wie bei +ganzen Zahlen. Man kann nun Übersetzern die Aufgabe überlassen zu überprüfen, +ob stets die richtige Operation auf einen Datentyp angewandt wird. + +Aufgabe (HSG): + + Was ist ein Datentyp? Welche Funktion erfüllen Datentypen? +Übungsziel: Datentyp-Konzept + +Einige Datentypen spielen bei der Programmierung eine besondere Rolle, weil +sie häufig benötigt werden. In ELAN sind das die Datentypen für + +- ganze Zahlen. Dieser Datentyp wird INT (für "integer") genannt. + +- reelle Zahlen (REAL). + +- Zeichen und Zeichenfolgen (TEXT). + +- Wahrheitswerte (BOOL). + +Diese Typen werden in ELAN elementare Datentypen genannt. Für effiziente +Rechnungen mit elementaren Datentypen gibt es in den meisten Rechnern +spezielle Schaltungen, so daß die Hervorhebung und besondere Rolle, die +sie in Programmiersprachen spielen, gerechtfertigt ist. Zudem hat man +Werte-Darstellungen innerhalb von Programmen für die elementaren Datentypen +vorgesehen, was wir im nächsten Abschnitt erklären wollen. + +Im weiteren Teil dieses Skripts werden wir uns zunächst auf die Behandlung +der elementaren Datentypen beschränken. Das bedeutet für den Programmierer, +daß er alle Objekte der realen Welt mit Hilfe der elementaren Datentypen in +den Computer abbilden muß. Das kann manchmal sehr schwierig sein (wie bilden +wir z.B. Personen oder UBoote mit den elementaren Datentypen ab?). Später +werden wir dann Möglichkeiten kennenlernen, neue - problemgerechte - +Datentypen in ELAN zu formulieren. + + + +Denoter (Werte-Repräsentationen) elementarer Datentypen + +Wenn wir mit Objekten elementarer Datentypen arbeiten, müssen wir die +Möglichkeit haben, Werte in ein Programm zu schreiben. Leider kann man einen +Wert "an sich" in einem Programm nicht direkt angeben. Schreiben wir z.B. +4711, dann meinen wir zwar einen INT-Wert, haben aber die Ziffern 4, 7, 1 und +1 geschrieben. Der eigentliche Wert wird in unserem Kopf oder - für unsere +Zwecke - in einem Rechner gebildet. + +Die Werte-Darstellungen oder Werte-Repräsentationen, die in ELAN "Denoter" +genannt werden, sind für jeden Datentyp unterschiedlich. Wie bereits erwähnt, +haben alle Datenobjekte in ELAN (also auch Denoter) nur einen - vom Über +setzer feststellbaren - Datentyp. Aus der Form eines Denoters ist also der +Datentyp erkennbar: + +- INT-Denoter: + Bestehen aus einer Aneinanderreihung von Ziffern. Beispiele: + + 17, 007, 32767, 0 + + Führende Nullen spielen bei der Bildung des Wertes keine Rolle (sie werden + vom ELAN-Compiler überlesen). Negative INT-Denoter gibt es nicht (wie + negative Werte-Darstellungen in einem Programm geschrieben werden, lernen + wir bei den Ausdrücken). + +- REAL-Denoter: + Hier gibt es zwei Formen. Die erste besteht aus zwei INT-Denotern, die + durch einen Dezimalpunkt getrennt werden. Beispiele: + + 0.314159, 17.28 + + Der Dezimalpunkt wird analog der deutschen Schreibweise als Komma + verwendet. Negative REAL-Denoter gibt es wiederum nicht. + + Eine zweite Form wird kurioserweise als "wissenschaftliche Notation" be- + zeichnet. Sie findet dann Verwendung, wenn sehr große oder Zahlen, die + nahe bei Null liegen, dargestellt werden müssen. Beispiele: + + 3.0 e5, 3.0e-5 + + Der (INT-) Denoter hinter dem Buchstaben e gibt an, wie viele Stellen der + Dezimalpunkt nach rechts (positive Werte) oder nach links zu verschieben + ist. Dieser Wert wird Exponent, der Teil vor dem Buchstaben e Mantisse + genannt. + +- TEXT-Denoter: + TEXT-Denoter werden in Anführungszeichen eingeschlossen. Beispiele: + + "Das ist ein TEXT-Denoter" + "Jetzt ein Text-Denoter ohne ein Zeichen: ein leerer Text" + "" + + Beachte, daß das Leerzeichen ebenfalls ein Zeichen ist. Soll ein An- + führungszeichen in einem TEXT erscheinen (also gerade das Zeichen, welches + einen TEXT-Denoter beendet), so muß es doppelt geschrieben werden: + + "Ein TEXT mit dem ""-Zeichen" + "Ein TEXT-Denoter nur mit dem ""-Zeichen:" + """" + + Manchmal sollen Zeichen in einem TEXT-Denoter enthalten sein, die auf dem + Eingabegerät nicht zur Verfügung stehen. In diesem Fall kann der Code- + Wert des Zeichens angegeben werden: + + ""32"" + + bedeutet z.B. das (ASCII-) Leerzeichen. Der Code-Wert eines Zeichens er- + gibt sich aus einer Code-Tabelle (installationsspezifisch), in der jedem + Zeichen eine ganze Zahl zugeordnet ist. + +- BOOL-Denoter: + Es gibt nur zwei BOOL-Denoter: TRUE (für "wahr") und FALSE (für "falsch"). + +Nun wird auch klar, was für Parameter wir in den obigen Programmen verwandt +haben. Es waren natürlich TEXT- bzw. INT-Denoter. + + +Aufgabe (TSW): + + Welche der folgenden Denotationen ist falsch? + + a) 1. e) 1 . 0 i) 007 + b) -1 f) "" j) "Ein "Getuem" stellt sich vor" + c) """ g) """" + d) "das ist ein text" h) TRUE k) 1.0 e 37 + +Übungsziel: Lernen von Denotationen + + + +ELAN-Datenobjekte + +Wie bereits erwähnt, wollen wir mit Hilfe von Programmen Datenobjekte so +verändern, daß wir erwünschte Ergebnisse erhalten. Meist wird zu dieser Ver- +änderung von Datenobjekten "Rechnen" gesagt, obwohl - wie wir gleich sehen +werden - nicht nur numerische Objekte manipuliert werden. Die Veränderung +der Datenobjekte findet zur "Laufzeit" (nicht zur Übersetzungszeit) im +Rechner statt. Die Darstellung eines Werts in einem Rechner zur Laufzeit +eines Programms wird #ib#Repräsentation#ie# genannt. Wenn es eindeutig ist, +daß es sich nur um die Repräsentation im Rechner handelt, sprechen wir kurz +von Werten. +Da also ein Datenobjekt wechselnde Werte annehmen kann, brauchen wir eine +Möglichkeit, es in einem Programm anzusprechen, egal welchen Wert das Objekt +zu einem Zeitpunkt beinhaltet. Zu diesem Zweck können wir einem Datenobjekt +einen Namen geben (wie z.B. einen Personennamen, hinter dem sich eine wirk +liche Person "verbirgt"). Wenn wir also den Namen des Datenobjekts in ein +Programm schreiben, dann meinen wir (meist) den Wert des Datenobjekts, den +es zu diesem Zeitpunkt besitzt. + +Nun sollen die zu behandelnden Datenobjekte ja auch neue Werte erhalten. In +diesem Fall müssen wir die Speicherstelle finden, in die der neue Wert ge- +bracht werden soll. Für diesen Zweck benutzen wir ebenfalls den Namen, zu- +sätzlich zu der Angabe einer Operation, durch die das Objekt einen neuen +Wert erhalten soll. Diese Operation (Wert "schreiben") nennen wir Zuweisung. +Der Zuweisungs-Befehl wird ':=' geschrieben. Beispiel: + + a := 5 + +Bedeutet, daß das Datenobjekt mit dem Namen 'a' den Wert '5' erhält. + +Von manchen Datenobjekten wissen wir, daß wir ihnen nur einmal einen Wert +geben wollen. Sie sollen also nicht verändert werden. Oder wir wissen, daß +in einem Programmbereich ein Datenobjekt nicht verändert werden soll. Um ein +unbeabsichtigtes Verändern zu verhindern, wird in ELAN dem Namen eines +Datenobjekts ein zusätzlicher Schutz mitgegeben: das Zugriffsrecht oder +Accessrecht. Es besteht aus der Angabe der Worte VAR (für Lesen und Ver- +ändern) oder CONST (für ausschließliches Lesen). + + + +Die Deklaration (Vereinbarung) von Datenobjekten + +Wollen wir ein Datenobjekt in einem Programm verwenden, so müssen wir dem +Übersetzer mitteilen, welchen Datentyp und welches Accessrecht das Objekt +haben soll. Das dient u.a. dazu, nicht vereinbarte Namen (z.B. verschriebene) +vom Übersetzer entdecken zu lassen. Weiterhin ist aus dem bei der Deklaration +angegebenen Datentyp zu entnehmen, wieviel Speicherplatz für das Objekt zur +Laufzeit zu reservieren ist. Beispiel: + +INT VAR mein datenobjekt + +Zuerst wird der Datentyp, dann das Accessrecht und schließlich der Name des +Datenobjekts angegeben. Wie werden nun Namen in ELAN formuliert? + +Das erste Zeichen eines Namens muß immer ein kleiner Buchstabe sein. Danach +dürfen beliebig viele kleine Buchstaben, aber auch Ziffern folgen. Zur bes- +seren Lesbarkeit können (wie bei den obigen Prozedurnamen) Leerzeichen in +einem Namen erscheinen, die aber nicht zum Namen zählen. Beispiele: + + name1 + n a m e 1 + x27 + gehalts konto + das ist ein langer name + +Verschiedene Datenobjekte mit gleichem Datentyp und Accessrecht dürfen in +einer Deklaration angegeben werden (durch Kommata trennen). Mehrere Dekla- +rationen werden - genauso wie Anweisungen - durch das Trennsymbol +voneinander getrennt. Beispiele: + + INT VAR mein wert, dein wert, unser wert; + BOOL VAR listen ende; + TEXT VAR zeile, wort + + + +Die Initialisierung von Datenobjekten + +Um mit den so vereinbarten Datenobjekten arbeiten zu können, muß man ihnen +eine Wert geben. Hat ein Datenobjekt noch keinen Wert erhalten, so sagt man, +sein Wert sei undefiniert. Das versehentliche Arbeiten mit undefinierten +Werten ist eine beliebte Fehlerquelle. Deshalb wird von Programmierern +streng darauf geachtet, diese Fehlerquelle zu vermeiden. Eine Wertgebung an +ein Datenobjekt kann (muß aber nicht) bereits bei der Deklaration erfolgen, +was man in ELAN Initialisierung nennt. Beispiele: + + INT CONST gewuenschtes gehalt :: 12 000; + TEXT VAR zeile :: ""; + REAL CONST pi :: 3.14159; + BOOL VAR bereits sortiert :: TRUE + +Allerdings: für mit CONST vereinbarte Datenobjekte ist die Initialisierung +die einzige Möglichkeit, ihnen einen Wert zu geben. + +Die Initialisierung erfolgt mit Hilfe des '::'-Symbols. Anschließend folgt +der Wert, den das Datenobjekt erhalten soll. (In den Beispielen haben wir +nur Denoter geschrieben. Es sind aber auch allgemeinere Ausdrücke erlaubt.). +Es ist nun möglich, mit der oben erwähnten 'put'-Prozedur auch den Wert von +Datenobjekten ausgeben zu lassen. + + +Programm 5: + + INT VAR nummer :: 5; + TEXT CONST bemerkung :: ".Programm"; + put (nummer); + put (bemerkung) + +Beachte dabei, daß bei der Aufführung eines Namens in diesem Fall immer der +Wert des Datenobjekts gemeint ist. Auch die 'put'-Prozedur druckt nicht etwa +den Namen des Datenobjekts oder die Adresse der Speicherstelle, sondern +ebenfalls den Wert. + + +Aufgabe (HSG): + + Welche Aufgabe erfüllen Deklarationen? Was heißt: "Eine Variable hat + einen undefinierten Wert"? Was ist eine Initialisierung? Was ist ein + CONST-Datenobjekt? Warum müssen CONST-Datenobjekte initialisiert + werden? +Übungsziel: Verständnis von Deklarationen und Accessrecht + + + +Schlüsselworte + +Einige Worte haben in ELAN eine feste Bedeutung und können somit nicht - +wie etwa Namen - frei gewählt werden. Solche Worte werden bei den meisten +ELAN-Übersetzern mit großen Buchstaben geschrieben, wie z.B. VAR, CONST, +INT oder REAL u.a.m. Wie wir später sehen werden, besteht die Möglichkeit, +neue Schlüsselworte einzuführen. Halten wir vorläufig fest, daß feste +Bestandteile der Sprache (wie z.B. CONST oder VAR) und Datentypen (wie INT +oder REAL) Schlüsselworte sind, also mit großen Buchstaben geschrieben +werden. + + + +Ausdrücke + +Nun wäre es natürlich schlecht, wenn Programmierer nicht mehr machen könnten, +als Werte ausgeben. Als erste Stufe von etwas komplexeren "Rechnungen" +dürfen Ausdrücke gebildet werden. Ausdrücke sind eine Zusammenstellung von +Datenobjekten (Denoter, VAR- oder CONST-Objekte) und Operatoren. Schauen wir +uns dazu erst ein Programm an: + + +Programm 6: + + INT CONST wert 1 :: 1, + wert 2 :: 2, + wert 3 :: 3; + + put (wert1 + wert2); + put (wert2 - wert1); + put (wert2 * wert3); + put (wert3 DIV wert2); + put (wert2 ** wert3) + +In diesem Programm werden drei Datenobjekte initialisiert. Anschließend +werden jeweils die Werte von zwei Objekten addiert (Operatorzeichen: '+'), +subtrahiert ('-'), multipliziert ('*'), dividiert (ganzzahlige Division ohne +Rest: 'DIV') und potenziert ('**'). Dies sind Operatoren, die zwei Operanden +haben: man nennt sie dyadische Operatoren. Die monadischen Operatoren da- +gegen haben nur einen Operanden. Beispiel: + + put ( - wert1) + +Operatoren in ELAN werden - wie wir an den obigen Beispielen sehen - durch +ein oder zwei spezielle Zeichen oder durch große Buchstaben (in den Fällen, +in denen kein "vernünftiges" Zeichen mehr zur Verfügung steht) als Schlüssel- +wort dargestellt. + +Als Operanden (also die Datenobjekte, auf die ein Operator "wirken" soll) +eines Operators darf ein VAR- oder CONST-Datenobjekt, aber auch ein Denoter +verwendet werden. Das Resultat eines Operators (also das Ergebnis einer +Berechnung) ist bei den obigen Ausdrücken wieder vom Datentyp INT mit dem +Accessrecht CONST. Darum ist es erlaubt, solch einen Ausdruck wiederum als +Operanden zu verwenden. Praktisch bedeutet dies, daß wir mehrere Operatoren +und Datenobjekte zusammen in einem Ausdruck haben dürfen. + + +Programm 7: + + INT CONST wert 1 :: 1, + wert 2 :: 2, + wert 3 :: 3; + + put (wert2 + 3 - wert2 * wert3); + put (- wert2 * wert3) + +Nun haben wir eine Schwierigkeit: Der Ausdruck in der ersten 'put'-Anweisung +ist mehrdeutig, d.h. kann - je nach Reihenfolge der Auswertung - unter- +schiedliche Ergebnisse als Resultat liefern. Beispiel: + + a) (wert2 + 3 = 5) - (wert2 * wert3 = 6) = -1 + b) ((wert2 + 3 = 5) - wert2 = 3) * 3 = 9 + +Es kommt also auf die Reihenfolge der Auswertung von Operatoren an. Diese +kann man durch die Angabe von Klammern steuern. Beispiel: + + (a + b) * (a + b) + +Es wird jeweils erst 'a + b' ausgewertet und dann erst die Multiplikation +durchgeführt. In ELAN ist es erlaubt, beliebig viel Klammernpaare zu ver- +wenden (Regel: die innerste Klammer wird zuerst ausgeführt). Es ist sogar +zulässig, Klammern zu verwenden, wo keine notwendig sind, denn überflüssige +Klammernpaare werden überlesen. Beispiel: + + ((a - b)) * 3 * ((c + d) * (c - d)) + +Somit können wir beliebig komplizierte Ausdrücke formulieren. (Was man aber +vermeiden sollte, weil sie leicht zu Fehlern führen. Stattdessen kann man +einen komplizierten Ausdrücke in mehrere (einfachere) zerlegen.) + +Um solche Ausdrücke einfacher zu behandeln und sie so ähnlich schreiben zu +können, wie man es in der Mathematik gewohnt ist, wird in Programmiersprachen +die Reihenfolge der Auswertung von Operatoren festgelegt. In ELAN wurden +neun Ebenen, Prioritäten genannt, festgelegt: + + +Priorität Operatoren + + 9 alle monadischen Operatoren + 8 ** + 7 *, /, DIV, MOD + 6 +, - + 5 =, <>, <, <=, >, >= + 4 AND + 3 OR + 2 alle übrigen, nicht in dieser Tabelle aufgeführten + dyadischen Operatoren + 1 := + + +(Die bis jetzt noch nicht erwähnten Operatoren in der Tabelle werden wir in +den weiteren Abschnitten besprechen.) + +Operatoren mit der höchsten Priorität werden zuerst ausgeführt, dann die mit +der nächst höheren Priorität usw. Operatoren mit gleicher Priorität werden +von links nach rechts ausgeführt. Dadurch ergibt sich die gewohnte Abarbei- +tungsfolge wie beim Rechnen. Beispiel: + + -2 + 3 * 2 ** 3 + + a) -2 + b) 2 ** 3 + c) 3 * (2 ** 3) + d) ((-2)) + (3 * (2 ** 3)) + +Wie bereits erwähnt, ist es immer erlaubt, Klammern zu setzen. Ist man sich +also über die genaue Abarbeitungsfolge nicht im Klaren, so kann man Klammern +verwenden. + + +Aufgabe (HSG): + + Welche INT-Werte ergeben sich? + + a) 14 DIV 4 e) -14 DIV -4 + b) + 14 DIV 4 f) 2 * 3 DIV 2 ** 2 * 4 + c) -14 DIV 4 g) 2 ** 3 ** 4 + d) 14 DIV -4 h) 3 + 4 * 2 + 3 + +Übungsziel: Arithmetische Ausdrücke + + +Aufgabe (HSG): + + Bilden Sie für folgende mathematische Formeln entsprechende ELAN- + Ausdrücke: + + a b a+b + a) - c d) a g) - --- + b c + + + a+b b a c + b) --- e) -a h) - * - + c+d b d + + + a+b -b c + c) --- e f) a i) (a*b) + c+d + +Übungsziel: Arithmetische Ausdrücke formulieren + + + +Generische Operatoren und Prozeduren + +Bis jetzt wurden nur Ausdrücke mit INT-Operanden verwendet. Wie sieht es +jetzt mit REALs aus? + + +Programm 8: + + put (1.0 + 2.0); + put (2.0 - 1.0); + put (2.0 * 3.0); + put (3.0 / 2.0); + put (2.0 ** 3.0) + +Man beachte die Unterschiede zum Programm 7: Wir müssen nun REAL-Denoter +verwenden (mit INT-Denotern zu arbeiten wäre ein Fehler). Der Divisions- +Operator hat sich nun von 'DIV' zu '/' gewandelt. Die Ergebnisse sind nun +nicht INT-, sondern REAL-Werte. Für die Reihenfolge der Auswertung der +Operatoren sowie die Verwendung von Klammern gilt das für INT-Ausdrücke +gesagte. + +Wir haben den '+'-Operator in zwei verschiedenen Formen gesehen: in Programm +7 mit Operanden vom Datentyp INT, ein INT-Resultat liefernd, und in Programm +8 das gleiche mit REALs. Es liegen also zwei verschiedene Operatoren vor, +die aber den gleichen Namen (Zeichen: '+') haben. + +In ELAN ist es somit möglich, unterschiedlichen Operatoren (aber auch Proze- +duren) gleiche Namen zu geben. Solche Operatoren werden generische Opera- +toren genannt. Ein ELAN-Compiler wählt den richtigen Operator aufgrund der +Datentypen der Operanden aus. Oft werden die verfügbaren Operatoren wie folgt +dokumentiert: + + INT OP + (INT CONST links, rechts) + +Diese Form nennt man einen "Operator-Kopf". Sie wird in ELAN-Programmen bei +der Definition von Operatoren benötigt. Dabei steht OP für "OPERATOR". Die +Angabe des Datentyps davor gibt den Datentyp des Resultats des Operators an. +Zwischen 'OP' und der öffnenden Klammer steht der Name des Operators (hier: +'+'). In den Klammern werden die Datentypen und das Accessrecht der +Operanden angegeben. CONST bedeutet hier: der Operand darf vom Operator +nicht verändert werden, während bei VAR (was normalerweise ja nicht sein +sollte!) ein Operand bei der Abarbeitung eines Operators verändert werden +kann. + +Damit wir solche Definitionen besser beherrschen, geben wir noch weitere +Beispiele an: + + INT OP - (INT CONST operand) + REAL OP / (INT CONST l, r) + +Bei dem ersten Operator handelt es sich um den monadischen Operator '-' für +INT-Operanden (z.B.: 'INT VAR a :: 1; put (-a)'), während es sich bei dem +zweiten Operator um eine Divisions-Operator handelt, der jedoch ein REAL- +Resultat liefert (z.B.: 'put (3 / 2)' liefert 1.5). Der MOD-Operator liefert +den Rest einer Division: + + INT OP MOD (INT CONST l, r) + REAL OP MOD (REAL CONST l, r) + +Die Beschreibung von generischen Prozeduren verläuft analog. Beispiele: + + PROC put (INT CONST wert) + PROC put (REAL CONST wert) + +Hier wird das Wort 'OP' durch 'PROC' (für 'PROCEDURE') ersetzt. Die Angaben +in Klammern bezeichnen nun nicht Operanden, sondern Parameter. + +Über die verfügbaren Operatoren und Prozeduren für INT- und REAL-Datenob- +jekte kann man sich im ELAN-Handbuch oder im EUMEL-Benutzerhandbuch infor- +mieren. Einige - aber nicht alle - der Operatoren und Prozeduren (auch für +andere Datentypen) werden wir erklären, wenn wir sie in Programmen benötigen. + + + +Die Zuweisung + +Ein spezieller Operator ist die Zuweisung (Zeichen: ':='). Dieser Operator +hat immer die geringste Priorität, wird also immer als letzter eines Aus- +drucks ausgeführt. Die Zuweisung wird verwendet, um einer Variablen einen +neuen Wert zu geben. Beispiel: + + a := b + +Hier wird der Wert von 'b' der Variablen 'a' zugewiesen. Der vorher vor- +handene Wert von 'a' geht dabei verloren. Man sagt auch, der Wert wird über- +schrieben. Auf der rechten Seite (also als rechter Operand) des ':=' +Operators darf auch ein Ausdruck stehen. Beispiel: + + a := b + c + +Hier wird das Resultat von 'b + c' an die Variable 'a' zugewiesen. Man be- +achte dabei die Prioritäten der Operatoren '+' (Priorität 6) und ':=' (Pri- +orität 1): die Addition wird vor der Zuweisung ausgeführt. Die Auswertung +von Zuweisungen mit Ausdrücken muß immer so verlaufen, da die Zuweisung +stets die niedrigste Priorität aller Operatoren hat. + +Schauen wir uns zum besseren Verständnis die Definitionen des (natürlich +auch generischen) Operators ':=' an: + + OP := (INT VAR ziel, INT CONST quelle) + OP := (REAL VAR ziel, REAL CONST quelle) + OP := (TEXT VAR ziel, TEXT CONST quelle) + OP := (BOOL VAR ziel, BOOL CONST quelle) + +Der Operator ':=' liefert also kein Resultat (man sagt auch, er liefert +keinen Wert) und verlangt als linken Operanden ein VAR-Datenobjekt (an den +der Wert der rechten Seite zugewiesen werden soll). Der Wert des linken +Operanden wird also verändert. Für den rechten Operanden ist durch CONST +sichergestellt, daß er nur gelesen wird. + +Oft kommt es vor, daß ein Objekt auf der linken und rechten Seite des Zuwei- +sungsoperators erscheint, z.B. wenn ein Wert erhöht werden soll. Beispiele: + + a := a + 1; + a := a + 17 + +Hier wird der "alte", aktuelle Wert von 'a' genommen, um '1' erhöht und dem +Objekt 'a' zugewiesen. Man beachte, daß hier in einer Anweisung ein Datenob- +jekt unterschiedliche Werte zu unterschiedlichen Zeitpunkten haben kann. + +In solchen Fällen darf man den Operator INCR verwenden: + + a INCR 1; + a INCR 17 + +Analoges gilt für den Operator DECR, bei dem ein Wert von einer Variable +subtrahiert wird. Also: + + OP INCR (INT VAR ziel, INT CONST dazu) + OP INCR (REAL VAR ziel, REAL CONST dazu) + + OP DECR (INT VAR ziel, INT CONST abzug) + OP DECR (REAL VAR ziel, REAL CONST abzug) + +Schauen wir uns folgendes Programm an, bei dem zwei Werte vertauscht werden: + + +Programm 9: + + INT VAR a, b, x; + + get (a); + get (b); + x := a; + a := b; + b := x; + put (a); + put (b) + +Wie wir an diesem Beispiel sehen, existieren nicht nur 'put'-Prozeduren, +sondern auch 'get'-Prozeduren, die einen Wert vom Eingabemedium einlesen. +Es gibt folgende 'get'- Prozeduren (die 'put'-Prozeduren führen wir der +Vollständigkeit halber auch mit auf): + + PROC get (INT VAR wert) + PROC get (REAL VAR wert) + PROC get (TEXT VAR wert) + + PROC put (INT CONST wert) + PROC put (REAL CONST wert) + PROC put (TEXT CONST wert) + + +Aufgabe (HSG): + + Was versteht man unter Generizität? + Übungsziel: Generizitäts-Begriff + + + +Refinements + +Bevor wir die Operationen für TEXTe und BOOLs besprechen, wollen wir eine +weitere wichtige Eigenschaft von ELAN diskutieren, nämlich die Namensgebung. +Namen für Datenobjekte haben wir bereits kennengelernt. In ELAN ist es eben- +falls möglich, Namen für Ausdrücke oder eine bzw. mehrere Anweisungen zu +vergeben. + + +Programm 10: + + INT VAR a, b, x; + einlesen von a und b; + vertauschen von a und b; + vertauschte werte ausgeben. + + einlesen von a und b: + get (a); + get (b). + + vertauschen von a und b: + x := a; + a := b; + b := x. + + vertauschte werte ausgeben: + put (a); + put (b). + +Dies ist das gleiche Programm wie das 9. Beispielprogramm. Für den Namen +'einlesen von a und b' werden die Anweisungen 'get (a); get (b)' vom +ELAN-Übersetzer eingesetzt. Man kann also die ersten vier Zeilen des +Programms als eigentliches Programm ansehen, wobei die Namen durch die +betreffenden Anweisungen ersetzt werden. Eine solche Konstruktion wird in +ELAN Refinement genannt. Was wird dadurch erreicht? + +Durch die sinnvolle Verwendung von Refinements wird ein Programm im Programm +und nicht in einer separaten Beschreibung dokumentiert. Weiterhin kann ein +Programm "von oben nach unten" ("top down") entwickelt werden: wir haben das +obige - zugegeben einfache - Beispielprogramm in drei Teile zerlegt und +diese durch Namen beschrieben. Bei der Beschreibung von Aktionen durch Namen +sagen wir, was wir machen wollen und nicht wie, denn wir brauchen uns auf +dieser Stufe der Programmentwicklung um die Realisierung der Refinements +(noch) keine Sorgen zu machen. Das erfolgt erst, wenn wir genauer definieren +müssen, wie das Refinement programmiert werden muß. Dabei können wir +wiederum Refinements verwenden usw., bis wir auf eine Ebene "herunterge- +stiegen" sind, bei dem eine (jetzt: Teil-) Problemlösung sehr einfach ist +und wir sie direkt hinschreiben können. Wir beschäftigen uns also an jedem +Punkt der Problemlösung nur mit einem Teilaspekt des gesamten Problems. +Zudem sieht man - wenn die Refinements einigermaßen vernünftig verwendet +werden - dem Programm an, wie die Problemlösung entstanden ist. + +Die Verwendung von Refinements hat also eine Anzahl von Vorteilen. Schauen +wir uns deshalb an, wie die Refinements formal verwandt werden müssen. Das +"Hauptprogramm" wird durch einen Punkt abgeschlossen, falls ein Refinement +folgt. Ein Refinement besteht aus der Nennung des Refinement-Namens, der +von einem Doppelpunkt gefolgt sein muß. In einem Refinement kann eine +Anweisung oder mehrere - durch Semikolon getrennt - stehen. Das Refinement +wird durch einen Punkt abgeschlossen. + +Refinements können auch dort verwendet werden, wo ein Wert erwartet wird, +z.B. in einem Ausdruck oder einer 'put'-Anweisung. In diesem Fall muß das +Refinement natürlich einen Wert liefern. Wie macht man das? Eine Möglichkeit +ist, daß im Refinement ein Ausdruck geschrieben wird, der einen Wert als +Resultat liefert. + + +Programm 11: + + INT VAR a :: 1, b :: 2, c :: 3; + put (resultat). + + resultat: + (a * b + c) ** 3. + +Eine Zuweisung liefert - wie bereits erwähnt - kein Resultat. Es ist auch +erlaubt, ein Refinement mit mehreren Anweisungen zu schreiben, das einen Wert +liefert. Allgemeine Regel: die letzte Anweisung eines Refinements bestimmt, +ob ein Refinement einen Wert liefert - und wenn ja, von welchen Datentyp. + + + +BOOLesche Operationen + +Für BOOLesche Datenobjekte gibt es einige Operatoren: + + BOOL OP AND (BOOL CONST links, rechts) + BOOL OP OR (BOOL CONST links, rechts) + BOOL OP NOT (BOOL CONST operand) + +Der Operator AND liefert als Resultat die logische "und"-Verknüpfung (nur +wenn beide Operanden den Wert TRUE haben ist das Resultat TRUE, sonst FALSE), +OR ist das logische "oder" (nur wenn beide Operanden FALSE liefern, ist das +Resultat FALSE, sonst TRUE) und die logische Negation NOT (als Resultat wird +das "Gegenteil" geliefert). + +Ebenfalls wichtig sind die Vergleichs-Operatoren, die zwar keine BOOLeschen +Operanden erwarten, aber ein BOOLesches Resultat liefern: + + BOOL OP = (INT CONST links, rechts) + BOOL OP <> (INT CONST links, rechts) + BOOL OP < (INT CONST links, rechts) + BOOL OP <= (INT CONST links, rechts) + BOOL OP > (INT CONST links, rechts) + BOOL OP >= (INT CONST links, rechts) + +Diese Operatoren: = (gleich), <> (ungleich), < (kleiner), <= (kleiner +gleich), > (größer), >= (größer gleich) gibt es auch noch für Operanden vom +Datentyp REAL und TEXT. Da die Vergleichs-Operatoren ein BOOLesches Resultat +liefern, kann man sie in BOOLeschen Ausdrücken verwenden. Zu beachten ist +dabei die Priorität der Operatoren: die Vergleiche werden immer vor den +Operatoren AND bzw. OR ausgeführt. + + +Programm 12: + + BOOL CONST kaufen; + kaufen := will ich AND NOT zu teuer. + + will ich: + TEXT VAR produktname; + get (produktname); + produktname = "muesli" OR produktname = "vollkornbrot". + + zu teuer: + INT VAR preis; + get (preis); + preis > 20. + + + +Aufgabe (HSG): + + Welche BOOL-Werte ergeben sich? + + a) TRUE AND FALSE e) TRUE AND TRUE OR TRUE + b) TRUE OR FALSE f) 10 < 3 AND 17 > 4 + c) TRUE AND NOT FALSE g) 17 + 4 = 21 OR TRUE + d) NOT TRUE AND FALSE h) TRUE AND FALSE OR TRUE + + Übungsziel: Boolesche Ausdrücke + + + +Abfragen + +BOOLesche Ausdrücke werden in einer speziellen Anweisung verwandt, der +Abfrage: + + +Programm 13: + + INT VAR a, b; + get (a); get (b); + IF a > b + THEN vertausche a und b + END IF; + put (a); put (b). + + vertausche a und b: + INT CONST x :: a; + a := b; + b := x. + +Das Refinement im THEN-Teil der bedingten Anweisung wird nur durchgeführt, +wenn der BOOLesche Ausdruck ('a > b') den Wert TRUE liefert. Liefert er den +Wert FALSE, wird die Anweisung, die der bedingten Anweisung folgt (nach END +IF), ausgeführt. Programm 13 kann etwas anders geschrieben werden: + + +Programm 14: + + INT VAR a, b; + get (a); get (b); + IF a > b + THEN put (a); + put (b) + ELSE put (b); + put (a) + END IF. + +Der THEN-Teil wird wiederum ausgeführt, wenn die BOOLesche Bedingung +erfüllt ist. Liefert sie dagegen FALSE, wird der ELSE-Teil ausgeführt. + +Die bedingte Anweisung gibt uns also die Möglichkeit, abhängig von einer +Bedingung eine oder mehrere Anweisungen ausführen zu lassen. Dabei können +im THEN- bzw. ELSE-Teil wiederum bedingte Anweisungen enthalten sein usw. +Solche geschachtelten bedingten Anweisungen sollte man jedoch vermeiden, +weil sie leicht zu Fehlern führen können (statt dessen durch Refinements +realisieren). Man beachte auch die Einrückungen, die man machen sollte, um +die "Zweige" besonders kenntlich zu machen. + + +Aufgabe (HSG): + + a) In welcher Reihenfolge werden Operatoren ausgewertet? + b) Reihenfolge der Auswertung von: a + b + c + c) INT VAR a, b, c; + ... + IF NOT a = 0 AND b = 0 THEN... + ergibt einen syntaktischen Fehler. Welchen? + d) Wie wird der BOOLesche Ausdruck ausgewertet? + INT VAR a :: 0, b :: 4; + ... + IF a = 0 AND b DIV a > 0 + e) Warum ist + BOOL VAR ende :: TRUE; + ... + IF ende = TRUE + THEN... + Unsinn? + + Übungsziel: Reihenfolge der Auswertung von Ausdrücken + +Bei Abfrageketten kann das ELIF-Konstrukt eingesetzt werden. (ELIF ist eine +Zusammenziehung der Worte ELSE und IF). Anstatt + + ... + IF bedingung1 + THEN aktion1 + ELSE IF bedingung2 + THEN aktion2 + ELSE aktion3 + END IF + END IF; + ... + +kann man besser + + ... + IF bedingung1 + THEN aktion1 + ELIF bedingung2 + THEN aktion2 + ELSE aktion3 END IF; + ... + +schreiben. + +Die bedingte Anweisung kann auch einen Wert liefern. In diesem Fall muß der +ELSE-Teil vorhanden sein und jeder Zweig den gleichen Datentyp liefern +(jeweils die letzte Anweisung muß einen Wert liefern). + + +Aufgabe (HSG): + + Was berechnen folgende (Teil-) Programme? + + a) INT VAR a; + get (a); + put (wert). + + wert: + IF a < 0 + THEN -a + ELSE a + END IF. + + b) INT VAR brutto, netto; + get (brutto); + berechne gehalt; + put ("mein gehalt:"); + put (netto). + + berechne gehalt: + IF jahresverdienst > 30 000 (* zu wenig? *) + THEN sonderabgabe + END IF; + netto := brutto - brutto DIV 100 * 20. + + jahresverdienst: + brutto * 12. + + sonderabgabe: + brutto := brutto - brutto DIV 100 * 30 + + c) INT VAR x; + ... + put (signum). + + signum: + IF x > 0 + THEN 1 + ELSE kleiner gleich + END IF. + + kleiner gleich: + IF x = 0 + THEN 0 + ELSE -1 + END IF. + + + +TEXTe + +TEXT-Denoter haben wir bereits kennengelernt. Im folgenden Programm stellen +wir die Wirkung einiger TEXT-Operationen vor. + + +Programm 15: + + TEXT VAR a, b, c; + a := "ELAN"; + b := "-Programm"; + c := a + b; + put (c) + +Der Operator + + TEXT OP + (TEXT CONST links, rechts) + +liefert als Ergebnis einen TEXT, bei dem an den linken der rechte Operand +angefügt wurde (Fachausdruck: "Konkatenation"). Weitere Operatoren: + + TEXT OP CAT (TEXT VAR ziel, TEXT CONST dazu) + TEXT OP * (INT CONST i, TEXT CONST a) + TEXT OP SUB (TEXT CONST t, INT CONST pos) + +Der Operator CAT fügt an einen TEXT einen zweiten an ('a CAT b' wirkt wie +'a := a + b'). Mit dem '*'-Operator kann man einen TEXT vervielfältigen +(Beispiel: 17 * "--"), während man mit SUB ein Zeichen aus einem TEXT her- +ausholen kann (Beispiel: "ELAN" SUB 3 liefert "A"). + +Die meisten TEXT-Operationen sind als Prozeduren realisiert, weil mehr als +zwei Operanden benötigt werden. Die Wirkung einiger Operationen geben wir in +kurzen Kommentaren an: + + TEXT PROC subtext (TEXT CONST t, INT CONST von) + (* rechter Teiltext von 't' von der Position 'von' bis Ende *) + + TEXT PROC subtext (TEXT CONST t, INT CONST von, bis) + (* Teiltext von 't' von der Position 'von' bis 'bis' *) + + PROC change (TEXT VAR t, TEXT CONST old, new) + (* Ersetzung von 'old' in 'new' im TEXT 't' *) + + INT PROC length (TEXT CONST t) + (* Anzahl Zeichen von 't' *) + + INT PROC pos (TEXT CONST t, muster) + (* Die Position des ersten Auftretens von 'muster' in 't' *) + +Die Vergleichs-Operatoren für TEXTe arbeiten bei dem Vergleich nach der +alphabetischen Reihenfolge ('"a" < "b"' liefert TRUE). Dabei definiert ELAN +nur die Reihenfolge innerhalb der kleinen und großen Buchstaben und Ziffern. +Das Leerzeichen ("#ib#blank#ie#") ist jedoch stets das "kleinste" Zeichen. +Wie diese "Zeichenblöcke" und die restlichen Zeichen angeordnet sind, wurde +nicht spezifiziert. Ob '"a" < "Z"' TRUE oder FALSE liefert, wurde also nicht +festgelegt und ist somit rechnerspezifisch. Anmerkung: Im EUMEL-Betriebs- +system wird der ASCII-Zeichencode, DIN 66 003 mit Erweiterungen verwandt. +Die folgenden Vergleiche sind alle TRUE: + + "otto" = "otto" + "a" < "z" + "Adam" < "Eva" + "hallo" < "hallu" + "hallo" < "hallo " + length ("ha") = 2 + subtext ("ELAN-Programmierung", 14) = "ierung" + + +Aufgabe (HSG): + + Gib die Realisierung von folgenden vorgegebenen Prozeduren und Opera- + toren an: + a) TEXT PROC subtext (TEXT CONST t, INT CONST von) durch + TEXT PROC subtext (TEXT CONST t, INT CONST von, bis) + b) OP CAT (TEXT VAR a, TEXT CONST b) durch ':=' und '+' + c) TEXT OP SUB (TEXT CONST t, INT CONST p) durch 'subtext' + + Übungsziel: Lernen einiger vorgegebener TEXT-Operationen + + + +Die Wiederholungs-Anweisung + +Wiederholungs-Anweisungen ermöglichen es uns, Anweisungen wiederholt - meist +in Abhängigkeit von einer Bedingung - ausführen zu lassen. Darum wird die +Wiederholungs-Anweisung oft auch #ib#Schleife#ie# genannt, die in ihr ent- +haltenen Anweisungen #ib#Schleifenrumpf#ie#. Die Schleife von ELAN baut auf +einem Basis-Konstrukt auf: + + REP + anweisungen + END REP + +Diese Anweisungsfolge realisiert eine sogenannte "Endlosschleife", weil nicht +spezifiziert wird, wann die Schleife beendet werden soll. + +Bei der abweisenden Schleife wird die Abbruchbedingung an den Anfang der +Schleife geschrieben: + + WHILE boolesche bedingung REP + anweisungen + END REP + +Bei jedem erneuten Durchlauf durch die Schleife wird überprüft, ob der +BOOLesche Ausdruck den Wert TRUE liefert. Ist das nicht der Fall, wird mit +der nächsten, auf die Schleife folgenden Anweisung mit der Bearbeitung fort- +gefahren. Die Schleife wird abweisende Schleife genannt, weil der Schleifen- +rumpf nicht ausgeführt wird, wenn die Bedingung vor Eintritt in die Schleife +bereits FALSE liefert. + +Anders verhält es bei der nicht abweisenden Schleife: + + REP + anweisungen + UNTIL boolesche Bedingung END REP + +Hier wird der Schleifenrumpf auf jeden Fall einmal bearbeitet. Am Ende des +Rumpfes wird die BOOLesche Bedingung abgefragt. Liefert diese den Wert FALSE, +wird die Schleife erneut abgearbeitet. Liefert die Bedingung den Wert TRUE, +wird die Schleife abgebrochen und mit der ersten Anweisung hinter der +Schleife in der Bearbeitung fortgefahren. + +Bei beiden Arten der Wiederholungs-Anweisung ist es wichtig, daß Elemente +der BOOLeschen Bedingung in der Schleife verändert werden, damit das +Programm terminieren kann, d.h. die Schleife abgebrochen wird. + +Eine Endlos-Schleife wird bei der Zählschleife meist nicht vorkommen: + + FOR i FROM anfangswert UPTO endwert REP + anweisungen + END REP + +Zählschleifen werden eingesetzt, wenn die genaue Anzahl der Schleifendurch- +läufe bekannt ist. Hier wird eine Laufvariable verwendet (in unserem Bei- +spiel 'i': sie muß mit INT VAR deklariert werden), die die INT-Werte von +'anfangswert' bis 'endwert' in Schritten von '1' durchläuft. Diese Schleife +zählt "aufwärts". Wird anstatt UPTO das Schlüsselwort DOWNTO verwendet, wird +mit Schritten von -1 "abwärts" gezählt. Beispiel: + + FOR i FROM endwert DOWNTO anfangswert REP + ... + +Für ein Beispielprogramm stellen wir uns die Aufgabe, aus TEXTen das Auf- +treten des Buchstabens "e" herauszufinden. Die TEXTe sollen vom Eingabe- +medium solange eingelesen werden, bis wir den TEXT "00" eingeben. + + +Programm 16: + + INT VAR anzahl e :: 0; + TEXT VAR wort; + REP + get (wort); + zaehle e im wort + UNTIL wort = "00" END REP; + put (anzahl e). + + zaehle e im wort: + INT VAR i; + FOR i FROM 1 UPTO length (wort) REP + IF das i te zeichen ist e + THEN anzahl e INCR 1 + END IF + END REP. + + das i te zeichen ist e: + (wort SUB i) = "e". + + +Aufgabe (HSG): + + Die Klammern in dem letzten Refinement sind notwendig. Warum? + +Bevor wir ein Programm einem Rechner zur Bearbeitung übergeben, sollten wir +uns davon überzeugen, daß das Programm wirklich das leistet, was es soll. +Eine der wichtigsten Bedingungen ist die Terminierung eines Programms, d.h. +das Programm darf nicht in eine Endlosschleife geraten. Unser Beispielpro- +gramm terminiert, wenn beide Schleifen terminieren: die obere Schleife +terminiert durch das Endekriterium, während die zweite Schleife automatisch +durch die Zählschleife begrenzt wird. Das Programm wird also auf jeden Fall +beendet (kann in keine Endlosschleife geraten), falls das Endekriterium ein- +gegeben wird. +Interessant sind dabei immer "Grenzfälle", wie z.B. die Eingabe eines +"leeren Textes", sehr lange TEXTe usw. + + +Aufgabe (HSG): + + Welche Fehler befinden sich in den folgenden Programmteilen? + a) INT VAR i; + FOR i FROM 1 UPTO i REP + tue irgendwas + END REP + + b) BOOL CONST noch werte :: TRUE; + INT VAR i; + WHILE noch werte REP + get (i); + ... + IF i = O + THEN noch werte := FALSE + END IF + END REP + + c) INT VAR anz berechnungen :: 1; + REP + lies eingabe wert; + berechnung; + drucke ausgabewert + UNTIL anz berechnungen > 10 END REP. + + d) INT VAR anz berechnungen; + WHILE anz berechnungen <= 10 REP + lies eingabewert; + berechnung; + drucke ausgabewert; + anz berechnungen INCR 1 + END REP. + + e) INT VAR n := 1, summe; + summe der ersten 100 zahlen. + + summe der ersten 100 zahlen: + WHILE n < 100 REP + summe := summe + n; + n INCR 1 + END REP. + (* Achtung: 2 Fehler! (Vorwarnen ist feige) *) + + f) INT VAR n := 1; + REP + INT VAR summe := 0; + summe := summe + n; + n INCR 1 + UNTIL n = 100 END REP + (* Achtung: 2 Fehler! *) + + Übungsziel: Arbeiten mit Schleifen + + +Das Programm 16 können wir etwas besser formulieren. Dazu wollen wir uns +aber eine etwas andere Aufgabe stellen: wie viele Leerzeichen sind in einem +Text? Zur Lösung dieser Aufgabe sollten wir den Text nicht wortweise ein- +lesen, sondern zeilenweise. Dazu verwenden wir die Prozedur + + PROC get (TEXT VAR t, INT CONST max length) + +die einen TEXT 't' mit maximal 'max length' Zeichen einliest. Auf dem +EUMEL-System gibt es dafür auch die Prozedur 'getline'. + + +Programm 17: + + INT VAR anzahl blanks :: 0; + REP + lies zeile ein; + zaehle blanks + UNTIL zeile hat endekriterium END REP. + + lies zeile ein: + TEXT VAR zeile; + get (zeile, 80). + + zaehle blanks: + INT VAR von :: 1; + WHILE zeile hat ab von ein blank REP + anzahl blanks INCR 1; + von auf blank position setzen + END REP. + + zeile hat ab von ein blank: + pos (zeile, " ", von) > 0. + + von auf blank position setzen: + von := pos (zeile, " ", von). + + zeile hat endekriterium: + pos (zeile, "00") > 0. + + +Aufgabe (TSW): + + Das Programm 17 enthält (mindestens) zwei Fehler. Finden Sie diese bitte + heraus. + + Übungsziel: Finden von Programmierfehlern. + + +Aufgabe (HSG): + + a) Welche Werte liefern folgende Ausdrücke für die Textvariable + TEXT VAR t :: "Das ist mein Text" + a1) pos (t, "ist") + a2) pos (t, "ist", 5) + a3) length (t) + a4) subtext (t, 14) + a5) subtext (t, 14, 17) + + b) Welche Werte liefern folgende Ausdrücke für die Textkonstanten + TEXT CONST text :: "ELAN-Programm", + alphabet :: "abcde...xyz" + b1) 3 * text + b2) length ("mein" + text + 3 * "ha") + b3) 3 * "ha" < text + b4) pos (text, alphabet SUB 1) + b5) pos (text, subtext (alphabet, 7, 7)) + + c) Schreibe in anderer Form: + c1) subtext (text, 7, 7) + c2) change (text, "alt", "neu") + c3) INT VAR laenge :: length (text); + IF subtext (text, laenge, laenge) =... + c4) IF NOT (text = "aha") + THEN aktion 1 + ELSE aktion 2 + END IF + + Übungsziel: TEXT-Ausdrücke und Prozeduren + + + +Die Repräsentation von Datentypen + +Wie bereits erwähnt, sind Datentypen Klassen von Objekten der realen Umwelt. +Die Objekte eines Datentyps müssen in den Speicher eines Rechners abgebildet +werden. Die Darstellung eines Objekts im Rechner wird Repräsentation genannt. +Aus organisatorischen Gründen versucht man, immer feste, gleich große Ein- +heiten für die Objekte eines Datentyps zu verwenden. Durch die Begrenzung auf +feste Speicherplatzeinheiten ist der Wertebereich beschränkt. Diese Grenzen +hat man beim Programmieren zu beachten. + +Beim Datentyp BOOL spielt die Repräsentation nur insoweit eine Rolle, daß +man die zwei möglichen Werte mehr oder weniger speicheraufwendig realisieren +kann. Eine Einschränkung des Wertebereichs gibt es nicht. + +Bei INTs ist jedoch eine Einschränkung des Wertebereichs gegeben. Für die +Repräsentation von INTs sind Einheiten von 16, 32 Bit u.a.m. gebräuchlich. +Es existiert die Möglichkeit, den größten INT-Wert mit Hilfe von + + maxint + +zu erfragen. Z.B. ist 'maxint' für EUMEL-Systeme z.Zt. 32 767. Der kleinste +INT-Wert ist oft nicht ' - maxint' (im EUMEL-System kann er unter 'minint' +angesprochen werden). Übersteigt ein Wert 'maxint', gibt es eine Fehler- +meldung 'overflow', im andern Fall 'underflow'. + +REALs sind noch schwieriger. Durch die endliche Darstellung der Mantisse +treten "Lücken" zwischen zwei benachbarten REALs auf. Deshalb ist bei Ver- +wendung von REALs immer mit Repräsentationsfehlern zu rechnen. Dieses Thema +der "Rundungsfehler" wollen wir hier jedoch nicht weiter vertiefen. Auf +jeden Fall gibt es aber auch einen größten REAL-Wert + + maxreal + +Bei TEXTen gibt es zwei Repräsentations-Schwierigkeiten. Einerseits werden +TEXTe durch "irgendeinen" Code im Rechner repräsentiert, der z.B. bei Ver- +gleichen verwendet wird. ELAN-Compiler auf Rechenanlagen mit unterschied- +lichen Zeichencodes können daher unterschiedliche Ergebnisse liefern. +Andererseits ist in ELAN nicht definiert, wie viele Zeichen maximal in einen +TEXT passen, was ebenfalls vom Rechner bzw. von einem ELAN-Compiler abhängt. +Auf dem EUMEL-System kann die maximale Anzahl Zeichen eines TEXTs durch +'maxtext length' erfragt werden. Sie ist z.Z. '32 000'. + + + +Ein- und Ausgabe + +Wie Datenobjekte - auf einfache Weise - auf einem Ausgabemedium ausgegeben +werden können, haben wir bereits geschildert (Prozedur 'put'). Die Ausgabe +erfolgt solange auf einer Zeile, bis ein auszugebender Wert nicht mehr auf +eine Zeile paßt. In diesem Fall wird die Ausgabe in die nächste Zeile pla- +ziert. Zwischen den einzelnen Werten auf einer Zeile wird jeweils ein Blank +Zwischenraum gelassen, um die Ausgaben voneinander zu trennen. Mit folgenden +Prozeduren kann man die Ausgabe flexibel gestalten: + + PROC line (* bewirkt einen Zeilenvorschub *) + + PROC line (INT CONST anzahl) (* bewirkt 'anzahl' Zeilenvorschübe *) + + PROC page (* bewirkt einen Seitenvorschub auf + einem Drucker oder löscht den Bild- + schirm und positioniert in die linke + obere Ecke *) + + PROC putline (TEXT CONST zeile) (* gibt 'zeile' auf dem Bildschirm aus + und positioniert auf die nächste + neue Zeile *) + + PROC cursor (INT CONST reihe, spalte) (* Positioniert die Schreibmarke + auf dem Bildschirm in die an- + gegebene Position *) + +Die Prozedur 'get' holt Eingaben vom Eingabemedium. Ein Element der Eingabe +wird dabei durch ein Blank vom nächsten getrennt. Einige weitere Eingabe- +Prozeduren: + + PROC get (TEXT VAR t, TEXT CONST delimiter) (* die nächste Eingabe wird + nicht von einem Blank + begrenzt, sondern durch + 'delimiter' *) + + TEXT PROC get (* dient zum Initialisieren *) + + PROC inchar (TEXT VAR zeichen) (* wartet solange, bis ein Zeichen vom + Bildschirm eingegeben wird *) + + TEXT PROC incharety (* Versucht ein Zeichen vom Bildschirm + zu lesen. Ist kein Zeichen vor- + handen, wird "" geliefert *) + + PROC editget (TEXT VAR line) (* Bei der Eingabe kann 'line' editiert + werden *) + + PROC get cursor (INT VAR zeile, spalte) (* Informationsprozedur, wo die + Schreibmarke aktuell steht *) + + + +Konvertierungen + +Manchmal ist es notwendig, eine Datentyp-Wandlung für ein Objekt vorzunehmen. +Die Wandlungen von einem INT- bzw. einen REAL-Wert in einen TEXT und umge- +kehrt sind relativ unkritisch: + + TEXT PROC text (INT CONST value) + TEXT PROC text (REAL CONST value) + INT PROC int (TEXT CONST number) + REAL PROC real (TEXT CONST number) + +Aber bei der folgenden Prozedur 'int' gehen im allgemeinen Fall Informationen +verloren (es wird abgeschnitten): + + INT PROC int (REAL CONST value) + REAL PROC real (INT CONST value) + +Zusätzlich steht eine Informationsprozedur 'last conversion ok' zur Ver- +fügung, die den Wert TRUE liefert, falls die letzte Konversion fehlerfrei +war: + + BOOL PROC last conversion ok + +Solche Abfragen sind notwendig, weil die Konversionsroutinen bei falschen +Parameterwerten (z.B. 'int (maxreal)') nicht mit einer Fehlermeldung ab- +brechen. Als Beispiel zeigen wir ein Programm zum Einlesen von Werten, von +denen man nicht weiß, ob sie INT oder REAL sind. Darum kann auch nicht die +'get'-Prozedur für INT oder REAL verwandt werden: + + +Programm 18: + + TEXT VAR eingabe element; + REP + get (eingabe element); + wert nach intwert oder realwert bringen; + berechnung + UNTIL ende ENDREP. + + wert nach intwert oder realwert bringen: + IF pos (eingabe element, ".") > 0 + THEN REAL VAR realwert :: real (eingabe element) + ELSE INT VAR intwert :: int (eingabe element) + END IF; + IF NOT last conversion ok + THEN put ("Fehler bei Konvertierung:" + eingabe element); + line + END IF. + + berechnung: + ... + + diff --git a/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil6b b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil6b new file mode 100644 index 0000000..7fdaf39 --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil6b @@ -0,0 +1,1425 @@ + EUMEL-Benutzerhandbuch + + + TEIL 6: Erste Hilfe in ELAN + +Prozeduren + +Prozeduren werden verwendet, wenn + +- Anweisungen und Datenobjekte unter einem Namen zusammengefaßt werden + sollen ("Abstraktion"). + +- gleiche Anweisungen von mehreren Stellen eines Programms verwandt werden + sollen (Codereduktion) u.U. mit verschieden Datenobjekten (Parameter); + +- wenn Datenobjekte nur kurzfristig benötigt werden (dynamische Speicherver- + waltung) und diese nicht von dem gesamten Programm angesprochen werden + sollen (lokale, globale Datenobjekte); + +Im folgenden Programm stellen wir ein Fragment vor, in dem zwei Werte ver- +tauscht werden. In der einen (linken) Lösung wird ein Refinement, in der +anderen eine Prozedur verwandt. + +Programm 19: + + ... PROC vertausche a und b: + IF a > b INT CONST x :: a; + THEN vertausche a und b a := b; + END IF; b := x + ... END PROC vertausche a und b; + vertausche a und b; ... + ... IF a > b + THEN vertausche a und b + vertausche a und b: END IF; + INT CONST x :: a; ... + a := b; vertausche a und b; + b := x. ... + +Beim ersten Hinsehen leisten beide Programme das Gleiche. Es gibt jedoch +drei wichtige Unterschiede: + +1) Das Refinement 'vertausche a und b' wird zweimal (vom ELAN-Compiler) + eingesetzt, d.h. der Code ist zweimal vorhanden. Die Prozedur dagegen ist + vom Code nur einmal vorhanden, wird aber zweimal - durch das Aufführen + des Prozedurnamens - aufgerufen. + +2) Die Variable 'x' ist in der linken Programmversion während des gesamten + Ablauf des Programms vorhanden. Solche Datenobjekte nennt man statische + Datenobjekte oder auch (aus Gründen, die erst etwas später offensichtlich + werden) Paket-Objekte. Das Datenobjekt 'x' der rechten Version dagegen + ist nur während der Bearbeitung der Prozedur vorhanden. Solche Daten- + objekte, die nur kurzfristig Speicher belegen, werden dynamische Daten- + objekte genannt. + + Prozeduren sind also ein Mittel, um die Speicherbelegung zu beeinflussen, + was besonders bei großen Datenobjekten notwendig ist. + +3) 'x' kann in der linken Programmversion - obwohl sie in einem Refinement + deklariert wurde - von jeder Stelle des Programms angesprochen werden. + Solche Datenobjekte werden globale Datenobjekte genannt. Das Datenobjekt + 'x' der Prozedur dagegen kann nur innerhalb der Prozedur angesprochen + werden, sie ist also ein lokales Datenobjekt hinsichtlich der Prozedur. + Innerhalb der Prozedur dürfen globale Datenobjekte (also Objekte, die + außerhalb von Prozeduren deklariert wurden) angesprochen werden. + + Eine Prozedur in ELAN bildet im Gegensatz zu Refinements einen eigenen + Gültigkeitsbereich hinsichtlich Datenobjekten und Refinements, die inner- + halb der Prozedur deklariert werden. Prozeduren sind somit ein Mittel, um + die in ihr deklarierten Datenobjekte hinsichtlich der Ansprechbarkeit + nach Außen "abzuschotten". + +Prozeduren wie die in Programm 19 werden mit dem Schlüsselwort PROC, dem +Namen der Prozedur und einem Doppelpunkt eingeleitet. Dies nennt man den +Prozedurkopf. Der Prozedurkopf entspricht den Definitionen, die wir bereits +in vorigen Abschnitten dieses Skripts gegeben haben. Nach dem Prozedurkopf +folgt der Prozedurrumpf, der Datenobjekt-Deklarationen, Anweisungen und +Refinements enthalten kann. Abgeschlossen wird die Prozedur durch END PROC +und dem Prozedurnamen. + + +Aufgabe (HSG): + + a) Erkläre den Unterschied zwischen einer Prozedur und einem Refinement. + b) Was sind globale bzw. lokale Datenobjekte? +Übungsziel: Begriffe, die mit Prozeduren zusammenhängen + + +Aufgabe (TSW): + + Gegeben sei folgendes Programmfragment: + INT VAR a, b; + ... (*1*) + PROC x: + INT VAR x1; + ... (*2*) + END PROC x; + TEXT VAR t; + PROC y: + REAL VAR y1 + ... (*3*) + END PROC y; + ... (*4*) + + 1.) Welche Objekte (einschließlich Prozeduren) sind an den Punkten + (*1*) : + (*2*) : + (*3*) : + (*4*) : + ansprechbar? + + 2.) Welche Datenobjekte sind in der Prozedur 'y' + global: + lokal: +Übungsziel: Globale und lokale Objekte + + +Prozeduren mit Parametern erlauben es, gleiche Anweisungen mit unterschied- +lichen Datenobjekten auszuführen: + + +Programm 20: + + PROC vertausche (INT VAR a, b): + INT VAR x :: a; + a := b; + b := x + END PROC vertausche; + + INT VAR eins :: 1, + zwei :: 2, + drei :: 3; + vertausche (eins, zwei); + vertausche (zwei, drei); + vertausche (eins, zwei); + put (eins); put (zwei); put (drei) + +Die Datenobjekte 'a' und 'b' der Prozedur 'vertausche' werden formale Para- +meter genannt. Sie stehen als Platzhalter für die bei einem Prozeduraufruf +einzusetzenden aktuellen Parameter (in unserem Beispiel die Datenobjekte +'eins', 'zwei' und 'drei'). + + +Aufgabe (HSG): + + Welche Werte werden in dem Programm 20 ausgedruckt? +Übungsziel: Arbeiten mit Prozeduren und Parameter-Mechanismus. + + +Parameter werden im Prozedurkopf nach dem Prozedurnamen in Klammern mit +Datentyp und Accessrecht angegeben. Dabei bedeutet CONST, daß auf den +Parameter nur lesend zugegriffen wird, während auf einen VAR-Parameter auch +z.B. eine Zuweisung angewandt werden kann. CONST-Parameter sind also +Eingabe-Parameter, während VAR-Parameter Ein-/Ausgabe-Parameter realisieren. + +Bei den aktuellen Parametern ist folgendes zu beachten: + +a) Wird ein VAR-Parameter in der Definition der Prozedur vorgeschrieben (wie + z.B. im Programm 20), darf kein Ausdruck als aktueller Parameter "überge- + ben" werden, weil an einen Ausdruck nichts zugewiesen werden kann. + Gegenbeispiel: + + vertausche ( eins * zwei, drei) + + Ausdrücke haben - wie bereits erwähnt - das Accessrecht CONST. + +b) Wird ein CONST-Parameter verlangt, dann darf in diesem Fall ein Ausdruck + als aktueller Parameter geschrieben werden. Aber auch ein VAR-Datenobjekt + darf angegeben werden. In diesem Fall wird eine Wandlung des Accessrechts + (CONSTing) vorgenommen: der aktuelle Parameter erhält sozusagen für die + Zeit der Abarbeitung der Prozedur das Accessrecht CONST. + +Es ist auch möglich, Prozeduren als Parameter zu definieren, worauf wir aber +hier nicht eingehen wollen. + +Eine Werte liefernde Prozedur erhält man, wenn der Prozedurrumpf einen Wert +liefert, d.h. die letzte ausführbare Anweisung des Prozedurrumpfes muß einen +Wert liefern (analog Werte liefernde Refinements) und der zu liefernde +Datentyp vor den Prozedurkopf geschrieben wird. + + +Programm 21: + + INT PROC max (INT CONST a, b): + IF a > b + THEN a + ELSE b + END IF + END PROC max; + + put (max (3, 4)) + +(In unserem Beispiel liefert die IF-Anweisung einen Wert. Das erfolgt da- +durch, daß beide Zweige der Anweisung einen Wert liefern.) + + + +Neudefinierte Operatoren + +Neue, zusätzliche Operatoren können in ELAN wie Prozeduren definiert werden. +Es ist nur notwendig, bei der Definition das Wort PROC gegen OP zu vertau- +schen. Es sind aber auch nur 1 oder 2 Parameter bei Operatoren erlaubt. + + +Programm 22a: + + TEXT OP * (INT CONST mal, TEXT CONST t): + INT VAR zaehler :: mal; + TEXT VAR ergebnis :: ""; + WHILE zaehler > 0 REP + ergebnis := ergebnis + t; + zaehler := zaehler - 1 + END REP; + ergebnis + END OP *; + +Dieser Operator vervielfältigt TEXTe ( 2 * "ha" liefert "haha"). Der Name +des Operators ist '*'. Man kann als Operatornamen die vorhandenen, bereits +benutzten Sonderzeichen verwenden. In diesem Fall bekommt der neudefinierte +Operator die gleiche Priorität wie der bereits vorhandene oder ein Schlüssel- +wort. + +Der "Aufruf" eines Operators unterscheidet sich von einer Prozedur durch die +infix-Schreibweise. Im übrigen gilt das für Prozeduren Gesagte. + + + +Optimierungen + +Optimierungen werden vorgenommen, wenn man mit den Laufzeiten bzw. Speicher- +bedarf eines Programms nicht zufrieden ist. Kleinere, lokale Optimierungen +sind meist nicht sinnvoll und notwendig und bringen mehr Fehler, als Ver- +besserungen: + + +Programm 22b: + + TEXT OP * (INT CONST mal, TEXT CONST t): + INT VAR i; + TEXT VAR ergebnis :: ""; + FOR i FROM 1 UPTO mal REP + ergebnis CAT t + END REP; + ergebnis + END OP *; + +Wir haben hier die WHILE-Schleife durch eine Zählschleife und 'ergebnis := +ergebnis + t' durch 'ergebnis CAT t' ersetzt. Dies ist nur eine minimale +Optimierung (wenn sie überhaupt etwas einbringt). Leider sind solche +"Optimierungen" sehr häufig anzutreffen. Besser ist es, eine Lösung zu +finden, die algorithmisch oder von den Datenstrukturen her prinzipiell +besser ist. Wir haben dies für das Programm 22 getan. Lösungsidee: jeweilige +Verdopplung eines Zwischentextes ("Russische Multiplikation"). + + +Programm 22c: + + TEXT OP * (INT CONST mal, TEXT CONST t): + INT VAR zaehler :: mal; + TEXT VAR einer :: "", + dopplung :: t; + IF fehlerhafter aufruf + THEN LEAVE * WITH "" + ELSE verdopplung + END IF; + dopplung + einer. + + fehlerhafter aufruf: + zaehler < 1. + + verdopplung: + WHILE zaehler > 1 REP + IF zaehler ist ungerade + THEN einer CAT t + END IF; + dopplung CAT dopplung; + zaehler := zaehler DIV 2 + END REP. + + zaehler ist ungerade: + zaehler MOD 2 = 1. + + END OP *; + + +In diesem Programm wurde eine Anweisung verwendet (LEAVE), die wir im +folgenden Abschnitt erklären wollen. + + + +Das LEAVE-Konstrukt + +Das LEAVE-Konstrukt wird verwendet, um eine benannte Anweisung (Refinement, +Prozedur oder Operator) vorzeitig zu verlassen. Es ist auch möglich, mehr- +fach geschachtelte Refinements zu verlassen. Durch eine (optionale) +WITH-Angabe kann auch ein wertelieferndes Refinement verlassen werden. + + + +Reihungen + +Wir haben bis jetzt bereits zusammengesetzte algorithmische Objekte kennen- +gelernt, die man unter einem Namen als Ganzes ansprechen kann (Prozeduren). +Die gleiche Möglichkeit gibt es auch bei Datenobjekten, wobei wir gleich- +artige oder ungleichartige Objekte zu einem Objekt zusammenfassen können. +Zuerst zu der Zusammenfassung gleichartiger Datenobjekte, die in ELAN eine +Reihung (ROW) genannt wird. Die einzelnen Objekte einer Reihung werden +Elemente genannt. Beispiel (Deklaration einer Reihung von 10 INT-Elementen): + + ROW 10 INT VAR feld + +Die Angabe hinter dem Schlüsselwort ROW muß ein INT-Denoter sein (oder +durch ein LET definierter Name). Dabei ist ROW 10 INT ein (neuer, von den +elementaren unterschiedlicher) Datentyp, für den keine Operationen definiert +sind, außer der Zuweisung. Das Accessrecht (VAR in unserem Beispiel) 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 uns sehr +schnell einsichtig, wenn wir uns vorstellen, 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 +unterschiedliche Operationen definiert. Man müßte nun für jeden dieser +zusammengesetzten 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 vorgegebene Operationen auf zusammengesetzte +Datentypen gibt. + +Zugegebenermaßen könnte man mit solchen Datentypen, die nur über eine Opera- +tion verfügen (Zuweisung), nicht sehr viel anfangen, wenn es nicht eine wei- +tere vorgegebene Operation gäbe, die #ib#Subskription#ie#. Sie erlaubt es, +auf die Elemente einer Reihung zuzugreifen und den Datentyp der Elemente +"aufzudecken". 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 (in unserem Fall '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 über- +all da verwendet werden, wo ein entsprechender Datentyp benötigt wird (Aus- +nahme: Schleifenvariable). Als Beispiel zeigen wir zwei Prozeduren, die eine +Reihung einlesen bzw. ausgeben: + + +Programm 23: + + 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 + + +Wie bereits erwähnt, ist es erlaubt, Reihungen überall dort zu verwenden, wo +auch die elementaren Datentypen verwandt werden können, also auch als +Parameter. Zudem haben wir die generischen Eigenschaften von Prozeduren in +ELAN bei der Benennung der Prozeduren benutzt. + +Diese beiden Prozeduren benutzen wir gleich im nächsten Programm, welches +10 Werte einliest und die Summe berechnet: + + +Programm 24: + + 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). + + +Aufgabe (HSG): + + Wie kann man vermeiden, daß 'summe > maxint' ("overflow"-Bedingung) + wird? + + +Oft benötigt man die Werte einer Reihung sortiert. Das Programm 25 zeigt +einen (sehr dummen und ineffizienten) Sortieralgorithmus: + + +Programm 25: + + ROW 10 INT VAR wert; + lies die werte ein; + sortiere in eine zweite liste; + drucke die zweite liste. + + lies die werte ein: + get (wert). + + sortiere in eine zweite liste: + INT VAR i; + FOR i FROM 1 UPTO 10 REP + suche kleinstes element aus der werte liste; + bringe dieses in die zweite liste; + entferne es aus der werte liste + END REP. + + suche kleinstes element aus der werte liste: + INT VAR kleinstes element :: maxint, position kleinstes element :: 0, k; + FOR k FROM 1 UPTO 10 REP + IF wert [k] < kleinstes element + THEN kleinstes element := wert [k]; + position kleinstes element := k + END IF + END REP. + + bringe dieses in die zweite liste: + ROW 10 INT VAR liste2; + liste2 [i] := kleinstes element. + + entferne es aus der werte liste: + wert [position kleinstes element] := maxint. + + drucke die zweite liste: + put (liste2). + +Anmerkung: Bei diesem einfachen Sortieralgorithmus (der übrigens "lineare +Auswahl" heißt), wurde der Wert 'maxint' als zulässiger Wert ausgeschlossen. +Der Algorithmus ist ziemlich der schlechteste, den wir uns ausdenken können. +Einmal braucht er den doppelten Speicherplatz für die zu sortierende Liste, +andererseits sind für N Werte N*N Durchläufe durch die Liste notwendig (man +sagt, der Algorithmus ist von der Ordnung N Quadrat). + +Da es möglich ist, von jedem Datentyp eine Reihung zu bilden, kann man +natürlich auch von einer Reihung eine Reihung bilden: + + 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 zuzu- +greifen: + + matrix [3] + +liefert ein Datenobjekt mit dem Datentyp ROW 10 INT, für den wir bereits in +Programm 23 die Prozeduren 'get' und 'put' geschrieben haben, die wir +verwenden können: + + get (matrix [4]) + +Subskribieren wir jedoch 'matrix' nochmals, so erhalten wir ein INT: + + matrix [2] [8] + +(jede Subskription "schält" von Außen ein ROW vom Datentyp ab). + + +Aufgabe (HSG): + + a) Geben Sie Datentyp, Accessrecht und Name der folgenden Datenobjekte + an: + ROW 17 INT CONST alpha; + ROW 3 ROW 4 TEXT VAR matrix; + ... + beta [3] := 7; + gamma [4] := gamma [5] + + b) Was führt zu Fehlern? Wenn ja, warum? + ROW 17 INT VAR alpha; + ROW 3 ROW 4 TEXT VAR beta, gamma; + ROW 4 ROW 3 TEXT CONST delta; + INT VAR x :: 7; + ROW x BOOL VAR y; + get (alpha); + get (beta [7]); + FOR x FROM 1 UPTO 3 REP + get (beta [x]) + END REP; + beta := delta; + delta [1] [2] := "mist"; + beta := gamma; + beta [3] := gamma [3]; + get (beta [1] [1]); + gamma [1] [5] := beta [1] [1] + "ELAN" + x := alpha [3]; + x := 20; + alpha [x] := alpha [3] + 7 +Übungsziel: Umgang mit Reihungen + + + +Strukturen + +Strukturen sind Datenverbunde wie Reihungen, aber die Komponenten können +ungleichartige Datentypen haben. Die Komponenten von Strukturen heißen +Felder (bei Reihungen: 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ß. +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: + + 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: + + STRUCT (TEXT produkt name, INT artikel nr) VAR erzeugnis + +ist ein anderer Datentyp als im ersten Beispiel dieses Abschnitts. Für +Strukturen - genauso wie bei Reihungen - kann man sich neue Operationen +definieren. Im folgenden Programm definieren wir für eine Struktur, die +Personen beschreibt, die Operationen 'put', 'get' und den dyadischen +Operator HEIRATET. Anschließend werden drei Paare verHEIRATET. + + +Programm 26a: + + 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; + + 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 Reihenfolge vorzunehmen, wie die Datentypen aufgebaut wurden (von +außen nach innen). + + +Aufgabe (HSG): + + In ELAN heissen + a1) Datenverbunde gleichartiger Komponenten: + a2) Datenverbunde ungleichartiger Komponenten: + b1) die Komponenten eines ROWs: + b2) die Komponenten eines STRUCTs: + c1) die Zugriffe auf die Komponenten eines ROWs: + c2) die Zugriffe auf die Komponenten eines STRUCTs: +Übungsziel: Begriffe von ROWs und STRUCTs kennenlernen + + + +LET-Konstrukt + +Wie wir in Programm 26 gesehen haben, ist die Verwendung von Strukturen +oder auch Reihungen manchmal schreibaufwendig. Mit dem LET-Konstrukt darf +man Datentypen (und Denotern) 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. Beispiel: + + +Programm 26b: + + 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 werden kann, kann 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 wir +etwas später erklären, nicht mehr der Fall ist). + +Neben der Funktion der Abkürzung von Datentypen kann das LET-Konstrukt +auch für die Namensgebung für die Denoter verwandt werden. Beispiele: + + LET pi = 3.14159; + LET blank = " "; + LET anzahl = 27 + +Der Einsatz von LET-Namen für INT-Denoter macht es möglich, Programme +leicht zu ändern: + + +Programm 26c: + + LET anzahl paare = 3; + ROW anzahl paare PERSON VAR frau, mann; + + personendaten einlesen; + heiraten lassen; + paardaten ausgeben. + + personendaten einlesen: + INT VAR i; + FOR i FROM 1 UPTO anzahl paare REP + get (frau [i]); + get (mann [i]) + END REP. + ... + +Ebenso wie die Abkürzung von Datentypen (LET PERSON = STRUCT (...)) wird +im obigen Beispiel für den Namen 'anzahl paare' bei jedem Auftreten der +Denoter '3' vom ELAN-Compiler eingesetzt. Um nun (z.B.) 27 Paare "heiraten" +zu lassen, brauchen wir nur die LET-Anweisung in '27' zu verändern... +(Scheidungen erfordern etwas mehr Aufwand). + + +Aufgabe (HSG): + + Was ist falsch? + LET anz = 5, + max = 5*5, + MAT = ROW anz ROW anz TEXT; + + PROC get (MAT CONST m): + FOR i FROM 1 UPTO max REP + get (m [i]) + END REP + END PROC get; + + MAT VAR x,y; + get (x); + x := y + 1 + + +Aufgabe (HSG): + + Schreibe ein Programm, das mit den Deklarationen + LET anz = 5, + VEC = ROW anz INT, + MAT = ROW anz VEC; + folgende Prozeduren realisiert: + PROC get (VEC VAR v) + PROC get (MAT VAR m) + PROC put (VEC CONST v) + PROC put (MAT CONST m) + INT PROC reihensumme (VEC CONST v) +Übungsziel: Reihungen als Parameter + + + +Denoter für Datenverbunde: Konstruktoren + +Denoter für die elementaren Datentypen haben wir kennengelernt. Oft ergibt +sich auch die Notwendigkeit (z.B. bei Initialisierungen), Datenverbunde in +einem Programm Werte zu geben. Das 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 + +Aber man möchte auch Denoter für Datenverbunde z.B. in Ausdrücken verwenden, +was durch die Konstruktoren ermöglicht wird. 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 Datenver- +bundes in einem Programm zu notieren. Ein Konstruktor besteht aus der Angabe +des Datentyps (der auch durch einen LET-Namen abgekürzt sein darf), einem +Doppelpunkt und den in Klammern eingefaßten Komponenten (hier Denoter). +Besteht eine der Komponenten wiederum aus einem Datenverbund, muß inner- +halb des Konstruktors wiederum ein Konstruktor eingesetzt werden usw. Kon- +struktoren sind natürlich für Reihungen auch möglich: + + ROW 7 INT VAR feld; + feld := ROW 7 INT : ( 1, 2, 3, 4, 5, 6, 7); + + +Aufgabe (HSG): + + Geben Sie Datentyp, Accessrecht und Name der folgenden Datenobjekte an: + STRUCT (INT alter, TEXT name) VAR mensch; + STRUCT (INT jahrgang, ROW 2 TEXT lage) CONST wein; + ROW 100 STRUCT (PERSON p, NUMMER n) VAR betriebsangehoeriger; + STRUCT (INT anz terminals, STRUCT (TEXT systemname, INT version) art) + CONST betriebsystem; + mensch := ...; + betriebsangehoeriger [2] := ...; + betriebsangehoeriger [2]. n := NUMMER: (...); + betriebsystem.art.systemname := "EUMEL"; + wein.lage := ROW 2 TEXT: ("Loire", "Frankreich"); + wein.lage [1] := "Kroever Nacktarsch"; +Übungsziel: Umgang mit Strukturen. + + + +Rekursive Prozeduren und Operatoren + +Alle Prozeduren und Operatoren dürfen in ELAN rekursiv sein. + + +Programm 27: + + INT PROC fakultaet (INT CONST n): + IF n > 0 + THEN fakultaet (n-1) * n + ELSE 1 + END IF + END PROC fakultaet + +Dieses Beispiel ist aber (leider) kein gutes Beispiel für eine Rekursion, +denn das Programm kann leicht in eine iterative Version umgewandelt werden: + + +Programm 28: + + INT PROC fakultaet (INT CONST n): + INT VAR prod :: 1, i; + FOR i FROM 2 UPTO n REP + prod := prod * i + END REP; + prod + END PROC fakultaet + +Die Umwandlung von einem rekursiven Programm in ein iteratives ist übrigens +immer möglich, jedoch oft nicht so einfach wie in diesem Fall. Beispiel +(Ackermann-Funktion): + + +Programm 29: + + INT PROC acker (INT CONST m, n): + IF m = 0 + THEN n + 1 + ELIF n = 0 + THEN acker (m-1, 0) + ELSE acker (m - 1, acker (m, n - 1)) + ENDIF + END PROC acker + + +Aufgabe (HSG): + + a) Beschreibe die Unterschiede zwischen Iteration und Rekursion. Worauf + muß man bei Rekursionen achten? + b) Wie groß ist der Wert von 'acker (2, 2)'? Hilfreicher Tip: stelle + dabei eine Tabelle auf! + c) Zudem enthält die Programmierung der Ackermann-Funktion (mindestens) + einen Fehler. Welchen? +Übungsziel: Umgang mit Rekursion + + +Das eigentliche Einsatzgebiet von rekursiven Algorithmen liegt aber bei den +'backtrack'-Verfahren. Diese werden eingesetzt, wenn eine exakte algorithmi- +sche Lösung nicht bekannt ist oder nicht gefunden werden kann und man ver- +schiedene Versuche machen muß, um zu einem Ziel (oder Lösung) zu gelangen. + +Als Beispielprogramm zeigen wir das Spiel "Maus sucht Käse". In einem Laby- +rinth (realisiert durch eine Reihung von einer Reihung), das mit Hindernis- +sen bestückt ist, wurde ein Käse versteckt. Eine sehr dumme Maus sucht +systematisch die umliegenden Felder (in allen vier Himmelsrichtungen) nach +dem Käse ab. Ist sie auf einem neuen Feld und ist das Feld frei, sucht sie +erneut. Felder, auf denen sie bereits war, werden von ihr markiert. Da die +Maus sehr kurzsichtig ist und nicht richtig riechen kann, bemerkt sie den +Käse erst, wenn sie sozusagen mit allen vier Pfoten in ihm gelandet ist +(analog bei Hindernissen, die nicht überklettert werden können). Damit die +Maus nicht aus dem Labyrinth entfliehen kann, wird der Rand als Hindernis +angesehen. + + +(Teil-) Programm 30: + + PROC suche weg (INT CONST x, y): + IF labyrinth [x] [y] = kaese + THEN kaese gefunden + ELIF labyrinth [x] [y] = frei + THEN suche weiter + END IF. + + suche weiter: + labyrinth [x] [y] := markiert; + INT VAR richtung; + FOR richtung FROM osten UPTO sueden REP + versuche diese richtung + END REP; + labyrinth [x] [y] := frei. + + versuche diese richtung: + IF richtung = osten + THEN suche weg (x + 1, y) + ELIF richtung = norden + THEN suche weg (x, y + 1) + ... + + + +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 Massenspei- +chern aufbewahrt wird. Dateien sind in bestimmten Informationsmengen, den +Sätzen ("records") organisiert. + +In ELAN gibt es zwei Arten von Dateien: + +a) FILE: sequentielle Dateien. Die Sätze können nur sequentiell gelesen bzw. + geschrieben werden. Eine Positionierung ist nur zum nächsten Satz möglich. +b) DIRFILE: indexsequentielle Dateien. Die Positionierung erfolgt direkt mit + Hilfe eines Schlüssels ("key") oder Index, kann aber auch sequentiell + vorgenommen werden. + + Wichtig: + DIRFILEs sind auf dem EUMEL-System nicht implementiert! Deswegen wird + auf diesen Dateityp hier nicht weiter eingegangen. + +Dateien werden normalerweise von dem #ib#Betriebsystem#ie# 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 Betriebsystem notwendig. Dies erfolgt durch +sogenannte Assoziierungsprozeduren. Beispiele: + + FILE VAR meine datei :: sequential file (output, "xyz"); + FILE CONST eine andere datei :: sequential file (input, "abc") + +Die Assoziierungsprozedur heißt 'sequential file' für FILEs. Der erste +Parameter einer Assoziierungsprozedur gibt immer die sogenannte Betriebs- +richtung ("TRANSPUTDIRECTION") an. Es gibt folgende Betriebsrichtungen: + + input nur Lesen der Datei + output nur Schreiben der Datei + + Anmerkung: + Im EUMEL-System gibt es noch die Betriebsrichtung 'modify', die es er- + laubt, beliebig zu positionieren, Sätze zu löschen und/oder einzufügen + usw. Dafür gibt es keine DIRFILEs. Siehe dazu auch das Kapitel über + Dateien in diesem Benutzerhandbuch. + +Der zweite Parameter einer Assoziierungsprozedur gibt an, unter welchem +Namen die Datei in dem Betriebsystem bekannt ist. Mit Hilfe dieses Namens +wird die Datei an das Datenobjekt gekoppelt, das bei der FILE-Deklaration im +Programm erzeugt wurde. + +Welche Operationen sind nun für Dateien zugelassen? Wir beschreiben die +wichtigsten für die beiden Dateiarten und Betriebsrichtungen getrennt: + +a) FILE mit 'input' (nur lesen): + + PROC getline (FILE CONST f, TEXT VAR zeile) + PROC get (FILE CONST f, TEXT VAR t) + PROC get (FILE CONST f, REAL VAR r) + PROC get (FILE CONST f, INT VAR i) + BOOL PROC eof (FILE CONST f) + (* Abfrageprozedur auf das Ende eines FILEs (letzter Satz) *) + + Als Beispiel zeigen wir ein Programm, welches eine Datei liest und auf + dem Ausgabemedium ausgibt. + + + Programm 31: + + FILE CONST f :: sequential file (input, "datei1"); + TEXT VAR satz; + WHILE NOT eof (f) REP + getline (f, satz); + put (satz); line + END REP. + +b) FILE mit 'output' (nur schreiben): + + PROC putline (FILE VAR f, TEXT CONST zeile) + PROC put (FILE VAR f, TEXT CONST t) + PROC put (FILE VAR f, REAL CONST r) + PROC put (FILE VAR f, INT CONST i) + PROC line (FILE VAR f, INT CONST zeilenzahl) + + +Aufgabe (HSG): + + a) Das Arbeiten mit Dateien ist manchmal notwendig, weil ... + b) Wenn man mit Dateien in ELAN arbeitet, sind Assoziierungsprozeduren + notwendig. + b1) Wie heißen diese? + b2) Was gibt man in diesen an? + c) Welche Betriebsrichtungen gibt es bei FILES und was bewirken sie? +Übungsziel: Datei-Begriffe + + +Aufgabe (TSW): + + Welche Fehler befinden sich in den folgenden Programmfragmenten? + a) FILE VAR f :: sequential file (input, "MIST"); + TEXT VAR zeile; + REP + getline (f, zeile); + ... + UNTIL eof (f) END REP + + b) FILE VAR f :: sequential file (output, "NOCHMAL"); + TEXT VAR zeile; + REP + getline (f, zeile); + put (zeile) + UNTIL eof (f) END REP + + c) FILE VAR f :: sequential file (input, "VERDAMMT"), + g :: sequential file (input, "DAEMLICH"); + TEXT VAR zeile; + kopiere g in f. + + kopiere g in f: + FOR i FROM 1 UPTO 100 REP + getline (g, zeile); + putline (f, zeile) + UNTIL eof (g) END REP. +Übungsziel: Arbeiten mit Dateien + + + +Programmstruktur 1 + +Bis jetzt haben wir noch nicht vollständig erklärt, wie ein ELAN-Programm +formal als Ganzes aufgebaut sein muß, d.h. wie und in welcher Reihenfolge +die Anweisungen, Refinements, Prozeduren und Deklarationen geschrieben +werden müssen. + +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. In diesem Abschnitt wollen wir uns nur mit dem Aufbau eines +solchen PACKETs beschäftigen. Wir werden dabei nicht alle Möglichkeiten +besprechen, sondern nur die wichtigsten Anwendungen beschreiben, mit einer +Empfehlung, in welcher Reihenfolge die Elemente geschrieben werden sollten. + +Ein "main packet" kann aus folgenden Elementen bestehen: + +a) Deklarationen und Anweisungen. Diese müssen nicht in einer bestimmten + Reihenfolge 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 Programmierpraxis, die meisten Deklarationen an den + Anfang eines Programms (außer z.B. Datenobjekte, die nur lokal oder + kurzfristig benötigt werden, wie Hilfsvariablen oder Laufvariablen) zu + plazieren. + + <Deklarationen> ; + <Anweisungen> + +b) Deklarationen, Refinements und Anweisungen. In diesem Fall ist es notwen- + dig, die Refinements hintereinander zu plazieren. Refinement-Aufrufe + und/oder Anweisungen sollten textuell vorher erscheinen. Die Refinements + werden durch einen Punkt von den Aufrufen getrennt: + + <Deklarationen> ; + <Refinement-Aufrufe und/oder Anweisungen> . + <Refinements> + + Innerhalb der Refinements sind Anweisungen und/oder Deklarationen möglich. + +c) Deklarationen, Prozeduren und Anweisungen. Werden Prozeduren vereinbart, + sollte man sie nach den Deklarationen plazieren. Danach sollten die + Anweisungen folgen: + + <Deklarationen> ; + <Prozeduren> ; + <Anweisungen> + + Mehrere (parallele) 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 wiederum 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. + +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: + + <Deklarationen> ; + <Prozeduren> ; + <Anweisungen> . + <Refinements> + + 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 Refinements). In PACKET-Refinements dürfen natürlich keine + Datenobjekte verwandt werden, die lokal zu einer Prozedur sind. + + + +Moduln (PACKETs) + +PACKETs sind in ELAN eine Zusammenfassung von Datenobjekten, Prozeduren/ +Operatoren und Datentypen. Man kann sich ein PACKET als ein 'main packet' +mit Zusätzen vorstellen. PACKETs können separat übersetzt werden, so +daß der "Zusammenbau" eines umfangreichen Programms aus mehreren PACKETs +möglich ist. + +Elemente eines PACKETs (Prozeduren/Operatoren, Datentypen) können außerhalb +des PACKETs nur angesprochen werden, wenn sie in der Schnittstelle des +PACKETs, die auch "interface" genannt wird, aufgeführt wird. Mit anderen +Worten: es können alle Elemente eines PACKETs von außen nicht angesprochen +werden, sofern sie nicht über die Schnittstelle "nach außen gereicht" wird. +Damit wird gewährleistet, daß mehrere Programmierer an einem gemeinsamen +Projekt arbeiten können und daß eine gemeinsame Benutzung (oder Störung) von +Programmteilen nur über die in den Schnittstellen von PACKETs aufgeführten +Objekte erfolgen kann. + +Im Gegensatz zu einer Prozedur kann ein PACKET nicht aufgerufen werden (nur +die Elemente der Schnittstelle können benutzt werden). Beispiel: + + +Programm 32: + + PACKET fuer eine prozedur DEFINES swap: + + PROC swap (INT VAR a, b): + INT CONST x :: a; + b := a; + a := x + END PROC swap + + END PACKET fuer eine prozedur + +Dies ist ein PACKET, das eine Tausch-Prozedur für INT-Datenobjekte bereit- +stellt. Das PACKET kann übersetzt werden und dem ELAN-Compiler bekannt +gemacht werden (EUMEL: "insertieren"). Ist das geschehen, kann man 'swap' +wie alle anderen Prozeduren (z.B. 'put', 'get') in einem Programm verwenden. +Tatsächlich werden die meisten Prozeduren und Operatoren (aber auch einige +Datentypen), die in ELAN zur Verfügung stehen, nicht durch den ELAN-Compiler +realisiert, sondern durch solche PACKETs. Um solche Objekte einigermaßen +zu standardisieren, wurde in der ELAN-Sprachbeschreibung festgelegt, welche +Datentypen, Prozeduren und Operatoren in jedem ELAN-System vorhanden +sein müssen. Solche PACKETs werden Standard-Pakete genannt. Jeder Installa- +tion - aber auch jedem Benutzer - steht es jedoch frei, zu den Standard- +Paketen zusätzliche PACKETs mit in den Compiler aufzunehmen und damit den +ELAN-Sprachumfang zu erweitern. + +Ein ELAN-PACKET beginnt mit dem PACKET-Schlüsselwort. Danach folgt der Name +des PACKETs (der am Ende des PACKETs hinter END PACKET wieder erscheinen +muß), gefolgt von der DEFINES-Liste. In dieser Schnittstelle werden die Ob- +jekte angegeben, die nachfolgenden PACKETs zur Verfügung gestellt werden +sollen. + +In der Schnittstelle werden Prozeduren/Operatoren nur mit ihrem Namen ange- +geben. Weiterhin können Datentypen und mit CONST vereinbarte Datenobjekte +in der Schnittstelle aufgeführt werden, aber keine VAR-Datenobjekte, weil +diese sonst über PACKET-Grenzen hinweg verändert werden könnten. + +Im obigen Programm 32 haben wir ein PACKET in der Funktion als spracher- +weiterndes Instrument gezeigt. Im folgenden Beispiel zeigen wir ein Programm, +in dem das PACKET-Konzept verwandt wird, um Datenobjekte vor unbefugten +Zugriff zu schützen. + + +Programm 33: + + PACKET stack handling DEFINES push, pop, init stack: + + LET max = 1000; + ROW max INT VAR stack; + INT VAR stack pointer; + + PROC init stack: + stack pointer := 0 + END PROC init stack; + + PROC push (INT CONST dazu wert): + stack pointer INCR 1; + IF stack pointer > max + THEN errorstop ("stack overflow") + ELSE stack [stack pointer] := dazu wert + END IF + END PROC push; + + PROC pop (INT VAR von wert): + IF stack pointer = 0 + THEN errorstop ("stack empty") + ELSE von wert := stack [stack pointer]; + stack pointer DECR 1 + END IF + END PROC pop + + END PACKET stack handling; + +Nun kann man den Stack über die Prozeduren 'init stack', 'push' und 'pop' +benutzen (in einem 'main packet'). + + +Programm 34: + + init stack; + werte einlesen und pushen; + werte poppen und ausgeben. + + werte einlesen und pushen: + INT VAR anzahl :: 0, wert; + REP + get (wert); + push (wert); + anzahl INCR 1 + UNTIL ende kriterium END REP. + + werte poppen und ausgeben: + INT VAR i; + FOR i FROM 1 UPTO anzahl REP + pop (wert); + put (wert) + END REP. + +Die Datenobjekte 'stack' und 'stack pointer' haben nur Gültigkeit innerhalb +des PACKETs 'stack handling'. Anweisungen wie z.B. + + put (stack [3]); + stack [27] := 5 + +außerhalb des PACKETs 'stack handling' sind also verboten und werden vom +ELAN-Compiler entdeckt. + +Ein PACKET bietet also auch einen gewissen Schutz vor fehlerhafter Verwen- +dung von Programmen und Datenobjekten. Wichtig ist weiterhin, daß die Reali- +sierung des Stacks ohne weiteres geändert werden kann, ohne daß Benutzer- +programme im 'main packet' geändert werden müssen, sofern die Schnittstelle +nicht verändert wird. Beispielsweise kann man sich entschließen, den Stack +nicht durch eine Reihung, sondern durch eine gekettete Liste zu realisieren. +Davon bleibt ein Benutzerprogramm unberührt. + +Die letzte Funktion von PACKETs ist die Realisierung von abstrakten Daten- +typen. Dazu müssen wir uns aber zuvor die Möglichkeiten anschauen, neue +Datentypen zu definieren. + + + +Die Definition neuer Datentypen + +Im Gegensatz zur LET-Vereinbarung, bei der lediglich ein neuer Name für +einen bereits vorhandenen Datentyp eingeführt wurde 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- +Vereinbarung ein gänzlich neuer Datentyp eingeführt. Im Gegensatz zu +Strukturen und Reihungen stehen für solche Datentypen noch nicht einmal die +Zuweisung zur Verfügung. Beispiel: + + TYPE PERSON = STRUCT (TEXT name, vorname, INT alter) + +Ein solcher Datentyp kann wie auch alle anderen Datentypen verwandt werden +(Deklarationen, Parameter, Werte liefernde Prozeduren, als Komponenten in +Reihungen und Strukturen usw.). + +Der neudefinierte Datentyp wird abstrakter Datentyp genannt. Er kann mit +Hilfe eines PACKETs (vergl. nächsten Abschnitt) anderen Programmteilen zur +Verfügung gestellt werden. Die rechte Seite der TYPE-Vereinbarung wird +"konkreter Typ", "Realisierung des Datentyps" oder Feinstruktur genannt. + +Um neue Operatoren und/oder Prozeduren für einen abstrakten Datentyp zu +schreiben, 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 abstrakten Typ zum Datentyp der Feinstruktur. +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 Struk- +turen, dann wird durch eine Selektion oder Subskription eine implizite Kon- +kretisierung vorgenommen. Beispiel: + + TYPE LISTE = ROW 100 INT; + + LISTE VAR personal nummer; + ... + personal nummer [3] := ... + (* das gleiche wie *) + CONCR (personal nummer) [3] := ... + +Denoter für neudefinierte Datentypen werden mit Hilfe des Konstruktors +gebildet: + + TYPE GEHALT = INT; + + GEHALT VAR meins :: GEHALT : (1 000 000); + +Besteht die Feinstruktur aus einem Datenverbund, muß der Konstruktor u.U. +mehrfach geschachtelt angewandt werden: + + TYPE KOMPLEX = ROW 2 REAL; + + KOMPLEX CONST x :: KOMPLEX : ( ROW 2 REAL : ( 1.0, 2.0)); + + + +Abstrakte Datentypen + +Auf die Feinstruktur über den Konkretisierer eines neudefinierten Datentyps +darf nur in dem PACKET zugegriffen werden, in dem der Datentyp definiert +wurde. Der Konstruktor kann ebenfalls nur in dem typdefinierenden PACKET +verwandt werden. + +Wird der Datentyp über die Schnittstelle des PACKETs anderen Programmteilen +zur Benutzung zur Verfügung gestellt, so müssen Operatoren und/oder Proze- +duren für den Datentyp ebenfalls "herausgereicht" werden. Da dann der neude- +finierte Datentyp genauso wie alle anderen Datentypen verwandt werden kann, +aber die Komponenten 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ßerhalb des definierenden PACKETs zur Verfügung steht) + + +Programm 35: + + 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: + + 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). + + +Aufgabe (HSG): + + Was ist ein Modul? Was ist ein Interface? Was ist der Unterschied + zwischen einem PACKET und einer Prozedur? + Die Realisierung von WIDERSTAND durch INTs ist nicht in allen Fällen + befriedigend. Warum? (Beachte besonders die Realisierung des OP + PARALLEL). + Wenn man bei der Typ-Vereinbarung von WIDERSTAND INT gegen REAL + austauschen würde, wo müßte man noch Änderungen vornehmen? Sind + insbesondere Änderungen im Benutzer-Programm (hier im 'main packet') + notwendig? +Übungsziel: PACKET-Begriff + + + +Programmstruktur 2 + +Nun können wir auch erklären, wie ein ELAN-Programm mit mehreren PACKETs +aussieht. Ein Programm besteht aus einer Folge von PACKETs, dem ein 'main +packet' folgt. Es ist auch möglich, PACKETs vorübersetzen zu lassen, so daß +es für einen Nutzer so aussieht, als ob er nur ein 'main packet' übersetzen +läßt. Tatsächlich sind zumindest die Standard-Packets vorübersetzt vorhanden. + + diff --git a/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil7 b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil7 new file mode 100644 index 0000000..1aadc5f --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil7 @@ -0,0 +1,2469 @@ + EUMEL-Benutzerhandbuch + + TEIL 7: Dateien, Datei-Verwaltung und Datenräume + +1. Übersicht + +Dateien dienen zur Aufnahme von Informationen, die auch über die Bearbei- +tungszeit eines Programms erhalten bleiben (können). Dateien werden als +Objekte in einer Task gehalten. Sie bleiben solange erhalten, bis sie expli- +zit gelöscht ('forget'-Kommando) oder die Task beendet wird ('end'-Kommando). + +Dateien kann man an andere Tasks schicken ('save'-Kommando) oder von anderen +Tasks holen ('fetch'-Kommando). Mit diesen (hier vorgestellten) Kommandos +ist der Transport von Dateien jedoch nur in direkter Linie des Task-Baums +möglich, also an einen "Vater" oder einen "Sohn". Damit ist automatisch eine +Datei-Hierarchie im EUMEL-System realisiert. + +Alle Datei-Arten des EUMEL-Systems basieren auf Datenräumen. Ein Datenraum +ist ein Speicherplatz, der 1 MByte Daten speichern kann und vom EUMEL-System +verwaltet wird. Datenräume können gelöscht, kopiert usw. werden. Mit Hilfe +Mit Hilfe von Datenräumen werden alle Datei-Arten des EUMEL-Systems reali- +siert, indem einem Datenraum eine Struktur (Datentyp) aufgeprägt wird. Da- +durch wird es Benutzern des EUMEL-Systems ermöglicht, auf einfache Weise +neben den bereits vorhandenen Datei-Arten (FILEs für die Speicherung von +Texten, PICFILEs für die Speicherung von Bildinformationen, u.a.m.) +spezielle Dateien zu konstruieren. + +Die wichtigste Datei-Art, mit der ein Benutzer in Berührung kommt, ist die +sequentielle Datei, genannt FILE. Ein FILE kann nur TEXTe aufnehmen und hat +z.Zt. ein Fassungsvermögen von 4000 Zeilen (Sätze). Insgesamt darf ein FILE +1 MByte aufnehmen. Eine Datei-Zeile (Satz) kann bis zu 32 000 Zeichen auf- +nehmen. + +FILEs können in einer von drei Betriebsrichtungen bearbeitet werden: +- "input": nur Lesen. +- "output": nur Schreiben. +- "modify": Lesen/Schreiben und zusätzlich beliebiges Positionieren, Ein- + fügen und Löschen von Sätzen. + +'input'-Dateien sind also Eingabedateien, 'output'- sind Ausgabedateien und +'modify'-Dateien kann man verändern. Insbesondere die 'modify'-Dateien eig- +nen sich, um andere Datei-Arten leicht zu realisieren (z.B. indexsequentiel- +le Dateien). + +Eine Datei kann auf einen bestimmten Zeilenbereich eingeschränkt werden. Ein +solches Segment kann selbst wie eine Datei von einem Programm behandelt +werden. + + + +2. Datei-Kommandos + +Dateien werden in der Regel in einer Benutzer-Task gehalten. Die Kommandos +für die Behandlung von Dateien in einer Benutzer-Task werden hier vorge- +stellt. Dann wird erklärt, wie Dateien zu einer übergeordneten Task ge- +schickt oder geholt werden können. + + + +Datei-Kommandos für Benutzer-Tasks + +Im Monitor-Dialog kann man Dateien kopieren, löschen und einen anderen Namen +geben. + +Mit dem Kommando + + edit ("dateiname") + +wird eine Text-Datei im Monitor-Dialog (implizit) eingerichtet, wenn es sich +um einen noch nicht vorhandenen 'dateiname' handelt (vergl. auch die Editor- +Beschreibung). + +Welche Dateien in der Benutzer-Task vorhanden sind, kann mit dem Kommando + + list + +erfragt werden. 'list' zeigt auf dem Bildschirm die Dateinamen der Benutzer- +Task. Vor jedem Namen steht ein Datum, welches anzeigt, an welchem Tag die +Datei zuletzt von einem Programm bearbeitet wurde. Ein 'a' hinter dem Datum +kennzeichnet Dateien, die nach einer Archivierung nicht bearbeitet wurden. + +Ein Duplizieren einer Datei kann mit + + copy ("alte datei", "neue datei") + +erreicht werden, wobei eine Kopie von 'alter datei' angelegt wird, die den +Namen 'neue datei' erhält. Man beachte, daß es sich um eine logische (und +vorerst um keine physikalische) Kopie handelt. Erst bei Schreibzugriffen +werden Seiten " entshared" ("copy-on-write"). Ein Umbenennen einer Datei +kann mit + + rename ("alter datei name", "neuer datei name") + +erfolgen. Mit + + forget ("dateiname") + +kann eine Datei gelöscht werden. + +Wurde in einer Datei editiert, kann durch Löschen oder Einfügen von Zeilen +der interne Verwaltungsaufwand hoch werden, so daß Positionierungen nicht +mehr effizient vor sich gehen. Mit dem Kommando + + reorganize ("dateiname") + +wird die Datei so organisiert, als wenn sie neu erstellt wäre (gilt nur für +Text-Dateien). Sie braucht dann in der Regel auch etwas weniger Speicher- +platz. + + +Merke: Das Kommando 'rename' gibt einer Datei einen anderen Namen, 'copy' +dupliziert eine Datei. Mit 'list' kann man sich anzeigen lassen, welche +Dateien in der Task vorhanden sind. + + + +Datei-Kommandos für Vater-Tasks + +Man kann Dateien von einer Vater-Task holen oder an eine Vater-Task schicken, +um sie dort längerfristig zu speichern. Auch wenn die Benutzer-Task gelöscht +wird, bleiben alle Dateien, die bei einer Vater-Task gespeichert (also +"gerettet") sind, erhalten. Andere Sohn-Tasks können sich Dateien bei einer +Vater-Task abholen. + +Auf Dateien einer Benutzer-Task können andere Nutzer aus anderen Tasks in +der Regel nicht zugreifen. Manchmal ist es jedoch notwendig, daß mehrere +Nutzer Dateien gemeinsam benutzen oder eine Datei eine Task "überleben" soll. +In solchen Fällen muß man Dateien bei einem Vater aufbewahren. + +Mit der Prozedur + + global manager + +kann die Benutzer-Task zu einem Datei-Manager gemacht werden. Erst nach +Aufruf dieser Prozedur können Söhne dieser Task eingerichtet werden. + +Von einer Benutzer-Task kann eine Datei mit + + save ("Buch 1") + +der direkten Vater-Task übergeben werden, wobei 'buch 1' in der Benutzer- +Task erhalten bleibt. 'save' wirkt also wie ein Transport einer Kopie der +angegebenen Datei in die Vater-Task. Achtung: ist eine Datei 'Buch 1' in der +Vater-Task bereits vorhanden, wird diese ohne Warnung überschrieben. + +Analog zu der 'forget'-Prozedur für Dateien einer Benutzer-Task können +Dateien einer unmittelbaren Vater-Task mit + + erase ("datei name") + +gelöscht werden. Soll eine Datei von einer Vater-Task in eine Benutzer-Task +geholt werden, so benutzt man die Prozedur + + fetch ("datei") + +Nach Aufruf dieser Prozedur wird eine Kopie der angegebenen Datei in der +Benutzer-Task angelegt. Ist bereits eine Datei 'datei' in der Benutzer-Task +vorhanden, so erfolgt eine Fehlermeldung. + +Mit 'save', 'fetch' und 'erase' ist es möglich, daß zwei oder mehr Benutzer +eine Datei alternierend bearbeiten. In diesem Fall müssen sich die Benutzer +als Söhne einer gemeinsamen Vater-Task einrichten und die Datei mit 'fetch' +jeweils in die Benutzer-Task holen. Um zu verhindern, daß ein anderer Be- +nutzer zur gleichen Zeit mit der Datei arbeitet, wird sie jeweils mit 'erase' +bei der Vater-Task gelöscht. Nach Beendigung der Arbeiten muß die Datei dann +wieder mit 'save' in die Vater-Task transportiert werden. Dann steht sie +wieder anderen Benutzern zur Verarbeitung zur Verfügung. Beispiel: + + fetch ("datei"); erase ("datei"); (* Datei vom Vater holen und dort + loeschen *) + edit ("datei"); (* Datei bearbeiten *) + save ("datei"); (* Datei zur Vater-Task bringen *) + forget ("datei") (* Datei in Benutzer-Task + loeschen *) + +Mit den Prozeduren + + save all + fetch all + +kann man alle Dateien einer Benutzer-Task in die direkte Vater-Task schicken +oder von dort holen. + +Merke: + * * * * * * * * * * + * * + * <-+ * Vater-Task + * | | * + * * * | * * | * * * + | | + fetch save + | | + * * * | * * | * * * + * | | * + * ->edit| * Benutzer-Task + * * + * * * * * * * * * * + + + +Ansprechen von anderen Tasks + +Sollen Dateien in andere als die direkte Vater-Task transportiert oder von +anderen Tasks geholt werden, muß man den internen Task-Bezeichner angeben. + +Es gibt einige Prozeduren, mit denen man den internen Task-Bezeichner einer +Task bekommt. Solch eine Prozedur ist + + father + +Prozeduren, mit denen man Dateien transportieren kann, liegen auch in einer +Version vor, bei denen man den internen Task-Bezeichner angeben kann. +Beispiel: + + save ("datei", father) (* wie: save ("datei") *) + erase ("datei", father) (* wie: erase ("datei") *) + fetch ("datei", father) (* wie: fetch ("datei") *) + +Weitere Prozeduren, die einen internen Task-Bezeichner liefern, sind: + + myself + printer + public + archive + +Anmerkung: Zur Prozedur 'archive' siehe auch das nächste Kapitel; zu 'print' +siehe auch SPOOLER. Dadurch kann man Dateien auch zu anderen als der +Vater-Task transportieren, holen oder löschen. Beispiele: + + erase ("datei", public) (* Loescht 'datei' in Task 'PUBLIC' *) + fetch ("datei", public) (* Holt 'datei' aus der Task "PUBLIC" *) + save ("datei", public) (* Kopiert 'datei' in die Task 'PUBLIC' *) + save ("datei", printer) (* Uebergibt 'datei' dem Spooler und + druckt die Datei *) + list (father) (* Listet Dateien der Vater-Task *) + +Bei komplizierten "Verwandschafts-Verhältnisse" von Tasks ist es einfacher, +eine Task mit Hilfe des Task-Namens anzusprechen. Das erfolgt mit Hilfe der +Prozedur 'task'. Beispiel: + + save ("datei", task ("hugo")) + +'task' liefert den internen Task-Bezeichner von 'hugo'. Die Umkehr-Prozedur +zu 'task' ist 'name': + + put (name (myself)) + +schreibt den Namen der Task, in der man sich gerade befindet, auf den Bild- +schirm. + +Durch die Prozedur 'father', die einen internen Task-Bezeichner als +Parameter erwartet, kann man an die Vater-Task einer Task gelangen. +Beispiel: + + save ("datei", father (father)) + +Hier wird die Datei 'datei' an die Vater-Task der Vater-Task geschickt (also +zur "Großvater-Task"). + +Mit dem Operator / + +kann man aus einem Tasknamen den internen Tasknamen erhalten. '/' kann über- +all dort eingesetzt werden, wo ein interner Taskname verlangt wird. Beispiel: + + task status (/"meine task") + + +Merke: Mit den internen Task-Bezeichner kann man mit anderen Tasks als der +Vater-Task kommunizieren. + + + +Kommandos für mehrere Dateien + +Durch die vom EUMEL-System bereitgestellten Task-Variablen und Datei-Ver- +zeichnisse (Thesaurus, Plural: Thesauren) ist es möglich, mehrere Dateien +mit einem Kommando zu behandeln. + +Sollen alle Dateien einer Task zu einer anderen transportiert werden (mit +'save') oder alle Dateien geholt werden, kann man 'save all' und 'fetch all' +auch mit einem internen Task-Bezeichner versehen. Beispiele: + + save all (public) + fetch all (public) + +Damit werden alle Dateien der Benutzer-Task zu der Task 'PUBLIC' geschickt +oder von dort geholt. + +Die internen Tasknamen wie z.B. 'myself', 'father', 'public' usw. werden +auch bei dem Einsatz eines Thesaurus benutzt. Was ist ein "Thesaurus"? + +Das EUMEL-System hält sich die Dateinamen einer Task des Taskbaums in einer +internen Liste. Die Namens-Liste wird Thesaurus (laut Duden: ein +"systematisch geordnetes Verzeichnis") genannt. + +Der Operator ALL liefert den Thesaurus einer Task. Beispiel: + + ALL father + ALL myself + +liefert jeweils den Thesaurus der Vater- oder der eigenen Task. Solche +Thesauren kann man als Parameter der meisten der oben erwähnten Kommandos +verwenden: + + save (ALL myself) (* kopiert alle Dateien in die Vater-Task; + arbeitet wie 'save all' *) + forget (ALL myself) (* loescht alle Dateien der Benutzer-Task *) + fetch (ALL father) (* holt alle Dateien der Vater-Task; + arbeitet wie 'fetch all' *) + +Der Operator SOME dagegen bietet einen Thesaurus vorher zum Editieren an, +um Dateinamen zu streichen (HOP RUBOUT). Beispiele: + + fetch (SOME father) (* holt die nicht gestrichenen Dateien *) + save (SOME myself) (* kopiert die nicht gestrichenen Dateien *) + forget (SOME myself) (* loescht die nicht gestrichenen Dateien *) + +Es ist auch möglich, aus den Thesauren mehrerer Tasks einen neuen Thesaurus +zu bilden: + + - (* Differenzmenge *) + / (* Schnittmenge *) + + (* Vereinigungsmenge *) + +Beispiel: + + fetch (ALL father - ALL myself) + +holt alle Dateien der Vater-Task, die nicht bereits in der Benutzer-Task +sind. + + +Merke: Mit den Operatoren 'ALL' und 'SOME' kann man mehrere Dateien mit +einem Kommando behandeln. + + + +Datei-Schutz durch Paßworte und Verschlüsselung + +Dateien können vor unbefugtem Zugriff mit Hilfe von Paßworten und/oder der +Verschlüsselung der Informationen geschützt werden. + + + +Paßworte + +Paßworte für Dateien dienen zur Verhinderung von unbefugtem Zugriff auf +Dateien, die bei einer Vater-Task gespeichert werden. (Die Dateien der +Benutzer-Task können durch ein Task-Paßwort geschützt werden). Dabei sollte +man bedenken, daß Paßworte bekannt werden können. + +Der Paßwort-Schutz ist im EUMEL-System etwas sicherer als in anderen +Betriebssystemen, weil Paßworte nur selten angegeben werden müssen und +daher nicht so leicht bekannt werden können (z.B. durch "über die Schulter +schauen"). Die Kommandozeile wird zudem bei der Angabe eines Paßworts nach +dem Betätigen der RETURN-Taste gelöscht. + +Paßworte werden nur im Verkehr mit Vater-Tasks eingesetzt. Lokale Benutzer- +Dateien brauchen nicht gesondert gesichert zu werden, da man ein Paßwort +auf die Benutzer-Task legen kann oder die zu sichernden Dateien aus dem +System nehmen kann. Ein Paßwort kann mit der Prozedur + + enter password ("schreibpasswort / lesepasswort") + +angegeben oder ein bereits eingestelltes Paßwort kann mit dieser Prozedur +überschrieben werden. Voreingestellt ist kein Paßwort. Nachdem ein Benutzer +die 'enter password'-Prozedur angegeben hat, wird jeder Datei-Verkehr mit +einer Vater-Task mit Hilfe dieses Paßworts überprüft. Unzulässige Zugriffe +durch Benutzer anderer Tasks auf Dateien einer Vater-Task werden abgewiesen. + +Ein Paßwort hat eine eigene Syntax. Es besteht aus zwei Teilen, die leer +sein können und die durch ein "/"-Zeichen voneinander getrennt sind. Der +erste Teil ist das Schreib-Paßwort, der zweite das Lese-Paßwort. Wird kein +Lese-Paßwort angegeben, gilt das Schreib-Paßwort auch für das Lesen. Ist +also kein "/"-Zeichen im Paßwort-String vorhanden, so wird das Schreib- +Paßwort sozusagen gedoppelt. Beispiele: + + enter password ("") (* kein Paßwort *) + enter password ("hugo") (* 'hugo' gilt fuer das Schreiben und + Lesen *) + enter password ("egon/meier") (* 'egon' fuers Schreiben, 'meier' fuers + Lesen *) + +Zusätzlich kann das "-"-Zeichen in dem Teil des Paßworts angegeben werden, +für den ein Zugriff nicht erlaubt sein soll. Beispiel: + + enter password ("-/nurlesen") (* Schreibzugriff nicht erlaubt, + Lese-Passwort ist 'nurlesen' *) + +Das Lese-Paßwort gilt für die Prozedur + + fetch + +während das Schreib-Paßwort für die Prozeduren + + save + erase + +gilt. Sofern die betreffende Datei durch ein Paßwort geschützt ist, ist +folgendes zu beachten: + +a) fetch: + Will ein Benutzer mit der Prozedur 'fetch' eine Datei in seine Benutzer- + Task holen, so wird sein aktuell eingestelltes Paßwort (nur Lese-Teil) + und das Paßwort der Datei überprüft. Stimmen diese nicht überein, so wird + der 'fetch'-Zugriff auf eine Datei der Vater-Task abgewiesen. + +b) save: + Bei einem Transport in eine Vater-Task mit Hilfe der Prozedur 'save' sind + zwei Fälle zu unterscheiden: + + - Datei ist in der Vater-Task noch nicht vorhanden: Diese Datei wird + in der Vater-Task mit dem aktuellen Paßwort des Benutzers einge- + tragen. + + - Datei ist in der Vater-Task bereits vorhanden und soll durch die + neue Datei ersetzt werden: Es wird überprüft, ob das aktuelle + Schreib-Paßwort des Benutzers mit dem der gleichnamigen Datei in der + Vater-Task übereinstimmt. Ist dies nicht der Fall, wird die Datei + nicht in der Vater-Task eingetragen. + +c) erase: + Soll eine Datei der Vater-Task gelöscht werden, wird überprüft, ob das + aktuelle Schreib-Paßwort mit dem der zu löschenden Datei in der Vater- + Task übereinstimmt. Ist dies nicht der Fall, wird die Lösch-Operation + abgewiesen. + + +Merke: Dateien können bei der Sicherung in einer Vater-Task vor unbefugtem +Zugriff durch Paßworte geschützt werden. + + + +Dateien verschlüsseln + +Zusätzlich zu einem Paßwort kann man eine Datei vor unbefugtem Zugriff +schützen, indem sie verschlüsselt wird. + +Mit den Prozeduren + + crypt + decrypt + +kann eine Datei ver- oder entschlüsselt werden (Datenschutz für einzelne +Dateien). Dabei ist es möglich, eine Datei mehrfach zu verschlüsseln (man +muß die Verschlüsselung dann allerdings auch mehrfach rückgängig machen). +Beispiel: + + crypt ("datei", "schluessel") + +verschlüsselt 'datei' mit 'schluessel'. Die Entschlüsselung erfolgt, indem +man die Prozedur 'decrypt' auf 'datei' anwendet und den gleichen Schlüssel +zur Entschlüsselung benutzt. Beispiel: + + decrypt ("datei", "schluessel") + +Den Text des Schlüssels (hier: 'schluessel') sollte man sich also unbedingt +merken, sonst kann die Datei nicht mehr entschluesselt werden. + +Merke: Dateien werden durch 'crypt' und 'decrypt' ver- und entschlüsselt. + + + +3. Das Archiv + +Dateien werden im EUMEL-System auf Systemträgern gespeichert. Mit dem Archiv +können Dateien vom System auf externe Speichermedien (normalerweise +Disketten) gebracht und von diesen ins System geholt werden. + +Das EUMEL-Archiv hat folgende Aufgaben: + +a) Das Archiv wird als Sicherheitsbereich benutzt, indem man von wichtigen + Dateien Kopien anlegt und diese außerhalb des EUMEL-Systems speichert. + +b) Man kann das Archiv-System aber auch benutzen, um Dateien, die nur selten + oder in größeren Zeitabständen benötigt werden, zu kopieren ("archi- + vieren") und im EUMEL-System zu löschen. Falls diese Dateien wieder + gebraucht werden, können sie wieder in das EUMEL-System geholt werden. + Damit wird erreicht, daß im EUMEL-System nur die wirklich notwendigen + Dateien stehen. + +c) Sollen Dateien von einer EUMEL-Installation auf eine andere übertragen + werden, so kann man ebenfalls Archive verwenden. + +d) Bei Versionswechsel des EUMEL-Systems sind Archive die einzige Möglich- + keit, Dateien in die neue Systemversion einzuspielen. Dabei wird garan- + tiert, daß zumindest Archive der letzten Version gelesen werden können. + +Merke: Durch das Archiv können Dateien außerhalb des Systems gesichert +werden. + + + +Das Archiv reservieren + +Soll archiviert werden, muß man das dem Archiv-System mitteilen, damit nicht +ein anderer Benutzer zur gleichen Zeit auf das Archiv zugreift. Dieser +Vorgang wird "reservieren" genannt. + +Archiv-Disketten haben aus Sicherheitsgründen einen Namen. Dieser Name muß +bei der Anmeldung einer Archivierung angegeben werden. Die Anmeldung einer +Archivierung und gleichzeitige Reservierung erfolgt mit + + archive ("name") + +Der Archiv-Name wird bei folgenden Archiv-Operationen zur Überprüfung mit +dem eingelegten Archiv verwandt. + +Wichtig: Eine Diskette sollte erst nach dem 'archive'-Kommando in das +Laufwerk geschoben werden, d.h. erst dann, wenn das Archiv-System reserviert +ist. Sonst kann es geschehen, daß ein anderer Benutzer auf dieser Diskette +archiviert. + +Archivierungen erfolgen durch die schon beschriebenen Transportkommandos +'save' und 'fetch'. Dabei wird als Zieltask 'archive' angegeben. Beispiel: + + save ("mein buch", archive) + fetch ("kapitel 1", archive) + save all (archive) + fetch all (archive) + +Das Archiv bleibt für den Nutzer solange reserviert, wie er Archivierungs- +operationen vollzieht. Dann sollte er das Archiv wieder für andere Benutzer +mit der Prozedur + + release (archive) + +freigeben. + +Leitet ein Nutzer innerhalb von fünf Minuten nach der letzten Archiv- +Operation keine neue ein und meldet sich ein anderer Nutzer mit 'archive' +bei dem Archiv-System an, so wird dem ersten Nutzer die Archiv-Berechtigung +entzogen, um Blockaden zu verhindern. Wenn der erste Nutzer eine erneute +Archiv-Operation versucht, erhält er eine Fehlermeldung. Dadurch kann ein +Nutzer das Archiv längere Zeit (ohne 'release') benutzen, ohne den Betrieb +zu stören, da andere Nutzer bei Bedarf jederzeit eingeschoben werden. + +Wichtig: Muß die Archiv-Floppy gewechselt werden (weil etwa von einer +Diskette eine Datei gelesen wurde und diese auf eine andere geschrieben +werden soll), muß erneut das 'archive'-Kommando gegeben werden. Dies ist +notwendig, um das Verzeichnis aller auf der Diskette befindlichen Dateien +der neuen Diskette zu lesen. + +Merke: Mit 'archive' wird die Archiv-Verwaltung für einen Nutzer reserviert, mit 'release' wieder freigegeben. Mit 'archive' wird +gleichzeitig ein Archiv-Name eingestellt, der bei Archiv-Operationen mit dem +auf der Diskette gespeicherten Archiv-Namen verglichen wird. + + + +Archiv löschen und einen Namen geben + +Bevor ein Archiv-Diskette benutzt werden kann, muß sie den mit 'archive' +eingestellten Namen bekommen. + +Bei der Erstbenutzung eines Archivs muß dieses mit einem Namen versehen +werden. Als Archiv-Name wird der mit 'archive' eingestellte Name verwandt. +Dies erfolgt mit der Prozedur + + clear (archive) + +Gleichzeitig werden alle Dateien, die sich eventuell vorher auf dem Archiv- +Träger befanden, gelöscht. Somit wird 'clear' auch für das Löschen von +Archiven verwendet. + + +Merke: Mit 'clear' wird die Archiv-Diskette gelöscht und gleichzeitig der +mit 'archive' eingestellte Name gegeben. + + + +Einfache Archiv-Operationen + +In diesem Abschnitt werden einfache Archiv-Operationen beschrieben. + +Mit den Prozeduren + + save ("datei", archive) + fetch ("datei", archive) + erase ("datei", archive) + +kann jeweils eine Datei auf die Archiv-Diskette ('save') und von dem Archiv +in das EUMEL-System kopiert ('fetch') oder auf dem Archiv gelöscht ('erase') +werden. Dabei bedeutet 'datei' die zu kopierende Datei und 'archive' der +interne Task-Name für die Archiv-Verwaltung. Bei den ersten zwei Kommandos +ist zu beachten, daß die Datei, die auf das Archiv geschrieben (bei 'save') +oder die in die Benutzer-Task geholt werden soll (bei 'fetch'), immer +kopiert wird. Dateien bleiben also im "Ursprung" immer erhalten. + +Ist eine Datei gleichen Namens bereits auf der Archiv-Diskette (bei 'save') +oder in der Benutzer-Task (bei 'fetch') vorhanden, wird von der Archiv-Ver- +waltung angefragt, ob diese Datei überschrieben werden darf. Es kann somit +nicht zu einem unbeabsichtigten Löschen von Dateien kommen. + +Mit dem Kommando + + list (archive) + +erhält man (wie bei dem "normalen" 'list'-Kommando) ein Namens-Verzeichnis +aller Dateien, die sich auf der eingelegten Archiv-Diskette befinden. + + +Merke: Nachdem ein Archiv mit 'archive' reserviert wurde, kann mit 'save' +eine Datei auf das Archiv geschrieben und mit 'fetch' eine Datei von dem +Archiv in die Benutzer-Task kopiert werden. + + + +Archiv-Operationen für mehrere Dateien + +Hier wird beschrieben, wie man mehrere Dateien auf einmal auf ein Archiv +schreibt oder von einem Archiv liest. + +Mit den Kommandos + + save all (archive) + fetch all (archive) + +werden alle Dateien der Benutzer-Task auf das Archiv geschrieben bzw. von +dort geholt. + +Zusätzlich ist es möglich, die Operatoren 'ALL' und 'SOME' auf ein Archiv +anzuwenden. Wie bereits geschildert, liefern diese Operatoren einen +Thesaurus der angegebenen Task: 'ALL' liefert alle Dateinamen, während man +bei 'SOME' eine Auswahl treffen kann. Damit ist es möglich, alle oder einige +Dateien der Benutzer-Task auf eine Archiv-Diskette zu kopieren oder von der +Archiv-Diskette in die Benutzer-Task zu holen: + + fetch (SOME archive, archive) (* zeigt die Namen der Dateien der + Archiv-Diskette. Die nicht ge- + strichenen Dateien werden in die + Benutzer-Task geholt *) + save (SOME myself, archive) (* zeigt die Namen der Dateien der + Benutzer-Task. Die nicht ge- + strichenen Dateien werden auf die + Archiv-Diskette kopiert *) + save (ALL archive, archive) (* sichert alle Dateien der Benutzer- + Task, die sich schon auf dem Archiv + befinden (alte Version). Das + Kommando ist für Sicherungs- + Disketten gedacht, bei dem man immer + die gleichen Dateien auf dem Archiv + haben will *) + +Durch die Thesaurus-Operatoren '-' (Differenzmenge), '/' (Schnittmenge) und +'+' (Vereinigungsmenge) kann man kompliziertere Wirkungen erzielen. +Beispiele: + + save (ALL myself - ALL archive, archive) (* Schreibt alle Dateien der + Benutzer-Task auf das Archiv, + die nicht bereits auf dem + Archiv stehen *) + save (ALL myself - ALL father - ALL archive, archive) + (* Schreibt alle Dateien der + Benutzer-Task auf das Archiv, + mit Ausnahme der Dateien, die + längerfristig in der Vater- + Task gespeichert sind und die + nicht bereits auf dem Archiv + stehen *) + fetch (ALL archive - ALL myself) (* Holt alle Dateien vom Archiv, + die sich nicht bereits in der + Benutzer-Task befinden *) + +Werden mehrere Dateien mittels eines Thesaurus bearbeitet, kann man nach +einer Unterbrechung der Bearbeitung (d.h. Fehlermeldung) die Operation wieder +aufsetzen. Dazu liefert das Kommando + + remainder + +den "Rest"-Thesaurus. Er enthält alle nicht bearbeiteten Dateinamen. +Beispiel: + + save (SOME myself, archive) (* Unterbrechung, z.B. durch einen vom + Programm erzeugten 'errorstop' oder SV + und 'halt' *) + save (remainder, archive) (* bearbeitet die restlichen Dateien *) + + +Merke: Mit 'save all' bzw. 'fetch all' kann man alle Dateien einer Benutzer- +Task archivieren bzw. alle Dateien eines Archivs in die Benutzer-Task holen. +Mit den Operatoren SOME und ALL sind weitere Operationen möglich. + + + +Fehlermeldungen des Archivs + +Bei Archiv-Operationen kann es zu Fehlersituationen kommen. + +Versucht man eine Datei vom Archiv zu lesen, kann es vorkommen, daß das +Archiv-System + + Lese-Fehler (Archiv) + +meldet und den Lese-Vorgang abbricht. Dies kann auftreten, wenn die Floppy +beschädigt oder aus anderen Gründen nicht lesbar ist (z.B. nicht justierte +Disketten-Geräte). In einem solchen Fall vermerkt das Archiv-System intern, +daß die Datei nicht korrekt gelesen werden kann. Das sieht man z.B. beim +'list (archive)'. Dort ist der betreffende Datei-Name mit dem Zusatz 'mit +Lese-Fehler' gekennzeichnet. Um diese Datei trotzdem zu lesen, muß man sie +im Datei-Namen mit dem Zusatz 'mit Lese-Fehler' versehen. Beispiel: + + fetch ("dateiname mit Lese-Fehler") + +Die Datei wird in diesem Fall trotz Lese-Fehler (Informationsverlust!) vom +Archiv gelesen. + +Um solche Fälle möglichst zu vermeiden, sieht das EUMEL-System die +Möglichkeit vor, Archive bzw. Archiv-Dateien nach beschreiben zu prüfen. Das +erfolgt mit dem Kommando + + check ("dateiname", archive) (* oder *) + check (ALL archive, archive) (* fuer alle Archiv-Dateien *) + +Durch dieses Kommando werden eventuelle Lese-Fehler gemeldet. + +Weitere Fehlermeldungen des Archivs: + +* Lesen unmöglich (Archiv) Archiv-Floppy nicht eingelegt oder die Tür + des Laufwerks ist nicht geschlossen. + +* Schreiben unmöglich (Archiv) Floppy ist schreibgeschützt. + +* Archiv nicht angemeldet Archiv wurde nicht angemeldet + ('archive ("name")' geben). + +* Lese-Fehler (Archiv) Siehe obige Beschreibung. + +* Schreibfehler (Archiv) Die Floppy kann nicht (mehr) beschrieben + werden. Andere Floppy verwenden. + +* Speicherengpass Im System ist nicht mehr genügend Platz, um + eine Datei vom Archiv zu laden. + Ggf. Dateien löschen. + +* RERUN beim Archiv-Zugriff Das System wurde bei einer Archiv-Operation + durch Ausschalten bzw. Reset unterbrochen. + +* ... gibt es nicht Die Datei ... gibt es nicht auf dem Archiv. + +* Archiv heißt ... Die eingelegte Floppy hat einen anderen als + den eingestellten Archiv-Namen. + +* Archiv wird von Task ... benutzt Das Archiv wurde von einem anderen + Benutzer reserviert. + +* ... kann nicht geschrieben werden (Archive voll) Das Archiv ist voll. + Neue Archiv-Floppy + benutzen. + +* Archiv inkonsistent Die eingelegte Floppy hat nicht die Struk- + tur einer Archiv-Floppy ('clear (archive)' + vergessen). + +* save/erase wegen Lese-Fehler verboten Bei Archiven mit Lese-Fehler sind + Schreiboperationen verboten, weil + ein Erfolg nicht garantiert + werden kann. + + + +4. FILEs in Programmen + +Die bisher geschilderten Kommandos gelten für alle Datei-Arten. In diesem +Kapitel wird der Standard Datei-Typ FILE beschrieben. Eine Datei von Daten- +typ FILE ist eine sequentielle Datei, die das Lesen und Schreiben von Daten +in strikter Aufeinanderfolge von Sätzen erlaubt (Betriebsrichtungen 'input' +und 'output'). Die Betriebsrichtung 'modify' erlaubt das gleichzeitige Lesen +und Schreiben sowie beliebiges Positionieren. + + + +Deklaration, Assoziierung und Betriebsrichtungen + +Für ELAN-Programme gibt es standardmäßig den Datentyp FILE. FILEs müssen +deklariert werden. Die Kopplung einer FILE VAR im Programm mit einer Datei +erfolgt durch eine Assoziierungsprozedur. Bei der Assoziierung muß man an- +geben, wie die Datei bearbeitet werden soll. + +Dateien müssen in einem ELAN-Programm - wie alle anderen Objekte auch - +deklariert werden. Beispiel: + + FILE VAR f :: ... + +Mit der Deklaration wird dem ELAN-Compiler der Name der Datei-Variablen +bekannt gemacht. Dabei ist zu beachten, daß im EUMEL-System alle FILEs mit +VAR deklariert werden müssen, denn jede Lese/Schreib-Operation verändert +einen FILE. FILE CONST Objekte sind also nicht erlaubt. Ähnlich wie bei +anderen Datenobjekten werden FILEs initialisiert. In der Regel erfolgt dies +mit einer Assoziierungsprozedur. Beispiele: + + FILE VAR meine datei :: sequential file (output, "daten") + ... + (* oder: *) + TEXT VAR datei name; + put ("Dateiname bitte:"); get (datei name); + FILE VAR f :: sequential file (input, datei name); + +Die Assoziierungsprozedur 'sequential file' hat die Aufgabe, eine in einem +Programm deklarierte FILE VAR mit einer bereits vorhandenen oder noch einzu- +richtenden Datei (abhängig von der Betriebsrichtung, siehe unten) des +EUMEL-Systems zu koppeln. Den Dateinamen gibt man als zweiten Parameter +an. Dadurch können ELAN-Programme geschrieben werden, die Dateien +bearbeiten, deren Namen man beim Erstellen des Programms noch nicht kennt. + +Der erste Parameter gibt die sog. Betriebsrichtung an. Sie bestimmt, in +welcher Weise die assoziierte Datei bearbeitet wird. Es gibt folgende drei +Betriebsarten: + +a) input: + Die Datei kann vom Programm nur gelesen werden. Durch 'input' wird bei + der Assoziierung automatisch auf den ersten Satz der Datei positioniert. + Ist die zu lesende Datei nicht vorhanden, wird ein Fehler gemeldet. + +b) 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 vorhanden, wird sie automatisch einge- + richtet. + +c) 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. Hier ist nicht definiert, auf welchen Satz der Datei + man nach erfolgter Assoziierung steht. Die Datei wird automatisch einge- + richtet, wenn sie vor der Assoziierung nicht vorhanden war. + +Anmerkung: +In jeder Betriebsrichtung sind nur bestimmte Operationen zugelassen. Z.B. +sind bei 'input' keine Schreib-Prozeduren erlaubt. Vergl. dazu die nächsten +Abschnitte. + +Neben der Betriebsrichtung 'input', 'output' oder 'modify' muß bei +'sequential file' als zweiter Parameter der Name der zu bearbeitenden Datei +angegeben werden. Beispiel: + + TEXT VAR datei name, zeile; + put ("Bitte Name der zu bearbeitenden Datei eingeben:"); + get (datei name); + FILE VAR f :: sequential file (input, dateiname); + ... + getline (f, zeile); + ... + +Hier wird der Name der zu bearbeitenden Datei zuerst eingelesen. Diese Datei +wird mit 'f' in der Betriebsrichtung 'input' assoziiert, d.h. würde man z.B. +die Prozedur + + putline (f, irgendein text) + +an einer Stelle im Programm verwenden, wird ein Fehler gemeldet. Die Be- +triebsrichtung hilft also, Fehler bei der Programmierung zu vermeiden. + +Mit den Prozeduren + + modify (f) + input (f) + output (f) + +kann die Betriebsrichtung von Dateien geändert werden. + +Dateien brauchen im EUMEL-System vor Programmende nicht geschlossen zu +werden, da sie vom System immer konsistent gehalten werden. + +Merke: Die Betriebsrichtung gibt an, wie man eine Datei bearbeiten will. +'input' steht für Lesen, 'output' für Schreiben und 'modify' für Verändern. +Jede Datei muß vor einer Benutzung mit 'sequential file' assoziiert werden. +Die Assoziierungsprozedur stellt die Kopplung zwischen dem Programm und dem +EUMEL-Betriebssystem her. + + + +Operationen der Betriebsrichtung 'output' + +In der Betriebsrichtung 'output' sind nur Schreib-Operationen gestattet. +'output' ist also für das Bearbeiten von Ausgabedateien vorgesehen. + +Mit den Prozeduren + + put + +können INT-, REAL- und TEXT-Werte in eine Datei geschrieben werden. Die +Prozedur + + line + +sorgt dafür, daß eine neue Zeile in der Datei begonnen wird. Beispiel: + + FILE VAR f :: sequential file (output, "daten"); + put (f, "Daten:"); + line (f); + schreibe daten. + + schreibe daten: + INT VAR intwert; + REAL VAR textwert; + put ("bitte Daten eingeben (INT, REAL):"); + REP + get (intwert); + put (f, intwert); + get (realwert); + put (f, realwert); + line (f); + UNTIL yes ("fertig") END REP. + +Durch die Assoziierungsprozedur mit der Betriebsrichtung 'output' wird +hinter den letzten Satz der Datei positioniert, bei einer leeren Datei also +auf den ersten Satz. In dem ersten Satz in unserem Beispiel wird also +'Daten:' geschrieben. Durch die Prozedur 'line' geht man auf den nächsten +Satz. Dann werden jeweils ein INT- und ein REAL-Wert in eine Datei-Zeile +geschrieben, bis die Frage 'fertig' mit 'j' beantwortet wird. + +Die 'put'-Prozeduren schreiben die Werte jeweils in die aktuelle Datei-Zeile. +Zwischen den Werten wird von den 'put'-Prozeduren jeweils ein Leerzeichen +eingefügt. Im Gegensatz zu den 'put'-Prozeduren schreibt die Prozedur 'write' +einen TEXT ohne ein anschließendes Leerzeichen in die aktuelle Datei-Zeile. +Beispiel: + + ... + write (f, "meine Daten:"); + write (f, " "); + write (f, text (17 + 4)); + (* das Gleiche wie: put (f, "meine Daten:"); put (f, 17 + 4) *) + +Auf eine neue Datei-Zeile kann auf zwei verschiedene Arten positioniert +werden: + +a) Prozedur 'line': + Diese darf auch mit einem Parameter angegeben werden, der die Anzahl + Zeilen angibt. Beispiel: + + line (f); (* positioniert auf die naechste Zeile *) + line (f, 1) (* das Gleiche *) + line (f, 4) (* Vier Zeilen weiter; dazwischen sind 3 Leerzeilen *) + +b) Überschreiten der Zeilengrenze: + Eine Datei-Zeile kann (voreingestellt) 77 Zeichen aufnehmen. Wird bei + einer Schreib-Operation diese Grenze überschritten, wird der auszugebende + Wert auf die nächste Zeile plaziert. Mit der Prozedur 'max line length' + kann die eingestellte Datei-Zeilenlänge gelesen oder verändert werden. + Beispiel: + + FILE VAR f :: sequential file (output, "meine daten"); + put (max line length (f)); (* ergibt 77 *) + max line length (f, 132); + put (max line length (f)) (* ergibt 132 *) + + Ist die Länge des auszugebenden Textes größer als die verbleibende + Zeilenbreite, wird der Text auf der nächsten Zeile ausgegeben. + +Die 'putline'-Prozedur bietet die Möglichkeit, eine ganze Datei-Zeile auf +einmal auszugeben. Eine Positionierung auf die nächste Datei-Zeile ('line') +braucht dabei nicht vorgenommen werden. Beispiel: + + TEXT VAR zeile :: ""; + ... + zeile := ...; + putline (f, zeile); + ... + +Merke: In der Betriebsrichtung 'output' kann in eine Datei geschrieben +werden. Dazu stehen die Prozeduren 'put', 'write' und 'putline' zur Verfü- +gung. Die Prozedur 'line' positioniert auf die nächste Zeile der Ausgabe- +datei. Mit 'max line length' kann die Länge einer Datei-Zeile verändert oder +erfragt werden. + + + +Operationen der Betriebsrichtung 'input' + +In der Betriebsrichtung 'input' sind nur Lese-Operationen gestattet. 'input' +ist also für das Bearbeiten von Eingabedateien vorgesehen. + +Analog der Betriebsrichtung 'output' sind bei 'input' 'get'-Prozeduren vor- +handen, die INT-, REAL- oder TEXT-Werte aus einer Datei lesen. Beispiel: + + FILE VAR f :: sequential file (input, "Betriebszeiten"); + REAL VAR zeiten; + zeiten einlesen und berechnen. + + zeiten einlesen und berechnen: + REP + get (f, zeiten); + IF zeiten = 0.0 + THEN LEAVE zeiten einlesen und berechnen + FI; (* siehe auch 'eof'-Prozedur *) + berechne + END REP. + + berechne: + ... + +Die 'get'-Prozeduren positionieren automatisch auf die nächste Zeile, sofern +keine Werte mehr in der aktuellen Zeile vorhanden sind. Mit der Prozedur +'line' kann explizit auf die nächste Zeile positioniert werden. Damit können +die restlichen Daten einer Zeile überschlagen werden. Für die 'get'-Proze- +duren gilt, daß jeder zu lesende Wert entweder beim nächsten Leerzeichen +oder beim Zeilenende aufhört. Beispiel: + + FILE VAR f :: sequential file (input, "text"); + TEXT VAR wort; + lese worte. + + lese worte: + REP + get (f, wort); (* Lesen eines Worts ohne Leerzeichen *) + put (wort); (* Schreiben eines Worts mit Leerzeichen *) + IF wort = "Ende" + THEN LEAVE lese worte + FI + END REP. + + +Trennzeichen ("separator") zwischen den Worten sind also Leerzeichen, welche +nicht eingelesen werden. Manchmal sollen jedoch Daten eingelesen werden, die +durch andere Zeichen als dem Leerzeichen voneinander getrennt sind. Eine +Möglichkeit, solche Daten zu behandeln, bietet die 'getline'-Prozedur. Sie +liest (analog 'putline') eine ganze Zeile und positioniert auf die nächste +Zeile. Dann kann man mit Hilfe von TEXT-Prozeduren solche Zeilen 'per Hand' +auseinandernehmen. Als Beispiel zeigen wir ein Programm, welches den zweiten +Wert einer Zeile lesen soll. Die Werte werden durch Kommata voneinander +getrennt: + + FILE VAR eingabe datei :: sequential file (input, "daten"); + TEXT VAR zeile, wert; + lese jeweils zweiten wert; + verarbeite wert. + + lese jeweils zweiten wert: + REP + getline (f, zeile); + IF zeile = "Ende" + THEN LEAVE lese jeweils zweiten wert + FI; + extrahiere zweiten wert + END REP. + + extrahiere zweiten wert: + wert := subtext (zeile, anfang, ende). + + anfang: + pos (zeile, ",") + 1. + + ende: + pos (zeile, ",", anfang) + 1. + + verarbeite wert: + ... + +Diese (etwas umständliche) Methode ist immer dann angebracht, wenn Zeilen +unterschiedlich untersucht werden müssen. Eine einfachere Möglichkeit, die +in vielen Fällen angewandt werden kann, bietet eine andere Form der 'get'- +Prozedur, bei der man das oder die Trennzeichen angeben kann. Beispiel: + + ... + extrahiere zweiten wert: + get (f, wert, ","); (* ersten Wert der Zeile ueberlesen *) + get (f, wert, ","). (* hier der richtige zweite Wert *) + +Hier wird also das Trennzeichen mit angegeben (dritter Parameter). Eine +andere Methode müssen wir anwenden, wenn Daten nicht durch ein Trennzeichen +unterschieden werden, sondern nur durch ihre Länge definiert sind. Beispiel: + + ... + lese fuenfstellige werte: + REP + get (f, wort, 5); + verarbeite wert + ... + END REP. + +Bei dieser 'get'-Prozedur wird die Länge des einzulesenden Textes als +dritter Parameter angegeben. Man beachte, daß die letzten zwei 'get'-Proze- +duren nur TEXTe einlesen. Entsprechende Typwandlungen hat der Programmierer +vorzunehmen. + +Merke: Die Betriebsrichtung 'input' erlaubt nur Lesen aus einer Eingabedatei. +Für diesen Zweck gibt es die Prozeduren 'get', 'getline' und 'line'. + + + +Operationen der Betriebsrichtung 'modify' + +Die Betriebsrichtung 'modify' erlaubt das Lesen und Schreiben von Informa- +tionen auf Dateien. Zusätzlich ist beliebiges Positionieren auf Dateien +erlaubt. 'modify' ist also für Dateien gedacht, die man gleichzeitig als +Ausgabe- und Eingabedateien behandeln will. + +Die Betriebsrichtung 'modify' erlaubt ein Ändern einer Datei ("updating"), +wobei die sequentielle Natur der Datei erhalten bleibt. + +Eine Datei der Betriebsrichtung 'modify' muß ebenso mit 'sequential file' +assoziiert werden, wie bei den zwei anderen Betriebsrichtungen. Während bei +'input' auf den ersten bzw. bei 'output' auf den letzten Satz der Datei +positioniert wird, ist bei 'modify' nicht definiert, auf welchem Satz der +Datei nach erfolgter Assoziierung positioniert wird. Man muß also die erste +Positionierung explizit vornehmen. Für die Zwecke der Positionierung gibt es +die Prozeduren + + to line (* auf eine bestimmte Zeile *) + col (* auf eine Spalte innerhalb der Zeile *) + down (* eine Zeile vorwaerts *) + up (* eine Zeile zurueck *) + +Neben diesen Positionierungsprozeduren gibt es die Informationsprozeduren: + + lines (* Anzahl Zeilen in der Datei *) + line no (* aktuelle Zeilennummer *) + eof (* Dateiende? *) + +Beispiele: + + down (f); (* wie: to line (f, line no (f) + 1) *) + (* Nicht über eof *) + up (f); (* wie: to line (f, line no (f) - 1) *) + (* Nicht über Zeile 1 *) + +Mit der Prozedur + + read record + +kann der Satz, auf den aktuell positioniert wurde, gelesen werden. Mit + + write record + +kann sein Inhalt geschrieben werden (also auch "überschreiben"). Mit den +Prozeduren + + insert record + delete record + +kann eine Zeile vor der aktuellen eingefügt (Position ist dann die einge- +fügte Zeile) oder der aktuelle Satz gelöscht werden (Position ist dann der +nächste Satz). Beispiele: + + FILE VAR f :: sequential file (modify, "meine daten") + TEXT VAR zeile, neue zeile; + to line (f, 1); + read record (f, zeile); (* erste Zeile lesen *) + ... + insert record (f); (* neue erste Zeile *) + write record (f, neue zeile); + down (f); (* auf die 2. Zeile, die vorher die 1. war *) + delete record (f); (* diese loeschen, so dass die + Zeilenzahl wieder stimmt *) + +Das nächste Beispiel zeigt, wie hinter den letzten Satz einer Datei eine +Zeile eingefügt werden kann (hier wird ausgenutzt, daß man in der Betriebs- +richtung 'modify' hinter den letzten Satz der Datei positioniert werden +kann): + + FILE VAR f :: sequential file (modify, "test"); + to line (f, lines (f)); (* auf die letzte Zeile *) + down (f); + insert record (f); + write record (f, "neue letzte Zeile"); + ... + +Mit 'down' bzw. 'up' kann man auch um einige Zeilen auf einmal vorwärts oder +rückwärts positionieren. Beispiele: + + down (f, 17) (* 17 Zeilen vorwaerts *) + up (f, 13) (* 13 zeilen rueckwaerts *) + +Merke: In der Betriebsrichtung 'modify' können Dateien gelesen und/oder ge- +schrieben werden ('read record' oder 'write record'). Positionierungen kön- +nen mit 'down', 'up' oder 'to line' vorgenommen werden. + + + +Manipulationen von FILEs + +FILEs können im EUMEL-System auch als Einheiten behandelt werden. Dazu +stehen die bereits erläuterten Prozeduren zur Verfügung, die wir hier der +Vollständigkeit halber nochmals aufführen. + +Mit der Prozedur + + exists + +kann erfragt werden, ob eine Datei bereits existiert. Beispiel: + + TEXT VAR name; + REP + erfrage name; + UNTIL exists (name) END REP; + ... + + erfrage name: + put ("Dateiname bitte:"); + get (name); + line. + +Weitere Prozeduren: + + forget (* Datei löschen *) + rename (* umbenennen *) + copy (* kopieren *) + +Für Programmierer ist eine Version der 'forget'-Prozedur interessant, die +eine Datei ohne Kontroll-Anfrage löscht. Beispiel: + + forget ("meine scratch datei", quiet) + +Merke: Mit 'exists' kann erfragt werden, ob ein FILE bereits existiert. + + + +Texte Suchen + +Mit den Prozeduren 'down' und 'up' kann man (ebenso wie im Editor) auch nach +Texten suchen. + +Die Prozeduren 'down' bzw. 'up' suchen einen Text in der Datei. Beispiele: + + down (f, "dieser text") + up (f, "noch'n text") + +Diese Prozeduren suchen direkt auf der Dateistruktur. Wird der gesuchte Text +gefunden, steht man direkt auf dem gesuchten Text. Wird der Text nicht +gefunden, steht man auf dem ersten (bei 'up') oder hinter dem letzten (bei +'down') Zeichen der Datei. Die Position innerhalb der Zeile nach einer Suche +kann mit + + col (f) + +abgefragt werden. Um die Suche auf einen Bereich zu beschränken, kann man +'down' bzw. 'up' mit einem weiterem Parameter versehen, der die max. Anzahl +von Zeilen angibt. Beispiel: + + FILE VAR f :: ... + ... + INT VAR akt zeilennr :: line no (f); + down (f, "pattern", 100); + (* sucht in den naechsten 100 Zeilen nach 'pattern' *) + IF line no (f) <> akt zeilen nr + 100 + THEN gefunden + ELSE nicht gefunden + FI; + ... + +Achtung: 'down' bzw. 'up' beginnen die Suche immer mit dem nächsten Zeichen +in Suchrichtung, so daß man mehrmals hintereinander suchen kann, ohne in +eine Endlosschleife zu geraten (Erinnerung: wird ein Text gefunden, ist die +Position innerhalb der Zeile das erste Zeichen des gesuchten Begriffs). + +Mit den Prozeduren (gleiche Parameterversorgung wie 'down' und 'up') + + downety + uppety + +beginnt man mit der Suche immer auf der aktuellen Position. Darum sollte man +diese Prozeduren mit Vorsicht verwenden. Mit der Prozedur + + pattern found + +kann man anfragen, ob die letzte Suchoperation erfolgreich war oder nicht. +Beispiel: + + FILE VAR f :: ... + ... + INT VAR akt zeilennr :: line no (f); + down (f, "pattern", 100); + (* sucht in den naechsten 100 Zeilen nach 'pattern' *) + IF pattern found THEN gefunden + ELSE nicht gefunden + FI; + ... + +Mit der Prozedur + + at + +kann man anfragen, ob man auf einem gewünschten Wort steht. Beispiel: + + IF at (f, "pattern") + THEN .. + FI + +Die Prozedur + + word + +liefert das aktuelle Wort der aktuellen Position einer Zeile. Beispiele: + + TEXT VAR dieses wort :: word (f); + (* Zeichenkette von der aktuellen Position bis zum nächsten Blank oder + Zeilenende *) + dieses wort := word (f, "<"); + (* Zeichenkette (Wort) von der aktuellen Position bis zum Zeichen '<' + oder Zeilenende *) + dieses wort := word (f, 13); + (* Zeichenkette (Wort) mit der Laenge 13 *) + +Merke: Die Prozeduren 'down' und 'up' suchen einen Text innerhalb einer +Datei. Mit 'at' kann man anfragen, ob man auf dem gesuchten Begriff steht. +'word' liefert das aktuelle Wort. + + + +FILE-Ausschnitte + +Hier wird erklärt, wie man mehrere Zeilen aus einer Datei auf einmal löschen +und/oder verschieben und wie man nur einen Ausschnitt einer Datei zugänglich +machen kann. + +Den einfachsten Zugang zu Datei-Abschnitten erhält ein Programmierer durch +einige Anwendungsprozeduren, die u.a. auch im Editor verwandt werden. Dort +gibt es die Möglichkeit, einen markierten Bereich "vorsichtig" zu löschen +und u.U. an anderer Stelle wieder einzufügen (ESC RUBOUT und ESC RUBIN). +Solche Prozeduren stehen auch einem Programmierer zur Verfügung. Beispiel: + + FILE VAR f :: .... + .... + remove (f, 100); (* entfernt 100 Zeilen von der aktuellen + Position rueckwaerts (!) aus der Datei 'f' *) + to line (27); (* zum Beispiel *) + re insert (f) (* fuegt die "vorsichtig" geloeschten Zeilen vor + (!) die Zeile 27 ein *) + +Die Prozedur + + remove + +löscht also eine angebbare Anzahl von Zeilen in der Datei (rückwärts von der +aktuellen Zeilennummer ab) und schreibt diesen Datei-Abschnitt in einen +internen Puffer. Man beachte, daß sich dabei natürlich die Zeilennummer der +Datei ändert. Die entfernten Zeilen können aus dem internen Puffer an einer +anderen Stelle durch + + reinsert + +genau einmal wieder eingefügt werden. Sollen jedoch die mit 'remove' ent- +fernten Zeilen wirklich gelöscht und nicht mehr an anderer Stelle eingesetzt +werden, dann kann man die Prozedur + + clear removed + +verwenden. Beispiel: + + ... + remove (f, 50); (* loescht vorsichtig *) + clear removed (f); (* und endgueltig *) + ... + +Durch solche Löschungen oder Einfügungen entstehen Datei-Segmente. +Innerhalb eines Segments kann direkt positioniert werden. Werden jedoch +Löschungen oder Einfügungen vorgenommen (Sätze werden ein- oder ausgekettet), +muß erst zu einem entsprechenden Segment positioniert und dann innerhalb des +Segments auf den entsprechenden Satz positioniert werden. Das kann - je nach +Anzahl der Segmente - zeitaufwendig sein. Deshalb existiert die Prozedur + + segments + +mit der man feststellen kann, wieviel Datei-Segmente in der Datei existieren. +(Sind es "zu viele", kann man die Datei "reorganisieren"). + +Diese und die folgenden Prozeduren nutzen eine vom EUMEL-System bereitge- +stellte Möglichkeit, Ausschnitte aus Dateien wie eigenständige Dateien zu +behandeln. Beispiel: + + FILE VAR f :: ... + ... + FRANGE VAR alter bereich; + set range (f, 200, 1, alter bereich); + (* Datei mit 200 Zeilen von der Spalte 1 der aktuellen Zeile *) + edit (f); (* Zeilen 1-200 editieren *) + set range (f, alter bereich); (* Datei zuruecksetzen *) + ... + +Von dem Beispiel-Programm wird die Datei 'f' bearbeitet. Die FRANGE-Variable +dient hier dazu, sich den ursprünglichen Bereich der Datei 'f' (der auch +schon eingeschränkt sein kann), zu merken. Mit der Prozedur 'set range' wird +die Datei 'f' auf 200 Zeilen eingeschränkt (von der aktuellen Zeile 200 +Zeilen rückwärts). Mit der Prozedur 'edit' kann nun der Benutzer unseres +Programms die (eingeschränkte) Datei beliebig editieren. Ihm steht am Anfang +Zeilen 1 bis 200 zur Verfügung; die "ausgeblendeten" Datei-Teile kann er +nicht verändern. Mit dem zweiten Aufruf von 'set range' wird der einge- +schränkte (und u.U. veränderte) Datei-Bereich aufgehoben, so daß hier wieder +alle ursprünglichen Datei-Zeilen zur Verfügung stehen. + +Solche Beschränkungen können natürlich mehrmals geschachtelt vorgenommen +werden. Um nach Ablauf solcher Programmteile sicher wieder die ursprüngliche +Datei (mit allen ihren Zeilen) zur Verfügung zu haben, gibt es die Prozedur + + reset range (f) + +Sie setzt die Datei 'f' auf den größtmöglichen Bereich zurück. + +Merke: Mit 'remove' und 'reinsert' können Zeilen gelöscht und/oder ver- +schoben werden. Mit dem Datentyp FRANGE und den Prozeduren 'set range' +können Dateien eingeschränkt werden. + + + +5. Datenräume + +Die bis jetzt behandelten Dateien können nur TEXTe aufnehmen (bei einigen +Schreib-/Lese-Operationen werden Daten in Texte umgewandelt, z.B. bei 'get' +und 'put'). Damit ist gewährleistet, daß alle Programme im EUMEL-System +(Editor, Drucker, Compiler, Benutzer-Programme usw.) auf gleiche Art und +Weise auf Dateien zugreifen können, unabhängig davon, welche Daten wirklich +gespeichert sind. Der folgende Abschnitt zeigt, wie man mit Dateien umgeht, +die nicht vom Standardtyp FILE sind. + + + +Konzept des Datenraums + +Standarddateien (FILEs) 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. Hierfür stehen Standard- +prozeduren 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. Daher wurden in EUMEL� die +Datenräume eingef�hrt, 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 +der Datei gespeicherten Objektes nicht kennen. + +Einen Datenraum kann man sich als eine Sammlung von Daten vorstellen (u.U. +leer), die ausschließlich von einem Programm her behandelt wird. Man kann +einem Datenraum durch ein Programm einen Datentyp "aufprägen". Meist handelt +es sich um Reihungen, weil die Benutzung von Datenräumen erst bei größeren +Datenmengen lohnt. Nach einem solchen "Aufpräge"-Vorgang kann der Datenraum +wie ein "normaler" Datentyp behandelt werden, mit dem Unterschied, daß die +Daten in einem Datenraum (d.h. Datei) gespeichert werden. Somit können nach- +folgende Programme auf die im Datenraum gespeicherten Daten zugreifen, so- +fern sie den gleichen Datentyp auf den Datenraum aufprägen. + +Merke: Ein Datenraum ist eine Sammlung von Daten. Er kann ausschließlich +durch ein Programm (und z.B. nicht durch den Editor) behandelt werden. +Programme können Datenräumen Datentypen aufprägen und sie dann mit den ver- +fügbaren Operationen dieses Datentyps manipulieren. + + +Ein Beispiel + +Diesen etwas komplizierten Vorgang wollen wir an Hand eines Beispiels +Schritt für Schritt erklären. + +Angenommen, Programmierer Meier hat ein Gehaltsprogramm zu erstellen. Er +überlegt sich, das Programm in (mindestens) zwei Moduln (PACKETs) zu er- +stellen: + +a) Berechnung der Gehaltssumme aus den Arbeitszeiten (also Bruttogehalt) und + dann +b) Endgültige Berechnung der Gehälter durch Abzug von Steuern usw. + +Das Programm aus a) erstellt also eine Gehaltsliste für alle Beschäftigten +des Betriebs. Die Gehaltsliste soll ebenfalls von Modul b) genutzt werden. + +Meier entschließt sich, die Gehaltsliste in einem Datenraum zu speichern. +Das hat neben der effizienteren Bearbeitung noch den Vorteil, daß man die +Gehaltsliste - ohne Programmierkenntnisse zu besitzen - nicht mit dem Editor +bearbeiten kann (Datenschutz). + +Dem ELAN-Compiler muß Meier also mitteilen, daß die Reihung für die +Gehaltsliste (oder irgendein anderer Datentyp) nicht im Speicherbereich des +Programms, sondern in einem Datenraum gespeichert werden soll. Dies erfolgt +mit dem Schlüsselwort BOUND, welches dem Datentyp bei der Deklaration +vorangestellt wird. Beispiel: + + BOUND ROW 1000 REAL VAR gehaltsliste + +Dieses BOUND-Objekt muß Meier noch mit einer Datei verbinden, man spricht +von "ankoppeln". Die Ankopplung erfolgt durch den Operator ':='. Dies kann +man gleich bei der Initialisierung vornehmen. Beispiel: + + BOUND ROW 1000 REAL VAR gehaltsliste := new ("hugo") + +Die Prozedur 'new' kreiert dabei einen leeren Datenraum (hier mit dem Namen +'hugo'), der mit Hilfe der Zuweisung (hier: Initialisierung) an die Variable +'gehaltsliste' gekoppelt wird. + +Nun kann Meier mit der 'gehaltsliste' arbeiten wie mit allen anderen Feldern +auch, mit dem Unterschied, daß die Daten, die er in 'gehaltsliste' speichert, +eigentlich im Datenraum 'hugo' gespeichert sind. Beispiele: + + gehaltsliste [5] := 10 000.0; (* Traumgehalt *) + gehaltsliste [index] INCR 200.0; (* usw. *) + +Meier kann auch Prozeduren schreiben, die auf der Gehaltsliste arbeiten. +Beispiel: + + PROC sort (ROW 1000 REAL VAR liste): + ... + END PROC sort; + ... + sort (gehaltsliste); + ... + +Man beachte, daß der formale Parameter der Prozedur 'sort' nicht mit BOUND +spezifiziert werden darf (BOUND wird nur bei der Deklaration des Objekts +angegeben). Das ist übrigens ein weiterer wichtiger Vorteil von BOUND-Objek- +ten: man kann alle Prozeduren des EUMEL-Systems auch für BOUND-Objekte +verwenden, nur die Datentypen müssen natürlich übereinstimmen. + +Nach der Bearbeitung des Moduls a) ist Meier nun sicher, daß seine Brutto- +daten in dem Datenraum 'hugo' stehen. Meier braucht (genauso wie bei FILEs) +den Datenraum nicht zu schließen. Im zweiten Modul muß Meier nun erneut ein +BOUND-Objekt deklarieren. +Deshalb deklariert Meier nun + + BOUND ROW 1000 REAL VAR nettoliste :: old ("hugo"); + +Hier muß Meier nun die Prozedur 'old' verwenden, weil der Datenraum bereits +aus dem ersten Modul existiert. Nun kann Meier weiter programmieren, bis er +letztendlich den Datenraum löscht: + + forget ("hugo") + +Merke: Ein Datenobjekt eines beliebigen Datentyps kann mit einem vorange- +stellten BOUND deklariert werden und an einen Datenraum gekoppelt werden. +Der Datentyp ist dann auf den Datenraum aufgeprägt und man kann mit ihm +arbeiten wie mit allen anderen Objekten dieses Datentyps. + + + +Datenräume als Datentyp + +Datenräume können auch als eigener Datentyp (DATASPACE) in einem Programm +behandelt werden. Somit können Datenräume (als Ganzes) ohne Kenntnis eines +eventuell (vorher oder später) aufgeprägten Typs verwandt werden. + +Als Operationen auf DATASPACE-Objekten sind nur Transporte, Löschen und +Initialisieren zugelassen. + + DATASPACE VAR ds :: old ("daten"); + +Der Zuweisungsoperator bewirkt eine Kopie des Datenraums vom rechten auf +den linken Operanden. Des weiteren gibt es eine DATASPACE Konstante 'nil- +space', die eine leere Datenraum repräsentiert. Mit diesem Wert initialisiert +der Datei-Manager Dateien, die neu kreiert werden. + +Eine neuer Datenraum kann durch + + new ("name") + +eingerichtet werden. 'new' liefert gleichzeitig einen Datenraum und wird +deshalb für Initialisierungen verwandt. Beispiel: + + DATASPACE VAR datenraum :: new ("name1"); (* Kopie ! *) + +Ein bereits vorhandener Datenraum in der Benutzer-Task kann mit + + old ("datei") + +erneut benutzt werden. 'old' liefert (wie 'new') einen DATASPACE, so daß +'old' ebenfalls zur Initialisierung benutzt werden kann. Die Prozedur + + nilspace + +liefert einen leeren Datenraum. + +Für Datenräume gelten zusätzlich einige der Prozeduren wie für FILEs, u.a.: + + forget + fetch + save + rename + +Ausgenommen davon sind Prozeduren, die einen TEXT-File voraussetzen, wie +z.B. 'crypt' und 'decrypt', 'put', 'putline' usw. + +Abschließend soll hier noch auf häufig gemachte Fehler hingewiesen werden: + +Wenn man an ein DATASPACE-Objekt zuweist (z.B.: DATASPACE VAR ds := +new ("mein datenraum")) so erhält man, wie oben 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 +(d.h. im Beispiel, daß die Datenraum 'hugo' nicht verändert wird, hier also +leer bleibt). Für Änderungen in den vom Datei-Manager verwalteten Dateien +ist also stets direkt anzukoppeln, wie es im Beispiel gezeigt wurde. + +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'. +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) (* Datei löschen, damit der Platz wieder verwendet wird *) + +Ein automatisches Löschen von DATASPACE-Objekten erfolgt auch nicht bei +Programmende (sonst könnten sie ihre Funktion als Datei nicht erfüllen). +Erst beim Löschen einer Task werden alle ihr gehörenden DATASPACE-Objekte +freigegeben. Verboten ist weiterhin folgendes: + + BOUND X ...; + +wobei 'X' mit BOUND deklariert wurde oder ein DATASPACE ist. + +Merke: Datenräume können durch 'new' erschaffen werden. Mit 'old' kann ein +bereits vorhandener Datenraum angesprochen werden. Im Übrigen gelten auch +einige der für FILEs vorhandenen Operationen. + + + +Datei-Typen definieren + +Durch die Datenräume und die Datentyp-Definition von ELAN ist es für +Programmierer 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 zeigen wir an dem Beispiel DIRFILE (welcher zwar im +ELAN-Standard definiert, aber nicht im EUMEL-System realisiert ist), wie ein +neuer Datei-Datentyp definiert wird: + + 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 vor- +handenen Datenraum oder richtet einen neuen ein. Um eine Initialisierung mit +der 'dirfile'-Prozedur vornehmen zu können, braucht man auch einen Zu- +weisungsoperator, 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 +benutzen. 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; + ... + +Merke: Neue Datei-Typen für spezielle Anwendungen kann man leicht selbst +programmieren. + + + +6. Beschreibung der Prozeduren + +In diesem Abschnitt werden alle Operationen, die für Dateien zur Verfügung +stehen, aufgeführt. Dabei werden die Operationen für FILEs und Datenräume +mit (F) gekennzeichnet. + ++ + THESAURUS OP + (THESAURUS CONST left, right) + Zweck: Vereinigungsmenge von 'left' und 'right'. + + THESAURUS OP + (THESAURUS VAR left, TEXT CONST name) + Zweck: Nimmt den TEXT 'name' in den Thesaurus 'left' auf. Beispiel: + + save (SOME father + "hugo", archive) + +- + THESAURUS OP - (THESAURUS CONST left, right) + Zweck: Differenzmenge von 'left' und 'right'. + + THESAURUS OP - (THESAURUS VAR left, TEXT CONST name) + Zweck: Liefert einen Thesaurus aus left, aber ohne den Eintrag 'name'. + Beispiel: + + save (ALL myself - "hugo", archive) + +/ + THESAURUS OP / (THESAURUS CONST left, right) + Zweck: Schnittmenge von 'left' und 'right'. + + TASK OP / (TEXT CONST task name) + Zweck: Liefert aus einem Tasknamen den internen Tasknamen. '/' kann über- + all dort eingesetzt werden, wo ein interner Taskname verlangt wird. + +ALL + THESAURUS OP ALL (TASK CONST task) + Zweck: Liefert einen Thesaurus, der alle Dateinamen der angegebenen Task + enthält (auch der Benutzer-Task: 'myself'). + + THESAURUS OP ALL (TEXT CONST file name) + Zweck: Liefert einen Thesaurus, der die in 'file name' vorhandenen Datei- + namen (jede Zeile ein Name) enthält. + +at (F) + BOOL PROC at (FILE VAR f, TEXT CONST word) + Zweck: Abfrage, ob man auf 'word' in der Datei 'f' positioniert ist. + Beispiel: + + ... + down (f, "muster") + IF at (f, "muster") + THEN gefunden + ELSE nicht gefunden + FI; + ... + +archive + PROC archive (TEXT CONST archive name) + Zweck: Anmeldung von Archiv-Operationen. 'archive name' wird zur Über- + prüfung für alle folgenden Archiv-Operationen verwandt, um die + unberechtigte Benutzung eines Archivs zu verhindern. Die Anmeldung + wird abgelehnt, wenn ein anderer Nutzer das Archiv belegt hat. + + TASK PROC archive + Zweck: Liefert den internen Task-Bezeichner für die Verwendung in + Datei-Kommandos. Beispiel: + + save ("datei", archive) + +brother + TASK PROC brother (TASK CONST task) + Zweck: Liefert den internen Task-Bezeichner der angegebenen "Bruder"- + Task. + +check + PROC check (TEXT CONST dateiname, TASK CONST task) + Zweck: Überprüft, ob die Datei 'dateiname' auf dem Archiv lesbar ist. + Beispiel: + + check ("meine datei", archive) + + PROC check (THESAURUS CONST t, TASK CONST task) + Zweck: Überprüft, ob die in dem Thesaurus 't' enthaltenen Dateien auf dem + Archiv lesbar sind. Beispiel: + + check (ALL archive, archive) + +clear + PROC clear (TASK CONST task) + Zweck: Löscht alle Dateien der Task 'task'. Ist z.Z. nur für die Task + 'ARCHIVE' implementiert. + +clear removed (F) + PROC clear removed (FILE VAR f) + Zweck: Löscht die mit 'remove' "vorsichtig" gelöschten Zeilen aus der + Datei 'f' endgültig. + +close (F) + PROC close (FILE VAR file) + Zweck: Schließen der Datei 'file'. Im EUMEL-System ist der Aufruf von + 'close' nicht notwendig. 'close' wurde nur aufgenommen, um die + Kompatibilität zu Standard zu wahren. + +col (F) + PROC col (FILE VAR f, INT CONST position) + Zweck: Positionierung auf die Spalte 'position' innerhalb der aktuellen + Zeile. + + INT PROC col (FILE CONST f) + Zweck: Liefert die aktuelle Position innerhalb der aktuellen Zeile. + +copy (F) + PROC copy (TEXT CONST source, destination) + Zweck: Kopiert die Datei 'source' in eine neue Datei mit dem Namen + 'destination' in der Benutzer-Task. + Fehlerfälle: + * destination file already exists + Eine Datei mit dem Namen 'destination' existiert bereits. + * source file does not exist + Die Ursprungsdatei mit dem Namen 'source' ist nicht vorhanden. + * directory overflow + Die Anzahl der zulässigen Dateien der Benutzer-Task ist über- + schritten. + + PROC copy (DATASPACE CONST ds, TEXT CONST destination) + Zweck: Eintragen eines unbenannten DATASPACE in die Datei-Verwaltung. + Fehlerfälle: + * destination file already exists + Eine Datei mit dem Namen 'destination' existiert bereits. + * directory overflow + Die Anzahl der zulässigen Dateien der Benutzer-Task ist über- + schritten. + +create + PROC create (TEXT CONST name) + Zweck: Erschafft einen neuen Datenraum in der Benutzer-Task. + Fehlerfälle: + * file already exists + Eine Datei mit dem Namen 'name' existiert bereits in der Benutzer- + Task. + * directory overflow + Die Anzahl der zulässigen Dateien der Benutzer-Task ist über- + schritten. + +crypt (F) + PROC crypt (TEXT CONST name, parole) + Zweck: Verschlüsseln des Inhaltes der Datei 'name' mit Hilfe des Textes + 'parole' für Zwecke des Datenschutzes. Die Verschlüsselung ist + umso besser (bzw. umso schwieriger zu "knacken"), je länger der + Text 'parole' ist. Die Datei kann mit der Prozedur 'decrypt' + wieder entschlüsselt werden. + + Eine Datei kann mehrfach verschlüsselt werden. Dabei gilt bei + einer Entschlüsselung das Klammerungsprinzip. Es muß also genau so + oft entschlüsselt werden, wie anfangs verschlüsselt wurde. Dabei + ist auf die richtige Angabe der 'parole'n zu achten. Beispiel: + + crypt ("hugo", "verschluesselung1"); + crypt ("hugo", "verschluesselung2"); + ... + decrypt ("hugo", "verschluesselung2"); + decrypt ("hugo", "verschluesselung1") + + Achtung: 'crypt' und 'decrypt' sind nicht standardmäßig insertiert. + +decrypt (F) + PROC decrypt (TEXT CONST name, parole) + Zweck: Entschlüsselt die Datei 'name' mit Hilfe der angegebenen 'parole'. + Dabei ist darauf zu achten, daß die gleiche 'parole' anzugeben + ist, die verwendet wurde, um die Datei zu verschlüsseln (sonst + wirkt 'decrypt' wie ein erneuter Aufruf von 'crypt').Beim mehr- + fachen Ver- und Entschlüsseln ist das Klammerungsprinzip zu be- + achten (dazu vergl. 'crypt'). + +delete record (F) + PROC delete record (FILE VAR file) + Zweck: Der aktuelle Satz der Datei 'file' wird gelöscht. Der folgende + Satz wird der aktuelle Satz. Die Datei 'file' muß mit der Verar- + beitungsart 'modify' assoziiert worden sein. + +do + PROC do (PROC (TEXT CONST) operate, THESAURUS CONST thesaurus) + Zweck: Ruft 'operate' mit allen im 'thesaurus' enthaltenen Dateinamen + nacheinander auf. Man beachte, daß bei Prozedur-Parametern der + Name der Prozedur hinter dessen Parametern geschrieben wird. + Beispiel: + + do (PROC (TEXT CONST) reorganize, ALL myself) + + PROC do (PROC (TEXT CONST, TASK CONST) operate, + THESAURUS CONST thesaurus, TASK CONST task) + Zweck: S.o.. Dabei ist zu beachten, daß 'task' als zweiter Parameter in + der Prozedur 'operate' eingesetzt wird. Beispiel: + + do (PROC (TEXT CONST, TASK CONST) save, + SOME myself, father) + (* enspricht: *) + save (SOME myself, father) + +down (F) + PROC down (FILE VAR f) + Zweck: Positionieren um eine Zeile vorwärts in der Datei 'f'. + + PROC down (FILE VAR f, INT CONST number) + Zweck: Positionieren um 'number' Zeilen vorwärts in der Datei 'f'. + + PROC down (FILE VAR f, TEXT CONST pattern) + Zweck: Suche nach 'pattern' in der Datei 'f'. Wird 'pattern' gefunden, + ist die Position das erste Zeichen von 'pattern'. Andernfalls + steht man hinter dem letzten Zeichen der Datei. Achtung: 'down' + sucht vom nächsten Zeichen rechts ab, so daß wiederholtes Suchen + keine Endlosschleife ergibt. + + PROC down (FILE VAR f, TEXT CONST pattern, INT CONST number) + Zweck: Wie obiges 'down', aber maximal nur 'number'-Zeilen weit. + +downety (F) + PROC downety (FILE VAR f, TEXT CONST pattern) + Zweck: Suche nach 'pattern' in der Datei 'f'. Wird 'pattern' gefunden, + ist die Position das erste Zeichen von 'pattern'. Andernfalls + steht man auf dem letzten Zeichen der Datei. Achtung: 'downety' + sucht (im Gegensatz zu 'down') vom aktuellen Zeichen. + + PROC downety (FILE VAR f, TEXT CONST pattern, INT CONST number) + Zweck: Wie obiges 'downety', aber maximal nur 'number'-Zeilen weit. + +enter password + PROC enter password (TEXT CONST password) + Zweck: Einstellen eines Paßwortes in der Benutzer-Task für den Datei- + Verkehr mit einer Vater-Task. Der Parameter 'password' kann dabei + aus zwei Teilen bestehen, die durch ein "/"-Zeichen getrennt + werden müssen. Der erste Teil bedeutet das schreib-Passwort, + während der TEXT nach dem "/"-Zeichen das Lese-Paßwort beinhaltet. + Enthält der Parameter 'password' kein "/"-Zeichen, gilt der ange- + gebene TEXT sowohl für das Schreib- wie auch für das Lese-Paßwort. + Im Schreib- bzw. Lese-Teil des Paßworts kann man das "-"-Zeichen + angeben, um eine Datei vor überschreibendem oder lesendem Zugriff + zu schützen. + + Die Paßwort-Überprüfung findet statt bei + + - fetch (Überprüfung der Lese-Berechtigung) + - save (Überprüfung der Schreib-Berechtigung) + - erase (Überprüfung der Schreib-Berechtigung) + +eof (F) + BOOL PROC eof (FILE CONST file) + Zweck: Informationsprozedur auf das Ende eines FILEs. Liefert den Wert + TRUE, sofern hinter den letzten Satz eines FILEs positioniert + wurde. + +erase + PROC erase (TEXT CONST name) + Zweck: Löscht eine Datei mit dem Namen 'name' in der unmittelbaren + Vater-Task. + Fehlerfälle: + * ... gibt es nicht + Eine Datei mit dem Namen 'name' existiert in der unmittelbaren + Vater-Task nicht. + * wrong password + Es wurde mit der Prozedur 'enter password' nicht das richtige + Paßwort angegeben. + + PROC erase (TEXT CONST name, TASK CONST task) + Zweck: Löscht eine Datei mit dem Namen 'name' in der Task 'task'. Bei- + spiel: + + erase ("meine datei", father) + + PROC erase (THESAURUS CONST thesaurus) + Zweck: Löscht die im 'thesaurus' angegebenen Dateien in der Vater-Task. + Beispiel (löscht alle Dateien in der Vater-Task, die in der Benut- + zer-Task vorhanden sind): + + erase (ALL myself) + + PROC erase (THESAURUS CONST thesaurus, TASK CONST manager) + Zweck: S.o.. + +exists (F) + BOOL PROC exists (TEXT CONST name) + Zweck: Informationsprozedur zur Abfrage der Existenz einer Datei in der + Benutzer-Task. Beispiel: + + IF exists ("dateiname") + THEN FILE VAR f :: sequential file ...; + ELSE errorstop ("Datei existiert nicht") + FI + +father + TASK PROC father + Zweck: Liefert den internen Task-Bezeichner der Vater-Task der Benutzer- + Task. Beispiel: + + save ("datei", father) + + TASK PROC father (TASK CONST task) + Zweck: Liefert den internen Task-Bezeichner von 'task'. Beispiel: + + save ("datei", father (father)) (* Kopiert 'datei' zum "Opa" *) + +fetch + PROC fetch (TEXT CONST name) + Zweck: Einbringen einer Datei in die Benutzer-Task von dem "direkten" + Vater im Taskbaum. + Fehlerfälle: + * ... gibt es nicht + Die Datei existiert bei dem Vater nicht. + * directory overflow + Die Anzahl der zulässigen Dateien der Benutzer-Task ist über- + schritten. + * wrong password + Es wurde mit der Prozedur 'enter password' nicht das richtige + Paßwort angegeben. + + PROC fetch (TEXT CONST name, TASK CONST task) + Zweck: Kopieren einer Datei in die Benutzer-Task von 'task'. Beispiel: + + fetch ("datei", public) + + PROC fetch (THESAURUS CONST thesaurus) + Zweck: Holt alle im 'thesaurus' enthaltenen Dateien von der Vater-Task. + + PROC fetch (THESAURUS CONST thesaurus, TASK CONST manager) + Zweck: Holt alle im 'thesaurus' enthaltenen Dateien von der 'manager'- + Task. + +forget (F) + PROC forget (TEXT CONST name) + Zweck: Löschen einer Datei mit dem Namen 'name' in der Benutzer-Task. + Fehlerfälle: + * ... gibt es nicht + Die Datei mit dem Namen 'name' existiert nicht in der Benutzer- + Task. + + PROC forget (DATASPACE VAR ds) + Zweck: Löschen des Datenraums 'ds'. + + PROC forget (THESAURUS CONST thesaurus) + Zweck: Löscht die im 'thesaurus' enthaltenen Dateinamen in der Benutzer- + Task. Beispiel: + + forget (SOME myself) + + PROC forget (TEXT CONST file name, QUIET CONST q) + Zweck: Löschen der Datei 'file name' ohne Anfrage. Als zweiter Parameter + muß 'quiet' übergeben werden. Beispiel: + + forget ("hugo", quiet) + +get (F) + PROC get (FILE VAR f, INT VAR number) + Zweck: Lesen eines INT-Wertes 'number' von der Datei 'f'. + + PROC get (FILE VAR f, REAL VAR number) + Zweck: Lesen eines REAL-Wertes 'number' von der Datei 'f'. + + PROC get (FILE VAR f, TEXT VAR text) + Zweck: Lesen eines TEXT-Wertes 'text' von der Datei 'f'. + + PROC get (FILE VAR f, TEXT VAR text, TEXT CONST delimiter) + Zweck: Lesen eines TEXT-Wertes 'text' von der Datei 'f', bis das Zeichen + 'delimiter' angetroffen wird. Ein eventueller Zeilenwechsel in der + Datei wird dabei nicht übergangen. + + PROC get (FILE VAR f, TEXT VAR text, INT CONST maxlength) + Zweck: Lesen eines TEXT-Wertes 'text' von der Datei 'f' mit 'maxlength' + Zeichen. Ein eventueller Zeilenwechsel in der Datei wird dabei + nicht übergangen. + +getline (F) + PROC get line (FILE VAR file, TEXT VAR record) + Zweck: Lesen einer Zeile 'record' von einer sequentiellen Datei 'file'. + Die Datei muß mit 'input' assoziiert sein (vergl. 'sequential + file'). + Fehlerfälle: + * file not open + Die Datei 'file' ist gegenwärtig nicht assoziiert. + * input after end of file + Es wurde versucht, über die letzte Zeile einer Datei zu lesen. + * input access to output file + Es wurde versucht, von einem mit 'output' assoziierten FILE zu + lesen. + +global manager + PROC global manager + Zweck: Durch den Aufruf der Prozedur wird die Benutzer-Task zu einem + Datei-Manager. Danach können Söhne dieser Task eingerichtet + werden. + +input (F) + PROC input (FILE VAR f) + Zweck: Ändern der Verarbeitungsart von 'modify' oder 'output' in 'input'. + Dabei wird auf den ersten Satz der Datei positioniert. + + TRANSPUTDIRECTION CONST input + Zweck: Assoziierung in Zusammenhang mit der Prozedur 'sequential file' + einer sequentiellen Datei mit der 'TRANSPUTDIRECTION' 'input' (nur + lesen). + +insert record (F) + PROC insert record (FILE VAR file) + Zweck: Es wird ein leerer Satz in die Datei 'file' vor die aktuelle + Position eingefügt. Dieser Satz kann anschließend mit 'write + record' beschrieben werden (d.h. der neue Satz ist jetzt der + aktuelle Satz). Die Datei 'file' muß mit der Verarbeitungsart + 'modify' assoziiert worden sein. + +line no (F) + INT PROC line no (FILE CONST file) + Zweck: Liefert die aktuelle Zeilennummer. + +line (F) + PROC line (FILE VAR file) + Zweck: Positionierung auf die nähhste Zeile der Datei 'file'. Die Datei + 'file' darf mit 'output' oder 'input' assoziiert sein. Wird ver- + sucht, über das Ende eines mit 'input' assoziierten FILEs zu + positionieren, wird keine Aktion vorgenommen. + + PROC line (FILE VAR file, INT CONST lines) + Zweck: Positionierung auf 'lines' nächste Zeilen der Datei 'file'. Die + Datei 'file' darf mit 'output' oder 'input' assoziiert sein. Wird + versucht, über das Ende eines mit 'input' assoziierten FILEs zu + positionieren, wird keine Aktion vorgenommen. Ist 'lines' <= 0, + wird keine Aktion durchgeführt. + +lines (F) + PROC lines (FILE VAR f) + Zweck: Liefert die Anzahl der Zeilen der Datei 'f'. + +list + PROC list + Zweck: Listet alle Dateien der Benutzer-Task mit Namen und Datum des + letzten Zugriffs auf dem Terminal auf. + + PROC list (FILE VAR f) + Zweck: Schreibt alle Dateien der Benutzer-Task mit Namen und Datum der + letzten Änderung in die Datei 'f'. + + PROC list (TASK CONST task) + Zweck: Listet alle Dateien der angegebenen 'task' mit Namen und Datum der + letzten Änderung auf dem Terminal auf. Beispiel: + + list (father) + +max line length (F) + INT PROC max line length (FILE CONST file) + Zweck: Informationsprozedur über die Anzahl von Zeichen in einer Zeile + der Datei 'file'. Standardmäßig sind die Anzahl der Zeichen einer + Zeile wie beim Editor 77 Zeichen. + + PROC max line length (FILE VAR file, INT CONST number) + Zweck: Setzen der Anzahl von Zeichen einer Zeile in dem FILE 'file'. + +modify (F) + TRANSPUTDIRECTION CONST modify + Zweck: Diese Betriebsrichtung erlaubt das Vorwärts- und Rückwärts-Posi- + tionieren und das beliebige Einfügen und Löschen von Sätzen. + 'modify' wird für die Assoziierungsprozedur 'sequential file' + benötigt. + + PROC modify (FILE VAR f) + Zweck: Ändern der Betriebsrichtung von 'input' oder 'output' in die Be- + triebsrichtung 'modify'. + +myself + TASK PROC myself + Zweck: Liefert den internen Task-Bezeichner der Benutzer-Task. Beispiel: + + save (ALL myself, father) + +name + TEXT PROC name (TASK CONST task) + Zweck: Liefert den TEXT-Namen von 'task'. Beispiel: + + put (name (myself)) + +new (F) + DATASPACE PROC new (TEXT CONST name) + Zweck: Richtet eine neue Datei in der Benutzer-Task ein. + Fehlerfälle: + * file already exists + Die Datei mit dem Namen 'name' existiert bereits in der Benutzer- + Task. + * directory overflow + Die Anzahl der zulässigen Dateien in der Benutzer-Task ist über- + schritten. + +nilspace (F) + DATASPACE CONST nilspace + Zweck: Liefert einen leeren Datenraum. + +old (F) + DATASPACE PROC old (TEXT CONST name) + Zweck: Eine bereits vorhandene Datei der Benutzer-Task wird erneut zur + Bearbeitung angemeldet. + Fehlerfälle: + * ... gibt es nicht + Die Datei mit dem Namen 'name' ist nicht in der Benutzer-Task + vorhanden. + +output (F) + PROC output (FILE VAR file) + Zweck: Ändern der Verarbeitungsart von 'input' oder 'modify' in 'output'. + Dabei wird hinter den letzten Satz der Datei positioniert. + + TRANSPUTDIRECTION CONST output + Zweck: In Verbindung mit der Prozedur 'sequential file' kann eine Datei + assoziiert werden mit der Betriebsrichtung 'output' (nur + schreiben). + +pattern found + BOOL PROC pattern found + Zweck: Liefert TRUE, sofern die letzte Suchoperation (siehe 'down' und + 'up') erfolgreich war, sonst FALSE. + +printer + TASK PROC printer + Zweck: Liefert den internen TASK-Bezeichner der SPOOLer-Task für den + Drucker. Beispiel: + + save ("datei", printer) + +public + TASK PROC public + Zweck: Liefert den internen Task-Bezeichner von "PUBLIC". Beispiel: + + fetch ("datei", public) + +put (F) + PROC put (FILE VAR f, INT CONST number) + Zweck: Ausgabe eines INT-Wertes 'number' in die Datei 'f'. Dabei wird ein + Leerzeichen an die Ausgabe angefügt. + + PROC put (FILE VAR f, REAL CONST number) + Zweck: Ausgabe eines REAL-Wertes 'number' in die Datei 'f'. Dabei wird + ein Leerzeichen an die Ausgabe angefügt. + + PROC put (FILE VAR f, TEXT CONST text) + Zweck: Ausgabe eines TEXT-Wertes 'text' in die Datei 'f'. Dabei wird ein + Leerzeichen an die Ausgabe angefügt. + +putline (F) + PROC putline (FILE VAR file, TEXT CONST record) + Zweck: Ausgabe eines TEXTes 'record' in die Datei 'file'. 'file' muß mit + 'output' assoziiert sein. + Fehlerfälle: + * file not open + Die Datei 'file' ist gegenwärtig nicht assoziiert. + * output access to input file + Es wurde versucht, auf einen mit 'input' assoziierten FILE zu + schreiben. + +read record (F) + PROC read record (FILE CONST file, TEXT VAR record) + Zweck: Liest den aktuellen Satz der Datei 'file' in den TEXT 'record'. + Die Position wird dabei nicht verändert. Die Datei 'file' muß mit + der Verarbeitungsart 'modify' assoziiert worden sein. + +reinsert (F) + PROC reinsert (FILE VAR f) + Zweck: Einfügen von "vorsichtig gelöschten" Zeilen (vergl. 'remove') an + der aktuellen Position. + +release + PROC release (TASK CONST task) + Zweck: Aufgabe der Reservierung des Archivs. Ein implizites 'release' + wird automatisch fünf Minuten nach der letzten Archiv-Operation + gegeben, sofern ein 'archive' eines anderen Nutzers vorliegt. + Beispiel: + + release (archive) + +rename (F) + PROC rename (TEXT CONST oldname, newname) + Zweck: Umbenennen einer Datei von 'oldname' in 'newname'. + +remainder + THESAURUS PROC remainder + Zweck: Liefert nach der Unterbrechung einer Thesaurus-Operation den + "Rest"-Thesaurus. + +reorganize (F) + PROC reorganize (TEXT CONST filename) + Zweck: Reorganisiert eine Datei. Die durch eventuelles Einfügen und + Löschen entstandene Lücken werden eliminiert und die Anordung der + Sätze der Datei wird linearisiert. + +reset (F) + PROC reset (FILE VAR file) + Zweck: Positionieren in einem FILE auf den Anfang (bei mit 'input' asso- + ziierten FILEs) oder auf das Ende (bei mit 'output' assoziierten + FILEs). + +reset range (F) + PROC reset range (FILE VAR file) + Zweck: Setzt alle Einschränkungen auf 'file' zurück. Siehe auch 'set + range'. + +remove (F) + PROC remove (FILE VAR f, INT CONST anzahl) + Zweck: Löscht eine 'anzahl' von Zeilen "vorsichtig" aus der Datei 'f', + die mit 'reinsert' an anderer Stelle wieder eingesetzt werden + können. + +save + PROC save (TEXT CONST datei) + Zweck: Datei 'datei' wird an die unmittelbare Vater-Task übertragen. + Fehlerfälle: + * ... gibt es nicht + Eine Datei mit dem Namen 'datei' existiert nicht in der Benutzer- + Task. + * directory overflow + Die Anzahl der zulässigen Dateien in 'task' ist überschritten. + * wrong password + Es wurde mit der Prozedur 'enter password' nicht das richtige + Paßwort angegeben. + + PROC save (TEXT CONST name, TASK CONST task) + Zweck: Datei mit dem Namen 'name' in Task 'task' kopieren. Beispiel: + + save ("meine datei", father) + + Fehlerfälle: + * ... gibt es nicht + Eine Datei mit dem Namen 'name' existiert nicht in der Benutzer- + Task. + * directory overflow + Die Anzahl der zulässigen Dateien in der angegebenen task ist + überschritten. + * wrong password + Es wurde mit der Prozedur 'enter password' nicht das richtige + Paßwort angegeben. + + PROC save (THESAURUS CONST thesaurus) + Zweck: Kopiert die Dateien, die in 'thesaurus' enthalten sind, in die + Vater-Task. Beispiel: + + save (SOME myself) + + PROC save (THESAURUS CONST thesaurus, TASK CONST manager) + Zweck: Kopiert die Dateien, die in 'thesaurus' enthalten sind, in Task + 'manager'. + +segments (F) + INT PROC segments (FILE CONST f) + Zweck: Liefert die Anzahl der Datei-Segmente von 'f'. Nach 'reorganize' + besteht 'f' aus einem Segment. Einfügungen oder Löschungen + erhöhen die Segmentanzahl. + +sequential file (F) + FILE PROC sequential file (TRANSPUTDIRECTION CONST mode, DATASPACE VAR ds) + Zweck: Assoziierung einer sequentiellen Datei mit dem Dataspace 'ds' und + der Betriebsrichtung 'TRANSPUTDIRECTION' (vergl. 'modify', 'input' + bzw. 'output'). Diese Prozedur dient zur Assoziierung eines tempo- + rären Datenraums in der Benutzer-Task, der nach der Beendigung + des Programmlaufs nicht mehr zugriffsfähig ist (weil der Name des + Datenraums nicht mehr ansprechbar ist). Somit muß der Datenraum + explizit vom Programm gelöscht werden. + + FILE PROC sequential file (TRANSPUTDIRECTION CONST mode, TEXT CONST name) + Zweck: Assoziierung einer sequentiellen Datei mit dem Namen 'name' und + der Betriebsrichtung 'TRANSPUTDIRECTION' (vergl. 'input' bzw. + 'output'). Existiert der FILE bereits, dann wird mit 'input' auf + den Anfang des FILEs, bei 'output' hinter den letzten Satz der + Datei positioniert. Existiert dagegen der FILE noch nicht und ist + die TRANSPUTDIRECTION 'output', wird ein neuer FILE eingerichtet. + Fehlerfall: + * input file not existing + Es wurde versucht, einen nicht vorhandenen FILE mit 'input' zu + assoziieren. + +set range (F) + PROC set range (FILE VAR f, INT CONST anz, INT CONST column, FRANGE VAR b) + Zweck: Schränkt die Datei 'f' auf 'anz' Zeilen beginnend bei der Position + 'column' der aktuellen Zeile. Der "alte" Datei-Bereich wird in 'b' + gespeichert. + + PROC set range (FILE VAR f, FRANGE VAR b) + Zweck: Setzt die Datei 'f' auf die in 'b' gespeicherten Bereich zurück. + +son + TASK PROC son (TASK CONST task) + Zweck: Liefert den internen Task-Bezeichner der Sohn-Task. Beispiel: + + put (name (son (myself))) + +SOME + THESAURUS OP SOME (THESAURUS CONST thesaurus) + Zweck: Bietet den angegebenen 'thesaurus' zum Editieren an. Dabei können + nicht erwünschte Namen gestrichen werden. + + THESAURUS OP SOME (TASK CONST task) + Zweck: Bietet einen THESAURUS von 'task' zum Editieren an. + + THESAURUS OP SOME (TEXT CONST file name) + Zweck: Bietet einen 'thesaurus', der aus 'file name' gebildet wird, zum + editieren an. + +to line (F) + PROC to line (FILE VAR f, INT CONST number) + Zweck: Positionierung auf die Zeile 'number'. Nur erlaubt in der + Betriebsrichtung 'modify'. + +task + TASK PROC task (TEXT CONST task name) + Zweck: Liefert den internen Task-Bezeichner von 'task name'. Beispiel: + + save ("datei", task ("PUBLIC")) + + (* das gleiche wie: *) + + save ("datei", public) + +type (F) + INT PROC type (DATASPACE CONST ds) + Zweck: Liefert den frei wählbaren (INT-) Schlüssel des Datenraums 'ds'. + Wurde der Datenraum noch nie angekoppelt, so liefert die Prozedur + 'type' einen Wert < 0, erfolgte eine Ankopplung und hat ein + Programmierer für den Datenraum 'ds' noch keinen anderen Schlüssel + festgelegt, so liefert 'type' den Wert '0'. + + PROC type (DATASPACE CONST ds, INT CONST type) + Zweck: Setzt den frei wählbaren Schlüssel 'type' für den Datenraum 'ds' + (vergl. obige Prozedur 'type'). + +up (F) + PROC up (FILE VAR f) + Zweck: Positionieren um eine Zeile rückwärts in der Datei 'f'. + + PROC up (FILE VAR f, INT CONST number) + Zweck: Positionieren um 'number' Zeilen rückwärts in der Datei 'f'. + + PROC up (FILE VAR f, TEXT CONST pattern) + Zweck: Suche nach 'pattern' rückwärts in der Datei 'f'. Wird 'pattern' + gefunden, ist die Position das erste Zeichen von 'pattern'. + Andernfalls steht man auf dem ersten Zeichen der Datei. Achtung: + 'down' sucht vom nächsten Zeichen links ab, so daß wiederholtes + Suchen keine Endlosschleife ergibt. + + PROC up (FILE VAR f, TEXT CONST pattern, INT CONST number) + Zweck: Wie obiges 'up', aber maximal nur 'number'-Zeilen weit. + +uppety (F) + PROC uppety (FILE VAR f, TEXT CONST pattern) + Zweck: Suche nach 'pattern' rückwärts in der Datei 'f'. Wird 'pattern' + gefunden, ist die Position das erste Zeichen von 'pattern'. + Andernfalls steht man auf dem ersten Zeichen der Datei. Achtung: + 'uppety' sucht (im Gegensatz zu 'up') vom aktuellen Zeichen. + + PROC uppety (FILE VAR f, TEXT CONST pattern, INT CONST number) + Zweck: Wie obiges 'uppety', aber maximal nur 'number'-Zeilen weit. + +word (F) + TEXT PROC word (FILE CONST f) + Zweck: Liefert das aktuelle Wort (bis zum nächsten Leerzeichen oder + Zeilenende). + + TEXT PROC word (FILE CONST f, TEXT CONST sep) + Zweck: Liefert einen Text von der aktuellen Position bis zum nächsten + 'sep-Zeichen oder Zeilenende. + + TEXT CONST word (FILE CONST f, INT CONST len) + Zweck: Liefert einen Text von der aktuellen Position mit der Länge 'len' + bzw. bis zum Zeilenende. + +write (F) + PROC write (FILE VAR f, TEXT CONST text) + Zweck: Schreibt 'text' in die Datei 'f' (analog 'put (f, text)'), aber + ohne Trennblank. + +write record (F) + PROC write record (FILE VAR file, TEXT CONST record) + Zweck: Schreibt einen Satz in die Datei 'file' an die aktuelle Position. + Dieser Satz muß bereits vorhanden sein, d.h. mit 'write record' + kann keine leere Datei beschrieben werden, sondern es wird der + Satz an der aktuellen Position überschrieben. Die Position in der + Datei wird nicht verändert. Die Datei 'file' muß mit der Verar- + beitungsart 'modify' assoziiert worden sein. + + diff --git a/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil8 b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil8 new file mode 100644 index 0000000..16e4d07 --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil8 @@ -0,0 +1,1345 @@ + EUMEL-Benutzerhandbuch + + TEIL 8: Standardpakete + + +1. Übersicht + +Hier werden die im EUMEL-System verfügbaren Prozeduren und Operatoren aufge- +führt, die nicht bereits in anderen Teilen des Benutzerhandbuchs beschrieben +wurden. + +Die meisten der hier beschriebenen Objekte werden nicht vom ELAN-Compiler, +sondern von vorübersetzten Moduln (PACKETs) realisiert (vergl. dazu auch den +Quellcode). Die in diesem Teil beschriebenen Prozeduren und Operatoren +weisen einige wenige Modifikationen, aber beträchtliche Erweiterungen gegen- +über dem Standard auf, um sie für die Zwecke des EUMEL-Systems anzupassen. +Hier werden nur diejenigen Objekte aufgeführt, die bei einer System-Aus- +lieferung dem EUMEL-System beigefügt sind. Jeder Installation ist es frei- +gestellt, diesen "EUMEL-Standard" zu erweitern oder zu modifizieren. + +Die Operationen des EUMEL-Standards lassen sich in verschiedene Klassen - +je nach Aufgabenbereich - ordnen. + + + +Ein-/Ausgabe + +Die Ein-/Ausgabe erfolgt im EUMEL-System in der Regel auf dem Terminal des +Benutzers. Sie kann aber auch in einen File umgeleitet werden. + +Die Ein-/Ausgabe eines Programms erfolgt in der Regel auf dem Terminal des +Benutzers, welches einem Prozeß zugeordnet ist. Die Eingabe vom Bildschirm +kann man mit den Prozeduren + + get + +programmieren, welche INT, REAL und TEXT-Werte einlesen. Bei der Eingabe +kann der Eingabetext editiert werden (Zeichen löschen, einfügen, über- +schreiben oder Lernsequenzen abrufen). Die Ausgabe erfolgt mit den Proze- +duren + + put + +(für INT-, REAL- und TEXT-Werte). Von den 'put'-Prozeduren wird ein Leer- +zeichen an eine Ausgabe angefügt, um diese von der vorhergehenden zu trennen. +Zusätzlich existiert die + + write + +Prozedur, welche an die Ausgabe kein Leerzeichen anfügt. Mit + + line + +kann man eine Positionierung auf eine neue Zeile bei der Ein-/Ausgabe er- +wirken. Mit + + getline + putline + +kann eine ganze Zeile eingelesen bzw. ausgegeben werden. + +Wie bereits erwähnt, erfolgt die Ein-/Ausgabe in der Regel auf dem Terminal +des Benutzers. Es ist jedoch möglich, die Ein-/Ausgabe dieser Prozeduren +"umzuleiten". Diese Umleitung erfolgt in eine oder von einer Datei. Dazu +gibt es die Prozeduren + + online (* liefert TRUE, wenn die Task an ein Terminal + gekoppelt ist *) + sysout ("name") (* Ausgabe erfolgt in die Datei 'name'. 'sysout + ("")' schaltet auf das Terminal zurück *) + sysout (* Liefert den Namen der eingestellten 'sysout'- + Datei. Wird "" geliefert, ist man an ein + Terminal gekoppelt *) + sysin ("name") (* Umschaltung der Eingabe vom Terminal auf die + Datei 'name'. sysin ("")' schaltet auf das + Terminal zurück *) + sysin (* Liefert den Namen der eingestellten 'sysin'- + Datei. Wird "" geliefert, ist man an ein + Terminal gekoppelt *) + +Wie bereits erwähnt, ist die Umschaltung nur für die Prozeduren 'get' und +'put'/'write', sowie 'getline' und 'putline' und die Prozedur 'line' möglich. +(Die folgenden Prozeduren haben immer eine Wirkung auf das Benutzer- +Terminal). Die Prozedur + + out + +schreibt wie 'write' einen Text auf den Bildschirm (läßt sich aber nicht +"umleiten"). + + cout + +schreibt einen INT-Wert an die aktuelle Cursor-Position auf den Bildschirm +und positioniert anschließend auf diese Position wieder zurück. Diese +Prozedur wird vorwiegend für Kontroll-Ausgaben (z.B. Zeilennummern) benutzt. +Ist die Task nicht angekoppelt, geht die Ausgabe ins "Leere"; das Programm +der Task läuft also weiter (im Gegensatz zu 'put' auf den Bildschirm). Mit +der Prozedur + + cursor + +kann - neben der Möglichkeit des Arbeitens mit Steuerzeichen - auf eine +bestimmte Position des Bildschirms positioniert werden. Mit + + get cursor + +kann die aktuelle Position des Cursors auf dem Terminal des Benutzers er- +fragt werden. Mit Hilfe der Prozedur + + inchar + +kann ein Zeichen vom Bildschirm gelesen werden. Der Prozeß wartet solange, +bis ein Zeichen eingegeben wird. Dagegen wird bei + + incharety + +niltext geliefert, wenn kein Zeichen eingegeben wurde. Eine weitere 'inchare- +ty'-Prozedur wartet zusätzlich noch eine angebbare Zeitdauer, ob ein Zeichen +eingegeben wird. Der Operator + + TIMESOUT + +stellt einen TEXT mehrfach auf dem Bildschirm dar. Die Prozedur + + page + +positioniert auf einen "neuen Bildschirm": der Bildschirm wird gelöscht und +der Cursor befindet sich anschließend in der linken oberen Ecke des Bild- +schirms. + + + +Manipulation von Texten + +Ein Text kann im EUMEL-System bis zu 32 000 Zeichen haben. Für TEXTe +stehen neben der Zuweisung die Vergleichsoperatoren + + = , < , <= , > , >= , <> + +zur Verfügung. Dabei ist die lexikographische Reihenfolge der Zeichen (vergl. +EUMEL-Zeichensatz) zu beachten. Zur Verkettung zweier TEXTe ist der + + + + +Operator vorhanden. Der Operator + + * + +nimmt eine Vervielfachung eines TEXTes vor. Der Operator + + CAT + +konkateniert den linken mit dem rechten Operanden und weist das Resultat dem +linken Operanden zu. Die Prozeduren + + pos + +liefern die Position des ersten Auftretens eines TEXTes oder einer +Zeichenklasse in einem anderen TEXT. Die Prozeduren + + code + +konvertieren ein Zeichen in einen INT-Wert und umgekehrt (vergl. dazu den +EUMEL-Zeichensatz) und dienen z.B. zur Behandlung von Zeichen, die nicht +auf einer Tastatur zu finden sind. Die Prozedur + + compress + +schneidet führende und nachfolgende Leerzeichen eines TEXTs ab, während + + delete char (* ein Zeichen loeschen *) + insert char (* ein Zeichen einfuegen *) + +ein Zeichen einfügt bzw. löscht. Mit + + change + +kann bei dem erstmaligen Auftreten eines Teiltextes in einem TEXT dieser +ersetzt werden. Mit + + change all + +kann jedesmal, wenn ein Teiltext in einem TEXT auftritt, dieser durch einen +anderen Text ersetzt werden. + + LENGTH (* oder *) + length + +liefert die Länge (d.h. die Anzahl der Zeichen in einem TEXT einschließlich +der Leerzeichen) eines TEXTes. Mit + + replace + +kann eine Ersetzung eines Teiltextes erzielt werden. Im Gegensatz zu +'replace' kann sich bei 'change' die Länge des Textes ändern. Mit + + SUB + subtext + +kann ein Zeichen ('SUB') oder ein Teiltext ('subtext') aus einem Text geholt +werden. + +TEXTe werden im EUMEL-System über einen Heap realisiert, d.h. nicht wie +andere Objekte auf einem Stack. Das hat u.a. zur Folge, daß TEXT-"Leichen" +auf dem Heap nicht automatisch beseitigt werden. Darum kann der benötigte +Speicherplatz durch TEXT-Operationen anwachsen. Der Heap kann nun von +unnötigem Speicherplatz durch die Prozedur + + collect heap garbage + +bereinigt werden. Die Größe des Heaps (in KB) kann durch die Prozedur + + heap size + +erfragt werden. Übrigens überprüft der Standard-Monitor nach jedem Kommando +die Heap-Größe und veranlaßt eine Bereinigung des Heaps, wenn dieser um +mindestens 4 KB gewachsen ist. + + + +Mathematische Operationen + +Folgende mathematische Prozeduren bzw. Operatoren stehen im EUMEL zur Zeit +zur Verfügung (manche Prozeduren stehen in mehr als einer Version zur +Verfügung, z.B. die sin-Prozedur für Radiant und Winkelgrad): + + ** (* Exponentiation *) + abs (* Absolutbetrag *) + arctan (* Arcus Tangens-Funktion *) + cos (* Kosinus-Funktion *) + e (* Eulersche Zahl (2.718282) *) + pi (* Die Zahl pi (3.141593) *) + exp (* Exponential-Funktion *) + floor (* REAL mit abgeschnittenen Nachkommastellen *) + frac (* Nachkommastellen eines REALs *) + random, + initialize random (* Zufallszahlen *) + ln, log2, log10 (* Logarithmus-Funktionen *) + max, min (* Minimum bzw. Maximum zweier Werte *) + MOD (* Modulo-Funktion *) + round (* Rundung *) + sign (* Vorzeichen feststellen *) + sin (* Sinus-Funktion *) + sqrt (* Wurzel-Funktion *) + tan (* Tangens-Funktion *) + + + +Konvertierungs-Operationen + +Mit den Prozeduren + + text + +kann aus einem INT- bzw. REAL-Wert ein TEXT, während mit + + int + +aus einem REAL- bzw. TEXT-Wert ein INT und mit + + real + +aus einem INT- bzw. TEXT-Wert ein REAL gemacht werden kann. Mit + + last conversion ok + +kann abgefragt werden, ob die letzte Umwandlung ohne Fehler bzw. fehlerhaft +vorgenommen wurde. Mit + + decimal exponent + +kann der Exponent eines REAL-Wertes ausgeblendet werden. + + + +Kommando-Dialog + +Die Prozeduren für den Kommando-Dialog dienen zur bequemen Programmierung +von interaktiven Anfragen an einen Benutzer eines Programms. (Diese +Prozeduren werden u.a. auch vom Monitor verwendet). Der Kommando-Dialog +ist im Normalfall eingeschaltet. Mit der Prozedur + + command dialogue + +kann man den Kommando-Dialog ein- bzw. ausschalten. Mit der Prozedur + + say + +kann - sofern der Kommando-Dialog eingeschaltet ist - ein Text auf dem +Bildschirm ausgegeben werden. Sofern der Kommando-Dialog eingeschaltet ist, +schreibt die Prozedur + + yes + +einen Text auf den Bildschirm des Benutzers. An den Text wird '(j/n) ?' +angefügt. Die Prozedur 'yes' liefert den Wert TRUE, sofern der Benutzer auf +die Frage mit dem Zeichen "j" antwortet und den Wert FALSE, sofern die +Antwort "n" lautete. Die Prozedur + + no + +arbeitet wie 'NOT yes'. + + + +Verschiedenes + +Mit den Prozeduren + + stop + errorstop + +kann ein Abbruch (letztere mit Meldung; vergl. Fehlerbehandlung im System- +handbuch) erreicht werden. Die Prozedur + + clock + +liefert Zeitwerte als REAL-Wert, nämlich die verbrauchte CPU-Zeit einer Task +oder die aktuelle Uhrzeit (inklusive Datum). Die Prozedur + + time of day + +liefert die aktuelle Uhrzeit. Mit den Konvertierungsprozeduren + + date + time + +können die Werte der Prozedur 'clock' in eine lesbare Form gebracht werden. +Mit der Prozedur + + pause + +kann eine bestimmte Zeitdauer gewartet werden, ohne den Prozessor zu be- +lasten. Die Wartezeit wird abgebrochen, wenn die Zeitgrenze erreicht ist +oder sobald ein Zeichen am Terminal des Benutzers eingegeben wurde. Dieses +Zeichen wird nicht verarbeitet. + + + +2. Die EUMEL-Standardpakete + +Die elementaren Datentypen BOOL, INT, REAL, TEXT und die entsprechenden Zu- +weisungsoperatoren werden hier nicht angegeben. + += + BOOL OP = (INT CONST a, b) + Zweck: Vergleich. + + BOOL OP = (REAL CONST a, b) + Zweck: Vergleich. + + BOOL OP = (TEXT CONST left, right) + Zweck: Vergleich von zwei Texten auf Gleichheit (Texte mit ungleichen + Längen sind immer ungleich). + +< + BOOL OP < (INT CONST a, b) + Zweck: Vergleich auf kleiner. + + BOOL OP < (REAL CONST a, b) + Zweck: Vergleich auf kleiner. + + BOOL OP < (TEXT CONST left, right) + Zweck: Vergleich zweier Texte auf kleiner ('left' kommt lexikographisch + vor 'right'). + +> + BOOL OP > (INT CONST a, b) + Zweck: Vergleich auf größer. + + BOOL OP > (REAL CONST a, b) + Zweck: Vergleich auf größer. + + BOOL OP > (TEXT CONST left, right) + Zweck: Vergleich zweier Texte auf größer ('left' kommt lexikographisch + nach 'right'). + +<= + BOOL OP <= (INT CONST a, b) + Zweck: Vergleich auf kleiner gleich. + + BOOL OP <= (REAL CONST a, b) + Zweck: Vergleich auf kleiner gleich. + + BOOL OP <= (TEXT CONST left, right) + Zweck: Vergleich von zwei Texten auf kleiner gleich ('left' kommt + lexikographisch vor oder ist gleich 'right'). + +>= + BOOL OP >= (INT CONST a, b) + Zweck: Vergleich auf größer gleich. + + BOOL OP >= (REAL CONST a, b) + Zweck: Vergleich auf größer gleich. + + BOOL OP >= (TEXT CONST left, right) + Zweck: Vergleich zweier Texte auf größer gleich ('left' kommt lexiko- + graphisch nach oder ist gleich 'right'). + +<> + BOOL OP <> (INT CONST a, b) + Zweck: Vergleich auf Ungleichheit. + + BOOL OP <> (REAL CONST a, b) + Zweck: Vergleich auf Ungleichheit. + + BOOL OP <> (TEXT CONST left, right) + Zweck: Vergleich von zwei Texten auf Ungleichheit (Texte mit ungleichen + Längen sind stets ungleich). + ++ + INT OP + (INT CONST a) + Zweck: Monadischer Operator (Vorzeichen, ohne Wirkung). + + REAL OP + (REAL CONST a) + Zweck: Monadischer Operator (Vorzeichen, ohne Wirkung). + + INT OP + (INT CONST a, b) + Zweck: Addition. + + REAL OP + (REAL CONST a, b) + Zweck: Addition. + + TEXT OP + (TEXT CONST left, right) + Zweck: Verkettung der Texte 'left' und 'right' in dieser Reihenfolge. Die + Länge des Resultats ergibt sich aus der Addition der Längen der + Operanden. + +- + INT OP - (INT CONST a) + Zweck: Vorzeichen-Umkehrung. + + REAL OP - (REAL CONST a) + Zweck: Vorzeichen-Umkehrung. + + INT OP - (INT CONST a, b) + Zweck: Subtraktion. + + REAL OP - (REAL CONST a, b) + Zweck: Subtraktion. + +* + INT OP * (INT CONST a, b) + Zweck: Multiplikation. + + REAL OP * (REAL CONST a, b) + Zweck: Multiplikation. + + TEXT OP * (INT CONST times, TEXT CONST source) + Zweck: 'times' fache Erstellung von 'source' und Verkettung. Dabei muß + + times >= 0 + + sein, sonst wird 'niltext' geliefert. + +/ + REAL OP / (REAL CONST a, b) + Zweck: Division. + Fehlerfall: + * Division durch 0 + +** + INT OP ** (INT CONST arg, exp) + Zweck: Exponentiation mit 'exp' >= 0 + Fehlerfälle: + * INT OP ** : negative exponent + Ein negativer Exponent ist nicht zugelassen. + * 0 ** 0 is not defined + 'arg' und 'exp' dürfen nicht beide 0 sein. + + REAL OP ** (REAL CONST arg, exp) + Zweck: Exponentiation. + Fehlerfälle: + * hoch mit negativer basis + Der 'exp' muß >= 0.0 sein. + * 0**0 geht nicht + 'arg' und 'exp' dürfen nicht gleichzeitig 0.0 sein. + + REAL OP ** (REAL CONST arg, INT CONST exp) + Zweck: Exponentiation. + Fehlerfall: + * 0.0 ** 0 geht nicht + +abs + INT PROC abs (INT CONST argument) + Zweck: Absolutbetrag eines INT-Wertes. + + INT OP ABS (INT CONST argument) + Zweck: Absolutbetrag eines INT-Wertes. + + REAL PROC abs (REAL CONST value) + Zweck: Absolutbetrag eines REAL-Wertes. + + REAL OP ABS (REAL CONST value) + Zweck: Absolutbetrag eines REAL-Wertes. + +AND + BOOL OP AND (BOOL CONST a, b) + Zweck: Logisches und. + +arctan + REAL PROC arctan (REAL CONST x) + Zweck: Arcus Tangens-Funktion. Liefert einen Wert in Radiant. + +arctand + REAL PROC arctand (REAL CONST x) + Zweck: Arcus Tangens-Funktion. Liefert einen Wert in Grad. + +CAT + OP CAT (TEXT VAR left, TEXT CONST right) + Zweck: Hat die gleiche Wirkung wie + + left := left + right + + Hinweis: Der Operator 'CAT' hat eine geringere Heap-Belastung als + die Operation mit expliziter Zuweisung. + +change + PROC change (TEXT VAR destination, TEXT CONST old, new) + Zweck: Ersetzung des (Teil-) TEXTes 'old' in 'destination' durch 'new' bei + dem erstmaligen Auftreten. Ist 'old' nicht in 'source' vorhanden, + so wird keine Meldung abgesetzt (Abweichung vom Standard). Beachte, + daß sich dabei die Länge von 'destination' verändern kann. + Beispiel: + + TEXT VAR mein text :: "EUMEL-Benutzerhandbuch"; + change (mein text, "Ben", "N"); (* EUMEL-Nutzerhandbuch *) + +PROC change (TEXT VAR destination, INT CONST from, to, TEXT CONST new) + Zweck: Der TEXT 'new' wird in den TEXT 'destination' anstatt des TEXTes, + der zwischen 'from' und 'to' steht, eingesetzt. Beachte, daß sich + dabei die Länge von 'destination' ändern kann. Beispiel: + + TEXT VAR mein text :: "EUMEL-Benutzerhandbuch"; + change (mein text, 7, 9, "N"); (* wie oben *) + +change all + PROC change all (TEXT VAR destination, TEXT CONST old, new) + Zweck: Der Teiltext 'old' wird durch 'new' in 'destination' ersetzt. Im + Unterschied zur 'change'-Prozedur findet die Ersetzung nicht nur + bei dem erstmaligen Auftreten von 'old' statt, sondern so oft, wie + 'old' in 'destination' vorhanden ist. Beispiel: + + + TEXT VAR x :: "Das ist ein Satz"; + change all (x, " ", ""); (* DasisteinSatz *) + +clock + REAL PROC clock (INT CONST index) + Zweck: Datum und Uhrzeit werden vom EUMEL-System für alle Tasks geführt. + Neben einer Uhr ('Realzeituhr'), die das Datum und die aktuelle + Uhrzeit enthält, wird eine Uhr für die von der Task verbrauchte + CPU-Zeit geführt ('CPU-Zeituhr'). Beide Zeiten werden vom System + als REALs realisiert. Die Prozedur 'clock' liefert die aktuellen + Werte dieser Uhren. Bei 'index = 0' wird die akkumulierte CPU-Zeit + der Task, bei 'index = 1' der Wert der Realzeituhr geliefert. + + Mit den REAL-Werten der Uhren kann ohne weiteres gerechnet werden, + jedoch sind nur Werte > 0 definiert. Die REAL-Werte der Realzeit- + uhr beginnen beim 1.1.1900 um 0 Uhr. Es sind nur Werte für dieses + Jahrhundert zugelassen. Werte der Realzeituhr in lesbarer Form + kann man durch die Konvertierungsprozeduren 'date' (für den + aktuellen Tag) und 'time of day' (Uhrzeit) erhalten. + + Um die benötigte CPU-Zeit eines Programms zu berechnen, muß man + die CPU-Zeituhr zweimal abfragen. Um solche Zeiten in lesbarer + Form zu erhalten, kann man die Konvertierungsprozedur 'time' + verwenden. Beispiel: + + REAL CONST anfang :: clock (0); + berechnungen; + REAL CONST ende :: clock (0); + put ("benoetigte CPU-Zeit:"); + put (time (ende - anfang)) + +code + TEXT PROC code (INT CONST code) + Zweck: Wandelt einen INT-Wert 'code' in ein Zeichen um. 'code' muß + + 1 <= code <= 254 + + sein. + + INT PROC code (TEXT CONST text) + Zweck: 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). + +collect heap garbage + PROC collect heap garbage + Zweck: Bereinigung des Heaps von nicht mehr benötigten TEXTen. + +command dialogue + PROC command dialogue (BOOL CONST status) + Zweck: Ein- bzw. Ausschalten des Kommando-Dialogs. Ist der Kommando- + dialog eingeschaltet, dann funktionieren z.B. die Prozeduren 'yes' + bzw. 'no' und ein Aufruf der Prozedur 'errorstop' liefert eine + Fehlermeldung auf dem Terminal. Ist der Kommandodialog ausge- + schaltet, wird z.B. durch die Prozedur 'yes' kein Text ausgegeben + (es wird TRUE geliefert) und errorstop erzeugt keine Fehler- + meldungen. + + BOOL PROC command dialogue + Zweck: Liefert den Wert TRUE, wenn der Kommando-Dialog eingeschaltet + ist, andernfalls FALSE. + +compress + TEXT PROC compress (TEXT CONST text) + Zweck: Liefert den TEXT 'text' ohne führende und nachfolgende Leerzeichen. + +cos + REAL PROC cos (REAL CONST x) + Zweck: Kosinus-Funktion. 'x' muß in Radiant angegeben werden. + +cosd + REAL PROC cosd (REAL CONST x) + Zweck: Cosinus-Funktion. 'x' muß in Winkelgrad angegeben werden. + +cout + PROC cout (INT CONST number) + Zweck: Schreibt 'number' an die aktuelle Cursor-Position auf den Bild- + schirm. Anschließend wird an diese Position wieder zurück positio- + niert. 'number' muß > 0 sein. Paßt 'number' nicht mehr auf die + Zeile, so ist die Wirkung von 'cout' nicht definiert. 'cout' gibt + den Wert von 'number' nur aus, wenn genügend freie Kanal-Kapazität + für diese Ausgabe vorhanden ist. Das hat zur Folge, daß Programme + nicht auf die Beendigung einer Ausgabe von 'number' warten müssen + und ggf. Ausgaben überschlagen werden. + +cursor + PROC cursor (INT CONST column, row) + Zweck: Positioniert den Cursor auf dem Bildschirm, wobei 'column' die + Spalte und 'row' die Zeile angibt. Die zulässigen Bereiche von + 'column' und 'row' sind geräteabhängig. Zur Zeit gilt auf allen + EUMEL-Geräten + + 1 <= column <= 80 + 1 <= row <= 24 + +date + TEXT PROC date (REAL CONST time) + Zweck: Konvertierungsprozedur für das Datum, welches sich aus dem Aufruf + der Prozedur 'clock (1)' ergibt. Das Datum wird in der Form + 'tt.mm.jj' geliefert. Beispiel: + + put (date (clock (1))) (* z.B.: 24.12.82 *) + + + REAL PROC date (TEXT CONST datum) + Zweck: Konvertierungsprozedur für ein Datum in der Form 'tt.mm.jj'. + Liefert einen REAL-Wert, wie ihn die Prozedur 'clock (1)' liefern + würde. Beispiel: + + put (date ("24.12.82")) (* 6.270670e10 *) + + TEXT PROC date + Zweck: Liefert das Tagesdatum. Wirkt wie 'date (clock (1))', ist jedoch + erheblich schneller. + +day + REAL CONST day + Zweck: Liefert die Anzahl der Sekunden eines Tages (86 400.0). + +decimal exponent + INT PROC decimal exponent (REAL CONST mantisse) + Zweck: Liefert aus einem REAL-Wert den dezimalen Exponenten als INT-Wert. + +DECR + OP DECR (INT VAR left, INT CONST right) + Zweck: Wirkt wie left := left - right + + OP DECR (REAL VAR left, REAL CONST right) + Zweck: Wirkt wie left := left - right + +delete char + PROC delete char (TEXT VAR string, INT CONST delete pos) + Zweck: 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. + +DIV + INT OP DIV (INT CONST a, b) + Zweck: INT-Division. + Fehlerfall: + * DIV by 0 + Division durch Null. + +e + REAL CONST e + Zweck: Eulersche Zahl (2.718282). + +errorstop + PROC errorstop (TEXT CONST error message) + Zweck: Abbruch unter Ausgabe einer Fehlermeldung (vergl. Fehlerbehand- + lung). + +exp + REAL PROC exp (REAL CONST z) + Zweck: Exponentialfunktion. + +floor + REAL PROC floor (REAL CONST real) + Zweck: Schneidet die Nachkommastellen des REAL-Wertes 'real' ab. + +frac + REAL PROC frac (REAL CONST z) + Zweck: Liefert die Stellen eines REAL-Wertes hinter dem Dezimalpunkt. + +get + PROC get (INT VAR number) + Zweck: Einlesen eines INT-Wertes vom Bildschirm. Der einzulesende INT- + Wert kann bei der Eingabe vom Terminal editiert werden. Die + Eingabe kann vom Benutzer-Terminal so umgeleitet werden, daß sie + von einer Datei aus erfolgt (vergl. 'sysin'). + + PROC get (REAL VAR value) + Zweck: Einlesen eines REAL-Wertes vom Bildschirm. Der einzulesende + REAL-Wert kann bei der Eingabe vom Terminal editiert werden. Die + Eingabe kann vom Benutzer-Terminal so umgeleitet werden, daß sie + von einer Datei aus erfolgt (vergl. 'sysin'). + + PROC get (TEXT VAR word) + Zweck: Liest einen Text in die Variable 'word' mit maximal 255 Zeichen. + Es werden solange Zeichen vom Terminal gelesen, bis ein Leer- + zeichen oder ein Positionierungszeichen eingegeben wird. Dabei + werden führende Leerzeichen übergeben. Der einzulesende Text kann + bei der Eingabe editiert werden. Eine leere Eingabe ist nicht + erlaubt. Die Eingabe kann vom Benutzer-Terminal so umgeleitet + werden, daß sie von einer Datei aus erfolgt (vergl. 'sysin'). + + PROC get (TEXT VAR word, INT CONST laenge) + Zweck: Liest einen Text vom Bildschirm mit der Länge 'laenge' oder bis + ein Positionierungszeichen angetroffen wird. Der einzulesende Wert + kann bei der Eingabe editiert werden. Dabei gilt: + + 1 <= laenge <= 255 + + PROC get (TEXT VAR word, TEXT CONST separator) + Zweck: Liest einen Text vom Bildschirm, bis ein Zeichen 'separator' ange- + troffen oder ein Positionierungszeichen eingegeben wird. Der ein- + zulesende Text kann bei der Eingabe editiert werden. + +get cursor + PROC get cursor (INT VAR x, y) + Zweck: Erfragung der aktuellen Cursor-Position. Die Koordinaten des Cur- + sors werden in 'x' und 'y' geliefert. Die aktuelle Cursor-Position + ist nach Ausgabe von 'HOME' (Code = 1) oder einer Positionierung + des Cursors mit der Prozedur 'cursor' stets definiert. Die Proze- + dur 'get cursor' liefert jedoch undefinierte Werte, wenn über den + rechten Rand einer Zeile hinausgeschrieben wurde (die Wirkung + einer solchen Operation hängt von der Hardware eines Terminals ab). + +getline + PROC get line (TEXT VAR line) + Zweck: Das System wartet auf eine Zeile vom Bildschirm (max. 255 Zeichen). + Eine leere Eingabe ist nicht möglich. Die Eingabe kann vom Benut- + zer-Terminal so umgeleitet werden, daß sie von einer Datei aus + erfolgt (vergl. 'sysin'). + +heap size + INT PROC heap size + Zweck: Informationsprozedur für die Größe (in KB) des TEXT-Heaps. + +hour + REAL CONST hour + Zweck: Liefert die Anzahl der Sekunden einer Stunde (3600.0). + +inchar + PROC inchar (TEXT VAR character) + Zweck: Wartet solange, bis ein Zeichen von der Tastatur eingegeben wird, + und schreibt dieses Zeichen in die Variable 'character'. + +incharety + TEXT PROC incharety + Zweck: Versucht, ein Zeichen von der Tastatur zu lesen. Wurde kein + Zeichen eingegeben, wird niltext geliefert. + + TEXT PROC incharety (INT CONST time limit) + Zweck: Versucht, ein Zeichen vom Bildschirm zu lesen. Dabei wird maximal + eine 'time limit' lange Zeit auf das Zeichen gewartet (gemessen in + Zehntel-Sekunden). + +INCR + OP INCR (INT VAR left, INT CONST right) + Zweck: Wirkt wie left := left + right + + OP INCR (REAL VAR left, REAL CONST right) + Zweck: Wirkt wie left := left + right + +initialize random + PROC initialize random (INT CONST value) + Zweck: Initialisieren der 'random'-Prozedur, um nicht reproduzierbare + Zufallszahlen zu bekommen. Diese 'init random'-Prozedur gilt für + den "INT-Random Generator". + + PROC initialize random (REAL CONST z) + Zweck: 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". + +insert char + PROC insert char (TEXT VAR string, TEXT CONST char, INT CONST insert pos) + Zweck: 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. + +int + INT PROC int (REAL CONST a) + Zweck: Konvertierungsprozedur. + + INT PROC int (TEXT CONST number) + Zweck: Umwandlung eines Textes in einen INT-Wert. Der Text 'number' darf + ein "+"- oder "-"-Zeichen vor den Ziffern enthalten. Führende + Blanks werden überlesen. Enthält 'number' an einer Position ein + Zeichen, das nicht umgewandelt werden kann, so wird die Umwand- + lung gestoppt und der bis dahin umgewandelte Wert (bzw. der Wert 0) + geliefert. + +last conversion ok + BOOL PROC last conversion ok + Zweck: Liefert den Wert TRUE, sofern die letzte Konvertierungsprozedur + nicht auf einen Fehler bei der Umwandlung gestoßen ist, andernfalls + FALSE. + +length + INT PROC length (TEXT CONST text) + Zweck: Anzahl von Zeichen ("Länge") von 'text' einschließlich Leerzeichen. + +LENGTH + INT OP LENGTH (TEXT CONST text) + Zweck: Anzahl von Zeichen ("Länge") von 'text' einschließlich Leerzeichen. + +line + PROC line + Zweck: Es wird zum Anfang einer neuen Zeile positioniert. + + PROC line (INT CONST number) + Zweck: Es werden 'number' Zeilenwechsel vorgenommen. + +ln + REAL PROC ln (REAL CONST x) + Zweck: Natürlicher Logarithmus. + Fehlerfall: + * ln mit nicht positiver Zahl + Nur echt positive Argumente sind zulässig. + +log2 + REAL PROC log2 (REAL CONST z) + Zweck: Logarithmus zur Basis 2. + Fehlerfall: + * log2 mit negativer zahl + Nur echt positive Argumente sind zulässig. + +log10 + REAL PROC log10 (REAL CONST x) + Zweck: Logarithmus zur Basis 10. + Fehlerfall: + * log10 mit negativer zahl + Nur echt positive Argumente sind zulässig. + +max + INT PROC max (INT CONST first, second) + Zweck: Liefert den Größten der beiden INT-Werte. + + REAL PROC max (REAL CONST first, second) + Zweck: Liefert den Größten der beiden REAL-Werte. + +maxint + INT CONST maxint + Zweck: Größter INT-Wert im EUMEL-System (32 767). + +maxreal + REAL CONST maxreal + Zweck: Größter REAL-Wert im EUMEL-System (9.999999999999e126). + +max text length + INT CONST max text length + Zweck: Maximale Anzahl von Zeichen in einem TEXT (32 000). + +min + INT PROC min (INT CONST first, second) + Zweck: Liefert den Kleinsten der beiden INT-Werte. Beispiele: + + min (3.0, 2.0) ==> 2.0 + min (-2.0, 3.0) ==> -2.0 + + REAL PROC min (REAL CONST first, second) + Zweck: Liefert den Kleinsten der beiden REAL-Werte. + +MOD + INT OP MOD (INT CONST left, right) + Zweck: Liefert den Rest einer INT-Division. Beispiele: + + 3 MOD 2 ==> 1 + -3 MOD 2 ==> 1 + + Fehlerfall: + * DIV by 0 + Division durch 0 ist verboten. + + REAL OP MOD (REAL CONST left, right) + Zweck: Modulo-Funktion für REALs (liefert den Rest). Beispiele: + + 5.0 MOD 2.0 ==> 1.0 + 4.5 MOD 4.0 ==> 0.5 + +no + BOOL PROC no (TEXT CONST question) + Zweck: Wirkt wie + + NOT yes + +NOT + BOOL OP NOT (BOOL CONST a) + Zweck: Logische Negation. + +online + BOOL PROC online + Zweck: Liefert TRUE, wenn die Task mit einem Terminal gekoppelt ist. + +OR + BOOL OP OR (BOOL CONST a, b) + Zweck: Logisches oder. + +out + PROC out (TEXT CONST text) + Zweck: Ausgabe eines Textes auf dem Bildschirm. Im Unterschied zu 'put' + wird kein Blank an den ausgegebenen Text angefügt. 'out' kann + nicht umgeleitet werden (vergl. 'sysout'). + +out subtext + PROC out subtext (TEXT CONST source, INT CONST from) + Zweck: Ausgabe eines Teiltextes von 'source' von der Position 'from' bis + Textende. Es wird keine Aktion vorgenommen für + + from > LENGTH source + + PROC out subtext (TEXT CONST source, INT CONST from, to) + Zweck: Ausgabe eines Teiltextes von 'source' von der Position 'from' bis + zur Position 'to'. Für + + to > LENGTH source + + wird für die fehlenden Zeichen Leerzeichen (blanks) ausgegeben. + +page + PROC page + Zweck: Es wird zum Anfang einer neuen Seite positioniert (hier: linke + obere Ecke des Bildschirms, wobei der Bildschirm gelöscht wird). + +pause + PROC pause (INT CONST time limit) + Zweck: Wartet 'time limit' in Zehntel-Sekunden. Bei negativen Werten ist + die Wirkung nicht definiert. Die Wartezeit wird nicht nur durch + das Erreichen der Grenze abgebrochen, sondern auch durch die + Eingabe eines beliebigen Zeichens. + +pi + REAL CONST pi + Zweck: Die Zahl pi (3.141593). + +pos + INT PROC pos (TEXT CONST source, pattern) + Zweck: Liefert die erste Position des ersten Zeichens von 'pattern' in + 'source', falls 'pattern' gefunden wird. Wird 'pattern' nicht + gefunden oder ist 'pattern' niltext, so wird der Wert '0' ge- + liefert. Beispiel: + + TEXT VAR t1 :: "abcdefghijk...xyz", + t2 :: "cd"; + ... pos (t1, t2) ... (* liefert 3 *) + ... pos (t2, t1) ... (* liefert 0 *) + + INT PROC pos (TEXT CONST source, pattern, INT CONST from) + Zweck: Wie obige Prozedur, jedoch wird erst ab der Position 'from' ab + gesucht. Dabei gilt folgende Einschränkung: + + length (pattern) < 255 + +INT PROC pos (TEXT CONST source, low char, high char, INT CONST from) + Zweck: Liefert die Position des ersten Zeichens 'x' in 'source' ab der + Position 'from', so daß + + low char <= x <= high char + + 'low char' und 'high char' müssen TEXTe der Länge 1 sein. Wird + kein Zeichen in 'source' 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); + +put + PROC put (INT CONST number) + Zweck: Ausgabe eines INT-Wertes auf dem Bildschirm. Anschließend wird + ein Leerzeichen ausgegeben. Die Ausgabe kann umgeleitet werden + (vergl. 'sysout'). + + PROC put (REAL CONST real) + Zweck: Ausgabe eines REAL-Wertes auf dem Bildschirm. Anschließend wird + ein Leerzeichen ausgegeben. Die Ausgabe kann umgeleitet werden + (vergl. 'sysout') + + PROC put (TEXT CONST text) + Zweck: Ausgabe eines Textes auf dem Bildschirm. Nach der Ausgabe von + 'text' wird ein Blank ausgegeben, um nachfolgenden Ausgaben auf + der gleichen Zeile voneinander zu trennen. Hardwareabhängig sind + die Aktionen, wenn eine Ausgabe über eine Zeilengrenze (hier: + Bildschirmzeile) vorgenommen wird. Meist wird die Ausgabe auf der + nächsten Zeile fortgesetzt. Die Ausgabe kann umgeleitet werden + (vergl. 'sysout'). + +putline + PROC putline (TEXT CONST text) + Zweck: Ausgabe von 'text' auf dem Bildschirm. Nach der Ausgabe wird auf + den Anfang der nächsten Zeile positioniert. Gibt man TEXTe nur mit + 'putline' aus, so ist gesichert, daß jede Ausgabe auf einer neuen + Zeile beginnt. Hardwareabhängig sind die Aktionen, wenn eine Aus- + gabe über eine Zeilengrenze (hier: Bildschirmzeile) vorgenommen + wird. Meist wird die Ausgabe auf der nächsten Zeile fortgesetzt. + Die Ausgabe kann umgeleitet werden (vergl. 'sysout'). + +random + INT PROC random (INT CONST lower bound, upper bound) + Zweck: Pseudo-Zufallszahlen-Generator im Intervall 'upper bound' und + 'lower bound' einschließlich. Es handelt sich hier um den "INT + Random Generator". + + REAL PROC random + Zweck: Pseudo-Zufallszahlen-Generator im Intervall 0 und 1. Es handelt + sich hier um den "REAL Random Generator". + +real + REAL PROC real (INT CONST a) + Zweck: Konvertierungsprozedur. + + REAL PROC real (TEXT CONST text) + Zweck: 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 + PROC replace (TEXT VAR destination, INT CONST position, TEXT CONST source) + Zweck: Ersetzung eines Teiltextes in 'destination' durch 'source' an der + Position 'position' in 'destination'. Es muß gelten + + 1 <= position <= LENGTH destination + + d.h. 'position' muß innerhalb von 'destination' liegen und 'source' + muß von der Position 'position' ab in 'destination' einsetzbar + sein. Dabei bleibt die Länge von 'destination' unverändert. + +round + REAL PROC round (REAL CONST real, INT CONST digits) + Zweck: 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 Vorkomma- + stellen gerundet. Beispiel: + + round (123.456, -2) + + liefert '100.0'. Abweichung vom Standard: Es wird mit 'digits'- + Ziffern gerundet. + +say + PROC say (TEXT CONST message) + Zweck: Sofern der Kommando-Dialog eingeschaltet ist (vergl. 'command + dialogue'), wird der TEXT 'message' an die augenblickliche Cursor- + Position geschrieben. + +sign + INT PROC sign (INT CONST argument) + Zweck: Feststellen des Vorzeichens eines INT-Wertes. Folgende Werte + werden geliefert: + + argument > 0 ==> 1 + argument = 0 ==> 0 + argument < 0 ==> -1 + + INT OP SIGN (INT CONST argument) + Zweck: Feststellen des Vorzeichens eines INT-Wertes. + + INT PROC sign (REAL CONST number) + Zweck: Feststellen des Vorzeichens eines REAL-Wertes. + + INT OP SIGN (REAL CONST number) + Zweck: Feststellen des Vorzeichens eines REAL-Wertes. + +sin + REAL PROC sin (REAL CONST x) + Zweck: Sinus-Funktion. 'x' muß in Radiant (Bogenmaß) angegeben werden. + +sind + REAL PROC sind (REAL CONST x) + Zweck: Sinus-Funktion. 'x' muß im Winkelgrad angegeben werden. + +smallreal + REAL PROC smallreal + Zweck: 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 + REAL PROC sqrt (REAL CONST z) + Zweck: Wurzel-Funktion. + Fehlerfall: + * sqrt von negativer Zahl + Das Argument muß größer gleich 0.0 sein. + +stop + PROC stop + Zweck: Abbruch (vergl. Fehlerbehandlung). + +SUB + TEXT OP SUB (TEXT CONST text, INT CONST pos) + Zweck: 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. + +subtext + TEXT PROC subtext (TEXT CONST source, INT CONST from) + Zweck: Teiltext von 'source', der bei der Position 'from' anfängt. Die + Länge des Resultats ergibt sich also zu + + LENGTH source - from + 1 + + d.h. von der Position 'from' bis zum Ende von 'source'. 'from' muß + innerhalb von 'source' liegen. Ist from < 1, dann wird 'source' + geliefert. Falls from > LENGTH source ist, wird niltext geliefert. + + TEXT PROC subtext (TEXT CONST source, ITT CONST from, to) + Zweck: Teiltext von 'source' von der Position 'from' bis einschließlich + der Position 'to'. Die Länge des Resultats ist also + + from - to + 1 + + Dabei muß gelten + + 1 <= from <= to <= LENGTH source + + d.h. die Positionen 'from' und 'to' müssen in dieser Reihenfolge + innerhalb von 'source' liegen. Ist + + to >= LENGTH source + + wird 'subtext (source, from)' ausgeführt. Für die Bedingungen für + 'from' siehe vorstehende Beschreibung von 'subtext'. + +sysin + PROC sysin (TEXT CONST file name) + Zweck: Eingabe-Routinen ('get', 'getline' und 'line') lesen nicht mehr + vom Benutzer-Terminal, sondern aus der Datei 'file name'. + + TEXT PROC sysin + Zweck: Liefert den Namen der eingestellten 'sysin'-Datei. "" bezeichnet + das Benutzer-Terminal. + +sysout + PROC sysout (TEXT CONST file name) + Zweck: Ausgabe-Routinen ('put', 'putline', 'write', 'line') gehen nicht + mehr zum Benutzer-Terminal, sondern in die Datei 'file name'. + + TEXT PROC sysout + Zweck: Liefert den Namen der eingestellten 'sysout'-Datei. "" bezeichnet + das Benutzer-Terminal. + +tan + REAL PROC tan (REAL CONST x) + Zweck: Tangens-Funktion. 'x' muß in Radiant angegeben werden. + +tand + REAL PROC tand (REAL CONST x) + Zweck: Tangens-Funktion. 'x' muß in Winkelgrad angegeben werden. + +text + TEXT PROC text (INT CONST number) + Zweck: Umwandlung eines INT-Wertes in einen Text. Negative Werte werden + mit einem "-"-Zeichen geliefert. + + TEXT PROC text (INT CONST number, laenge) + Zweck: Umwandlung eines INT-Wertes 'number' in einen Text mit der Länge + 'laenge'. Für + + LENGTH (text (number)) < laenge + + werden die Ziffern rechtsbündig in einen Text mit der Länge + 'laenge' eingetragen. Fehlende Ziffern der gewünschten 'laenge' + werden im TEXT vorne mit Leerzeichen aufgefüllt. Für + + LENGTH (text (number)) > laenge + + wird ein Text mit der Länge 'laenge' geliefert, der mit + "*"-Zeichen gefüllt ist. + + TEXT PROC text (REAL CONST real) + Zweck: Konvertierung eines REAL-Wertes in einen TEXT. Ggf. wird der TEXT + in Exponenten-Darstellung geliefert. + + TEXT PROC text (REAL CONST real, laenge) + Zweck: Siehe oben. 'laenge' gibt die Anzahl von Zeichen an. + + TEXT PROC text (REAL CONST real, INT CONST laenge, fracs) + Zweck: Konvertierung eines REAL-Wertes in einen TEXT. Dabei gibt 'laenge' + die Länge des Resultats einschließlich des Dezimalpunktes und + 'fracs' die Anzahl der Dezimalstellen an. Kann der REAL-Wert nicht + wie gewünscht dargestellt werden, wird + + laenge * "*" + + geliefert. + + TEXT PROC text (TEXT CONST source, INT CONST laenge) + Zweck: Teiltext aus 'source' mit der Länge 'laenge', beginnend bei der + Position 1 von 'source'. Es muß gelten + + 1 <= laenge <= LENGTH source + + d.h. der gewünschte Teiltext muß aus 'source' ausblendbar sein. + Wenn + + laenge > LENGTH source + + die Länge des gewünschten Resultats ist größer als die Länge von + 'source' ist, wird der zu liefernde TEXT mit der an 'laenge' + fehlenden Zeichen mit Leerzeichen aufgefüllt. + + TEXT PROC text (TEXT CONST source, INT CONST laenge, from) + Zweck: Teiltext aus 'source' mit der Länge 'laenge', beginnend an der + Position 'from' in dem TEXT 'source'. Entspricht + + text (subtext (source, from, LENGTH source), laenge) + + Es muß + + laenge >= 0 + 1 <= from <= LENGTH source + + gelten, d.h. 'from' muß eine Position angeben, die innerhalb von + 'source' liegt. Für + + laenge > LENGTH source - from + 1 + + also wenn die angegebene Länge 'laenge' größer ist als der auszu- + blendende Text, wird das Resultat rechts mit Leerzeichen aufge- + füllt. Wenn + + laenge < LENGTH source - from + 1 + + d.h. wenn die angegebene Länge kleiner ist als der Teiltext von + 'from' bis zum letzten Zeichen von 'source', wird das Resultat mit + der Länge + + LENGTH source - from + 1 + + geliefert. + +time + TEXT PROC time (REAL CONST time) + Zweck: Konvertierungsprozedur für die Zeiten der CPU-Zeituhr. Liefert die + Zeiten in der Form 'hh:mm:ss.s'. Vergl. dazu 'clock'. + + TEXT PROC time (REAL CONST value, INT CONST laenge) + Zweck: Konvertiert die Zeit in externe Darstellung. Für die 'laenge'- + Werte ergibt sich: + + laenge = 10 (* hh:mm:ss.s *) + laenge = 12 (* hhh:mm:ss.s *) + +REAL PROC time (TEXT CONST time) + Zweck: Konvertierungsprozedur für Texte der CPU-Zeituhr in REAL-Werte. + +time of day + TEXT PROC time of day (REAL CONST time) + Zweck: Konvertierungsprozedur für REALs, wie sie die Realzeituhr + liefert. Es wird die Tageszeit in der Form 'hh:mm' geliefert. + Beispiel: + + put (time of day (clock (1))) (* z.B.: 17:25 *) + + + TEXT PROC time of day + Zweck: Liefert die aktuelle Tageszeit. Entspricht + + time of day (clock (1)) + +TIMESOUT + OP TIMESOUT (INT CONST times, TEXT CONST text) + Zweck: Ausgabe eines TEXTes 'text' 'times'mal. An die Ausgabe wird im + Gegensatz zu 'put' kein Leerzeichen angefügt. Es wird kein Text + ausgegeben für + + times < 1 + +write + PROC write (TEXT CONST text) + Zweck: Gibt 'text' ohne Trennblank aus ('put' mit Trennblank). Läßt sich + im Gegensatz zu 'out' in eine Datei umleiten (vergl. 'sysout'). + +XOR + BOOL OP XOR (BOOL CONST a, b) + Zweck: Exklusives oder. + +yes + BOOL PROC yes (TEXT CONST question) + Zweck: Sofern der Kommando-Dialog (vergl. 'command dialogue') einge- + schaltet ist, wird der TEXT 'question' auf dem Bildschirm des + Benutzers geschrieben. Der TEXT 'question' wird dabei mit einem + Fragezeichen ergänzt. Der Benutzer kann nun am Terminal mit den + Zeichen 'j' oder 'n' antworten (oder: 'J', 'N', 'y', 'n', 'Y', + 'N'). Nach Eingabe eines dieser Zeichen wird von der Prozedur + 'yes' auf eine neue Zeile positioniert. Die Prozedur 'yes' liefert + den Wert TRUE bei der Eingabe von 'j' und den Wert FALSE bei der + Eingabe von 'n'. Ist der Kommando-Dialog nicht eingeschaltet, + liefert die Prozedur 'yes' den Wert TRUE. + diff --git a/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil9 b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil9 new file mode 100644 index 0000000..318dd06 --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil9 @@ -0,0 +1,936 @@ + EUMEL-Benutzerhandbuch + + TEIL 9: Standard-Datentypen + +1. VECTOR und MATRIX + +Vektoren und Matrizen enthalten Elemente vom Datentyp REAL. Für beide Daten- +typen sind die üblichen Operatoren definiert. Im Unterschied zu "normalen" +'ROW n REAL' bzw. 'ROW n ROW m REAL' brauchen die Anzahl der Elemente, die +sich in einem Vektor bzw. in einer Matrix befinden, nicht bereits zur Über- +setzungszeit deklariert, sondern können "dynamisch" zur Laufzeit eines ELAN- +Programms festgelegt werden. Somit ist es möglich, eine zur Übersetzungszeit +noch unbekannte Anzahl von REAL-Elementen zu bearbeiten und dabei nur soviel +Speicherplatz wie notwendig zu verwenden. Bei beiden Datentypen ist die +maximale Anzahl von Elementen jeweils 4 000. + +Bei VECTOR und MATRIX ist auf die üblichen Rundungsfehler bei der Verwendung +von REALs zu achten, die bei umfangreicheren Rechnungen unvermeidlich ent- +stehen. Rundungsfehler durch Ein- bzw. Ausgaberoutinen können z.Zt. im +EUMEL-System jedoch nicht vorkommen, weil REAL-Werte dezimal im Rechner +abgespeichert werden (13 Stellen, von denen jedoch nur 7 ausgegeben werden). + + + +VECTOR + +Folgende VECTOR-Operationen stehen zur Verfügung: + +vector Erzeugung eines VECTOR-Objekts +get Eingabe der Elemente vom Terminal +put Ausgabe der Elemente auf das Terminal +replace Ersetzung eines Elementes eines VECTORs +SUB Zugriff auf ein REAL-Element eines VECTORs +LENGTH Anzahl der Elemente eines VECTORs +length dito +NORM Euklidische Norm + + + - + * + / + := + = + <> + + + +Beschreibung der VECTOR-Operationen + +Aus Optimierungsgründen (Heapbelastung) wurde der Datentyp INITVECTOR ge- +schaffen. Dieser wird im VECTOR-Paket intern gehalten (wird nicht über das +Interface herausgereicht) und kann somit nicht in einer Deklaration benutzt +werden. INITVECTOR wird nur für die Operationen + + := + vector + +verwendet. Bei Verwendung eines Datenobjekts vom Datentyp INITVECTOR wird +nicht soviel Speicherplatz wie bei einem Objekt vom Datentyp VECTOR benötigt. + += + BOOL OP = (VECTOR CONST a, b) + Zweck: Vergleich zweier Vektoren. Der Operator liefert FALSE, wenn die + Anzahl der Elemente von 'a' und 'b' ungleich ist oder wenn zwei + Elemente mit gleichem Index ungleich sind. Beispiel: + + VECTOR VAR x :: vector (10, 1.0), + y :: vector (15, 2.0), + z :: vector (10, 1.0); + ... x = y ... (* FALSE *) + ... x = z ... (* TRUE *) + +<> + BOOL OP <> (VECTOR CONST a, b) + Zweck: Vergleich zweier Vektoren auf Ungleichheit (NOT (a = b)). + +:= + OP := (VECTOR VAR ziel, VECTOR CONST quelle) + Zweck: Zuweisung. Nach der Zuweisung gilt auch + + length (quelle) = length (ziel) + + d.h. der linke Operand besitzt nach der Zuweisung genauso viele + Elemente wie 'quelle', unabhängig davon, ob 'ziel' vor der Zu- + weisung mehr oder weniger Elemente als 'quelle' besaß. Beispiel: + + VECTOR VAR y :: vector (10, 1.0), + z :: vector (15, 2.0); + ... + y := z; (* length (y) liefert nun 15 ! *) + + OP := (VECTOR VAR ziel, INITVECTOR CONST quelle) + Zweck: Dient zur Initialisierung eines VECTORs. Beispiel: + + VECTOR VAR x :: vector (17); + + 'vector' erzeugt ein Objekt vom Datentyp INITVECTOR. Dieses + Objekt braucht nicht soviel Speicherplatz wie ein VECTOR-Objekt. + Dadurch wird vermieden, daß nach erfolgter Zuweisung nicht ein + durch 'vector' erzeugtes Objekt auf dem Heap unnötig Speicher- + platz verbraucht. + ++ + VECTOR OP + (VECTOR CONST a) + Zweck: Monadisches '+' für VECTOR. Keine Auswirkung. + + VECTOR OP + (VECTOR CONST a, b) + Zweck: Elementweise Addition der Vektoren 'a' und 'b'. Beispiel: + + VECTOR VAR x, (* 'x' hat undefinierte Laenge *) + a :: vector (10, 1.0), + b :: vector (10, 2.0); + ... + x := a + b; (* 'x' hat nun 10 Elemente mit Werten '3.0' *) + Fehlerfall: + * VECTOR OP + : LENGTH a <> LENGTH b + 'a' und 'b' haben nicht die gleiche Anzahl von Elementen. + +- + VECTOR OP - (VECTOR CONST a) + Zweck: Monadisches '-'. + + VECTOR OP - (VECTOR CONST a, b) + Zweck: Elementweise Subtraktion der Vektoren 'a' und 'b'. + Fehlerfall: + * VECTOR OP - : LENGTH a <> LENGTH b + 'a' und 'b' haben nicht die gleiche Anzahl von Elementen. + +* + REAL OP * (VECTOR CONST a, b) + Zweck: Skalarprodukt zweier Vektoren. Liefert die Summe der element- + weisen Multiplikation der Vektoren 'a' und 'b'. Beachte even- + tuelle Rundungsfehler! Beispiel: + + REAL VAR a; + VECTOR VAR b :: vector (10, 2.0), + c :: vector (10, 2.0); + ... + a := b * c; (* 40.0 *) + Fehlerfall: + * REAL OP * : LENGTH a <> LENGTH b + 'a' und 'b' haben nicht die gleiche Anzahl von Elementen. + + VECTOR OP * (VECTOR CONST a, REAL CONST s) + Zweck: Multiplikation des Vektors 'a' mit dem Skalar 's'. + + VECTOR OP * (REAL CONST s, VECTOR CONST a) + Zweck: Multiplikation des Skalars 's' mit dem Vektor 'a'. + +/ + VECTOR OP / (VECTOR CONST a, REAL CONST s) + Zweck: Division des Vektors 'a' durch den Skalar 's'. Beispiel: + + VECTOR VAR a, (* 'a' hat undefinierte Laenge *) + b :: vector (10, 4.0); + ... + a := b / 2.0; + (* 'a' hat nun 10 Elemente mit Werten '2.0' *) + +get + PROC get (VECTOR VAR a, INT CONST l) + Zweck: Einlesen der Elemente von 'a' vom Terminal, wobei 'l' die Anzahl + der Elemente angibt. + Fehlerfall: + * PROC get : size <= 0 + Die angeforderte Elementanzahl 'l' muß > 0 sein. + +length + INT PROC length (VECTOR CONST a) + Zweck: Liefert die Anzahl der Elemente von 'a'. Beispiel: + + VECTOR VAR a :: vector (10, 1.0), + b :: vector (15, 2.0); + ... + ... length (a) ... (* 10 *) + ... length (b) ... (* 15 *) + +LENGTH + INT OP LENGTH (VECTOR CONST a) + Zweck: Liefert die Anzahl der Elemente von 'a'. + +NORM + REAL OP NORM (VECTOR CONST v) + Zweck: Euklidische Norm (Wurzel aus der Summe der Quadrate der Elemente). + +put + PROC put (VECTOR CONST v) + Zweck: Ausgabe der Werte der Elemente von 'v' auf dem Terminal. + +replace + PROC replace (VECTOR VAR v, INT CONST i, REAL CONST r) + Zweck: Zuweisung des i-ten Elementes von 'v' mit dem Wert von 'r'. + Beispiel: + + VECTOR VAR v :: ...; + ... + replace (v, 13, 3.14); + (* Das 13. Element von 'v' bekommt den Wert '3.14' *) + Fehlerfälle: + * PROC replace : subscript overflow + Der Index 'i' mit dem Wert 'm' liegt außerhalb des Vektors (i > + LENGTH v). + * PROC replace : subscript underflow + Der Index 'i' mit dem Wert 'm' liegt außerhalb des Vektors + (i < 1). + +SUB + REAL OP SUB (VECTOR CONST v, INT CONST i) + Zweck: Liefert das 'i'-te Element von 'v'. + Fehlerfälle: + * OP SUB : subscript overflow + Der Index 'i' mit dem Wert 'm' liegt außerhalb des Vektors (i > + LENGTH v). + * OP SUB : subscript underflow + Der Index 'i' mit dem Wert 'm' liegt außerhalb des Vektors + (i < 1). + +vector + INITVECTOR PROC vector (INT CONST l) + Zweck: Erzeugen eines Vektors mit 'l' Elementen. Ein INITVECTOR-Objekt + benötigt nicht soviel Speicherplatz wie ein VECTOR-Objekt. Die + Elemente werden mit dem Wert '0.0' initialisiert. + Fehlerfall: + * PROC vector : size <= 0 + Die angeforderte Elementanzahl 'l' muß > 0 sein. + + INITVECTOR PROC vector (INT CONST l, REAL CONST value): + Zweck: Erzeugen eines Vektors mit 'l' Elementen. Ein INITVECTOR-Objekt + benötigt nicht soviel Speicherplatz wie ein VECTOR-Objekt. Die + Elemente werden mit dem Wert 'value' initialisiert. Beispiel: + + VECTOR VAR v := vector (17, 3.14159); + (* 'v' hat 17 Elemente mit den Wert '3.14159' *) + Fehlerfall: + * PROC vector : size <= 0 + Die angeforderte Elementanzahl 'l' muß > 0 sein. + + + +MATRIX + +Folgende Operationen stehen für MATRIX zur Verfügung: + +matrix Erzeugung eines MATRIX-Objekts +idn Erzeugung einer Einheitsmatrix +put Ausgabe der MATRIX auf dem Terminal +get Eingabe der Matrix vom Terminal +replace row Ersetzung einer Zeile +replace column Ersetzung einer Spalte +replace element Ersetzung eines Elements +row Liefert einen VECTOR (Zeile einer MATRIX) +column Liefert einen VECTOR (Spalte einer MATRIX) +sub Liefert ein REAL-Elemement +COLUMNS Anzahl Spalten +ROWS Anzahl Zeilen +INV Inverse +DET Determinante +TRANSP Transponierte +transp Transponierte (speicherfreundlich) + + + - + * + := + = + <> + + + +Beschreibung der MATRIX-Operationen + +Aus Optimierungsgründen (Heapbelastung) wurde der Datentyp INITMATRIX +geschaffen. Dieser wird im MATRIX-Paket intern gehalten (wird nicht über das +Interface herausgereicht) und kann somit nicht in einer Deklaration benutzt +werden. INITMATRIX wird nur für die Operationen + + := + idn + matrix + +verwendet. Bei Verwendung eines Objekts vom Datentyp INITMATRIX wird nicht +der Speicherplatz für eine MATRIX benötigt. + ++ + MATRIX OP + (MATRIX CONST m) + Zweck: Monadisches '+'. Keine Auswirkungen. + + MATRIX OP + (MATRIX CONST l, r) + Zweck: Addition zweier Matrizen. Die Anzahl der Reihen und der Spalten + muß gleich sein. Beispiel: + + MATRIX VAR a :: matrix (3, 43, 1.0), + b :: matrix (3, 43, 2.0), + summe; + summe := a + b; + (* Alle Elemente haben den Wert '3.0' *) + Fehlerfälle: + * MATRIX OP + : COLUMNS l <> COLUMNS r + Die Anzahl der Spalten von 'l' und 'r' sind nicht gleich. + * MATRIX OP + : ROWS l <> ROWS r + Die Anzahl der Zeilen von 'l' und 'r' sind nicht gleich. + +- + MATRIX OP - (MATRIX CONST m) + Zweck: Monadisches Minus. Beispiel: + + MATRIX VAR a :: matrix (3, 4, 10.0) + a := - a; (* Alle Elemente haben den Wert '-10.0' *) + + MATRIX OP - (MATRIX CONST l, r) + Zweck: Subtraktion zweier Matrizen. Die Anzahl der Reihen und Spalten + muß gleich sein. + Fehlerfälle: + * MATRIX OP - : COLUMNS l <> COLUMNS r + Die Anzahl der Spalten von 'l' und 'r' sind nicht gleich. + * MATRIX OP - : ROWS l <> ROWS r + Die Anzahl der Zeilen von 'l' und 'r' sind nicht gleich. + +* + MATRIX OP * (REAL CONST r, MATRIX CONST m) + Zweck: Multiplikation einer Matrix 'm' mit einem Skalar 'r'. Beispiel: + + MATRIX VAR a :: matrix (3, 4, 2.0); + ... + a := 3 * a; (* Alle Elemente haben den Wert '6.0' *) + + MATRIX OP * (MATRIX CONST m, REAL CONST r) + Zweck: Multiplikation einer Matrix 'm' mit einem Skalar 'r'. + + MATRIX OP * (MATRIX CONST l, r) + Zweck: Multiplikation zweier Matrizen. Die Anzahl der Spalten von 'l' + und die Anzahl der Zeilen von 'r' müssen gleich sein. Beispiel: + + MATRIX VAR a :: matrix (3, 4, 2.0), + b :: matrix (4, 2, 3.0), + produkt; + produkt := a * b; + (* Alle Elemente haben den Wert '24.0' *) + Fehlerfall: + * MATRIX OP * : COLUMNS l <> ROWS r + Die Anzahl der Spalten von 'l' muß mit der Anzahl der Zeilen + von 'r' übereinstimmen. + + VECTOR OP * (VECTOR CONST v, MATRIX CONST m) + Zweck: Multiplikation des Vektors 'v' mit der Matrix 'm'. + Fehlerfall: + * VECTOR OP * : LENGTH v <> ROWS m + Die Anzahl der Elemente von 'v' stimmt nicht mit den Anzahl der + Zeilen von 'm' überein. + + VECTOR OP * (MATRIX CONST m, VECTOR CONST v) + Zweck: Multiplikation der Matrix 'm' mit dem Vektor 'v'. + Fehlerfall: + * VECTOR OP * : COLUMNS m <> LENGTH v + Die Anzahl der Spalten von 'm' stimmt nicht mit der Anzahl der + Elementen von 'v' überein. + += + BOOL OP = (MATRIX CONST l, r) + Zweck: Vergleich zweier Matrizen. Der Operator '=' liefert FALSE, wenn + die Anzahl Spalten oder Reihen der Matrizen 'l' und 'r' ungleich + ist und wenn mindestens ein Element mit gleichen Indizes der zwei + Matrizen ungleiche Werte haben. Beispiel: + + MATRIX VAR a :: matrix (3, 3), + b :: matrix (3, 3, 1.0), + c :: matrix (4, 4); + ... a = b ... + (* FALSE wegen ungleicher Werte *) + ... a = c ... + (* FALSE wegen ungleicher Groesse *) + ... b = c ... + (* FALSE wegen ungleicher Groesse *) + +<> + BOOL OP <> (MATRIX CONST l, r) + Zweck: Vergleich der Matrizen 'l' und 'r' auf Ungleichheit. + +:= + OP := (MATRIX VAR l, MATRIX CONST r) + Zweck: Zuweisung von 'r' auf 'l'. Die MATRIX 'l' bekommt u.U. eine neue + Anzahl von Elementen. Beispiel: + + MATRIX VAR a :: matrix (3, 4, 0.0), + b :: matrix (5, 5, 3.0); + ... + a := b; (* 'a' hat jetzt 5 x 5 Elemente *) + + OP := (MATRIX VAR l, INITMATRIX CONST r) + Zweck: Dient zur Initialisierung einer Matrix. Beispiel: + + MATRIX VAR x :: matrix (17, 4); + + 'matrix' erzeugt ein Objekt vom Datentyp INITMATRIX. Dieses + Objekt braucht nicht soviel Speicherplatz wie ein MATRIX-Objekt. + Dadurch wird vermieden, daß nach erfolgter Zuweisung nicht ein + durch 'matrix' erzeugtes Objekt auf dem Heap unnötig Speicher- + platz verbraucht. + +column + VECTOR PROC column (MATRIX CONST m, INT CONST i) + Zweck: Die 'i'-te Spalte von 'm' wird als VECTOR mit 'ROWS m' Elementen + geliefert. Beispiel: + + MATRIX CONST a :: matrix (3, 4); + VECTOR VAR b :: column (a, 1); + (* 'b' hat drei Elemente mit den Werten '0.0' *) + Fehlerfälle: + * PROC column : subscript overflow + Der Index 'i' liegt außerhalb der Matrix 'm' (i > COLUMNS m). + * PROC column : subscript underflow + Der Index 'i' liegt außerhalb der Matrix 'm' (i < 1). + +COLUMNS + INT OP COLUMNS (MATRIX CONST m) + Zweck: Liefert die Anzahl der Spalten von 'm'. Beispiel: + + MATRIX VAR a :: matrix (3, 4), + b :: matrix (7, 10); + put (COLUMNS a); (* 4 *) + put (COLUMNS b); (* 10 *) + +DET + REAL OP DET (MATRIX CONST m) + Zweck: Es wird der Wert der Determinanten von 'm' geliefert. + Fehlerfall: + * OP DET : no square matrix + Die Matrix ist nicht quadratisch, d.h. ROWS m <> COLUMNS m + +get + PROC get (MATRIX VAR m, INT CONST rows, columns) + Zweck: Einlesen von Werten für die Matrix 'm' vom Terminal mit 'rows'- + Zeilen und 'columns'-Spalten. + +idn + INITMATRIX PROC idn (INT CONST size) + Zweck: Erzeugen einer Einheitsmatrix vom Datentyp INITMATRIX. Beispiel: + + MATRIX VAR a :: idn (10); + (* Erzeugt eine Matrix mit 10 x 10 Elementen, + deren Werte '0.0' sind, mit der Ausnahme der + Diagonalelemente, die den Wert '1.0' haben. *) + Fehlerfall: + * PROC idn : size <= 0 + Die angeforderte 'size' Anzahl Spalten oder Zeilen muß > 0 sein. + +INV + MATRIX OP INV (MATRIX CONST m) + Zweck: Liefert als Ergebnis die Inverse von 'm' (Achtung: starke Run- + dungsfehler möglich). + Fehlerfälle: + * OP INV : no square matrix + Die Matrix 'm' ist nicht quadratisch, d.h. ROWS m <> COLUMNS m + * OP INV : singular matrix + Die Matrix ist singulär. + +matrix + INITMATRIX PROC matrix (INT CONST rows, columns) + Zweck: Erzeugen eines Datenobjekts vom Datentyp INITMATRIX mit 'rows' + Zeilen und 'columns' Spalten. Alle Elemente werden mit dem Wert + '0.0' initialisiert. Beispiel: + + MATRIX CONST :: matrix (3, 3); + Fehlerfälle: + * PROC matrix : rows <= 0 + Die angeforderte Zeilenanzahl 'rows' muß > 0 sein. + * PROC matrix : columns <= 0 + Die angeforderte Spaltenanzahl 'columns' muß > 0 sein. + + INITMATRIX PROC matrix (INT CONST rows, columns, REAL CONST value) + Zweck: Erzeugen eines Datenobjekts vom Datentyp MATRIX mit 'rows' + Zeilen und 'columns' Spalten. Alle Elemente der erzeugten MATRIX + werden mit dem Wert 'value' initialisiert. Beispiel: + + MATRIX CONST :: matrix (3, 3, 3.14); + Fehlerfälle: + * PROC matrix : rows <= 0 + Die angeforderte Zeilenanzahl 'rows' muß > 0 sein. + * PROC matrix : columns <= 0 + Die angeforderte Spaltenanzahl 'columns' muß > 0 sein. + +put + PROC put (MATRIX CONST m) + Zweck: Ausgabe der Werte einer Matrix auf dem Terminal. + +replace column + PROC replace column (MATRIX VAR m, INT CONST column index, + VECTOR CONST column value) + Zweck: Ersetzung der durch 'column index' definierten Spalte in der + MATRIX 'm' durch den VECTOR 'column value'. Beispiel: + + MATRIX VAR a :: matrix (3, 5, 1.0); + VECTOR VAR b :: vector (3, 2.0); + ... + replace column (a, 2, b); + (* Die zweite Spalte von 'a' wird durch die Werte von 'b' + ersetzt *) + Fehlerfälle: + * PROC replace column : LENGTH columnvalue <> ROWS m + Die Anzahl der Zeilen der MATRIX 'm' stimmt nicht mit der Anzahl + der Elemente von 'columnvalue' überein. + * PROC replace column : column subscript overflow + Der Index 'columnindex' liegt außerhalb von 'm' + (columnindex > COLUMNS m). + * PROC sub : column subscript underflow + Der Index 'columnindex' liegt außerhalb von 'm' + (columnindex < 1). + +replace element + PROC replace element (MATRIX VAR m , INT CONST row, column, + REAL CONST value) + Zweck: Ersetzung eines Elementes von 'm' in der 'row'-ten Zeile und + 'column'-ten Spalte durch den Wert 'value'. Beispiel: + + MATRIX VAR a :: matrix (5, 5); + ... + replace element (1, 1, 3.14159); + Fehlerfälle: + * PROC replace element : row subscript overflow + Der Index 'row' liegt außerhalb von 'm' (row > ROWS m). + * PROC replace element : row subscript underflow + Der Index 'row' liegt außerhalb von 'm' (row < 1). + * PROC replace element : column subscript overflow + Der Index 'column' liegt außerhalb von 'm' (column > COLUMNS m). + * PROC replace element : row subscript underflow + Der Index 'column' liegt außerhalb von 'm' (column < 1). + +replace row + PROC replace row (MATRIX VAR m, INT CONST rowindex, + VECTOR CONST rowvalue) + Zweck: Ersetzung der Reihe 'rowindex' in der MATRIX 'm' durch den + VECTOR 'rowvalue'. Beispiel: + + MATRIX VAR a :: matrix (3, 5, 1.0); + VECTOR VAR b :: vector (5, 2.0); + ... + replace row (a, 2, b); + (* Die 2. Reihe von 'a' wird durch Werte von 'b' ersetzt *) + Fehlerfälle: + * PROC replace row : LENGTH rowvalue <> COLUMNS m + Die Anzahl der Spalten der MATRIX 'm' stimmt nicht mit der Anzahl + der Elemente von 'rowvalue' überein. + * PROC replace row : row subscript overflow + Der Index 'rowindex' liegt außerhalb von 'm' (rowindex > ROWS m). + * PROC sub : row subscript underflow + Der Index 'rowindex' liegt außerhalb von 'm' (rowindex < 1). + +row + VECTOR PROC row (MATRIX CONST m, INT CONST i) + Zweck: Die 'i'-te Reihe von 'm' wird als VECTOR mit 'COLUMNS m' + Elementen geliefert. Beispiel: + + MATRIX CONST a :: matrix (3, 4); + VECTOR VAR b :: row (a, 1); + (* 'b' hat vier Elemente mit den Werten '0.0'*) + Fehlerfälle: + * PROC row : subscript overflow + Der Index 'i' liegt außerhalb der Matrix 'm' (i > ROWS m). + * PROC row : subscript underflow + Der Index 'i' liegt außerhalb der Matrix 'm' (i < 1). + +ROWS + INT OP ROWS (MATRIX CONST m) + Zweck: Liefert die Anzahl der Zeilen von 'm'. Beispiel: + + MATRIX VAR a :: matrix (3, 4), + b :: matrix (7, 10); + ... + put (ROWS a); (* 3 *) + put (ROWS b); (* 7 *) + +sub + REAL PROC sub (MATRIX CONST m, INT CONST row, column) + Zweck: Liefert den Wert eines Elementes von 'm', welches durch die + Indizes 'row' und 'column' bestimmt wird. Beispiel: + + MATRIX VAR m :: matrix (5, 10, 1.0); + put (sub (m, 3, 7)); + Fehlerfälle: + * PROC sub : row subscript overflow + Der Index 'row' liegt außerhalb von 'm' (row > ROWS m). + * PROC sub : row subscript underflow + Der Index 'row' liegt außerhalb von 'm' (row < 1). + * PROC sub : column subscript overflow + Der Index 'column' liegt außerhalb von 'm' (column > ROWS m). + * PROC sub : row subscript underflow + Der Index 'column' liegt außerhalb von 'm' (column < 1). + +TRANSP + MATRIX OP TRANSP (MATRIX CONST m) + Zweck: Liefert als Ergebnis die transponierte Matrix 'm'. + +transp + PROC transp (MATRIX VAR m) + Zweck: Transponieren der Matrix 'm', wobei kaum zusätzlicher Speicher- + platz benötigt wird. + + + +2. COMPLEX + +Das COMPLEX-Paket ist im ausgelieferten Standard-System noch nicht vorüber- +setzt, sondern wird im Quellcode ausgeliefert und kann so bei Bedarf von +jeder EUMEL-Installation in die implementationsabhängigen Standard-Pakete +aufgenommen werden. + +Folgende Operationen stehen für COMPLEX zur Verfügung: + +put Ausgabe auf dem Terminal +get Eingabe auf dem Terminal +complex zero Denotierungsprozedur +complex one dito +complex i dito +complex dito +real part Realteil eines komplexen Werts +imag part Imaginärteil eines komplexen Werts +phi Winkel in der Polardarstellung (Radiant) +dphi dito, in Winkelgrad +CONJ Konjugiert komplexer Wert +sqrt Wurzelfunktion + + + - + * + / + := + = + <> + + + +Beschreibung der COMPLEX-Operationen + += + BOOL OP = (COMPLEX CONST a, b) + Zweck: Vergleich von 'a' und 'b' auf Gleichheit. + +:= + OP := (COMPLEX VAR a, COMPLEX CONST b) + Zweck: Zuweisung. + +<> + BOOL OP <> (COMPLEX CONST a, b) + Zweck: Vergleich von 'a' und 'b' auf Ungleichheit. + ++ + COMPLEX OP + (COMPLEX CONST a, b) + Zweck: Summe von 'a' und 'b'. + +- + COMPLEX OP - (COMPLEX CONST a, b) + Zweck: Differenz von 'a' und 'b'. + +* + COMPLEX OP * (COMPLEX CONST a, b) + Zweck: Multiplikation von 'a' mit 'b'. + +/ + COMPLEX OP / (COMPLEX CONST a, b) + Zweck: Division von 'a' mit 'b'. + +ABS + REAL OP ABS (COMPLEX CONST x) + Zweck: REAL-Betrag von 'x'. + +complex + COMPLEX PROC complex (REAL CONST re, im) + Zweck: Denotierungsprozedur. Angabe in kartesischen Koordinaten. + +complex i + COMPLEX PROC complex i + Zweck: Denotierungsprozedur für den komplexen Wert '0.0 + i 1.0'. + +complex one + COMPLEX PROC complex one + Zweck: Denotierungsprozedur für den komplexen Wert '1.0 + i 0.0'. + +complex zero + COMPLEX PROC complex zero + Zweck: Denotierungsprozedur für den komplexen Wert '0.0 + i 0.0'. + +CONJ + COMPLEX OP CONJ (COMPLEX CONST number) + Zweck: Liefert den konjugiert komplexen Wert von 'number'. + +dphi + REAL PROC dphi (COMPLEX CONST x) + Zweck: Winkel von 'x' (Polardarstellung). + +get + PROC get (COMPLEX VAR a) + Zweck: Einlesen eines komplexen Wertes vom Bildschirm in der Form + zweier REAL-Denoter. Die Eingabe kann editiert werden. + +imag part + REAL PROC imag part (COMPLEX CONST number) + Zweck: Liefert den Imaginärteil des komplexen Wertes 'number'. + +phi + REAL PROC phi (COMPLEX CONST x) + Zweck: Winkel von 'x' (Polardarstellung) in Radiant. + +put + PROC put (COMPLEX CONST a) + Zweck: Ausgabe eines komplexen Wertes auf dem Bildschirm in Form zweier + REAL-Werte. Hinter jedem REAL-Wert wird ein Leerzeichen angefügt. + +real part + REAL PROC real part (COMPLEX CONST number) + Zweck: Liefert den Real-Teil des komplexen Wertes 'number'. + +sqrt + COMPLEX PROC sqrt (COMPLEX CONST x) + Zweck: Wurzelfunktion für komplexe Werte. + + + +3. LONGINT + +LONGINT ist ein Datentyp, für den (fast) alle Prozeduren und Operatoren des +Datentyps INT implementiert wurden. LONGINT unterscheidet sich von INT +dadurch, daß erheblich größere Werte darstellbar sind. + +Für den Datentyp LONGINT stehen folgende Operationen zur Verfügung: + +get Eingabe vom Terminal +put Ausgabe vom Terminal +ABS, abs Absolutbetrag +INCR, DECR Addition und Zuweisung bzw. Subtraktion und Zuweisung +DIV Division ohne Rest +int, text Konvertierungen +longint dito +max, min Maximum bzw. Minimum zweier LONGINTs +MOD Modulo-Funktion +random Zufallszahlen +sign Vorzeichen + < + > + <= + <> + = + - + + + * + ** + + + +Beschreibung der LONGINT-Operationen + +< + BOOL OP < (LONGINT CONST left, right) + Zweck: Vergleichen zweier LONGINTs auf kleiner. + +> + BOOL OP > (LONGINT CONST left, right) + Zweck: Vergleichen zweier LONGINTs auf größer. + +<= + BOOL OP <= (LONGINT CONST left, right) + Zweck: Vergleichen zweier LONGINTs auf kleiner gleich. + +>= + BOOL OP >= (LONGINT CONST left, right) + Zweck: Vergleichen zweier LONGINTs auf größer gleich. + +<> + BOOL OP <> (LONGINT CONST left, right) + Zweck: Vergleichen zweier LONGINTs auf Ungleichheit. + += + BOOL OP = (LONGINT CONST left, right) + Zweck: Vergleichen zweier LONGINTs auf Gleichheit. + +- + LONGINT OP - (LONGINT CONST argument) + Zweck: Vorzeichenumkehrung. + + LONGINT OP - (LONGINT CONST left, right) + Zweck: Subtraktion zweier LONGINTs. + ++ + LONGINT OP + (LONGINT CONST argument) + Zweck: Monadischer Operator. Ohne Wirkung. + + LONGINT OP + (LONGINT CONST left, right) + Zweck: Addition zweier LONGINTs. + +* + LONGINT OP * (LONGINT CONST left, right) + Zweck: Multiplikation von zwei LONGINTs. + +** + LONGINT OP ** (LONGINT CONST argument, exponent) + Zweck: Exponentiation zweier LONGINTs mit positivem Exponenten. + Fehlerfälle : + * LONGINT OP ** : negative exponent + Der 'exponent' muß >= 0 sein. + * 0 ** 0 is not defined + 'argument' und 'exponent' dürfen nicht gleich 0 sein. + + + LONGINT OP ** (LONGINT CONST argument, INT CONST exponent) + Zweck: Exponentiation eines LONGINT mit positiven INT Exponenten. + Fehlerfälle : + * LONGINT OP ** : negative exponent + Der 'exponent' muß >= 0 sein. + * 0 ** 0 is not defined + 'argument' und 'exponent' dürfen nicht gleich 0 sein. + +ABS + LONGINT OP ABS (LONGINT CONST argument) + Zweck: Absolutbetrag eines LONGINT. + +abs + LONGINT PROC abs (LONGINT CONST argument) + Zweck: Absolutbetrag eines LONGINT. + +DECR + OP DECR (LONGINT VAR resultat, LONGINT CONST ab) + Zweck: resultat := resultat - ab + +DIV + LONGINT OP DIV (LONGINT CONST left, right) + Zweck: Division zweier LONGINTs. + Fehlerfall : + * divide by zero + 'right' muß <> 0 sein. + +get + PROC get (LONGINT VAR zahl) + Zweck: Eingabe eines LONGINTs vom Terminal. + + PROC get (FILE VAR file, LONGINT VAR zahl) + Zweck: Einlesen von 'zahl' aus der sequentiellen Datei 'file'. Die + Datei muß mit 'input' assoziiert sein (vergl. 'sequential file'). + Fehlerfälle : + * file not open + Die Datei 'file' ist gegenwärtig nicht assoziiert. + * input after end of file + Es wurde versucht, über die letzte Zeile einer Datei zu lesen. + * input access to output file + Es wurde versucht, von einem mit 'output' assoziierten FILE zu + lesen. + +INCR + LONGINT OP INCR (LONGINT VAR resultat, LONGINT CONST dazu) + Zweck: resultat := resultat + dazu + +int + INT PROC int (LONGINT CONST longint) + Zweck: Konvertierung von LONGINT nach INT. + Fehlerfall : + * integer overflow + 'longint' ist größer als 'maxint'. + +longint + LONGINT PROC longint (INT CONST int) + Zweck: Konvertierung von 'int' nach LONGINT. + + LONGINT PROC longint (TEXT CONST text) + Zweck: Konvertierung von 'text' nach LONGINT. + +max + LONGINT PROC max (LONGINT CONST left, right) + Zweck: Liefert das Maximum zweier LONGINTs. + +min + LONGINT PROC min (LONGINT CONST left, right) + Zweck: Liefert das Minimum zweier LONGINTs. + +MOD + LONGINT OP MOD (LONGINT CONST left, right) + Zweck: Modulo-Funktion für LONGINTs. Der Rest einer LONGINT-Division + wird ermittelt. + Fehlerfall : + * text (left) + 'MOD 0' + 'right' muß ungleich null sein. + +put + PROC put (LONGINT CONST longint) + Zweck: Ausgabe eines LONGINTs auf dem Bildschirm. Anschließend wird + ein Leerzeichen ausgegeben. Hardwareabhängig sind die Aktionen, + wenn eine Ausgabe über die Bildschirmzeilengrenze vorgenommen + wird. Meist wird jedoch die Ausgabe auf der nächsten Zeile fort- + gesetzt. + + PROC put (FILE VAR file, LONGINT CONST zahl) + Zweck: Ausgabe von 'zahl' in die sequentielle Datei 'file'. 'file' muß + mit 'output' assoziiert sein. + Fehlerfälle : + * file not open + Die Datei 'file' ist gegenwärtig nicht assoziiert. + * output access to input file + Es wurde versucht, auf einem mit 'input' assoziierten FILE zu + schreiben. + +random + LONGINT PROC random (LONGINT CONST lower bound, upper bound) + Zweck: Pseudo-Zufallszahlen-Generator im Intervall 'lower bound' und + 'upper bound' einschließlich. Es handelt sich hier um den + 'LONGINT Random Generator'. + +SIGN + INT OP SIGN (LONGINT CONST longint) + Zweck: Feststellen des Vorzeichens von 'longint'. Liefert: + + 0 wenn 'longint' = 0, + 1 wenn 'longint' > 0, + -1 wenn 'longint' < 0. + +sign + INT PROC sign (LONGINT CONST longint) + Zweck: Feststellen des Vorzeichens von 'longint'. Liefert: + + 0 wenn 'longitt' = 0, + 1 wenn 'longint' > 0, + -1 wenn 'longint' < 0. + +text + TEXT PROC text (LONGINT CONST longint) + Zweck: Konvertierung von 'longint' nach TEXT. + + TEXT PROC text (LONGINT CONST longint, INT CONST laenge) + Zweck: Konvertierung von 'longint' nach TEXT. Die Anzahl der Zeichen + soll 'laenge' betragen. Für + + LENGTH (text (longint)) < laenge + + werden die Zeichen rechtsbündig in einen Text mit der Länge + 'laenge' eingetragen. Ist der daraus entstehende TEXT kleiner + als 'laenge', werden die an 'laenge' fehlenden Zeichen im TEXT + mit Leerzeichen aufgefüllt. Für + + LENGTH (text (longint)) > length + + wird ein Text mit der Länge 'length' geliefert, der mit + '*'-Zeichen gefüllt ist. + diff --git a/doc/user-manual/1.7.3-pd/doc/source-disk b/doc/user-manual/1.7.3-pd/doc/source-disk new file mode 100644 index 0000000..f769920 --- /dev/null +++ b/doc/user-manual/1.7.3-pd/doc/source-disk @@ -0,0 +1 @@ +173_publicdomain/03_benutzerhandbuch.img diff --git a/doc/user-manual/1.8.7/doc/benutzerhandbuch.1 b/doc/user-manual/1.8.7/doc/benutzerhandbuch.1 new file mode 100644 index 0000000..7c8fec7 --- /dev/null +++ b/doc/user-manual/1.8.7/doc/benutzerhandbuch.1 @@ -0,0 +1,580 @@ +____________________________________________________________________________ + + +#on("b")##on ("u")# +#center#Betriebssystem E U M E L +#off ("u")# + + +#center#Benutzerhandbuch + + + + +#off("b")# +#center#Lizenzfreie Software der +#on ("b")# + +#center#Gesellschaft für Mathematik und Datenverarbeitung mbH, +#center#5205 Sankt Augustin + + +#off("b")# +#center#Die Nutzung der Software ist nur im Schul- und Hochschulbereich für +#center#nichtkommerzielle Zwecke gestattet. + +#center#Gewährleistung und Haftung werden ausgeschlossen + + +____________________________________________________________________________ +#page# + +#start(5.0,1.5)##pagenr("%",1)##setcount(1)##block##pageblock##count per page# +#headeven# +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# + EUMEL-Benutzerhandbuch +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#headodd# +#lpos(0.0)##cpos(5.5)##rpos(11.0)##fillchar(" ")# +#table# + Teil 1: Einleitung +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#bottomeven# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +1 - % GMD +#tableend##clearpos# +#end# +#bottomodd# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +GMD 1 - % +#tableend##clearpos# +#end# +TEIL 1: Einleitung +#free(1.0)# + +1.1. Vorwort +#free(1.0)# + +Dieses Buch bietet Ihnen eine Anleitung zur Handhabung des Betriebssystems +EUMEL in Hinblick auf die Textverarbeitung. Das Buch wendet sich somit an alle, die +das leicht erlernbare EUMEL-System zur Erstellung von Texten jeglicher Art und +jeden Umfangs nutzen wollen. + +Die Anleitung erfordert keinerlei Vorkenntnisse, weder von Computern im allgemei +nen noch von EUMEL im besonderen. Neulingen auf dem Gebiet der Benutzung eines +Computers sei empfohlen, dieses erste Kapitel, das sich kurz mit der 'grauen Theorie' +beschäftigt, mindestens zweimal zu lesen: + +- Der erste Durchgang sollte nur einer groben Orientierung dienen. Die Begriffe, die + teilweise erst im routinierteren Umgang Sinn gewinnen, sollten Sie 'mal gehört' + haben, um die folgenden Kapitel leichter lesen zu können. + +- Der zweite Durchgang erscheint uns sinnvoll, wenn Sie sich 'freigeschwommen' + haben. Wenn der Umgang mit dem EUMEL-System Ihnen nach einigen Tagen + schon vertrauter erscheint, ist es zweckmäßig, sich auf dem Hintergrund der + gemachten Erfahrungen die Erklärungen noch einmal durchzulesen. Einige der + Begriffe werden erst dann wirklich verständlich und manche Unsicherheit wird + beseitigt werden. + +Die weiteren Teile des Buches geben dann Anleitung vom ersten Einstieg ins +EUMEL-System bis hin zur detaillierten Beschreibung der Textverarbeitung. Alle in +Teil 3 und 4 enthaltenen Beispiele sollten Sie sorgfältig durchgehen und am Bild +schirm nachvollziehen. Aus dem Teil 5 können Sie nach eigener Einschätzung zu +nächst die Bereiche auswählen, die Sie selbst für besonders wichtig halten. Sie wer +den feststellen, daß Sie durch den Umgang mit der EUMEL-Textverarbeitung mit +fortschreitender Routine immer mehr der gebotenen Möglichkeiten hinzunehmen +werden. +#free(1.0)# +Was ist ein Betriebssystem ? + +Ein #ib#Betriebssystem#ie# ist eine Sammlung von Programmen, die dem Benutzer eines +Computers die Arbeit mit diesem Gerät erst ermöglichen. Die Programme des Be +triebssystems stellen die Verbindung zwischen den Bausteinen eines Computers, der +Hardware, und den Anwendungsprogrammen eines Benutzers her. + +Alle Programme, die diese riesige Lücke schließen und z.B. dafür sorgen, daß der +Befehl: #on("i")#drucke ("diesen brief")#off("i")# tatsächlich dazu führt, daß der eben noch am Bild +schirm verfaßte Brief zum Drucker gesendet und dort ausgedruckt wird, sind soge +nannte Systemprogramme, Teile des Betriebssystems. + +Dieses Benutzerhandbuch zum Betriebssystem EUMEL wird Ihnen schrittweise die +Befehle erklären, die Sie zur Nutzung aller Möglichkeiten der Textverarbeitung mit +EUMEL verwenden können, und Ihnen somit einen Teil des Betriebssystems vorstel +len. +#free(1.0)# +Ist EUMEL anders als andere ? + +#on("b")#Ja.#off("b")# Das Betriebssystem EUMEL (#on("b")#E#off("b")#xtendable multi #on("b")#U#off("b")#ser #on("b")#M#off("b")#icroprocessor #on("b")#EL#off("b")#an Sy +stem) erklärt durch seinen voll ausgeschriebenen Namen einen wesentlichen Unter +schied zu anderen Systemen: "Erweiterbares Mehrbenutzer Mikroprozessor ELAN- +System." + +Während andere auf Mikroprozessoren (und damit auf sogenannte Personal Compu +ter) abgestimmte Betriebssysteme #on("u")#einen#off("u")# Benutzer bei seiner Arbeit unterstützen, ist +EUMEL fähig, #on("u")#mehreren#off("u")# Anwendern gleichzeitig die Benutzung eines Computers zu +ermöglichen. Natürlich funktioniert EUMEL ebensogut für einen einzigen Benutzer. Es +gibt aber bei EUMEL die Möglichkeit, durch Ankoppeln weiterer Bildschirme an den +Rechner und #on("b")#ohne#off("b")# Kosten für zusätzliche Software mehreren Benutzern gleichzeitig +die Arbeit an diesem Rechner zu ermöglichen. + +Zweitens ist EUMEL hardwareunabhängig, das heißt, gleichgültig von welchem Her +steller Ihr Computer stammt, die Bedienung und die Kommandosprache ist immer +gleich. Auch können Disketten, die mit einem XY-Rechner beschrieben wurden, von +einem ABC-Computer gelesen werden; durchaus keine Selbstverständlichkeit. + +Eine weitere Besonderheit des EUMEL-Systems macht alle froh, die damit arbeiten: +EUMEL ist durchgängig in der Programmiersprache ELAN gehalten. Auch wenn Sie +(noch) nicht programmieren möchten, erleichtert Ihnen ELAN das Leben dadurch, daß +Sie schreiben können, was Sie meinen: eine Datei, die einen Geschäftsbrief fix und +fertig und druckbereit enthält, heißt nicht etwa: + + $TXT.PRT + +sondern: + + Angebot an Fa.Müller 1.7.86 + + +Ein weiterer wichtiger Unterschied wird Ihnen bewußt werden, wenn Sie ein anderes +Betriebssystem kennen: Die EUMEL-Textverarbeitung ist kein zusätzliches Programm +mit eigener Kommandosprache, welches bei Bedarf geladen werden muß, sondern +steht jederzeit, im wahrsten Sinne des Wortes auf Knopfdruck, zu Ihrer Verfügung. +#free(1.5)# +1.2. Wichtige Begriffe +#free(1.0)# +- #on("b")#TASK#off("b")#. Eine #ib#Task#ie# ist ein eigenständiger Prozeß innerhalb eines EUMEL-Systems, + der entweder zur Verwaltung des EUMEL-Systems oder zu einem Benutzer + gehört. Indem jedem Benutzer ein eigener Arbeitsbereich zugewiesen ist, wird + verhindert, daß unkontrolliert auf fremde Daten zugegriffen wird. Eine Task hat + einen Namen, mit dem sie angesprochen werden kann. Ein EUMEL-System + besteht aus mehreren Tasks. + + Ein brauchbarer Vergleich mit einem EUMEL-Tasksystem ist ein Firmengebäude: + Es besteht aus vielen Räumen und jeder Raum ( = Task ) ist entweder ein nor + males Arbeitszimmer oder ein Chefzimmer oder eine Werkstatt, in der Dienst + leistungen für andere erledigt werden. + + Eine solche Ordnung zeigt folgendes Tasksystem; der #on("i")#kursiv#off("i")# gesetzte Kommentar + zeigt die Benennung der 'Dienstposten' eines vergleichbaren Büros: + + + SUPERVISOR #on("i")#(* Zimmerverwalter *)#off("i")# - + - + + SYSUR #on("i")#(* Werkstattmeister *)#off("i")# + + + ARCHIVE #on("i")#(* Archivar *)#off("i")# + + configurator #on("i")#(* Elektriker *)#off("i")# + + OPERATOR #on("i")#(* Hausmeister *)#off("i")# + + shutup #on("i")#(* Nachtwächter *)#off("i")# + + UR #on("i")#(* Aufsichtsrat *)#off("i")# + + PUBLIC #on("i")#(* Abteilungsleiter *)#off("i")# + + Meier #on("i")#(* Angestellter *)#off("i")# + Müller #on("i")#(* " *)#off("i")# + Schulze #on("i")#(* " *)#off("i")# + + + Bildlich gesprochen stellt eine Task also ein 'Arbeitszimmer' für einen EUMEL- + Benutzer dar. Als EUMEL Anwender richten Sie sich Ihre Task selbst ein, indem + Sie das Kommando 'begin ("taskname")' geben. + + Nachdem Sie dieses Kommando einmal gegeben haben, existiert diese Task unter + dem von Ihnen gewählten Namen. + + In der Task (also sinngemäß im Arbeitszimmer) arbeiten Sie - insbesondere legen + Sie Dateien (= Akten) an. Dateien existieren nur innerhalb einer Task. + + Tasks werden durch den SUPERVISOR verwaltet, er regelt den Zugriff auf Tasks. + Um Ihre Task zu verlassen, geben Sie das Kommando 'break' an den + SUPERVISOR, um sie wieder zu betreten, das Kommando 'continue ("taskna + me")'. + + +- #on("b")#DATEI#off("b")#. Eine #ib#Datei#ie# ist eine Menge von zusammengehörigen Daten. Eine Datei in + einer Task entspricht einer Akte in einem Arbeitszimmer. Eine Task kann bis zu + 200 Dateien enthalten. Jede Datei in einer Task hat einen eigenen Namen, in ver + schiedenen Tasks dürfen gleichnamige Dateien existieren. Eine Datei ist in Zeilen + unterteilt. + + Für die Arbeit in einer Datei am Bildschirm muß auf die Datei mit dem Editor + zugegriffen werden: 'edit ("dateiname")', danach kann der Inhalt der Datei am + Terminal bearbeitet werden (siehe Kapitel 4 und 5). + + +- #on("b")#KOMMANDO#off("b")#. Ein #ib#Kommando#ie# ist ein Befehl an den Rechner, eine Arbeit zu tun. + Welche Kommandos Sie dem Rechner zum jeweiligen Zeitpunkt geben können, + hängt davon ab, auf welcher 'Kommandoebene' Sie sich befinden. Als Anhalt gilt: + + - Kommandos auf Supervisor-Ebene betreffen das Tasksystem. + + - Kommandos auf Monitor-Ebene betreffen die eigene Task oder Dateien. + + - Kommandos auf Editor- Ebene betreffen Zeilen, Worte oder einzelne Zeichen + der aktuellen Datei. + + Auf welcher Ebene Sie sich befinden, werden Sie nach kurzer Gewöhnung leicht + am Bildschirm erkennen (siehe Teil 3). + + Bei manchen Kommandos muß nicht nur gesagt werden, was getan werden soll, + sondern auch, womit es getan werden soll. Eine solche Angabe zum Kommando + heißt #ib#Parameter#ie#. + Kommando Parameter + | | + Beispiel: Lege neue Task an = begin ("taskname") + Drucke Datei = print ("dateiname"). + Suche das Wort ENDE = down ("ENDE") + + Parameter werden in runde Klammern gesetzt und ggf. durch Kommata voneinan + der getrennt. Textparameter werden zusätzlich in Anführungsstriche gesetzt. + + Ein Kommando kann keinen, einen oder viele Parameter benötigen; die + Beschreibung der Kommandos in diesem Buch zeigt jeweils alle Möglichkeiten. + + +- #on("b")#SUPERVISOR#off("b")#. Spezielle Task zur Überwachung eines EUMEL-Systems. Ein + Benutzer kann durch die #ib#Supervisor#ie#-Kommandos Leistungen von dieser Task + fordern: neue Task einrichten, Task wiederaufnehmen und diverse Informationen. + + +- #on("b")#MONITOR#off("b")#. Befehlsempfänger in einer Task. Jede Arbeit im EUMEL-System + findet in einer Task statt. Die Arbeit mit einem Computer besteht in wesentlichen + Teilen im Aufruf von Programmen durch Kommandos. Der Empfänger dieser + Kommandos in einer Task ist der #ib#Monitor#ie#. Der Monitor ist sichtbar durch eine + Zeile, in der 'gib kommando' steht. In diese Zeile werden #ib#Kommando#ie#s und erfor + derliche Parameter eingegeben. + + +- #on("b")#ARCHIVE#off("b")#. Spezielle Task zur Verwaltung des Diskettenlaufwerks. Da für die + längerfristige Datenhaltung und zur zusätzlichen Datensicherung Dateien auf + Disketten geschrieben werden, besitzt das EUMEL-System für diese Aufgabe + eine besondere Task, die die Bedienung vereinfacht und exklusiven Zugriff auf das + Laufwerk garantiert. + + +- #on("b")#EDITOR#off("b")#. Programm zur Dateibearbeitung am Bildschirm. Das Programm wird + durch das ( Monitor- ) Kommando 'edit' und die Eingabe des Namens der ge + wünschten Datei als Parameter gestartet. + + Da ein Bildschirm normelerweise auf 80 Zeichen Zeilenbreite und 24 Zeilen be + schränkt ist, kann der Editor als Fenster betrachtet werden, das über die mögli + cherweise weitaus größere Datei bewegt wird und durch das der betrachtete Aus + schnitt der Datei bearbeitet werden kann. + + + +-------------------------------------------------------------------+ + i i + i i + +------------------------------------+ i + i i i + i Der Editor, Fenster zur i i + i Dateibearbeitung i i + i i i + +------------------------------------+ i + i i + +-------------------------------------------------------------------+ + + + + + + + + + + +1.3. Die Notation in diesem Buch +#free(1.0)# +Im weiteren Text werden Sie schrittweise in die Bedienung des Systems eingeführt. +Für alle Kommandos und Arbeiten haben wir Beispiele in dieses Buch aufgenommen, +die Sie direkt am Rechner nachvollziehen sollten. + +Beachten Sie dabei bitte folgende Regeln der Aufschreibung: + +- Es gibt eine Reihe von Tasten auf einer Computertastatur, die eine besondere + Bedeutung haben. Diese sogenannten Funktionstasten werden ebenso wie beson + dere Tastenkombinationen explizit als Tasten dargestellt: + + + <SV> + + <ESC> <e> + + <CR> + + +- Alles, was Sie am Bildschirm Ihres Rechners schreiben oder lesen sollen, ist in + Textbereiche, die einen Bildschirm darstellen, eingefaßt. + + Beispiel: + +____________________________________________________________________________ + +gib kommando: +edit ("meine datei") + +____________________________________________________________________________ + + +- Innerhalb des Handbuchs sind in der Aufschreibung die Konventionen der + Programmiersprache ELAN, in der alle Programme des Betriebssystems geschrie + ben sind, berücksichtigt. Dabei sind folgende Besonderheiten zu beachten: + + 1) Kommandos werden grundsätzlich klein geschrieben. + + 2) Dateinamen u.ä. werden in Klammern und Anführungsstriche gesetzt. In + diesem Buch steht an den Stellen, wo ein Dateiname auftaucht #on("i")# 'dateiname' #off("i")#; + den Namen, den Sie tatsächlich verwenden, können Sie frei wählen. + + 3) Falls besondere Begriffe oder Beispiele innerhalb eines normalen Textes + auftreten, werden sie in einfache Anführungsstriche gesetzt. + + +Also: Das Kommando 'edit' benötigt als Parameter einen Dateinamen. Wählen Sie + einen Namen und geben Sie 'edit ("dateiname")' ein. Falls Sie den Namen #on("i")# + "Geschäftsbrief" #off("i")# gewählt haben, müssen Sie am Bildschirm: + + +edit ("Geschäftsbrief") + + +tippen und das Kommando mit der <CR> Taste dem Monitor zur Bearbeitung überge +ben: + +____________________________________________________________________________ + +gib kommando : +edit ("Geschäftsbrief") + +____________________________________________________________________________ + + + + +#on("b")##on("i")#Die Eingabe von <CR> als 'Auslöser' für die Ausführung von +Kommandos wird im weiteren nicht besonders hervorgehoben.#off("b")##off("i")# +#page# +1.4. Voraussetzungen + +#free(1.0)# +Neben dem Computer an sich ist die vollständige Installation eines EUMEL-Systems +auf diesem Computer Voraussetzung für alle im folgenden beschriebenen Aktivitäten. + +Die Beschreibung einer Systeminstallation finden Sie im Anhang I. Im weiteren gehen +wir davon aus, daß Ihr Rechner sich in einem Zustand befindet, der durch Eingabe +von <SV> oder <CNTL> <b> (gleichzeitig) die sogenannte EUMEL-Tapete zeigt und +Supervisor-Kommandos annimmt. + + +____________________________________________________________________________ + + Terminal 2 + + + EUMEL Version 1.8/M + + + gib supervisor kommando: + begin("meine erste task") + + + + ESC ? --> help + ESC b --> begin("") ESC h --> halt + ESC c --> continue("") ESC s --> storage info + ESC q --> break ESC t --> task info + + +____________________________________________________________________________ + + + +Weiterführende Information zum Aufbau eines EUMEL-Systems finden Sie im An +hang I. + +#page# +Die Funktionstasten des EUMEL-Systems + + + +Die Lage der EUMEL-Funktionstasten entnehmen Sie bitte der speziellen Installa +tionsanleitung zu dem von Ihnen benutzten Gerät. #l pos (0.0)##l pos(4.0)# + + +<,>,v,^ Positionierungstasten +#table# +#free(0.5)# +<SHIFT> Umschalttaste +#free(0.5)# +<CR> Eingabe-/ Absatztaste +#free(0.5)# +<HOP> Verstärkertaste +#free(0.5)# +<RUBOUT> Löschtaste +#free(0.5)# +<RUBIN> Einfügetaste +#free(0.5)# +<TAB> Tabulatortaste +#free(0.5)# +<MARK> Markiertaste +#free(0.5)# +<ESC> Kommandotaste +#free(0.5)# +<SV> Supervisortaste +#free(0.5)# +<STOP> Stoptaste +#free(0.5)# +<WEITER> Weitertaste +#tableend##clear pos# + +Task-Organisation +#free(1.0)# + +Zum Verständnis der Handhabung des Systems sollten Sie versuchen, eine Vorstel +lung von der Organisation der Teile zu bekommen. + +Die einzelnen #ib#Task#ie#s eines EUMEL-Systems 'stehen nicht frei im Raum', sondern +sind in einer baumartigen Beziehung organisiert: + + + +SUPERVISOR + - + SYSUR + configurator + OPERATOR + + ARCHIVE +UR + PUBLIC + Meyer + Müller + Schulze + + + +Das System besteht aus zwei Zweigen, die nebeneinander liegen: + +Dem Systemzweig mit der Wurzel SUPERVISOR + + und + +dem Benutzerzweig mit der Wurzel UR. + +Der Systemzweig stellt Ihnen privilegierte Dienstleistungen zur Verfügung, der Benut +zerzweig stellt die normale Arbeitsumgebung dar. + +Alle unter diesen Wurzeln liegenden Tasks des EUMEL-Systems haben mindestens +einen Vorgänger, es besteht also eine 'Vater-Sohn Beziehung' zwischen allen Tasks +des Systems. + +Grundsätzlich können Dateien ohne besondere Kommandos zur Vater-Task geschickt +und von der Vater-Task geholt werden, aber nicht zu beliebigen anderen Tasks. + +'Müller' kann eine Datei an '#ib#PUBLIC#ie#' schicken und 'Schulze' kann sie dann dort +abholen, aber eine direkte Sendung von 'Müller' nach 'Schulze' ist in der Regel nicht +möglich. + +Zur Sprechweise: jede Task, über die diese Art von 'Dateivermittlung' abgewickelt +werden kann, heißt 'Manager-Task'. Jede Task kann zum '#ib#Manager#ie#' erklärt werden. +1.5. Eine Beispielsitzung +#free(1.0)# +Der Ablauf zur Erstellung eines Schreibens stellt sich im EUMEL-System wie folgt +dar: + + <SV> SUPERVISOR aufrufen + + + +____________________________________________________________________________ + + Terminal 2 + + + EUMEL Version 1.8/M + + + gib supervisor kommando: + begin("meine erste task") + + + + ESC ? --> help + ESC b --> begin("") ESC h --> halt + ESC c --> continue("") ESC s --> storage info + ESC q --> break ESC t --> task info + + +____________________________________________________________________________ + + +Durch das Kommando 'begin ("meine erste task")', welches durch <CR> abgeschlos +sen werden muß, wird eine Task mit dem Namen 'meine erste task' im Benutzer +zweig, also unterhalb von 'PUBLIC' angelegt. Würde diese Task bereits existieren, so +könnten Sie sie mit 'continue ("meine erste task")' an das Terminal holen. + +____________________________________________________________________________ + +gib kommando : +edit ("Rechnung zum 31.12.86") + +____________________________________________________________________________ + + +In der Task eröffnen Sie eine Datei mit dem Kommando 'edit ("dateiname")'. Falls +diese Datei neu ist, erfolgt eine Kontrollfrage (zur Kontrolle der gewünschten Schreib +weise des Dateinamens), die Sie durch <j> bejahen. + +Die Datei ist in diesem Beispiel bereits mit etwas Text gefüllt. Tippen Sie einen belie +bigen Text ein und beenden Sie die Bearbeitung dieser ersten Datei durch Drücken +der Tasten <ESC> <q> (nacheinander!). + + +____________________________________________________________________________ +.................... Rechnung zum 31.12.86 ...................... Zeile 1 + G M D + Sankt Augustin + Schloß Birlinghoven + +Sehr geehrte Damen und Herren, +> + + +____________________________________________________________________________ + + + + +Um die Arbeit in der Task zu beenden, geben Sie auch an dieser Stelle <ESC> <q> +(nacheinander!) ein. + +Nach Verlassen der Task ist wiederum die EUMEL-Tapete auf dem Bildschirm. Jede +weitere Aktion wird wiederum von hier aus durch <SV> begonnen. Insbesondere zum +#ib#Ausschalten des Geräts#ie# muß nach <SV> die Task '#ib#shutup#ie#' angestoßen werden (siehe +auch Anhang I). + diff --git a/doc/user-manual/1.8.7/doc/benutzerhandbuch.2 b/doc/user-manual/1.8.7/doc/benutzerhandbuch.2 new file mode 100644 index 0000000..0153fae --- /dev/null +++ b/doc/user-manual/1.8.7/doc/benutzerhandbuch.2 @@ -0,0 +1,443 @@ +#start(5.0,1.5)##pagenr("%",1)##setcount(1)##block##pageblock##count per page# +#headeven# +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# + EUMEL-Benutzerhandbuch +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#headodd# +#lpos(0.0)##cpos(5.5)##rpos(11.0)##fillchar(" ")# +#table# + Teil 2: Der Supervisor +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#bottomeven# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +2 - % GMD +#tableend##clearpos# +#end# +#bottomodd# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +GMD 2 - % +#tableend##clearpos# +#end# + +TEIL 2: Der Supervisor +#free(1.0)# + +#ib(9)#2.1. Steuerkommandos#ie(9)# +#free(1.0)# + +Jegliche Aktivität im EUMEL-System beginnt mit dem Aufruf des SUPERVISOR +durch Drücken der Taste + + <SV> + + +Dieser Tastendruck koppelt Ihr Terminal an den Rechner an. Dieser Vorgang ist auch +dann nötig, wenn diese Geräte praktisch eine Einheit bilden. + + +____________________________________________________________________________ + + Terminal 2 + + + EUMEL Version 1.8/M + + + gib supervisor kommando: + + + + + ESC ? --> help + ESC b --> begin("") ESC h --> halt + ESC c --> continue("") ESC s --> storage info + ESC q --> break ESC t --> task info + + +____________________________________________________________________________ + + +Die auf den unteren Informationszeilen angezeigten Kommandos stehen nun zur +Auswahl. Für alle diese Kommandos gilt, daß sie entweder durch zwei aufeinander +folgende Tastendrücke <ESC> und Kennzeichen oder auch durch vollständiges Eintip +pen eingegeben werden können und mit <CR> ausgelöst werden. + +Die Eingabe eines falschen Zeichens nach <ESC> oder eines falschen Kommandos +wird abgewiesen. Die Eingabe ist dann zu wiederholen. + + +Bedeutung der Kommandos: + +#on("b")# +1) Steuerkommandos #off("b")# + + #ib#ESC b#ie# #ib#begin#ie# ("taskname") Task einrichten. + #ib#ESC c#ie# #ib#continue#ie# ("taskname") Task wieder ankoppeln. + #ib#ESC q#ie# #ib#break#ie# Terminal abkoppeln. + #ib#ESC h#ie# #ib#halt#ie# Programmlauf abbrechen. + + + +#on("b")# +2) Informationskommandos#off("b")# (nur Supervisor) + + #ib#ESC ?#ie# #ib#help#ie# Information. + #ib#ESC s#ie# #ib#storage info#ie# Belegten Speicherplatz anzeigen. + #ib#ESC t#ie# #ib#task info#ie# Im System befindliche Tasks anzeigen. + +#page# +2.2. Eine Task einrichten +#free(1.0)# + + + Mit dem Kommando 'begin' wird eine neue Task eingerichtet. + + +#free(1.0)# + +Zunächst koppeln Sie Terminal und Rechner, dann legen Sie eine neue Task an. + + Terminal ankoppeln: <SV> + + <ESC> <b> + +Die Tastenkombination 'ESC b' schaltet den Einfügemodus ein und positioniert +den Cursor passend für die Eingabe des Tasknamens. + +____________________________________________________________________________ + +gib supervisor kommando : +begin ("") + +____________________________________________________________________________ + + + +Dateinamen eintippen: + +____________________________________________________________________________ + + gib supervisor kommando: + begin ("taskname") + +____________________________________________________________________________ + + +Nachdem Sie den Namen eingegeben haben, betätigen Sie die <CR> Taste. Daraufhin +meldet sich der Monitor der neuen Task und Sie können beliebige Monitor- +Kommandos (siehe Teil 3) eingeben. + +Wird eine Task in dieser geschilderten Weise neu eingerichtet, so wird sie automa +tisch (von der Task SUPERVISOR) als Sohn der Task PUBLIC angelegt. + + +Soll eine Task nicht als Sohn von PUBLIC, sondern als Sohn einer anderen Task +angelegt werden, so ist das Kommando 'begin' mit zwei Parametern zu geben. Die +neue Task wird dann als Sohn einer anderen Manager-Task angelegt (siehe Teil 3). + + +____________________________________________________________________________ + + gib supervisor kommando: + begin ("taskname","name der vatertask") + +____________________________________________________________________________ + + + +ACHTUNG: Die Task, die als Vater-Task angegeben wird, muß + eine Manager-Task sein, sonst passiert überhaupt nichts! + (s. Kap. 3.1.2.) + +#page# +Task wiederankoppeln +#free(1.0)# + + + Mit dem Kommando 'continue' wird eine existierende Task an das + Terminal angekoppelt. + + +#free(1.0)# + +Wenn Sie die Arbeit in einer Task wiederaufnehmen wollen, holen Sie die Task mit +dem Kommando 'continue' an das Terminal. Dieser Vorgang ähnelt dem Einrichten +einer neuen Task: + + Terminal ankoppeln: <SV> + + <ESC> <c> + +Die Tastenkombination 'ESC c' schaltet den den Einfügemodus ein und positioniert +den Cursor passend für die Eingabe des Tasknamens. + + +____________________________________________________________________________ + + gib supervisor kommando: + continue ("taskname") + +____________________________________________________________________________ + + +Nach dieser Eingabe finden Sie die wiederaufgenommene Task so vor, wie Sie sie +verlassen haben. + +#page# +Terminal abkoppeln +#free(1.0)# + + + Mit dem Kommando 'break' wird das Terminal vom Rechner abgekoppelt. + + +#free(1.0)# + +Wenn Sie beispielsweise nach einem Informationskommando (siehe Teil 2.3.ff) das +Terminal sofort vom Rechner abkoppeln möchten, geben Sie das 'break'-Kommando. +Nach 'storage info' geht es jedoch nur mit <SV> weiter. + +____________________________________________________________________________ + + gib supervisor kommando: + break + +____________________________________________________________________________ + + +Nach dieser Eingabe ist das Terminal abgekoppelt. Jede neue Aktivität ist wiederum +mit <SV> einzuleiten. +#page# +Laufendes Programm stoppen +#free(1.0)# + + + Mit dem Kommando 'halt' wird ein Programm gestoppt, das am betreffenden Termi + nal läuft. + + +#free(1.0)# + +Dieses Kommando ist in besonderen Fehlersituationen von Wichtigkeit. Falls Sie ein +Programm abbrechen wollen, aber keine regulären Eingaben am Bildschirm mehr +möglich sind, so geben Sie zunächst <SV> ein. + +Sobald der Supervisor-Bildschirm erscheint, drücken Sie die Tasten + +#center# <ESC> <h> (oder tippen 'halt' und drücken 'CR'). + +____________________________________________________________________________ + + gib supervisor kommando: + halt + +____________________________________________________________________________ + + +Nach dieser Eingabe wird das an diesem Terminal laufende Programm unterbrochen. +Nach dem Abbruch kommen Sie wieder auf die Monitor-Ebene (s. Teil 3). +#page# +2.3. Informationskommandos +#free(1.0)# + + + Mit den Informationskommandos können Informationen zum System abgerufen + werden. + +#free(1.0)# + +Die folgenden Informationskommandos können direkt an den SUPERVISOR gegeben +werden. + + Terminal ankoppeln: <SV> + + <ESC> <s> + + +beziehungsweise + +____________________________________________________________________________ + + gib supervisor kommando : + storage info + +____________________________________________________________________________ + + +gibt Auskunft über den belegten Speicherplatz auf dem EUMEL-Hintergrundspeicher. + +Das Kommando: + + +____________________________________________________________________________ + + gib supervisor kommando : + task info + +____________________________________________________________________________ + + +gibt Auskunft über die Namen der im EUMEL-System befindlichen Tasks und die +Struktur des Taskbaums. Verzweigungen im Taskbaum sind durch Einrückungen in +den Ebenen des Taskbaums dargestellt. + + +Alle in dem Schema der Task-Organisation (siehe Teil 1) fettgedruckten Tasks sind +auch auf jedem Multi-User-Sysrtem zu finden, da sie zum Betrieb nötig sind. + +Die unterhalb von PUBLIC gelegenen Tasks werden, falls überhaupt schon vorhan +den, häufig nach ihrem 'Besitzer' oder der in ihnen erledigten Arbeit benannt sein. + +#page# +2.4. Übersicht über Supervisor-Kommandos +#free(1.0)# + + + In diesem Abschnitt werden alle Supervisor- und Task-Kommandos in der + ELAN-Notation dargestellt. + +#free(1.0)# + +Die Supervisor-Kommandos entsprechen - wie alle anderen Kommandos im +EUMEL-System - der ELAN-Syntax (Kommando-Namen werden klein geschrie +ben, Parameter in Klammern, mehrere Parameter durch Kommata getrennt, TEXT- +Parameter in Anführungsstrichen usw.). +#free(1.0)# +Die ELAN-Notation +#free(1.0)# + +Diese Notation dient der präzisen Beschreibung von Konstrukten der Programmier +sprache ELAN. Im Anschluß an die teilweise eher informelle Formulierung innerhalb +des Kapitels folgt jedem Teil eine Kurzbeschreibung der zu diesem Themenkreis +gehörigen Konstrukte. + +Eine solche Beschreibung hat z.B. die Form: + + PROC edit (TEXT CONST dateiname) + +Die klein geschriebenen Benennungen von Prozeduren, Parametern etc. sind hoffent +lich selbsterklärend, die groß geschriebenen Begriffe sind sogenannte Schlüsselworte +und haben folgende Bedeutung: + +OP Operator + Ein Operator bewirkt eine elementare Operation. Operatoren werden stets + durch Großbuchstaben oder Sonderzeichen dargestellt. + + Beispiel: + ( Addition zweier Zahlen) + + +PROC Prozedur + Programm, welches unter seinem Namen aufrufbar ist, ggf. unter Anfügung + von Parametern. <CR> beendet die Eingabe und läßt das Programm ablaufen. + + Beispiel: 'edit ("dateiname")' + + +CONST Konstante + Unveränderbarer Wert. + + +VAR Variable + Veränderbarer Wert. + + +BOOL Wahrheitswert + Typ, der nur die Werte TRUE oder FALSE annnehmen kann. + + +TEXT Text + Typ, der alle Buchstaben, Sonderzeichen, aber auch Ziffern umfaßt. Eine + TEXT CONST ist somit eine sogenannte Zeichenkette: + + "meine datei" + "$abc123(XYZ)" + "abrechnung vom 30.09.86" + + + Eine im Editor erstellte Datei besteht ausschließlich aus TEXTen. Ein Text + wird in Anführungszeichen " " eingeschlossen. + + +INT Integer + Ganze Zahl. Ein INT CONST ist also irgendeine ganze Zahl. Falls beschrie + ben ist: 'INT CONST zeilennr', so ist gemeint, daß an dieser Stelle die Zeilen + nummer der gewünschten Zeile der Datei anzugeben ist, also '25' oder '999'. + + +REAL Real + Reelle Zahl. Eine REAL CONST bezeichnet eine Zahl mit Dezimalpunkt. + + PROC sin (REAL CONST x) => sin (0.5) + + + +TASK Task + Eine TASK CONST bezeichnet eine existierende Task durch einen internen + Task-Bezeichner. + + + +THESAURUS + Ein THESAURUS ist eine Liste von Namen, z.B. eine Liste von Dateinamen. + + + +#page# +Folgende Supervisor-Kommandos stehen zur Verfügung: + + +#sy("begin + PROC begin (TEXT CONST task name) + Richtet eine neue Task als Sohn von PUBLIC ein. + + PROC begin (TEXT CONST task name, father task name) + Richtet eine neue Task als Sohn der 'fathertaskname'-Task ein. + + +break + PROC break + Das Terminal wird vom Rechner abgekoppelt. + + +continue + PROC continue (TEXT CONST task name) + Eine existierende Task wird an das Terminal des Benutzers angekoppelt. + +halt + PROC halt + Das laufende Programm der dem Terminal aktuell zugeordneten Task wird + abgebrochen. Natürlich wird die Task nicht gelöscht. + + Genauer: + Es wird der Fehler 'halt from terminal' induziert. Normalerweise wird das + Programm dadurch wie durch jeden anderen Fehler abgebrochen. Genaueres + findet man im Systemhandbuch unter Fehlerbehandlung. + +storage info + PROC storage info + Informationsprozedur über den Hintergrund-Speicher. + +task info + PROC task info + Informiert über alle Tasknamen im System unter gleichzeitiger Angabe der + Vater/Sohn-Beziehungen durch Einrückungen. + diff --git a/doc/user-manual/1.8.7/doc/benutzerhandbuch.3 b/doc/user-manual/1.8.7/doc/benutzerhandbuch.3 new file mode 100644 index 0000000..eb1c762 --- /dev/null +++ b/doc/user-manual/1.8.7/doc/benutzerhandbuch.3 @@ -0,0 +1,2019 @@ +#start(5.0,1.5)##pagenr("%",1)##setcount(1)##block##pageblock##count per page# +#headeven# +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# + EUMEL-Benutzerhandbuch +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#headodd# +#lpos(0.0)##cpos(5.5)##rpos(11.0)##fillchar(" ")# +#table# + Teil 3: Der Monitor +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#bottomeven# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +3 - % GMD +#tableend##clearpos# +#end# +#bottomodd# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +GMD 3 - % +#tableend##clearpos# +#end# + +TEIL 3: Der Monitor +#free(1.0)# +#ib(9)#3.1. Der Monitor#ie(9)# +#free(1.0)# + + + Der Monitor nimmt die Kommandos des Benutzers entgegen, die dieser innerhalb + seiner Task gibt. In diesem Kapitel sind die gebräuchlichen Kommandos zur Text + verarbeitung beschrieben. + + +#free(1.0)# + +Der #ib#Monitor#ie# ist der Empfänger der Kommandos in einer EUMEL-Task. Jede Task +und somit jeder aktive Benutzer eines EUMEL-Systems verfügt über einen eigenen +Monitor. Halten Sie sich an dieser Stelle vor Augen: +#on("i")##on("b")# + + +Der SUPERVISOR ist die Task, die die Aufsicht über +alle weiteren Tasks des EUMEL-Systems hat. + +Der Monitor ist der Befehlsempfänger in Ihrer Task. +Jede Task hat einen Monitor. + +#goalpage("Mon-kdo")# +Der Monitor in Ihrer Task macht sich direkt bemerkbar durch die Zeile: + +____________________________________________________________________________ + +#ib#gib kommando#ie# : +____________________________________________________________________________ + + +Die Kommandos der Monitor-Ebene, die Sie an dieser Stelle eingeben können, +lassen sich in Gruppen ordnen: +#on("b")# + + +Informationskommandos #off("b")# + + #ib#storage info#ie# Belegten Speicherplatz anzeigen. + #ib#task info#ie# Im System befindliche Tasks anzeigen. + #ib#task status#ie# Zustand der Task anzeigen. + + +#on("b")# +Kommandos zur Tasksteuerung #off("b")# + + #ib#break#ie# Task abkoppeln. + #ib#end#ie# Task löschen. + #ib#global manager#ie# Task zum Manager machen, d.h. + Sohn-Tasks können eingerichtet + werden. + + +#on("b")# +Kommandos zur Dateibearbeitung #off("b")# + + #ib#copy#ie# ("dateiname","kopie") Datei kopieren. + #ib#edit#ie# ("dateiname") Editor aufrufen. + #ib#forget#ie# ("dateiname") Datei löschen. + #ib#list#ie# Dateien auflisten. + #ib#rename#ie# ("dateiname","neu") Datei umbenennen. + +#on("b")# +Transport von Dateien#off("b")# + + #ib#fetch#ie# ("dateiname") Datei von Vater-Task holen. + #ib#erase#ie# ("dateiname") Datei in Vater-Task löschen. + #ib#save#ie# ("dateiname") Datei zu Vater-Task senden. + + +#on("b")# +Archiv-Kommandos#off("b")# + + #ib#archive#ie# ("name") Archivlaufwerk reservieren. + #ib#fetch#ie# ("dateiname",archive) Datei von Archiv holen. + #ib#save#ie# ("dateiname",archive) Datei auf Archiv schreiben. + #ib#list (archive)#ie# Inhalt des Archivs listen. + #ib#check#ie# ("dateiname",archive) Datei auf Lesbarkeit prüfen. + #ib#clear#ie# (archive) Archiv löschen/umbenennen. + #ib#format (archive)#ie# Archivdiskette für Benutzung + vorbereiten. + +#on("b")# +Textverarbeitung #off("b")# + + #ib#list fonts#ie# Nennt die eingestellten + Schrifttypen. + #ib#fonttable#ie# Stellt die gewünschte Fonttabelle ein. + #ib#lineform#ie# ("dateiname") Zeilenweise formatieren. + #ib#autoform#ie# ("dateiname") Automatische Zeilenformatierung. + #ib#pageform#ie# ("dateiname") Seitenweise formatieren. + #ib#autopageform#ie# ("dateiname") Automatische Seitenformatierung. + #ib#index#ie# ("dateiname.p") Stichwortverzeichnis erzeugen. + #ib#outline#ie# ("dateiname") Übersicht bzw. Kurzfassung eines + Textes erstellen. + #ib#print#ie# ("dateiname") Datei drucken. + + + +#on("b")# +Passwortschutz #off("b")# + + #ib#task password#ie# ("geheim") Passwort für existierende Task festlegen. + #ib#begin password#ie# ("geheim") Passwort für neue Task festlegen. + #ib#family password#ie# ("geheim") Passwort für mehrere Tasks + festlegen. + #ib#enter password#ie# ("geheim") Passwort für Datei festlegen. + +#page# +3.1.1. Informationskommandos +#free(1.0)# + + + Mit den Informationskommandos können Informationen zur eigenen Task bzw. zum + gesamten System abgerufen werden. + +#free(0.5)# + +Bereits von Teil 2 bekannt sind die Informationskommandos 'ESC s' und 'ESC t'. Auf +der Monitor-Ebene ist die abkürzende Schreibweise nicht voreingestellt. + +____________________________________________________________________________ + +gib kommando : +storage info + +____________________________________________________________________________ + + +gibt Auskunft über den belegten Speicherplatz auf dem EUMEL-Hintergrundspeicher. + +____________________________________________________________________________ + +gib kommando : +task info + +____________________________________________________________________________ + + +gibt Auskunft über die Namen der im EUMEL-System befindlichen Tasks und die +Struktur des Taskbaums. +#page# +Auf Monitor-Ebene kann durch zusätzliche Angabe einer Zahl zwischen 1 und 3 +Zusatzinformation angefordert werden. + +____________________________________________________________________________ + +gib kommando : +task info (2) + +____________________________________________________________________________ + +liefert: + +____________________________________________________________________________ +26.11.86 10:10 CPU PRIO CHAN STATUS +SUPERVISOR........................... 0001:08:50 0 - wait + -................................ 0000:00:08 0 2 i/o + -................................ 0000:01:45 0 - wait + SYSUR............................ 0000:01:48 0 - wait + configurator................. 0000:00:43 0 - wait + OPERATOR..................... 0000:00:03 0 - i/o + shutup dialog............ 0000:03:08 0 - i/o + ARCHIVE...................... 0000:03:03 0 31 wait +UR................................... 0000:00:43 0 - wait + PUBLIC........................... 0000:01:26 0 - i/o + agfa......................... 0000:00:11 0 - i/o + werner....................... 0000:06:00 0 - -busy- + + +____________________________________________________________________________ + + + + +'task info (1)' entspricht dabei dem Kommando ohne Parameterangabe, '(2)' liefert +zusätzlich die verbrauchte CPU-Zeit (=reine Rechenzeit), die Priorität, den Kanal +(siehe S.#topage("Kanal")#) und den Taskstatus für jede Task des Systems. '(3)' liefert neben diesen +Angaben auch noch den belegten Speicherplatz jeder Task. Die Ausführung von task +info (3) ist sehr zeitaufwendig! + +Um insbesondere den belegten Speicherplatz der eigenen Task anzusehen, aber auch +die übrigen der oben erwähnten Angaben, benutzt man das Kommando: + +____________________________________________________________________________ + + gib kommando : + task status + +24.12.86 18:30 TASK: wenni + +Speicher: 1000K +CPU-Zeit: 0000.01:11 +Zustand : -busy-, (Prio 1), Kanal 1 + + gib kommando : + +____________________________________________________________________________ +#page# +3.2. Tasksteuerung +#free(1.0)# +Task abkoppeln +#free(1.0)# + + + Mit dem Kommando 'break' wird eine Task vom Terminal abgekoppelt. + + +#free(1.0)# + +Durch die Eingabe des Kommandos 'break' auf Monitor-Ebene wird die Task vom +Terminal abgekoppelt. Dieses Kommando bewirkt ansonsten keine Veränderungen. + +____________________________________________________________________________ + +gib kommando : +break + +____________________________________________________________________________ + + + +Statt 'break' einzutippen, können Sie auch die Tastenkombination + +#center#<ESC> <q> + +benutzen. + +#page# + +Eine Manager-Task erzeugen +#free(1.0)# + + + Eine Task kann zum #ib#Manager#ie#, d.h. zum Kommunikationspartner anderer Tasks, + erklärt werden. Insbesondere zwischen Manager-Tasks und anderen, die + zueinander in Vater-Sohn-Beziehung stehen, ist ein einfacher Dateitransfer + möglich (siehe S.#topage("Dateitrans")#). + +#free(1.0)# + +Normalerweise werden Benutzertasks als Sohn der Task PUBLIC eingerichtet. Es +kann jedoch wünschenswert sein, selbst eine Task-Hierarchie aufzubauen und eine +vorhandene Task zum Vater einer oder mehrerer in Zukunft einzurichtender Tasks zu +machen, um somit auch eine Dateihierarchie mit den benötigten Operationen zu +erhalten. Dazu wird diese Task zum 'Manager' erklärt:#goalpage("globalmanager")# + +____________________________________________________________________________ + +gib kommando: +global manager + +____________________________________________________________________________ + + +Durch das '#ib#global manager#ie#'-Kommando wird implizit ein 'break'-Kommando gege +ben, so daß Sie nach Eingabe dieses Kommandos wieder ein Supervisor-Kommando +geben können. Wenn Sie nun zu irgendeinem Zeitpunkt diese (zunächst potentielle) +Vater-Task wieder ankoppeln ('continue'-Kommando), meldet sich die Task nicht +wie gewohnt mit 'gib kommando :', sondern mit: + +____________________________________________________________________________ + +maintenance : + +____________________________________________________________________________ + + +um anzudeuten, daß es sich um eine Manager-Task handelt. + +Um eine Sohn-Task unterhalb einer Manager-Task einzurichten, wird zur Erzeu +gung dieser neuen Task nicht nur der gewünschte Name, sondern auch der Name der +Vater-Task angegeben.#u#1)#e# +#foot# +#u#1)#e# Falls keine Vater-Task angegeben wird, so ist die neue Task Sohn der +Manager-Task 'PUBLIC'. +#end# + +____________________________________________________________________________ + + Terminal 2 + + + EUMEL Version 1.8/M + + + gib supervisor kommando: + begin("sohntask","vatertask") + + + + ESC ? --> help + ESC b --> begin("") ESC h --> halt + ESC c --> continue("") ESC s --> storage info + ESC q --> break ESC t --> task info + + +____________________________________________________________________________ + + + + +In dieser Sohn-Task können dann mit einfachen Kommandos Dateien von der +Vater-Task geholt und zur Vater-Task geschickt werden. + +Soll eine Task für alle anderen Tasks, nicht nur für Sohn-Tasks, des Gesamtsystems +als Kommunikationspartner erreichbar sein, so muß diese Task als freier Manager +deklariert werden: + +____________________________________________________________________________ + +gib kommando: +#ib#free global manager#ie# + +____________________________________________________________________________ + + +Auf eine solche Task kann von #on("u")#jeder#off("u")# anderen Task aus zugegriffen werden, ansonsten +gilt das für gewöhnliche Manager-Tasks gesagte. +#page# +Task löschen +#free(1.0)# + + + Eine Task kann mit dem '#ib#end#ie#' Kommando gelöscht werden (und mit ihr alle Daten). + + #free(0.5)# +Normale Benutzertasks werden meistens zweck- oder themengebunden eingerichtet. +Sind die Aufgaben im Zusammenhang mit einer solchen Task erledigt, so sollte die +Task gelöscht werden, nachdem alle Daten von Bedeutung auf Diskette gesichert +wurden. + +____________________________________________________________________________ + +gib kommando : +end + +____________________________________________________________________________ + +Wie bei allen Löschungen im EUMEL-System folgt eine Kontrollfrage durch den +Monitor: + +____________________________________________________________________________ + +gib kommando : +end +task "taskname" löschen (j/n) ? + + +____________________________________________________________________________ + + +Nur bei der positiven Antwort wird gelöscht, alle Dateien sind unwiderruflich verlo +ren. Als positive Antwort auf derartige Abfragen wirken: + +#center#<j> <J> <y> <Y> + +<n> bzw. <N> unterdrücken die angebotene Aktion, andere Eingaben werden abgewie +sen. + +#on("b")# +ACHTUNG: Wird eine Manager-Task gelöscht, so werden alle Sohn- Enkel- etc. + Tasks ohne zusätzliche Nachfrage gelöscht, falls die Sicherheitsabfrage + mit 'j' beantwortet wurde. #off("b")# +#page# +3.3. Dateibearbeitung +#free(1.0)# +Datei einrichten +#free(1.0)# + + + Mit dem Editoraufruf 'edit' wird eine neue Datei eingerichtet, bzw. eine existierende + Datei zur Bearbeitung am Bildschirm gezeigt. + + + +#free(0.5)# + +Eine Datei enthält Texte, die logisch zusammengehören und sie wird über ihren +Namen eindeutig gekennzeichnet. + +Das EUMEL-System speichert einmal geschriebene Texte, bis sie vom Benutzer +gelöscht werden. In der Regel wird nicht nur ein (langer) Text oder ein Programm +text geschrieben, sondern mehrere und unterschiedliche. Um diese auseinanderhalten +zu können, versehen wir sie jeweils mit einem Namen, der frei gewählt werden kann. +Beispiele für Namen: + + + "Brief vom 1.12.86" + "1. Kapitel meines Buches" + + +Eine Sammlung von Zeichen (also im Normalfall unsere geschriebenen Texte), die mit +einem Namen versehen worden ist, nennt man eine #ib##on("b")#Datei#ie##off("b")#. Der Editor erstellt also eine +Datei, wenn wir einen Text schreiben. Eine Datei kann bis zu 4 000 Zeilen fassen, +wobei jede bis zu 32 000 Zeichen lang sein darf. + + +Einrichten der ersten #ib#Datei#ie# in Ihrer Task: + +Der erste Schritt sollte darin bestehen, daß Sie sich einen vernünftigen Dateinamen +ausdenken. Das EUMEL-System legt Ihnen praktisch keine Beschränkungen über +Länge oder Form des Dateinamens auf, deshalb sollten Sie sich angewöhnen, Ihre +Dateien so zu benennen, daß Sie anhand des Namens auch nach einer Woche oder +länger noch erahnen können, was diese Datei enthält. + +Ein guter Name für die erste Datei wäre zum Beispiel: "meine erste Datei" oder +"werners test vom 1.12.86". Im weiteren Text steht nur "dateiname" o. ä.. Setzen Sie +dafür den von Ihnen gewählten Namen ein. + +____________________________________________________________________________ + +gib kommando: +edit ("dateiname") + +____________________________________________________________________________ + +____________________________________________________________________________ + +gib kommando: +edit ("dateiname") + +"dateiname" neu einrichten (j/n)? + +____________________________________________________________________________ + +Drücken Sie 'j', so wird eine neue Datei unter dem von Ihnen eingegebenen Namen +eingerichtet. Die Datei ist zunächst leer: + +____________________________________________________________________________ + ................... dateiname .................... Zeile 1 + +____________________________________________________________________________ + + + +Welche Möglichkeiten Sie bei der Bedienung des Editors haben, können Sie in Teil 4 +nachschlagen. Schreiben Sie an dieser Stelle nur einige Worte in die Datei, anhand +derer der Dateiinhalt wiederzuerkennen ist. Sie können die Tastatur genauso benutzen +wie die einer Schreibmaschine. + +____________________________________________________________________________ + ................... dateiname .................... Zeile 1 +Inhalt der ersten Datei. 1234567890 + +____________________________________________________________________________ + + +Die Datei sollte an dieser Stelle wieder geschlossen werden. + +Drücken Sie dazu <ESC> <q>. + +Dabei ist gleichgültig, wo der Cursor steht. + +Wiederholen Sie das Neuanlegen einer Datei mit einer zweiten Datei "anderer datein +ame". Bitte schreiben Sie wiederum einige Zeichen in die Datei. + +____________________________________________________________________________ + +gib kommando : +edit ("anderer dateiname") + +____________________________________________________________________________ + + +Vorschlag zur Eingabe: + +____________________________________________________________________________ + + .............. anderer dateiname ................. Zeile 1 +Halten Sie irgendeine Taste gedrücktttttttttttttttt + +____________________________________________________________________________ + + +Beenden Sie die Arbeit ebenfalls mit <ESC> <q> . + + +#page# +Dateinamen auflisten +#free(1.0)# + + + Mit dem Kommando 'list' werden die Dateinamen der Dateien in der Task aus + gegeben. + + +#free(1.0)# + +Vor jedem Dateinamen wird das Datum der letzten Bearbeitung der Datei angezeigt. + +____________________________________________________________________________ + +gib kommando: +list + +____________________________________________________________________________ + +bewirkt: +____________________________________________________________________________ + + ..................... list ....................... Zeile 1 + +01.08.86 "dateiname" +01.08.86 "anderer dateiname" + +____________________________________________________________________________ + + + +Auch bei dieser Auflistung der Dateinamen handelt es sich um eine EUMEL-Datei + (allerdings um eine schreibgeschützte), die Ausgabe wird also wie gewohnt durch + das Kommando <ESC> <q> beendet. +#page# +Datei duplizieren +#free(1.0)# + + + Mit dem Kommando 'copy' wird eine existierende Datei dupliziert. + + +#free(1.0)# + +Eine existierende Datei kann dupliziert werden durch das Kommando : + +____________________________________________________________________________ + +gib kommando: +copy ("dateiname","kopiename") + +____________________________________________________________________________ + + +Durch dieses Kommando wird eine Kopie der Datei "dateiname" unter dem Namen +"kopiename" angelegt, der Inhalt der beiden Dateien ist zunächst identisch. Kontrol +lieren Sie die Richtigkeit dieser Behauptung, indem Sie nachsehen, ob der Inhalt der +kopierten Datei gleich dem Inhalt der Ursprungsdateiname ist: + +____________________________________________________________________________ + +gib kommando: +edit ("kopiename") + +____________________________________________________________________________ +#page# +Dateinamen ändern +#free(1.0)# + + + Mit dem Kommando 'rename' wird der Name einer Datei geändert. + + +#free(1.0)# + +Sollte Ihnen der Name einer Datei nicht gefallen, so besteht die Möglichkeit, den +Namen zu ändern: + +____________________________________________________________________________ + +gib kommando: +rename ("dateiname","neuer dateiname") + +____________________________________________________________________________ + + +#page# +Datei löschen +#free(1.0)# + + + Mit dem Kommando 'forget' wird eine Datei gelöscht. + + +#free(1.0)# + +Das Löschen einer Datei wird durch das Kommando: + +____________________________________________________________________________ + +gib kommando: +forget ("neuer dateiname") + +____________________________________________________________________________ + +eingeleitet. Aus Gründen der Sicherheit erfolgt vor der Ausführung des Kommandos +jedoch die Abfrage: + +____________________________________________________________________________ + +gib kommando: +forget ("neuer dateiname") + +"dateiname" löschen ? (j/n) + +____________________________________________________________________________ + +Als positive Antwort auf derartige Abfragen wirken: <j> <J> <y> <Y> + +<n> bzw. <N> unterdrücken die angebotene Aktion, andere Eingaben werden abgewie +sen. + +#page# +Dateien verschicken +#free(1.0)# +#goalpage("Dateitrans")# + + + Dateien können zur Vater-Task geschickt und von der Vater-Task geholt werden. + +#free(1.0)# + +Die Vereinbarung, daß Dateien in einer Task lokal sind, d.h. daß nur in dieser Task +Zugriff auf die Daten möglich ist, ist häufig zu einschränkend. So kann es zweck +mäßig sein, von mehreren Arbeitsplätzen (= Tasks) aus die wesentlichen Ergebnisse +an einer zentralen Stelle zu sammeln oder Ergebnisse aus Tasks, die nur kurzzeitig +für eine spezielle Aufgabe eingerichtet wurden, länger aufzubewahren. + +Zu diesem Zweck wird eine Benutzertask zum Manager erklärt (siehe S.#topage("globalmanager")#) und es +werden Söhne dieser Task eingerichtet. +#page# +Datei zur Vater-Task schicken +#free(1.0)# + + + Mit dem Kommando 'save' wird die Kopie einer Datei zur Vater-Task geschickt. + + +#free(1.0)# + +____________________________________________________________________________ + +gib kommando: +save ("dateiname") + +____________________________________________________________________________ + +Wird eine Datei an die Vater-Task gesendet, wird eine Kopie der Ursprungsdateina +me unter dem Namen 'dateiname' in der Vater-Task eingerichtet. Danach sind diese +beiden, zunächst gleichen Dateien unabhängig voneinander. Änderungen, welcher Art +auch immer, haben keinen Einfluß auf die namensgleiche Kopie in der anderen Task. + +Falls in der Vater-Task bereits eine Datei mit dem Namen 'dateiname' existiert, sei +es durch Zufall oder weil bereits einmal eine 'save'-Operation durchgeführt worden +ist, erfolgt eine Abfrage: + +____________________________________________________________________________ + +gib kommando: +save ("dateiname") + +"dateiname" überschreiben ? (j/n) + +____________________________________________________________________________ + +Nur wenn die positive Eingabe 'j' erfolgt, wird die Datei in der Vater-Task durch die +eigene Datei überschrieben. +#page# +Datei von der Vater-Task holen +#free(1.0)# + + + Mit dem Kommando 'fetch' wird die Kopie einer Datei von der Vater-Task geholt. + + +#free(1.0)# + +Entsprechend dem Versenden einer Dateikopie können Sie eine Kopie von der Vater +Task holen und ggf., natürlich nach Abfrage, Ihre Datei dieses Namens überschrei +ben. + +____________________________________________________________________________ + +gib kommando: +fetch ("dateiname") + +____________________________________________________________________________ + +#page# +Datei in der Vater-Task löschen +#free(1.0)# + + + Mit dem Kommando 'erase' wird eine Datei in der Vater-Task gelöscht. + + +#free(1.0)# + +Soll eine Datei in der Vater-Task gelöscht werden, so kann dieses, dem 'forget'- +Kommando analoge Kommando, in der Sohn-Task gegeben werden: + +____________________________________________________________________________ + +gib kommando: +erase ("dateiname") + +____________________________________________________________________________ + +Falls die Datei in der Vater-Task existiert, wird sie nach Kontrollfrage gelöscht. + +____________________________________________________________________________ + +gib kommando: +erase ("dateiname") +"dateiname" loeschen (j/n) j + +gib kommando : + + +____________________________________________________________________________ + + + Anm: Die Task 'PUBLIC' ist grundsätzlich eine Manager-Task. Da Benut + zer-Tasks als Sohn von '#ib#PUBLIC#ie#' eingerichtet werden, falls Sie nicht als + Sohn einer besonderen Manager-Task eingerichtet wurden, beziehen sich + 'fetch'-, 'save'- und 'erase'-Kommandos auf 'PUBLIC'. +#page# +3.4. Das Archiv +#free(1.0)# + + + Das Archiv dient der Speicherung von Dateien auf Disketten (Sicherung). + +#free(1.0)# + +Das #ib#Archiv#ie# übernimmt im EUMEL-System die Verwaltung der langfristigen Daten +haltung. Das Archiv sollen Sie benutzen, um: + +- Sicherungskopien wichtiger Dateien außerhalb des Rechners zu besitzen; + +- nicht benötigte Dateien außerhalb einer Task zu halten (Speicherplatzersparnis!); + +- Dateien auf andere Rechner zu übertragen. + +Das Archiv wird im EUMEL-System durch die Task 'ARCHIVE', die das Disketten +laufwerk des Rechners verwaltet, realisiert. Die Steuerung durch eine Task hat für Sie +die erfreuliche Folge, daß die Handhabung des Archivs sich kaum von den schon +bekannten Dateioperationen unterscheidet. In den Kommandos wird zusätzlich ange +geben, daß das Archiv angesprochen werden soll. + +#page# +Archiv-Kommandos +#free(1.0)# + + + Der Arbeitsablauf bei Benutzung des Archivs besteht immer aus der Reservierung, + dem Lese- oder Schreibzugriff und der Freigabe des Archivs nach Ende der + Arbeit. Jede Arbeit mit dem Archiv beginnt mit dem Reservierungskommando. + + +#free(1.0)# + +Als ersten Schritt der Archivbenutzung müssen Sie das Archiv reservieren, das heißt +der Verwaltung Ihres EUMEL-Systems mitteilen, daß Sie die Task 'ARCHIVE', die +der Steuerung des Diskettenlaufwerks dient, für Ihre Task arbeiten lassen. Solange für +Ihre Task das Archiv reserviert ist, kann keine andere Task das Archivlaufwerk benut +zen. + +Für die Reservierung müssen Sie bei Benutzung einer schon vorbereiteten oder sogar +beschriebenen Diskette den Namen dieser Archivdiskette kennen (er sollte auf dem +Diskettenaufkleber stehen) oder vor Benutzung einer neuen Diskette einen Namen +festlegen (und auf dem Aufkleber vermerken). Wie gewohnt gibt es keine Vorschrif +ten für die Namensgebung. + +Erst nachdem Sie das Reservierungskommando gegeben haben: + +____________________________________________________________________________ + +gib kommando: +archive ("diskettenname") + +____________________________________________________________________________ + + +sollten Sie die Diskette in das Laufwerk einschieben, um zu verhindern, daß ein +anderer Benutzer, der das Archiv bereits für sich reserviert hat, auf Ihrer zufällig +gleichnamigen Datei arbeitet. + + +Eine Datei wird mit dem Kommando: + +____________________________________________________________________________ + +save ("dateiname",archive) + + +____________________________________________________________________________ + + +auf eine Diskette geschrieben und mit dem Kommando: + +____________________________________________________________________________ + +fetch ("dateiname",archive) + +____________________________________________________________________________ + + +von einer Diskette geholt. + +Das Inhaltsverzeichnis einer Diskette erhalten Sie durch: + +____________________________________________________________________________ + +list (archive) + +____________________________________________________________________________ + +#page# +Benutzung einer neuen Archivdiskette +#free(1.0)# + + + Eine neue Diskette muß für die Benutzung vorbereitet (formatiert) werden. + + + +#free(1.0)# +Vor der erstmaligen Benutzung einer Archivdiskette muß diese formatiert, d.h. in +Spuren und Sektoren für die Positionierung des Schreib-/Lesekopfes des Disketten +laufwerks eingeteilt werden, um überhaupt ein Beschreiben der Diskette zu ermög +lichen. Die Einteilung ist geräteabhängig, häufige Formate sind: + + 40 Spuren zu je 9 Sektoren (360 K) + 80 Spuren zu je 9 Sektoren (720 K). + +Die #on("b")#Erst#off("b")#benutzung einer #ib#Archivdiskette#ie# erfordert nach der Reservierung des Archivs +das Kommando: + +____________________________________________________________________________ + +gib kommando: +format (archive) + +____________________________________________________________________________ + + +Erst nach einer Kontrollabfrage: + +____________________________________________________________________________ + +gib kommando: +format (archive) + +Archiv "diskettenname" formatieren ? (j/n) + +____________________________________________________________________________ + +wird tatsächlich formatiert und die Diskette steht mit dem Namen "diskettenname" für +Archivoperationen zur Verfügung. + +#on("b")# +ACHTUNG: Wird eine bereits beschriebene Diskette noch einmal formatiert, so sind + alle Daten, die auf der Diskette waren, verloren.#off("b")# + + +Bei einigen Rechnern ist es möglich, die Formatierung zu variieren. Falls beim Forma +tieren auf einem solchen Rechner ein anderes als das Standardformat erzeugt werden +soll, so ist die Codierung des gewünschten Formats mitanzugeben. + + +Beispiel: Für ein Gerät mit 5μ Zoll Disketten wäre z.B. einstellbar: + code 0 : Standardformat + code 1 : 40 Spuren + code 2 : 80 Spuren + code 3 : High Density + + 'format (archive)' erzeugt ebenso wie 'format (0,archive)' eine standard + formatierte Diskette, 'format (3,archive)' erzeugt eine High Density + Formatierung. +#page# +Diskette löschen / umbenennen +#free(1.0)# + + + Bereits benutzte Disketten können wieder gelöscht und auch umbenannt werden. + + +#free(1.0)# + +Falls Sie den Inhalt einer beschriebenen Archivdiskette löschen oder den Namen einer +Diskette ändern wollen, müssen Sie das Archiv unter dem gewünschten Namen reser +vieren: Falls Sie den Inhalt löschen möchten, tun Sie das unter dem bisherigen und +bestehenden Namen. Falls Sie die Diskette umbenennen wollen, reservieren Sie das +Archiv unter dem neuen gewünschten Namen. Beachten Sie, daß durch das Umbe +nennen eines Archivs alle darauf befindlichen Dateien gelöscht werden. Anschließend +geben Sie das Kommando: + +____________________________________________________________________________ + +gib kommando: +#ib#clear#ie# (archive) + +____________________________________________________________________________ + +Durch die Ausführung des Kommandos erhält die eingelegte Diskette den in der +Reservierung angegebenen Namen. Das Inhaltsverzeichnis, das sich auf der Diskette +befindet, wird gelöscht. Damit sind die Daten, die sich eventuell auf dieser Diskette +befanden, nicht mehr auffindbar. Die Diskette entspricht einer neu formatierten Disket +te#u#1)#e#. #foot# +#u#1)#e# Das Kommando 'format' enthält implizit 'clear'. +#end# +Eine Neuformatierung ist demnach bei Wiederverwendung der Diskette nicht notwen +dig. + +#page# +Inhaltsverzeichnis der Diskette +#free(1.0)# + + + Mit 'list (archive)' werden die Dateien auf der Diskette angezeigt. + + +#free(1.0)# + +Eine formatierte Diskette kann nach der Archivanmeldung gelesen oder beschrieben +werden. Um zu sehen, welche Dateien auf der Diskette zu holen (= lesen) sind bzw. +wieviel Platz zum Beschreiben vorhanden ist, ist es zweckmäßig, zunächst das In +haltsverzeichnis der Diskette zu betrachten. + +____________________________________________________________________________ + +gib kommando: +list (archive) + +____________________________________________________________________________ + +Beispiel: + +____________________________________________________________________________ + + ............diskettenname (100 K belegt von 720 K).............. + +01.05.86 25 K "rechnungen april" +01.06.86 23 K "rechnungen mai" +01.07.86 20 K "rechnungen juni" +01.08.86 32 K "rechnungen juli" + +____________________________________________________________________________ +#page# +Lesen und Schreiben auf Diskette +#free(1.0)# + + + Lesen und Schreiben auf der Diskette entspricht den bekannten Operationen zum + Senden und Holen von Dateien. + + + +#free(1.0)# +Das Schreiben einer Datei auf Diskette entspricht dem Übersenden einer Datei an die +Vater-Task. Einziger Unterschied ist, daß Sie das Ziel explizit angeben müssen: + +____________________________________________________________________________ + +gib kommando: +#ib#save#ie# ("dateiname",archive) + +____________________________________________________________________________ + +Entsprechend funktioniert auch das Lesen einer Datei von der Diskette: + +____________________________________________________________________________ + +gib kommando: +fetch ("dateiname",archive) + +____________________________________________________________________________ + +Wie auch bei der Kommunikation zwischen Sohn- und Vater-Task werden nur +Kopien der Dateien geholt bzw. geschrieben. +#page# +Wechsel der Archivdiskette +#free(1.0)# +Bei Einlegen einer anderen Archivdiskette müssen Sie erneut das Kommando + +____________________________________________________________________________ + +gib kommando: +archive ("diskettenname") + +____________________________________________________________________________ + +geben, da mit der Archivreservierung zugleich die Prüfung von Diskettenname und +-Inhaltsverzeichnis vorbereitet wird. +#page# +Beenden der Archivreservierung +#free(1.0)# + + + Nach Benutzung Archiv freigeben! + + +#free(1.0)# + +Wenn Sie alle gewünschten Arbeiten mit dem Archiv fertiggestellt haben, geben Sie +das Archiv wieder frei. + +____________________________________________________________________________ + +gib kommando: +#ib#release#ie# (archive) + +____________________________________________________________________________ + +Durch dieses Kommando kann die Task 'ARCHIVE' mit ihren Leistungen von einer +anderen Task in Anspruch genommen werden. Falls Sie dieses Kommando nicht +gegeben haben aber seit 5 Minuten keine Archivoperation ausgelöst haben, kann eine +andere Task durch die Anforderung 'archive("diskettenname")' das Archiv reservieren. +Durch diese Maßnahme wird verhindert, daß ein vergeßlicher Benutzer bei einem +System mit mehreren Benutzern das Archiv blockiert. +#page# +Fehlermeldungen des Archivs +#free(1.0)# + + + Bei Archiv-Operationen kann es zu Fehlersituationen kommen. + +#free(1.0)# + +Versucht man, eine Datei vom Archiv zu holen, kann es vorkommen, daß das Ar +chiv-System + +____________________________________________________________________________ + +#ib#Lese-Fehler (Archiv)#ie# + +____________________________________________________________________________ + +meldet und den Lese-Vorgang abbricht. Dies kann auftreten, wenn die Floppy +beschädigt oder aus anderen Gründen nicht lesbar ist (z.B. nicht justierte Disket +ten-Geräte). In einem solchen Fall vermerkt das Archiv-System intern, daß die Datei +nicht korrekt gelesen werden kann. Das sieht man z.B. bei 'list (archive)'. Dort ist der +betreffende Datei-Name mit dem Zusatz 'mit Lese-Fehler' gekennzeichnet. Um +diese Datei trotzdem zu lesen, muß man sie unter ihrem Dateinamen mit dem Zusatz +'mit Lese-Fehler' lesen. + +____________________________________________________________________________ + +gib kommando: +fetch ("dateiname mit Lese-Fehler") + +____________________________________________________________________________ + +Die Datei wird in diesem Fall trotz Lese-Fehler (Informationsverlust!) vom Archiv +gelesen. + +Um solche Fälle möglichst zu vermeiden, sieht das EUMEL-System die Möglichkeit +vor, Archive bzw. Archiv-Dateien nach Beschreiben zu prüfen. Das erfolgt mit dem +Kommando + +____________________________________________________________________________ + +gib kommando : +#ib#check#ie# ("dateiname", archive) + +____________________________________________________________________________ + + +Durch dieses Kommando werden eventuelle Lese-Fehler gemeldet. + +Weitere Fehlermeldungen des Archivs: + +* Lesen unmöglich (Archiv) + Die Archiv-Diskette ist nicht eingelegt oder die Tür des Laufwerks ist nicht ge + schlossen. +=> Diskette einlegen bzw. Tür schließen. + +* Schreiben unmöglich (Archiv) + Die Diskette ist schreibgeschützt. +=> falls wirklich gewünscht, Schreibschutz entfernen. + +* Archiv nicht angemeldet + Das Archiv wurde nicht angemeldet +=> 'archive ("name")' geben. + +* Lese-Fehler (Archiv) + Siehe Lesen unmöglich + +* Schreibfehler (Archiv) + Die Diskette kann nicht (mehr) beschrieben werden. +=> Andere Diskette verwenden. + +* Speicherengpass + Im System ist nicht mehr genügend Platz, um eine Datei vom Archiv zu laden, ggf. +=> ggf. Dateien löschen. + +* RERUN bei Archiv-Zugriff Das System wurde bei einer Archiv-Operation durch + Ausschalten bzw. Reset unterbrochen. + +* "dateiname" gibt es nicht + Die Datei "dateiname" gibt es nicht auf dem Archiv. +=> mit 'list(archive)' Archiv prüfen. + +* Archiv heißt ... + Die eingelegte Diskette hat einen anderen als den eingegebenen Archivnamen. +=> Kommando 'archive' mit korrektem Namen geben. + +* Archiv wird von Task ... benutzt + Das Archiv wurde von einem anderen Benutzer reserviert. +=> Abwarten. + +* "dateiname" kann nicht geschrieben werden (Archiv voll) + Die Datei ist zu groß für die eingelegte Diskette. +=> Andere Diskette für diese Datei nehmen. + +* Archiv inkonsistent + Die eingelegte Diskette hat nicht die Struktur einer Archiv-Diskette. +=> 'format (archive)' vergessen. + +* save/erase wegen Lese-Fehler verboten + Bei Archiven mit Lese-Fehler sind Schreiboperationen verboten, weil ein Erfolg + nicht garantiert werden kann. + + + +3.5. Kommandos für mehrere Dateien +#free(1.0)# + + + Durch Anwendung der besonderen Operatoren 'ALL' und 'SOME' können Sie + mehrere Dateien mit einem Kommando behandeln. + + +#free(1.0)# +Oft ist es sehr zweckmäßig und erleichternd, einen Befehl für eine ganze Reihe von +Dateien wirken zu lassen, wie z.B. beim Archivieren, wenn Sie etwa alle während des +Tages veränderten Dateien mit deren neuen Stand auf Diskette schreiben möchten. + +Da Tasks einen Namen haben und jede Task ein Inhaltsverzeichnis ihrer Dateien +führt, ist es möglich, Listen von Dateien zu benennen. +#page# +Interne Tasknamen +#free(1.0)# +Wenn Sie eine andere als die eigene oder die Vater-Task ansprechen wollen, ist es +notwendig, den 'internen Tasknamen' anzugeben. Diese auf den ersten Blick etwas +undurchsichtige Forderung hat folgenden Hintergrund: + +Durch die in der Einleitung vorgestellte Baumstruktur des EUMEL-Systems ist es +ohne besondere Angaben nur möglich, Kommandos zu geben, die die eigene Task +('edit'..) oder die Vater-Task ('save'..) betreffen. Beim Archivieren zum Beispiel wäre +es demzufolge erforderlich, eine Datei über den Vater vom Vater vom Vater... an den +Sohn des Sohnes... zu schicken, damit die Datei endlich in der Task 'ARCHIVE' +landet. Statt dessen verwenden Sie eine Prozedur 'archive', die den internen Task +bezeichner liefert. Damit wird die gewünschte Task intern identifiziert, ohne daß Sie +sich darum kümmern müssen. + +Wichtige Prozeduren, die interne Taskbezeichner liefern, sind: + + myself Bezeichner der eigenen Task + public Bezeichner von PUBLIC + father Bezeichner der Vater-Task#u##count##e# + archive Bezeichner von ARCHIVE + printer Bezeichner von PRINTER #foot# +#u##value##e# Falls kein besonderer Manager eingerichtet wurde, liefern 'father' und 'public' + natürlich dieselbe Task: PUBLIC. #end# +#page# +Dateiverzeichnisse +#free(1.0)# +Jede Task verfügt über ein Verzeichnis der in ihr befindlichen Dateien. Das Verzeich +nis Ihrer eigenen Task können Sie mit dem 'list'-Kommando betrachten. Das Ver +zeichnis einer anderen Task sehen Sie beispielsweise durch das Kommando 'list +(archive)'. In diesem Fall müssen Sie dem eigentlichen Kommando den internen +Taskbezeichner der gewünschten Task hinzugeben, um das Verzeichnis zu sehen. + +Um ein Verzeichnis in Verbindung mit anderen Kommandos benutzen zu können, gibt +es besondere Operatoren: + + #ib#ALL#ie# liefert das gesamte Verzeichnis + #ib#SOME#ie# bietet das Verzeichnis zur Auswahl von Einträgen an. + + +In Verbindung mit einem internen Taskbezeichner wird einer der beiden Operatoren +einem Monitor-Kommando als Parameter nachgestellt. Das Kommando wirkt dann +nacheinander auf alle im Verzeichnis enthaltenen Dateien. + + +____________________________________________________________________________ + +gib kommando: +fetch (ALL father) + +____________________________________________________________________________ + +Alle Dateien der Vater-Task werden nacheinander geholt, bei Namensgleichheit +erfolgt die bekannte Kontrollfrage, ob die gleichnamige Datei in der eigenen Task +überschrieben werden soll. + +Falls nur einige Dateien des Verzeichnisses bearbeitet werden sollen, wird der Opera +tor 'SOME' dem Taskbezeichner vorangestellt: + +____________________________________________________________________________ + +gib kommando: +fetch (SOME father) + +____________________________________________________________________________ + + +Hier wird zunächst das Dateiverzeichnis der Task angeboten. Streichen Sie alle +Dateien, die auf der Diskette sind, aber nicht in Ihre Task geholt werden sollen, aus +dem Verzeichnis, indem Sie + +- den Dateinamen mit Blanks überschreiben + + oder: + +- die Zeile mit <HOP> <RUBOUT> löschen + + oder: + +- mehrere Zeilen markieren, indem Sie zu Beginn des zu markierenden Bereichs + 'mark' betätigen und mit Hilfe der Cursor-Tasten den Beereich so weit wie benö + tigt ausdehnen. Im Anschluß daran können Sie diese Zeilen durch + + <ESC> <RUBOUT> oder + + <ESC> <p> + + löschen. + + +____________________________________________________________________________ + + .............................. .......................... #markoff# +rechnungen april +rechnungen mai +rechnungen juni +rechnungen juli + + + +____________________________________________________________________________ + + + +In obigem Beispiel werden nach dem Kommando 'ESC RUBOUT' (=Löschen der +markierten Zeilen) und dem Kommando 'ESC q' (=editieren beenden) die Dateien +'rechnungen juni' und 'rechnungen juli' vom Archiv geholt. + +Als weitere Vereinfachung gibt es die Prozedur 'all' als Abkürzung für 'ALL myself'. + +Beispiel: alle Dateien auf Archivdiskette schreiben. + +____________________________________________________________________________ + +gib kommando: +save (all,archive) + +____________________________________________________________________________ + + +Für Fortgeschrittene: + +Sie können auch aus den Verzeichnissen mehrerer Tasks ein neues Verzeichnis +bilden. Zu diesem Zweck sind folgende Mengenoperationen auf Verzeichnisse mög +lich: + + #ib#-#ie# Differenzmenge + #ib#+#ie# Vereinigungsmenge + #ib#/#ie# Schnittmenge + +Beispiel: + + fetch (ALL father - ALL myself) + +Alle Dateien der Vater-Task, die noch nicht in der eigenen Task sind, werden geholt. + +3.7. Passwortschutz +#free(1.0)# + + + Das EUMEL- System ermöglicht Passwortschutz für Dateien, einzelne Tasks und + ganze Zweige des Taskbaumes. + +#free(1.0)# + +Falls Sie sicherstellen wollen (oder müssen), daß Teile Ihres EUMEL-Systems vor +unberechtigter Benutzung geschützt sind, können Sie den Zugriff mit einem Passwort +regeln. + +Als Passwort können Sie jeden beliebigen Text nehmen. Bedenken Sie jedoch, daß +ein wirklich wirksamer Schutz nur dann gewährleistet ist, wenn Sie weder ein triviales +Passwort (etwa den eigenen Vornamen) auswählen, noch eines, das Sie selbst nicht +behalten. #u##count("1")#)#e# #foot# +#u##value("1")#)#e# Man darf Passwörter nicht vergessen! Durch Passwörter geschützte Tasks kann +niemand - außer durch die Angabe des korrekten Passworts - wieder ankoppeln. +Hat man das Passwort vergessen, kann man nur noch die Task löschen. +#end# + +ACHTUNG: Es gibt ein besonderes Passwort im EUMEL-System: "-". Dieses + Passwort verhindert, daß die Task in der es gegeben wurde (z.B. UR), an + ein Terminal geholt wird, es darf folglich nicht für normale + Manager-Tasks gegeben werden. +#page# +Eine Task mit Passwort schützen +#free(1.0)# +Das Monitor-Kommando '#ib#task password#ie#' sorgt dafür, daß eine Task fortan nur wieder +mit einem 'continue'-Kommando 'betreten' werden kann, wenn man vorher das +richtige Passwort angibt. + +____________________________________________________________________________ + +gib kommando: +task password ("rosebud") + +____________________________________________________________________________ + +Versucht nun ein Benutzer, die mit dem Passwort geschützte Task mit dem 'conti +nue'-Kommando an sein Terminal anzukoppeln, wird er zunächst nach dem #ib#Pass +wort#ie# gefragt. Nur unter Angabe des Passworts wird die Task angekoppelt. + +Bei der Beantwortung des Passworts werden statt der eingegebenen Zeichen Punkte +auf den Bildschirm geschrieben. Durch Betätigen von ESC können die getippten +Zeichen lesbar gemacht werden. + +____________________________________________________________________________ + + gib supervisor kommando: + continue("taskname") + Passwort: ....... + + +____________________________________________________________________________ + + +Der Passwortschutz gewährleistet, daß kein unberechtigter Benutzer direkt an die +Dateien und Programme der Task gelangen kann. Es gibt jedoch noch zwei Situatio +nen, die einen unberechtigten Zugang zu Dateien erlauben: + +a) Dateien in die Vater-Task schicken: + Transportiert man Dateien in die Vater-Task ('save'-Kommando) können Benut + zer auf diese Dateien zugreifen (sofern sie Zugang zu dieser Task haben). Dies + kann man verhindern, indem man ein Datei-Passwort angibt. Man beachte, daß + das Passwort für Dateien und das oben beschriebene Passwort für Tasks nichts + miteinander zu tun haben. + +b) Dateien werden in eine Sohn-Task geholt: + Ist die Task als Vater-Task eingerichtet ('global manager'-Kommando), dann ist + es möglich, von der Sohn-Task Dateien ('fetch'-Kommando) aus der Vater- + Task zu holen, die mit einem Passwort geschützt ist. Darum muß man verhindern, + daß unberechtigte Benutzer Söhne einer mit Passwort geschützten Task einrich + ten können. Das kann man mit dem Kommando + +____________________________________________________________________________ + +maintenance : +#ib#begin password#ie# ("geheim") + +____________________________________________________________________________ + + + Wird dieses Kommando gegeben, wird man bei dem Versuch, eine Sohn-Task + einzurichten, nach einem Passwort gefragt. Beachten Sie, daß das 'begin pass + word' nichts mit dem Task-Passwort und Datei-Passwort zu tun hat. + + +Man kann einen ganzen Zweig eines EUMEL-Systems durch das Kommando 'family +password' vor unberechtigtem Zugriff schützen. Das Kommando: + +____________________________________________________________________________ + +maintenance: +family password ("geheim") + +____________________________________________________________________________ + +wird dazu (wie gewohnt als Monitor-Kommando) in der Vater-Task des zu schüt +zenden Zweigs des Taskbaumes gegeben. Damit ist das Passwort aller Söhne, Enkel +usw. dieser Task auf 'geheim' gesetzt, falls sie vorher kein Passwort oder das gleiche +Passwort wie die aufrufende Task haben. Eine Task in diesem Zweig, die bereits ein +eigenes, vom 'family password' verschiedenes Passwort besitzt, behält dieses eigene +Passwort. + +Bsp: Für 'PUBLIC' wird das Kommando '#ib#family password#ie# ("geheim")' gege + ben. Dann ist das Passwort von 'PUBLIC' und aller Tasks des Benutzerzweiges + auf 'geheim' gesetzt. + + +Es ist zu beachten, daß bei der Vergabe des 'family password' nur die aktuellen +Söhne der Task berücksichtigt werden. Söhne, die nach der Vergabe des 'family +password' eingerichtet werden, sind nicht durch dieses Passwort geschützt. + +Passwort löschen + + +Um ein Passwort zu löschen, geben Sie das Passwort-Kommando mit "" als Para +meter: + +____________________________________________________________________________ + +maintenance: +begin password("") + +____________________________________________________________________________ + + +Durch diese Angabe haben Sie den Passwort einen leeren Text als Parameter gege +ben, der das bisherige Passwort 'überschreibt'. + +#page# +Dateipasswort + + +Etwas komplizierter gestaltet sich der Passwortschutz für einzelne Dateien einer +Manager-Task, da in dieser Anwendung eine Unterscheidung nach Schreib- und +Leseschutz vorgenommen wird. + +Da in dieser Anwendung nur einige Dateien der Vater-Task vor Lesen ('fetch'), +Schreiben ('save','erase') oder beidem geschützt werden sollen, benötigt diese Proze +dur Angaben über Dateinamen, Schreibpasswort und Lesepasswort. + +____________________________________________________________________________ + +maintenance : +enter password ("dateiname","schreibschutz","leseschutz") + +____________________________________________________________________________ + +Falls die Datei nicht gegen Lesen geschützt werden soll, wird (wie beim Löschen +eines Passworts) '""' als Lesepasswort angegeben. + +Falls Schreiben und/oder Lesen für eine Datei gänzlich verboten#u#1)#e# sein soll, so ist +"-" als entsprechendes Passwort anzugeben. +#foot# +1) Natürlich kann die Datei in der Manager-Task, der sie gehört, normal editiert + werden. +#end# + +Um von einer Sohn-Task eine Datei mit Passwortschutz in der Vater-Task zu lesen +oder zu schreiben muß vor dem 'fetch', 'save' oder 'erase' Kommando das 'enter +password' Kommando eineggeben werden: + +____________________________________________________________________________ + +gib kommando: +enter password ("schreibpasswort/lesepasswort") + +____________________________________________________________________________ + +In der Sohn-Task wird also nur ein Passwort eingegeben. Falls wie oben ein '/' in +diesem Passwort enthalten ist, wird der erste Teil vor dem '/' als Schreibpasswort und +der zweite Teil als Lesepasswort geprüft. Falls kein '/' in dem Passwort enthalten ist, +wird das Wort sowohl als Schreib- als auch als Lesepasswort interpretiert. + +Beispiel: +In einer Manager-Task wird eine Datei "texte" eingerichtet, die Textvorlagen enthält. +In einigen Sohn-Tasks soll diese Datei geholt (= gelesen) werden können. Die +bearbeitete, somit veränderte Datei darf aber nicht zurück in die Vater-Task ge +schrieben werden. + +In der Vater-Task: enter password ("texte","-","psw") + + +In der Sohn-Task : enter password ("psw") + + +Falls das Passwort in einer Sohn-Task fehlerhaft oder gar nicht eingegeben wurde, +erscheint die Meldung : + +____________________________________________________________________________ + + gib kommando : + fetch ("geschützte datei") +FEHLER : Passwort falsch + +____________________________________________________________________________ + + +Somit kann diese Datei nur von Benutzern, die das Lesepasswort kennen, geholt +werden. Ein Überschreiben der Datei ist nicht möglich, da das Schreibpasswort nicht +gegeben werden kann ("-" !). +#page# +3.8. Monitor-Kommandos +#free(1.0)# +ALL + THESAURUS OP ALL (TASK CONST task) + Liefert einen Thesaurus#u#1)#e#, der alle Dateinamen der angegebenen Task enthält + (auch der Benutzer-Task 'myself'). +#foot# +1) Ein Thesaurus ist eine Liste, in diesem Zusammenhang eine Liste von Dateien. + (Siehe auch 2.4. Die ELAN-Notation +#end# + fetch (ALL father) + + THESAURUS OP ALL (TEXT CONST datei) + Liefert einen Thesaurus, der die in 'datei' vorhandenen Dateinamen (jede Zeile ein + Name) enthält. + + fetch (ALL "dateiliste") + +archive + PROC archive (TEXT CONST archivname) + Anmeldung von Archiv-Operationen. 'archivname' wird zur Überprüfung für alle + folgenden Archiv-Operationen verwandt, um die unberechtigte Benutzung eines + Archivs zu verhindern. Die Anmeldung wird abgelehnt, wenn ein anderer Nutzer + das Archiv belegt hat. + + + archive ("textdiskette") + + + TASK PROC archive + Liefert den internen Task-Bezeichner für die Verwendung in Dateikommandos. + + + save ("dateiname", archive) + + + +begin password + PROC begin password (TEXT CONST geheim) + Verhindert das unberechtigte Einrichten einer Sohn-Task. + + + begin password("gmd") + + +break + PROC break + Die zum Terminal aktuell zugeordnete Task wird abgekoppelt. Sie wird damit zu + einer Hintergrund-Task. + + +brother + TASK PROC brother (TASK CONST task) + Liefert den internen Task-Bezeichner der angegebenen "Bruder"-Task. + + + list(brother) + + +check + PROC check (TEXT CONST dateiname, TASK CONST task) + Überprüft, ob die Datei 'dateiname' auf dem Archiv lesbar ist. + + + check ("meine datei", archive) + + + PROC check (THESAURUS CONST t, TASK CONST task) + Überprüft, ob die in dem Thesaurus 't' enthaltenen Dateien auf dem Archiv lesbar + sind. + + + check (ALL archive, archive) + + + +clear + PROC clear (TASK CONST task) + Löscht alle Dateien der Task 'ARCHIVE'und benennt die Diskette um, falls ein + anderer als der bisherige Diskettenname bei der Reservierung angegeben wurde. + + + archive("disk1"); clear(archive) + + +copy + PROC copy (TEXT CONST quelle, ziel) + Kopiert die Datei 'quelle' in eine neue Datei mit dem Namen 'ziel' in der + Benutzer-Task. + + + copy("datei","neue datei") + + Fehlerfälle: "ziel" existiert bereits + "quelle" gibt es nicht + zu viele Dateien + + +edit + PROC edit + a) Im Monitor: + Ruft den Editor mit den zuletzt verwandten Dateinamen auf. + b) Im Editor: + Der Dateiname wird erfragt. + Für jedes 'edit' gilt: + Wurde 'edit' zum ersten Mal aufgerufen, nimmt das Fenster den gesamten + Bildschirm ein. Bei erneutem 'edit'-Aufruf wird ein Fenster nach rechts unten ab + der aktuellen Cursor-Position eröffnet. + + PROC edit (TEXT CONST dateiname) + Ruft den Editor mit 'dateiname' auf. + + + edit("handbuch teil3") + + + + PROC edit (TEXT CONST dateiname, x, y, xbreite, yhöhe) + Wie obiger 'edit'-Aufruf, jedoch kann das Fenster, in dem 'dateiname' editierbar + ist, gesetzt werden. Die Parameter definieren ein Editor-Fenster mit der linken + oberen Ecke auf den Bildschirmkoordinaten 'x' und 'y' und einer Zeilenbreite + 'xbreite' und 'yhöhe' Zeilen. Wird der Editor mit 'edit ("dateiname")' aufgerufen, + wird implizit 'edit ("dateiname", 1, 1, 79, 24)' aufgerufen. + + + edit("notiz",5,5,44,12) + + + PROC edit (THESAURUS CONST t) + Editieren aller in dem Thesaurus 't' enthaltenen Dateien nacheinander. + + + edit (ALL father) + + + +end + PROC end + Die zum Terminal aktuell gehörende Task wird abgebrochen und gelöscht. + +enter password + PROC enter password (TEXT CONST datei, schreibpass, lesepass) + Die angegebene Datei wird mit Schreib- und Lesepassword versehen. Die + Passwörter werden in der eigenen Task nicht berücksichtigt. + Falls der Schutz total sein soll, so ist für die verbotene Operation "-" als + Passwort anzugeben. + + + enter password ("daten","sicher","heit") + + + PROC enter password (TEXT CONST password) + Gibt Schreib- und Lesepasswort für den Austausch mit Manager-Task an. Falls + zwei verschiedene Passwörter für Lesen und Schreiben vereinbart sind, so sind + sie als ein Text durch "/" getrennt einzugeben. + + + enter password ("lese/schreibpasswort") + + +erase + PROC erase (TEXT CONST datei) + Löscht eine Datei mit dem Namen 'name' in der unmittelbaren Vater-Task. + + + erase("alte datei") + + + Fehlerfälle: + "datei" gibt es nicht + Passwort falsch + + PROC erase (TEXT CONST name, TASK CONST manager) + Löscht eine Datei mit dem Namen 'name' in der Task 'manager'. + + + erase ("dateiname", father) + + + PROC erase (THESAURUS CONST thesaurus) + Löscht die im 'thesaurus' angegebenen Dateien in der Vater-Task. + + + erase (ALL myself) + (* löscht alle Dateien in der Vater-Task, die in der + Benutzer-Task vorhanden sind *) + + + PROC erase (THESAURUS CONST thesaurus, TASK CONST manager) + + + erase (all,father) + (* löscht alle Dateien in der Vater-Task, die in der + Benutzer-Task vorhanden sind *) + + + +father + TASK PROC father + Liefert den internen Task-Bezeichner der Vater-Task der Benutzer-Task. + + + list(father) + + + TASK PROC father (TASK CONST task) + Liefert den internen Task-Bezeichner von 'task'. + + + save ("dateiname", father (father)) + (* Kopiert 'dateiname' zum "Großvater" *) + + + +fetch + PROC fetch (TEXT CONST name) + Kopieren einer Datei von der Vater-Task in die Benutzer-Task + + + fetch("sicherungskopie") + + Fehlerfälle: + "datei" gibt es nicht + Passwort falsch + zu viele Dateien + + + PROC fetch (TEXT CONST name, TASK CONST manager) + Kopieren einer Datei in die Benutzer-Task von 'manager'. + + + fetch ("dateiname", /"global") + + + PROC fetch (THESAURUS CONST thesaurus) + Holt alle im 'thesaurus' enthaltenen Dateien von der Vater-Task. + + + fetch (ALL) + + + PROC fetch (THESAURUS CONST thesaurus, TASK CONST manager) + Zweck: Holt alle im 'thesaurus' enthaltenen Dateien von der 'manager'-Task. + + + fetch (ALL /"global", /"global") + + +forget + PROC forget (TEXT CONST datei) + Löschen einer Datei mit dem Namen 'name' in der Benutzer-Task. + + + forget ("alte datei") + + Fehlerfälle: + "datei" gibt es nicht + + PROC forget (THESAURUS CONST thesaurus) + Löscht die im 'thesaurus' enthaltenen Dateien in der Benutzer-Task. + + + forget (SOME myself) + + +format + PROC format (THESAURUS CONST thes) + Formatieren von Disketten und Einstellen des Namens. + + + format(archive) + + + PROC format (INT CONST art, THESAURUS CONST thes) + Formatieren von Disketten im Nichtstandardformat des benutzten Geräts + + + format(2,archive) + + +global manager + PROC global manager + Durch den Aufruf der Prozedur wird die Benutzer-Task zu einem Datei- + Manager. Danach können Söhne dieser Task eingerichtet werden. + + +list + PROC list + Listet alle Dateien der Benutzer-Task mit Namen und Datum des letzten Zugriffs + auf dem Terminal auf. + + PROC list (TASK CONST task) + Listet alle Dateien der angegebenen 'task' mit Namen und Datum der letzten + Änderung auf dem Terminal auf. + + + list (father) + + + +myself + TASK PROC myself + Liefert den internen Task-Bezeichner der Benutzer-Task. + + + save (ALL myself, father) + + + +public + TASK PROC public + Liefert den internen Task-Bezeichner von "PUBLIC". + + + fetch ("dateiname", public) + + + +rename + PROC rename (TEXT CONST altername,neuername) + Umbenennen einer Datei von 'altername' in 'neuername'. + + + rename("altes handbuch","neues handbuch") + + +save + PROC save (TEXT CONST dateiname) + Datei 'dateiname' wird an die unmittelbare Vater-Task übertragen. + + + save("neues handbuch") + + + Fehlerfälle: + "neues handbuch" gibt es nicht + zu viele Dateien + Passwort falsch + + PROC save (TEXT CONST name, TASK CONST task) + Datei mit dem Namen 'name' in Task 'task' kopieren + + + save ("dateiname", /"global") + + + Fehlerfälle: + "dateiname" gibt es nicht + zu viele Dateien + Passwort falsch + + PROC save (THESAURUS CONST thesaurus) + Kopiert die Dateien, die in 'thesaurus' enthalten sind, in die Vater-Task. + + + save (SOME myself) + + + PROC save (THESAURUS CONST thesaurus, TASK CONST manager) + Kopiert die Dateien, die in 'thesaurus' enthalten sind, in Task 'manager'. + + + save(SOME myself, /"global") + + +SOME + THESAURUS OP SOME (THESAURUS CONST thesaurus) + Bietet den angegebenen 'thesaurus' zum Editieren an. Dabei können nicht + erwünschte Namen gestrichen werden. + + THESAURUS OP SOME (TASK CONST task) + Bietet einen THESAURUS von 'task' zum Editieren an. + + THESAURUS OP SOME (TEXT CONST dateiname) + Bietet einen 'thesaurus', der aus 'dateiname' gebildet wird, zum Editieren an. + + +task + TASK PROC task (TEXT CONST task name) + Liefert den internen Task-Bezeichner von 'task name'. + + + save ("dateiname", task ("PUBLIC")) + = save ("dateiname", public) + + + +storage info + PROC storage info + Informationsprozedur über den belegten Hintergrund-Speicher. + + +task info + PROC task info + Informiert über alle Tasknamen im System unter gleichzeitiger Angabe der + Vater/Sohn-Beziehungen (Angabe durch Einrückungen). + + PROC task info (INT CONST art) + Informiert über alle Tasks im System. Mit 'art' kann man die Art der Zusatz- + Information auswählen. Für 'art' sind zur Zeit folgende Werte zugelassen: + + art=1: entspricht 'task info' ohne Parameter, d.h. es gibt nur die Tasknamen + unter Angabe der Vater/Sohn-Beziehungen aus. + + art=2: gibt die Tasknamen aus. Zusätzlich erhalten Sie Informationen über die + verbrauchte CPU-Zeit der Task, die Priorität, den Kanal, an dem die + Task angekoppelt ist, und den eigentlichen Taskstatus. Hierbei bedeuten: + + 0 -busy- Task ist aktiv. + 1 i/o Task wartet auf Beendigung des Outputs oder auf + Eingabe. + 2 wait Task wartet auf Sendung von einer anderen Task. + 4 busy-blocked Task ist rechenwillig, aber blockiert. + 5 i/o -blocked Task wartet auf I/O, ist aber blockiert. + 6 wait-blocked Task wartet auf Sendung, ist aber blockiert. + Achtung: Die Task wird beim Eintreffen einer + Sendung automatisch entblockiert. + + art=3: wie 2, aber zusätzlich wird der belegte Speicher angezeigt. (Achtung: + Prozedur ist zeitaufwendig!). + + + task info(2) + + +task status + PROC task status + Informationsprozedur über den Zustand der eigenen Task. Informiert u.a. über + - Name der Task, Datum und Uhrzeit; + - verbrauchte CPU-Zeit; + - belegten Speicherplatz; + - Kanal, an den die Task angekoppelt ist; + - Zustand der Task (rechnend u.a.m.); + - Priorität. + + PROC task status (TASK CONST t) + Wie obige Prozedur, aber über die Task mit dem internen Tasknamen 't'. + + + task status (father) + + + +task password + PROC task password (TEXT CONST geheim) + Einstellen eines Passworts für Benutzertask. Das Kommando 'task password' ist + ein Monitor-Kommando. Ist eine Task mit einem Paßwort geschützt, so wird + durch den Supervisor nach dem 'continue'-Kommando das Passwort angefragt. + Nur nach Eingabe des richtigen Passworts gelangt man in die gewünschte Task. + Das Passwort kann durch nochmaligen Aufruf von 'task password' geändert + werden, z.B. wenn es in regelmäßigen Abständen geändert werden muß, um + personenbezogene Daten zu schützen. + + Es gibt keine Möglichkeit, ein einmal eingestelltes Passwort in Erfahrung zu + bringen. Sollte das Passwort vergessen werden, kann somit die Task nur noch + gelöscht werden. + + Wird als Passwort ein '-'-Zeichen eingegeben, so wird verhindert, daß die + betreffende Task jemals wieder mit dem 'continue'-Kommando angekoppelt + werden kann. Dies ist z.B. für Manager-Tasks sinnvoll. + + + task password("mein geheimnis") + + ++ + THESAURUS OP + (THESAURUS CONST links, rechts) + Vereinigungsmenge von 'links' und 'rechts'. + + THESAURUS OP + (THESAURUS VAR thes, TEXT CONST name) + Nimmt den TEXT 'name' in den Thesaurus 'thes' auf. + + + save (SOME father + "rechnung", archive) + + + +- + THESAURUS OP - (THESAURUS CONST links, rechts) + Differenzmenge von 'links' und 'rechts'. + + THESAURUS OP - (THESAURUS VAR thes, TEXT CONST name) + Liefert einen Thesaurus aus 'thes', aber ohne den Eintrag 'name'. + + + save (ALL myself - "rechnung", archive) + + + +/ + THESAURUS OP / (THESAURUS CONST links, rechts) + Zweck: Schnittmenge von 'links' und 'rechts'. + + + save(ALL myself / ALL father, archive) + + + TASK OP / (TEXT CONST task name) + Liefert aus einem Tasknamen den internen Tasknamen. '/' kann überall dort + eingesetzt werden, wo ein interner Taskname verlangt wird. + + + fetch ("dateiname", /"global") + diff --git a/doc/user-manual/1.8.7/doc/benutzerhandbuch.4 b/doc/user-manual/1.8.7/doc/benutzerhandbuch.4 new file mode 100644 index 0000000..c13a091 --- /dev/null +++ b/doc/user-manual/1.8.7/doc/benutzerhandbuch.4 @@ -0,0 +1,2242 @@ +#start(5.0,1.5)##pagenr("%",1)##setcount(1)##block##pageblock##count per page# +#headeven# +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# + EUMEL-Benutzerhandbuch +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#headodd# +#lpos(0.0)##cpos(5.5)##rpos(11.0)##fillchar(" ")# +#table# + Teil 4: Der Editor +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#bottomeven# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +4 - % GMD +#tableend##clearpos# +#end# +#bottomodd# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +GMD 4 - % +#tableend##clearpos# +#end# +TEIL 4: Der Editor +#free(1.0)# + +4.0. Vorwort + +#free(1.0)# +Mit dem #ib#EUMEL-Editor#ie# schreiben Sie alle Ihre Texte und Daten. Er bietet vielfäl +tige Möglichkeiten, um Autoren oder Programmierer bei dem Erstellen, Korrigieren und +Gestalten von Manuskripten oder Programmen zu unterstützen. Die größte Hilfe beim +Schreiben besteht (durch die Speicherfähigkeit von Computern) im beliebig häufigen +Zugriff auf einmal geschriebene Informationen. Im Gegensatz zu einer Schreibmaschi +ne können Sie mit dem EUMEL-Editor (beliebig oft) Einfügungen vornehmen, Texte +korrigieren, löschen und neu gestalten. + +Somit ist das Schreiben von Texten mittels des EUMEL-Systems besonders dann +vorteilhaft und zeitsparend, wenn Texte häufig geändert werden oder wenn sie in +einer besonders schönen Form gedruckt werden sollen. Weiterhin bietet der Editor +Hilfen zum Schreiben an, wie z.B. automatischen Wortumbruch am Zeilenende, eine +Einrückungsautomatik, "Lernen" von Texten u.a.m. Zusätzlich kann der Editor in +seinen Fähigkeiten erweitert und somit für spezielle Schreibarbeiten angepaßt werden. +Aber das soll in einem späteren Kapitel beschrieben werden. + +Bei der Entwicklung des Editors wurde besonderer Wert auf einfache Bedienung +gelegt: innerhalb von wenigen Minuten können Sie schon Texte schreiben und Daten +erfassen und sehen stets auf dem Bildschirm, was mit Ihrem Text passiert. Das +Schreiben und Korrigieren werden durch einige wenige, aber leistungsstarke Funk +tionstasten unterstützt. + +Einige Gestaltungsmöglichkeiten für Texte kann man nicht direkt auf dem Terminal +"sehen", wie z.B. Proportionalschriften, Fettdruck usw. Solche Leistungen können +durch Anweisungen an die Textkosmetik-Programme und den EUMEL-Drucker +angefordert werden. Diese Anweisungen müssen in den Text eingefügt werden. Lesen +Sie hierzu Teil 5 ("Textkosmetik"). +#free(1.0)# + +#ib(9)#4.1. #ib#Ein- und Ausschalten des Editors#ie##ie(9)# + +#free("1.0")# + #on("i")# + Hier beschreiben wir, wie der Editor ein- und ausgeschaltet wird und wie der + Editor eine Datei einrichtet. + + #off("i")##free(1.0)# +Wenn in Ihrer Task auf dem Bildschirm die Aufforderung + +____________________________________________________________________________ + +gib kommando : + +____________________________________________________________________________ + + +erscheint, tippen Sie + +____________________________________________________________________________ + +#ib#edit#ie# ("dateiname") + +____________________________________________________________________________ + + +und der EUMEL-Editor wird eingeschaltet. Ist die Datei noch nicht vorhanden, d.h. +kein Text unter dem angegebenen Namen im System gespeichert, folgt eine Anfrage, +ob eine Datei unter dem eingegebenen Namen neu eingerichtet werden soll: + +____________________________________________________________________________ + +"dateiname" neu einrichten (j/n) ? + +____________________________________________________________________________ + + +Dies dient zur Kontrolle von Schreibfehlern, die besonders bei ähnlichen Dateina +men auftreten. Man kann dann das Einrichten der Datei ablehnen, den Dateinamen +verbessern und das Kommando erneut geben. + +Falls Sie die Datei neu anlegen wollen, bejahen Sie diese Frage mit + +#center##taste1(" j ")# #taste1(" J ")# #taste1(" y ")# oder #taste1(" Y ")# + + +Es erscheint ein leerer Editorbildschirm. Die oberste Zeile des Bildschirms ist die +#ib#Titelzeile#ie#. In ihr kann nicht geschrieben werden. Sie zeigt jedoch verschiedene +nützliche Dinge an: den Namen der Datei, die Nummer der aktuellen Zeile, in der +gerade geschrieben wird, Tabulatormarken, Einfügemodus, Lernmodus, Auftrennung +usw. + +____________________________________________________________________________ + + ................. dateiname ...................... Zeile 1 +_ + + +____________________________________________________________________________ + + +In unserem Fall haben Sie eine neue Datei angelegt. Sie enthält noch keinen Text. In +der Titelzeile sind jedoch schon der Name der Datei und die aktuelle Zeilennummer +eingetragen. Bei einer neuen Datei ist der Bildschirm unterhalb der Titelzeile leer. +Dieser Teil dient als "Schreibfläche". Der #ib#Cursor#ie# steht dann direkt unter der Titelzei +le. Er zeigt immer die aktuelle #ib# Schreibposition#ie# an. Jetzt kann sofort mit dem Schrei +ben begonnen werden, ganz wie mit einer normalen Schreibmaschine. + +Rufen Sie eine Datei auf, in die Sie schon Text geschrieben haben, zeigt Ihnen der +Editor das zuletzt bearbeitete Textstück und Sie können normal weiter schreiben. + +Wollen Sie die #ib#Schreibarbeit beenden#ie# und den #ib#Editor ausschalten#ie#, so drücken Sie die +beiden Tasten + +<ESC> <q> + +nacheinander. Es erscheint + +____________________________________________________________________________ + +gib kommando: + +____________________________________________________________________________ + + +und Sie haben damit den #ib#Editor verlassen#ie# und befinden sich wieder im Monitor. #page# + +#ib(9)#4.2. Die wichtigsten Tasten des Editors#ie(9)# +#free(1.0)# +#ib(9)#4.2.1. Das #ib#Tastenfeld#ie##ie(9)# + +#free(1.0)# + #on("i")# + Auf dem Tastenfeld gibt es einige Tasten, die auf einer Schreibmaschine nicht vor + handen sind. + + #off("i")# +#free(1.0)# +Das Tastenfeld eines EUMEL-Terminals entspricht weitgehend dem einer Schreib +maschine. Sie finden also die Buchstaben a-z und die Ziffern 0-9 auf Tasten. Mit +der #ib#SHIFT-Taste#ie# (Umschalttaste) und gleichzeitigem Drücken einer anderen Taste +können Sie die großen Buchstaben und eine Reihe von speziellen anderen Zeichen, +die #ib#Sonderzeichen#ie# genannt werden, schreiben. Die "Zwischenraumtaste" oder Leer +taste erzeugt immer ein Leerzeichen. + +Nun gibt es in der Praxis zwei unterschiedliche Tastaturen. Zum einen existiert die +#ib#EDV-Tastatur#ie#, die zum Schreiben von Programmen benutzt wird. Sie erkennt man +daran, daß keine #ib#Umlaute#ie# (ä, ö, ü) und kein ß auf den Tasten abgebildet sind. Dafür +gibt es Tasten für eckige und geschweifte Klammern. Sollen auf einer solchen Tasta +tur die Umlaute geschrieben werden, muß man sich eines Tricks bedienen: mit der +Taste ESC und nachfolgendem Betätigen einer anderen Taste (z.B. a, o, u) erhalten +wir den entsprechenden Umlaut. + +In der Regel kann man die Umlaute auf dem Bildschirm eines solchen EDV-Ter +minals nicht sehen, sondern sie erscheinen als "a", "u", usw. Beim Druck eines +Textes werden sie aber richtig dargestellt. + +Die andere Tastatur entspricht in der #ib#Tastenbelegung#ie# weitgehend einer deutschen +Schreibmaschine und besitzt Tasten für die Umlaute und ß. Sollen vorwiegend deut +sche Texte geschrieben werden, empfiehlt es sich, solch ein Terminal zu verwenden. + + + + Tastatur + + + + + + + + + + + + + + + +Neben diesen "einfachen" Tasten gibt es die Funktionstasten, die zur Bedienung des +Editors (aber auch anderer Programme) notwendig sind. Wo die Tasten auf Ihrem +Gerät liegen, hängt von dem jeweiligen Gerätetyp ab. Die Wirkung der Tasten +erklären wir in den anschließenden Abschnitten. #count("1")#) #foot# +#value("1")#) Es kann sein, daß die Tasten nicht richtig beschriftet sind. Die Installations + anleitung muß dann die Entsprechungen beschreiben. Zusätzlich zu den im + folgenden beschriebenen können sich noch weitere Tasten auf Ihrem Terminal + befinden, die aber standardmäßig keine besondere Bedeutung für den Editor + haben. +#end# +#page# +Die Funktionstasten des EUMEL-Systems +#l pos (0.0)##l pos(4.0)# + + +<,>,v,^ Positionierungstasten +#table# +#free(0.5)# +<SHIFT> Umschalttaste +#free(0.5)# +<CR> Eingabe-/ Absatztaste +#free(0.5)# +<HOP> Verstärkertaste +#free(0.5)# +<RUBOUT> Löschtaste +#free(0.5)# +<RUBIN> Einfügetaste +#free(0.5)# +<TAB> Tabulatortaste +#free(0.5)# +<MARK> Markiertaste +#free(0.5)# +<ESC> Kommandotaste +#free(0.5)# +<SV> Supervisortaste +#free(0.5)# +<STOP> Stoptaste +#free(0.5)# +<WEITER> Weitertaste +#tableend##clear pos# + + +#page# +Die Wirkung der Funktionstasten +#free(0.5)# +<SHIFT> + +#ib#Umschalttaste#ie# + +Wird diese Taste gleichzeitig mit einer anderen betätigt, so wird ein Buchstabe in +Großschreibung, bei den übrigen Tasten das obere Zeichen, ausgegeben. So wird z.B. +anstelle der "9" das Zeichen ")" ausgegeben. +#free(1.5)# +<CNTL> + +#ib#Kontroll-/Steuertaste#ie# + +Mit dieser Taste in Kombination mit Zusatztasten können Sonderfunktionen des +Systems angewählt werden. Für EUMEL sind folgende drei Tastenkombinationen +(wobei die Tasten gleichzeitig betätigt werden müssen) wichtig: + +<CTRL> <a> Anhalten der Bildschirmausgabe + +<CTRL> <b> Wirkung der SV-Taste (bei jedem Rechner) + +<CTRL> <c> Bildschirmausgabe fortführen +#l pos (0.0)##l pos(4.0)# + + +#free(1.5)# +<CR> + +#ib#Eingabetaste / Absatztaste#ie#, Carriage Return, kurz: 'CR' + +Diese Taste wird im Editor betätigt, um das Ende eines Absatzes zu kennzeichnen. +Die kontinuierliche Fließtexteingabe wird durch sie unterbrochen und es wird an den +Beginn der nächsten Zeile positioniert. Einrückungen werden beibehalten. Eine Ab +satzmarke ist im Editor an der Inversmarkierung am rechten Bildschirmrand zu erken +nen. + +Die 'CR'-Taste ist oft mit einem geknicktem Pfeil nach links gekennzeichnet. Im +Kommandomodus (also bei "gib kommando :") wird durch Betätigung dieser Taste ein +gegebenes Kommando ausgeführt. + +Die sonstige Benutzung dieser Taste außerhalb des Editors wird in der jeweiligen +Anwendung beschrieben, z.B. Bestätigung eines Trennvorschlags bei der Silbentren +nung. + +<, >, v, ^ + +Tasten für die Positionierung + +#ib#Positionierung des Cursors#ie# um eine Spalten-/Zeilenposition in die jeweilige Richtung. +#free(1.5)# +<HOP> + +"#ib#Verstärkertaste#ie#"; wird als Vorschalttaste bedient. + +In Kombination mit anderen Funktionstasten wird deren Wirkung verstärkt. (vgl. +4-#topage("HOP")#) + +#on("u")#Beispiel:#off("u")# + + +<HOP> <v> + +Steht der Cursor nicht am unteren Bildrand, so wird er dorthin positioniert. Steht er +am unteren Bildrand, so wird um einen Bildschirminhalt "weitergeblättert". + +Auch die Funktionen 'RUBIN'/'RUBOUT' werden in Kombination mit der HOP-Taste +verstärkt.(vgl. 4-#topage("verstärkt")#ff) #free(1.5)# +<RUBOUT> + +#ib#Löschtaste#ie# + +Das Zeichen, auf dem der Cursor steht, wird gelöscht. Wenn der Cursor hinter dem +letzten Zeichen einer Zeile steht, wie bei fortlaufender Eingabe üblich, wird das letzte +Zeichen gelöscht. + +#on("u")#Beispiel:#off("u")# + +____________________________________________________________________________ + ................. dateiname ...................... Zeile 4 + +Mit der RUBOUT-Taste ist es möglich, ein +Zeichen nach dem anderen auf dem Bildschirm +zu löschen. Steht der Cursor auf einem +Zeichen, das irrtümlicherweise eingetipp?t +wurde, kann dieses durch einmaliges +Betätigen der RUBOUT-Taste aus der Datei +gelöscht werden. + +____________________________________________________________________________ + + +Nach Betätigen der <RUBOUT> - Taste: + + +____________________________________________________________________________ + ................. dateiname ...................... Zeile 4 + +Mit der RUBOUT-Taste ist es möglich, ein +Zeichen nach dem anderen auf dem Bildschirm +zu löschen. Steht der Cursor auf einem +Zeichen, das irrtümlicherweise eingetippt +wurde, kann dieses durch einmaliges +Betätigen der RUBOUT-Taste aus der Datei +gelöscht werden. + +____________________________________________________________________________ + +#page# + + +<RUBIN> + +#ib#Ein- bzw. Ausschalten des Einfügemodus.#ie# + +Das Betätigen der Taste schaltet in den Einfügemodus.Der Zustand wird durch das +Wort "RUBIN" im linken Drittel der Titelzeile der Datei angezeigt. Vor dem Zeichen, +auf dem der Cursor steht, wird eingefügt. Nochmaliges Betätigen der Taste schaltet +den Einfügemodus aus. + +#on("u")#Beispiel:#off("u")# + + +____________________________________________________________________________ + ................. dateiname ...................... Zeile 5 + +Das Betätigen der Taste schaltet in den +Einfügemodus. Der Zustand wird durch das +Wort "RUBIN" im linken Drittel der Titelzeile +angezeigt. Vor dem Zeichen, auf dem der +Cursor steht, wird ' ' eingefügt. +Nochmaliges Betätigen der Taste schaltet den +Einfügemodus aus. + +____________________________________________________________________________ + + + +Nach Betätigen der <RUBIN> - Taste und Einfügen des Wortes " jetzt": + +____________________________________________________________________________ + .......RUBIN...... dateiname ..................... +Zeile 5 +Das Betätigen der Taste schaltet in den +Einfügemodus. Der Zustand wird durch das +Wort "RUBIN" im linken Drittel der Titelzeile +angezeigt. Vor dem Zeichen, auf dem der +Cursor steht, wird jetzt ' ' eingefügt. +Nochmaliges Betätigen der Taste schaltet den +Einfügemodus aus. + +____________________________________________________________________________ + + + +<TAB> + +#ib#Tabulatortaste#ie# + +Betätigen Sie die 'TAB'-Taste, um vom linken Bildschirmrand auf den Textbeginn in +der Zeile bzw. eine Tabellenspalte zu positionieren. Erneutes Betätigen der 'TAB'- +Taste positioniert den Cursor auf die nächste eingestellte Tabulator-Position. Die +eingestellten Tabulatorpositionen erkennen Sie an den Tabulatorzeichen (Dachzei +chen) in der obersten Bildschirmzeile. + +Wenn keine TABs gesetzt sind, werden die beiden Schreibgrenzen, linker Bildschirm +rand und Ende der Zeile, als #on("i")#voreingestellte# #off("i")# TABs angesehen. +#free(1.5)# +<MARK> + +#ib#Ein- bzw. Ausschalten der Markierung#ie#. + +Bei Betätigung dieser Taste wird in einen speziellen #ib#Markierzustand#ie# geschaltet. Alles, +was Sie jetzt schreiben bzw. durch Bewegen des Cursors in Richtung Dateiende +kennzeichnen, steht als #on("i")#markierter# #off("i")# Bereich für die Bearbeitung zur Verfügung. Zur +besseren Sichtbarkeit wird der markierte Bereich invers zum übrigen Text dargestellt. + +Wird der Cursor in eine Richtung bewegt, wird das gesamte Textstück zwischen +Einschaltpunkt der Markierung und aktueller Cursorposition markiert. Rückwärtsbewe +gungen des Cursors verkürzen den markierten Bereich wieder. + +Einen derart markierten Bereich können Sie nun z.B. duplizieren, verschieben, lö +schen, durchsuchen oder weiterverarbeiten. (vgl. 4- #topage("mark")# ff). + +Durch erneutes Betätigen der MARK-Taste schalten Sie den Markier-Zustand auch +wieder aus. + +#on("u")#Beispiel:#off("u")# + +Sie wollen einen Textteil markieren, um ihn an eine andere Stelle zu verschieben +(evtl. um ihn an dieser Stelle später zu löschen): + +Sie positionieren den Cursor auf den Beginn des Textteils, gehen in den Markierzu +stand durch Betätigen der MARK-Taste und führen nun den Cursor mit Hilfe der +Positioniertasten bis zum Ende des zu markierenden Bereichs. + + +____________________________________________________________________________ + ................. dateiname ...................... Zeile 5 + +Mit dem Cursor positionieren Sie an die +Stelle, ab der markiert werden soll und +betätigen die MARK-Taste. Nun führen Sie den +Cursor bis zu der Stelle, bis zu der +markiert werden soll. Der markierte Text wird +normalerweise "schwarz auf weiss" +dargestellt. + +____________________________________________________________________________ + + + +Mit weiteren Kommandos (vgl. ESC-Taste und Kommando-Verarbeitung, 4- #topage("ESC")#) +kann der Bereich nun bearbeitet werden. +#free(1.5)# +<ESC> + +#ib#Kommandotaste#ie# + +Mit der ESC-Taste in Kombination mit einer Folgetaste können Sie vordefinierte +Aktionen anwählen. Es gibt Aktionen, die vorprogrammiert zur Verfügung stehen, und +Sie selbst können weitere hinzufügen. (vgl. 4-#topage("ESC")# ) #free(1.5)# +<SV> + +#ib#SUPERVISOR-Taste im Mehrbenutzer-Betrieb#ie# + +Betätigen Sie diese Taste im Editor, dann unterbrechen Sie Ihre Editierarbeit und +erhalten die Meldung + +____________________________________________________________________________ + + Terminal 2 + + + EUMEL Version 1.8/M + + + gib supervisor kommando: + + + + + ESC ? --> help + ESC b --> begin("") ESC h --> halt + ESC c --> continue("") ESC s --> storage info + ESC q --> break ESC t --> task info + + +____________________________________________________________________________ + + +Wollen Sie nun im Editor fortfahren bzw. haben Sie irrtümlich die SV-Taste betätigt, +dann geben Sie das Kommando + +____________________________________________________________________________ + + gib supervisor kommmando : + continue ("Sekretariat") + + +____________________________________________________________________________ + + +(falls Ihre Task, in der Sie arbeiteten, wirklich "Sekretariat" hieß!) + +Um Ihren in Bearbeitung befindlichen Text wieder vollständig auf dem Bildschirm zu +sehen, betätigen die die Tasten + +<ESC> <b> + +Sie sind wieder an der Stelle, an der Sie den Text mit der SV-Taste verlassen ha +ben, und können normal weiterarbeiten. + +#on("u")#Achtung:#off("u")# Die SV-Taste kann, je nach Terminal, durch das Betätigen von zwei +Tasten gleichzeitig realisiert sein (oft 'CTRL b'). Beachten Sie die Beschreibung Ihrer +Tastatur! +#free(1.5)# +<STOP> + +#ib#Unterbrechen einer Ausgabe#ie# (oft auch als CTRL a realisiert). + +Haben Sie diese Taste aus Versehen betätigt, erkennen Sie dies daran, daß der +Editor nicht "reagiert". Betätigen Sie die WEITER-Taste (oft auch CTRL c). +#free(1.5)# +<WEITER> + +Unterbrochene Ausgabe fortsetzen. + +Ein mit der STOP-Taste angehaltene Ausgabe können Sie durch Betätigen der +#ib#WEITER-Taste#ie# fortsetzen. + + +#on("u")#VORSICHT:#off("u")# Die STOP-Taste unterbricht nur die Ausgabe auf den Bildschirm. +Zeichen, die während des STOP eingegeben werden, werden gespeichert und nach +'WEITER' ausgegeben! + + +#page# +4.2.2 Speicherung von Texten +#free(1.0)# + #on("i")# + In diesem Abschnitt wird der Begriff "Datei" erklärt und es wird erläutert, wie + unterschiedliche Texte auseinandergehalten werden können. + ## #off("i")# + + + +Das EUMEL-System speichert einmal geschriebene Texte, bis sie vom Benutzer +gelöscht werden. In der Regel wird nicht nur ein (langer) Text oder ein Programm +geschrieben, sondern mehrere und unterschiedliche. Um diese auseinanderhalten zu +können, versehen wir sie jeweils mit einem Namen, der frei gewählt werden kann. +Beispiele für Namen: + + + "Brief vom 1.12.86" + "1. Kapitel meines Buches" + + +Eine Sammlung von Zeichen (also im Normalfall unsere geschriebenen Texte), die mit +einem Namen versehen worden ist, nennt man eine #ib##on("bold")#Datei#ie##off("bold")#. Der Editor erstellt also eine +Datei, wenn wir einen Text schreiben. Eine Datei kann bis zu 4 000 Zeilen fassen, +wobei jede Zeile bis zu 32 000 Zeichen lang sein darf. Das Produkt aus der Anzahl +der Zeilen und den Zeichen pro Zeile kann z.Zt. jedoch 1 000 000 Zeichen (=1MB) +nicht übersteigen. #page# + +#ib(9)#4.2.3. #ib#Schreiben von Texten#ie##ie(9)# +#free(1.0)# + #on("i")# + Texte werden fortlaufend geschrieben. Absätze werden durch die CR-Taste + markiert. + # #off("i")# + +#free(0.8)# + +Nach dieser etwas langen Vorrede können wir endlich losschreiben. Wird ein Zeichen +geschrieben, rückt der #ib#Cursor#ie# automatisch nach rechts auf die nächste Schreibstelle. +Durch den automatischen #ib#Wortumbruch#ie# werden angefangene Worte, die über ein +Zeilenende hinausgehen würden, ohne Silbentrennung in die nächste Zeile gebracht. +#u##count("6")#)#e# +#foot# +#u##value("6")#)#e# Nehmen Sie bitte keine Silbentrennung "per Hand" vor. Eingebrachte Trenn + striche gelten als Bindestrich und bleiben somit auch bei Umformatierungen + erhalten, was unerwünscht ist. Für diese mühevolle Aufgabe gibt es in der Text + verarbeitung ein Programm! +#end# + +Die 'CR'-Taste (bei einer Schreibmaschine bedeutet sie "Wagenrücklauf") braucht +also nur noch betätigt zu werden, wenn eine Zeile vorzeitig beendet werden soll, d.h. +bei einem #ib#Absatz#ie# oder einer #ib#Leerzeile#ie#. Der Cursor wird dabei an den Anfang der +nächsten Zeile positioniert. Gleichzeitig erscheint in der vorherigen Zeile am rechten +Rand des Bildschirms eine Markierung, die anzeigt, daß hier ein Absatz gemacht +wurde. + +Darum ist das Betätigen der 'CR'-Taste bei Tabellenzeilen und Programmtexten +besonders wichtig, denn hier soll ja jede Zeile separat bleiben. Sie wirkt nur hinter +dem letzten Zeichen. + +Der Editor ist auf das Schreiben von "normalen" Texten eingestellt. Bei normalen +Texten soll ein Wort, welches über das Ende einer Zeile gehen würde, automatisch in +die nächste Zeile gebracht werden. Diese Funktion wird "Wortumbruch" genannt. + +Ist kein Wortumbruch erwünscht, zum Beispiel bei der Beschreibung von Program +men, so geben Sie, bevor Sie den Editor aufrufen, im Monitor das Kommando + +____________________________________________________________________________ +gib kommando : +#ib#word wrap (false)#ie# + +____________________________________________________________________________ + + +Der Wortumbruch kann durch das Kommando + +____________________________________________________________________________ + +gib kommando : +#ib#word wrap (true)#ie# + +____________________________________________________________________________ + + +wieder eingeschaltet werden. Der Editor ist standardmäßig auf "Wortumbruch" einge +stellt und Sie sollten nur in Ausnahmefällen diese Benutzungsart ausschalten. + +Ein Bildschirm faßt (neben der Titelzeile) üblicherweise 23 Zeilen, die mit Text be +schrieben werden können. Ist die letzte Zeile voll und muß eine neue Zeile begonnen +werden, "rutscht" der Bildschirminhalt automatisch um eine Zeile nach oben. Damit +ist Platz für eine Leerzeile, die nun ebenfalls beschrieben werden kann, usw. Keine +Angst: die so verschwundenen Zeilen sind natürlich nicht "weg". Da ein Bildschirm +immer nur eine beschränkte Anzahl von Zeilen hat, kann der Editor nur einen Aus +schnitt aus der Datei zeigen. +#page# +Einrückungen +#free(1.0)# + #on("i")# + Die #ib#Einrückungautomatik#ie# erlaubt bei fortlaufendem Schreiben, die Einrückung zu + erhalten. + # #off("i")# +#free(0.5)# +Soll ein Text eingerückt werden, so betätigt man entsprechend oft die Leertaste. Die +in dieser Zeile geschriebene Einrückung wird automatisch in den folgenden Zeilen +beibehalten, bis sie durch die Cursor-Positionierungstasten wieder aufgehoben wird. + +#on("u")#Beispiele für Aufzählungen:#off("u")# Einrückung funktioniert automatisch ohne aktive Eingabe +von Leerschritten. + +____________________________________________________________________________ + ................. dateiname ...................... Zeile 1 + - Der erste Typ der Aufzählungsform + ist die #ib#Aufzählung#ie# durch Voran + stellen eines Sondersymbols. + Als Sondersymbole sind die beiden + Zeichen "-" und "*" zugelassen. An + ihnen erkennt der Editor eine + Aufzählung. + + 12. Weiterhin können Aufzählungen + durch Begriffe, gefolgt von + einem Punkt oder einer ")", als + #ib#Aufzählungskriterium#ie# verwendet + werden. + + + Aufzählung: Auch diese Möglichkeit + steht Ihnen zur Verfü + gung. Der Editor er + kennt, daß Sie hier + einen Begriff erläutern + wollen. + +____________________________________________________________________________ + +#page# +Wann werden nun Aufzählungen vom Editor erkannt? + +Die hier aufgeführten Einzelheiten sollte nur der hieran interessierte Anfänger lesen! + +Wenn die Einrückung nicht funktionieren sollte, prüfen Sie die folgenden Punkte, die +für das Einrücken erfüllt sein müssen: + +1) Die Vorgängerzeile hat eine Absatzmarke. + + Wichtig: Innerhalb eines Aufzählungspunktes schaltet die Absatztaste die Aufzäh + lungseinrückung aus! + +2) "*" bzw. "-" und mindestes ein Leerzeichen sind die ersten Zeichen in der + Zeile. + +3) "." bzw. ")" und mindestens ein Leerzeichen nach höchstens sieben Zeichen sind + die ersten Zeichen in der Zeile. + +4) ":" und mindestens ein Leerzeichen nach höchstens 19 Zeichen sind die ersten + Zeichen in der Zeile. +#page# + +#ib(9)#4.2.4. #ib#Positionieren#ie# im Text#ie(9)# + +#free(1.0)# + #on("i")# + Um Korrekturen (Überschreiben, Löschen oder Einfügen) vorzunehmen, muß der + #ib#Cursor#ie#, der die aktuelle Schreibposition anzeigt, bewegt werden können. Bei + längeren Texten ist es möglich, den Cursor auch auf Zeilen zu positionieren, die + (noch nicht) auf dem Bildschirm angezeigt werden. Somit zeigt der Editor nicht nur + immer das Ende einer Datei, sondern einen beliebigen Ausschnitt, der auf dem + Bildschirm im sogenannten '#ib#Fenster#ie#' sichtbar ist. + #off("i")# +#free(1.0)# +Ist eine Korrektur notwendig, positionieren Sie den Cursor auf die Stelle, an der die +Korrektur vorgenommen werden soll. Dazu verwenden Sie die #ib#Positionierungstasten#ie# +LINKS, RECHTS, OBEN und UNTEN. LINKS und RECHTS bewegen den Cursor +innerhalb einer Zeile. Stößt man mit RECHTS an das Ende einer Zeile, wird der +Cursor an den Anfang der nachfolgenden Zeile bewegt. + + v ^ + +Ein #ib#Zeilenwechsel#ie# kann einfacher mit den Tasten OBEN und UNTEN vorgenommen +werden. Die Taste OBEN bewegt den Cursor eine Zeile nach oben, die Taste UNTEN +entsprechend eine Zeile tiefer. + +Was passiert nun, wenn Sie den unteren oder den oberen Rand des Bildschirms +erreicht haben, und Sie positionieren darüber hinaus? In diesem Fall wird der Text +zeilenweise nach oben oder nach unten verschoben und es erscheint die gewünschte +Zeile, wobei am anderen Rand einige verschwinden". Wir sehen also, daß wir mit den +Positionierungstasten den Bildschirm als Fenster über die Datei hinweggleiten lassen +können. Den Text selbst können wir uns auf einem langen Band geschrieben vorstel +len. Die #ib#Zeilennummer#ie#, die die Position des Cursors angibt, wird stets in der Titel +zeile angezeigt. + +Vermeiden Sie es, den Cursor über das Textende hinaus nach unten laufen zu las +sen. Sie verlängern dadurch Ihren Text um Leerzeilen, die Sie beim Weiterschrei +ben nicht auffüllen, sondern vor sich herschieben. + +Innerhalb einer Zeile ist es etwas anders: Positionieren wir bei einer Zeile, die breiter +als der Bildschirm ist, nach rechts, wird nicht das Fenster verschoben, sondern die +Zeile 'gerollt'.(vgl. Sie hierzu das Verschieben des Gesamtfensters mit dem 'mar +gin'-Kommando 4-#topage("margin")#) +4.2.5. Korrigieren im Text +#free(1.0)# + + #on("i")# + Einfache Korrekturen können durch #ib#Überschreiben von Zeichen#ie#, #ib#Löschen von + Zeichen#ie# und #ib#Einfügen von Zeichen#ie# vorgenommen werden. + + #off("i")# +#free(1.0)# +<RUBOUT> + +Die einfachste Möglichkeit der Korrektur ist das #ib#Überschreiben#ie#. Soll z.B. ein Zeichen +durch ein anderes ersetzt werden, so positioniert man der Cursor genau über dieses +und tippt das richtige Zeichen ein. Das kann natürlich auch mit mehreren Zeichen +nacheinander erfolgen. + +Korrekturen können Sie gleich beim Schreiben vornehmen, indem Sie die zuletzt +geschriebenen Zeichen mit der #ib#RUBOUT-Taste#ie# löschen. Häufig bemerkt man aber +#ib#Schreibfehler#ie# erst etwas später, so daß man diese Fehler nicht so leicht korrigieren +kann. Für solche Zwecke müssen Sie den Cursor an die Textstelle bewegen, an der +korrigiert werden soll. + +Wollen Sie ein #ib#Zeichen löschen#ie#, so positionieren Sie den Cursor auf dieses Zeichen +und betätigen die Taste #ib#RUBOUT#ie#. Das Zeichen verschwindet und die Restzeile rückt +heran. Sollen mehrere Zeichen gelöscht werden, muß die RUBOUT-Taste entspre +chend oft gedrückt werden. + +Steht der Cursor hinter dem letzten Zeichen der Zeile, wird immer das letzte Zeichen +der Zeile gelöscht. Man kann also mit dieser Eigenschaft eine Zeile "von hinten +wegradieren".(vgl. hierzu auch 4- #topage("ESC RUBOUT")#) + + + +<RUBIN> + +Fehlende Zeichen können Sie genauso einfach einfügen. Sie bringen den Cursor auf +das Zeichen, vor das eingefügt werden soll. Dann drücken Sie die Taste #ib#RUBIN#ie#. Der +Editor gelangt in den #ib#Einfügemodus#ie#, was in der Titelzeile durch RUBIN angezeigt +wird. Er fügt alle Zeichen ein, die jetzt getippt werden (anstatt zu überschreiben). Der +Teil der Zeile rechts vom Cursor rückt jeweils um entsprechend viele Stellen nach +rechts. + +Wichtig ist, daß im RUBIN-Modus der Editor genauso funktioniert wie im Normalzu +stand (natürlich mit der Ausnahme, daß eingefügt statt überschrieben wird). + +Im eingeschalteten RUBIN-Modus können keine Zeichen verloren gehen. Viele +Benutzer lassen darum den RUBIN-Modus immer eingeschaltet, um sich vor einem +unbeabsichtigten Überschreiben von Texten zu schützen. Sie korrigieren, indem Sie +die Verbesserung einfügen und den alten Text löschen. + +Durch erneutes Betätigen der RUBIN-Taste beenden Sie den Einfügemodus. Die +RUBIN-Taste wirkt wie ein Schalter, der den Einfügemodus ein- und ausschaltet. +Allerdings können Sie nur so viele Zeichen in eine Zeile einfügen, bis das letzte Wort +der Zeile an das Zeilenende stößt. Das letzte Wort wird am Anfang der folgenden +Zeile eingefügt, sofern dort noch Platz ist und es sich nicht offensichtlich um die +letzte Zeile eines Absatzes handelt. Andernfalls wird automatisch eine neue Zeile für +das angefangene Wort eingefügt.(vgl. Sie hierzu auch 4- #topage("ESC RUBIN")#) #free(1.5)# +#page# +Springen und Zeilen einfügen/löschen +#free(1.0)# + #on("i")# + Bewegungen des Cursors sind mit den Positionierungstasten bei größeren "Ab + ständen" etwas mühsam, ebenso bei umfangreichen Löschungen und Einfügun + gen. Die "#ib#Verstärkertaste#ie#" HOP ermöglicht es, diese Operationen auf einfache + Weise zu beschleunigen. Mit der #ib#HOP-Taste#ie# kann man das Fenster über der + Datei nicht nur zeilenweise, sondern auch um jeweils eine Fensterlänge verschie + ben. Das nennt man #ib#Blättern#ie#. + + #off("i")# +#free(1.0)# +#goalpage("HOP")# +Wird die HOP-Taste vor einer anderen der schon erklärten Funktionstasten gedrückt, +verstärkt sie deren Wirkung. Die HOP-Taste ist eine "Präfix"-Taste: sie wird vor +(und nicht gleichzeitig mit, wie z.B. die Umschalttaste SHIFT) einer anderen Taste ge +drückt. Zuerst das springende Positionieren: +#free(1.0)# +<HOP> <>> + +#ib#Sprung an das rechte Bildschirmende#ie#. + +Falls die Zeile länger als das Fenster breit ist, wird die Zeile um eine Fensterbreite +nach links verschoben. +#free(1.0)# +<HOP> <<> + +#ib#Sprung an den Bildschirmrand links#ie# (ggf. seitlich blätternd). +#free(1.0)# +<HOP> <^> + +#ib#Sprung auf die erste Zeile des Bildschirms#ie#. + +Nochmaliges Betätigen dieser Tastenkombination positioniert den Cursor (und damit +das Fenster in der Datei) um ein Fenster zurück. ("Blättern") +#free(1.0)# +<HOP> <v> + +#ib#Sprung auf die letzte Zeile des Bildschirms#ie#. + +Das Blättern erfolgt analog HOP OBEN. +#free(1.0)# +<HOP> <CR> + +Positioniert das Fenster so, daß die aktuelle Zeile zur ersten des Fensters wird. +#free(1.0)# +<HOP> <RUBIN> + +#ib#Einfügen von Textpassagen#ie#. #goalpage("verstärkt")# Die HOP-Taste in Verbindung mit RUBIN und +RUBOUT wird zum "verstärkten" Löschen und Einfügen verwendet. + +Ab der aktuellen Position des Cursors "verschwindet" der restliche Text. Es kann wie +bei der anfänglichen Texteingabe fortgefahren werden. Die Anzeige '#ib#REST#ie#' in der +Titelzeile erinnert daran, daß noch ein Resttext existiert. Dieser erscheint nach einem +neuerlichen Betätigen der beiden Tasten HOP RUBIN wieder auf dem Bildschirm (die +Anzeige 'REST' verschwindet dann wieder). + +____________________________________________________________________________ + ................. dateiname ...................... Zeile 4 + +In diesem Text soll vor dem zweiten Satz +etwas eingefügt werden. #cursor("H")#ierzu wird der +Cursor an die Position geführt, an der +ein beliebiger Text eingefügt werden soll. + +____________________________________________________________________________ + + +Nach Betätigen der Tasten <HOP> und <RUBIN> sieht der Bildschirm wie folgt +aus: + +____________________________________________________________________________ + ............... dateiname .........REST.......... Zeile 4 + +In diesem Text soll vor dem zweiten Satz +etwas eingefügt werden. + + +____________________________________________________________________________ + + + +Nun kann beliebig viel Text eingefügt werden. Nochmaliges Betätigen von HOP und +RUBIN führt den Text-Rest wieder bündig heran. + + +<HOP> <RUBOUT> + +Löscht die Zeile ab Cursor-Position bis Zeilenende. + + +____________________________________________________________________________ + ................. dateiname ...................... Zeile 4 + +Soll eine ganze Zeile oder ein Textrest +gelöscht werden, so positioniert man an die +Stelle, ab der gelöscht werden soll. 'R'est löschen.... +Nach HOP RUBOUT ist der Zeilenrest gelöscht. + + +____________________________________________________________________________ + + +Nach Betätigen der Tasten <HOP> und <RUBOUT> sieht der Bildschirm wie +folgt aus: + +____________________________________________________________________________ + ................. dateiname ...................... Zeile 4 + +Soll eine ganze Zeile oder ein Textrest +gelöscht werden, so positioniert man an die +Stelle, ab der gelöscht werden soll. +Nach HOP RUBOUT ist der Zeilenrest gelöscht. + +____________________________________________________________________________ + + + +Steht der Cursor am Zeilenanfang, wird nach HOP RUBOUT dementsprechend die +ganze Zeile gelöscht und die Lücke durch Nachrücken der Folgezeilen geschlossen +(HOP RUBOUT betätigen). +#page# +Zeilen aufbrechen und Rückumbruch + +#free(1.0)# + #on("i")# + Um grössere Textpassagen einzufügen, betätigt man #ib#HOP RUBIN#ie# nacheinander. + Diese Tastenfolge kann benutzt werden, um eine Zeile bzw. eine längere Textpas + sage aufzubrechen). #ib#HOP RUBOUT#ie# am Ende einer Zeile macht einen #ib#Rückum + bruch#ie#. + + #off("i")# +#free(1.0)# +<HOP> <RUBIN> + +Wie bereits beschrieben, bewirkt #ib#HOP RUBIN#ie# in einer Zeile, daß der Zeilenrest rechts +des Cursors und alle Zeilen unterhalb der aktuellen Zeile scheinbar verschwinden. +#ib#REST#ie# in der Titelzeile erinnert daran, daß ein Teil der Datei nicht sichtbar ist. + +Wird unmittelbar nach HOP RUBIN wiederum HOP RUBIN betätigt, wird der vorherige +Zeilenrest als eigenständige Zeile dargestellt. Es ist damit eine Aufspaltung einer Zeile +in zwei Zeilen vollzogen. + + +<HOP> <RUBOUT> + +Der umgekehrte Fall, nämlich zwei Zeilen zu einer zusammenzufassen (sog. #ib# Rück +umbruch#ie#), ist durch #ib#HOP RUBOUT#ie# hinter dem letzten Zeichen einer Zeile möglich. +Hinter das letzte Zeichen einer Zeile kann einfach mit dem Tabulator positioniert +werden. + +Das Aufbrechen einer Zeile und der Rückumbruch zusammen angewandt stellen den +ursprünglichen Zustand wieder her. Beispiel: Mit HOP RUBIN bricht man eine Zeile +auf, der Rest der Zeile und nachfolgende Zeilen verschwinden vom Bildschirm. Erneu +tes HOP RUBIN stellt den rechten Zeilenteil auf der nächsten Zeile und die nachfol +genden Zeilen auf dem Bildschirm wieder dar. Da der Cursor sich noch immer am +rechten Rand der aufgebrochenen Zeile befindet, kann man mit HOP RUBOUT den +ursprünglichen rechten Zeilenteil wieder rekombinieren. +#page# + + +#ib(9)#4.2.6. Der #ib#Tabulator#ie##ie(9)# + +#free(1.0)# + #on("i")# + Eine weitere wichtige #ib#Positionierungshilfe#ie# innerhalb einer Zeile ist die #ib#TAB#ie#-Taste. + Sie wird u.a. zum Schreiben von Tabellen benötigt. Wie bei einer Schreibmaschine + können #ib#Tabulatormarken#ie# gesetzt bzw. gelöscht werden. + + #off("i")# +#free(1.0)# +<TAB> + +Der Tabulator hat eine wichtige Funktion für das schnelle Positionieren, auch wenn +keine Marken eingestellt wurden. #ib#Voreingestellte Tabulatormarken#ie# sind nämlich der +Textanfang einer Zeile (Einrückung, falls vorhanden) und die Stelle direkt hinter dem +letzten Zeichen der Zeile. Betätigt man also die Taste TAB, dann springt die Schreib +marke an die nächste dieser voreingestellten Positionen. So kann man schnell mit +dem Cursor an den Anfang oder das Ende einer Zeile gelangen (und z.B. am Zeilen +ende Zeichen "von hinten" löschen oder dort weiterschreiben). + +<HOP> <TAB> + +Nun zum #ib#Setzen des Tabulators#ie#: Sie setzen ihn, indem Sie den Cursor auf die Zei +lenposition bringen, in der die Marke plaziert werden soll. Hier betätigen Sie nun #ib#HOP +TAB#ie#. Die Tabulatorsetzung kann man in der Titelzeile an einer Markierung ("Dach +"-Zeichen) sehen, falls sie im Fensterbereich ist und die aktuelle Zeile nicht seitlich +verschoben ist. Betätigt man nun an irgendeiner Position innerhalb einer Zeile die +TAB-Taste, wird der Cursor auf die Position der nächsten Tabulatormarkierung (die +sich rechts von dem Cursor befindet) oder eine der voreingestellten Positionen be +wegt. + +#ib#Gesetzte Tabulatormarken#ie# können gelöscht werden, indem man mit der TAB-Taste +die Position der Tabulatormarke einstellt und dann HOP TAB betätigt. Die Marke ist +dann gelöscht, das Dach verschwindet in der Titelzeile. + +Tabulatormarkierungen hinterlassen keine Spuren in der Datei, sondern dienen nur als +Positionierungshilfen. mit 'HOP TAB' gesetzte Markierungen, die mit 'TAB' ange +sprungen werden, wirken beim Schreiben von Zahlen wie Dezimaltabulatoren, vgl. Sie +dazu 4- #topage("zahlen")#. + +#on("u")#Beispiel:#off("u")# + +Es soll für den Textbeginn eine Tabulatorposition auf die 12. Spalte gesetzt werden. +Hierzu wird der Cursor auf die 12. Spalte positioniert und die HOP- und die TAB- +Taste nacheinander betätigt. Das "Dach"-Zeichen erscheint in der 12. Spalte in der +Titelzeile und von nun an kann durch Betätigen der TAB-Taste diese Position direkt +angesteuert werden. + +____________________________________________________________________________ + ..........^....... dateiname ...................... Zeile 4 + +HOP TAB wurde in der 12. Spalte betätigt. + Mit TAB stehen Sie auf der 12. + Spalte. + +____________________________________________________________________________ + + +Werden #ib#Tabulatormarken#ie# gesetzt (HOP TAB), gelten die voreingestellten Tabulator +marken (Anfang und Ende einer Zeile) nicht mehr. Dies ist z.B. bei dem Schreiben +von Tabellen notwendig. Andererseits möchte man beim Schreiben von "normalem" +Text wieder die voreingestellten Tabulatormarken bedienen können. Mit den Tasten + +<ESC> <TAB> + +kann man die gesetzten Tabulatormarken (erkenntlich an dem "Dach"-Zeichen in +der Kopfzeile) vorübergehend verschwinden lassen. Dann gelten wieder die voreinge +stellten Marken. Erneutes #ib#ESC TAB#ie# stellt die gesetzten Tabulatormarken wieder her +usw.. +#free(1.5)# +Zahlentabellen schreiben: Dezimaltabulator +#goalpage("zahlen")# + +#free(1.0)# + #on("i")# + Beim Schreiben von #ib#Zahlentabellen#ie# sollen die Zahlen oft rechtsbündig im Text + erscheinen. Dazu bietet der Editor den #ib#Dezimaltabulator#ie# an. + + #off("i")# +#free(1.0)# +Für jede Zahlenkolonne wird die gewünschte Position der Einerstelle (also der letzten +Stelle) mit Hilfe eines Tabulators eingestellt. Mit #ib#TAB#ie# wird der Cursor zur jeweils +nächsten Tabulatormarke vorgerückt. Werden nun Ziffern geschrieben, so schreibt +man nicht - wie gewohnt - nach rechts, sondern die Ziffern werden nach links +eingerückt. Etwas genauer: Beim Drücken einer Zifferntaste wird, solange links vor +der Zahl noch ein Blank, eine Zahl, "+", "-" oder ein Punkt sichtbar ist, diese +gelöscht und die hierdurch neu entstandene Ziffernfolge rechtsbündig an der Tabula +torposition geschrieben. Das Schreiben von rechtsbündigen Zahlenkolonnen ist so +leicht möglich #count("11")#): +#foot# +#value("11")#) Wird eine #ib#Proportionalschrift#ie# (Schrift, bei der die Zeichen unterschiedliche + Breiten haben) verwendet, sollte man zwischen den einzelnen Zahlenkolonnen + mindestens zwei Leerzeichen schreiben. Andernfalls bekommt man - auf Grund + der unterschiedlicher Zeichenbreiten - keine rechtsbündigen Kolonnen gedruckt. +#end# + + + 12 12345,78 + 1 0,23 + 12345 1234,00 + + + +Es gibt somit vier nützliche Automatiken: neben dem automatischen Dezimaltabulator +den Wortumbruch, die Einrückautomatik und die Zeileneinfügeautomatik beim ein +fügenden Schreiben. +4.2.7. Lernen im Editor + +#free(1.0)# + + Beliebige Folgen von Tastenbetätigungen können gelernt und Tasten zugeordnet + werden. Das ist sinnvoll, wenn Sie wiederholt immer die gleichen Tastenbetä + tigungen ausführen müssen, wie z.B. in Tabellenzeilen etwas einfügen oder wenn + des öfteren gleiche Texte geschrieben werden müssen, wie z.B. ein Absender, + Grußformeln usw. + #goalpage("ESC")# + #free(1.0)# +< ESC> <HOP> + +Der #ib#Lernmodus#ie# wird durch Betätigen der Tasten #ib#ESC HOP#ie# eingeschaltet, es erscheint +#ib#LEARN#ie# als Kontrolle rechts in der Titelzeile). Alle Tastenanschläge werden jetzt bis +zum Ausschalten des Lernmodus gelernt. Auch Tastenanschläge wie 'CR'), so daß +man kann demnach auch mehrere Zeilen lernen lassen kann. + +<ESC> <HOP> <'taste'> z.B. ESC HOP j + +Das Beenden oder Ausschalten des Lernmodus erfolgt durch Drücken der drei Tasten +#ib#ESC HOP 'taste'#ie#. Dabei wird die gelernte Tastenanschlagsfolge, auch #ib#Lernsequenz#ie# +genannt, der Taste 'taste' zugeordnet. + +<ESC> <'taste'> z.B. ESC j + +Durch späteres Betätigen der Tastenfolge ESC 'taste' kann der gelernte Text an jeder +Stelle der Datei geschrieben werden. + +#on("u")#Beispiel:#off("u")# + +Ein Sachbearbeiter hat jeden Tag 50 mal die Worte 'Gesellschaft für Datenverarbei +tung' zu tippen. Er läßt den Editor diese Worte lernen mit + + +ESC HOP Gesellschaft für Datenverarbeitung ESC HOP m + +Die Worte liegen jetzt auf der Taste 'm'. Wird 'm' gedrückt, erscheint ein 'm' auf dem +Bildschirm. Mit ESC 'm' erscheinen die obigen Worte. ESC ist also notwendig, um +das normale 'm' von der Lernsequenz zu unterscheiden. + +Welche Tasten dürfen zum #ib#Lernen#ie# belegt werden? Alle Tasten, außer + +- vom System benutzte Tasten, wie SV, CTRL; +- vom Editor (je nach Anwendung) vorbelegte Tasten, wie die Tasten q oder ESC + und HOP; +- durch Programmierung (siehe dieses Kapitel) fest belegte Tasten. + +Praktische Tips: Man sollte die Tastatur nicht mit Lernsequenzen überlasten, weil man +sich zu viele Tasten nicht merken kann. Besser ist es, einige wenige Tasten fest zu +belegen und andere für momentane Aufgaben einzusetzen. + +Der Einsatz von #ib#Lernsequenz#ie#en ist besonders sinnvoll für das Schreiben von Text +kosmetikanweisungen. Anweisungen wie z.B. 'Unterstreichen einschalten', Schrift +typ-Anweisungen usw. werden zweckmäßigerweise auf Tasten gelegt. + +Hat man sich einmal beim '#ib#Lernen#ie#' verschrieben, so ist das nicht weiter schlimm: es +kann ohne Bedenken korrigiert werden (z.B. mit der Taste RUBOUT). Solche Tasten +anschläge werden dann allerdings auch gelernt, was aber bei der Benutzung der +Lernsequenzen keine Bedeutung hat. +4.2.8. Textabschnitte durch Markieren bearbeiten + +#free(1.0)# + #on("i")# + Oft ergibt sich die Notwendigkeit, mehrere Zeilen oder ganze Textpassagen zu + löschen oder zu verschieben. Hierbei hilft die Taste #ib#MARK#ie#, mit der man #ib#Texte + markieren#ie# (also kennzeichnen) kann. Die so markierten Texte können dann auf + verschiedene Weisen als Ganzes verarbeitet werden. + #goalpage("ESC")# + + #free(1.0)# +<MARK> + +Durch Drücken der Taste MARK wird die #ib#Markierung#ie# eingeschaltet und - bei erneu +ter Betätigung - wieder ausgeschaltet. Der Anfang der Markierung wird "festgehal +ten" und man kann nun das Markierende durch die Positionierungstasten und die +HOP-Taste in Richtung auf das Dateiende verschieben, wobei die dazwischen lie +genden Zeichen markiert (in der Regel "schwarz auf weißem Grund" dargestellt) +werden. + + +<ESC> <RUBOUT> + +Ein so markierter Text kann mit #ib#ESC RUBOUT#ie# gelöscht werden. #ib#Markieren und +löschen#ie# mit ESC RUBOUT ist eine bequeme und sichere Löschmethode, da man +genau sieht, was gelöscht wird.#goalpage("ESC RUBOUT")# + + +<ESC> <RUBIN> +#goalpage("ESC RUBIN")# + +Der gelöschte Abschnitt ist aber nicht vollständig gelöscht, sondern er kann an ande +rer (oder an der gleichen) Stelle im Text durch #ib#ESC RUBIN#ie# wieder eingefügt werden. +Der vorsichtig gelöschte Text landet in einem #ib#Zwischenspeicher#ie# und kann bei Bedarf +mit #ib#ESC RUBIN#ie# wieder aufgerufen werden. Wird erneut vorsichtig gelöscht, so wird +der letzte Text des Zwischenspeichers überschrieben. Im Zwischenspeicher ist nur für +einen #on("u")#Text#off("u")# Platz. Auf diese Art kann ein Textabschnitt beliebiger Länge an eine +andere Stelle des Textes sicher, schnell und bequem verschoben werden. Zusätzlich +ist die nachträgliche Korrektur von fehlerhaften Löschungen möglich, weil der Text +wieder mit ESC RUBIN reproduziert werden kann. + +Mit eingeschalteter Markierung kann auch geschrieben werden. Das #ib#markierende +Schreiben#ie# ist eine besonders vorsichtige Art der Texterstellung, denn der Textein +schub bleibt erst durch Ausschalten der Markierung (MARK) wirklich bestehen. Er +kann wieder gelöscht (ESC RUBOUT) und an eine andere Stelle gebracht werden +(ESC RUBIN). Beim markierenden Schreiben wirkt RUBOUT immer auf das Zeichen +vor der Cursorposition. + +Hinweis: Positionierungen sind nur innerhalb der Markierung möglich. +#page# +4.2.9. Der Fenstereditor +#free(1.0)# + + #on("i")# + Oft ist es notwendig, mit mehreren Dateien gleichzeitig zu arbeiten, z.B. wenn aus + einer Datei etwas in eine andere kopiert werden muß, wenn Fehler durch die + Textkosmetik-Programme oder einen Compiler gefunden werden oder wenn man + kurz etwas in einer anderen Datei nachschauen will. Zu diesem Zweck bietet der + Editor die Möglichkeit, zwei (oder mehr) Dateien zur gleichen Zeit zu bearbeiten. #off("i")# + + +#free(1.0)# +Der Editor ermöglicht dem Benutzer wie durch ein Fenster auf den zu bearbeitenden +Text zu schauen. Es ist in diesem Zusammenhang nur natürlich, daß man bei der +Bearbeitung eines Textes sich die Möglichkeit wünscht, weitere Texte gleichzeitig +ansehen zu können. Dies kann notwendig sein, um zu vergleichen, Fehler zu entdek +ken oder Textteile aus einem Fenster in ein anderes zu übertragen. + +Um ein neues Editor-Fenster zu "öffnen", betätigt man im Editor + +<ESC> <e> + +Betätigt man ESC e ungefähr in der Mitte des Bildschirms, hat man das Fenster auf +die neue Datei in der unteren Hälfte des Bildschirms und die "alte" Datei in der +oberen Bildschirmhälfte. Zunächst wird der Dateiname erfragt. Nach dessen Eingabe +und dem Betätigen der 'CR' Taste wird ein Fenster auf eine andere Datei eröffnet. +Die obere linke Ecke des Fensters befindet sich an der aktuellen Cursor-Position. +Dabei darf sich der Cursor nicht zu sehr am rechten oder unteren Rand befinden, weil +das Fenster sonst zu klein würde. In diesem "Fenster" kann man dann genauso +arbeiten wie im "normalen" Editor. + + +Mit der Tastenfolge + +<ESC> <w> + +wechselt man von einem Fenster (zyklisch) in das benachbarte. Es gibt eine Hier +archie zwischen den Fenstern in der Reihenfolge, in der eines im anderen einge +richtet worden ist. Gibt man + +<ESC> <q> + +in einem Fenster, so verschwindet dieses und alle darin eingeschachtelten Fenster, +und man befindet sich im übergeordneten Fenster. + +Wir schilderten zuvor, daß man mit ESC RUBOUT und ESC RUBIN Texte verschie +ben und löschen kann. Zwischen Dateien im Fenstereditor geht dies folgendermaßen: + +Durch + +<ESC> <p> oder <ESC> <d> + +schreibt man einen markierten Teil in eine temporäre Datei (einen Zwischenspeicher); +durch ESC p wird ein markierter Text aus der Ursprungsdatei entfernt und in einen +Zwischenspeicher geschrieben. Im Gegensatz dazu wird er durch ESC d kopiert. +Durch + +<ESC> <g> + +fügt man ihn in eine andere (oder dieselbe) Datei ein. Im Unterschied zu ESC RUBIN +wird die temporäre Datei dadurch nicht entleert. + +Die Funktionen ESC d und ESC g leisten auf schnellere Weise dasselbe wie die +Kommandos 'PUT ""' und 'GET ""'. +#page# +4.2.10. Die wichtigsten vorbelegten Tasten +#free(1.0)# + + #on ("i")# + Lernsequenzen und Kommandos (d.h. ELAN-Programme) können Tasten zuge + ordnet werden. Da einige Funktionen häufig benötigt werden, sind diese stan + dardmäßig bestimmten Tasten zugeordnet. #off("i")# + + + +#free(1.0)# +#ib#ESC q#ie# Verlassen des Editors bzw. der eingeschachtelten Fenster. + +#ib#ESC e#ie# Weiteres Editorfenster einschalten. + +#ib#ESC n#ie# Notizbuch "aufschlagen". + +#ib#ESC v#ie# Dateifenster auf ganzen Bildschirm vergrößern + bzw. Bildschirm rekonstruieren (eingeschachteltes Fenster verlas + sen). + +#ib#ESC w#ie# Dateiwechsel beim Fenstereditor. + +#ib#ESC f#ie# Nochmalige Ausführung des letzten Kommandos. + +#ib#ESC b#ie# Das Fenster wird auf den linken Rand der aktuellen (ggf. verscho + benen) Zeile gesetzt. + +ESC > Zum nächsten Wortanfang. + +ESC < Zum vorherigen Wortanfang. + +#ib#ESC 1#ie# Zum Anfang der Datei. + +#ib#ESC 9#ie# Zum Ende der Datei. +#page# +Lernen + + +#ib#ESC HOP#ie# Lernen einschalten. + +#ib#ESC HOP taste#ie# Lernen ausschalten und Lernsequenz auf 'taste' legen. + +#ib#ESC HOP HOP#ie# Gelerntes vergessen. Bedingung ist, daß man die Lernsequenz in + der Task löscht, in der man sie hat lernen lassen. +#free(1.0)# +Operationen auf Markierungen + +#free(1.0)# +#ib#ESC RUBOUT#ie# Markiertes "vorsichtig" löschen. + +#ib#ESC RUBIN#ie# Vorsichtig mit ESC RUBOUT Gelöschtes einfügen. + +#ib#ESC p#ie# Markiertes löschen und in die Notiz-Datei schreiben. Kann mit ESC + g an anderer Stelle reproduziert werden. + +#ib#ESC d#ie# Duplizieren: + Markiertes in die Notiz-Datei kopieren (PUT ""), anschließend die + Markierung abschalten. Kann mit ESC g beliebig oft reproduziert + werden. + +#ib#ESC g#ie# MIT ESC p gelöschten oder mit ESC d duplizierten Text an aktuelle + Cursor-Stelle schreiben, d.h. Notiz-Datei an aktueller Stelle einfü + gen (GET ""). +#free(1.0)# +#on("b")#Zeichen schreiben#u#1#e# +#off("b")# +#foot# +1) Diese Tasten sind standardmäßig so vorbelegt wie hier aufgeführt, sie könne aber +von Benutzern und in Anwenderprogrammen geändert werden. +#end# +#free(0.5)# +#ib#ESC a#ie# Schreibt ein ä. +#ib#ESC A#ie# Schreibt ein Ä. +#ib#ESC o#ie# Schreibt ein ö. +#ib#ESC O#ie# Schreibt ein Ö. +#ib#ESC u#ie# Schreibt ein ü. +#ib#ESC U#ie# Schreibt ein Ü. +#ib#ESC s#ie# Schreibt ein ß. +#ib#ESC (#ie# Schreibt eine [. +#ib#ESC )#ie# Schreibt eine ]. +#ib#ESC <#ie# Schreibt eine {. +#ib#ESC >#ie# Schreibt eine }. +#ib#ESC \##ie# Schreibt ein \#, das auch gedruckt werden kann. +#ib#ESC #ie# Schreibt einen (geschützten) Trennstrich, siehe Textverarbeitung. +#ib#ESC k#ie# Schreibt ein (geschütztes) "k", siehe Textverarbeitung. +#ib#ESC blank#ie# Schreibt ein (geschütztes) Leerzeichen, siehe Textverarbeitung. +#free(1.0)# +Kommando auf Taste legen + +#free(1.0)# +#ib#ESC ESC#ie# Kommandodialog einschalten + +#ib#ESC ! taste#ie# Im Kommandodialog: + Geschriebenes Kommando auf Taste legen. + +#ib#ESC ? taste#ie# Im Kommandodialog: + Auf 'taste' gelegtes Kommando zum Editieren anzeigen. + +#ib#ESC k#ie# Im Kommandodialog: + Das zuletzt editierte Kommando (einzeilige ELAN-Programm) + anzeigen. + +Eine ausführliche Beschreibung des Kommandodialogs finden Sie im folgenden Kapi +tel. +4.3. Die wichtigsten Editor-Kommandos +#goalpage("ESC")# +#free(0.5)# + +#ib(9)#4.3.1. Der #ib#Kommandodialog#ie##ie(9)# + +#free(1.0)# + #on("i")# + Einige Operationen kann man nur mühselig mit den bis jetzt beschriebenen Tasten + durchführen. Z.B. ist es sehr zeitaufwendig, eine bestimmte Textstelle zu finden. + Andere Operationen sind mit den im vorigen Kapitel beschriebenen Tasten über + haupt nicht möglich, wie etwa die Zeilenbreite einzustellen oder Programme aufzu + rufen, die die zu editierende Datei verarbeiten. Solche Operationen werden durch + Kommandos ermöglicht, die man auf Editorebene geben kann. #off("i")# + + +#free(1.0)# +Um Kommandos an den Editor geben zu können, schalten wir in den #ib#Kommando +zustand#ie#. + +<ESC> <ESC> + +Durch zweimaliges Betätigen von ESC erfolgt #on("u")#im Editor#off("u")# die Aufforderung + +____________________________________________________________________________ + ................. dateiname ...................... Zeile 4 + +Mit der ESC-Taste ist es möglich, den Kommandodialog +gib kommando : + +____________________________________________________________________________ + + + +Auf dem Bildschirm erscheint eine #ib#Kommandozeile#ie#, in der der Benutzer +Kommandos schreiben kann. Durch Betätigen der Taste 'CR' wird das +Kommando ausgeführt. +#page# + + +#ib(9)#4.3.2. Zeile und #ib#Textstelle anwählen#ie##ie(9)# +#free(1.0)# + #on("i")# + Auf der Kommandoebene des Editors können Sie Kommandos erteilen, um an eine + beliebige Stelle in der Datei zu positionieren.#off ("i")# + +#free(1.0)# +Sie haben einen (größeren) Text erstellt und stehen nun vor dem Problem, für die +Korrektur die entsprechenden Textstellen aufzufinden. + +#on("u")#Beispiel:#off("u")# + +Bei der Durchsicht eines Ausdrucks Ihres Textes stellen Sie fest, daß Sie sich ver +schrieben haben. Anstelle von "diese Zeichen" haben Sie "diese Ziichen" geschrie +ben. Um diese Textstelle anzuwählen, gehen Sie wie folgt vor: Sie positionieren an +den Beginn der Datei und betätigen die Tastenfolge + + +<ESC> <ESC> + + +Auf dem Bildschirm ersceint: + +____________________________________________________________________________ + +gib kommando: + +____________________________________________________________________________ + + +Sie schreiben nun die zu suchende Textstelle auf: + +____________________________________________________________________________ + +gib kommando: "diese Ziichen" + +____________________________________________________________________________ + + +Durch die Angabe eines TEXTes in Anführungsstrichen wird nach dem eingeschlosse +nen TEXT 'diese Ziichen' ab der aktuellen Cursor-Position gesucht. Wird 'diese +Ziichen' gefunden, bleibt der Cursor auf dem gesuchten Text stehen. Andernfalls steht +der Cursor am Ende der letzten Zeile der Datei. + +Eine andere Möglichkeit, an eine entferntere Stelle im Text zu kommen, ist die fol +gende: + +<ESC> <ESC> + + +Es erscheint auf dem Bildschirm: + +____________________________________________________________________________ + +gib kommando: + +____________________________________________________________________________ + + +Sie geben nun die Textzeile an, die Sie suchen: + +____________________________________________________________________________ + +gib kommando: 134 + +____________________________________________________________________________ + + +Durch dieses Kommando wird auf die 134. Zeile positioniert. +#page# + +#ib(9)#4.3.3. #ib#Suchen und Ersetzen#ie##ie(9)# +#free(1.0)# + #on("i")# + Auf der Kommandoebene des Editors können Sie wie auf der Monitor-Ebene + beliebige Kommandos geben. Diese können Sie zu (ELAN-) Programmen ver + knüpfen. Zur Erstellung dieser Programme editieren Sie wie gewohnt in der Kom + mandozeile. Für das Positionieren, Suchen und Ersetzen innerhalb Ihres ELAN- + Programms stehen Ihnen Kommandos zur Verfügung. Beliebige ELAN-Prog + ramme sind zulässig.#off ("i")# + +#free(1.0)# +Die #ib#Kommandozeile#ie# kann wie eine "normale" Textzeile editiert werden (Positionieren, +Überschreiben, Einfügen, Löschen und Markieren). Bevor ein Programm eine Aus +gabe erzeugt oder fehlerhafte Kommandos Fehlermeldungen hervorrufen, wird der +Cursor in die linke obere Ecke positioniert. Um die Meldungen festzuhalten, sollte das +#ib#Kommando 'pause'#ie# folgen. Diese Meldungen werden dann in der ersten Zeile des +Bildschirms angezeigt. Danach ist man wieder im Editor und kann wie gewohnt +arbeiten. + +Kommandos werden durch ein Semikolon voneinander getrennt. + +#on("u")#Beispiel:#off("u")# + +____________________________________________________________________________ + +gib kommando: T1; "Geschäftsführung";fetch("Lieferanten",archive) + +____________________________________________________________________________ + + +Ihr ELAN-Programm besteht aus zwei Kommandos: zunächst positionieren Sie in die +erste Zeile und suchen ab dort nach dem Wort "Geschäftsführung". dann lesen Sie +die Datei "Lieferanten" von der Diskette in den Arbeitsspeicher. + +Die beiden beschriebenen Kommandos (Text bzw. eine Zeile anwählen) sind Spezial +kommandos und können in dieser Form nicht durch ein Semikolon mit anderen Kom +mandos kombiniert werden. Deshalb gibt es für sie eine ELAN-Form, die es erlaubt, +sie mit anderen Kommandos zusammen zu verwenden: + +a) Einen Text ab der aktuellen Cursor-Position suchen (D ist eine Abkürzung für + '#ib#DOWN#ie#'): + +____________________________________________________________________________ + +gib kommando: "diese Zeichen" + +____________________________________________________________________________ + +(* Kurzform *) + + +____________________________________________________________________________ + +gib kommando: #ib#D#ie# "diese Zeichen" + +____________________________________________________________________________ + +(* Allgemeine Version *) + + + +b) Auf eine Zeile positionieren (#ib#T#ie# ist eine Abkürzung für '#ib#TO LINE#ie#'): + +____________________________________________________________________________ + +gib kommando: 127 + +____________________________________________________________________________ + + +(* Kurzform *) + + +____________________________________________________________________________ + +gib kommando: T 127 + +____________________________________________________________________________ + + +(* Allgemeine Version *) + + +Mehrere Kommandos können in der Kommandozeile angegeben werden. Die einzel +nen Kommandos müssen in diesem Fall mit ';' voneinander getrennt werden. + +#on("u")#Beispiel:#off("u")# + +<ESC> <ESC> + +schaltet in den Kommandomodus + +____________________________________________________________________________ + +gib kommando: T 1; D "noch Zeichen" + +____________________________________________________________________________ + + + +Diese zwei Kommandos werden nacheinander ausgeführt. Zuerst wird auf die erste +Zeile positioniert und dann (von der ersten Zeile ab) nach 'noch Zeichen' gesucht. +Damit ist es möglich, die Datei nicht nur ab der aktuellen Zeile zu durchsuchen, +sondern die gesamte Datei. Soll nicht in Richtung auf das Dateiende, sondern in +Richtung auf den Dateianfang (also nach "oben") gesucht werden, kann man das +#ib#U-Kommando#ie# (Abkürzung für #ib#UP#ie#) verwenden: + +<ESC> <ESC> + +____________________________________________________________________________ + +gib kommando: U "noch ein Text" + +____________________________________________________________________________ + + + +Ein weiteres Kommando ist das #ib#C-Kommando#ie# (Abkürzung für '#ib#CHANGE#ie#'), mit +welchem man einen TEXT sucht und diesen dann ersetzt. + +#on("u")#Beispiel:#off("u")# + +<ESC> <ESC> + +____________________________________________________________________________ + +gib kommando: "alte Zeichen" C "neue Zeichen" + +____________________________________________________________________________ + + +Ab der aktuellen Cursor-Position wird nach 'alte Zeichen' gesucht. Wird der TEXT +gefunden, wird er durch 'neue Zeichen' ersetzt. Der Cursor befindet sich in diesem +Fall hinter dem ersetzten TEXT. Wird 'alte Zeichen' dagegen nicht in der Datei gefun +den, befindet sich der Cursor (wie beim erfolglosen Suchen mit D) am Ende der +letzten Zeile der Datei. + +Wie alle anderen Kommandos kann auch das C-Kommando mit anderen Komman +dos verbunden werden. + +#on("u")#Beispiel:#off("u")# + +<ESC> <ESC> + +____________________________________________________________________________ + +gib kommando: #ib#T#ie# 500; "Schreibfelher" #ib#C#ie# "Schreibfehler" + +____________________________________________________________________________ + + + +Hier wird ab der 500. Zeile der Datei nach 'Schreibfelher' gesucht und ggf. ersetzt. +Soll ein TEXT nicht nur einmal, sondern bei jedem Auftreten ersetzt werden, benutzt +man das #ib#CA-Kommando#ie# (Abkürzung für #ib#CHANGE ALL#ie#): + +<ESC> <ESC> + +____________________________________________________________________________ + +gib kommando: "dieser alte Text" CA "dieser neue Text" + +____________________________________________________________________________ + + +Dadurch wird 'dieser alte Text' bei jedem Auftreten ab der aktuellen Cursor-Position +durch 'dieser neue Text' ersetzt. +Pattern Matcher +#free(1.0)# + + + Der #ib#Pattern Matcher#ie# ist ein Werkzeug zur #ib#Mustererkennung#ie#. Er dient zur + Beschreibung von Texten, die in verschiedenen Ausprägungen auftreten können. + Zum Suchen oder Ersetzen wird nicht ein Text fester Gestalt vorgegeben, sondern + eine Beschreibung der gesuchten Struktur. + + +#free(1.0)# + +Häufig werden Sie #ib#Texte suchen#ie# oder ersetzen wollen, die in einigen Varianten inner +halb eines umfangreicheren Textes auftauchen können. + +Beispiel: Gesucht wird 'unser' in verschiedenen Zusammenstellungen, also auch + 'unsere' oder 'unserem'. Alle Textstellen, die diesem Muster entsprechen, + können in #on("u")#einem#off("u")# Suchverfahren gefunden werden, indem das Muster, + welches diese Texte beschreibt, für die Suche benutzt wird: + +____________________________________________________________________________ +Suchen nach Begriffen deren genaue Ausprägung unbekannt ist. +gib kommando:D(" unser" + any + " ") + + +____________________________________________________________________________ + + + + Leseweise: + + Suche 'unser', gefolgt beliebigen Zeichen plus einem Leerzeichen, oder + auch nur einem Leerzeichen. + + + Dieses Suchkommando liefert Treffer bei 'unser', 'unsere', 'unseres' usw.. + +#free(1.0)# +Wie baut man ein Pattern ? + +#free(1.0)# + + + Texte werden durch ihr Konstruktionsmuster aus bekannten und unbekannten + Teilen beschrieben + +#free(1.0)# + +Ein Text, der in seiner konkreten Form nicht bekannt ist, dessen Aufbau jedoch durch +ein Muster beschrieben werden kann, besteht aus Teilen, die als: + + - bekannte Texte + - unbekannte Texte + +bezeichnet werden und die mit dem Operatoren: + + '+' Zusammensetzen + 'OR' Alternative + +kombiniert werden können. + + +Ein bekannter Text ist z.B. ein Stück eines gesuchten Textes, das als fest vorgegeben +betrachtet werden kann, wie etwa der Wortstamm 'unser' in dem obigen Beispiel. Wie +gewohnt wird ein solcher bekannter Text, in Anführungsstriche gesetzt, als TEXT +CONST "text" notiert. + +Demgegenüber ist ein unbekannter Text von nicht näher zu beschreibender Gestalt. +Das Muster, welches einen unbekannten Text beschreibt, steht für irgendeinen einer +Vielzahl von Texten, die diesem Muster entsprechen. + +Mit der Prozedur: + + any + +wird das Muster für einen beliebigen Text geliefert. + +Im einleitenden Beispiel ist der Wortstamm bekannt, das Teilwort 'unser' kann also im +'Klartext' angegeben werden. Die Endungen sind je nach dem Zusammenhang in dem +das gesuchte Wort auftritt verschieden, also zunächst unbekannt. +Ein solcher unbekannter Text kann entweder durch Aufzählung der möglichen +Alternativen seiner Erscheinung beschrieben werden oder durch die Prozedur 'any'. + + + (text + ("er" OR "es" OR "em" OR ..... ) + + alternative Verknüpfung durch OR + + + ("text" + any + .... ) + + additive Verknüpfung durch + + +Grundsätzlich ist zu beachten, daß der Suchvorgang des Pattern Matcher Zeichenket +ten untersucht und nicht etwa einzelne Worte und stets nach dem längstmöglichen +Muster gesucht wird! + +Ein schlecht beschriebener Suchtext kostet somit nicht nur viel Rechenzeit, sondern +liefert auch unerwünschte Ergebnisse: z.B. sollte der Artikel 'der' mit einem führenden +Leerzeichen als " der" gesucht werden, da andernfalls jedes Wort, das die Silbe 'der' +enthält, einen Treffer in der Suche ergibt. + +Da die Suche nach unbekannten Texten viele unerwünschte Ergebnisse liefern +könnte, kann die Prozedur any in zweifacher Weise eingeschränkt werden: + + +D(" d" + any (2) ) + + Die Länge der unbekannten Textes wird vorgegeben, indem die Anzahl + der Zeichen aus denen der Text besteht, angegeben wird. Die Angabe + steht in Klammern hinter 'any'. (In diesem Beispiel genau 2 Zeichen). + + +D(" d" + any ("aeirs")) + + + Das Alphabet, aus dem der unbekannte Text bestehen darf, wird angege + ben. (In diesem Beispiel darf der Text der einen Treffer ergibt nur aus + den Zeichen 'a', 'e', 'i', 'r', 's' bestehen, z.B: der, die, das oder auch + dies.) + + +D(" d" + any (2,"aeirs") + + + Auch die Kombination der Beschränkungen ist möglich. (Jetzt liefern nur + noch 'der', 'die','das' etc. Treffer). + + +#on("b")# +ACHTUNG: Das Zeichen '*' nimmt eine Sonderstellung ein, da es als Abkürzung für + 'any' verwandt werden kann. Soll dieses Zeichen im Text gesucht oder + ersetzt werden, müssen Sie statt "*" 'any(1,"*")' schreiben. + + Weitere Informationen zum Pattern Matcher finden Sie im EUMEL- + Handbuch zur Programmierung. +#off("b")# +#free(1.0)# +4.3.4. Kommandos auf Tasten legen + +#free(1.0)# + #on("i")# + Oft benutzte Kommandos können auf Tasten gelegt werden. Damit ist es möglich, + den Editor auf Ihre speziellen Bedürfnisse einzurichten.#off ("i")# + +#free(1.0)# + +Oft benutzte Kommandos können mit der Drei-Tastenfolge + +<ESC> <!> <'taste'> auf eine Taste gelegt werden. + +#on("u")#Beispiel:#off("u")# + + +<ESC> <ESC> (* die Kommandozeile erscheint *) + +____________________________________________________________________________ + +gib kommando: save (SOME myself) + +____________________________________________________________________________ + + +<ESC> <!> <s> (* das Kommando 'save (SOME myself)' ist + nun auf die Taste 's' gelegt *) + + +Wird nun die Taste 's' gedrückt, erscheint das Zeichen 's' auf dem Bildschirm. Mit +#ib#ESC s#ie# wird das 'save'-Kommando ausgeführt. Natürlich können auch kompliziertere +Kommandos auf Tasten gelegt werden. + +Möchten Sie ein Kommando, das auf eine Taste gelegt wurde, verändern, drücken Sie +im Kommandodialog (!) die Drei-Tastenfolge + +<ESC> <?> <'taste'> + + +#on("u")#Beispiel:#off("u")# + +<ESC> <ESC> (* in den Kommandodialog gehen *) + + +<ESC> <?> <s> (* es erscheint nun: 'save (SOME myself)' *) + +Dieses Kommando kann nun z.B. verändert und ausgeführt (durch 'CR') oder +wiederum auf die gleiche oder eine andere Taste gelegt werden (durch #ib#ESC ! 'taste'#ie#). + +Im Editor kann das letzte im Kommandodialog eingegebene Kommando durch '#ib#ESC f#ie#' +wiederholt werden. +#page# + +#ib(9)#4.3.5. Texte aus anderen Dateien benutzen#ie(9)# +#free(1.0)# + #on("i")# + Manchmal ist es notwendig, einen Text in eine andere Datei zu schreiben (z.B. + wenn man diesen Text noch einmal verwenden will) oder einen Text einer anderen + Datei in den zu bearbeitenden Text einzufügen. Die '#ib#GET#ie#'- und '#ib#PUT#ie#'-Kom + mandos bieten die Möglichkeit, Texte zwischen Dateien auszutauschen (vergl. + auch den Abschnitt über paralleles Editieren).#off ("i")# + +#free(1.0)# +Mit dem #ib#'GET'-Kommando#ie# können wir Texte aus einer anderen Datei an die aktuelle +Schreibposition kopieren. + +____________________________________________________________________________ + +gib kommando: GET "absender" + +____________________________________________________________________________ + +holt den Text 'absender'. Wenn also des öfteren Briefe geschrieben werden, braucht +man sich den Absender nur einmalig in die Datei 'absender' zu schreiben und kann +diesen mit dem Kommando 'GET' (was man auf eine Taste legen kann) u.U. mehr +mals an verschiedenen Stellen in die Datei einfügen. + +Mit dem #ib#'PUT'-Kommando#ie# können wir zuvor markierte Textteile in eine Datei schrei +ben. + +____________________________________________________________________________ + +gib kommando: PUT "adressen" + +____________________________________________________________________________ + + +schreibt einen markierten Text in die Datei 'adressen'. 'adressen' wird ggf. eingerich +tet. Ist die Datei 'adressen' bereits vorhanden, so wird erfragt, ob die Datei gelöscht +werden kann, um den markierten Text aufzunehmen (überschreiben). Andernfalls wird +der markierte Text an den bereits vorhandenen Text in 'adressen' angefügt. Es ist +somit durch mehrmaliges Markieren und das 'PUT'-Kommando möglich, Texte aus +einer Datei zu sammeln und in eine neue Datei zu geben. +#page# + +#ib(9)#4.3.6. #ib#Breitere Zeilen#ie# bearbeiten#ie(9)##goalpage("margin")# +#free(1.0)# + #on("i")# + Der Editor ist auf eine Zeilenbreite von 77 Zeichen eingestellt. Oft ist es notwen + dig, mit einer anderen Zeilenbreite zu schreiben, welche man mit dem #ib#'limit'- + Kommando#ie# einstellen kann. Aber auch die Positionierung innerhalb einer Zeile + wird dadurch anders, weil breitere Zeilen nicht als Ganzes auf den Bildschirm + passen. In diesem Fall wird "#ib#gerollt#ie#".#off ("i")# + +#free(1.0)# +Eine andere Zeilenbreite stellt man durch 'limit' ein. Beachten Sie, daß die eingestell +te Zeilenbreite für die gesamte Datei gilt. + +#on("u")#Beispiel:#off("u")# + +____________________________________________________________________________ + +gib kommando: limit (180) + +____________________________________________________________________________ + + +Nun können Sie wie gewohnt schreiben. Allerdings wird die aktuelle Zeile, in der man +sich befindet, nicht wie gewohnt am Bildschirmende umgebrochen, sondern erst an +der Spalte 180, sofern sie nicht vorher durch die 'CR'-Taste beendet wird. Wird über +das rechte Bildschirmende hinaus geschrieben, bleibt die Cursor-Position am Ende +des Bildschirms erhalten, aber die Zeile wird beim weiteren Schreiben nach links +verschoben, "rollt" also nach links (der Anfang der Zeile verschwindet scheinbar nach +links). + +Mit der Positionierung verhält es sich ähnlich. Wird mit RECHTS über den rechten +Bildschirmrand positioniert, wird die Zeile ebenfalls gerollt. #ib#HOP RECHTS#ie# bewirkt ein +#ib#Blättern#ie# innerhalb einer einzelnen Zeile nach rechts. Analog verläuft es bei verscho +bener Zeile, wenn nach links (LINKS bzw. #ib#HOP LINKS#ie#) positioniert wird. + +Beim Schreiben von Tabellen kann es sinnvoll sein, das Fenster vorübergehend auf +eine andere Anfangsposition (als 1) einzustellen. Das kann mit dem +#ib#'margin'-Kommando#ie# erfolgen. + +#on("u")#Beispiel:#off("u")# + +____________________________________________________________________________ + +gib kommando:#ib#margin#ie# (50) + +____________________________________________________________________________ + + +Das Editorfenster zeigt nun einen Ausschnitt aus der Datei, beginnend ab der Spalte +50. In der Titelzeile wird "M50" angezeigt. +#page# + +#ib(9)#4.3.7. Die wichtigsten Kommandos#ie(9)# +#free(1.0)# + #on("i")# + Einige Kommandos sind speziell für die Textverarbeitung im Editor programmiert. + Die wichtigsten werden hier vorgestellt.#off ("i")# + +#free(1.0)# +any + TEXT PROC any + liefert ein Muster beliebiger Gestalt und Länge (also auch der Länge 0) für + Suchoperationen. + + + " ir" + any + "was" + + +any + TEXT PROC any (TEXT CONST alphabet) + liefert den längstmöglichen Text, der aus den in 'alphabet' angegebenen Zeichen + besteht. + + + any ("1234567890") (* suche Zahlen *) + + +any + TEXT PROC any (INT CONST laenge) + liefert ein Muster beliebiger Gestalt und der Länge 'laenge'. + + + " d" + any (2) + + +any + TEXT PROC any (INT CONST laenge, TEXT CONST alphabet) + liefert ein Muster der Länge 'laenge', das nur aus Zeichen aus + 'alphabet' besteht. + + + " d" + any (2,"erias") + + + +C + OP C (TEXT CONST muster, ersatz) + Ab der aktuellen Positon wird 'muster' in Richtung Dateiende gesucht und durch + 'ersatz' ersetzt. Der Cursor steht danach hinter 'ersatz'. + + + "alt" C "neu" + + + +CA + OP CA (TEXT CONST muster, ersatz) + Arbeitet ab der aktuellen Position wie C. Die Aktion wird jedoch bis zum Erreichen + des Dateiendes wiederholt. Nach Ausführung ist somit jedes 'muster' durch + 'ersatz' ersetzt. Der Cursor steht danach hinter dem letzten Zeichen der Datei. + + + "alt" CA "neu" + + + + +D + OP D (INT CONST n) + Positioniert das Fenster n Zeilen vorwärts in Richtung auf das Dateiende. + + + D 50 + + + OP D (TEXT CONST muster) + Sucht 'muster' vorwärts in Richtung auf das Dateiende. Die Suche beginnt direkt + hinter der aktuellen Cursor-Position. Wird 'muster' nicht gefunden, steht der + Cursor hinter dem letzten Zeichen der Datei. Wird 'muster' gefunden, steht der + Cursor direkt auf dem ersten Zeichen von 'muster'. + + + D "muster" + + + +GET + OP GET (TEXT CONST dateiname) + Kopiert den Inhalt der Datei mit dem angegebenen Namen vor die aktuelle + Cursor-Position. Ist ein Teil der Quelldatei markiert, wird nur der markierte Teil + kopiert. + + + GET "quelldatei" + + + OP G (TEXT CONST dateiname) + Wie GET. + + +limit + OP limit (INT CONST limit) + Setzt die rechte Schreibgrenze auf 'limit'. + + + limit (50) + + + +margin + PROC margin (INT CONST anfang) + Alle Zeilen erscheinen erst ab Spalte 'anfang' im Sichtfenster. + + + margin (50) + + + +OR + TEXT OP OR (TEXT CONST texteins,textzwei) + Liefert ein Muster, wenn texteins oder textzwei gefunden wird. Die Reihenfolge + spielt keine Rolle. + + + D ("Geschäfts" + ("führung" OR "leitung")) + + + +PUT + OP PUT (TEXT CONST dateiname) + Richtet eine Datei mit dem angegebenen Namen ein und kopiert den markierten + Textabschnitt in diese. + + + PUT ("meine hilfsdatei") + + + OP P (TEXT CONST dateiname) + Zweck: Wie PUT. + + +T + OP T (INT CONST n) + Positioniert auf die Zeile 'n'. + + + T 999 + + + +type + PROC type (TEXT CONST zeichenkette) + + Fügt 'zeichenkette' in die aktuelle Position der editierten Datei ein. Besonders + nützlich in Verbindung mit der Prozedur 'code', um nicht auf der Tastatur enthal + tene Zeichen in den Text zu bringen. + + + type(code(200)) + + + +U + OP U (INT CONST n) + Positioniert das Fenster n Zeilen rückwärts in Richtung auf den Dateianfang. + + + U 100 + + + OP U (TEXT CONST muster) + Sucht 'muster' rückwärts in Richtung auf den Dateianfang. Die Suche beginnt + links neben der aktuellen Cursor-Position. Vergl. D + + + U "muster" + + +word wrap + PROC word wrap (BOOL CONST an) + Schaltet den automatischen Wortumbruch an (voreingestellt) bzw. aus. + + + word wrap (true) (* angeschaltet *) + word wrap (false) (* ausgeschaltet *) + +4.4. Fehlersituationen und Abhilfe + +#free(1.0)# + #on("i")# + Von Zeit zu Zeit werden Sie als Anfänger in Arbeitssituationen geraten, wo Sie + nicht weiterwissen. Hier sind einige Tips, wie Sie sich behelfen können.#off ("i")# + +#free(1.0)# + +Wie helfe ich mir, wenn... + + +... nach + continue("taskname") + + der Monitor #on("u")#nicht#off("u")# + + gib kommando: + + sagt, sondern "schweigt"? + +=> Sie haben die Task bei der letzten Benutzung nicht mit dem Kommando + 'break' verlassen (evtl. haben Sie SV betätigt?). Sie sind jetzt im Editor, sehen + aber den zuletzt bearbeiteten Textausschnitt nicht. Betätigen Sie die Tasten + + ESC b + + und der Text wird neu auf dem Bildschirm ausgegeben. +#free(1.0)# +... im Editor kein Tastendruck mehr akzeptiert wird? + +=> Sie haben irrtümlich die STOP-Taste (auch oft als CTRL a realisiert, abhängig + vom Terminal), d.h. Anhalten der Bildschirmausgabe betätigt. + + Drücken Sie die WEITER-Taste (= CTRL c, d.h. Bildschirmausgabe fortfüh + ren). Alle Tastenanschläge, die zwischenzeitlich zu keiner Reaktion führten, + werden jetzt ausgegeben. + + Je nach Tastatur können STOP und WEITER auch auf anderen Tasten liegen. #free(1.0)# +... der Lernmodus über lange Zeit (ungewollt) eingeschaltet war? + +=> a) Sie merken plötzlich, daß über einen unbestimmt langen Zeitraum alle Ihre + Tastenanschläge gelernt wurden (zu erkennen an der "LEARN"-Anzeige in + der Überschriftzeile). + + #on("u")#Was ist zu tun?#off("u")# + + Mit dem Kommando + + ESC HOP HOP + + vergessen Sie alles Gelernte und schalten den Lernmodus aus. + +=> b) Sie beenden den Editor mit ESC q und die Meldung + +____________________________________________________________________________ + + WARNUNG: Lernmodus nicht ausgeschaltet + +____________________________________________________________________________ + + + + erscheint auf dem Bildschirm. + + #on("u")#Was ist zu tun?#off("u")# + + Sie können mit + + ESC HOP HOP + + das Gelernte sofort vergessen. +#free(1.0)# +... Sie zu viele Absatzzeichen in Ihrem Text gesetzt haben und diese entfernen + müssen? + +=> Sie positionieren in die Zeile, in der die Absatzmarke gelöscht werden soll. Sie + betätigen dann die TAB-Taste, um hinter den Text zu positionieren, dann die + RUBOUT-Taste. Wenn Sie jetzt die Zeile mit den Cursor-Tasten nach oben + oder unter verlassen, verschwindet die Absatzmarkierung. +#free(1.0)# +... nach + + save("dateiname","vatertask") + + das Betriebssystem nicht mehr reagiert? + +=> Sie haben die Vater-Task nicht mit dem Kommando 'global manager' in + jenem Prozeß zum Empfang von Daten aus anderen Prozessen vorbereitet. +#free(1.0)# +... Sie in Ihrer Task das Archive mit dem Kommando + + archive("archivname") + + anmelden wollen und das System Ihnen die Meldung + + "Fehler: Archive wird von Task "bib" benutzt" + + zustellt? + +=> Es gibt zwei Möglichkeiten: + a) Ein anderer Benutzer benötigt das Archiv-Laufwerk in diesem Moment. Sie + müssen warten, bis er seine Arbeit beendet hat. + + b) Ein anderer Benutzer (oder Sie selbst) hat vergessen, mit dem Kommando + + release(archive) + + das Archiv in jener Task freizugeben. Falls Sie es selbst waren, holen Sie + das nach. Ansonsten kann das Archiv-Kommando wieder erfolgreich gege + ben werden, wenn fünf Minuten nicht auf das Archiv + zugegriffen wurde. #free(1.0)# +... Sie eine (scheinbare oder echte) Endlosschleife auf einer Taste (z.B. Taste "x") + gelernt haben und diese (versehentlich oder bewußt) durch 'ESC x' aktivieren? + +=> Wie immer, wenn Sie eine endlos laufende Task beenden wollen, gelangen Sie + mit der SV-Taste in den Supervisor-Modus und mit dem Kommando + + 'halt' + + beenden Sie die Endlosschleife. + + Mit + + ESC HOP HOP x + + wird danach das Gelernte 'vergessen'! +#free(1.0)# +... Sie Ihre Datei verlassen wollen und + + 'ESC q' + + (scheinbar) nicht funktioniert? + +=> Sie haben versehentlich den Feststeller für Großbuchstaben (SHIFT LOCK / + CAPS LOCK) betätigt und ESC q zeigt keine Wirkung (wie auch andere Tasten + kombinationen mit Großbuchstaben evtl. keine Wirkung zeigen). + diff --git a/doc/user-manual/1.8.7/doc/benutzerhandbuch.5a b/doc/user-manual/1.8.7/doc/benutzerhandbuch.5a new file mode 100644 index 0000000..1e907f0 --- /dev/null +++ b/doc/user-manual/1.8.7/doc/benutzerhandbuch.5a @@ -0,0 +1,1446 @@ +#start(5.0,1.5)##pagenr("%",1)##setcount(1)##block##pageblock##count per page# +#headeven# +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# + EUMEL-Benutzerhandbuch +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#headodd# +#lpos(0.0)##cpos(5.5)##rpos(11.0)##fillchar(" ")# +#table# + Teil 5: Textkosmetik und Druck +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#bottomeven# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +5 - % GMD +#tableend##clearpos# +#end# +#bottomodd# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +GMD 5 - % +#tableend##clearpos# +#end# + +#ib(9)#TEIL 5: Textkosmetik und Druck#ie(9)# +#free(1.0)# +#ib(9)#5.0. Vorwort#ie(9)# + +#free(1.0)# +Die #ib#Textkosmetik-Programme#ie# des EUMEL-Systems bieten Ihnen eine einfach zu +erlernende und zu bedienende Möglichkeit, Texte für den Druck zu gestalten (pro +grammtechnisch: #ib#formatieren#ie#) und zu manipulieren. + +Die Textkosmetik-Programme bearbeiten Ihre Dateien, die durch den EUMEL-Editor +erstellt wurden. Darum sollten Sie sich zuerst mit dem EUMEL-Editor vertraut +machen. + +Die Programme sind so konstruiert, daß die meisten Aufgaben durch in den Text +eingefügte Anweisungen gesteuert werden. Solche Angaben für die Textkosmetik und +den EUMEL-Drucker nennen wir im folgenden kurz #on("b")##on("i")#'Anweisung' #off("b")##off("i")#. Die Form der +#ib#Anweisung#ie# ist für die Textkosmetik und den EUMEL-Drucker gleich und entspricht +der ELAN-Syntax. Beachten Sie den #ib#Unterschied zwischen einem Kommando und +einer Text-Anweisung#ie#: während ein Kommando direkt ausgeführt wird, wird eine in +den Text eingebettete Anweisung erst nach dem Aufruf von Textkosmetik- und +Drucker-Programmen wirksam. + +Die Wirkungsweise der Textkosmetik-Anweisungen ist leicht zu erlernen und kann +vor allen Dingen stufenweise erfolgen. Deshalb ein guter Rat für Anfänger: Lesen Sie +diesen Teil des Benutzer-Handbuchs erst oberflächlich, so daß Sie ungefähr +Bescheid wissen, welche Möglichkeiten die Textkosmetik-Programme bieten. Dann +können Sie diejenigen Teile der Textkosmetik auswählen und bei Bedarf anwenden, +die Sie für Ihre spezielle Anwendung benötigen. +#page# + +#ib(9)#5.1. Einführung in die Benutzung der + #ib#Textkosmetik#ie##ie(9)# + +#free(1.0)# + #on("i")# + In diesem Kapitel erhalten Sie eine Übersicht über die verfügbaren Programme der + Textkosmetik. + +#off("i")# +#free(1.3)# +Schreiben, Gestalten und Drucken von Texten + +#free(1.0)# + #on("i")# + Im EUMEL-System unterscheiden wir zwischen drei Stufen einer Textbehand + lung:#on("b")# Erstellung, Gestaltung#off("b")# und #on("b")#Druck#off("b")#. Die Trennung in verschiedene Arbeits + stufen hat den Vorteil, daß Sie sich zu einem Zeitpunkt nur auf einen Arbeitsschritt + konzentrieren müssen. + #off("i")# +#free(1.3)# +Texterstellung bzw. Textbearbeitung + +#free(1.0)# +Das Schreiben von Texten wird mit Hilfe des Editors erledigt. In dieser Stufe der +Texterstellung können Sie sich ausschließlich auf das Schreiben und die inhaltliche +Korrektheit Ihres Textes konzentrieren. Wird ein Text ohne Anweisungen gedruckt, +dann erscheint er so, wie er mit dem Editor geschrieben wurde. Bei der Erstellung +des Textes können Sie aber auch bereits Textkosmetik-Anweisungen in den Text +einfügen. + +____________________________________________________________________________ + + Es ist wichtig, daß Sie das Kapitel 'Editor' + \#on("b")\#sehr\#off("b")\# gründlich lesen. + +____________________________________________________________________________ + + +Druckbild: + +Es ist wichtig, daß Sie das Kapitel 'Editor' +#on("b")#sehr#off("b")# gründlich lesen. + + +Sie sollten Texte im 'Fließtext'-Modus erstellen, d.h., dann werden Worte, die über +Zeilengrenzen gehen, ohne Silbentrennung vom Editor in die nächste Zeile gebracht. +#free(1.5)# +Textkosmetik bzw. Textgestaltung + +#free(1.0)# +Nachdem Sie einen Text geschrieben haben, können Sie ihn mit #ib#Textkosmetik- +Programme#ie#n gestalten, ohne ihn inhaltlich zu verändern. Dies kann auch vor oder +nach eventuellen Korrekturen erfolgen. Die Textkosmetik bietet zur Zeit vier Pro +gramme an, die je nach Bedarf eingesetzt werden können: + +--- #on("b")#'#ib#lineform'/'autoform#ie#'#off("b")# formatiert einen Text zeilenweise und vollzieht eine + Silbentrennung. Weiterhin erlaubt 'lineform'/'autoform' die Verwendung unter + schiedlicher Schrifttypen und Schrifthöhen. + +--- #on("b")#'#ib#pageform#ie#'/'#ib#autopageform#ie#'#off("b")# gestattet die Formatierung eines Textes in Seiten + (drucktechnisch: "Seitenumbruch"). Dabei berücksichtigt 'pageform'/'auto + pageform' unterschiedliche Schrifthöhen. Es ist mit 'pageform'/ 'autopage + form' u.a. möglich, die Seiteneinteilung zu bestimmen, eine Seite in Spalten + zu formatieren ("Zeitungsformat"), Zeilen am Anfang bzw. Ende jeder Seite + einfügen zu lassen, eine Seitennumerierung (drucktechnisch: "Paginierung") + zu erhalten und Fußnoten zu gestalten. + +--- #on("b")#'#ib#index#ie#'#off("b")# erlaubt die Erstellung von Stichwort- und Inhaltsverzeichnissen aus + einer mit 'pageform'/'autopageform' bearbeiteten Datei. + +--- #on("b")#'#ib#outline#ie#'#off("b")# holt aus einer Datei alle mit Index-Anweisung gekennzeichneten + Überschriften und Stichworte. Es erstellt somit eine Übersicht bzw. Kurz + fassung eines Textes. +#free(1.5)# +Drucken +#free(1.0)# +Zu jedem Zeitpunkt der Texterstellung kann gedruckt werden. Der EUMEL-Drucker +beachtet die gleichen Anweisungen wie die Textkosmetik-Programme und noch +einige zusätzliche, die nur für die Druckaufbereitung notwendig sind. Spezielle Druck +leistungen, wie z.B. verschiedenartige Schrifttypen, können nur auf besonderen +Druckern erzeugt werden. Verfügt ein Drucker nicht über eine bestimmte Hardware- +Eigenschaft, wird die von ihm geforderte Leistung ignoriert. Somit ist es möglich, +Probedrucke für Korrekturen etc. auch auf preiswerten Druckern herzustellen. (siehe +hierzu 5.6.1.) +#page# + + +-------------------------+ + l Text-Eingabe l + l l + +->-+ Editor +->-+ + l l l l + l l erstellt Datei l l + l +------------+------------+ l + l l l + l V l + l +------------+------------+ l + l l lineform l l + +-<-+ +->-+ + l l formatiert Zeilen l l + l +------------+------------+ l + l l l + l V l + l +------------+------------+ l + l l outline l l +--------------------------+ + l l l l l E U M E L - Drucker l + +-<-+ gibt Übersicht bzw. +->-+ ->--+ l + l l Kurzfassung eines Textesl l l Probe- bzw. l + l l l l l endgültiger Druck l + l l Dateiname + '.outline' l l +--------------------------+ + l +------------+------------+ l + l l l + l V l + l +------------+------------+ l + l l pageform l l + l l l l + +-<-+ formatiert Seiten +->-+ + l l l l + l l Druckdatei l l + l l Dateiname + ".p" l l + l +------------+------------+ l + l l l + l V l + l +------------+------------+ l + l l index l l + l l l l + l l erstellt Stichwort- und l l + +-<-+ Inhaltsverzeichnisse +->-+ + l l + l Indexdatei(en) l + l Dateiname + "i<nummer>" l + +-------------------------+ + #page# + +#ib(9)#5.1.1. Anweisungen für die Textkosmetik + und den Drucker#ie(9)# +#free(1.0)# + #on("i")# + In diesem Abschnitt wird beschrieben, wie Sie #ib#Anweisungen#ie# für die Textkosme + tik- und Druckprogramme in einen Text einfügen können. Beachten Sie, daß jede + Anweisung von '\#'-Zeichen eingeschlossen werden muß. Benötigen Sie das + '\#'-Zeichen in Ihrem Text, müssen Sie es mit 'ESC' schreiben. + #off("i")# +#free(1.0)# +Es gibt zwei Arten von Anweisungen: + +a) Anweisungen, die das gesamte Aussehen eines Manuskripts verändern (#on("i")##ib#"layout- + Anweisungen"#ie##off("i")#). Zu diesen Anweisungen gehören die Anweisungen \#limit (...)\# + (Einstellen der Zeilenbreite), \#linefeed (...)\# (Zeilenabstand), \#page\# (neue Seite) + usw. Diese Anweisungen gelten erst ab der nächsten Zeile und Sie sollten sie + daher in eine extra Zeile zwischen den Text stellen. + +____________________________________________________________________________ + +\#type ("trium8")\#\#limit (11.0)\# +\#start(5.0,1.5)\# +\#pagelength(17.4)\#\#pagenr("%",148)\#\#setcount(1)\# +\#block\#\#pageblock\# +\#count per page\# +\#headeven\# +\#lpos(0.0)\#\#cpos(5.5)\#\#rpos(11.0)\# +\#table\# + EUMEL-Benutzerhandbuch +\#fillchar(" ")\# +\#on("u")\# \#off("u")\# +\#table end\#\#clear pos\# + +\#end\# +\#headodd\# +\#lpos(0.0)\#\#cpos(5.5)\#\#rpos(11.0)\#\#fillchar(" ")\# +\#table\# + Teil 5: Textkosmetik und Druck +\#fillchar(" ")\# +\#on("u")\# \#off("u")\# +\#table end\#\#clear pos\# + +\#end\# + +____________________________________________________________________________ + + + Das Druckbild (das Ergebnis der Anweisungen) sehen Sie im vorliegenden + Benutzerhandbuch. + + Anweisungen, die für den Gesamttext gelten sollen, müssen Sie an den Anfang + der Datei stellen (noch vor \#head\#). + +b) Anweisungen, die unmittelbar auf den nachfolgenden Text wirken sollen, wie z.B. + \#type\# (Schrifttyp), \#on\#/\#off\# (Modifikationen wie unterstreichen oder fett druk + ken), \#ib\#/\#ie\# (Markierung von Stichworten) usw. Solche Anweisungen werden + unmittelbar beachtet und können überall auf einer Zeile stehen (wie in dem fol + genden Beispiel). + +____________________________________________________________________________ + + \#on("underline")\#Ausnahmen\#off("underline")\# werden bei der + Beschreibung der Anweisungen speziell erwähnt. + +____________________________________________________________________________ + + +Druckbild: + + #on("u")#Ausnahmen#off("u")# werden bei der + Beschreibung der Anweisungen speziell erwähnt. + +____________________________________________________________________________ + +Weitere Beispiele für Textkosmetik-Anweisungen: + +____________________________________________________________________________ + +\#page\# +\#free(3.0)\# +\#type("quadrato")\# + +____________________________________________________________________________ + + +Diese Anweisungen entsprechen - wie alle Kommandos im EUMEL-System - der +ELAN-Syntax (u.a. müssen sie klein geschrieben werden; Parameter in runden +Klammern; mehrere Parameter werden durch Kommata getrennt; #ib#TEXT-Parameter#ie# in +Anführungsstrichen; #ib#REAL-Parameter#ie# mit Dezimalpunkt usw.). Leerzeichen spielen +(außer in TEXT-Parametern) keine Rolle und können zur besseren Lesbarkeit belie +big verwendet werden. + +Die Zeichen, aus denen eine Anweisung besteht, werden bei der Formatierung einer +Zeile oder Seite nicht mitgezählt und vom EUMEL-Drucker nicht gedruckt. Eine +Zeile, die nur aus Anweisungen besteht, wird ebenso behandelt, auch wenn sie mit +<CR> abgeschlossen wird. +#page# +#on("b")# + +#ib(9)#5.1.2. #ib#Aufruf der Textkosmetik-Programme#ie##ie(9)# +#free(1.0)# + #on("i")# + In diesem Abschnitt wird beschrieben, wie Sie die #ib#Textkosmetik-Programme + aktivieren#ie# können. + #off("i")# +#free(1.0)# +Sie rufen die Textkosmetik-Programme durch Kommandos auf (d.h. in der 'gib +kommando'-Ebene). Sie geben ebenso wie zum Editieren den Namen des Pro +gramms und der Datei an.#goalpage("lineform")# + +____________________________________________________________________________ + + gib kommando: + lineform ("dateiname") + +____________________________________________________________________________ + + + oder: + autoform ("dateiname") + pageform ("dateiname") + autopageform ("dateiname") + outline ("dateiname") +#mark ("", "")# + index ("dateiname") + + + + +'lineform'/'autoform' können Sie auch vom EUMEL-Editor aus aufrufen. Zu diesem +Zweck markieren Sie den zu formatierenden Abschnitt der Datei und geben im +Kommando-Zustand ( <ESC> <ESC> drücken) 'lineform' bzw. 'autoform' (ohne Para +meter). +#mark ("", "")# + +Das Programm 'pageform'/'autopageform' erzeugt aus der Eingabedatei eine #ib#Druck +datei#ie#, die den Namen der angegebenen Eingabedatei mit dem Zusatz '.p' bekommt. + +____________________________________________________________________________ + + gib kommando: + pageform ("dateiname") + +____________________________________________________________________________ + + +Als Ergebnis erhalten Sie: "dateiname.p" + + + + +Das Programm 'index' kann nur eine Druckdatei bearbeiten: + +____________________________________________________________________________ + + gib kommando: + index ("dateiname.p") + +____________________________________________________________________________ + + +und erstellt die angeforderten Verzeichnisse in Dateien, die mit dem Zusatz +'.i<nummer>' gekennzeichnet werden. + +Beispiele: "dateiname.i1", "dateiname.i2" etc. + + + + +'#ib#outline#ie#' erstellt ebenfalls eine neue Datei. + +____________________________________________________________________________ + + gib kommando: + outline ("dateiname") + +____________________________________________________________________________ + + +führt zu dem Ergebnis: "dateiname.outline" #mark ("", "")# +#page# + +#ib(9)#5.1.3. Vorzeitiger #ib#Abbruch#ie# und + #ib#Fehlermeldungen#ie##ie(9)# +#free(1.0)# + #on("i")# + Sie können alle Textkosmetik-Programme vorzeitig abbrechen. Eventuelle + Fehlermeldungen werden Ihnen in einem Fenster angezeigt. + #off("i")# +#free(1.0)# +Durch die #ib#<ESC>#ie(1,"-Abbruch")##ib##ie(1,"Abbruch mit ESC")#-Taste oder die #ib#<SV> #ie#-Taste und das Supervisor-Kommando 'halt' +können Sie die Textkosmetik-Programme jederzeit vorzeitig abbrechen. Die Eingabe +datei steht Ihnen dann unverändert zur Verfügung. Ein #ib#vorzeitiger Abbruch#ie# kann +notwendig sein, wenn Sie ein Programm mit einer falschen Datei aufgerufen haben +oder zu viele Fehler gemeldet wurden. +#mark ("", "")# + +Alle Textkosmetik-Programme melden Fehler, wenn Sie Anweisungen falsch be +nutzen. Die Fehlermeldungen werden auf dem Bildschirm angezeigt. Bei Beendigung +eines Programms wird - falls Fehler entdeckt wurden - automatisch der #ib#Fenster- +Editor#ie# aufgerufen, wobei die Fehlermeldungen im unteren #ib#Fenster#ie# (das ist das #ib#Notiz +buch#ie#) angezeigt werden, während Ihnen im oberen Fenster die Eingabedatei zur +Korrektur angeboten wird. + +____________________________________________________________________________ + +.......................dateiname.................Zeile 1 + + \#corner1("-5.0")\#\#on("i")\# + Sie können alle Textkosmetik-Programme vorzeitig abbrechen. + Eventuelle Fehlermeldungen werden Ihnen in einem Fenster ange + zeigt. + \#box3("T","2","115.0")\#\#off("i")\# + #cursor(" ")# + +.......................notebook..................Zeile 1 +FEHLER Zeile 1: Unbekannte Anweisung (ignoriert): corner1("-5.0") + >>> Bitte Korrigieren +FEHLER Zeile 5: Unbekannte Anweisung (ignoriert): + box3("T","2","115.0") + >>> Bitte Korrigieren + +____________________________________________________________________________ + + + + + +Um von der Eingabedatei zum Notizbuch - und umgekehrt - zu wechseln, betätigen +Sie <ESC> <w>. +#page# + +#ib(9)#5.2. #ib#Lineform/Autoform#ie##ie(9)# +#free(1.0)# + #on("i")# + Die Programme '#ib(1, "ff")#lineform#ie#' oder '#ib(1, "ff")#autoform#ie#' formatieren einen Text zeilenweise (ggf. + mit Silbentrennung) unter Berücksichtigung von Schrifttyp und Zeilenbreite. + #off("i")# +#free(1.0)# +Zur #ib#Zeilenformatierung#ie# werden Ihnen zwei Programme (Kommandos) angeboten, die +sich nur in ihrem interaktiven Charakter unterscheiden (Behandlung von Silben +trennungen): + +---- #on("b")##ib#autoform#ie##off("b")#: + Zeilenformatierung mit automatischer #ib#Silbentrennung#ie#. Sie sollten 'autoform' + nur bei Texten einsetzen, in denen einige wenige Trennfehler nicht von + großer Bedeutung sind, z.B. bei Probedrucken. + +---- #on("b")##ib#lineform#ie##off("b")#: + Zeilenformatierung mit Silbentrennung "per Hand", wobei (nach deutschen + Trennregeln) ein sinnvoller Trennvorschlag gemacht wird. Die Trennstelle + kann interaktiv soweit verschoben werden, wie das zu trennende Wort noch + auf die Zeile paßt. + + +'lineform'/'autoform' hat im wesentlichen vier Aufgaben: + +---- #ib#Auffüllen von Zeilen#ie#: + 'lineform'/'autoform' kann besonders gut nach Korrekturen eingesetzt wer + den, bei denen - nach Einfügungen oder Löschungen - nicht vollständige + oder zu lange Zeilen in der Datei stehenbleiben können. + +---- Erstellen von Zeilen mit unterschiedlichen Schrifttypen: + Werden in einer Datei mehrere Schriftarten (\#type\#-Anweisung) verwendet, + berechnet 'lineform'/'autoform' nach der eingestellten Zeilenbreite die Anzahl + der Zeichen, die auf eine Zeile passen. + +---- Bearbeitung unterschiedlicher Zeilenbreiten: + Manchmal ist es notwendig, die Zeilenbreite zu verändern (\#limit\#- + Anweisung). Dies wird von 'autoform'/'lineform' berücksichtigt. + +---- Silbentrennung: + Automatische ('autoform') und interaktive Silbentrennung ('lineform'). + + +'lineform'/'autoform' akzeptiert als Eingabe eine Datei und verändert diese. Dafür wird +eine (interne) Zwischendatei benötigt. Deshalb müssen Sie darauf achten, daß noch +ausreichend Platz auf dem System ist, der jedoch nur zwischenzeitlich für den Forma +tierungsschritt benötigt wird. + +'lineform' und auch 'pageform' sind auf den ersten Schrifttyp der Fonttabelle, auf eine +Zeilenbreite von 16.0 und eine Seitenhöhe von 25.0 initialisiert. Sind die ersten An +weisungen, die das verändern könnten, fehlerhaft, so bleiben diese Werte (wie auch +sonst bei ignorierten Anweisungen) erhalten. + +'lineform'/'autoform'fragt nach dem Kommando an, mit welchem #ib#Schrifttyp#ie# und mit +welcher #ib#Zeilenbreite#ie# die Datei formatiert werden soll. Dabei erscheinen zuerst die +voreingestellten Anweisungen. Beispiel: + +____________________________________________________________________________ + +LINEFORM (für ... Zeilen): dateiname + +Bitte Schrifttyp: micro +Zeilenbreite (in cm): 16.0 + + +____________________________________________________________________________ + + + +Diese Anweisungen können Sie jetzt durch Ihre gewünschten Anweisungen ersetzen. +Diese Informationen werden von 'autoform'/'lineform' in Form von \#limit\#- und +\#type\#-Anweisungen in der Datei vermerkt, so daß die Anfragen bei weiteren +Datei-Bearbeitungen entfallen. + +Bei Zeilen, die länger als die angegebene Zeilenbreite sind, werden diejenigen Worte, +die über die Zeilenbreite hinausgehen, in die nächste Zeile umgebrochen. Kürzere +Zeilen werden aus der nachfolgenden Zeile bis zur Zeilenbreite aufgefüllt. Worte +werden jedoch nicht über Absatzgrenzen hinweg verschoben. Deshalb sollten Sie vor +Anwendung von 'lineform'/'autoform' darauf achten, daß Absätze richtig markiert +wurden. Fehlende Markierungen sollten Sie nachträglich einfügen ( <CR> am Ende +einer Zeile), andernfalls werden Zeilen über Absatzgrenzen zusammengezogen. Dies +ist besonders bei Tabellenzeilen unangenehm. + +#ib#Einrückungen#ie# (Leerzeichen am Anfang einer Zeile) werden von 'lineform'/'autoform' +ebenfalls bei der Formatierung von Zeilen eingehalten. +#page# + +#ib(9)#5.2.1. #ib#Zeilenweise formatieren#ie##ie(9)# +#free(1.0)# +#ib(9)#5.2.1.1. #ib#Interaktive Silbentrennung#ie##ie(9)# +#free(1.0)# + #on("i")# + 'lineform' trennt Silben interaktiv, d.h., es werden Ihnen von 'lineform' #ib#Trennungs + vorschläge#ie# gemacht, die Sie bestätigen oder ablehnen können. + #off("i")# +#free(1.0)# +Paßt ein Wort nicht mehr ganz auf eine Zeile, dann wird es zur interaktiven Tren +nung angeboten. Bei der Trennung werden Anweisungen innerhalb des Wortes ent +sprechend berücksichtigt. Die Umgebung dieses Wortes wird zur Erleichterung des +Trennvorgangs mit angezeigt. Das Trennzeichen erscheint an einer sinnvollen Stelle +im zu trennenden Wort. + +____________________________________________________________________________ + + Text vor dem Trennwort; das + Trenn-wort steht mit diesem Text in dieser Zeile + +____________________________________________________________________________ + + +Der Teil des zu trennenden Wortes, der noch auf die Zeile passen würde, wird mar +kiert angezeigt. Sie können das Trennzeichen mit Hilfe der Positionierungstasten +innerhalb des Trennbereichs verschieben. An der gewünschten Trennposition (der +Wortteil, der noch auf die Zeile kommen soll, steht links vom Trennstrich) kann die +<CR>-Taste betätigt werden. <CR> zeigt dem Programm 'lineform' an, daß an dieser +Stelle die Trennung erfolgen soll. 'lineform' fügt an den ersten Teil des Wortes das +"-"-Zeichen an und schreibt den abgetrennten Wortteil in die nächste Zeile. +#page# +Es stehen folgende #ib(1)#Operationen bei der interaktiven Trennung#ie# zur Verfügung: +#lpos(0.0)# #bpos(4.0, 11.0)# #table# + +#on("b")#Taste Bedeutung#off("b")# + +<CR> Trennen. + + +<<> Trennzeichen um ein Zeichen nach links verschieben. + + +<>> Trennstelle um ein Zeichen nach rechts verschieben. + + +<HOP> <<> Trennstelle vor das Wort setzen (das Wort wird an + dieser Position nicht getrennt). + + +<HOP> <>> Trennstelle an das Ende der Markierung setzen. + + +<BLANK> Trennzeichen wird von "-" auf " " umgeschaltet. + Dies kann verwendet werden, um Worte, die nicht + zusammengeschrieben werden sollen, beim Trenn + vorgang in zwei Worte aufzuspalten. + + +<-> Schaltet das Trennzeichen von Leerzeichen (" ") + wieder auf den Trennstrich ("-") um. + + +<ESC> Abbruch von 'lineform'/'autoform'. Die zu bearbeitende + Datei steht unverändert zur Verfügung. + +#tableend##clearpos# +#page# +Zwei Besonderheiten sind bei der interaktiven Trennung noch zu beachten: + + - Bei Worten mit Bindestrich wird die Trennstelle hinter dem Bindestrich als Leer + zeichen angezeigt. + + - Bei einer Trennposition zwischen den Zeichen "ck" wird das Zeichen "c" in ein + "k" umgewandelt. + + Beispiel: Druk-ker + +Sofern es für die Zeilenformatierung notwendig ist, macht die Prozedur 'lineform' +bereits erfolgte Trennungen rückgängig (das Trennzeichen wird entfernt und die +Wortteile werden wieder zusammengefügt), wenn sich das getrennte Wort (etwa durch +Korrekturen oder Veränderungen der Zeilenbreite) nicht mehr am Zeilenende befinden +sollte. + +Wenn Sie nicht Ihren Gesamttext mit 'lineform' bearbeiten möchten, haben Sie die +Möglichkeit, #ib#'lineform' auf einen Textausschnitt#ie# anzuwenden. Hierfür markieren Sie +den gewünschten Bereich, drücken <ESC> <ESC> und geben im Editor das Kommando +'lineform'. (siehe S. #topage("lineform")#) + +____________________________________________________________________________ + +...................dateiname................... Zeile 30 + + +Wenn Sie nicht Ihren Gesamttext mit 'lineform' bearbeiten +möchten/brauchen, haben Sie die Möglichkeit, +'lineform' für einen +Textausschnitt anzuwenden. Hierfür markieren Sie den gewünschten +Bereich, drücken 'ESC' 'ESC' und +geben das Kommando 'lineform'. + + +gib kommando:lineform + + +____________________________________________________________________________ + + +#page# + +#ib(9)#5.2.1.2. #ib#Automatische Silbentrennung#ie# mit + '#ib#autoform#ie#'#ie(9)# +#free(1.0)# + #on("i")# + 'autoform' arbeitet wie 'lineform', nur werden die Silbentrennungen automatisch + vorgenommen. + #off("i")# +#free(1.0)# +Ist eine Silbentrennung bei der Formatierung notwendig, übernimmt 'autoform' diese +automatisch. Die Trennungen werden in das #ib#Notizbuch#ie# eingetragen. Nach Beendigung +der Formatierung wird die bearbeitete Datei und das Notizbuch zur Kontrolle der +Silbentrennungen angezeigt. Die automatische Silbentrennung arbeitet mit einer hohen +#ib#Trenngüte#ie#; allerdings nur für deutsche Texte. Trotzdem kann es vorkommen, daß +einige Trennungen, insbesondere bei zusammengesetzten Worten, falsch vorgenom +men werden. In einem solchen Fall müssen Sie diese nachträglich mit dem Editor +korrigieren. (vgl. Sie dazu auch 5.8.4.) +#page# + +#ib(9)#5.2.2. #ib#Unterschiedliche Schriften#ie##ie(9)# +#free(1.0)# + #on("i")# + #ib#Unterschiedliche Schrifttypen#ie# (Schriftarten) können Sie mit der \#type ("schrift + name")\#-Anweisung anfordern. + #off("i")# +#free(1.0)# +Sie haben die Möglichkeit, mit 'lineform' verschiedenartige #ib#Schrifttypen#ie(1, ", unterschiedliche")# (kurz Typen +genannt) verarbeiten zu lassen. Jede Type hat eine bestimmte Höhe und jedes Zei +chen hat eine bestimmte Breite. Alle Typen werden auf einer Grundlinie gedruckt. + +Es gibt zwei Arten von Schriften: +bei#on("b")# #ib#äquidistanten Schriften#ie##off("b")# sind alle Zeichen gleich breit (wie bei einer Schreib +maschine).#on("b")# #ib#Proportionalschrift#ie##off("b")# findet man in gedruckten Büchern. Hier haben unter +schiedliche Zeichen auch unterschiedliche Breiten. Die Zeichen ".", "i", "!" sind z.B. +schmaler als die Zeichen "w", "o", "m" usw. + +Mit der Anweisung: + +____________________________________________________________________________ + + \#type ("schriftname")\# + +____________________________________________________________________________ + + +kann auf einen anderen Schrifttyp umgeschaltet werden (auch mehrmals innerhalb +einer Zeile). Diese Type gilt solange, bis wieder eine neue \#type ("schriftname")\#- +Anweisung gegeben wird. + +____________________________________________________________________________ + + + \#type ("micro")\#Jetzt schreiben wir mit einem + Schrifttyp, der 'micro' heißt. Und jetzt + \#type ("modern15")\#schalten wir auf eine an + dere Schriftart um. Nun \#type ("modern12")\# + möchten wir mit einer größeren Type schrei + ben. Um wieder zu unserem gewohnten Schrift + typ zu gelangen, schalten wir auf \#type + ("trium8")\# zurück. + + +____________________________________________________________________________ + + +Druckbild (ohne 'lineform'): + + +Jetzt schreiben wir mit einem +Schrifttyp, der 'micro' heißt. Und jetzt +schalten wir auf eine an +dere Schriftart um. Nun +möchten wir mit einer größeren Type schrei +ben. Um wieder zu unserem gewohnten Schrift +typ zu gelangen, schalten wir auf +\#type ("trium8")\# zurück. + + + +Welche Schriftarten Ihnen zur Verfügung stehen, hängt natürlich von dem verfügbaren +Drucker ab. Sie können die vorhandenen Schrifttypen mit dem Kommando 'list fonts' +erfragen. + +Schrifttypen können modifiziert, d.h. verändert, gedruckt werden (vergl. Sie dazu den +nächsten Abschnitt). Durch die Angabe einer \#type ("schriftname")\#-Anweisung +werden alle Modifikationen ausgeschaltet. +#page# +#goalpage("on")##goalpage("off")# + +#ib(9)#5.2.3. #ib#Veränderung des Schrifttyps#ie##ie(9)# +#free(1.0)# + #on("i")# + Mit der #ib#\#on ("..."\#-#ie(1,"Anweisung")# und #ib#\#off ("...")\#-Anweisung#ie# können Sie einen Schrifttyp in + seinem Aussehen verändern. Die Schrift wird zwar nicht gewechselt, aber ver + ändert gedruckt. Zur Zeit ist #ib##ie(1,"Unterstreichung")##ib# unterstrichen#ie#, #ib#fett#ie#, #ib#kursiv#ie# und der Druck von#ib# weiß auf + schwarz #ie#möglich (abhängig vom eingesetzten Drucker). + #off("i")# +#free(0.7)# +Die \#on\#/\#off\#-Anweisung wirkt wie ein Schalter, der die gewünschte #ib#Schrifttyp- +Modifikation#ie# ein- bzw. ausschaltet. Die Anweisung \#on\# schaltet die Modifikation ein, +\#off\# schaltet sie aus. + +____________________________________________________________________________ + + Das EUMEL-System ermöglicht es Ihnen, + + \#on ("italic")\#kursiv\#off ("italic")\# + \#on ("i")\# \#off ("i")\# + + und + + \#on ("underline")\#unterstrichen\#off ("underline")\# + \#on ("u")\# \#off ("u")\# + + und + + \#on ("bold")\#fett\#off ("bold")\# + \#on ("b")\# \#off ("b")\# + + und + + \#on ("reverse")\#invers (weiß auf schwarz)\#off ("reverse")\# + \#on ("r")\# \#off ("r")\# + + zu schreiben + +____________________________________________________________________________ +#page# +Druckbild: + + + Das EUMEL-System ermöglicht es Ihnen, + + #on("i")#kursiv#off("i")# + + und + + #on("underline")#unterstrichen#off("underline")# + + und + + #on("b")#fett#off("b")# + + und + + #on("reverse")#invers (weiß auf schwarz)#off("reverse")# + + zu schreiben. + + + +Dabei sollten Sie folgendes beachten: + +a) Ein \#type\#-Anweisung schaltet immer eine vorausgehende Modifikation aus, d.h. + ein Schrifttypwechsel macht eventuelle \#off ("b")\#-, \#off ("u")\#-, \#off ("i")\#- + und \#off ("r")\#-Anweisungen überflüssig. + +b) 'lineform'/'autoform' erzeugt eine Warnung, falls Sie vergessen haben, eine Modi + fikation auszuschalten. + +c) Nicht alle Drucker können die hier angegebenen Modifikationen auch drucken. + Welche Modifikationen gleichzeitig eingeschaltet werden können, ist ebenfalls + druckerabhängig. +#page# + +#ib(9)#5.2.4. #ib#Gesperrt schreiben#ie##ie(9)# +#free(1.0)# + #on("i")# + Die Silbentrennung an einem Leerzeichen verhindert man durch Verwendung des + geschützten Leerzeichens 'ESC' und 'Leertaste'. + #off("i")# +#free(1.0)# +Möchten Sie ein Wort g e s p e r r t schreiben, muß natürlich verhindert werden, daß +dieses Wort beim Formatieren getrennt wird. Andere Worte, wie z.B. in Formeln, +sollten ebenfalls zusammen auf eine Zeile geschrieben werden (z.B. 'sin (x)'). Dies +können Sie erreichen, indem Sie nicht das Leerzeichen zwischen die Zeichen schrei +ben, denn das Leerzeichen bedeutet für 'autoform'/'lineform' immer das Ende eines +Wortes. Stattdessen verwenden Sie <ESC> <Leertaste>. Das geschützte Leerzeichen +erscheint auf dem Bildschirm zur besseren Identifizierung invers dargestellt bzw. als +ein anderes Zeichen (abhängig von Ihrem Gerät). Beim Drucken wird jedoch wieder +ein Leerzeichen produziert. + + + +____________________________________________________________________________ + + g e s p e r r t + + +____________________________________________________________________________ + + +Druckbild: + + g e s p e r r t + + + +#page# +#goalpage("limit")# + +#ib(9)#5.2.5. #ib#Zeilenbreite einstellen#ie##ie(9)# +#free(1.0)# + #on("i")# + Mit der #ib#\#limit\#-Anweisung#ie# können Sie die Zeilenbreite einstellen. + #off("i")# +#free(1.0)# +Die \#limit\#-Anweisung gibt in cm an, wie breit die Zeile sein soll. Beachten Sie, daß +diese Anweisung nichts mit dem Editor-Kommando 'limit' zu tun hat. Dieses gibt an, +wie viele Zeichen eine Bildschirmzeile lang sein soll. + +Die Zeilenbreite wird zusammen mit dem Schrifttyp beim erstmaligen Aufruf von +'autoform'/'lineform' interaktiv erfragt und als \#limit\#-Anweisung (zusammen mit der +\#type\#-Anweisung) in die erste Zeile der Datei eingetragen. Sie kann in einer Datei +mehrmals verändert werden. + +Die neue Zeilenbreite gilt immer ab der #on("b")#nächsten#off("b")# Zeile, die der \#limit\#-Anweisung +folgt. Beachten Sie, daß Sie als Parameter in der \#limit\#-Anweisung eine Zahl mit +Dezimalpunkt und Nachkommastelle angeben müssen. + +____________________________________________________________________________ + + +\#limit(9.0)\# + Mit der \#limit\#-Anweisung können Sie Para + graphen in einem anderen Format leicht gestal + ten. Die rechte Schreibgrenze wird durch die + \#limit\#-Anweisung eingestellt, wobei Sie den + linken Rand durch eine entsprechende Ein + rückung gestalten können. +\#limit(11.0)\# + +____________________________________________________________________________ + + +Druckbild (mit 'lineform' bearbeitet): + + + Mit der \#limit\#-Anweisung können Sie Paragraphen in einem + anderen Format leicht gestalten. Die rechte Schreibgrenze + wird durch die \#limit\#-Anweisung eingestellt, wobei Sie den + linken Rand durch eine entsprechende Einrückung gestalten + können. + + + +Die folgende Tabelle gibt sinnvolle #ib#'limit'-Einstellungen#ie# für die am häufigsten ver +wendeten Papiergrößen an: + + + #on("b")#Format 'limit' Verbleibender + (Zeilenbreite) Rand#off("b")# + + DIN A4 16.0 cm je 2.50 cm + + DIN A5 12.0 cm je 1.42 cm + + DIN A4 quer 25.0 cm je 2.35 cm +#page# +#goalpage("einfache Tabellen")# + +#ib(9)#5.2.6. Einfache #ib#Tabellen#ie(1,", einfache")# und #ib#Aufzählungen#ie# + schreiben#ie(9)# +#free(1.0)# + #on("i")# + Aufzählungen und einfache #ib#Tabellen#ie(1, ", einfache")# werden automatisch richtig formatiert und + gedruckt, wenn Sie sich an einige einfache Regeln halten. + #off("i")# +#free(1.0)# +Verwenden Sie eine #ib#Proportionalschrift#ie# beim Tabellenschreiben, so sind die Spalten in +der Regel unterschiedlich breit, selbst wenn Sie eine gleiche Anzahl Zeichen in jeder +Spalte schreiben. Dies können Sie durch das Schreiben von einem "#ib#Doppelblank#ie#" +("#ib#Mehrfachblank#ie#") vermeiden; für kompliziertere Tabellen gibt es spezielle Tabellen +anweisungen. (siehe auch S. #topage("tabellenanw")#) + +____________________________________________________________________________ + + iiii ooooo + mmmm lllll + +____________________________________________________________________________ + + + +Druckbild: + + + iiii ooooo + mmmm lllll + +Erste und zweite Spalte stehen nicht untereinander. + + +Aber mit Doppelblanks: + +____________________________________________________________________________ + + iiii ooooo + mmmm lllll + +____________________________________________________________________________ + + +Druckbild: + + + iiii ooooo + mmmm lllll + +Erste und zweite Spalte stehen jetzt untereinander. + +Das Doppelblank dient 'lineform'/'autoform' und dem Drucker als Zeichen, daß die +Positionen speziell berechnet und beim Druck berücksichtigt werden müssen. Das gilt +nur nach einer Absatzzeile. In seltenen Fällen (insbesondere beim Einsatz von Schrift +typen, die in der Größe stark voneinander abweichen) kann es vorkommen, daß diese +Tabellenautomatik nicht funktioniert und Spalten übereinander gedruckt werden. In +solchen Fällen müssen Sie die Anzahl der trennenden Doppelblanks erhöhen. + +#on("b")##on("is")#Praktischer Tip:#off("is")##off("b")# +Beachten Sie, daß es für das Funktionieren der "#ib#Tabellenautomatik#ie#" erforderlich ist, +daß jede Tabellenzeile eine Absatzzeile ist. Man sollte diese Zeilen vor dem Druck +daraufhin überprüfen oder durch 'lineform'/'autoform' die Datei bearbeiten lassen. +Sollten durch die zeilenweise Formatierung einmal wegen fehlender Absatzkennzeich +nung zwei Zeilen zusammengezogen sein, können Sie diese leicht mit dem Editor +wieder "auseinanderbrechen" ( <HOP> <RUBIN> , <CR> und <HOP> <RUBIN> ). + + +Ähnliches gilt bei Aufzählungen. + +____________________________________________________________________________ + + 1) Das ist die erste Aufzählung. + Dieser Satz wird bündig gedruckt. + 2) Hier auch. + +____________________________________________________________________________ + + +Druckbild: + + + 1) Das ist die erste Aufzählung. + Dieser Satz wird bündig gedruckt. + 2) Hier auch. + + +Auch in solchen Fällen wird der gedruckte Text in der Regel richtig eingerückt. Die +#ib#Tabellenautomatik#ie# wirkt nur nach einem Absatz. Hier aber ein Beispiel für eine +typische Fehlersituation: + +____________________________________________________________________________ + + \#type("normal")\# + 1. Aufzählung + 2. Aufzählung + 3. Aufzählung + + \#type("fett")\#M1. Aufzählung + +____________________________________________________________________________ + + +Die Einrückbreite wird durch den Schrifttyp bestimmt, der vor der Zeile herrscht, und +den ganzen Absatz über beibehalten. + + +Druckbild: + + + 1. Aufzählung + 2. Aufzählung + 3. Aufzählung + + M1. Aufzählung + + +Das Blank zwischen 'M1.' und 'Aufzählung' reicht nicht aus, um eine Überschreibung +zu verhindern. Diesen Fehler können Sie umgehen, indem Sie die \#type\#-Anweisung +in eine gesonderte Zeile stellen. Richtig wäre folgendes (gewünschter Schrifttyp vor +die Zeile!): + +____________________________________________________________________________ + + \#type("trium8")\# + 1. Aufzählung + 2. Aufzählung + 3. Aufzählung + + \#type("triumb14")\# + M1. Aufzählung + +____________________________________________________________________________ + + + +Druckbild: + + + 1. Aufzählung + 2. Aufzählung + 3. Aufzählung + + + M1. Aufzählung + + +Die genauen Regeln sind etwas kompliziert, so daß sie hier nicht einzeln aufgeführt +werden (siehe S. 5-89#topage("block")# unter der Anweisung \#block\#). Treffen Sie auf einen der +seltenen Fälle, wo die Tabellenautomatik nicht funktioniert, können Sie immer noch +Tabellen-Anweisungen verwenden. +#mark ("", "")# +#page# + +#goalpage("tabellenanw")# +#ib(9)#5.2.6.1. #ib#Tabellenanweisungen#ie##ie(9)# +#free(1.0)# + Mit den Tabellenanweisungen der Textkosmetik können Sie auf einfache Art Tabel + len auch mit Porportionalschriften gestalten. +#free(1.0)# +Es ist sehr einfach, eine Tabelle in einer äquidistanten Schrift zu schreiben, denn +hierbei stimmt das Schriftbild auf dem Terminal weitgehend mit dem späteren Druck +überein. Bei einer äquidistanten Schrift ist jedes Zeichen gleich breit - Sie können +also "sehen", an welcher Zeilenposition eine neue Spalte beginnt. + +Etwas schwieriger sind Tabellen mit Proportionalschriften, da hier jedes Zeichen eine +unterschiedliche Breite hat. Sie können somit einer Spaltenbreite nicht direkt "an +sehen", wie breit sie beim Druck wirklich wird. "Einfache" Tabellen können Sie mit +dem Mehrfachblank gestalten (siehe S. 5-27). Bei komplizierteren Tabellen müssen +Sie die folgenden Tabellenanweisungen benutzen. + +Um eine Tabelle zu gestalten, gehen Sie folgendermaßen vor: + +- Definieren Sie die Spaltenpositionen der Tabelle mit den folgenden Anweisungen. + Für die Punkte bei den Anweisungen müssen Sie entsprechende Parameter + einsetzen. + +#goalpage("lpos")##goalpage("rpos")##goalpage("cpos")##goalpage("dpos")##goalpage("bpos")# +#goalpage("fillchar")# +____________________________________________________________________________ + + #ib#\#l pos#ie(1,"-Anweisung")# (...)\# (* linksbündig *) + #ib#\#r pos#ie(1,"-Anweisung")# (...)\# (* rechtsbündig *) + #ib#\#c pos#ie(1,"-Anweisung")# (...)\# (* zentrierend *) + #ib#\#d pos#ie(1,"-Anweisung")# (..., ...)\# (* zentrierend um eine Zeichenkette *) + #ib#\#b pos#ie(1,"-Anweisung")# (..., ...)\# (* Blocksatz in einer Spalte *) + #ib#\#fillchar#ie(1,"-Anweisung")# (...)\# (* Füllzeichen zwischen Spalten *) + +____________________________________________________________________________ + + + Die Zentrierung um eine Zeichenkette ist wie folgt zu verstehen: Die Spalte wird + bis zum Anfang der angegebenen Zeichenkette rechtsbündig und ab der Zeichen + kette linksbündig geschrieben. + +#goalpage("table")# +- Schreiben Sie dann die Tabelle. Sie muß von den Anweisungen + +____________________________________________________________________________ + + #ib#\#table\##ie(1,"-Anweisung")# + + + #ib#\#table end\##ie(1,"-Anweisung")# + +____________________________________________________________________________ + + + eingefaßt werden. Die Spalten in der Tabelle müssen Sie durch mindestens zwei + Leerzeichen voneinander trennen. Es müssen alle Spalten in einer Tabelle vor + handen sein. Soll einmal eine Spalte leer bleiben, müssen Sie für diese Spalte ein + #ib#geschütztes Leerzeichen#ie# verwenden. + +- Da die Spaltenpositionen erhalten bleiben (auch über die Anweisung \#table end\# + hinweg), sollten Sie direkt hinter dem Tabellenende die #ib#\#clear pos\#-Anweisung#ie# + geben. + +- Dann können Sie 'lineform'/'autoform' vornehmen. + +____________________________________________________________________________ + + + \#r pos (2.2)\#\#c pos (3.8)\#\#l pos (5.8)\#\#d pos (8.8, ".")\# + \#table\# + erste Spalte zweite Spalte dritte Spalte vierte Spalte + rechtsbündig zentriert linksbündig dezi.mal + 1234 1234 1234 12.34 + 12345 12345 12345 123.45 + 123456 123456 123456 1234.56 + \#table end\# \#clear pos\# + +____________________________________________________________________________ + + +Druckbild: + + + #r pos (2.2)##c pos (3.8)##l pos (5.8)##d pos (8.8, ".")# + #table# + erste Spalte zweite Spalte dritte Spalte vierte. Spalte + rechtsbündig zentriert linksbündig dezi.mal + 1234 1234 1234 12.34 + 12345 12345 12345 123.45 + 123456 123456 123456 1234.56 + #table end##clear pos# + + + +Solche Tabellen können Sie in \#head\#, \#bottom\# oder innerhalb von Fußnoten schrei +ben. Es ist jedoch nicht möglich, eine Fußnote innerhalb dieser Tabelle zu definieren. +Ausweg: Tabelle um die Fußnote aufspalten. +#page# + +#ib(9)#5.2.6.2. Einstellen der #ib#Tabellenpositionen#ie (1, ", Einstellen von")##ie(9)# +#free(0.7)# + #on("i")# + Mit den \#pos\#-Anweisungen können Sie eine bestimmte Position innerhalb der + Tabelle einstellen, zugleich aber auch bestimmen, wie die Spalte gedruckt werden + soll. #off("i")# + +#free(0.7)# +____________________________________________________________________________ + + \#l pos (5.0)\#\#r pos (10.0)\#\#d pos (15.0, ".")\# + +____________________________________________________________________________ + + +Die Anweisung oben stellt die erste Spalte der Tabelle auf 5 cm vom Rand ein (links +bündig). Die zweite Spalte endet 10 cm vom Rand, wobei diese Spalte rechtsbündig +geschrieben werden soll. Die dritte wird an die Position 15, zentriert um den Dezimal +punkt, gedruckt#u##count#)#e#.#foot# +#u##value#)#e# Spaltenposition < 0.0 und Spaltenposition > 'eingestelltes limit' sind nicht + erlaubt. +#end# + +Beachten Sie, daß ein "Überlappen" von Spalten erfolgen kann (in unserem Beispiel +kann die erste Spalte in die zweite hineinschreiben). 'lineform' bzw. 'autoform' meldet +bei Spalten-Überschreibungen einen entsprechenden Fehler. + +Für jede Spaltenposition nehmen Sie ein Element einer Zeile. Die Elemente müssen +Sie beim Schreiben im Editor durch mindestens zwei Leerzeichen voneinander tren +nen. Auf die erste Spaltenposition wird das erste Element gedruckt, auf die zweite +Position das zweite Element usw. Für das Drucken der Spalten wird der eingeschal +tete Schrifttyp mit möglicherweise einer Modifikation genommen. Der Schrifttyp und +die Modifikation können innerhalb der Tabelle geändert werden#u##count#)#e#.#foot# +#u##value#)#e# Die Zwischenräume zwischen den Spalten werden nicht modifiziert (also z.B. + nicht unterstrichen). +#end# + +Beachten Sie, daß die Tabellenpositionen so lange erhalten bleiben, bis sie explizit +gelöscht werden (\#clear pos\#-Anweisung, siehe S. 5-38). +#page# + +#ib(9)#5.2.6.3. #ib#Blocksatz innerhalb einer Spalte#ie##ie(9)# +#free(1.0)# + #on("i")# + Für Blocksatz innerhalb einer Spalte verwenden Sie die \#b pos (...)\#-Anweisung. + #off("i")# +#free(1.0)# +____________________________________________________________________________ + +\#l pos (0.0)\#\#b pos (2.2, 8.0)\#\#l pos (9.0)\# +\#table\# +1. Spalte Die mittlere Spalte wird bis zur Druck 3. Spalte +1. Spalte position '8.0' in Blocksatz gedruckt. Um 3. Spalte +1. Spalte in dieser Spalte einen Absatz zu bekom 3. Spalte +1. Spalte men, muß ein geschütztes Leerzeichen am 3. Spalte +1. Spalte Ende der Spalte stehen. #cursor(" ")# 3. Spalte +\#table end\# \#clear pos\# + +____________________________________________________________________________ + + + +Druckbild: + +#l pos (0.0)##b pos (2.2, 8.0)##l pos (9.0)# +#table# +1. Spalte Die mittlere Spalte wird bis zur Druck 3. Spalte +1. Spalte position '8.0' in Blocksatz gedruckt. Um 3. Spalte +1. Spalte in dieser Spalte einen Absatz zu bekom 3. Spalte +1. Spalte men, muß ein geschütztes Leerzeichen am 3. Spalte +1. Spalte Ende der Spalte stehen. 3. Spalte +#table end##clear pos# +#page# + +#ib(9)#5.2.6.4. #ib#Tabellenspalten auffüllen#ie# (#ib#Füllzeichen#ie#)#ie(9)# +#free(1.0)# + #on("i")# + Mit der \#fillchar\#-Anweisung können Sie Spaltenzwischenräume füllen. + #off("i")# +#free(1.0)# +Angenommen, Sie möchten eine Rechnung erstellen. Die Warenposten sollen links +bündig an der Druckposition '0.0' und die Beträge rechtsbündig an der Position '9.0' +gedruckt werden. Zwischen einem Warenposten und dem dazugehörigen Betrag sollen +entsprechend viele Punkte ('.') gedruckt werden. Das folgende Druckbild: + +#l pos (0.0)##r pos (9.0)##fillchar(".")# +#table# +30 Benutzerhandbücher 450,-DM +10 Systemhandbücher 150,-DM + +#table end##clear pos# + +wird mit + +____________________________________________________________________________ + + \#l pos (0.0)\#\#r pos (9.0)\#\#fillchar(".")\# + \#table\# + 30 Benutzerhandbücher 450,-DM + 10 Systemhandbücher 150,-DM + + \#table end\#\#clear pos\# + +____________________________________________________________________________ + + +erreicht. Mit der Anweisung \##ib#fillchar#ie#\# stellen Sie das/die #ib#Füllzeichen#ie# ein. Somit wer +den entsprechend viele Füllzeichen (anstatt der Leerzeichen) von dem Textende einer +Spalte bis zu dem Textanfang der nächsten Spalte gedruckt. Die Füllzeichen bleiben +so lange eingestellt, bis erneut die Anweisung \#fillchar\# gegeben wird. Insbesondere +bleibt das Füllzeichen - genauso wie auch die eingestellten Spaltenpositionen - +über das Tabellenende erhalten. Die Anweisung \#clear pos\# löscht - zusätzlich zu +den Tabellenpositionen - auch das eingestellte Füllzeichen (setzt das Zeichen auf ' ' +zurück). + +Beachten Sie, daß die Füllzeichen direkt gedruckt werden (also ohne Leerzeichen +zwischen dem Spaltentext und den Füllzeichen). Möchten Sie einen Zwischenraum +zwischen dem Spaltentext und den Füllzeichen haben, dann fügen Sie ein geschütz +tes Leerzeichen an den Spaltentext an oder setzen eins vor die nachfolgende Spalte. + +Die Anweisung \#fillchar\# gilt für Zwischenräume zwischen allen Spalten. Soll nur #on("i")#ein#off("i")# +Spaltenzwischenraum ausgefüllt werden, müssen Sie die \#fillchar\#-Anweisung in der +Tabelle entsprechend geben. + +____________________________________________________________________________ + + \#l pos (1.0)\#\#r pos (5.0)\#\#r pos (10.0)\# + \#table\# + 1\#fillchar(".")\# 3\#fillchar(" ")\# 4 + 2\#fillchar(".")\# 17\#fillchar(" ")\# 6 + \#table end\# + +____________________________________________________________________________ + + + +Druckbild: + +#l pos (1.0)##r pos (5.0)##r pos(10.0)# +#table# +1#fillchar(".")# 3#fillchar(" ")# 4 +2#fillchar(".")# 17#fillchar(" ")# 6 +#tableend##clear pos# + + + + +Eingeschaltete Modifikationen gelten in diesem Fall auch für die Spaltenzwischen +räume. +#page# + +#ib(9)#5.2.6.5. #ib#Tabellenpositionen löschen#ie##ie(9)# +#goalpage("clearpos")# +#free(1.0)# + #on("i")# + Mit der #ib#\#clear pos\#-Anweisung#ie# löschen Sie alle eingestellten Positionen. + #off("i")# +#free(1.0)# +Sollen gänzlich neue Positionen eingestellt werden, benutzen Sie die Anweisung + + +____________________________________________________________________________ + + \##ib#clear pos#ie(1,"-Anweisung")#\# + +____________________________________________________________________________ + + + +ohne Parameter. Sie löscht alle eingestellten Tabellenpositionen. Beachten Sie, daß +\#clear pos\# auch das Füllzeichen für die \#fillchar\#-Anweisung löscht (es wird wieder +ein ' ' voreingestellt). Eine einzelne Tabellenposition können Sie z.B. mit + + +____________________________________________________________________________ + + \#clear pos (10.0)\# + +____________________________________________________________________________ + + +löschen. +#mark ("","")# +#page# + +#goalpage("u")##goalpage("d")# +#ib(9)#5.2.7. #ib#Indizes#ie# und #ib#Exponenten#ie##ie(9)# + +#free(1.0)# + #on("i")# + Mit den Anweisungen #ib#\#u\##ie(1, "-Anweisung")#, #ib#\#d\##ie(1,"-Anweisung")# und #ib#\#e\##ie(1,"-Anweisung")# können Sie Exponenten und Indizes + schreiben. + #off("i")# +#free(1.0)# +Die Anweisung \#u\# (steht für 'up') schaltet auf eine Exponenten-Schreibweise um +und zwar so lange, bis die Anweisung \#e\# (steht für 'end') angetroffen wird. Dabei +wird automatisch auf den nächst kleineren Schrifttyp umgeschaltet (sofern vorhanden). + +____________________________________________________________________________ + + a\#u\#i,k\#e\# + +____________________________________________________________________________ + + +Druckbild: + + a#u#i,k#e# + + + +Die \#d\#-Anweisung ('d' steht für 'down') ist für Indizes gedacht und arbeitet analog +zur \#u\#-Anweisung. + +____________________________________________________________________________ + + a\#d\#i,k\#e\# + +____________________________________________________________________________ + + +Druckbild: + + a#d#i,k#e# + + +Die automatische Umschaltung auf den nächst kleineren Schrifttyp erfolgt nur, wenn +in der #ib#Fonttabelle#ie# ein nächst kleinerer Schrifttyp angegeben ist. Sonst wird der ein +gestellte Schrifttyp für den Exponenten beibehalten. + +Nach der \#e\#-Anweisung wird automatisch wieder der Schrifttyp eingestellt, der vor +der zugehörigen \#u\#-Anweisung galt. Die \#u\#- und \#e\#-Anweisungen bilden also +Klammern. Innerhalb einer Anweisung kann jede beliebige, sinnvolle Textkosmetik- +Anweisung stehen. Beachten Sie, daß Anweisungen innerhalb einer Klammer die +Zeilenhöhe nicht verändern sollen. Wenn Sie beispielsweise eine \#type\#-Anweisung +in eine Klammer schreiben, wird zwar der Index/Exponent in diesem Schrifttyp ge +druckt, aber der Drucker geht davon aus, daß die Zeilenhöhe nicht überschritten wird. +Deshalb ist es angeraten, nur einen kleineren Schrifttyp innerhalb eines Index/Expo +nenten zu verwenden. Wie bereits erwähnt, wird auch in diesem Beispiel nach dem +Klammerende auf den vorher eingestellten Schrifttyp zurückgestellt. + +Die Index/Exponenten-Klammern können auch geschachtelt werden. + +____________________________________________________________________________ + + a\#u\#um 1 hoch\#u\#noch 1 hoch\#e\#um 1 zurück\#e\# Grundlinie + +____________________________________________________________________________ + + +Druckbild: + + a#u#um 1 hoch#u#noch 1 hoch#e#um 1 zurück#e# Grundlinie + + + +Es gelten folgende #on("b")#Einschränkungen#off("b")#: + +1. Ein Exponent (Index) wird so positioniert, daß es in der Regel keine Überschrei + bung mit der vorhergehenden (nachfolgenden) Zeile gibt. + +2. Bei mehrfachen Exponenten oder Indizes oder bei Umschaltung auf einen anderen + Schrifttyp innerhalb eines Exponenten (Index) oder wenn nicht auf einen kleineren + Schrifttyp umgeschaltet werden kann, besteht die Möglichkeit, daß der Exponent + oder Index über die "normale" Zeile hinausragt. In diesem Fall kann es Über + schreibungen geben, die Sie mit der #ib#\#linefeed\#-Anweisung#ie# ausgleichen können. + +3. Eine Exponenten- oder Index-Klammer muß als Ganzes auf einer Zeile stehen. + +4. Gleichzeitige Exponenten- und Index-Ausdrücke, die übereinander stehen + sollen, sind zur Zeit mit den \#u\#/\#d\#-Anweisungen nicht möglich. Jedoch funk + tioniert folgendes: + + +____________________________________________________________________________ + + a\#u\#Exponent\#d\#Index des Exponenten\#e\#\#e\# + +____________________________________________________________________________ + + + + Druckbild: + + a#u#Exponent#d#Index des Exponenten#e##e# + + + +5. Doppelblanks spielen innerhalb einer solchen Klammer keine Rolle, wirken also + wie zwei "normale" Leerzeichen und nicht als implizite Positionierung. Innerhalb + einer solchen Klammer werden Blanks, sofern die Anweisung \#block\# gegeben + wurde, nicht verbreitert. + +6. Indizes oder Exponenten sollten nicht mit den Modifikationen \#underline\# und/oder + \#reverse\# zusammen verwendet werden, da z.B. ein Unterstreichen von Indizes + und Exponenten innerhalb einer unterstrichenen Zeile zu einem solchen Ergebnis + führt: + + + Druckbild: + + #on("u")#Indizes und Exponenten a#d#i,k#e# a#u#i,k#e# sollten nicht unterstrichen werden!#off("u")# +#page# + diff --git a/doc/user-manual/1.8.7/doc/benutzerhandbuch.5b b/doc/user-manual/1.8.7/doc/benutzerhandbuch.5b new file mode 100644 index 0000000..748e398 --- /dev/null +++ b/doc/user-manual/1.8.7/doc/benutzerhandbuch.5b @@ -0,0 +1,1632 @@ +#start(5.0,1.5)##pagenr("%",42)##setcount(1)##block##pageblock##count per page# +#headeven# +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# + EUMEL-Benutzerhandbuch +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#headodd# +#lpos(0.0)##cpos(5.5)##rpos(11.0)##fillchar(" ")# +#table# + Teil 5: Textkosmetik und Druck +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#bottomeven# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +5 - % GMD +#tableend##clearpos# +#end# +#bottomodd# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +GMD 5 - % +#tableend##clearpos# +#end# + +#ib(9)#5.3. #ib#Pageform#ie##ie(9)# +#free(1.0)# +#ib(9)#5.3.1. #ib#Seitenweise formatieren#ie##ie(9)# +#goalpage("pageform")##goalpage ("autopageform")# +#free(1.0)# + #on("i")# + 'pageform'/'autopageform' formatiert eine Datei seitenweise und erledigt Routine + arbeiten wie die Plazierung von Fußnoten, Seitennumerierung usw. + #off("i")# +#free(1.0)# + +Das Programm 'pageform' können Sie mit dem Kommando + +____________________________________________________________________________ + + gib kommando: + pageform ("dateiname") + +____________________________________________________________________________ + + + +aufrufen. 'pageform' erzeugt aus der Eingabedatei (z.B.: "dateiname") eine Druck +datei, deren Name durch ein angehängtes '.p' gebildet wird (z.B.: "dateiname.p"). + +Die von 'pageform' erzeugte Druckdatei besteht aus der Eingabedatei mit ggf. neu +eingefügten Zeilen. Die eingesetzten Zeilen stammen aus \#head\#-, \#bottom\#- oder +\#foot\#-Anweisungen. Dadurch erhöht sich die Zeilenanzahl der Datei. + +Sie können in Kopf- oder Fußzeilen Seitennummern aufnehmen. Diese Seiten +nummern werden von 'pageform'/'autopageform' bei Seitenwechseln automatisch +erhöht und an eine von Ihnen gekennzeichnete Stelle eingesetzt. Fußnoten können +auch durch Nummern gekennzeichnet werden. Querverweise sind ebenfalls möglich. +#page# +Nachdem 'pageform' eventuelle Kopf-, Fuß- und Fußnotenzeilen eingefügt hat, +berechnet es die Anzahl von Zeilen, die auf eine Seite passen, aus den Angaben für +Seitenlänge und Zeilenvorschub und aus der Höhe der eingestellten Schrifttypen +(\#type\#-Anweisung). Dann zeigt 'pageform' das errechnete Seitenende auf dem Bild +schirm an. Das Seitenende kann interaktiv verschoben werden, um es an eine ge +wünschte Stelle zu plazieren und es können Leerzeilen eingefügt/gelöscht werden, um +Seiten gleich lang zu machen. Zusätzlich können Sie Seiten in Spalten ("Zeitungs +druck") aufteilen und diese interaktiv formatieren. + +Bei mehreren Schrifttypen innerhalb einer Zeile wird als Zeilenhöhe automatisch die +des größten Schrifttyps genommen. Dabei müssen Sie bedenken, daß zu Beginn der +Zeile immer der Schrifttyp der vorherigen Zeile eingeschaltet ist. +#page# + +#ib(9)#5.3.1.1. #ib#Automatische Seitenformatierung#ie(9)##ie# +#free(1.0)# + + #on("i")# + 'autopageform' arbeitet wie 'pageform', jedoch werden die Seitenenden automa + tisch plaziert. + #off("i")# +#free(1.0)# +'autopageform' sucht zuerst das rechnerische Seitenende. Ist dort ein Absatz vor +handen, wird die Seite an dieser Stelle beendet. Falls nicht, sucht 'autopageform' +nach oben in den nächsten vier Zeilen nach einem Absatz. Wird keiner gefunden, +wird die Seite am rechnerischen Seitenende beendet. + +Ist die \#pageblock\#-Anweisung gegeben, wird zuerst nach oben in den vier letzten +Zeilen nach einem Absatz gesucht, um dort die Seite zu beenden. Ist dort keiner +vorhanden, wird auch über das rechnerische Seitenende hinweg versucht, die Seiten +länge zu plazieren (4 Zeilen). 'autopageform' beachtet in einem solchen Fall die +'pagelength'-Anweisung, indem der Zeilenabstand gestaucht wird. +#page# + +#ib(9)#5.3.1.2. #ib#Seitenende interaktiv verschieben#ie# #ie(9)# +#free(1.0)# + #on("i")# + In diesem Abschnitt wird beschrieben, welche interaktiven Möglichkeiten Ihnen + 'pageform' bietet, Seiten zu gestalten. + #off("i")# +#free(1.0)# +Auf dem Bildschirm wird das von 'pageform' errechnete jeweilige Seitenende unter +Angabe der aktuellen Seitennummer angezeigt. Das Seitenende erscheint ungefähr in +der Mitte des Bildschirmes und wird durch eine von 'pageform' erzeugte Zeile ge +kennzeichnet, die auch - nach erfolgter Seitenformatierung - in der Druckdatei zu +sehen ist. Der EUMEL-Drucker druckt diese Zeile nicht. + +____________________________________________________________________________ + +Mehrere Fußnoten innerhalb einer Seite werden von 'pageform'/ +'autopageform' in der Reihenfolge ihres Auftretens gesammelt und +am Ende der Seite plaziert. Für eine entsprechende Trennung der +Fußnoten voneinander (z.B. durch Leerzeilen) müssen Sie selbst +sorgen. +\#page\#\#--------------------- Ende Seite 215 --------\# +Unter Umständen paßt die Fußnote nicht mehr auf die aktuelle +Seite und muß deshalb von 'pageform'/'autopageform' auf die näch +ste Seite gebracht werden. 'pageform'/'autopageform' geht davon +aus, daß die Kennzeichnung der Fußnote in der Zeile unmittelbar +vor der Fußnote steht und bringt diese Zeile ebenfalls auf die +neue Seite. + + +____________________________________________________________________________ + + +Über der Markierung erscheinen die letzten Zeilen der bereits verarbeiteten Seite, +darunter die ersten Zeilen der nächsten Seite. Sie können nun mit Hilfe der Positio +nierungstasten die Markierung und damit das Seitenende nach oben verschieben. +Damit vermeiden Sie, daß ein logisch zusammengehöriger Text auseinandergerissen +wird und sogenannte "Waisenkinder" entstehen (letzte Zeile eines Abschnittes kommt +auf die neue Seite). + +Bei der interaktiven #ib#Formatierung#ie (1, " für Seiten")# können Sie die Markierung nicht über das errech +nete Ende einer Seite nach unten oder über das vorherige, bereits verarbeitete Seiten +ende nach oben verschieben. + +Haben Sie jedoch zu Beginn die #ib#\#pageblock\##ie(1,"-Anweisung")#-Anweisung (siehe S. 5-91) gegeben, +ist es erlaubt, die Seitenende-Markierung auch einige Zeilen über das rechnerische +Seitenende hinaus zu bewegen. Betätigen Sie dann <CR> , wird der Drucker (sofern +möglich) den Zeilenabstand auf dieser Seite stauchen. In diesem Fall sollten Sie +darauf achten, daß das Seitenende bei einem Absatz immer #on("b")##on("i")#vor#off("b")##off("i")# eventuell vorhan +dene Leerzeilen plaziert wird. Andernfalls werden die Leerzeilen am Ende der Seite +als Textzeile mitgezählt und es bleibt entsprechender Platz frei! + +Innerhalb einer Fußnote kann die Markierung nicht verschoben werden. In diesem Fall +wird interaktiv angefragt, ob die Fußnote auf der nächsten Seite fortgesetzt werden +soll. Verneinen Sie die Anfrage, positioniert 'pageform' vor die Fußnote. Von dieser +Stelle aus können Sie das Seitenende wie gewohnt verschieben. + +Bejahen Sie dagegen die Anfrage nach dem Fußnotenumbruch, plaziert 'pageform' +das Seitende an dieser Stelle innerhalb der Fußnote. Der restliche Teil der Fußnote +kommt auf die nächste Seite mit einer Anmerkung ('Forts. von letzter Seite')#u##count#)#e#. +#foot# +#u##value#)#e# Bei fremdsprachlichen Texten sollten Sie nach 'pageform' diese Anmerkungen + in der '.p'-Datei ändern. +#end# + +Entstehen bei der Seitenformatierung am Anfang einer Seite #ib#Leerzeilen#ie(1, " am Seitenanfang")# (z.B. durch +Plazierung des Seitenendes zwischen zwei Absätzen), so werden diese von 'page +form' automatisch aus der Druckdatei entfernt. Möchten Sie #ib#Leerzeilen am Anfang +einer Seite#ie#, dann sollten Sie die \#free\#-Anweisung in Verbindung mit der \#page\#- +Anweisung verwenden. + +Zusätzlich können Sie Leerzeilen in eine Seite der Druckdatei einfügen und/oder +beliebige Zeilen löschen (vergl. b). +#page# +Folgende Operationen stehen Ihnen bei der interaktiven Seitenformatierung zur Ver +fügung: + +#on("b")#a) #ib#Seitenende verschieben#ie#:#off("b")# + +'pageform' berechnet das "rechnerische" Seitenende und zeigt dieses auf dem Bild +schirm durch die Markierung an. Die Markierung kann interaktiv verschoben werden: + + #on("b")#Taste Bedeutung#off("b")# + + <CR> Seitenende an diese Stelle plazieren. + + + <^> Seitenende eine Zeile nach oben verschieben. + + + <v> Seitenende eine Zeile nach unten verschieben (wenn + vorher nach oben verschoben bzw. wenn \#pageblock\#- + Anweisung gegeben ist). + + + <HOP> <^> Seitenende um einen Bildschirm nach oben verschieben. + + + <HOP> <v> Seitenende um einen Bildschirm nach unten verschieben. + + + <ESC> Abbruch der Seitenformatierung. + + + +#on("b")#b) #ib#Leerzeilen einfügen#ie# und/oder #ib#Zeilen löschen#ie##off("b")# + +Ist nach den Berechnungen von 'pageform' der Text ungünstig auf der Seite plaziert, +können Sie in die Seite (der Druckdatei!) Leerzeilen einfügen und/oder Zeilen löschen. +Dies kann beispielsweise sinnvoll sein, wenn durch die Löschung einer Zeile ein +Absatz noch auf die Seite passen würde oder durch die Einfügung von Leerzeilen ein +Absatz auf der letzten Zeile der Seite endet. Oft ist es auch sinnvoll, daß alle Seiten +gleich lang sind. In diesem Fall sollten vor Kapiteln und Absätzen Leerzeilen eingefügt +oder gelöscht werden. + +Um Leerzeilen einzufügen und/oder Zeilen zu löschen, müssen Sie die Markierung +wie unter a) beschrieben an die Stelle plazieren, an der die Änderung vorgenommen +werden soll. + + + #on("b")#Taste Bedeutung#off("b")# + + + <HOP> <RUBIN> Leerzeilen einfügen. Anstatt der Markierung können + durch (u.U. mehrmaliges) <CR> Leerzeilen eingefügt + werden. <HOP> <RUBIN> beendet den Vorgang (wie + Zeileneinfügen im Editor). + + <HOP> <RUBOUT> Zeile löschen. Die Zeile unmittelbar oberhalb der + Markierung wird gelöscht. + + + +Anschließend berechnet 'pageform' die Seite erneut. + + + +#on("b")#c) #ib(9)##ib#\#page\#-Anweisung bestätigen/löschen#ie(9)##ie##off ("bold")# + +Wird von der Prozedur 'pageform' eine #ib#\#page\#-Anweisung#ie# angetroffen, so wird das +gewünschte Seitenende auf Ihrem Bildschirm angezeigt. Die \#page\#-Anweisung +können Sie entweder bestätigen oder löschen. + + #on("b")#Taste Bedeutung#off("b")# + + + <CR> Seitenende bestätigen. + + <RUBOUT> \#page\#-Anweisung ignorieren. Die Prozedur 'pageform' + bearbeitet in diesem Fall die Datei weiter, als ob keine + \#page\#-Anweisung angetroffen wurde. + + <ESC> Abbruch der Seitenformatierung. +#page# + +#ib(9)#5.3.2. #ib#Seitenlänge einstellen#ie##ie(9)# +#goalpage("pagelength")# +#free(0.7)# + #on("i")# + 'pageform'/'autopageform' ist auf ein Schreibfeld von 25.0 cm eingestellt (ent + spricht einem DIN A4-Schreibfeld). Wünschen Sie eine andere Seitenlänge, + müssen Sie die #ib#\#pagelength\#-Anweisung#ie# in den Text einfügen. + #off("i")# +#free(0.7)# +____________________________________________________________________________ + + \#pagelength (20.0)\# + +____________________________________________________________________________ + + +stellt die Seitenlänge auf 20 cm ein. + +Beachten Sie, daß + +1. die neu eingestellte Seitenlänge immer erst ab der nächsten Seite gilt (die bislang + eingestellte Seitenlänge gilt noch für die aktuelle Seite). + +2. die eingestellte Seitenlänge am Anfang der Datei (also vor der ersten Textzeile) für + die erste Seite gilt. +#mark ("", "")# + +3. der Dezimalpunkt bei der Seitenlänge mit angegeben werden muß. + +Die folgende Tabelle gibt die Seitenlänge für die am häufigsten gewählten Papier +größen an: + + #on("b")#Format Seitenlänge oberer und + (in cm) unterer Rand#off("b")# + + DIN A4 25.0 je 2.35 cm + + DIN A5 18.0 je 2.15 cm + + DIN A4 quer 16.0 je 2.50 cm +#page# + +#ib(9)#5.3.3. #ib#Zeilenabstand einstellen#ie##ie(9)# +#goalpage ("linefeed")# +#free(1.0)# + #on("i")# + Mit der #ib#\#linefeed\#-Anweisung#ie# stellen Sie einen #ib#Zeilenvorschub#ie# relativ zu der + #ib#Schrifthöhe#ie# des eingestellten Schrifttyps ein. + #off("i")# +#free(1.0)# +'pageform'/'autopageform' berechnet die Anzahl der Zeilen pro Seite immer in Ab +hängigkeit von dem eingestellten Schrifttyp. Haben Sie z.B. eine Schrift gewählt, die +doppelt so hoch wie eine Schreibmaschinenschrift ist, bekommen Sie auch entspre +chend weniger Zeilen auf eine Seite. Um diesen Berechnungsvorgang brauchen Sie +sich in der Regel nicht zu kümmern. + +Anders verhält es sich, wenn ein anderer #ib#Zeilenabstand#ie# als der "normale" Abstand +zwischen Zeilen eingestellt werden soll. In diesem Fall wird die \#linefeed\#- +Anweisung eingesetzt. Der Parameter gibt an, um welchen Faktor eine Zeilenhöhe #on("i")##on("b")#ab +der nächsten druckbaren Zeile#off("b")##off("i")# erhöht oder verringert werden soll. + +____________________________________________________________________________ + + \#linefeed (2.0)\# + +____________________________________________________________________________ + + +druckt die folgenden Zeilen mit doppeltem Zeilenabstand. Nach Antreffen dieser An +weisung wird die Zeilenhöhe durch 2 * eingestellte Schrifttypgröße errechnet. Es wird +also der Zeilenabstand zwischen den Zeilen entsprechend vergrößert, da die Schrift +größe gleich bleibt. Dies entspricht dem zweizeiligen Schreiben bei einer Schreib +maschine (wenn man davon absieht, daß auch hier unterschiedliche Schrifthöhen +möglich sind). Ein 1 1/2 zeiliges Schreiben wäre mit + +____________________________________________________________________________ + + \#linefeed (1.5)\# + +____________________________________________________________________________ + + +einzustellen. + +____________________________________________________________________________ + + \#linefeed (0.5)\# + +____________________________________________________________________________ + + +stellt die Zeilenhöhe = 1/2 * eingestellte Schrifthöhe ein, so daß die Zeilen teilweise +ineinander gedruckt werden (was bei manchen Druckern zu nicht lesbaren Resultaten +führt). Bei \#linefeed (0.0)\# werden Zeilen übereinander gedruckt (druckerabhängig). + +Beachten Sie, daß die Angabe in der \#linefeed\#-Anweisung relativ erfolgt. Bei allen +anderen Anweisungen der Textkosmetik werden Angaben in Zentimetern verlangt. Die +\#linefeed\#-Anweisung bildet somit eine Ausnahme. +#page# + +#ib(9)#5.3.4. #ib#Platz freihalten#ie# #ie(9)# +#goalpage ("free")# +#free(1.0)# + #on("i")# + Mit der #ib#\#free\#-Anweisung#ie# können Sie einen zusammenhängenden Teil auf einer + Seite freihalten. + #off("i")# +#free(1.0)# +Die \#free\#-Anweisung setzen Sie an solchen Stellen im Text ein, an denen - nach +dem Druck - Zeichnungen, Tabellen und ähnliches eingeklebt werden sollen. Sie +können sie auch zwischen Absätzen, Kapiteln usw. einsetzen, wenn der Abstand nicht +gleich dem Vielfachen der Zeilenhöhe ist. Es wird der in der \#free\#-Anweisung +angegebene Platz freigehalten. + +____________________________________________________________________________ + +\#free (2.0)\# + +____________________________________________________________________________ + + +hält zwei Zentimeter frei. Paßt der angeforderte Platz nicht mehr auf die Seite, so wird +er auf der nächsten Seite reserviert ('pageform'/'autopageform' plaziert das Seiten +ende vor die \#free\#-Anweisung). + + + +#on("i")##on("b")#Praktischer Tip:#off("b")##off("i")# +Sie sollten eine \#free\#-Anweisung allein auf eine Zeile schreiben, damit Sie sie u.U. +durch 'pageform' interaktiv entfernen können, wenn die \#free\#-Anweisung ungünstig +an den Seitenanfang oder das Seitenende kommt. +#page# + +#ib(9)#5.3.5. #ib#Neue Seite beginnen#ie##ie(9)# +#goalpage("page")# +#free(1.0)# + #on("i")# + An einigen Stellen im Text, z.B. zu Beginn eines neuen Kapitels, möchten Sie + unbedingt eine neue Seite anfangen. Dies erreichen Sie mit der #ib#\#page\#- + Anweisung#ie#. + #off("i")# +#free(1.0)# +'pageform' meldet in diesem Fall, nach wie vielen Zentimetern auf der Seite die An +weisung angetroffen wurde. Sie können nun mit <CR> das Seitenende bestätigen oder +die Anweisung (in der Druckdatei) löschen. Im letzteren Fall berechnet 'pageform' die +Seite neu, als ob die \#page\#-Anweisung nicht dagewesen wäre. + +Gleichzeitig können Sie mit Hilfe der #ib#\#page\#-Anweisung#ie(1, ", mit neuer Seitenummer")# eine neue Seitennummer +für die neue Seite einstellen (vergl. Sie dazu die nächsten Abschnitte). +#page# + +#ib(9)#5.3.6. #ib#Kopf- und Fußzeilen#ie##ie(9)# +#goalpage("head")##goalpage("bottom")# +#free(1.0)# + #on("i")# + Mit den #ib#\#head\#-#ie(1, "Anweisung")# und #ib#\#bottom\#-Anweisung#ie#en können Sie Zeilen am Anfang und + Ende jeder Seite einfügen. + #off("i")# +#free(1.0)# +Sie schreiben Zeilen am Anfang ("#ib#Kopfzeilen#ie#") und Ende ("#ib#Fußzeilen#ie#") jeder Seite nur +einmal und kennzeichnen sie mit Anweisungen. Diese Zeilen fügt 'pageform'/ +'autopageform' dann an den entsprechenden Stellen ein. + +____________________________________________________________________________ + + \#head\# + Unser EUMEL-Benutzerhandbuch + + \#end\# + +____________________________________________________________________________ + + +Diese Zeile (also die zwischen den \#head\#- und #ib#\#end\#-Anweisung#ie#en eingeschlos +sene Zeile) wird von 'pageform'/'autopageform' an den Anfang jeder Seite in die +Druckdatei plaziert. + +Entsprechendes gilt für Fußzeilen, die zwischen \#bottom\# und \#end\# eingeschlossen +werden müssen: + +____________________________________________________________________________ + + \#bottom\# + + Autor: I. Listig + \#end\# + +____________________________________________________________________________ + + +#on("b")#Praktischer Tip#off("b")#: + +Fügen Sie mindestens eine Leerzeile am Ende eines \#head\# bzw. am Anfang eines +\#bottom\# ein, um den eigentlichen Text von den Kopf- bzw. Fußzeilen abzuheben. + + +'pageform'/'autopageform' zählt die Seiten, beginnend mit der Seitennummer '1'. (Wie +man Seitennummern in die Kopf- und Fußzeilen bekommt, erfahren Sie im nächsten +Abschnitt). Sie können nun getrennte Kopf- und Fußzeilen für gerade und ungerade +Seiten gestalten (wie in diesem Benutzerhandbuch). Dies erfolgt mit den Anweisungen +\#headeven\# und \#headodd\# für Seiten mit geraden und ungeraden Seitennummern; +ebenso \#bottomeven\# und \#bottomodd\#. Diese Anweisungen müssen ebenfalls jeweils +mit einer \#end\#-Anweisung beendet werden. + +Sie haben die Möglichkeit, Kopf- und Fußzeilen mehrmals innerhalb einer Datei zu +wechseln, um unterschiedliche Beschriftungen zu erhalten (z.B. kapitelweise). Dies ist +jedoch nur sinnvoll, wenn es auf einer neuen Seite erfolgt, also unmittelbar #on("b")##on("is")#nach#off("b")##off("is")# einer +\#page\#-Anweisung. + +____________________________________________________________________________ + + \#page\# + \#head\# + Neuer Seitenkopf + + \#end\# + +____________________________________________________________________________ + + +Kopf- und Fußzeilen sollen überall gleiches Aussehen haben, unabhängig davon, +welche Anweisungen im restlichen Text gegeben werden. Darum werden die bei der +Definition einer Kopf- und Fußzeile aktuellen Werte für + + + limit + type + linefeed + + +bei dem Einsetzen der Zeilen berücksichtigt. Für Kopf- oder Fußzeilen können Sie +einen anderen Schrifttyp als im restlichen Text verwenden, indem Sie die \#type\#- +Anweisung innerhalb eines \#head\#- oder \#bottom\#-Bereiches geben. Beachten Sie, +daß nach \#head\#-, \#bottom\# und auch \#foot\#-Bereichen die oben genannten An +weisungen nicht automatisch zurückgestellt werden. Darum sollten Sie vor der +\#end\#-Anweisung wieder auf die im übrigen Text verwendeten Werte zurückstellen. + +____________________________________________________________________________ + + \#bottom\# + \#type ("klein")\# + Autor: I. Listig + (Schrifttyp + zurückstellen): + \#type ("normal")\# + \#end\# + +____________________________________________________________________________ + + +#page# + +#ib(9)#5.3.7. #ib#Seiten numerieren#ie##ie(9)# +#free(1.0)# + #on("i")# + In den Kopf- und Fußzeilen steht das #ib#'%'-Zeichen#ie# für die aktuelle Seiten + nummer. + #off("i")# +#free(1.0)# +Erscheint das '%'-Zeichen innerhalb eines Kopf- oder Fußbereiches, wird von +'pageform'/'autopageform' beim Einsetzen dieser Zeilen auf jeder Seite die aktuelle +#ib#Seitennummer#ie# eingesetzt (sind mehrere '%'-Zeichen vorhanden, wird die Seiten +nummer mehrmals eingesetzt). + +____________________________________________________________________________ + + \#head\# + Seite: - % - + + \#end\# + +____________________________________________________________________________ + + +Wenn Sie die Seitenzahl in der Zeilenmitte oder am rechten Rand plazieren möchten, +können Sie die Anweisungen \#center\# (siehe S. 5-93) oder \#right\# (siehe S. 5-94) +verwenden. + +Durch das Einrichten eines Fußbereiches können Sie die Seitennummern auch am +unteren Ende einer Seite erzeugen. Beachten Sie, daß sich bei mehrstelligen Seiten +nummern die Zeilenlänge durch das Einsetzen vergrößert. + +Um zum Beispiel das #ib#Vorhandensein einer Folgeseite#ie# in einem Fußbereich zu kenn +zeichnen, müssen Sie das '%'-Zeichen zweimal direkt hintereinander schreiben. + +____________________________________________________________________________ + + \#bottom\# + + \#right\# %% + \#end\# + +____________________________________________________________________________ + + +In dem Beispiel oben wird die Seitenzahl rechtsbündig gedruckt. + + +Manchmal ist es notwendig und sinnvoll, einen Text in mehreren Dateien zu halten. +Bei einer Folgedatei müssen Sie die Seitennummer dann neu setzen. Das erfolgt mit +der \#pagenr\#- oder der \#page\#-Anweisung. + +____________________________________________________________________________ + + \#page (4)\# + +____________________________________________________________________________ + + +bewirkt eine neue Seite. Die Seitennummer der neuen Seite ist '4'. + +#goalpage("pagenr")# + +Bei einigen Spezialanwendungen benötigen Sie unter Umständen mehr als eine +Seitennummer. Beispielsweise soll ein Text nicht nur absolut, sondern auch jede Seite +in jedem Kapitel separat durchgezählt werden. + +____________________________________________________________________________ + + \#page (4711)\# + \#pagenr ("$", 1)\# + \#head\# + Mein Buch Seite: % Kapitelseite: $ + + \#end\# + +____________________________________________________________________________ + + +Die Anweisung #ib#\#pagenr#ie# ("$",1)\# veranlaßt, daß ab der nächsten Seite eine neue +Numerierung durchgeführt wird. Dabei steht '$' stellvertretend für die neue Zahl. Die +'1' bedeutet, daß bei der Numerierung mit '1' begonnen wird. 'pageform'/ +'autopageform' erhöht bei jeder neuen Seite das Zeichen um '1' und setzt es ggf. in +die Kopf- und Fußzeilen. Es sind zwei zusätzliche Seitenzeichen (neben dem '%') +möglich. + +Beachten Sie, daß die neuen Seitennummern immer erst ab der nächsten Seite gel +ten. Geben Sie die \#page (...)\#- oder die \#pagenr (...,...)\#-Anweisung am Anfang +der Datei (also vor der ersten Textzeile), gelten die neuen Seitennummern für die +erste Seite. +#page# + +#ib(9)#5.3.8. #ib#Fußnoten#ie# schreiben#ie(9)# +#goalpage("foot")# +#free(1.0)# + #on("i")# + Fußnoten werden direkt im Text durch die Anweisungen \#foot\# und \#end\# + gekennzeichnet. Die Fußnoten plaziert 'pageform'/'autopageform' an das Ende + einer Seite. + #off("i")# +#free(1.0)# +#ib#Fußnoten#ie# schreiben Sie direkt in den Text, am besten an der Stelle, an der später die +Fußnote aufgerufen werden soll. Die Fußnote wird von 'pageform'/'autopageform' an +das Ende einer Seite, ggf. vor die Fußzeilen, plaziert. Für die Kennzeichnung von +Fußnoten und die entsprechende Markierung im Text sind Sie selbst zuständig. Aller +dings werden von 'pageform'/'autopageform' bei dem Einsetzen einer Fußnote am +Ende einer Seite Unterstriche vor die Fußnoten eingefügt, damit Fußnoten vom lau +fenden Text abgehoben werden. + +____________________________________________________________________________ + + \#foot\# + *) Das ist die erste Anmerkung auf dieser Seite. + \#end\# + +____________________________________________________________________________ + + +Druckbild: + +______ +*) Das ist die erste Anmerkung auf dieser Seite. + + +Mehrere Fußnoten innerhalb einer Seite werden von 'pageform'/'autopageform' in der +Reihenfolge ihres Auftretens gesammelt und am Ende der Seite plaziert. Für eine +entsprechende Trennung der Fußnoten voneinander (z.B. durch Leerzeilen) müssen +Sie selbst sorgen. + +Unter Umständen paßt die Fußnote nicht mehr auf die aktuelle Seite und muß deshalb +von 'pageform'/'autopageform' auf die nächste Seite gebracht werden. 'pageform'/ +'autopageform' geht davon aus, daß die Kennzeichnung der Fußnote in der Zeile +unmittelbar vor der Fußnote steht und bringt diese Zeile ebenfalls auf die neue Seite. + +____________________________________________________________________________ + +Es ist auch möglich, eine Fußnote innerhalb eines Abschnitts zu +schreiben, wie z.B. in dieser Zeile\#u\#*)\#e\#.\#foot\# +\#u\#*)\#e\# Fußnote in einem Abschnitt! +\#end\# +Sie fahren anschließend ohne Unterbrechung mit dem Schreiben +Ihres Textes fort. + +____________________________________________________________________________ + + +Druckbild (nach lineform): + +Es ist auch möglich, eine Fußnote innerhalb eines Abschnitts zu schreiben, wie z.B. +in dieser Zeile#u#*)#e#. Sie fahren anschließend ohne Unterbrechung mit dem Schreiben#foot# +#u#*)#e# Fußnote in einem Abschnitt! +#end# +Ihres Textes fort. + + +In diesem Fall ist es wünschenswert, daß 'lineform' die Zeile, die \#foot\# vorausgeht, +mit der Zeile, die \#end\# folgt, auffüllt. Dies geschieht unter folgenden Bedingungen: + +1. Hinter \#foot\# darf nichts mehr stehen, also auch kein Absatzzeichen. + +2. Es werden so lange Worte von der Zeile nach \#end\# vor die \#foot\#-Anweisung + plaziert, bis die Zeile gefüllt oder die Zeile nach \#end\# leergeräumt ist. + +3. Beachten Sie, daß Textkosmetik-Anweisungen ebenfalls mit über die Fußnote + genommen werden. Handelt es sich beispielsweise um eine \#type\#-Anweisung, + kann sich das Aussehen der Fußnote verändern! Darum ist es angeraten, even + tuelle Anweisungen, die die Fußnote verändern sollen, innerhalb der Fußnote zu + plazieren. + +Sie sollten vermeiden, umfangreiche Texte in Fußnoten zu schreiben (beispielsweise +längere Zitate). Aus programmtechnischen Gründen begrenzt 'pageform'/'autopage +form' die maximale Länge von Fußnoten auf einer Seite auf 85% des effektiven +Schreibfeldes (effektives Schreibfeld: Seitenlänge minus Länge von \#head\#- bzw. +\#bottom\#-Zeilen). Nimmt eine Fußnote einen größeren Raum ein, bricht 'pageform'/ +'autopageform' die Seitenformatierung mit einer Fehlermeldung ab. +#page# + +#ib(9)#5.3.8.1. #ib#Fußnoten numerieren#ie##ie(9)# +#goalpage("count")##goalpage("value")# +#free(1.0)# + #on("i")# + Gleichartige Textteile wie Lehrsätze, Beispiele, Fußnoten usw. werden i. allg. + durchnumeriert. Da Sie bei der Abfassung eines längeren Textes ihre genaue + Anzahl meist nicht vorausplanen können, übernimmt 'pageform'/'autopageform' die + Zählung. + #off("i")# +#free(1.0)# +Durch die #ib#\#count\#-Anweisung#ie# wird 'pageform'/'autopageform' veranlaßt, einen +internen Zähler (beginnend bei dem Wert 0) zu erhöhen und diesen Wert statt der +\#count\#-Anweisungen in den Text einzusetzen. + +____________________________________________________________________________ + + \#count\# + +____________________________________________________________________________ + + +setzt den Wert 1 statt der Anweisung ein. Jede weitere \#count\#-Anweisung erhöht +den internen Zähler und der Zählerwert wird wiederum eingesetzt: + +____________________________________________________________________________ + + \#count\# + +____________________________________________________________________________ + + +setzt den Wert 2 ein usw. Dadurch ist es möglich, beliebige Textteile (Kapitel, +mathematische Sätze u.a.m.) fortlaufend zu numerieren, ohne auf die Numerierung +beim Schreiben und Ändern des Textes zu achten. + +Anmerkung: +Trifft 'lineform' auf eine \#count\#-Anweisung, so wird die Zeile berechnet, als ob drei +Ziffern anstatt der Anweisung im Text ständen. + +Mit der \#value\#-Anweisung können Sie den #on("b")##on("i")#letzten#off("i")##off("b")# erreichten count-Wert nochmals +einsetzen. Das ist insbesondere für Fußnoten sinnvoll einsetzbar. + +____________________________________________________________________________ + + Text ....... (\#count\#) + \#foot\# + (\#value\#) Text der Fußnote + \#end\# + Text ....... + +____________________________________________________________________________ + + +Das Resultat sähe folgendermaßen aus: + + Text ....... (3) + Text ....... + ............... + ______ + (3) Text der Fußnote + +Beachten Sie, daß in diesem Fall die \#value\#-Anweisung der \#count\#-Anweisung +folgen muß, ohne daß eine weitere \#count\#-Anweisung dazwischen steht. Das liegt +- wie bereits oben erwähnt - daran, daß die \#value\#-Anweisung immer den letzten +\#count\#-Wert einsetzt. + +Das können Sie umgehen, indem Sie die \#count\#- und \#value\#-Anweisungen mit +einem TEXT-Parameter versehen, der als Kennzeichnung dient. + +____________________________________________________________________________ + + \#count ("Merk1")\# + +____________________________________________________________________________ + + +\#count ("Merk1")\# arbeitet ebenso wie \#count\# ohne Parameter und setzt für unser +Kapitel hier den Wert 4 ein. Zusätzlich zu dem fortlaufend gezählten Wert (fortlau +fende Numerierung der Fußnoten) vermerkt 'pageform'/'autopageform' einen Wert, der +bei Bedarf an irgendeiner anderen Stelle im Text durch \#value ("Merk1")\# wieder +aufgerufen werden kann, zum Beispiel, wenn Sie auf eine andere Fußnote verweisen +möchten. + +____________________________________________________________________________ + + \#count\#\#count\# + \#value("Merk1")\# + +____________________________________________________________________________ + + +Die ersten zwei \#count\#-Anweisungen produzieren - in unserem Kapitel - die +Werte 5 bzw. 6. Die \#value\#-Anweisung dagegen setzt den vermerkten Wert 4 ein. + +Dies ist insbesondere sinnvoll, wenn Sie im Text auf eine Fußnote verweisen möch +ten. + +Beispiel: + +Sie schreiben einen mehrseitigen Prospekt über ein neues Produkt. Auf Seite 5 möch +ten Sie auf eine Fußnote verweisen, die auf einer anderen Seite steht. Dann fügen Sie +'siehe auch Anmerkung (\#value("liefertermin")\#) in Ihren Text ein und fahren mit dem +Schreiben fort. 'pageform'/'autopageform' setzt später die entsprechende Zahl für den +Verweis ein. + +Auf der Seite, auf die Sie Bezug nehmen, sieht das ganze folgendermaßen aus: + +____________________________________________________________________________ + + Der Textverarbeitungskurs ist ein Lernprogramm für Anfänger. + \#(count)("Liefertermin")\#) + \#foot\# + (\#(value)("Liefertermin")\#) + Der Textverarbeitungskurs wird ab August erhältlich sein. + \#end\# + Das Programm ist auf den neuesten Erkenntnissen der Lehr + forschung aufgebaut. Der Kurs umfaßt Lehrbuch, Arbeitsbuch und + sechs Kassetten. + +____________________________________________________________________________ + + +#page# +Soll die Zahl für den Verweis bzw. für die Fußnote hochgestellt werden, fügen Sie die +Anweisungen \#u\# und \#e\# hinzu. + +____________________________________________________________________________ + + \#u\# (\#value("Liefertermin")\#)\#e\# + +____________________________________________________________________________ + + + + +Im gedruckten Prospekt sähe es (nach 'lineform') wie folgt aus: + +Der Textverarbeitungskurs ist ein Lernprogramm für Anfänger#u##count#)#e#.#foot# +#u##value#)#e#Der Textverarbeitungskurs wird ab August erhältlich sein. +#end# +Das Programm ist auf den neuesten Erkenntnissen der Lehrforschung aufgebaut. Der +Kurs umfaßt Lehrbuch, Arbeitsbuch und sechs Kassetten. + +Manchmal ist es notwendig (ebenso wie bei der Seitennummer), den internen Zähler +neu zu setzen. + +____________________________________________________________________________ + + \#setcount (13)\#\#count\# + +____________________________________________________________________________ +#goalpage("setcount")# + +produziert den Wert 13. +#page# + +#ib(9)#5.3.9. #ib#Querverweise#ie# #ie(9)# +#goalpage("topage")##goalpage("goalpage")# +#free(1.0)# + #on("i")# + Mit den Anweisungen #ib#\#topage\##ie(1,"-Anweisung")# und #ib#\#goalpage\##ie(1,"-Anweisung")# sind Querverweise möglich, die + von 'pageform'/'autopageform' in die Druckdatei eingefügt werden. + #off("i")# +#free(1.0)# +Mit Hilfe von Querverweisen soll auf andere Stellen im Text verwiesen werden, was +nur bei längeren Texten üblich ist. Um dem Leser die mühselige Suche nach der +Textstelle zu ersparen, gibt man in der Regel die Seitennummer an. Normalerweise +steht die Seitennummer vor der Fertigstellung des Textes noch nicht fest. Auch in +diesem Fall kann 'pageform'/'autopageform' helfen. Die \#topage\#-Anweisung ver +weist auf eine andere Seite im Text, an der sich eine Anweisung \#goalpage\# befinden +muß. Statt der Anweisung \#topage\# wird die Seitennummer der Seite eingesetzt, auf +der sich \#goalpage\# befindet. Damit jedes \#topage\# auch sein entsprechendes \#goal +page\# findet, geben Sie bei beiden Anweisungen einen TEXT-Parameter an. + + +____________________________________________________________________________ + + ... siehe auch auf Seite \#topage("Funktionstasten")\# ... + + +____________________________________________________________________________ + + +Auf einer anderen Seite befindet sich + +____________________________________________________________________________ + + ... \#goalpage("Funktionstasten")\# + +____________________________________________________________________________ + + +Nach 'Seite' wird die entsprechende Seitennummer eingesetzt. + +Es ist möglich, mehrmals auf die gleiche (Ziel-)Seite zu verweisen. Sie müssen nur +darauf achten, daß Sie immer das gleiche Merkmal (TEXT-Parameter) verwenden. +Beachten Sie auch, daß die \#goalpage\#-Anweisungen sich in den Zeilen befinden +müssen, die tatsächlich gedruckt werden. Setzen Sie sie nicht in die ersten Zeilen +einer Seite oder eines Textes, die Anweisungen für das Layout enthalten. + +Die Zahl der Querverweise darf 300 nicht übersteigen. #page# + +#ib(9)#5.3.10. Kombination von Tabellen, Fußnoten + und Kopf- bzw. Fußzeilen#ie(9)# +#free(1.0)# + #on("i")# + In Fußnoten, \#head\#- oder \#bottom\#-Bereichen können Tabellen untergebracht + werden. + #off("i")# +#free(1.0)# +____________________________________________________________________________ + +\#head\# +\#lpos(0.0)\#\#cpos(5.0)\#\#rpos(11.0)\# +\#table\# +Korrekturen EUMEL-Benutzerhandbuch S.007 + +\#table end\# +\#end\# + + +____________________________________________________________________________ + + + +Die obigen Eingaben schreiben an jeden Seitenanfang folgenden Text: + +#lpos(0.0)##cpos(5.0)##rpos(11.0)# +#table# +Korrekturen EUMEL-Benutzerhandbuch S.007 +#table end##clear pos# + +Die Tabelle sollte also vollständig in den oben erwähnten Bereichen enthalten sein. +#page# + +#ib(9)#5.3.11. #ib#Formatierung von Spalten#ie##ie(9)# +#goalpage("columns")# +#free(1.0)# + #on("i")# + Mit der \#columns\#-Anweisung ist es möglich, einen Text in #ib#Spalten#ie(1,"formatierung")# zu formatie + ren ("Zeitungsdruck"). + #off("i")# +#free(1.0)# +Durch die Angabe der \#columns\#-Anweisung wird 'pageform'/'autopageform' auf +gefordert, den Text in Spalten zu formatieren. Die Spaltenbreite müssen Sie mit der #ib# +\#limit\#-Anweisung#ie (1, " für Spalten")# einstellen. + +____________________________________________________________________________ + + \#limit (18.0)\# + ... + \#columns (2, 2.0)\# + \#limit (8.0)\# + ... + +____________________________________________________________________________ + + + +Anfangs schreiben Sie mit einer Zeilenbreite von 18 cm. Dann fordern Sie mit der +\#columns\#-Anweisung zweispaltigen Druck an (zwischen den Spalten sollen 2 cm +Abstand sein). Somit muß die \#limit\#-Anweisung (sie gilt für beide Spalten) auf 8 cm +eingestellt werden. + +Die interaktive #ib#Spaltenformatierung#ie# wird von 'pageform' wie gewohnt vorgenommen. +Auf dem Bildschirm erscheint nun das Spaltenende, wobei die Nummer der Spalte +angezeigt wird. Fußnoten werden spaltenweise eingeordnet und müssen somit die +gleiche Zeilenbreite haben wie die restlichen Spalten. + +'pageform'/'autopageform' erzeugt in der Druckdatei die Spalten hintereinander. Das +folgende Beispiel zeigt einen Ausschnitt aus der Druckdatei mit Kopf- und Fußzeilen +bei einem zweispaltigen Druck: + +____________________________________________________________________________ + + head-Zeilen + xx + xx + xx + bottom-Zeilen + \#page\#\#------- Ende Seite 1 Spalte 1 ----\# + xx + xx + xx + \#page\#\#------- Ende Seite 1 Spalte 2 ----\# + +____________________________________________________________________________ + + +Die zweite Spalte erscheint also ohne Kopf- und Fußzeilen, die jedoch bei der +Berechnung berücksichtigt werden. Beachten Sie, daß die Kopf- und Fußzeilen über +die Spalten gehen können. Dies erreichen Sie durch geeignete \#limit\#-Anweisungen +in den genannten Bereichen. + +Die meisten Drucker plazieren die zweite Spalte im Druckbild neben die erste. Bei +einigen wenigen Druckern müssen Sie die Spalten nebeneinander kleben. + +Alle Anweisungen funktionieren beim spaltenweisen Formatieren wie üblich. Die +\#free\#-Anweisung z.B. hält entsprechenden Platz in einer Spalte frei. Eine Aus +nahme bildet die #ib#\#page\#-Anweisung#ie (1, " für Spaltenende")#. Sie vollzieht hier ein #ib#Spaltenende#ie#. Die +\#page\#-Anweisung mit einem Parameter (welcher die Seitennummer der nächsten +Seite angibt) vollzieht dagegen ein Seitenende. + +Die #ib#\#columns end\#-Anweisung#ie# beendet die spaltenweise #ib#Formatierung#ie(1, " spaltenweise")#. Sie wirkt wie +eine \#page\#-Anweisung. + +#ib#Überschriften#ie (1, " in Spalten")# (bzw. Textblöcke) über mehrere Spalten hinweg sind nur auf der ersten +Seite direkt hinter der \#columns\#-Anweisung möglich. + +____________________________________________________________________________ + + \#page\# + \#limit (10.0)\# + Überschriften (bzw. Textblöcke) über mehrere Spalten hinweg + sind nur auf der ersten Seite direkt hinter der \#columns\#- + Anweisung möglich. + + + \#columns (2,2.0)\# + \#limit (4.0)\# + Die erste Spalte soll nur wenige Zeilen beinhalten. Das vor + zeitige Beendigen der Spalte erreicht man mit der \#page\#- + Anweisung. + \#page\# + In der zweiten Spalte kann dann mit dem Schreiben des Textes + fortgefahren werden. + ..................... + ..................... + ..................... + ..................... + ..................... + \#columns end\# + +____________________________________________________________________________ + + +#page# +Druckbild (mit 'lineform' bearbeitet): + + + + Überschriften (bzw. Textblöcke) über mehrere Spalten hinweg sind nur auf + der ersten Seite direkt hinter der \#columns\#-Anweisung möglich. + #columns (2,2.0)# + + Die erste Spalte soll nur + wenige Zeilen beinhalten. + Das vorzeitige Beendigen + der Spalte erreicht man mit + der \#page\#-Anweisung. + #page# + + + In der zweiten Spalte kann + dann mit dem Schreiben + des Textes fortgefahren + werden. + ..................... + ..................... + ..................... + +#columns end# + + + + +Die Zeilen für die zweispaltige Überschrift werden berücksichtigt. Dies gilt jedoch nur +unmittelbar hinter der \#columns\#-Anweisung. Möchten Sie diesen Effekt nochmals +erzeugen, beenden Sie mit \#columns end\#, schreiben die breite Überschrift und +schalten die \#columns\#-Anweisung wieder ein (jeweils unter richtiger Setzung von +\#limit\#). +#page# + +#ib(9)#5.4. #ib#Index#ie##ie(9)# +#free(1.0)# +#ib(9)#5.4.1. Stichwort- und/oder#ib# + Inhaltsverzeichnis#ie#se erstellen#ie(9)# +#free(1.0)# + + #on("i")# + Mit dem Programm '#ib#index#ie(1, "-Kommando")#' können Sie Stichwort- und Inhaltsverzeichnisse er + stellen. #ib#Stichwortverzeichnis#ie#se können sortiert werden. Mehrere Stichwortverzeich + nisse können Sie durch 'index merge' zusammenführen. + #off("i")# +#free(1.0)# +Durch den Aufruf von: + +____________________________________________________________________________ + + gib kommando: + index ("dateiname.p") + +____________________________________________________________________________ + + + +werden durch #ib#Indexanweisungen#ie# gekennzeichnete Worte in Dateien, den sogenannten +Indexdateien, gespeichert. + +Die Worte, die in einen Index übernommen werden sollen, müssen Sie in der Druck +datei für 'index' durch Anweisungen kennzeichnen. Solche #ib(1,"ff")#Indexanweisungen#ie# werden +von den anderen Textbe- und -verarbeitungs-Programmen ('lineform', 'pageform', +EUMEL-Drucker) ignoriert. Sie können also bei dem Schreiben mit dem Editor +gleich festlegen, welche Worte in einen Index aufgenommen werden sollen. + +Solche Verzeichnisse von Worten werden im EUMEL-System allgemein als #ib#Index#ie# +bezeichnet. 'index' kann ebenfalls benutzt werden, um ein #ib#Inhaltsverzeichnis#ie# und/oder +ein Verzeichnis aller Abbildungen zu erstellen oder Literaturhinweise zu überprüfen. + +Nachdem eine oder mehrere Indexdateien aus einer Druckdatei erstellt sind, werden +die Indexdateien auf Anfrage alphabetisch sortiert. Bei einem Inhaltsverzeichnis sollten +Sie die Sortierung natürlich ablehnen. Nach der Sortierung werden gleiche Einträge +automatisch zusammengefaßt und die entsprechenden Seitennummern nacheinander +aufgeführt. + + + +#on("b")##on("i")#Praktischer Tip:#off("b")##off("i")# +Möchten Sie nur eine Sortierung, aber keine Zusammenfassung von Einträgen, dann +lehnen Sie die Sortieranfrage ab. Anschließend können Sie die Indexdatei mit '#ib#lex sort#ie# +("indexdateiname")' sortieren. Hierbei bleiben gleiche Einträge erhalten. + + + +Das Programm + +____________________________________________________________________________ + + gib kommando: + index merge ("dateiname.i1", "dateiname.i2") + +____________________________________________________________________________ + + + +erlaubt es Ihnen, zwei durch 'index' erzeugte Verzeichnisse zusammenzuführen und +- nach Anfrage - wieder zu sortieren. +#page# + +#ib(9)#5.4.1.1. #ib#Worte für 'index' kennzeichnen#ie##ie(9)# #goalpage ("ib")##goalpage("ie")# +#free(1.0)# + #on("i")# + Worte, die in einen Index übernommen werden sollen, kennzeichnen Sie mit \#ib\# + und \#ie\#. + #off("i")# +#free(1.0)# +Da in einem Index - neben dem eigentlichen Worteintrag - die #ib#Seitennummer#ie# +enthalten sein soll, arbeitet das Programm 'index' nur mit einer #ib#Druckdatei#ie#, d.h. einer +Ausgabedatei von 'pageform'/'autopageform'. Die Indexworte werden in #ib#Indexdateien#ie# +gesammelt. Die Indexdateien erhalten den Namen der bearbeiteten Datei, an den ".i" +und die Nummer des Index angefügt wird. + +____________________________________________________________________________ + + ... Hier wird eine Eigenschaft des \#ib(1)\#EUMEL- + Systems\#ie(1)\# beschrieben. ... + +____________________________________________________________________________ + + +Die durch die Anweisungen #ib#\#ib\##ie(1,"-Anweisung")# und #ib#\#ie\##ie(1,"-Anweisung")# gekennzeichneten Worte werden mit der +dazugehörigen Seitennummer in die erste Indexdatei geschrieben. + +Die Einträge in einer Indexdatei werden von den Seitennummern durch mindestens +drei Punkte getrennt. Werden diese nicht gewünscht, können Sie sie leicht mit dem +Editor entfernen. + + +Sie haben die Möglichkeit, bis zu neun unterschiedliche Indexdateien zu erstellen, +z.B. gehen durch + +____________________________________________________________________________ + + \#ib (1)\# und \#ie (1)\# + +____________________________________________________________________________ + + +gekennzeichnete Worte in die Indexdatei mit der Nummer 1, durch + +____________________________________________________________________________ + + \#ib (9)\# und \#ie (9)\# + +____________________________________________________________________________ + + +gekennzeichnete Worte gehen in die Indexdatei mit der Nummer 9. Wenn Sie nur +einen Index erstellen müssen, dürfen die \#ib\#- und \#ie\#-Anweisungen ohne Para +meter benutzt werden, was gleichbedeutend ist mit \#ib (1)\# und \#ie (1)\#. + + + +Die durch \#ib\#- und \#ie\#-Anweisungen gekennzeichneten Worte können auch über +Zeilengrenzen (mit Silbentrennungen) gehen. + +____________________________________________________________________________ + + .... \#ib\#viele Index + Anweisungen\#ie\# ... + +____________________________________________________________________________ + + +'index' zieht getrennte Worte zusammen (hier: 'viele Index-Anweisungen'). Möchten +Sie einige Worte in verschiedenen Indexdateien haben, dürfen Sie die \#ib\#- und +\#ie\#-Anweisungen auch "schachteln". Dies können Sie besonders bei Kapitelüber +schriften nutzen. + + + +____________________________________________________________________________ + + \#ib(9)\#Eine Anweisung: die '\#ib\#limit\#ie\#'-Anweisung\#ie(9)\# + +____________________________________________________________________________ + + +In diesem Beispiel wird das Inhaltsverzeichnis in die Indexdatei '9' gebracht, während +der "allgemeine" Index in der Indexdatei '1' gesammelt wird. +#page# + +#ib(9)#5.4.1.2. #ib#Nebeneinträge erzeugen#ie##ie(9)# + +#free(1.0)# + #on("i")# + Sie haben die Möglichkeit, an die Seitennummer eines Eintrags einen beliebigen + Text anfügen zu lassen. + #off("i")# #free(1.0)# +Beispiel: + + + EUMEL-System ... 27ff. + Monitor ........ 13(Def.) + + + + + +Dies wird durch eine weitere Form der \#ib\#-Anweisung ermöglicht: + +____________________________________________________________________________ + + ... der \#ib(1,"(Kap.4)")\#EUMEL-Editor\#ie\# ist gut + geeignet, Texte zu erstellen ... + +____________________________________________________________________________ + + + +erzeugt den folgenden Eintrag: + + + +Druckbild: + + EUMEL-Editor ... 1(Kap.4) + + +An einen Eintrag können Sie einen weiteren Text angefügen, um etwa Untereinträge +zu bilden: + +Druckbild: + + EUMEL-System .................................. 27 + + EUMEL-System, komplexes ....................... 29 + + +Das wird ebenfalls durch eine andere Form der \#ib\#-Anweisung ermöglicht: + +____________________________________________________________________________ + + ... ist das \#ib\#EUMEL-System\#ie(1,", benutzerfreundliches")\# + wirklich ein benutzerfreundliches System ... + +____________________________________________________________________________ + + +erzeugt den folgenden Eintrag: + +Druckbild: + + EUMEL-System, benutzerfreundliches ............ 28 + + + +Nach der Erstellung einer Indexdatei können - nach interaktiver Anfrage - die +Einträge sortiert werden. Die Sortierung erfolgt alphabetisch nach DIN 5007, Abschnitt +1 und 3.2 (Umlaute werden "richtig" eingeordnet). + + + +Wie bereits erwähnt, können Sie 'index' vielseitig einsetzen: + +a) Erstellung von Stichwortverzeichnissen: + Wie bereits beschrieben. + +b) Erstellung von Inhaltsverzeichnissen: + Kapitelüberschriften mit eigenen Indexanweisungen klammern und durch 'index' + wie beschrieben verarbeiten. + + ____________________________________________________________________________ + + \#ib(9)\#6.1. Eine Datei drucken\#ie(9)\# + + _________________________________________________________________________ + + + Dann sind Sie sicher, daß das Inhaltsverzeichnis bezüglich Seitennummern und + Kapitelüberschriften korrekt ist. + +c) Erstellung von #ib#Abbildungsverzeichnisse#ie#n: + Abbildungsüberschriften- bzw. -unterschriften wie Kapitelüberschriften verarbei + ten. + +d) Überprüfung von Literaturhinweisen auf Vollständigkeit: + Sie klammern alle Literaturhinweise mit gesonderten Indexanweisungen. + + ____________________________________________________________________________ + + \#ib(8)\#/Meier82/\#ie(8)\#) + + _________________________________________________________________________ + + und überprüfen dann mit Hilfe dieser Indexdatei die Literaturverweise. So können + Sie sichergehen, daß alle Literaturverweise im Text auch in der Literaturaufstellung + stehen. +#page# + +#ib(9)#5.4.1.3. #ib#Indexdateien zusammenführen#ie##ie(9)# +#free(1.0)# + #on("i")# + Durch das Programm '#ib#index merge#ie(1,"-Kommando")#' können Sie eine Indexdatei in eine zweite + "einmischen". + #off("i")# +#free(1.0)# +Es ist somit möglich, einen Index zu erstellen, der sich über mehrere Dateien er +streckt, indem Sie 'index' die Druckdateien dieser Dateien bearbeiten und an +schließend die entstandenen Indexdateien mit 'index merge' zusammenfassen lassen. +Indexdateien können ggf. mit dem Editor bzw. 'lineform' und/oder 'pageform'/ +'autopageform' bearbeitet und anschließend gedruckt werden. + + +____________________________________________________________________________ + + gib kommando: + index merge ("1.kapitel.i1", "2.kapitel.i1") + +____________________________________________________________________________ + + + + +Hier wird die Indexdatei des 1. Kapitels in die Indexdatei des 2. Kapitels eingeordnet +und auf Wunsch sortiert. +#page# + +#ib(9)#5.5. #ib#Outline#ie##ie(9)# +#goalpage("outline")# +#free(1.0)# +#ib(9)#5.5.1. Eine#ib# Strukturübersicht#ie# oder + #ib#Zusammenfassung#ie# erstellen#ie(9)# +#free(1.0)# + #on("i")# + Das Programm 'outline' erstellt aus einem Text eine Zusammenfassung aller + (Kapitel-) Überschriften und Stichworte, sofern diese mit #ib#Index-Anweisungen#ie# + gekennzeichnet sind. + #off("i")# +#free(1.0)# +Manchmal sollen Stichworte oder das Inhaltsverzeichnis aus einem Text herausgeholt +werden, ohne vorher 'pageform' durchlaufen zu müssen. Das ist dann nützlich, wenn +Sie + +- Stichworte auf Korrektheit und Vollständigkeit überprüfen möchten; +- die Reihenfolge von Kapiteln überprüfen müssen; +- eine Übersicht durch Kapitel-Überschriften und Stichworte anfertigen möchten; +- einen Text auf logische Zusammenstellung überprüfen. + + +In solchen Fällen hilft das Programm 'outline', das mit dem Monitor-Kommando + +____________________________________________________________________________ + + gib kommando: + outline ("dateiname") + +____________________________________________________________________________ + + + +aufgerufen wird. 'outline' arbeitet ähnlich wie 'index', indem es alle mit \#ib\# und \#ie\# +markierten Textteile in eine Datei mit dem Zusatz 'outline' schreibt. Im Unterschied zu +'index' muß die Eingabe-Datei keine Druckdatei ('.p'-Zusatz) sein. + +Das Programm 'outline' fragt zuerst, mit welcher Indexnummer das Inhaltsverzeichnis +versehen ist. Das ist notwendig, weil die Kapitelüberschriften gegenüber Stichwörtern +in der 'outline'-Datei hervorgehoben werden (Einrückungen). + +Eingabe-Datei ("dateiname"): + +____________________________________________________________________________ + + ... + \#ib(9)\#1. Kapitel\#ie(9)\# + ... + ...\#ib\#Stichwort 1\#ie\# + \#ib\#Stichwort 2\#ie\#... + + \#ib(9)\#1.1. Kapitel\#ie(9)\# + ... + \#ib\#Stichwort 3\#ie\# + usw... + +____________________________________________________________________________ + + + +Druckbild der erzeugten Datei ("dateiname.outline"): + + 1. Kapitel + Stichwort 1 + Stichwort 2 + 1.1. Kapitel + Stichwort 3 + + +In diesem Beispiel werden alle Indizes mit Ausnahme der Kapitelüberschrift jeweils in +einer Zeile aufgeführt und gegenüber der Kapitelüberschrift eingerückt. Ein neues +Kapitel, sofern es dezimal gekennzeichnet ist, wird gegenüber einem Kapitel mit +höherer Ordnung eingerückt. +#page# + +#ib(9)#5.6. #ib#Print#ie##ie(9)##goalpage("print")# +#free(1.0)# + #on("i")# + Der #ib#EUMEL-Drucker#ie#, der mit dem #ib#'print'#ie(1,"-Kommando")#-Kommando angesprochen wird, ist + eine Software-Schnittstelle zu einem angeschlossenen Drucker. In diesem Kapitel + wird erklärt, wie Sie mit dem EUMEL-Drucker eine Datei drucken können und + welche speziellen Anweisungen den Drucker steuern. + #off("i")# +#free(1.0)# +Jeder Drucker erbringt "hardwaremäßig" unterschiedliche Leistungen (z.B. Typen und +Modifikationen). Diese Leistungen werden durch Eingabe spezieller Zeichenfolgen +veranlaßt, die herstellerspezifisch sind. + +Um vom EUMEL-System unterschiedliche Drucker auf gleiche Weise ansprechen zu +können, wurde eine Software-Schnittstelle geschaffen, die #ib#EUMEL-Drucker#ie# ge +nannt wird. Der EUMEL-Drucker akzeptiert eine Datei und veranlaßt, daß diese in +geeigneter Weise gedruckt wird. Weiterhin beachtet der EUMEL-Drucker die An +weisungen der Textkosmetik. Die Form der Anweisungen der Textkosmetik und des +EUMEL-Druckers sind identisch. +#page# + +#ib(9)#5.6.1. #ib#Eine Datei drucken#ie##ie(9)# +#free(1.0)# + #on("i")# + Mit dem Kommando '#ib#print#ie#' können Sie dem EUMEL-Drucker eine Datei zum + Drucken übergeben. + #off("i")# +#free(1.0)# +____________________________________________________________________________ + + gib kommando: + print ("dateiname") + +____________________________________________________________________________ + + +In der Regel ist im EUMEL-System (Multi-User) ein "Spooler" installiert, so daß Sie +sofort mit der Arbeit fortfahren können. Der EUMEL-Drucker arbeitet in diesem Fall +parallel zu Ihren anderen Arbeiten. +#page# + +#ib(9)#5.6.2. #ib#Anweisungen für den EUMEL-Drucker#ie##ie(9)# +#free(1.0)# +Ein Text (eine Datei) kann vom Drucker auch ohne Anweisungen gedruckt werden, +etwa für Probedrucke. Für diesen Fall hat der Drucker vernünftige Voreinstellungen. +Für einen "normalen" Text brauchen Sie keine speziellen Druckeranweisungen in den +zu druckenden Text einzufügen, denn die Anweisungen für die Textkosmetik reichen +zur Druckersteuerung aus. Nur wenn besondere Leistungen verlangt werden, wie z.B. +Blocksatz oder den gedruckten Text an eine bestimmte Stelle zu plazieren, sind +Druckeranweisungen notwendig. + +Werden vom Drucker Leistungen verlangt, die hardwaremäßig nicht vorhanden sind, +so sorgt der EUMEL-Drucker dafür, daß eine möglichst äquivalente Leistung erbracht +wird. Fordern Sie beispielsweise einen nicht vorhandenen Schrifttyp an, wird mit +dem Standard-Schrifttyp der jeweiligen Installation gedruckt. Damit ist es Ihnen +möglich, einen Text, der eigentlich für einen anderen Drucker bestimmt ist, auf einem +Drucker zu drucken, der die geforderte Type nicht kennt. + +Wie bereits erwähnt, beachtet der EUMEL-Drucker die gleichen Anweisungen wie +die Textkosmetik-Programme, aber einige Anweisungen sind nur für den Drucker +implementiert. Eine #ib#\#type\#-Anweisung#ie# beispielsweise, die einen bestimmten Schrift +typ anfordert, wird vom EUMEL-Drucker als Befehlsfolge an den angeschlossenen +Hardware-Drucker übergeben, sofern der Schrifttyp auf dem Drucker vorhanden ist. +Wie die Anweisungen geschrieben werden müssen, wurde in der Beschreibung der +Textkosmetik geschildert. + +Anweisungen werden nicht gedruckt. Besteht eine Zeile nur aus Anweisungen, so wird +diese Zeile vom EUMEL-Drucker nicht gedruckt. Im Gegensatz zu den Programmen +der Textkosmetik werden unbekannte oder #ib#fehlerhafte Anweisungen#ie# vom EUMEL +Drucker ohne Fehlermeldung "verschluckt". + +Neben den "normalen" Anweisungen, die nur in "\#"-Zeichen eingeschlossen wer +den, gibt es noch eine andere Form: + +Kommentar-#ib#Anweisungen#ie(1,", Kommentar-")#: + + Werden in "\#-" und "-\#"-Zeichen eingeschlossen. Solche Anweisungen wer + den ignoriert. + +____________________________________________________________________________ + + .......................... + Text...................... + .......................... + Kommentar-Anweisungen werden + beim Drucken ignoriert. + \#---- Ende der Seite 1 ---\# + +____________________________________________________________________________ + + + +Die letze Zeile erscheint im gedruckten Text nicht. +#page# +#goalpage("block")# +#ib(9)#5.6.3. #ib#Blocksatz#ie# #ie(9)# +#free(1.0)# +#ib(9)#5.6.3.1. #ib#Randausgleich#ie##ie(9)# +#free(1.0)# + #on("i")# + Die Anweisung #ib#\#block\##ie(1,"-Anweisung")# bewirkt einen Blocksatz beim Druck. + #off("i")# +#free(1.0)# +Fügen Sie in den Text (meist am Anfang einer Datei) die Anweisung + +____________________________________________________________________________ + + \#block\# + +____________________________________________________________________________ + + +ein, druckt der Drucker ab dieser Stelle alle Zeilen, die nicht mit einem Absatzkenn +zeichen versehen sind, im #ib#Blocksatz#ie#. Das heißt, daß durch Vergrößern der Wort +abstände alle Zeilen an der gleichen Position enden (rechter #ib#Randausgleich#ie#). Preis +werte Drucker können dies nur durch Einfügen ganzer Leerzeichen zwischen den +Worten vornehmen, was sich oft beim Lesen störend bemerkbar macht. Bei qualitativ +hochwertigen Druckern wird dagegen der Blocksatz durch Einfügen kleinerer Abstän +de zwischen den Worten erreicht. + +Der Text einer Zeile wird durch Vergrößern der #ib#Wortlücken#ie(1, ", Vergrößern der")# auf die Zeilenlänge, die +durch die \#limit\#-Anweisung eingestellt ist, verbreitert. + + +a) Es werden nicht verbreitert: + + - Absatzzeilen; + - der Text bis zum letzten #ib#Mehrfachblank#ie#; + - führende Leerzeichen (#ib#Einrückung#ie#); + - ein Leerzeichen hinter einer Aufzählung (siehe dazu b); + - geschützte Blanks. + + + +b) #ib#Aufzählungen#ie# gibt es nur nach einer Absatzzeile: + + - "Spiegelstrich" (Bindestrich und Leerzeichen am Anfang der Zeile); + - Doppelpunkt als Ende des ersten Wortes (Position < 20); + - schliessende Klammer oder Punkt als Ende des ersten Wortes (Position < 7), + z.B. 1) oder 1. +#page# +#goalpage ("pageblock")# + +#ib(9)#5.6.3.2. #ib#Seitenausgleich#ie##ie(9)# +#free(1.0)# + #on("i")# + Mit der #ib#\#pageblock\#-Anweisung#ie# wird der Drucker veranlaßt, einen Seiten + ausgleich (ähnlich wie bei der \#block\#-Anweisung für den rechten Rand + ausgleich) vorzunehmen. + #off("i")# +#free(1.0)# +Durch die automatische oder interaktive Seitenformatierung oder durch einen Fuß +notenumbruch von 'pageform'/'autoform' bleiben oft am Ende einer Seite Zeilen leer. +Dies können Sie durch die \#pageblock\#-Anweisung verhindern. Sie veranlaßt den +Drucker, Zwischenräume (Fachbegriff: Durchschuß) zwischen den Zeilen einzufügen, +so daß alle letzten Zeilen auf allen Seiten auf gleicher Höhe abschließen. Ebenso wie +beim Randausgleich hängt die Güte des Druckergebnisses jedoch von den Fähig +keiten des angeschlossenen Druckers ab. + +Beachten Sie jedoch, daß manche Verlage so bearbeitete Seiten nicht wünschen, weil +bei Verwendung von zu dünnem Papier beim Druck Zeilen "durchscheinen" können, +so daß das Lesen erschwert wird. + +Ist die Anweisung \#pageblock\# gegeben, können Sie in 'pageform' die Seitengrenze +auch über das rechnerische Seitenende hinaus plazieren. In diesem Fall werden die +Zeilen vom Drucker gestaucht. +#mark ("", "")# + + +____________________________________________________________________________ + +PAGEFORM für x Zeilen: dateiname ---> dateiname.p + +____________________________________________________________________________ + + +____________________________________________________________________________ + + Seitenende verschieben: UP, DOWN / bestaetigen: RETURN / Abbruch: ESC + +____________________________________________________________________________ + + +#page# + +#ib(9)#5.6.4. #ib#Schreibfeld verschieben#ie##ie(9)# #goalpage("start")# +#free(1.0)# + #on("i")# + Durch die Anweisung #ib#\#start\# #ie(1,"-Anweisung")#ist es Ihnen möglich, das #ib#Schreibfeld#ie# beim Druck auf + dem Papier an eine andere Stelle zu plazieren. + #off("i")# +#free(1.0)# +Der EUMEL-Drucker plaziert das Schreibfeld auf einem Drucker automatisch derart, +daß ein genügender Rand verbleibt. Die Wirkung dieser Voreinstellung ist natürlich +abhängig vom Drucker und der Installation. Mit der \#start\#-Anweisung können Sie +die automatische Einstellung verändern. + + +____________________________________________________________________________ + + \#start (1.0, 2.0)\# + +____________________________________________________________________________ + + +legt die linke, obere Ecke des Schreibfeldes fest (vom linken Rand 1 cm, vom oberen +Rand 2 cm). Die standardmäßige Voreinstellung ist \#start (2.54, 2.35)\#. Die \#start +(...)\#-Anweisung können Sie nur einmal pro Seite geben. +#page# + diff --git a/doc/user-manual/1.8.7/doc/benutzerhandbuch.5c b/doc/user-manual/1.8.7/doc/benutzerhandbuch.5c new file mode 100644 index 0000000..010cacd --- /dev/null +++ b/doc/user-manual/1.8.7/doc/benutzerhandbuch.5c @@ -0,0 +1,711 @@ +#start(5.0,1.5)##pagenr("%",93)##setcount(1)##block##pageblock##count per page# +#headeven# +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# + EUMEL-Benutzerhandbuch +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#headodd# +#lpos(0.0)##cpos(5.5)##rpos(11.0)##fillchar(" ")# +#table# + Teil 5: Textkosmetik und Druck +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#bottomeven# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +5 - % GMD +#tableend##clearpos# +#end# +#bottomodd# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +GMD 5 - % +#tableend##clearpos# +#end# +#goalpage("center")# +#ib(9)#5.6.5. #ib#Zentriert drucken#ie##ie(9)# +#free(1.0)# + #on("i")# + Mit der #ib#\#center\#-Anweisung#ie# können Sie einen Text in der Mitte der Zeile drucken + lassen. + #off("i")# +#free(1.0)# + +Die \#center\#-Anweisung zentriert den Text einer Absatzzeile. + + +____________________________________________________________________________ + + \#center\#Diese Zeile wird zentriert gedruckt. + +#mark ("", "")# + +____________________________________________________________________________ + + +Druckbild: + + #center#Diese Zeile wird zentriert gedruckt. +#page# + +#ib(9)#5.6.6. #ib#Rechtsbündig drucken#ie##ie(9)# +#goalpage("right")# +#free(1.0)# + #on("i")# + Mit der #ib#\#right\#-Anweisung#ie# können Sie einen Teil einer Absatzzeile rechtsbündig + drucken. + #off("i")# +#free(1.0)# + +Die \#right\#-Anweisung veranlaßt, daß der nachfolgende Text rechtsbündig gedruckt +wird. + +____________________________________________________________________________ + + \#head\# + \#center\#Diese Zeile wird zentriert\#right\#% + + \#end\# + +____________________________________________________________________________ + + + +Hierbei wird die Seitenzahl rechtsbündig gedruckt. + +Beachten Sie, daß die \#center\#- und die \#right\#-Anweisung zusammen verwendet +werden können. Beide Anweisungen wirken jedoch nur, wenn sie in einer Absatzzeile +stehen. + +#mark ("", "")# +#page# + +#ib(9)#5.6.7. #ib#Übereinander drucken#ie##ie(9)# +#goalpage ("b")# +#free(1.0)# + #on("i")# + Mit der #ib#\#b\#-Anweisung#ie# können Sie zwei Zeichen übereinander drucken. + #off("i")# + +#free(1.0)# +Die \#b\#-Anweisung veranlaßt, daß zwei aufeinanderfolgende Zeichen, die durch die +\#b\#-Anweisung verbunden sind, übereinander gedruckt werden. + + +____________________________________________________________________________ + +... 0\#b\#/ ... + +____________________________________________________________________________ + + + + +Druckbild: + +... 0#b#/ ... + + +Das Zeichen '/' wird über das Zeichen '0' gedruckt. 'lineform'/'autoform' nimmt für die +Zeilenberechnung nur ein Zeichen. Beachten Sie, daß direkt vor oder nach der +\#b\#-Anweisung keine Anweisung oder kein Blank stehen darf. +#mark ("", "")# +#page# + +#ib(9)#5.7. #ib#Textkosmetik-Makros#ie##ie(9)# +#free(1.0)# + #on("i")# + #ib#Makros#ie# verkürzen Ihren Arbeitsvorgang bei immer wiederkehrenden Textteilen + und/oder Anweisungen. + #off("i")# +#free(1.0)# +Unter 'Makro' verstehen wir eine "große" Anweisung, die aus vielen kleinen besteht +und die Sie mit Hilfe des Makronamens aufrufen können. + +Textkosmetik-Makros kommen zum Einsatz bei: + +- immer wiederkehrenden Textteilen; +- immer wiederkehrenden Anweisungssequenzen; +- bei der Erstellung von Manuskripten, deren endgültige Form Sie anfänglich noch + nicht kennen oder die Sie noch ändern möchten; +- oder bei Folgen von direkten Drucker-Anweisungen, die bestimmte Leistungen + erbringen. + +Die Definition von einem oder mehreren #ib#Makros#ie# wird mit dem Editor vorgenommen. +Diese #ib#Makro-Datei#ie# wird dann geladen. Von diesem Augenblick an "kennen" 'line +form'/'autoform' und 'pageform'/'autopageform' die Makros, d.h. die Textzeilen und/ +oder Anweisungen, die sich unter dem #ib#Makronamen#ie# "verbergen". + +'lineform'/'autoform' beachtet die Anweisungen, die ggf. in den Makros enthalten sind. +Sie erscheinen jedoch nicht in der Datei. Erst 'pageform'/'autopageform' setzt diese in +die Druckdatei ein. +#page# + +#ib(9)#5.7.1. Ein Makro-Beispiel#ie(9)# +#free(1.0)# + #on("is")# + Hier wird Ihnen ein einfaches Beispiel für einen Briefkopf gezeigt. + #off("is")# +#free(1.0)# +Angenommen, Sie schreiben mit dem EUMEL-System Ihre Geschäftsbriefe. Sie +haben einen Drucker zur Verfügung, mit dem Sie auch die Briefköpfe erstellen kön +nen. Für den #ib#Briefkopf#ie# schreiben Sie ein Makro \#kopf\# in eine Datei "macro defini +tionen": + +____________________________________________________________________________ + + \#*kopf\# + \#type("fett und gross")\#Firmenname + \#type("fett")\#Softwareprodukte + \#type("klein")\#Straße + Stadt + \#type ("normal")\# + \#*macro end\# + +____________________________________________________________________________ + + +Der Name des Makros ist \#kopf\#. Beachten Sie, daß eine #ib#Makro-Definition#ie# mit dem +Namen des Makros beginnen muß. Der #ib#Makroname#ie# muß dabei mit einem #on("b")#*#off("b")# gekenn +zeichnet werden, um ihn von "normalen" Text-Anweisungen unterscheiden zu kön +nen. Jedes Makro wird mit einer \#*macro end\#-Anweisung beendet. Sie dürfen +mehrere Makros hintereinander in die Datei schreiben. + +Nun müssen Sie das so definierte Makro 'laden': + +____________________________________________________________________________ + + gib kommando: + #ib#load macros#ie# ("macro definitionen") + +____________________________________________________________________________ +#goalpage("load macros")##goalpage("list macros")# + + +Zur Kontrolle können Sie sich die geladenen Makros in das Notizbuch ausgeben +lassen: + +____________________________________________________________________________ + + gib kommando: + #ib#list macros#ie# + +____________________________________________________________________________ +#mark ("", "")# + + + +Nun haben Sie von jetzt an eine neue Anweisung (mit dem Namen \#kopf\#) zur Ver +fügung, mit der Sie einen Briefkopf in jeden Brief drucken können. Sie schreiben nun +folgenden Brief: + +____________________________________________________________________________ + + \#kopf\# + + Sehr geehrter Herr .... + + usw. + +____________________________________________________________________________ + + +Beachten Sie hierbei, daß das Makro in Ihrem Text als Anweisung ohne #on("b")#*#off("b")# steht. Der +#ib#Aufruf eines Makros#ie#, welches z.B. in einer von 'lineform' zu bearbeitenden Datei +steht, unterscheidet sich also nicht von einer "normalen" Textanweisung. + +Nachdem Sie mit 'lineform' den Brief zeilenweise formatiert haben, kontrollieren Sie +die formatierte Datei. Hier hat sich noch nichts verändert. Die neue Anweisung \#kopf\# +steht unverändert in der Datei. 'lineform' beachtet zwar alle Anweisungen und Text +zeilen eines Makros, setzt diese jedoch nicht in die Datei ein. Allerdings ist 'lineform' +nicht in der Lage, die \#type\#- und \#limit\#-Anweisungen eines Makros zu erkennen, +wenn es an erster Stelle in einer Datei steht und in dessen Definition gleich zu +Anfang diese Anweisungen korrekt aufgeführt sind. Stattdessen fragt 'lineform' an +fangs 'type' und 'limit' an. Das können Sie umgehen, indem Sie mittels 'CR' die +Abfrage in 'lineform' ignorieren. + +Nun formatieren Sie die Datei, die den Brief enthält, mit 'pageform'/'autopageform'. In +der Druckdatei ist nun die Anweisung \#kopf\# verschwunden. Dort stehen nun die +Zeilen des #ib#Makrorumpf#ie#es. 'pageform'/'autopageform' setzt die Zeilen des Makros in +die Druckdatei ein: + +____________________________________________________________________________ + + \#type("fett und gross")\#Firmenname + \#type("fett")\#Softwareprodukte + \#type("klein")\#Straße + Stadt + \#type ("normal")\# + + + Sehr geehrter Herr ... + usw. + + +____________________________________________________________________________ + + + +#on("b")##on("i")#Anmerkung:#off("b")##off("i")# +Makros, die den gleichen Namen haben, aber sich durch die Anzahl der Parameter +unterscheiden, sind nicht erlaubt. Es ist auch nicht gestattet, Makros innerhalb einer +Makro-Definition aufzurufen. + +Beachten Sie ferner, daß Makro-Texte so verwendet werden, wie sie mit 'load +macros' geladen werden. + +____________________________________________________________________________ + + \#*textanfang\# + \#limit(11.0)\# + \#block\# + \#pageblock\# + \#type("trium8")\# + \#*macro end\# + +____________________________________________________________________________ + + +Betätigen Sie in der Makro-Datei nach jeder Zeile die #taste1(" CR ")#-Taste (Absatz), dann +erhalten Sie nach jedem \#...\# einen Absatz, was zum Beispiel bei Kapitelüberschriften +wünschenswert ist, nicht jedoch bei kleineren Anweisungen, bei denen dann mitten im +Satz ein Absatz erschiene. In solchen Anwendungen sollten Sie Makros ohne Absätze +speichern. Beachten Sie ferner, daß aus programmtechnischen Gründen eine \#foot\#- +oder die abschließende \#end\#-Anweisung einer Fußnote nicht in einem Makro ent +halten sein darf. +#page# + +#ib(9)#5.7.2. Ein Beispiel mit #ib#Makro-Parameter#ie#n#ie(9)# +#free(1.0)# + #on("i")# + Makro-Parameter erlauben es Ihnen, immer wiederkehrende Textteile, die sich + nur geringfügig voneinander unterscheiden, zu erzeugen. + #off("i")# +#free(1.0)# +Ihnen fällt nun auf, daß Sie Ihr Makro noch etwas verbessern können. Sie möchten +das Datum mit in den Briefkopf aufnehmen. Somit editieren Sie Ihre Makro-Datei +folgendermaßen (beachten Sie die '$'-Zeichen): + +____________________________________________________________________________ + + \#*kopf ($1)\# + \#type("gross")\#Firmenname + \#type("fett")\#Softwareprodukte + \#type("klein")\#Straße + Stadtname + \#type ("normal")\# + + Stadtname, den $1 + \#*macro end\# + +____________________________________________________________________________ + + +Damit haben Sie dem \#kopf\#-Makro einen Parameter gegeben: '$1'; die Parameter +werden numeriert. Ein zweiter Parameter würde '$2' heißen usw.. + +Bei der Erstellung eines Briefes müssen Sie die Anweisung \#kopf\# mit dem jeweiligen +Datum in einen Brief schreiben: + +____________________________________________________________________________ + + \#kopf ("20.8.1986")\# + +____________________________________________________________________________ + + +'pageform'/'autopageform' setzt nun das angegebene Datum direkt hinter 'Stadtname, +den' in den Briefkopf ein (in der Druckdatei). Beachten Sie, daß alle Parameter einer +Makro-Anweisung in Anführungszeichen stehen müssen (auch Zahlen). +#page# + +#ib(9)#5.7.3. #ib#Makros für Manuskripte#ie##ie(9)# +#free(1.0)# + #on("i")# + Hier wird gezeigt, wie Sie mit Makros Anweisungen formulieren können, die + aussagen, um was es sich bei einem Text handelt, und nicht, in welchem Format + er gedruckt wird. + #off("i")# +#free(1.0)# +Bei Manuskripten für Artikel, Bücher und Manuals wissen Sie oft vorher nicht, in +welchem Format das Manuskript gedruckt werden wird. Zu diesem Zweck ist es +ebenfalls nützlich, Makros zu verwenden. + +____________________________________________________________________________ + + \#*kapitelanfang ($1)\# + \#free (2.0)\# + \#type ("gross")\#\#ib (9)\#$1\#ie (9)\#\#type ("normal")\# + + \#*macro end\# + +____________________________________________________________________________ + + +In diesem Beispiel wird ein Makro für den Anfang eines Kapitels definiert. Zwischen +zwei Kapiteln sollen hier zwei Zentimeter Zwischenraum bleiben, die Kapitel- +Überschrift (als Parameter) wird in einer größeren Schrift gedruckt. Zusätzlich wird die +Überschrift für ein Inhaltsverzeichnis in den 9. Index aufgenommen. Nach der Über +schrift wird eine Leerzeile eingeschoben, bevor der eigentliche Text anfängt. + +Der Anwender dieses Makros schreibt also z.B. folgende Anweisung: + +____________________________________________________________________________ + + \#kapitelanfang ("Ein Beispiel fuer Manuskripte")\# + +____________________________________________________________________________ + + + +Beachten Sie, daß die Kapitel-Überschrift nicht länger als eine Textzeile sein darf. +Das liegt daran, daß 'lineform'/'autoform' zwar die Zeile bearbeitet, aber nicht in den +Text einsetzt. 'pageform'/'autopageform' setzt also die unveränderte - nicht umge +brochene - Textzeile ein. + +Sie können nun Makros für die meisten Textstrukturen definieren. Schreibkräfte +brauchen dann in der Regel die meisten Text-Anweisungen nicht zu kennen, son +dern nur noch eine Anzahl von einfachen Makro-Anweisungen. + +Die Makro-Definitionen können jederzeit geändert werden, um wechselnden Bedürf +nissen angepaßt zu werden, z.B. wenn ein Verlag ein bestimmtes Schreibformat +verbindlich vorschreibt. In diesem Fall brauchen nicht alle Text-Dateien geändert zu +werden, sondern nur die Makro-Definitionen. + +Ein weiterer Vorteil einer solchen Vorgehensweise ist, daß die Makro-Anweisungen in +diesem Fall angeben, #on("i")##on("b")#was#off("i")##off("b")# eine bestimmte Text-Struktur ist, und nicht, #on("i")##on("b")#wie#off("i")##off("b")# die +Struktur behandelt werden soll. + +#on("b")#Anmerkung#off("b")#: +In eine Makro-Definition sollten Sie ggf. \#limit\#-, \#type\#- und \#linefeed\#- +Angaben einsetzen, um die Makros unabhängig von der Aufrufstelle zu machen. Ggf. +sollten Sie auch die Datei vorher mit 'lineform' bearbeiten, um Trennungen vorzu +nehmen. +#page# + +#ib(9)#5.8. Textkosmetik für Spezialisten#ie(9)# +#free(1.0)# + #on("i")# + In diesem Abschnitt werden Ihnen Kommandos und Anweisungen vorgestellt, die + in der Regel nur für Spezialfälle benötigt werden. + #off("i")# +#free(1.0)# + +#ib(9)#5.8.1. Schalter-Anweisungen für + #ib#Kopf- und Fußbereiche#ie(1, "Schalter-Anweisungen für")##ie(9)# +#goalpage("head off")##goalpage("bottom off")# +#free(1.0)# + +Mit den Textkosmetik-Anweisungen + +____________________________________________________________________________ + + #ib#\#head off\##ie# + + #ib#\#bottom off\##ie# + +____________________________________________________________________________ + + + +können Sie die Erzeugung von Kopf- oder Fußzeilen abschalten. Mit + + +____________________________________________________________________________ + + #ib#\#head on\##ie# + + #ib#\#bottom on\##ie# + +____________________________________________________________________________ + + +können Sie diese wieder erzeugen. Beachten Sie, daß diese Anweisungen an der +Stelle beachtet werden, an der sie im Text stehen, d.h. diese Anweisungen gelten +bereits für die Seite, auf der sie sich bei der 'pageform'-Bearbeitung befinden. Möch +ten Sie die Kopfzeilen für eine Seite abschalten, dann sollten Sie an dieser Stelle die +#ib#\#head off\#-Anweisung#ie# geben. Um die Kopfzeilen für die nächste Seite wieder einzu +schalten, sollten Sie die #ib#\#head on\#-Anweisung#ie# an einer Stelle plazieren, von der Sie +sicher sind, daß sie auf die folgende Seite gelangt (im Zweifelsfall nach einer +\#page\#-Anweisung). +#mark ("", "")# +#page# + +#ib(9)#5.8.1.1. #ib#Kopf- und Fußbereiche abstellen#ie##ie(9)# +#goalpage ("first head")##goalpage("last bottom")# +#free(1.0)# + #on("i")# + Mit '#ib#first head#ie#' bzw. '#ib#last bottom#ie#' können Sie Kopf- oder Fußbereiche auf der + ersten (letzten) Seite ab- oder wieder anschalten. + #off("i")# +#free(1.0)# +Manchmal ist es notwendig, die Erzeugung von 'head'-Zeilen auf der ersten Seite +(z.B. weil dort ein Briefkopf erscheint) und/oder 'bottom'-Zeilen auf der letzten Seite +(weil keine Folgeseite existiert) zu verhindern. Mit dem Monitor-Kommando + +____________________________________________________________________________ + + gib kommando: + #ib#first head (FALSE)#ie# + +____________________________________________________________________________ + + +können Sie bei 'pageform' die Erzeugung von 'head'-Zeilen auf der ersten Seite +jeder Druckdatei abschalten. Die Erzeugung bleibt so lange abgeschaltet, bis sie +wieder durch + +____________________________________________________________________________ + + gib kommando: + #ib#first head (TRUE)#ie# + +____________________________________________________________________________ + + +angeschaltet wird. Das gleiche gilt analog für 'bottom'-Zeilen auf der letzten Seite: +Ein- und Ausschalten durch + +____________________________________________________________________________ + + gib kommando: + #ib#last bottom (FALSE)#ie# + +____________________________________________________________________________ +#mark("","")# + +bzw. + +____________________________________________________________________________ + + gib kommando: + #ib#last bottom (TRUE)#ie# + +____________________________________________________________________________ +#page# + +#ib(9)#5.8.2. Textzeilen markieren#ie(9)# +#goalpage("mark")# +#free(1.0)# +Mit der Anweisung + + +____________________________________________________________________________ + + \#mark("markierungszeichen links","markierungszeichen rechts")\# + +____________________________________________________________________________ + + + +können Sie einen Textabschnitt an den Rändern (außerhalb des Schreibfeldes!) mit +Texten markieren, wie z.B. im folgenden mit der Anweisung + +#mark ("", "")# + +____________________________________________________________________________ + + \#mark ("> ", " <")\# + +____________________________________________________________________________ + + +#mark ("> ", " <")# +Dabei gilt der erste Parameter für den linken und der zweite für den rechten Rand. +Beachten Sie, daß Sie einen genügenden Zwischenraum zwischen der Markierung +und dem Rand mit angeben müssen. + +Die Markierung ist insbesondere für Manuals interessant, wo Änderungen gegen +über der letzten Version hervorgehoben werden. Das Markierungszeichen wird neben +den linken und rechten Rand gedruckt (also außerhalb des von \#start\# und \#limit\# +begrenzten Textfeldes). Für das Drucken der Markierung wird der/die Schrifttyp/ Modi +fikationen benutzt, die an der Stelle der \#mark\#-Anweisung eingeschaltet ist. Der +eigentliche Text bleibt selbstverständlich unberührt. +#mark ("", "")# + +Um nur einen Rand zu markieren, kann auch ein leerer Parameter angegeben +werden. + +____________________________________________________________________________ + + \#type ("pica")\#\#mark ("", " |")\#\#type ("normal")\# + +____________________________________________________________________________ + + + +Mit der speziellen #ib#\#mark\#-Anweisung#ie# + +____________________________________________________________________________ + + \#mark ("", "")\# + +____________________________________________________________________________ + + +wird die Markierung ausgeschaltet. + +Soll ein Kopf-, Fuß-, Fußnoten- oder Tabellenbereich markiert werden, sollten sich +die Markierungsein- und ausschalt-Anweisungen vollständig in dem Bereich be +finden. +#page# + +#ib(9)#5.8.3. #ib#Fußnoten pro Seite zählen#ie##ie(9)# +#goalpage("countperpage")# +#free(1.0)# +Manchmal wird gewünscht, daß die Fußnoten für jede Seite separat - also für jede +Seite von 1 ab - gezählt werden. Das können Sie mit der Textkosmetik-Anweisung + + +____________________________________________________________________________ + + \#count per page\# + +____________________________________________________________________________ + + +erreichen. Sie schaltet von einer fortlaufenden Zählung auf eine seitenweise Zählung +um. Diese Anweisung sollte am Dateianfang stehen. Sie kann für die betreffende +Datei nicht mehr abgeschaltet werden. +#page# + +#ib(9)#5.8.4. Behandlung falscher #ib#Silbentrennungen#ie(1, ", Behandlung von falschen")#: + #ib#Ausnahmelexikon#ie##ie(9)# +#free(1.0)# + #on("i")# + In das Ausnahmelexikon können fehlerhaft getrennte Worte aufgenommen + werden. + #off("i")# +#free(1.0)# +Es kann vorkommen, daß das Silbentrenn-Programm der Textkosmetik einige Worte +immer wieder falsch trennt. Um dies zu vermeiden, können Sie diese Worte in ein +#on("b")##on("i")#Ausnahmelexikon#off("b")##off("i")# speichern. Die Worte des Ausnahme-Lexikons werden bei einer +Silbentrennung zuerst durchsucht. Wird ein Wort im Lexikon gefunden, dann wird das +eigentliche Silbentrenn-Programm nicht mehr ausgeführt. + +Die Ausnahmen müssen Sie - wie unten beschrieben - in einer Datei notieren und +mit dem Monitor-Kommando + +____________________________________________________________________________ + + gib kommando: + #ib#lade ausnahmen#ie# ("dateiname") + +____________________________________________________________________________ +#goalpage("lade ausnahmen")# + + +in das Lexikon laden. Die Ausnahmen müssen Sie folgendermaßen in die Datei +schreiben: + +____________________________________________________________________________ + + Sprech-stun-de + ins-be-son-de-re + Raum + Bei-spiel + ... + +____________________________________________________________________________ + + +Sie können jederzeit neue Ausnahmen in das Lexikon hinzuladen (wiederum mit 'lade +ausnahmen'). In diesem Fall wird angefragt, ob das Lexikon überschrieben werden +soll. + + + +Um zu kontrollieren, welche oder wie viele Ausnahmen sich im Lexikon befinden, +können Sie + +____________________________________________________________________________ + + gib kommando: + #ib#entlade ausnahmen#ie# ("dateiname") + +____________________________________________________________________________ + #goalpage("entlade ausnahmen")# + +geben. Das Lexikon wird dann in "dateiname" geschrieben. Auch hier können Sie +weitere Ausnahmen hinzufügen und diese neu laden (aber diesmal überschreiben). +#mark ("", "")# +#page# + +#ib(9)#5.8.5. #ib#Voreinstellungen ändern#ie#: + Einige Monitor-Kommandos#ie(9)# +#free(1.0)# +#ib(9)#5.8.5.1. Wenige oder viele #ib#Silbentrennung#ie#en: + #ib#Trennpunkt einstellen#ie##ie(9)# +#goalpage ("hyphenation width")# +#free(1.0)# + #on("i")# + Mit dem Kommando 'hyphenation width' können Sie bestimmen, an welchem + Punkt Worte zur Trennung angeboten werden. Die Trennbreite können Sie + zwischen 4 und 20 Prozent der Zeilenbreite einstellen. + #off("i")# +#free(1.0)# +Viele Silbentrennungen in einem Text erschweren das Lesen. Nehmen Sie keine +Silbentrennungen vor, wird der rechte Rand stark "ausgefranst" oder beim Blocksatz +("rechter Randausgleich") müssen viele Zwischenräume zwischen den Worten ein +gefügt werden. Durch das Monitor-Kommando + +____________________________________________________________________________ + + gib kommando: + #ib#hyphenation width#ie# (prozentuale angabe) + +____________________________________________________________________________ + + +unmittelbar vor dem Aufruf von 'autoform' oder 'lineform' können Sie den Punkt, an +dem die Silbentrennung einsetzen soll, einstellen. Die Klammern enthalten eine ganze +Zahl, die für Prozent der Zeilenbreite steht. Minimum sind 4, Maximum 20 Prozent. +Beispielsweise stellt 'hyphenation width (5)' den Trennpunkt auf 5% der Zeilenbreite +ein (voreingestellt ist 7). Bei einer Angabe von 20 werden somit sehr wenige Worte +zur Silbentrennung angeboten, d.h. je größer die Prozentangabe, desto weniger Worte +werden zur Trennung angeboten. Die Einstellung des Trennpunktes bestimmt also, ab +wann ein Wort zur Silbentrennung untersucht wird. Andererseits bestimmt die Ein +stellung auch, wieviel Zwischenraum zwischen Worten eingefügt werden muß, um +einen rechten Randausgleich zu erzielen. +#page# + +#ib(9)#5.8.5.2. Anzahl #ib#Leerzeilen vor Fußnoten#ie# + einstellen#ie(9)# +#goalpage("number empty")# +#free(1.0)# + #on("i")# + '#ib#number empty lines before foot#ie#' stellt die Anzahl der Leerzeilen vor Fußnoten ein. + #off("i")# +#free(1.0)# +Die Anzahl der Leerzeilen vor #ib#Fußnoten#ie(1, ", Leerzeilen davor")# (voreingestellt ist eine Leerzeile) können Sie +durch das Monitor-Kommando 'number empty lines before foot' einstellen. + + + +____________________________________________________________________________ + + gib kommando: + number empty lines before foot (3) + +____________________________________________________________________________ + + +stellt drei Leerzeilen vor dem Fußnotenblock ein. Beachten Sie, daß diese Einstellung +so lange gilt, bis Sie das Monitor-Kommando erneut geben. +#mark("","")# + diff --git a/doc/user-manual/1.8.7/doc/benutzerhandbuch.5d b/doc/user-manual/1.8.7/doc/benutzerhandbuch.5d new file mode 100644 index 0000000..8a61f29 --- /dev/null +++ b/doc/user-manual/1.8.7/doc/benutzerhandbuch.5d @@ -0,0 +1,211 @@ +#start(5.0,1.5)##pagenr("%",116)##setcount(1)##block##pageblock##count per page# +#headeven# +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# + EUMEL-Benutzerhandbuch +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#headodd# +#lpos(0.0)##cpos(5.5)##rpos(11.0)##fillchar(" ")# +#table# + Teil 5: Textkosmetik und Druck +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#bottomeven# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +5 - % GMD +#tableend##clearpos# +#end# +#bottomodd# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +GMD 5 - % +#tableend##clearpos# +#end# + +#ib(9)#5.9. Übersicht über die Anweisungen und + Kommandos der EUMEL-Textkosmetik#ie(9)# +#free(1.0)# + #on ("i")# + Zuerst werden die am häufigsten benutzten Kommandos/Anweisungen beschrie + ben. Danach sind (durch einen Strich getrennt) Kommandos/Anweisungen auf + geführt, die seltener benötigt werden. + #off ("i")# +#free(1.0)# +#on("b")# +#ib#Kommandos#ie##off("b")# +#free(1.0)# + #on("i")# + Kommandos werden im Monitor gegeben ('gib kommando :'). + #off("i")# +#free(1.0)# +#lpos(0.0)##lpos(4.6)# +#table# +#on("b")#Kommando Bedeutung#off("b")# +#free(1.0)# +#clearpos# +#lpos(0.0)##lpos(4.6)# +lineform ("x") Formatieren von Zeilen mit interaktiver Silben + trennung. +autoform ("x") Wie lineform, jedoch werden Silbentrennungen + automatisch vorgenommen. +pageform ("x") Interaktives Formatieren von Seiten, mit Behand + lung von Fußnoten, Kopf- und Fußzeilen, Seiten + numerierung, Seitenquerverweisen usw. Erzeugt + eine Druckdatei (Zusatz '.p'). +autopageform ("x") Wie pageform, jedoch werden die Seitengrenzen + automatisch plaziert. +print ("x") Datei drucken. +print ("x.p") Eine mit 'pageform' bearbeitete Datei drucken. +---------------- ---------------- +#page# +index ("x.p") Erstellt aus einer Druckdatei ein Stichwort- + und/oder Inhaltsverzeichnis. +index merge ("a.i1","b.i1") Führt Indexdateien zusammen. +outline ("x") Erstellt eine Übersicht aus Kapitelüberschriften + und Stichworten. +hyphenation width (int) Stellt die Trennbreite für die Silbentrennung ein. +load macros ("x") Lädt Makros. +list macros Zeigt geladene Makros. +lade ausnahmen ("x") Lädt Wörter, die von der Trennhilfe nicht korrekt + getrennt werden, in einen Ausnahme-Speicher. +entlade ausnahmen ("x") Entlädt die Worte aus dem Ausnahme-Speicher + in die angegebene Datei. +first head (false) Schaltet Kopfzeilen auf erster Seite aus. +first head (true) Schaltet Kopfzeilen auf erster Seite wieder ein. +last bottom (false) Schaltet Fußzeilen auf letzter Seite aus. +last bottom (true) Schaltet Fußzeilen auf letzter Seite wieder ein. +number empty lines before foot Stellt die Anzahl der Leerzeilen vor einer Fußnote +before foot ein. +#tableend##clearpos# +#page# +#on("b")# +#ib#Anweisungen#ie##off("b")# +#free(1.0)# + #on ("i")# + Anweisungen werden in die Datei geschrieben. Jede Anweisung muß in Anwei + sungszeichen eingeschlossen werden. Als Parameter (diese werden in Klammern + eingeschlossen) kommen in Frage: + 'int' bedeutet eine ganze Zahl: 17, 1, 311; + 'real' bedeutet eine Zahl mit Dezimalpunkt (meist cm-Angabe): 0.5, 1.25; + 'text' bedeutet eine Zeichen-Angabe. Muß in Anführungszeichen eingeschlos + sen werden: "%", "meine datei". + #off ("i")# +#free(1.0)# +#lpos(0.0)##lpos(4.6)# +#table# +#on("b")#Anweisung Bedeutung#off("b")# +#clearpos# +#lpos(0.0)##lpos (4.6)# + +type (text) Schrifttyp einstellen: \#type("trium8")\# +limit (real) Zeilenbreite einstellen: \#limit (16.0)\# +on (text) Modifikation einschalten: \#on("bold")\#. Erlaubt + sind: b(bold), r(everse), i(talic), u(nderline) +off (text) Modifikation ausschalten (siehe 'on'). +block Blocksatz (Randausgleich) einschalten. +head Kopfzeilen (für Seiten mit geraden/ungeraden +(bzw. headeven/headodd) Seitennummern) definieren. +... -%- Platzhalter für Seitenzahl. +end Kopfzeilen-Ende (pageform). +bottom Wie oben, jedoch für Fußzeilen. +(bzw. +bottomeven/bottomodd) +... +end Fußzeilen-Ende +pagenr (text, int) Seitennummer einstellen bzw. zusätzliches Sei + enzeichen ab nächster Seite einführen: + \#pagenr ("%", 17)\# +foot Fußnoten-Anfang. +... +end Fußnoten-Ende. +free (real) Platz freihalten (in cm): \#free (1.27)\# +page Neue Seite: \#page\# +page (int) Neue Seite mit Seitennummer 17: \#page (17)\# +linefeed (real) Zeilenhöhe relativ zum eingeschalteten Schrifttyp + verändern: \#linefeed (1.25)\# +pagelength (real) Seitenlänge einstellen (ab nächster Seite in cm): + \#pagelength (24.0)\# Nachfolgenden Zeilentext +center zentriert drucken. +right Nachfolgenden Zeilentext rechtsbündig drucken. +u ... e (steht für up) Exponent schreiben: \#u\#123\#e\# +d ... e (steht für down) Index schreiben. +start (real, real) Schriftfeld (linke obere Ecke) einstellen: \#start + (1.0, 2.0)\# +------------ ------------ +b Zwei Zeichen übereinander drucken. +bottom off Schaltet Fußzeilen aus. +bottom on Schaltet Fußzeilen ein. +bpos (real, real) Der Text zwischen den angegebenen Tabellen + positionen wird im Blocksatz gedruckt. +clearpos Löscht alle Tabellenpositionen. +clearpos (real) Löscht die angegebene Tabellenposition. +columns (int, real) Formatieren von Spalten mit Zwischenraum: + \#columns (3, 1.0)\#, 3 Spalten mit 1 cm Zwischen + raum. +columnsend Beendigung der Spaltenformatierung. +count Interner Zähler für Fußnoten wird eingesetzt + (pageform). +count (text) Wie oben, aber der Wert des internen Zählers + wird vermerkt: \#count ("neue Zahl")\# +count per page Interner Zähler beginnt bei jeder Seite mit 1. +cpos (real) Zentrierende Tabellenposition. +dpos (real, text) Um den angegebenen Text zentrierende Tabel + lenposition, meist Dezimalzeichen: + \#dpos (13.0, 2.")\# +fillchar (text) Zwischenräume zwischen Tabellenpositionen wer + den mit dem angegebenen Text beim Drucken + ausgefüllt. Beachten Sie, daß das Ausschalten der + Füllzeichen durch 'niltext' erfolgt. +goalpage (text) Stelle, auf die obige Anweisung verweist: \#goal + page ("1.Kapitel")\# +head off Schaltet Kopfzeile(n) aus. +head on Schaltet Kopfzeile(n) ein. +ib Anfang eines Stichworts oder einer Kapitel + überschrift kennzeichnen (Ablegen in Indexdatei + mit Zusatz '.i1'): \#ib\#ein Stichwort oder eine + Kapitelüberschrift\#ie\# +ib (int) Wie oben, jedoch wird Stichwort in angegebener + Indexdatei abgelegt. +ib (int, text) Wie oben, jedoch erhält Eintrag in der Indexdatei + den angegebenen Text an die Seiten + nummer angefügt. +ie Beendigung der Stichwortmarkierung. +ie (int) Wie oben (int-Angabe muß der in der ib-An + weisung entsprechen). +ie (int, text) Wie oben, jedoch wird die Textangabe hinter das + markierte Stichwort angefügt. +lpos (real) Linksbündige Tabellenposition. +mark (text, text) Markierung rechts und links neben der Schreib + fläche ein-/ausschalten. +pageblock Einschalten des vertikalen Blocksatzes. Falls ein + geschaltet, kann mit 'pageform' auch über das + (rechnerische) Seitenende formatiert werden. +rpos (real) Rechtsbündige Tabellenposition. +setcount (int) Zählerwert setzen: \#setcount (17)\# +table Anfang einer Tabelle. +... +table end Ende einer Tabelle. +topage (text) Seitenverweis (die Seitennummer, auf die verwie + sen wird, wird eingesetzt): + \#topage ("1.Kapitel")\# +value Letzter Zählerwert wird eingesetzt. +value (text) Wie oben, jedoch wird ein vermerkter Zählerwert + eingesetzt: \#value ("Vermerk")\# +#tableend# + diff --git a/doc/user-manual/1.8.7/doc/benutzerhandbuch.5e b/doc/user-manual/1.8.7/doc/benutzerhandbuch.5e new file mode 100644 index 0000000..d515c6a --- /dev/null +++ b/doc/user-manual/1.8.7/doc/benutzerhandbuch.5e @@ -0,0 +1,223 @@ +#start(5.0,1.5)##pagelength(17.4)##pagenr("%",121)##setcount(1)##block##pageblock##count per page# +#headeven# +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# + EUMEL-Benutzerhandbuch +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#headodd# +#lpos(0.0)##cpos(5.5)##rpos(11.0)##fillchar(" ")# +#table# + Teil 5: Textkosmetik und Druck +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#bottomeven# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +5 - % GMD +#tableend##clearpos# +#end# +#bottomodd# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +GMD 5 - % +#tableend##clearpos# +#end# + +#ib(9)#5.10. Fehlersituationen und Abhilfe#ie(9)# + +#free(1.0)# +Was können Sie machen, wenn + + +... bestimmte Anweisungen, die den Gesamttext betreffen, erst ab der zweiten + Seite wirksam werden? + + + Textkosmetik-Anweisungen, die ab der ersten Seite für den ganzen Text gelten + sollen, müssen Sie als erstes, d.h. in die erste Zeile einer Datei, schreiben. Dies + bezieht sich u.a. auf 'pagelength', 'start', 'block', 'pageblock' etc., die noch vor + \#head\#- oder \#bottom\#-Anweisungen gesetzt werden müssen. + + + + +... sich der Cursor nicht mehr bewegen läßt? + + + Eine Möglichkeit besteht darin, daß Sie versehentlich die 'STOP' -Taste + (='CTRL a' gleichzeitig, d.h. Anhalten der Bildschirmausgabe) betätigt haben. + In diesem Fall drücken Sie die 'WEITER' -Taste ('CTRL c' gleichzeitig, d.h. + Bildschirmausgabe fortführen). Alle Tastenanschläge, die Sie in der Zwischen + zeit vollzogen haben, werden jetzt ausgeführt. + + Eine andere Möglichkeit wäre, daß Sie Ihre Datei/Task nicht ordnungsgemäß + verlassen haben. Versuchen Sie über die 'SV'-Taste und 'ESC h' wieder auf + die Monitor-Ebene zu gelangen, so daß Sie dann auf die Aufforderung 'gib + kommando' hin, wieder in Ihre Datei gelangen können. + + + + +... Sie nur einen Dateiausschnitt löschen, duplizieren oder mit 'lineform' bearbeiten + möchten? + + + Der betreffende Ausschnitt muß markiert werden. Zum Löschen benutzen Sie + die Tasten 'ESC RUBOUT'. Der Ausschnitt ist hiermit aber noch nicht 'voll + ständig verschwunden', sondern Sie können ihn mit 'ESC RUBIN' an gleicher + oder anderer Stelle wieder hervorbringen, so lange bis Sie die Tasten erneut + benutzen. + + Das Duplizieren eines Textbereiches erfolgt nach dem Markieren durch das + Betätigen der Tastenfolge 'ESC d'. Hierbei bleibt der Originaltext erhalten und + kann beliebig oft dupliziert werden. Den duplizierten Text holen Sie sich mit + 'ESC g' an die gewünschte Stelle in Ihrer Datei. + + Möchten Sie 'lineform' nur auf einen Ausschnitt anwenden, markieren Sie + diesen und geben nach 'ESC ESC' das Kommando 'lineform'. + + + + +... beim Drucken die letzte bzw. die letzten beiden Zeilen auf einer gesonderten + Seite ausgedruckt werden? + + + a) Sie müssen die Fonttabelle noch einrichten. + + oder + + b) Sie setzen die \#pageblock\#-Anweisung zu Beginn des Textes und "stau + chen" um zwei Zeilen. + + oder + + c) Sie wählen eine kleineren Schrifttyp. + + + + +... in Ihrer Datei die Meldung + + _______________________________________________________________________ + + FEHLER: FILE-Überlauf + + gib kommando: + edit ("dateiname") + + _______________________________________________________________________ + + erscheint und das Abschicken des Kommandos mittels der 'CR'-Taste aber nur + zu einer identischen Meldung (siehe oben) führt? + + + Wenn Sie auf dem oben dargestellten Weg nach mehrmaligem Versuchen nicht + wieder in Ihre Datei gelangen, haben Sie die Möglichkeit, mit dem Kommando + + _______________________________________________________________________ + + gib kommando: + reorganize ("dateiname") + + _______________________________________________________________________ + + + Ihre Datei neu zu 'organisieren', um 'Lücken', die durch Einfügen oder Löschen + entstanden sind, zu eliminieren. Die Datei beansprucht dann in der Regel auch + weniger Speicherplatz. + + Sind Sie wieder in Ihrer Datei, empfiehlt es sich, die große Datei in mehrere + kleine aufzuteilen. Entweder Sie halbieren oder (besser) Sie dritteln Ihre Text + datei und verteilen den Text auf zwei bis drei Dateien. Zukünftig sollten Sie es + sich dann bei umfangreichen Texten zur Regel machen, nur ein logisch + zusammenhängendes Kapitel in einer Datei abzulegen. Sie sollten Ihre Datei nur + so groß halten, daß Ihnen noch genügend Raum zur Verfügung steht, Proze + duren wie z.B. 'pageform' durchzuführen, durch die sich der Umfang einer Datei + (z.T. wesentlich) vergrößert. + + + + +... bei Ihrem Text einige Wörter mit extrem großem Zwischenraum gedruckt + wurden? + + + Sie haben in diesem Fall wahrscheinlich vergessen, die Absatzmarkierung zu + setzen, so daß aufgrund der \#block\#-Anweisung ein rechter Randausgleich + erfolgte, den Sie an dieser Stelle nicht wünschten. + + + + +... eine Überschreibung erfolgt ist bzw. wenn 'lineform' eine Überschreibung + meldet? + + + Eine solche Überschreibung kann auftreten, wenn Sie mit einer besonders + großen Type in Fettdruck (z.B. triumb14) schreiben (vgl. Sie hierzu auch Kapitel + 5.2.6.). Um dies zu verhindern, können Sie zum einen die Anzahl der Blanks + zwischen den einzelnen Gliedern erhöhen oder zum anderen auch die + \#type\#-Anweisung in die vorhergehende Zeile setzen (n i c h t direkt v o r den + betreffenden Text). + + + + +... nach der erfolgten Prozedur 'lineform' Ihre Tabellen durcheinander geraten + sind? + + + Wenn Sie Tabellen schreiben, müssen Sie nach jeder Zeile die Absatzmarke + setzen. Sollen bei einigen Tabellenpositionen Spalten leer bleiben, müssen Sie + für diese Positionen ein geschütztes Blank einsetzen. + + + + +... bei der Prozedur 'pageform' das Seitenende nicht interaktiv verschoben werden + kann, obwohl am Anfang der Datei eine \#pageblock\#-Anweisung gegeben + wurde? + + + Eine \#page\#-Anweisung im Text bewirkt, daß Sie an dieser Stelle das Seiten + ende nur bestätigen, die Anweisung löschen oder als dritte Möglichkeit, die + Seitenformatierung abbrechen können. Für den Fall, daß die \#page\#- + Anweisung nicht mehr zutrifft bzw. falsch gesetzt wurde, sollten Sie die Anwei + sung löschen und das Seitenende interaktiv plazieren. + + + + +... Sie bei der Erstellung eines Inhaltsverzeichnisses oder eines Indexes keine + Füllzeichen zwischen Text und Seitenangabe haben möchten? + + + In diesem Fall gehen Sie mit 'ESC ESC' in den Kommandozustand und ändern + mit Hilfe von CA (Change All) die Füllzeichen in Leerzeichen um. Verwenden + Sie nicht nur einen Punkt, da sonst auch die Punkte zwischen den Ziffern der + Kapitelnumerierung verschwänden. Es kann bei einer ungeraden Anzahl von + Füllzeichen notwendig sein, nachträglich noch einige Punkte entfernen zu + müssen. + + _______________________________________________________________________ + + gib kommando: ".." CA " " + + _______________________________________________________________________ + diff --git a/doc/user-manual/1.8.7/doc/benutzerhandbuch.6 b/doc/user-manual/1.8.7/doc/benutzerhandbuch.6 new file mode 100644 index 0000000..5e035d2 --- /dev/null +++ b/doc/user-manual/1.8.7/doc/benutzerhandbuch.6 @@ -0,0 +1,474 @@ +#start(5.0,1.5)##pagenr("%",1)##setcount(1)##block##pageblock##count per page# +#headeven# +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# + EUMEL-Benutzerhandbuch +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#headodd# +#lpos(0.0)##cpos(5.5)##rpos(11.0)##fillchar(" ")# +#table# + Teil 6: Spezialitäten +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#bottomeven# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +6 - % GMD +#tableend##clearpos# +#end# +#bottomodd# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +GMD 6 - % +#tableend##clearpos# +#end# + +#kap("TEIL 6: Spezialitäten")# +#free(1.0)# + +6.1. Notizbuch +#free(1.0)# + Das Notizbuch erlaubt es u.a., Fehlermeldungen zwischenzeitig zu speichern und + am Ende einer Verarbeitung die Fehlermeldungen zusammen mit dem bearbeiteten + Text im Fenstereditor anzuzeigen. +#free(1.0)# +Das #ib#Notizbuch#ie# wird von den Programmen 'lineform' und 'pageform' zum Sammeln +von Warnungen und Fehlermeldungen verwendet. Wenn das Fenster des Notizbuches +an Bildschirm eröffnet ist, können Sie es handhaben wie das gewohnte Editorfenster. + +Falls Sie das Notizbuch selbst beim Editieren für Notizen verwenden möchten, drük +ken Sie statt <ESC> <e> für den Fenstereditor die Tasten <ESC> <n> an beliebiger +Stelle des Bildschirms. Durch dieses Kommando wird das Notizbuch statt einer Datei +gezeigt. Sie sparen somit die Eingabe eines Dateinamens und können direkt mit allen +vorgestellten Editorfunktionen im Notizbuch arbeiten. + + +#page# +____________________________________________________________________________ + ................ handbuch teil6 .............. Zeile 56 +\#kap("6.2. EUMEL-Zeichensatz")\# +\#free(1.0)\# +\#zus\# + \#corner1("-5.0")\# + Das EUMEL-System definiert einen Zeichensatz, der gewähr + auf allen Maschinen überall gleich codiert werden. Dadurch ist + Dateien und Programme ohne Konvertierungen zwischen EUMEL-Syst + unterschiedlicher Hersteller zu übertragen. Der \#ib\#EUMEL- + dem ASCII-Zeichensatz (DIN 66 003) mit Erweiterungen. + \#box3("T","2","115.0")\# + + ................. notebook ................... Zeile 1 +FEHLER Zeile 55: Modifikation nicht angeschaltet bei off: b + >>> Anweisung in angegebener Zeilennummer überprüfen +WARNUNG Zeile 55: Umschaltung auf gleichen Schrifttyp: trium8 + >>> Schrifttyp wurde darum nicht verändert! +WARNUNG Zeile 75: Überschreibung nach >\#ib(9)\#6.2.< Fehlende + >>> Bitte fehlende Leerzeichen einfügen + +____________________________________________________________________________ +#page# +6.2. EUMEL-Zeichensatz +#free(1.0)# + + + Das EUMEL-System definiert einen Zeichensatz, der gewährleistet, daß Zeichen + auf allen Geräten gleich codiert werden. Dadurch ist es z.B. möglich, Dateien und + Programme ohne Konvertierungen zwischen EUMEL-Systemen unterschiedlicher + Hersteller zu übertragen. Der #ib#EUMEL-Zeichensatz#ie# beruht auf dem ASCII- + Zeichensatz (DIN 66 003) mit Erweiterungen. + +#free(1.0)# + +Die Darstellung der einzelnen Zeichen hängt vom Endgerät ab. Die hier aufgeführten +Zeichen sind i.A. auf allen Geräten vorhanden. Ein erweiterter Zeichensatz (mit ma +thematischen, diakritischen und griechischen Zeichen) ist nur auf Spezialgeräten +verfügbar und wird deshalb hier nicht angegeben. +#page# +Beispiele zum Lesen der Tabelle: + + code (" ") -> 32 + code ("m") -> 109 + | 0 1 2 3 4 5 6 7 8 9 +--+---------------------------------------- +3 | SP ! " \# $ % & ' + | +4 | ( ) * + , - . / 0 1 + | +5 | 2 3 4 5 6 7 8 9 : ; + | +6 | < = > ? § A B C D E + | +7 | F G H I J K L M N O + | +8 | P Q R S T U V W X Y + | +9 | Z [ ��\� ] ^ _ ` a b c + | +10| d e f g h i j k l m + | +11| n o p q r s t u v w + | +12| x y z | } ~ + | +13| + . + . + . +20| + | +21| Ä Ö Ü ä ö ü + | +22| k \# SP + | +23| + | +24| + | +25| ß +#page# + + +Anmerkungen: + +1) SP bedeutet Leerzeichen ("blank"). + +2) Die Zeichen 'k', '-' und 'SP' mit den Codes 220, 221, 223 werden für die Zwecke + der Textkosmetik benötigt (Trenn-'k' bei der Umwandlung von 'ck' in 'kk'; Trenn + zeichen; geschütztes Leerzeichen). + +3) Das Zeichen '\#' (Code 222) ist druckbar, während das Zeichen '\#' (Code 35) nicht + druckbar ist (Einleitungszeichen für Anweisungen der Textkosmetik und Drucker). + +4) Das Zeichen SP (Code 223) wird zur besseren Identifizierung invers oder als + Unterstreichungsstrich auf dem Terminal dargestellt. In einem Ausdruck erscheint + es als ein Leerzeichen. + +Falls Sie Zeichen ausgeben möchten, die nicht auf der Tastatur sind, müssen Sie den +Code der gewünschten Zeichen zu Hilfe nehmen. + +Bewegen Sie den Cursor dazu an die Stelle der Datei, an die das Sonderzeichen +geschrieben werden soll und geben Sie nach <ESC> <ESC> ein: + + +____________________________________________________________________________ + ................. dateiname .................. Zeile 123 + + TABELLE 1 + _____________________ + | | + gib kommando : type(code(124)) + + + +____________________________________________________________________________ +#page# +6.3. Sortier-Programme +#free(1.0)# + + + Es stehen zwei verschiedene Sortier-Programme zur Verfügung: 'sort' (Sortierung + nach ASCII-Reihenfolge) und 'lex sort' (Sortierung nach deutschem Alphabet). + +#free(1.0)# + +Die Sortierprogramme sortieren eine Datei zeilenweise. + +Beispiel: + + +____________________________________________________________________________ + ................. dateiname ................. Zeile 1 + Berta ist eine Frau. + Adam ist ein Mann. + ... + +____________________________________________________________________________ + + +____________________________________________________________________________ +gib kommando : +#ib#sort#ie# ("dateiname") + +____________________________________________________________________________ + + + + +____________________________________________________________________________ + ................. dateiname ................. Zeile 1 + Adam ist ein Mann. + Berta ist eine Frau. + ... + +____________________________________________________________________________ + + + + +Dabei werden die Zeilen-Anfänge solange zeichenweise miteinander verglichen, bis +ein Unterschied auftritt und dann ggf. umgeordnet. Werden zwei ungleich lange Zeilen +(Anzahl Zeichen/Zeile) miteinander verglichen, dann kann man sich die kürzere Zeile +mit Leerzeichen auf die Länge der längeren Zeile verlängert denken. + +Die Reihenfolge, in der die Zeilen sortiert werden, erfolgt nach dem ASCII- +Zeichensatz in aufsteigender Reihenfolge (vergl EUMEL-Zeichencode): + + + das Leerzeichen + einige Sonderzeichen + die Ziffern + einige Sonderzeichen + große Buchstaben + einige Sonderzeichen + kleine Buchstaben + einige Sonderzeichen + die Umlaute und ß + + +Das bedeutet, daß z.B. folgendermaßen sortiert wird: + + +____________________________________________________________________________ + ................. dateiname ................. Zeile 1 + Adam + Ball + Zuruf + aber das ist ein Satz + niemals + Überlauf + +____________________________________________________________________________ + + + + +Um zu erreichen, daß große und kleine Buchstaben gleichwertig behandelt werden, +kann man das Kommando + +____________________________________________________________________________ +gib kommando : +#ib#lex sort#ie# ("dateiname") + +____________________________________________________________________________ + + + +geben. + +In diesem Fall würde die sortierte Datei folgendermaßen aussehen: + +____________________________________________________________________________ + ................. dateiname ................. Zeile 1 + aber das ist ein Satz + Adam + Ball + niemals + Überlauf + Zuruf + +____________________________________________________________________________ + + +Man beachte, daß der Umlaut 'Ü' wie 'Ue' behandelt wird (für die restlichen Umlaute +gilt eine analoge Behandlung; ebenso wird 'ß' wie 'ss' behandelt). Weiterhin werden +alle Sonderzeichen bei der Sortierreihenfolge ignoriert. + +6.4 Fonttabellen +#free(1.0)# + + + Eine Fonttabelle enthält Angaben zu den druckbaren Zeichen. + +#free(1.0)# + +Die Einstellung einer Fonttabelle#u#1)#e# erfolgt automatisch beim Einrichten der Drucker- +Task (siehe Anhang). Um den Namen der in der Task eingestellten Fonttabelle zu +erhalten geben Sie ein: +#foot# +1) Fonttabelle: Beschreibung der druckbaren Schrifttypen. +#end# + +____________________________________________________________________________ + +gib kommando: +put(fonttable) + +____________________________________________________________________________ + + +Die Ausgabe liefert den Namen der in der Task eingestellten Fonttabelle. + +____________________________________________________________________________ + +gib kommando: +put(fonttable) +agfa9 +gib kommando: + +____________________________________________________________________________ + + +Um eine neue oder andere Fonttabelle einzustellen, etwa weil verschiedene Drucker +benutzt werden können, geben Sie das 'fonttable' Kommando mit dem Namen der +gewünschten Fonttabelle als Parameter an: + +____________________________________________________________________________ + +gib kommando: +fonttable("name der fonttabelle") + +____________________________________________________________________________ + + + +Eine weitergehende Beschreibung der eingestellten Fonttabelle erhalten Sie durch das +Kommando 'list fonts': + +____________________________________________________________________________ + +gib kommando: +list fonts + +____________________________________________________________________________ + + +Durch dieses Kommando erhalten Sie in das Notizbuch eine Aufstellung der Schrift +typen mit Angaben zu Namen der verfügbaren Schrifttypen in der Fonttabelle, +Größenangaben zu den Schriftttypen etc. + +____________________________________________________________________________ + ................. notebook .................. Zeile 1 +FONTTABELLE : "agfa9"; + x einheit = 160.0; + y einheit = 160.0; + + FONT : "micro", "elanlist", "bulletin22"; + einrueckbreite = 20; + durchschuss = 7; + fonthoehe = 30; + fonttiefe = 8; + groesserer font = ""; + kleinerer font = ""; + + FONT : "trium10"; + einrueckbreite = 31; + durchschuss = 6; + fonthoehe = 54; + fonttiefe = 15; + groesserer font = "trium12"; + kleinerer font = "trium8"; + +____________________________________________________________________________ + + + +Anmerkung: + - Falls mehrere Namen für einen Schrifttyp angegeben sind, können Sie + einen beliebigen dieser Namen in der \#type\#-Anweisung benutzen. + + - Größenangaben sind in 'Mikroschritten', d.h. den kleinstmöglichen + Schritten des jeweiligen Druckers angegeben und nicht etwa in mm. + + - Weitere Informationen entnehmen Sie ggf. dem Systemhandbuch. + +#page# +6.5 Syntax der Kommandos +#free(1.0)# +code + TEXT PROC code (INT CONST zahl) + Wandelt 'zahl' in ein Zeichen um. Falls die Zahl kleiner als 32 oder größer als 254 + ist, (siehe Codetabelle) muß mit unerwarteten Ergebnissen gerechnet werden. + + + type(code(92)) + + + INT PROC code (TEXT CONST zeichen) + Wandelt 'zeichen' in die zugehörige EUMEL-Codierung um. Falls mehr als ein + Zeichen angegeben wird, ist das Resultat '-1'. + + + put(code(92)) + + + +list fonts + PROC list fonts + Listet die Fonts der eingestellten Tabelle ins #on("i")#notebook#off("i")#. + + PROC list fonts (TEXT CONST fonttable name) + Listet die Fonts der angegebenen Fonttabelle ins #on("i")#notebook#off("i")#. Die vorher eingestellte + Fonttabelle bleibt jedoch weiter eingestellt. + + + list fonts ("fonttab.alternativ") + + + +lex sort + PROC lex sort (TEXT CONST datei) + + Zeilenweise Sortierung nach (deutscher) lexikographischer Reihenfolge nach DIN + 5007. + + + lex sort ("telephonliste") + + + PROC lex sort (TEXT CONST datei, INT CONST anfang) + + Wie 'lex sort', jedoch wird bei der Sortierung bei 'anfang' jeder Zeile begonnen. + + + lex sort ("liste",20) + + +sort + PROC sort (TEXT CONST datei) + + Die Prozedur 'sort' sortiert die Datei 'datei' zeilenweise. Die Sortierung erfolgt + nach der Ordnung, die der EUMEL-Zeichencode vorschreibt. Beispielsweise + werden Zeilen ("Sätze"), die mit Ziffern beginnen, vor Sätzen, die mit Buchstaben + anfangen, eingeordnet. Sätze, die mit großen Buchstaben beginnen, werden vor + Sätzen mit kleinen Buchstaben einsortiert. Weiterhin werden die Umlaute und das + "ß" nach allen anderen Buchstaben eingeordnet. + + + sort ("liste") + + + PROC sort (TEXT CONST datei, INT CONST anfang) + + Sortiert eine Datei wie obige Prozedur, jedoch wird bei der Sortierung nicht der + Anfang eines Satzes beachtet, sondern die Position 'anfang'. + + + sort ("liste",10) + + + +type + PROC type (TEXT CONST zeichenkette) + + Fügt 'zeichenkette' in die aktuelle Position der editierten Datei ein. Besonders + nützlich in Verbindung mit der Prozedur 'code', um nicht auf der Tastatur enthal + tene Zeichen in den Text zu bringen. + + + type(code(200)) + diff --git a/doc/user-manual/1.8.7/doc/benutzerhandbuch.anhang b/doc/user-manual/1.8.7/doc/benutzerhandbuch.anhang new file mode 100644 index 0000000..5a58f95 --- /dev/null +++ b/doc/user-manual/1.8.7/doc/benutzerhandbuch.anhang @@ -0,0 +1,484 @@ +#start(5.0,1.5)##pagenr("%",1)##setcount(1)##block##pageblock##count per page# +#headeven# +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# + EUMEL-Benutzerhandbuch +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#headodd# +#lpos(0.0)##cpos(5.5)##rpos(11.0)##fillchar(" ")# +#table# + Anhang +#fillchar(" ")# +#on("u")# #off("u")# +#table end##clear pos# + +#end# +#bottomeven# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +A - % GMD +#tableend##clearpos# +#end# +#bottomodd# + +#lpos(0.0)##cpos(5.5)##rpos(11.0)# +#table# +#fillchar(" ")# +#on("u")# #off("u")# +#fillchar(" ")# +GMD A - % +#tableend##clearpos# +#end# +Aufbau und Installation +#free(0.5)# + Diese Installationsanleitung dient nur als Beispiel und soll nicht die Anleitung zu + dem von Ihnen benutzten Gerät ersetzen. Insbesondere die hier beschriebene + Möglichkeit der Partitionierung ist kein Standard! +#free(0.5)# +Allgemeines über das Betriebssystem EUMEL +#free(0.5)# + +Zum besseren Verständnis des Installierungsvorganges sei hier kurz der Aufbau des +Betriebssystems EUMEL erläutert (Der EUMEL-Kenner mag diesen Abschnitt über +springen) : + +Das System besteht im wesentlichen aus den folgenden Komponenten : + + - SHard (#on("i")##on("b")#S#off("b")##off("i")#oftware - #on("i")##on("b")#Hard#off("b")##off("i")#ware Interface) + - Systemkern (EUMEL-0) + - darauf aufbauende Systemteile + +Das #on("b")##ib#SHard#ie##off("b")# ist der #on("u")#hardwareabhängige#off("u")# Teil des Betriebssystems. Dieser Teil ist ver +antwortlich für den Informationsfluß zwischen der virtuellen Maschine EUMEL-0 und +den einzelnen Hardwarekomponenten (Tastatur, Diskettenlaufwerk, Schnittstellen, +usw.). + +Der #on("b")#Systemkern#off("b")# (auch mit EUMEL-0 oder Urlader bezeichnet) ist der #on("u")#prozessorab +hängige#off("u")# Teil des Systems. Er bestimmt im wesentlichen die Leistung des Betriebssy +stems, da er als virtueller Prozessor den Befehlsumfang für den ELAN-Compiler +definiert. Dieser Befehlsumfang wird dann auf den tatsächlichen Befehlsvorrat des +hardwaremäßig vorhandenen Prozessors abgebildet. + +Die auf dem Kern (EUMEL-0) #on("b")#aufbauenden Systemteile#off("b")# sind #on("u")#hardware- und prozes +sorunabhängig#off("u")#. Sie beinhalten den ELAN-Compiler und alle Tasks, Texte, insertier +ten ELAN-Pakete, benannte und unbenannte Datenräume eines EUMEL-Systems. +Diese Systemteile bilden zusammen mit dem Systemkern EUMEL-0 den #goalpage("v2")##on("b")#EUMEL- +Hintergrund#off("b")#, d.h. EUMEL-0 ist Teil des #ib#EUMEL-Hintergrundes#ie#. Momentan werden +je nach Rechnertyp Diskette und Festplatte als Hintergrundspeichermedium für +EUMEL unterstützt. + +Der Begriff EUMEL-Hintergrund (HG) resultiert aus dem Konzept des virtuellen +Speichers. Bei diesem Konzept wird der RAM-Speicherbereich der Hardware nur als +Pufferbereich nach dem Demand-Paging-Verfahren benutzt, mit Ausnahme der +residenten Systemteile (SHard und EUMEL-0). Das macht den Benutzer bezüglich +seiner Programme und Daten unabhängig von der eigentlichen Größe des RAM- +Speichers. Diese bestimmt lediglich den Durchsatz (Performance) des Systems, d.h. je +größer der RAM-Bereich Ihres Rechners ist, desto schneller arbeitet das EUMEL- +System. + +EUMEL-0 befindet sich auf der ersten Hintergrunddiskette. Das Laden von +EUMEL-0 und des restlichen EUMEL-Hintergrundes kann daher in einem Arbeits +gang geschehen. + +Der Auslieferungs-Hintergrund ist noch nicht konfiguriert und stellt ausschließlich die +im Handbuch beschriebenen Leistungen des Betriebssystems zur Verfügung. Er +besteht im wesentlichen aus insertierten ELAN-Paketen, die den Leistungsumfang +des Systems bestimmen (Single- oder Multiuser, mit oder ohne Textverarbeitung). +Steht dieser Hintergrund auf mehreren Disketten (Multiuser-Hintergründe), dann sind +diese fortlaufend numeriert. Die erste Hintergrunddiskette hat die Nummer 0, um +daran zu erinnern, daß sich auf dieser Diskette auch der Systemkern EUMEL-0 +befindet. + +Ein Hintergrund kann natürlich auch die Systemsicherung eines größeren Systems mit +z.B. mehreren Megabytes sein. Sollten Sie später einmal Ihr bestehendes System +durch ein anderes ersetzen wollen (Hintergrund überschreiben), so brechen Sie wäh +rend des Hochfahrens beim Speichertest das System durch Tastendruck ab und laden +durch Anwahl von 2 'neuen Hintergrund vom Archiv laden' im Startdialog das neue +System. + +#on("i")##on("u")#ACHTUNG:#off("u")##off("i")# Dabei gehen alle Daten des alten Systems unwiederbringlich verloren! + (Siehe dazu auch 'Laden eines EUMEL-Hintergrundes'.) + +Zur besseren Verständlichkeit sollen an dieser Stelle noch die Begriffe 'Systemstart' +und 'Systemabschaltung' des EUMEL-Systems erläutert werden : + +#on("i")##on("b")##ib#Systemstart#ie# :#off("b")##off("i")# +Wenn ein EUMEL-System gestartet wird (auch 'Hochfahren' genannt), und dies gilt +auch für kleinere Diskettensysteme wie den 'Generierungseumel' (siehe Seite #topage("v1")#), +wird zunächst das SHard geladen; dazu erscheint auf dem Bildschirm eine entspre +chende Meldung. Das SHard versucht nun den Systemkern vom Archivmedium (in der +Regel Diskette) zu laden. Ist keine entsprechende Diskette eingelegt, so wird ver +sucht, EUMEL-0 vom Hintergrundmedium (Festplatte) zu laden. + +Danach wird EUMEL-0 aktiv; auf dem Bildschirm erscheinen Angaben zu verfügba +ren Kanälen, RAM- und Hintergrundspeicher-Größe. Dann führt EUMEL-0 einen +Speichertest durch, was daran zu erkennen ist, daß eine Folge von Sternchen (*) auf +den Schirm geschrieben wird. Wird währenddessen eine beliebige Taste gedrückt, +dann gelangt man nach dem Speichertest in den 'Startdialog'. + +Nach dem Speichertest bzw. nach Wahl von <1> 'Systemstart' im Startdialog wird der +Hintergrund aktiviert, was je nach Größe des Systems und Art des Hintergrundmedi +ums unterschiedlich lange dauert. + +#on("i")##on("b")##ib#Systemabschaltung#ie# :#off("b")##off("i")# +Bevor man den Rechner ausschaltet, sollte jedes EUMEL-System ordnungsgemäß +abgeschaltet werden. Das geschieht durch den Befehl 'shutup', den man in der Multi +user-Version von EUMEL im privilegierten Zweig des Taskbaumes erteilen muß. Nur +dann ist gewährleistet, daß der aktuelle Zustand Ihres Systems gesichert ist. + +Andernfalls gilt das System als abgebrochen, was daran zu erkennen ist, daß sich das +System beim nächsten Systemstart mit 'RERUN' meldet. Dann kann nur am letzten +Fixpunkt wieder aufgesetzt werden, und Ihre in letzter Zeit (normalerweise ca. 15 +Minuten) gesammelten Daten können verloren sein. + +Installation des EUMEL-Systems +#free (1.0)# + +#goalpage("a1")#A: Erforderliche Disketten + + - EUMEL-Systemdiskette : "Generierungseumel XY"#u#1)#e# + - EUMEL-Hintergrunddisketten : "HG0" ... "HGn" + - EUMEL-Archivdisketten : "std..." + - EUMEL-Archivdiskette : "XY" (Typabhängig) + - MS-DOS-Diskette : "EUMELstart" + +#foot# +1) XY steht für die Typbezeichnung eines Rechners wie: XT, AT, M24 usw. + Die Anzahl der ausgelieferten Disketten ist auch typabhängig, da z.B. + 'EUMELstart' nur benötigt wird, falls tatsächlich eine Partitionierung möglich ist. +#end# + +Die Diskette #goalpage("v1")##on("u")#"Generierungseumel XY"#off("u")# ist ein kleines, jedoch vollständiges EUMEL- +System. Auf diesem System laufen nach dem Hochfahren Programme ab, die im +Dialog mit dem Benutzer die Generierung einer oder mehrerer EUMEL-Partitionen +ermöglichen, diese Bereiche bezüglich schlechter Spuren untersuchen und das SHard +auf der jeweiligen Partition installieren. #on("b")#Bei der Generierung darf diese Diskette nicht +schreibgeschützt sein !#off("b")# + +Die #on ("u")#Hintergrunddisketten "HG0" ... "HGn"#off ("u")# beinhalten das eigentliche Betriebssystem +EUMEL. Es sind dies der Systemkern EUMEL-0 und die darauf aufbauenden Sy +stemteile (siehe Seite #topage("v2")#). + +Die #on ("u")#Standardarchivdisketten "std..."#off ("u")# beinhalten ELAN-Programmpakete und Fontta +bellen, die Sie nach erfolgter Installation des Betriebssytems z.B. zum Zwecke einer +Druckerinstallation oder erweiterter Rechenfunktionen benötigen werden. Sie finden +dazu detaillierte Informationen in Ihrem Benutzer- und Systemhandbuch. + +Die #on("u")#Archivdiskette "XY"#off ("u")# beinhaltet ELAN-Programmpakete, die Funktionen, die nicht +zu den Standardleistungen von EUMEL bzw. der vorliegenden SHard-Version zählen. + +Die Diskette #on("u")#"EUMELstart"#off("u")# ist eine MS-DOS Diskette und beinhaltet Kommando- +Dateien. Falls Sie auch eine MS-DOS Partition eingerichtet haben, dann gewährlei +sten diese das Aktivieren einer EUMEL Partition mit gleichzeitigem Systemstart von +MS-DOS aus. +#free (1.0)# + +#goalpage("a2")#B: Partitionieren der Festplatte / Installation des SHard + + +Wenn Sie bereits ein Betriebssystem auf Ihrer Festplatte installiert haben, müssen Sie +darauf achten, daß noch ausreichend Platz für ein EUMEL-System übrig ist. Da z.B. +MS-DOS standardmäßig die gesamte Festplatte belegt, muß dieses System gesi +chert, mit dem MS-DOS-Kommando 'fdisk' gelöscht und entsprechend kleiner neu +eingerichtet werden. Sie können auch bei der EUMEL-Installation alle bereits beste +henden Systeme löschen; dazu bietet Ihnen der Generierungseumel die Option +#on("i")#Löschen der gesamten Partitionstabelle #off("i")# an. Dabei gehen jedoch alle bestehenden +Daten verloren. Achten Sie also darauf, daß sie alle Daten vorher gesichert haben ! + +#on("u")##on("i")#Hinweis:#off("i")##off("u")# Bei Festplatten mit einer Kapazität über 32 Megabyte kann die Installa + tion des SHard zu Problemen führen (Fehlermeldung #on("i")#Platte kann nicht + gelesen werden#off("i")# bei der Suche nach schlechten Spuren). Richten Sie + daher Ihre EUMEL-Partition(en) auf den ersten 32 Megabyte ein. + +Um nun die Partitionierung für Ihr EUMEL-System vorzunehmen, legen Sie die +Diskette 'Generierungseumel' in das Boot-Laufwerk. Sollte die Diskette mit einer +Schreibschutzmarke versehen sein, dann müssen Sie diese vorher entfernen. + +Schalten Sie nun den Rechner ein bzw. betätigen Sie den Tastatur-RESET, wenn Ihr +Gerät bereits eingeschaltet ist, indem Sie die Tasten <CTRL> <ALT> <DEL> gleichzeitig +betätigen. + +Der Generierungseumel meldet sich zunächst mit folgender SHard-Meldung: + + + +____________________________________________________________________________ + +Setup - SHard für EUMEL auf XY und Kompatiblen V x.x +Copyright (C) 1985,86 +EUMEL wird vom Hintergrund geladen + +____________________________________________________________________________ + + + +Danach erscheinen die EUMEL-0 Meldungen zu HG-, RAM- und Pufferkapazität, +bezogen auf den Diskettenhintergrundes des Generierungseumel. + +#on("i")##on("u")#ACHTUNG:#off("u")##off("i")# Der Generierungseumel soll während des Speichertests (Sternchen) + nicht unterbrochen werden. Geschieht dies versehentlich doch, dann + fahren Sie fort, indem Sie im Startdialog die Taste <1> für Systemstart + betätigen. Dann wird normal mit der Installation fortgefahren. Wählen + Sie keinesfalls <2> 'neuen Hintergrund vom Archive laden', solange sich + die Diskette 'Generierungseumel' im Archivlaufwerk befindet. + +Nach dem Hochfahren des 'Generierungseumel' wird Ihnen eine Tabelle angezeigt, +der Sie entnehmen können, ob bereits Partitionen auf der Festplatte eingerichtet und +wie diese spezifiziert sind. + +Angezeigt werden neben Größe, Start- und Endspur der einzelnen Partitionen auch +eine Typ-Nr.; für EUMEL-Partitionen werden in aufsteigender Reihenfolge die +Typ-Nummern 69 bis 72, für MS-DOS je nach Größe der eingerichteten Partition +die Nummer 1 oder 4 vergeben. Die Typ-Nummern der eingerichteten Partitionen +sollten Sie sich merken, da diese Angaben später von Bedeutung sind, wenn das +Gesamtsystem für Partitionswechsel vorbereitet wird. Richten Sie mehrere EUMEL- +Partitionen ein, dann können Sie diese ausschließlich über die Typ-Nummern identi +fizieren ! + +Außerdem wird die gerade aktive Partition durch einen entsprechenden Eintrag in der +Tabelle kenntlich gemacht. #on("b")#"Aktiv" ist die Partition, die nach dem nächsten Einschal +ten des Rechners bzw. nach dem nächsten Tastatur-RESET gebootet würde.#off("b")# + +Sie können nun eine der folgenden Funktionen auswählen : + + - Generieren einer EUMEL-Partition + - Aktivieren einer Partition + - Löschen einer EUMEL-Partition + - Löschen der gesamten Partitionstabelle + - Generierung beenden + +Beim Generieren einer EUMEL-Partition werden lediglich Angaben zu Größe und +Startzylinder abgefragt. Dafür werden Vorgaben gemacht, die Sie bestätigen können, +indem Sie die <CR> Taste betätigen. + +Beim Neueinrichten orientiert sich die Vorgabe für die Partitionsgröße an dem größten +zusammenhängenden Freiraum auf Ihrer Platte, die Vorgabe für den Startzylinder +orientiert sich dann an dem kleinsten zusammenhängenden Freiraum, auf dem eine +Partition der gewählten Größe eingerichtet werden kann. + +#on("i")##on("u")#ACHTUNG:#off("u")##off("i")# Soll eine EUMEL-Version installiert werden, die nur 16 Megabyte + verwalten kann (1.7.3 bzw. 1.8.0), dann darf die Partition nicht größer + eingerichtet werden. Es kann hier keine generelle Aussage über die + Anzahl der zu reservierenden Spuren gemacht werden, da sehr ver + schiedene Plattenaufteilungen angeboten werden. Entnehmen Sie die + entsprechenden Angaben bitte dem Festplatten-Handbuch Ihres Hard + wareherstellers. + +Das Löschen einer EUMEL-Partition geschieht nur logisch, nicht physisch, das heißt +es wird nur der Eintrag in der Partitionstabelle gelöscht. Sollten Sie später an gleicher +Stelle eine neue Partition einrichten und vorher diesen Bereich physisch nicht über +schrieben haben, dann würde nach dem Hochfahren des Rechners das alte System +wieder gestartet. Die Meldung 'kein EUMEL-System gefunden'(siehe unten) erscheint +dann nicht. + +Haben Sie Ihre EUMEL-Partition(en) eingerichtet, dann achten Sie darauf, daß Sie +Ihren Generierungseumel ordnungsgemäß wieder verlassen, da es sich hier, wie +bereits erwähnt, um ein vollständiges EUMEL-System mit Fixpoint/Rerun-Logik +handelt. Das 'shutup' wird automatisch ausgeführt, wenn Sie die Funktion '0. Gene +rierung beenden' wählen. + +Wenn die Meldung 'ENDE' auf Ihrem Bildschirm erscheint, ist dieser Schritt der +Installation beendet. Sie haben nun eine (oder mehrere) EUMEL-Partitionen einge +richtet und das SHard installiert. Bitte entfernen Sie jetzt die Diskette 'Generierungs +eumel' aus dem Diskettenlaufwerk. +#free (1.0)# +Laden eines EUMEL-Hintergrundes + +#free(1.0)# +Im nächsten Schritt wird auf Ihrer Festplatte das EUMEL-System installiert, d.h. es +wird ein Hintergrund auf der Festplatte erzeugt. + +Dazu müssen Sie nach dem ordnungsgemäßen Beenden des Generierungseumel und +Entfernen der Diskette aus dem Laufwerk den Tastatur-RESET betätigen. Dies +geschieht entweder durch gleichzeitiges Betätigen der Tasten <CNTL> <ALT> <DEL> +auf der Tastatur oder durch AUS- und wieder EIN-Schalten des Rechners (Bitte +warten Sie einen Augenblick zwischen dem AUS- und EIN-Schalten). + +Das System meldet sich nach kurzer Zeit mit folgender SHard-Meldung: + + +____________________________________________________________________________ + +SHard für EUMEL auf XY, V x.x +Copyright (C) 1985,86 +kein EUMEL-System gefunden + +____________________________________________________________________________ + + + +Sie legen nun die Hintergrunddiskette HG0 in das Boot-Laufwerk und betätigen eine +Taste. + +Der Systemkern wird nun geladen und es erscheinen die bereits oben erwähnten +Angaben zu HG-, RAM- und Pufferkapazität, sowie zu den angeschlossenen +Kanälen, diesmal jedoch bezogen auf die eingerichtete Festplatten-Partition. Wäh +rend des Speichertests drücken Sie bitte erneut eine Taste, um in den Startdialog zu +gelangen und damit zu verhindern, daß EUMEL-0 versucht, das System zu starten. +Sollten Sie dies versäumen, so erscheint die Meldung 'HG ungültig'. Sie haben dann +erneut die Möglichkeit, durch Betätigen einer Taste in den Startdialog zu gelangen. + +Hier wählen Sie den Menupunkt <2> 'neuen Hintergrund vom Archiv laden' und bestä +tigen die Frage 'Alten Hintergrund überschreiben' mit <j> für 'ja'. + +Es erscheint ein Zähler auf dem Bildschirm, der die gelesenen Blöcke anzeigt. Verteilt +sich Ihr Hintergrund auf mehrere Disketten, dann müssen Sie bei bei der Frage +'Neues HG-Archiv eingelegt' die nächste Diskette einlegen und mit <j># #off("i")# quittieren. +Bitte beachten Sie dabei genau die Numerierung der HG-Disketten ! + +Es können bei beschädigten Disketten Lesefehler auftreten; dann gibt das System +eine der Meldungen 'Harter Lesefehler' bzw. 'Softerror' aus. Bei letzterem konnte der +entsprechende Sektor nach mehrmaligem Versuch noch gelesen werden. Bei einem +harten Lesefehler können Sie die Diskette nicht verwenden. + +Wenn alle Disketten eingelesen sind, müssen Sie ein letztes mal den Tastatur- +RESET betätigen, um das System zu starten. Vergessen Sie nicht, vorher die Hinter +grunddiskette aus dem Diskettenlaufwerk zu entfernen. + +Wenn Sie jetzt während des Hochfahrens keine Taste drücken, dann startet der Lader +durch und das EUMEL-System meldet sich mit 'System aufgebaut'. Dies dauert +beim Auslieferungshintergrund wenige Sekunden, kann jedoch bei größeren Systemsi +cherungen auch mehrere Minuten in Anspruch nehmen; verlieren Sie dann bitte nicht +allzu schnell die Geduld. + +Da der Auslieferungs-Hintergrund unkonfiguriert ist, gelangt das System beim ersten +Hochfahren nach der Installation sofort in den 'configurator'. Sie müssen jetzt den +Kanal 1 entsprechend der vorhandenen Tastatur als "PC.german" oder "PC.ascii" +konfigurieren. Sollten Sie eine EUMEL-Version 1.7.3 benutzen und diesen Konfigura +tionsdatenraum nicht zur Verfügung haben, dann konfigurieren Sie den Kanal 1 als +"PC" und Terminal. Näheres dazu finden Sie im Systemhandbuch (Teil 1). +#page# + Die einzelnen Schritte der Installation im Überblick +#free (0.5)# +#linefeed(1.5)# + 1. Die Diskette 'Generierungseumel' in das Laufwerk stecken + 2. Rechner einschalten oder Tastatur-RESET mit <CTRL>, <ALT> <DEL> + 3. EUMEL-Partition einrichten + 4. Generierung beenden und auf 'ENDE'-Meldung warten + 5. Diskette 'Generierungseumel' entnehmen + 6. Tastatur-RESET + 7. Die Meldung 'Kein EUMEL-System gefunden' abwarten. Wenn die Meldung + 'EUMEL wird vom Hintergrund geladen' erscheint, dann weiter bei 9. + 8. Erste Hintergrunddiskette (HG0) einlegen und Taste drücken + 9. Beim Speichertest eine Taste betätigen, um in den Startdialog zu gelangen. + 10. Menupunkt <2> anwählen : Neuen Hintergrund vom Archiv laden + 11. Eventuell weitere HG-Disketten nach entsprechender Aufforderung einlegen + und mit <j> quittieren + 12. Tastatur-RESET nach entsprechender Aufforderung + 13. Nach dem Hochfahren des Systems Konfiguration lt. Systemhandbuch + vornehmen + 14. Ggf. in der Task 'SYSUR' ELAN-Pakete für Partitionswechsel insertieren. + #linefeed (1.0)# + Dazu - Falls eine EUMEL-Version 1.7.3 benutzt wird, zunächst das + Kommando #on("i")#free global manager#off("i")# in der Task 'configurator' absetzen + - Archivdiskette "XY" einlegen und anmelden : #on("i")#archive �("XY")#off("i")# + - Datei "XY install" von Archivdiskette lesen : + #on("i")#fetch ("XY install", archive)#off("i")# + - Insertierung starten : #on("i")#run#off("i")# +Druckersoftware einrichten + +#free(0.5)# +Um mit Ihrem EUMEL-System einen Drucker betreiben zu können, müssen Sie +außer dem Anschluß des Druckers mit einem passenden Kabel auch die passende +Software für diesen Drucker zur Verfügung stellen. Zu diesem Zweck dienen die +Druckeranpassungen. + +Das Standardarchive "std.printer" enthält Druckeranpassungen für die Ansteuerung +diverser gebräuchlicher Druckertypen. Soll einer dieser Drucker an das EUMEL- +System angeschlossen werden, so muß zuerst eine Task "#ib#PRINTER#ie#" als Sohntask +von "SYSUR" mit dem Supervisorkommando + +#linefeed (1.18)# + begin ("PRINTER", "SYSUR") +#linefeed (1.0)# + +eingerichtet werden. In dieser Task müssen dann die folgenden Schritte vollzogen +werden: + +- Archiv anmelden: +#linefeed (1.18)# + archive ("std.printer") +#linefeed (1.0)# + +- Druckeranpassung vom Archiv holen: +#linefeed (1.18)# + fetch ("printer.druckertyp", archive) +#linefeed (1.0)# + +- Zeilennummergenerierung bei der Insertierung abschalten: +#linefeed (1.18)# + check off +#linefeed (1.0)# + +- Druckeranpassung insertieren: +#linefeed (1.18)# + insert ("printer.druckertyp") +#linefeed (1.0)# + +Beispiel: +#linefeed (1.18)# + archive ("std.printer") + fetch ("printer.epson.fx", archive); + check off; + insert ("printer.epson.fx") +#linefeed (1.0)# + +Nach der Insertierung wird zuerst nach dem #ib#Druckerkanal#ie# gefragt. Dieser sollte mit +der Gerätetabelle 'transparent' konfiguriert sein. Dann werden ggf. druckerspezifische +Fragen zur Papierbreite, Positionierungsart oder ähnlichem gestellt, die mit 'j' oder 'n' +beantwortet werden müssen. Dabei werden alle Alternativantworten zu der jeweili +gen Frage hintereinander angeboten, bis eine Alternative mit 'j' beantwortet wird. + +Als letzter Schritt kommt die Aufforderung das Archiv mit der passenden Fonttabelle +einzulegen. Diese Fonttabelle, eine Beschreibung aller darstellbaren Zeichen in allen +druckbaren Schrifttypen, ist meistens auf derselben Diskette wie die Druckeranpas +sung. + +Wenn die Generierung beendet ist, muß im Multi-User Betrieb in allen bestehenden +Tasks - insbesondere in der Task 'PUBLIC' - die Fonttabelle mit dem fonttable- +Kommando eingestellt werden. + +Beispiel: + +#linefeed (1.18)# + fonttable("fonttab.epson.fx") +#linefeed (1.0)# + +Von jeder Task aus kann danach mit dem Kommando + +#linefeed (1.18)# + print ("dateiname") +#linefeed (1.0)# + +wird eine Datei ausgedruckt werden. + +Das Einstellene einer Fonttabelle ist insbesondere Voraussetzung für 'lineform', 'page +form' etc. + +Befindet sich keine passende Druckeranpassung für den anzuschließenden Drucker +typ auf dem Standardarchiv "std.printer", so sollte die Druckeranpassung "printer.std" +benutzt werden. Diese Druckeranpassung ist eine universelle Druckeranpassung für +alle Drucker, die mit ASCII-Code 13 ein 'Carriage Return' (d.h. Bewegung des +Druckkopfes an den linken Rand) und mit ASCII-Code 10 eine Zeilenschaltung von +1/6 Zoll vornehmen. Mit ihr kann dann in einem Schrifttyp (entweder 10 oder 12 +Zeichen pro Zoll, je nachdem welche Fonttabelle eingestellt ist) gedruckt werden. So +erhält man wenigstens eine Minimalansteuerung des Druckers. + + + +Druckersoftware im Single-User einrichten + + +Die Installation der Druckersoftware im Single-User erfolgt ähnlich wie die im Mul +ti-User. Hier brauchen nur die Schritte durchgeführt zu werden, die im Multi-User +in der Task "PRINTER" druchgeführt werden müssen. Eine Task "PRINTER" braucht +nicht eingerichtet zu werden. + diff --git a/doc/user-manual/1.8.7/doc/source-disk b/doc/user-manual/1.8.7/doc/source-disk new file mode 100644 index 0000000..97500ef --- /dev/null +++ b/doc/user-manual/1.8.7/doc/source-disk @@ -0,0 +1 @@ +grundpaket/09_handbuecher.1.img |