summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorLars-Dominik Braun <lars@6xq.net>2019-02-04 13:09:03 +0100
committerLars-Dominik Braun <lars@6xq.net>2019-02-04 13:09:03 +0100
commit04e68443040c7abad84d66477e98f93bed701760 (patch)
tree2b6202afae659e773bf6916157d23e83edfa44e3 /doc
downloadeumel-src-04e68443040c7abad84d66477e98f93bed701760.tar.gz
eumel-src-04e68443040c7abad84d66477e98f93bed701760.tar.bz2
eumel-src-04e68443040c7abad84d66477e98f93bed701760.zip
Initial import
Diffstat (limited to 'doc')
-rw-r--r--doc/porting-8086/8/doc/Port.80862483
-rw-r--r--doc/porting-8086/8/source-disk1
-rw-r--r--doc/porting-mc68k/1985.11.26/doc/Port.680002173
-rw-r--r--doc/porting-mc68k/1985.11.26/source-disk1
-rw-r--r--doc/porting-z80/8/doc/Port.Z802484
-rw-r--r--doc/porting-z80/8/source-disk1
-rw-r--r--doc/programmer-manual/1.8.7/doc/programmierhandbuch.1650
-rw-r--r--doc/programmer-manual/1.8.7/doc/programmierhandbuch.2a1845
-rw-r--r--doc/programmer-manual/1.8.7/doc/programmierhandbuch.2b1395
-rw-r--r--doc/programmer-manual/1.8.7/doc/programmierhandbuch.3728
-rw-r--r--doc/programmer-manual/1.8.7/doc/programmierhandbuch.41692
-rw-r--r--doc/programmer-manual/1.8.7/doc/programmierhandbuch.51329
-rw-r--r--doc/programmer-manual/1.8.7/doc/programmierhandbuch.5b1481
-rw-r--r--doc/programmer-manual/1.8.7/doc/programmierhandbuch.61441
-rw-r--r--doc/programmer-manual/1.8.7/doc/programmierhandbuch.index449
-rw-r--r--doc/programmer-manual/1.8.7/doc/programmierhandbuch.inhalt249
-rw-r--r--doc/programmer-manual/1.8.7/doc/programmierhandbuch.titel52
-rw-r--r--doc/programmer-manual/1.8.7/source-disk1
-rw-r--r--doc/system-manual/1.8.7/doc/systemhandbuch.11685
-rw-r--r--doc/system-manual/1.8.7/doc/systemhandbuch.21351
-rw-r--r--doc/system-manual/1.8.7/doc/systemhandbuch.31366
-rw-r--r--doc/system-manual/1.8.7/doc/systemhandbuch.41185
-rw-r--r--doc/system-manual/1.8.7/source-disk1
-rw-r--r--doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil1924
-rw-r--r--doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil10771
-rw-r--r--doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil111072
-rw-r--r--doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil12234
-rw-r--r--doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil2628
-rw-r--r--doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil32097
-rw-r--r--doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil42306
-rw-r--r--doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil5667
-rw-r--r--doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil6a1590
-rw-r--r--doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil6b1425
-rw-r--r--doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil72469
-rw-r--r--doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil81345
-rw-r--r--doc/user-manual/1.7.3-pd/doc/pd.Handbuch.Teil9936
-rw-r--r--doc/user-manual/1.7.3-pd/doc/source-disk1
-rw-r--r--doc/user-manual/1.8.7/doc/benutzerhandbuch.1580
-rw-r--r--doc/user-manual/1.8.7/doc/benutzerhandbuch.2443
-rw-r--r--doc/user-manual/1.8.7/doc/benutzerhandbuch.32019
-rw-r--r--doc/user-manual/1.8.7/doc/benutzerhandbuch.42242
-rw-r--r--doc/user-manual/1.8.7/doc/benutzerhandbuch.5a1446
-rw-r--r--doc/user-manual/1.8.7/doc/benutzerhandbuch.5b1632
-rw-r--r--doc/user-manual/1.8.7/doc/benutzerhandbuch.5c711
-rw-r--r--doc/user-manual/1.8.7/doc/benutzerhandbuch.5d211
-rw-r--r--doc/user-manual/1.8.7/doc/benutzerhandbuch.5e223
-rw-r--r--doc/user-manual/1.8.7/doc/benutzerhandbuch.6474
-rw-r--r--doc/user-manual/1.8.7/doc/benutzerhandbuch.anhang484
-rw-r--r--doc/user-manual/1.8.7/doc/source-disk1
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 SYSUR­Paß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 Hardware­Uhr 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) --> EUMEL­Version
+ id (1) --> Prozessortyp (1: Z80,
+ 2: Z8001,
+ 3: 8086 und kompatible,
+ 4: 68000
+ 5: 80286)
+ id (2) --> Urlader­Version
+ id (3) --> reserviert
+
+ Vom SHard werden geliefert:
+ id (4) --> Lizenznummer des SHards
+ id (5) --> Installationsnummer des EUMEL­Anwenders
+ id (6) --> SHard­spezifisch
+ id (7) --> SHard­spezifisch
+
+
+
+
+
+#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­
+lungs­Kommandos#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
+ Prompt­Zeichen eine Quittung (Handshake­Zeichen) 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 Handshake­Zeichen 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