summaryrefslogtreecommitdiff
path: root/system/net/1.8.7/src
diff options
context:
space:
mode:
Diffstat (limited to 'system/net/1.8.7/src')
-rw-r--r--system/net/1.8.7/src/basic net1148
-rw-r--r--system/net/1.8.7/src/net files-M5
-rw-r--r--system/net/1.8.7/src/net hardware interface389
-rw-r--r--system/net/1.8.7/src/net inserter145
-rw-r--r--system/net/1.8.7/src/net manager797
-rw-r--r--system/net/1.8.7/src/net report41
-rw-r--r--system/net/1.8.7/src/netz20
-rw-r--r--system/net/1.8.7/src/port server164
-rw-r--r--system/net/1.8.7/src/printer server99
-rw-r--r--system/net/1.8.7/src/spool cmd112
-rw-r--r--system/net/1.8.7/src/spool manager915
11 files changed, 3835 insertions, 0 deletions
diff --git a/system/net/1.8.7/src/basic net b/system/net/1.8.7/src/basic net
new file mode 100644
index 0000000..c5e9278
--- /dev/null
+++ b/system/net/1.8.7/src/basic net
@@ -0,0 +1,1148 @@
+PACKET basic net DEFINES (* D. Heinrichs *)
+ (* Version 10 (!) *) (* 18.02.87 *)
+ nam, (* 03.06.87 *)
+ max verbindungsnummer, (* *)
+ neuer start,
+ neue routen,
+ packet eingang,
+ neue sendung,
+ zeitueberwachung,
+ verbindung,
+ loesche verbindung:
+
+TEXT PROC nam (TASK CONST t):
+ IF t = collector THEN name (t)
+ ELIF station (t) <> station (myself)
+ THEN "** fremd "+text(station(t))+" **"
+ ELSE name (t)
+ FI
+END PROC nam;
+
+INT PROC tasknr (TASK CONST t):
+ IF t = collector THEN maxtasks
+ ELSE index (t)
+ FI
+END PROC tasknr;
+
+LET
+ maxtasks = 127,
+ maxstat = 127,
+ max strom = 20,
+ max strom 1 = 21,
+ stx = ""2"",
+ code stx = 2,
+ error nak = 2,
+ seiten groesse = 512,
+ dr verwaltungslaenge = 8,
+ dr verwaltungslaenge2=10,
+ openlaenge = 24,
+ vorspannlaenge = 14,
+ ack laenge = 12,
+ min data length = 64,
+ (* Codes der Verbindungsebene *)
+
+ task id code = 6,
+ name code = 7,
+ task info code = 8,
+ routen liefern code = 9,
+
+ (* Typen von Kommunikationsströmen *)
+
+ send wait = 0,
+ zustellung = 1,
+ call pingpong = 2,
+ call im wait = 3,
+ call im abbruch = 4,
+ call in zustellung = 5,
+
+ (*quittungscodes*)
+
+ ok = 0,
+ von vorne = 1,
+ wiederhole = 2,
+ loesche = 3,
+ beende = 4;
+
+LET STEUER =
+ STRUCT (
+ INT head,
+ zwischenziel,
+ zielrechner,
+ quellrechner,
+ strom,
+ sequenz,
+ seitennummer,
+ TASK quelle,ziel,
+ INT sende code);
+
+BOUND STEUER VAR open block;
+
+BOUND STRUCT (STEUER steuer, INT typ, maxseq) VAR info block;
+
+BOUND STRUCT (
+ INT head,
+ zwischenziel,
+ zielrechner,
+ quellrechner,
+ strom,
+ sequenz,
+ seitennummer) VAR vorspann ;
+
+LET ACK = STRUCT (
+ INT head,
+ zwischenziel,
+ zielrechner,
+ quellrechner,
+ strom,
+ code);
+BOUND ACK VAR ack packet ;
+BOUND ACK VAR transmitted ack packet;
+
+BOUND STRUCT (ROW maxstat INT port,
+ ROW maxstat INT zwischen) VAR route;
+
+INT CONST max verbindungsnummer := max strom;
+INT VAR codet,net mode, nutzlaenge := data length,
+ data len via node := data length via node;
+
+TEXT VAR buffer first;
+
+DATASPACE VAR work space := nilspace;
+DATASPACE VAR transmitted ack space := nilspace;
+
+
+INT VAR pakete pro seite,
+ pakete pro seite minus 1,
+ packets per page via node,
+ packets per page via node minus 1,
+ datenpacketlaenge via node,
+ datenpacketlaenge ;
+
+INT VAR strom;
+INT VAR last data := -1;
+INT VAR own:=station (myself) ,
+ quit max := 3,
+ quit zaehler := 3,
+ own256 := 256*own;
+INT CONST stx open := code stx+256*openlaenge,
+ stx quit := code stx+256*acklaenge;
+
+ STEUER VAR opti;
+ ROW maxstrom1 STEUER VAR verbindungen;
+ ROW maxstrom1 DATASPACE VAR netz dr;
+ ROW maxstrom1 INT VAR zeit, typ, open try;
+ FOR strom FROM 1 UPTO maxstrom1 REP vdr := nilspace; forget (vdr) PER;
+ ROW maxstrom INT VAR dr page ;
+ ROW maxtasks INT VAR alter call;
+
+.vx : verbindungen (strom).
+
+vdr: netz dr (strom).
+
+ via node:
+ vx.zielrechner <= 0 OR vx.quellrechner <= 0 OR
+ transmit via node OR receive via node.
+
+ transmit via node:
+ route.zwischen (vx.zielrechner) <> vx.zielrechner AND vx.zielrechner <> own.
+
+ receive via node:
+ route.zwischen (vx.quellrechner) <> vx.quellrechner AND vx.quellrechner <> own.
+
+falsche stromnummer: strom < 1 OR strom > maxstrom.
+
+zielrechner ok: vorspann.zielrechner > 0 AND vorspann.zielrechner <= maxstat.
+
+quellrechner ok: vorspann.quellrechner > 0
+ AND vorspann.quellrechner <= maxstat.
+
+call aufruf: typ(strom) >= call pingpong.
+
+alles raus: vx.seitennummer = -1 AND letztes packet der seite .
+
+letztes packet der seite :
+(vx.sequenz AND packets per page minus 1) = packets per page minus 1.
+
+neue verbindung: code t = open laenge.
+
+PROC neue routen:
+ route := old ("port intern");
+END PROC neue routen;
+
+PROC neuer start (INT CONST empfangsstroeme, mode):
+ net mode := mode;
+ strom := 1;
+ neue routen;
+ transmitted ack space := nilspace;
+ workspace := nilspace;
+ open block := workspace;
+ info block := workspace;
+ nutzlaenge := data length;
+ data len via node := data length via node;
+ pakete pro seite:= seitengroesse DIV nutzlaenge;
+ pakete pro seite minus 1 := pakete pro seite -1;
+ packets per page via node := seitengroesse DIV data len via node;
+ packets per page via node minus 1 := packets per page via node - 1;
+ datenpacketlaenge := vorspannlaenge + nutzlaenge;
+ datenpacketlaenge via node := vorspannlaenge + data len via node;
+ vorspann := workspace;
+ ack packet := workspace;
+ transmitted ack packet := transmitted ack space;
+ FOR strom FROM 1 UPTO maxstrom1 REP
+ vx.strom := 0; forget (vdr)
+ PER;
+ INT VAR i;
+ FOR i FROM 1 UPTO maxtasks REP alter call (i) := 0 PER;
+ quitmax := empfangsstroeme;
+ own:=station (myself);
+ quit zaehler := quit max;
+ own256 := 256*own;
+ reset box (net mode);
+ buffer first := "";
+ flush buffers;
+ INT VAR err;
+ fehlermeldung ruecksetzen.
+
+ fehlermeldung ruecksetzen:
+ control (12,0,0,err).
+
+END PROC neuer start;
+
+DATASPACE PROC verbindung (INT CONST nr):
+ INT VAR memory := strom;
+ strom := nr;
+ infoblock.steuer := verbindungen (nr);
+ infoblock.typ := typ (nr);
+ infoblock.maxseq := dspages (netzdr(nr)) * packets per page;
+ strom := memory;
+ workspace
+END PROC verbindung;
+
+PROC neue sendung (TASK CONST q,z, INT CONST cod,z stat, DATASPACE CONST dr):
+
+ naechste verbindung vorbereiten;
+ forget (vdr); vdr := dr;
+ sendung starten (q, z, z stat, cod)
+END PROC neue sendung;
+
+PROC zeitueberwachung
+ (INT VAR snr, TASK VAR q, z, INT VAR ant,DATASPACE VAR dr):
+ snr INCR 1;
+ FOR strom FROM snr UPTO maxstrom REP zeitkontrolle PER;
+ snr := 0.
+
+zeitkontrolle:
+ IF vx.strom <> 0 AND zeit(strom) > 0
+ THEN
+ zeit(strom) DECR 1;
+ IF sendung noch nicht zugestellt
+ THEN
+ IF zeit(strom) = 0
+ THEN
+ empfangsreport ("Nicht zustellbar. ");
+ loesche verbindung (strom)
+ ELSE
+ snr := strom;
+ q := vx.quelle;
+ z := vx.ziel;
+ ant := vx.sendecode;
+ dr := vdr;
+ LEAVE zeitueberwachung
+ FI
+ ELIF zeit(strom) = 0
+ THEN wiederholen
+ FI
+ FI.
+
+sendung noch nicht zugestellt:
+ typ (strom) = zustellung.
+
+wiederholen:
+ IF sendeeintrag
+ THEN
+ sendung wiederholen
+ ELSE
+ empfangseintrag freigeben
+ FI.
+
+sendeeintrag : vx.quellrechner = own .
+
+sendung wiederholen:
+ IF wiederholung noch sinnvoll
+ THEN
+ IF frisch
+ THEN
+ time out bei open
+ ELSE
+ datenteil wiederholen
+ FI
+ ELSE
+ sendung loeschen
+ FI.
+
+wiederholung noch sinnvoll:
+ task noch da AND bei call noch im call.
+
+task noch da: vx.quelle = collector OR exists (vx.quelle).
+
+bei call noch im call:
+ IF call aufruf
+ THEN
+ callee (vx.quelle) = vx.ziel
+ ELSE
+ TRUE
+ FI.
+
+frisch: vx.sequenz = -1.
+
+time out bei open:
+ IF vx.sendecode > -4 OR opentry (strom) > 0
+ THEN
+ open wiederholen ;
+ opentry (strom) DECR 1
+ ELSE
+ nak an quelle senden
+ FI.
+
+nak an quelle senden:
+ dr := nilspace;
+ BOUND TEXT VAR erm := dr;
+ erm := "Station "+text(vx.zielrechner)+" antwortet nicht";
+ snr := strom;
+ q := vx.ziel;
+ z := vx.quelle;
+ ant := error nak;
+ sendung loeschen;
+ LEAVE zeitueberwachung .
+
+open wiederholen:
+ sendereport ("wdh open");
+ IF opentry (strom) > 0 THEN zeit(strom) := 4 ELSE zeit(strom) := 40 FI;
+ openblock := vx;
+ openblock.head := stx open;
+ ab die post.
+
+datenteil wiederholen:
+ sendereport ("wdh data. sqnr "+text (vx.sequenz));
+ senden .
+
+empfangseintrag freigeben:
+ IF antwort auf call
+ THEN
+ weiter warten
+ ELSE
+ empfangsreport ("Empfangseintrag freigegeben");
+ loesche verbindung (strom)
+ FI.
+antwort auf call: callee (vx.ziel) = vx.quelle.
+
+weiter warten: zeit (strom) := 400.
+
+END PROC zeitueberwachung;
+
+PROC sendereport (TEXT CONST txt):
+ report (text (strom)+":"+txt+". Absender: """+nam (vx.quelle)+
+ """. Ziel "+text(vx.zielrechner) + " Taskindex: " +
+ text (index (vx.ziel)));
+END PROC sendereport;
+
+PROC empfangsreport (TEXT CONST txt):
+ report (text (strom)+":"+txt+". Empfänger: """
+ +nam (vx.ziel)+""". Quelle "+text (vx.quellrechner) +
+ " Taskindex: " + text (index (vx.quelle)));
+END PROC empfangsreport ;
+
+PROC sendung loeschen:
+ strom loeschen (tasknr (vx.quelle))
+END PROC sendung loeschen;
+
+PROC strom loeschen (INT CONST tasknr):
+ IF callaufruf CAND alter call (tasknr ) = strom
+ THEN
+ alter call (tasknr ) := 0
+ FI;
+ vx.strom := 0;
+ forget (vdr)
+END PROC strom loeschen;
+
+PROC empfang loeschen:
+ quit zaehler INCR 1;
+ strom loeschen (tasknr (vx.ziel))
+END PROC empfang loeschen;
+
+PROC loesche verbindung (INT CONST nr):
+ strom := nr;
+ IF sendeeintrag
+ THEN
+ sendung loeschen
+ ELSE
+ gegenstelle zum loeschen auffordern;
+ empfang loeschen
+ FI.
+
+gegenstelle zum loeschen auffordern:
+ IF verbindung aktiv THEN quittieren (-loesche) FI.
+
+verbindung aktiv: vx.strom > 0.
+
+sendeeintrag: vx.quellrechner = own .
+
+END PROC loesche verbindung;
+
+PROC weiter senden:
+ IF NOT alles raus
+ THEN
+ sequenz zaehlung;
+ IF neue seite THEN seitennummer eintragen FI;
+ senden
+ FI.
+
+sequenz zaehlung:
+ vx.sequenz INCR 1.
+
+neue seite:
+ IF via node THEN (vx.sequenz AND packets per page via node minus 1) = 0
+ ELSE (vx.sequenz AND pakete pro seite minus 1) = 0
+ FI.
+
+seitennummer eintragen:
+ dr page (strom) := vx.seiten nummer;
+ vx.seitennummer := next ds page (vdr, dr page (strom)).
+
+
+END PROC weiter senden;
+
+.packets per page:
+
+ IF via node THEN packets per page via node
+ ELSE pakete pro seite
+ FI.
+
+packets per page minus 1:
+ IF via node THEN packets per page via node minus 1
+ ELSE pakete pro seite minus 1
+ FI.
+
+used length:
+
+ IF via node THEN data len via node
+ ELSE nutzlaenge
+ FI.
+
+PROC senden:
+ INT VAR nl;
+ zeit(strom) := 6;
+ openblock := vx;
+ nl := used length;
+ transmit header (workspace);
+ vorspann senden;
+ daten senden;
+ transmit trailer.
+
+vorspann senden:
+ blockout (workspace, 1, dr verwaltungslaenge, vorspannlaenge).
+
+daten senden:
+ blockout (vdr,dr page (strom),distanz,nl).
+
+distanz: nl* (vx.sequenz AND packets per page minus 1).
+
+END PROC senden;
+
+PROC naechste verbindung vorbereiten:
+ FOR strom FROM 1 UPTO maxstrom REP
+ UNTIL vx.strom = 0 PER;
+ IF vx.strom <> 0 THEN errorstop ("Verbindungsengpass") FI.
+END PROC naechste verbindung vorbereiten;
+
+PROC sendung starten (TASK CONST quelle, ziel, INT CONST code):
+ sendung starten (quelle,ziel, station(ziel), code)
+END PROC sendung starten;
+
+PROC sendung starten (TASK CONST quelle, ziel, INT CONST ziel station,code):
+ IF ziel station = own
+ THEN
+ report ("Irrläufer: Sendung an eigene Station. Absender:"""+
+ nam (quelle)+""".");
+ vx.strom := 0;
+ forget (vdr)
+ ELSE
+ openblock.ziel := ziel;
+ openblock.quelle :=quelle;
+ openblock.sendecode := code;
+ openblock.zielrechner:= ziel station;
+ openblock.quellrechner :=own;
+ openblock.zwischenziel := route.zwischen (ziel station)+own256;
+ alten call loeschen (quelle);
+ IF call oder ping pong
+ THEN typ (strom) := call pingpong; call merken
+ ELSE typ (strom) := send wait FI;
+ sendung neu starten
+ FI.
+
+call oder pingpong: openblock.ziel = callee (openblock.quelle).
+
+call merken: alter call (tasknr (quelle)) := strom.
+
+END PROC sendung starten;
+
+PROC encode packet length (INT VAR val):
+
+ IF val < 96 THEN
+ ELIF val < 160 THEN val DECR 32
+ ELIF val < 288 THEN val DECR 128
+ ELIF val < 544 THEN val DECR 352
+ ELIF val < 1056 THEN val DECR 832
+ ELIF val < 2080 THEN val DECR 1824
+ FI;
+ rotate (val, 8)
+
+ENDPROC encode packet length;
+
+PROC sendung neu starten:
+ INT VAR value;
+ openblock.head:= stx open;
+ openblock.sequenz := -1;
+ openblock.seitennummer:= next ds page (vdr,-1);
+ openblock.strom := strom;
+ vx := open block;
+ schnelles nak bei routen liefern;
+ ab die post;
+ value := vorspannlaenge + used length;
+ encode packet length (value);
+ vx.head:=code stx+value.
+
+schnelles nak bei routen liefern:
+ IF openblock.sendecode = -routen liefern code
+ THEN
+ openblock.zwischenziel := openblock.zielrechner+own256;
+ zeit(strom) := 2;
+ opentry (strom) := 0
+ ELSE
+ zeit (strom) :=8;
+ opentry (strom) := 2
+ FI.
+
+END PROC sendung neu starten; .
+
+ab die post:
+ transmit header (workspace);
+ block out (work space,1, dr verwaltungslaenge,open laenge);
+ transmit trailer.
+
+PROC alten call loeschen (TASK CONST quelle):
+ IF alter call aktiv
+ THEN
+ INT VAR lstrom := strom;
+ vx:=openblock;
+ strom := alter call (tasknr (quelle));
+ IF in ausfuehrungsphase
+ THEN
+ sendereport ("Call-Löschung vorgemerkt");
+ loeschung vormerken
+ ELSE
+ report ("Call gelöscht."""+nam(quelle)+""". Strom "+text(strom));
+ loesche verbindung (strom)
+ FI;
+ strom := lstrom;
+ openblock := vx
+ FI.
+
+in ausfuehrungsphase:
+ typ(strom) = call im wait OR typ (strom) = call in zustellung.
+
+loeschung vormerken:
+ typ(strom) := call im abbruch;
+ alter call (tasknr (quelle)) := 0.
+
+
+ alter call aktiv:
+ alter call (tasknr (quelle)) > 0.
+
+END PROC alten call loeschen;
+
+PROC packet eingang
+ ( INT VAR snr, TASK VAR q, z, INT VAR ant,DATASPACE VAR dr):
+ snr := 0;
+ fehlertest;
+ vorspann holen;
+ IF NOT ring logik THEN daten teil FI.
+
+ring logik: FALSE.
+
+fehlertest:
+#
+ INT VAR c12;
+ control (12,0,0,c12);
+ IF c12 <> 0
+ THEN
+ flush buffers;
+ report ("E/A-Fehler "+text (c12));
+ control (12,0,0,c12);
+ LEAVE packet eingang
+ FI.
+
+ #.
+
+vorspann holen:
+ sync;
+ IF NOT blockin (workspace, 1, dr verwaltungslaenge2, block laenge)
+ THEN LEAVE packeteingang
+ FI.
+
+
+blocklaenge: IF code t > min data length
+ THEN
+ vorspannlaenge-2
+ ELSE
+ code t -2
+ FI.
+
+sync:
+ IF NOT packet start already inspected
+ THEN
+ TEXT VAR skipped, t:= "";
+ skipped := next packet start;
+ IF skipped = "" THEN LEAVE packet eingang FI;
+ t := incharety (1);
+ code t := code (t);
+ ELSE
+ skipped := buffer first;
+ buffer first := "";
+ t := incharety (1);
+ code t := code (t);
+ FI;
+ decode packet length;
+IF skipped=stx AND laenge ok THEN LEAVE sync FI;
+ REP
+ skipped CAT t;
+ t := incharety (1); (* next character *)
+ IF t = "" THEN
+ report ("skipped",skipped);
+ LEAVE packet eingang
+ FI ;
+ codet := code (t);
+ UNTIL blockanfang OR length (skipped) > 200 PER;
+ decode packet length;
+ IF skipped <> stx THEN report ("skipped bei sync:", skipped) FI.
+
+decode packet length:
+
+IF code t < 96 THEN
+ ELIF code t < 128 THEN code t INCR 32
+ ELIF code t < 160 THEN code t INCR 128
+ ELIF code t < 192 THEN code t INCR 352
+ ELIF code t < 224 THEN code t INCR 832
+ ELIF code t < 256 THEN code t INCR 1824
+FI.
+
+packet start already inspected: buffer first <> "".
+
+blockanfang:
+ (skipped SUB length(skipped)) = stx AND laenge ok.
+
+laenge ok:
+ (codet = datenpacketlaenge OR codet = datenpacketlaenge via node
+ OR codet = ack laenge OR code t = openlaenge).
+
+zielnummer: vorspann.zielrechner.
+
+daten teil:
+ IF zielnummer = own
+ THEN
+ ziel erreicht (openblock,snr,q,z,ant,dr)
+ ELSE
+ weiter faedeln
+ FI.
+
+weiter faedeln:
+ INT VAR value;
+ IF zielrechner ok
+ THEN
+ IF neue verbindung
+ THEN
+ IF (openblock.sendecode = -routenlieferncode) OR NOT route ok
+ THEN LEAVE packet eingang
+ FI
+ FI;
+ value := code t;
+ encode packet length (value);
+ vorspann.head := code stx + value;
+ vorspann.zwischenziel := own256 + route.zwischen (vorspann.zielrechner);
+ nutzdaten einlesen;
+ dr := workspace;
+ snr := 1000;
+ ant := zielnummer
+ FI.
+
+nutzdaten einlesen:
+ IF code t > data len via node
+ THEN
+ IF NOT blockin (workspace, 1, drverwaltungslaenge+vorspannlaenge, data len via node)
+ THEN
+ LEAVE packeteingang
+ FI;
+ IF NOT next packet ok THEN LEAVE packeteingang FI
+ FI.
+
+END PROC packet eingang;
+
+PROC ziel erreicht (STEUER CONST prefix,
+ INT VAR snr, TASK VAR q, z, INT VAR ant,DATASPACE VAR dr):
+ last data := -1;
+ IF NOT quellrechner ok
+ THEN
+ report ("Quellrechner "+text(prefix.quellrechner));
+ LEAVE ziel erreicht
+ FI;
+ IF neue verbindung
+ THEN
+ IF NOT route ok OR NOT quelltask ok
+ THEN report ("verbotene Route: " + text (prefix.quellrechner));
+ LEAVE ziel erreicht
+ FI;
+ verbindung bereitstellen
+ ELIF quittung
+ THEN
+ strom := ack packet.strom;
+ IF falsche stromnummer THEN report ("Strom falsch in Quittung");
+ LEAVE ziel erreicht FI;
+ IF vx.strom = 0 THEN LEAVE ziel erreicht FI;
+ IF ackpacket.code >= ok THEN weiter senden
+ ELIF NOT route ok THEN
+ sendereport ("verbotene Route bei Quittung");
+ LEAVE ziel erreicht
+ ELIF ackpacket.code = -von vorne THEN
+ sendereport ("Neustart");
+ openblock := vx;
+ sendung neu starten
+ ELIF ackpacket.code = -wiederhole THEN back 16
+ ELIF ackpacket.code = -loesche THEN fremdloeschung
+ ELIF ackpacket.code = -beende AND alles raus THEN strom abschliessen
+ FI
+ ELIF verbindung festgestellt
+ THEN
+ zeit(strom) := 400;
+ opti := vx;
+ datenpacket
+ ELSE
+ strom := maxstrom1;
+ vx:=prefix;
+ report ("Daten ohne Eroeffnung von " +text(prefix.quellrechner)
+ +" Sequenznr "+text(prefix.sequenz));
+ daten entfernen (used length);
+ IF alles raus THEN quittieren (-beende) ELSE quittieren(-von vorne) FI
+ FI.
+
+quelltask ok:
+ prefix.quelle = collector OR antwort auf routen liefern
+ OR station (prefix.quelle) = prefix.quellrechner.
+
+antwort auf routen liefern: prefix.quelle = myself.
+
+verbindung bereitstellen:
+ IF (prefix.sendecode < 0 OR station (prefix.ziel) = own)
+ AND quellrechner ok
+ THEN
+ freie verbindungsnummer;
+ vdr := nilspace;
+ vx := open block;
+ zeit(strom) := 30;
+ quittieren falls genug pufferplatz;
+ vx.sequenz := 0 ;
+ opti := vx;
+ dr page (strom) :=-2;
+ IF abschluss THEN rueckmeldung FI
+ FI.
+
+loeschung vorgemerkt: typ(strom) = call im abbruch.
+
+strom abschliessen:
+ IF call aufruf
+ THEN
+ wdh data vor ablauf der zustellversuche bei der gegenstation;
+ ausfuehrungsphase merken
+ ELSE
+ wdh data sperren
+ FI.
+
+wdh data sperren:
+ zeit (strom) := 12000.
+
+wdh data vor ablauf der zustellversuche bei der gegenstation:
+ zeit (strom) := 80.
+
+ausfuehrungsphase merken: typ(strom) := call in zustellung.
+
+back16:
+ datenraum etwas rueckspulen;
+ opentry (strom) := 2;
+ nicht sofort senden (* wegen vagabundierender Quittungen *).
+
+nicht sofort senden: zeit(strom) := 2.
+
+datenraum etwas rueckspulen:
+ INT VAR pps := packets per page ;
+ sendereport ("etwas rueckgespult");
+ INT VAR vs :=-1;
+ dr page (strom) := -1;
+ INT VAR i;
+ FOR i FROM 1 UPTO vx.sequenz DIV pps - etwas REP
+ vs INCR pps;
+ dr page (strom) := next ds page (vdr, dr page (strom))
+ PER;
+ vx.seiten nummer := next ds page (vdr, dr page (strom)) ;
+ vx.sequenz := vs.
+
+etwas: 3.
+
+fremdloeschung:
+ IF fremdrechner ok und sendung
+ THEN
+ IF typ (strom) = call in zustellung
+ THEN
+ typ (strom) := call im wait
+ ELSE
+ IF NOT alles raus
+ THEN
+ sendereport ("Sendung von Gegenstelle geloescht")
+ FI;
+ sendung loeschen
+ FI
+ FI.
+
+fremdrechner ok und sendung:
+ ackpacket.quellrechner = vx.zielrechner .
+
+
+quittieren falls genug pufferplatz:
+ IF quit zaehler > 0 THEN
+ quit zaehler DECR 1;
+ open quittieren;
+ block vorab quittieren
+ ELSE
+ quittieren (-wiederhole)
+ FI.
+
+open quittieren: quittieren (ok).
+block vorab quittieren:
+ IF prio (myself) < 3 THEN quittieren (ok) FI.
+
+quittung: code t <= ack laenge.
+
+
+verbindung festgestellt:
+ FOR strom FROM maxstrom DOWNTO 1 REP
+ IF bekannter strom
+ THEN LEAVE verbindung festgestellt WITH TRUE FI
+ PER;
+ FALSE.
+
+bekannter strom:
+ vx.strom = prefix.strom AND vom selben rechner.
+
+vom selben rechner:
+ vx.quellrechner = prefix.quellrechner.
+
+daten:
+ IF neue seite da THEN check for valid pagenr;
+ dr page(strom) := prefix.seitennummer;
+ ELIF prefix.seitennummer < dr page(strom)
+ THEN empfangsreport ("Falsche Seitennummer, Soll: " +
+ text(drpage(strom)) + " ist: " +
+ text (prefix.seitennummer)
+ + " bei Sequenznr: " +
+ text(prefix.sequenz));
+ flush buffers;
+ quittieren (- wiederhole);
+ LEAVE ziel erreicht
+ FI;
+ sequenz zaehlung;
+ IF neue seite kommt
+ THEN
+ vx.seiten nummer := prefix.seiten nummer;
+ dr page(strom) := prefix.seitennummer;
+ FI;
+ quittieren(ok);
+ IF NOT blockin (vdr, opti.seiten nummer, distanz, nl)
+ COR NOT next packet ok
+ THEN quittieren (-wiederhole);
+ LEAVE ziel erreicht
+ FI;
+ last data := strom.
+
+check for valid pagenr:
+ IF prefix.seitennummer < dr page(strom) AND prefix.seitennummer > -1
+ THEN report ("Absteigende Seitennummern, alt: " + text(drpage(strom))+
+ " neu: "+ text(prefix.seitennummer) + " Seq.nr: " +
+ text(vx.sequenz) ) ;
+ flush buffers;
+ quittieren (- von vorne);
+ LEAVE ziel erreicht;
+ FI.
+
+datenpacket:
+ INT VAR nl := used length;
+ INT VAR pps1 := packets per page minus 1;
+ IF sendung wartet auf zustellung THEN auffrischen ELSE daten holen FI.
+
+sendung wartet auf zustellung: typ (strom) = zustellung.
+
+auffrischen: zeit (strom) := 200; daten entfernen (nl).
+
+daten holen:
+ IF opti.sequenz >= prefix.sequenz AND opti.sequenz < prefix.sequenz+100
+ AND prefix.sequenz >= 0
+ THEN
+ IF opti.sequenz <> prefix.sequenz
+ THEN empfangsreport ("Sequenzreset von "+text(opti.sequenz)+" auf "+
+ text (prefix.sequenz));
+ vx.sequenz := prefix.sequenz;
+ IF pagenumber ok
+ THEN dr page (strom) := prefix.seitennummer
+ ELSE empfangsreport ("Blocknummer falsch, neu: "+
+ text (prefix.seitennummer) + ", alt : " +
+ text (drpage(strom)) );
+ FI;
+ vorabquittung regenerieren
+ FI;
+ daten ;
+ IF abschluss THEN rueckmeldung FI;
+ ELSE
+ empfangsreport ("Sequenzfehler: soll "+text(vx.sequenz)+" ist "+
+ text(prefix.sequenz));
+ quittieren (-wiederhole);
+ daten entfernen (nl)
+ FI.
+
+pagenumber ok:
+ dr page (strom) >= prefix.seitennummer .
+
+rueckmeldung:
+ snr := strom;
+ q := vx.quelle;
+ z := vx.ziel;
+ ant := vx.sendecode;
+ dr := vdr;
+ LEAVE ziel erreicht.
+
+vorabquittung regenerieren:
+ IF prio (myself) < 3
+ THEN
+ quittieren (ok)
+ FI.
+
+distanz: (opti.sequenz AND pps1 ) * nl.
+
+sequenz zaehlung:
+ vx.sequenz INCR 1.
+
+neue seite da:
+ neue seite kommt.
+
+neue seite kommt:
+(vx.sequenz AND pps1) = 0.
+
+freie verbindungsnummer:
+ INT VAR h strom :=maxstrom1, cstrom := 0;
+ FOR strom FROM 1 UPTO maxstrom REP
+ IF vx.strom = 0 THEN h strom := strom ;
+ typ(strom) := send wait
+ ELIF bekannter strom
+ THEN empfangsreport ("Reopen");
+ quit zaehler INCR 1;
+ IF typ (strom) = zustellung THEN typ (strom) := send wait FI;
+ forget (vdr);
+ LEAVE freie verbindungsnummer
+ ELIF antwort auf call
+ THEN
+ IF loeschung vorgemerkt
+ THEN
+ vx := prefix;
+ loesche verbindung (strom);
+ LEAVE ziel erreicht
+ FI;
+ cstrom := strom;
+ typ (strom) := call pingpong;
+ forget (vdr);
+ FI
+ PER;
+ IF cstrom > 0 THEN strom := cstrom ELSE strom := h strom FI;
+ IF strom = maxstrom1 THEN
+ vx:=prefix;
+ empfangsreport ("Verbindungsengpass");
+ quittieren (-wiederhole);
+ LEAVE ziel erreicht
+ FI.
+
+antwort auf call:
+ prefix.sendecode >= 0 AND
+ call aufruf AND vx.quelle = prefix.ziel AND vx.ziel = prefix.quelle.
+
+END PROC ziel erreicht;
+
+PROC daten entfernen (INT CONST wieviel):
+ BOOL VAR dummy ;
+ dummy:=blockin (workspace, 2, 0, wieviel)
+END PROC daten entfernen;
+
+BOOL PROC route ok:
+ INT VAR zwischenquelle := vorspann.zwischenziel DIV 256,
+ endquelle := vorspann.quellrechner;
+ zwischenquelle abgleichen;
+ endquelle abgleichen;
+ TRUE.
+
+zwischenquelle abgleichen:
+ IF NOT zwischenroute gleich
+ THEN
+ IF NOT zwischenabgleich erlaubt THEN LEAVE route ok WITH FALSE FI;
+ route.port (zwischenquelle) := channel;
+ route.zwischen (zwischenquelle) := zwischenquelle;
+ abgleich (zwischenquelle, zwischenquelle)
+ FI.
+
+zwischenabgleich erlaubt: route.port (zwischenquelle) < 256.
+
+endquelle abgleichen:
+ IF NOT endroute gleich
+ THEN
+ IF NOT endabgleich erlaubt THEN LEAVE route ok WITH FALSE FI;
+ route.port (endquelle) := channel;
+ route.zwischen (endquelle) := zwischenquelle;
+ abgleich (endquelle, zwischenquelle)
+ FI.
+
+endabgleich erlaubt: route.port (endquelle) < 256.
+
+zwischenroute gleich:
+ (route.port (zwischenquelle) AND 255) = channel
+ AND
+ route.zwischen (zwischenquelle) = zwischenquelle.
+
+endroute gleich:
+ (route.port (endquelle) AND 255) = channel
+ AND
+ route.zwischen (endquelle) = zwischenquelle.
+
+END PROC route ok;
+
+BOOL PROC abschluss:
+
+ last data := -1;
+ IF neue seite kommt AND vx.seiten nummer = -1
+ THEN
+ quittieren (-beende);
+ an ziel weitergeben
+ ELSE
+ FALSE
+ FI.
+neue seite kommt:
+(vx.sequenz AND packets per page minus 1) = 0.
+
+an ziel weitergeben:
+ IF tasknummerfrage THEN taskfrage beantworten ;pufferplatz ; FALSE
+ ELIF tasknamenfrage THEN name senden ;pufferplatz ; FALSE
+ ELIF taskinfofrage THEN task info senden;pufferplatz ; FALSE
+ ELIF routenfrage THEN routen senden; pufferplatz; FALSE
+ ELSE senden ; TRUE
+ FI.
+
+pufferplatz : quitzaehler INCR 1 .
+
+senden:
+ IF callaufruf
+ THEN
+ ein versuch (* bei Antwort auf Call muß ein Zustellversuch reichen *)
+ ELSE
+ max 100 versuche;
+ typ (strom) := zustellung
+ FI.
+
+tasknummerfrage:opti.sendecode = -taskid code.
+
+tasknamenfrage: opti.sendecode = -name code.
+
+taskinfofrage: opti.sendecode = -task info code.
+
+routenfrage: opti.sendecode = -routen liefern code.
+
+max 100 versuche: zeit(strom) := 100.
+
+ein versuch: zeit (strom) := 1.
+
+taskfrage beantworten:
+ disable stop;
+ BOUND TEXT VAR tsk := vdr;
+ TEXT VAR save tsk := tsk;
+ forget (vdr); vdr := nilspace;
+ BOUND TASK VAR task id := vdr;
+ task id := task(save tsk);
+ IF is error THEN
+ clear error; enable stop;
+ forget (vdr); vdr := nilspace;
+ BOUND TEXT VAR errtxt := vdr;
+ errtxt := text(own)+"/"""+save tsk+""" gibt es nicht";
+ sendung starten (collector, opti.quelle, 2)
+ ELSE
+ enable stop;
+ sendung starten (collector, opti.quelle, 0)
+ FI.
+
+name senden:
+ quittieren (-loesche);
+ forget (vdr); vdr := nilspace;
+ tsk := vdr;
+ tsk := nam (opti.ziel);
+ sendung starten (collector, opti.quelle, 0).
+
+routen senden:
+ forget (vdr); vdr := old ("port intern");
+ sendung starten (opti.ziel, opti.quelle, 0).
+
+task info senden:
+ disable stop;
+ BOUND INT VAR ti code := vdr;
+ INT VAR ti cd := ti code;
+ forget (vdr); vdr := nilspace;
+ FILE VAR task inf := sequential file (output,vdr);
+ head line (task inf,"Station "+text(own));
+ task info (ti cd, task inf);
+ IF is error
+ THEN
+ forget (vdr); vdr := nilspace;
+ errtxt := vdr;
+ errtxt := errormessage;
+ clear error;
+ sendung starten (collector, opti.quelle, 2)
+ ELSE
+ sendung starten (collector,opti.quelle,0)
+ FI;
+ enable stop
+END PROC abschluss ;
+
+PROC quittieren(INT CONST code) :
+ INT VAR quell := vx.quellrechner ;
+ transmitted ackpacket := ACK:(stx quit, route.zwischen (quell)+own256, quell, own,
+ vx.strom, code);
+ transmit header (transmitted ack space);
+ blockout (transmitted ack space,1,dr verwaltungslaenge, ack laenge);
+ transmit trailer;
+END PROC quittieren;
+
+BOOL PROC next packet ok:
+ buffer first := next packet start;
+ buffer first = "" COR normal packet start.
+
+normal packet start:
+ IF buffer first = stx
+ THEN
+ TRUE
+ ELSE
+ buffer first := ""; flush buffers; FALSE
+ FI.
+
+END PROC next packet ok;
+END PACKET basic net;
+
+
diff --git a/system/net/1.8.7/src/net files-M b/system/net/1.8.7/src/net files-M
new file mode 100644
index 0000000..ae6f9f3
--- /dev/null
+++ b/system/net/1.8.7/src/net files-M
@@ -0,0 +1,5 @@
+net report
+net hardware interface
+basic net
+net manager
+
diff --git a/system/net/1.8.7/src/net hardware interface b/system/net/1.8.7/src/net hardware interface
new file mode 100644
index 0000000..4e3466a
--- /dev/null
+++ b/system/net/1.8.7/src/net hardware interface
@@ -0,0 +1,389 @@
+PACKET net hardware
+
+(************************************************************************)
+(**** Netzprotokoll Anpassung *)
+(**** Komplette Version mit BUS Anpassung 10.06.87 *)
+(**** mit I/0 Controls fuer integrierte Karten *)
+(**** Verschiedene Nutztelegrammgrössen *)
+(**** Version: GMD 2.0 A.Reichpietsch *)
+(************************************************************************)
+
+ DEFINES
+ blockin,
+ blockout,
+ set net mode,
+ net address,
+ mode text,
+ data length,
+ data length via node,
+ decode packet length,
+ next packet start,
+ flush buffers,
+ transmit header,
+ transmit trailer,
+ version,
+ reset box,
+ max mode,
+ net mode:
+
+
+
+
+ LET eak prefix laenge = 6,
+ packet length before stx = 14 (*eth header =14 *),
+ maximum mode nr = 12,
+ stx = ""2"",
+ niltext = "",
+ null = "0",
+ hex null = ""0"",
+ blank = " ",
+ eak prefix = ""0""0""0""0"",
+ typefield = "EU",
+ prefix adresse = "BOX",
+ second prefix adresse = ""0"BOX",
+ second address type bound = 90;
+
+ INT CONST data length via node :: 64;
+ TEXT CONST version :: "GMD 2.0 (10.6.87)";
+
+
+ TEXT VAR own address;
+ INT VAR paketlaenge, eumel paket laenge, mode, rahmenlaenge, actual data length;
+
+BOOL PROC blockin (DATASPACE VAR ds, INT CONST seite, abstand, laenge):
+ INT VAR hilfslaenge:=laenge, code:= abstand+laenge+512;
+ REAL VAR time out := clock (1) + 10.0;
+ REP
+ blockin (ds,seite,code-hilfslaenge, hilfslaenge, hilfslaenge);
+ UNTIL hilfslaenge = 0 OR clock (1) > time out PER ;
+ IF hilfslaenge <> 0
+ THEN report ("blockin abbruch, fehlende Zeichen: "+text(hilfslaenge));
+ FI;
+ hilfslaenge = 0
+END PROC blockin;
+
+PROC blockout (DATASPACE CONST ds, INT CONST seite, abstand, laenge):
+ INT VAR hilfslaenge:=laenge, code:= abstand+laenge+512;
+ REP
+ blockout (ds,seite,code-hilfslaenge, hilfslaenge, hilfslaenge);
+ UNTIL hilfslaenge = 0 PER
+END PROC blockout;
+
+PROC set net mode (INT CONST new mode):
+ mode := new mode ;
+ own address := net address (station(myself));
+ SELECT mode OF
+ CASE 1,3 : set data length (64);
+ CASE 2 : std framelength; set data length (64)
+ CASE 4,6 : set data length (128)
+ CASE 5 : std framelength; set data length (128)
+ CASE 7,9 : set data length (256)
+ CASE 8 : std framelength; set data length (256)
+ CASE 10,12 : set data length (512)
+ CASE 11 : std framelength; set data length (512);
+
+ OTHERWISE
+ END SELECT.
+
+ std framelength:
+ rahmenlaenge := eak prefix laenge + packet length before stx.
+
+ENDPROC set net mode;
+
+INT PROC max mode:
+ maximum mode nr
+ENDPROC max mode;
+
+INT PROC net mode:
+ mode
+ENDPROC net mode;
+
+TEXT PROC mode text:
+ mode text (mode)
+ENDPROC mode text;
+
+TEXT PROC mode text (INT CONST act mode):
+ SELECT act mode OF
+ CASE 1: "Modus: (1) EUMEL-Netz 64 Byte"
+ CASE 2: "Modus: (2) ETHERNET via V.24 64 Byte"
+ CASE 3: "Modus: (3) ETHERNET integrated 64 Byte"
+ CASE 4: "Modus: (4) EUMEL-Netz 128 Byte"
+ CASE 5: "Modus: (5) ETHERNET via V.24 128 Byte"
+ CASE 6: "Modus: (6) ETHERNET integrated 128 Byte"
+ CASE 7: "MODUS: (7) EUMEL-Netz 256 Byte"
+ CASE 8: "MODUS: (8) ETHERNET via V.24 256 Byte"
+ CASE 9: "MODUS: (9) ETHERNET integrated 256 Byte"
+ CASE 10: "MODUS: (10) EUMEL-Netz 512 Byte"
+ CASE 11: "MODUS: (11) ETHERNET via V.24 512 Byte"
+ CASE 12: "MODUS: (12) ETHERNET integrated 512 Byte"
+ OTHERWISE errorstop ("Modus " + text(mode) + " gibt es nicht");
+ error message
+ END SELECT
+
+ENDPROC mode text;
+
+PROC set data length (INT CONST new data length):
+ actual data length := new data length
+ENDPROC set data length;
+
+INT PROC data length:
+ actual data length
+ENDPROC data length;
+
+PROC reset box (INT CONST net mode):
+ SELECT net mode OF
+ CASE 1,4,7,10 : eumel net box reset
+ CASE 2,5,8,11 : eak reset
+ OTHERWISE controler reset
+ END SELECT.
+
+ eumel net box reset:
+ out (90*""4"");
+ REP UNTIL incharety (1) = niltext PER.
+
+ eak reset:
+ out ("E0"13"E0"13"").
+
+ controler reset:
+ INT VAR dummy;
+ control (-35, 0,0,dummy);
+ control (22,0,0,dummy).
+
+ENDPROC reset box;
+
+PROC remove frame
+ (TEXT VAR erstes zeichen vom eumel telegramm, BOOL VAR kein telegramm da):
+ kein telegramm da := FALSE;
+ SELECT net mode OF
+ CASE 2,5,8,11 : remove ethernet frame
+ (erstes zeichen vom eumel telegramm, kein telegramm da)
+ OTHERWISE
+ END SELECT;
+ENDPROC remove frame;
+
+PROC remove ethernet frame (TEXT VAR string, BOOL VAR schrott):
+ TEXT VAR speicher, t;
+ INT VAR lg;
+
+ t := string;
+ speicher := niltext;
+ WHILE kein stx da REP
+ lies zeichen ein;
+ teste auf timeout;
+ UNTIL textoverflow PER;
+ melde eingelesene zeichen.
+
+ lies zeichen ein:
+ speicher CAT t;
+ t := incharety (1).
+
+ teste auf timeout:
+ IF t = niltext THEN schrott := (speicher <> niltext)
+ CAND not only fill characters;
+ string := niltext;
+ LEAVE remove ethernet frame
+ FI.
+
+ not only fill characters:
+ pos (speicher, ""1"", ""254"",1) <> 0.
+
+ kein stx da :
+ t <> stx.
+
+ textoverflow:
+ length (speicher) > 1000.
+
+ melde eingelesene zeichen:
+ IF kein stx da
+ THEN kein eumeltelegrammanfang
+ ELSE untersuche ethernet header
+ FI.
+
+ kein eumeltelegrammanfang:
+ report ("skipped ,fehlendes <STX> ,letztes Zeichen:", t);
+ string := t;
+ schrott := TRUE.
+
+ untersuche ethernet header:
+ string := t;
+ IF ethernet header inkorrekt
+ THEN melde fehler
+ FI.
+
+ ethernet header inkorrekt:
+ lg := length (speicher);
+ packet zu kurz COR adresse falsch.
+
+ packet zu kurz:
+ lg < packet length before stx.
+
+ adresse falsch:
+ INT VAR adrpos := pos (speicher, own address);
+ zieladresse falsch COR adresse nicht an der richtigen pos .
+
+ zieladresse falsch:
+ adrpos < 1.
+
+ adresse nicht an der richtigen pos:
+ adrpos <> lg - packet length before stx + 1.
+
+ melde fehler:
+ report ("Header inkorrekt eingelesen: ", speicher + t);
+ string := t;
+ schrott := TRUE.
+
+ENDPROC remove ethernet frame;
+
+TEXT PROC next packet start:
+
+ TEXT VAR t := niltext;
+ BOOL VAR schrott := FALSE;
+
+ t:= incharety (1);
+ IF t = niltext THEN LEAVE next packet start WITH niltext
+ ELSE remove frame (t, schrott)
+ FI;
+ IF schrott THEN no stx or niltext
+ ELSE t
+ FI.
+
+ no stx or niltext:
+ IF t = stx THEN "2"
+ ELIF t = niltext THEN "0"
+ ELSE t
+ FI.
+
+ENDPROC next packet start;
+
+PROC flush buffers:
+ REP UNTIL incharety (5) = niltext PER;
+ report ("buffers flushed");
+ENDPROC flush buffers;
+
+PROC transmit header (DATASPACE CONST w):
+ BOUND INT VAR laengeninformation := w;
+ eumel paket laenge := laengeninformation ;
+ decode packet length (eumel paket laenge);
+ SELECT net mode OF
+ CASE 1,4,7,10 :
+ CASE 2,5,8,11 : eak und eth header senden (w)
+ OTHERWISE : telegrammanfang melden;
+ std ethernet header senden (w)
+ END SELECT;
+
+ENDPROC transmit header;
+
+PROC decode packet length (INT VAR decoded length):
+
+ decoded length DECR 2;
+ rotate (decoded length, 8);
+
+ IF decoded length < 96 THEN
+ ELIF decoded length < 128 THEN decoded length INCR 32
+ ELIF decoded length < 160 THEN decoded length INCR 128
+ ELIF decoded length < 192 THEN decoded length INCR 352
+ ELIF decoded length < 224 THEN decoded length INCR 832
+ ELIF decoded length < 256 THEN decoded length INCR 1824
+ FI;
+
+ENDPROC decode packet length;
+
+PROC transmit trailer:
+ INT VAR dummy;
+ SELECT net mode OF
+ CASE 3,6,9,12 : control (21,0,0,dummy)
+ OTHERWISE
+ END SELECT.
+
+ENDPROC transmit trailer;
+
+PROC std ethernet header senden (DATASPACE CONST x):
+ TEXT VAR eth adresse, ethernet kopf := niltext;
+ INT VAR adresse;
+ BOUND STRUCT (INT head, zwischennummern) VAR header := x;
+ zieladresse holen;
+ zieladresse senden;
+ quelladresse senden;
+ typfeld senden;
+ ausgeben.
+
+ zieladresse holen:
+ adresse := header.zwischennummern AND 255;
+ eth adresse := net address (adresse).
+
+ zieladresse senden:
+ ethernetkopf CAT eth adresse.
+
+ quelladresse senden:
+ ethernetkopf CAT own address.
+
+ typfeld senden:
+ ethernetkopf CAT typefield.
+
+ ausgeben:
+ out (ethernetkopf).
+
+ENDPROC std ethernet header senden;
+
+PROC telegrammanfang melden:
+ INT VAR dummy;
+ control (20,eumel paket laenge + packet length before stx,0, dummy).
+
+ENDPROC telegrammanfang melden;
+
+PROC eak und eth header senden (DATASPACE CONST x):
+ TEXT VAR res:= niltext;
+
+ neue laenge berechnen;
+ eak kopf senden;
+ std ethernet header senden (x).
+
+ neue laenge berechnen:
+ paket laenge := rahmenlaenge + eumel paket laenge.
+
+ eak kopf senden:
+ res := code (paket laenge DIV 256);
+ res CAT (code (paket laenge AND 255));
+ res CAT eak prefix;
+ out(res).
+
+ENDPROC eak und eth header senden;
+
+TEXT PROC net address (INT CONST eumel address):
+ TEXT VAR res ;
+ INT VAR low byte;
+
+SELECT mode OF
+ CASE 1,4,7,10 : eumel net address
+ OTHERWISE ethernet address
+END SELECT.
+
+eumel net address:
+ text(eumel address).
+
+ethernet address:
+ IF second adress kind THEN second eth header
+ ELSE first eth header
+ FI;
+ res.
+
+ second adress kind:
+ eumel address = 34 COR
+ eumel address > second address type bound.
+
+ second eth header:
+ low byte := eumel address AND 255;
+ res := second prefix adresse + code (low byte);
+ res CAT hex null.
+
+ first eth header:
+ res := prefix adresse + text (eumel address, 3);
+ changeall (res, blank, null).
+
+ENDPROC net address;
+
+ENDPACKET net hardware;
+
+
+
+
diff --git a/system/net/1.8.7/src/net inserter b/system/net/1.8.7/src/net inserter
new file mode 100644
index 0000000..c89d0f0
--- /dev/null
+++ b/system/net/1.8.7/src/net inserter
@@ -0,0 +1,145 @@
+(*************************************************************************)
+(*** Insertiert alle notwendigen Pakete, die zum Betrieb des Netzes ***)
+(*** notwendig sind. ***)
+(*** Berücksichtigt nur EUMEL - Versionen ab 1.8.1, sowie ***)
+(*** Multi-User-Version ***)
+(*** ***)
+(*** ***)
+(*** 23.05.87 ar ***)
+(*************************************************************************)
+
+LET netfile = "netz",
+ multi files = "net files/M";
+
+
+INT CONST version :: id (0);
+THESAURUS VAR tesa;
+
+head;
+IF no privileged task
+ THEN errorstop (name (myself) + " ist nicht privilegiert!")
+ ELIF station number wrong
+ THEN errorstop ("'define station' vergessen ")
+FI;
+
+IF version < 181 THEN versionsnummer zu klein
+ ELSE install net
+FI.
+
+no privileged task:
+ NOT (myself < supervisor).
+
+station number wrong:
+ station (myself) < 1.
+
+install net :
+ IF NOT exists (netfile)
+ THEN errorstop ("Datei " + netfile +" existiert nicht")
+ FI;
+ IF is multi THEN insert multi net
+ ELSE errorstop ("Diese Netzversion ist nur für Multi-user Versionen freigegeben")
+ FI;
+ forget ("net install", quiet);
+ net start.
+
+net start :
+ say line (" ");
+ do ("start");
+ do ("global manager (PROC (DATASPACE VAR, INT CONST, INT CONST, TASK CONST)
+ net manager)").
+
+is multi :
+ (pcb(9) AND 255) > 1.
+
+insert multi net :
+ hole dateien vom archiv;
+ insert say and forget (tesa).
+
+hole dateien vom archiv :
+ fetch if necessary (multi files);
+ tesa := ALL (multi files);
+ forget (multi files, quiet);
+ fetch if necessary (tesa - all);
+ say line (" ");
+ say line ("Archiv-Floppy kann entnommen werden.");
+ release (archive).
+
+
+head :
+ IF online THEN page;
+ put center (" E U M E L - Netz wird installiert.");
+ line;
+ put center ("----------------------------------------");
+ line (2)
+ FI.
+
+versionsnummer zu klein :
+ errorstop ("Netzsoftware erst ab Version 1.8.1 insertierbar !").
+
+PROC fetch if necessary (TEXT CONST datei) :
+ IF NOT exists (datei) THEN say line ("Loading """ + datei + """...");
+ fetch (datei, archive)
+ FI.
+END PROC fetch if necessary;
+
+PROC fetch if necessary (THESAURUS CONST tes) :
+ do (PROC (TEXT CONST) fetch if necessary, tes)
+END PROC fetch if necessary;
+
+PROC insert say and forget (TEXT CONST name of packet):
+ IF online THEN INT VAR cx, cy;
+ put ("Inserting """ + name of packet + """...");
+ get cursor (cx, cy)
+ FI;
+ insert (name of packet);
+ IF online THEN cl eop (cx, cy); line FI;
+ forget (name of packet, quiet)
+END PROC insert say and forget;
+
+PROC insert say and forget (THESAURUS CONST tes):
+ do (PROC (TEXT CONST) insert say and forget, tes)
+END PROC insert say and forget;
+
+PROC put center (TEXT CONST t):
+ put center (t, xsize);
+END PROC put center;
+
+PROC put center (INT CONST zeile, TEXT CONST t):
+ put center (zeile, t, xsize);
+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):
+ cursor ((gesamtbreite - length (t)) DIV 2, zeile);
+ put (t).
+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;
+
+PROC say line (TEXT CONST t):
+ IF online THEN put line (t) FI
+ENDPROC say line;
+
+
+
diff --git a/system/net/1.8.7/src/net manager b/system/net/1.8.7/src/net manager
new file mode 100644
index 0000000..05f530e
--- /dev/null
+++ b/system/net/1.8.7/src/net manager
@@ -0,0 +1,797 @@
+PACKET net manager DEFINES stop,net manager,frei, routen aufbauen,
+ (* 175 net manager 8 (!) *)
+ start,
+ definiere netz,
+ aktiviere netz,
+ list option,
+ erlaube, sperre, starte kanal, routen:
+
+TEXT VAR stand := "Netzsoftware vom 10.06.87 ";
+ (*Heinrichs *)
+LET
+ maxstat = 127,
+ ack = 0,
+(* nak = 1, *)
+ error nak = 2,
+(* zeichen eingang = 4, *)
+ list code = 15,
+(* fetch code = 11, *)
+ freigabecode = 29,
+ tabellencode = 500,
+ continue code = 100,
+ erase code = 14,
+ report code = 99,
+ abgleichcode = 98,
+ neue routen code = 97,
+ dr verwaltungslaenge = 8,
+
+ (* Codes der Verbindungsebene *)
+
+ task id code = 6,
+ name code = 7,
+ task info code = 8,
+ routen liefern code = 9,
+
+ (* Weitergabecodes für Netzknoten *)
+
+ route code = 1001,
+ out code = 1003,
+
+ (* Typen von Kommunikationsströmen *)
+
+ zustellung = 1,
+ call im wait = 3,
+ call im abbruch = 4,
+ call in zustellung = 5;
+
+LET STEUER =
+ STRUCT (
+ INT head,
+ zwischenziel,
+ zielrechner,
+ quellrechner,
+ strom,
+ INT sequenz,
+ seiten nummer,
+ TASK quelle,ziel,
+ INT sende code);
+
+LET INFO = STRUCT (STEUER steuer, INT typ,maxseq);
+
+LET PARA = STRUCT (TASK quelle, ziel, INT sendecode, zielstation);
+
+
+TASK VAR sohn;
+INT VAR strom,c,kanalmode, rzaehler := 20;
+BOUND STRUCT (ROW maxstat INT port,
+ ROW maxstat INT zwischen) VAR route;
+
+
+TASK PROC netport (INT CONST ziel):
+ INT VAR kan := route.port (ziel) AND 255;
+ IF kan < 1 OR kan > 15
+ THEN
+ niltask
+ ELSE
+ IF NOT exists (nettask (kan))
+ THEN
+ access catalogue;
+ nettask (kan) := task (kan);
+ IF NOT (nettask (kan) < father) THEN nettask (kan) := niltask FI;
+ FI;
+ nettask (kan)
+ FI
+END PROC netport;
+
+PROC frei (INT CONST stat,lvl):
+ DATASPACE VAR ds := nilspace;
+ BOUND STRUCT (INT x,y) VAR msg := ds;
+ msg.x := stat; msg.y := lvl;
+ INT VAR return;
+ call (netport (stat), freigabecode, ds, return) ;
+ forget (ds)
+END PROC frei;
+
+PROC net manager (DATASPACE VAR ds, INT CONST order, phase, TASK CONST
+ ordertask):
+
+ IF order = report code AND ordertask < myself
+ THEN
+ IF storage (old("report")) > 20 THEN forget ("report", quiet) FI;
+ FILE VAR rp := sequential file (output, "report");
+ BOUND TEXT VAR rpt := ds;
+ putline (rp, rpt);
+ send (ordertask, ack, ds)
+ ELIF order = abgleichcode AND ordertask < myself
+ THEN
+ BOUND STRUCT (INT ende, zwischen) VAR x := ds;
+ route.port (x.ende) := channel (ordertask);
+ route.zwischen (x.ende) := x.zwischen;
+ send (ordertask, ack, ds)
+ ELIF order = neue routen code AND ordertask < myself
+ THEN
+ forget ("port intern");
+ copy (ds,"port intern");
+ route := old ("port intern");
+ send (ordertask, ack, ds)
+ ELIF station (ordertask) = station (myself)
+ THEN
+ IF ordertask < myself
+ OR order = list code
+ OR order > continue code
+ THEN
+ IF order = list code
+ THEN
+ enable stop;
+ forget (ds); ds := old ("report");
+ FILE VAR ff := sequential file (output,ds);
+ putline (ff,"bekannte Stationen:");
+ stationen; line (ff); putline (ff,"--------");
+ putline (ff,"Eingestellte Netzmodi:");
+ kanaele ;
+ paketgroessen;
+ line (ff); putline (ff,"********");
+ putline (ff,stand);
+ putline (ff,"Rechner "+text(station(myself))+" um "+time of day);
+ send (ordertask, ack, ds)
+ ELSE
+ free manager (ds,order,phase,order task)
+ FI
+ ELSE
+ errorstop ("nur 'list' ist erlaubt")
+ FI
+ FI .
+
+stationen:
+INT VAR stat;
+INT VAR mystation := station (myself);
+FOR stat FROM 1 UPTO maxstat REP
+ IF route.port (stat) > 0 AND stat <> mystation
+ THEN
+ put (ff,text(stat)+"("+text (route.port (stat) AND 255)+","+
+ text(route.zwischen(stat))+")")
+ FI
+PER.
+
+paketgroessen:
+
+ line(ff);
+ put (ff, "Nutzlaenge bei indirekter Verbindung "+
+ text (data length via node) + " Byte "); line (ff).
+
+kanaele:
+ INT VAR portnummer;
+ TASK VAR tsk;
+ FOR portnummer FROM 1 UPTO 15 REP
+ tsk := task (portnummer);
+ IF tsk < myself THEN beschreibe kanal FI;
+ PER.
+
+beschreibe kanal:
+ putline (ff, name (tsk) + " haengt an Kanal " + text (channel (tsk))
+ + ", " + mode text (netz mode (portnummer))).
+
+END PROC net manager;
+
+TASK VAR cd,stask;
+ROW maxstat INT VAR erlaubt;
+
+PROC communicate:
+ enable stop;
+ INT VAR scode, merken :=0;
+ DATASPACE VAR dr := nilspace;
+ neuer start (quit max, kanalmode);
+REP
+ forget (dr);
+ telegrammfreigabe;
+ wait (dr, scode, stask);
+ cd := collected destination;
+ IF weiterleitung steht noch aus
+ THEN
+ send (netport (merken), out code, mds, reply);
+ IF reply <> -2 THEN forget (mds); merken := 0 FI
+ FI;
+ IF zeichen da OR zeit abgelaufen
+ THEN
+ packet
+ ELIF cd = myself
+ THEN
+ netz info und steuerung
+ ELSE
+ sendung untersuchen (stask, cd, scode, dr)
+ FI
+PER.
+
+telegrammfreigabe:
+ INT VAR dummy;
+ control (22,0,0,dummy).
+
+zeichen da: scode < 0 .
+
+zeit abgelaufen: scode = ack AND cd = myself.
+
+packet:
+ INT VAR snr, ant,err;
+ TASK VAR quelle, ziel;
+ snr := 0;
+ IF NOT zeichen da THEN routen erneuern FI;
+ REP
+ IF NOT zeichen da
+ THEN
+ forget (dr);
+ zeitueberwachung (snr, quelle, ziel, ant, dr);
+ ELIF NOT weiterleitung steht noch aus
+ THEN
+ packet eingang (snr, quelle, ziel, ant, dr);
+ FI;
+ IF snr = 1000
+ THEN
+ packet weiterleiten
+ ELIF snr > 0
+ THEN
+ IF ant > 6 AND erlaubt(station (quelle)) < 0
+ THEN unerlaubt
+ ELSE
+ send (quelle,ziel,ant,dr,err);
+ fehlerbehandlung ;
+ FI
+ FI
+ UNTIL snr = 0 OR zeichen da PER.
+
+routen erneuern:
+ rzaehler DECR 1;
+ IF rzaehler = 0
+ THEN
+ rzaehler := 20;
+ neue routen holen
+ FI.
+
+weiterleitung steht noch aus: merken <> 0.
+
+packet weiterleiten:
+ INT VAR reply;
+ IF NOT ((route.port (ant) AND 255) = channel OR route.port (ant) < 0)
+ THEN
+ send (netport (ant), out code, dr, reply);
+ IF reply = -2
+ THEN
+ merken := ant;
+ DATASPACE VAR mds := dr
+ FI
+ ELSE
+ report ("Weiterleitung nicht möglich für "+text(ant))
+ FI.
+
+fehlerbehandlung:
+ IF ok oder ziel nicht da THEN loesche verbindung (snr) FI.
+
+ok oder ziel nicht da: err=0 OR err=-1.
+
+netz info und steuerung:
+ IF scode = list code THEN list status
+ ELIF scode = erase code THEN strom beenden
+ ELIF scode = freigabe code AND stask = father THEN freigabelevel
+ ELIF scode >= route code THEN weitergaben
+ ELIF scode > tabellencode THEN routen ausliefern
+ ELSE forget (dr); ablehnen ("nicht möglich")
+ FI.
+
+weitergaben:
+ IF stask < father
+ THEN
+ IF scode = out code
+ THEN
+ BOUND INT VAR stx lng := dr;
+ INT VAR decoded lng := stx lng;
+ decode packet length (decoded lng);
+ transmit header (dr);
+ blockout (dr,1,drverwaltungslaenge,decoded lng);
+ transmit trailer
+ ELIF scode = route code
+ THEN
+ BOUND PARA VAR parah := dr;
+ PARA VAR para := parah;
+ pingpong (stask, ack, dr, reply);
+ neue sendung (para.quelle, para.ziel, para.sendecode,
+ para.zielstation, dr);
+ forget (dr); dr := nilspace;
+ send (stask, ack, dr)
+ FI
+ ELSE
+ forget (dr);
+ ablehnen ("nicht Sohn von "+name(father))
+ FI.
+
+routen ausliefern:
+ neue sendung (stask, myself, -routen liefern code, scode-tabellencode,dr).
+
+freigabelevel:
+ BOUND STRUCT (INT stat,lvl) VAR lv := dr;
+ IF lv.stat > 0 AND lv.stat <= maxstat THEN erlaubt (lv.stat) := lv.lvl FI;
+ send (stask,ack,dr).
+
+unerlaubt:
+ report ("Fremdzugriff von "+text(station (quelle))+" auf "+nam(ziel)
+ +" code "+text(ant));
+ loesche verbindung (snr);
+ forget (dr); dr := nilspace;
+ BOUND TEXT VAR errtxt := dr;
+ errtxt:="Kein Zugriff auf Station "+text (station (myself));
+ neue sendung (ziel, quelle, error nak, station (quelle), dr).
+
+strom beenden:
+ BOUND TEXT VAR stromtext := dr;
+ INT VAR erase strom := int (stromtext);
+ forget (dr);
+ strom := erase strom;
+ IF falsche stromnummer THEN ablehnen ("Strom gibt es nicht")
+ ELSE
+ BOUND INFO VAR v := verbindung (strom);
+ IF
+ stask < supervisor OR stask = vx.quelle OR stask = vx.ziel
+ THEN
+ loeschen
+ ELSE ablehnen ("Nur Empfänger/Absender darf löschen")
+ FI
+ FI.
+
+loeschen:
+ IF sendeeintrag THEN
+ IF callee (vx.quelle) = vx.ziel THEN absender warnen FI;
+ loesche verbindung (strom)
+ ELSE
+ IF callee (vx.ziel) = vx.quelle THEN warnen FI;
+ loesche verbindung (strom)
+ FI;
+ dr := nilspace;
+ send (stask,ack,dr).
+
+absender warnen:
+ dr := nilspace;
+ send(vx.ziel,vx.quelle,1,dr,err) .
+
+warnen:
+ dr := nilspace;
+errtxt := dr; errtxt:= "Station antwortet nicht";
+send (vx.quelle,vx.ziel,error nak, dr, err).
+
+falsche stromnummer: strom < 1 OR strom > max verbindungsnummer.
+sendeeintrag: vx.quellrechner = station (myself).
+vx: v.steuer.
+END PROC communicate;
+
+PROC list option:
+ begin ("net list",PROC list net, sohn)
+END PROC list option;
+
+PROC list net:
+ disable stop;
+ DATASPACE VAR ds ;
+ INT VAR scode;
+ REP
+ wait (ds, scode, stask);
+ forget (ds); ds := nilspace;
+ FILE VAR f := sequential file (output, ds);
+ list (f, father);
+ list netports;
+ IF is error THEN clear error;
+ forget(ds);
+ ds := nilspace;
+ f := sequential file (output, ds);
+ output (f); putline (f,errormessage);
+ clear error
+ FI;
+ send (stask, ack, ds)
+ PER.
+
+list netports:
+ INT VAR k;
+ FOR k FROM 1 UPTO 15 REP
+ TASK VAR tsk := task (k);
+ IF tsk < father
+ THEN
+ putline (f, name (tsk));
+ list (f,tsk)
+ FI
+ PER.
+
+END PROC list net;
+
+PROC neue routen holen:
+ forget ("port intern", quiet);
+ fetch ("port intern");
+ route := old ("port intern");
+ neue routen
+END PROC neue routen holen;
+
+PROC sendung untersuchen (TASK CONST q, z, INT CONST cod, DATASPACE VAR dr):
+ IF z = collector
+ THEN
+ verbindungsebene
+ ELIF station (z) <> 0
+ THEN
+ sendung (q,z,cod,station (z),dr)
+ ELSE
+ ablehnen ("Station 0")
+ FI.
+
+verbindungsebene:
+ IF cod = 256 THEN name von fremdstation
+ ELIF cod > 256
+ THEN
+ taskinfo fremd
+ ELIF callee (q) = z (* gegen errornak an collector *)
+ THEN
+ task id von fremd
+ FI.
+
+taskinfo fremd: sendung (q, collector, -task info code,cod-256,dr).
+
+task id von fremd: sendung (q, collector, -task id code, zielstation, dr) .
+
+name von fremdstation:
+ BOUND TASK VAR tsk := dr;
+ TASK VAR tsk1 := tsk;
+ forget (dr);
+ dr := nilspace;
+ sendung (q, tsk1, -name code, station (tsk1), dr).
+
+zielstation: cod.
+END PROC sendung untersuchen;
+
+PROC sendung (TASK CONST q, z, INT CONST code, z stat, DATASPACE VAR dr):
+ IF z stat < 1 OR z stat > maxstat
+ THEN
+ ablehnen ("ungültige Stationsnummer");
+ LEAVE sendung
+ FI;
+ INT VAR reply;
+ INT VAR rp := route.port (z stat) AND 255;
+ IF rp = 255 THEN neue routen holen ;rp := route.port (z stat) AND 255 FI;
+ IF rp = channel
+ THEN
+ sendung selbst betreiben
+ ELIF rp > 0 AND rp < 16
+ THEN
+ sendung weitergeben
+ ELSE
+ ablehnen ("Station "+text(z stat)+" gibt es nicht")
+ FI.
+
+sendung selbst betreiben:
+ neue sendung (q, z, code, z stat, dr).
+
+sendung weitergeben:
+ DATASPACE VAR ds := nilspace;
+ BOUND PARA VAR p := ds;
+ p.quelle := q;
+ p.ziel := z;
+ p.zielstation := z stat;
+ p.sendecode := code;
+ call (netport (z stat), route code, ds, reply);
+ forget (ds);
+ pingpong (netport (z stat), 0, dr, reply);
+ forget (dr);
+ IF reply < 0 THEN ablehnen ("netport "+text(route.port(zstat)AND255)
+ + " fehlt") FI
+END PROC sendung;
+
+PROC ablehnen (TEXT CONST t):
+ DATASPACE VAR vdr := nilspace;
+ BOUND TEXT VAR errtxt := vdr;
+ INT VAR err;
+ errtxt := t;
+ send (cd,stask, error nak, vdr,err);
+ forget (vdr).
+END PROC ablehnen;
+
+PROC stop:
+ access catalogue;
+ IF exists task ("net timer")
+ THEN
+ TASK VAR nets := father (/"net timer");
+ ELSE
+ nets := myself
+ FI;
+ nets := son (nets);
+ WHILE NOT (nets = niltask) REP
+ IF text (name (nets),3) = "net" OR name (nets) = "router"
+ THEN
+ end (nets)
+ FI;
+ nets := brother (nets)
+ PER
+END PROC stop;
+
+PROC list status:
+
+ DATASPACE VAR ds := nilspace;
+ FILE VAR f:=sequential file (output, ds);
+ line(f);
+ FOR strom FROM 1 UPTO max verbindungsnummer REP
+ IF strom > 0 THEN
+ BOUND INFO VAR v := verbindung (strom);
+ IF vx.strom <> 0 THEN info FI
+ FI;
+ PER;
+ send (stask, ack, ds).
+
+info:
+ put (f,"Strom "+text(strom));
+ put (f,"(sqnr"+text(vx.sequenz)+"/"+text (v.maxseq)+")");
+ IF sendeeintrag THEN sendeinfo ELSE empfangsinfo FI;
+ line (f).
+
+sendeeintrag: vx.quellrechner = station(myself) .
+
+sendeinfo:
+ IF v.typ = call im wait THEN put (f,"erwartet Antwort von")
+ ELIF v.typ = call in zustellung THEN put (f,"Ziel busy. Zielstation:")
+ ELIF v.typ = call im abbruch THEN put (f,"wird gelöscht bei Antwort von")
+ ELSE put (f,"sendet an")
+ FI;
+ put (f,vx.zielrechner);
+ put (f,". Absender ist """+nam (vx.quelle)+""".").
+
+empfangsinfo:
+ IF v.typ = zustellung THEN
+ put (f,"Sendung noch nicht zustellbar")
+ ELSE
+ put (f,"empfängt von");
+ put (f,vx.quellrechner);
+ FI;
+ put (f,". Empfaenger ist """+nam (vx.ziel)+""".").
+
+vx: v.steuer.
+END PROC list status;
+
+INT VAR quitmax := 3;
+
+ROW 15 TASK VAR net task;
+ROW 15 INT VAR netz mode;
+
+PROC erlaube (INT CONST von, bis):
+ IF ein kanal gestartet
+ THEN
+ putline ("Warnung: 'erlaube' muß vor 'starte kanal'")
+ FI;
+ test (von); test (bis);
+ INT VAR i;
+ FOR i FROM von UPTO bis REP erlaubt (i) := 0 PER
+END PROC erlaube;
+
+PROC sperre (INT CONST von, bis):
+ IF ein kanal gestartet
+ THEN
+ putline ("Warnung: 'sperre' muß vor 'starte kanal'")
+ FI;
+ test (von); test (bis);
+ INT VAR i;
+ FOR i FROM von UPTO bis REP erlaubt (i) :=-1 PER
+END PROC sperre ;
+
+BOOL VAR alte routen, ein kanal gestartet;
+
+PROC definiere netz:
+ stop;
+ INT VAR i;
+ FOR i FROM 1 UPTO 15 REP net task (i) := niltask PER;
+ ein kanal gestartet := FALSE;
+ FILE VAR s := sequential file (output,"report");
+ putline (s," N e u e r S t a r t " + date + " " + time of day );
+ alte routen := exists ("port intern");
+ IF alte routen
+ THEN
+ route := old ("port intern")
+ ELSE
+ route := new ("port intern");
+ initialize routes
+ FI.
+
+ initialize routes:
+ FOR i FROM 1 UPTO maxstat REP
+ route.zwischen(i) := i
+ PER.
+
+END PROC definiere netz;
+
+PROC starte kanal (INT CONST k,modus,stroeme):
+ ein kanal gestartet := TRUE;
+ IF exists (canal (k)) THEN end (canal (k)) FI;
+ IF stroeme <= 0 THEN errorstop ("3.Parameter negativ") FI;
+ quitmax := stroeme;
+ c := k;
+ IF c < 1 OR c > 15 THEN errorstop ("unzulässiger Kanal:"+text(c)) FI;
+ kanalmode := modus;
+ IF kanalmode < 1 OR kanalmode > max mode
+ THEN errorstop ("unzulässiger Netzbetriebsmodus:"+text(kanalmode))
+ ELSE netz mode (c) := kanalmode
+ FI;
+ IF NOT exists task ("net port")
+ THEN
+ begin ("net port",PROC net io, net task (c));
+ define collector (/"net port")
+ ELSE
+ begin ("net port "+text (c),PROC net io, net task (c))
+ FI.
+END PROC starte kanal;
+
+PROC routen (INT CONST von, bis, kanal, zw):
+ INT VAR i;
+ IF kanal < 0 OR kanal > 15 THEN errorstop ("Kanal unzulässig") FI;
+ test (von); test (bis);
+ FOR i FROM von UPTO bis REP
+ route.port (i) := kanal+256;
+ IF zw=0
+ THEN
+ route.zwischen (i) := i
+ ELSE
+ test (zw);
+ route.zwischen (i) := zw
+ FI
+ PER.
+END PROC routen;
+
+PROC routen (INT CONST von, bis, kanal):
+ routen (von, bis, kanal, 0)
+END PROC routen;
+
+PROC test (INT CONST station):
+ IF station < 1 OR station > maxstat
+ THEN
+ errorstop (text (station) + " als Stationsnummer unzulässig")
+ FI
+END PROC test;
+
+PROC aktiviere netz:
+vorgegebene routen pruefen;
+IF existstask ("net timer") THEN end (/"net timer") FI;
+begin ("net timer",PROC timer,sohn);
+IF NOT alte routen
+THEN
+ routen aufbauen
+ELSE
+ IF online THEN break FI
+FI.
+
+vorgegebene routen pruefen:
+ INT VAR i;
+ FOR i FROM 1 UPTO maxstat REP
+ INT VAR s := route.port (i) AND 255;
+ IF s > 0 AND s <= 15 CAND nettask (s) = niltask
+ THEN
+ errorstop ("Kanal "+text(s)+" nicht gestartet, steht aber in Routen")
+ FI
+ PER.
+END PROC aktiviere netz;
+
+
+PROC routen aufbauen:
+ alte routen := TRUE;
+ c := channel;
+ break (quiet);
+ begin ("router", PROC rout0, sohn).
+END PROC routen aufbauen;
+
+PROC rout0:
+ disable stop;
+ rout;
+ IF is error
+ THEN
+ put error
+ FI;
+ end (myself)
+END PROC rout0;
+
+PROC rout:
+ IF c>0 THEN continue (c) FI;
+ clear error; enable stop;
+ fetch ("port intern");
+ route := old ("port intern");
+ routen aufbauen;
+ ds := old ("port intern");
+ call (father, neue routen code, ds, reply).
+
+routen aufbauen:
+ access catalogue;
+ TASK VAR port := brother (myself);
+ WHILE NOT (port = niltask) REP
+ IF text (name (port),8) = "net port" THEN nachbarn FI;
+ port := brother (port)
+ PER;
+ IF online THEN putline ("Fertig. Weiter mit SV !") FI.
+
+aenderbar: route.port (st) < 256.
+
+nachbarn:
+ INT VAR st,reply;
+ FOR st FROM 1 UPTO maxstat REP
+ IF erlaubt (st) >= 0 AND st <> station (myself) AND aenderbar
+ THEN
+ IF online THEN put (name (port)); put (st) FI;
+ DATASPACE VAR ds := nilspace;
+ call (port, tabellencode+st, ds, reply);
+ IF reply = ack
+ THEN
+ BOUND STRUCT (ROW maxstat INT port,
+ ROW maxstat INT zwischen) VAR fremd := ds;
+ route.port (st) := channel(port);
+ route.zwischen (st) := st;
+ indirekte ziele
+ ELIF reply < 0
+ THEN
+ errorstop ("netz läuft nicht (Kanalnummer falsch)")
+ ELSE
+ BOUND TEXT VAR xt := ds;
+ IF online THEN put (xt) FI;
+ FI;
+ IF online THEN line FI;
+ forget (ds)
+ FI
+ PER.
+
+indirekte ziele:
+ INT VAR kanal := fremd.port (station (myself)) AND 255;
+ INT VAR ind;
+ FOR ind FROM 1 UPTO maxstat REP
+ IF ind bei st bekannt AND NOT ((fremd.port (ind) AND 255) = kanal)
+ AND route.port (ind) < 256
+ THEN
+ route.port (ind) := channel (port);
+ route.zwischen (ind) := st
+ FI
+ PER.
+
+ind bei st bekannt: NOT (fremd.port (ind) = -1).
+
+END PROC rout;
+
+
+PROC timer:
+ disable stop;
+ access catalogue;
+ INT VAR old session := 1;
+ REP
+ IF session <> old session
+ THEN
+ define collector (/"net port");
+ old session := session
+ FI;
+ clear error;
+ pause (30);
+ sende tick an alle ports
+ PER.
+
+sende tick an alle ports :
+ TASK VAR fb := son (father);
+ REP
+ IF NOT exists (fb) THEN access catalogue;LEAVE sende tick an alle portsFI;
+ IF channel (fb) > 0
+ THEN
+ DATASPACE VAR ds := nilspace;
+ send (fb, ack, ds);
+ pause (10)
+ FI;
+ fb := brother (fb)
+ UNTIL fb = niltask PER.
+
+END PROC timer;
+
+PROC net io:
+ disable stop;
+ set net mode (kanalmode);
+ fetch ("port intern");
+ route := old ("port intern");
+ commanddialogue (FALSE);
+ continue (c);
+ communicate;
+ TEXT VAR emsg := "++++++ "+error message +" Zeile "+text(errorline);
+ clear error;
+ report (emsg);
+ end (myself)
+END PROC net io;
+
+PROC start: run ("netz") END PROC start;
+
+END PACKET net manager;
+
diff --git a/system/net/1.8.7/src/net report b/system/net/1.8.7/src/net report
new file mode 100644
index 0000000..ddc19d2
--- /dev/null
+++ b/system/net/1.8.7/src/net report
@@ -0,0 +1,41 @@
+PACKET net report DEFINES report, abgleich:
+(* Version 3 (!) *)
+
+LET reportcode = 99, abgleichcode = 98;
+
+PROC abgleich (INT CONST ende, zwischen):
+ DATASPACE VAR ds := nilspace;
+ BOUND STRUCT (INT ende, zwischen) VAR x := ds;
+ x.ende := ende;
+ x.zwischen := zwischen;
+ call (father, abgleichcode, ds, rep);
+ INT VAR rep;
+ forget (ds)
+END PROC abgleich;
+
+PROC report (TEXT CONST x):
+ report(x,"")
+END PROC report;
+
+PROC report (TEXT CONST txt, info):
+ DATASPACE VAR net report := nilspace;
+ BOUND TEXT VAR rinfo := net report;
+ rinfo := date;
+ rinfo CAT " "+time of day +" ";
+ rinfo CAT name(myself)+":";
+ rinfo CAT txt;
+ INT VAR i;
+ FOR i FROM 1 UPTO length (info) REP
+ INT VAR z := code (infoSUBi) ;
+ IF z < 32 OR z > 126
+ THEN rinfo CAT "%"+text(z)+" "
+ ELSE rinfo CAT (infoSUBi)+" "
+ FI
+ PER;
+ call (father, report code , net report, reply);
+ INT VAR reply;
+ forget (net report);
+END PROC report;
+
+END PACKET net report;
+
diff --git a/system/net/1.8.7/src/netz b/system/net/1.8.7/src/netz
new file mode 100644
index 0000000..c237ba2
--- /dev/null
+++ b/system/net/1.8.7/src/netz
@@ -0,0 +1,20 @@
+IF exists ("port intern") THEN forget ("port intern") FI;
+definiere netz;
+list option;
+erlaube(1,127);
+sperre (1,9);
+sperre (15,32);
+sperre (37,37);
+sperre (42,42);
+sperre (46,47);
+sperre (49,127);
+routen (1, 32,8);
+routen (33,43, 9);
+routen (34,34,8);
+routen (35,48,9);
+starte kanal (9,11,10);
+starte kanal (8,1,10);
+aktiviere netz;
+
+
+
diff --git a/system/net/1.8.7/src/port server b/system/net/1.8.7/src/port server
new file mode 100644
index 0000000..46c647f
--- /dev/null
+++ b/system/net/1.8.7/src/port server
@@ -0,0 +1,164 @@
+PACKET port server: (* Autor : R. Ruland *)
+ (* Stand : 21.03.86 *)
+
+INT VAR port station;
+TEXT VAR port := "PRINTER";
+
+put ("gib Name des Zielspools : "); editget (port); line;
+put ("gib Stationsnummer des Zielspools : "); get (port station);
+
+server channel (15);
+spool duty ("Verwalter fuer Task """ + port +
+ """ auf Station " + text (port station));
+
+LET max counter = 10 ,
+ time slice = 300 ,
+
+ ack = 0 ,
+ fetch code = 11 ,
+ param fetch code = 21 ,
+ file save code = 22 ,
+ file type = 1003 ,
+
+ begin char = ""0"",
+ end char = ""1"";
+
+
+INT VAR reply, old heap size;
+TEXT VAR file name, write pass, read pass, sendername, buffer;
+FILE VAR file;
+
+DATASPACE VAR ds, file ds, send ds;
+
+BOUND STRUCT (TEXT file name, write pass, read pass, sendername, INT station) VAR msg;
+BOUND TEXT VAR error msg ;
+
+spool manager (PROC save file);
+
+PROC save file :
+
+ disable stop ;
+ command dialogue (FALSE);
+ ds := nilspace; file ds := nilspace; send ds := nil space;
+ old heap size := heap size;
+
+ REP
+ execute save file;
+
+ IF is error THEN save error (error message) FI;
+
+ IF heap size > old heap size + 4
+ THEN collect heap garbage ;
+ old heap size := heap size
+ FI;
+
+ PER
+
+ENDPROC save file;
+
+
+PROC execute save file :
+
+enable stop;
+forget (file ds) ; file ds := nilspace;
+call (father, fetch code, file ds, reply);
+IF reply <> ack
+ THEN error msg := ds; errorstop (error msg);
+ ELSE save file ds
+FI;
+
+. save file ds :
+ IF type (file ds) = file type
+ THEN get file params;
+ insert file params;
+ call station (port station, port, file save code, file ds);
+ ELSE errorstop ("Datenraum hat falschen Typ")
+ FI;
+
+. get file params :
+ forget (ds); ds := nilspace;
+ call (father, param fetch code, ds, reply);
+ IF reply <> ack
+ THEN error msg := ds; errorstop (error msg);
+ ELSE msg := ds;
+ file name := msg. file name;
+ write pass := msg. write pass;
+ read pass := msg. read pass;
+ sendername := msg. sender name;
+ FI;
+
+. insert file params :
+ buffer := "";
+ in headline (filename);
+ in headline (write pass);
+ in headline (read pass);
+ in headline (sendername);
+ file := sequential file (input, file ds) ;
+ headline (file, buffer);
+
+END PROC execute save file;
+
+
+PROC call station (INT CONST order task station, TEXT CONST order task name,
+ INT CONST order code, DATASPACE VAR order ds) :
+
+ INT VAR counter := 0;
+ TASK VAR order task;
+ disable stop;
+ REP order task := order task station // order task name;
+ IF is error CAND pos (error message, "antwortet nicht") > 0
+ THEN clear error;
+ counter := min (max counter, counter + 1);
+ pause (counter * time slice);
+ ELSE enable stop;
+ forget (send ds); send ds := order ds;
+ call (order task, order code, send ds, reply);
+ disable stop;
+ IF reply = ack
+ THEN forget (order ds); order ds := send ds;
+ forget (send ds);
+ LEAVE call station
+ ELSE error msg := send ds;
+ errorstop (error msg);
+ FI;
+ FI;
+ PER;
+
+END PROC call station;
+
+
+TASK OP // (INT CONST station, TEXT CONST name) :
+
+ enable stop;
+ station / name
+
+END OP //;
+
+
+PROC in headline (TEXT CONST information) :
+ IF pos (information, begin char) <> 0
+ OR pos (information, end char) <> 0
+ THEN errorstop ("Name darf nicht Code 0 oder Code 1 enthalten") FI;
+ buffer CAT begin char;
+ buffer CAT information;
+ buffer CAT end char;
+END PROC in headline;
+
+
+PROC save error (TEXT CONST message) :
+ clear error;
+ file name CAT ".";
+ file name CAT sender name;
+ file name CAT ".ERROR";
+ file := sequential file (output, file name);
+ putline (file, " ");
+ putline (file, "Uebertragung nicht korrekt beendet ");
+ putline (file, " ");
+ put (file, "ERROR :"); put (file, message);
+ save (file name, public);
+ clear error;
+ forget(file name, quiet);
+END PROC save error;
+
+ENDPACKET port server;
+
diff --git a/system/net/1.8.7/src/printer server b/system/net/1.8.7/src/printer server
new file mode 100644
index 0000000..b1a30bc
--- /dev/null
+++ b/system/net/1.8.7/src/printer server
@@ -0,0 +1,99 @@
+PACKET multi user printer : (* Autor : Rudolf Ruland *)
+ (* Stand : 24.03.86 *)
+
+INT VAR c;
+put ("gib Druckerkanal : "); get (c);
+
+ server channel (c);
+ station only (FALSE) ;
+ spool duty ("Ausgabe mit dem Drucker");
+ spool control task (myself);
+
+LET ack = 0 ,
+
+ fetch code = 11 ,
+ param fetch code = 21 ,
+ file type = 1003 ;
+
+INT VAR reply, old heap size, sender station;
+TEXT VAR file name, userid, password, sendername;
+FILE VAR file ;
+
+DATASPACE VAR ds, file ds;
+
+BOUND STRUCT (TEXT file name, userid, password, sendername, INT station) VAR msg;
+BOUND TEXT VAR error msg ;
+
+spool manager (PROC printer);
+
+PROC printer :
+
+ disable stop ;
+ command dialogue (FALSE);
+ ds := nilspace; file ds := nilspace;
+ continue (server channel) ;
+ check error ("Kanal belegt");
+
+ old heap size := heap size ;
+ REP
+ execute print ;
+
+ IF is error
+ THEN put error;
+ clear error;
+ FI ;
+
+ IF heap size > old heap size + 4
+ THEN collect heap garbage ;
+ old heap size := heap size
+ FI
+ PER
+
+ENDPROC printer ;
+
+
+PROC execute print :
+
+ enable stop ;
+ forget (file ds) ; file ds := nilspace ;
+ call (father, fetch code, file ds, reply) ;
+ IF reply = ack CAND type (file ds) = file type
+ THEN get file params;
+ print file
+ FI ;
+
+. get file params :
+ forget (ds); ds := nilspace;
+ call (father, param fetch code, ds, reply);
+ IF reply <> ack
+ THEN error msg := ds; errorstop (error msg);
+ ELSE msg := ds;
+ file name := msg. file name;
+ userid := msg. userid;
+ password := msg. password;
+ sendername := msg. sender name;
+ sender station := msg. station;
+ FI;
+
+. print file :
+ file := sequential file (input, file ds);
+ print (file,
+ PROC (INT CONST, INT VAR, INT VAR) open,
+ PROC (INT CONST, INT CONST) close,
+ PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute);
+
+ENDPROC execute print ;
+
+
+PROC check error (TEXT CONST message) :
+ IF is error
+ THEN clear error;
+ rename myself (message);
+ IF is error THEN clear error; end (myself) FI;
+ pause (18000);
+ end (myself);
+ FI;
+END PROC check error;
+
+ENDPACKET multi user printer ;
+
diff --git a/system/net/1.8.7/src/spool cmd b/system/net/1.8.7/src/spool cmd
new file mode 100644
index 0000000..b44e799
--- /dev/null
+++ b/system/net/1.8.7/src/spool cmd
@@ -0,0 +1,112 @@
+PACKET spool cmd (* Autor: R. Ruland *)
+ (* Stand: 01.04.86 *)
+ DEFINES killer,
+ first,
+ start,
+ stop,
+ halt,
+ wait for halt :
+
+LET error nak = 2 ,
+
+ entry line code = 23 ,
+ killer code = 24 ,
+ first code = 25 ,
+ start code = 26 ,
+ stop code = 27 ,
+ halt code = 28 ,
+ wait for halt code = 29 ;
+
+DATASPACE VAR ds;
+
+BOUND STRUCT (TEXT entry line, INT index) VAR control msg;
+BOUND TEXT VAR error msg ;
+
+INT VAR reply;
+
+INITFLAG VAR in this task := FALSE;
+
+
+PROC control spool (TASK CONST spool, INT CONST control code,
+ TEXT CONST question, BOOL CONST leave) :
+
+ enable stop;
+ initialize control msg;
+ WHILE valid spool entry
+ REP IF control question THEN control spool entry FI PER;
+
+ . initialize control msg :
+ IF NOT initialized (in this task) THEN ds := nilspace FI;
+ forget (ds); ds := nilspace; control msg := ds;
+ control msg. entry line := "";
+ control msg. index := 0;
+ say (""13""10"");
+
+ . valid spool entry :
+ call (spool, entry line code, ds, reply);
+ IF reply = error nak
+ THEN error msg := ds;
+ errorstop (error msg);
+ FI;
+ control msg. index <> 0
+
+ . control question :
+ say (control msg. entry line);
+ yes (question)
+
+ . control spool entry :
+ call (spool, control code, ds, reply);
+ IF reply = error nak
+ THEN error msg := ds;
+ errorstop (error msg);
+ FI;
+ IF leave THEN LEAVE control spool FI;
+
+END PROC control spool;
+
+
+PROC killer (TASK CONST spool) :
+
+ control spool (spool, killer code, " loeschen", FALSE)
+
+END PROC killer;
+
+
+PROC first (TASK CONST spool) :
+
+ control spool (spool, first code, " als erstes", TRUE)
+
+END PROC first;
+
+
+PROC start (TASK CONST spool) :
+
+ call (stop code, "", spool);
+ call (start code, "", spool);
+
+END PROC start;
+
+
+PROC stop (TASK CONST spool) :
+
+ call (stop code, "", spool);
+
+END PROC stop;
+
+
+PROC halt (TASK CONST spool) :
+
+ call (halt code, "", spool);
+
+END PROC halt;
+
+
+PROC wait for halt (TASK CONST spool) :
+
+ call (wait for halt code, "", spool);
+
+END PROC wait for halt;
+
+
+END PACKET spool cmd;
+
diff --git a/system/net/1.8.7/src/spool manager b/system/net/1.8.7/src/spool manager
new file mode 100644
index 0000000..e711ab4
--- /dev/null
+++ b/system/net/1.8.7/src/spool manager
@@ -0,0 +1,915 @@
+PACKET spool manager DEFINES (* Autor: J. Liedtke *)
+ (* R. Nolting *)
+ (* R. Ruland *)
+ (* Stand: 22.07.86 *)
+
+ spool manager ,
+
+ server channel ,
+ spool duty,
+ station only,
+ spool control task :
+
+LET que size = 101 ,
+
+ ack = 0 ,
+ nak = 1 ,
+ error nak = 2 ,
+ message ack = 3 ,
+ question ack = 4 ,
+ second phase ack = 5 ,
+ false code = 6 ,
+
+ fetch code = 11 ,
+ save code = 12 ,
+ exists code = 13 ,
+ erase code = 14 ,
+ list code = 15 ,
+ all code = 17 ,
+ param fetch code = 21 ,
+ file save code = 22 ,
+ entry line code = 23 ,
+ killer code = 24 ,
+ first code = 25 ,
+ start code = 26 ,
+ stop code = 27 ,
+ halt code = 28 ,
+ wait for halt code = 29 ,
+
+ continue code = 100 ,
+
+ file type = 1003 ;
+
+LET begin char = ""0"",
+ end char = ""1"";
+
+LET PARAMS = STRUCT (TEXT name, userid, password, sendername, INT station),
+ ENTRY = STRUCT (PARAMS ds params, TEXT entry line, DATASPACE space);
+
+ROW que size ENTRY VAR que ;
+
+PARAMS CONST empty params := PARAMS : ("", "", "", "", -1);
+
+PARAMS VAR save params, file save params;
+
+ENTRY VAR fetch entry;
+
+FILE VAR file;
+
+INT VAR order, last order, phase, reply, old heap size, first, last, list index,
+ begin pos, end pos, order task station, sp channel, counter;
+
+TEXT VAR order task name, buffer, sp duty, start time;
+
+BOOL VAR server is waiting, stop command pending, stat only, valid fetch entry;
+
+TASK VAR order task, last order task, server, calling parent, task in control;
+
+INITFLAG VAR in this task := FALSE;
+
+DATASPACE VAR ds;
+
+BOUND STRUCT (TEXT name, userid, password) VAR msg;
+BOUND STRUCT (TEXT entry line, INT index) VAR control msg;
+BOUND PARAMS VAR fetch msg;
+BOUND THESAURUS VAR all msg;
+BOUND TEXT VAR error msg ;
+
+
+. first entry : que (first)
+. list entry : que (list index)
+. last entry : que (last)
+
+. que is empty : first = last
+. que is full : first = next (last)
+.;
+
+sp channel := 0;
+sp duty := "";
+stat only := FALSE;
+task in control := myself;
+
+PROC server channel (INT CONST channel nr) :
+ IF channel nr <= 0 OR channel nr >= 33
+ THEN errorstop ("falsche Kanalangabe") FI;
+ sp channel := channel nr;
+END PROC server channel;
+
+INT PROC server channel :
+ sp channel
+END PROC server channel;
+
+
+PROC station only (BOOL CONST flag) :
+ stat only := flag
+END PROC station only;
+
+BOOL PROC station only :
+ stat only
+END PROC station only;
+
+
+PROC spool duty (TEXT CONST duty) :
+ sp duty := duty;
+END PROC spool duty;
+
+TEXT PROC spool duty :
+ sp duty
+END PROC spool duty;
+
+
+PROC spool control task (TASK CONST task id):
+ task in control := task id;
+END PROC spool control task;
+
+TASK PROC spool control task :
+ task in control
+END PROC spool control task;
+
+
+PROC spool manager (PROC server start) :
+
+ spool manager (PROC server start, TRUE)
+
+END PROC spool manager;
+
+
+PROC spool manager (PROC server start, BOOL CONST with start) :
+
+ set autonom ;
+ break ;
+ disable stop ;
+ initialize spool manager ;
+ REP forget (ds) ;
+ wait (ds, order, order task) ;
+ IF order <> second phase ack
+ THEN prepare first phase ;
+ spool (PROC server start);
+ ELIF order task = last order task
+ THEN prepare second phase ;
+ spool (PROC server start);
+ ELSE send nak
+ FI ;
+ send error if necessary ;
+ collect heap garbage if necessary
+ PER
+
+ . initialize spool manager :
+ initialize if necessary;
+ stop;
+ erase fetch entry;
+ IF with start THEN start (PROC server start) FI;
+
+ . initialize if necessary :
+ IF NOT initialized (in this task)
+ THEN FOR list index FROM 1 UPTO que size
+ REP list entry. space := nilspace PER;
+ fetch entry. space := nilspace;
+ ds := nilspace;
+ last order task := niltask;
+ server := niltask;
+ calling parent := niltask;
+ server is waiting := FALSE;
+ stop command pending := FALSE;
+ old heap size := 0;
+ clear spool;
+ FI;
+
+ . prepare first phase :
+ IF order = save code OR order = erase code OR order = stop code
+ THEN phase := 1 ;
+ last order := order ;
+ last order task := order task ;
+ FI;
+
+ . prepare second phase :
+ phase INCR 1 ;
+ order := last order
+
+ . send nak :
+ forget (ds) ;
+ ds := nilspace ;
+ send (order task, nak, ds);
+
+ . send error if necessary :
+ IF is error
+ THEN forget (ds) ;
+ ds := nilspace ;
+ error msg := ds ;
+ CONCR (error msg) := error message;
+ clear error;
+ send (order task, error nak, ds)
+ FI;
+
+ . collect heap garbage if necessary :
+ IF heap size > old heap size + 2
+ THEN collect heap garbage;
+ old heap size := heap size;
+ FI;
+
+END PROC spool manager;
+
+
+PROC spool (PROC server start):
+
+ command dialogue (FALSE);
+ enable stop;
+ IF station only CAND station (ordertask) <> station (myself)
+ THEN errorstop ("kein Zugriffsrecht auf Task " + text (station(myself))
+ + "/""" + name(myself) + """")
+ FI;
+
+ SELECT order OF
+
+ CASE fetch code : out of que
+ CASE param fetch code : send fetch params
+ CASE save code : new que entry
+ CASE file save code : new file que entry
+ CASE exists code : exists que entry
+ CASE erase code : erase que entry
+ CASE list code : send spool list
+ CASE all code : send owners ds names
+
+ OTHERWISE :
+
+ IF order >= continue code AND order task = supervisor
+ THEN forget (ds);
+ spool command (PROC server start)
+
+ ELIF spool control allowed by order task
+ THEN SELECT order OF
+ CASE entry line code : send next entry line
+ CASE killer code : kill entry
+ CASE first code : make to first
+ CASE start code : start server
+ CASE stop code : stop server
+ CASE halt code : halt server
+ CASE wait for halt code : wait for halt
+ OTHERWISE : errorstop ("falscher Auftrag fuer Task """
+ + name(myself) + """")
+ END SELECT
+
+ ELSE errorstop ("falscher Auftrag fuer Task """
+ + name(myself) + """")
+ FI;
+ END SELECT;
+
+
+. spool control allowed by order task :
+ (order task = spool control task OR order task < spool control task
+ OR spool control task = supervisor)
+ AND station (order task) = station (myself)
+.
+ out of que :
+ IF NOT (order task = server)
+ THEN errorstop ("keine Servertask")
+ ELIF stop command pending
+ THEN forget (ds);
+ stop;
+ erase fetch entry;
+ ELIF que is empty
+ THEN forget (ds) ;
+ erase fetch entry;
+ server is waiting := TRUE;
+ ELSE send first entry;
+ FI;
+
+.
+ send fetch params :
+ IF order task = server
+ THEN send params
+ ELSE errorstop ("keine Servertask")
+ FI;
+
+ . send params :
+ forget(ds); ds := nilspace; fetch msg := ds;
+ fetch msg := fetch entry. ds params;
+ send (order task, ack, ds);
+
+.
+ new que entry :
+ IF phase = 1
+ THEN prepare into que
+ ELSE into que
+ FI;
+
+.
+ prepare into que :
+ msg := ds ;
+ save params. name := msg.name;
+ save params. userid := msg.userid;
+ save params. password := msg.password;
+ save params. sendername := name (order task);
+ save params. station := station (order task);
+ forget (ds); ds := nilspace;
+ send (order task, second phase ack, ds);
+
+.
+ new file que entry :
+ IF type (ds) <> file type
+ THEN errorstop ("Datenraum hat falschen Typ");
+ ELSE get file params;
+ into que;
+ FI;
+
+ . get file params :
+ file := sequential file (input, ds);
+ end pos := 0;
+ next headline information (file save params. name);
+ next headline information (file save params. userid);
+ next headline information (file save params. password);
+ next headline information (file save params. sendername);
+ next headline information (buffer);
+ file save params. station := int (buffer);
+ IF NOT last conversion ok
+ THEN file save params. station := station (order task) FI;
+ IF file save params. sendername = ""
+ THEN file save params. sendername := name (order task) FI;
+ IF file save params. name = ""
+ THEN IF headline (file) <> ""
+ THEN file save params. name := headline (file);
+ ELSE errorstop ("Name unzulaessig")
+ FI;
+ ELSE headline (file, file save params. name);
+ FI;
+
+.
+ exists que entry :
+ msg := ds ;
+ order task name := name (order task);
+ order task station := station (order task);
+ to first que entry;
+ WHILE next que entry found
+ REP IF is entry from order task (msg. name)
+ THEN send ack;
+ LEAVE exists que entry
+ FI;
+ PER ;
+ forget (ds); ds := nilspace;
+ send (order task, false code, ds)
+
+.
+ erase que entry :
+ msg := ds ;
+ order task name := name (order task);
+ order task station := station (order task);
+ IF phase = 1
+ THEN ask for erase
+ ELSE erase entry from order task
+ FI;
+
+ . ask for erase :
+ to first que entry;
+ WHILE next que entry found
+ REP IF is entry from order task (msg. name)
+ THEN manager question ("""" + msg.name + """ loeschen");
+ LEAVE erase que entry
+ FI;
+ PER ;
+ manager message ("""" + msg.name + """ existiert nicht");
+
+ . erase entry from order task :
+ IF is entry from order task (msg. name)
+ THEN delete que entry;
+ LEAVE erase que entry
+ ELSE to first que entry;
+ WHILE next que entry found
+ REP IF is entry from order task (msg. name)
+ THEN delete que entry;
+ LEAVE erase que entry
+ FI ;
+ PER ;
+ manager message ("""" + msg.name + """ existiert nicht");
+ FI;
+
+ . delete que entry :
+ erase entry (list index) ;
+ send ack;
+
+.
+ send owners ds names:
+ order task name := name (order task);
+ order task station := station (order task);
+ forget (ds); ds := nilspace; all msg := ds;
+ all msg := empty thesaurus;
+ to first que entry;
+ WHILE next que entry found
+ REP IF is entry from order task ("")
+ THEN insert (all msg, list entry. ds params. name)
+ FI;
+ PER;
+ send (order task, ack, ds)
+
+.
+ send spool list :
+ list spool;
+ send (order task, ack, ds);
+
+.
+ send next entry line :
+ control msg := ds;
+ get next entry line (control msg. entry line, control msg. index);
+ send (order task, ack, ds);
+
+.
+ kill entry :
+ control msg := ds;
+ list index := control msg. index;
+ IF is valid que entry (list index)
+ THEN erase entry (list index)
+ FI;
+ send (order task, ack, ds);
+
+.
+ make to first :
+ control msg := ds;
+ list index := control msg. index;
+ IF is valid que entry (list index)
+ THEN new first (list entry);
+ erase entry (list index);
+ FI;
+ send (order task, ack, ds);
+
+.
+ start server :
+ IF exists (server) THEN errorstop ("Spool muß zuerst gestoppt werden") FI;
+ start (PROC server start);
+ IF server channel <= 0 OR server channel >= 33
+ THEN manager message ("WARNUNG : Serverkanal nicht eingestellt");
+ ELSE send ack
+ FI;
+
+.
+ stop server:
+ IF phase = 1
+ THEN stop;
+ IF valid fetch entry
+ THEN valid fetch entry := FALSE;
+ manager question (""13""10"" +
+ fetch entry. entry line + " neu eintragen");
+ ELSE erase fetch entry;
+ send ack;
+ FI;
+ ELSE IF fetch entry. entry line <> "" THEN new first (fetch entry) FI;
+ erase fetch entry;
+ send ack;
+ FI;
+
+.
+ halt server :
+ stop command pending := TRUE;
+ IF NOT exists (server) OR server is waiting
+ THEN stop;
+ erase fetch entry;
+ FI;
+ send ack;
+
+.
+ wait for halt :
+ IF exists (calling parent)
+ THEN errorstop ("Task """ + name (calling parent) + """ wartet schon auf halt")
+ ELSE calling parent := order task;
+ stop command pending := TRUE;
+ forget (ds);
+ IF NOT exists (server) OR server is waiting
+ THEN stop;
+ erase fetch entry;
+ FI;
+ FI;
+
+END PROC spool;
+
+
+PROC send first entry :
+
+ forget (ds); ds := first entry. space;
+ send (server, ack, ds, reply) ;
+ IF reply = ack
+ THEN server is waiting := FALSE;
+ start time := time of day;
+ start time CAT " am ";
+ start time CAT date;
+ erase fetch entry;
+ fetch entry := first entry;
+ erase entry (first);
+ valid fetch entry := TRUE;
+ ELSE forget (ds);
+ FI;
+
+END PROC send first entry;
+
+
+PROC into que :
+
+ IF que is full
+ THEN errorstop ("Spool ist voll")
+ ELSE make new entry;
+ send ack;
+ awake server if necessary
+ FI;
+
+ . make new entry :
+ IF order = save code
+ THEN last entry. ds params := save params;
+ save params := empty params;
+ ELSE last entry. ds params := file save params;
+ file save params := empty params;
+ FI;
+ last entry. space := ds;
+ counter INCR 1;
+ build entry line;
+ last := next (last) ;
+
+ . build entry line :
+ IF LENGTH last entry. ds params. sender name > 16
+ THEN buffer := subtext (last entry. ds params. sender name, 1, 13);
+ buffer CAT "...""";
+ ELSE buffer := last entry. ds params. sender name;
+ buffer CAT """";
+ buffer := text (buffer, 17);
+ FI;
+ last entry. entry line := entry station text;
+ last entry. entry line CAT "/""";
+ last entry. entry line CAT buffer;
+ last entry. entry line CAT " : """ ;
+ last entry. entry line CAT last entry. ds params. name;
+ last entry. entry line CAT """ (" ;
+ last entry. entry line CAT text (storage (last entry. space));
+ last entry. entry line CAT " K)";
+
+ . entry station text :
+ IF last entry. ds params. station = 0
+ THEN " "
+ ELSE text (last entry. ds params. station, 3)
+ FI
+
+ . awake server if necessary :
+ IF server is waiting THEN send first entry FI;
+
+END PROC into que;
+
+
+PROC list spool :
+
+ forget (ds); ds := nilspace;
+ file := sequential file (output, ds) ;
+ max line length (file, 1000);
+ headline(file, station text + "/""" + name (myself) + """");
+ put spool duty;
+ put current job;
+ put spool que;
+
+ . station text :
+ IF station(myself) = 0
+ THEN ""
+ ELSE text (station(myself))
+ FI
+
+ . put spool duty :
+ IF spool duty <> ""
+ THEN write (file, "Aufgabe: ");
+ write (file, spool duty );
+ line (file, 2);
+ FI;
+
+ . put current job :
+ IF valid fetch entry AND exists (server)
+ THEN write (file, "In Bearbeitung seit ");
+ write (file, start time);
+ write (file, ":");
+ line (file, 2);
+ putline (file, fetch entry. entry line);
+ IF stop command pending
+ THEN putline (file, "Spool wird nach diesem Auftrag deaktiviert");
+ FI;
+ line (file);
+ ELSE write (file, "kein Auftrag in Bearbeitung");
+ IF NOT exists (server)
+ THEN write (file, ", da Spool deaktiviert");
+ ELIF que is empty
+ THEN write (file, ", da Warteschlange leer");
+ LEAVE list spool;
+ FI;
+ line (file, 2);
+ FI;
+
+ . put spool que :
+ IF que is empty
+ THEN putline (file, "Warteschlange ist leer");
+ ELSE write (file, "Warteschlange (");
+ write (file, text (counter));
+ write (file, " Auftraege):");
+ line (file, 2);
+ to first que entry ;
+ WHILE next que entry found
+ REP putline (file, list entry. entry line) PER;
+ FI;
+
+END PROC list spool ;
+
+
+PROC clear spool :
+
+ first := 1;
+ last := 1;
+ counter := 0;
+ FOR list index FROM 1 UPTO que size
+ REP list entry. ds params := empty params;
+ list entry. entry line := "";
+ forget (list entry. space)
+ PER;
+
+END PROC clear spool;
+
+(*********************************************************************)
+(* Hilfsprozeduren zum Spoolmanager *)
+
+BOOL PROC is valid que entry (INT CONST index) :
+
+ que (index). entry line <> ""
+
+END PROC is valid que entry;
+
+
+INT PROC next (INT CONST index) :
+
+ IF index < que size
+ THEN index + 1
+ ELSE 1
+ FI
+
+END PROC next;
+
+
+PROC to first que entry :
+
+ list index := first - 1;
+
+ENDPROC to first que entry ;
+
+
+BOOL PROC next que entry found :
+
+ list index := next (list index);
+ WHILE is not last que entry
+ REP IF is valid que entry (list index)
+ THEN LEAVE next que entry found WITH TRUE FI;
+ list index := next (list index);
+ PER;
+ FALSE
+
+ . is not last que entry :
+ list index <> last
+
+ENDPROC next que entry found ;
+
+
+PROC get next entry line (TEXT VAR entry line, INT VAR index) :
+
+ IF index = 0
+ THEN list index := first - 1
+ ELSE list index := index
+ FI;
+ IF next que entry found
+ THEN entry line := list entry. entry line;
+ index := list index;
+ ELSE entry line := "";
+ index := 0;
+ FI;
+
+END PROC get next entry line;
+
+
+PROC new first (ENTRY VAR new first entry) :
+
+ IF que is full
+ THEN errorstop ("Spool ist voll")
+ ELSE first DECR 1 ;
+ IF first = 0 THEN first := que size FI;
+ first entry := new first entry;
+ counter INCR 1;
+ FI;
+
+END PROC new first;
+
+
+PROC erase entry (INT CONST index) :
+
+ entry. ds params := empty params;
+ entry. entry line := "";
+ forget (entry.space) ;
+ counter DECR 1;
+ IF index = first
+ THEN inc first
+ FI ;
+
+ . entry : que (index)
+
+ . inc first :
+ REP first := next (first)
+ UNTIL que is empty OR is valid que entry (first) PER
+
+END PROC erase entry;
+
+
+PROC erase fetch entry :
+
+ fetch entry. ds params := empty params;
+ fetch entry. entry line := "";
+ forget (fetch entry. space);
+ valid fetch entry := FALSE;
+
+END PROC erase fetch entry;
+
+
+BOOL PROC is entry from order task (TEXT CONST file name) :
+
+ correct order task CAND correct filename
+
+ . correct order task :
+ order task name = list entry. ds params. sendername
+ AND order task station = list entry. ds params. station
+
+ . correct file name :
+ file name = "" OR file name = list entry. ds params. name
+
+END PROC is entry from order task;
+
+
+PROC start (PROC server start):
+
+ begin (PROC server start, server);
+
+END PROC start;
+
+
+PROC stop :
+
+ stop server;
+ send calling parent reply if necessary;
+
+ . stop server:
+ IF exists (server) THEN end (server) FI;
+ server := niltask;
+ server is waiting := FALSE;
+ stop command pending := FALSE;
+
+ . send calling parent reply if necessary :
+ IF exists (calling parent)
+ THEN forget (ds); ds := nilspace;
+ send (calling parent, ack, ds);
+ calling parent := niltask;
+ FI;
+
+END PROC stop;
+
+
+PROC next headline information (TEXT VAR t):
+
+ begin pos := pos (headline (file), begin char, end pos + 1);
+ IF begin pos = 0
+ THEN begin pos := LENGTH headline (file) + 1;
+ t := "";
+ ELSE end pos := pos (headline (file), end char, begin pos + 1);
+ IF end pos = 0
+ THEN end pos := LENGTH headline (file) + 1;
+ t := "";
+ ELSE t := subtext (headline (file), begin pos+1, end pos-1)
+ FI
+ FI
+
+END PROC next headline information;
+
+
+PROC send ack :
+
+ forget (ds); ds := nilspace;
+ send (order task, ack, ds)
+
+END PROC send ack;
+
+
+PROC manager question (TEXT CONST question) :
+
+ forget (ds); ds := nilspace; error msg := ds ;
+ error msg := question ;
+ send (order task, question ack, ds)
+
+ENDPROC manager question ;
+
+
+PROC manager message (TEXT CONST message) :
+
+ forget (ds); ds := nilspace; error msg := ds ;
+ error msg := message ;
+ send (order task, message ack, ds)
+
+ENDPROC manager message ;
+
+(*********************************************************************)
+(* Spool - Kommandos *)
+
+INT VAR command index , params ;
+TEXT VAR command line, param 1, param 2 ;
+
+LET spool command list =
+"break:1.0start:2.01stop:4.0halt:5.0first:6.0killer:7.0listspool:8.0
+clearspool:9.0spoolcontrolby:10.1";
+
+PROC spool command (PROC server start) :
+
+ enable stop ;
+ continue (order - continue code) ;
+ disable stop ;
+ REP command dialogue (TRUE) ;
+ get command ("gib Spool-Kommando:", command line);
+ analyze command (spool command list, command line, 3, command index,
+ params, param1, param2);
+ execute command (PROC server start);
+ UNTIL NOT online PER;
+ command dialogue (FALSE);
+ break (quiet);
+ set autonom;
+
+END PROC spool command;
+
+
+PROC execute command (PROC server start) :
+
+ enable stop;
+ SELECT command index OF
+ CASE 1 : break
+ CASE 2 : start server
+ CASE 3 : start server with new channel
+ CASE 4 : stop server
+ CASE 5 : halt server
+ CASE 6 : first cmd
+ CASE 7 : killer cmd
+ CASE 8 : show spool list
+ CASE 9 : clear spool
+ CASE 10 : spool control task (task (param1))
+ OTHERWISE do (command line)
+ END SELECT;
+
+ . start server :
+ IF server channel <= 0 OR server channel >= 33
+ THEN line;
+ putline ("WARNUNG : Serverkanal nicht eingestellt");
+ FI;
+ stop server;
+ start (PROC server start);
+
+ . start server with new channel:
+ INT VAR i := int (param1);
+ IF last conversion ok
+ THEN server channel (i);
+ start server;
+ ELSE errorstop ("falsche Kanalangabe")
+ FI;
+
+ . stop server :
+ disable stop;
+ stop;
+ IF valid fetch entry CAND
+ yes (""13""10"" + fetch entry. entry line + " neu eintragen")
+ THEN new first (fetch entry) FI;
+ erase fetch entry;
+ enable stop;
+
+ . halt server :
+ stop command pending := TRUE;
+ IF NOT exists (server) OR server is waiting
+ THEN stop server;
+ erase fetch entry;
+ FI;
+
+ . first cmd :
+ line ;
+ to first que entry ;
+ WHILE next que entry found
+ REP say (list entry. entry line) ;
+ IF yes (" als erstes")
+ THEN new first (list entry);
+ erase entry (list index);
+ LEAVE first cmd
+ FI ;
+ PER;
+
+ . killer cmd :
+ line ;
+ to first que entry ;
+ WHILE next que entry found
+ REP say (list entry. entry line) ;
+ IF yes (" loeschen") THEN erase entry (list index) FI ;
+ PER;
+
+ . show spool list :
+ list spool;
+ disable stop;
+ show (file);
+ forget (ds);
+
+ENDPROC execute command ;
+
+ENDPACKET spool manager;
+