Initial revision
This commit is contained in:
parent
28bbb40835
commit
0cc5442188
14
lang/m2/libm2/ASCII.def
Normal file
14
lang/m2/libm2/ASCII.def
Normal file
|
@ -0,0 +1,14 @@
|
|||
DEFINITION MODULE ASCII;
|
||||
|
||||
CONST
|
||||
nul = 00C; soh = 01C; stx = 02C; etx = 03C;
|
||||
eot = 04C; enq = 05C; ack = 06C; bel = 07C;
|
||||
bs = 10C; ht = 11C; lf = 12C; vt = 13C;
|
||||
ff = 14C; cr = 15C; so = 16C; si = 17C;
|
||||
dle = 20C; dc1 = 21C; dc2 = 22C; dc3 = 23C;
|
||||
dc4 = 24C; nak = 25C; syn = 26C; etb = 27C;
|
||||
can = 30C; em = 31C; sub = 32C; esc = 33C;
|
||||
fs = 34C; gs = 35C; rs = 36C; us = 37C;
|
||||
del = 177C;
|
||||
|
||||
END ASCII.
|
3
lang/m2/libm2/ASCII.mod
Normal file
3
lang/m2/libm2/ASCII.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
IMPLEMENTATION MODULE ASCII;
|
||||
BEGIN
|
||||
END ASCII.
|
62
lang/m2/libm2/Arguments.c
Normal file
62
lang/m2/libm2/Arguments.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
extern char **_argv, **_environ;
|
||||
extern int _argc;
|
||||
unsigned int Arguments_Argc;
|
||||
|
||||
static char *
|
||||
findname(s1, s2)
|
||||
register char *s1, *s2;
|
||||
{
|
||||
|
||||
while (*s1 == *s2++) s1++;
|
||||
if (*s1 == '\0' && *(s2-1) == '=') return s2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
scopy(src, dst, max)
|
||||
register char *src, *dst;
|
||||
unsigned int max;
|
||||
{
|
||||
register unsigned int i = 0;
|
||||
|
||||
while (*src && i < max) {
|
||||
i++;
|
||||
*dst++ = *src++;
|
||||
}
|
||||
if (i <= max) {
|
||||
*dst = '\0';
|
||||
return i+1;
|
||||
}
|
||||
while (*src++) i++;
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
Arguments()
|
||||
{
|
||||
Arguments_Argc = _argc;
|
||||
}
|
||||
|
||||
unsigned
|
||||
Arguments_Argv(n, argument, l, u, s)
|
||||
unsigned int u;
|
||||
char *argument;
|
||||
{
|
||||
|
||||
if (n >= _argc) return 0;
|
||||
return scopy(_argv[n], argument, u);
|
||||
}
|
||||
|
||||
unsigned
|
||||
Arguments_GetEnv(name, nn, nu, ns, value, l, u, s)
|
||||
char *name, *value;
|
||||
unsigned int nu, u;
|
||||
{
|
||||
register char **p = _environ;
|
||||
register char *v = 0;
|
||||
|
||||
while (*p && !(v = findname(name, *p++))) {
|
||||
/* nothing */
|
||||
}
|
||||
if (!v) return 0;
|
||||
return scopy(v, value, u);
|
||||
}
|
32
lang/m2/libm2/Arguments.def
Normal file
32
lang/m2/libm2/Arguments.def
Normal file
|
@ -0,0 +1,32 @@
|
|||
DEFINITION MODULE Arguments;
|
||||
(* Routines and variables to access the programs arguments and
|
||||
environment
|
||||
*)
|
||||
|
||||
VAR Argc: CARDINAL; (* Number of program arguments, including the program
|
||||
name, so it is at least 1.
|
||||
*)
|
||||
|
||||
PROCEDURE Argv( argnum : CARDINAL;
|
||||
VAR argument : ARRAY OF CHAR
|
||||
) : CARDINAL;
|
||||
(* Stores the "argnum'th" argument in "argument", and returns its length,
|
||||
including a terminating null-byte. If it returns 0, the argument was not
|
||||
present, and if it returns a number larger than the size of "argument",
|
||||
"argument" was'nt large enough.
|
||||
Argument 0 contains the program name.
|
||||
*)
|
||||
|
||||
PROCEDURE GetEnv( name : ARRAY OF CHAR;
|
||||
VAR value : ARRAY OF CHAR
|
||||
) : CARDINAL;
|
||||
(* Searches the environment list for a string of the form
|
||||
name=value
|
||||
and stores the value in "value", if such a string is present.
|
||||
It returns the length of the "value" part, including a terminating
|
||||
null-byte. If it returns 0, such a string is not present, and
|
||||
if it returns a number larger than the size of the "value",
|
||||
"value" was'nt large enough.
|
||||
The string in "name" must be null_terminated.
|
||||
*)
|
||||
END Arguments.
|
20
lang/m2/libm2/Conversion.def
Normal file
20
lang/m2/libm2/Conversion.def
Normal file
|
@ -0,0 +1,20 @@
|
|||
DEFINITION MODULE Conversions;
|
||||
|
||||
PROCEDURE ConvertOctal(num, len: CARDINAL; VAR str: ARRAY OF CHAR);
|
||||
(* Convert number "num" to right-justified octal representation of
|
||||
"len" positions, and put the result in "str".
|
||||
If the result does not fit in "str", it is truncated on the right.
|
||||
*)
|
||||
|
||||
PROCEDURE ConvertHex(num, len: CARDINAL; VAR str: ARRAY OF CHAR);
|
||||
(* Convert a hexadecimal number to a string *)
|
||||
|
||||
PROCEDURE ConvertCardinal(num, len: CARDINAL; VAR str: ARRAY OF CHAR);
|
||||
(* Convert a cardinal number to a string *)
|
||||
|
||||
PROCEDURE ConvertInteger(num: INTEGER;
|
||||
len: CARDINAL;
|
||||
VAR str: ARRAY OF CHAR);
|
||||
(* Convert an integer number to a string *)
|
||||
|
||||
END Conversions.
|
59
lang/m2/libm2/Conversion.mod
Normal file
59
lang/m2/libm2/Conversion.mod
Normal file
|
@ -0,0 +1,59 @@
|
|||
IMPLEMENTATION MODULE Conversions;
|
||||
|
||||
PROCEDURE ConvertNum(num, len, base: CARDINAL;
|
||||
neg: BOOLEAN;
|
||||
VAR str: ARRAY OF CHAR);
|
||||
VAR i: CARDINAL;
|
||||
r: CARDINAL;
|
||||
tmp: ARRAY [0..20] OF CHAR;
|
||||
BEGIN
|
||||
i := 0;
|
||||
IF neg THEN
|
||||
tmp[0] := '-';
|
||||
i := 1;
|
||||
END;
|
||||
REPEAT
|
||||
r := num MOD base;
|
||||
num := num DIV base;
|
||||
IF r <= 9 THEN
|
||||
tmp[i] := CHR(r + ORD('0'));
|
||||
ELSE
|
||||
tmp[i] := CHR(r - 10 + ORD('A'));
|
||||
END;
|
||||
INC(i);
|
||||
UNTIL num = 0;
|
||||
IF len > HIGH(str) + 1 THEN len := HIGH(str) + 1; END;
|
||||
IF i > HIGH(str) + 1 THEN i := HIGH(str) + 1; END;
|
||||
r := 0;
|
||||
WHILE len > i DO str[r] := ' '; INC(r); DEC(len); END;
|
||||
WHILE i > 0 DO str[r] := tmp[i-1]; DEC(i); INC(r); END;
|
||||
IF r <= HIGH(str) THEN str[r] := 0C; END;
|
||||
END ConvertNum;
|
||||
|
||||
PROCEDURE ConvertOctal(num, len: CARDINAL; VAR str: ARRAY OF CHAR);
|
||||
BEGIN
|
||||
ConvertNum(num, len, 8, FALSE, str);
|
||||
END ConvertOctal;
|
||||
|
||||
PROCEDURE ConvertHex(num, len: CARDINAL; VAR str: ARRAY OF CHAR);
|
||||
BEGIN
|
||||
ConvertNum(num, len, 16, FALSE, str);
|
||||
END ConvertHex;
|
||||
|
||||
PROCEDURE ConvertCardinal(num, len: CARDINAL; VAR str: ARRAY OF CHAR);
|
||||
BEGIN
|
||||
ConvertNum(num, len, 10, FALSE, str);
|
||||
END ConvertCardinal;
|
||||
|
||||
PROCEDURE ConvertInteger(num: INTEGER;
|
||||
len: CARDINAL;
|
||||
VAR str: ARRAY OF CHAR);
|
||||
BEGIN
|
||||
IF num < 0 THEN
|
||||
ConvertNum(-num, len, 10, TRUE, str);
|
||||
ELSE
|
||||
ConvertNum(num, len, 10, FALSE, str);
|
||||
END;
|
||||
END ConvertInteger;
|
||||
|
||||
END Conversions.
|
12
lang/m2/libm2/FIFFEF.def
Normal file
12
lang/m2/libm2/FIFFEF.def
Normal file
|
@ -0,0 +1,12 @@
|
|||
DEFINITION MODULE FIFFEF;
|
||||
|
||||
PROCEDURE FIF(arg1, arg2: REAL; VAR intres: REAL) : REAL;
|
||||
(* multiplies arg1 and arg2, and returns the integer part of the
|
||||
result in "intres" and the fraction part as the function result.
|
||||
*)
|
||||
|
||||
PROCEDURE FEF(arg: REAL; VAR exp: INTEGER) : REAL;
|
||||
(* splits "arg" in mantissa and a base-2 exponent.
|
||||
The mantissa is returned, and the exponent is left in "exp".
|
||||
*)
|
||||
END FIFFEF.
|
51
lang/m2/libm2/FIFFEF.e
Normal file
51
lang/m2/libm2/FIFFEF.e
Normal file
|
@ -0,0 +1,51 @@
|
|||
#
|
||||
mes 2,EM_WSIZE,EM_PSIZE
|
||||
|
||||
#define ARG1 0
|
||||
#define ARG2 EM_FSIZE
|
||||
#define IRES 2*EM_FSIZE
|
||||
|
||||
; FIFFEF_FIF is called with three parameters:
|
||||
; - address of integer part result (IRES)
|
||||
; - float two (ARG2)
|
||||
; - float one (ARG1)
|
||||
; and returns an EM_FSIZE-byte floating point number
|
||||
; Definition:
|
||||
; PROCEDURE FIF(ARG1, ARG2: REAL; VAR IRES: REAL) : REAL;
|
||||
|
||||
exp $FIFFEF_FIF
|
||||
pro $FIFFEF_FIF,0
|
||||
lal 0
|
||||
loi 2*EM_FSIZE
|
||||
fif EM_FSIZE
|
||||
lal IRES
|
||||
loi EM_PSIZE
|
||||
sti EM_FSIZE
|
||||
ret EM_FSIZE
|
||||
end ?
|
||||
|
||||
#define FARG 0
|
||||
#define ERES EM_FSIZE
|
||||
|
||||
; FIFFEF_FEF is called with two parameters:
|
||||
; - address of base 2 exponent result (ERES)
|
||||
; - floating point number to be split (FARG)
|
||||
; and returns an EM_FSIZE-byte floating point number (the mantissa)
|
||||
; Definition:
|
||||
; PROCEDURE FEF(FARG: REAL; VAR ERES: integer): REAL;
|
||||
|
||||
exp $FIFFEF_FEF
|
||||
pro $FIFFEF_FEF,0
|
||||
lal FARG
|
||||
loi EM_FSIZE
|
||||
fef EM_FSIZE
|
||||
lal ERES
|
||||
loi EM_PSIZE
|
||||
sti EM_WSIZE
|
||||
ret EM_FSIZE
|
||||
end ?
|
||||
|
||||
exp $FIFFEF
|
||||
pro $FIFFEF,0
|
||||
ret 0
|
||||
end ?
|
108
lang/m2/libm2/InOut.def
Normal file
108
lang/m2/libm2/InOut.def
Normal file
|
@ -0,0 +1,108 @@
|
|||
DEFINITION MODULE InOut;
|
||||
|
||||
CONST EOL = 12C;
|
||||
|
||||
VAR Done : BOOLEAN;
|
||||
termCH : CHAR;
|
||||
|
||||
PROCEDURE OpenInput(defext: ARRAY OF CHAR);
|
||||
(* Request a file name from the standard input stream and open
|
||||
this file for reading.
|
||||
If the filename ends with a '.', append the "defext" extension.
|
||||
Done := "file was successfully opened".
|
||||
If open, subsequent input is read from this file.
|
||||
*)
|
||||
|
||||
PROCEDURE OpenOutput(defext : ARRAY OF CHAR);
|
||||
(* Request a file name from the standard input stream and open
|
||||
this file for writing.
|
||||
If the filename ends with a '.', append the "defext" extension.
|
||||
Done := "file was successfully opened".
|
||||
If open, subsequent output is written to this file.
|
||||
*)
|
||||
|
||||
PROCEDURE OpenInputFile(filename: ARRAY OF CHAR);
|
||||
(* Like OpenInput, but filename given as parameter
|
||||
*)
|
||||
|
||||
PROCEDURE OpenOutputFile(filename: ARRAY OF CHAR);
|
||||
(* Like OpenOutput, but filename given as parameter
|
||||
*)
|
||||
|
||||
PROCEDURE CloseInput;
|
||||
(* Close input file. Subsequent input is read from the standard input
|
||||
stream.
|
||||
*)
|
||||
|
||||
PROCEDURE CloseOutput;
|
||||
(* Close output file. Subsequent output is written to the standard
|
||||
output stream.
|
||||
*)
|
||||
|
||||
PROCEDURE Read(VAR ch : CHAR);
|
||||
(* Read a character from the current input stream and leave it in "ch".
|
||||
Done := NOT "end of file".
|
||||
*)
|
||||
|
||||
PROCEDURE ReadString(VAR s : ARRAY OF CHAR);
|
||||
(* Read a string from the current input stream and leave it in "s".
|
||||
A string is any sequence of characters not containing blanks or
|
||||
control characters; leading blanks are ignored.
|
||||
Input is terminated by any character <= " ".
|
||||
This character is assigned to termCH.
|
||||
DEL or BACKSPACE is used for backspacing when input from terminal.
|
||||
*)
|
||||
|
||||
PROCEDURE ReadInt(VAR x : INTEGER);
|
||||
(* Read a string and convert it to INTEGER.
|
||||
Syntax: integer = ['+'|'-'] digit {digit}.
|
||||
Leading blanks are ignored.
|
||||
Done := "integer was read".
|
||||
*)
|
||||
|
||||
PROCEDURE ReadCard(VAR x : CARDINAL);
|
||||
(* Read a string and convert it to CARDINAL.
|
||||
Syntax: cardinal = digit {digit}.
|
||||
Leading blanks are ignored.
|
||||
Done := "cardinal was read".
|
||||
*)
|
||||
|
||||
PROCEDURE Write(ch : CHAR);
|
||||
(* Write character "ch" to the current output stream.
|
||||
*)
|
||||
|
||||
PROCEDURE WriteLn;
|
||||
(* Terminate line.
|
||||
*)
|
||||
|
||||
PROCEDURE WriteString(s : ARRAY OF CHAR);
|
||||
(* Write string "s" to the current output stream
|
||||
*)
|
||||
|
||||
PROCEDURE WriteInt(x : INTEGER; n : CARDINAL);
|
||||
(* Write integer x with (at least) n characters on the current output
|
||||
stream. If n is greater that the number of digits needed,
|
||||
blanks are added preceding the number.
|
||||
*)
|
||||
|
||||
PROCEDURE WriteCard(x, n : CARDINAL);
|
||||
(* Write cardinal x with (at least) n characters on the current output
|
||||
stream. If n is greater that the number of digits needed,
|
||||
blanks are added preceding the number.
|
||||
*)
|
||||
|
||||
PROCEDURE WriteOct(x, n : CARDINAL);
|
||||
(* Write cardinal x as an octal number with (at least) n characters
|
||||
on the current output stream.
|
||||
If n is greater that the number of digits needed,
|
||||
blanks are added preceding the number.
|
||||
*)
|
||||
|
||||
PROCEDURE WriteHex(x, n : CARDINAL);
|
||||
(* Write cardinal x as a hexadecimal number with (at least)
|
||||
n characters on the current output stream.
|
||||
If n is greater that the number of digits needed,
|
||||
blanks are added preceding the number.
|
||||
*)
|
||||
|
||||
END InOut.
|
420
lang/m2/libm2/InOut.mod
Normal file
420
lang/m2/libm2/InOut.mod
Normal file
|
@ -0,0 +1,420 @@
|
|||
IMPLEMENTATION MODULE InOut ;
|
||||
|
||||
IMPORT Unix;
|
||||
IMPORT Conversions;
|
||||
FROM TTY IMPORT isatty;
|
||||
FROM SYSTEM IMPORT ADR;
|
||||
|
||||
CONST BUFSIZ = 1024; (* Tunable *)
|
||||
TAB = 11C;
|
||||
|
||||
TYPE IOBuf = RECORD
|
||||
fildes: INTEGER;
|
||||
cnt: INTEGER;
|
||||
maxcnt: INTEGER;
|
||||
bufferedcount: INTEGER;
|
||||
buf: ARRAY [1..BUFSIZ] OF CHAR;
|
||||
END;
|
||||
numbuf = ARRAY[0..255] OF CHAR;
|
||||
|
||||
VAR ibuf, obuf: IOBuf;
|
||||
unread: BOOLEAN;
|
||||
unreadch: CHAR;
|
||||
|
||||
PROCEDURE Read(VAR c : CHAR);
|
||||
BEGIN
|
||||
IF unread THEN
|
||||
unread := FALSE;
|
||||
c := unreadch;
|
||||
ELSE
|
||||
WITH ibuf DO
|
||||
IF cnt <= maxcnt THEN
|
||||
c := buf[cnt];
|
||||
INC(cnt);
|
||||
Done := TRUE;
|
||||
ELSE
|
||||
c := FillBuf(ibuf);
|
||||
END;
|
||||
END;
|
||||
END;
|
||||
END Read;
|
||||
|
||||
PROCEDURE UnRead(ch: CHAR);
|
||||
BEGIN
|
||||
unread := TRUE;
|
||||
unreadch := ch;
|
||||
END UnRead;
|
||||
|
||||
PROCEDURE FillBuf(VAR ib: IOBuf) : CHAR;
|
||||
VAR c : CHAR;
|
||||
BEGIN
|
||||
WITH ib DO
|
||||
maxcnt := Unix.read(fildes, ADR(buf), bufferedcount);
|
||||
cnt := 2;
|
||||
Done := maxcnt > 0;
|
||||
IF NOT Done THEN
|
||||
c := 0C;
|
||||
ELSE
|
||||
c := buf[1];
|
||||
END;
|
||||
END;
|
||||
RETURN c;
|
||||
END FillBuf;
|
||||
|
||||
PROCEDURE Flush(VAR ob: IOBuf);
|
||||
VAR dummy: INTEGER;
|
||||
BEGIN
|
||||
WITH ob DO
|
||||
dummy := Unix.write(fildes, ADR(buf), cnt);
|
||||
cnt := 0;
|
||||
END;
|
||||
END Flush;
|
||||
|
||||
PROCEDURE Write(c: CHAR);
|
||||
BEGIN
|
||||
WITH obuf DO
|
||||
INC(cnt);
|
||||
buf[cnt] := c;
|
||||
IF cnt >= bufferedcount THEN
|
||||
Flush(obuf);
|
||||
END;
|
||||
END;
|
||||
END Write;
|
||||
|
||||
PROCEDURE OpenInput(defext: ARRAY OF CHAR);
|
||||
VAR namebuf : ARRAY [1..256] OF CHAR;
|
||||
BEGIN
|
||||
IF ibuf.fildes # 0 THEN
|
||||
CloseInput;
|
||||
END;
|
||||
MakeFileName("Name of input file: ", defext, namebuf);
|
||||
IF (namebuf[1] = '-') AND (namebuf[2] = 0C) THEN
|
||||
ELSE
|
||||
WITH ibuf DO
|
||||
fildes := Unix.open(ADR(namebuf), 0);
|
||||
Done := fildes >= 0;
|
||||
maxcnt := 0;
|
||||
cnt := 1;
|
||||
END;
|
||||
END;
|
||||
END OpenInput;
|
||||
|
||||
PROCEDURE OpenInputFile(filename: ARRAY OF CHAR);
|
||||
BEGIN
|
||||
IF ibuf.fildes # 0 THEN
|
||||
CloseInput;
|
||||
END;
|
||||
IF (filename[0] = '-') AND (filename[1] = 0C) THEN
|
||||
ELSE
|
||||
WITH ibuf DO
|
||||
fildes := Unix.open(ADR(filename), 0);
|
||||
Done := fildes >= 0;
|
||||
maxcnt := 0;
|
||||
cnt := 1;
|
||||
END;
|
||||
END;
|
||||
END OpenInputFile;
|
||||
|
||||
PROCEDURE CloseInput;
|
||||
BEGIN
|
||||
WITH ibuf DO
|
||||
IF (fildes > 0) AND (Unix.close(fildes) < 0) THEN
|
||||
;
|
||||
END;
|
||||
fildes := 0;
|
||||
maxcnt := 0;
|
||||
cnt := 1;
|
||||
END;
|
||||
END CloseInput;
|
||||
|
||||
PROCEDURE OpenOutput(defext: ARRAY OF CHAR);
|
||||
VAR namebuf : ARRAY [1..256] OF CHAR;
|
||||
BEGIN
|
||||
IF obuf.fildes # 1 THEN
|
||||
CloseOutput;
|
||||
END;
|
||||
MakeFileName("Name of output file: ", defext, namebuf);
|
||||
IF (namebuf[1] = '-') AND (namebuf[2] = 0C) THEN
|
||||
ELSE
|
||||
WITH obuf DO
|
||||
fildes := Unix.creat(ADR(namebuf), 666B);
|
||||
Done := fildes >= 0;
|
||||
bufferedcount := BUFSIZ;
|
||||
cnt := 0;
|
||||
END;
|
||||
END;
|
||||
END OpenOutput;
|
||||
|
||||
PROCEDURE OpenOutputFile(filename: ARRAY OF CHAR);
|
||||
BEGIN
|
||||
IF obuf.fildes # 1 THEN
|
||||
CloseOutput;
|
||||
END;
|
||||
IF (filename[0] = '-') AND (filename[1] = 0C) THEN
|
||||
ELSE
|
||||
WITH obuf DO
|
||||
fildes := Unix.creat(ADR(filename), 666B);
|
||||
Done := fildes >= 0;
|
||||
bufferedcount := BUFSIZ;
|
||||
cnt := 0;
|
||||
END;
|
||||
END;
|
||||
END OpenOutputFile;
|
||||
|
||||
PROCEDURE CloseOutput;
|
||||
BEGIN
|
||||
Flush(obuf);
|
||||
WITH obuf DO
|
||||
IF (fildes # 1) AND (Unix.close(fildes) < 0) THEN
|
||||
;
|
||||
END;
|
||||
fildes := 1;
|
||||
bufferedcount := 1;
|
||||
cnt := 0;
|
||||
END;
|
||||
END CloseOutput;
|
||||
|
||||
PROCEDURE MakeFileName(prompt, defext : ARRAY OF CHAR;
|
||||
VAR buf : ARRAY OF CHAR);
|
||||
VAR i, k : INTEGER;
|
||||
j : CARDINAL;
|
||||
ch: CHAR;
|
||||
BEGIN
|
||||
FOR k := 1 TO 3 DO
|
||||
IF isatty(0) THEN
|
||||
XWriteString(prompt);
|
||||
END;
|
||||
XReadString(buf);
|
||||
i := 0;
|
||||
WHILE buf[i] # 0C DO i := i + 1 END;
|
||||
IF i # 0 THEN
|
||||
i := i - 1;
|
||||
IF buf[i] = '.' THEN
|
||||
FOR j := 0 TO HIGH(defext) DO
|
||||
i := i + 1;
|
||||
buf[i] := defext[j];
|
||||
END;
|
||||
buf[i+1] := 0C;
|
||||
END;
|
||||
RETURN;
|
||||
END;
|
||||
END;
|
||||
Error("no proper file name in three attempts. Giving up.");
|
||||
END MakeFileName;
|
||||
|
||||
PROCEDURE Error(s: ARRAY OF CHAR);
|
||||
VAR Xch: ARRAY[1..1] OF CHAR;
|
||||
BEGIN
|
||||
XWriteString("Error: ");
|
||||
XWriteString(s);
|
||||
Xch[1] := 12C;
|
||||
XWriteString(Xch);
|
||||
Unix.exit(1);
|
||||
END Error;
|
||||
|
||||
PROCEDURE ReadInt(VAR integ : INTEGER);
|
||||
CONST
|
||||
SAFELIMITDIV10 = MAX(INTEGER) DIV 10;
|
||||
SAFELIMITREM10 = MAX(INTEGER) MOD 10;
|
||||
VAR
|
||||
int : INTEGER;
|
||||
ch : CHAR;
|
||||
neg : BOOLEAN;
|
||||
safedigit: [0 .. 9];
|
||||
chvalue: CARDINAL;
|
||||
BEGIN
|
||||
Read(ch);
|
||||
WHILE (ch = ' ') OR (ch = TAB) OR (ch = 12C) DO
|
||||
Read(ch)
|
||||
END;
|
||||
IF ch = '-' THEN
|
||||
neg := TRUE;
|
||||
Read(ch)
|
||||
ELSIF ch = '+' THEN
|
||||
neg := FALSE;
|
||||
Read(ch)
|
||||
ELSE
|
||||
neg := FALSE
|
||||
END;
|
||||
|
||||
safedigit := SAFELIMITREM10;
|
||||
IF neg THEN safedigit := safedigit + 1 END;
|
||||
int := 0;
|
||||
IF (ch >= '0') & (ch <= '9') THEN
|
||||
WHILE (ch >= '0') & (ch <= '9') DO
|
||||
chvalue := ORD(ch) - ORD('0');
|
||||
IF (int > SAFELIMITDIV10) OR
|
||||
( (int = SAFELIMITDIV10) AND
|
||||
(chvalue > safedigit)) THEN
|
||||
Error("integer overflow");
|
||||
ELSE
|
||||
int := 10*int + VAL(INTEGER, chvalue);
|
||||
Read(ch)
|
||||
END;
|
||||
END;
|
||||
IF neg THEN
|
||||
integ := -int
|
||||
ELSE
|
||||
integ := int
|
||||
END;
|
||||
Done := TRUE;
|
||||
ELSE
|
||||
Done := FALSE
|
||||
END;
|
||||
UnRead(ch)
|
||||
END ReadInt;
|
||||
|
||||
PROCEDURE ReadCard(VAR card : CARDINAL);
|
||||
CONST
|
||||
SAFELIMITDIV10 = MAX(CARDINAL) DIV 10;
|
||||
SAFELIMITREM10 = MAX(CARDINAL) MOD 10;
|
||||
|
||||
VAR
|
||||
int : CARDINAL;
|
||||
ch : CHAR;
|
||||
safedigit: [0 .. 9];
|
||||
chvalue: CARDINAL;
|
||||
BEGIN
|
||||
Read(ch);
|
||||
WHILE (ch = ' ') OR (ch = TAB) OR (ch = 12C) DO
|
||||
Read(ch)
|
||||
END;
|
||||
|
||||
safedigit := SAFELIMITREM10;
|
||||
int := 0;
|
||||
IF (ch >= '0') & (ch <= '9') THEN
|
||||
WHILE (ch >= '0') & (ch <= '9') DO
|
||||
chvalue := ORD(ch) - ORD('0');
|
||||
IF (int > SAFELIMITDIV10) OR
|
||||
( (int = SAFELIMITDIV10) AND
|
||||
(chvalue > safedigit)) THEN
|
||||
Error("cardinal overflow");
|
||||
ELSE
|
||||
int := 10*int + chvalue;
|
||||
Read(ch)
|
||||
END;
|
||||
END;
|
||||
card := int;
|
||||
Done := TRUE;
|
||||
ELSE
|
||||
Done := FALSE
|
||||
END;
|
||||
UnRead(ch)
|
||||
END ReadCard;
|
||||
|
||||
PROCEDURE ReadString(VAR s : ARRAY OF CHAR);
|
||||
VAR i : CARDINAL;
|
||||
ch : CHAR;
|
||||
|
||||
BEGIN
|
||||
i := 0;
|
||||
LOOP
|
||||
Read(ch);
|
||||
termCH := ch;
|
||||
IF (NOT Done) OR (ch <= " ") THEN s[i] := 0C; RETURN END;
|
||||
s[i] := ch;
|
||||
INC(i);
|
||||
IF i > HIGH(s) THEN DEC(i); END;
|
||||
END;
|
||||
END ReadString;
|
||||
|
||||
PROCEDURE XReadString(VAR s : ARRAY OF CHAR);
|
||||
VAR i : INTEGER;
|
||||
j : CARDINAL;
|
||||
ch : CHAR;
|
||||
|
||||
BEGIN
|
||||
j := 0;
|
||||
LOOP
|
||||
i := Unix.read(0, ADR(ch), 1);
|
||||
IF i < 0 THEN
|
||||
Error("failed read");
|
||||
END;
|
||||
IF ch <= " " THEN
|
||||
s[j] := 0C;
|
||||
EXIT;
|
||||
END;
|
||||
IF j < HIGH(s) THEN
|
||||
s[j] := ch;
|
||||
INC(j);
|
||||
END;
|
||||
END;
|
||||
END XReadString;
|
||||
|
||||
PROCEDURE XWriteString(s: ARRAY OF CHAR);
|
||||
VAR i: CARDINAL;
|
||||
BEGIN
|
||||
i := 0;
|
||||
LOOP
|
||||
IF (i <= HIGH(s)) AND (s[i] # 0C) THEN
|
||||
INC(i);
|
||||
ELSE
|
||||
EXIT;
|
||||
END;
|
||||
END;
|
||||
IF Unix.write(1, ADR(s), i) < 0 THEN
|
||||
;
|
||||
END;
|
||||
END XWriteString;
|
||||
|
||||
PROCEDURE WriteCard(card, width : CARDINAL);
|
||||
VAR
|
||||
buf : numbuf;
|
||||
BEGIN
|
||||
Conversions.ConvertCardinal(card, width, buf);
|
||||
WriteString(buf);
|
||||
END WriteCard;
|
||||
|
||||
PROCEDURE WriteInt(int : INTEGER; width : CARDINAL);
|
||||
VAR
|
||||
buf : numbuf;
|
||||
BEGIN
|
||||
Conversions.ConvertInteger(int, width, buf);
|
||||
WriteString(buf);
|
||||
END WriteInt;
|
||||
|
||||
PROCEDURE WriteHex(card, width : CARDINAL);
|
||||
VAR
|
||||
buf : numbuf;
|
||||
BEGIN
|
||||
Conversions.ConvertHex(card, width, buf);
|
||||
WriteString(buf);
|
||||
END WriteHex;
|
||||
|
||||
PROCEDURE WriteLn;
|
||||
BEGIN
|
||||
Write(EOL)
|
||||
END WriteLn;
|
||||
|
||||
PROCEDURE WriteOct(card, width : CARDINAL);
|
||||
VAR
|
||||
buf : numbuf;
|
||||
BEGIN
|
||||
Conversions.ConvertOctal(card, width, buf);
|
||||
WriteString(buf);
|
||||
END WriteOct;
|
||||
|
||||
PROCEDURE WriteString(str : ARRAY OF CHAR);
|
||||
VAR
|
||||
nbytes : CARDINAL;
|
||||
BEGIN
|
||||
nbytes := 0;
|
||||
WHILE (nbytes <= HIGH(str)) AND (str[nbytes] # 0C) DO
|
||||
Write(str[nbytes]);
|
||||
INC(nbytes)
|
||||
END;
|
||||
END WriteString;
|
||||
|
||||
BEGIN (* InOut initialization *)
|
||||
WITH ibuf DO
|
||||
fildes := 0;
|
||||
bufferedcount := BUFSIZ;
|
||||
maxcnt := 0;
|
||||
cnt := 1;
|
||||
END;
|
||||
WITH obuf DO
|
||||
fildes := 1;
|
||||
bufferedcount := 1;
|
||||
cnt := 0;
|
||||
END;
|
||||
END InOut.
|
28
lang/m2/libm2/LIST
Normal file
28
lang/m2/libm2/LIST
Normal file
|
@ -0,0 +1,28 @@
|
|||
tail_m2.a
|
||||
InOut.mod
|
||||
Terminal.mod
|
||||
TTY.mod
|
||||
ASCII.mod
|
||||
FIFFEF.e
|
||||
MathLib0.mod
|
||||
Processes.mod
|
||||
RealInOut.mod
|
||||
Storage.mod
|
||||
Conversion.mod
|
||||
Semaphores.mod
|
||||
random.mod
|
||||
Strings.mod
|
||||
Arguments.c
|
||||
catch.c
|
||||
hol0.e
|
||||
LtoUset.e
|
||||
StrAss.c
|
||||
absd.c
|
||||
absf.e
|
||||
absi.c
|
||||
absl.c
|
||||
halt.c
|
||||
transfer.e
|
||||
store.c
|
||||
load.c
|
||||
stackprio.c
|
38
lang/m2/libm2/LtoUset.e
Normal file
38
lang/m2/libm2/LtoUset.e
Normal file
|
@ -0,0 +1,38 @@
|
|||
#
|
||||
mes 2,EM_WSIZE,EM_PSIZE
|
||||
|
||||
; _LtoUset is called for set displays containing { expr1 .. expr2 }.
|
||||
; It has five parameters, of which the caller must pop four:
|
||||
; - The set in which bits must be set.
|
||||
; - The set size in bytes.
|
||||
; - The upper bound of set elements, specified by the set-type.
|
||||
; - "expr2", the upper bound
|
||||
; - "expr1", the lower bound
|
||||
|
||||
#define SETBASE 4*EM_WSIZE
|
||||
#define SETSIZE 3*EM_WSIZE
|
||||
#define USETSIZ 2*EM_WSIZE
|
||||
#define LWB EM_WSIZE
|
||||
#define UPB 0
|
||||
exp $_LtoUset
|
||||
pro $_LtoUset,0
|
||||
lal SETBASE ; address of initial set
|
||||
lol SETSIZE
|
||||
los EM_WSIZE ; load initial set
|
||||
1
|
||||
lol LWB ; low bound
|
||||
lol UPB ; high bound
|
||||
bgt *2 ; while low <= high
|
||||
lol LWB
|
||||
lol SETSIZE
|
||||
set ? ; create [low]
|
||||
lol SETSIZE
|
||||
ior ? ; merge with initial set
|
||||
inl LWB ; increment low bound
|
||||
bra *1 ; loop back
|
||||
2
|
||||
lal SETBASE
|
||||
lol SETSIZE
|
||||
sts EM_WSIZE ; store result over initial set
|
||||
ret 0
|
||||
end 0
|
13
lang/m2/libm2/Makefile
Normal file
13
lang/m2/libm2/Makefile
Normal file
|
@ -0,0 +1,13 @@
|
|||
HOME = ../../..
|
||||
DEFDIR = $(HOME)/lib/m2
|
||||
|
||||
SOURCES = ASCII.def FIFFEF.def MathLib0.def Processes.def \
|
||||
RealInOut.def Storage.def Arguments.def Conversion.def \
|
||||
random.def Semaphores.def Unix.def \
|
||||
Strings.def InOut.def Terminal.def TTY.def
|
||||
|
||||
all:
|
||||
|
||||
install:
|
||||
-mkdir $(DEFDIR)
|
||||
for i in $(SOURCES) ; do cp $$i $(DEFDIR)/$$i ; done
|
19
lang/m2/libm2/MathLib0.def
Normal file
19
lang/m2/libm2/MathLib0.def
Normal file
|
@ -0,0 +1,19 @@
|
|||
DEFINITION MODULE MathLib0;
|
||||
|
||||
PROCEDURE sqrt(x : REAL) : REAL;
|
||||
|
||||
PROCEDURE exp(x : REAL) : REAL;
|
||||
|
||||
PROCEDURE ln(x : REAL) : REAL;
|
||||
|
||||
PROCEDURE sin(x : REAL) : REAL;
|
||||
|
||||
PROCEDURE cos(x : REAL) : REAL;
|
||||
|
||||
PROCEDURE arctan(x : REAL) : REAL;
|
||||
|
||||
PROCEDURE real(x : INTEGER) : REAL;
|
||||
|
||||
PROCEDURE entier(x : REAL) : INTEGER;
|
||||
|
||||
END MathLib0.
|
337
lang/m2/libm2/MathLib0.mod
Normal file
337
lang/m2/libm2/MathLib0.mod
Normal file
|
@ -0,0 +1,337 @@
|
|||
IMPLEMENTATION MODULE MathLib0;
|
||||
(* Rewritten in Modula-2.
|
||||
The originals came from the Pascal runtime library.
|
||||
*)
|
||||
|
||||
FROM FIFFEF IMPORT FIF, FEF;
|
||||
|
||||
CONST
|
||||
HUGE = 1.701411733192644270E38;
|
||||
|
||||
PROCEDURE sinus(arg: REAL; quad: INTEGER): REAL;
|
||||
|
||||
(* Coefficients for sin/cos are #3370 from Hart & Cheney (18.80D).
|
||||
*)
|
||||
CONST
|
||||
twoopi = 0.63661977236758134308;
|
||||
p0 = 0.1357884097877375669092680E8;
|
||||
p1 = -0.4942908100902844161158627E7;
|
||||
p2 = 0.4401030535375266501944918E6;
|
||||
p3 = -0.1384727249982452873054457E5;
|
||||
p4 = 0.1459688406665768722226959E3;
|
||||
q0 = 0.8644558652922534429915149E7;
|
||||
q1 = 0.4081792252343299749395779E6;
|
||||
q2 = 0.9463096101538208180571257E4;
|
||||
q3 = 0.1326534908786136358911494E3;
|
||||
VAR
|
||||
e, f: REAL;
|
||||
ysq: REAL;
|
||||
x,y: REAL;
|
||||
k: INTEGER;
|
||||
temp1, temp2: REAL;
|
||||
BEGIN
|
||||
x := arg;
|
||||
IF x < 0.0 THEN
|
||||
x := -x;
|
||||
quad := quad + 2;
|
||||
END;
|
||||
x := x*twoopi; (*underflow?*)
|
||||
IF x>32764.0 THEN
|
||||
y := FIF(x, 10.0, e);
|
||||
e := e + FLOAT(quad);
|
||||
temp1 := FIF(0.25, e, f);
|
||||
quad := TRUNC(e - 4.0*f);
|
||||
ELSE
|
||||
k := TRUNC(x);
|
||||
y := x - FLOAT(k);
|
||||
quad := (quad + k) MOD 4;
|
||||
END;
|
||||
IF ODD(quad) THEN
|
||||
y := 1.0-y;
|
||||
END;
|
||||
IF quad > 1 THEN
|
||||
y := -y;
|
||||
END;
|
||||
|
||||
ysq := y*y;
|
||||
temp1 := ((((p4*ysq+p3)*ysq+p2)*ysq+p1)*ysq+p0)*y;
|
||||
temp2 := ((((ysq+q3)*ysq+q2)*ysq+q1)*ysq+q0);
|
||||
RETURN temp1/temp2;
|
||||
END sinus;
|
||||
|
||||
PROCEDURE cos(arg: REAL): REAL;
|
||||
BEGIN
|
||||
IF arg < 0.0 THEN
|
||||
arg := -arg;
|
||||
END;
|
||||
RETURN sinus(arg, 1);
|
||||
END cos;
|
||||
|
||||
PROCEDURE sin(arg: REAL): REAL;
|
||||
BEGIN
|
||||
RETURN sinus(arg, 0);
|
||||
END sin;
|
||||
|
||||
(*
|
||||
floating-point arctangent
|
||||
|
||||
arctan returns the value of the arctangent of its
|
||||
argument in the range [-pi/2,pi/2].
|
||||
|
||||
coefficients are #5077 from Hart & Cheney. (19.56D)
|
||||
*)
|
||||
|
||||
CONST
|
||||
sq2p1 = 2.414213562373095048802E0;
|
||||
sq2m1 = 0.414213562373095048802E0;
|
||||
pio2 = 1.570796326794896619231E0;
|
||||
pio4 = 0.785398163397448309615E0;
|
||||
p4 = 0.161536412982230228262E2;
|
||||
p3 = 0.26842548195503973794141E3;
|
||||
p2 = 0.11530293515404850115428136E4;
|
||||
p1 = 0.178040631643319697105464587E4;
|
||||
p0 = 0.89678597403663861959987488E3;
|
||||
q4 = 0.5895697050844462222791E2;
|
||||
q3 = 0.536265374031215315104235E3;
|
||||
q2 = 0.16667838148816337184521798E4;
|
||||
q1 = 0.207933497444540981287275926E4;
|
||||
q0 = 0.89678597403663861962481162E3;
|
||||
|
||||
(*
|
||||
xatan evaluates a series valid in the
|
||||
range [-0.414...,+0.414...].
|
||||
*)
|
||||
|
||||
PROCEDURE xatan(arg: REAL) : REAL;
|
||||
VAR
|
||||
argsq, value: REAL;
|
||||
BEGIN
|
||||
argsq := arg*arg;
|
||||
value := ((((p4*argsq + p3)*argsq + p2)*argsq + p1)*argsq + p0);
|
||||
value := value/(((((argsq + q4)*argsq + q3)*argsq + q2)*argsq + q1)*argsq + q0);
|
||||
RETURN value*arg;
|
||||
END xatan;
|
||||
|
||||
PROCEDURE satan(arg: REAL): REAL;
|
||||
BEGIN
|
||||
IF arg < sq2m1 THEN
|
||||
RETURN xatan(arg);
|
||||
ELSIF arg > sq2p1 THEN
|
||||
RETURN pio2 - xatan(1.0/arg);
|
||||
ELSE
|
||||
RETURN pio4 + xatan((arg-1.0)/(arg+1.0));
|
||||
END;
|
||||
END satan;
|
||||
|
||||
(*
|
||||
atan makes its argument positive and
|
||||
calls the inner routine satan.
|
||||
*)
|
||||
|
||||
PROCEDURE arctan(arg: REAL): REAL;
|
||||
BEGIN
|
||||
IF arg>0.0 THEN
|
||||
RETURN satan(arg);
|
||||
ELSE
|
||||
RETURN -satan(-arg);
|
||||
END;
|
||||
END arctan;
|
||||
|
||||
(*
|
||||
sqrt returns the square root of its floating
|
||||
point argument. Newton's method.
|
||||
*)
|
||||
|
||||
PROCEDURE sqrt(arg: REAL): REAL;
|
||||
VAR
|
||||
x, temp: REAL;
|
||||
exp, i: INTEGER;
|
||||
BEGIN
|
||||
IF arg <= 0.0 THEN
|
||||
IF arg < 0.0 THEN
|
||||
(* ??? *)
|
||||
;
|
||||
END;
|
||||
RETURN 0.0;
|
||||
END;
|
||||
x := FEF(arg,exp);
|
||||
(*
|
||||
* NOTE
|
||||
* this wont work on 1's comp
|
||||
*)
|
||||
IF ODD(exp) THEN
|
||||
x := 2.0 * x;
|
||||
DEC(exp);
|
||||
END;
|
||||
temp := 0.5*(1.0 + x);
|
||||
|
||||
WHILE exp > 28 DO
|
||||
temp := temp * 16384.0;
|
||||
exp := exp - 28;
|
||||
END;
|
||||
WHILE exp < -28 DO
|
||||
temp := temp / 16384.0;
|
||||
exp := exp + 28;
|
||||
END;
|
||||
WHILE exp >= 2 DO
|
||||
temp := temp * 2.0;
|
||||
exp := exp - 2;
|
||||
END;
|
||||
WHILE exp <= -2 DO
|
||||
temp := temp / 2.0;
|
||||
exp := exp + 2;
|
||||
END;
|
||||
FOR i := 0 TO 4 DO
|
||||
temp := 0.5*(temp + arg/temp);
|
||||
END;
|
||||
RETURN temp;
|
||||
END sqrt;
|
||||
|
||||
(*
|
||||
ln returns the natural logarithm of its floating
|
||||
point argument.
|
||||
|
||||
The coefficients are #2705 from Hart & Cheney. (19.38D)
|
||||
*)
|
||||
PROCEDURE ln(arg: REAL): REAL;
|
||||
CONST
|
||||
log2 = 0.693147180559945309E0;
|
||||
sqrto2 = 0.707106781186547524E0;
|
||||
p0 = -0.240139179559210510E2;
|
||||
p1 = 0.309572928215376501E2;
|
||||
p2 = -0.963769093368686593E1;
|
||||
p3 = 0.421087371217979714E0;
|
||||
q0 = -0.120069589779605255E2;
|
||||
q1 = 0.194809660700889731E2;
|
||||
q2 = -0.891110902798312337E1;
|
||||
VAR
|
||||
x,z, zsq, temp: REAL;
|
||||
exp: INTEGER;
|
||||
BEGIN
|
||||
IF arg <= 0.0 THEN
|
||||
(* ??? *)
|
||||
RETURN -HUGE;
|
||||
END;
|
||||
x := FEF(arg,exp);
|
||||
IF x<sqrto2 THEN
|
||||
x := x + x;
|
||||
DEC(exp);
|
||||
END;
|
||||
|
||||
z := (x-1.0)/(x+1.0);
|
||||
zsq := z*z;
|
||||
|
||||
temp := ((p3*zsq + p2)*zsq + p1)*zsq + p0;
|
||||
temp := temp/(((zsq + q2)*zsq + q1)*zsq + q0);
|
||||
temp := temp*z + FLOAT(exp)*log2;
|
||||
RETURN temp;
|
||||
END ln;
|
||||
|
||||
(*
|
||||
exp returns the exponential function of its
|
||||
floating-point argument.
|
||||
|
||||
The coefficients are #1069 from Hart and Cheney. (22.35D)
|
||||
*)
|
||||
|
||||
PROCEDURE floor(d: REAL): REAL;
|
||||
BEGIN
|
||||
IF d < 0.0 THEN
|
||||
d := -d;
|
||||
IF FIF(d, 1.0, d) # 0.0 THEN
|
||||
d := d + 1.0;
|
||||
END;
|
||||
d := -d;
|
||||
ELSE
|
||||
IF FIF(d, 1.0, d) # 0.0 THEN
|
||||
(* just ignore result of FIF *)
|
||||
;
|
||||
END;
|
||||
END;
|
||||
RETURN d;
|
||||
END floor;
|
||||
|
||||
PROCEDURE ldexp(fr: REAL; exp: INTEGER): REAL;
|
||||
VAR
|
||||
neg,i: INTEGER;
|
||||
BEGIN
|
||||
neg := 1;
|
||||
IF fr < 0.0 THEN
|
||||
fr := -fr;
|
||||
neg := -1;
|
||||
END;
|
||||
fr := FEF(fr, i);
|
||||
exp := exp + i;
|
||||
IF exp > 127 THEN
|
||||
(* Too large. ??? *)
|
||||
RETURN FLOAT(neg) * HUGE;
|
||||
END;
|
||||
IF exp < -127 THEN
|
||||
RETURN 0.0;
|
||||
END;
|
||||
WHILE exp > 14 DO
|
||||
fr := fr * 16384.0;
|
||||
exp := exp - 14;
|
||||
END;
|
||||
WHILE exp < -14 DO
|
||||
fr := fr / 16384.0;
|
||||
exp := exp + 14;
|
||||
END;
|
||||
WHILE exp > 0 DO
|
||||
fr := fr + fr;
|
||||
DEC(exp);
|
||||
END;
|
||||
WHILE exp < 0 DO
|
||||
fr := fr / 2.0;
|
||||
INC(exp);
|
||||
END;
|
||||
RETURN FLOAT(neg) * fr;
|
||||
END ldexp;
|
||||
|
||||
PROCEDURE exp(arg: REAL): REAL;
|
||||
CONST
|
||||
p0 = 0.2080384346694663001443843411E7;
|
||||
p1 = 0.3028697169744036299076048876E5;
|
||||
p2 = 0.6061485330061080841615584556E2;
|
||||
q0 = 0.6002720360238832528230907598E7;
|
||||
q1 = 0.3277251518082914423057964422E6;
|
||||
q2 = 0.1749287689093076403844945335E4;
|
||||
log2e = 1.4426950408889634073599247;
|
||||
sqrt2 = 1.4142135623730950488016887;
|
||||
maxf = 10000.0;
|
||||
VAR
|
||||
fract: REAL;
|
||||
temp1, temp2, xsq: REAL;
|
||||
ent: INTEGER;
|
||||
BEGIN
|
||||
IF arg = 0.0 THEN
|
||||
RETURN 1.0;
|
||||
END;
|
||||
IF arg < -maxf THEN
|
||||
RETURN 0.0;
|
||||
END;
|
||||
IF arg > maxf THEN
|
||||
(* result too large ??? *)
|
||||
RETURN HUGE;
|
||||
END;
|
||||
arg := arg * log2e;
|
||||
ent := TRUNC(floor(arg));
|
||||
fract := (arg-FLOAT(ent)) - 0.5;
|
||||
xsq := fract*fract;
|
||||
temp1 := ((p2*xsq+p1)*xsq+p0)*fract;
|
||||
temp2 := ((xsq+q2)*xsq+q1)*xsq + q0;
|
||||
RETURN ldexp(sqrt2*(temp2+temp1)/(temp2-temp1), ent);
|
||||
END exp;
|
||||
|
||||
PROCEDURE entier(x: REAL): INTEGER;
|
||||
BEGIN
|
||||
RETURN TRUNC(x); (* ??? *)
|
||||
END entier;
|
||||
|
||||
PROCEDURE real(x: INTEGER): REAL;
|
||||
BEGIN
|
||||
RETURN FLOAT(x); (* ??? *)
|
||||
END real;
|
||||
|
||||
BEGIN
|
||||
END MathLib0.
|
25
lang/m2/libm2/Processes.def
Normal file
25
lang/m2/libm2/Processes.def
Normal file
|
@ -0,0 +1,25 @@
|
|||
DEFINITION MODULE Processes;
|
||||
|
||||
TYPE SIGNAL;
|
||||
|
||||
PROCEDURE StartProcess(P: PROC; n: CARDINAL);
|
||||
(* Start a concurrent process with program "P" and workspace of
|
||||
size "n"
|
||||
*)
|
||||
|
||||
PROCEDURE SEND(VAR s: SIGNAL);
|
||||
(* One process waiting for "s" is resumed
|
||||
*)
|
||||
|
||||
PROCEDURE WAIT(VAR s: SIGNAL);
|
||||
(* Wait for some other process to send "s"
|
||||
*)
|
||||
|
||||
PROCEDURE Awaited(s: SIGNAL): BOOLEAN;
|
||||
(* Return TRUE if at least one process is waiting for sinal "s".
|
||||
*)
|
||||
|
||||
PROCEDURE Init(VAR s: SIGNAL);
|
||||
(* Compulsory initialization
|
||||
*)
|
||||
END Processes.
|
98
lang/m2/libm2/Processes.mod
Normal file
98
lang/m2/libm2/Processes.mod
Normal file
|
@ -0,0 +1,98 @@
|
|||
IMPLEMENTATION MODULE Processes [1];
|
||||
(* This implementation module comes from
|
||||
"Programming in Modula-2", by Niklaus Wirth,
|
||||
3rd edition, Springer-Verlag, New York, 1985
|
||||
*)
|
||||
|
||||
FROM SYSTEM IMPORT ADDRESS, TSIZE, NEWPROCESS, TRANSFER;
|
||||
|
||||
FROM Storage IMPORT ALLOCATE;
|
||||
|
||||
TYPE SIGNAL = POINTER TO ProcessDescriptor;
|
||||
|
||||
ProcessDescriptor =
|
||||
RECORD next: SIGNAL; (* ring *)
|
||||
queue: SIGNAL; (* queue of waiting processes *)
|
||||
cor: ADDRESS;
|
||||
ready: BOOLEAN;
|
||||
END;
|
||||
|
||||
VAR cp: SIGNAL; (* current process *)
|
||||
|
||||
PROCEDURE StartProcess(P: PROC; n: CARDINAL);
|
||||
VAR s0: SIGNAL;
|
||||
wsp: ADDRESS;
|
||||
BEGIN
|
||||
s0 := cp;
|
||||
ALLOCATE(wsp, n);
|
||||
ALLOCATE(cp, TSIZE(ProcessDescriptor));
|
||||
WITH cp^ DO
|
||||
next := s0^.next;
|
||||
s0^.next := cp;
|
||||
ready := TRUE;
|
||||
queue := NIL
|
||||
END;
|
||||
NEWPROCESS(P, wsp, n, cp^.cor);
|
||||
TRANSFER(s0^.cor, cp^.cor);
|
||||
END StartProcess;
|
||||
|
||||
PROCEDURE SEND(VAR s: SIGNAL);
|
||||
VAR s0: SIGNAL;
|
||||
BEGIN
|
||||
IF s # NIL THEN
|
||||
s0 := cp;
|
||||
cp := s;
|
||||
WITH cp^ DO
|
||||
s := queue;
|
||||
ready := TRUE;
|
||||
queue := NIL
|
||||
END;
|
||||
TRANSFER(s0^.cor, cp^.cor);
|
||||
END
|
||||
END SEND;
|
||||
|
||||
PROCEDURE WAIT(VAR s: SIGNAL);
|
||||
VAR s0, s1: SIGNAL;
|
||||
BEGIN
|
||||
(* insert cp in queue s *)
|
||||
IF s = NIL THEN
|
||||
s := cp
|
||||
ELSE
|
||||
s0 := s;
|
||||
s1 := s0^.queue;
|
||||
WHILE s1 # NIL DO
|
||||
s0 := s1;
|
||||
s1 := s0^.queue
|
||||
END;
|
||||
s0^.queue := cp
|
||||
END;
|
||||
s0 := cp;
|
||||
REPEAT
|
||||
cp := cp^.next
|
||||
UNTIL cp^.ready;
|
||||
IF cp = s0 THEN
|
||||
(* deadlock *)
|
||||
HALT
|
||||
END;
|
||||
s0^.ready := FALSE;
|
||||
TRANSFER(s0^.cor, cp^.cor)
|
||||
END WAIT;
|
||||
|
||||
PROCEDURE Awaited(s: SIGNAL): BOOLEAN;
|
||||
BEGIN
|
||||
RETURN s # NIL
|
||||
END Awaited;
|
||||
|
||||
PROCEDURE Init(VAR s: SIGNAL);
|
||||
BEGIN
|
||||
s := NIL
|
||||
END Init;
|
||||
|
||||
BEGIN
|
||||
ALLOCATE(cp, TSIZE(ProcessDescriptor));
|
||||
WITH cp^ DO
|
||||
next := cp;
|
||||
ready := TRUE;
|
||||
queue := NIL
|
||||
END
|
||||
END Processes.
|
25
lang/m2/libm2/RealInOut.def
Normal file
25
lang/m2/libm2/RealInOut.def
Normal file
|
@ -0,0 +1,25 @@
|
|||
DEFINITION MODULE RealInOut;
|
||||
|
||||
VAR Done: BOOLEAN;
|
||||
|
||||
PROCEDURE ReadReal(VAR x: REAL);
|
||||
(* Read a real number "x" according to the syntax:
|
||||
|
||||
['+'|'-'] digit {digit} ['.' digit {digit}]
|
||||
['E' ['+'|'-'] digit [digit]]
|
||||
|
||||
Done := "a number was read".
|
||||
Input terminates with a blank or any control character.
|
||||
When reading from a terminal, backspacing may be done by either
|
||||
DEL or BACKSPACE, depending on the implementation of ReadString.
|
||||
*)
|
||||
|
||||
PROCEDURE WriteReal(x: REAL; n: CARDINAL);
|
||||
(* Write x using n characters.
|
||||
If fewer than n characters are needed, leading blanks are inserted.
|
||||
*)
|
||||
|
||||
PROCEDURE WriteRealOct(x: REAL);
|
||||
(* Write x in octal form with exponent and mantissa.
|
||||
*)
|
||||
END RealInOut.
|
222
lang/m2/libm2/RealInOut.mod
Normal file
222
lang/m2/libm2/RealInOut.mod
Normal file
|
@ -0,0 +1,222 @@
|
|||
IMPLEMENTATION MODULE RealInOut;
|
||||
|
||||
FROM FIFFEF IMPORT FIF, FEF;
|
||||
IMPORT InOut;
|
||||
|
||||
CONST NDIG = 80;
|
||||
|
||||
TYPE string = ARRAY[0..NDIG+6] OF CHAR;
|
||||
|
||||
PROCEDURE cvt(arg: REAL;
|
||||
ndigits: INTEGER;
|
||||
VAR decpt: INTEGER;
|
||||
VAR sign: BOOLEAN;
|
||||
eflag: BOOLEAN;
|
||||
VAR buf: string);
|
||||
VAR r2, i: INTEGER;
|
||||
fi, fj: REAL;
|
||||
ind1, ind2 : INTEGER;
|
||||
BEGIN
|
||||
IF ndigits < 0 THEN ndigits := 0 END;
|
||||
IF ndigits >= NDIG-1 THEN ndigits := NDIG-2; END;
|
||||
r2 := 0;
|
||||
sign := arg < 0.0;
|
||||
ind1 := 0;
|
||||
IF sign THEN arg := -arg END;
|
||||
arg := FIF(arg, 1.0, fi);
|
||||
(*
|
||||
Do integer part, which is now in "fi". "arg" now contains the
|
||||
fraction part.
|
||||
*)
|
||||
IF fi # 0.0 THEN
|
||||
ind2 := NDIG;
|
||||
WHILE fi # 0.0 DO
|
||||
DEC(ind2);
|
||||
buf[ind2] := CHR(TRUNC((FIF(fi, 0.1, fi) +
|
||||
0.03
|
||||
) * 10.0
|
||||
) + ORD('0')
|
||||
);
|
||||
INC(r2);
|
||||
END;
|
||||
WHILE ind2 < NDIG DO
|
||||
buf[ind1] := buf[ind2];
|
||||
INC(ind1);
|
||||
INC(ind2);
|
||||
END;
|
||||
ELSIF arg > 0.0 THEN
|
||||
WHILE arg*10.0 < 1.0 DO
|
||||
arg := arg * 10.0;
|
||||
fj := arg;
|
||||
DEC(r2);
|
||||
END;
|
||||
END;
|
||||
ind2 := ndigits;
|
||||
IF NOT eflag THEN ind2 := ind2 + r2 END;
|
||||
decpt := r2;
|
||||
IF ind2 < 0 THEN
|
||||
buf[0] := 0C;
|
||||
RETURN;
|
||||
END;
|
||||
WHILE (ind1 <= ind2) AND (ind1 < NDIG) DO
|
||||
arg := FIF(arg, 10.0, fj);
|
||||
buf[ind1] := CHR(TRUNC(fj)+ORD('0'));
|
||||
INC(ind1);
|
||||
END;
|
||||
IF ind2 >= NDIG THEN
|
||||
buf[NDIG-1] := 0C;
|
||||
RETURN;
|
||||
END;
|
||||
ind1 := ind2;
|
||||
buf[ind2] := CHR(ORD(buf[ind2])+5);
|
||||
WHILE buf[ind2] > '9' DO
|
||||
buf[ind2] := '0';
|
||||
IF ind2 > 0 THEN
|
||||
DEC(ind2);
|
||||
buf[ind2] := CHR(ORD(buf[ind2])+1);
|
||||
ELSE
|
||||
buf[ind2] := '1';
|
||||
INC(decpt);
|
||||
IF NOT eflag THEN
|
||||
IF ind1 > 0 THEN buf[ind1] := '0'; END;
|
||||
INC(ind1);
|
||||
END;
|
||||
END;
|
||||
END;
|
||||
buf[ind1] := 0C;
|
||||
END cvt;
|
||||
|
||||
PROCEDURE ecvt(arg: REAL;
|
||||
ndigits: INTEGER;
|
||||
VAR decpt: INTEGER;
|
||||
VAR sign: BOOLEAN;
|
||||
VAR buf: string);
|
||||
BEGIN
|
||||
cvt(arg, ndigits, decpt, sign, TRUE, buf);
|
||||
END ecvt;
|
||||
|
||||
PROCEDURE fcvt(arg: REAL;
|
||||
ndigits: INTEGER;
|
||||
VAR decpt: INTEGER;
|
||||
VAR sign: BOOLEAN;
|
||||
VAR buf: string);
|
||||
BEGIN
|
||||
cvt(arg, ndigits, decpt, sign, FALSE, buf);
|
||||
END fcvt;
|
||||
|
||||
PROCEDURE WriteReal(arg: REAL; ndigits: CARDINAL);
|
||||
VAR buf, cvtbuf: string;
|
||||
ind1, ind2: INTEGER;
|
||||
d,i: INTEGER;
|
||||
sign: BOOLEAN;
|
||||
|
||||
BEGIN
|
||||
IF ndigits-6 < 2 THEN i := 2 ELSE i := ndigits-6; END;
|
||||
ecvt(arg,i,d,sign,cvtbuf);
|
||||
IF sign THEN buf[0] := '-' ELSE buf[0] := ' ' END;
|
||||
ind1 := 1;
|
||||
ind2 := 0;
|
||||
IF cvtbuf[ind2] = '0' THEN INC(d); END;
|
||||
buf[ind1] := cvtbuf[ind2]; INC(ind1); INC(ind2);
|
||||
buf[ind1] := '.'; INC(ind1);
|
||||
FOR i := i-1 TO 1 BY -1 DO
|
||||
buf[ind1] := cvtbuf[ind2]; INC(ind1); INC(ind2);
|
||||
END;
|
||||
buf[ind1] := 'E'; INC(ind1);
|
||||
DEC(d);
|
||||
IF d < 0 THEN
|
||||
d := -d;
|
||||
buf[ind1] := '-';
|
||||
ELSE
|
||||
buf[ind1] := '+';
|
||||
END;
|
||||
INC(ind1);
|
||||
buf[ind1] := CHR(ORD('0') + CARDINAL(d DIV 10));
|
||||
buf[ind1+1] := CHR(ORD('0') + CARDINAL(d MOD 10));
|
||||
buf[ind1+2] := 0C;
|
||||
InOut.WriteString(buf);
|
||||
END WriteReal;
|
||||
|
||||
PROCEDURE ReadReal(VAR x: REAL);
|
||||
CONST BIG = 1.0E17;
|
||||
VAR r : REAL;
|
||||
pow10 : INTEGER;
|
||||
i : INTEGER;
|
||||
e : REAL;
|
||||
ch : CHAR;
|
||||
signed: BOOLEAN;
|
||||
signedexp: BOOLEAN;
|
||||
Buf: ARRAY[0..512] OF CHAR;
|
||||
iB: INTEGER;
|
||||
|
||||
PROCEDURE dig(ch: CARDINAL);
|
||||
BEGIN
|
||||
IF r>BIG THEN INC(pow10) ELSE r:= 10.0*r + FLOAT(ch) END;
|
||||
END dig;
|
||||
|
||||
PROCEDURE isdig(ch: CHAR) : BOOLEAN;
|
||||
BEGIN
|
||||
RETURN (ch >= '0') AND (ch <= '9');
|
||||
END isdig;
|
||||
|
||||
BEGIN
|
||||
r := 0.0;
|
||||
pow10 := 0;
|
||||
InOut.ReadString(Buf);
|
||||
iB := 0;
|
||||
signed := FALSE;
|
||||
IF Buf[0] = '-' THEN signed := TRUE; INC(iB)
|
||||
ELSIF Buf[0] = '+' THEN INC(iB)
|
||||
END;
|
||||
ch := Buf[iB]; INC(iB);
|
||||
IF NOT isdig(ch) THEN Done := FALSE; RETURN END;
|
||||
REPEAT
|
||||
dig(ORD(ch));
|
||||
ch := Buf[iB]; INC(iB);
|
||||
UNTIL NOT isdig(ch);
|
||||
IF ch = '.' THEN
|
||||
ch := Buf[iB]; INC(iB);
|
||||
IF NOT isdig(ch) THEN Done := FALSE; RETURN END;
|
||||
REPEAT
|
||||
dig(ORD(ch));
|
||||
DEC(pow10);
|
||||
ch := Buf[iB]; INC(iB);
|
||||
UNTIL NOT isdig(ch);
|
||||
END;
|
||||
IF ch = 'E' THEN
|
||||
ch := Buf[iB]; INC(iB);
|
||||
i := 0;
|
||||
signedexp := FALSE;
|
||||
IF ch = '-' THEN signedexp := TRUE; ch:= Buf[iB]; INC(iB)
|
||||
ELSIF Buf[iB] = '+' THEN ch := Buf[iB]; INC(iB)
|
||||
END;
|
||||
IF NOT isdig(ch) THEN Done := FALSE; RETURN END;
|
||||
REPEAT
|
||||
i := i*10 + INTEGER(ORD(ch) - ORD('0'));
|
||||
ch := Buf[iB]; INC(iB);
|
||||
UNTIL NOT isdig(ch);
|
||||
IF signedexp THEN i := -i END;
|
||||
pow10 := pow10 + i;
|
||||
END;
|
||||
IF pow10 < 0 THEN i := -pow10; ELSE i := pow10; END;
|
||||
e := 1.0;
|
||||
DEC(i);
|
||||
WHILE i >= 0 DO
|
||||
e := e * 10.0;
|
||||
DEC(i)
|
||||
END;
|
||||
IF pow10<0 THEN
|
||||
r := r / e;
|
||||
ELSE
|
||||
r := r * e;
|
||||
END;
|
||||
IF signed THEN x := -r; ELSE x := r END;
|
||||
END ReadReal;
|
||||
|
||||
PROCEDURE WriteRealOct(x: REAL);
|
||||
BEGIN
|
||||
END WriteRealOct;
|
||||
|
||||
BEGIN
|
||||
Done := FALSE;
|
||||
END RealInOut.
|
27
lang/m2/libm2/Semaphores.def
Normal file
27
lang/m2/libm2/Semaphores.def
Normal file
|
@ -0,0 +1,27 @@
|
|||
DEFINITION MODULE Semaphores;
|
||||
|
||||
TYPE Sema;
|
||||
|
||||
PROCEDURE Level(s: Sema) : CARDINAL;
|
||||
(* Returns current value of semaphore s *)
|
||||
|
||||
PROCEDURE NewSema(n: CARDINAL) : Sema;
|
||||
(* Creates a new semaphore with initial level "n" *)
|
||||
|
||||
PROCEDURE Down(VAR s: Sema);
|
||||
(* If the value of "s" is > 0, then just decrement "s".
|
||||
Else, suspend the current process until the semaphore becomes
|
||||
positive again.
|
||||
May result in a process switch.
|
||||
*)
|
||||
|
||||
PROCEDURE Up(VAR s: Sema);
|
||||
(* Increment the semaphore "s".
|
||||
This call may result in a process switch
|
||||
*)
|
||||
|
||||
PROCEDURE StartProcess(P: PROC; n: CARDINAL);
|
||||
(* Create a new process with procedure P and workspace of size "n".
|
||||
Also transfer control to it.
|
||||
*)
|
||||
END Semaphores.
|
100
lang/m2/libm2/Semaphores.mod
Normal file
100
lang/m2/libm2/Semaphores.mod
Normal file
|
@ -0,0 +1,100 @@
|
|||
IMPLEMENTATION MODULE Semaphores [1];
|
||||
|
||||
FROM SYSTEM IMPORT ADDRESS, NEWPROCESS, TRANSFER;
|
||||
FROM Storage IMPORT ALLOCATE;
|
||||
FROM random IMPORT Uniform;
|
||||
|
||||
TYPE Sema = POINTER TO Semaphore;
|
||||
Processes = POINTER TO Process;
|
||||
Semaphore =
|
||||
RECORD
|
||||
level: CARDINAL;
|
||||
END;
|
||||
Process =
|
||||
RECORD next: Processes;
|
||||
proc: ADDRESS;
|
||||
waiting: Sema;
|
||||
END;
|
||||
|
||||
VAR cp: Processes; (* current process *)
|
||||
|
||||
PROCEDURE StartProcess(P: PROC; n: CARDINAL);
|
||||
VAR s0: Processes;
|
||||
wsp: ADDRESS;
|
||||
BEGIN
|
||||
s0 := cp;
|
||||
ALLOCATE(wsp, n);
|
||||
ALLOCATE(cp, SIZE(Process));
|
||||
WITH cp^ DO
|
||||
next := s0^.next;
|
||||
s0^.next := cp;
|
||||
waiting := NIL;
|
||||
END;
|
||||
NEWPROCESS(P, wsp, n, cp^.proc);
|
||||
TRANSFER(s0^.proc, cp^.proc);
|
||||
END StartProcess;
|
||||
|
||||
PROCEDURE Up(VAR s: Sema);
|
||||
BEGIN
|
||||
s^.level := s^.level + 1;
|
||||
ReSchedule;
|
||||
END Up;
|
||||
|
||||
PROCEDURE Down(VAR s: Sema);
|
||||
BEGIN
|
||||
IF s^.level = 0 THEN
|
||||
cp^.waiting := s;
|
||||
ELSE
|
||||
s^.level := s^.level - 1;
|
||||
END;
|
||||
ReSchedule;
|
||||
END Down;
|
||||
|
||||
PROCEDURE NewSema(n: CARDINAL): Sema;
|
||||
VAR s: Sema;
|
||||
BEGIN
|
||||
ALLOCATE(s, SIZE(Semaphore));
|
||||
s^.level := n;
|
||||
RETURN s;
|
||||
END NewSema;
|
||||
|
||||
PROCEDURE Level(s: Sema): CARDINAL;
|
||||
BEGIN
|
||||
RETURN s^.level;
|
||||
END Level;
|
||||
|
||||
PROCEDURE ReSchedule;
|
||||
VAR s0: Processes;
|
||||
i, j: CARDINAL;
|
||||
BEGIN
|
||||
s0 := cp;
|
||||
i := Uniform(1, 5);
|
||||
j := i;
|
||||
LOOP
|
||||
cp := cp^.next;
|
||||
IF Runnable(cp) THEN
|
||||
DEC(i);
|
||||
IF i = 0 THEN EXIT END;
|
||||
END;
|
||||
IF (cp = s0) AND (j = i) THEN (* deadlock *) HALT END;
|
||||
END;
|
||||
IF cp # s0 THEN TRANSFER(s0^.proc, cp^.proc); END;
|
||||
END ReSchedule;
|
||||
|
||||
PROCEDURE Runnable(p: Processes): BOOLEAN;
|
||||
BEGIN
|
||||
IF p^.waiting = NIL THEN RETURN TRUE; END;
|
||||
IF p^.waiting^.level > 0 THEN
|
||||
p^.waiting^.level := p^.waiting^.level - 1;
|
||||
p^.waiting := NIL;
|
||||
RETURN TRUE;
|
||||
END;
|
||||
RETURN FALSE;
|
||||
END Runnable;
|
||||
BEGIN
|
||||
ALLOCATE(cp, SIZE(Process));
|
||||
WITH cp^ DO
|
||||
next := cp;
|
||||
waiting := NIL;
|
||||
END
|
||||
END Semaphores.
|
20
lang/m2/libm2/Storage.def
Normal file
20
lang/m2/libm2/Storage.def
Normal file
|
@ -0,0 +1,20 @@
|
|||
DEFINITION MODULE Storage;
|
||||
|
||||
FROM SYSTEM IMPORT ADDRESS;
|
||||
|
||||
PROCEDURE ALLOCATE(VAR a : ADDRESS; size : CARDINAL);
|
||||
(* Allocate an area of the given size and return the address
|
||||
in "a". If no space is available, the calling program is
|
||||
killed.
|
||||
*)
|
||||
|
||||
PROCEDURE DEALLOCATE(VAR a : ADDRESS; size : CARDINAL);
|
||||
(* Free the area at address "a" with the given size. The area
|
||||
must have been allocated by "ALLOCATE", with the same size.
|
||||
*)
|
||||
|
||||
PROCEDURE Available(size : CARDINAL) : BOOLEAN;
|
||||
(* Return TRUE if an area with the given size could be allocated.
|
||||
*)
|
||||
|
||||
END Storage.
|
275
lang/m2/libm2/Storage.mod
Normal file
275
lang/m2/libm2/Storage.mod
Normal file
|
@ -0,0 +1,275 @@
|
|||
IMPLEMENTATION MODULE Storage;
|
||||
(* This storage manager maintains an array of lists of objects with the
|
||||
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 SYSTEM IMPORT ADDRESS, ADR;
|
||||
|
||||
CONST
|
||||
NLISTS = 20;
|
||||
|
||||
TYPE
|
||||
ALIGNTYPE =
|
||||
RECORD
|
||||
CASE : INTEGER OF
|
||||
1: l: LONGINT |
|
||||
2: p: ADDRESS |
|
||||
3: d: LONGREAL
|
||||
END
|
||||
END; (* A type with high alignment requirements *)
|
||||
BucketPtr = POINTER TO Bucket;
|
||||
Bucket =
|
||||
RECORD
|
||||
CASE : BOOLEAN OF
|
||||
FALSE: BSIZE: INTEGER; (* size of user part in UNITs *)
|
||||
BNEXT: BucketPtr; | (* next free Bucket *)
|
||||
TRUE: BXX: ALIGNTYPE
|
||||
END;
|
||||
BSTORE: ALIGNTYPE;
|
||||
END;
|
||||
|
||||
CONST
|
||||
UNIT = SIZE(ALIGNTYPE);
|
||||
USED = BucketPtr(1);
|
||||
|
||||
VAR
|
||||
FreeLists: ARRAY[0..NLISTS] OF BucketPtr; (* small blocks *)
|
||||
Llist: BucketPtr; (* others *)
|
||||
Compacted: BOOLEAN; (* avoid recursive reorganization *)
|
||||
FirstBlock: BucketPtr;
|
||||
|
||||
PROCEDURE Allocate(size: CARDINAL) : ADDRESS;
|
||||
VAR nu : INTEGER;
|
||||
b : INTEGER;
|
||||
p, q: BucketPtr;
|
||||
brk : ADDRESS;
|
||||
BEGIN
|
||||
nu := (size + (UNIT-1)) DIV UNIT;
|
||||
IF nu = 0 THEN
|
||||
RETURN NIL;
|
||||
END;
|
||||
IF nu <= NLISTS THEN
|
||||
b := nu;
|
||||
IF FreeLists[b] # NIL THEN
|
||||
(* Exact fit *)
|
||||
p := FreeLists[b];
|
||||
FreeLists[b] := p^.BNEXT;
|
||||
p^.BNEXT := USED;
|
||||
RETURN ADR(p^.BSTORE);
|
||||
END;
|
||||
|
||||
(* Search for a block with >= 2 units more than requested.
|
||||
We pay for an additional header when the block is split.
|
||||
*)
|
||||
FOR b := b+2 TO NLISTS DO
|
||||
IF FreeLists[b] # NIL THEN
|
||||
q := FreeLists[b];
|
||||
FreeLists[b] := q^.BNEXT;
|
||||
p := ADDRESS(q) + CARDINAL((nu+1)*UNIT);
|
||||
(* p indicates the block that must be given
|
||||
back
|
||||
*)
|
||||
p^.BSIZE := q^.BSIZE - nu - 1;
|
||||
p^.BNEXT := FreeLists[p^.BSIZE];
|
||||
FreeLists[p^.BSIZE] := p;
|
||||
q^.BSIZE := nu;
|
||||
q^.BNEXT := USED;
|
||||
RETURN ADR(q^.BSTORE);
|
||||
END;
|
||||
END;
|
||||
END;
|
||||
|
||||
p := Llist;
|
||||
IF p # NIL THEN
|
||||
q := NIL;
|
||||
WHILE (p # NIL) AND (p^.BSIZE < nu) DO
|
||||
q := p;
|
||||
p := p^.BNEXT;
|
||||
END;
|
||||
|
||||
IF p # NIL THEN
|
||||
(* p^.BSIZE >= nu *)
|
||||
IF p^.BSIZE <= nu + NLISTS + 1 THEN
|
||||
(* Remove p from this list *)
|
||||
IF q # NIL THEN q^.BNEXT := p^.BNEXT
|
||||
ELSE Llist := p^.BNEXT;
|
||||
END;
|
||||
p^.BNEXT := USED;
|
||||
IF p^.BSIZE > nu + 1 THEN
|
||||
(* split block,
|
||||
tail goes to FreeLists area
|
||||
*)
|
||||
q := ADDRESS(p) + CARDINAL((nu+1)*UNIT);
|
||||
q^.BSIZE := p^.BSIZE -nu -1;
|
||||
q^.BNEXT := FreeLists[q^.BSIZE];
|
||||
FreeLists[q^.BSIZE] := q;
|
||||
p^.BSIZE := nu;
|
||||
END;
|
||||
RETURN ADR(p^.BSTORE);
|
||||
END;
|
||||
(* Give part of tail of original block.
|
||||
Block stays in this list.
|
||||
*)
|
||||
q := ADDRESS(p) + CARDINAL((p^.BSIZE-nu)*UNIT);
|
||||
q^.BSIZE := nu;
|
||||
p^.BSIZE := p^.BSIZE - nu - 1;
|
||||
q^.BNEXT := USED;
|
||||
RETURN ADR(q^.BSTORE);
|
||||
END;
|
||||
END;
|
||||
|
||||
IF Compacted THEN
|
||||
(* reorganization did not yield sufficient memory *)
|
||||
RETURN NIL;
|
||||
END;
|
||||
|
||||
brk := sbrk(UNIT * (nu + 1));
|
||||
IF brk = ILLBREAK THEN
|
||||
ReOrganize();
|
||||
Compacted := TRUE;
|
||||
brk := Allocate(size);
|
||||
Compacted := FALSE;
|
||||
RETURN brk;
|
||||
END;
|
||||
|
||||
p := brk;
|
||||
p^.BSIZE := nu;
|
||||
p^.BNEXT := USED;
|
||||
RETURN ADR(p^.BSTORE);
|
||||
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);
|
||||
END;
|
||||
END ALLOCATE;
|
||||
|
||||
PROCEDURE Available(size: CARDINAL): BOOLEAN;
|
||||
VAR a: ADDRESS;
|
||||
BEGIN
|
||||
a:= Allocate(size);
|
||||
IF a # NIL THEN
|
||||
DEALLOCATE(a, size);
|
||||
RETURN TRUE;
|
||||
END;
|
||||
RETURN FALSE;
|
||||
END Available;
|
||||
|
||||
PROCEDURE DEALLOCATE(VAR a: ADDRESS; size: CARDINAL);
|
||||
VAR p: BucketPtr;
|
||||
BEGIN
|
||||
IF (a = NIL) THEN RETURN; END;
|
||||
p := a - UNIT;
|
||||
IF (p^.BNEXT # USED) THEN RETURN; END;
|
||||
WITH p^ DO
|
||||
IF BSIZE <= NLISTS THEN
|
||||
BNEXT := FreeLists[BSIZE];
|
||||
FreeLists[BSIZE] := p;
|
||||
ELSE
|
||||
BNEXT := Llist;
|
||||
Llist := p;
|
||||
END;
|
||||
END;
|
||||
END DEALLOCATE;
|
||||
|
||||
PROCEDURE ReOrganize();
|
||||
VAR lastblock: BucketPtr;
|
||||
b, be: BucketPtr;
|
||||
i: INTEGER;
|
||||
BEGIN
|
||||
FOR i := 1 TO NLISTS DO
|
||||
b := FreeLists[i];
|
||||
WHILE b # NIL DO
|
||||
IF ADDRESS(b) > ADDRESS(lastblock) THEN
|
||||
lastblock := b;
|
||||
END;
|
||||
be := b^.BNEXT;
|
||||
b^.BNEXT := NIL; (* temporary free mark *)
|
||||
b := be;
|
||||
END;
|
||||
END;
|
||||
|
||||
b := Llist;
|
||||
WHILE b # NIL DO
|
||||
IF ADDRESS(b) > ADDRESS(lastblock) THEN
|
||||
lastblock := b;
|
||||
END;
|
||||
be := b^.BNEXT;
|
||||
b^.BNEXT := NIL;
|
||||
b := be;
|
||||
END;
|
||||
|
||||
(* Now, all free blocks have b^.BNEXT = NIL *)
|
||||
|
||||
b := FirstBlock;
|
||||
WHILE ADDRESS(b) < ADDRESS(lastblock) DO
|
||||
LOOP
|
||||
be := ADDRESS(b)+CARDINAL((b^.BSIZE+1)*UNIT);
|
||||
IF b^.BNEXT # NIL THEN
|
||||
(* this block is not free *)
|
||||
EXIT;
|
||||
END;
|
||||
IF ADDRESS(be) > ADDRESS(lastblock) THEN
|
||||
(* no next block *)
|
||||
EXIT;
|
||||
END;
|
||||
IF be^.BNEXT # NIL THEN
|
||||
(* next block is not free *)
|
||||
EXIT;
|
||||
END;
|
||||
(* this block and the next one are free,
|
||||
so merge them
|
||||
*)
|
||||
b^.BSIZE := b^.BSIZE + be^.BSIZE + 1;
|
||||
END;
|
||||
b := be;
|
||||
END;
|
||||
|
||||
(* clear all free lists *)
|
||||
FOR i := 1 TO NLISTS DO FreeLists[i] := NIL; END;
|
||||
Llist := NIL;
|
||||
|
||||
(* collect free blocks in them again *)
|
||||
b := FirstBlock;
|
||||
WHILE ADDRESS(b) <= ADDRESS(lastblock) DO
|
||||
WITH b^ DO
|
||||
IF BNEXT = NIL THEN
|
||||
IF BSIZE <= NLISTS THEN
|
||||
BNEXT := FreeLists[BSIZE];
|
||||
FreeLists[BSIZE] := b;
|
||||
ELSE
|
||||
BNEXT := Llist;
|
||||
Llist := b;
|
||||
END;
|
||||
END;
|
||||
END;
|
||||
b := ADDRESS(b) + CARDINAL((b^.BSIZE+1) * UNIT);
|
||||
END;
|
||||
END ReOrganize;
|
||||
|
||||
PROCEDURE InitStorage();
|
||||
VAR i: INTEGER;
|
||||
brk: ADDRESS;
|
||||
BEGIN
|
||||
FOR i := 1 TO NLISTS DO
|
||||
FreeLists[i] := NIL;
|
||||
END;
|
||||
Llist := NIL;
|
||||
brk := sbrk(0);
|
||||
brk := sbrk(UNIT - INTEGER(brk MOD UNIT));
|
||||
FirstBlock := sbrk(0);
|
||||
Compacted := FALSE;
|
||||
END InitStorage;
|
||||
|
||||
BEGIN
|
||||
InitStorage();
|
||||
END Storage.
|
13
lang/m2/libm2/StrAss.c
Normal file
13
lang/m2/libm2/StrAss.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
_StringAssign(dstsiz, srcsiz, dstaddr, srcaddr)
|
||||
register char *dstaddr, *srcaddr;
|
||||
{
|
||||
while (srcsiz > 0) {
|
||||
*dstaddr++ = *srcaddr++;
|
||||
srcsiz--;
|
||||
dstsiz--;
|
||||
}
|
||||
while (dstsiz > 0) {
|
||||
*dstaddr++ = 0;
|
||||
dstsiz--;
|
||||
}
|
||||
}
|
51
lang/m2/libm2/Strings.def
Normal file
51
lang/m2/libm2/Strings.def
Normal file
|
@ -0,0 +1,51 @@
|
|||
DEFINITION MODULE Strings;
|
||||
(* Note: truncation of strings may occur if the user does not provide
|
||||
large enough variables to contain the result of the operation.
|
||||
*)
|
||||
|
||||
(* Strings are of type ARRAY OF CHAR, and their length is the size
|
||||
of the array, unless a 0-byte occurs in the string to indicate the
|
||||
end of the string.
|
||||
*)
|
||||
|
||||
PROCEDURE Assign(source: ARRAY OF CHAR; VAR dest: ARRAY OF CHAR);
|
||||
(* Assign string source to dest
|
||||
*)
|
||||
|
||||
PROCEDURE Insert(substr: ARRAY OF CHAR; VAR str: ARRAY OF CHAR; inx: CARDINAL);
|
||||
(* Insert the string substr into str, starting at str[inx].
|
||||
If inx is equal to or greater than Length(str) then substr is appended
|
||||
to the end of str.
|
||||
*)
|
||||
|
||||
PROCEDURE Delete(VAR str: ARRAY OF CHAR; inx, len: CARDINAL);
|
||||
(* Delete len characters from str, starting at str[inx].
|
||||
If inx >= Length(str) then nothing happens.
|
||||
If there are not len characters to delete, characters to the end of the
|
||||
string are deleted.
|
||||
*)
|
||||
|
||||
PROCEDURE Pos(substr, str: ARRAY OF CHAR): CARDINAL;
|
||||
(* Return the index into str of the first occurrence of substr.
|
||||
Pos returns a value greater than HIGH(str) of no occurrence is found.
|
||||
*)
|
||||
|
||||
PROCEDURE Copy(str: ARRAY OF CHAR;
|
||||
inx, len: CARDINAL;
|
||||
VAR result: ARRAY OF CHAR);
|
||||
(* Copy at most len characters from str into result, starting at str[inx].
|
||||
*)
|
||||
|
||||
PROCEDURE Concat(s1, s2: ARRAY OF CHAR; VAR result: ARRAY OF CHAR);
|
||||
(* Concatenate two strings.
|
||||
*)
|
||||
|
||||
PROCEDURE Length(str: ARRAY OF CHAR): CARDINAL;
|
||||
(* Return number of characters in str.
|
||||
*)
|
||||
|
||||
PROCEDURE CompareStr(s1, s2: ARRAY OF CHAR): INTEGER;
|
||||
(* Compare two strings, return -1 if s1 < s2, 0 if s1 = s2, and 1 if s1 > s2.
|
||||
*)
|
||||
|
||||
END Strings.
|
161
lang/m2/libm2/Strings.mod
Normal file
161
lang/m2/libm2/Strings.mod
Normal file
|
@ -0,0 +1,161 @@
|
|||
IMPLEMENTATION MODULE Strings;
|
||||
|
||||
PROCEDURE Assign(source: ARRAY OF CHAR; VAR dest: ARRAY OF CHAR);
|
||||
(* Assign string source to dest
|
||||
*)
|
||||
VAR i: CARDINAL;
|
||||
max: CARDINAL;
|
||||
BEGIN
|
||||
max := HIGH(source);
|
||||
IF HIGH(dest) < max THEN max := HIGH(dest); END;
|
||||
i := 0;
|
||||
WHILE (i <= max) AND (source[i] # 0C) DO
|
||||
dest[i] := source[i];
|
||||
INC(i);
|
||||
END;
|
||||
IF i < HIGH(dest) THEN dest[i] := 0C; END;
|
||||
END Assign;
|
||||
|
||||
PROCEDURE Insert(substr: ARRAY OF CHAR; VAR str: ARRAY OF CHAR; inx: CARDINAL);
|
||||
(* Insert the string substr into str, starting at str[inx].
|
||||
If inx is equal to or greater than Length(str) then substr is appended
|
||||
to the end of str.
|
||||
*)
|
||||
VAR sublen, length, i: CARDINAL;
|
||||
BEGIN
|
||||
sublen := Length(substr);
|
||||
IF sublen = 0 THEN RETURN; END;
|
||||
length := Length(str);
|
||||
IF inx > length THEN inx := length; END;
|
||||
i := length;
|
||||
IF i + sublen - 1 > HIGH(str) THEN i := HIGH(str); END;
|
||||
WHILE i > inx DO
|
||||
str[i+sublen-1] := str[i-1];
|
||||
DEC(i);
|
||||
END;
|
||||
FOR i := 0 TO sublen - 1 DO
|
||||
IF i + inx <= HIGH(str) THEN
|
||||
str[i + inx] := substr[i];
|
||||
ELSE
|
||||
RETURN;
|
||||
END;
|
||||
END;
|
||||
IF length + sublen <= HIGH(str) THEN
|
||||
str[length + sublen] := 0C;
|
||||
END;
|
||||
END Insert;
|
||||
|
||||
PROCEDURE Delete(VAR str: ARRAY OF CHAR; inx, len: CARDINAL);
|
||||
(* Delete len characters from str, starting at str[inx].
|
||||
If inx >= Length(str) then nothing happens.
|
||||
If there are not len characters to delete, characters to the end of the
|
||||
string are deleted.
|
||||
*)
|
||||
VAR length: CARDINAL;
|
||||
i : CARDINAL;
|
||||
BEGIN
|
||||
IF len = 0 THEN RETURN; END;
|
||||
length := Length(str);
|
||||
IF inx >= length THEN RETURN; END;
|
||||
WHILE inx + len < length DO
|
||||
str[inx] := str[inx + len];
|
||||
INC(inx);
|
||||
END;
|
||||
str[inx] := 0C;
|
||||
END Delete;
|
||||
|
||||
PROCEDURE Pos(substr, str: ARRAY OF CHAR): CARDINAL;
|
||||
(* Return the index into str of the first occurrence of substr.
|
||||
Pos returns a value greater than HIGH(str) of no occurrence is found.
|
||||
*)
|
||||
VAR i, j, max, subl: CARDINAL;
|
||||
BEGIN
|
||||
max := Length(str);
|
||||
subl := Length(substr);
|
||||
IF subl > max THEN RETURN HIGH(str) + 1; END;
|
||||
IF subl = 0 THEN RETURN 0; END;
|
||||
max := max - subl;
|
||||
FOR i := 0 TO max DO
|
||||
j := 0;
|
||||
WHILE (j <= subl-1) AND (str[i+j] = substr[j]) DO
|
||||
INC(j);
|
||||
END;
|
||||
IF j = subl THEN RETURN i; END;
|
||||
END;
|
||||
RETURN HIGH(str) + 1;
|
||||
END Pos;
|
||||
|
||||
PROCEDURE Copy(str: ARRAY OF CHAR;
|
||||
inx, len: CARDINAL;
|
||||
VAR result: ARRAY OF CHAR);
|
||||
(* Copy at most len characters from str into result, starting at str[inx].
|
||||
*)
|
||||
VAR i: CARDINAL;
|
||||
BEGIN
|
||||
IF Length(str) <= inx THEN RETURN END;
|
||||
i := 0;
|
||||
LOOP
|
||||
IF i > HIGH(result) THEN RETURN; END;
|
||||
IF len = 0 THEN EXIT; END;
|
||||
IF inx > HIGH(str) THEN EXIT; END;
|
||||
result[i] := str[inx];
|
||||
INC(i); INC(inx); DEC(len);
|
||||
END;
|
||||
IF i <= HIGH(result) THEN result[i] := 0C; END;
|
||||
END Copy;
|
||||
|
||||
PROCEDURE Concat(s1, s2: ARRAY OF CHAR; VAR result: ARRAY OF CHAR);
|
||||
(* Concatenate two strings.
|
||||
*)
|
||||
VAR i, j: CARDINAL;
|
||||
BEGIN
|
||||
i := 0;
|
||||
WHILE (i <= HIGH(s1)) AND (s1[i] # 0C) DO
|
||||
IF i > HIGH(result) THEN RETURN END;
|
||||
result[i] := s1[i];
|
||||
INC(i);
|
||||
END;
|
||||
j := 0;
|
||||
WHILE (j <= HIGH(s2)) AND (s2[j] # 0C) DO
|
||||
IF i > HIGH(result) THEN RETURN END;
|
||||
result[i] := s2[j];
|
||||
INC(i);
|
||||
INC(j);
|
||||
END;
|
||||
IF i <= HIGH(result) THEN result[i] := 0C; END;
|
||||
END Concat;
|
||||
|
||||
PROCEDURE Length(str: ARRAY OF CHAR): CARDINAL;
|
||||
(* Return number of characters in str.
|
||||
*)
|
||||
VAR i: CARDINAL;
|
||||
BEGIN
|
||||
i := 0;
|
||||
WHILE (i <= HIGH(str)) DO
|
||||
IF str[i] = 0C THEN RETURN i; END;
|
||||
INC(i);
|
||||
END;
|
||||
RETURN i;
|
||||
END Length;
|
||||
|
||||
PROCEDURE CompareStr(s1, s2: ARRAY OF CHAR): INTEGER;
|
||||
(* Compare two strings, return -1 if s1 < s2, 0 if s1 = s2, and 1 if s1 > s2.
|
||||
*)
|
||||
VAR i: CARDINAL;
|
||||
max: CARDINAL;
|
||||
BEGIN
|
||||
max := HIGH(s1);
|
||||
IF HIGH(s2) < max THEN max := HIGH(s2); END;
|
||||
i := 0;
|
||||
WHILE (i <= max) DO
|
||||
IF s1[i] < s2[i] THEN RETURN -1; END;
|
||||
IF s1[i] > s2[i] THEN RETURN 1; END;
|
||||
IF s1[i] = 0C THEN RETURN 0; END;
|
||||
INC(i);
|
||||
END;
|
||||
IF (i <= HIGH(s1)) AND (s1[i] # 0C) THEN RETURN 1; END;
|
||||
IF (i <= HIGH(s2)) AND (s2[i] # 0C) THEN RETURN -1; END;
|
||||
RETURN 0;
|
||||
END CompareStr;
|
||||
|
||||
END Strings.
|
3
lang/m2/libm2/TTY.def
Normal file
3
lang/m2/libm2/TTY.def
Normal file
|
@ -0,0 +1,3 @@
|
|||
DEFINITION MODULE TTY;
|
||||
PROCEDURE isatty(fd: INTEGER): BOOLEAN;
|
||||
END TTY.
|
18
lang/m2/libm2/TTY.mod
Normal file
18
lang/m2/libm2/TTY.mod
Normal file
|
@ -0,0 +1,18 @@
|
|||
#
|
||||
IMPLEMENTATION MODULE TTY;
|
||||
FROM Unix IMPORT ioctl;
|
||||
FROM SYSTEM IMPORT ADR;
|
||||
PROCEDURE isatty(fd: INTEGER): BOOLEAN;
|
||||
VAR buf: ARRAY[1..100] OF CHAR;
|
||||
BEGIN
|
||||
#ifdef __USG
|
||||
RETURN ioctl(fd, INTEGER(ORD('T') * 256 + 1), ADR(buf)) >= 0;
|
||||
#else
|
||||
#ifdef __BSD4_2
|
||||
RETURN ioctl(fd, INTEGER(ORD('t') * 256 + 8 + 6*65536 + 40000000H), ADR(buf)) >= 0;
|
||||
#else
|
||||
RETURN ioctl(fd, INTEGER(ORD('t') * 256 + 8), ADR(buf)) >= 0;
|
||||
#endif
|
||||
#endif
|
||||
END isatty;
|
||||
END TTY.
|
30
lang/m2/libm2/Terminal.def
Normal file
30
lang/m2/libm2/Terminal.def
Normal file
|
@ -0,0 +1,30 @@
|
|||
DEFINITION MODULE Terminal;
|
||||
|
||||
PROCEDURE Read(VAR ch : CHAR);
|
||||
(* Read a character from the terminal and leave it in ch
|
||||
*)
|
||||
|
||||
PROCEDURE BusyRead(VAR ch : CHAR);
|
||||
(* Read a character from the terminal and leave it in ch.
|
||||
This is a non-blocking call. It returns 0C in ch if no
|
||||
character was typed.
|
||||
*)
|
||||
|
||||
PROCEDURE ReadAgain;
|
||||
(* Causes the last character read to be returned again upon the
|
||||
next call of Read.
|
||||
*)
|
||||
|
||||
PROCEDURE Write(ch : CHAR);
|
||||
(* Write character ch to the terminal.
|
||||
*)
|
||||
|
||||
PROCEDURE WriteLn;
|
||||
(* Terminate line.
|
||||
*)
|
||||
|
||||
PROCEDURE WriteString(s : ARRAY OF CHAR);
|
||||
(* Write string s to the terminal.
|
||||
*)
|
||||
|
||||
END Terminal.
|
100
lang/m2/libm2/Terminal.mod
Normal file
100
lang/m2/libm2/Terminal.mod
Normal file
|
@ -0,0 +1,100 @@
|
|||
#
|
||||
IMPLEMENTATION MODULE Terminal;
|
||||
(* This implementation is Unix-dependant
|
||||
*)
|
||||
IMPORT Unix;
|
||||
FROM SYSTEM IMPORT ADR;
|
||||
|
||||
VAR fildes: INTEGER;
|
||||
unreadch: CHAR;
|
||||
unread: BOOLEAN;
|
||||
tty: ARRAY[0..8] OF CHAR;
|
||||
|
||||
PROCEDURE Read(VAR ch: CHAR);
|
||||
BEGIN
|
||||
IF unread THEN
|
||||
ch := unreadch;
|
||||
unread := FALSE
|
||||
ELSE
|
||||
IF Unix.read(fildes, ADR(ch), 1) < 0 THEN
|
||||
;
|
||||
END;
|
||||
END;
|
||||
unreadch := ch;
|
||||
END Read;
|
||||
|
||||
PROCEDURE BusyRead(VAR ch: CHAR);
|
||||
VAR l: INTEGER;
|
||||
BEGIN
|
||||
IF unread THEN
|
||||
ch := unreadch;
|
||||
unread := FALSE
|
||||
ELSE
|
||||
#ifdef __USG
|
||||
l := Unix.fcntl(fildes, (*FGETFL*) 3, 0);
|
||||
IF Unix.fcntl(fildes,
|
||||
(* FSETFL *) 4,
|
||||
l + (*ONDELAY*) 2) < 0 THEN
|
||||
;
|
||||
END;
|
||||
IF Unix.read(fildes, ADR(ch), 1) = 0 THEN
|
||||
ch := 0C;
|
||||
ELSE
|
||||
unreadch := ch;
|
||||
END;
|
||||
IF Unix.fcntl(fildes, (*FSETFL*)4, l) < 0 THEN
|
||||
;
|
||||
END;
|
||||
#else
|
||||
#ifdef __BSD4_2
|
||||
IF Unix.ioctl(fildes, INTEGER(ORD('f')*256+127+4*65536+40000000H), ADR(l)) < 0 THEN
|
||||
#else
|
||||
IF Unix.ioctl(fildes, INTEGER(ORD('f')*256+127), ADR(l)) < 0 THEN
|
||||
#endif
|
||||
;
|
||||
END;
|
||||
|
||||
IF l = 0 THEN
|
||||
ch := 0C;
|
||||
ELSE
|
||||
IF Unix.read(fildes, ADR(ch), 1) < 0 THEN
|
||||
;
|
||||
END;
|
||||
unreadch := ch;
|
||||
END;
|
||||
#endif
|
||||
END;
|
||||
END BusyRead;
|
||||
|
||||
PROCEDURE ReadAgain;
|
||||
BEGIN
|
||||
unread := TRUE;
|
||||
END ReadAgain;
|
||||
|
||||
PROCEDURE Write(ch: CHAR);
|
||||
BEGIN
|
||||
IF Unix.write(fildes, ADR(ch), 1) < 0 THEN
|
||||
;
|
||||
END;
|
||||
END Write;
|
||||
|
||||
PROCEDURE WriteLn;
|
||||
BEGIN
|
||||
Write(12C);
|
||||
END WriteLn;
|
||||
|
||||
PROCEDURE WriteString(s: ARRAY OF CHAR);
|
||||
VAR i: CARDINAL;
|
||||
BEGIN
|
||||
i := 0;
|
||||
WHILE (i <= HIGH(s)) & (s[i] # 0C) DO
|
||||
Write(s[i]);
|
||||
INC(i)
|
||||
END
|
||||
END WriteString;
|
||||
|
||||
BEGIN
|
||||
tty := "/dev/tty";
|
||||
fildes := Unix.open(ADR(tty), 2);
|
||||
unread := FALSE;
|
||||
END Terminal.
|
112
lang/m2/libm2/Unix.def
Normal file
112
lang/m2/libm2/Unix.def
Normal file
|
@ -0,0 +1,112 @@
|
|||
(*$Foreign language module *)
|
||||
DEFINITION MODULE Unix;
|
||||
(* An interface to some Unix system-calls *)
|
||||
FROM SYSTEM IMPORT WORD, ADDRESS;
|
||||
|
||||
(* Type needed for Signal *)
|
||||
TYPE SignalPrc = PROCEDURE(INTEGER):INTEGER;
|
||||
CONST
|
||||
SIGDFL = SignalPrc(0);
|
||||
SIGIGN = SignalPrc(1);
|
||||
ILLBREAK = ADDRESS(-1);
|
||||
|
||||
VAR errno: INTEGER;
|
||||
(* Possible values of errno: *)
|
||||
CONST
|
||||
EPERM = 1; (* Not owner *)
|
||||
ENOENT = 2; (* No such file or directory *)
|
||||
ESRCH = 3; (* No such process *)
|
||||
EINTR = 4; (* Interrupted system call *)
|
||||
EIO = 5; (* I/O error *)
|
||||
ENXIO = 6; (* No such device or address *)
|
||||
E2BIG = 7; (* Arg list too long *)
|
||||
ENOEXEC = 8; (* Exec format error *)
|
||||
EBADF = 9; (* Bad file number *)
|
||||
ECHILD = 10; (* No child processes *)
|
||||
EAGAIN = 11; (* No more processes *)
|
||||
ENOMEM = 12; (* Not enough space *)
|
||||
EACCES = 13; (* Permission denied *)
|
||||
EFAULT = 14; (* Bad address *)
|
||||
ENOTBLK = 15; (* Block device required *)
|
||||
EBUSY = 16; (* Mount device busy *)
|
||||
EEXIST = 17; (* File exists *)
|
||||
EXDEV = 18; (* Cross-device link *)
|
||||
ENODEV = 19; (* No such device *)
|
||||
ENOTDIR = 20; (* Not a directory *)
|
||||
EISDIR = 21; (* Is a directory *)
|
||||
EINVAL = 22; (* Invalid argument *)
|
||||
ENFILE = 23; (* File table overflow *)
|
||||
EMFILE = 24; (* Too many open files *)
|
||||
ENOTTY = 25; (* Not a typewriter *)
|
||||
ETXTBSY = 26; (* Text file busy *)
|
||||
EFBIG = 27; (* File too large *)
|
||||
ENOSPC = 28; (* No space left on device *)
|
||||
ESPIPE = 29; (* Illegal seek *)
|
||||
EROFS = 30; (* Read-only file system *)
|
||||
EMLINK = 31; (* Too many links *)
|
||||
EPIPE = 32; (* Broken pipe *)
|
||||
EDOM = 33; (* Math argument *)
|
||||
ERANGE = 34; (* Result too large *)
|
||||
|
||||
PROCEDURE access(path: ADDRESS; amode : INTEGER) : INTEGER;
|
||||
PROCEDURE acct(path: ADDRESS) : INTEGER;
|
||||
PROCEDURE alarm(sec: CARDINAL) : CARDINAL;
|
||||
PROCEDURE brk(endds: ADDRESS) : INTEGER;
|
||||
PROCEDURE sbrk(incr: INTEGER) : ADDRESS;
|
||||
PROCEDURE chdir(path: ADDRESS) : INTEGER;
|
||||
PROCEDURE chmod(path: ADDRESS; mode: INTEGER) : INTEGER;
|
||||
PROCEDURE chown(path: ADDRESS; owner, group: INTEGER) : INTEGER;
|
||||
PROCEDURE chroot(path: ADDRESS) : INTEGER;
|
||||
PROCEDURE close(fildes: INTEGER) : INTEGER;
|
||||
PROCEDURE creat(path: ADDRESS;
|
||||
mode: INTEGER) : INTEGER;
|
||||
PROCEDURE dup(fildes: INTEGER) : INTEGER;
|
||||
PROCEDURE execve(path: ADDRESS;
|
||||
argv: ADDRESS;
|
||||
envp: ADDRESS) : INTEGER;
|
||||
PROCEDURE exit(status: INTEGER);
|
||||
(* Sys5 *) PROCEDURE fcntl(fildes, request, arg: INTEGER) : INTEGER;
|
||||
PROCEDURE ftime(bufp:ADDRESS) : INTEGER;
|
||||
PROCEDURE fork() : INTEGER;
|
||||
PROCEDURE getpid() : INTEGER;
|
||||
PROCEDURE getppid() : INTEGER;
|
||||
PROCEDURE getuid() : INTEGER;
|
||||
PROCEDURE geteuid() : INTEGER;
|
||||
PROCEDURE getgid() : INTEGER;
|
||||
PROCEDURE getegid() : INTEGER;
|
||||
PROCEDURE ioctl(fildes, request: INTEGER; arg: ADDRESS) : INTEGER;
|
||||
PROCEDURE kill(pid, sig: INTEGER) : INTEGER;
|
||||
PROCEDURE link(path1, path2: ADDRESS) : INTEGER;
|
||||
PROCEDURE lseek(fildes: INTEGER; offset: LONGINT; whence: INTEGER) : LONGINT;
|
||||
PROCEDURE mknod(path: ADDRESS; mode, dev: INTEGER) : INTEGER;
|
||||
PROCEDURE mount(spec, dir: ADDRESS; rwflag: INTEGER) : INTEGER;
|
||||
PROCEDURE nice(incr: INTEGER) : INTEGER;
|
||||
PROCEDURE open(path: ADDRESS; oflag: INTEGER) : INTEGER;
|
||||
PROCEDURE pause();
|
||||
PROCEDURE pipe(fildes: ADDRESS) : INTEGER;
|
||||
PROCEDURE profil(buff: ADDRESS;
|
||||
bufsiz, offset, scale: INTEGER);
|
||||
PROCEDURE ptrace(request, pid, addr, data: WORD) : INTEGER;
|
||||
PROCEDURE read(fildes: INTEGER;
|
||||
buf: ADDRESS;
|
||||
nbyte: INTEGER) : INTEGER;
|
||||
PROCEDURE setuid(uid: INTEGER) : INTEGER;
|
||||
PROCEDURE setgid(gid: INTEGER) : INTEGER;
|
||||
PROCEDURE signal(sig: INTEGER;
|
||||
func: SignalPrc;
|
||||
VAR oldfunc: SignalPrc) : INTEGER;
|
||||
PROCEDURE stat(path: ADDRESS; statbuf: ADDRESS) : INTEGER;
|
||||
PROCEDURE fstat(fildes: INTEGER; statbuf: ADDRESS) : INTEGER;
|
||||
PROCEDURE stime(t: LONGINT) : INTEGER;
|
||||
PROCEDURE sync();
|
||||
PROCEDURE time(tloc: ADDRESS) : LONGINT;
|
||||
PROCEDURE times(buffer: ADDRESS) : LONGINT;
|
||||
PROCEDURE umask(cmask: INTEGER) : INTEGER;
|
||||
PROCEDURE umount(spec: ADDRESS) : INTEGER;
|
||||
PROCEDURE unlink(path: ADDRESS) : INTEGER;
|
||||
PROCEDURE utime(path: ADDRESS; times: ADDRESS) : INTEGER;
|
||||
PROCEDURE wait(VAR statloc: INTEGER): INTEGER;
|
||||
PROCEDURE write(fildes: INTEGER;
|
||||
buf: ADDRESS;
|
||||
nbyte: CARDINAL) : INTEGER;
|
||||
END Unix.
|
8
lang/m2/libm2/absd.c
Normal file
8
lang/m2/libm2/absd.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef NOFLOAT
|
||||
double
|
||||
_absd(i)
|
||||
double i;
|
||||
{
|
||||
return i >= 0 ? i : -i;
|
||||
}
|
||||
#endif
|
21
lang/m2/libm2/absf.e
Normal file
21
lang/m2/libm2/absf.e
Normal file
|
@ -0,0 +1,21 @@
|
|||
#
|
||||
mes 2,EM_WSIZE,EM_PSIZE
|
||||
exp $_absf
|
||||
pro $_absf,0
|
||||
mes 5
|
||||
mes 9,8
|
||||
lal 0
|
||||
loi EM_FSIZE
|
||||
zrf EM_FSIZE
|
||||
cmf EM_FSIZE
|
||||
zlt *3
|
||||
lal 0
|
||||
loi EM_FSIZE
|
||||
bra *4
|
||||
3
|
||||
lal 0
|
||||
loi EM_FSIZE
|
||||
ngf EM_FSIZE
|
||||
4
|
||||
ret EM_FSIZE
|
||||
end 0
|
4
lang/m2/libm2/absi.c
Normal file
4
lang/m2/libm2/absi.c
Normal file
|
@ -0,0 +1,4 @@
|
|||
_absi(i)
|
||||
{
|
||||
return i >= 0 ? i : -i;
|
||||
}
|
6
lang/m2/libm2/absl.c
Normal file
6
lang/m2/libm2/absl.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
long
|
||||
_absl(i)
|
||||
long i;
|
||||
{
|
||||
return i >= 0 ? i : -i;
|
||||
}
|
96
lang/m2/libm2/catch.c
Normal file
96
lang/m2/libm2/catch.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
#include <em_abs.h>
|
||||
|
||||
static struct errm {
|
||||
int errno;
|
||||
char *errmes;
|
||||
} errors[] = {
|
||||
{ EARRAY, "array bound error"},
|
||||
{ ERANGE, "range bound error"},
|
||||
{ ESET, "set bound error"},
|
||||
{ EIOVFL, "integer overflow"},
|
||||
{ EFOVFL, "floating overflow"},
|
||||
{ EFUNFL, "floating underflow"},
|
||||
{ EIDIVZ, "divide by 0"},
|
||||
{ EFDIVZ, "divide by 0.0"},
|
||||
{ EIUND, "undefined integer"},
|
||||
{ EFUND, "undefined float"},
|
||||
{ ECONV, "conversion error"},
|
||||
|
||||
{ ESTACK, "stack overflow"},
|
||||
{ EHEAP, "heap overflow"},
|
||||
{ EILLINS, "illegal instruction"},
|
||||
{ EODDZ, "illegal size argument"},
|
||||
{ ECASE, "case error"},
|
||||
{ EMEMFLT, "addressing non existent memory"},
|
||||
{ EBADPTR, "bad pointer used"},
|
||||
{ EBADPC, "program counter out of range"},
|
||||
{ EBADLAE, "bad argument of lae"},
|
||||
{ EBADMON, "bad monitor call"},
|
||||
{ EBADLIN, "argument if LIN too high"},
|
||||
{ EBADGTO, "GTO descriptor error"},
|
||||
{ 64, "stack size of process too large"},
|
||||
{ -1, 0}
|
||||
};
|
||||
|
||||
extern char *_hol0();
|
||||
extern char *_argv[];
|
||||
extern exit();
|
||||
|
||||
_catch(trapno)
|
||||
int trapno;
|
||||
{
|
||||
register struct errm *ep = &errors[0];
|
||||
char *errmessage;
|
||||
char *pp[8];
|
||||
register char **qq = &pp[0];
|
||||
register char *p;
|
||||
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;
|
||||
else {
|
||||
*qq++ = "error number";
|
||||
p = &("xxxxxxxxxxx: "[11]);
|
||||
i = trapno;
|
||||
if (i < 0) {
|
||||
/* ??? */
|
||||
*qq++ = "-";
|
||||
i = -i;
|
||||
}
|
||||
do
|
||||
*--p = 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)
|
||||
;
|
||||
}
|
||||
exit(trapno);
|
||||
}
|
4
lang/m2/libm2/halt.c
Normal file
4
lang/m2/libm2/halt.c
Normal file
|
@ -0,0 +1,4 @@
|
|||
_halt()
|
||||
{
|
||||
exit(0);
|
||||
}
|
96
lang/m2/libm2/head_m2.e
Normal file
96
lang/m2/libm2/head_m2.e
Normal file
|
@ -0,0 +1,96 @@
|
|||
#
|
||||
/*
|
||||
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
*
|
||||
* This product is part of the Amsterdam Compiler Kit.
|
||||
*
|
||||
* Permission to use, sell, duplicate or disclose this software must be
|
||||
* obtained in writing. Requests for such permissions may be sent to
|
||||
*
|
||||
* Dr. Andrew S. Tanenbaum
|
||||
* Wiskundig Seminarium
|
||||
* Vrije Universiteit
|
||||
* Postbox 7161
|
||||
* 1007 MC Amsterdam
|
||||
* The Netherlands
|
||||
*
|
||||
*/
|
||||
|
||||
/* Author: C.J.H. Jacobs */
|
||||
|
||||
mes 2,EM_WSIZE,EM_PSIZE
|
||||
|
||||
#define STACKSIZE 1024 /* maximum stack size for a coroutine */
|
||||
|
||||
exa _environ
|
||||
exa _argv
|
||||
exa _argc
|
||||
exa _CurrentProcess
|
||||
exa _MainProcess
|
||||
exa _StackBase
|
||||
exa _MainLB
|
||||
exa _StackSize
|
||||
exp $_catch
|
||||
|
||||
_environ
|
||||
bss EM_PSIZE,0,0
|
||||
_argv
|
||||
bss EM_PSIZE,0,0
|
||||
_argc
|
||||
bss EM_WSIZE,0,0
|
||||
_CurrentProcess
|
||||
bss EM_PSIZE,0,0
|
||||
_MainProcess
|
||||
bss EM_PSIZE,0,0
|
||||
_StackBase
|
||||
bss EM_PSIZE,0,0
|
||||
_MainLB
|
||||
bss EM_PSIZE,0,0
|
||||
_StackSize
|
||||
bss EM_WSIZE,0,0
|
||||
mainroutine
|
||||
bss 2*EM_PSIZE,0,0
|
||||
|
||||
exp $m_a_i_n
|
||||
pro $m_a_i_n, STACKSIZE
|
||||
|
||||
loc STACKSIZE
|
||||
ste _StackSize
|
||||
|
||||
lor 0
|
||||
lae _MainLB
|
||||
sti EM_PSIZE
|
||||
|
||||
lal -EM_WSIZE
|
||||
adp EM_WSIZE
|
||||
lae _StackBase
|
||||
sti EM_PSIZE
|
||||
|
||||
lae mainroutine
|
||||
adp 2*EM_PSIZE
|
||||
dup EM_PSIZE
|
||||
lae _CurrentProcess
|
||||
sti EM_PSIZE
|
||||
lae _MainProcess
|
||||
sti EM_PSIZE
|
||||
|
||||
lal EM_WSIZE+EM_PSIZE
|
||||
loi EM_PSIZE
|
||||
lae _environ ; save environment pointer
|
||||
sti EM_PSIZE
|
||||
|
||||
lal EM_WSIZE
|
||||
loi EM_PSIZE
|
||||
lae _argv ; save argument pointer
|
||||
sti EM_PSIZE
|
||||
|
||||
lol 0
|
||||
ste _argc ; save argument count
|
||||
|
||||
lpi $_catch
|
||||
sig
|
||||
asp EM_PSIZE
|
||||
cal $_M2M
|
||||
loc 0
|
||||
ret EM_WSIZE
|
||||
end
|
29
lang/m2/libm2/hol0.e
Normal file
29
lang/m2/libm2/hol0.e
Normal file
|
@ -0,0 +1,29 @@
|
|||
#
|
||||
|
||||
; $Header$
|
||||
;
|
||||
; (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
;
|
||||
; This product is part of the Amsterdam Compiler Kit.
|
||||
;
|
||||
; Permission to use, sell, duplicate or disclose this software must be
|
||||
; obtained in writing. Requests for such permissions may be sent to
|
||||
;
|
||||
; Dr. Andrew S. Tanenbaum
|
||||
; Wiskundig Seminarium
|
||||
; Vrije Universiteit
|
||||
; Postbox 7161
|
||||
; 1007 MC Amsterdam
|
||||
; The Netherlands
|
||||
;
|
||||
;
|
||||
|
||||
mes 2,EM_WSIZE,EM_PSIZE
|
||||
|
||||
; _hol0 return the address of the ABS block (hol0)
|
||||
|
||||
exp $_hol0
|
||||
pro $_hol0,0
|
||||
lae 0
|
||||
ret EM_PSIZE
|
||||
end ?
|
8
lang/m2/libm2/load.c
Normal file
8
lang/m2/libm2/load.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
_load(siz, addr, p)
|
||||
register char *addr;
|
||||
register int siz;
|
||||
{
|
||||
register char *q = (char *) &p;
|
||||
|
||||
while (siz--) *q++ = *addr++;
|
||||
}
|
12
lang/m2/libm2/random.def
Normal file
12
lang/m2/libm2/random.def
Normal file
|
@ -0,0 +1,12 @@
|
|||
DEFINITION MODULE random;
|
||||
|
||||
PROCEDURE Random(): CARDINAL;
|
||||
(* Return a random CARDINAL
|
||||
*)
|
||||
|
||||
PROCEDURE Uniform (lwb, upb: CARDINAL): CARDINAL;
|
||||
(* Return CARDINALs, uniformly distributed between "lwb" and "upb".
|
||||
"lwb" must be smaller than "upb", or "lwb" is returned.
|
||||
*)
|
||||
|
||||
END random.
|
19
lang/m2/libm2/random.mod
Normal file
19
lang/m2/libm2/random.mod
Normal file
|
@ -0,0 +1,19 @@
|
|||
IMPLEMENTATION MODULE random;
|
||||
|
||||
VAR seed: CARDINAL;
|
||||
|
||||
PROCEDURE Random(): CARDINAL;
|
||||
BEGIN
|
||||
seed := seed * 77 + 153;
|
||||
RETURN seed;
|
||||
END Random;
|
||||
|
||||
PROCEDURE Uniform (lwb, upb: CARDINAL): CARDINAL;
|
||||
BEGIN
|
||||
IF upb <= lwb THEN RETURN lwb; END;
|
||||
RETURN lwb + (Random() MOD (upb - lwb + 1));
|
||||
END Uniform;
|
||||
|
||||
BEGIN
|
||||
seed := 253B;
|
||||
END random.
|
7
lang/m2/libm2/stackprio.c
Normal file
7
lang/m2/libm2/stackprio.c
Normal file
|
@ -0,0 +1,7 @@
|
|||
_stackprio(n)
|
||||
{
|
||||
}
|
||||
|
||||
_unstackprio()
|
||||
{
|
||||
}
|
8
lang/m2/libm2/store.c
Normal file
8
lang/m2/libm2/store.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
_store(siz, addr, p)
|
||||
register char *addr;
|
||||
register int siz;
|
||||
{
|
||||
register char *q = (char *) &p;
|
||||
|
||||
while (siz--) *addr++ = *q++;
|
||||
}
|
245
lang/m2/libm2/transfer.e
Normal file
245
lang/m2/libm2/transfer.e
Normal file
|
@ -0,0 +1,245 @@
|
|||
#
|
||||
#include <em_mes.h>
|
||||
|
||||
mes 2, EM_WSIZE, EM_PSIZE
|
||||
|
||||
; This file contains the implementation of the following routines from
|
||||
; the SYSTEM module:
|
||||
; TRANSFER, NEWPROCESS
|
||||
; The NEWPROCESS routine creates a new coroutine stack frame.
|
||||
; The TRANSFER routine implements transfers from one coroutine to another.
|
||||
; The memory organization for coroutines is rather complicated.
|
||||
; One problem is caused by the fact that the user must allocate the
|
||||
; stackspace. So, this stackspace can be located anywhere, including on
|
||||
; the heap. This means that we cannot use this space as a stack, because
|
||||
; in EM, the stack-pointer may never point below the heap-pointer.
|
||||
; So, this space is only used to save the stack when the coroutine isn't
|
||||
; running.
|
||||
; It also contains information about the size of the frame, the
|
||||
; address of the procedure that forms the coroutine body, the offset
|
||||
; of the LB from the start of the frame, and the offset of the SP from
|
||||
; the start of the frame.
|
||||
; So, is looks like this:
|
||||
; |-----------------------------|
|
||||
; | |
|
||||
; | |
|
||||
; | |
|
||||
; .
|
||||
; .
|
||||
; .
|
||||
; | |
|
||||
; | |
|
||||
; | | <--- coroutine ident
|
||||
; |-----------------------------|
|
||||
; | saved SP |
|
||||
; |-----------------------------|
|
||||
; | saved LB |
|
||||
; |-----------------------------|
|
||||
; | procedure address or 0 |
|
||||
; |-----------------------------|
|
||||
; | size |
|
||||
; |-----------------------------|
|
||||
;
|
||||
; Another problem is that the coroutines must always run at the same
|
||||
; place in the stack. Therefore, in the runtime startoff a piece of the
|
||||
; stack is allocated for coroutines.
|
||||
|
||||
exp $SYSTEM_NEWPROCESS
|
||||
exp $SYSTEM_TRANSFER
|
||||
inp $_ChkSize
|
||||
|
||||
pro $SYSTEM_NEWPROCESS, 0
|
||||
|
||||
; This procedure only initializes the area used for saving the stack.
|
||||
; Its definition is:
|
||||
; PROCEDURE NEWPROCESS(P:PROC; A:ADDRESS; n:CARDINAL; VAR p1:ADDRESS);
|
||||
|
||||
lol 2*EM_PSIZE ; size of frame (n)
|
||||
cal $_ChkSize
|
||||
asp EM_WSIZE
|
||||
lfr EM_WSIZE
|
||||
sil EM_WSIZE ; store size in area (indicated by A)
|
||||
lal EM_PSIZE
|
||||
loi EM_PSIZE ; address of area (A)
|
||||
lal 0
|
||||
loi EM_PSIZE ; address of coroutine body (P)
|
||||
lal EM_PSIZE
|
||||
loi EM_PSIZE
|
||||
adp EM_WSIZE
|
||||
sti EM_PSIZE ; store it in area
|
||||
lal EM_PSIZE
|
||||
loi EM_PSIZE
|
||||
adp 3*EM_PSIZE + EM_WSIZE ; this becomes the coroutine identifier
|
||||
lal 2*EM_PSIZE+EM_WSIZE
|
||||
loi EM_PSIZE
|
||||
sti EM_PSIZE
|
||||
ret 0
|
||||
end 0
|
||||
|
||||
_target
|
||||
bss EM_PSIZE, 0, 0
|
||||
|
||||
pro $SYSTEM_TRANSFER, 0
|
||||
|
||||
; This procedure does all the hard work.
|
||||
; It must save the current environment, and restore the one to which the
|
||||
; transfer is done. It must also make it look like the return is done
|
||||
; from ITS invocation of transfer.
|
||||
; Definition is:
|
||||
; PROCEDURE TRANSFER(VAR p1, p2 : ADDRESS);
|
||||
|
||||
mes ms_gto ; This is a dangerous procedure
|
||||
|
||||
lal EM_PSIZE
|
||||
loi EM_PSIZE
|
||||
loi EM_PSIZE ; address of target coroutine
|
||||
dup EM_PSIZE
|
||||
lae _CurrentProcess
|
||||
loi EM_PSIZE
|
||||
dup EM_PSIZE
|
||||
lal 0
|
||||
loi EM_PSIZE ; address of place where to store address of current coroutine
|
||||
sti EM_PSIZE ; store
|
||||
cmp ; compare with current process
|
||||
zne *1
|
||||
; Here, no real transfer needs to be done
|
||||
asp EM_PSIZE
|
||||
ret 0 ; just return
|
||||
1
|
||||
lae _target
|
||||
sti EM_PSIZE ; store it in _target
|
||||
|
||||
; Now, we save the current stack
|
||||
; Use local base from main program
|
||||
|
||||
lor 0 ; load LB
|
||||
lae _CurrentProcess
|
||||
loi EM_PSIZE
|
||||
adp -2*EM_PSIZE
|
||||
sti EM_PSIZE ; save it
|
||||
lae _CurrentProcess
|
||||
loi EM_PSIZE
|
||||
lae _MainProcess
|
||||
loi EM_PSIZE
|
||||
cmp
|
||||
zeq *2
|
||||
|
||||
lae _MainLB
|
||||
loi EM_PSIZE
|
||||
str 0
|
||||
|
||||
lae _StackBase
|
||||
loi EM_PSIZE
|
||||
lae _CurrentProcess
|
||||
loi EM_PSIZE
|
||||
adp -3*EM_PSIZE-EM_WSIZE
|
||||
loi EM_WSIZE ; get size
|
||||
ngi EM_WSIZE
|
||||
ads EM_WSIZE ; gives source address
|
||||
lae _CurrentProcess
|
||||
loi EM_PSIZE ; destination address
|
||||
lae _CurrentProcess
|
||||
loi EM_PSIZE
|
||||
adp -3*EM_PSIZE-EM_WSIZE
|
||||
loi EM_WSIZE
|
||||
bls EM_WSIZE ; copy
|
||||
2
|
||||
lor 1 ; load SP
|
||||
lae _CurrentProcess
|
||||
loi EM_PSIZE
|
||||
adp -EM_PSIZE
|
||||
sti EM_PSIZE ; save it
|
||||
|
||||
|
||||
; Now, we must find a stack we can temporarily use.
|
||||
; Just take the one from the main program.
|
||||
lae _MainProcess
|
||||
loi EM_PSIZE
|
||||
adp -EM_PSIZE
|
||||
loi EM_PSIZE
|
||||
str 1 ; temporary stackpointer
|
||||
lae _target
|
||||
loi EM_PSIZE
|
||||
dup EM_PSIZE
|
||||
lae _CurrentProcess
|
||||
sti EM_PSIZE ; store target process descriptor in _CurrentProcess
|
||||
lae _MainProcess
|
||||
loi EM_PSIZE
|
||||
cmp
|
||||
zeq *4
|
||||
; Now check if the coroutine was called before
|
||||
lae _target
|
||||
loi EM_PSIZE
|
||||
adp -3*EM_PSIZE
|
||||
loi EM_PSIZE
|
||||
zer EM_PSIZE
|
||||
cmp
|
||||
zeq *5
|
||||
; No, it was'nt
|
||||
lae _StackBase
|
||||
loi EM_PSIZE
|
||||
str 1 ; new stack pointer
|
||||
lae _target
|
||||
loi EM_PSIZE
|
||||
adp -3*EM_PSIZE
|
||||
loi EM_PSIZE
|
||||
zer EM_PSIZE
|
||||
lae _target
|
||||
loi EM_PSIZE
|
||||
adp -3*EM_PSIZE
|
||||
sti EM_PSIZE
|
||||
cai
|
||||
loc 0
|
||||
cal $_exit
|
||||
ret 0
|
||||
5
|
||||
lae _target
|
||||
loi EM_PSIZE ; push source address
|
||||
lae _StackBase
|
||||
loi EM_PSIZE ; subtract size from this and we have the destination address
|
||||
lae _target
|
||||
loi EM_PSIZE
|
||||
adp -3*EM_PSIZE-EM_WSIZE
|
||||
loi EM_WSIZE
|
||||
ngi EM_WSIZE
|
||||
ads EM_WSIZE ; got it
|
||||
lae _target
|
||||
loi EM_PSIZE
|
||||
adp -3*EM_PSIZE-EM_WSIZE
|
||||
loi EM_WSIZE
|
||||
bls EM_WSIZE
|
||||
4
|
||||
lae _target
|
||||
loi EM_PSIZE
|
||||
adp -EM_PSIZE
|
||||
loi EM_PSIZE
|
||||
str 1 ; restore SP
|
||||
lae _target
|
||||
loi EM_PSIZE
|
||||
adp -2*EM_PSIZE
|
||||
loi EM_PSIZE
|
||||
str 0 ; restore LB
|
||||
ret 0
|
||||
end 0
|
||||
|
||||
pro $_ChkSize, 0
|
||||
lol 0
|
||||
loc 3*EM_PSIZE+EM_WSIZE
|
||||
sbi EM_WSIZE
|
||||
dup EM_WSIZE
|
||||
stl 0
|
||||
loe _StackSize
|
||||
cmu EM_WSIZE
|
||||
zle *1
|
||||
loc 64 ; trap number for "stack size too large"
|
||||
trp
|
||||
1
|
||||
lol 0
|
||||
loc EM_WSIZE-1
|
||||
adi EM_WSIZE
|
||||
loc EM_WSIZE
|
||||
dvi EM_WSIZE
|
||||
loc EM_WSIZE
|
||||
mli EM_WSIZE
|
||||
ret EM_WSIZE
|
||||
end 0
|
28
mach/mantra/libm2/Makefile
Normal file
28
mach/mantra/libm2/Makefile
Normal file
|
@ -0,0 +1,28 @@
|
|||
SUF=o
|
||||
EMHOME=../../..
|
||||
MAKEFILE=$(EMHOME)/mach/proto/libg/Makefile
|
||||
MACHDEF="MACH=mantra" "SUF=$(SUF)"
|
||||
M2LIB = lang/m2/libm2
|
||||
MOD="PREF=m2" "SUB=" "SRC=$(M2LIB)"
|
||||
|
||||
install: cpmod
|
||||
|
||||
cpmod:
|
||||
make -f $(MAKEFILE) $(MOD) $(MACHDEF) cp
|
||||
|
||||
cmp: cmpmod
|
||||
|
||||
cmpmod:
|
||||
make -f $(MAKEFILE) $(MOD) $(MACHDEF) tail
|
||||
-$(EMHOME)/mach/compare tail_m2
|
||||
make -f $(MAKEFILE) $(MOD) $(MACHDEF) head
|
||||
-$(EMHOME)/mach/compare head_m2
|
||||
|
||||
clean:
|
||||
-rm -f *.old *.[ce$(SUF)] tail* head*
|
||||
|
||||
opr:
|
||||
make pr | opr
|
||||
|
||||
pr:
|
||||
@pr Makefile
|
4
mach/mantra/libm2/compmodule
Executable file
4
mach/mantra/libm2/compmodule
Executable file
|
@ -0,0 +1,4 @@
|
|||
if ${MACH?} -I../../../h ${MACHFL?} $1 1>&2
|
||||
then echo `basename $1 $2`.o
|
||||
else exit 1
|
||||
fi
|
28
mach/pdp/libm2/Makefile
Normal file
28
mach/pdp/libm2/Makefile
Normal file
|
@ -0,0 +1,28 @@
|
|||
SUF=o
|
||||
EMHOME=../../..
|
||||
MAKEFILE=$(EMHOME)/mach/proto/libg/Makefile
|
||||
MACHDEF="MACH=pdp" "SUF=$(SUF)" "ASAR=ar"
|
||||
M2LIB = lang/m2/libm2
|
||||
MOD="PREF=m2" "SUB=" "SRC=$(M2LIB)"
|
||||
|
||||
install: cpmod
|
||||
|
||||
cpmod:
|
||||
make -f $(MAKEFILE) $(MOD) $(MACHDEF) cp
|
||||
|
||||
cmp: cmpmod
|
||||
|
||||
cmpmod:
|
||||
make -f $(MAKEFILE) $(MOD) $(MACHDEF) tail
|
||||
-$(EMHOME)/mach/compare tail_m2
|
||||
make -f $(MAKEFILE) $(MOD) $(MACHDEF) head
|
||||
-$(EMHOME)/mach/compare head_m2
|
||||
|
||||
clean:
|
||||
-rm -f *.old *.[ce$(SUF)] tail* head*
|
||||
|
||||
opr:
|
||||
make pr | opr
|
||||
|
||||
pr:
|
||||
@pr Makefile
|
4
mach/pdp/libm2/compmodule
Executable file
4
mach/pdp/libm2/compmodule
Executable file
|
@ -0,0 +1,4 @@
|
|||
if ${MACH?} -I../../../h ${MACHFL?} $1 1>&2
|
||||
then echo `basename $1 $2`.o
|
||||
else exit 1
|
||||
fi
|
28
mach/sun3/libm2/Makefile
Normal file
28
mach/sun3/libm2/Makefile
Normal file
|
@ -0,0 +1,28 @@
|
|||
SUF=o
|
||||
EMHOME=../../..
|
||||
MAKEFILE=$(EMHOME)/mach/proto/libg/Makefile
|
||||
MACHDEF="MACH=sun3" "SUF=$(SUF)" "ASAR=aal"
|
||||
M2LIB = lang/m2/libm2
|
||||
MOD="PREF=m2" "SUB=" "SRC=$(M2LIB)"
|
||||
|
||||
install: cpmod
|
||||
|
||||
cpmod:
|
||||
make -f $(MAKEFILE) $(MOD) $(MACHDEF) cp
|
||||
|
||||
cmp: cmpmod
|
||||
|
||||
cmpmod:
|
||||
make -f $(MAKEFILE) $(MOD) $(MACHDEF) tail
|
||||
-$(EMHOME)/mach/compare tail_m2
|
||||
make -f $(MAKEFILE) $(MOD) $(MACHDEF) head
|
||||
-$(EMHOME)/mach/compare head_m2
|
||||
|
||||
clean:
|
||||
-rm -f *.old *.[ce$(SUF)] tail* head*
|
||||
|
||||
opr:
|
||||
make pr | opr
|
||||
|
||||
pr:
|
||||
@pr Makefile
|
4
mach/sun3/libm2/compmodule
Executable file
4
mach/sun3/libm2/compmodule
Executable file
|
@ -0,0 +1,4 @@
|
|||
if ${MACH?} -I../../../h ${MACHFL?} $1 1>&2
|
||||
then echo `basename $1 $2`.o
|
||||
else exit 1
|
||||
fi
|
30
mach/vax4/libm2/Makefile
Normal file
30
mach/vax4/libm2/Makefile
Normal file
|
@ -0,0 +1,30 @@
|
|||
SUF=o
|
||||
EMHOME=../../..
|
||||
MAKEFILE=$(EMHOME)/mach/proto/libg/Makefile
|
||||
MACHDEF="MACH=vax4" "SUF=$(SUF)" "ASAR=ar"
|
||||
M2LIB = lang/m2/libm2
|
||||
MOD="PREF=m2" "SUB=" "SRC=$(M2LIB)"
|
||||
|
||||
install: cpmod
|
||||
|
||||
cpmod:
|
||||
RANLIB=ranlib ; export RANLIB ; \
|
||||
make -f $(MAKEFILE) $(MOD) $(MACHDEF) cp
|
||||
|
||||
cmp: cmpmod
|
||||
|
||||
cmpmod:
|
||||
RANLIB=ranlib ; export RANLIB ; \
|
||||
make -f $(MAKEFILE) $(MOD) $(MACHDEF) tail
|
||||
-$(EMHOME)/mach/compare tail_m2
|
||||
make -f $(MAKEFILE) $(MOD) $(MACHDEF) head
|
||||
-$(EMHOME)/mach/compare head_m2
|
||||
|
||||
clean:
|
||||
-rm -f *.old *.[ce$(SUF)] tail* head*
|
||||
|
||||
opr:
|
||||
make pr | opr
|
||||
|
||||
pr:
|
||||
@pr Makefile
|
4
mach/vax4/libm2/compmodule
Executable file
4
mach/vax4/libm2/compmodule
Executable file
|
@ -0,0 +1,4 @@
|
|||
if ${MACH?} -I../../../h ${MACHFL?} $1 1>&2
|
||||
then echo `basename $1 $2`.o
|
||||
else exit 1
|
||||
fi
|
Loading…
Reference in a new issue