fixes, different traps, new files

This commit is contained in:
ceriel 1987-06-26 15:59:52 +00:00
parent 8e013368b3
commit ea69982a26
17 changed files with 798 additions and 71 deletions

View file

@ -4,6 +4,7 @@ ASCII.def
Arguments.def
Conversion.def
EM.def
PascalIo.def
InOut.def
Makefile
Mathlib.def
@ -19,3 +20,4 @@ Terminal.def
Unix.def
head_m2.e
random.def
Traps.def

View file

@ -1,6 +1,10 @@
(*$Foreign *)
DEFINITION MODULE EM;
(* An interface to EM instructions *)
(* An interface to EM instructions and data *)
FROM SYSTEM IMPORT ADDRESS;
TYPE TrapHandler = PROCEDURE(INTEGER);
PROCEDURE FIF(arg1, arg2: LONGREAL; VAR intres: LONGREAL) : LONGREAL;
(* multiplies arg1 and arg2, and returns the integer part of the
@ -14,4 +18,10 @@ DEFINITION MODULE EM;
PROCEDURE TRP(trapno: INTEGER);
(* Generate EM trap number "trapno" *)
PROCEDURE SIG(t: TrapHandler): TrapHandler;
PROCEDURE FILN(): ADDRESS;
PROCEDURE LINO(): INTEGER;
END EM.

View file

@ -58,3 +58,31 @@
trp
ret 0
end ?
#define PROC 0
; SIG is called with one parameter:
; - procedure instance identifier (PROC)
; and returns the old traphandler.
; only the procedure identifier inside the PROC is used.
exp $SIG
pro $SIG, 0
lal PROC
loi EM_PSIZE
sig
ret EM_PSIZE
end ?
exp $LINO
pro $LINO,0
loe 0
ret EM_WSIZE
end ?
exp $FILN
pro $FILN,0
lae 4
loi EM_PSIZE
ret EM_PSIZE
end ?

View file

@ -1,9 +1,8 @@
#include <em_abs.h>
IMPLEMENTATION MODULE InOut ;
IMPORT Unix;
IMPORT Conversions;
IMPORT EM;
IMPORT Traps;
FROM TTY IMPORT isatty;
FROM SYSTEM IMPORT ADR;
@ -244,7 +243,8 @@ IMPLEMENTATION MODULE InOut ;
IF (int > SAFELIMITDIV10) OR
( (int = SAFELIMITDIV10) AND
(chvalue > safedigit)) THEN
EM.TRP(EIOVFL);
Traps.Message("integer too large");
HALT;
ELSE
int := 10*int + VAL(INTEGER, chvalue);
INC(index)
@ -256,7 +256,8 @@ IMPLEMENTATION MODULE InOut ;
integ := int
END;
IF buf[index] > " " THEN
EM.TRP(66);
Traps.Message("illegal integer");
HALT;
END;
Done := TRUE;
END ReadInt;
@ -287,14 +288,16 @@ IMPLEMENTATION MODULE InOut ;
IF (int > SAFELIMITDIV10) OR
( (int = SAFELIMITDIV10) AND
(chvalue > safedigit)) THEN
EM.TRP(EIOVFL);
Traps.Message("cardinal too large");
HALT;
ELSE
int := 10*int + chvalue;
INC(index);
END;
END;
IF buf[index] > " " THEN
EM.TRP(67);
Traps.Message("illegal cardinal");
HALT;
END;
card := int;
Done := TRUE;
@ -310,7 +313,9 @@ IMPLEMENTATION MODULE InOut ;
REPEAT
Read(ch);
UNTIL NOT (ch IN charset{' ', TAB, 12C, 15C});
UnRead(ch);
IF NOT Done THEN
RETURN;
END;
REPEAT
Read(ch);
termCH := ch;
@ -322,7 +327,7 @@ IMPLEMENTATION MODULE InOut ;
END;
INC(i);
UNTIL (NOT Done) OR (ch <= " ");
UnRead(ch);
IF Done THEN UnRead(ch); END;
END ReadString;
PROCEDURE XReadString(VAR s : ARRAY OF CHAR);

View file

@ -1,4 +1,5 @@
tail_m2.a
PascalIo.mod
RealInOut.mod
InOut.mod
Terminal.mod
@ -13,9 +14,9 @@ Conversion.mod
Semaphores.mod
random.mod
Strings.mod
Traps.mod
Arguments.c
catch.c
hol0.e
LtoUset.e
StrAss.c
absd.c

View file

@ -5,7 +5,7 @@ SOURCES = ASCII.def EM.def MathLib0.def Processes.def \
RealInOut.def Storage.def Arguments.def Conversion.def \
random.def Semaphores.def Unix.def RealConver.def \
Strings.def InOut.def Terminal.def TTY.def \
Mathlib.def
Mathlib.def PascalIo.def Traps.def
all:

138
lang/m2/libm2/PascalIO.def Normal file
View file

@ -0,0 +1,138 @@
DEFINITION MODULE PascalIo;
(* This module provides for I/O that is essentially equivalent to the I/O
provided by Pascal with "text", or "file of char".
However, the user must call a cleanup routine at the end of his program
for the output buffers to be flushed.
*)
CONST EOS = 0C; (* End of string character *)
TYPE Text;
VAR input, output: Text; (* standard input and standard output available
immediately.
Standard output is not buffered when
connected to a terminal.
*)
VAR notext: Text; (* Initialize your Text variables with this *)
PROCEDURE Reset(filename: ARRAY OF CHAR; VAR inputtext: Text);
(* When inputtext indicates an open textfile, it is first flushed
and closed. Then, the file indicated by "filename" is opened for reading.
If this fails, a runtime error results. Otherwise, inputtext is
associated with the new input file.
*)
PROCEDURE Rewrite(filename: ARRAY OF CHAR; VAR outputtext: Text);
(* When outputtext indicates an open textfile, it is first flushed
and closed. Then, the file indicated by "filename" is opened for writing.
If this fails, a runtime error results. Otherwise, outputtext is
associated with the new output file.
*)
PROCEDURE PascalIoCleanup();
(* To be called at the end of the program, to flush all output buffers *)
(***************************************************************************
Input routines;
All these routines result in a runtime error when not called with either
"input", or a "Text" value obtained by Reset.
Also, the routines that actually advance the "read pointer", result in a
runtime error when end of file is reached prematurely.
****************************************************************************)
PROCEDURE NextCHAR(inputtext: Text): CHAR;
(* Returns the next character of the inputtext, 0C on end of file.
Does not advance the "read pointer", so behaves much like "input^"
in Pascal. However, unlike Pascal, if Eoln(inputtext) is true, it
returns the newline character, rather than a space.
*)
PROCEDURE Get(inputtext: Text);
(* Advances the "read pointer" by one character *)
PROCEDURE Eoln(inputtext: Text): BOOLEAN;
(* Returns TRUE if the next character of the inputtext is a linefeed *)
PROCEDURE Eof(inputtext: Text): BOOLEAN;
(* Returns TRUE if the end of the inputtext is reached *)
PROCEDURE ReadCHAR(inputtext: Text; VAR ch: CHAR);
(* Read a character from the inputtext, and leave result in "ch" *)
PROCEDURE ReadLn(inputtext: Text);
(* Skip the rest of the current line of the inputtext, including the linefeed *)
PROCEDURE ReadINTEGER(inputtext: Text; VAR int: INTEGER);
(* Skip leading blanks, read an optionally signed integer from the
inputtext, and leave the result in "int".
If no integer is read, or when overflow occurs, a runtime error results.
Input stops at the character following the integer.
*)
PROCEDURE ReadCARDINAL(inputtext: Text; VAR card: CARDINAL);
(* Skip leading blanks, read a cardinal from the inputtext, and leave the
result in "card".
If no cardinal is read, or when overflow occurs, a runtime error results.
Input stops at the character following the integer.
*)
PROCEDURE ReadREAL(inputtext: Text; VAR real: REAL);
(* Skip leading blanks, read a real from the inputtext, and leave the
result in "card".
Syntax:
real --> [(+|-)] digit {digit} [. digit {digit}]
[ (e|E) [(+|-)] digit {digit} ]
If no real is read, or when overflow/underflow occurs, a runtime error
results.
Input stops at the character following the integer.
*)
(***************************************************************************
Output routines;
All these routines result in a runtime error when not called with either
"output", or a "Text" value obtained by Rewrite.
****************************************************************************)
PROCEDURE WriteCHAR(outputtext: Text; ch: CHAR);
(* Writes the character "ch" to the outputtext *)
PROCEDURE WriteLn(outputtext: Text);
(* Writes a linefeed to the outputtext *)
PROCEDURE Page(outputtext: Text);
(* Writes a form-feed to the outputtext *)
PROCEDURE WriteINTEGER(outputtext: Text; int: INTEGER; width: CARDINAL);
(* Write integer "int" to the outputtext, using at least "width" places,
blank-padding to the left if needed.
*)
PROCEDURE WriteCARDINAL(outputtext: Text; card: CARDINAL; width: CARDINAL);
(* Write cardinal "card" to the outputtext, using at least "width" places,
blank-padding to the left if needed.
*)
PROCEDURE WriteBOOLEAN(outputtext: Text; bool: BOOLEAN; width: CARDINAL);
(* Write boolean "bool" to the outputtext, using at least "width" places,
blank-padding to the left if needed.
Equivalent to WriteSTRING(" TRUE", width), or
WriteSTRING("FALSE", width)
*)
PROCEDURE WriteSTRING(outputtext: Text;
str: ARRAY OF CHAR; width: CARDINAL);
(* Write string "str" to the outputtext, using at least "width" places,
blank-padding to the left if needed.
The string is terminated either by the character EOS, or the upperbound of
the array "str".
*)
PROCEDURE WriteREAL(outputtext: Text; real: REAL; width, nfrac: CARDINAL);
(* Write real "real" to the outputtext. If "nfrac" = 0, use scientific
notation, otherwise use fixed-point notation with "nfrac" digits behind
the dot.
Always use at least "width" places, blank-padding to the left if needed.
*)
END PascalIo.

471
lang/m2/libm2/PascalIO.mod Normal file
View file

@ -0,0 +1,471 @@
IMPLEMENTATION MODULE PascalIo;
IMPORT Unix;
IMPORT Conversions;
IMPORT Traps;
IMPORT RealConversions;
FROM TTY IMPORT isatty;
FROM Storage IMPORT ALLOCATE;
FROM SYSTEM IMPORT ADR;
TYPE charset = SET OF CHAR;
btype = (reading, writing, free);
CONST BUFSIZ = 1024; (* Tunable *)
spaces = charset{11C, 12C, 13C, 14C, 15C, ' '};
TYPE IOBuf = RECORD
type: btype;
eof: BOOLEAN;
next: Text;
fildes: INTEGER;
cnt: INTEGER;
maxcnt: INTEGER;
bufferedcount: INTEGER;
buf: ARRAY [1..BUFSIZ] OF CHAR;
END;
Text = POINTER TO IOBuf;
numbuf = ARRAY[0..255] OF CHAR;
VAR ibuf, obuf: IOBuf;
head: Text;
PROCEDURE Reset(filename: ARRAY OF CHAR; VAR inputtext: Text);
BEGIN
doclose(inputtext);
getstruct(inputtext);
WITH inputtext^ DO
eof := FALSE;
fildes := Unix.open(ADR(filename), 0);
IF fildes < 0 THEN
Traps.Message("could not open input file");
HALT;
END;
type := reading;
cnt := 1;
maxcnt := 0;
bufferedcount := BUFSIZ;
END;
END Reset;
PROCEDURE Rewrite(filename: ARRAY OF CHAR; VAR outputtext: Text);
BEGIN
doclose(outputtext);
getstruct(outputtext);
WITH outputtext^ DO
eof := FALSE;
fildes := Unix.creat(ADR(filename), 666B);
IF fildes < 0 THEN
Traps.Message("could not open output file");
HALT;
END;
type := writing;
cnt := 0;
maxcnt := 0;
bufferedcount := BUFSIZ;
END;
END Rewrite;
PROCEDURE PascalIoCleanup();
VAR text: Text;
BEGIN
text := head;
WHILE text # NIL DO
doclose(text);
text := text^.next;
END;
END PascalIoCleanup;
PROCEDURE doclose(text: Text);
VAR dummy: INTEGER;
BEGIN
IF text # notext THEN
WITH text^ DO
IF type = writing THEN
Flush(text);
END;
IF type # free THEN
type := free;
dummy := Unix.close(fildes);
END;
END;
END;
END doclose;
PROCEDURE getstruct(VAR text: Text);
BEGIN
text := head;
WHILE (text # NIL) AND (text^.type # free) DO
text := text^.next;
END;
IF text = NIL THEN
NEW(text);
text^.next := head;
head := text;
END;
END getstruct;
PROCEDURE chk(text: Text; tp: btype);
BEGIN
IF text^.type # tp THEN
IF tp = reading THEN
Traps.Message("input text expected");
ELSE
Traps.Message("output text expected");
END;
HALT;
END;
END chk;
PROCEDURE ReadCHAR(inputtext: Text; VAR ch : CHAR);
BEGIN
ch := NextCHAR(inputtext);
Get(inputtext);
END ReadCHAR;
PROCEDURE NextCHAR(inputtext: Text): CHAR;
VAR c: CHAR;
BEGIN
chk(inputtext, reading);
WITH inputtext^ DO
IF cnt <= maxcnt THEN
c := buf[cnt];
ELSE
c := FillBuf(inputtext);
END;
END;
RETURN c;
END NextCHAR;
PROCEDURE Get(inputtext: Text);
VAR dummy: CHAR;
BEGIN
chk(inputtext, reading);
WITH inputtext^ DO
IF eof THEN
(* ??? trap here ??? *)
END;
IF cnt > maxcnt THEN
dummy := FillBuf(inputtext);
END;
INC(cnt);
END;
END Get;
PROCEDURE FillBuf(ib: Text) : CHAR;
VAR c : CHAR;
BEGIN
WITH ib^ DO
IF eof THEN RETURN 0C; END;
maxcnt := Unix.read(fildes, ADR(buf), bufferedcount);
cnt := 1;
IF maxcnt <= 0 THEN
c := 0C;
eof := TRUE;
ELSE
c := buf[1];
END;
END;
RETURN c;
END FillBuf;
PROCEDURE Eoln(inputtext: Text): BOOLEAN;
BEGIN
RETURN NextCHAR(inputtext) = 12C;
END Eoln;
PROCEDURE Eof(inputtext: Text): BOOLEAN;
BEGIN
RETURN (NextCHAR(inputtext) = 0C) AND inputtext^.eof;
END Eof;
PROCEDURE ReadLn(inputtext: Text);
VAR ch: CHAR;
BEGIN
REPEAT
ReadCHAR(inputtext, ch)
UNTIL ch = 12C;
END ReadLn;
PROCEDURE Flush(ob: Text);
VAR dummy: INTEGER;
BEGIN
WITH ob^ DO
dummy := Unix.write(fildes, ADR(buf), cnt);
cnt := 0;
END;
END Flush;
PROCEDURE WriteCHAR(outputtext: Text; ch: CHAR);
BEGIN
chk(outputtext, writing);
WITH outputtext^ DO
INC(cnt);
buf[cnt] := ch;
IF cnt >= bufferedcount THEN
Flush(outputtext);
END;
END;
END WriteCHAR;
PROCEDURE WriteLn(outputtext: Text);
BEGIN
WriteCHAR(outputtext, 12C);
END WriteLn;
PROCEDURE Page(outputtext: Text);
BEGIN
WriteCHAR(outputtext, 14C);
END Page;
PROCEDURE ReadINTEGER(inputtext: Text; VAR int : INTEGER);
CONST
SAFELIMITDIV10 = MAX(INTEGER) DIV 10;
SAFELIMITREM10 = MAX(INTEGER) MOD 10;
VAR
neg : BOOLEAN;
safedigit: CARDINAL;
ch: CHAR;
chvalue: CARDINAL;
BEGIN
WHILE NextCHAR(inputtext) IN spaces DO
Get(inputtext);
END;
ch := NextCHAR(inputtext);
IF ch = '-' THEN
Get(inputtext);
ch := NextCHAR(inputtext);
neg := TRUE;
ELSIF ch = '+' THEN
Get(inputtext);
ch := NextCHAR(inputtext);
neg := FALSE;
ELSE
neg := FALSE
END;
safedigit := SAFELIMITREM10;
IF neg THEN safedigit := safedigit + 1 END;
int := 0;
IF (ch >= '0') AND (ch <= '9') THEN
WHILE (ch >= '0') & (ch <= '9') DO
chvalue := ORD(ch) - ORD('0');
IF (int < -SAFELIMITDIV10) OR
( (int = -SAFELIMITDIV10) AND
(chvalue > safedigit)) THEN
Traps.Message("integer too large");
HALT;
ELSE
int := 10*int - VAL(INTEGER, chvalue);
Get(inputtext);
ch := NextCHAR(inputtext);
END;
END;
IF NOT neg THEN
int := -int
END;
ELSE
Traps.Message("integer expected");
HALT;
END;
END ReadINTEGER;
PROCEDURE ReadCARDINAL(inputtext: Text; VAR card : CARDINAL);
CONST
SAFELIMITDIV10 = MAX(CARDINAL) DIV 10;
SAFELIMITREM10 = MAX(CARDINAL) MOD 10;
VAR
ch : CHAR;
safedigit: CARDINAL;
chvalue: CARDINAL;
BEGIN
WHILE NextCHAR(inputtext) IN spaces DO
Get(inputtext);
END;
ch := NextCHAR(inputtext);
safedigit := SAFELIMITREM10;
card := 0;
IF (ch >= '0') AND (ch <= '9') THEN
WHILE (ch >= '0') & (ch <= '9') DO
chvalue := ORD(ch) - ORD('0');
IF (card > SAFELIMITDIV10) OR
( (card = SAFELIMITDIV10) AND
(chvalue > safedigit)) THEN
Traps.Message("cardinal too large");
HALT;
ELSE
card := 10*card + chvalue;
Get(inputtext);
ch := NextCHAR(inputtext);
END;
END;
ELSE
Traps.Message("cardinal expected");
HALT;
END;
END ReadCARDINAL;
PROCEDURE ReadREAL(inputtext: Text; VAR real: REAL);
VAR
buf: numbuf;
ch: CHAR;
ok: BOOLEAN;
index: INTEGER;
BEGIN
index := 0;
WHILE NextCHAR(inputtext) IN spaces DO
Get(inputtext);
END;
ch := NextCHAR(inputtext);
IF (ch ='+') OR (ch = '-') THEN
buf[index] := ch;
INC(index);
Get(inputtext);
ch := NextCHAR(inputtext);
END;
IF (ch >= '0') AND (ch <= '9') THEN
WHILE (ch >= '0') AND (ch <= '9') DO
buf[index] := ch;
INC(index);
Get(inputtext);
ch := NextCHAR(inputtext);
END;
IF (ch = '.') THEN
IF (ch >= '0') AND (ch <= '9') THEN
WHILE (ch >= '0') AND (ch <= '9') DO
buf[index] := ch;
INC(index);
Get(inputtext);
ch := NextCHAR(inputtext);
END;
ELSE
ok := FALSE;
END;
END;
IF ok AND (ch = 'E') THEN
Get(inputtext);
ch := NextCHAR(inputtext);
IF (ch ='+') OR (ch = '-') THEN
buf[index] := ch;
INC(index);
Get(inputtext);
ch := NextCHAR(inputtext);
END;
IF (ch >= '0') AND (ch <= '9') THEN
WHILE (ch >= '0') AND (ch <= '9') DO
buf[index] := ch;
INC(index);
Get(inputtext);
ch := NextCHAR(inputtext);
END;
ELSE
ok := FALSE;
END;
END;
ELSE
ok := FALSE;
END;
IF ok THEN
buf[index] := 0C;
RealConversions.StringToReal(buf, real, ok);
END;
IF NOT ok THEN
Traps.Message("Illegal real");
HALT;
END;
END ReadREAL;
PROCEDURE WriteCARDINAL(outputtext: Text; card: CARDINAL; width: CARDINAL);
VAR
buf : numbuf;
BEGIN
Conversions.ConvertCardinal(card, 1, buf);
WriteSTRING(outputtext, buf, width);
END WriteCARDINAL;
PROCEDURE WriteINTEGER(outputtext: Text; int: INTEGER; width: CARDINAL);
VAR
buf : numbuf;
BEGIN
Conversions.ConvertInteger(int, 1, buf);
WriteSTRING(outputtext, buf, width);
END WriteINTEGER;
PROCEDURE WriteBOOLEAN(outputtext: Text; bool: BOOLEAN; width: CARDINAL);
BEGIN
IF bool THEN
WriteSTRING(outputtext, " TRUE", width);
ELSE
WriteSTRING(outputtext, "FALSE", width);
END;
END WriteBOOLEAN;
PROCEDURE WriteREAL(outputtext: Text; real: REAL; width, nfrac: CARDINAL);
VAR
buf: numbuf;
ok: BOOLEAN;
digits: INTEGER;
BEGIN
IF width > SIZE(buf) THEN
width := SIZE(buf);
END;
IF nfrac > 0 THEN
RealConversions.RealToString(real, nfrac, width, buf, ok);
ELSE
IF width < 9 THEN width := 9; END;
IF real < 0.0 THEN
digits := 7 - INTEGER(width);
ELSE
digits := 6 - INTEGER(width);
END;
RealConversions.RealToString(real, digits, width, buf, ok);
END;
WriteSTRING(outputtext, buf, 0);
END WriteREAL;
PROCEDURE WriteSTRING(outputtext: Text; str: ARRAY OF CHAR; width: CARDINAL);
VAR index: CARDINAL;
BEGIN
index := 0;
WHILE (index <= HIGH(str)) AND (str[index] # EOS) DO
INC(index);
END;
WHILE index < width DO
WriteCHAR(outputtext, " ");
INC(index);
END;
index := 0;
WHILE (index <= HIGH(str)) AND (str[index] # EOS) DO
WriteCHAR(outputtext, str[index]);
INC(index);
END;
END WriteSTRING;
BEGIN (* PascalIo initialization *)
WITH ibuf DO
eof := FALSE;
type := reading;
fildes := 0;
bufferedcount := BUFSIZ;
maxcnt := 0;
cnt := 1;
END;
WITH obuf DO
eof := FALSE;
type := writing;
fildes := 1;
IF isatty(1) THEN
bufferedcount := 1;
ELSE
bufferedcount := BUFSIZ;
END;
cnt := 0;
END;
notext := NIL;
input := ADR(ibuf);
output := ADR(obuf);
input^.next := output;
output^.next := NIL;
head := input;
END PascalIo.

View file

@ -8,6 +8,8 @@ IMPLEMENTATION MODULE Processes [1];
FROM Storage IMPORT ALLOCATE;
FROM Traps IMPORT Message;
TYPE SIGNAL = POINTER TO ProcessDescriptor;
ProcessDescriptor =
@ -72,6 +74,7 @@ IMPLEMENTATION MODULE Processes [1];
UNTIL cp^.ready;
IF cp = s0 THEN
(* deadlock *)
Message("deadlock");
HALT
END;
s0^.ready := FALSE;

View file

@ -4,7 +4,7 @@ DEFINITION MODULE RealConversions;
(* Convert string "str" to a real number "r" according to the syntax:
['+'|'-'] digit {digit} ['.' digit {digit}]
['E' ['+'|'-'] digit [digit]]
['E' ['+'|'-'] digit {digit}]
ok := "conversion succeeded"
Leading blanks are skipped;

View file

@ -187,7 +187,6 @@ IMPLEMENTATION MODULE RealConversions;
END;
IF ind1 > CARDINAL(width) THEN
ok := FALSE;
str[0] := 0C;
RETURN;
END;
IF ind1 < CARDINAL(width) THEN
@ -263,7 +262,7 @@ IMPLEMENTATION MODULE RealConversions;
END;
UNTIL (iB > HIGH(str)) OR NOT (ch IN SETOFCHAR{'0'..'9'});
END;
IF (ch = 'E') OR (ch = 'e') THEN
IF (ch = 'E') THEN
IF iB > HIGH(str) THEN
ok := FALSE;
RETURN;

View file

@ -2,7 +2,7 @@ IMPLEMENTATION MODULE RealInOut;
IMPORT InOut;
IMPORT RealConversions;
IMPORT EM;
IMPORT Traps;
FROM SYSTEM IMPORT WORD;
CONST MAXNDIG = 32;
@ -28,7 +28,8 @@ IMPLEMENTATION MODULE RealInOut;
InOut.ReadString(Buf);
RealConversions.StringToReal(Buf, x, ok);
IF NOT ok THEN
EM.TRP(68);
Traps.Message("real expected");
HALT;
END;
Done := TRUE;
END ReadReal;

View file

@ -3,6 +3,7 @@ IMPLEMENTATION MODULE Semaphores [1];
FROM SYSTEM IMPORT ADDRESS, NEWPROCESS, TRANSFER;
FROM Storage IMPORT ALLOCATE;
FROM random IMPORT Uniform;
FROM Traps IMPORT Message;
TYPE Sema = POINTER TO Semaphore;
Processes = POINTER TO Process;
@ -76,7 +77,11 @@ IMPLEMENTATION MODULE Semaphores [1];
DEC(i);
IF i = 0 THEN EXIT END;
END;
IF (cp = s0) AND (j = i) THEN (* deadlock *) HALT END;
IF (cp = s0) AND (j = i) THEN
(* deadlock *)
Message("deadlock");
HALT
END;
END;
IF cp # s0 THEN TRANSFER(s0^.proc, cp^.proc); END;
END ReSchedule;

View file

@ -3,8 +3,9 @@ IMPLEMENTATION MODULE Storage;
same size. Commonly used sizes have their own bucket. The larger ones
are put in a single list.
*)
FROM Unix IMPORT sbrk, write, exit, ILLBREAK;
FROM Unix IMPORT sbrk, write, ILLBREAK;
FROM SYSTEM IMPORT ADDRESS, ADR;
FROM Traps IMPORT Message;
CONST
NLISTS = 20;
@ -140,16 +141,11 @@ IMPLEMENTATION MODULE Storage;
END Allocate;
PROCEDURE ALLOCATE(VAR a: ADDRESS; size: CARDINAL);
VAR err: ARRAY[0..20] OF CHAR;
BEGIN
a := Allocate(size);
IF a = NIL THEN
err:= "Out of core";
err[11] := 12C;
IF write(2, ADR(err), 12) < 0 THEN
;
END;
exit(1);
Message("out of core");
HALT;
END;
END ALLOCATE;

20
lang/m2/libm2/Traps.def Normal file
View file

@ -0,0 +1,20 @@
DEFINITION MODULE Traps;
IMPORT EM;
TYPE TrapHandler = EM.TrapHandler;
PROCEDURE InstallTrapHandler(t: TrapHandler): TrapHandler;
(* Install a new trap handler, and return the previous one.
Parameter of trap handler is the trap number.
*)
PROCEDURE Message(str: ARRAY OF CHAR);
(* Write message "str" on standard error, preceeded by filename and
linenumber if possible
*)
PROCEDURE Trap(n: INTEGER);
(* cause trap number "n" to occur *)
END Traps.

77
lang/m2/libm2/Traps.mod Normal file
View file

@ -0,0 +1,77 @@
IMPLEMENTATION MODULE Traps;
IMPORT EM;
IMPORT Unix;
FROM SYSTEM IMPORT ADDRESS, ADR;
FROM Arguments IMPORT Argv;
PROCEDURE InstallTrapHandler(t: TrapHandler): TrapHandler;
(* Install a new trap handler, and return the previous one.
Parameter of trap handler is the trap number.
*)
BEGIN
RETURN EM.SIG(t);
END InstallTrapHandler;
PROCEDURE Message(str: ARRAY OF CHAR);
(* Write message "str" on standard error, preceeded by filename and
linenumber if possible
*)
VAR p, q: POINTER TO CHAR;
l: CARDINAL;
dummy, lino: INTEGER;
buf, buf2: ARRAY [0..255] OF CHAR;
i, j: CARDINAL;
BEGIN
p := EM.FILN();
IF p # NIL THEN
q := p;
WHILE p^ # 0C DO
p := ADDRESS(p) + 1;
END;
dummy := Unix.write(2, q, ADDRESS(p) - ADDRESS(q));
ELSE
l := Argv(0, buf);
dummy := Unix.write(2, ADR(buf), l);
END;
lino := EM.LINO();
i := 0;
IF lino # 0 THEN
i := 2;
buf[0] := ',';
buf[1] := ' ';
IF lino < 0 THEN
buf[2] := '-';
i := 3;
lino := - lino;
END;
j := 0;
REPEAT
buf2[j] := CHR(CARDINAL(lino) MOD 10 + ORD('0'));
lino := lino DIV 10;
INC(j);
UNTIL lino = 0;
WHILE j > 0 DO
DEC(j);
buf[i] := buf2[j];
INC(i);
END;
END;
buf[i] := ':';
buf[i+1] := ' ';
dummy := Unix.write(2, ADR(buf), i+2);
i := 0;
WHILE (i <= HIGH(str)) AND (str[i] # 0C) DO
INC(i);
END;
dummy := Unix.write(2, ADR(str), i);
buf[0] := 12C;
dummy := Unix.write(2, ADR(buf), 1);
END Message;
PROCEDURE Trap(n: INTEGER);
(* cause trap number "n" to occur *)
BEGIN
EM.TRP(n);
END Trap;
END Traps.

View file

@ -31,14 +31,9 @@ static struct errm {
{ 64, "stack size of process too large"},
{ 65, "too many nested traps + handlers"},
{ 66, "illegal integer"},
{ 67, "illegal cardinal"},
{ 68, "illegal real"},
{ -1, 0}
};
extern char *_hol0();
extern char *_argv[];
extern exit();
_catch(trapno)
@ -46,56 +41,32 @@ _catch(trapno)
{
register struct errm *ep = &errors[0];
char *errmessage;
char *pp[8];
register char **qq = &pp[0];
register char *p;
char buf[20];
register char *p, *s;
char *q;
int i;
if (p = FILN)
*qq++ = p;
else
*qq++ = _argv[0];
p = &("xxxxxxxxxxx: "[11]);
if (i = LINO) {
if (i < 0) {
/* ??? */
*qq++ = ", -";
i = -i;
}
else
*qq++ = ", ";
do
*--p = i % 10 + '0';
while (i /= 10);
}
*qq++ = p;
while (ep->errno != trapno && ep->errmes != 0) ep++;
if (ep->errmes)
*qq++ = ep->errmes;
if (p = ep->errmes) {
while (*p) p++;
Traps_Message(ep->errmes, 0, (int) (p - ep->errmes), 1);
}
else {
*qq++ = "error number";
p = &("xxxxxxxxxxx: "[11]);
i = trapno;
int i = trapno;
q = "error number xxxxxxxxxxxxx";
p = &q[13];
s = buf;
if (i < 0) {
/* ??? */
*qq++ = "-";
i = -i;
*p++ = '-';
}
do
*--p = i % 10 + '0';
*s++ = i % 10 + '0';
while (i /= 10);
*qq++ = p;
}
*qq++ = "\n";
*qq = 0;
qq = pp;
while (q = *qq++) {
p = q;
while (*p)
p++;
if (write(2,q,p-q) < 0)
;
*s = 0;
s = buf;
while (*p++ = *s++) /* nothing */;
Traps_Message(q, 0, (int) (p - q), 1);
}
exit(trapno);
}