summaryrefslogtreecommitdiff
path: root/system/setup
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 /system/setup
downloadeumel-src-04e68443040c7abad84d66477e98f93bed701760.tar.gz
eumel-src-04e68443040c7abad84d66477e98f93bed701760.tar.bz2
eumel-src-04e68443040c7abad84d66477e98f93bed701760.zip
Initial import
Diffstat (limited to 'system/setup')
-rw-r--r--system/setup/3.1/source-disk1
-rw-r--r--system/setup/3.1/src/AT-4.xbin0 -> 1024 bytes
-rw-r--r--system/setup/3.1/src/SHARDbin0 -> 7680 bytes
-rw-r--r--system/setup/3.1/src/SHard Basisbin0 -> 7680 bytes
-rw-r--r--system/setup/3.1/src/bootblockbin0 -> 4608 bytes
-rw-r--r--system/setup/3.1/src/configuration2
-rw-r--r--system/setup/3.1/src/neu34
-rw-r--r--system/setup/3.1/src/setup eumel -1: mini eumel dummies28
-rw-r--r--system/setup/3.1/src/setup eumel 0: -M32
-rw-r--r--system/setup/3.1/src/setup eumel 0: -S35
-rw-r--r--system/setup/3.1/src/setup eumel 1: basisoperationen1071
-rw-r--r--system/setup/3.1/src/setup eumel 2: modulzugriffe441
-rw-r--r--system/setup/3.1/src/setup eumel 3: modulkonfiguration854
-rw-r--r--system/setup/3.1/src/setup eumel 4: dienstprogramme218
-rw-r--r--system/setup/3.1/src/setup eumel 5: partitionierung435
-rw-r--r--system/setup/3.1/src/setup eumel 6: shardmontage389
-rw-r--r--system/setup/3.1/src/setup eumel 7: setupeumel1238
-rw-r--r--system/setup/3.1/src/setup eumel erzeugen15
-rw-r--r--system/setup/3.1/src/setup eumel erzeugen-M14
-rw-r--r--system/setup/3.1/src/shget.exebin0 -> 1536 bytes
20 files changed, 4807 insertions, 0 deletions
diff --git a/system/setup/3.1/source-disk b/system/setup/3.1/source-disk
new file mode 100644
index 0000000..1421205
--- /dev/null
+++ b/system/setup/3.1/source-disk
@@ -0,0 +1 @@
+setup/setup-src-3.1_shard-4.9_1989-04-18.img
diff --git a/system/setup/3.1/src/AT-4.x b/system/setup/3.1/src/AT-4.x
new file mode 100644
index 0000000..86962e3
--- /dev/null
+++ b/system/setup/3.1/src/AT-4.x
Binary files differ
diff --git a/system/setup/3.1/src/SHARD b/system/setup/3.1/src/SHARD
new file mode 100644
index 0000000..c1619b3
--- /dev/null
+++ b/system/setup/3.1/src/SHARD
Binary files differ
diff --git a/system/setup/3.1/src/SHard Basis b/system/setup/3.1/src/SHard Basis
new file mode 100644
index 0000000..60800a1
--- /dev/null
+++ b/system/setup/3.1/src/SHard Basis
Binary files differ
diff --git a/system/setup/3.1/src/bootblock b/system/setup/3.1/src/bootblock
new file mode 100644
index 0000000..00b56a2
--- /dev/null
+++ b/system/setup/3.1/src/bootblock
Binary files differ
diff --git a/system/setup/3.1/src/configuration b/system/setup/3.1/src/configuration
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/system/setup/3.1/src/configuration
@@ -0,0 +1,2 @@
+
+
diff --git a/system/setup/3.1/src/neu b/system/setup/3.1/src/neu
new file mode 100644
index 0000000..a89779c
--- /dev/null
+++ b/system/setup/3.1/src/neu
@@ -0,0 +1,34 @@
+TEXT VAR t1 :: "SHardmodul Floppy", t2 :: "FLOPPY.EXE";
+reserve ("ds", /"DOS");
+IF yes("init",FALSE)
+ THEN init modules list;
+FI;
+THESAURUS VAR th1 :: all modules, th2 :: empty thesaurus;
+WHILE yes ("noch Module holen", TRUE) REP
+t2 := ONE /"DOS";
+t1 := ONE (th1);
+editget (t1); line;
+forget (t1);
+fetch (t2, /"DOS");
+copy (t2, t1); last param (t1);
+th2 := th2 + t1
+PER;
+WHILE yes ("jetzt noch andere holen", FALSE) REP
+ t2 := ONE /"DOS";
+ t1 := ONE all;
+editget (t1); line;
+forget (t1);
+fetch (t2, /"DOS");
+copy (t2, t1); last param (t1);
+PER;
+release (/"DOS");
+
+linkshard module (th2);
+
+
+
+
+
+
+
+
diff --git a/system/setup/3.1/src/setup eumel -1: mini eumel dummies b/system/setup/3.1/src/setup eumel -1: mini eumel dummies
new file mode 100644
index 0000000..a1fa2b5
--- /dev/null
+++ b/system/setup/3.1/src/setup eumel -1: mini eumel dummies
@@ -0,0 +1,28 @@
+
+PACKET setup eumel mini eumel dummies (* Stand : 08.04.88 *)
+DEFINES FILE,
+ sequentialfile,
+ output,
+ putline,
+ :=,
+ run :
+
+TYPE FILE = INT;
+
+INT CONST output :: 0;
+
+OP := (FILE VAR a, FILE CONST b):
+
+END OP :=;
+FILE PROC sequentialfile (INT CONST a, TEXT CONST b) :
+ FILE : (0).
+END PROC sequentialfile;
+
+PROC putline (FILE CONST a, TEXT CONST b):
+END PROC putline;
+
+PROC run (TEXT CONST a):
+END PROC run;
+
+END PACKET setup eumel mini eumel dummies;
+
diff --git a/system/setup/3.1/src/setup eumel 0: -M b/system/setup/3.1/src/setup eumel 0: -M
new file mode 100644
index 0000000..bad5028
--- /dev/null
+++ b/system/setup/3.1/src/setup eumel 0: -M
@@ -0,0 +1,32 @@
+PACKET setup eumel multiuserspecials (* Copyright (C) 1985, 1988 *)
+DEFINES terminal setup, (* Martin Schönbeck, Spenge *)
+ indirect list, (* Lutz Prechelt, Karlsruhe *)
+ setup testing : (* Stand: 07.05.88 2.1 *)
+
+LET sysout file = "sysout";
+
+BOOL VAR setup test version :: FALSE;
+
+PROC terminal setup:
+ (* It took about 2 manmonths to debug this procedure ! *)
+END PROC terminal setup;
+
+PROC indirect list (BOOL CONST make indirection) :
+ IF make indirection
+ THEN sysout (sysout file);
+ ELSE sysout ("");
+ print (sysout file);
+ forget (sysout file, quiet)
+ FI.
+END PROC indirect list;
+
+PROC setup testing (BOOL CONST new ):
+ setup test version := new;
+END PROC setup testing;
+
+BOOL PROC setup testing :
+ setup test version.
+END PROC setup testing;
+
+END PACKET setup eumel multiuserspecials;
+
diff --git a/system/setup/3.1/src/setup eumel 0: -S b/system/setup/3.1/src/setup eumel 0: -S
new file mode 100644
index 0000000..50a8330
--- /dev/null
+++ b/system/setup/3.1/src/setup eumel 0: -S
@@ -0,0 +1,35 @@
+PACKET setup eumel singleuserspecials (* Copyright (C) 1985, 1988 *)
+DEFINES terminal setup, (* Martin Schönbeck, Spenge *)
+ break, (* Lutz Prechelt, Karlsruhe *)
+ indirect list, (* Stand: 07.05.88 2.1 *)
+ setup testing :
+
+LET printer channel = 15,
+ screen channel = 1;
+
+
+PROC break (QUIET CONST quiet):
+END PROC break;
+
+PROC terminal setup:
+ setup
+END PROC terminal setup;
+
+PROC indirect list (BOOL CONST make indirection) :
+ (* Man beachte, daß es nicht besonders sinnvoll ist, auf einem Drucker
+ cout zu machen...
+ *)
+ IF make indirection
+ THEN continue (printer channel)
+ ELSE continue (screen channel) FI.
+END PROC indirect list;
+
+PROC setup testing (BOOL CONST new):
+END PROC setup testing;
+
+BOOL PROC setup testing :
+ FALSE.
+END PROC setup testing;
+
+END PACKET setup eumel singleuserspecials;
+
diff --git a/system/setup/3.1/src/setup eumel 1: basisoperationen b/system/setup/3.1/src/setup eumel 1: basisoperationen
new file mode 100644
index 0000000..a705ff4
--- /dev/null
+++ b/system/setup/3.1/src/setup eumel 1: basisoperationen
@@ -0,0 +1,1071 @@
+
+(**************************************************************************)
+(***** Grundoperationen für den Setup-Eumel (Modul-SHard) *****************)
+(***** Copyright (c) 1985 - 1988 by *****************)
+(***** Martin Schönbeck, Spenge / Lutz Prechelt, Karlsruhe ****************)
+(**************************************************************************)
+
+(* Fünf Pakete :
+ 1. setup eumel basisoperationen
+ Handhabung von 16-Bit unsigned Werten in INTs und Editierfunktionen
+ 2. splitting
+ Worttrennung von REALs und Bytetrennung von INTs
+ 3. basic block io
+ blockin und blockout auf Datenräume mit retrys und Fehlermeldungen
+ 4. write file
+ Direktes Schreiben/Lesen eines Datenraums in/aus eine(r) Partition
+ 5. thesaurus utilities
+ ONE,CERTAIN,certain zum Aussuchen aus Thesauri ohne Editor
+*)
+
+
+PACKET setup eumel basisoperationen (* (C) 1987 Lutz Prechelt, Karlsruhe *)
+DEFINES editget, editgetchar, (* Stand: 08.04.88 Version 1.1 *)
+ yes, no, (* Eumel 1.8.0 *)
+ direction, reset direction,
+ data error, write head,
+ LIST, list, CAT, emptylist,
+ (*UNSIGNED,*) unsigned, int, text,
+ RANGE, range, everywhere,
+ ANDXOR, andxor,
+ dec, hex, bin,
+ IN,
+ := ,
+ put :
+
+(* Dieses Paket stellt die Basisfunktionen für den Elanteil des Setup-SHard
+ zur Verfügung.
+ Es ist dies im Wesentlichen die Handhabung von INT-Werten auch in Binär-
+ und Hexdarstellung, sowie die Plausibilitätsprüfung mit Fehleranzeigen.
+*)
+
+TYPE LIST = TEXT, (* TEXT aus mehreren UNSIGNEDen (replace/ISUB) *)
+ RANGE = STRUCT (UNSIGNED low, high),
+ ANDXOR = STRUCT (UNSIGNED and mask, xor mask);
+
+LET UNSIGNED = INT; (* 16 bit *)
+
+TYPE REPRESENTATION = INT;
+
+REPRESENTATION CONST dec :: REPRESENTATION : (10),
+ hex :: REPRESENTATION : (16),
+ bin :: REPRESENTATION : (2);
+
+(* Diese Typen dienen zur Wertprüfung bei der Eingabe. *)
+
+LET up = ""3"",
+ down = ""10"",
+ right = ""2"",
+ error = ""0""; (* fuer current direction *)
+
+TEXT VAR current direction :: ""; (* enthaelt up oder down oder "" *)
+BOOL VAR direction valid :: FALSE;
+
+TEXT CONST hex digits :: "0123456789abcdef";
+
+(********************* Zuweisungen *************************************)
+
+OP := (LIST VAR a, LIST CONST b) :
+ CONCR (a) := CONCR (b)
+END OP := ;
+
+OP := (RANGE VAR a, RANGE CONST b) :
+ a.low := b.low;
+ a.high := b.high
+END OP := ;
+
+OP := (ANDXOR VAR a, ANDXOR CONST b) :
+ a.and mask := b.and mask;
+ a.xor mask := b.xor mask
+END OP := ;
+
+OP := (REPRESENTATION VAR a, REPRESENTATION CONST b) :
+ CONCR (a) := CONCR (b)
+END OP := ;
+
+(************************** IN ******************************************)
+
+BOOL OP IN (UNSIGNED CONST a, LIST CONST l) :
+ INT CONST p :: pos (CONCR (l), textform (a));
+ p > 0 AND p MOD 2 = 1 (* enthalten und word-aligned *)
+END OP IN;
+
+BOOL OP IN (UNSIGNED CONST a, RANGE CONST b) :
+ (* RANGES sind inklusiv ihrer Grenzen *)
+ reverse (textform (a)) <= reverse (textform (b.high)) AND
+ reverse (textform (a)) >= reverse (textform (b.low))
+END OP IN;
+
+BOOL OP IN (UNSIGNED CONST a, ANDXOR CONST mask) :
+ (* Es muss (Bitweise) (a AND andmask) XOR xormask = 0 sein *)
+ ((a AND mask.and mask) XOR mask.xor mask) = 0
+END OP IN;
+
+(************************* Konstruktoren ********************************)
+
+LIST CONST emptylist :: LIST : ("");
+
+LIST PROC list (TEXT CONST list text) :
+ (* Konstruiert aus einer in Textform gegebenen Liste von Unsigneds eine
+ LIST. Die einzelnen Werte sind durch Komma getrennt und dürfen in
+ dezimaler, sedezimaler oder binärer Darstellung notiert sein.
+ *)
+ TEXT VAR t :: compress (list text);
+ IF t = "" THEN emptylist
+ ELSE TEXT VAR result :: "";
+ REPEAT
+ INT VAR first comma pos :: pos (t, ",");
+ IF first comma pos = 0 THEN first comma pos := LENGTH t + 1 FI;
+ result CAT textform (unsigned (subtext (t, 1, first comma pos - 1)));
+ t := subtext (t, first comma pos + 1)
+ UNTIL t = "" PER;
+ LIST : (result)
+ FI
+END PROC list;
+
+(*UNSIGNED PROC unsigned (INT CONST sixteen bits) :
+ sixteen bits
+END PROC unsigned;*)
+
+UNSIGNED PROC unsigned (TEXT CONST number) :
+ INT VAR result :: 0, i;
+ TEXT VAR t :: compress (to lower (number)), type :: t SUB LENGTH t;
+ IF pos ("hb" + hex digits, type) = 0
+ THEN set conversion (FALSE);
+ LEAVE unsigned WITH 0
+ FI;
+ IF type = "h"
+ THEN convert hex
+ ELIF type = "b"
+ THEN convert binary
+ ELSE convert decimal FI;
+ result.
+
+convert hex :
+ FOR i FROM 1 UPTO LENGTH t - 1 REP
+ TEXT CONST c :: t SUB i;
+ IF pos (hex digits, c) = 0
+ THEN set conversion (FALSE);
+ LEAVE unsigned WITH 0
+ FI;
+ rotate (result, 4);
+ result INCR pos (hex digits, c) - 1
+ PER.
+
+convert binary :
+ FOR i FROM 1 UPTO LENGTH t - 1 REP
+ TEXT CONST bit :: t SUB i;
+ IF bit <> "0" AND bit <> "1"
+ THEN set conversion (FALSE);
+ LEAVE unsigned WITH 0
+ FI;
+ rotate (result, 1);
+ result INCR int (bit)
+ PER.
+
+convert decimal :
+ REAL VAR x :: real (t);
+ IF NOT last conversion ok THEN LEAVE unsigned WITH 0 FI;
+ IF x < 32768.0
+ THEN result := int (x)
+ ELSE result := int (x - 65536.0) FI.
+END PROC unsigned;
+
+RANGE CONST everywhere :: RANGE : (0, -1);
+
+RANGE PROC range (UNSIGNED CONST low, high) :
+ RANGE : (low, high)
+END PROC range;
+
+ANDXOR PROC andxor (UNSIGNED CONST and mask, xor mask) :
+ ANDXOR : (and mask, xor mask)
+ENDPROC andxor;
+
+
+(******* weitere Operationen für UNSIGNED, LIST, RANGE, ANDXOR **************)
+
+INT PROC int (UNSIGNED CONST a) :
+ (* falls jemand noch exotische Dinge damit tun will *)
+ a
+END PROC int;
+
+OP CAT (LIST VAR l, UNSIGNED CONST a) :
+ (* Liste nachtraeglich erweitern *)
+ CONCR (l) CAT textform (a)
+END OP CAT;
+
+(********************* editget(char), yes, no *****************************)
+
+PROC editget (INT CONST spalte, zeile, TEXT CONST prompt, INT VAR i) :
+ cursor (spalte, zeile);
+ editget (prompt, i)
+END PROC editget;
+
+PROC editget (INT CONST spalte, zeile, TEXT CONST prompt, UNSIGNED VAR a,
+ REPRESENTATION CONST r) :
+ cursor (spalte, zeile);
+ editget (prompt, a, r)
+END PROC editget;
+
+PROC editget (TEXT CONST prompt, INT VAR i) :
+ TEXT VAR t :: text (i);
+ test up or down (prompt, t);
+ IF current direction <> "" THEN LEAVE editget FI;
+ editget (t,7,7);
+ i := int (t);
+ IF NOT last conversion ok
+ THEN data error ("Eingabe unerlaubt als Zahl") FI
+END PROC editget;
+
+PROC editget (TEXT CONST prompt, UNSIGNED VAR a, REPRESENTATION CONST r) :
+ TEXT VAR t :: text (a, r);
+ test up or down (prompt, t);
+ IF current direction <> "" THEN LEAVE editget FI;
+ editget (t,18,18);
+ a := unsigned (t);
+ IF NOT last conversion ok
+ THEN data error ("Eingabe unerlaubt") FI
+END PROC editget;
+
+BOOL PROC yes (TEXT CONST frage, BOOL CONST std antwort) :
+ (* Achtung: hierdrin kann nicht die alte "yes" Prozedur benutzt werden, da
+ diese kein getchar benutzt.
+ Die alten yes/no werden unten durch Resultatlose ueberdeckt.
+ *)
+ LET allowed = "NnJj";
+ INT VAR x,y; get cursor (x,y);
+ IF NOT command dialogue THEN LEAVE yes WITH std antwort FI;
+ REP UNTIL getcharety = "" PER;
+ REP
+ cursor (x,y);
+ test up or down (frage + " ? (j/n)", standard antwort text);
+ IF current direction <> "" THEN LEAVE yes WITH std antwort FI;
+ TEXT VAR t;
+ getchar (t);
+ IF t = ""13""
+ THEN t := standard antwort text FI;
+ IF pos (allowed, t) = 0
+ THEN out (""7"") ELSE out (t); out (""13""10"") FI
+ UNTIL pos (allowed, t) <> 0 PER;
+ t = "j" OR t = "J".
+
+standard antwort text:
+ IF std antwort
+ THEN "j"
+ ELSE "n"
+ FI.
+END PROC yes;
+
+BOOL PROC yes (INT CONST spalte, zeile, TEXT CONST frage,
+ BOOL CONST std antwort) :
+ cursor (spalte, zeile);
+ yes (frage, std antwort).
+END PROC yes;
+
+PROC yes (TEXT CONST dummy): END PROC yes;
+
+PROC no (TEXT CONST dummy): END PROC no;
+
+PROC editgetchar (INT CONST spalte, zeile, TEXT CONST prompt, allowed,
+ UNSIGNED VAR a) :
+ cursor (spalte, zeile);
+ editgetchar (prompt, allowed, a)
+END PROC editgetchar;
+
+PROC editgetchar (TEXT CONST prompt, allowed, UNSIGNED VAR a) :
+ (* Bietet Zeichen an (nehmen mit RETURN), nimmt nur die in allowed.
+ obere 8 Bit der Vorbesetzung werden abgeschnitten.
+ *)
+ TEXT VAR t;
+ test up or down (prompt, perhaps a);
+ a := a MOD 256;
+ IF current direction <> "" THEN LEAVE editgetchar FI;
+ getchar (t);
+ IF t = ""13""
+ THEN (* Vorbesetzung behalten *)
+ out (right)
+ ELIF pos (allowed, t) <> 0
+ THEN a := code (t);
+ out (t)
+ ELSE out (t);
+ data error ("unzulässiges Zeichen")
+ FI.
+
+perhaps a:
+ IF a > 31 THEN code (a) ELSE "" FI.
+END PROC editgetchar;
+
+(********* data error, write head, (reset) direction *********************)
+
+PROC data error (TEXT CONST fehlermeldung) :
+ cursor (1, 24);
+ out (""7"Fehler : " + fehlermeldung + " (Bitte Taste) ");
+ REP UNTIL incharety (2) = "" PER; pause;
+ cursor (1, 24); out (""4"");
+ current direction := error
+END PROC data error;
+
+PROC write head (TEXT CONST headtext) :
+ TEXT CONST text :: subtext (headtext, 1, 77);
+ INT CONST luecke :: (79 - LENGTH text) DIV 2 - 1;
+ out (""1""4""15"");
+ luecke TIMESOUT " ";
+ out (text);
+ luecke TIMESOUT " ";
+ out (""14""13""10""10"").
+END PROC write head;
+
+TEXT PROC direction :
+ current direction
+END PROC direction;
+
+PROC reset direction (BOOL CONST manouvres possible) :
+ (* Hiermit kann die letzte Manövrierbewegung nach der Auswertung gelöscht
+ werden. Mit NOT manouvres possible wird der ganze Manövriermechanismus
+ außer Betrieb gesetzt.
+ *)
+ direction valid := manouvres possible;
+ current direction := ""
+END PROC reset direction;
+
+(*********************** put *******************************************)
+
+PROC put (INT CONST spalte, zeile, UNSIGNED CONST a, REPRESENTATION CONST r):
+ cursor (spalte, zeile);
+ put (a, r)
+END PROC put;
+
+PROC put (INT CONST spalte, zeile, LIST CONST l, REPRESENTATION CONST r):
+ cursor (spalte, zeile);
+ put (l, r)
+END PROC put;
+
+PROC put (INT CONST spalte, zeile, RANGE CONST a, REPRESENTATION CONST r):
+ cursor (spalte, zeile);
+ put (a, r)
+END PROC put;
+
+PROC put (UNSIGNED CONST a, REPRESENTATION CONST r) :
+ put (text (a, r))
+END PROC put;
+
+PROC put (LIST CONST a, REPRESENTATION CONST r) :
+ INT VAR i, l :: LENGTH CONCR (a) DIV 2;
+ write ("(");
+ FOR i FROM 1 UPTO l REP
+ put (text (CONCR (a) ISUB i, r));
+ IF i < l THEN put (",") FI
+ PER;
+ IF l > 0 THEN out (""8"") FI;
+ put (")")
+END PROC put;
+
+PROC put (RANGE CONST a, REPRESENTATION CONST r) :
+ write (text (a.low, r));
+ write ("...");
+ write (text (a.high, r))
+END PROC put;
+(*** ist put auf RANGE in dieser Weise sinnvoll ?
+ vielleicht lieber die Maske bitweise mit x, 1, 0 darstellen ?
+***)
+
+PROC put (BOOL CONST b):
+ IF b
+ THEN put ("Ja ");
+ ELSE put ("Nein");
+ FI
+END PROC put;
+
+
+(********************* interne Hilfsprozeduren ****************************)
+
+TEXT PROC text (UNSIGNED CONST a, REPRESENTATION CONST r) :
+ TEXT VAR result :: "";
+ INT VAR i;
+ set conversion (TRUE);
+ IF CONCR (r) = 10 THEN decimal form
+ ELIF CONCR (r) = 2 THEN binary form
+ ELSE hex form FI.
+
+decimal form :
+ IF bit (a, 15) (* dann kriegt man im Eumel negatives Vorzeichen *)
+ THEN result := text (real (text (a)) + 65536.0); (* Der Umweg ueber
+ Text ist noetig, wegen (1.8.0) real (-32767-1) --> stack overflow *)
+ subtext (result, 1, pos (result, ".") - 1) (* Dezimalpunkt weghauen *)
+ ELSE text (a) FI.
+
+binary form :
+ FOR i FROM 15 DOWNTO 0 REP
+ IF bit (a, i) THEN result CAT "1" ELSE result CAT "0" FI
+ PER;
+ result + "b".
+
+hex form :
+ INT VAR help :: a;
+ FOR i FROM 1 UPTO 4 REP
+ rotate (help, 4); (* oberste 4 bit zu untersten 4 machen *)
+ result CAT (hex digits SUB nibble + 1); (* oberste 4 bit darstellen *)
+ PER;
+ result + "h".
+
+nibble :
+ help MOD 16. (* unterste 4 bit *)
+END PROC text;
+
+TEXT PROC textform (UNSIGNED CONST a) :
+ (* speichert das INT in einen TEXT (mit ISUB lesbar) *)
+ TEXT VAR ta :: " ";
+ replace (ta, 1, a);
+ ta
+END PROC textform;
+
+TEXT PROC reverse (TEXT CONST a) :
+ (* Text umdrehen. Das braucht man, um die ISUBS direkt vergleichen zu
+ koennen.
+ *)
+ IF LENGTH a <= 1 THEN a
+ ELSE reverse (subtext (a, 2)) + (a SUB 1) FI
+END PROC reverse;
+
+PROC test up or down (TEXT CONST prompt, data) :
+ IF current direction <> "" AND NOT direction valid
+ THEN current direction := "";
+ LEAVE test up or down
+ FI;
+ out (prompt);
+ out (" "8""8""8""8""8""8""); (* nächste 6 Zeichen Löschen *)
+ out (data); LENGTH data TIMESOUT ""8"";
+ IF NOT direction valid THEN LEAVE test up or down FI;
+ getchar (current direction);
+ IF current direction = up OR current direction = down
+ THEN (* verschlucken, spaeter auswerten *)
+ ELSE push (current direction);
+ current direction := ""
+ FI
+END PROC test up or down;
+
+TEXT PROC to lower (TEXT CONST text) :
+ TEXT VAR t :: text;
+ INT VAR i;
+ FOR i FROM 1 UPTO LENGTH t REP
+ IF (t SUB i) >= ""65"" AND (t SUB i) <= ""90""
+ THEN replace (t, i, code (code (t SUB i) + 32)) FI
+ PER;
+ t
+END PROC to lower;
+
+END PACKET setup eumel basisoperationen;
+
+
+
+PACKET splitting DEFINES low byte, (* Copyright (C) 1985 *)
+ high byte, (* Martin Schönbeck, Spenge *)
+ low word, (* Stand: 13.09.85 *)
+ high word:
+
+INT PROC high byte (INT CONST value):
+
+ TEXT VAR x := " ";
+ replace (x, 1, value);
+ code (x SUB 2)
+
+END PROC high byte;
+
+INT PROC low byte (INT CONST value):
+
+ TEXT VAR x := " ";
+ replace (x, 1, value);
+ code (x SUB 1)
+
+END PROC low byte;
+
+INT PROC high word (REAL CONST double precission int):
+
+ int (double precission int / 65536.0)
+
+END PROC high word;
+
+INT PROC low word (REAL CONST double precission int):
+
+ string of low bytes ISUB 1.
+
+string of low bytes:
+ code (int (double precission int MOD 256.0)) +
+ code (int ((double precission int MOD 65536.0) / 256.0)).
+
+END PROC low word;
+
+END PACKET splitting;
+
+
+
+PACKET basic block io DEFINES
+ verify track,
+ read block,
+ write block:
+
+
+PROC read block (DATASPACE VAR ds,
+ INT CONST ds page no,
+ INT CONST block no,
+ INT VAR return code):
+ read block;
+ retry if read error.
+
+read block:
+ block in (ds, ds page no, 0, block no, return code).
+
+retry if read error:
+ INT VAR retry;
+ FOR retry FROM 1 UPTO 10 WHILE return code = 2 REP
+ reset to block 0 if fifth try;
+ read block
+ PER.
+
+reset to block 0 if fifth try:
+ IF retry = 5
+ THEN block in (ds, ds page no, 0, 0, return code)
+ FI.
+
+END PROC read block;
+
+PROC write block (DATASPACE CONST ds,
+ INT CONST ds page no,
+ INT CONST block no,
+ INT VAR return code):
+ write block;
+ retry if write error.
+
+write block:
+ block out (ds, ds page no, 0, block no, return code).
+
+retry if write error:
+ INT VAR retry;
+ FOR retry FROM 1 UPTO 10 WHILE return code = 2 REP
+ reset to block 0 if fifth try;
+ write block
+ PER.
+
+reset to block 0 if fifth try:
+ IF retry = 5
+ THEN disable stop;
+ DATASPACE VAR dummy ds := nilspace;
+ block in (dummy ds, 2, 0, 0, return code);
+ forget (dummy ds);
+ enable stop
+ FI.
+
+END PROC write block;
+
+PROC read block (DATASPACE VAR ds, INT CONST ds page,
+ REAL CONST archive block):
+
+ enable stop;
+ read block (ds, ds page, archive block, error);
+ INT VAR error;
+ SELECT error OF
+ CASE 0:
+ CASE 1: error stop ("Platte kann nicht gelesen werden");
+ CASE 2: error stop ("Lesefehler bei Block "+ text (archive block));
+ CASE 3: error stop ("Versorgungsfehler Archiv");
+ OTHERWISE error stop ("unbekannter Fehler auf Platte");
+ END SELECT;
+
+END PROC read block;
+
+PROC write block (DATASPACE CONST ds, INT CONST ds page,
+ REAL CONST archive block):
+
+ enable stop;
+ write block (ds, ds page, archive block, error);
+ INT VAR error;
+ SELECT error OF
+ CASE 0:
+ CASE 1: error stop ("Platte kann nicht geschrieben werden");
+ CASE 2: error stop ("Schreibfehler bei Block "+ text (archive block));
+ CASE 3: error stop ("Versorgungsfehler Archiv");
+ OTHERWISE error stop ("unbekannter Fehler auf Platte");
+ END SELECT;
+
+END PROC write block;
+
+PROC read block (DATASPACE VAR ds,
+ INT CONST ds page no,
+ REAL CONST block no,
+ INT VAR return code):
+ read block;
+ retry if read error.
+
+read block:
+ block in (ds, ds page no, high word (block no) OR -512,
+ low word (block no), return code).
+
+retry if read error:
+ INT VAR retry;
+ FOR retry FROM 1 UPTO 10 WHILE return code = 2 REP
+ reset to block 0 if fifth try;
+ read block
+ PER.
+
+reset to block 0 if fifth try:
+ IF retry = 5
+ THEN block in (ds, ds page no, 0, 0, return code)
+ FI.
+
+END PROC read block;
+
+PROC write block (DATASPACE CONST ds,
+ INT CONST ds page no,
+ REAL CONST block no,
+ INT VAR return code):
+ write block;
+ retry if write error.
+
+write block:
+ block out (ds, ds page no, high word (block no) OR -512,
+ low word (block no), return code).
+
+retry if write error:
+ INT VAR retry;
+ FOR retry FROM 1 UPTO 10 WHILE return code = 2 REP
+ reset to block 0 if fifth try;
+ write block
+ PER.
+
+reset to block 0 if fifth try:
+ IF retry = 5
+ THEN disable stop;
+ DATASPACE VAR dummy ds := nilspace;
+ block in (dummy ds, 2, 0, 0, return code);
+ forget (dummy ds);
+ enable stop
+ FI.
+
+END PROC write block;
+
+PROC verify track (DATASPACE VAR ds, INT CONST ds page no,
+ REAL CONST startblock no, INT VAR return code):
+ block in (ds, ds page no, high word (startblock no) OR -256,
+ low word (startblock no), return code);
+END PROC verify track;
+
+END PACKET basic block io;
+
+
+
+PACKET write file DEFINES write file, (* Copyright (C) 1985, 1987 *)
+ read file : (* Martin Schönbeck, Spenge *)
+ (* Lutz Prechelt, Karlsruhe *)
+ (* Stand: 07.06.87 *)
+
+PROC write file (TEXT CONST file name, REAL CONST start block,
+ INT CONST number of blocks):
+
+ INT VAR count;
+ disable stop;
+ DATASPACE VAR ds := old (file name);
+ FOR count FROM 0 UPTO (number of blocks - 1) REP
+ write block (ds, count + 3, start block + real (count))
+ UNTIL is error PER;
+ forget (ds).
+
+END PROC write file;
+
+PROC write file (TEXT CONST file name, REAL CONST start block,
+ INT CONST number of blocks, write channel):
+
+ enable stop;
+ INT VAR old channel := channel;
+ IF old channel <> write channel THEN continue (write channel) FI;
+ disable stop;
+ write file (file name, start block, number of blocks);
+ IF old channel <> write channel
+ THEN break (quiet);
+ continue (old channel)
+ FI.
+END PROC write file;
+
+PROC read file (DATASPACE VAR file, REAL CONST start block,
+ INT CONST number of blocks):
+ INT VAR count;
+ disable stop;
+ forget (file); file := nilspace;
+ FOR count FROM 0 UPTO (number of blocks - 1) REP
+ read block (file, count + 3, start block + real (count))
+ UNTIL is error PER.
+END PROC read file;
+
+PROC read file (DATASPACE VAR file, REAL CONST start block,
+ INT CONST number of blocks, read channel):
+ enable stop;
+ INT VAR old channel := channel;
+ IF old channel <> read channel THEN continue (read channel) FI;
+ disable stop;
+ read file (file, start block, number of blocks);
+ IF old channel <> channel
+ THEN break (quiet);
+ continue (old channel)
+ FI.
+END PROC read file;
+
+END PACKET write file;
+
+PACKET thesaurus utilities
+DEFINES ONE, certain : (* Stand: 21.03.88 *)
+ (* Korr : Lutz Prechelt *)
+LET max entries = 200;
+
+LET oben unten rubout return = ""3""10""12""13"";
+
+INT VAR anzahl,
+ firstline, size, (* erste Bildschirmz./Anz. Zeilen für Vorgang *)
+ realc, virtc; (* akt. Zeile in Fenster/Eintragsnummer *)
+
+TEXT VAR string;
+
+THESAURUS PROC certain (THESAURUS CONST in, pre) :
+ einzelne (in, pre, TRUE).
+END PROC certain;
+
+TEXT OP ONE (THESAURUS CONST t):
+ name (einzelne (t, empty thesaurus, FALSE),1)
+END OP ONE;
+
+THESAURUS PROC einzelne (THESAURUS CONST thes, preselections,
+ BOOL CONST viele):
+ (* Benutzt nur den Rest des Bildschirms ab der aktuellen Zeile nach unten.
+ Die in preselections enthaltenen Namen aus t sind bereits zu Beginn
+ angekreuzt.
+ Ein Aufruf mit NOT viele und preselections/t <> empty thesaurus ist
+ nicht sinnvoll.
+ Die Cursorposition nach Verlassen ist wieder in der "aktuellen" Zeile
+ auf Position 1, so daß mit out (""4"") der Kram selektiv gelöscht
+ werden kann.
+ *)
+ ROW maxentries TEXT VAR eintrag;
+ THESAURUS VAR ausgabe :: empty thesaurus,
+ t :: empty thesaurus + thes; (* Leereinträge entfernen! *)
+ INT VAR i;
+ initialisiere ankreuzen;
+ IF anzahl = 0 THEN LEAVE einzelne WITH empty thesaurus FI;
+ bildschirm vorbereiten;
+ bild (1, eintrag);
+ virtc := 1;
+ realc := 1;
+ realcursor setzen;
+ kreuze an (viele, eintrag);
+ ausgabe erzeugen;
+ cursor (1, firstline - 2); out (""4"");
+ ausgabe.
+
+initialisiere ankreuzen:
+ anzahl := highest entry (t);
+ string := "";
+ (* t enthält keine Leereinträge mehr ! *)
+ FOR i FROM 1 UPTO anzahl REP
+ eintrag [i] := name (t,i)
+ PER;
+ FOR i FROM 1 UPTO highest entry (preselections) REP
+ INT CONST preselection link :: link (t, name (preselections, i));
+ IF preselection link > 0
+ THEN string CAT textstr (preselection link) FI
+ PER.
+
+bildschirm vorbereiten:
+ get cursor (i, firstline);
+ out (""13""4""); (* Restbildschirm löschen *)
+ IF viele
+ THEN putline ("Wählen <CR> Löschen <RUBOUT> " +
+ "alle Löschen <HOP><RUBOUT> Beenden <ESC>q")
+ ELSE putline ("Auswählen <CR>") FI;
+ putline ("Marke bewegen <RUNTER> <RAUF> <HOP><RUNTER> <HOP><RAUF>");
+ firstline INCR 2;
+ size := 24 - firstline + 1.
+
+ausgabe erzeugen:
+ WHILE string <> "" REP
+ insert (ausgabe, eintrag [string ISUB 1]);
+ string := subtext (string, 3);
+ PER
+END PROC einzelne;
+
+PROC realcursor setzen:
+ TEXT CONST mark :: marke (virtc, TRUE);
+ cursor (1, firstline + realc - 1);
+ out (mark + LENGTH mark * ""8"").
+END PROC real cursor setzen;
+
+TEXT PROC marke (INT CONST zeiger, BOOL CONST mit cursor):
+ INT VAR pl :: nr (zeiger);
+ IF pl = 0
+ THEN leer
+ ELSE mit zahl
+ FI.
+
+mit zahl:
+ IF mit cursor
+ THEN (3 - length (text (pl))) * "-" + text (pl) + "-> "
+ ELSE text (pl, 3) + " > "
+ FI.
+
+leer:
+ IF mit cursor
+ THEN ">>>>> "
+ ELSE " "
+ FI
+END PROC marke;
+
+PROC bild (INT CONST anfang, ROW maxentries TEXT CONST eintrag):
+ cursor (1, firstline);
+ out (""4""3""); (* Restschirm löschen, 1 Zeile rauf *)
+ INT VAR i;
+ FOR i FROM anfang UPTO grenze REP
+ out (""13""10"");
+ out (marke (i, FALSE));
+ out (eintrag [i])
+ PER.
+
+grenze:
+ min (anzahl, anfang + size - 1)
+END PROC bild;
+
+PROC kreuze an (BOOL CONST viele, ROW maxentries TEXT CONST eintrag) :
+ REP zeichen lesen;
+ zeichen interpretieren
+ PER.
+
+zeichen lesen:
+ TEXT VAR zeichen;
+ inchar (zeichen, ""1""27""3""10""13"1Xx+"11""12"Oo0-").
+
+zeichen interpretieren:
+ SELECT code (zeichen) OF
+ CASE 1 (* hop *) : hoppen (eintrag)
+ CASE 27 (* ESC *) : IF incharety (600) = "q" THEN LEAVE kreuze an FI
+ CASE 3 (* rauf *) : nach oben (eintrag)
+ CASE 10 (* runter *) : nach unten (eintrag)
+ CASE 13 (* Return *) : ankreuzen (eintrag, TRUE); evtl aufhoeren
+ CASE 49,(* 1 *)
+ 88,(* X *)
+ 120,(* x *)
+ 43,(* + *)
+ 11 (* Rubin *) : ankreuzen (eintrag, FALSE); evtl aufhoeren
+ CASE 12,(* Rubout *)
+ 79,(* O *)
+ 111,(* o *)
+ 48,(* 0 *)
+ 45 (* - *) : auskreuzen (eintrag)
+ END SELECT.
+
+evtl aufhoeren:
+ IF NOT viele THEN LEAVE kreuze an FI.
+
+END PROC kreuze an;
+
+PROC hoppen (ROW maxentries TEXT CONST eintrag) :
+ zweites zeichen lesen;
+ zeichen interpretieren.
+
+zweites zeichen lesen:
+ TEXT VAR zz;
+ inchar (zz).
+
+zeichen interpretieren:
+ SELECT pos (oben unten rubout return, zz) OF
+ CASE 1 : hop nach oben
+ CASE 2 : hop nach unten
+ CASE 3 : alles loeschen
+ CASE 4 : rest ankreuzen
+ OTHERWISE out (""7"")
+ END SELECT.
+
+rest ankreuzen:
+ INT VAR i;
+ FOR i FROM 1 UPTO anzahl REP (* alles *)
+ IF nr (i) = 0 (* was noch nicht angekreuzt ist *)
+ THEN string CAT textstr (i) (* ankreuzen *)
+ FI
+ PER;
+ bild aktualisieren.
+
+alles loeschen:
+ string := "";
+ bild aktualisieren.
+
+hop nach oben:
+ IF ganz oben
+ THEN out (""7"")
+ ELIF oben im fenster
+ THEN raufblaettern
+ ELSE top of page
+ FI.
+
+ganz oben:
+ virtc = 1.
+
+oben im fenster:
+ realc = 1.
+
+raufblaettern:
+ virtc DECR size;
+ virtc := max (virtc, 1);
+ bild (virtc, eintrag);
+ realcursor setzen.
+
+top of page:
+ loesche marke;
+ virtc DECR (realc - 1);
+ realc := 1;
+ realcursor setzen.
+
+hop nach unten:
+ IF ganz unten
+ THEN out (""7"")
+ ELIF unten im fenster
+ THEN runterblaettern
+ ELSE bottom of page
+ FI.
+
+ganz unten:
+ virtc = anzahl.
+
+unten im fenster:
+ firstline + realc > 24.
+
+runterblaettern:
+ INT VAR alter virtc :: virtc;
+ virtc INCR size;
+ virtc := min (virtc, anzahl);
+ realc := virtc - alter virtc;
+ bild (alter virtc + 1, eintrag);
+ realcursor setzen.
+
+bottom of page:
+ loesche marke;
+ alter virtc := virtc;
+ virtc INCR (size - realc);
+ virtc := min (anzahl, virtc);
+ realc INCR (virtc - alter virtc);
+ realcursor setzen
+END PROC hoppen;
+
+PROC ankreuzen (ROW maxentries TEXT CONST eintrag, BOOL CONST ggf auskreuzen):
+ (* bei ggf auskreuzen wird der Eintrag, falls er schon angekreuzt ist,
+ ausgekreuzt, andernfalls normal angekreuzt.
+ *)
+ INT VAR pl :: nr (virtc);
+ IF pl <> 0
+ THEN schon angekreuzt
+ FI;
+ string CAT textstr (virtc);
+ IF virtc < anzahl THEN nach unten (eintrag) ELSE realcursor setzen FI.
+
+schon angekreuzt :
+ IF ggf auskreuzen THEN auskreuzen (eintrag) ELSE out (""7"") FI;
+ LEAVE ankreuzen.
+END PROC ankreuzen;
+
+PROC auskreuzen (ROW maxentries TEXT CONST eintrag) :
+ INT VAR posi :: nr (virtc);
+ IF posi = 0
+ THEN out (""7""); LEAVE auskreuzen
+ FI;
+ rausschmeissen;
+ loesche marke;
+ bild aktualisieren;
+ IF virtc < anzahl THEN nach unten (eintrag) FI.
+
+rausschmeissen:
+ string := subtext (string,1, 2*posi-2) + subtext (string,2*posi+1)
+END PROC auskreuzen;
+
+PROC bild aktualisieren:
+ INT VAR ob, un, i;
+ ob := virtc - realc + 1;
+ un := min (ob + size - 1, anzahl);
+ cursor (1, firstline - 1);
+ FOR i FROM ob UPTO un REP
+ out (""13""10""); out (marke (i, FALSE))
+ PER;
+ realcursor setzen.
+END PROC bild aktualisieren;
+
+PROC nach oben (ROW maxentries TEXT CONST eintrag) :
+ IF noch nicht oben (* virtuell *)
+ THEN gehe nach oben
+ ELSE out (""7"")
+ FI;
+ realcursor setzen.
+
+noch nicht oben:
+ virtc > 1.
+
+gehe nach oben:
+ IF realc = 1
+ THEN scroll down
+ ELSE cursor up
+ FI.
+
+scroll down:
+ virtc DECR 1;
+ bild (virtc, eintrag).
+
+cursor up:
+ loesche marke;
+ virtc DECR 1;
+ realc DECR 1.
+END PROC nach oben;
+
+PROC nach unten (ROW maxentries TEXT CONST eintrag) :
+ IF noch nicht unten (* virtuell *)
+ THEN gehe nach unten
+ ELSE out (""7"")
+ FI.
+
+noch nicht unten:
+ virtc < anzahl.
+
+gehe nach unten:
+ IF realc > size - 1
+ THEN scroll up
+ ELSE cursor down
+ FI.
+
+scroll up:
+ virtc INCR 1;
+ bild (virtc - size + 1, eintrag);
+ realcursor setzen.
+
+cursor down:
+ loesche marke;
+ virtc INCR 1;
+ realc INCR 1;
+ realcursor setzen
+END PROC nach unten;
+
+PROC loesche marke:
+ out (marke (virtc, FALSE))
+END PROC loesche marke;
+
+TEXT PROC textstr (INT CONST nr):
+ TEXT VAR help :: " ";
+ replace (help, 1, nr);
+ help.
+END PROC textstr;
+
+INT PROC nr (INT CONST zeiger):
+ IF pos (string, textstr (zeiger)) = 0 (* haut hin, da zeiger < 255 *)
+ THEN 0
+ ELSE (pos (string,textstr (zeiger)) DIV 2) + 1
+ FI
+END PROC nr;
+
+PROC inchar (TEXT VAR t, TEXT CONST allowed) :
+ REP
+ getchar (t);
+ IF pos (allowed, t) = 0 THEN out (""7"") FI
+ UNTIL pos (allowed, t) > 0 PER.
+END PROC inchar;
+
+END PACKET thesaurus utilities;
+
diff --git a/system/setup/3.1/src/setup eumel 2: modulzugriffe b/system/setup/3.1/src/setup eumel 2: modulzugriffe
new file mode 100644
index 0000000..42163f4
--- /dev/null
+++ b/system/setup/3.1/src/setup eumel 2: modulzugriffe
@@ -0,0 +1,441 @@
+
+(* Pakete:
+ 1. setup eumel modulzugriffe
+ Abstrakter Datentyp MODUL : Typ, Datenraumtyp, Zugriffsoperationen
+ 2. setup eumel modul und shard zugriffe
+ Zugriffe in Module und SHards (Datentyp MODUL) mit Strukturwissen
+*)
+
+(**************************************************************************)
+(***** Datentyp MODUL und Zugriffsoperationen dafür ****************)
+(***** Copyright (c) 1987, 1988 by ****************)
+(***** Lutz Prechelt, Karlsruhe ****************)
+(**************************************************************************)
+
+PACKET setup eumel modulzugriffe (* Copyright (c) 1987 by *)
+DEFINES int, byte, text, unsigned, (* Lutz Prechelt, Karlsruhe *)
+ dtcb abfragen, ccb abfragen, (* Stand : 12.03.88 1.1 *)
+ dtcb refinements, ccb refinements, (* Eumel 1.8.1 *)
+ info,
+ page,
+ copy,
+ datenraumtyp modul,
+ MODUL :
+
+
+(* Dies Paket realisiert gezielte Zugriffe in einen Struct vom Typ MODUL.
+ Dies ist das Format eines SHard Moduls. Der Typ wird auch verwendet, um
+ das SHard-Hauptmodul oder einzelne ccbs zu handhaben!
+ Für die Adressierung der Bytes werden REAL-Werte verwendet, damit die
+ Größe nicht auf maxint beschränkt ist. Dies ist normalerweise sicher
+ (wegen der BCD-Arithmetik des Eumel), jedoch sind sinnlose nichtganzzahlige
+ Adressen dadurch möglich. Das wird aus Effizienzgründen nicht abgefangen,
+ die korrekte Benutzung liegt in der Verantwortung des Aufrufers.
+ Es sollen alle Zugriffe auf Module nur mit den Prozeduren dieses Pakets
+ abgewickelt werden.
+*)
+
+
+INT CONST high only ::-256,
+ low only :: 255;
+
+LET max page = 128;
+
+TYPE MODUL = STRUCT (ALIGN dummy, ROW 256 INT header,
+ ROW max page ROW 256 INT b,
+ INT dtcb abfragen, ccb abfragen,
+ TEXT dtcb ref, ccb ref, info);
+
+(* Der Typ kann wegen des ALIGN direkt auf einen Datenraum (für ein Modul)
+ gelegt werden. Der Teil b fasst 64kB Daten und kann direkt für blockout
+ verwendet werden. Die restlichen Teile sind nur für Module relevant.
+*)
+
+INT CONST datenraumtyp modul :: 5687; (* Typ eines MODUL als Datenraum *)
+
+(*********************** INT ********************************************)
+
+INT PROC int (MODUL CONST m, REAL CONST byte nr) :
+ (* liefert das INT aus dem Modul m, das bei Byte "byte nr" beginnt *)
+ INT VAR page :: int (byte nr DIV 512.0) + 1,
+ nr :: int (byte nr MOD 512.0) DIV 2 + 1;
+ INT VAR whole int :: m.b[page][nr];
+ IF byte nr MOD 2.0 <> 0.0
+ THEN rotate (whole int, 8); (* high und low byte vertauschen *)
+ (whole int AND low only) + next byte in high
+ ELSE whole int FI.
+
+next byte in high :
+ IF nr = 256 THEN nr := 1; page INCR 1 ELSE nr INCR 1 FI;
+ INT VAR help :: m.b[page][nr] AND low only;
+ rotate (help, 8);
+ help.
+END PROC int;
+
+INT PROC int (MODUL CONST m, INT CONST byte nr) :
+ int (m, real (byte nr))
+END PROC int;
+
+PROC int (MODUL VAR m, REAL CONST byte nr, INT CONST new) :
+ (* schreibt den neuen 16-Bit Wert new ab dem Byte "byte nr" in den Teil b
+ des Moduls m. Hier kommt es nicht sehr aufs Tempo an, deshalb benutzen
+ wir hier einfach "byte".
+ *)
+ INT VAR value :: new;
+ rotate (value, 8); (* high byte zu low byte machen *)
+ byte (m, byte nr, new AND low only);
+ byte (m, byte nr + 1.0, value AND low only);
+END PROC int;
+
+PROC int (MODUL VAR m, INT CONST byte nr, INT CONST new) :
+ int (m, real (byte nr), new)
+END PROC int;
+
+(************************** BYTE *******************************************)
+
+INT PROC byte (MODUL CONST m, REAL CONST byte nr) :
+ (* liefert das Byte mit der Nummer "byte nr" aus dem Teil b des Moduls m.
+ Das erste Byte hat die Nummer 0
+ *)
+ INT CONST page :: int (byte nr DIV 512.0) + 1,
+ nr :: int (byte nr MOD 512.0) DIV 2 + 1;
+ INT VAR whole int :: m.b[page][nr];
+ IF byte nr MOD 2.0 <> 0.0
+ THEN rotate (whole int, 8); (* high und low byte vertauschen *) FI;
+ whole int AND low only.
+END PROC byte;
+
+INT PROC byte (MODUL CONST m, INT CONST byte nr) :
+ byte (m, real (byte nr))
+END PROC byte;
+
+PROC byte (MODUL VAR m, REAL CONST byte nr, INT CONST new) :
+ (* Schreibt die unteren 8 bit von new an das Byte der Stelle byte nr im
+ Modul m
+ *)
+ INT CONST page :: int (byte nr DIV 512.0) + 1,
+ nr :: int (byte nr MOD 512.0) DIV 2 + 1;
+ INT VAR new byte :: new AND low only,
+ whole int :: m.b[page][nr];
+ m.b[page][nr] := new int.
+
+new int :
+ IF byte nr MOD 2.0 = 0.0 (* low byte ändern ? *)
+ THEN (whole int AND high only) + new byte
+ ELSE rotate (new byte, 8); (* new nach high rotieren *)
+ new byte + (whole int AND low only)
+ FI.
+END PROC byte;
+
+PROC byte (MODUL VAR m, INT CONST byte nr, INT CONST new) :
+ byte (m, real (byte nr), new)
+END PROC byte;
+
+(*********************** TEXT ********************************************)
+
+TEXT PROC text (MODUL CONST m, REAL CONST first byte nr, INT CONST length) :
+ (* Extrahiert die naechsten length bytes aus m ab byte nr als TEXT *)
+ REAL VAR i :: first byte nr;
+ TEXT VAR result :: "";
+ WHILE i < first byte nr + real (length) REP
+ result CAT code (byte (m, i));
+ i INCR 1.0
+ PER;
+ result.
+END PROC text;
+
+TEXT PROC text (MODUL CONST m, INT CONST first byte nr, INT CONST length) :
+ text (m, real (first byte nr), length)
+END PROC text;
+
+(* Ein schreibendes Analogon zu "text" gibt es nicht. *)
+
+(*********************** unsigned *****************************************)
+
+REAL PROC unsigned (INT CONST sixteen bits) :
+ (* hiermit kann man die Vorzeichenprobleme umschiffen, die der Eumel bei
+ INTs über maxint macht.
+ Liefert das INT als 16-Bit unsigned Wert interpretiert im REAL-Format.
+ *)
+ real (text (sixteen bits, dec))
+END PROC unsigned;
+
+INT PROC unsigned (REAL CONST sixteen bit value) :
+ (* Umkehrung des obigen : REAL 0..65536 rein, passenden 16 bit unsigned
+ Wert raus
+ *)
+ TEXT CONST t :: text (sixteen bit value);
+ int (unsigned (value text)).
+
+value text :
+ IF pos (t, ".") <> 0
+ THEN subtext (t, 1, pos (t, ".") - 1)
+ ELSE t
+ FI.
+END PROC unsigned;
+
+(******************** dtcb, ccb, info **************************************)
+
+INT PROC dtcb abfragen (MODUL CONST m) :
+ m.dtcb abfragen
+END PROC dtcb abfragen;
+
+PROC dtcb abfragen (MODUL VAR m, INT CONST neu) :
+ m.dtcb abfragen := neu
+END PROC dtcb abfragen;
+
+TEXT PROC dtcb refinements (MODUL CONST m) :
+ m.dtcb ref
+END PROC dtcb refinements;
+
+PROC dtcb refinements (MODUL VAR m, TEXT CONST neu) :
+ m.dtcb ref := neu
+END PROC dtcb refinements;
+
+INT PROC ccb abfragen (MODUL CONST m) :
+ m.ccb abfragen
+END PROC ccb abfragen;
+
+PROC ccb abfragen (MODUL VAR m, INT CONST neu) :
+ m.ccb abfragen := neu
+END PROC ccb abfragen;
+
+TEXT PROC ccb refinements (MODUL CONST m) :
+ m.ccb ref
+END PROC ccb refinements;
+
+PROC ccb refinements (MODUL VAR m, TEXT CONST neu) :
+ m.ccb ref := neu
+END PROC ccb refinements;
+
+TEXT PROC info (MODUL CONST m) :
+ m.info
+END PROC info;
+
+PROC info (MODUL VAR m, TEXT CONST neu) :
+ m.info := neu
+END PROC info;
+
+(********************* page **********************************************)
+
+(* Die Prozedur page dient dazu, aus dem Datenbereich b eines MODULs
+ einzelne Seiten (512 Byte Blöcke) in Form eines ROW 256 INT anzusprechen
+ um damit blockin/blockout zu machen.
+ Die Seitennummern gehen von 1 bis max page
+*)
+
+ROW 256 INT PROC page (MODUL CONST m, INT CONST page nr) :
+ m.b[page nr]
+END PROC page;
+
+PROC page (MODUL VAR m, INT CONST page nr, ROW 256 INT CONST new page) :
+ m.b[page nr] := new page
+END PROC page;
+
+(*********************** copy ********************************************)
+
+PROC copy (MODUL CONST from, REAL CONST origin,
+ MODUL VAR to, REAL CONST destination, INT CONST length) :
+ (* Kopiert schnell eine Anzahl von Bytes aus einem Modul in ein anderes
+ die Optimierung klappt nur, wenn von einer geraden Adresse an eine
+ gerade Adresse kopiert wird oder von ungerade nach ungerade.
+ Macht cout.
+ *)
+ INT VAR i, interval :: cout interval;
+ REAL VAR offset :: 0.0;
+ IF length < 0 THEN errorstop ("copy : length = " + text (length)) FI;
+ IF origin MOD 2.0 <> destination MOD 2.0
+ THEN copy slow
+ ELSE copy fast FI;
+ cout (length).
+
+cout interval :
+ IF length > 1024 THEN 32
+ ELIF length > 64 THEN 8
+ ELSE 1 FI.
+
+copy slow :
+ FOR i FROM 1 UPTO length REP
+ IF i MOD 2*interval = 0 THEN cout (i) FI;
+ byte (to, destination + offset, byte (from, origin + offset));
+ offset INCR 1.0
+ PER.
+
+copy fast :
+ IF origin MOD 2.0 <> 0.0 AND length > 0
+ THEN byte (to, destination, byte (from, origin));
+ offset := 1.0
+ FI;
+ FOR i FROM 1 UPTO (length - int (origin MOD 2.0)) DIV 2 REP
+ INT CONST page1 :: int ((origin+offset) DIV 512.0) + 1,
+ nr1 :: int ((origin+offset) MOD 512.0) DIV 2 + 1,
+ page2 :: int ((destination+offset) DIV 512.0) + 1,
+ nr2 :: int ((destination+offset) MOD 512.0) DIV 2 + 1;
+ to.b[page2][nr2] := from.b[page1][nr1];
+ IF i MOD interval = 0 THEN cout (2*i) FI;
+ offset INCR 2.0
+ PER;
+ IF length - int (offset) = 1
+ THEN byte (to, destination + offset, byte (from, origin + offset)) FI.
+END PROC copy;
+
+(************************ Hilfsprozeduren ********************************)
+
+REAL OP DIV (REAL CONST a, b) :
+ floor (a/b)
+END OP DIV;
+
+END PACKET setup eumel modulzugriffe;
+
+
+(**************************************************************************)
+(***** Zugriffe in Module mit Strukturwissen ****************)
+(***** Copyright (c) 1988 by ****************)
+(***** Lutz Prechelt, Karlsruhe ****************)
+(**************************************************************************)
+
+PACKET setup eumel modul und shard zugriffe (* Copyright (c) 1988 by *)
+DEFINES sh dtcb offset, (* Lutz Prechelt, Karlsruhe *)
+ sh ccb offset, (* Stand : 23.04.88 1.2 *)
+ get new channel table, (* Eumel 1.8.1 *)
+ init modules list,
+ all modules,
+ module type,
+ module name:
+
+(* Dieses Paket definiert Operationen zum Zugriff auf bestimmte Daten in
+ SHardmodulen und SHards. Es ist hierin Wissen über die Struktur dieser
+ Teile enthalten.
+ Beschreibung des SHardformats siehe setup eumel 4: modulkonfiguration
+*)
+
+LET nr of channels total = 40,
+ offset channel table pointer = 10;
+
+THESAURUS VAR all the beautiful modules we know :: emptythesaurus;
+
+(******************* Kanaltabelle lesen/schreiben **************************)
+
+(* Hier geht schöne Struktur (und damit zugleich einfache Programmierung)
+ über gute Performance. (Wir lesen einiges mehrfach)
+*)
+
+REAL PROC sh dtcb offset (MODUL CONST shard, INT CONST kanal) :
+ unsigned (int (shard, ct + 4 * kanal)).
+
+ct :
+ int (shard, offset channel table pointer).
+END PROC sh dtcb offset;
+
+REAL PROC sh ccb offset (MODUL CONST shard, INT CONST kanal) :
+ unsigned (int (shard, ct + 4 * kanal + 2)).
+
+ct :
+ int (shard, offset channel table pointer).
+END PROC sh ccb offset;
+
+PROC sh dtcb offset (MODUL VAR shard, INT CONST kanal, REAL CONST value) :
+ int (shard, ct + 4 * kanal, unsigned (value)).
+
+ct :
+ int (shard, offset channel table pointer).
+END PROC sh dtcb offset;
+
+PROC sh ccb offset (MODUL VAR shard, INT CONST kanal, REAL CONST value) :
+ int (shard, ct + 4 * kanal + 2, unsigned (value)).
+
+ct :
+ int (shard, offset channel table pointer).
+END PROC sh ccb offset;
+
+PROC get new channel table (MODUL CONST new shard,
+ ROW 256 INT VAR channel table of new shard) :
+ (* Kopiert die Kanaltabelle aus new shard nach
+ channel table of new shard
+ *)
+ INT VAR offset :: int (new shard, offset channel table pointer);
+ INT VAR i;
+ FOR i FROM 1 UPTO 2 * nr of channels total REP
+ channel table of new shard [i] := int (new shard, offset);
+ offset INCR 2
+ PER.
+END PROC get new channel table;
+
+(********************* modules list handling *****************************)
+
+TEXT VAR m list;
+
+PROC init modules list :
+ (* Baut in der Variablen m list einen "Assoziativspeicher" für
+ Modulnamen <--> Modultyp auf und erstellt eine Liste aller
+ Shardmoduldateinamen für "all modules"
+ Der Text m list enthält für jede Datei, die ein SHardmodul enthält,
+ einen Eintrag folgender Form :
+ ""0"", modultyp, ""0"", Dateiname, ""0""
+ Dabei ist modultyp genau 4 Byte lang.
+ Diese Eintragsform ermöglicht ein (auf dem Eumel) sehr effizientes
+ Suchen, sowohl von Modultypen zu Modulnamen als auch umgekehrt.
+ Die Prozedur macht cout (dateinummer)
+ *)
+ INT VAR i;
+ TEXT VAR t;
+ m list := ""; all the beautiful modules we know := empty thesaurus;
+ FOR i FROM 1 UPTO highest entry (all) REP
+ cout (i);
+ t := name (all, i);
+ IF t <> "" CAND type (old (t)) = datenraumtyp modul
+ THEN add t FI
+ PER.
+
+add t :
+ insert (all the beautiful modules we know, t);
+ TEXT CONST typ :: read module type (t);
+ m list cat typmarker;
+ m list CAT t;
+ m list CAT ""0"".
+
+m list cat typmarker :
+ m list CAT ""0"";
+ m list CAT typ;
+ m list CAT ""0"".
+END PROC init modules list;
+
+THESAURUS PROC all modules :
+ all the beautiful modules we know.
+END PROC all modules;
+
+TEXT PROC read module type (TEXT CONST datei) :
+ (* Liefert den 4-Byte Modultyp des in der Datei datei enthaltenen
+ SHardmoduls, falls möglich, andernfalls ""
+ *)
+ IF NOT exists (datei) COR type (old (datei)) <> datenraumtyp modul
+ THEN ""
+ ELSE BOUND MODUL CONST m :: old (datei);
+ text (m, int (m, 8), 4)
+ FI.
+END PROC read module type;
+
+TEXT PROC module type (TEXT CONST module name) :
+ (* Liefert den 4-Byte Modultyp zu module name aus m list, sofern vorhanden
+ andernfalls ""
+ *)
+ INT CONST p :: pos (m list, ""0"" + module name + ""0"");
+ IF p = 0
+ THEN ""
+ ELSE subtext (m list, p - 4, p - 1) FI.
+END PROC module type;
+
+TEXT PROC module name (TEXT CONST module type) :
+ (* Liefert den Moduldateinamen zum 4-Byte Modultyp module type, oder
+ "" falls kein solches Modul vorhanden.
+ *)
+ INT VAR p :: pos (m list, ""0"" + module type + ""0"");
+ IF p = 0
+ THEN ""
+ ELSE p INCR 6;
+ subtext (m list, p, pos (m list, ""0"", p) - 1)
+ FI.
+END PROC module name;
+
+END PACKET setup eumel modul und shard zugriffe;
+
diff --git a/system/setup/3.1/src/setup eumel 3: modulkonfiguration b/system/setup/3.1/src/setup eumel 3: modulkonfiguration
new file mode 100644
index 0000000..529d0de
--- /dev/null
+++ b/system/setup/3.1/src/setup eumel 3: modulkonfiguration
@@ -0,0 +1,854 @@
+
+(**************************************************************************)
+(***** Ergänzung des SHards um ein Modul (mit Dialog) *****************)
+(***** Copyright (c) 1987, 1988 by *****************)
+(***** Lutz Prechelt, Karlsruhe *****************)
+(**************************************************************************)
+
+PACKET setup eumel modulkonfiguration (* Copyright (c) by *)
+DEFINES configurate module, (* Lutz Prechelt, Karlsruhe *)
+ print configuration, (* Eumel 1.8.1 *)
+ give me, take you, (* Stand : 12.07.88 3.2 *)
+ new index,
+ perform dtcb dialogue,
+ perform ccb dialogue,
+ (* für Modulprogrammierer : *)
+ write info,
+ channel free,
+ reserve channel,
+ channels of this module,
+ buffer address :
+
+(* Dieses Modul führt den kompletten Dialog mit dem Benutzer durch, der
+ nötig ist, um alle Kanäle, die mit demselben Modul laufen sollen, zu
+ konfigurieren.
+ Verfahren :
+ im alten SHard den dtcb suchen
+ dtcb und Modul im neuen SHard eintragen
+ dtcb mit oder ohne Vorbild konfigurieren
+ alle ccbs zu dem Modul im alten SHard suchen und Kanalnummern merken
+ Auswahl einer Kanalmenge durch Benutzer mit alten als Vorschlag
+ ccbs in neuen SHard kopieren
+ ccbs mit oder ohne Vorbild konfigurieren
+ Kanaltabelle auf den neuen Stand bringen
+ neuen Shard und seine geänderte Länge zurückgeben
+
+ Dabei kann der "Dialog" bei geeigneten Rahmenbedingungen durch bloßes
+ Übertragen der Werte aus einem Vorlage-SHard ersetzt werden, wenn der
+ Benutzer dies wünscht (want automatic mode). Dann geht alles von selbst.
+ (....kaufen Sie Setup-Eumel und es geht alles wie von selbst !)
+
+Format des SHard-Hauptmoduls :
+ 1. (Byte 0-2) jmp boot (3 Byte)
+ 2. (Byte 3) reserviert
+ 3. (Byte 4) SHard-Version
+ 4. (Byte 5) SHard-Release
+ 5. (Byte 6/7) SHardlänge (2 Byte)
+ 6. (Byte 8/9) Verweis auf Bad-Block Tabelle (2 Byte)
+ 7. (Byte 10/11) Verweis auf Kanaltabelle
+ 8. (Byte 16-175) Eumelleiste
+ 9. (Byte 176-299) SHardleiste
+ 10. (ab Byte 300) Shardhauptmodulroutinen und -daten
+ 11. (danach) Rumpf des Hauptmoduls mit Bad-Block-Tabelle,
+ Kanaltabelle, Routinen und Daten
+ 12. (danach) Folge der Module (bis Byte SHardlänge - 1)
+
+Kanaltabelle:
+ feste Länge 40 Einträge "nr of channels total" (Kanal 0 bis Kanal 39)
+ jeder Eintrag besteht aus : (alles 2 Byte)
+ offset dtcb, offset ccb
+
+Achtung : Dieses Programm schmiert bei SHards über 32767 Byte Länge
+ eventuell ab (es hat noch niemand probiert) !
+
+Abkürzungen: cb steht für control block und meint entweder ccb oder dtcb
+
+Implementationsanmerkung :
+Bei der Verwendung von THESAURUS wird von dem Wissen über die Art der
+Implementation derselben Gebrauch gemacht, indem folgende Annahmen in den
+Code eingehen:
+1. Bei einem THESAURUS, in dem nicht gelöscht wurde, ist highest entry gleich
+ der Kardinalität
+2. außerdem entspricht dann die Nummer (link) eines Eintrags seinem
+ Eintragszeitpunkt, d.h. der Position in der Eintragsfolge
+3. + und - liefert THESAURi, in denen nicht gelöscht wurde und die Eintrags-
+ reihenfolge ist wie von den Parametern vorgegeben (bei + links zuerst)
+4. certain und ONE liefern THESAURi, in denen nicht gelöscht wurde.
+*)
+
+(************************* Daten ********************************)
+
+LET nr of channels total = 40, (* SHard Tabellenlänge *)
+ mdts = 40, (* max dialogtable size in INTs *)
+ mchm = 20, (* max channels for module *)
+ offset sh version = 4,
+ offset sh structureversion = 5,
+ offset shardlength = 6,
+
+ do name = "PrOgRaM tO Do";
+
+LET UNSIGNED = INT,
+ VARIABLES = ROW mdts ROW mchm INT;
+TEXT CONST variables var xxv :: "ROW " + text (mdts) + " ROW "+
+ text (mchm) + " INT VARxxv;";
+
+VARIABLES VAR v; (* siehe give me / take you *)
+
+INT VAR max index; (* Information für new index *)
+
+INT VAR channels of module; (* Information für channels of this module *)
+
+TEXT VAR actual info; (* fuer write info *)
+
+ROW 256 INT VAR channel table of new shard; (* für channel free *)
+
+DATASPACE VAR dummy ds; (* für print configuration *)
+
+REAL VAR new shard length;
+
+(***************************************************************************)
+(************* Hier geht's los...... ***************************************)
+(***************************************************************************)
+
+(******************** configurate module **********************************)
+
+PROC configurate module (MODUL VAR new shard, MODUL CONST old shard,
+ BOOL CONST old shard valid, want automatic mode,
+ TEXT CONST modulname) :
+ do configurate module (new shard, old shard, old shard valid,
+ want automatic mode, modulname, FALSE)
+END PROC configurate module;
+
+(********************** print configuration *******************************)
+
+PROC print configuration (MODUL CONST old shard, TEXT CONST modulname) :
+ (* Es ist hier schon sichergestellt, daß old shard valid ist und das Modul
+ auch im SHard enthalten
+ *)
+ forget (dummy ds); dummy ds := nilspace;
+ BOUND MODUL VAR dummy :: dummy ds;
+ do configurate module (dummy, old shard, TRUE, FALSE, modulname, TRUE);
+ forget (dummy ds).
+END PROC print configuration;
+
+
+(******************* do configurate module *********************************)
+
+PROC do configurate module (MODUL VAR new shard, MODUL CONST old shard,
+ BOOL CONST old shard valid, want automatic mode,
+ TEXT CONST modulname,
+ BOOL CONST print configuration only):
+ (* In dieser Prozedur ist die Beschränkung auf Module mit unter 32kB
+ Länge ausgenutzt.
+ Ist kein alter SHard vorhanden, so muss ein leerer SHard übergeben
+ werden (d.h. alle Einträge in der Kanaltabelle sind 0).
+ Ein alter SHard darf keinesfalls unterschiedliche releases desselben
+ Modultyps enthalten.
+ Resultierende SHardgesamtlängen von über 32k sind noch nicht getestet.
+ *)
+ BOUND MODUL VAR m;
+ INT VAR (***** Daten über das neue Modul *****)
+ sh version, sh structure version, release,
+ max ccb, nr of ccbs,
+ dtcb table entries, offset dtcb table, (* Variablentabellen *)
+ ccb table entries, offset ccb table,
+ muster ccb length, offset muster ccb, (* Muster-ccb im Modul *)
+ module body length, (* Länge des zu kopierenden Modulrumpfs *)
+ offset module body, offset dtcb;
+ TEXT VAR modultyp; (* 4 Byte *)
+ INT VAR (***** Daten über den alten SHard *****)
+ old release :: -2; (* garantiert inkompatibel *)
+ REAL VAR offset old dtcb :: 0.0;
+ ROW nr of channels total REAL VAR offset old ccb;
+ BOOL VAR old cbs valid :: FALSE;
+ THESAURUS VAR old channels :: empty thesaurus;
+ (***** Daten über den neuen SHard *****)
+ REAL VAR dtcb location;
+ ROW nr of channels total REAL VAR ccb location;
+ (***** Sonstige Daten *****)
+ INT VAR i, k, kanal, ccb count;
+ BOOL VAR automatic mode, configurate :: NOT print configuration only;
+ reset direction (FALSE); (* zur Sicherheit *)
+ IF configurate
+ THEN new shard length := unsigned (int (new shard, offset shard length)) FI;
+ connect module;
+ get module data;
+ test sh version compatibility; (* ggf. LEAVE *)
+ (* Bisher wurde nur gelesen, ab jetzt darf nicht mehr abgebrochen werden *)
+ search old shard for module and find all old ccbs;
+ test release compatibility; (* ggf. LEAVE *)
+ IF configurate
+ THEN write module with dtcb to shard;
+ perhaps set automatic mode;
+ FI;
+ configurate dtcb;
+ IF configurate
+ THEN kopf;
+ select channels;
+ write ccbs to shard;
+ ELSE nr of ccbs := highest entry (old channels)
+ FI;
+ configurate ccbs;
+ IF configurate
+ THEN make entries in channeltable of new shard;
+ int (new shard, offset shardlength, unsigned (new shard length))
+ FI.
+
+connect module :
+ m := old (modulname);
+ actual info := info (m);
+ IF configurate
+ THEN kopf
+ ELSE put ("-----"); put (modulname); putline ("-----")
+ FI.
+
+get module data :
+ (* Format des Moduls in den ersten Bytes:
+ Byte Entry
+ 0/1 offset dtcb variablen tabelle
+ 2/3 offset ccb variablen tabelle
+ 4/5 offset muster-ccb
+ 6/7 offset modulrumpf
+ 8/9 offset dtcb
+ 10/11 max anzahl ccbs
+ die tabellen enthalten im ersten Wort die Anzahl ihrer Einträge
+ der modulrumpf und der ccb ihre Länge in Byte
+ die Länge der Tabellen ergibt sich aus den offset-Differenzen.
+ dtcb-Format : Modultyp (4 Byte)
+ SHardversion (1 Byte)
+ SHardstrukturversion (1 Byte)
+ Modulrelease (2 Byte) ....
+ *)
+ max ccb := int (m, 10);
+ offset dtcb table := int (m, 0);
+ dtcb table entries := int (m, offset dtcb table);
+ offset ccb table := int (m, 2);
+ ccb table entries := int (m, offset ccb table);
+ offset muster ccb := int (m, 4);
+ muster ccb length := int (m, offset muster ccb);
+ offset module body := int (m, 6);
+ module body length := int (m, offset module body);
+ offset dtcb := int (m, 8);
+(*****
+put (" offset dtcb table:"); put( offset dtcb table); line;
+put (" dtcb table entrie:"); put( dtcb table entries); line;
+put (" offset ccb table :"); put( offset ccb table); line;
+put (" ccb table entrie:"); put( ccb table entries); line;
+put (" offset muster ccb:"); put( offset muster ccb); line;
+put (" muster ccb length:"); put( muster ccb length); line;
+put (" offset module bod:"); put( offset module body); line;
+put (" module body lengt:"); put( module body length); line;
+put (" offset dtcb :"); put( offset dtcb); line;*****)
+ modultyp := text (m, offset dtcb, 4);
+ sh version := byte (m, offset dtcb + 4);
+ sh structureversion := byte (m, offset dtcb + 5);
+ release := int (m, offset dtcb + 6).
+
+test sh version compatibility :
+ IF configurate AND NOT version is compatible
+ THEN putline ("Das Modul ist mit dieser SHard-Version nicht mehr verträglich.");
+ putline (""10""10""15" Installation des Moduls wird abgebrochen. "14""7""13""10"");
+ go on;
+ LEAVE do configurate module
+ FI.
+
+version is compatible:
+ (* Kompatibel, wenn das Modul eine ältere oder gleiche sh version verlangt
+ und die gleiche sh structureversion
+ *)
+ sh version <= byte (new shard, offset sh version) CAND
+ sh structure version = byte (new shard, offset sh structureversion).
+
+search old shard for module and find all old ccbs :
+ (* Es werden alle Kanäle des alten SHard untersucht, ob der dortige Treiber
+ den gleichen Modultyp hat und in diesem Fall die Kanalnummer in
+ "old channels" gesammelt, sowie offset old ccb gemerkt, im Nichterfolgs-
+ falle wird offset old ccb auf diesem Kanal 0 gesetzt.
+ Es werden auch alle verketteten Treiber untersucht.
+ Auch old cbs valid und offset old dtcb werden ggf. gesetzt.
+ *)
+ IF NOT old shard valid
+ THEN LEAVE search old shard for module and find all old ccbs FI;
+ IF configurate THEN put ("Ich untersuche den alten SHard :") FI;
+ FOR kanal FROM 0 UPTO nr of channels total - 1 REP
+ IF configurate THEN cout (kanal) FI;
+ collect ccbs on this channel
+ PER;
+ IF configurate THEN put (""13""5"") FI. (* Zeile löschen *)
+
+collect ccbs on this channel :
+ REAL VAR p dtcb :: sh dtcb offset (old shard, kanal),
+ p ccb :: sh ccb offset (old shard, kanal);
+ WHILE p dtcb <> 0.0 AND p ccb <> 0.0 REP
+ BOOL CONST success :: text (old shard, p dtcb, 4) = modultyp;
+ IF success
+ THEN offset old dtcb := p dtcb;
+ old release := int (old shard, p dtcb + 6.0);
+ insert (old channels, text (kanal));
+ offset old ccb [kanal+1] := p ccb
+ ELSE p dtcb := unsigned (int (old shard, p ccb + 2.0)); (* verkettet *)
+ p ccb := unsigned (int (old shard, p ccb + 4.0))
+ FI
+ UNTIL success PER;
+ old cbs valid := old shard valid AND offset old dtcb <> 0.0 AND
+ (release = old release + 1 OR release = old release).
+
+test release compatibility:
+ IF print configuration only AND NOT old cbs valid
+ THEN putline ("Kein Zugriff auf die Konfigurationsdaten möglich");
+ LEAVE do configurate module
+ FI.
+
+write module with dtcb to shard :
+ put ("Modul """ + modulname + """ wird in den SHard eingetragen :");
+ IF int (new shard length MOD 2.0) <> offset module body MOD 2
+ THEN new shard length INCR 1.0 FI; (* kopiert so schneller *)
+ dtcb location := new shard length +
+ real (offset dtcb - offset module body);
+ copy (m, real (offset module body), new shard, new shard length,
+ module body length);
+ new shard length INCR real (module body length).
+
+perhaps set automatic mode :
+ IF old cbs valid AND old release = release
+ THEN automatic mode := want automatic mode
+ ELSE automatic mode := FALSE FI.
+
+configurate dtcb :
+ IF configurate
+ THEN kopf;
+ putline ("Konfiguration des Treibers :");
+ get new channel table (new shard, channel table of new shard);
+ FI;
+ perform dtcb dialogue (m, real (offset dtcb table+2), dtcb table entries,
+ new shard, dtcb location,
+ old shard, offset old dtcb,
+ old cbs valid, release = old release,
+ dtcb refinements (m), dtcb abfragen (m),
+ automatic mode, print configuration only).
+
+select channels :
+ ccb count := highest entry (old channels);
+ k := min (ccb count, max ccb); (* .... Mutter der Porzellankiste *)
+ nr of ccbs := max (k, 1);
+ IF automatic mode THEN LEAVE select channels FI;
+ IF max ccb > 1
+ THEN REP
+ editget ("Wieviele Kanäle mit diesem Treiber (1 bis " +
+ text (max ccb) + ") : ", nr of ccbs);
+ out (""13"")
+ UNTIL nr of ccbs IN range (1, max ccb) PER;
+ out (""10""10"")
+ ELSE nr of ccbs := 1 FI;
+ IF nr of ccbs < ccb count (* weniger als früher *)
+ THEN put ("Wählen Sie mindestens"); putline (x kanäle aus deren);
+ putline ("Werte nicht als Vorbesetzung angeboten werden sollen"10"");
+ REP
+ THESAURUS CONST help :: certain (old channels, empty thesaurus);
+ IF NOT enough refused THEN out (""7"") FI
+ UNTIL enough refused PER;
+ old channels := old channels - help;
+ out (""3""3""3""4"") (* clear screen from incl. "Wählen..." on *)
+ FI.
+
+x kanäle aus deren :
+ IF ccb count - nr of ccbs > 1
+ THEN text (ccb count - nr of ccbs) + " Kanäle aus, deren"
+ ELSE "einen Kanal aus, dessen" FI.
+
+enough refused :
+ highest entry (help) >= ccb count - nr of ccbs.
+
+write ccbs to shard :
+ (* Ausserdem wird hier ccb location vorbereitet *)
+ out ("Die Kanäle werden in den neuen SHard eingetragen : ");
+ FOR i FROM 1 UPTO nr of ccbs REP
+ ccb location [i] := new shard length;
+ copy (m, real (offset muster ccb + 2), new shard, new shard length,
+ muster ccb length);
+ new shard length INCR real (muster ccb length)
+ PER.
+
+configurate ccbs :
+ (*put (old shard valid); put ("Release:"); put (release); put (" old release:"); put (old release);
+ put (old cbs valid); pause;*)
+ IF configurate
+ THEN out (""13""10"Konfiguration der Kanäle:"13""10"");
+ get new channel table (new shard, channel table of new shard)
+ FI;
+ ccb count := 0;
+ FOR kanal FROM 0 UPTO nr of channels total REP
+ IF old channels CONTAINS text (kanal)
+ THEN ccb count INCR 1;
+ offset old ccb [ccb count] := offset old ccb [kanal+1]
+ FI
+ PER;
+ FOR i FROM ccb count + 1 UPTO nr of ccbs REP
+ offset old ccb [i] := 0.0
+ PER;
+ perform ccb dialogue (m, real (offset ccb table+2), ccb table entries,
+ new shard, ccb location,
+ old shard, offset old ccb,
+ nr of ccbs,
+ offset old dtcb <> 0.0, release = old release,
+ ccb refinements (m), ccb abfragen (m),
+ automatic mode, print configuration only).
+
+make entries in channeltable of new shard :
+ kopf;
+ out ("Konfigurationsdaten werden in den neuen SHard eingetragen : ");
+ FOR i FROM 1 UPTO nr of ccbs REP
+ cout (i);
+ kanal := (*v[1][i]falsch???!!!*) byte (new shard, ccb location [i]);
+ make entry in channeltable of new shard
+ PER.
+
+make entry in channeltable of new shard :
+ IF NOT channel free (kanal)
+ THEN (* dtcb/ccb Adresse aus channel table nach neuem ccb umtragen. *)
+ int (new shard, ccb location [i] + 2.0,
+ unsigned (sh dtcb offset (new shard, kanal)));
+ int (new shard, ccb location [i] + 4.0,
+ unsigned (sh ccb offset (new shard, kanal)));
+ ELSE (* Folge-dtcb/ccb Adresse auf 0 setzen *)
+ int (new shard, ccb location [i] + 2.0, 0);
+ int (new shard, ccb location [i] + 4.0, 0);
+ FI;
+ (* Jetzt neue Adresse in channel table eintragen *)
+ sh dtcb offset (new shard, kanal, dtcb location);
+ sh ccb offset (new shard, kanal, ccb location [i]);
+ k := byte (new shard, ccb location [i] + 1.0); (* Zusatzkanalnummer *)
+ IF k <> 255 (* 255 = kein Zusatzkanal vorhanden *)
+ THEN (* IF NOT channel free (k) THEN alter eintrag futsch !!! *)
+ sh dtcb offset (new shard, k, dtcb location);
+ sh ccb offset (new shard, k, ccb location [i])
+ FI.
+
+kopf :
+ write head ("""" + modulname + """ in den SHard aufnehmen");
+ out (actual info);
+ out (""13""10"").
+END PROC do configurate module;
+
+
+(********************* perform dialogue ************************************)
+
+PROC perform dtcb dialogue
+ (MODUL VAR m, REAL CONST offset dialogue table,
+ INT CONST dialogue table entries,
+ MODUL VAR dtcb, REAL CONST offset dtcb,
+ MODUL CONST old dtcb, REAL CONST offset old dtcb,
+ BOOL CONST old dtcb valid, same release,
+ TEXT CONST refinements, INT CONST count,
+ BOOL CONST automatic mode, print configuration only):
+ ROW nr of channels total REAL VAR offset cb, offset old cb;
+ offset cb [1] := offset dtcb;
+ offset old cb [1] := offset old dtcb;
+ perform dialogue (TRUE, m, offset dialogue table, dialogue table entries,
+ dtcb, offset cb, old dtcb, offset old cb, 1,
+ old dtcb valid, same release, refinements, count,
+ automatic mode, print configuration only).
+END PROC perform dtcb dialogue;
+
+PROC perform ccb dialogue
+ (MODUL VAR m, REAL CONST offset dialogue table,
+ INT CONST dialogue table entries,
+ MODUL VAR ccb, ROW nr of channels total REAL CONST offset ccb,
+ MODUL CONST old ccb, ROW nr of channels total REAL CONST offset old ccb,
+ INT CONST nr of ccbs, BOOL CONST old ccbs valid, same release,
+ TEXT CONST refinements, INT CONST count,
+ BOOL CONST automatic mode, print configuration only) :
+ perform dialogue (FALSE, m, offset dialogue table, dialogue table entries,
+ ccb, offset ccb, old ccb, offset old ccb, nr of ccbs,
+ old ccbs valid, same release, refinements, count,
+ automatic mode, print configuration only).
+END PROC perform ccb dialogue;
+
+
+PROC perform dialogue
+ (BOOL CONST is dtcb,
+ MODUL VAR m, REAL CONST offset dialogue table,
+ INT CONST dialogue table entries,
+ MODUL VAR cb, ROW nr of channels total REAL CONST offset cb,
+ MODUL CONST old cb, ROW nr of channels total REAL CONST offset old cb,
+ INT CONST nr of cbs, BOOL CONST old cb valid, same release,
+ TEXT CONST refinements, INT CONST refinement count,
+ BOOL CONST automatic mode, print configuration only) :
+ (* Konfigurationsdialog für einen (Satz von) Kontrollblock(s) oder bloßes
+ Anzeigen der Konfigurationsdaten derselben.
+
+ 1. bei NOT print configuration only:
+ Führt den Dialog für eine Tabelle (also ccb oder dtcb Variablentabelle)
+ durch und bestückt den controlblock entsprechend.
+ Es wird gleich eine ganze Tabelle von controlblocks (max. mchm Stück)
+ abgearbeitet und zwar nr of cbs Stück; im Falle is dtcb wird natürlich
+ nur der Eintrag 1 der Tabellen benutzt (vom Aufrufer).
+ Das Eingabemodul ist m mit der zu bearbeitenden Tabelle an der Stelle
+ offset dialogue table. Die Tabelle enthält dialogue table entries
+ Einträge (max. mdts Stück !)
+ Die Ausgabe des Prozesses landet im Modul cb ab den Stellen offset cb.
+ cb ist dabei jeweils der neue SHard, damit man nicht das Modul ändert.
+ Die Vorlagen zum Abgucken liefert, falls old cb valid ist, das
+ Modul old cb (der alte SHard) ab offset old cb, dabei ist die Struktur
+ gleich der neuen, wenn same release gilt, andernfalls sind die
+ Vorversionsoffsets zu benutzen (Versionsnummer um genau 1 erhöht).
+ Bei automatic mode werden nur still diese Vorgabewerte übernommen.
+ Die Elan-Teile für den Dialog liefert schliesslich der Text refinements,
+ er enthält refinement count Abfragen der Namen r1, r2, .....
+ Wenn refinent count = 0 ist, passiert hier eigentlich nichts,
+ deshalb sollte dann
+ für eine korrekte Initialisierung auch die Variablentabelle leer sein;
+ ist sie es allerdings doch nicht, werden hier noch die Standardwerte in
+ die ccbs eingetragen und nur der leere Dialog unterdrückt.
+ Vor Beginn/Nach Ende des gesamten Dialogs wird das refinement
+ dialoguestart/dialogueend aufgerufen; bei NOT is dtcb vor/nach dem Dialog
+ jedes Kanals auch noch channelstart/channelend.
+
+ 2. bei print configuration only:
+ Die Daten zum new shard werden überhaupt nicht benutzt, von den
+ refinements wird nur für jeden Kanal einmal "print configuration"
+ aufgerufen.
+ *)
+ REAL VAR table byte :: offset dialogue table;
+ ROW mdts INT VAR offset, old offset, length;
+ INT VAR i, k;
+ BOOL VAR configurate :: NOT print configuration only;
+ TEXT VAR program, t;
+ IF print configuration only (* Hier wird evtl. schon verlassen *)
+ THEN startup for print
+ ELSE startup for dialogue FI;
+ IF refinement count > 0 THEN build program FI;
+ build data in v;
+ IF refinement count > 0 THEN do program FI;
+ IF configurate THEN put values in cb FI.
+
+startup for print :
+ IF refinement count = 0 OR dialogue table entries = 0
+ THEN LEAVE perform dialogue FI.
+
+startup for dialogue:
+ IF refinement count = 0
+ THEN putline ("Keine Konfiguration notwendig.");
+ IF dialogue table entries = 0
+ THEN pause (20); LEAVE perform dialogue FI
+ ELSE putline ("Die Konfiguration wird vorbereitet.") FI.
+
+build program:
+ max index := refinement count; (* damit new index bescheid weiss *)
+ program := variables var xxv;
+ program cat main part;
+ perhaps program cat data refinements;
+ program CAT refinements.
+
+program cat main part :
+ program CAT "LET UNSIGNED=INT;giveme(xxv);INT VARxxi::1,actchannel;";
+ IF print configuration only OR automatic mode
+ THEN program cat main part for print or automatic mode
+ ELSE program cat main part for dialogue FI.
+
+program cat main part for print or automatic mode:
+ (* Leider muss man, wenn man den Modulprogrammierer bei den .ccb und .dtcb
+ Teilen nicht zu stark reglementieren will, einiges mitübersetzen, was
+ dann gar nicht benutzt wird (z.B. alle Refinements).
+ Und der Gedanke macht ihn blaß,
+ wenn er fragt: was kostet das ?
+ Wilhelm Busch
+ *)
+ program CAT "FORactchannelFROM 1 UPTOchannelsofthismoduleREP";
+ IF print configuration only
+ THEN program CAT "printconfigurationPER."
+ ELSE (* automatic mode: *) program CAT "automaticPER;takeyou(xxv)."
+ FI;
+ program CAT " xxa:actchannel. thischannel:";
+ IF NOT is dtcb THEN program CAT "channelstart;" FI;
+ FOR i FROM 1 UPTO refinement count REP
+ program CAT "r"; (* Alle in this channel aufrufen, damit *)
+ program CAT text (i); (* "LEAVE this channel" kein Fehler ist. *)
+ program CAT ";"
+ PER;
+ IF NOT is dtcb
+ THEN program CAT "channelend" FI;
+ program CAT ". ".
+
+program cat main part for dialogue:
+ program CAT "dialoguestart;FORactchannelFROM 1 UPTOchannelsofthismoduleREP";
+ program CAT "thischannelPER;dialogueend;takeyou(xxv). ";
+ program CAT "xxa:actchannel. thischannel:";
+ IF NOT is dtcb THEN program CAT "channelstart;" FI;
+ program CAT "REP SELECTxxiOF ";
+ FOR i FROM 1 UPTO refinement count REP
+ program CAT "CASE ";
+ program CAT text (i);
+ program CAT ":r";
+ program CAT text (i);
+ program CAT " "
+ PER;
+ program CAT "ENDSELECT UNTIL NOTnewindex(xxi)PER";
+ IF NOT is dtcb
+ THEN program CAT ";channelend;reservechannel(xxv[1][xxa])" FI;
+ program CAT ". ".
+
+perhaps program cat data refinements :
+ FOR i FROM 1 UPTO dialogue table entries REP
+ IF configurate THEN cout (i) FI;
+ read start of next table entry; (* must be done in autom. mode, too, *)
+ t := next variable name; (* to get offset/oldoffset/length [i] *)
+ program CAT t;
+ program CAT ":xxv[";
+ program CAT text (i);
+ program CAT "][xxa]. "; (* Das war der normale Eintrag "varname" *)
+ program CAT t; (* Jetzt der für alle Kanäle "varname k" *)
+ program CAT "k:xxv[";
+ program CAT text (i);
+ program CAT "]. "
+ PER.
+
+read start of next table entry :
+ (* Format der Einträge in den Variablentabellen:
+ dw offset in cb
+ dw offset in old cb (oder ffffh falls neu)
+ db Typ (d.h. Länge und ist 1 oder 2)
+ db Namenslänge
+ db ...(Name)...
+ *)
+ INT CONST length of variable :: byte (m, table byte + 4.0),
+ length of name :: byte (m, table byte + 5.0);
+ old offset [i] := int (m, table byte + 2.0); (* Diese Sammlung *)
+ offset [i] := int (m, table byte); (* bereitet das Datenholen vor *)
+ length [i] := length of variable;
+ IF length of variable < 1 OR length of variable > 2
+ THEN errorstop ("invalid variablelength : " + text (length of variable))
+ FI;
+ table byte INCR 6.0.
+
+next variable name:
+ table byte INCR real (length of name);
+ text (m, table byte - real (length of name), length of name).
+
+build data in v :
+ FOR k FROM 1 UPTO nr of cbs REP (* Kanäle *)
+ IF configurate THEN cout (k) FI;
+ FOR i FROM 1 UPTO dialogue table entries REP (* Variablen *)
+ v[i][k] := next init value
+ PER
+ PER.
+
+next init value :
+ IF old cb valid CAND old cb present CAND value accessible
+ THEN value from old cb
+ ELSE value from new cb FI.
+
+old cb present :
+ offset old cb [k] > 0.0.
+
+value accessible :
+ same release OR
+ (* Ein release zuvor und Variable gibts schon: *) old offset [i] <> -1.
+
+value from old cb :
+ IF length [i] = 1
+ THEN byte (old cb, offset old cb [k] + real (offset of old value))
+ ELSE int (old cb, offset old cb [k] + real (offset of old value))
+ FI.
+
+value from new cb :
+ IF length [i] = 1
+ THEN byte (cb, offset cb [k] + real (offset [i]))
+ ELSE int (cb, offset cb [k] + real (offset [i])) FI.
+
+offset of old value :
+ IF same release
+ THEN offset [i]
+ ELSE old offset [i] FI.
+
+do program :
+ reset direction (TRUE);
+ channels of module := nr of cbs;
+ IF setup testing
+ THEN (* für diesen THEN-Teil beim abgespeckten Eumel
+ setup eummel mini eumel dummies insertieren *)
+ forget (do name, quiet);
+ FILE VAR f := sequentialfile (output, do name);
+ putline (f, program);
+ (*edit (do name);*)
+ run (do name);
+ forget(do name, quiet);
+ ELSE do (program);
+ FI;
+ program := ""; (* Platz sparen *)
+ reset direction (FALSE).
+
+put values in cb :
+ FOR k FROM 1 UPTO nr of cbs REP
+ cout (k);
+ FOR i FROM 1 UPTO dialogue table entries REP
+ IF length [i] = 1 THEN put byte ELSE put int FI
+ PER;
+ PER.
+
+put byte :
+ byte (cb, offset cb [k] + real (offset [i]), v[i][k]).
+
+put int :
+ int (cb, offset cb [k] + real (offset [i]), v[i][k]).
+END PROC perform dialogue;
+
+(****************** give me, take you, new index ***************************)
+
+(* Diese Prozeduren werden aus dem do beim perform dialogue heraus aufgerufen
+ Sie dienen zur Kommunikation mit den Paketdaten dieses Pakets (give me,
+ take you) oder zur Verkleinerung des do-Programms (new index)
+*)
+
+PROC give me (VARIABLES VAR variables) :
+ (* Der Sinn dieser Prozedur besteht in Folgendem :
+ bei perform dialogue wird in dem do, das die refinements des
+ SHard-Moduls ausführt, eine Datenstruktur vom Typ VARIABLES aufgebaut,
+ die alle in den Variablentabellen des Moduls aufgeführten Variablen
+ enthält und einzeln über passend benannte refinements zugänglich macht.
+ Diese Datenstruktur wird zuvor in diesem Paket hier initialisiert mit
+ Initwerten aus der Variablentabelle oder wenn möglich mit den
+ entsprechenden Werten aus dem alten SHard. Mit give me fordert das
+ do-Programm die initialisierte Datenstruktur aus diesem Paket hier an.
+ Im do wird am Schluss mit take you diese Datenstruktur an dieses Paket
+ (und damit an perform dialogue) zurückgegeben, damit die durch den
+ Dialog gesetzten Werte in den neuen SHard eingetragen werden können.
+ Eine alternative Methode, diese Kommunikation zu realisieren, wäre die
+ Benutzung von BOUND VARIABLES VARs mit demselben Datenraum.
+ *)
+ variables := v
+END PROC give me;
+
+PROC take you (VARIABLES CONST variables) :
+ (* Gegenstück zu give me, siehe dort *)
+ v := variables
+END PROC take you;
+
+BOOL PROC new index (INT VAR index) :
+ (* Verändert den Index je nach der direction und fragt bei down am Ende,
+ ob fertig. Liefert, ob es noch weitergehen soll (falls nein: index = 1)
+ *)
+ LET up = ""3"",
+ down = ""10"",
+ error = ""0"";
+ TEXT CONST old direction :: direction;
+ reset direction (TRUE);
+ IF old direction = error (* Bei Fehlern immer stehenbleiben *)
+ THEN TRUE
+ ELIF index = max index (* am Schluss aufhören oder nach 1 springen *)
+ THEN perhaps end
+ ELIF index = 1 AND old direction = up (* bei 1 und up an den Schluss *)
+ THEN index := max index; TRUE
+ ELSE normal new index (* sonst je nach direction up oder down *)
+ FI.
+
+perhaps end : (* index = max index *)
+ IF old direction = up AND max index > 1 (* hoch vom Ende *)
+ THEN index DECR 1;
+ TRUE
+ ELIF old direction = up
+ THEN TRUE
+ ELIF old direction = down (* runter am Ende *)
+ THEN index := 1;
+ TRUE
+ ELSE reset direction (FALSE); (* normal oder runter ans Ende *)
+ index := 1;
+ BOOL CONST ready :: yes (1, 23, "Fertig", FALSE);
+ reset direction (TRUE);
+ NOT ready
+ FI.
+
+normal new index :
+ IF old direction = up
+ THEN index DECR 1; TRUE
+ ELSE index INCR 1; TRUE FI.
+END PROC new index;
+
+(******************** channel (table) handling *****************************)
+
+BOOL PROC channel free (INT CONST nr,
+ ROW 256 INT CONST channel table of shard) :
+ IF nr < 0 OR nr > nr of channels total
+ THEN FALSE
+ ELSE channel table of shard [index ccb offset] = 0 FI.
+
+index ccb offset :
+ 2 * nr + 1 + 1.
+END PROC channel free;
+
+BOOL PROC channel free (INT CONST nr) :
+ channel free (nr, channel table of new shard).
+END PROC channel free;
+
+PROC reserve channel (INT CONST nr,
+ ROW 256 INT VAR channel table of shard) :
+ IF nr >= 0 AND nr < nr of channels total
+ THEN channel table of shard [index ccb offset] := 1 (* nichtnull *) FI.
+
+index ccb offset :
+ 2 * nr + 1 + 1. (* Start nicht bei 0 und ccb hinter dtcb *)
+END PROC reserve channel;
+
+PROC reserve channel (INT CONST nr) :
+ reserve channel (nr, channel table of new shard).
+END PROC reserve channel;
+
+(*THESAURUS PROC free channels (ROW 256 INT VAR channel table of shard):
+ (* Liefert einen THESAURUS, der die Klartextform genau aller in
+ channel table of shard als frei angegebenen Kanäle enthält.
+ *)
+ INT VAR i;
+ THESAURUS VAR result :: empty thesaurus;
+ FOR i FROM 1 UPTO nr of channels total REP
+ IF channel free (i, channel table of shard)
+ THEN insert (result, text (i)) FI
+ PER;
+ result.
+END PROC free channels;*)
+
+INT PROC channels of this module :
+ channels of module.
+END PROC channels of this module;
+
+(********************* write info, buffer adress **************************)
+
+PROC write info :
+ putline (actual info)
+END PROC write info;
+
+INT PROC buffer address (INT CONST buffer size):
+ IF new shard length MOD 2.0 <> 0.0 THEN new shard length INCR 1.0 FI;
+ INT CONST buf adr := unsigned (new shard length);
+ new shard length INCR real (buffer size);
+ IF new shard length >= 65536.0 OR buffer size > 1024
+ THEN errorstop ("zu großer Puffer verlangt")
+ FI;
+ buf adr
+END PROC buffer address;
+
+(************************* Hilfsprozeduren *******************************)
+
+PROC elan (INT CONST mode, DATASPACE CONST source, TEXT CONST line,
+ INT VAR start module nr, BOOL CONST new init, ins, dump, lst,
+ sys, coder, rt check, sermon) :
+ EXTERNAL 256
+END PROC elan;
+
+PROC do (TEXT CONST long line) :
+ DATASPACE VAR ds;
+ INT VAR module nr :: 0;
+ elan (2, ds, long line, module nr, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE);
+ forget (ds);
+ no do again
+END PROC do;
+
+PROC go on :
+ put (" >>>>> Taste drücken zum Weitermachen ");
+ REPEAT UNTIL incharety (2) = "" PER;
+ pause;
+ line.
+END PROC go on;
+
+END PACKET setup eumel modulkonfiguration;
+
diff --git a/system/setup/3.1/src/setup eumel 4: dienstprogramme b/system/setup/3.1/src/setup eumel 4: dienstprogramme
new file mode 100644
index 0000000..9ce9ca3
--- /dev/null
+++ b/system/setup/3.1/src/setup eumel 4: dienstprogramme
@@ -0,0 +1,218 @@
+
+(**************************************************************************)
+(***** Dienstprogramme für Modulprogrammierer *****************)
+(***** Copyright (c) 1987, 1988 *****************)
+(***** Lutz Prechelt, Karlsruhe *****************)
+(**************************************************************************)
+
+PACKET setup eumel dienstprogramme (* Copyright (c) 1987 by *)
+DEFINES (* Lutz Prechelt, Karlsruhe *)
+ file as one text, (* Stand : 07.05.88 1.4 *)
+ ich schreibe jetzt ein neues shard modul, (* Eumel 1.8.1 *)
+ link shard module,
+ all modules:
+
+(* Dies sind Dienstprogramme, die der Modul-Programmierer braucht *)
+
+(* Das Format der Refinementdateien für den dtcb- und ccb-Setupdialog ist wie
+ folgt:
+ 1. Zeile: INT-Denoter für die Anzahl von Abfragerefinements, die drin sind
+ Rest der Zeile muß leer sein.
+ Danach : lauter ELAN-Refinements mit den Namen r1, r2 usw.
+ evtl. weitere Refinements zur Hilfe mit beliebigen Namen (es
+ gibt ein paar Ausnahmen, über die man beim ersten Test dann aber
+ stolpert.)
+ In den Refinements dürfen Variablen vereinbart werden. Vor dem ersten
+ refinement der Datei darf KEIN Punkt sein (es ist sowieso schlechter
+ Stil, die Punkte nicht hinter die vorherige Zeile zu setzen, sondern
+ vor den refinementnamen.), hingegen MUSS nach dem letzten Refinement der
+ Datei ein Punkt stehen.
+ Wer das für nötig hält, kann auch Prozeduren definieren und verwenden,
+ was allerdings nicht geht, sind Pakete.
+ Wenn man mit Kommentaren und sonstigen Bytefressern sparsam
+ umgeht, läuft der Dialog beim Setup später etwas schneller an.
+*)
+
+LET modul namentyp = "SHardmodul *";
+
+DATASPACE VAR ds;
+
+(***************************************************************************)
+
+THESAURUS PROC all modules (THESAURUS CONST th):
+ (* Hier wird schlabberig nach Namen ausgewählt, während der Setup Eumel
+ im Betrieb die Datenraumtypen als Auswahlkriterium verwendet.
+ Die Schwierigkeiten, die bei Nichteinhalten der Namenskonventionen
+ entstehen, veranlassen hoffentlich jeden zur nötigen Disziplin...
+ *)
+ (th LIKE "SHardmodul *") - (th LIKE "SHardmodul *.ccb")
+ - (th LIKE "SHardmodul *.dtcb") - (th LIKE "SHardmodul *.info")
+END PROC all modules;
+
+(*****THESAURUS PROC all modules: wird sauber in Teil 2 realisiert
+ all modules (all)
+END PROC all modules;
+*****)
+
+(********************* link shard module *********************************)
+
+PROC link shard module:
+ TEXT VAR module :: std;
+ REPEAT
+ page;
+ putline (" L I N K S H A R D - M O D U L E"); line (2);
+ put ("Modulname:"); editget (module); line (2);
+ link shard module (module); line;
+ UNTIL NOT yes ("noch ein Modul linken", FALSE) PER
+END PROC link shard module;
+
+PROC link shard module (THESAURUS CONST th):
+ do (PROC (TEXT CONST) link shard module, th);
+END PROC link shard module;
+
+PROC link shard module (TEXT CONST module):
+ (* Ruft link shard module (modul, dtcb, ccb, info) unter Anwendung von
+ Namenskonventionen (nämlich entsprechende Suffixe ".dtcb" etc.) auf.
+ *)
+ TEXT VAR dtcb, ccb, info;
+ BOOL VAR elan neu;
+ dtcb := module + ".dtcb";
+ ccb := module + ".ccb";
+ info := module + ".info";
+ perhaps change filenames;
+ elan neu := yes (module + ": neue Elan Teile machen", FALSE);
+ IF elan neu THEN neue elan teile machen FI;
+ link shard module (module, dtcb, ccb, info);
+ IF elan neu THEN check syntax FI.
+
+neue elan teile machen:
+ edit (dtcb); line (2);
+ edit (ccb); line (2);
+ edit (info); page.
+
+perhaps change filenames:
+(*put ("Datei mit dtcb-refinements :"); editget (dtcb); line;
+ put ("Datei mit ccb-refinements :"); editget (ccb); line;
+ put ("Datei mit Infotext :"); editget (info); line (2)*) .
+
+check syntax :
+ line (2); put (module); putline (": Syntax-Check");
+ forget (ds);
+ ds := nilspace;
+ BOUND MODUL VAR m :: old (module), old shard :: ds, new shard :: ds;
+ INT VAR offset dtcb table :: int (m, 0),
+ dtcb table entries :: int (m, offset dtcb table),
+ offset ccb table :: int (m, 2),
+ ccb table entries :: int (m, offset ccb table);
+ (* Jetzt einen total verkrüppelten automatischen "perform dialogue" für
+ die Probeübersetzung der .dtcb und .ccb refinements aufrufen.
+ *)
+ perform dtcb dialogue (m, real (offset dtcb table+2), dtcb table entries,
+ new shard, 0.0,
+ old shard, 0.0,
+ FALSE, FALSE,
+ dtcb refinements (m), dtcb abfragen (m),
+ TRUE, FALSE);
+ putline ("dtcb refinements O.K.");
+ ROW 40 REAL VAR x :: ROW 40 REAL : (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0);
+ perform ccb dialogue (m, real (offset ccb table+2), ccb table entries,
+ new shard, x,
+ old shard, x,
+ 1,
+ FALSE, FALSE,
+ ccb refinements (m), ccb abfragen (m),
+ TRUE, FALSE);
+ putline ("ccb refinements O.K.");
+ forget (ds).
+END PROC link shard module;
+
+PROC link shard module (TEXT CONST module, dtcb, ccb, infofile) :
+ IF type (old (module)) <> datenraumtyp modul CAND NOT typ aendern
+ THEN LEAVE link shard module
+ ELSE type (old (module), datenraumtyp modul) FI;
+ IF NOT (module LIKE modul namentyp)
+ THEN errorstop ("Module MÜSSEN Namen der Art """ + modul namentyp +
+ """ haben")
+ FI;
+ line;
+ BOUND MODUL VAR m :: old (module);
+ TEXT VAR dtcb ref :: file as one text (dtcb, FALSE),
+ ccb ref :: file as one text (ccb, FALSE),
+ info text:: file as one text (infofile, TRUE);
+ INT CONST pos dtcb :: pos (dtcb ref, " "), (* Ende der ersten Zeile, die *)
+ pos ccb :: pos (ccb ref, " "); (* die Abfragezahl enthält *)
+ INT VAR dtcb count, ccb count;
+ dtcb count := int (subtext (dtcb ref, 1, pos dtcb));
+ IF NOT last conversion ok OR dtcb count < 0 OR dtcb count > 1000
+ THEN errorstop ("keine vernünftige Zahl von dtcb Abfragen gefunden") FI;
+ ccb count := int (subtext (ccb ref, 1, pos ccb));
+ IF NOT last conversion ok OR ccb count < 0 OR ccb count > 1000
+ THEN errorstop ("keine vernünftige Zahl von ccb Abfragen gefunden") FI;
+ (* JETZT PASSIERTS : *)
+ dtcb abfragen (m, dtcb count);
+ dtcb refinements (m, subtext (dtcb ref, pos dtcb + 1));
+ ccb abfragen (m, ccb count);
+ ccb refinements (m, subtext (ccb ref, pos ccb + 1));
+ info (m, infotext);
+ line;
+ putline (""""+module+""" gelinkt. " + text (storage (old (module))) +
+ " K Datenraumgröße.").
+
+typ aendern :
+ IF type (old (module)) = 1003 (* file type *)
+ THEN putline ("(""" + module + """ hat den Typ FILE)") FI;
+ putline ("Achtung: """ + module + """ ist nicht vom Typ eines SHard-Moduls");
+ yes ("Soll es dazu gemacht werden (Typ aufprägen)", FALSE).
+END PROC link shard module;
+
+(******************** file as one text ************************************)
+
+TEXT PROC file as one text (TEXT CONST filename, BOOL CONST verbatim) :
+ FILE VAR f :: sequential file (input, filename);
+ TEXT VAR result :: "", t;
+ put ("Lese """ + filename + """ :");
+ WHILE NOT eof (f) REP
+ cout (line no (f));
+ getline (f, t);
+ work on t;
+ result CAT t
+ PER;
+ line;
+ result.
+
+work on t :
+ IF verbatim
+ THEN t CAT ""13""10""
+ ELSE t := compress (t); t CAT " " FI.
+END PROC file as one text;
+
+(****** ich schreibe jetzt ein neues shard modul ***************************)
+
+PROC ich schreibe jetzt ein neues shard modul :
+ line (2);
+ putline ("So so, Sie wollen also ein neues SHard-Modul schreiben."); line;
+ pause (20);
+ putline ("Mir kommt es so vor, als sei heute der " + date +
+ " und im Moment gerade " + time of day + " Uhr"); line;
+ IF NOT yes ("Stimmt das ungefähr (auf 5 Minuten kommt's nicht an)", TRUE)
+ THEN do ("set date"); line (2) FI;
+ putline ("Also gut. Schreiben Sie Ihr verdammtes Modul.");
+ putline ("Aber merken Sie sich die folgenden 4 Bytes als ihren Modultyp");
+ put (""15" ");
+ REAL VAR x :: floor (clock (1) - date ("05.05.79") - time ("10:00:00"));
+ INT VAR i;
+ FOR i FROM 1 UPTO 4 REP
+ put (int (x MOD 256.0));
+ x := floor (x / 256.0)
+ PER;
+ put (" "14""); line (2);
+ putline ("Also : die Dinger merken (schreiben Sie sie auf, sonst vergessen Sie");
+ putline (" sie ja doch) und NICHT MEHR ÄNDERN !");
+ line (3)
+END PROC ich schreibe jetzt ein neues shard modul;
+
+END PACKET setup eumel dienstprogramme;
+
diff --git a/system/setup/3.1/src/setup eumel 5: partitionierung b/system/setup/3.1/src/setup eumel 5: partitionierung
new file mode 100644
index 0000000..705f26d
--- /dev/null
+++ b/system/setup/3.1/src/setup eumel 5: partitionierung
@@ -0,0 +1,435 @@
+PACKET setup eumel partitionierung (* Copyright (C) 1985 *)
+ (* Martin Schönbeck, Spenge *)
+DEFINES tracks, (* Lutz Prechelt, Karlsruhe *)
+ sectors, (* Änderungen: Ley ms *)
+ heads, (* Stand: 07.04.89 *)
+ first track,
+ last track,
+ partition start,
+ partition type,
+ partition active,
+ partition size,
+ partition word 0,
+
+ get boot block,
+ put boot block,
+ clear partition,
+
+ (*get bad track table,*)
+ get bad sector table,
+ clear partition table,
+ setup channel,
+ start of partition:
+
+ LET bst size = 1024; (* nr of bad sector table entrys *)
+
+ROW 256 INT VAR boot block;
+INT VAR boot block session := session - 1;
+INT VAR fd channel := 28; (* Festplatten-Setupkanal *)
+
+INT PROC setup channel:
+ fd channel
+END PROC setup channel;
+
+PROC setup channel (INT CONST new channel):
+ enable stop;
+ teste kanal typ;
+ boot block session DECR 1;
+ wirf altes pac raus;
+ fd channel := new channel;
+ sorge dafuer dass kanal uptodate ist.
+
+teste kanal typ:
+ IF (get value (1, new channel) AND 12) <> 12
+ THEN errorstop ("Hier gibt es leider keine Platte")
+ FI.
+
+wirf altes pac raus:
+ IF new channel <> fd channel
+ THEN INT VAR raus := get value (-13, fd channel);
+ FI.
+
+sorge dafuer dass kanal uptodate ist:
+ INT VAR old channel := channel;
+ ROW 256 INT VAR dummy; INT VAR i;
+ continue (new channel);
+ disable stop;
+ blockin (dummy, -1, -1, i);
+ break (quiet);
+ continue (old channel).
+
+END PROC setup channel;
+
+PROC get bad sector table (ROW bst size REAL VAR bb tab,
+ INT VAR bad sect, INT CONST eumel type):
+ initialisiere tabelle;
+ suche schlechte sectoren.
+
+initialisiere tabelle:
+ INT VAR i;
+ FOR i FROM 1 UPTO bst size REP
+ bb tab [i] := -1.0;
+ PER.
+
+suche schlechte sectoren:
+ INT VAR my channel := channel;
+ REAL VAR sector := start of partition (eumel type),
+ end := sector + partition size (partition number (eumel type)),
+ track mode restart :: 0.0;
+ INT VAR akt track := 0,
+ fehler code;
+ bad sect := 1; (* Eintragsnr. des NÄCHSTEN schlechten Sektors *)
+ continue (fd channel);
+ disable stop;
+ DATASPACE VAR ds := nilspace;
+ REAL CONST cylinder size :: real (sectors * heads),
+ track size :: real (sectors);
+ track mode restart := sector + track size -
+ (sector MOD track size);
+ (* wenn sector nicht erster der spur, dann die erste einzeln *)
+ WHILE sector < end REP
+ IF sector MOD cylinder size = 0.0
+ THEN melde naechste spur FI;
+ IF sector >= track mode restart
+ THEN check track
+ ELSE check sector FI
+ UNTIL bad sect > bst size OR is error PER;
+ continue (my channel);
+ forget (ds);
+ enable stop;
+ IF bad sect > bst size
+ THEN errorstop ("Zu viele schlechte Sektoren");
+ FI;
+ lass nicht zu dass ein ersatzsektor ein schlechter ist;
+ bad sect DECR 1. (* ANZAHL schlechter Sektoren *)
+
+melde naechste spur:
+ break (quiet);
+ continue (my channel);
+ akt track INCR 1;
+ cout (akt track);
+ continue (fd channel).
+
+check track :
+ verify track (ds, 2, sector, fehler code);
+ IF schlechten sektor gefunden
+ THEN track mode restart := sector + tracksize
+ ELSE sector INCR track size FI.
+
+check sector :
+ read block (ds, 2, sector, fehler code);
+ IF schlechten sektor gefunden
+ THEN eintragen FI;
+ sector INCR 1.0.
+
+schlechten sektor gefunden:
+ SELECT fehler code OF
+ CASE 0: FALSE
+ CASE 1: error stop ("Platte kann nicht gelesen werden"); FALSE
+ CASE 2: TRUE
+ CASE 3: error stop ("Versorgungsfehler beim Plattentest"); FALSE
+ OTHERWISE error stop ("unbekannter Fehler auf Platte"); FALSE
+ END SELECT.
+
+eintragen:
+ bb tab [bad sect] := sector;
+ bad sect INCR 1.
+
+lass nicht zu dass ein ersatzsektor ein schlechter ist:
+ REAL VAR aktueller ersatz := end - real (bad sect - 1);
+ INT VAR akt b sect;
+ FOR akt b sect FROM 1 UPTO bad sect - 1 REP
+ IF aktueller ersatz ist in tabelle
+ THEN vertausche aktuell zu ersetzenden mit ihm
+ FI;
+ PER.
+
+aktueller ersatz ist in tabelle:
+ INT VAR such index;
+ FOR such index FROM 1 UPTO bad sect REP
+ IF aktueller ersatz = bb tab (such index)
+ THEN LEAVE aktueller ersatz ist in tabelle WITH TRUE
+ FI;
+ PER;
+ FALSE.
+
+vertausche aktuell zu ersetzenden mit ihm:
+ bb tab ( such index ) := bb tab ( akt b sect );
+ bb tab (akt b sect) := aktueller ersatz.
+END PROC get bad sector table;
+
+INT PROC cyl and head (REAL CONST sector):
+ cylinder code (int (sector / real (sectors)) DIV heads) OR head.
+
+head :
+ (int (sector / real (sectors)) MOD heads).
+END PROC cyl and head;
+
+PROC get boot block:
+ IF boot block session <> session
+ THEN hole aktuellen boot block
+ FI.
+
+hole aktuellen bootblock :
+ disable stop;
+ DATASPACE VAR dummy ds := nilspace;
+ BOUND STRUCT (ALIGN dummy,
+ ROW 256 INT block) VAR partition table := dummy ds;
+ get external block (dummy ds, 2, 0, fd channel);
+ IF NOT is error
+ THEN transfer data to boot block
+ FI;
+ forget (dummy ds).
+
+transfer data to boot block:
+ IF not valid boot block
+ THEN try to get valid boot block from file
+ FI;
+ boot block := partition table. block;
+ boot block session := session.
+
+not valid boot block:
+ partition table. block [256] <> boot indicator OR
+ it is an old boot block of eumel.
+
+boot indicator: -21931.
+
+it is an old boot block of eumel:
+ partition table. block [1] = 1514.
+
+try to get valid boot block from file:
+ forget (dummy ds);
+ partition table := old ("bootblock");
+ IF is error THEN LEAVE transfer data to boot block FI.
+END PROC get boot block;
+
+PROC clear partition table (INT CONST sicherung):
+ IF sicherung = -3475
+ THEN neuen boot block;
+ put boot block
+ FI.
+
+neuen boot block:
+ enable stop;
+ BOUND STRUCT (ALIGN dummy,
+ ROW 256 INT block) VAR partition table;
+ partition table := old ("bootblock");
+ boot block := partition table. block;
+ boot block session := session.
+END PROC clear partition table;
+
+PROC put boot block:
+ IF boot block ist uptodate
+ THEN schreibe block auf platte
+ ELSE errorstop ("boot block nicht uptodate")
+ FI.
+
+boot block ist uptodate:
+ boot block session = session.
+
+schreibe block auf platte:
+ disable stop;
+ DATASPACE VAR dummy ds := nilspace;
+ BOUND STRUCT (ALIGN dummy,
+ ROW 256 INT block) VAR partition table := dummy ds;
+ transfer data to dataspace;
+ put external block (dummy ds, 2, 0, fd channel);
+ forget (dummy ds).
+
+transfer data to dataspace:
+ partition table. block := boot block.
+END PROC put boot block;
+
+INT PROC partition number (INT CONST part type):
+ INT VAR partition;
+ FOR partition FROM 1 UPTO 4 REP
+ IF partition type (partition) = part type
+ THEN LEAVE partition number WITH partition
+ FI
+ PER;
+ errorstop ("Partitiontyp gibt es nicht");
+ 7.
+END PROC partition number;
+
+INT PROC partition word 0 (INT CONST partition):
+ boot block (entry (partition))
+END PROC partition word 0;
+
+PROC partition word 0 (INT CONST partition, word):
+ boot block (entry (partition)) := word
+END PROC partition word 0;
+
+REAL PROC start of partition (INT CONST partition type):
+ partition start (partition number (partition type))
+END PROC start of partition;
+
+
+INT PROC first track (INT CONST partition):
+ high byte (boot block [entry (partition) + 1])
+ + 4 * (low byte (boot block [entry (partition) + 1]) AND (128 + 64))
+END PROC first track;
+
+INT PROC last track (INT CONST partition):
+ high byte (boot block [entry (partition) + 3])
+ + 4 * (low byte (boot block [entry (partition) + 3]) AND (128 + 64))
+END PROC last track;
+
+INT PROC partition type (INT CONST partition):
+ low byte (boot block [entry (partition) + 2])
+END PROC partition type;
+
+BOOL PROC partition active (INT CONST partition):
+ low byte (boot block [entry (partition)]) = 128
+END PROC partition active;
+
+(****************** neu eingefügt ******************************)
+PROC partition active (INT CONST partition, BOOL CONST active):
+ IF active THEN activate this partition
+ ELSE deactivate this partition
+ FI.
+
+deactivate this partition:
+ set bit (boot block [entry (partition)], 7);
+ (* first setting needed, because reset bit does xor *)
+ reset bit (boot block [entry (partition)], 7).
+
+activate this partition:
+ set bit (boot block [entry (partition)], 7).
+END PROC partition active;
+
+(****************** neu eingefügt ******************************)
+
+PROC first track (INT CONST partition, cylinder):
+ boot block [entry (partition) + 1]
+ := cylinder code (cylinder) OR start sector.
+
+start sector:
+ IF cylinder = 0
+ THEN 2
+ ELSE 1
+ FI.
+END PROC first track;
+
+PROC last track (INT CONST partition, cylinder):
+ boot block [entry (partition) + 3] := cylinder code (cylinder).
+END PROC last track;
+
+PROC partition type (INT CONST partition, type):
+ boot block [entry (partition) + 2] := type.
+END PROC partition type;
+
+REAL PROC partition start (INT CONST partition):
+ unsigned low word + high word.
+
+unsigned low word:
+ real (low byte (boot block [entry (partition) + 4])) +
+ real (high byte (boot block [entry (partition) + 4])) * 256.0.
+
+high word:
+ real (boot block [entry (partition) + 5]) * 65536.0.
+END PROC partition start;
+
+PROC partition start (INT CONST partition, REAL CONST sector offset):
+ boot block [entry (partition) + 4] := low word (sector offset);
+ boot block [entry (partition) + 5] := high word (sector offset)
+END PROC partition start;
+
+REAL PROC partition size (INT CONST partition):
+ unsigned low word + high word.
+
+unsigned low word:
+ real (low byte (boot block [entry (partition) + 6])) +
+ real (high byte (boot block [entry (partition) + 6])) * 256.0.
+
+high word:
+ real (boot block [entry (partition) + 7]) * 65536.0.
+END PROC partition size;
+
+PROC partition size (INT CONST partition, REAL CONST number of blocks):
+ boot block [entry (partition) + 6] := low word (number of blocks);
+ boot block [entry (partition) + 7] := high word (number of blocks)
+END PROC partition size;
+
+PROC clear partition (INT CONST partition):
+ INT VAR i;
+ FOR i FROM 0 UPTO 7 REP
+ boot block [entry (partition) + i] := 0
+ PER
+END PROC clear partition;
+
+INT PROC entry (INT CONST partition):
+ get boot block;
+ 256 - 5 * 8 + (partition * 8)
+END PROC entry;
+
+INT PROC cylinder code (INT CONST cylinder):
+ cylinder text ISUB 1.
+
+cylinder text:
+ high cylinder bits + low cylinder bits.
+
+high cylinder bits:
+ code ((cylinder AND (256 + 512)) DIV 4).
+
+low cylinder bits:
+ code (cylinder AND (128 + 64 + 32 + 16 + 8 + 4 + 2 + 1)).
+END PROC cylinder code;
+
+INT PROC tracks:
+ get value (-10, fd channel)
+END PROC tracks;
+
+INT PROC sectors:
+ get value (-11, fd channel)
+END PROC sectors;
+
+INT PROC heads:
+ get value (-12, fd channel)
+END PROC heads;
+
+INT PROC get value (INT CONST control code, channel for value):
+ enable stop;
+ INT VAR old channel := channel;
+ IF channel for value <> old channel THEN continue (channel for value) FI;
+ INT VAR value;
+ control (control code, 0, 0, value);
+ IF channel for value <> old channel THEN continue (old channel) FI;
+ value
+END PROC get value;
+
+PROC get external block (DATASPACE VAR ds, INT CONST ds page,
+ archive block, get channel):
+ INT VAR old channel := channel;
+ continue (get channel);
+ disable stop;
+ read block (ds, ds page, archive block, error);
+ INT VAR error;
+ SELECT error OF
+ CASE 0:
+ CASE 1: error stop ("Platte kann nicht gelesen werden");
+ CASE 2: error stop ("Lesefehler bei Block "+ text (archive block));
+ CASE 3: error stop ("Versorgungsfehler Archiv");
+ OTHERWISE error stop ("unbekannter Fehler auf Platte");
+ END SELECT;
+ continue (old channel).
+END PROC get external block;
+
+PROC put external block (DATASPACE CONST ds, INT CONST ds page,
+ archive block, get channel):
+ INT VAR old channel := channel;
+ continue (get channel);
+ disable stop;
+ write block (ds, ds page, archive block, error);
+ INT VAR error;
+ SELECT error OF
+ CASE 0:
+ CASE 1: error stop ("Platte kann nicht geschrieben werden");
+ CASE 2: error stop ("Schreibfehler bei Block "+ text (archive block));
+ CASE 3: error stop ("Versorgungsfehler Archiv");
+ OTHERWISE error stop ("unbekannter Fehler auf Platte");
+ END SELECT;
+ continue (old channel).
+END PROC put external block;
+
+END PACKET setup eumel partitionierung;
+
diff --git a/system/setup/3.1/src/setup eumel 6: shardmontage b/system/setup/3.1/src/setup eumel 6: shardmontage
new file mode 100644
index 0000000..cc0d475
--- /dev/null
+++ b/system/setup/3.1/src/setup eumel 6: shardmontage
@@ -0,0 +1,389 @@
+
+(**************************************************************************)
+(***** Zusammenbau eines SHards aus Modulen mit Dialog *****************)
+(***** Copyright (c) 1987, 1988 by *****************)
+(***** Lutz Prechelt, Karlsruhe *****************)
+(**************************************************************************)
+
+PACKET setup eumel shardmontage (* Copyright (c) 1987 by *)
+DEFINES build shard, (* Lutz Prechelt, Karlsruhe *)
+ add bad sector table to shard, (* Stand : 08.04.88 3.2 *)
+ installation nr, (* Eumel 1.8.1 *)
+ print configuration :
+
+(* Beschreibung des SHard-Hauptmodulformats siehe "modulkonfiguration" *)
+
+(* In diesem Paket sind viele Namenskonventionen verankert.
+ Das leere SHard-Hauptmodul hat den Namen "SHard leer", teilaufgebaute
+ SHards heissen normalerweise in der Form "SHard 07.07.87 14:34" (andere
+ Namen sind möglich, wenn sie mit "SHard " beginnen.)
+ Die Prozedur build shard bastelt in Dialogsteuerung durch den Benutzer
+ aus Modulen und einem leeren oder teilaufgebauten SHard-Hauptmodul einen
+ neuen SHard zusammen und schreibt ihn in die Datei SHARD
+ Die Prozedur add bad block table to shard fügt einem so zusammengebauten
+ SHard eine bad block tabelle gemäß dem Zustand der Partition hinzu oder
+ ändert die vorhandene.
+ Dann ist der SHard komplett fertig zum auf-die-Partition-schleudern.
+ (einschliesslich Installationsnummer)
+*)
+
+LET hauptmodul namentyp = "SHard *",
+ (*modul namentyp = "SHardmodul *",*)
+ shard name = "SHARD";
+
+LET bad sector table size = 1024, (* Entries *)
+ max sh length = 60, (* Blocks, vorläufig !!! *)
+ nr of channels total = 40,
+ offset shard length = 6,
+ offset bad sector table pointer = 8,
+ offset verbal identification = 176, (* Start Shardleiste *)
+ offset id 4 = 196; (* 176 + 14h *)
+
+INT VAR actual installation nr :: id (5);
+DATASPACE VAR ds :: nilspace;
+
+PROC build shard (DATASPACE CONST old shard ds) :
+ (* Der Aufrufer muß hinterher nachsehen, ob es die Datei SHARD auch
+ wirklich gibt. Falls nicht, ist "Aufbau des SHards war nicht möglich"
+ zu melden.
+ *)
+ BOUND MODUL VAR old shard :: old shard ds, new shard;
+ TEXT VAR t;
+ INT VAR i;
+ THESAURUS VAR th, modules, automatic mode modules,
+ modules in old shard, modules in new shard;
+ BOOL CONST old shard valid :: int (old shard, offset id 4) = id (4) AND
+ verbal identification ok;
+ perhaps take old shard; (* ggf. LEAVE *)
+ get main module name in t;
+ copy (t, shard name);
+ new shard := old (shard name);
+ enable stop;
+ eliminate bad sector table from shard (new shard);
+ get module names;
+ configurate modules and build shard;
+ add ids.
+
+verbal identification ok :
+ text (old shard, offset verbal identification, 16) =
+ "SHard Schoenbeck".
+
+perhaps take old shard :
+ kopf;
+ forget (shard name, quiet);
+ IF old shard valid CAND
+ yes ("Wollen Sie den SHard genauso wie beim letzten Setup", FALSE)
+ THEN copy (old shard ds, shard name); LEAVE build shard
+ ELSE out (""10"") FI.
+
+get main module name in t :
+ putline (" A u s w a h l d e s S H a r d - H a u p t m o d u l s "10"");
+ th := all LIKE hauptmodul namentyp;
+ IF highestentry (th) > 1
+ THEN let the user select one
+ ELSE take the only one FI.
+
+let the user select one :
+ putline ("Wählen Sie jetzt bitte, welches SHard-Hauptmodul Sie als");
+ putline ("Ausgangspunkt der Konfiguration benutzen möchten.");
+ putline ("(Namen durch Zeiger auswählen dann RETURN-Taste drücken)");
+ t := ONE th;
+ out (""4""13""10""10""10"").
+
+take the only one :
+ t := name (th, 1);
+ putline ("Das einzige verfügbare SHard Hauptmodul ist");
+ putline (t);
+ pause (30).
+
+get module names :
+ (* Besorgt die Listen 1. vorhandene Module 2. Module im alten SHard
+ und 3. Module im SHard Hauptmodul
+ Liefert in modules eine Auswahl von 1. ohne 3. mit 2. als Vorschläge
+ und in automatic mode modules eine Auswahl von 2. (alles vorgeschlagen)
+ Die Liste 2. ist dabei so sortiert, daß stets eingekettete Module in der
+ richtigen Reihenfolge auftauchen.
+ *)
+ kopf;
+ put ("Ich untersuche den SHard: ");
+ get modules in shard (new shard, modules in new shard);
+ IF old shard valid
+ THEN get modules in shard (old shard, modules in old shard)
+ ELSE modules in old shard := empty thesaurus FI;
+ kopf;
+ putline ("Wählen Sie jetzt bitte mit RETURN/rauf/runter, welche Module Sie");
+ putline ("mit in den SHard aufnehmen möchten.");
+ putline ("(Zum Verlassen ESC q)");
+ modules := certain (all modules - modules in new shard,
+ modules in old shard);
+ IF old shard valid
+ THEN kopf;
+ putline ("Wählen Sie jetzt, welche der Module vollautomatisch wie im");
+ putline ("Vorlage-SHard konfiguriert werden sollen (Reihenfolge egal)");
+ automatic mode modules := certain (modules / modules in old shard,
+ modules in old shard)
+ ELSE automatic mode modules := empty thesaurus FI.
+
+configurate modules and build shard :
+ FOR i FROM 1 UPTO highest entry (modules) REP
+ page; cout (i); collect heap garbage;
+ t := name (modules, i);
+ configurate module (new shard, old shard,
+ modules in old shard CONTAINS t,
+ automatic mode modules CONTAINS t, t)
+ PER;
+ IF highest entry (automatic mode modules) < highest entry (modules)
+ THEN perhaps keep copy of partly build shard FI;
+ collect heap garbage.
+
+perhaps keep copy of partly build shard :
+ kopf;
+ storage info;
+ out (""10"Möchten Sie eine zusätzliche Kopie des SHard in dieser Version"13""10"");
+ IF yes ("aufheben", FALSE)
+ THEN TEXT CONST start :: subtext (hauptmodul namentyp, 1,
+ LENGTH hauptmodul namentyp - 1);
+ t := date;
+ put ("Gewünschter Name :"); out (start); editget (t); out (""13""10"");
+ t := start + t;
+ IF NOT exists (t) COR overwrite THEN copy (shard name, t) FI
+ FI.
+
+add ids :
+ int (new shard, offset id 4 + 2 (* ID5 *), actual installation nr);
+ int (new shard, offset id 4 + 4 (* ID6 *), id (6));
+ int (new shard, offset id 4 + 6 (* ID7 *), id (7)).
+
+overwrite :
+ IF yes ("Existierende Datei """ + t + """ überschreiben", FALSE)
+ THEN forget (t, quiet);
+ TRUE
+ ELSE FALSE FI.
+END PROC build shard;
+
+(******************** print configuration **********************************)
+
+PROC print configuration (DATASPACE CONST old shard ds, BOOL CONST on screen):
+ (* Ruft für alle Module, die in old shard ds und als Datei vorhanden sind
+ print configuration aus dem Paket modulkonfiguration auf.
+ Macht bei on screen nach jedem Modul eine Pause, andernfalls wird die
+ Ausgabe in einem Rutsch gemacht und mit indirect list auf den Drucker
+ umgeleitet.
+ *)
+ BOUND MODUL VAR old shard :: old shard ds;
+ THESAURUS VAR modules in old shard;
+ BOOL CONST old shard valid :: int (old shard, offset id 4) = id (4) AND
+ verbal identification ok;
+ enable stop;
+ IF NOT old shard valid
+ THEN errorstop ("Der SHard ist ungültig");
+ LEAVE print configuration
+ FI;
+ write head ("Anzeigen der Konfiguration des SHard");
+ put ("Bitte fassen Sie sich in Geduld");
+ get modules in shard (old shard, modules in old shard);
+ out (""4""13""10""); (* clear cout, line *)
+ IF on screen
+ THEN putline ("Nach jedem Modul eine Taste drücken.")
+ ELSE putline ("Die Ausgabe geht zum Drucker");
+ indirect list (TRUE);
+ putline ("***** SHardkonfiguration *****"); line;
+ FI;
+ disable stop;
+ do print configuration (old shard, modules in old shard, on screen);
+ IF is error THEN put error; pause; clear error FI;
+ enable stop;
+ IF NOT on screen THEN indirect list (FALSE) FI.
+
+verbal identification ok :
+ text (old shard, offset verbal identification, 16) =
+ "SHard Schoenbeck".
+END PROC print configuration;
+
+PROC do print configuration (MODUL CONST old shard,
+ THESAURUS CONST modules in old shard,
+ BOOL CONST on screen) :
+ INT VAR i;
+ TEXT VAR t;
+ enable stop;
+ FOR i FROM 1 UPTO highest entry (modules in old shard) REP
+ t := name (modules in old shard, i);
+ print configuration (old shard, t);
+ collect heap garbage;
+ IF on screen THEN pause FI
+ PER.
+END PROC do print configuration;
+
+(********************** modules in shard **********************************)
+
+PROC get modules in shard (MODUL CONST old shard,
+ THESAURUS VAR modules in old shard) :
+ (* Stellt einem THESAURUS zusammen, der aus den Namen aller in old shard
+ enthaltenen Module besteht (ohne Duplikate).
+ Dabei sind diejenigen Modulnamen, deren Treiber in old SHard nicht als
+ eingekettete Treiber vorkommen, im Resultat VOR den eingeketteten
+ (d.h. mit kleineren link-Nummern) zu finden, um die richtige
+ Konfigurationsreihenfolge vorschlagen zu können.
+ Es muß zuvor bereits einmal init modules list aufgerufen worden sein !
+ *)
+ INT VAR kanal;
+ REAL VAR p dtcb, p ccb;
+ TEXT VAR type, m name;
+ THESAURUS VAR simple :: empty thesaurus, chained :: empty thesaurus;
+ FOR kanal FROM 0 UPTO nr of channels total - 1 REP
+ cout (kanal);
+ p dtcb := sh dtcb offset (old shard, kanal);
+ p ccb := sh ccb offset (old shard, kanal);
+ look at this chain
+ PER;
+ invert chained thesaurus;
+ modules in old shard := what comes out when i let nameset do all the hard
+ work for me with a little trick and knowledge of implementation.
+
+look at this chain :
+ (* Das Verfahren ist auf den ersten Blick etwas kompliziert, spart aber
+ einiges an Kodeduplikation
+ *)
+ m name := "";
+ WHILE p dtcb <> 0.0 AND p ccb <> 0.0 REP
+ IF m name <> "" AND NOT (chained CONTAINS m name)
+ THEN insert (chained, m name) FI;
+ type := text (old shard, p dtcb, 4);
+ m name := module name (type);
+ p dtcb := unsigned (int (old shard, p ccb + 2.0)); (* verkettet *)
+ p ccb := unsigned (int (old shard, p ccb + 4.0));
+ PER;
+ IF m name <> "" THEN insert (simple, m name) FI.
+
+invert chained thesaurus :
+ (* bis jetzt sind bei mehrfachen Verkettungen die zuletzt eingeketteten
+ Treiber als erstes eingetragen, das darf jedoch nicht so bleiben
+ *)
+ INT VAR i;
+ THESAURUS VAR help :: empty thesaurus;
+ FOR i FROM highest entry (chained) DOWNTO 1 REP
+ insert (help, name (chained, i))
+ PER;
+ chained := help.
+
+what comes out when i let nameset do all the hard
+work for me with a little trick and knowledge of implementation :
+ (* Beware of false algebraic identities ! These are neither numbers nor
+ sets but lists (ordered and not duplicate-free)
+ *)
+ empty thesaurus + (simple - chained) + chained.
+END PROC get modules in shard;
+
+(*************** add bad sector table to shard ****************************)
+
+PROC add bad sector table to shard (INT CONST eumel type,
+ DATASPACE CONST shard ds,
+ BOOL CONST take from partition,
+ INT VAR bad sector count) :
+ (* Fügt einem SHard eine bad sector table hinzu oder ändert sie.
+ Ist noch keine vorhanden, so sollte der Zeiger 0 sein.
+ *)
+ ROW bad sector table size REAL VAR bst;
+ BOUND MODUL VAR new shard :: shard ds;
+ REAL VAR new shard length, offset bst;
+ INT VAR i;
+ enable stop;
+ IF take from partition
+ THEN put ("kopiere Tabelle :");
+ find bst in shard on partition
+ ELSE put ("Spur :");
+ get bad sector table (bst, bad sector count, eumel type);
+ FI;
+ eliminate bad sector table from shard (new shard);
+ new shard length := unsigned (int (new shard, offset shard length));
+ int (new shard, new shard length, bad sector count);
+ int (new shard, offset bad sector table pointer, unsigned (new shard length));
+ new shard length INCR 2.0;
+ IF take from partition
+ THEN copy bst from old to new shard
+ ELSE write bst to new shard FI;
+ int (new shard, offset shard length, unsigned (new shard length)).
+
+copy bst from old to new shard :
+ copy (old shard, offset bst + 2.0, new shard, new shard length,
+ bad sector count * 4);
+ cout (bad sector count * 4);
+ new shard length INCR real (bad sector count * 4).
+
+write bst to new shard :
+ FOR i FROM 1 UPTO bad sector count REP
+ cout (i);
+ enter bad sector low word
+ PER;
+ FOR i FROM 1 UPTO bad sector count REP
+ cout (i);
+ enter bad sector high word;
+ PER.
+
+find bst in shard on partition :
+ cout (0);
+ read file (ds, start of partition (eumel type) + 1.0, max sh length,
+ setup channel);
+ BOUND MODUL CONST old shard :: ds;
+ IF int (old shard, offset id 4) <> id (4)
+ THEN errorstop ("SHard auf Partition unbrauchbar") FI;
+ offset bst := unsigned (int (old shard, offset bad sector table pointer));
+ bad sector count := int (old shard, unsigned (offset bst)).
+
+enter bad sector low word :
+ int (new shard, new shard length, low word (bst [i]));
+ new shard length INCR 2.0.
+
+enter bad sector high word :
+ int (new shard, new shard length, high word (bst [i]));
+ new shard length INCR 2.0.
+END PROC add bad sector table to shard;
+
+(************ eliminate bad sector table from shard ****************)
+
+PROC eliminate bad sector table from shard (MODUL VAR shard) :
+ (* Entfernt die bad sector table (bst) aus dem shard falls sie sich am Ende
+ desselben befindet. Trägt korrekte neue Werte für den bst pointer und
+ shard laenge ein.
+ *)
+ REAL VAR shard length :: unsigned (int (shard, offset shard length)),
+ bst offset :: unsigned (int (shard, offset bad sector table pointer));
+ LET bst entry length = 4.0; (* bst entries sind Wort-Paare *)
+ IF bst offset = 0.0
+ THEN (* ist gar keine bst vorhanden, also schon prima eliminiert *)
+ ELIF bst ist am ende
+ THEN bst entfernen FI;
+ bst austragen.
+
+bst ist am ende :
+ bst offset + bst entry length * nr of bst entries + 2.0 =
+ shard length.
+
+nr of bst entries :
+ unsigned (int (shard, bst offset)).
+
+bst entfernen :
+ int (shard, offset shard length, unsigned (bst offset)).
+
+bst austragen :
+ int (shard, offset bad sector table pointer, 0).
+END PROC eliminate bad sector table from shard;
+
+(******************* installation nr *************************************)
+
+INT PROC installation nr :
+ actual installation nr
+END PROC installation nr;
+
+PROC installation nr (INT CONST new) :
+ actual installation nr := new
+END PROC installation nr;
+
+(*********************** Hilfsprozeduren **********************************)
+
+PROC kopf :
+ write head ("M o d u l - S H a r d Zusammenbau eines SHard").
+END PROC kopf;
+
+END PACKET setup eumel shardmontage;
+
diff --git a/system/setup/3.1/src/setup eumel 7: setupeumel b/system/setup/3.1/src/setup eumel 7: setupeumel
new file mode 100644
index 0000000..0504e97
--- /dev/null
+++ b/system/setup/3.1/src/setup eumel 7: setupeumel
@@ -0,0 +1,1238 @@
+(*************************************************************************)
+(*** Hauptprogramm des setup-Eumel:Einstellen der EUMEL - Partitionen ***)
+(*** und SHard-Installation auf einer Festplatte. ***)
+(*** ***)
+(*** Autor : W. Sauerwein Stand : 07.04.89 ***)
+(*** I. Ley Version : 2.3 ***)
+(*** Anpassung an Modul-SHard : Lutz Prechelt, Karlsruhe ***)
+(*** -"- : Werner Metterhausen ***)
+(*** -"- : Martin Schönbeck ***)
+(*************************************************************************)
+(*** V 3.1 14.04.89 shard wird immer mit 'max sh size' geschriegen ***)
+(*** da mit 'ds pages' ggf teile fehlten, wenn innen ***)
+(*** unbenutzte pages (buffer) waren ***)
+(*** V 3.0 10.04.89 support fuer mehrere Laufwerke eingebaut ***)
+(*** ausgabe der module vor loeschen etc. entfernt ***)
+
+PACKET setup eumel DEFINES setup eumel, setup eumel endlos, version,
+show partition table:
+
+LET setup version = "Version 3.1";
+
+TEXT VAR stand :: "Stand : 18.04.89 (mit Modul-SHard Version 4.9)";
+
+PROC version (TEXT CONST vers): stand := vers END PROC version;
+
+PROC version: editget (stand) END PROC version;
+
+LET max partitions = 4,
+ max sh size = 128, (* Anzahl Bloecke *)
+ return = ""13"",
+ escape = ""27"";
+
+LET hauptmodul namentyp = "SHard *",
+ modul namentyp = "SHardmodul *",
+ sh name = "SHARD",
+ sh backup = "SHARD Sicherungskopie";
+
+ROW max partitions INT VAR part list;
+ROW max partitions INT VAR part type, part active,
+ part first track, part last track;
+ROW max partitions REAL VAR part start,
+ part size;
+
+ INT VAR zylinder,
+ startzeile tabelle :: 1,
+ startzeile menu :: 12,
+ active partition,
+ partitions,
+ partition, i, j, cx, cy, help;
+ TEXT VAR retchar,
+ meldung := "";
+ BOOL VAR testausgabe,
+ mit schreibzugriff := TRUE,
+ meldung eingetroffen := FALSE,
+ endlos :: FALSE,
+ at version;
+THESAURUS VAR minimum modulkollektion := empty thesaurus;
+DATASPACE VAR ds := nilspace;
+
+(************************* setup eumel endlos *****************************)
+
+PROC setup eumel endlos (BOOL CONST b) :
+ endlos := b;
+ IF endlos
+ THEN line;
+ putline ("Bitte geben Sie nun alle die Dateien an, die der Benutzer auf");
+ putline ("keinen Fall löschen darf. (Taste drücken)");
+ minimum modulkollektion := certain (all, emptythesaurus);
+ line (3);
+ putline ("Der setup eumel kann nun nach dem nächsten Aufruf nicht mehr ");
+ putline ("verlassen werden. ")
+ FI.
+END PROC setup eumel endlos;
+
+(******************** get/put actual partition data ************************)
+
+PROC get actual partition data :
+ get boot block;
+ zylinder := tracks;
+ FOR i FROM 1 UPTO max partitions REP
+ part type (i) := partition type (i);
+ part first track (i) := first track (i);
+ part last track (i) := last track (i);
+ part start (i) := partition start (i);
+ part size (i) := partition size (i);
+ part active (i) := partition word 0 (i);
+ IF partition active (i) THEN active partition := i FI
+ PER;
+ get number of installed partitions;
+ generate part list.
+
+get number of installed partitions :
+ partitions := 0;
+ FOR i FROM 1 UPTO max partitions REP
+ IF part type (i) <> 0 THEN partitions INCR 1 FI
+ PER.
+
+generate part list :
+ FOR i FROM 1 UPTO max partitions REP
+ IF part type (i) <> 0 THEN part list (i) := i
+ ELSE part list (i) := 0
+ FI;
+ PER;
+ schiebe nullen nach hinten;
+ sort part list.
+
+schiebe nullen nach hinten :
+ i := 1; INT VAR k := 0;
+ REP k INCR 1;
+ IF part list (i) = 0 THEN circle
+ ELSE i INCR 1
+ FI
+ UNTIL k = max partitions - 1 PER.
+
+circle :
+ FOR j FROM i UPTO max partitions - 1 REP
+ part list (j) := part list (j + 1)
+ PER;
+ part list (max partitions) := 0.
+
+sort part list :
+ FOR i FROM 2 UPTO partitions REP
+ FOR j FROM 1 UPTO i - 1 REP
+ IF part first track (part list (i)) < part first track (part list (j))
+ THEN tausche FI
+ PER
+ PER.
+
+tausche :
+ help := part list (i);
+ part list (i) := part list (j);
+ part list (j) := help.
+
+END PROC get actual partition data;
+
+PROC put actual partition data :
+ FOR i FROM 1 UPTO max partitions REP
+ IF partition exists (i) THEN put partition
+ ELSE clear partition (i)
+ FI;
+ PER;
+ IF mit schreibzugriff THEN put boot block FI.
+
+put partition :
+ IF is eumel (i) THEN partition type (i, part type (i));
+ first track (i, part first track (i));
+ last track (i, part last track (i));
+ partition start (i, part start (i));
+ partition size (i, part size (i))
+ FI;
+ partition word 0 (i, part active (i));
+ IF active partition = i
+ THEN partition active (i, TRUE)
+ ELSE partition active (i, FALSE)
+ FI.
+
+END PROC put actual partition data;
+
+(*************************** setup eumel ********************************)
+
+PROC setup eumel :
+ line; command dialogue (TRUE);
+ at version := yes ("System für AT", TRUE);
+ testausgabe := FALSE; (*yes ("Testversion", FALSE); *)
+ pruefe ob notwendige dateien vorhanden;
+ init modules list;
+ IF yes ("Leere Floppy für Systemsicherung eingelegt", FALSE)
+ THEN command dialogue (FALSE); save system; command dialogue (TRUE) FI;
+ IF NOT endlos THEN putline ("Verlassen mit ESC."); pause (40) FI;
+ terminal setup;
+ logo;
+ generate eumel.
+
+pruefe ob notwendige dateien vorhanden:
+ BOUND INT VAR y;
+ IF mit schreibzugriff THEN y := old (sh name);
+ y := old ("shget.exe");
+ y := old ("bootblock");
+ y := old ("configuration");
+ y := old ("AT-4.x")
+ FI.
+
+END PROC setup eumel;
+
+PROC generate eumel :
+ disable stop;
+ show partition table;
+ REP update table;
+ main menu;
+ action;
+ IF is error THEN fehler;
+ put line (error message);
+ put line ("Bitte betätigen Sie eine Taste !");
+ clear error;
+ pause;
+ IF mit schreibzugriff THEN terminal setup FI
+ FI
+ PER.
+
+action :
+ INT VAR choice;
+ clear error;
+ REP
+ cursor (cx, cy);
+ IF partitions < max partitions
+ THEN choice := get choice (0, max, retchar)
+ ELSE choice := get choice (2, max, 0, retchar)
+ FI;
+ IF escaped CAND NOT endlos THEN LEAVE generate eumel FI;
+ UNTIL retchar = return PER;
+ cl eop (1, startzeile menu - 1);
+ INT VAR unser kanal := channel;
+ SELECT choice OF
+ CASE 0 : programm ende
+ CASE 1 : create partition (TRUE)
+ CASE 2 : create partition (FALSE)
+ CASE 3 : activate partition
+ CASE 4 : delete partition
+ CASE 5 : delete partition table
+ CASE 6 : konfiguration anzeigen
+ CASE 7 : shard zusammenbauen
+ CASE 8 : modulkollektion aendern
+ CASE 9 : change drive
+
+ END SELECT;
+ continue (unser kanal).
+
+max :
+ 9.
+
+change drive:
+ cursor (1, startzeile menu);
+ put ("Bitte Laufwerksnummer angeben:");
+ get cursor (cx, cy);
+ put (" 0 - 3");
+ REP cursor (cx, cy);
+ INT VAR drive := get choice (0, 3, retchar);
+ IF sure escaped THEN LEAVE change drive FI;
+ UNTIL NOT escaped PER;
+ setup channel (28-drive);
+ show partition table.
+
+
+programm ende :
+ cursor (1, startzeile menu);
+ IF keine partition aktiv
+ THEN IF trotz warnung beenden THEN eumel beenden FI
+ ELSE IF yes ("Wollen Sie die Partitionierung Ihrer Festplatte beenden", FALSE)
+ THEN eumel beenden
+ FI FI.
+
+keine partition aktiv : active partition = 0.
+
+trotz warnung beenden :
+ put line ("ACHTUNG : Es ist keine Partition aktiv gesetzt !");
+ put line (" Sie können daher nicht von der Festplatte booten !");
+ line;
+ yes ("Wollen Sie trotzdem die Partitionierung der Festplatte beenden", FALSE).
+
+eumel beenden :
+ cl eop (1, startzeile menu - 1);
+ cursor (1, startzeile menu + 3);
+ shutup; terminal setup;
+ logo;
+ show partition table.
+
+shard zusammenbauen :
+ cl eop (1, startzeile menu);
+ IF yes ("Wollen Sie Ihren SHard neu konfigurieren", FALSE)
+ THEN shard sichern und vorlage beschaffen;
+
+ IF NOT is error THEN build shard (ds) FI;
+ IF is error OR NOT exists (sh name)
+
+ THEN forget (sh name, quiet); rename (sh backup, sh name);
+ putline ("Zusammenbau fehlgeschlagen. Alter SHard erhalten.");
+ pause (300);
+ FI;
+ forget (sh backup, quiet); forget (ds);
+ show partition table
+ FI.
+
+shard sichern und vorlage beschaffen :
+ forget (sh backup, quiet);
+ IF exists (shname)
+ THEN copy (sh name, sh backup);
+ FI;
+ forget (ds);
+ line;
+ IF yes (""3"Ist in einer existierenden Eumel-Partition ein SHard installiert,
+"13""10"der als Vorlage dienen soll", FALSE)
+ THEN INT VAR vorlage :: 69;
+ editget (1, startzeile menu + 4, "Partitiontyp: ", vorlage);
+ (* Das sollte man mal noch schöner machen !!! *)
+ read file (ds, start of partition (vorlage) + 1.0, max sh size,
+ setup channel)
+ ELSE ds := old (sh name) FI.
+
+
+konfiguration anzeigen :
+ hole anzuzeigenden ds;
+ line;
+ print configuration (ds, NOT yes ("Auf dem Drucker ausgeben", FALSE));
+ show partition table.
+
+hole anzuzeigenden ds:
+ forget (ds);
+ line;
+ IF yes ("Soll ein SHard aus einer Partition angezeigt werden", TRUE)
+ THEN INT VAR anzeige :: 69;
+ editget (1, startzeile menu + 4, "Partitiontyp: ", anzeige);
+ (* Das sollte man mal noch schöner machen !!! *)
+ read file (ds, start of partition (anzeige) + 1.0, max sh size,
+ setup channel)
+ ELSE ds := old (ONE ((all LIKE hauptmodul namentyp) + "SHARD")) FI.
+
+
+modulkollektion aendern :
+ THESAURUS VAR th;
+ TEXT VAR x :: "SHard";
+ INT VAR i ;
+ page;
+ th := (all LIKE hauptmodul namentyp) + (all LIKE modul namentyp) +
+ (all LIKE sh name) ;
+ (* Diese Ausgabe macht leider den Bildschirmaufbau kaputt *)
+ (* mit dem Erfolg, daß man dann nicht mehr sieht, was man *)
+ (* ankreuzt, deshalb auskommentiert *)
+ (*******
+ putline(" Alle SHards :");
+ line;
+ FOR i FROM 1 UPTO highest entry(th)
+ REP
+ putline(name(th,i))
+ PER;
+ *******)
+ putline(" Modulkollektion ändern");
+ line;
+ IF yes ("Wollen Sie irgendwelche Module löschen", FALSE)
+ THEN th := (all LIKE hauptmodul namentyp) + (all LIKE modul namentyp) +
+ (all LIKE sh name) - minimum modulkollektion;
+ forget (certain (th, emptythesaurus));
+ ELIF yes ("Wollen Sie Module vom Archiv holen", FALSE)
+ THEN put ("Archivname:"); editget (x); line;
+ archive (x);
+ th := ALL archive LIKE modul namentyp;
+ fetch (certain (th, emptythesaurus), archive);
+ release (archive)
+ FI;
+ init modules list;
+ show partition table.
+
+
+END PROC generate eumel;
+
+
+PROC show partition table :
+ IF NOT mit schreibzugriff THEN get actual partition data FI;
+ headline;
+ devide table;
+ columns;
+ underlines;
+ rows;
+ downline.
+
+head line :
+ cl eop (1, startzeile tabelle);
+ put center (startzeile tabelle, "Aktuelle Partitions - Tabelle", TRUE).
+
+devide table :
+ FOR i FROM 1 UPTO 8
+ REP
+ cursor (45, startzeile tabelle + i); out (inverse (""))
+ PER.
+
+columns :
+ cursor ( 1, startzeile tabelle + 2);
+ out ("Nr. System Typ Zustand Grösse Anfang Ende");
+ cursor (48, startzeile tabelle + 2);
+ out ("Platte : Zyl. / KB").
+
+underlines :
+ cursor ( 1, startzeile tabelle + 3);
+ out ("--------------------------------------------");
+ cursor (47, startzeile tabelle + 3);
+ out ("------------------------------").
+
+rows :
+ FOR i FROM 1 UPTO max partitions
+ REP cursor (2, startzeile tabelle + 3 + i);
+ put (text (i) + " :")
+ PER.
+
+downline :
+ put center (startzeile menu - 3, " EUMEL Installationssystem " + setup version
+ + " (IBM PC/" + rechner typ
+ + " und kompatible Rechner) ", TRUE);
+ put center (startzeile menu - 2, stand, TRUE).
+
+rechner typ :
+ IF at version THEN "AT"
+ ELSE "XT"
+ FI.
+
+END PROC show partition table;
+
+PROC main menu :
+ biete auswahl an;
+ IF meldung eingetroffen THEN melde FI;
+ IF testausgabe THEN ausgabe fuer test FI.
+
+ausgabe fuer test :
+ testrahmen;
+ test out.
+
+testrahmen :
+ FOR i FROM startzeile menu - 1 UPTO startzeile menu + 9
+ REP
+ cl eol (45, i);
+ put (inverse (""))
+ PER;
+ cursor (52, startzeile menu);
+ put ("Ecke für Test-Output");
+ cursor (52, startzeile menu).
+
+test out :
+ FOR i FROM 1 UPTO max partitions
+ REP
+ cursor (52, startzeile menu + 1 + i);
+ put (text (i) + ":");
+ put (part type (i));
+ put (part first track (i));
+ put (part last track (i));
+ IF active partition = i THEN put ("aktiv")
+ ELSE put ("inaktiv")
+ FI;
+ PER.
+
+melde :
+ cursor (1, 24);
+ put (inverse ("Meldung :"));
+ put (meldung);
+ meldung eingetroffen := FALSE.
+
+biete auswahl an :
+ cl eop (1, startzeile menu - 1); line;
+ IF partitions < max partitions
+ THEN putline (" EUMEL - Partition einrichten .............. 1")
+ ELSE line;
+ putline (" EUMEL - Partition")
+ FI;
+ cursor (20, startzeile menu + 1);
+ putline ("erneuern (Neuer SHard) .. 2");
+ putline (" aktivieren .............. 3");
+ putline (" löschen ................. 4");
+ putline (" Partitionstabelle löschen ................. 5");
+ putline (" SHard-Konfiguration anzeigen .............. 6");
+ putline (" SHard konfigurieren ....................... 7");
+ putline (" SHardmodule laden oder löschen ............ 8");
+ putline (" Bearbeitetes Laufwerk wechseln ............ 9");
+ putline (" SETUP-EUMEL beenden ....................... 0");
+ putline ("-----------------------------------------------");
+ put (" Ihre Wahl >>");
+ get cursor (cx, cy).
+
+END PROC main menu;
+
+PROC update table :
+ IF mit schreibzugriff THEN get actual partition data FI;
+ FOR i FROM 1 UPTO partitions REP update partition PER;
+ FOR i FROM partitions + 1 UPTO max partitions REP rubout partition PER;
+ zeige plattengroesse;
+ IF active partition = 0 THEN meldung := "ACHTUNG : Es ist keine Partition aktiv gesetzt !";
+ meldung eingetroffen := TRUE
+ FI.
+
+update partition :
+ partition := part list (i);
+ show partition.
+
+rubout partition :
+ cursor (5, startzeile tabelle + 3 + i);
+ out (" ").
+
+show partition :
+ cursor (5, startzeile tabelle + 3 + i);
+ put (name + type + zustand + groesse + startspur + endspur).
+
+name : subtext (subtext (part name, 1, 7)
+ + " ", 1, 8).
+
+type : text (part type (partition), 5) + " ".
+
+zustand : IF active partition = partition THEN (" aktiv ")
+ ELSE (" ")
+ FI.
+
+startspur : " " + text (part first track (partition), 5).
+endspur : text (part last track (partition), 6).
+groesse : text (part groesse, 5).
+
+zeige plattengroesse :
+ put gesamt;
+ put noch freie;
+ put maximaler zwischenraum.
+
+put maximaler zwischenraum :
+ cursor (48, startzeile tabelle + 6);
+ put ("gr. Lücke : " + text (maximaler zwischenraum, 5) + " / "
+ + kilobyte(maximaler zwischenraum)).
+
+put gesamt :
+ cursor (48, startzeile tabelle + 4);
+ put ("Gesamt : " + text (zylinder, 5) + " / "
+ + kilobyte(zylinder)).
+
+put noch freie :
+ cursor (48, startzeile tabelle + 5);
+ put ("Frei : " + text (freie zylinder, 5) + " / "
+ + kilobyte( freie zylinder)).
+
+END PROC update table;
+
+
+TEXT PROC kilobyte (INT CONST zylinderzahl):
+ TEXT VAR kb;
+ kb := text(round(real(zylinderzahl) * real(heads) * real(sectors) * 0.512,0));
+ subtext(kb,1,length(kb)-2)
+
+END PROC kilobyte;
+
+
+PROC create partition (BOOL CONST partition is new) :
+ IF NOT partition is new
+ THEN renew partition
+ ELIF freie part number gefunden CAND noch platz uebrig
+ THEN new partition
+ ELSE kein platz mehr FI.
+
+kein platz mehr :
+ fehler;
+ put ("Es kann keine neue Partition mehr eingerichtet werden.");
+ pause (300).
+
+noch platz uebrig : freie zylinder > 0.
+
+freie part number gefunden :
+ IF partitions < max partitions THEN suche nummer;
+ TRUE
+ ELSE FALSE
+ FI.
+
+suche nummer :
+ partition := 0;
+ REP partition INCR 1 UNTIL part type (partition) = 0 PER.
+
+new partition :
+ cl eop (1, startzeile menu);
+ IF yes ("Neue EUMEL - Partition einrichten", FALSE)
+ THEN INT VAR alte aktive partition := active partition;
+ IF NOT partition exists (partition)
+ THEN IF enter partition spezifikations
+ THEN IF mit schreibzugriff THEN check part and install FI
+ FI;
+ ELSE keine freie partition
+ FI FI.
+
+renew partition :
+ cl eop (1, startzeile menu);
+ IF yes ("Neuen SHard auf bestehende EUMEL - Partition schreiben", FALSE)
+ THEN enter part number;
+ IF mit schreibzugriff THEN check part and install FI
+ FI.
+
+enter part number :
+ put ("Welche Partition wollen Sie erneuern :");
+ get cursor (cx, cy);
+ put (" Abbruch mit <ESC>");
+ REP
+ REP cursor (cx, cy);
+ partition := get choice (1, 4, retchar);
+ IF sure escaped THEN LEAVE create partition FI;
+ partition := part list (partition)
+ UNTIL NOT escaped PER;
+ IF NOT (partition exists (partition) AND is eumel (partition))
+ THEN fehler; put ("Keine EUMEL - Partition");
+ pause (300); cl eop (1, 20);
+ FI
+ UNTIL partition exists (partition) AND is eumel (partition) PER.
+
+check part and install:
+ IF partition is new THEN put actual partition data FI;
+ IF testausgabe THEN put ("Keine Überprüfung schlechter Sektoren, da Testversion !")
+ ELSE trage schlechte sektoren ein;
+ FI;
+ IF is error AND partition is new
+ THEN active partition := alte aktive partition;
+ rubout partition;
+ LEAVE check part and install
+ ELIF NOT is error
+ THEN line;
+ put ("Shard wird auf die Partition geschrieben..."); line (2);
+ bringe shard auf platte (part type (partition));
+ ELSE line;
+ putline ("Fehler aufgetreten. Partition unverändert")
+ FI;
+ put ("Bitte betätigen Sie eine Taste !");
+ loesche eingabepuffer;
+ pause.
+
+trage schlechte sektoren ein:
+ INT VAR anzahl schlechter sektoren;
+ line (2);
+ putline ("Überprüfen der Partition nach schlechten Sektoren.");
+ add bad sector table to shard (part type (partition), old (sh name),
+ NOT partition is new, anzahl schlechter sektoren);
+ line;
+ IF NOT is error THEN put ("Ich habe " + bs zahl + " gefunden.") FI.
+
+bs zahl:
+ IF anzahl schlechter sektoren = 0
+ THEN "keine schlechten Sektoren"
+ ELIF anzahl schlechter sektoren > 1
+ THEN text (anzahl schlechter sektoren) + " schlechte Sektoren"
+ ELSE "einen schlechten Sektor"
+ FI.
+
+keine freie partition :
+ fehler;
+ put line ("Sie können nur auf freien Partitionen 'EUMEL' einrichten.");
+ put ("Die Partition " + text (partition) + " ist bereits mit einem System belegt !");
+ pause (300).
+
+END PROC create partition;
+
+BOOL PROC enter partition spezifikations :
+ cl eol (60, startzeile menu); put ("Abbruch mit <ESC>");
+ cl eol (1, startzeile menu + 2);
+ put ("Typ : EUMEL,");
+ INT VAR old end := part last track (partition);
+ enter part size;
+ enter part first track;
+ put end track;
+ cl eol (60, startzeile menu);
+ IF NOT eingaben ok THEN LEAVE enter partition spezifikations WITH FALSE FI;
+ cl eol (1, startzeile menu + 4);
+ part first track (partition) := int (start);
+ part last track (partition) := int (start) + int (size) - 1;
+ part start (partition) := first usable sector;
+ part size (partition) := first sector behind partition -
+ part start (partition);
+ active partition := partition;
+ part type (partition) := kleinste freie eumel nummer;
+ add to part list;
+ TRUE.
+
+eingaben ok :
+ cl eop (1, startzeile menu + 4);
+ yes ("Sind die Partitionsangaben korrekt", FALSE).
+
+enter part size :
+ get cursor (cx, cy);
+ REP
+ REP cursor (cx, cy);
+ put ("Welche Grösse :");
+ TEXT VAR size := groessenvorschlag;
+ loesche eingabepuffer;
+ editget (size, escape, "", retchar);
+ IF sure escaped
+ THEN LEAVE enter partition spezifikations WITH FALSE
+ FI
+ UNTIL NOT escaped PER;
+ IF NOT size ok THEN falsche groesse FI
+ UNTIL size ok AND not too big PER;
+ cl eol (1, y + 1);
+ cl eol (1, y + 2);
+ cl eol (cx, cy);
+ put ("Grösse : " + size + ";").
+
+size ok :
+ NOT size greater maxint
+ CAND size positiv
+ AND desired size <= maximaler zwischenraum.
+
+not too big:
+ INT VAR x,y;
+ get cursor(x,y);
+ IF real(kilobyte(int(size))) >= 16196.0
+ THEN line;
+ putline("Eine Partition grösser 16 MB ist nur bei einer + Version sinnvoll !");
+ yes("Eingabe korrekt",FALSE)
+ ELSE TRUE
+ FI.
+
+size greater maxint :
+ length (size) >= 5.
+
+size positiv :
+ desired size > 0.
+
+falsche groesse :
+ fehler;
+ put line ("Es kann keine Partition mit " + size + " Zylindern eingerichtet werden !");
+ IF NOT size greater maxint CAND size positiv
+ THEN put ("Die grösste zusammenhängende Anzahl Zylinder ist "
+ + text (maximaler zwischenraum) + ".")
+ ELSE put ("Bitte eine positive Grösse angeben !")
+ FI.
+
+groessenvorschlag :
+ text (maximaler zwischenraum).
+
+enter part first track :
+ get cursor (cx, cy);
+ REP
+ REP cursor (cx, cy);
+ put ("Start - Zylinder der Partition :");
+ TEXT VAR start := startvorschlag;
+ loesche eingabepuffer;
+ editget (start, escape, "", retchar);
+ IF sure escaped THEN part last track (partition) := old end;
+ LEAVE enter partition spezifikations WITH FALSE
+ FI
+ UNTIL NOT escaped PER;
+ IF NOT start ok THEN falscher start FI
+ UNTIL start ok PER;
+ cl eol (cx, cy);
+ put ("Start : " + start + ";").
+
+put end track :
+ put ("Ende : " + text (int (start) + int (size) - 1)).
+
+start ok :
+ length (start) < 5
+ CAND enough room
+ AND NOT in existing partition
+ AND NOT out of volume.
+
+out of volume : desired start > zylinder OR desired start < 0.
+
+in existing partition :
+ IF partitions = 0 THEN FALSE
+ ELSE i := 0;
+ REP
+ i INCR 1
+ UNTIL start of part i > desired start
+ OR last partition
+ OR error found PER;
+ IF error found THEN TRUE ELSE FALSE FI
+ FI.
+
+error found :
+ part index <> i AND
+ (start of part i <= desired start AND end spur i >= desired start).
+
+part index :
+ 0.
+
+desired start : int (start).
+
+start of part i : part first track (part list (i)).
+
+last partition : i = partitions.
+
+enough room :
+ desired start + desired size <= begin of next partition.
+
+desired size : int (size).
+
+begin of next partition :
+ IF partitions = 0 THEN zylinder
+ ELSE i := 0;
+ REP
+ i INCR 1;
+ UNTIL start of part i > desired start
+ OR last partition PER;
+ IF start of part i > desired start THEN start of part i
+ ELSE zylinder
+ FI
+ FI.
+
+falscher start :
+ fehler;
+ put ("Auf Zylinder " + start);
+ put ("kann keine Partition der Grösse " + size);
+ put ("beginnen !").
+
+startvorschlag :
+ text (best start position).
+
+best start position :
+ IF partitions = 0 THEN 0
+ ELSE best start spur vor und zwischen den partitionen
+ FI.
+
+best start spur vor und zwischen den partitionen :
+ INT VAR best start := 0, min size := zylinder;
+ FOR i FROM 0 UPTO partitions
+ REP
+ IF platz genug zwischen i und i plus 1 AND kleiner min size
+ THEN min size := platz zwischen i und i plus 1;
+ best start := start des zwischenraums
+ FI
+ PER;
+ best start.
+
+start des zwischenraums :
+ end spur i + 1.
+
+end spur i :
+ IF i = 0 THEN -1
+ ELSE part last track (part list (i))
+ FI.
+
+platz zwischen i und i plus 1 :
+ part first track i plus 1 - (end spur i + 1).
+
+part first track i plus 1 :
+ IF i = partitions THEN zylinder
+ ELSE part first track (part list (i + 1))
+ FI.
+
+platz genug zwischen i und i plus 1 :
+ platz zwischen i und i plus 1 >= int (size).
+
+kleiner min size : platz zwischen i und i plus 1 < min size.
+
+first usable sector:
+ IF int (start) = 0
+ THEN 1.0
+ ELSE real (heads * sectors) * real (start)
+ FI.
+
+first sector behind partition:
+ real (heads * sectors) * (real(start) + real (size)).
+
+kleinste freie eumel nummer :
+ IF partitions = 0 THEN 69
+ ELSE search for part type (69)
+ FI.
+
+END PROC enter partition spezifikations;
+
+INT PROC search for part type (INT CONST minimum) :
+ IF minimum exists THEN search for part type (minimum + 1)
+ ELSE minimum
+ FI.
+
+minimum exists :
+ BOOL VAR exists := FALSE;
+ INT VAR i;
+ FOR i FROM 1 UPTO partitions REP
+ IF part type (part list (i)) = minimum THEN exists := TRUE FI
+ PER;
+ exists.
+
+END PROC search for part type;
+
+PROC bringe shard auf platte (INT CONST eumel type):
+ IF mit schreibzugriff THEN
+ enable stop;
+ INT CONST old session :: session;
+ fixpoint;
+ IF session <> old session
+ THEN errorstop ("SHard auf Platte schreiben im RERUN !") FI;
+ write file ("shget.exe", start der eumel partition, 1, setup channel);
+ write file (sh name, start der eumel partition + 1.0,
+ max sh size, setup channel)
+ FI.
+
+start der eumel partition:
+ start of partition (eumel type).
+END PROC bringe shard auf platte;
+
+
+PROC add to part list :
+ IF part list leer THEN part list (1) := partition
+ ELIF neuer start vor letzter partition THEN fuege ein
+ ELSE haenge an
+ FI;
+ partitions INCR 1.
+
+part list leer : partitions = 0.
+
+neuer start vor letzter partition :
+ part first track (partition) < part first track (part list (partitions)).
+
+haenge an : part list (partitions + 1) := partition.
+
+fuege ein :
+ suche erste partition die spaeter startet;
+ schiebe restliste auf;
+ setze partition ein.
+
+suche erste partition die spaeter startet :
+ i := 0;
+ REP i INCR 1
+ UNTIL part first track (part list (i)) > part first track (partition) PER.
+
+schiebe restliste auf :
+ FOR j FROM partitions DOWNTO i
+ REP
+ part list (j + 1) := part list (j)
+ PER.
+
+setze partition ein :
+ part list (i) := partition.
+
+END PROC add to part list ;
+
+INT PROC maximaler zwischenraum :
+ IF partitions = 0 THEN zylinder
+ ELSE max (maximaler platz vor und zwischen den partitionen,
+ platz hinter letzter partition)
+ FI.
+
+maximaler platz vor und zwischen den partitionen :
+ help := platz vor erster partition;
+ FOR i FROM 1 UPTO partitions - 1
+ REP
+ help := max (help, begin of part i plus 1 - end of part i - 1)
+ PER;
+ help.
+
+platz vor erster partition :
+ part first track (part list (1)).
+
+platz hinter letzter partition :
+ zylinder - part last track (part list (partitions)) - 1.
+
+begin of part i plus 1 :
+ part first track (part list (i + 1)).
+
+end of part i :
+ part last track (part list (i)).
+
+END PROC maximaler zwischenraum;
+
+PROC activate partition :
+ enter part number;
+ IF NOT escaped THEN set partition active FI.
+
+set partition active :
+ IF yes ("Partition mit Typnummer " + text (part type (partition)) + " aktivieren", FALSE)
+ THEN active partition := partition;
+ put actual partition data
+ FI.
+
+enter part number :
+ cursor (60, startzeile menu); put ("Abbruch mit <ESC>");
+ cursor ( 1, startzeile menu);
+ put ("Welche Partition wollen Sie aktivieren :");
+ get cursor (cx, cy);
+ REP
+ REP cursor (cx, cy);
+ partition := get choice (1, 4, retchar);
+ IF sure escaped THEN LEAVE activate partition FI;
+ partition := part list (partition)
+ UNTIL NOT escaped PER;
+ IF NOT partition exists (partition) THEN fehler melden FI
+ UNTIL partition exists (partition) PER;
+ cl eol (60, startzeile menu);
+ cl eop (1, cy + 2).
+
+fehler melden :
+ partition gibt es nicht.
+
+partition gibt es nicht :
+ fehler;
+ put ("Diese Partition gibt es nicht.").
+
+END PROC activate partition;
+
+PROC delete partition :
+ enter part number;
+ IF NOT escaped THEN
+ IF yes ("Partition mit Typnummer " + text (part type (partition)) + " löschen", FALSE)
+ AND ganz sicher
+ THEN rubout partition
+ FI FI.
+
+enter part number :
+ cursor (60, startzeile menu); put ("Abbruch mit <ESC>");
+ cursor ( 1, startzeile menu);
+ put ("Welche Partition wollen Sie löschen :");
+ get cursor (cx, cy);
+ REP
+ REP cursor (cx, cy);
+ partition := get choice (1, 4, retchar);
+ IF sure escaped THEN LEAVE delete partition FI;
+ partition := part list (partition)
+ UNTIL NOT escaped PER;
+ IF NOT (partition exists (partition) AND is eumel (partition)) THEN fehler melden FI
+ UNTIL partition gueltig AND is eumel (partition) PER;
+ cl eol (60, startzeile menu);
+ cl eop (1, cy + 2).
+
+fehler melden :
+ IF NOT partition exists (partition) THEN partition gibt es nicht
+ ELSE keine eumel partition
+ FI.
+
+partition gibt es nicht :
+ fehler;
+ put ("Diese Partition gibt es nicht.").
+
+ganz sicher :
+ line;
+ yes ("Sind Sie sich ganz sicher", FALSE).
+
+END PROC delete partition;
+
+PROC delete partition table :
+ cursor ( 1, startzeile menu + 1);
+ put ("Es gehen ALLE Daten verloren, die sich auf Ihrer Platte befinden !");
+ line (2);
+ IF yes ("Wollen Sie wirklich die ganze Partitionstabelle löschen", FALSE)
+ THEN line;
+ IF yes ("Sind Sie sich ganz sicher", FALSE)
+ THEN loesche ganze tabelle
+ FI FI.
+
+loesche ganze tabelle :
+ FOR i FROM 1 UPTO max partitions
+ REP part type (i) := 0;
+ part first track (i) := 0;
+ part last track (i) := 0;
+ part start (i) := 0.0;
+ part size (i) := 0.0;
+ part list (i) := 0
+ PER;
+ partitions := 0;
+ active partition := 0;
+ IF mit schreibzugriff THEN clear partition table (-3475) FI.
+
+END PROC delete partition table;
+
+PROC rubout partition :
+ part type (partition) := 0;
+ part first track (partition) := 0;
+ part last track (partition) := 0;
+ IF active partition = partition THEN active partition := 0 FI;
+ del from part list;
+ put actual partition data.
+
+del from part list :
+ search for partition in part list;
+ delete it and set highest to 0;
+ partitions DECR 1.
+
+search for partition in part list :
+ i := 0;
+ REP i INCR 1 UNTIL part list (i) = partition PER.
+
+delete it and set highest to 0 :
+ FOR j FROM i UPTO partitions - 1
+ REP
+ part list (j) := part list (j + 1)
+ PER;
+ part list (partitions) := 0.
+
+END PROC rubout partition;
+
+INT PROC get choice (INT CONST von, bis, TEXT VAR retchar):
+ get choice (von, bis, von, retchar)
+END PROC get choice;
+
+INT PROC get choice (INT CONST von, bis, zusatz, TEXT VAR retchar):
+ LET return = ""13"",
+ escape = ""27"",
+ left = ""8"";
+ TEXT VAR buffer;
+ INT VAR cx, cy;
+ get cursor (cx, cy); out (" " + left);
+ REP
+ REP
+ cursor (cx, cy); buffer := incharety;
+ UNTIL input ok OR buffer = escape PER;
+ IF buffer = escape THEN retchar := escape;
+ LEAVE get choice WITH 0
+ FI;
+ out (buffer);
+ leseschleife bis left or ret;
+ IF retchar = left THEN out (left + " ") FI;
+ IF retchar = escape THEN LEAVE get choice WITH 0 FI
+ UNTIL retchar = return OR retchar = escape PER;
+ int (buffer).
+
+input ok : (buffer >= text (von) AND buffer <= text (bis)) OR buffer = text (zusatz).
+
+leseschleife bis left or ret:
+ REP
+ inchar (retchar)
+ UNTIL retchar = return OR retchar = left OR retchar = escape PER.
+
+END PROC get choice;
+
+TEXT PROC inverse (TEXT CONST t):
+ ""15"" + t + " " + ""14""
+END PROC inverse;
+
+PROC put center (TEXT CONST t):
+ put center (t, 80)
+END PROC put center;
+
+PROC put center (INT CONST zeile, TEXT CONST t, BOOL CONST inverse):
+ put center (zeile, t, 80, inverse);
+END PROC put center;
+
+PROC put center (INT CONST zeile, TEXT CONST t):
+ put center (zeile, t, 80)
+END PROC put center;
+
+PROC put center (TEXT CONST t, INT CONST gesamtbreite):
+ INT VAR cy;
+ get cursor (cy, cy);
+ put center (cy, t, gesamtbreite)
+END PROC put center;
+
+PROC put center (INT CONST zeile, TEXT CONST t, INT CONST gesamtbreite):
+ put center (zeile, t, gesamtbreite, FALSE);
+END PROC put center;
+
+PROC put center (INT CONST zeile, TEXT CONST t, INT CONST gesamtbreite,
+ BOOL CONST inverse):
+ IF inverse
+ THEN cursor (1, zeile);
+ out (""15"");
+ gesamtbreite - 2 TIMESOUT " ";
+ FI;
+ cursor ((gesamtbreite - length (t)) DIV 2, zeile);
+ put (t);
+ IF inverse
+ THEN cursor (gesamtbreite - 1, zeile);
+ out (""14"");
+ FI
+END PROC put center;
+
+PROC cl eol:
+ out (""5"")
+END PROC cl eol;
+
+PROC cl eop:
+ out (""4"")
+END PROC cl eop;
+
+PROC cl eol (INT CONST cx, cy):
+ cursor (cx, cy);
+ cl eol
+END PROC cl eol;
+
+PROC cl eop (INT CONST cx, cy):
+ cursor (cx, cy);
+ cl eop
+END PROC cl eop;
+
+INT PROC partition groesse (INT CONST part) :
+ part last track (part) - part first track (part) + 1
+END PROC partition groesse;
+
+BOOL PROC is eumel (INT CONST partition) :
+ part type (partition) >= 69 AND part type (partition) <= 72
+END PROC is eumel;
+
+BOOL PROC partition exists (INT CONST partition) :
+ IF partition > 0 AND partition <= max partitions
+ THEN part type (partition) <> 0
+ ELSE FALSE
+ FI
+END PROC partition exists;.
+
+part groesse : partition groesse (partition).
+
+part name :
+ SELECT part type (partition) OF
+ CASE 1, 4 : "DOS"
+ CASE 69, 70, 71, 72 : "EUMEL"
+ OTHERWISE text (part type (partition))
+ END SELECT.
+
+escaped : retchar = escape.
+
+sure escaped :
+ IF escaped THEN cl eop (1, 20); cursor (1, 22);
+ yes ("Vorgang abbrechen", TRUE)
+ ELSE FALSE
+ FI.
+
+partition gueltig :
+ partition > 0
+ AND partition <= max partitions.
+
+freie zylinder :
+ zylinder - belegte zylinder.
+
+belegte zylinder :
+ help := 0;
+ FOR i FROM 1 UPTO partitions REP
+ help INCR partition groesse (part list (i))
+ PER;
+ help.
+
+keine eumel partition :
+ fehler;
+ put line ("Sie dürfen mit diesem System nur 'EUMEL' - Partitionen manipulieren.");
+ put ("Die Partition " + text (partition) + " ist nicht vom Typ 'EUMEL' !").
+
+fehler :
+ cl eop (1, 20);
+ put (""7"" + inverse ("FEHLER :")); line (2).
+
+loesche eingabepuffer :
+ REP UNTIL incharety = "" PER. ;
+
+PROC logo :
+ page;
+ put center (3, "S E T U P - E U M E L "+ setup version);
+ put center (5, "für");
+ put center (7, "M O D U L - S H A R D");
+ put center (13, "======================================================");
+ put center (15, "(für IBM " + typ + " und Kompatible)");
+ put center (20, stand);
+ pause (50);
+ collect heap garbage.
+
+typ :
+ IF at version THEN "AT" ELSE "XT" FI.
+END PROC logo;
+
+END PACKET setup eumel;
+
+setup eumel
+
+
+
+
+
+
+
diff --git a/system/setup/3.1/src/setup eumel erzeugen b/system/setup/3.1/src/setup eumel erzeugen
new file mode 100644
index 0000000..7a50898
--- /dev/null
+++ b/system/setup/3.1/src/setup eumel erzeugen
@@ -0,0 +1,15 @@
+check off;
+insert("setup eumel -1: mini eumel dummies");
+insert("setup eumel 0: /S");
+insert("setup eumel 1: basisoperationen");
+insert("setup eumel 2: modulzugriffe");
+insert("setup eumel 3: modulkonfiguration");
+insert("setup eumel 5: partitionierung");
+insert("setup eumel 6: shardmontage");
+insert("setup eumel 7: setupeumel");
+putline("Jetzt 'setup eumel endlos' nicht vergessen");
+
+
+
+
+
diff --git a/system/setup/3.1/src/setup eumel erzeugen-M b/system/setup/3.1/src/setup eumel erzeugen-M
new file mode 100644
index 0000000..ad85301
--- /dev/null
+++ b/system/setup/3.1/src/setup eumel erzeugen-M
@@ -0,0 +1,14 @@
+check off;
+insert("setup eumel 0: /M");
+insert("setup eumel 1: basisoperationen");
+insert("setup eumel 2: modulzugriffe");
+insert("setup eumel 3: modulkonfiguration");
+insert("setup eumel 5: partitionierung");
+insert("setup eumel 6: shardmontage");
+insert("setup eumel 7: setupeumel");
+putline("Jetzt 'setup eumel endlos' nicht vergessen");
+
+
+
+
+
diff --git a/system/setup/3.1/src/shget.exe b/system/setup/3.1/src/shget.exe
new file mode 100644
index 0000000..902d697
--- /dev/null
+++ b/system/setup/3.1/src/shget.exe
Binary files differ