home *** CD-ROM | disk | FTP | other *** search
- (*
- Title : Routinen:
- Demoprogramm fuer Coroutinen
- Last Edit : 12.6.87.
- Author : Joerg BEYER
- System : CP/M Turbo MODULA-2 Beta-Version
- *)
-
- (* Bitte beachten Sie, dass es trotz der relativ strengen Normen von MOUDLA-2
- unterschiedliche Implementierungen mit gewissen Unterschieden gibt. Dies
- gilt besonders fuer die Biliotheksprozeduren. Die verwendeten SYSTEM-Pro-
- zeduren und Typen entsprechen allerdings dem Wirth'schen Standard. *)
-
- MODULE Routinen;
-
- FROM InOut IMPORT WriteCard,
- WriteReal,
- WriteString,
- Write,
- WriteLn;
-
- FROM Terminal IMPORT ReadChar,
- ClearScreen;
-
- FROM SYSTEM IMPORT WORD, (* Typ zur Speicherverwaltung *)
- PROCESS, (* Typ eines Coprozesses *)
- (* In neueren MODULA-2 Implementationen wird statt PROCESS ADDRESS verwendet.
- Dies entspricht der neuesten Sprachdefinition von Niklaus Wirth
- (Programmieren in Modula-2 3.Auflage *)
- ADR, (* Typ zum Bestimmen von Speicheradressen *)
- NEWPROCESS,(* Installation des Prozesspeichers *)
- TRANSFER; (* Befehl zum Wechsel zwischen zwei *)
- (* Coroutinen *)
-
- CONST BufferSize = 500; (* fuer Prozessbuffergroesse in BYTE *)
-
- TYPE RoutineBuffer = ARRAY (. 0..((BufferSize DIV 2) -1) .) OF WORD;
- (* (. und .) kann in vielen Compilern statt *)
- (* eckiger Klammern verwendet werden *)
- VAR main,
- proc1,
- proc2,
- proc3,
- err : PROCESS; (* Prozessvariable, der eine Prozedur *)
- (* zugewiesen wird *)
- Proc1Sp, (* Variablen, die Speicherplatz fuer *)
- Proc2Sp, (* regionale PROCESS-Variablen frei- *)
- Proc3Sp, (* halten *)
- errorSp : RoutineBuffer;
-
- VAR i : CARDINAL; (* globaler Schleifenzaehler *)
-
- errMessage : ARRAY (. 0..79 .) OF CHAR;
- (* String fuer Fehlermeldung *)
- NewInstall : BOOLEAN; (* Schleifenkontrolle f. Hauptpgm. *)
-
-
- PROCEDURE Zaehler;
-
- BEGIN
- i := i + 1;
- WriteString(" Global:");
- WriteCard (i,3);
- Write(" ");
- END Zaehler;
-
-
- PROCEDURE Message(Proz : CARDINAL;
- Break: CHAR);
-
- BEGIN (* Message *)
- WriteLn;
- WriteString("Routine");
- WriteCard (Proz,1);
- WriteString(" Testpunkt ");
- Write (Break);
- Zaehler;
- END Message;
-
-
- PROCEDURE Menue;
-
- VAR hlp : CHAR;
-
- BEGIN (* Menue *)
- WriteLn;
- WriteLn; WriteString("Tastatur waehrend des Programmablaufs");
- WriteLn; WriteString("1 -> Wechsel nach Routine 1");
- WriteLn; WriteString("2 -> Wechsel nach Routine 2");
- WriteLn; WriteString("3 -> Wechsel nach Routine 3");
- WriteLn; WriteString("H -> Hilfsmenue");
- WriteLn; WriteString("E -> Ende des Programmes");
- WriteLn; WriteString("Keine Taste -> Pause ");
- WriteLn; WriteString("Uebrige Tasten -> Programmablauf");
- WriteLn;
- WriteLn; WriteString("Programmstart mit jeder Taste");
- ReadChar(hlp);
- END Menue;
-
-
- PROCEDURE ChangeRoutine(VAR proc :PROCESS);
-
- VAR hlp : CHAR;
-
- BEGIN
- ReadChar(hlp);
- hlp := CAP(hlp);
- CASE hlp OF
- | "1" : TRANSFER(proc,proc1)
- | "2" : TRANSFER(proc,proc2)
- | "3" : TRANSFER(proc,proc3)
- | "E" : TRANSFER(proc,main)
- | "H" : Menue
- ELSE
- (* garnichts *)
- END; (* CASE *)
- END ChangeRoutine;
-
-
- PROCEDURE error;
-
- BEGIN
- LOOP
- WriteLn;
- WriteString(errMessage);
- NewInstall := TRUE;
- TRANSFER(err,main);
- END (* LOOP *);
- END error;
-
-
- PROCEDURE Routine1;
-
- VAR a,b,c: REAL;
-
- BEGIN
- a := 1.2;
- b := 10.;
- LOOP
- Message(1,"A"); (* Testpunkt A *)
- c := a+b;
- WriteString("Adition ");
- WriteReal(c,3,3);
- ChangeRoutine(proc1);
- Message(1,"B"); (* Testpunkt B *)
- c := b*a;
- WriteString("Multiplikation ");
- WriteReal(c,3,3);
- ChangeRoutine(proc1);
- Message(1,"C"); (* Testpunkt C *)
- IF c = 0. THEN
- errMessage := "Division durch 0 in Routine 1";
- error;
- END (* IF *);
- c := a/b;
- WriteString("Division ");
- WriteReal(c,3,3);
- ChangeRoutine(proc1);
- a := c+2.3;
- b := b - 0.5; (* Hier wird das gelegentl. Auftreten einer *)
- END (* LOOP *); (* Div. durch 0 provoziert, um die Fehler- *)
- END Routine1; (* behandlung zu demonstieren *)
-
-
- PROCEDURE Routine2;
-
- BEGIN
- LOOP
- Message(2,"X"); (* Testpunkt X *)
- WriteString("Tick ");
- ChangeRoutine(proc2);
- Message(2,"Y"); (* Testpunkt Y *)
- WriteString("Tack ");
- ChangeRoutine(proc2);
- END (* LOOP *);
- END Routine2;
-
-
- PROCEDURE Routine3; (* Diese Prozedur ist keine endlose Schleife. Sie *)
- (* wuerde am Ende zu einem Run-Time-Error wegen *)
- VAR ch : CHAR; (* Verlassens eines PROCESS fuehren *)
-
- BEGIN
- FOR ch := "A" TO "Z" DO
- Message(3,"N"); (* Testpunkt N *)
- WriteString("Buchstabenreihe :");
- Write(ch);
- ChangeRoutine(proc3);
- END (* FOR *);
- errMessage := "Routinenende in Routine 3 erreicht";
- error; (* Hier wird das Ende *)
- END Routine3; (* des PROCESS ab- *)
- (* gefangen *)
-
- BEGIN (* Beginn des Hauptprogramms *)
- ClearScreen;
- WriteLn; WriteString("Demoprogramm fuer Coroutinen");
- WriteLn;
- WriteLn;
- (* Initialisierung *)
- i := 0;
- REPEAT
- NewInstall:= FALSE;
- Menue;
- (* Einrichten der Prozesse *)
- NEWPROCESS(error, ADR(errorSp), SIZE(errorSp),err);
- NEWPROCESS(Routine1, ADR(Proc1Sp), SIZE(Proc1Sp),proc1);
- NEWPROCESS(Routine2, ADR(Proc2Sp), SIZE(Proc2Sp),proc2);
- NEWPROCESS(Routine3, ADR(Proc3Sp), SIZE(Proc3Sp),proc3);
- (* Uebergabe an Routine 1 *)
- TRANSFER(main,proc1);
- UNTIL NOT NewInstall;
- (* Hauptprozess wird wieder aufgenommen und beendet *)
- WriteLn; WriteString("Ende des Programmes Routinen");
- END Routinen.
-